diff --git a/docs/rh-log.txt b/docs/rh-log.txt index 571355694..9efe01e0a 100644 --- a/docs/rh-log.txt +++ b/docs/rh-log.txt @@ -1,6 +1,40 @@ May 29, 2008 - Fixed: PrtScn/SysRq key did not work on Linux. +May 29, 2008 (Changes by Graf Zahl) +- Changed: The texture loader now looks for a TEXTURES lump for text based + texture definitions. HIRESTEX is still supported but deprecated. +- Removed all 16 bit values from texture manager. +- Changed: The texture manager now sorts all textures for a WAD by type + to avoid priority issues with HIRESTEX defined textures. +- Changed sidedef flag WALLF_ADDTRANS into a linedef flag because it is + always the same for both sides of a linedef. This also makes handling + this in the UDMF parser easier because the linedef parsing function does + not need to access the sidedef data. +- Added new ZDoom specific UDMF linedef and sidedef properties to map parser. + +May 28, 2008 (Changes by Graf Zahl) +- Added new ZDoom specific UDMF sector properties to map parser. +- Added class definitions for new interpolators that are better + equipped to interact with the interpolated objects. +- Separated interpolation code into its own file r_interpolate.cpp. +- Added some simple customization options to the end game screens. + +May 27, 2008 (Changes by Graf Zahl) +- Fixed: Polyobject detection in the internal node builder did not work + anymore due to some code rearrangement for UDMF map loading. To keep + it compatible between all map formats the THINGS lump of binary format + maps must be loaded before building the nodes. This also means that + the spawning itself can be done in the same function for all map types + (except Build) now. +- Changed 'Smooth mouse movement' menu option from m_filter to smooth_mouse + which is more what would be expected from this option. +- Fixed: Weapons and ammo items that were modified by Dehacked gave full + ammo when being dropped by monsters. To properly handle this the + handling of spawning Dehacked modified pickups was changed to use + the DECORATE replacement feature instead of hacking the spawn state + of the original item and calling a spawn function from there. + May 28, 2008 - Added an alternate module replay engine that uses foo_dumb's replayer, a heavily customized version of DUMB (Dynamic Universal Music Bibliotheque). diff --git a/src/d_dehacked.cpp b/src/d_dehacked.cpp index 01af1cadf..6106ba120 100644 --- a/src/d_dehacked.cpp +++ b/src/d_dehacked.cpp @@ -145,39 +145,13 @@ DehInfo deh = // from the original actor's defaults. The original actor is then changed to // spawn the new class. -void A_SpawnDehackedPickup (AActor *); - -class ADehackedPickup : public AInventory -{ - DECLARE_ACTOR (ADehackedPickup, AInventory) - HAS_OBJECT_POINTERS -public: - void Destroy (); - const char *PickupMessage (); - bool ShouldRespawn (); - bool ShouldStay (); - bool TryPickup (AActor *toucher); - void PlayPickupSound (AActor *toucher); - void DoPickupSpecial (AActor *toucher); -private: - const PClass *DetermineType (); - AInventory *RealPickup; -}; - IMPLEMENT_POINTY_CLASS (ADehackedPickup) DECLARE_POINTER (RealPickup) END_POINTERS -FState ADehackedPickup::States[] = -{ - S_NORMAL(TNT1, 0, 0, NULL, &States[1]), - S_NORMAL(TNT1, 0, 0, A_SpawnDehackedPickup, NULL) -}; - -BEGIN_DEFAULTS (ADehackedPickup, Any, -1, 0) +BEGIN_STATELESS_DEFAULTS (ADehackedPickup, Any, -1, 0) END_DEFAULTS -TArray DehackedPickups; TArray TouchedActors; char *UnchangedSpriteNames; @@ -2613,22 +2587,15 @@ void FinishDehPatch () (typeNameBuilder, sizeof(ADehackedPickup)); AActor *defaults2 = GetDefaultByType (subclass); memcpy (defaults2, defaults1, sizeof(AActor)); - subclass->ActorInfo->GameFilter = type->ActorInfo->GameFilter; - subclass->ActorInfo->SpawnID = type->ActorInfo->SpawnID; - subclass->ActorInfo->DoomEdNum = type->ActorInfo->DoomEdNum; + // Make a copy the state labels MakeStateDefines(type->ActorInfo->StateList); InstallStates(subclass->ActorInfo, defaults2); - // Alter the original class so that it just spawns the new one - //memcpy (defaults1, GetDefault(), sizeof(AActor)); - defaults1->SpawnState = &ADehackedPickup::States[0]; - defaults1->flags = 0; - defaults1->flags2 = 0; - defaults1->flags3 = 0; - defaults1->health = DehackedPickups.Push (subclass); - type->ActorInfo->SpawnID = 0; - type->ActorInfo->DoomEdNum = -1; + // Use the DECORATE replacement feature to redirect all spawns + // of the original class to the new one. + type->ActorInfo->Replacement = subclass->ActorInfo; + subclass->ActorInfo->Replacee = type->ActorInfo; DPrintf ("%s replaces %s\n", subclass->TypeName.GetChars(), type->TypeName.GetChars()); } @@ -2641,29 +2608,6 @@ void FinishDehPatch () } } -void A_SpawnDehackedPickup (AActor *actor) -{ - if ((size_t)actor->health < DehackedPickups.Size()) - { - AActor *real = Spawn (DehackedPickups[actor->health], actor->x, actor->y, actor->z, NO_REPLACE); - if (real != NULL) - { - // Copy properties from the original item to the dehacked pickup it spawns - if (actor->flags & MF_DROPPED) - { - real->flags |= MF_DROPPED; - } - real->special = actor->special; - memcpy (real->args, actor->args, sizeof(real->args)); - if (actor->tid != 0) - { - real->tid = actor->tid; - real->AddToHash (); - } - } - } -} - bool ADehackedPickup::TryPickup (AActor *toucher) { const PClass *type = DetermineType (); @@ -2678,6 +2622,20 @@ bool ADehackedPickup::TryPickup (AActor *toucher) { RealPickup->flags &= ~MF_DROPPED; } + // If this item has been dropped by a monster the + // amount of ammo this gives must be halved. + if (droppedbymonster) + { + if (RealPickup->IsKindOf(RUNTIME_CLASS(AWeapon))) + { + static_cast(RealPickup)->AmmoGive1 /= 2; + static_cast(RealPickup)->AmmoGive2 /= 2; + } + else if (RealPickup->IsKindOf(RUNTIME_CLASS(AAmmo))) + { + RealPickup->Amount /= 2; + } + } if (!RealPickup->TryPickup (toucher)) { RealPickup->Destroy (); @@ -2759,3 +2717,8 @@ const PClass *ADehackedPickup::DetermineType () return NULL; } +void ADehackedPickup::Serialize(FArchive &arc) +{ + Super::Serialize(arc); + arc << droppedbymonster; +} diff --git a/src/d_dehacked.h b/src/d_dehacked.h index 9650b6a28..2d7203655 100644 --- a/src/d_dehacked.h +++ b/src/d_dehacked.h @@ -34,6 +34,29 @@ #ifndef __D_DEHACK_H__ #define __D_DEHACK_H__ +#include "a_pickups.h" + +class ADehackedPickup : public AInventory +{ + DECLARE_STATELESS_ACTOR (ADehackedPickup, AInventory) + HAS_OBJECT_POINTERS +public: + void Destroy (); + const char *PickupMessage (); + bool ShouldRespawn (); + bool ShouldStay (); + bool TryPickup (AActor *toucher); + void PlayPickupSound (AActor *toucher); + void DoPickupSpecial (AActor *toucher); + void Serialize(FArchive &arc); +private: + const PClass *DetermineType (); + AInventory *RealPickup; +public: + bool droppedbymonster; +}; + + void DoDehPatch (const char *patchfile, bool autoloading); void FinishDehPatch (); diff --git a/src/dobject.h b/src/dobject.h index bbfa58b3d..708648e29 100644 --- a/src/dobject.h +++ b/src/dobject.h @@ -456,7 +456,7 @@ public: // use this method. virtual size_t PointerSubstitution (DObject *old, DObject *notOld); static size_t StaticPointerSubstitution (DObject *old, DObject *notOld); - + PClass *GetClass() const { if (Class == NULL) diff --git a/src/doomdata.h b/src/doomdata.h index 33b3395c4..b1ef43682 100644 --- a/src/doomdata.h +++ b/src/doomdata.h @@ -139,6 +139,8 @@ struct maplinedef2_t #define ML_SPAC_SHIFT 10 #define ML_SPAC_MASK 0x1c00 // Hexen's activator mask. These flags are no longer used. +#define ML_ADDTRANS 0x400 // additive translucency (can only be set internally) + // Extended flags #define ML_MONSTERSCANACTIVATE 0x00002000 // [RH] Monsters (as well as players) can active the line #define ML_BLOCK_PLAYERS 0x00004000 diff --git a/src/f_finale.cpp b/src/f_finale.cpp index d70125fac..4ededf3f4 100644 --- a/src/f_finale.cpp +++ b/src/f_finale.cpp @@ -252,9 +252,15 @@ void F_Ticker () wipegamestate = GS_FORCEWIPE; if (EndSequences[FinaleSequence].EndType == END_Bunny) { - S_StartMusic ("d_bunny"); + if (!EndSequences[FinaleSequence].Advanced) + S_StartMusic ("d_bunny"); } } + if (EndSequences[FinaleSequence].Advanced && + !EndSequences[FinaleSequence].Music.IsEmpty()) + { + S_ChangeMusic(EndSequences[FinaleSequence].Music, 0, EndSequences[FinaleSequence].MusicLooping); + } } } else @@ -590,7 +596,8 @@ void F_StartCast (void) castframes = 0; castonmelee = 0; castattacking = false; - S_ChangeMusic ("d_evil"); + if (!EndSequences[FinaleSequence].Advanced) + S_ChangeMusic ("d_evil"); } @@ -782,8 +789,21 @@ void F_CastDrawer (void) void F_DemonScroll () { + const char *tex1, *tex2; + if (EndSequences[FinaleSequence].Advanced) + { + tex1 = EndSequences[FinaleSequence].PicName; + tex2 = EndSequences[FinaleSequence].PicName2; + } + else + { + tex1 = "FINAL1"; + tex2 = "FINAL2"; + } + int yval; - FTexture *final1 = TexMan("FINAL1"); + FTexture *final1 = TexMan(tex1); + FTexture *final2 = TexMan(tex2); int fwidth = final1->GetWidth(); int fheight = final1->GetHeight(); @@ -806,7 +826,7 @@ void F_DemonScroll () DTA_VirtualHeight, fheight, DTA_Masked, false, TAG_DONE); - screen->DrawTexture (TexMan("FINAL2"), 0, yval - fheight, + screen->DrawTexture (final2, 0, yval - fheight, DTA_VirtualWidth, fwidth, DTA_VirtualHeight, fheight, DTA_Masked, false, @@ -814,7 +834,7 @@ void F_DemonScroll () } else { //else, we'll just sit here and wait, for now - screen->DrawTexture (TexMan("FINAL2"), 0, 0, + screen->DrawTexture (final2, 0, 0, DTA_VirtualWidth, fwidth, DTA_VirtualHeight, fheight, DTA_Masked, false, @@ -902,35 +922,51 @@ void F_DrawUnderwater(void) */ void F_BunnyScroll (void) { - static const char tex1name[2][8] = { "CREDIT", "PFUB1" }; - static const char tex2name[2][8] = { "VELLOGO", "PFUB2" }; - static size_t laststage; - bool bunny = EndSequences[FinaleSequence].EndType != END_BuyStrife; + bool bunny = false; int scrolled; char name[10]; size_t stage; FTexture *tex; int fwidth; int fheight; + const char *tex1; + const char *tex2; + + if (EndSequences[FinaleSequence].Advanced) + { + tex1 = EndSequences[FinaleSequence].PicName; + tex2 = EndSequences[FinaleSequence].PicName2; + bunny = EndSequences[FinaleSequence].PlayTheEnd; + } + else if (EndSequences[FinaleSequence].EndType == END_BuyStrife) + { + tex1 = "CREDIT"; + tex2 = "VELLOGO"; + } + else + { + tex1 = "PFUB1"; + tex2 = "PFUB2"; + bunny = true; + } V_MarkRect (0, 0, SCREENWIDTH, SCREENHEIGHT); - tex = TexMan(tex1name[bunny]); + tex = TexMan(tex1); fwidth = tex->GetWidth(); fheight = tex->GetHeight(); scrolled = clamp (((signed)FinaleCount-230)*fwidth/640, 0, fwidth); - tex = TexMan(tex1name[bunny]); screen->DrawTexture (tex, scrolled, 0, DTA_VirtualWidth, fwidth, DTA_VirtualHeight, fheight, DTA_Masked, false, TAG_DONE); - tex = TexMan(tex2name[bunny]); + tex = TexMan(tex2); screen->DrawTexture (tex, scrolled - fwidth, 0, DTA_VirtualWidth, fwidth, DTA_VirtualHeight, fheight, diff --git a/src/g_level.cpp b/src/g_level.cpp index 0060ca177..e287d454d 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -910,7 +910,62 @@ static void ParseMapInfoLower (FScanner &sc, sprintf (sc.String, "MAP%02d", map); } } - if (strnicmp (sc.String, "EndGame", 7) == 0) + if (sc.Compare ("endgame")) + { + newSeq.Advanced = true; + newSeq.EndType = END_Pic1; + newSeq.PlayTheEnd = false; + newSeq.MusicLooping = true; + sc.MustGetStringName("{"); + while (!sc.CheckString("}")) + { + sc.MustGetString(); + if (sc.Compare("pic")) + { + sc.MustGetString(); + newSeq.EndType = END_Pic; + strncpy (newSeq.PicName, sc.String, 8); + newSeq.PicName[8] = 0; + } + else if (sc.Compare("hscroll")) + { + newSeq.EndType = END_Bunny; + sc.MustGetString(); + strncpy (newSeq.PicName, sc.String, 8); + newSeq.PicName[8] = 0; + sc.MustGetString(); + strncpy (newSeq.PicName2, sc.String, 8); + newSeq.PicName2[8] = 0; + if (sc.CheckNumber()) + newSeq.PlayTheEnd = !!sc.Number; + } + else if (sc.Compare("vscroll")) + { + newSeq.EndType = END_Demon; + sc.MustGetString(); + strncpy (newSeq.PicName, sc.String, 8); + newSeq.PicName[8] = 0; + sc.MustGetString(); + strncpy (newSeq.PicName2, sc.String, 8); + newSeq.PicName2[8] = 0; + } + else if (sc.Compare("cast")) + { + newSeq.EndType = END_Cast; + } + else if (sc.Compare("music")) + { + sc.MustGetString(); + newSeq.Music = sc.String; + if (sc.CheckNumber()) + { + newSeq.MusicLooping = !!sc.Number; + } + } + } + useseq = true; + } + else if (strnicmp (sc.String, "EndGame", 7) == 0) { int type; switch (sc.String[7]) @@ -970,7 +1025,13 @@ static void ParseMapInfoLower (FScanner &sc, } if (useseq) { - int seqnum = FindEndSequence (newSeq.EndType, newSeq.PicName); + int seqnum = -1; + + if (!newSeq.Advanced) + { + seqnum = FindEndSequence (newSeq.EndType, newSeq.PicName); + } + if (seqnum == -1) { seqnum = (int)EndSequences.Push (newSeq); @@ -1286,7 +1347,7 @@ static int FindEndSequence (int type, const char *picname) num = EndSequences.Size (); for (i = 0; i < num; i++) { - if (EndSequences[i].EndType == type && + if (EndSequences[i].EndType == type && !EndSequences[i].Advanced && (type != END_Pic || stricmp (EndSequences[i].PicName, picname) == 0)) { return (int)i; diff --git a/src/g_level.h b/src/g_level.h index cce5ab220..6673bb355 100644 --- a/src/g_level.h +++ b/src/g_level.h @@ -281,7 +281,12 @@ enum EndTypes struct EndSequence { BYTE EndType; + bool Advanced; + bool MusicLooping; + bool PlayTheEnd; char PicName[9]; + char PicName2[9]; + FString Music; }; extern TArray EndSequences; diff --git a/src/m_options.cpp b/src/m_options.cpp index 4782756e1..2bb774f6c 100644 --- a/src/m_options.cpp +++ b/src/m_options.cpp @@ -229,7 +229,7 @@ menu_t OptionMenu = *=======================================*/ EXTERN_CVAR (Bool, use_mouse) -EXTERN_CVAR (Bool, m_filter) +EXTERN_CVAR (Bool, smooth_mouse) EXTERN_CVAR (Float, m_forward) EXTERN_CVAR (Float, m_pitch) EXTERN_CVAR (Float, m_side) @@ -245,7 +245,7 @@ static menuitem_t MouseItems[] = { redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} }, { slider, "Overall sensitivity", {&mouse_sensitivity}, {0.5}, {2.5}, {0.1}, {NULL} }, { discrete, "Prescale mouse movement",{&m_noprescale}, {2.0}, {0.0}, {0.0}, {NoYes} }, - { discrete, "Smooth mouse movement",{&m_filter}, {2.0}, {0.0}, {0.0}, {YesNo} }, + { discrete, "Smooth mouse movement",{&smooth_mouse}, {2.0}, {0.0}, {0.0}, {YesNo} }, { redtext, " ", {NULL}, {0.0}, {0.0}, {0.0}, {NULL} }, { slider, "Turning speed", {&m_yaw}, {0.5}, {2.5}, {0.1}, {NULL} }, { slider, "Mouselook speed", {&m_pitch}, {0.5}, {2.5}, {0.1}, {NULL} }, diff --git a/src/namedef.h b/src/namedef.h index c307c3744..ad235754f 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -334,3 +334,37 @@ xx(Monsterpush) xx(ZDoom) xx(ZDoomTranslated) + +xx(Xpanningfloor) +xx(Ypanningfloor) +xx(Xpanningceiling) +xx(Ypanningceiling) +xx(Xscalefloor) +xx(Yscalefloor) +xx(Xscaleceiling) +xx(Yscaleceiling) +xx(Rotationfloor) +xx(Rotationceiling) +xx(Lightfloor) +xx(Lightceiling) +xx(Lightfloorabsolute) +xx(Lightceilingabsolute) +xx(Gravity) +xx(Lightcolor) +xx(Fadecolor) +xx(Desaturation) +xx(Silent) +xx(Nofallingdamage) +xx(Dropactors) + +xx(offsetx_top) +xx(offsety_top) +xx(offsetx_mid) +xx(offsety_mid) +xx(offsetx_bottom) +xx(offsety_bottom) +xx(light) +xx(lightabsolute) +xx(nofakecontrast) + +xx(Renderstyle) \ No newline at end of file diff --git a/src/p_enemy.cpp b/src/p_enemy.cpp index 459566390..a61b87266 100644 --- a/src/p_enemy.cpp +++ b/src/p_enemy.cpp @@ -45,6 +45,7 @@ #include "a_doomglobal.h" #include "a_action.h" #include "thingdef/thingdef.h" +#include "d_dehacked.h" #include "gi.h" @@ -2415,6 +2416,11 @@ AInventory *P_DropItem (AActor *source, const PClass *type, int special, int cha // The same goes for ammo from a weapon. static_cast(mo)->AmmoGive1 /= 2; static_cast(mo)->AmmoGive2 /= 2; + } + else if (mo->IsKindOf (RUNTIME_CLASS(ADehackedPickup))) + { + // For weapons and ammo modified by Dehacked we need to flag the item. + static_cast(mo)->droppedbymonster = true; } if (inv->SpecialDropAction (source)) { diff --git a/src/p_lnspec.cpp b/src/p_lnspec.cpp index a9145d7e5..716871ec8 100644 --- a/src/p_lnspec.cpp +++ b/src/p_lnspec.cpp @@ -2630,19 +2630,11 @@ FUNC(LS_TranslucentLine) lines[linenum].Alpha = Scale(clamp(arg1, 0, 255), FRACUNIT, 255); if (arg2 == 0) { - sides[lines[linenum].sidenum[0]].Flags &= ~WALLF_ADDTRANS; - if (lines[linenum].sidenum[1] != NO_SIDE) - { - sides[lines[linenum].sidenum[1]].Flags &= ~WALLF_ADDTRANS; - } + lines[linenum].flags &= ~ML_ADDTRANS; } else if (arg2 == 1) { - sides[lines[linenum].sidenum[0]].Flags |= WALLF_ADDTRANS; - if (lines[linenum].sidenum[1] != NO_SIDE) - { - sides[lines[linenum].sidenum[1]].Flags |= WALLF_ADDTRANS; - } + lines[linenum].flags |= ML_ADDTRANS; } else { diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index ad17ec949..f2976e51c 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -3688,7 +3688,7 @@ APlayerPawn *P_SpawnPlayer (FMapThing *mthing, bool tempplayer) if (multiplayer) { - unsigned an = ( ANG45 * (mthing->angle/45) ) >> ANGLETOFINESHIFT; + unsigned an = mobj->angle >> ANGLETOFINESHIFT; Spawn ("TeleportFog", mobj->x+20*finecosine[an], mobj->y+20*finesine[an], mobj->z + TELEFOGHEIGHT, ALLOW_REPLACE); } diff --git a/src/p_setup.cpp b/src/p_setup.cpp index c4b5e0d41..8339bea87 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -70,7 +70,6 @@ extern bool P_LoadBuildMap (BYTE *mapdata, size_t len, FMapThing **things, int * extern void P_TranslateTeleportThings (void); void P_ParseTextMap(MapData *map); -void P_SpawnTextThings(int position); extern int numinterpolations; extern unsigned int R_OldBlend; @@ -1369,9 +1368,8 @@ WORD MakeSkill(int flags) return res; } -void P_LoadThings (MapData * map, int position) +void P_LoadThings (MapData * map) { - FMapThing mt2; // [RH] for translation int lumplen = map->Size(ML_THINGS); int numthings = lumplen / sizeof(mapthing_t); @@ -1382,6 +1380,9 @@ void P_LoadThings (MapData * map, int position) map->Read(ML_THINGS, mtp); mt = (mapthing_t*)mtp; + MapThingsConverted.Resize(numthings); + FMapThing *mti = &MapThingsConverted[0]; + // [RH] ZDoom now uses Hexen-style maps as its native format. // Since this is the only place where Doom-style Things are ever // referenced, we translate them into a Hexen-style thing. @@ -1395,20 +1396,20 @@ void P_LoadThings (MapData * map, int position) // [RH] Need to translate the spawn flags to Hexen format. short flags = LittleShort(mt->options); - memset (&mt2, 0, sizeof(mt2)); + memset (&mti[i], 0, sizeof(mti[i])); - mt2.SkillFilter = MakeSkill(flags); - mt2.ClassFilter = 0xffff; // Doom map format doesn't have class flags so spawn for all player classes + mti[i].SkillFilter = MakeSkill(flags); + mti[i].ClassFilter = 0xffff; // Doom map format doesn't have class flags so spawn for all player classes flags &= ~MTF_SKILLMASK; - mt2.flags = (short)((flags & 0xf) | 0x7e0); + mti[i].flags = (short)((flags & 0xf) | 0x7e0); if (gameinfo.gametype == GAME_Strife) { - mt2.flags &= ~MTF_AMBUSH; - if (flags & STF_SHADOW) mt2.flags |= MTF_SHADOW; - if (flags & STF_ALTSHADOW) mt2.flags |= MTF_ALTSHADOW; - if (flags & STF_STANDSTILL) mt2.flags |= MTF_STANDSTILL; - if (flags & STF_AMBUSH) mt2.flags |= MTF_AMBUSH; - if (flags & STF_FRIENDLY) mt2.flags |= MTF_FRIENDLY; + mti[i].flags &= ~MTF_AMBUSH; + if (flags & STF_SHADOW) mti[i].flags |= MTF_SHADOW; + if (flags & STF_ALTSHADOW) mti[i].flags |= MTF_ALTSHADOW; + if (flags & STF_STANDSTILL) mti[i].flags |= MTF_STANDSTILL; + if (flags & STF_AMBUSH) mti[i].flags |= MTF_AMBUSH; + if (flags & STF_FRIENDLY) mti[i].flags |= MTF_FRIENDLY; } else { @@ -1416,18 +1417,16 @@ void P_LoadThings (MapData * map, int position) { flags &= 0x1F; } - if (flags & BTF_NOTDEATHMATCH) mt2.flags &= ~MTF_DEATHMATCH; - if (flags & BTF_NOTCOOPERATIVE) mt2.flags &= ~MTF_COOPERATIVE; - if (flags & BTF_FRIENDLY) mt2.flags |= MTF_FRIENDLY; + if (flags & BTF_NOTDEATHMATCH) mti[i].flags &= ~MTF_DEATHMATCH; + if (flags & BTF_NOTCOOPERATIVE) mti[i].flags &= ~MTF_COOPERATIVE; + if (flags & BTF_FRIENDLY) mti[i].flags |= MTF_FRIENDLY; } - if (flags & BTF_NOTSINGLE) mt2.flags &= ~MTF_SINGLE; + if (flags & BTF_NOTSINGLE) mti[i].flags &= ~MTF_SINGLE; - mt2.x = LittleShort(mt->x) << FRACBITS; - mt2.y = LittleShort(mt->y) << FRACBITS; - mt2.angle = LittleShort(mt->angle); - mt2.type = LittleShort(mt->type); - - SpawnMapThing (i, &mt2, position); + mti[i].x = LittleShort(mt->x) << FRACBITS; + mti[i].y = LittleShort(mt->y) << FRACBITS; + mti[i].angle = LittleShort(mt->angle); + mti[i].type = LittleShort(mt->type); } delete [] mtp; } @@ -1444,12 +1443,11 @@ void P_LoadThings (MapData * map, int position) // //=========================================================================== -void P_LoadThings2 (MapData * map, int position) +void P_LoadThings2 (MapData * map) { int lumplen = map->MapLumps[ML_THINGS].Size; int numthings = lumplen / sizeof(mapthinghexen_t); - int i; char *mtp; MapThingsConverted.Resize(numthings); @@ -1475,13 +1473,19 @@ void P_LoadThings2 (MapData * map, int position) mti[i].flags &= ~(MTF_SKILLMASK|MTF_CLASS_MASK); } delete[] mtp; +} + + +void P_SpawnThings (int position) +{ + int numthings = MapThingsConverted.Size(); // [RH] Spawn slope creating things first. - P_SpawnSlopeMakers (mti, mti + numthings); + P_SpawnSlopeMakers (&MapThingsConverted[0], &MapThingsConverted[numthings]); - for (i=0; i < numthings; i++) + for (int i=0; i < numthings; i++) { - SpawnMapThing (i, &mti[i], position); + SpawnMapThing (i, &MapThingsConverted[i], position); } } @@ -1638,11 +1642,7 @@ void P_FinishLoadingLineDef(line_t *ld, int alpha) ld->Alpha = alpha; if (ld->args[2] == 1) { - sides[ld->sidenum[0]].Flags |= WALLF_ADDTRANS; - if (ld->sidenum[1] != NO_SIDE) - { - sides[ld->sidenum[1]].Flags |= WALLF_ADDTRANS; - } + ld->flags |= ML_ADDTRANS; } } else @@ -1654,11 +1654,7 @@ void P_FinishLoadingLineDef(line_t *ld, int alpha) lines[j].Alpha = alpha; if (lines[j].args[2] == 1) { - sides[lines[j].sidenum[0]].Flags |= WALLF_ADDTRANS; - if (lines[j].sidenum[1] != NO_SIDE) - { - sides[lines[j].sidenum[1]].Flags |= WALLF_ADDTRANS; - } + lines[j].flags |= ML_ADDTRANS; } } } @@ -3311,6 +3307,10 @@ void P_SetupLevel (char *lumpname, int position) P_FinishLoadingLineDefs (); unclock (times[5]); + if (!map->HasBehavior) + P_LoadThings (map); + else + P_LoadThings2 (map); // [RH] Load Hexen-style things } else { @@ -3446,15 +3446,8 @@ void P_SetupLevel (char *lumpname, int position) if (!buildmap) { - if (!map->isText) - { - clock (times[14]); - if (!map->HasBehavior) - P_LoadThings (map, position); - else - P_LoadThings2 (map, position); // [RH] Load Hexen-style things - } - else P_SpawnTextThings(position); + clock (times[14]); + P_SpawnThings(position); for (i = 0; i < MAXPLAYERS; ++i) { @@ -3464,7 +3457,7 @@ void P_SetupLevel (char *lumpname, int position) unclock (times[14]); clock (times[15]); - if (!map->HasBehavior) + if (!map->HasBehavior && !map->isText) P_TranslateTeleportThings (); // [RH] Assign teleport destination TIDs unclock (times[15]); } diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index a84aaabc8..855ec5335 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -42,7 +42,13 @@ #include "i_system.h" #include "gi.h" -// These tables define whichline an +//=========================================================================== +// +// Maps for Hexen namespace need to filter out all extended line and sector +// specials to comply with the spec. +// +//=========================================================================== + static char HexenLineSpecialOk[]={ 1,1,1,1,1,1,1,1,1,0, // 0-9 1,1,1,1,0,0,0,0,0,0, // 10-19 @@ -136,6 +142,12 @@ struct UDMFParser fogMap = normMap = NULL; } + //=========================================================================== + // + // Parses a 'key = value' line of the map but doesn't read the semicolon + // + //=========================================================================== + FName ParseKey() { sc.MustGetString(); @@ -163,6 +175,12 @@ struct UDMFParser return key; } + //=========================================================================== + // + // Syntax checks + // + //=========================================================================== + int CheckInt(const char *key) { if (sc.TokenType != TK_IntConst) @@ -176,7 +194,7 @@ struct UDMFParser { if (sc.TokenType != TK_IntConst && sc.TokenType != TK_FloatConst) { - sc.ScriptMessage("Floatint point value expected for key '%s'", key); + sc.ScriptMessage("Floating point value expected for key '%s'", key); } return sc.Float; } @@ -209,6 +227,12 @@ struct UDMFParser else value &= ~mask; } + //=========================================================================== + // + // Parse a thing block + // + //=========================================================================== + void ParseThing(FMapThing *th) { memset(th, 0, sizeof(*th)); @@ -373,6 +397,12 @@ struct UDMFParser } } + //=========================================================================== + // + // Parse a linedef block + // + //=========================================================================== + void ParseLinedef(line_t *ld) { bool passuse = false; @@ -538,6 +568,19 @@ struct UDMFParser // This switch contains all keys which are ZDoom specific if (namespace_bits & (Zd|Zdt)) switch(key) { + case NAME_Alpha: + ld->Alpha = CheckFixed(key); + break; + + case NAME_Renderstyle: + { + const char *str = CheckString(key); + if (!stricmp(str, "translucent")) ld->flags &= ~ML_ADDTRANS; + else if (!stricmp(str, "add")) ld->flags |= ML_ADDTRANS; + else sc.ScriptMessage("Unknown value \"%s\" for 'renderstyle'\n", str); + break; + } + case NAME_Anycross: Flag(ld->activation, SPAC_AnyCross, key); break; @@ -605,6 +648,12 @@ struct UDMFParser } } + //=========================================================================== + // + // Parse a sidedef block + // + //=========================================================================== + void ParseSidedef(side_t *sd, mapsidedef_t *sdt) { fixed_t texofs[2]={0,0}; @@ -647,6 +696,52 @@ struct UDMFParser default: break; } + + if (namespace_bits & (Zd|Zdt)) switch(key) + { + case NAME_offsetx_top: + sd->SetTextureXOffset(side_t::top, CheckFixed(key)); + break; + + case NAME_offsety_top: + sd->SetTextureYOffset(side_t::top, CheckFixed(key)); + break; + + case NAME_offsetx_mid: + sd->SetTextureXOffset(side_t::mid, CheckFixed(key)); + break; + + case NAME_offsety_mid: + sd->SetTextureYOffset(side_t::mid, CheckFixed(key)); + break; + + case NAME_offsetx_bottom: + sd->SetTextureXOffset(side_t::bottom, CheckFixed(key)); + break; + + case NAME_offsety_bottom: + sd->SetTextureYOffset(side_t::bottom, CheckFixed(key)); + break; + + case NAME_light: + sd->Light = CheckInt(key); + break; + + case NAME_lightabsolute: + if (CheckBool(key)) sd->Flags|=WALLF_ABSLIGHTING; + else sd->Flags&=~WALLF_ABSLIGHTING; + break; + + case NAME_nofakecontrast: + if (CheckBool(key)) sd->Flags&=~WALLF_AUTOCONTRAST; + else sd->Flags|=WALLF_AUTOCONTRAST; + break; + + default: + break; + + } + sc.MustGetToken(';'); } // initialization of these is delayed to allow separate offsets and add them with the global ones. @@ -658,8 +753,18 @@ struct UDMFParser sd->AddTextureYOffset(side_t::bottom, texofs[1]); } + //=========================================================================== + // + // parse a sector block + // + //=========================================================================== + void ParseSector(sector_t *sec) { + int lightcolor = -1; + int fadecolor = -1; + int desaturation = -1; + memset(sec, 0, sizeof(*sec)); sec->lightlevel = 160; sec->floor_xscale = FRACUNIT; // [RH] floor and ceiling scaling @@ -726,6 +831,99 @@ struct UDMFParser default: break; } + + if (namespace_bits & (Zd|Zdt)) switch(key) + { + case NAME_Xpanningfloor: + sec->floor_xoffs = CheckFixed(key); + break; + + case NAME_Ypanningfloor: + sec->floor_yoffs = CheckFixed(key); + break; + + case NAME_Xpanningceiling: + sec->ceiling_xoffs = CheckFixed(key); + break; + + case NAME_Ypanningceiling: + sec->ceiling_yoffs = CheckFixed(key); + break; + + case NAME_Xscalefloor: + sec->floor_xscale = CheckFixed(key); + break; + + case NAME_Yscalefloor: + sec->floor_yscale = CheckFixed(key); + break; + + case NAME_Xscaleceiling: + sec->ceiling_xscale = CheckFixed(key); + break; + + case NAME_Yscaleceiling: + sec->ceiling_yscale = CheckFixed(key); + break; + + case NAME_Rotationfloor: + sec->floor_angle = CheckFixed(key); + break; + + case NAME_Rotationceiling: + sec->ceiling_angle = CheckFixed(key); + break; + + case NAME_Lightfloor: + sec->FloorLight = CheckInt(key); + break; + + case NAME_Lightceiling: + sec->CeilingLight = CheckInt(key); + break; + + case NAME_Lightfloorabsolute: + if (CheckBool(key)) sec->FloorFlags |= SECF_ABSLIGHTING; + else sec->FloorFlags &= ~SECF_ABSLIGHTING; + break; + + case NAME_Lightceilingabsolute: + if (CheckBool(key)) sec->CeilingFlags |= SECF_ABSLIGHTING; + else sec->CeilingFlags &= ~SECF_ABSLIGHTING; + break; + + case NAME_Gravity: + sec->gravity = float(CheckFloat(key)); + break; + + case NAME_Lightcolor: + lightcolor = CheckInt(key); + break; + + case NAME_Fadecolor: + fadecolor = CheckInt(key); + break; + + case NAME_Desaturation: + desaturation = int(255*CheckFloat(key)); + break; + + case NAME_Silent: + Flag(sec->Flags, SECF_SILENT, key); + break; + + case NAME_Nofallingdamage: + Flag(sec->Flags, SECF_NOFALLINGDAMAGE, key); + break; + + case NAME_Dropactors: + Flag(sec->Flags, SECF_FLOORDROP, key); + break; + + default: + break; + } + sc.MustGetToken(';'); } @@ -752,6 +950,12 @@ struct UDMFParser } } + //=========================================================================== + // + // parse a vertex block + // + //=========================================================================== + void ParseVertex(vertex_t *vt) { vt->x = vt->y = 0; @@ -778,6 +982,12 @@ struct UDMFParser } } + //=========================================================================== + // + // Processes the linedefs after the map has been loaded + // + //=========================================================================== + void ProcessLineDefs() { int sidecount = 0; @@ -845,6 +1055,12 @@ struct UDMFParser } } + //=========================================================================== + // + // Main parsing function + // + //=========================================================================== + void ParseTextMap(MapData *map) { char *buffer = new char[map->Size(ML_TEXTMAP)]; @@ -983,11 +1199,3 @@ void P_ParseTextMap(MapData *map) parse.ParseTextMap(map); } - -void P_SpawnTextThings(int position) -{ - for(unsigned i=0; i Textures; - TArray Translation; - WORD HashFirst[HASH_SIZE]; + TArray Translation; + int HashFirst[HASH_SIZE]; int DefaultTexture; }; diff --git a/src/r_interpolate.cpp b/src/r_interpolate.cpp new file mode 100644 index 000000000..c282dad43 --- /dev/null +++ b/src/r_interpolate.cpp @@ -0,0 +1,449 @@ +// Stuff from BUILD to interpolate floors and ceilings +// +// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman +// Ken Silverman's official web site: "http://www.advsys.net/ken" +// See the included license file "BUILDLIC.TXT" for license info. +// This code has been modified from its original form. + +#include "r_data.h" +#include "p_3dmidtex.h" +#include "stats.h" + +struct FActiveInterpolation +{ + FActiveInterpolation *Next; + void *Address; + EInterpType Type; + + friend FArchive &operator << (FArchive &arc, FActiveInterpolation *&interp); + + static int CountInterpolations (); + static int CountInterpolations (int *usedbuckets, int *minbucketfill, int *maxbucketfill); + +private: + fixed_t oldipos[2], bakipos[2]; + + void CopyInterpToOld(); + void CopyBakToInterp(); + void DoAnInterpolation(fixed_t smoothratio); + + static size_t HashKey(EInterpType type, void *interptr); + static FActiveInterpolation *FindInterpolation(EInterpType, void *interptr, FActiveInterpolation **&interp_p); + + friend void updateinterpolations(); + friend void setinterpolation(EInterpType, void *interptr, bool dolinks); + friend void stopinterpolation(EInterpType, void *interptr, bool dolinks); + friend void dointerpolations(fixed_t smoothratio); + friend void restoreinterpolations(); + friend void clearinterpolations(); + friend void SerializeInterpolations(FArchive &arc); + + static FActiveInterpolation *curiposhash[INTERPOLATION_BUCKETS]; +}; + + + +static bool didInterp; + +FActiveInterpolation *FActiveInterpolation::curiposhash[INTERPOLATION_BUCKETS]; + +void FActiveInterpolation::CopyInterpToOld () +{ + switch (Type) + { + case INTERP_SectorFloor: + oldipos[0] = ((sector_t*)Address)->floorplane.d; + oldipos[1] = ((sector_t*)Address)->floortexz; + break; + case INTERP_SectorCeiling: + oldipos[0] = ((sector_t*)Address)->ceilingplane.d; + oldipos[1] = ((sector_t*)Address)->ceilingtexz; + break; + case INTERP_Vertex: + oldipos[0] = ((vertex_t*)Address)->x; + oldipos[1] = ((vertex_t*)Address)->y; + break; + case INTERP_FloorPanning: + oldipos[0] = ((sector_t*)Address)->floor_xoffs; + oldipos[1] = ((sector_t*)Address)->floor_yoffs; + break; + case INTERP_CeilingPanning: + oldipos[0] = ((sector_t*)Address)->ceiling_xoffs; + oldipos[1] = ((sector_t*)Address)->ceiling_yoffs; + break; + case INTERP_WallPanning_Top: + case INTERP_WallPanning_Mid: + case INTERP_WallPanning_Bottom: + oldipos[0] = ((side_t*)Address)->GetTextureYOffset(Type - INTERP_WallPanning_Top); + oldipos[1] = ((side_t*)Address)->GetTextureXOffset(Type - INTERP_WallPanning_Top); + break; + } +} + +void FActiveInterpolation::CopyBakToInterp () +{ + switch (Type) + { + case INTERP_SectorFloor: + ((sector_t*)Address)->floorplane.d = bakipos[0]; + ((sector_t*)Address)->floortexz = bakipos[1]; + break; + case INTERP_SectorCeiling: + ((sector_t*)Address)->ceilingplane.d = bakipos[0]; + ((sector_t*)Address)->ceilingtexz = bakipos[1]; + break; + case INTERP_Vertex: + ((vertex_t*)Address)->x = bakipos[0]; + ((vertex_t*)Address)->y = bakipos[1]; + break; + case INTERP_FloorPanning: + ((sector_t*)Address)->floor_xoffs = bakipos[0]; + ((sector_t*)Address)->floor_yoffs = bakipos[1]; + break; + case INTERP_CeilingPanning: + ((sector_t*)Address)->ceiling_xoffs = bakipos[0]; + ((sector_t*)Address)->ceiling_yoffs = bakipos[1]; + break; + case INTERP_WallPanning_Top: + case INTERP_WallPanning_Mid: + case INTERP_WallPanning_Bottom: + ((side_t*)Address)->SetTextureYOffset(Type - INTERP_WallPanning_Top, bakipos[0]); + ((side_t*)Address)->SetTextureXOffset(Type - INTERP_WallPanning_Top, bakipos[1]); + break; + } +} + +void FActiveInterpolation::DoAnInterpolation (fixed_t smoothratio) +{ + fixed_t *adr1, *adr2, pos; + int v1, v2; + + switch (Type) + { + case INTERP_SectorFloor: + adr1 = &((sector_t*)Address)->floorplane.d; + adr2 = &((sector_t*)Address)->floortexz; + break; + case INTERP_SectorCeiling: + adr1 = &((sector_t*)Address)->ceilingplane.d; + adr2 = &((sector_t*)Address)->ceilingtexz; + break; + case INTERP_Vertex: + adr1 = &((vertex_t*)Address)->x; + adr2 = &((vertex_t*)Address)->y; + break; + case INTERP_FloorPanning: + adr1 = &((sector_t*)Address)->floor_xoffs; + adr2 = &((sector_t*)Address)->floor_yoffs; + break; + case INTERP_CeilingPanning: + adr1 = &((sector_t*)Address)->ceiling_xoffs; + adr2 = &((sector_t*)Address)->ceiling_yoffs; + break; + case INTERP_WallPanning_Top: + case INTERP_WallPanning_Mid: + case INTERP_WallPanning_Bottom: + v1 = ((side_t*)Address)->GetTextureYOffset(Type - INTERP_WallPanning_Top); + v2 = ((side_t*)Address)->GetTextureXOffset(Type - INTERP_WallPanning_Top); + adr1 = &v1; + adr2 = &v2; + break; + default: + return; + } + + pos = bakipos[0] = *adr1; + *adr1 = oldipos[0] + FixedMul (pos - oldipos[0], smoothratio); + + pos = bakipos[1] = *adr2; + *adr2 = oldipos[1] + FixedMul (pos - oldipos[1], smoothratio); + + switch (Type) + { + case INTERP_WallPanning_Top: + case INTERP_WallPanning_Mid: + case INTERP_WallPanning_Bottom: + ((side_t*)Address)->SetTextureYOffset(Type - INTERP_WallPanning_Top, v1); + ((side_t*)Address)->SetTextureXOffset(Type - INTERP_WallPanning_Top, v2); + break; + default: + return; + } + +} + +size_t FActiveInterpolation::HashKey (EInterpType type, void *interptr) +{ + return (size_t)type * ((size_t)interptr>>5); +} + +int FActiveInterpolation::CountInterpolations () +{ + int d1, d2, d3; + return CountInterpolations (&d1, &d2, &d3); +} + +int FActiveInterpolation::CountInterpolations (int *usedbuckets, int *minbucketfill, int *maxbucketfill) +{ + int count = 0; + int inuse = 0; + int minuse = INT_MAX; + int maxuse = INT_MIN; + + for (int i = INTERPOLATION_BUCKETS-1; i >= 0; --i) + { + int use = 0; + FActiveInterpolation *probe = FActiveInterpolation::curiposhash[i]; + if (probe != NULL) + { + inuse++; + } + while (probe != NULL) + { + count++; + use++; + probe = probe->Next; + } + if (use > 0 && use < minuse) + { + minuse = use; + } + if (use > maxuse) + { + maxuse = use; + } + } + *usedbuckets = inuse; + *minbucketfill = minuse == INT_MAX ? 0 : minuse; + *maxbucketfill = maxuse; + return count; +} + +FActiveInterpolation *FActiveInterpolation::FindInterpolation (EInterpType type, void *interptr, FActiveInterpolation **&interp_p) +{ + size_t hash = HashKey (type, interptr) % INTERPOLATION_BUCKETS; + FActiveInterpolation *probe, **probe_p; + + for (probe_p = &curiposhash[hash], probe = *probe_p; + probe != NULL; + probe_p = &probe->Next, probe = *probe_p) + { + if (probe->Address > interptr) + { // We passed the place it would have been, so it must not be here. + probe = NULL; + break; + } + if (probe->Address == interptr && probe->Type == type) + { // Found it. + break; + } + } + interp_p = probe_p; + return probe; +} + +void clearinterpolations() +{ + for (int i = INTERPOLATION_BUCKETS-1; i >= 0; --i) + { + for (FActiveInterpolation *probe = FActiveInterpolation::curiposhash[i]; + probe != NULL; ) + { + FActiveInterpolation *next = probe->Next; + delete probe; + probe = next; + } + FActiveInterpolation::curiposhash[i] = NULL; + } +} + +void updateinterpolations() //Stick at beginning of domovethings +{ + for (int i = INTERPOLATION_BUCKETS-1; i >= 0; --i) + { + for (FActiveInterpolation *probe = FActiveInterpolation::curiposhash[i]; + probe != NULL; probe = probe->Next) + { + probe->CopyInterpToOld (); + } + } +} + +void setinterpolation(EInterpType type, void *posptr, bool dolinks) +{ + FActiveInterpolation **interp_p; + FActiveInterpolation *interp = FActiveInterpolation::FindInterpolation (type, posptr, interp_p); + if (interp != NULL) return; // It's already active + interp = new FActiveInterpolation; + interp->Type = type; + interp->Address = posptr; + interp->Next = *interp_p; + *interp_p = interp; + interp->CopyInterpToOld (); + + if (dolinks) + { + if (type == INTERP_SectorFloor) + { + P_Start3dMidtexInterpolations((sector_t*)posptr, false); + P_StartLinkedSectorInterpolations((sector_t*)posptr, false); + } + else if (type == INTERP_SectorCeiling) + { + P_Start3dMidtexInterpolations((sector_t*)posptr, true); + P_StartLinkedSectorInterpolations((sector_t*)posptr, true); + } + } +} + +void stopinterpolation(EInterpType type, void *posptr, bool dolinks) +{ + FActiveInterpolation **interp_p; + FActiveInterpolation *interp = FActiveInterpolation::FindInterpolation (type, posptr, interp_p); + if (interp != NULL) + { + *interp_p = interp->Next; + delete interp; + + if (dolinks) + { + if (type == INTERP_SectorFloor) + { + P_Stop3dMidtexInterpolations((sector_t*)posptr, false); + P_StopLinkedSectorInterpolations((sector_t*)posptr, false); + } + else if (type == INTERP_SectorCeiling) + { + P_Stop3dMidtexInterpolations((sector_t*)posptr, true); + P_StopLinkedSectorInterpolations((sector_t*)posptr, true); + } + } + } +} + +void dointerpolations(fixed_t smoothratio) //Stick at beginning of drawscreen +{ + if (smoothratio == FRACUNIT) + { + didInterp = false; + return; + } + + didInterp = true; + + for (int i = INTERPOLATION_BUCKETS-1; i >= 0; --i) + { + for (FActiveInterpolation *probe = FActiveInterpolation::curiposhash[i]; + probe != NULL; probe = probe->Next) + { + probe->DoAnInterpolation (smoothratio); + } + } +} + +void restoreinterpolations() //Stick at end of drawscreen +{ + if (didInterp) + { + didInterp = false; + for (int i = INTERPOLATION_BUCKETS-1; i >= 0; --i) + { + for (FActiveInterpolation *probe = FActiveInterpolation::curiposhash[i]; + probe != NULL; probe = probe->Next) + { + probe->CopyBakToInterp (); + } + } + } +} + +void SerializeInterpolations (FArchive &arc) +{ + FActiveInterpolation *interp; + int numinterpolations; + int i; + + if (arc.IsStoring ()) + { + numinterpolations = FActiveInterpolation::CountInterpolations(); + arc.WriteCount (numinterpolations); + for (i = INTERPOLATION_BUCKETS-1; i >= 0; --i) + { + for (interp = FActiveInterpolation::curiposhash[i]; + interp != NULL; interp = interp->Next) + { + arc << interp; + } + } + } + else + { + clearinterpolations (); + numinterpolations = arc.ReadCount (); + for (i = numinterpolations; i > 0; --i) + { + FActiveInterpolation **interp_p; + arc << interp; + if (FActiveInterpolation::FindInterpolation (interp->Type, interp->Address, interp_p) == NULL) + { // Should always return NULL, because there should never be any duplicates stored. + interp->Next = *interp_p; + *interp_p = interp; + } + } + } +} + +FArchive &operator << (FArchive &arc, FActiveInterpolation *&interp) +{ + BYTE type; + union + { + vertex_t *vert; + sector_t *sect; + side_t *side; + void *ptr; + } ptr; + + if (arc.IsStoring ()) + { + type = interp->Type; + ptr.ptr = interp->Address; + arc << type; + switch (type) + { + case INTERP_Vertex: arc << ptr.vert; break; + case INTERP_WallPanning_Top: + case INTERP_WallPanning_Mid: + case INTERP_WallPanning_Bottom: + arc << ptr.side; break; + default: arc << ptr.sect; break; + } + } + else + { + interp = new FActiveInterpolation; + arc << type; + interp->Type = (EInterpType)type; + switch (type) + { + case INTERP_Vertex: arc << ptr.vert; break; + case INTERP_WallPanning_Top: + case INTERP_WallPanning_Mid: + case INTERP_WallPanning_Bottom: + arc << ptr.side; break; + default: arc << ptr.sect; break; + } + interp->Address = ptr.ptr; + } + return arc; +} + +ADD_STAT (interpolations) +{ + int inuse, minuse, maxuse, total; + FString out; + total = FActiveInterpolation::CountInterpolations (&inuse, &minuse, &maxuse); + out.Format ("%d interpolations buckets:%3d min:%3d max:%3d avg:%3d %d%% full %d%% buckfull", + total, inuse, minuse, maxuse, inuse?total/inuse:0, total*100/INTERPOLATION_BUCKETS, inuse*100/INTERPOLATION_BUCKETS); + return out; +} diff --git a/src/r_interpolate.h b/src/r_interpolate.h index 14b867268..b0cfc08b9 100644 --- a/src/r_interpolate.h +++ b/src/r_interpolate.h @@ -7,6 +7,129 @@ #define INTERPOLATION_BUCKETS 107 +#if 0 + +class DInterpolation : public DObject +{ + DECLARE_ABSTRACT_CLASS(DInterpolation, DObject) + HAS_OBJECT_POINTERS + + DInterpolation *Next; + +protected: + DInterpolation(); + +public: + + void Destroy(); + void CopyInterpToOld() = 0; + void CopyBakToInterp() = 0; + void DoAnInterpolation(fixed_t smoothratio) = 0; + void Serialize(FArchive &arc); +}; + +class DSectorPlaneInterpolation : public DInterpolation +{ + DECLARE_CLASS(DSectorPlaneInterpolation, DInterpolation) + + sector_t *sector; + fixed_t oldheight, oldtexz; + fixed_t bakheight, baktexz; + bool floor; + TArray attached; + + +public: + + DSectorPlaneInterpolation(sector_t *sector, int plane, bool attach); + void Destroy(); + void CopyInterpToOld(); + void CopyBakToInterp(); + void DoAnInterpolation(fixed_t smoothratio); + void Serialize(FArchive &arc); + size_t PointerSubstitution (DObject *old, DObject *notOld); + size_t PropagateMark(); +}; + +class DSectorScrollInterpolation : public DInterpolation +{ + DECLARE_CLASS(DFloorScrollInterpolation, DInterpolation) + + sector_t *sector; + fixed_t oldx, oldy; + fixed_t bakx, baky; + bool floor; + +public: + + DSectorScrollInterpolation(sector_t *sector, int plane); + void Destroy(); + void CopyInterpToOld(); + void CopyBakToInterp(); + void DoAnInterpolation(fixed_t smoothratio); + void Serialize(FArchive &arc); +}; + +class DWallScrollInterpolation : public DInterpolation +{ + DECLARE_CLASS(DWallScrollInterpolation, DInterpolation) + + side_t *side; + side_t::ETexpart part; + fixed_t oldx, oldy; + fixed_t bakx, baky; + +public: + + DWallScrollInterpolation(side_t *side, side_t::ETexpart part); + void Destroy(); + void CopyInterpToOld(); + void CopyBakToInterp(); + void DoAnInterpolation(fixed_t smoothratio); + void Serialize(FArchive &arc); +}; + +class DPolyobjInterpolation : public DInterpolation +{ + DECLARE_CLASS(DPolyobjInterpolation, DInterpolation) + + FPolyobj *poly; + vertex_t *oldverts, *bakverts; + +public: + + DPolyobjInterpolation(FPolyobj *poly); + void Destroy(); + void CopyInterpToOld(); + void CopyBakToInterp(); + void DoAnInterpolation(fixed_t smoothratio); + void Serialize(FArchive &arc); +}; + +struct FInterpolator +{ + DInterpolation *curiposhash[INTERPOLATION_BUCKETS]; + + int CountInterpolations (); + int CountInterpolations (int *usedbuckets, int *minbucketfill, int *maxbucketfill); + +private: + + size_t HashKey(FName type, void *interptr); + DInterpolation *FindInterpolation(const PClass *, void *interptr, DInterpolation **&interp_p); + +public: + DInterpolation *FindInterpolation(const PClass *, void *interptr); + void UpdateInterpolations(); + void AddInterpolation(DInterpolation *); + void RemoveInterpolation(DInterpolation *); + void DoInterpolations(fixed_t smoothratio); + void RestoreInterpolations(); +}; + + +#endif + class FArchive; enum EInterpType @@ -21,38 +144,6 @@ enum EInterpType INTERP_WallPanning_Bottom, }; -struct FActiveInterpolation -{ - FActiveInterpolation *Next; - void *Address; - EInterpType Type; - - friend FArchive &operator << (FArchive &arc, FActiveInterpolation *&interp); - - static int CountInterpolations (); - static int CountInterpolations (int *usedbuckets, int *minbucketfill, int *maxbucketfill); - -private: - fixed_t oldipos[2], bakipos[2]; - - void CopyInterpToOld(); - void CopyBakToInterp(); - void DoAnInterpolation(fixed_t smoothratio); - - static size_t HashKey(EInterpType type, void *interptr); - static FActiveInterpolation *FindInterpolation(EInterpType, void *interptr, FActiveInterpolation **&interp_p); - - friend void updateinterpolations(); - friend void setinterpolation(EInterpType, void *interptr, bool dolinks); - friend void stopinterpolation(EInterpType, void *interptr, bool dolinks); - friend void dointerpolations(fixed_t smoothratio); - friend void restoreinterpolations(); - friend void clearinterpolations(); - friend void SerializeInterpolations(FArchive &arc); - - static FActiveInterpolation *curiposhash[INTERPOLATION_BUCKETS]; -}; - void updateinterpolations(); void setinterpolation(EInterpType, void *interptr, bool dolinks = true); void stopinterpolation(EInterpType, void *interptr, bool dolinks = true); @@ -61,5 +152,5 @@ void restoreinterpolations(); void clearinterpolations(); void SerializeInterpolations(FArchive &arc); -#endif - +#endif + diff --git a/src/r_main.cpp b/src/r_main.cpp index 405b80f0c..95a823a1b 100644 --- a/src/r_main.cpp +++ b/src/r_main.cpp @@ -1783,414 +1783,3 @@ void R_MultiresInit () R_OldBlend = ~0; } -// Stuff from BUILD to interpolate floors and ceilings -// -// "Build Engine & Tools" Copyright (c) 1993-1997 Ken Silverman -// Ken Silverman's official web site: "http://www.advsys.net/ken" -// See the included license file "BUILDLIC.TXT" for license info. -// This code has been modified from its original form. - -static bool didInterp; - -FActiveInterpolation *FActiveInterpolation::curiposhash[INTERPOLATION_BUCKETS]; - -void FActiveInterpolation::CopyInterpToOld () -{ - switch (Type) - { - case INTERP_SectorFloor: - oldipos[0] = ((sector_t*)Address)->floorplane.d; - oldipos[1] = ((sector_t*)Address)->floortexz; - break; - case INTERP_SectorCeiling: - oldipos[0] = ((sector_t*)Address)->ceilingplane.d; - oldipos[1] = ((sector_t*)Address)->ceilingtexz; - break; - case INTERP_Vertex: - oldipos[0] = ((vertex_t*)Address)->x; - oldipos[1] = ((vertex_t*)Address)->y; - break; - case INTERP_FloorPanning: - oldipos[0] = ((sector_t*)Address)->floor_xoffs; - oldipos[1] = ((sector_t*)Address)->floor_yoffs; - break; - case INTERP_CeilingPanning: - oldipos[0] = ((sector_t*)Address)->ceiling_xoffs; - oldipos[1] = ((sector_t*)Address)->ceiling_yoffs; - break; - case INTERP_WallPanning_Top: - case INTERP_WallPanning_Mid: - case INTERP_WallPanning_Bottom: - oldipos[0] = ((side_t*)Address)->GetTextureYOffset(Type - INTERP_WallPanning_Top); - oldipos[1] = ((side_t*)Address)->GetTextureXOffset(Type - INTERP_WallPanning_Top); - break; - } -} - -void FActiveInterpolation::CopyBakToInterp () -{ - switch (Type) - { - case INTERP_SectorFloor: - ((sector_t*)Address)->floorplane.d = bakipos[0]; - ((sector_t*)Address)->floortexz = bakipos[1]; - break; - case INTERP_SectorCeiling: - ((sector_t*)Address)->ceilingplane.d = bakipos[0]; - ((sector_t*)Address)->ceilingtexz = bakipos[1]; - break; - case INTERP_Vertex: - ((vertex_t*)Address)->x = bakipos[0]; - ((vertex_t*)Address)->y = bakipos[1]; - break; - case INTERP_FloorPanning: - ((sector_t*)Address)->floor_xoffs = bakipos[0]; - ((sector_t*)Address)->floor_yoffs = bakipos[1]; - break; - case INTERP_CeilingPanning: - ((sector_t*)Address)->ceiling_xoffs = bakipos[0]; - ((sector_t*)Address)->ceiling_yoffs = bakipos[1]; - break; - case INTERP_WallPanning_Top: - case INTERP_WallPanning_Mid: - case INTERP_WallPanning_Bottom: - ((side_t*)Address)->SetTextureYOffset(Type - INTERP_WallPanning_Top, bakipos[0]); - ((side_t*)Address)->SetTextureXOffset(Type - INTERP_WallPanning_Top, bakipos[1]); - break; - } -} - -void FActiveInterpolation::DoAnInterpolation (fixed_t smoothratio) -{ - fixed_t *adr1, *adr2, pos; - int v1, v2; - - switch (Type) - { - case INTERP_SectorFloor: - adr1 = &((sector_t*)Address)->floorplane.d; - adr2 = &((sector_t*)Address)->floortexz; - break; - case INTERP_SectorCeiling: - adr1 = &((sector_t*)Address)->ceilingplane.d; - adr2 = &((sector_t*)Address)->ceilingtexz; - break; - case INTERP_Vertex: - adr1 = &((vertex_t*)Address)->x; - adr2 = &((vertex_t*)Address)->y; - break; - case INTERP_FloorPanning: - adr1 = &((sector_t*)Address)->floor_xoffs; - adr2 = &((sector_t*)Address)->floor_yoffs; - break; - case INTERP_CeilingPanning: - adr1 = &((sector_t*)Address)->ceiling_xoffs; - adr2 = &((sector_t*)Address)->ceiling_yoffs; - break; - case INTERP_WallPanning_Top: - case INTERP_WallPanning_Mid: - case INTERP_WallPanning_Bottom: - v1 = ((side_t*)Address)->GetTextureYOffset(Type - INTERP_WallPanning_Top); - v2 = ((side_t*)Address)->GetTextureXOffset(Type - INTERP_WallPanning_Top); - adr1 = &v1; - adr2 = &v2; - break; - default: - return; - } - - pos = bakipos[0] = *adr1; - *adr1 = oldipos[0] + FixedMul (pos - oldipos[0], smoothratio); - - pos = bakipos[1] = *adr2; - *adr2 = oldipos[1] + FixedMul (pos - oldipos[1], smoothratio); - - switch (Type) - { - case INTERP_WallPanning_Top: - case INTERP_WallPanning_Mid: - case INTERP_WallPanning_Bottom: - ((side_t*)Address)->SetTextureYOffset(Type - INTERP_WallPanning_Top, v1); - ((side_t*)Address)->SetTextureXOffset(Type - INTERP_WallPanning_Top, v2); - break; - default: - return; - } - -} - -size_t FActiveInterpolation::HashKey (EInterpType type, void *interptr) -{ - return (size_t)type * ((size_t)interptr>>5); -} - -int FActiveInterpolation::CountInterpolations () -{ - int d1, d2, d3; - return CountInterpolations (&d1, &d2, &d3); -} - -int FActiveInterpolation::CountInterpolations (int *usedbuckets, int *minbucketfill, int *maxbucketfill) -{ - int count = 0; - int inuse = 0; - int minuse = INT_MAX; - int maxuse = INT_MIN; - - for (int i = INTERPOLATION_BUCKETS-1; i >= 0; --i) - { - int use = 0; - FActiveInterpolation *probe = FActiveInterpolation::curiposhash[i]; - if (probe != NULL) - { - inuse++; - } - while (probe != NULL) - { - count++; - use++; - probe = probe->Next; - } - if (use > 0 && use < minuse) - { - minuse = use; - } - if (use > maxuse) - { - maxuse = use; - } - } - *usedbuckets = inuse; - *minbucketfill = minuse == INT_MAX ? 0 : minuse; - *maxbucketfill = maxuse; - return count; -} - -FActiveInterpolation *FActiveInterpolation::FindInterpolation (EInterpType type, void *interptr, FActiveInterpolation **&interp_p) -{ - size_t hash = HashKey (type, interptr) % INTERPOLATION_BUCKETS; - FActiveInterpolation *probe, **probe_p; - - for (probe_p = &curiposhash[hash], probe = *probe_p; - probe != NULL; - probe_p = &probe->Next, probe = *probe_p) - { - if (probe->Address > interptr) - { // We passed the place it would have been, so it must not be here. - probe = NULL; - break; - } - if (probe->Address == interptr && probe->Type == type) - { // Found it. - break; - } - } - interp_p = probe_p; - return probe; -} - -void clearinterpolations() -{ - for (int i = INTERPOLATION_BUCKETS-1; i >= 0; --i) - { - for (FActiveInterpolation *probe = FActiveInterpolation::curiposhash[i]; - probe != NULL; ) - { - FActiveInterpolation *next = probe->Next; - delete probe; - probe = next; - } - FActiveInterpolation::curiposhash[i] = NULL; - } -} - -void updateinterpolations() //Stick at beginning of domovethings -{ - for (int i = INTERPOLATION_BUCKETS-1; i >= 0; --i) - { - for (FActiveInterpolation *probe = FActiveInterpolation::curiposhash[i]; - probe != NULL; probe = probe->Next) - { - probe->CopyInterpToOld (); - } - } -} - -void setinterpolation(EInterpType type, void *posptr, bool dolinks) -{ - FActiveInterpolation **interp_p; - FActiveInterpolation *interp = FActiveInterpolation::FindInterpolation (type, posptr, interp_p); - if (interp != NULL) return; // It's already active - interp = new FActiveInterpolation; - interp->Type = type; - interp->Address = posptr; - interp->Next = *interp_p; - *interp_p = interp; - interp->CopyInterpToOld (); - - if (dolinks) - { - if (type == INTERP_SectorFloor) - { - P_Start3dMidtexInterpolations((sector_t*)posptr, false); - P_StartLinkedSectorInterpolations((sector_t*)posptr, false); - } - else if (type == INTERP_SectorCeiling) - { - P_Start3dMidtexInterpolations((sector_t*)posptr, true); - P_StartLinkedSectorInterpolations((sector_t*)posptr, true); - } - } -} - -void stopinterpolation(EInterpType type, void *posptr, bool dolinks) -{ - FActiveInterpolation **interp_p; - FActiveInterpolation *interp = FActiveInterpolation::FindInterpolation (type, posptr, interp_p); - if (interp != NULL) - { - *interp_p = interp->Next; - delete interp; - - if (dolinks) - { - if (type == INTERP_SectorFloor) - { - P_Stop3dMidtexInterpolations((sector_t*)posptr, false); - P_StopLinkedSectorInterpolations((sector_t*)posptr, false); - } - else if (type == INTERP_SectorCeiling) - { - P_Stop3dMidtexInterpolations((sector_t*)posptr, true); - P_StopLinkedSectorInterpolations((sector_t*)posptr, true); - } - } - } -} - -void dointerpolations(fixed_t smoothratio) //Stick at beginning of drawscreen -{ - if (smoothratio == FRACUNIT) - { - didInterp = false; - return; - } - - didInterp = true; - - for (int i = INTERPOLATION_BUCKETS-1; i >= 0; --i) - { - for (FActiveInterpolation *probe = FActiveInterpolation::curiposhash[i]; - probe != NULL; probe = probe->Next) - { - probe->DoAnInterpolation (smoothratio); - } - } -} - -void restoreinterpolations() //Stick at end of drawscreen -{ - if (didInterp) - { - didInterp = false; - for (int i = INTERPOLATION_BUCKETS-1; i >= 0; --i) - { - for (FActiveInterpolation *probe = FActiveInterpolation::curiposhash[i]; - probe != NULL; probe = probe->Next) - { - probe->CopyBakToInterp (); - } - } - } -} - -void SerializeInterpolations (FArchive &arc) -{ - FActiveInterpolation *interp; - int numinterpolations; - int i; - - if (arc.IsStoring ()) - { - numinterpolations = FActiveInterpolation::CountInterpolations(); - arc.WriteCount (numinterpolations); - for (i = INTERPOLATION_BUCKETS-1; i >= 0; --i) - { - for (interp = FActiveInterpolation::curiposhash[i]; - interp != NULL; interp = interp->Next) - { - arc << interp; - } - } - } - else - { - clearinterpolations (); - numinterpolations = arc.ReadCount (); - for (i = numinterpolations; i > 0; --i) - { - FActiveInterpolation **interp_p; - arc << interp; - if (FActiveInterpolation::FindInterpolation (interp->Type, interp->Address, interp_p) == NULL) - { // Should always return NULL, because there should never be any duplicates stored. - interp->Next = *interp_p; - *interp_p = interp; - } - } - } -} - -FArchive &operator << (FArchive &arc, FActiveInterpolation *&interp) -{ - BYTE type; - union - { - vertex_t *vert; - sector_t *sect; - side_t *side; - void *ptr; - } ptr; - - if (arc.IsStoring ()) - { - type = interp->Type; - ptr.ptr = interp->Address; - arc << type; - switch (type) - { - case INTERP_Vertex: arc << ptr.vert; break; - case INTERP_WallPanning_Top: - case INTERP_WallPanning_Mid: - case INTERP_WallPanning_Bottom: - arc << ptr.side; break; - default: arc << ptr.sect; break; - } - } - else - { - interp = new FActiveInterpolation; - arc << type; - interp->Type = (EInterpType)type; - switch (type) - { - case INTERP_Vertex: arc << ptr.vert; break; - case INTERP_WallPanning_Top: - case INTERP_WallPanning_Mid: - case INTERP_WallPanning_Bottom: - arc << ptr.side; break; - default: arc << ptr.sect; break; - } - interp->Address = ptr.ptr; - } - return arc; -} - -ADD_STAT (interpolations) -{ - int inuse, minuse, maxuse, total; - FString out; - total = FActiveInterpolation::CountInterpolations (&inuse, &minuse, &maxuse); - out.Format ("%d interpolations buckets:%3d min:%3d max:%3d avg:%3d %d%% full %d%% buckfull", - total, inuse, minuse, maxuse, inuse?total/inuse:0, total*100/INTERPOLATION_BUCKETS, inuse*100/INTERPOLATION_BUCKETS); - return out; -} diff --git a/src/r_segs.cpp b/src/r_segs.cpp index b9a7d0060..1bd1af94e 100644 --- a/src/r_segs.cpp +++ b/src/r_segs.cpp @@ -208,7 +208,7 @@ void R_RenderMaskedSegRange (drawseg_t *ds, int x1, int x2) // [RH] modified because we don't use user-definable translucency maps ESPSResult drawmode; - drawmode = R_SetPatchStyle (LegacyRenderStyles[curline->sidedef->Flags & WALLF_ADDTRANS ? STYLE_Add : STYLE_Translucent], + drawmode = R_SetPatchStyle (LegacyRenderStyles[curline->linedef->flags & ML_ADDTRANS ? STYLE_Add : STYLE_Translucent], MIN(curline->linedef->Alpha, FRACUNIT), 0, 0); if ((drawmode == DontDraw && !ds->bFogBoundary)) diff --git a/src/textures/texturemanager.cpp b/src/textures/texturemanager.cpp index 9937df0f8..27bb56c1e 100644 --- a/src/textures/texturemanager.cpp +++ b/src/textures/texturemanager.cpp @@ -115,6 +115,7 @@ int FTextureManager::CheckForTexture (const char *name, int usetype, BITFIELD fl if (usetype == FTexture::TEX_Any) { // All NULL textures should actually return 0 + if (tex->UseType == FTexture::TEX_FirstDefined && !(flags & TEXMAN_ReturnFirst)) return 0; return tex->UseType==FTexture::TEX_Null? 0 : i; } else if ((flags & TEXMAN_Overridable) && tex->UseType == FTexture::TEX_Override) @@ -314,7 +315,7 @@ int FTextureManager::AddTexture (FTexture *texture) // Later textures take precedence over earlier ones size_t bucket = MakeKey (texture->Name) % HASH_SIZE; TextureHash hasher = { texture, HashFirst[bucket] }; - WORD trans = Textures.Push (hasher); + int trans = Textures.Push (hasher); Translation.Push (trans); HashFirst[bucket] = trans; return trans; @@ -522,7 +523,7 @@ void FTextureManager::AddHiresTextures (int wadnum) // //========================================================================== -void FTextureManager::LoadHiresTex(int wadnum) +void FTextureManager::LoadTextureDefs(int wadnum, const char *lumpname) { int remapLump, lastLump; char src[9]; @@ -534,7 +535,7 @@ void FTextureManager::LoadHiresTex(int wadnum) lastLump = 0; src[8] = '\0'; - while ((remapLump = Wads.FindLump("HIRESTEX", &lastLump)) != -1) + while ((remapLump = Wads.FindLump(lumpname, &lastLump)) != -1) { if (Wads.GetLumpFile(remapLump) == wadnum) { @@ -565,7 +566,8 @@ void FTextureManager::LoadHiresTex(int wadnum) FName texname = sc.String; sc.MustGetString(); - int lumpnum = Wads.CheckNumForFullName(sc.String, true, ns_graphics); + int lumpnum = Wads.CheckNumForFullName(sc.String, true, ns_patches); + if (lumpnum == -1) lumpnum = Wads.CheckNumForFullName(sc.String, true, ns_graphics); if (tlist.Size() == 0) { @@ -611,7 +613,8 @@ void FTextureManager::LoadHiresTex(int wadnum) sc.GetString(); memcpy(src, ExtractFileBase(sc.String, false), 8); - int lumpnum = Wads.CheckNumForFullName(sc.String, true, ns_graphics); + int lumpnum = Wads.CheckNumForFullName(sc.String, true, ns_patches); + if (lumpnum == -1) lumpnum = Wads.CheckNumForFullName(sc.String, true, ns_graphics); sc.GetString(); is32bit = !!sc.Compare("force32bit"); @@ -652,6 +655,14 @@ void FTextureManager::LoadHiresTex(int wadnum) { ParseXTexture(sc, FTexture::TEX_Sprite); } + else if (sc.Compare("walltexture")) + { + ParseXTexture(sc, FTexture::TEX_Wall); + } + else if (sc.Compare("flat")) + { + ParseXTexture(sc, FTexture::TEX_Flat); + } } } } @@ -724,6 +735,7 @@ void FTextureManager::LoadTextureX(int wadnum) void FTextureManager::AddTexturesForWad(int wadnum) { + int firsttexture = Textures.Size(); int lumpcount = Wads.GetNumLumps(); // First step: Load sprites @@ -801,8 +813,65 @@ void FTextureManager::AddTexturesForWad(int wadnum) // Seventh step: Check for hires replacements. AddHiresTextures(wadnum); - LoadHiresTex(wadnum); + LoadTextureDefs(wadnum, "TEXTURES"); + LoadTextureDefs(wadnum, "HIRESTEX"); + SortTexturesByType(firsttexture, Textures.Size()); +} +//========================================================================== +// +// FTextureManager :: SortTexturesByType +// sorts newly added textures by UseType so that anything defined +// in HIRESTEX gets in its proper place. +// +//========================================================================== + +void FTextureManager::SortTexturesByType(int start, int end) +{ + TArray newtextures; + + // First unlink all newly added textures from the hash chain + for (int i = 0; i < HASH_SIZE; i++) + { + while (HashFirst[i] >= start && HashFirst[i] != HASH_END) + { + HashFirst[i] = Textures[HashFirst[i]].HashNext; + } + } + newtextures.Resize(end-start); + for(int i=start; iUseType == texturetypes[i]) + { + AddTexture(newtextures[j]); + newtextures[j] = NULL; + } + } + } + // This should never happen. All other UseTypes are only used outside + for(unsigned j = 0; jName); + AddTexture(newtextures[j]); + } + } } //========================================================================== diff --git a/src/version.h b/src/version.h index 974086fc3..efdc8d214 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 992 +#define MINSAVEVER 1001 #if SVN_REVISION_NUMBER < MINSAVEVER // Never write a savegame with a version lower than what we need diff --git a/zdoom.vcproj b/zdoom.vcproj index d0a568921..9c4261dc1 100644 --- a/zdoom.vcproj +++ b/zdoom.vcproj @@ -1,7 +1,7 @@ + + + + + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - @@ -950,6 +940,16 @@ Outputs=""src/$(InputName).h"" /> + + + @@ -1544,6 +1544,16 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + - - - + + + - - - + + + - - - + + + - - - + + + - - - - - - @@ -1932,6 +1924,14 @@ Outputs="$(IntDir)\$(InputName).obj" /> + + + + + @@ -2789,14 +2793,6 @@ AdditionalIncludeDirectories="src\win32;$(NoInherit)" /> - - - @@ -2806,6 +2802,14 @@ AdditionalIncludeDirectories="src\win32;$(NoInherit)" /> + + + @@ -3076,7 +3080,7 @@ />