mirror of
https://git.do.srb2.org/STJr/SRB2.git
synced 2025-03-24 03:32:22 +00:00
Merge branch 'nightsplus-le' into 'master'
NiGHTS Linedef Executor Triggers Closes #102 See merge request STJr/SRB2Internal!142
This commit is contained in:
commit
01314b6674
5 changed files with 249 additions and 3 deletions
|
@ -1126,6 +1126,8 @@ static boolean PIT_CheckThing(mobj_t *thing)
|
|||
// Respawn rings and items
|
||||
P_ReloadRings();
|
||||
}
|
||||
|
||||
P_RunNightsLapExecutors(pl->mo);
|
||||
}
|
||||
droneobj->extravalue1 = pl->flyangle;
|
||||
droneobj->extravalue2 = (INT32)leveltime + TICRATE;
|
||||
|
|
|
@ -8775,7 +8775,8 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
|
|||
nummaprings = -1; // no perfect bonus, rings are free
|
||||
break;
|
||||
case MT_EGGCAPSULE:
|
||||
mobj->extravalue1 = -1; // timer for how long a player has been at the capsule
|
||||
mobj->extravalue1 = -1; // sphere timer for how long a player has been at the capsule
|
||||
mobj->extravalue2 = -1; // tic timer for how long a player has been at the capsule
|
||||
break;
|
||||
case MT_REDTEAMRING:
|
||||
mobj->color = skincolor_redteam;
|
||||
|
|
227
src/p_spec.c
227
src/p_spec.c
|
@ -1375,6 +1375,67 @@ void P_ChangeSectorTag(UINT32 sector, INT16 newtag)
|
|||
}
|
||||
}
|
||||
|
||||
//
|
||||
// P_RunNightserizeExecutors
|
||||
//
|
||||
void P_RunNightserizeExecutors(mobj_t *actor)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < numlines; i++)
|
||||
{
|
||||
if (lines[i].special == 323 || lines[i].special == 324)
|
||||
P_RunTriggerLinedef(&lines[i], actor, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// P_RunDeNightserizeExecutors
|
||||
//
|
||||
void P_RunDeNightserizeExecutors(mobj_t *actor)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < numlines; i++)
|
||||
{
|
||||
if (lines[i].special == 325 || lines[i].special == 326)
|
||||
P_RunTriggerLinedef(&lines[i], actor, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// P_RunNightsLapExecutors
|
||||
//
|
||||
void P_RunNightsLapExecutors(mobj_t *actor)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < numlines; i++)
|
||||
{
|
||||
if (lines[i].special == 327 || lines[i].special == 328)
|
||||
P_RunTriggerLinedef(&lines[i], actor, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// P_RunNightsCapsuleTouchExecutors
|
||||
//
|
||||
void P_RunNightsCapsuleTouchExecutors(mobj_t *actor, boolean entering, boolean enoughspheres)
|
||||
{
|
||||
size_t i;
|
||||
|
||||
for (i = 0; i < numlines; i++)
|
||||
{
|
||||
if ((lines[i].special == 329 || lines[i].special == 330)
|
||||
&& ((entering && (lines[i].flags & ML_TFERLINE))
|
||||
|| (!entering && !(lines[i].flags & ML_TFERLINE)))
|
||||
&& ((lines[i].flags & ML_DONTPEGTOP)
|
||||
|| (enoughspheres && !(lines[i].flags & ML_BOUNCY))
|
||||
|| (!enoughspheres && (lines[i].flags & ML_BOUNCY))))
|
||||
P_RunTriggerLinedef(&lines[i], actor, NULL);
|
||||
}
|
||||
}
|
||||
|
||||
/** Hashes the sector tags across the sectors and linedefs.
|
||||
*
|
||||
* \sa P_FindSectorFromTag, P_ChangeSectorTag
|
||||
|
@ -1458,6 +1519,145 @@ static void P_AddExecutorDelay(line_t *line, mobj_t *mobj, sector_t *sector)
|
|||
P_AddThinker(&e->thinker);
|
||||
}
|
||||
|
||||
/** Used by P_RunTriggerLinedef to check a NiGHTS trigger linedef's conditions
|
||||
*
|
||||
* \param triggerline Trigger linedef to check conditions for; should NEVER be NULL.
|
||||
* \param actor Object initiating the action; should not be NULL.
|
||||
* \sa P_RunTriggerLinedef
|
||||
*/
|
||||
static boolean P_CheckNightsTriggerLine(line_t *triggerline, mobj_t *actor)
|
||||
{
|
||||
INT16 specialtype = triggerline->special;
|
||||
size_t i;
|
||||
|
||||
UINT8 inputmare = max(0, min(255, sides[triggerline->sidenum[0]].textureoffset>>FRACBITS));
|
||||
UINT8 inputlap = max(0, min(255, sides[triggerline->sidenum[0]].rowoffset>>FRACBITS));
|
||||
|
||||
boolean ltemare = triggerline->flags & ML_NOCLIMB;
|
||||
boolean gtemare = triggerline->flags & ML_BLOCKMONSTERS;
|
||||
boolean ltelap = triggerline->flags & ML_EFFECT1;
|
||||
boolean gtelap = triggerline->flags & ML_EFFECT2;
|
||||
|
||||
boolean lapfrombonustime = triggerline->flags & ML_EFFECT3;
|
||||
boolean perglobalinverse = triggerline->flags & ML_DONTPEGBOTTOM;
|
||||
boolean perglobal = !(triggerline->flags & ML_EFFECT4) && !perglobalinverse;
|
||||
|
||||
boolean donomares = triggerline->flags & ML_BOUNCY; // nightserize: run at end of level (no mares)
|
||||
boolean fromnonights = triggerline->flags & ML_TFERLINE; // nightserize: from non-nights // denightserize: all players no nights
|
||||
boolean fromnights = triggerline->flags & ML_DONTPEGTOP; // nightserize: from nights // denightserize: >0 players are nights
|
||||
|
||||
UINT8 currentmare = UINT8_MAX;
|
||||
UINT8 currentlap = UINT8_MAX;
|
||||
|
||||
// Do early returns for Nightserize
|
||||
if (specialtype >= 323 && specialtype <= 324)
|
||||
{
|
||||
// run only when no mares are found
|
||||
if (donomares && P_FindLowestMare() != UINT8_MAX)
|
||||
return false;
|
||||
|
||||
// run only if there is a mare present
|
||||
if (!donomares && P_FindLowestMare() == UINT8_MAX)
|
||||
return false;
|
||||
|
||||
// run only if player is nightserizing from non-nights
|
||||
if (fromnonights)
|
||||
{
|
||||
if (!actor->player)
|
||||
return false;
|
||||
else if (actor->player->powers[pw_carry] == CR_NIGHTSMODE)
|
||||
return false;
|
||||
}
|
||||
// run only if player is nightserizing from nights
|
||||
else if (fromnights)
|
||||
{
|
||||
if (!actor->player)
|
||||
return false;
|
||||
else if (actor->player->powers[pw_carry] != CR_NIGHTSMODE)
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// Get current mare and lap (and check early return for DeNightserize)
|
||||
if (perglobal || perglobalinverse
|
||||
|| (specialtype >= 325 && specialtype <= 326 && (fromnonights || fromnights)))
|
||||
{
|
||||
UINT8 playersarenights = 0;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
continue;
|
||||
|
||||
// denightserize: run only if all players are not nights
|
||||
if (specialtype >= 325 && specialtype <= 326 && fromnonights
|
||||
&& players[i].powers[pw_carry] == CR_NIGHTSMODE)
|
||||
return false;
|
||||
|
||||
// count number of nights players for denightserize return
|
||||
if (specialtype >= 325 && specialtype <= 326 && fromnights
|
||||
&& players[i].powers[pw_carry] == CR_NIGHTSMODE)
|
||||
playersarenights++;
|
||||
|
||||
UINT8 lap = lapfrombonustime ? players[i].marebonuslap : players[i].marelap;
|
||||
|
||||
// get highest mare/lap of players
|
||||
if (perglobal)
|
||||
{
|
||||
if (players[i].mare > currentmare || currentmare == UINT8_MAX)
|
||||
{
|
||||
currentmare = players[i].mare;
|
||||
currentlap = UINT8_MAX;
|
||||
}
|
||||
if (players[i].mare == currentmare
|
||||
&& (lap > currentlap || currentlap == UINT8_MAX))
|
||||
currentlap = lap;
|
||||
}
|
||||
// get lowest mare/lap of players
|
||||
else if (perglobalinverse)
|
||||
{
|
||||
if (players[i].mare < currentmare || currentmare == UINT8_MAX)
|
||||
{
|
||||
currentmare = players[i].mare;
|
||||
currentlap = UINT8_MAX;
|
||||
}
|
||||
if (players[i].mare == currentmare
|
||||
&& (lap < currentlap || currentlap == UINT8_MAX))
|
||||
currentlap = lap;
|
||||
}
|
||||
}
|
||||
|
||||
// denightserize: run only if >0 players are nights
|
||||
if (specialtype >= 325 && specialtype <= 326 && fromnights
|
||||
&& playersarenights < 1)
|
||||
return false;
|
||||
}
|
||||
// get current mare/lap from triggering player
|
||||
else if (!perglobal && !perglobalinverse)
|
||||
{
|
||||
if (!actor->player)
|
||||
return false;
|
||||
currentmare = actor->player->mare;
|
||||
currentlap = lapfrombonustime ? actor->player->marebonuslap : actor->player->marelap;
|
||||
}
|
||||
|
||||
if (lapfrombonustime && !currentlap)
|
||||
return false; // special case: player->marebonuslap is 0 until passing through on bonus time. Don't trigger lines looking for inputlap 0.
|
||||
|
||||
// Compare current mare/lap to input mare/lap based on rules
|
||||
if (!(specialtype >= 323 && specialtype <= 324 && donomares) // don't return false if donomares and we got this far
|
||||
&& ((ltemare && currentmare > inputmare)
|
||||
|| (gtemare && currentmare < inputmare)
|
||||
|| (!ltemare && !gtemare && currentmare != inputmare)
|
||||
|| (ltelap && currentlap > inputlap)
|
||||
|| (gtelap && currentlap < inputlap)
|
||||
|| (!ltelap && !gtelap && currentlap != inputlap))
|
||||
)
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/** Used by P_LinedefExecute to check a trigger linedef's conditions
|
||||
* The linedef executor specials in the trigger linedef's sector are run if all conditions are met.
|
||||
* Return false cancels P_LinedefExecute, this happens if a condition is not met.
|
||||
|
@ -1668,6 +1868,18 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
|
|||
return false;
|
||||
}
|
||||
break;
|
||||
case 323: // nightserize - each time
|
||||
case 324: // nightserize - once
|
||||
case 325: // denightserize - each time
|
||||
case 326: // denightserize - once
|
||||
case 327: // nights lap - each time
|
||||
case 328: // nights lap - once
|
||||
case 329: // nights egg capsule touch - each time
|
||||
case 330: // nights egg capsule touch - once
|
||||
if (!P_CheckNightsTriggerLine(triggerline, actor))
|
||||
return false;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1796,6 +2008,10 @@ boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller
|
|||
|| specialtype == 318 // Unlockable trigger - Once
|
||||
|| specialtype == 320 // Unlockable - Once
|
||||
|| specialtype == 321 || specialtype == 322 // Trigger on X calls - Continuous + Each Time
|
||||
|| specialtype == 324 // Nightserize - Once
|
||||
|| specialtype == 326 // DeNightserize - Once
|
||||
|| specialtype == 328 // Nights lap - Once
|
||||
|| specialtype == 330 // Nights Bonus Time - Once
|
||||
|| specialtype == 399) // Level Load
|
||||
triggerline->special = 0; // Clear it out
|
||||
|
||||
|
@ -6419,6 +6635,17 @@ void P_SpawnSpecials(INT32 fromnetsave)
|
|||
}
|
||||
break;
|
||||
|
||||
// NiGHTS trigger executors
|
||||
case 323:
|
||||
case 324:
|
||||
case 325:
|
||||
case 326:
|
||||
case 327:
|
||||
case 328:
|
||||
case 329:
|
||||
case 330:
|
||||
break;
|
||||
|
||||
case 399: // Linedef execute on map load
|
||||
// This is handled in P_RunLevelLoadExecutors.
|
||||
break;
|
||||
|
|
|
@ -66,6 +66,10 @@ void P_SwitchWeather(INT32 weathernum);
|
|||
boolean P_RunTriggerLinedef(line_t *triggerline, mobj_t *actor, sector_t *caller);
|
||||
void P_LinedefExecute(INT16 tag, mobj_t *actor, sector_t *caller);
|
||||
void P_ChangeSectorTag(UINT32 sector, INT16 newtag);
|
||||
void P_RunNightserizeExecutors(mobj_t *actor);
|
||||
void P_RunDeNightserizeExecutors(mobj_t *actor);
|
||||
void P_RunNightsLapExecutors(mobj_t *actor);
|
||||
void P_RunNightsCapsuleTouchExecutors(mobj_t *actor, boolean entering, boolean enoughspheres);
|
||||
|
||||
ffloor_t *P_GetFFloorByID(sector_t *sec, UINT16 id);
|
||||
|
||||
|
|
16
src/p_user.c
16
src/p_user.c
|
@ -631,6 +631,8 @@ static void P_DeNightserizePlayer(player_t *player)
|
|||
|
||||
// Restore from drowning music
|
||||
P_RestoreMusic(player);
|
||||
|
||||
P_RunDeNightserizeExecutors(player->mo);
|
||||
}
|
||||
|
||||
//
|
||||
|
@ -790,6 +792,9 @@ void P_NightserizePlayer(player_t *player, INT32 nighttime)
|
|||
(player->flyangle > 90 && player->flyangle < 270 ? ANGLE_90 : -ANGLE_90)
|
||||
: (player->flyangle > 90 && player->flyangle < 270 ? -ANGLE_90 : ANGLE_90));
|
||||
|
||||
// Do this before setting CR_NIGHTSMODE so we can tell if player was non-NiGHTS
|
||||
P_RunNightserizeExecutors(player->mo);
|
||||
|
||||
player->powers[pw_carry] = CR_NIGHTSMODE;
|
||||
}
|
||||
|
||||
|
@ -5952,6 +5957,8 @@ static void P_DoNiGHTSCapsule(player_t *player)
|
|||
{
|
||||
INT32 i;
|
||||
|
||||
player->capsule->extravalue2++; // tic counter
|
||||
|
||||
if (abs(player->mo->x-player->capsule->x) <= 2*FRACUNIT)
|
||||
{
|
||||
P_UnsetThingPosition(player->mo);
|
||||
|
@ -6013,6 +6020,9 @@ static void P_DoNiGHTSCapsule(player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
if (player->capsule->extravalue2 <= 0 && player->capsule->health > 0)
|
||||
P_RunNightsCapsuleTouchExecutors(player->mo, true, player->spheres >= player->capsule->health); // run capsule entrance executors
|
||||
|
||||
// Time to blow it up!
|
||||
if (player->mo->x == player->capsule->x
|
||||
&& player->mo->y == player->capsule->y
|
||||
|
@ -6036,7 +6046,7 @@ static void P_DoNiGHTSCapsule(player_t *player)
|
|||
player->capsule->flags &= ~MF_NOGRAVITY;
|
||||
player->capsule->momz = 5*FRACUNIT;
|
||||
player->capsule->reactiontime = 0;
|
||||
player->capsule->extravalue1 = -1;
|
||||
player->capsule->extravalue1 = player->capsule->extravalue2 = -1;
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
if (playeringame[i] && !player->exiting && players[i].mare == player->mare)
|
||||
|
@ -6105,6 +6115,7 @@ static void P_DoNiGHTSCapsule(player_t *player)
|
|||
P_SetTarget(&players[i].capsule, NULL); // Remove capsule from everyone now that it is dead!
|
||||
S_StartScreamSound(player->mo, sfx_ngdone);
|
||||
P_SwitchSpheresBonusMode(true);
|
||||
P_RunNightsCapsuleTouchExecutors(player->mo, false, true); // run capsule exit executors, and we destroyed it
|
||||
}
|
||||
}
|
||||
else
|
||||
|
@ -6113,7 +6124,8 @@ static void P_DoNiGHTSCapsule(player_t *player)
|
|||
player->texttimer = 4*TICRATE;
|
||||
player->textvar = 3; // Get more rings!
|
||||
player->capsule->reactiontime = 0;
|
||||
player->capsule->extravalue1 = -1;
|
||||
player->capsule->extravalue1 = player->capsule->extravalue2 = -1;
|
||||
P_RunNightsCapsuleTouchExecutors(player->mo, false, false); // run capsule exit executors, and we lacked rings
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
Loading…
Reference in a new issue