diff --git a/specs/udmf_zdoom.txt b/specs/udmf_zdoom.txt index 74d5fb4f7..611a667af 100644 --- a/specs/udmf_zdoom.txt +++ b/specs/udmf_zdoom.txt @@ -212,6 +212,8 @@ Note: All fields default to false unless mentioned otherwise. leakiness = ; // Probability of leaking through radiation suit (0 = never, 256 = always), default = 0. damageterraineffect = ; // Will spawn a terrain splash when damage is inflicted. Default = false. damagehazard = ; // Changes damage model to Strife's delayed damage for the given sector. Default = false. + floorterrain = ; // Sets the terrain for the sector's floor. Default = 'use the flat texture's terrain definition.' + ceilingterrain = ; // Sets the terrain for the sector's ceiling. Default = 'use the flat texture's terrain definition.' * Note about dropactors diff --git a/src/actor.h b/src/actor.h index 468dcc0c6..cb0524587 100644 --- a/src/actor.h +++ b/src/actor.h @@ -896,6 +896,7 @@ public: struct sector_t *floorsector; FTextureID floorpic; // contacted sec floorpic + int floorterrain; struct sector_t *ceilingsector; FTextureID ceilingpic; // contacted sec ceilingpic fixed_t radius, height; // for movement checking diff --git a/src/g_level.cpp b/src/g_level.cpp index aba58e810..03474a5b7 100644 --- a/src/g_level.cpp +++ b/src/g_level.cpp @@ -1232,6 +1232,7 @@ void G_FinishTravel () pawn->dropoffz = pawndup->dropoffz; pawn->floorsector = pawndup->floorsector; pawn->floorpic = pawndup->floorpic; + pawn->floorterrain = pawndup->floorterrain; pawn->ceilingsector = pawndup->ceilingsector; pawn->ceilingpic = pawndup->ceilingpic; pawn->floorclip = pawndup->floorclip; diff --git a/src/namedef.h b/src/namedef.h index 9ca8cb8ed..ae456883c 100644 --- a/src/namedef.h +++ b/src/namedef.h @@ -512,6 +512,8 @@ xx(damageinterval) xx(leakiness) xx(damageterraineffect) xx(damagehazard) +xx(floorterrain) +xx(ceilingterrain) // USDF keywords xx(Amount) diff --git a/src/p_3dfloors.cpp b/src/p_3dfloors.cpp index 3fbbfeab7..496809fac 100644 --- a/src/p_3dfloors.cpp +++ b/src/p_3dfloors.cpp @@ -346,7 +346,7 @@ void P_PlayerOnSpecial3DFloor(player_t* player) // Apply flat specials (using the ceiling!) P_PlayerOnSpecialFlat( - player, TerrainTypes[rover->model->GetTexture(rover->flags & FF_INVERTSECTOR? sector_t::floor : sector_t::ceiling)]); + player, rover->model->GetTerrain(rover->top.isceiling)); break; } @@ -762,6 +762,7 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li linedef->frontsector->floorplane.ZatPoint(x, y), linedef->backsector->floorplane.ZatPoint(x, y) }; FTextureID highestfloorpic; + int highestfloorterrain = -1; FTextureID lowestceilingpic; highestfloorpic.SetInvalid(); @@ -792,6 +793,7 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li { highestfloor = ff_top; highestfloorpic = *rover->top.texture; + highestfloorterrain = rover->model->GetTerrain(rover->top.isceiling); } if(ff_top > lowestfloor[j] && ff_top <= thing->z + thing->MaxStepHeight) lowestfloor[j] = ff_top; } @@ -801,6 +803,7 @@ void P_LineOpening_XFloors (FLineOpening &open, AActor * thing, const line_t *li { open.bottom = highestfloor; open.floorpic = highestfloorpic; + open.floorterrain = highestfloorterrain; } if(lowestceiling < open.top) diff --git a/src/p_3dmidtex.cpp b/src/p_3dmidtex.cpp index 9a9492e08..dbca50d10 100644 --- a/src/p_3dmidtex.cpp +++ b/src/p_3dmidtex.cpp @@ -37,6 +37,7 @@ #include "templates.h" #include "p_local.h" +#include "p_terrain.h" //============================================================================ @@ -290,6 +291,8 @@ bool P_LineOpening_3dMidtex(AActor *thing, const line_t *linedef, FLineOpening & open.bottom = tt; open.abovemidtex = true; open.floorpic = linedef->sidedef[0]->GetTexture(side_t::mid); + open.floorterrain = TerrainTypes[open.floorpic]; + } // returns true if it touches the midtexture return (abs(thing->z - tt) <= thing->MaxStepHeight); diff --git a/src/p_buildmap.cpp b/src/p_buildmap.cpp index 670f53751..d9074310d 100644 --- a/src/p_buildmap.cpp +++ b/src/p_buildmap.cpp @@ -443,6 +443,7 @@ static void LoadSectors (sectortype *bsec) sec->movefactor = ORIG_FRICTION_FACTOR; sec->ColorMap = map; sec->ZoneNumber = 0xFFFF; + sec->terrainnum[sector_t::ceiling] = sec->terrainnum[sector_t::floor] = -1; if (bsec->floorstat & 4) { diff --git a/src/p_local.h b/src/p_local.h index 63ee4c1b1..fd5064f3c 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -293,6 +293,7 @@ struct FLineOpening sector_t *topsec; FTextureID ceilingpic; FTextureID floorpic; + int floorterrain; bool touchmidtex; bool abovemidtex; }; @@ -408,6 +409,7 @@ struct FCheckPosition fixed_t ceilingz; fixed_t dropoffz; FTextureID floorpic; + int floorterrain; sector_t *floorsector; FTextureID ceilingpic; sector_t *ceilingsector; diff --git a/src/p_map.cpp b/src/p_map.cpp index fe5959df9..7aeb9d115 100644 --- a/src/p_map.cpp +++ b/src/p_map.cpp @@ -242,6 +242,7 @@ void P_GetFloorCeilingZ(FCheckPosition &tmf, int flags) tmf.floorz = tmf.dropoffz = sec->floorplane.ZatPoint(tmf.x, tmf.y); tmf.ceilingz = sec->ceilingplane.ZatPoint(tmf.x, tmf.y); tmf.floorpic = sec->GetTexture(sector_t::floor); + tmf.floorterrain = sec->GetTerrain(sector_t::floor); tmf.ceilingpic = sec->GetTexture(sector_t::ceiling); } else @@ -264,6 +265,7 @@ void P_GetFloorCeilingZ(FCheckPosition &tmf, int flags) { tmf.dropoffz = tmf.floorz = ff_top; tmf.floorpic = *rover->top.texture; + tmf.floorterrain = rover->model->GetTerrain(rover->top.isceiling); } } if (ff_bottom <= tmf.ceilingz && ff_bottom > tmf.z + tmf.thing->height) @@ -304,6 +306,7 @@ void P_FindFloorCeiling(AActor *actor, int flags) tmf.floorz = tmf.dropoffz = actor->floorz; tmf.ceilingz = actor->ceilingz; tmf.floorpic = actor->floorpic; + tmf.floorterrain = actor->floorterrain; tmf.ceilingpic = actor->ceilingpic; P_GetFloorCeilingZ(tmf, flags); } @@ -311,6 +314,7 @@ void P_FindFloorCeiling(AActor *actor, int flags) actor->dropoffz = tmf.dropoffz; actor->ceilingz = tmf.ceilingz; actor->floorpic = tmf.floorpic; + actor->floorterrain = tmf.floorterrain; actor->floorsector = tmf.floorsector; actor->ceilingpic = tmf.ceilingpic; actor->ceilingsector = tmf.ceilingsector; @@ -337,6 +341,7 @@ void P_FindFloorCeiling(AActor *actor, int flags) actor->dropoffz = tmf.dropoffz; actor->ceilingz = tmf.ceilingz; actor->floorpic = tmf.floorpic; + actor->floorterrain = tmf.floorterrain; actor->floorsector = tmf.floorsector; actor->ceilingpic = tmf.ceilingpic; actor->ceilingsector = tmf.ceilingsector; @@ -348,6 +353,7 @@ void P_FindFloorCeiling(AActor *actor, int flags) if (actor->Sector != NULL) { actor->floorpic = actor->Sector->GetTexture(sector_t::floor); + actor->floorterrain = actor->Sector->GetTerrain(sector_t::floor); actor->ceilingpic = actor->Sector->GetTexture(sector_t::ceiling); } } @@ -455,6 +461,7 @@ bool P_TeleportMove(AActor *thing, fixed_t x, fixed_t y, fixed_t z, bool telefra thing->ceilingz = tmf.ceilingz; thing->floorsector = tmf.floorsector; thing->floorpic = tmf.floorpic; + thing->floorterrain = tmf.floorterrain; thing->ceilingsector = tmf.ceilingsector; thing->ceilingpic = tmf.ceilingpic; thing->dropoffz = tmf.dropoffz; // killough 11/98 @@ -532,14 +539,14 @@ void P_PlayerStartStomp(AActor *actor) inline fixed_t secfriction(const sector_t *sec, int plane = sector_t::floor) { if (sec->Flags & SECF_FRICTION) return sec->friction; - fixed_t friction = Terrains[TerrainTypes[sec->GetTexture(plane)]].Friction; + fixed_t friction = Terrains[sec->GetTerrain(plane)].Friction; return friction != 0 ? friction : ORIG_FRICTION; } inline fixed_t secmovefac(const sector_t *sec, int plane = sector_t::floor) { if (sec->Flags & SECF_FRICTION) return sec->friction; - fixed_t movefactor = Terrains[TerrainTypes[sec->GetTexture(plane)]].MoveFactor; + fixed_t movefactor = Terrains[sec->GetTerrain(plane)].MoveFactor; return movefactor != 0 ? movefactor : ORIG_FRICTION_FACTOR; } @@ -633,7 +640,7 @@ int P_GetFriction(const AActor *mo, int *frictionfactor) } if (!(sec->Flags & SECF_FRICTION) && - Terrains[TerrainTypes[sec->GetTexture(sector_t::floor)]].Friction == 0) + Terrains[sec->GetTerrain(sector_t::floor)].Friction == 0) { continue; } @@ -891,6 +898,7 @@ bool PIT_CheckLine(line_t *ld, const FBoundingBox &box, FCheckPosition &tm) tm.floorz = open.bottom; tm.floorsector = open.bottomsec; tm.floorpic = open.floorpic; + tm.floorterrain = open.floorterrain; tm.touchmidtex = open.touchmidtex; tm.abovemidtex = open.abovemidtex; tm.thing->BlockingLine = ld; @@ -1436,6 +1444,7 @@ bool P_CheckPosition(AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, bo tm.floorz = tm.dropoffz = newsec->floorplane.ZatPoint(x, y); tm.ceilingz = newsec->ceilingplane.ZatPoint(x, y); tm.floorpic = newsec->GetTexture(sector_t::floor); + tm.floorterrain = newsec->GetTerrain(sector_t::floor); tm.floorsector = newsec; tm.ceilingpic = newsec->GetTexture(sector_t::ceiling); tm.ceilingsector = newsec; @@ -1468,6 +1477,7 @@ bool P_CheckPosition(AActor *thing, fixed_t x, fixed_t y, FCheckPosition &tm, bo { tm.floorz = tm.dropoffz = ff_top; tm.floorpic = *rover->top.texture; + tm.floorterrain = rover->model->GetTerrain(rover->top.isceiling); } if (ff_bottom < tm.ceilingz && abs(delta1) >= abs(delta2)) { @@ -2091,6 +2101,7 @@ bool P_TryMove(AActor *thing, fixed_t x, fixed_t y, thing->ceilingz = tm.ceilingz; thing->dropoffz = tm.dropoffz; // killough 11/98: keep track of dropoffs thing->floorpic = tm.floorpic; + thing->floorterrain = tm.floorterrain; thing->floorsector = tm.floorsector; thing->ceilingpic = tm.ceilingpic; thing->ceilingsector = tm.ceilingsector; @@ -4951,6 +4962,7 @@ bool P_AdjustFloorCeil(AActor *thing, FChangePosition *cpos) thing->ceilingz = tm.ceilingz; thing->dropoffz = tm.dropoffz; // killough 11/98: remember dropoffs thing->floorpic = tm.floorpic; + thing->floorterrain = tm.floorterrain; thing->floorsector = tm.floorsector; thing->ceilingpic = tm.ceilingpic; thing->ceilingsector = tm.ceilingsector; diff --git a/src/p_maputl.cpp b/src/p_maputl.cpp index 0a39460e7..e6d5a99e6 100644 --- a/src/p_maputl.cpp +++ b/src/p_maputl.cpp @@ -194,6 +194,7 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef, open.bottom = ff; open.bottomsec = front; open.floorpic = front->GetTexture(sector_t::floor); + open.floorterrain = front->GetTerrain(sector_t::floor); open.lowfloor = bf; } else @@ -201,6 +202,7 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef, open.bottom = bf; open.bottomsec = back; open.floorpic = back->GetTexture(sector_t::floor); + open.floorterrain = back->GetTerrain(sector_t::floor); open.lowfloor = ff; } } @@ -211,6 +213,7 @@ void P_LineOpening (FLineOpening &open, AActor *actor, const line_t *linedef, open.top = FIXED_MAX; open.bottomsec = NULL; open.floorpic.SetInvalid(); + open.floorterrain = -1; open.bottom = FIXED_MIN; open.lowfloor = FIXED_MAX; } diff --git a/src/p_mobj.cpp b/src/p_mobj.cpp index 48f16ba0e..8c814738e 100644 --- a/src/p_mobj.cpp +++ b/src/p_mobj.cpp @@ -191,6 +191,10 @@ void AActor::Serialize (FArchive &arc) << tics << state << Damage; + if (SaveVersion >= 4530) + { + arc << floorterrain; + } if (SaveVersion >= 3227) { arc << projectileKickback; @@ -4035,6 +4039,7 @@ AActor *AActor::StaticSpawn (const PClass *type, fixed_t ix, fixed_t iy, fixed_t { actor->floorsector = actor->Sector; actor->floorpic = actor->floorsector->GetTexture(sector_t::floor); + actor->floorterrain = actor->floorsector->GetTerrain(sector_t::floor); actor->ceilingsector = actor->Sector; actor->ceilingpic = actor->ceilingsector->GetTexture(sector_t::ceiling); } @@ -4046,6 +4051,7 @@ AActor *AActor::StaticSpawn (const PClass *type, fixed_t ix, fixed_t iy, fixed_t else { actor->floorpic = actor->Sector->GetTexture(sector_t::floor); + actor->floorterrain = actor->Sector->GetTerrain(sector_t::floor); actor->floorsector = actor->Sector; actor->ceilingpic = actor->Sector->GetTexture(sector_t::ceiling); actor->ceilingsector = actor->Sector; @@ -4339,7 +4345,7 @@ void AActor::AdjustFloorClip () sector_t *hsec = m->m_sector->GetHeightSec(); if (hsec == NULL && m->m_sector->floorplane.ZatPoint (x, y) == z) { - fixed_t clip = Terrains[TerrainTypes[m->m_sector->GetTexture(sector_t::floor)]].FootClip; + fixed_t clip = Terrains[m->m_sector->GetTerrain(sector_t::floor)].FootClip; if (clip < shallowestclip) { shallowestclip = clip; @@ -5303,13 +5309,13 @@ void P_RipperBlood (AActor *mo, AActor *bleeder) int P_GetThingFloorType (AActor *thing) { - if (thing->floorpic.isValid()) + if (thing->floorterrain >= 0) { - return TerrainTypes[thing->floorpic]; + return thing->floorterrain; } else { - return TerrainTypes[thing->Sector->GetTexture(sector_t::floor)]; + return thing->Sector->GetTerrain(sector_t::floor); } } @@ -5362,6 +5368,7 @@ bool P_HitWater (AActor * thing, sector_t * sec, fixed_t x, fixed_t y, fixed_t z } #endif + // 'force' means, we want this sector's terrain, no matter what. if (!force) { for (unsigned int i = 0; ie->XFloor.ffloors.Size(); i++) @@ -5373,7 +5380,7 @@ bool P_HitWater (AActor * thing, sector_t * sec, fixed_t x, fixed_t y, fixed_t z { if (rover->flags & (FF_SOLID | FF_SWIMMABLE)) { - terrainnum = TerrainTypes[*rover->top.texture]; + terrainnum = rover->model->GetTerrain(rover->top.isceiling); goto foundone; } } @@ -5384,11 +5391,11 @@ bool P_HitWater (AActor * thing, sector_t * sec, fixed_t x, fixed_t y, fixed_t z hsec = sec->GetHeightSec(); if (force || hsec == NULL || !(hsec->MoreFlags & SECF_CLIPFAKEPLANES)) { - terrainnum = TerrainTypes[sec->GetTexture(sector_t::floor)]; + terrainnum = sec->GetTerrain(sector_t::floor); } else { - terrainnum = TerrainTypes[hsec->GetTexture(sector_t::floor)]; + terrainnum = hsec->GetTerrain(sector_t::floor); } foundone: diff --git a/src/p_saveg.cpp b/src/p_saveg.cpp index 8e2f7e9d9..918eb7a89 100644 --- a/src/p_saveg.cpp +++ b/src/p_saveg.cpp @@ -369,6 +369,10 @@ void P_SerializeWorld (FArchive &arc) << sec->heightsec << sec->bottommap << sec->midmap << sec->topmap << sec->gravity; + if (SaveVersion >= 4530) + { + arc << sec->terrainnum[0] << sec->terrainnum[1]; + } if (SaveVersion >= 4529) { arc << sec->damageamount; diff --git a/src/p_sectors.cpp b/src/p_sectors.cpp index 321ecdd37..5a60933ba 100644 --- a/src/p_sectors.cpp +++ b/src/p_sectors.cpp @@ -26,6 +26,7 @@ #include "doomstat.h" #include "g_level.h" #include "nodebuild.h" +#include "p_terrain.h" #include "po_man.h" #include "farchive.h" #include "r_utility.h" @@ -873,6 +874,11 @@ void sector_t::TransferSpecial(sector_t *model) Flags = (Flags&~SECF_SPECIALFLAGS) | (model->Flags & SECF_SPECIALFLAGS); } +int sector_t::GetTerrain(int pos) const +{ + return terrainnum[pos] >= 0 ? terrainnum[pos] : TerrainTypes[GetTexture(pos)]; +} + FArchive &operator<< (FArchive &arc, secspecial_t &p) { if (SaveVersion < 4529) diff --git a/src/p_setup.cpp b/src/p_setup.cpp index 772679269..3749e97aa 100644 --- a/src/p_setup.cpp +++ b/src/p_setup.cpp @@ -1532,6 +1532,7 @@ void P_LoadSectors (MapData *map, FMissingTextureTracker &missingtex) ss->gravity = 1.f; // [RH] Default sector gravity of 1.0 ss->ZoneNumber = 0xFFFF; + ss->terrainnum[sector_t::ceiling] = ss->terrainnum[sector_t::floor] = -1; // [RH] Sectors default to white light with the default fade. // If they are outside (have a sky ceiling), they use the outside fog. diff --git a/src/p_terrain.cpp b/src/p_terrain.cpp index a1a9ea25b..006835ea6 100644 --- a/src/p_terrain.cpp +++ b/src/p_terrain.cpp @@ -121,7 +121,6 @@ static void ParseSplash (FScanner &sc); static void ParseTerrain (FScanner &sc); static void ParseFloor (FScanner &sc); static int FindSplash (FName name); -static int FindTerrain (FName name); static void GenericParse (FScanner &sc, FGenericParse *parser, const char **keywords, void *fields, const char *type, FName name); static void ParseDamage (FScanner &sc, int keyword, void *fields); @@ -427,7 +426,7 @@ void ParseTerrain (FScanner &sc) sc.MustGetString (); name = sc.String; - terrainnum = (int)FindTerrain (name); + terrainnum = (int)P_FindTerrain (name); if (terrainnum < 0) { FTerrainDef def; @@ -637,7 +636,7 @@ static void ParseFloor (FScanner &sc) return; } sc.MustGetString (); - terrain = FindTerrain (sc.String); + terrain = P_FindTerrain (sc.String); if (terrain == -1) { Printf ("Unknown terrain %s\n", sc.String); @@ -657,7 +656,7 @@ static void ParseDefault (FScanner &sc) int terrain; sc.MustGetString (); - terrain = FindTerrain (sc.String); + terrain = P_FindTerrain (sc.String); if (terrain == -1) { Printf ("Unknown terrain %s\n", sc.String); @@ -692,7 +691,7 @@ int FindSplash (FName name) // //========================================================================== -int FindTerrain (FName name) +int P_FindTerrain (FName name) { unsigned int i; diff --git a/src/p_terrain.h b/src/p_terrain.h index 482c66b00..85059a945 100644 --- a/src/p_terrain.h +++ b/src/p_terrain.h @@ -122,4 +122,6 @@ struct FTerrainDef extern TArray Splashes; extern TArray Terrains; +int P_FindTerrain(FName name); + #endif //__P_TERRAIN_H__ diff --git a/src/p_udmf.cpp b/src/p_udmf.cpp index e95193860..9cfcbc0c2 100644 --- a/src/p_udmf.cpp +++ b/src/p_udmf.cpp @@ -47,6 +47,7 @@ #include "r_data/colormaps.h" #include "w_wad.h" #include "p_tags.h" +#include "p_terrain.h" //=========================================================================== // @@ -1300,6 +1301,7 @@ public: sec->heightsec = NULL; // sector used to get floor and ceiling height sec->sectornum = index; sec->damageinterval = 32; + sec->terrainnum[sector_t::ceiling] = sec->terrainnum[sector_t::floor] = -1; if (floordrop) sec->Flags = SECF_FLOORDROP; // killough 3/7/98: end changes @@ -1550,6 +1552,14 @@ public: Flag(sec->Flags, SECF_HAZARD, key); break; + case NAME_floorterrain: + sec->terrainnum[sector_t::floor] = P_FindTerrain(CheckString(key)); + break; + + case NAME_ceilingterrain: + sec->terrainnum[sector_t::ceiling] = P_FindTerrain(CheckString(key)); + break; + case NAME_MoreIds: // delay parsing of the tag string until parsing of the sector is complete // This ensures that the ID is always the first tag in the list. diff --git a/src/r_defs.h b/src/r_defs.h index 536376b63..a7e37f369 100644 --- a/src/r_defs.h +++ b/src/r_defs.h @@ -699,6 +699,8 @@ struct sector_t Flags &= ~SECF_SPECIALFLAGS; } + int GetTerrain(int pos) const; + void TransferSpecial(sector_t *model); void GetSpecial(secspecial_t *spec); void SetSpecial(const secspecial_t *spec); @@ -734,6 +736,8 @@ struct sector_t // when processed as mobj properties. Fix is to make them sector properties. fixed_t friction, movefactor; + int terrainnum[2]; + // thinker_t for reversable actions TObjPtr floordata; // jff 2/22/98 make thinkers on TObjPtr ceilingdata; // floors, ceilings, lighting, diff --git a/src/version.h b/src/version.h index b10074f41..6a0eb9c4b 100644 --- a/src/version.h +++ b/src/version.h @@ -76,7 +76,7 @@ const char *GetVersionString(); // Use 4500 as the base git save version, since it's higher than the // SVN revision ever got. -#define SAVEVER 4529 +#define SAVEVER 4530 #define SAVEVERSTRINGIFY2(x) #x #define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)