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. hidden = <bool>; // if true this sector will not be drawn on the textured automap.
waterzone = <bool>; // Sector is under water and swimmable 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") 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) damagetype = <string>; // Damage type for sector damage, Default = "None". (generic damage)
damageinterval = <int>; // Interval in tics between damage application, default = 32. damageinterval = <int>; // Interval in tics between damage application, default = 32.
leakiness = <int>; // Probability of leaking through radiation suit (0 = never, 256 = always), default = 0. 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 * Note about dropactors

View file

@ -2071,17 +2071,17 @@ static bool AM_CheckSecret(line_t *line)
{ {
if (line->frontsector != NULL) 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 (am_map_secrets==2 && !(line->flags & ML_SECRET)) return true;
} }
} }
if (line->backsector != NULL) 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; 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. //Checks if a sector is dangerous.
bool FCajunMaster::IsDangerous (sector_t *sec) bool FCajunMaster::IsDangerous (sector_t *sec)
{ {
int special; return sec->damageamount > 0;
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;
} }

View file

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

View file

@ -422,6 +422,8 @@ public:
int killcount, itemcount, secretcount; // for intermission int killcount, itemcount, secretcount; // for intermission
int damagecount, bonuscount;// for screen flashing int damagecount, bonuscount;// for screen flashing
int hazardcount; // for delayed Strife damage 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 int poisoncount; // screen flash for poison damage
FName poisontype; // type of poison damage to apply FName poisontype; // type of poison damage to apply
FName poisonpaintype; // type of Pain state to enter for poison damage 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 // 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) void FParser::SF_SectorType(void)
{ {
int tagnum, secnum; // I don't think this was ever used publicly so I'm not going to bother fixing it.
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;
}
} }
//========================================================================== //==========================================================================

View file

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

View file

