This commit is contained in:
Christoph Oelckers 2016-01-06 17:16:06 +01:00
commit 1b20a06ec4
35 changed files with 1206 additions and 1058 deletions

View File

@ -204,10 +204,15 @@ Note: All <bool> fields default to false unless mentioned otherwise.
hidden = <bool>; // if true this sector will not be drawn on the textured automap.
waterzone = <bool>; // Sector is under water and swimmable
moreids = <string>; // Additional sector IDs/tags, specified as a space separated list of numbers (e.g. "2 666 1003 4505")
damageamount = <int>; // Amount of damage inflicted by this sector, default = 0
damageamount = <int>; // Amount of damage inflicted by this sector, default = 0. If this is 0, all other damage properties will be ignored.
// Setting damage through these properties will override any damage set through 'special'.
// Setting damageamount to a negative value will create a healing sector.
damagetype = <string>; // Damage type for sector damage, Default = "None". (generic damage)
damageinterval = <int>; // Interval in tics between damage application, default = 32.
leakiness = <int>; // Probability of leaking through radiation suit (0 = never, 256 = always), default = 0.
damageterraineffect = <bool>; // Will spawn a terrain splash when damage is inflicted. Default = false.
damagehazard = <bool>; // Changes damage model to Strife's delayed damage for the given sector. Default = false.
* Note about dropactors

View File

@ -2071,17 +2071,17 @@ static bool AM_CheckSecret(line_t *line)
{
if (line->frontsector != NULL)
{
if (line->frontsector->secretsector)
if (line->frontsector->wasSecret())
{
if (am_map_secrets!=0 && !(line->frontsector->special&SECRET_MASK)) return true;
if (am_map_secrets!=0 && !line->frontsector->isSecret()) return true;
if (am_map_secrets==2 && !(line->flags & ML_SECRET)) return true;
}
}
if (line->backsector != NULL)
{
if (line->backsector->secretsector)
if (line->backsector->wasSecret())
{
if (am_map_secrets!=0 && !(line->backsector->special&SECRET_MASK)) return true;
if (am_map_secrets!=0 && !line->backsector->isSecret()) return true;
if (am_map_secrets==2 && !(line->flags & ML_SECRET)) return true;
}
}

View File

@ -354,21 +354,5 @@ void DBot::Pitch (AActor *target)
//Checks if a sector is dangerous.
bool FCajunMaster::IsDangerous (sector_t *sec)
{
int special;
return
sec->damageamount
|| sec->special & DAMAGE_MASK
|| (special = sec->special & 0xff, special == dLight_Strobe_Hurt)
|| special == dDamage_Hellslime
|| special == dDamage_Nukage
|| special == dDamage_End
|| special == dDamage_SuperHellslime
|| special == dDamage_LavaWimpy
|| special == dDamage_LavaHefty
|| special == dScroll_EastLavaDamage
|| special == hDamage_Sludge
|| special == sLight_Strobe_Hurt
|| special == Damage_InstantDeath
|| special == sDamage_SuperHellslime;
return sec->damageamount > 0;
}

View File

@ -1106,11 +1106,8 @@ static void PrintSecretString(const char *string, bool thislevel)
if (*string == ';') string++;
if (thislevel && secnum >= 0 && secnum < numsectors)
{
if (sectors[secnum].secretsector)
{
if ((sectors[secnum].special & SECRET_MASK)) colstr = TEXTCOLOR_RED;
else colstr = TEXTCOLOR_GREEN;
}
if (sectors[secnum].isSecret()) colstr = TEXTCOLOR_RED;
else if (sectors[secnum].wasSecret()) colstr = TEXTCOLOR_GREEN;
else colstr = TEXTCOLOR_ORANGE;
}
}

View File

@ -422,6 +422,8 @@ public:
int killcount, itemcount, secretcount; // for intermission
int damagecount, bonuscount;// for screen flashing
int hazardcount; // for delayed Strife damage
int hazardinterval; // Frequency of damage infliction
FName hazardtype; // Damage type of last hazardous damage encounter.
int poisoncount; // screen flash for poison damage
FName poisontype; // type of poison damage to apply
FName poisonpaintype; // type of Pain state to enter for poison damage

View File

@ -4323,44 +4323,12 @@ void FParser::SF_KillInSector()
//==========================================================================
//
// new for GZDoom: Sets a sector's type
// (Sure, this is not particularly useful. But having it made it possible
// to fix a few annoying bugs in some old maps ;) )
//
//==========================================================================
void FParser::SF_SectorType(void)
{
int tagnum, secnum;
sector_t *sector;
if (CheckArgs(1))
{
tagnum = intvalue(t_argv[0]);
// argv is sector tag
secnum = T_FindFirstSectorFromTag(tagnum);
if(secnum < 0)
{ script_error("sector not found with tagnum %i\n", tagnum); return;}
sector = &sectors[secnum];
if(t_argc > 1)
{
int i = -1;
int spec = intvalue(t_argv[1]);
// set all sectors with tag
FSSectorTagIterator itr(tagnum);
while ((i = itr.Next()) >= 0)
{
sectors[i].special = spec;
}
}
t_return.type = svt_int;
t_return.value.i = sector->special;
}
// I don't think this was ever used publicly so I'm not going to bother fixing it.
}
//==========================================================================

View File

