From 77b9c162e265eeb67f54c436bf59a6dccb9c2b66 Mon Sep 17 00:00:00 2001 From: Christoph Oelckers Date: Fri, 30 May 2008 06:56:50 +0000 Subject: [PATCH] - 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. - 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. - 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. SVN r1001 (trunk) --- docs/rh-log.txt | 34 +++ src/d_dehacked.cpp | 87 ++----- src/d_dehacked.h | 23 ++ src/dobject.h | 2 +- src/doomdata.h | 2 + src/f_finale.cpp | 60 ++++- src/g_level.cpp | 67 ++++- src/g_level.h | 5 + src/m_options.cpp | 4 +- src/namedef.h | 34 +++ src/p_enemy.cpp | 6 + src/p_lnspec.cpp | 12 +- src/p_mobj.cpp | 2 +- src/p_setup.cpp | 89 +++---- src/p_udmf.cpp | 228 +++++++++++++++- src/r_defs.h | 18 +- src/r_interpolate.cpp | 449 ++++++++++++++++++++++++++++++++ src/r_interpolate.h | 159 ++++++++--- src/r_main.cpp | 411 ----------------------------- src/r_segs.cpp | 2 +- src/textures/texturemanager.cpp | 81 +++++- src/version.h | 2 +- zdoom.vcproj | 440 +++++++++++++++---------------- 23 files changed, 1388 insertions(+), 829 deletions(-) create mode 100644 src/r_interpolate.cpp 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 @@ />