@ -139,7 +139,7 @@ void DLightningThinker::LightningFlash ()
for (i = numsectors, j = 0; i > 0; --i, ++j, ++tempSec) for (i = numsectors, j = 0; i > 0; --i, ++j, ++tempSec)
{ {
// allow combination of the lightning sector specials with bit masks // 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 if (tempSec->GetTexture(sector_t::ceiling) == skyflatnum
|| special == Light_IndoorLightning1 || special == Light_IndoorLightning1
|| special == Light_IndoorLightning2 || 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 (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; int anglespeed = tagManager.GetFirstSectorTag(sec) - 100;
fixed_t speed = (anglespeed % 10) << (FRACBITS - 4); fixed_t speed = (anglespeed % 10) << (FRACBITS - 4);

View file

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

View file

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

View file

@ -345,8 +345,7 @@ void P_PlayerOnSpecial3DFloor(player_t* player)
} }
// Apply sector specials // 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!) // Apply flat specials (using the ceiling!)
P_PlayerOnSpecialFlat( P_PlayerOnSpecialFlat(

View file

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

View file

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

View file

@ -1255,8 +1255,7 @@ int P_DamageMobj (AActor *target, AActor *inflictor, AActor *source, int damage,
} }
// end of game hell hack // end of game hell hack
if ((target->Sector->special & 255) == dDamage_End if ((target->Sector->Flags & SECF_ENDLEVEL) && damage >= target->health)
&& damage >= target->health)
{ {
damage = target->health - 1; 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); l = new DPhased (sector, baselevel);
int numsteps = PhaseHelper (sector->NextSpecialSector ( int numsteps = PhaseHelper (sector->NextSpecialSector (
(sector->special & 0x00ff) == LightSequenceSpecial1 ? sector->special == LightSequenceSpecial1 ?
LightSequenceSpecial2 : LightSequenceSpecial1, prev), LightSequenceSpecial2 : LightSequenceSpecial1, prev),
index + 1, l->m_BaseLevel, sector); index + 1, l->m_BaseLevel, sector);
l->m_Phase = ((numsteps - index - 1) * 64) / numsteps; l->m_Phase = ((numsteps - index - 1) * 64) / numsteps;
sector->special &= 0xff00; sector->special = 0;
return numsteps; return numsteps;
} }
@ -820,7 +820,6 @@ DPhased::DPhased (sector_t *sector, int baselevel, int phase)
{ {
m_BaseLevel = baselevel; m_BaseLevel = baselevel;
m_Phase = phase; m_Phase = phase;
sector->special &= 0xff00;
} }
//============================================================================ //============================================================================

View file

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

File diff suppressed because it is too large Load diff

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) Terrains[TerrainTypes[sec->GetTexture(sector_t::floor)]].Friction == 0)
{ {
continue; continue;

View file

@ -3452,7 +3452,7 @@ void AActor::Tick ()
if (player != NULL) if (player != NULL)
{ {
int scrolltype = sec->special & 0xff; int scrolltype = sec->special;
if (scrolltype >= Scroll_North_Slow && if (scrolltype >= Scroll_North_Slow &&
scrolltype <= Scroll_SouthWest_Fast) scrolltype <= Scroll_SouthWest_Fast)
@ -4424,7 +4424,7 @@ APlayerPawn *P_SpawnPlayer (FPlayerStart *mthing, int playernum, int flags)
( gameaction != ga_worlddone ) && ( gameaction != ga_worlddone ) &&
( p->mo != NULL ) && ( p->mo != NULL ) &&
( !(p->mo->Sector->Flags & SECF_NORESPAWN) ) && ( !(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_x = p->mo->x;
spawn_y = p->mo->y; spawn_y = p->mo->y;
@ -5320,7 +5320,7 @@ int P_GetThingFloorType (AActor *thing)
// Returns true if hit liquid and splashed, false if not. // 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) if (thing->flags3 & MF3_DONTSPLASH)
return false; return false;
@ -5362,24 +5362,27 @@ bool P_HitWater (AActor * thing, sector_t * sec, fixed_t x, fixed_t y, fixed_t z
} }
#endif #endif
for(unsigned int i=0;i<sec->e->XFloor.ffloors.Size();i++) if (!force)
{ {
F3DFloor * rover = sec->e->XFloor.ffloors[i]; for (unsigned int i = 0; i<sec->e->XFloor.ffloors.Size(); 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
{ {
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]; if (rover->flags & (FF_SOLID | FF_SWIMMABLE))
goto foundone; {
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(); 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)]; terrainnum = TerrainTypes[sec->GetTexture(sector_t::floor)];
} }
@ -5403,7 +5406,7 @@ foundone:
// Don't splash for living things with small vertical velocities. // Don't splash for living things with small vertical velocities.
// There are levels where the constant splashing from the monsters gets extremely annoying // 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; return Terrains[terrainnum].IsLiquid;
splash = &Splashes[splashnum]; 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); 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); if (sector->seqType >= 0)
} {
else if (sector->SeqName != NAME_None) SN_StartSequence(sector, CHAN_FLOOR, sector->seqType, SEQ_PLATFORM, 0);
{ }
SN_StartSequence (sector, CHAN_FLOOR, sector->SeqName, 0); else if (sector->SeqName != NAME_None)
} {
else SN_StartSequence(sector, CHAN_FLOOR, sector->SeqName, 0);
{ }
SN_StartSequence (sector, CHAN_FLOOR, "Floor", 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) void DPlat::PlayPlatSound (const char *sound)
{ {
if (m_Sector->Flags & SECF_SILENTMOVE) return;
if (m_Sector->seqType >= 0) if (m_Sector->seqType >= 0)
{ {
SN_StartSequence (m_Sector, CHAN_FLOOR, m_Sector->seqType, SEQ_PLATFORM, 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) if (line)
sec->SetTexture(sector_t::floor, line->sidedef[0]->sector->GetTexture(sector_t::floor)); sec->SetTexture(sector_t::floor, line->sidedef[0]->sector->GetTexture(sector_t::floor));
if (change == 1) if (change == 1) sec->ClearSpecial();
sec->special &= SECRET_MASK; // Stop damage and other stuff, if any
} }
switch (type) 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_Low = sec->floorplane.d;
plat->m_Status = DPlat::up; plat->m_Status = DPlat::up;
plat->PlayPlatSound ("Floor"); plat->PlayPlatSound ("Floor");
sec->special &= SECRET_MASK; // NO MORE DAMAGE, IF APPLICABLE sec->ClearSpecial();
break; break;
case DPlat::platUpByValue: case DPlat::platUpByValue:

View file

@ -368,8 +368,17 @@ void P_SerializeWorld (FArchive &arc)
<< sec->planes[sector_t::ceiling] << sec->planes[sector_t::ceiling]
<< sec->heightsec << sec->heightsec
<< sec->bottommap << sec->midmap << sec->topmap << sec->bottommap << sec->midmap << sec->topmap
<< sec->gravity << sec->gravity;
<< sec->damageamount; if (SaveVersion >= 4529)
{
arc << sec->damageamount;
}
else
{
short dmg;
arc << dmg;
sec->damageamount = dmg;
}
if (SaveVersion >= 4528) if (SaveVersion >= 4528)
{ {
arc << sec->damageinterval arc << sec->damageinterval
@ -398,15 +407,22 @@ void P_SerializeWorld (FArchive &arc)
} }
} }
arc << sec->SoundTarget arc << sec->SoundTarget
<< sec->SecActTarget << sec->SecActTarget
<< sec->sky << sec->sky
<< sec->MoreFlags << sec->MoreFlags
<< sec->Flags << sec->Flags
<< sec->FloorSkyBox << sec->CeilingSkyBox << sec->FloorSkyBox << sec->CeilingSkyBox
<< sec->ZoneNumber << sec->ZoneNumber;
<< sec->secretsector if (SaveVersion < 4529)
<< sec->interpolations[0] {
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[1]
<< sec->interpolations[2] << sec->interpolations[2]
<< sec->interpolations[3] << 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)) && if (NULL != (tsec = getNextSector (ln, this)) &&
tsec != nogood && tsec != nogood &&
(tsec->special & 0x00ff) == type) tsec->special == type)
{ {
return tsec; 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 secplane_t::CopyPlaneIfValid (secplane_t *dest, const secplane_t *opp) const
{ {
bool copy = false; bool copy = false;

View file

@ -1512,7 +1512,6 @@ void P_LoadSectors (MapData *map, FMissingTextureTracker &missingtex)
ss->special = LittleShort(ms->special); ss->special = LittleShort(ms->special);
else // [RH] Translate to new sector special else // [RH] Translate to new sector special
ss->special = P_TranslateSectorSpecial (LittleShort(ms->special)); ss->special = P_TranslateSectorSpecial (LittleShort(ms->special));
ss->secretsector = !!(ss->special&SECRET_MASK);
tagManager.AddSectorTag(i, LittleShort(ms->tag)); tagManager.AddSectorTag(i, LittleShort(ms->tag));
ss->thinglist = NULL; ss->thinglist = NULL;
ss->touching_thinglist = NULL; // phares 3/14/98 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->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(); 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. // Has hit ground.
AInventory *ironfeet; 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 // [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)); 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 // P_SpawnSpecials
// //
@ -1187,135 +1318,7 @@ void P_SpawnSpecials (void)
if (sector->special == 0) if (sector->special == 0)
continue; continue;
// [RH] All secret sectors are marked with a BOOM-ish bitfield P_InitSectorSpecial(sector, sector->special, false);
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;
}
} }
// Init other misc stuff // Init other misc stuff
@ -2056,11 +2059,11 @@ void P_SetSectorFriction (int tag, int amount, bool alterFlag)
// can be enabled and disabled at will. // can be enabled and disabled at will.
if (friction == ORIG_FRICTION) if (friction == ORIG_FRICTION)
{ {
sectors[s].special &= ~FRICTION_MASK; sectors[s].Flags &= ~SECF_FRICTION;
} }
else 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. // Be sure the special sector type is still turned on. If so, proceed.
// Else, bail out; the sector type has been changed on us. // Else, bail out; the sector type has been changed on us.
if (!(sec->special & PUSH_MASK)) if (!(sec->Flags & SECF_PUSH))
return; return;
// For constant pushers (wind/current) there are 3 situations: // 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); bool CheckIfExitIsGood (AActor *self, level_info_t *info);
// at map load // at map load
void P_InitSectorSpecial(sector_t *sector, int special, bool nothinkers);
void P_SpawnSpecials (void); void P_SpawnSpecials (void);
// every tic // every tic
@ -673,7 +674,7 @@ protected:
// [RH] Need these for BOOM-ish transferring ceilings // [RH] Need these for BOOM-ish transferring ceilings
FTextureID m_Texture; FTextureID m_Texture;
int m_NewSpecial; secspecial_t m_NewSpecial;
// ID // ID
int m_Tag; int m_Tag;
@ -760,7 +761,7 @@ protected:
int m_Crush; int m_Crush;
bool m_Hexencrush; bool m_Hexencrush;
int m_Direction; int m_Direction;
int m_NewSpecial; secspecial_t m_NewSpecial;
FTextureID m_Texture; FTextureID m_Texture;
fixed_t m_FloorDestDist; fixed_t m_FloorDestDist;
fixed_t m_Speed; fixed_t m_Speed;

View file

@ -1542,6 +1542,14 @@ public:
sec->leakydamage = CheckInt(key); sec->leakydamage = CheckInt(key);
break; break;
case NAME_damageterraineffect:
Flag(sec->Flags, SECF_DMGTERRAINFX, key);
break;
case NAME_damagehazard:
Flag(sec->Flags, SECF_HAZARD, key);
break;
case NAME_MoreIds: case NAME_MoreIds:
// delay parsing of the tag string until parsing of the sector is complete // 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. // 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. // Reset the planes to their defaults if not all of the plane equation's parameters were found.
if (fplaneflags != 15) if (fplaneflags != 15)
@ -1612,10 +1628,10 @@ public:
{ {
// [RH] Sectors default to white light with the default fade. // [RH] Sectors default to white light with the default fade.
// If they are outside (have a sky ceiling), they use the outside fog. // 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) if (fogMap == NULL)
fogMap = GetSpecialLights (PalEntry (255,255,255), level.outsidefog, 0); fogMap = GetSpecialLights(PalEntry(255, 255, 255), level.outsidefog, 0);
sec->ColorMap = fogMap; sec->ColorMap = fogMap;
} }
else else
@ -1628,9 +1644,9 @@ public:
else else
{ {
if (lightcolor == -1) lightcolor = PalEntry(255,255,255); if (lightcolor == -1) lightcolor = PalEntry(255,255,255);
if (fadecolor == -1) 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; fadecolor = level.outsidefog;
else else
fadecolor = level.fadeto; fadecolor = level.fadeto;

View file

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

View file

@ -392,6 +392,20 @@ enum
SECF_NOFALLINGDAMAGE= 2, // No falling damage in this sector 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_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_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 enum
@ -466,6 +480,23 @@ struct FTransform
fixed_t base_angle, base_yoffs; 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 struct sector_t
{ {
// Member functions // Member functions
@ -695,7 +726,35 @@ struct sector_t
return pos == floor? floorplane:ceilingplane; 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); bool PlaneMoving(int pos);
@ -764,7 +823,7 @@ struct sector_t
float gravity; // [RH] Sector gravity (1.0 is normal) float gravity; // [RH] Sector gravity (1.0 is normal)
FNameNoInit damagetype; // [RH] Means-of-death for applied damage 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 damageinterval; // Interval for damage application
short leakydamage; // chance of leaking through radiation suit short leakydamage; // chance of leaking through radiation suit
@ -782,7 +841,6 @@ struct sector_t
// regular sky. // regular sky.
TObjPtr<ASkyViewpoint> FloorSkyBox, CeilingSkyBox; TObjPtr<ASkyViewpoint> FloorSkyBox, CeilingSkyBox;
short secretsector; //jff 2/16/98 remembers if sector WAS secret (automap)
int sectornum; // for comparing sector copies 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. 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 { // Clamp frequency to Timidity's limits
if (self < 4000) if (self < 4000)
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 // Use 4500 as the base git save version, since it's higher than the
// SVN revision ever got. // SVN revision ever got.
#define SAVEVER 4528 #define SAVEVER 4529
#define SAVEVERSTRINGIFY2(x) #x #define SAVEVERSTRINGIFY2(x) #x
#define SAVEVERSTRINGIFY(x) SAVEVERSTRINGIFY2(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 gameinfo
{ {
titlepage = "INTERPIC" titlepage = "DMENUPIC"
} }
clearepisodes clearepisodes