@ -87,7 +87,6 @@ DEFINE_MAP_OPTION(fs_nocheckposition, false)
{
FFsOptions *opt = info->GetOptData<FFsOptions>("fragglescript");
parse.ParseAssign();
if (parse.CheckAssign())
{
parse.sc.MustGetNumber();

View File

@ -139,7 +139,7 @@ void DLightningThinker::LightningFlash ()
for (i = numsectors, j = 0; i > 0; --i, ++j, ++tempSec)
{
// allow combination of the lightning sector specials with bit masks
int special = tempSec->special & 0xff;
int special = tempSec->special;
if (tempSec->GetTexture(sector_t::ceiling) == skyflatnum
|| special == Light_IndoorLightning1
|| special == Light_IndoorLightning2

View File

@ -630,11 +630,11 @@ DEFINE_ACTION_FUNCTION(AActor, A_CheckTerrain)
if (self->z == sec->floorplane.ZatPoint (self->x, self->y))
{
if ((sec->special & 0xFF) == Damage_InstantDeath)
if (sec->special == Damage_InstantDeath)
{
P_DamageMobj (self, NULL, NULL, 999, NAME_None);
P_DamageMobj (self, NULL, NULL, 999, NAME_InstantDeath);
}
else if ((sec->special & 0xFF) == Scroll_StrifeCurrent)
else if (sec->special == Scroll_StrifeCurrent)
{
int anglespeed = tagManager.GetFirstSectorTag(sec) - 100;
fixed_t speed = (anglespeed % 10) << (FRACBITS - 4);

View File

@ -329,6 +329,7 @@ void DIntermissionScreenText::Drawer ()
int c;
const FRemapTable *range;
const char *ch = mText;
const int kerning = SmallFont->GetDefaultKerning();
// Count number of rows in this text. Since it does not word-wrap, we just count
// line feed characters.
@ -380,6 +381,7 @@ void DIntermissionScreenText::Drawer ()
}
pic = SmallFont->GetChar (c, &w);
w += kerning;
w *= CleanXfac;
if (cx + w > SCREENWIDTH)
continue;

View File

@ -510,6 +510,8 @@ xx(damageamount)
xx(damagetype)
xx(damageinterval)
xx(leakiness)
xx(damageterraineffect)
xx(damagehazard)
// USDF keywords
xx(Amount)

View File

@ -345,8 +345,7 @@ void P_PlayerOnSpecial3DFloor(player_t* player)
}
// Apply sector specials
if (rover->model->special || rover->model->damageamount)
P_PlayerInSpecialSector(player, rover->model);
P_PlayerInSpecialSector(player, rover->model);
// Apply flat specials (using the ceiling!)
P_PlayerOnSpecialFlat(

View File

@ -90,6 +90,7 @@ void DCeiling::Serialize (FArchive &arc)
void DCeiling::PlayCeilingSound ()
{
if (m_Sector->Flags & SECF_SILENTMOVE) return;
if (m_Sector->seqType >= 0)
{
SN_StartSequence (m_Sector, CHAN_CEILING, m_Sector->seqType, SEQ_PLATFORM, 0, false);
@ -142,7 +143,7 @@ void DCeiling::Tick ()
// movers with texture change, change the texture then get removed
case genCeilingChgT:
case genCeilingChg0:
m_Sector->special = m_NewSpecial;
m_Sector->SetSpecial(&m_NewSpecial);
// fall through
case genCeilingChg:
m_Sector->SetTexture(sector_t::ceiling, m_Texture);
@ -175,7 +176,7 @@ void DCeiling::Tick ()
// then remove the active ceiling
case genCeilingChgT:
case genCeilingChg0:
m_Sector->special = m_NewSpecial;
m_Sector->SetSpecial(&m_NewSpecial);
// fall through
case genCeilingChg:
m_Sector->SetTexture(sector_t::ceiling, m_Texture);
@ -435,11 +436,11 @@ DCeiling *DCeiling::Create(sector_t *sec, DCeiling::ECeiling type, line_t *line,
switch (change & 3)
{
case 1: // type is zeroed
ceiling->m_NewSpecial = 0;
ceiling->m_NewSpecial.Clear();
ceiling->m_Type = genCeilingChg0;
break;
case 2: // type is copied
ceiling->m_NewSpecial = sec->special;
sec->GetSpecial(&ceiling->m_NewSpecial);
ceiling->m_Type = genCeilingChgT;
break;
case 3: // type is left alone
@ -454,11 +455,11 @@ DCeiling *DCeiling::Create(sector_t *sec, DCeiling::ECeiling type, line_t *line,
switch (change & 3)
{
case 1: // type is zeroed
ceiling->m_NewSpecial = 0;
ceiling->m_NewSpecial.Clear();
ceiling->m_Type = genCeilingChg0;
break;
case 2: // type is copied
ceiling->m_NewSpecial = line->frontsector->special;
line->frontsector->GetSpecial(&ceiling->m_NewSpecial);
ceiling->m_Type = genCeilingChgT;
break;
case 3: // type is left alone

View File

@ -250,6 +250,8 @@ void DDoor::DoorSound(bool raise, DSeqNode *curseq) const
choice = !raise;
if (m_Sector->Flags & SECF_SILENTMOVE) return;
if (m_Speed >= FRACUNIT*8)
{
choice += 2;
@ -511,8 +513,6 @@ void P_SpawnDoorCloseIn30 (sector_t *sec)
fixed_t height;
DDoor *door = new DDoor (sec);
sec->special = 0;
door->m_Sector = sec;
door->m_Direction = 0;
door->m_Type = DDoor::doorRaise;
@ -533,7 +533,6 @@ void P_SpawnDoorCloseIn30 (sector_t *sec)
void P_SpawnDoorRaiseIn5Mins (sector_t *sec)
{
sec->special = 0;
new DDoor (sec, DDoor::doorRaiseIn5Mins, 2*FRACUNIT, TICRATE*30/7, 0);
}

View File

@ -55,6 +55,8 @@ inline FArchive &operator<< (FArchive &arc, DFloor::EFloor &type)
static void StartFloorSound (sector_t *sec)
{
if (sec->Flags & SECF_SILENTMOVE) return;
if (sec->seqType >= 0)
{
SN_StartSequence (sec, CHAN_FLOOR, sec->seqType, SEQ_PLATFORM, 0);
@ -159,7 +161,7 @@ void DFloor::Tick ()
case donutRaise:
case genFloorChgT:
case genFloorChg0:
m_Sector->special = (m_Sector->special & SECRET_MASK) | m_NewSpecial;
m_Sector->SetSpecial(&m_NewSpecial);
//fall thru
case genFloorChg:
m_Sector->SetTexture(sector_t::floor, m_Texture);
@ -175,7 +177,7 @@ void DFloor::Tick ()
case floorLowerAndChange:
case genFloorChgT:
case genFloorChg0:
m_Sector->special = (m_Sector->special & SECRET_MASK) | m_NewSpecial;
m_Sector->SetSpecial(&m_NewSpecial);
//fall thru
case genFloorChg:
m_Sector->SetTexture(sector_t::floor, m_Texture);
@ -233,14 +235,14 @@ void DFloor::SetFloorChangeType (sector_t *sec, int change)
switch (change & 3)
{
case 1:
m_NewSpecial = 0;
m_NewSpecial.Clear();
m_Type = DFloor::genFloorChg0;
break;
case 2:
m_Type = DFloor::genFloorChg;
break;
case 3:
m_NewSpecial = sec->special & ~SECRET_MASK;
sec->GetSpecial(&m_NewSpecial);
m_Type = DFloor::genFloorChgT;
break;
}
@ -438,11 +440,11 @@ bool EV_DoFloor (DFloor::EFloor floortype, line_t *line, int tag,
{
FTextureID oldpic = sec->GetTexture(sector_t::floor);
sec->SetTexture(sector_t::floor, line->frontsector->GetTexture(sector_t::floor));
sec->special = (sec->special & SECRET_MASK) | (line->frontsector->special & ~SECRET_MASK);
sec->TransferSpecial(line->frontsector);
}
else
{
sec->special &= SECRET_MASK;
sec->ClearSpecial();
}
break;
@ -453,8 +455,7 @@ bool EV_DoFloor (DFloor::EFloor floortype, line_t *line, int tag,
floor->m_Texture = sec->GetTexture(sector_t::floor);
// jff 1/24/98 make sure floor->m_NewSpecial gets initialized
// in case no surrounding sector is at floordestheight
// --> should not affect compatibility <--
floor->m_NewSpecial = sec->special & ~SECRET_MASK;
sec->GetSpecial(&floor->m_NewSpecial);
//jff 5/23/98 use model subroutine to unify fixes and handling
sector_t *modelsec;
@ -462,7 +463,7 @@ bool EV_DoFloor (DFloor::EFloor floortype, line_t *line, int tag,
if (modelsec != NULL)
{
floor->m_Texture = modelsec->GetTexture(sector_t::floor);
floor->m_NewSpecial = modelsec->special & ~SECRET_MASK;
modelsec->GetSpecial(&floor->m_NewSpecial);
}
break;
@ -635,7 +636,7 @@ bool EV_BuildStairs (int tag, DFloor::EStair type, line_t *line,
{
// [RH] Find the next sector by scanning for Stairs_Special?
tsec = sec->NextSpecialSector (
(sec->special & 0xff) == Stairs_Special1 ?
sec->special == Stairs_Special1 ?
Stairs_Special2 : Stairs_Special1, prev);
if ( (ok = (tsec != NULL)) )
@ -792,7 +793,7 @@ bool EV_DoDonut (int tag, line_t *line, fixed_t pillarspeed, fixed_t slimespeed)
floor->m_Sector = s2;
floor->m_Speed = slimespeed;
floor->m_Texture = s3->GetTexture(sector_t::floor);
floor->m_NewSpecial = 0;
floor->m_NewSpecial.Clear();
height = s3->FindHighestFloorPoint (&spot);
floor->m_FloorDestDist = s2->floorplane.PointToDist (spot, height);
floor->StartFloorSound ();
@ -1091,7 +1092,7 @@ bool EV_DoChange (line_t *line, EChange changetype, int tag)
if (line)
{ // [RH] if no line, no change
sec->SetTexture(sector_t::floor, line->frontsector->GetTexture(sector_t::floor));
sec->special = (sec->special & SECRET_MASK) | (line->frontsector->special & ~SECRET_MASK);
sec->TransferSpecial(line->frontsector);
}
break;
case numChangeOnly:
@ -1099,7 +1100,7 @@ bool EV_DoChange (line_t *line, EChange changetype, int tag)
if (secm)
{ // if no model, no change
sec->SetTexture(sector_t::floor, secm->GetTexture(sector_t::floor));
sec->special = secm->special;
sec->TransferSpecial(secm);
}
break;
default:

View File

@ -1255,8 +1255,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
}
// end of game hell hack
if ((target->Sector->special & 255) == dDamage_End
&& damage >= target->health)
if ((target->Sector->Flags & SECF_ENDLEVEL) && damage >= target->health)
{
damage = target->health - 1;
}

View File

@ -786,12 +786,12 @@ int DPhased::PhaseHelper (sector_t *sector, int index, int light, sector_t *prev
l = new DPhased (sector, baselevel);
int numsteps = PhaseHelper (sector->NextSpecialSector (
(sector->special & 0x00ff) == LightSequenceSpecial1 ?
sector->special == LightSequenceSpecial1 ?
LightSequenceSpecial2 : LightSequenceSpecial1, prev),
index + 1, l->m_BaseLevel, sector);
l->m_Phase = ((numsteps - index - 1) * 64) / numsteps;
sector->special &= 0xff00;
sector->special = 0;
return numsteps;
}
@ -820,7 +820,6 @@ DPhased::DPhased (sector_t *sector, int baselevel, int phase)
{
m_BaseLevel = baselevel;
m_Phase = phase;
sector->special &= 0xff00;
}
//============================================================================

View File

@ -1945,6 +1945,9 @@ FUNC(LS_Sector_ChangeFlags)
rtn = false;
FSectorTagIterator itr(arg0);
// exclude protected flags
arg1 &= ~SECF_NOMODIFY;
arg2 &= ~SECF_NOMODIFY;
while ((secNum = itr.Next()) >= 0)
{
sectors[secNum].Flags = (sectors[secNum].Flags | arg1) & ~arg2;

View File

@ -508,7 +508,7 @@ void P_TraceBleed (int damage, AActor *target, angle_t angle, int pitch);
void P_TraceBleed (int damage, AActor *target, AActor *missile); // missile version
void P_TraceBleed (int damage, AActor *target); // random direction version
bool P_HitFloor (AActor *thing);
bool P_HitWater (AActor *thing, sector_t *sec, fixed_t splashx = FIXED_MIN, fixed_t splashy = FIXED_MIN, fixed_t splashz=FIXED_MIN, bool checkabove = false, bool alert = true);
bool P_HitWater (AActor *thing, sector_t *sec, fixed_t splashx = FIXED_MIN, fixed_t splashy = FIXED_MIN, fixed_t splashz=FIXED_MIN, bool checkabove = false, bool alert = true, bool force = false);
void P_CheckSplash(AActor *self, fixed_t distance);
void P_RailAttack (AActor *source, int damage, int offset_xy, fixed_t offset_z = 0, int color1 = 0, int color2 = 0, double maxdiff = 0, int flags = 0, const PClass *puff = NULL, angle_t angleoffset = 0, angle_t pitchoffset = 0, fixed_t distance = 8192*FRACUNIT, int duration = 0, double sparsity = 1.0, double drift = 1.0, const PClass *spawnclass = NULL, int SpiralOffset = 270); // [RH] Shoot a railgun

View File

@ -630,7 +630,7 @@ int P_GetFriction(const AActor *mo, int *frictionfactor)
}
}
if (!(sec->special & FRICTION_MASK) &&
if (!(sec->Flags & SECF_FRICTION) &&
Terrains[TerrainTypes[sec->GetTexture(sector_t::floor)]].Friction == 0)
{
continue;

View File

@ -3452,7 +3452,7 @@ void AActor::Tick ()
if (player != NULL)
{
int scrolltype = sec->special & 0xff;
int scrolltype = sec->special;
if (scrolltype >= Scroll_North_Slow &&
scrolltype <= Scroll_SouthWest_Fast)
@ -4424,7 +4424,7 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
( gameaction != ga_worlddone ) &&
( p->mo != NULL ) &&
( !(p->mo->Sector->Flags & SECF_NORESPAWN) ) &&
( (p->mo->Sector->special & 255) != Damage_InstantDeath ))
( p->mo->Sector->damageamount < TELEFRAG_DAMAGE )) // this really should be a bit smarter...
{
spawn_x = p->mo->x;
spawn_y = p->mo->y;
@ -5320,7 +5320,7 @@ int P_GetThingFloorType (AActor *thing)
// Returns true if hit liquid and splashed, false if not.
//---------------------------------------------------------------------------
bool P_HitWater (AActor * thing, sector_t * sec, fixed_t x, fixed_t y, fixed_t z, bool checkabove, bool alert)
bool P_HitWater (AActor * thing, sector_t * sec, fixed_t x, fixed_t y, fixed_t z, bool checkabove, bool alert, bool force)
{
if (thing->flags3 & MF3_DONTSPLASH)
return false;
@ -5362,24 +5362,27 @@ bool P_HitWater (AActor * thing, sector_t * sec, fixed_t x, fixed_t y, fixed_t z
}
#endif
for(unsigned int i=0;i<sec->e->XFloor.ffloors.Size();i++)
if (!force)
{
F3DFloor * rover = sec->e->XFloor.ffloors[i];
if (!(rover->flags & FF_EXISTS)) continue;
fixed_t planez = rover->top.plane->ZatPoint(x, y);
if (z > planez - FRACUNIT/2 && z < planez + FRACUNIT/2) // allow minor imprecisions
for (unsigned int i = 0; i<sec->e->XFloor.ffloors.Size(); i++)
{
if (rover->flags & (FF_SOLID|FF_SWIMMABLE) )
F3DFloor * rover = sec->e->XFloor.ffloors[i];
if (!(rover->flags & FF_EXISTS)) continue;
fixed_t planez = rover->top.plane->ZatPoint(x, y);
if (z > planez - FRACUNIT / 2 && z < planez + FRACUNIT / 2) // allow minor imprecisions
{
terrainnum = TerrainTypes[*rover->top.texture];
goto foundone;
if (rover->flags & (FF_SOLID | FF_SWIMMABLE))
{
terrainnum = TerrainTypes[*rover->top.texture];
goto foundone;
}
}
planez = rover->bottom.plane->ZatPoint(x, y);
if (planez < z && !(planez < thing->floorz)) return false;
}
planez = rover->bottom.plane->ZatPoint(x, y);
if (planez < z && !(planez < thing->floorz)) return false;
}
hsec = sec->GetHeightSec();
if (hsec == NULL || !(hsec->MoreFlags & SECF_CLIPFAKEPLANES))
if (force || hsec == NULL || !(hsec->MoreFlags & SECF_CLIPFAKEPLANES))
{
terrainnum = TerrainTypes[sec->GetTexture(sector_t::floor)];
}
@ -5403,7 +5406,7 @@ foundone:
// Don't splash for living things with small vertical velocities.
// There are levels where the constant splashing from the monsters gets extremely annoying
if ((thing->flags3&MF3_ISMONSTER || thing->player) && thing->velz >= -6*FRACUNIT)
if (((thing->flags3&MF3_ISMONSTER || thing->player) && thing->velz >= -6*FRACUNIT) && !force)
return Terrains[terrainnum].IsLiquid;
splash = &Splashes[splashnum];

View File

@ -198,17 +198,20 @@ DPillar::DPillar (sector_t *sector, EPillar type, fixed_t speed,
m_FloorSpeed = Scale (speed, floordist, ceilingdist);
}
if (sector->seqType >= 0)
if (!(m_Sector->Flags & SECF_SILENTMOVE))
{
SN_StartSequence (sector, CHAN_FLOOR, sector->seqType, SEQ_PLATFORM, 0);
}
else if (sector->SeqName != NAME_None)
{
SN_StartSequence (sector, CHAN_FLOOR, sector->SeqName, 0);
}
else
{
SN_StartSequence (sector, CHAN_FLOOR, "Floor", 0);
if (sector->seqType >= 0)
{
SN_StartSequence(sector, CHAN_FLOOR, sector->seqType, SEQ_PLATFORM, 0);
}
else if (sector->SeqName != NAME_None)
{
SN_StartSequence(sector, CHAN_FLOOR, sector->SeqName, 0);
}
else
{
SN_StartSequence(sector, CHAN_FLOOR, "Floor", 0);
}
}
}

View File

@ -72,6 +72,8 @@ void DPlat::Serialize (FArchive &arc)
void DPlat::PlayPlatSound (const char *sound)
{
if (m_Sector->Flags & SECF_SILENTMOVE) return;
if (m_Sector->seqType >= 0)
{
SN_StartSequence (m_Sector, CHAN_FLOOR, m_Sector->seqType, SEQ_PLATFORM, 0);
@ -280,8 +282,7 @@ bool EV_DoPlat (int tag, line_t *line, DPlat::EPlatType type, int height,
{
if (line)
sec->SetTexture(sector_t::floor, line->sidedef[0]->sector->GetTexture(sector_t::floor));
if (change == 1)
sec->special &= SECRET_MASK; // Stop damage and other stuff, if any
if (change == 1) sec->ClearSpecial();
}
switch (type)
@ -293,7 +294,7 @@ bool EV_DoPlat (int tag, line_t *line, DPlat::EPlatType type, int height,
plat->m_Low = sec->floorplane.d;
plat->m_Status = DPlat::up;
plat->PlayPlatSound ("Floor");
sec->special &= SECRET_MASK; // NO MORE DAMAGE, IF APPLICABLE
sec->ClearSpecial();
break;
case DPlat::platUpByValue:

View File

@ -368,8 +368,17 @@ void P_SerializeWorld (FArchive &arc)
<< sec->planes[sector_t::ceiling]
<< sec->heightsec
<< sec->bottommap << sec->midmap << sec->topmap
<< sec->gravity
<< sec->damageamount;
<< sec->gravity;
if (SaveVersion >= 4529)
{
arc << sec->damageamount;
}
else
{
short dmg;
arc << dmg;
sec->damageamount = dmg;
}
if (SaveVersion >= 4528)
{
arc << sec->damageinterval
@ -398,15 +407,22 @@ void P_SerializeWorld (FArchive &arc)
}
}
arc << sec->SoundTarget
arc << sec->SoundTarget
<< sec->SecActTarget
<< sec->sky
<< sec->MoreFlags
<< sec->Flags
<< sec->FloorSkyBox << sec->CeilingSkyBox
<< sec->ZoneNumber
<< sec->secretsector
<< sec->interpolations[0]
<< sec->ZoneNumber;
if (SaveVersion < 4529)
{
short secretsector;
arc << secretsector;
if (secretsector) sec->Flags |= SECF_WASSECRET;
sec->special &= ~(SECRET_MASK|FRICTION_MASK|PUSH_MASK);
P_InitSectorSpecial(sec, sec->special, true);
}
arc << sec->interpolations[0]
<< sec->interpolations[1]
<< sec->interpolations[2]
<< sec->interpolations[3]

View File

@ -49,7 +49,7 @@ sector_t *sector_t::NextSpecialSector (int type, sector_t *nogood) const
if (NULL != (tsec = getNextSector (ln, this)) &&
tsec != nogood &&
(tsec->special & 0x00ff) == type)
tsec->special == type)
{
return tsec;
}
@ -843,6 +843,60 @@ sector_t *sector_t::GetHeightSec() const
}
void sector_t::GetSpecial(secspecial_t *spec)
{
spec->special = special;
spec->damageamount = damageamount;
spec->damagetype = damagetype;
spec->damageinterval = damageinterval;
spec->leakydamage = leakydamage;
spec->Flags = Flags & SECF_SPECIALFLAGS;
}
void sector_t::SetSpecial(const secspecial_t *spec)
{
special = spec->special;
damageamount = spec->damageamount;
damagetype = spec->damagetype;
damageinterval = spec->damageinterval;
leakydamage = spec->leakydamage;
Flags = (Flags & ~SECF_SPECIALFLAGS) | (spec->Flags & SECF_SPECIALFLAGS);
}
void sector_t::TransferSpecial(sector_t *model)
{
special = model->special;
damageamount = model->damageamount;
damagetype = model->damagetype;
damageinterval = model->damageinterval;
leakydamage = model->leakydamage;
Flags = (Flags&~SECF_SPECIALFLAGS) | (model->Flags & SECF_SPECIALFLAGS);
}
FArchive &operator<< (FArchive &arc, secspecial_t &p)
{
if (SaveVersion < 4529)
{
short special;
arc << special;
sector_t sec;
P_InitSectorSpecial(&sec, special, true);
sec.GetSpecial(&p);
}
else
{
arc << p.special
<< p.damageamount
<< p.damagetype
<< p.damageinterval
<< p.leakydamage
<< p.Flags;
}
return arc;
}
bool secplane_t::CopyPlaneIfValid (secplane_t *dest, const secplane_t *opp) const
{
bool copy = false;

View File

@ -1512,7 +1512,6 @@ void P_LoadSectors (MapData *map, FMissingTextureTracker &missingtex)
ss->special = LittleShort(ms->special);
else // [RH] Translate to new sector special
ss->special = P_TranslateSectorSpecial (LittleShort(ms->special));
ss->secretsector = !!(ss->special&SECRET_MASK);
tagManager.AddSectorTag(i, LittleShort(ms->tag));
ss->thinglist = NULL;
ss->touching_thinglist = NULL; // phares 3/14/98
@ -4049,7 +4048,7 @@ void P_SetupLevel (const char *lumpname, int position)
{
if (mo->flags & MF_COUNTKILL)
{
if (mo->Sector->special == dDamage_End)
if (mo->Sector->damageamount > 0 && (mo->Sector->Flags & (SECF_ENDGODMODE|SECF_ENDLEVEL)) == (SECF_ENDGODMODE|SECF_ENDLEVEL))
{
mo->ClearCounters();
}

View File

@ -437,146 +437,55 @@ void P_PlayerInSpecialSector (player_t *player, sector_t * sector)
}
}
int special = sector->special & ~SECRET_MASK;
// Has hit ground.
AInventory *ironfeet;
// Allow subclasses. Better would be to implement it as armor and let that reduce
// the damage as part of the normal damage procedure. Unfortunately, I don't have
// different damage types yet, so that's not happening for now.
for (ironfeet = player->mo->Inventory; ironfeet != NULL; ironfeet = ironfeet->Inventory)
{
if (ironfeet->IsKindOf (RUNTIME_CLASS(APowerIronFeet)))
break;
}
// [RH] Normal DOOM special or BOOM specialized?
if (special >= dLight_Flicker && special <= 255)
{
switch (special)
{
case Sector_Heal:
// CoD's healing sector
if (!(level.time & 0x1f))
P_GiveBody (player->mo, 1);
break;
case Damage_InstantDeath:
// Strife's instant death sector
P_DamageMobj (player->mo, NULL, NULL, 999, NAME_InstantDeath);
break;
case dDamage_Hellslime:
// HELLSLIME DAMAGE
if (ironfeet == NULL && !(level.time&0x1f))
P_DamageMobj (player->mo, NULL, NULL, 10, NAME_Slime);
break;
case dDamage_Nukage:
// NUKAGE DAMAGE
case sLight_Strobe_Hurt:
if (ironfeet == NULL && !(level.time&0x1f))
P_DamageMobj (player->mo, NULL, NULL, 5, NAME_Slime);
break;
case hDamage_Sludge:
if (ironfeet == NULL && !(level.time&0x1f))
P_DamageMobj (player->mo, NULL, NULL, 4, NAME_Slime);
break;
case dDamage_SuperHellslime:
// SUPER HELLSLIME DAMAGE
case dLight_Strobe_Hurt:
// STROBE HURT
if (ironfeet == NULL || pr_playerinspecialsector() < 5)
{
if (!(level.time&0x1f))
P_DamageMobj (player->mo, NULL, NULL, 20, NAME_Slime);
}
break;
case sDamage_Hellslime:
if (ironfeet == NULL)
player->hazardcount += 2;
break;
case sDamage_SuperHellslime:
if (ironfeet == NULL)
player->hazardcount += 4;
break;
case dDamage_End:
// EXIT SUPER DAMAGE! (for E1M8 finale)
player->cheats &= ~CF_GODMODE;
if (!(level.time & 0x1f))
P_DamageMobj (player->mo, NULL, NULL, 20, NAME_None);
if (player->health <= 10 && (!deathmatch || !(dmflags & DF_NO_EXIT)))
G_ExitLevel(0, false);
break;
case dDamage_LavaWimpy:
case dScroll_EastLavaDamage:
if (!(level.time & 15))
{
P_DamageMobj(player->mo, NULL, NULL, 5, NAME_Fire);
P_HitFloor(player->mo);
}
break;
case dDamage_LavaHefty:
if(!(level.time & 15))
{
P_DamageMobj(player->mo, NULL, NULL, 8, NAME_Fire);
P_HitFloor(player->mo);
}
break;
default:
// [RH] Ignore unknown specials
break;
}
}
else
{
//jff 3/14/98 handle extended sector types for secrets and damage
switch (special & DAMAGE_MASK)
{
case 0x000: // no damage
break;
case 0x100: // 2/5 damage per 31 ticks
if (ironfeet == NULL && !(level.time&0x1f))
P_DamageMobj (player->mo, NULL, NULL, 5, NAME_Fire);
break;
case 0x200: // 5/10 damage per 31 ticks
if (ironfeet == NULL && !(level.time&0x1f))
P_DamageMobj (player->mo, NULL, NULL, 10, NAME_Slime);
break;
case 0x300: // 10/20 damage per 31 ticks
if (ironfeet == NULL
|| pr_playerinspecialsector() < 5) // take damage even with suit
{
if (!(level.time&0x1f))
P_DamageMobj (player->mo, NULL, NULL, 20, NAME_Slime);
}
break;
}
}
// [RH] Apply any customizable damage
if (sector->damageamount != 0)
if (sector->damageamount > 0)
{
if (level.time % sector->damageinterval == 0 && (ironfeet == NULL || pr_playerinspecialsector() < sector->leakydamage))
// Allow subclasses. Better would be to implement it as armor and let that reduce
// the damage as part of the normal damage procedure. Unfortunately, I don't have
// different damage types yet, so that's not happening for now.
for (ironfeet = player->mo->Inventory; ironfeet != NULL; ironfeet = ironfeet->Inventory)
{
P_DamageMobj (player->mo, NULL, NULL, sector->damageamount, sector->damagetype);
if (ironfeet->IsKindOf (RUNTIME_CLASS(APowerIronFeet)))
break;
}
if (sector->Flags & SECF_ENDGODMODE) player->cheats &= ~CF_GODMODE;
if ((ironfeet == NULL || pr_playerinspecialsector() < sector->leakydamage))
{
if (sector->Flags & SECF_HAZARD)
{
player->hazardcount += sector->damageamount;
player->hazardtype = sector->damagetype;
player->hazardinterval = sector->damageinterval;
}
else if (level.time % sector->damageinterval == 0)
{
P_DamageMobj(player->mo, NULL, NULL, sector->damageamount, sector->damagetype);
if ((sector->Flags & SECF_ENDLEVEL) && player->health <= 10 && (!deathmatch || !(dmflags & DF_NO_EXIT)))
{
G_ExitLevel(0, false);
}
if (sector->Flags & SECF_DMGTERRAINFX)
{
P_HitWater(player->mo, sector, INT_MIN, INT_MIN, INT_MIN, false, true, true);
}
}
}
}
else if (sector->damageamount < 0)
{
if (level.time % sector->damageinterval == 0)
{
P_GiveBody(player->mo, -sector->damageamount, 100);
}
}
if (sector->special & SECRET_MASK)
if (sector->isSecret())
{
sector->special &= ~SECRET_MASK;
sector->ClearSecret();
P_GiveSecret(player->mo, true, true, int(sector - sectors));
}
}
@ -1167,6 +1076,228 @@ void P_SpawnPortal(line_t *line, int sectortag, int plane, int alpha)
}
//
// P_SetSectorDamage
//
// Sets damage properties for one sector. Allows combination of original specials with explicit use of the damage properties
//
static void P_SetupSectorDamage(sector_t *sector, int damage, int interval, int leakchance, FName type, int flags)
{
// Only set if damage is not yet initialized. This ensures that UDMF takes precedence over sector specials.
if (sector->damageamount == 0)
{
sector->damageamount = damage;
sector->damageinterval = MAX(1, interval);
sector->leakydamage = leakchance;
sector->damagetype = type;
sector->Flags = (sector->Flags & ~SECF_DAMAGEFLAGS) | (flags & SECF_DAMAGEFLAGS);
}
}
//
// P_InitSectorSpecial
//
// Sets up everything derived from 'sector->special' for one sector
// ('fromload' is necessary to allow conversion upon savegame load.)
//
void P_InitSectorSpecial(sector_t *sector, int special, bool nothinkers)
{
// [RH] All secret sectors are marked with a BOOM-ish bitfield
if (sector->special & SECRET_MASK)
{
sector->Flags |= SECF_SECRET | SECF_WASSECRET;
level.total_secrets++;
}
if (sector->special & FRICTION_MASK)
{
sector->Flags |= SECF_FRICTION;
}
if (sector->special & PUSH_MASK)
{
sector->Flags |= SECF_PUSH;
}
if ((sector->special & DAMAGE_MASK) == 0x100)
{
P_SetupSectorDamage(sector, 5, 32, 0, NAME_Fire, 0);
}
else if ((sector->special & DAMAGE_MASK) == 0x200)
{
P_SetupSectorDamage(sector, 10, 32, 0, NAME_Slime, 0);
}
else if ((sector->special & DAMAGE_MASK) == 0x300)
{
P_SetupSectorDamage(sector, 20, 32, 5, NAME_Slime, 0);
}
sector->special &= 0xff;
// [RH] Normal DOOM special or BOOM specialized?
bool keepspecial = false;
switch (sector->special)
{
case Light_Phased:
if (!nothinkers) new DPhased (sector, 48, 63 - (sector->lightlevel & 63));
break;
// [RH] Hexen-like phased lighting
case LightSequenceStart:
if (!nothinkers) new DPhased (sector);
break;
case dLight_Flicker:
if (!nothinkers) new DLightFlash (sector);
break;
case dLight_StrobeFast:
if (!nothinkers) new DStrobe (sector, STROBEBRIGHT, FASTDARK, false);
break;
case dLight_StrobeSlow:
if (!nothinkers) new DStrobe (sector, STROBEBRIGHT, SLOWDARK, false);
break;
case dLight_Strobe_Hurt:
if (!nothinkers) new DStrobe (sector, STROBEBRIGHT, FASTDARK, false);
P_SetupSectorDamage(sector, 20, 32, 5, NAME_Slime, 0);
break;
case dDamage_Hellslime:
P_SetupSectorDamage(sector, 10, 32, 0, NAME_Slime, 0);
break;
case dDamage_Nukage:
P_SetupSectorDamage(sector, 5, 32, 0, NAME_Slime, 0);
break;
case dLight_Glow:
if (!nothinkers) new DGlow (sector);
break;
case dSector_DoorCloseIn30:
P_SpawnDoorCloseIn30 (sector);
break;
case dDamage_End:
P_SetupSectorDamage(sector, 20, 32, 256, NAME_None, SECF_ENDGODMODE|SECF_ENDLEVEL);
break;
case dLight_StrobeSlowSync:
if (!nothinkers) new DStrobe (sector, STROBEBRIGHT, SLOWDARK, true);
break;
case dLight_StrobeFastSync:
if (!nothinkers) new DStrobe (sector, STROBEBRIGHT, FASTDARK, true);
break;
case dSector_DoorRaiseIn5Mins:
P_SpawnDoorRaiseIn5Mins (sector);
break;
case dFriction_Low:
sector->friction = FRICTION_LOW;
sector->movefactor = 0x269;
sector->Flags |= SECF_FRICTION;
break;
case dDamage_SuperHellslime:
P_SetupSectorDamage(sector, 20, 32, 5, NAME_Slime, 0);
break;
case dLight_FireFlicker:
if (!nothinkers) new DFireFlicker (sector);
break;
case dDamage_LavaWimpy:
P_SetupSectorDamage(sector, 5, 32, 256, NAME_Fire, SECF_DMGTERRAINFX);
break;
case dDamage_LavaHefty:
P_SetupSectorDamage(sector, 8, 32, 256, NAME_Fire, SECF_DMGTERRAINFX);
break;
case dScroll_EastLavaDamage:
P_SetupSectorDamage(sector, 5, 32, 256, NAME_Fire, SECF_DMGTERRAINFX);
if (!nothinkers)
{
new DStrobe(sector, STROBEBRIGHT, FASTDARK, false);
new DScroller(DScroller::sc_floor, (-FRACUNIT / 2) << 3,
0, -1, int(sector - sectors), 0);
}
keepspecial = true;
break;
case hDamage_Sludge:
P_SetupSectorDamage(sector, 4, 32, 0, NAME_Slime, 0);
break;
case sLight_Strobe_Hurt:
P_SetupSectorDamage(sector, 5, 32, 0, NAME_Slime, 0);
if (!nothinkers) new DStrobe (sector, STROBEBRIGHT, FASTDARK, false);
break;
case sDamage_Hellslime:
P_SetupSectorDamage(sector, 2, 32, 0, NAME_Slime, SECF_HAZARD);
break;
case Damage_InstantDeath:
// Strife's instant death sector
P_SetupSectorDamage(sector, TELEFRAG_DAMAGE, 1, 256, NAME_InstantDeath, 0);
break;
case sDamage_SuperHellslime:
P_SetupSectorDamage(sector, 4, 32, 0, NAME_Slime, SECF_HAZARD);
break;
case Sector_Hidden:
sector->MoreFlags |= SECF_HIDDEN;
break;
case Sector_Heal:
// CoD's healing sector
P_SetupSectorDamage(sector, -1, 32, 0, NAME_None, 0);
break;
case Sky2:
sector->sky = PL_SKYFLAT;
break;
default:
if (sector->special >= Scroll_North_Slow &&
sector->special <= Scroll_SouthWest_Fast)
{ // Hexen scroll special
static const char hexenScrollies[24][2] =
{
{ 0, 1 }, { 0, 2 }, { 0, 4 },
{ -1, 0 }, { -2, 0 }, { -4, 0 },
{ 0, -1 }, { 0, -2 }, { 0, -4 },
{ 1, 0 }, { 2, 0 }, { 4, 0 },
{ 1, 1 }, { 2, 2 }, { 4, 4 },
{ -1, 1 }, { -2, 2 }, { -4, 4 },
{ -1, -1 }, { -2, -2 }, { -4, -4 },
{ 1, -1 }, { 2, -2 }, { 4, -4 }
};
int i = sector->special - Scroll_North_Slow;
fixed_t dx = hexenScrollies[i][0] * (FRACUNIT/2);
fixed_t dy = hexenScrollies[i][1] * (FRACUNIT/2);
if (!nothinkers) new DScroller (DScroller::sc_floor, dx, dy, -1, int(sector-sectors), 0);
}
else if (sector->special >= Carry_East5 &&
sector->special <= Carry_East35)
{ // Heretic scroll special
// Only east scrollers also scroll the texture
if (!nothinkers) new DScroller (DScroller::sc_floor,
(-FRACUNIT/2)<<(sector->special - Carry_East5),
0, -1, int(sector-sectors), 0);
}
keepspecial = true;
break;
}
if (!keepspecial) sector->special = 0;
}
//
// P_SpawnSpecials
//
@ -1187,135 +1318,7 @@ void P_SpawnSpecials (void)
if (sector->special == 0)
continue;
// [RH] All secret sectors are marked with a BOOM-ish bitfield
if (sector->special & SECRET_MASK)
level.total_secrets++;
switch (sector->special & 0xff)
{
// [RH] Normal DOOM/Hexen specials. We clear off the special for lights
// here instead of inside the spawners.
case dLight_Flicker:
// FLICKERING LIGHTS
new DLightFlash (sector);
sector->special &= 0xff00;
break;
case dLight_StrobeFast:
// STROBE FAST
new DStrobe (sector, STROBEBRIGHT, FASTDARK, false);
sector->special &= 0xff00;
break;
case dLight_StrobeSlow:
// STROBE SLOW
new DStrobe (sector, STROBEBRIGHT, SLOWDARK, false);
sector->special &= 0xff00;
break;
case dLight_Strobe_Hurt:
case sLight_Strobe_Hurt:
// STROBE FAST/DEATH SLIME
new DStrobe (sector, STROBEBRIGHT, FASTDARK, false);
break;
case dLight_Glow:
// GLOWING LIGHT
new DGlow (sector);
sector->special &= 0xff00;
break;
case dSector_DoorCloseIn30:
// DOOR CLOSE IN 30 SECONDS
P_SpawnDoorCloseIn30 (sector);
break;
case dLight_StrobeSlowSync:
// SYNC STROBE SLOW
new DStrobe (sector, STROBEBRIGHT, SLOWDARK, true);
sector->special &= 0xff00;
break;
case dLight_StrobeFastSync:
// SYNC STROBE FAST
new DStrobe (sector, STROBEBRIGHT, FASTDARK, true);
sector->special &= 0xff00;
break;
case dSector_DoorRaiseIn5Mins:
// DOOR RAISE IN 5 MINUTES
P_SpawnDoorRaiseIn5Mins (sector);
break;
case dLight_FireFlicker:
// fire flickering
new DFireFlicker (sector);
sector->special &= 0xff00;
break;
case dFriction_Low:
sector->friction = FRICTION_LOW;
sector->movefactor = 0x269;
sector->special &= 0xff00;
sector->special |= FRICTION_MASK;
break;
// [RH] Hexen-like phased lighting
case LightSequenceStart:
new DPhased (sector);
break;
case Light_Phased:
new DPhased (sector, 48, 63 - (sector->lightlevel & 63));
break;
case Sky2:
sector->sky = PL_SKYFLAT;
break;
case dScroll_EastLavaDamage:
new DStrobe (sector, STROBEBRIGHT, FASTDARK, false);
new DScroller (DScroller::sc_floor, (-FRACUNIT/2)<<3,
0, -1, int(sector-sectors), 0);
break;
case Sector_Hidden:
sector->MoreFlags |= SECF_HIDDEN;
sector->special &= 0xff00;
break;
default:
if ((sector->special & 0xff) >= Scroll_North_Slow &&
(sector->special & 0xff) <= Scroll_SouthWest_Fast)
{ // Hexen scroll special
static const char hexenScrollies[24][2] =
{
{ 0, 1 }, { 0, 2 }, { 0, 4 },
{ -1, 0 }, { -2, 0 }, { -4, 0 },
{ 0, -1 }, { 0, -2 }, { 0, -4 },
{ 1, 0 }, { 2, 0 }, { 4, 0 },
{ 1, 1 }, { 2, 2 }, { 4, 4 },
{ -1, 1 }, { -2, 2 }, { -4, 4 },
{ -1, -1 }, { -2, -2 }, { -4, -4 },
{ 1, -1 }, { 2, -2 }, { 4, -4 }
};
int i = (sector->special & 0xff) - Scroll_North_Slow;
fixed_t dx = hexenScrollies[i][0] * (FRACUNIT/2);
fixed_t dy = hexenScrollies[i][1] * (FRACUNIT/2);
new DScroller (DScroller::sc_floor, dx, dy, -1, int(sector-sectors), 0);
}
else if ((sector->special & 0xff) >= Carry_East5 &&
(sector->special & 0xff) <= Carry_East35)
{ // Heretic scroll special
// Only east scrollers also scroll the texture
new DScroller (DScroller::sc_floor,
(-FRACUNIT/2)<<((sector->special & 0xff) - Carry_East5),
0, -1, int(sector-sectors), 0);
}
break;
}
P_InitSectorSpecial(sector, sector->special, false);
}
// Init other misc stuff
@ -2056,11 +2059,11 @@ void P_SetSectorFriction (int tag, int amount, bool alterFlag)
// can be enabled and disabled at will.
if (friction == ORIG_FRICTION)
{
sectors[s].special &= ~FRICTION_MASK;
sectors[s].Flags &= ~SECF_FRICTION;
}
else
{
sectors[s].special |= FRICTION_MASK;
sectors[s].Flags |= SECF_FRICTION;
}
}
}
@ -2176,7 +2179,7 @@ void DPusher::Tick ()
// Be sure the special sector type is still turned on. If so, proceed.
// Else, bail out; the sector type has been changed on us.
if (!(sec->special & PUSH_MASK))
if (!(sec->Flags & SECF_PUSH))
return;
// For constant pushers (wind/current) there are 3 situations:

View File

@ -158,6 +158,7 @@ bool PIT_PushThing (AActor *thing);
bool CheckIfExitIsGood (AActor *self, level_info_t *info);
// at map load
void P_InitSectorSpecial(sector_t *sector, int special, bool nothinkers);
void P_SpawnSpecials (void);
// every tic
@ -673,7 +674,7 @@ protected:
// [RH] Need these for BOOM-ish transferring ceilings
FTextureID m_Texture;
int m_NewSpecial;
secspecial_t m_NewSpecial;
// ID
int m_Tag;
@ -760,7 +761,7 @@ protected:
int m_Crush;
bool m_Hexencrush;
int m_Direction;
int m_NewSpecial;
secspecial_t m_NewSpecial;
FTextureID m_Texture;
fixed_t m_FloorDestDist;
fixed_t m_Speed;

View File

@ -1542,6 +1542,14 @@ public:
sec->leakydamage = CheckInt(key);
break;
case NAME_damageterraineffect:
Flag(sec->Flags, SECF_DMGTERRAINFX, key);
break;
case NAME_damagehazard:
Flag(sec->Flags, SECF_HAZARD, 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.
@ -1568,7 +1576,15 @@ public:
}
}
sec->secretsector = !!(sec->special&SECRET_MASK);
if (sec->damageamount == 0)
{
// If no damage is set, clear all other related properties so that they do not interfere
// with other means of setting them.
sec->damagetype = NAME_None;
sec->damageinterval = 0;
sec->leakydamage = 0;
sec->Flags &= ~SECF_DAMAGEFLAGS;
}
// Reset the planes to their defaults if not all of the plane equation's parameters were found.
if (fplaneflags != 15)
@ -1612,10 +1628,10 @@ public:
{
// [RH] Sectors default to white light with the default fade.
// If they are outside (have a sky ceiling), they use the outside fog.
if (level.outsidefog != 0xff000000 && (sec->GetTexture(sector_t::ceiling) == skyflatnum || (sec->special&0xff) == Sector_Outside))
if (level.outsidefog != 0xff000000 && (sec->GetTexture(sector_t::ceiling) == skyflatnum || (sec->special & 0xff) == Sector_Outside))
{
if (fogMap == NULL)
fogMap = GetSpecialLights (PalEntry (255,255,255), level.outsidefog, 0);
fogMap = GetSpecialLights(PalEntry(255, 255, 255), level.outsidefog, 0);
sec->ColorMap = fogMap;
}
else
@ -1630,7 +1646,7 @@ public:
if (lightcolor == -1) lightcolor = PalEntry(255,255,255);
if (fadecolor == -1)
{
if (level.outsidefog != 0xff000000 && (sec->GetTexture(sector_t::ceiling) == skyflatnum || (sec->special&0xff) == Sector_Outside))
if (level.outsidefog != 0xff000000 && (sec->GetTexture(sector_t::ceiling) == skyflatnum || (sec->special & 0xff) == Sector_Outside))
fadecolor = level.outsidefog;
else
fadecolor = level.fadeto;

View File

@ -362,6 +362,8 @@ player_t &player_t::operator=(const player_t &p)
damagecount = p.damagecount;
bonuscount = p.bonuscount;
hazardcount = p.hazardcount;
hazardtype = p.hazardtype;
hazardinterval = p.hazardinterval;
poisoncount = p.poisoncount;
poisontype = p.poisontype;
poisonpaintype = p.poisonpaintype;
@ -2538,10 +2540,8 @@ void P_PlayerThink (player_t *player)
if (!(player->cheats & CF_PREDICTING))
{
P_PlayerOnSpecial3DFloor (player);
if (player->mo->Sector->special || player->mo->Sector->damageamount != 0)
{
P_PlayerInSpecialSector (player);
}
P_PlayerInSpecialSector (player);
if (player->mo->z <= player->mo->Sector->floorplane.ZatPoint(
player->mo->x, player->mo->y) ||
player->mo->waterlevel)
@ -2600,8 +2600,8 @@ void P_PlayerThink (player_t *player)
if (player->hazardcount)
{
player->hazardcount--;
if (!(level.time & 31) && player->hazardcount > 16*TICRATE)
P_DamageMobj (player->mo, NULL, NULL, 5, NAME_Slime);
if (!(level.time % player->hazardinterval) && player->hazardcount > 16*TICRATE)
P_DamageMobj (player->mo, NULL, NULL, 5, player->hazardtype);
}
if (player->poisoncount && !(level.time & 15))
@ -3014,7 +3014,12 @@ void player_t::Serialize (FArchive &arc)
<< air_finished
<< turnticks
<< oldbuttons;
bool IsBot;
if (SaveVersion >= 4929)
{
arc << hazardtype
<< hazardinterval;
}
bool IsBot = false;
if (SaveVersion >= 4514)
{
arc << Bot;

View File

@ -392,6 +392,20 @@ enum
SECF_NOFALLINGDAMAGE= 2, // No falling damage in this sector
SECF_FLOORDROP = 4, // all actors standing on this floor will remain on it when it lowers very fast.
SECF_NORESPAWN = 8, // players can not respawn in this sector
SECF_FRICTION = 16, // sector has friction enabled
SECF_PUSH = 32, // pushers enabled
SECF_SILENTMOVE = 64, // Sector movement makes mo sound (Eternity got this so this may be useful for an extended cross-port standard.)
SECF_DMGTERRAINFX = 128, // spawns terrain splash when inflicting damage
SECF_ENDGODMODE = 256, // getting damaged by this sector ends god mode
SECF_ENDLEVEL = 512, // ends level when health goes below 10
SECF_HAZARD = 1024, // Change to Strife's delayed damage handling.
SECF_WASSECRET = 1 << 30, // a secret that was discovered
SECF_SECRET = 1 << 31, // a secret sector
SECF_DAMAGEFLAGS = SECF_ENDGODMODE|SECF_ENDLEVEL|SECF_DMGTERRAINFX|SECF_HAZARD,
SECF_NOMODIFY = SECF_SECRET|SECF_WASSECRET, // not modifiable by Sector_ChangeFlags
SECF_SPECIALFLAGS = SECF_DAMAGEFLAGS|SECF_FRICTION|SECF_PUSH, // these flags originate from 'special and must be transferrable by floor thinkers
};
enum
@ -466,6 +480,23 @@ struct FTransform
fixed_t base_angle, base_yoffs;
};
struct secspecial_t
{
FNameNoInit damagetype; // [RH] Means-of-death for applied damage
int damageamount; // [RH] Damage to do while standing on floor
short special;
short damageinterval; // Interval for damage application
short leakydamage; // chance of leaking through radiation suit
int Flags;
void Clear()
{
memset(this, 0, sizeof(*this));
}
};
FArchive &operator<< (FArchive &arc, secspecial_t &p);
struct sector_t
{
// Member functions
@ -695,7 +726,35 @@ struct sector_t
return pos == floor? floorplane:ceilingplane;
}
bool isSecret() const
{
return !!(Flags & SECF_SECRET);
}
bool wasSecret() const
{
return !!(Flags & SECF_WASSECRET);
}
void ClearSecret()
{
Flags &= ~SECF_SECRET;
}
void ClearSpecial()
{
// clears all variables that originate from 'special'. Used for sector type transferring thinkers
special = 0;
damageamount = 0;
damageinterval = 0;
damagetype = NAME_None;
leakydamage = 0;
Flags &= ~SECF_SPECIALFLAGS;
}
void TransferSpecial(sector_t *model);
void GetSpecial(secspecial_t *spec);
void SetSpecial(const secspecial_t *spec);
bool PlaneMoving(int pos);
@ -764,7 +823,7 @@ struct sector_t
float gravity; // [RH] Sector gravity (1.0 is normal)
FNameNoInit damagetype; // [RH] Means-of-death for applied damage
short damageamount; // [RH] Damage to do while standing on floor
int damageamount; // [RH] Damage to do while standing on floor
short damageinterval; // Interval for damage application
short leakydamage; // chance of leaking through radiation suit
@ -782,7 +841,6 @@ struct sector_t
// regular sky.
TObjPtr<ASkyViewpoint> FloorSkyBox, CeilingSkyBox;
short secretsector; //jff 2/16/98 remembers if sector WAS secret (automap)
int sectornum; // for comparing sector copies
extsector_t * e; // This stores data that requires construction/destruction. Such data must not be copied by R_FakeFlat.

View File

@ -58,7 +58,7 @@ CUSTOM_CVAR (Int, timidity_pipe, 90, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
}
}
CUSTOM_CVAR (Int, timidity_frequency, 22050, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
CUSTOM_CVAR (Int, timidity_frequency, 44100, CVAR_ARCHIVE|CVAR_GLOBALCONFIG)
{ // Clamp frequency to Timidity's limits
if (self < 4000)
self = 4000;

View File

@ -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 4528
#define SAVEVER 4529
#define SAVEVERSTRINGIFY2(x) #x
#define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(x)

View File

@ -0,0 +1,29 @@
/***** BFG Scorches ********************************************************/
decal BFGLightning1
{
pic BFGLITE1
shade "80 80 ff"
fullbright
randomflipx
animator GoAway2
lowerdecal BFGScorch
}
decal BFGLightning2
{
pic BFGLITE2
shade "80 80 ff"
fullbright
randomflipy
animator GoAway2
lowerdecal BFGScorch
}
decalgroup BFGLightning
{
BFGLightning1 1
BFGLightning2 1
}

View File

@ -3,7 +3,7 @@ include "mapinfo/doom2.txt"
gameinfo
{
titlepage = "INTERPIC"
titlepage = "DMENUPIC"
}
clearepisodes