From 0715b7dfc668f138e99b598613acdd6efde5423a Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Sun, 12 Dec 2010 15:43:35 +0000 Subject: [PATCH] - cleaned up switch code and fixed several problems: * savegames stored an index in the switch table and performed no validation when loading a savegame. * setting of a random switch animation duration was broken. * separated the 2 values stored in the Time variable into 2 separate variables. * defining a switch with one texture already belonging to another switch could leave broken definitions in the switch table. - added function for serializing switch and door animation pointers. - bumped min. savegame versions due to changes to DButtonThinker and removed all current savegame compatibility code. SVN r3030 (trunk) --- src/d_netinfo.cpp | 8 +- src/dobject.cpp | 5 -- src/farchive.h | 4 + src/g_shared/a_quake.cpp | 12 +-- src/g_shared/a_skies.cpp | 5 -- src/p_doors.cpp | 23 +----- src/p_mobj.cpp | 109 ++++---------------------- src/p_pspr.cpp | 12 +-- src/p_saveg.cpp | 31 +------- src/p_switch.cpp | 95 ++++++++++------------ src/p_user.cpp | 34 +------- src/r_interpolate.cpp | 11 +-- src/s_advsound.cpp | 4 - src/textures/anim_switches.cpp | 139 ++++++++++++++++++++------------- src/textures/animations.cpp | 21 +++++ src/textures/textures.h | 18 ++--- src/version.h | 7 +- 17 files changed, 194 insertions(+), 344 deletions(-) diff --git a/src/d_netinfo.cpp b/src/d_netinfo.cpp index 51467369cb..def8006582 100644 --- a/src/d_netinfo.cpp +++ b/src/d_netinfo.cpp @@ -835,11 +835,9 @@ FArchive &operator<< (FArchive &arc, userinfo_t &info) { arc.Read (&info.netname, sizeof(info.netname)); } - arc << info.team << info.aimdist << info.color << info.skin << info.gender << info.neverswitch; - if (SaveVersion >= 2193) - { - arc << info.colorset; - } + arc << info.team << info.aimdist << info.color + << info.skin << info.gender << info.neverswitch + << info.colorset; return arc; } diff --git a/src/dobject.cpp b/src/dobject.cpp index 3bd815bd60..2dd6aa1edb 100644 --- a/src/dobject.cpp +++ b/src/dobject.cpp @@ -540,11 +540,6 @@ void DObject::SerializeUserVars(FArchive &arc) DWORD count, j; int *varloc; - if (SaveVersion < 1933) - { - return; - } - symt = &GetClass()->Symbols; if (arc.IsStoring()) diff --git a/src/farchive.h b/src/farchive.h index 533b3920eb..7ee05fdcdf 100644 --- a/src/farchive.h +++ b/src/farchive.h @@ -291,7 +291,11 @@ template<> inline FArchive &operator<< (FArchive &arc, FFont* &font) } struct FStrifeDialogueNode; +struct FSwitchDef; +struct FDoorAnimation; template<> FArchive &operator<< (FArchive &arc, FStrifeDialogueNode *&node); +template<> FArchive &operator<< (FArchive &arc, FSwitchDef* &sw); +template<> FArchive &operator<< (FArchive &arc, FDoorAnimation* &da); diff --git a/src/g_shared/a_quake.cpp b/src/g_shared/a_quake.cpp index c536053331..725f120482 100644 --- a/src/g_shared/a_quake.cpp +++ b/src/g_shared/a_quake.cpp @@ -55,16 +55,8 @@ void DEarthquake::Serialize (FArchive &arc) { Super::Serialize (arc); arc << m_Spot << m_Intensity << m_Countdown - << m_TremorRadius << m_DamageRadius; - - if (SaveVersion >= 1912) - { - arc << m_QuakeSFX; - } - else - { - m_QuakeSFX = "world/quake"; - } + << m_TremorRadius << m_DamageRadius + << m_QuakeSFX; } //========================================================================== diff --git a/src/g_shared/a_skies.cpp b/src/g_shared/a_skies.cpp index 21edd2ba1a..bb13eac013 100644 --- a/src/g_shared/a_skies.cpp +++ b/src/g_shared/a_skies.cpp @@ -70,11 +70,6 @@ void ASkyViewpoint::Serialize (FArchive &arc) { Super::Serialize (arc); arc << bInSkybox << bAlways << Mate; - if (SaveVersion < 2992) - { - fixed_t eatme; - arc << eatme; - } } void ASkyViewpoint::Destroy () diff --git a/src/p_doors.cpp b/src/p_doors.cpp index 7f385242d7..557928c557 100644 --- a/src/p_doors.cpp +++ b/src/p_doors.cpp @@ -638,14 +638,7 @@ DAnimatedDoor::DAnimatedDoor (sector_t *sec) void DAnimatedDoor::Serialize (FArchive &arc) { Super::Serialize (arc); - - FTextureID basetex; - if (arc.IsStoring()) - { - basetex = m_DoorAnim->BaseTexture; - } - arc << m_Line1 << m_Line2 << m_Frame << m_Timer @@ -653,20 +646,8 @@ void DAnimatedDoor::Serialize (FArchive &arc) << m_Status << m_Speed << m_Delay - << basetex; - if (SaveVersion < 2336) - { - m_SetBlocking1 = m_SetBlocking2 = true; - } - else - { - arc << m_SetBlocking1 << m_SetBlocking2; - } - - if (arc.IsLoading()) - { - m_DoorAnim = TexMan.FindAnimatedDoor (basetex); - } + << m_DoorAnim + << m_SetBlocking1 << m_SetBlocking2; } DAnimatedDoor::DAnimatedDoor (sector_t *sec, line_t *line, int speed, int delay, FDoorAnimation *anim) diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index a736008917..bc173b9cb0 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -258,18 +258,9 @@ void AActor::Serialize (FArchive &arc) << args[0] << args[1] << args[2] << args[3] << args[4] << goal << waterlevel - << MinMissileChance; - if (SaveVersion >= 2826) - { - arc << SpawnFlags; - } - else - { - WORD w; - arc << w; - SpawnFlags = w; - } - arc << Inventory + << MinMissileChance + << SpawnFlags + << Inventory << InventoryID << id << FloatBobPhase @@ -281,12 +272,9 @@ void AActor::Serialize (FArchive &arc) << ActiveSound << UseSound << BounceSound - << WallBounceSound; - if (SaveVersion >= 2234) - { - arc << CrushPainSound; - } - arc << Speed + << WallBounceSound + << CrushPainSound + << Speed << FloatSpeed << Mass << PainChance @@ -313,83 +301,14 @@ void AActor::Serialize (FArchive &arc) << pushfactor << Species << Score - << Tag; - if (SaveVersion >= 1904) - { - arc << lastpush << lastbump; - } - - if (SaveVersion >= 1900) - { - arc << PainThreshold; - } - if (SaveVersion >= 1914) - { - arc << DamageFactor; - } - if (SaveVersion > 2036) - { - arc << WeaveIndexXY << WeaveIndexZ; - } - else - { - int index; - - if (SaveVersion < 2036) - { - index = special2; - } - else - { - arc << index; - } - // A_BishopMissileWeave and A_CStaffMissileSlither stored the weaveXY - // value in different parts of the index. - if (this->IsKindOf(PClass::FindClass("BishopFX"))) - { - WeaveIndexXY = index >> 16; - WeaveIndexZ = index; - } - else - { - WeaveIndexXY = index; - WeaveIndexZ = 0; - } - } - if (SaveVersion >= 2450) - { - arc << PoisonDamageReceived << PoisonDurationReceived << PoisonPeriodReceived << Poisoner; - arc << PoisonDamage << PoisonDuration << PoisonPeriod; - } - - // Skip past uservar array in old savegames - if (SaveVersion < 1933) - { - int foo; - for (int i = 0; i < 10; ++i) - arc << foo; - } - - if (SaveVersion > 2560) - { - arc << ConversationRoot << Conversation; - } - else // old code which uses relative indexing. - { - int convnum; - - convnum = arc.ReadCount(); - if (GetConversation(GetClass()->TypeName) == -1) - { - Conversation = NULL; - ConversationRoot = -1; - } - else - { - // This cannot be restored anymore. - I_Error("Cannot load old savegames with active dialogues"); - } - } + << Tag + << lastpush << lastbump + << PainThreshold + << DamageFactor + << WeaveIndexXY << WeaveIndexZ + << PoisonDamageReceived << PoisonDurationReceived << PoisonPeriodReceived << Poisoner + << PoisonDamage << PoisonDuration << PoisonPeriod + << ConversationRoot << Conversation; if (arc.IsLoading ()) { diff --git a/src/p_pspr.cpp b/src/p_pspr.cpp index a30e2d7360..606acdb26e 100644 --- a/src/p_pspr.cpp +++ b/src/p_pspr.cpp @@ -861,15 +861,7 @@ void P_MovePsprites (player_t *player) FArchive &operator<< (FArchive &arc, pspdef_t &def) { - arc << def.state << def.tics << def.sx << def.sy; - if (SaveVersion >= 2295) - { - arc << def.sprite << def.frame; - } - else - { - def.sprite = def.state->sprite; - def.frame = def.state->Frame; - } + arc << def.state << def.tics << def.sx << def.sy + << def.sprite << def.frame; return arc; } diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index c7ad7125cd..ebc975ff87 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -347,16 +347,8 @@ void P_SerializeWorld (FArchive &arc) << sec->interpolations[0] << sec->interpolations[1] << sec->interpolations[2] - << sec->interpolations[3]; - - if (SaveVersion < 2492) - { - sec->SeqName = NAME_None; - } - else - { - arc << sec->SeqName; - } + << sec->interpolations[3] + << sec->SeqName; sec->e->Serialize(arc); if (arc.IsStoring ()) @@ -444,15 +436,7 @@ FArchive &operator<< (FArchive &arc, sector_t::splane &p) { arc << p.xform.xoffs << p.xform.yoffs << p.xform.xscale << p.xform.yscale << p.xform.angle << p.xform.base_yoffs << p.xform.base_angle - << p.Flags << p.Light << p.Texture << p.TexZ; - if (SaveVersion >= 2992) - { - arc << p.alpha; - } - else - { - p.alpha = FRACUNIT; - } + << p.Flags << p.Light << p.Texture << p.TexZ << p.alpha; return arc; } @@ -614,15 +598,6 @@ void P_SerializeSubsectors(FArchive &arc) } else { - if (SaveVersion < 2609) - { - if (hasglnodes) - { - RecalculateDrawnSubsectors(); - } - return; - } - arc << num_verts << num_subs << num_nodes; if (num_verts != numvertexes || num_subs != numsubsectors || diff --git a/src/p_switch.cpp b/src/p_switch.cpp index 622fd63946..6e468e41d3 100644 --- a/src/p_switch.cpp +++ b/src/p_switch.cpp @@ -56,18 +56,19 @@ class DActiveButton : public DThinker DECLARE_CLASS (DActiveButton, DThinker) public: DActiveButton (); - DActiveButton (side_t *, int, WORD switchnum, fixed_t x, fixed_t y, bool flippable); + DActiveButton (side_t *, int, FSwitchDef *, fixed_t x, fixed_t y, bool flippable); void Serialize (FArchive &arc); void Tick (); - side_t *m_Side; - SBYTE m_Part; - WORD m_SwitchDef; - WORD m_Frame; - WORD m_Timer; - bool bFlippable; - fixed_t m_X, m_Y; // Location of timer sound + side_t *m_Side; + SBYTE m_Part; + bool bFlippable; + bool bReturning; + FSwitchDef *m_SwitchDef; + SDWORD m_Frame; + DWORD m_Timer; + fixed_t m_X, m_Y; // Location of timer sound protected: bool AdvanceFrame (); @@ -81,8 +82,7 @@ protected: // //========================================================================== -static bool P_StartButton (side_t *side, int Where, int switchnum, - fixed_t x, fixed_t y, bool useagain) +static bool P_StartButton (side_t *side, int Where, FSwitchDef *Switch, fixed_t x, fixed_t y, bool useagain) { DActiveButton *button; TThinkerIterator iterator; @@ -97,7 +97,7 @@ static bool P_StartButton (side_t *side, int Where, int switchnum, } } - new DActiveButton (side, Where, switchnum, x, y, useagain); + new DActiveButton (side, Where, Switch, x, y, useagain); return true; } @@ -168,15 +168,15 @@ bool P_CheckSwitchRange(AActor *user, line_t *line, int sideno) if (open.range <= 0) goto onesided; - if ((TexMan.FindSwitch (side->GetTexture(side_t::top))) != -1) + if ((TexMan.FindSwitch (side->GetTexture(side_t::top))) != NULL) { return (user->z + user->height >= open.top); } - else if ((TexMan.FindSwitch (side->GetTexture(side_t::bottom))) != -1) + else if ((TexMan.FindSwitch (side->GetTexture(side_t::bottom))) != NULL) { return (user->z <= open.bottom); } - else if ((line->flags & (ML_3DMIDTEX)) || (TexMan.FindSwitch (side->GetTexture(side_t::mid))) != -1) + else if ((line->flags & (ML_3DMIDTEX)) || (TexMan.FindSwitch (side->GetTexture(side_t::mid))) != NULL) { // 3DMIDTEX lines will force a mid texture check if no switch is found on this line // to keep compatibility with Eternity's implementation. @@ -202,18 +202,17 @@ bool P_ChangeSwitchTexture (side_t *side, int useAgain, BYTE special, bool *ques { int texture; int sound; - int i; FSwitchDef *Switch; - if ((i = TexMan.FindSwitch (side->GetTexture(side_t::top))) != -1) + if ((Switch = TexMan.FindSwitch (side->GetTexture(side_t::top))) != NULL) { texture = side_t::top; } - else if ((i = TexMan.FindSwitch (side->GetTexture(side_t::bottom))) != -1) + else if ((Switch = TexMan.FindSwitch (side->GetTexture(side_t::bottom))) != NULL) { texture = side_t::bottom; } - else if ((i = TexMan.FindSwitch (side->GetTexture(side_t::mid))) != -1) + else if ((Switch = TexMan.FindSwitch (side->GetTexture(side_t::mid))) != NULL) { texture = side_t::mid; } @@ -225,7 +224,6 @@ bool P_ChangeSwitchTexture (side_t *side, int useAgain, BYTE special, bool *ques } return false; } - Switch = TexMan.GetSwitch(i); // EXIT SWITCH? if (Switch->Sound != 0) @@ -252,10 +250,10 @@ bool P_ChangeSwitchTexture (side_t *side, int useAgain, BYTE special, bool *ques pt[0] = line->v1->x + (line->dx >> 1); pt[1] = line->v1->y + (line->dy >> 1); - side->SetTexture(texture, Switch->u[0].Texture); + side->SetTexture(texture, Switch->frames[0].Texture); if (useAgain || Switch->NumFrames > 1) { - playsound = P_StartButton (side, texture, i, pt[0], pt[1], !!useAgain); + playsound = P_StartButton (side, texture, Switch, pt[0], pt[1], !!useAgain); } else { @@ -289,9 +287,11 @@ DActiveButton::DActiveButton () m_X = 0; m_Y = 0; bFlippable = false; + bReturning = false; + m_Frame = 0; } -DActiveButton::DActiveButton (side_t *side, int Where, WORD switchnum, +DActiveButton::DActiveButton (side_t *side, int Where, FSwitchDef *Switch, fixed_t x, fixed_t y, bool useagain) { m_Side = side; @@ -299,9 +299,10 @@ DActiveButton::DActiveButton (side_t *side, int Where, WORD switchnum, m_X = x; m_Y = y; bFlippable = useagain; + bReturning = false; - m_SwitchDef = switchnum; - m_Frame = 65535; + m_SwitchDef = Switch; + m_Frame = -1; AdvanceFrame (); } @@ -313,18 +314,8 @@ DActiveButton::DActiveButton (side_t *side, int Where, WORD switchnum, void DActiveButton::Serialize (FArchive &arc) { - SDWORD sidenum; - Super::Serialize (arc); - if (arc.IsStoring ()) - { - sidenum = m_Side ? SDWORD(m_Side - sides) : -1; - } - arc << sidenum << m_Part << m_SwitchDef << m_Frame << m_Timer << bFlippable << m_X << m_Y; - if (arc.IsLoading ()) - { - m_Side = sidenum >= 0 ? sides + sidenum : NULL; - } + arc << m_Side << m_Part << m_SwitchDef << m_Frame << m_Timer << bFlippable << m_X << m_Y << bReturning; } //========================================================================== @@ -335,16 +326,23 @@ void DActiveButton::Serialize (FArchive &arc) void DActiveButton::Tick () { + if (m_SwitchDef == NULL) + { + // We lost our definition due to a bad savegame. + Destroy(); + return; + } + + FSwitchDef *def = bReturning? m_SwitchDef->PairDef : m_SwitchDef; if (--m_Timer == 0) { - FSwitchDef *def = TexMan.GetSwitch(m_SwitchDef); if (m_Frame == def->NumFrames - 1) { - m_SwitchDef = def->PairIndex; - if (m_SwitchDef != 65535) + bReturning = true; + def = m_SwitchDef->PairDef; + if (def != NULL) { - def = TexMan.GetSwitch(def->PairIndex); - m_Frame = 65535; + m_Frame = -1; S_Sound (m_X, m_Y, 0, CHAN_VOICE|CHAN_LISTENERZ, def->Sound != 0 ? FSoundID(def->Sound) : FSoundID("switches/normbutn"), 1, ATTN_STATIC); @@ -358,7 +356,7 @@ void DActiveButton::Tick () } bool killme = AdvanceFrame (); - m_Side->SetTexture(m_Part, def->u[m_Frame].Texture); + m_Side->SetTexture(m_Part, def->frames[m_Frame].Texture); if (killme) { @@ -376,7 +374,7 @@ void DActiveButton::Tick () bool DActiveButton::AdvanceFrame () { bool ret = false; - FSwitchDef *def = TexMan.GetSwitch(m_SwitchDef); + FSwitchDef *def = bReturning? m_SwitchDef->PairDef : m_SwitchDef; if (++m_Frame == def->NumFrames - 1) { @@ -391,17 +389,10 @@ bool DActiveButton::AdvanceFrame () } else { - if (def->u[m_Frame].Time & 0xffff0000) + m_Timer = def->frames[m_Frame].TimeMin; + if (def->frames[m_Frame].TimeRnd != 0) { - int t = pr_switchanim(); - - m_Timer = (WORD)((((t | (pr_switchanim() << 8)) - % def->u[m_Frame].Time) >> 16) - + (def->u[m_Frame].Time & 0xffff)); - } - else - { - m_Timer = (WORD)def->u[m_Frame].Time; + m_Timer += pr_switchanim(def->frames[m_Frame].TimeRnd); } } return ret; diff --git a/src/p_user.cpp b/src/p_user.cpp index 836b665d6c..a9c04ad499 100644 --- a/src/p_user.cpp +++ b/src/p_user.cpp @@ -432,10 +432,6 @@ void APlayerPawn::Serialize (FArchive &arc) << MorphWeapon << DamageFade << PlayerFlags; - if (SaveVersion < 2435) - { - DamageFade.a = 255; - } } //=========================================================================== @@ -2554,33 +2550,9 @@ void player_t::Serialize (FArchive &arc) << poisoncount << poisoner << attacker - << extralight; - if (SaveVersion < 1858) - { - int fixedmap; - arc << fixedmap; - fixedcolormap = NOFIXEDCOLORMAP; - fixedlightlevel = -1; - if (fixedmap >= NUMCOLORMAPS) - { - fixedcolormap = fixedmap - NUMCOLORMAPS; - } - else if (fixedmap > 0) - { - fixedlightlevel = fixedmap; - } - } - else if (SaveVersion < 1893) - { - int ll; - arc << fixedcolormap << ll; - fixedlightlevel = ll; - } - else - { - arc << fixedcolormap << fixedlightlevel; - } - arc << morphTics + << extralight + << fixedcolormap << fixedlightlevel + << morphTics << MorphedPlayerClass << MorphStyle << MorphExitFlash diff --git a/src/r_interpolate.cpp b/src/r_interpolate.cpp index f2fba2f8c0..f145347a5b 100644 --- a/src/r_interpolate.cpp +++ b/src/r_interpolate.cpp @@ -826,16 +826,7 @@ void DPolyobjInterpolation::Serialize(FArchive &arc) arc << po << oldverts; poly = polyobjs + po; - if (SaveVersion >= 2448) - { - arc << oldcx << oldcy; - } - else - { - // This will glitch if an old savegame is loaded but at least it'll allow loading it. - oldcx = poly->CenterSpot.x; - oldcy = poly->CenterSpot.y; - } + arc << oldcx << oldcy; if (arc.IsLoading()) bakverts.Resize(oldverts.Size()); } diff --git a/src/s_advsound.cpp b/src/s_advsound.cpp index c194d74482..32c2f3222f 100644 --- a/src/s_advsound.cpp +++ b/src/s_advsound.cpp @@ -2016,10 +2016,6 @@ void AAmbientSound::Serialize (FArchive &arc) { Super::Serialize (arc); arc << bActive << NextCheck; - if (SaveVersion < 2798) - { - NextCheck += level.maptime; - } } //========================================================================== diff --git a/src/textures/anim_switches.cpp b/src/textures/anim_switches.cpp index cb1b5ae8a8..ca82532034 100644 --- a/src/textures/anim_switches.cpp +++ b/src/textures/anim_switches.cpp @@ -63,8 +63,6 @@ void FTextureManager::InitSwitchList () { const BITFIELD texflags = TEXMAN_Overridable | TEXMAN_TryAny; int lump = Wads.CheckNumForName ("SWITCHES"); - FSwitchDef **origMap; - int i, j; if (lump != -1) { @@ -87,46 +85,19 @@ void FTextureManager::InitSwitchList () { def1 = (FSwitchDef *)M_Malloc (sizeof(FSwitchDef)); def2 = (FSwitchDef *)M_Malloc (sizeof(FSwitchDef)); - def1->PreTexture = def2->u[0].Texture = CheckForTexture (list_p /* .name1 */, FTexture::TEX_Wall, texflags); - def2->PreTexture = def1->u[0].Texture = CheckForTexture (list_p + 9, FTexture::TEX_Wall, texflags); + def1->PreTexture = def2->frames[0].Texture = CheckForTexture (list_p /* .name1 */, FTexture::TEX_Wall, texflags); + def2->PreTexture = def1->frames[0].Texture = CheckForTexture (list_p + 9, FTexture::TEX_Wall, texflags); def1->Sound = def2->Sound = 0; def1->NumFrames = def2->NumFrames = 1; - def1->u[0].Time = def2->u[0].Time = 0; - def2->PairIndex = AddSwitchDef (def1); - def1->PairIndex = AddSwitchDef (def2); + def1->frames[0].TimeMin = def2->frames[0].TimeMin = 0; + def1->frames[0].TimeRnd = def2->frames[0].TimeRnd = 0; + AddSwitchPair(def1, def2); } } } mSwitchDefs.ShrinkToFit (); - - // Sort mSwitchDefs for quick searching - origMap = new FSwitchDef *[mSwitchDefs.Size ()]; - for (i = 0; i < (int)mSwitchDefs.Size (); i++) - { - origMap[i] = mSwitchDefs[i]; - } - - qsort (&mSwitchDefs[0], i, sizeof(FSwitchDef *), SortSwitchDefs); - - // Correct the PairIndex of each switch def, since the sorting broke them - for (i = (int)(mSwitchDefs.Size () - 1); i >= 0; i--) - { - FSwitchDef *def = mSwitchDefs[i]; - if (def->PairIndex != 65535) - { - for (j = (int)(mSwitchDefs.Size () - 1); j >= 0; j--) - { - if (mSwitchDefs[j] == origMap[def->PairIndex]) - { - def->PairIndex = (WORD)j; - break; - } - } - } - } - - delete[] origMap; + qsort (&mSwitchDefs[0], mSwitchDefs.Size(), sizeof(FSwitchDef *), SortSwitchDefs); } //========================================================================== @@ -228,18 +199,18 @@ void FTextureManager::ProcessSwitchDef (FScanner &sc) def2 = (FSwitchDef *)M_Malloc (sizeof(FSwitchDef)); def2->Sound = def1->Sound; def2->NumFrames = 1; - def2->u[0].Time = 0; - def2->u[0].Texture = picnum; + def2->frames[0].TimeMin = 0; + def2->frames[0].TimeRnd = 0; + def2->frames[0].Texture = picnum; } def1->PreTexture = picnum; - def2->PreTexture = def1->u[def1->NumFrames-1].Texture; + def2->PreTexture = def1->frames[def1->NumFrames-1].Texture; if (def1->PreTexture == def2->PreTexture) { sc.ScriptError ("The on state for switch %s must end with a texture other than %s", picname.GetChars(), picname.GetChars()); } - def2->PairIndex = AddSwitchDef (def1); - def1->PairIndex = AddSwitchDef (def2); + AddSwitchPair(def1, def2); def1->QuestPanel = def2->QuestPanel = quest; } @@ -286,7 +257,8 @@ FSwitchDef *FTextureManager::ParseSwitchDef (FScanner &sc, bool ignoreBad) if (sc.Compare ("tics")) { sc.MustGetNumber (); - thisframe.Time = sc.Number & 65535; + thisframe.TimeMin = sc.Number & 65535; + thisframe.TimeRnd = 0; } else if (sc.Compare ("rand")) { @@ -300,11 +272,13 @@ FSwitchDef *FTextureManager::ParseSwitchDef (FScanner &sc, bool ignoreBad) { swapvalues (min, max); } - thisframe.Time = ((max - min + 1) << 16) | min; + thisframe.TimeMin = min; + thisframe.TimeRnd = (max - min + 1); } else { - thisframe.Time = 0; // Shush, GCC. + thisframe.TimeMin = 0; // Shush, GCC. + thisframe.TimeRnd = 0; sc.ScriptError ("Must specify a duration for switch frame"); } frames.Push(thisframe); @@ -324,11 +298,11 @@ FSwitchDef *FTextureManager::ParseSwitchDef (FScanner &sc, bool ignoreBad) return NULL; } - def = (FSwitchDef *)M_Malloc (myoffsetof (FSwitchDef, u[0]) + frames.Size()*sizeof(frames[0])); + def = (FSwitchDef *)M_Malloc (myoffsetof (FSwitchDef, frames[0]) + frames.Size()*sizeof(frames[0])); def->Sound = sound; def->NumFrames = frames.Size(); - memcpy (&def->u[0], &frames[0], frames.Size() * sizeof(frames[0])); - def->PairIndex = 65535; + memcpy (&def->frames[0], &frames[0], frames.Size() * sizeof(frames[0])); + def->PairDef = NULL; return def; } @@ -338,20 +312,54 @@ FSwitchDef *FTextureManager::ParseSwitchDef (FScanner &sc, bool ignoreBad) // //========================================================================== -WORD FTextureManager::AddSwitchDef (FSwitchDef *def) +void FTextureManager::AddSwitchPair (FSwitchDef *def1, FSwitchDef *def2) { unsigned int i; + FSwitchDef *sw1 = NULL; + FSwitchDef *sw2 = NULL; + unsigned int index1 = -1, index2 = -1; for (i = mSwitchDefs.Size (); i-- > 0; ) { - if (mSwitchDefs[i]->PreTexture == def->PreTexture) + if (mSwitchDefs[i]->PreTexture == def1->PreTexture) { - M_Free (mSwitchDefs[i]); - mSwitchDefs[i] = def; - return (WORD)i; + index1 = i; + sw1 = mSwitchDefs[index1]; + if (index2 != -1) break; + } + if (mSwitchDefs[i]->PreTexture == def2->PreTexture) + { + index2 = i; + sw2 = mSwitchDefs[index2]; + if (index1 != -1) break; } } - return (WORD)mSwitchDefs.Push (def); + + def1->PairDef = def2; + def2->PairDef = def1; + + if (sw1 != NULL && sw2 != NULL && sw1->PairDef == sw2 && sw2->PairDef == sw1) + { + //We are replacing an existing pair so we can safely delete the old definitions + M_Free(sw1); + M_Free(sw2); + mSwitchDefs[index1] = def1; + mSwitchDefs[index2] = def2; + } + else + { + // This new switch will not or only partially replace an existing pair. + // We should not break up an old pair if the new one only redefined one + // of the two textures. These paired definitions will only be used + // as the return animation so their names don't matter. Better clear them to be safe. + if (sw1 != NULL) sw1->PreTexture.SetInvalid(); + if (sw2 != NULL) sw2->PreTexture.SetInvalid(); + sw1 = NULL; + sw2 = NULL; + unsigned int pos = mSwitchDefs.Reserve(2); + mSwitchDefs[pos] = def1; + mSwitchDefs[pos+1] = def2; + } } //========================================================================== @@ -360,7 +368,7 @@ WORD FTextureManager::AddSwitchDef (FSwitchDef *def) // //========================================================================== -int FTextureManager::FindSwitch (FTextureID texture) +FSwitchDef *FTextureManager::FindSwitch (FTextureID texture) { int mid, low, high; @@ -373,7 +381,7 @@ int FTextureManager::FindSwitch (FTextureID texture) mid = (high + low) / 2; if (mSwitchDefs[mid]->PreTexture == texture) { - return mid; + return mSwitchDefs[mid]; } else if (texture < mSwitchDefs[mid]->PreTexture) { @@ -385,6 +393,27 @@ int FTextureManager::FindSwitch (FTextureID texture) } } while (low <= high); } - return -1; + return NULL; +} + +//========================================================================== +// +// operator<< +// +//========================================================================== + +template<> FArchive &operator<< (FArchive &arc, FSwitchDef* &Switch) +{ + if (arc.IsStoring()) + { + arc << Switch->PreTexture; + } + else + { + FTextureID tex; + arc << tex; + Switch = TexMan.FindSwitch(tex); + } + return arc; } diff --git a/src/textures/animations.cpp b/src/textures/animations.cpp index 3a75334aee..65405e5c8f 100644 --- a/src/textures/animations.cpp +++ b/src/textures/animations.cpp @@ -903,3 +903,24 @@ void FTextureManager::UpdateAnimations (DWORD mstime) } } +//========================================================================== +// +// operator<< +// +//========================================================================== + +template<> FArchive &operator<< (FArchive &arc, FDoorAnimation* &Doorani) +{ + if (arc.IsStoring()) + { + arc << Doorani->BaseTexture; + } + else + { + FTextureID tex; + arc << tex; + Doorani = TexMan.FindAnimatedDoor(tex); + } + return arc; +} + diff --git a/src/textures/textures.h b/src/textures/textures.h index 21a57d2269..4937e02ae7 100644 --- a/src/textures/textures.h +++ b/src/textures/textures.h @@ -85,15 +85,16 @@ struct FAnimDef struct FSwitchDef { FTextureID PreTexture; // texture to switch from - WORD PairIndex; // switch def to use to return to PreTexture + FSwitchDef *PairDef; // switch def to use to return to PreTexture WORD NumFrames; // # of animation frames - int Sound; // sound to play at start of animation. Changed to int to avoiud having to include s_sound here. bool QuestPanel; // Special texture for Strife mission + int Sound; // sound to play at start of animation. Changed to int to avoiud having to include s_sound here. struct frame // Array of times followed by array of textures { // actual length of each array is - DWORD Time; + WORD TimeMin; + WORD TimeRnd; FTextureID Texture; - } u[1]; + } frames[1]; }; struct FDoorAnimation @@ -397,12 +398,7 @@ public: void UpdateAnimations (DWORD mstime); int GuesstimateNumTextures (); - int FindSwitch (FTextureID texture); - FSwitchDef *GetSwitch (unsigned int index) - { - if (index < mSwitchDefs.Size()) return mSwitchDefs[index]; - else return NULL; - } + FSwitchDef *FindSwitch (FTextureID texture); FDoorAnimation *FindAnimatedDoor (FTextureID picnum); private: @@ -440,7 +436,7 @@ private: void InitSwitchList (); void ProcessSwitchDef (FScanner &sc); FSwitchDef *ParseSwitchDef (FScanner &sc, bool ignoreBad); - WORD AddSwitchDef (FSwitchDef *def); + void AddSwitchPair (FSwitchDef *def1, FSwitchDef *def2); struct TextureHash { diff --git a/src/version.h b/src/version.h index 6a99a02adc..32cd44b398 100644 --- a/src/version.h +++ b/src/version.h @@ -75,7 +75,7 @@ // SAVESIG should match SAVEVER. // MINSAVEVER is the minimum level snapshot version that can be loaded. -#define MINSAVEVER 1848 +#define MINSAVEVER 3030 #if SVN_REVISION_NUMBER < MINSAVEVER // If we don't know the current revision write something very high to ensure that @@ -85,8 +85,11 @@ static inline const char *MakeSaveSig() { static char foo[] = { 'Z','D','O','O','M','S','A','V','E', +#if SAVEVER > 99999 + '0' + (SAVEVER / 100000), +#endif #if SAVEVER > 9999 - '0' + (SAVEVER / 10000), + '0' + ((SAVEVER / 10000) % 10), #endif #if SAVEVER > 999 '0' + ((SAVEVER / 1000) % 10),