Optimisation: reduce the number of calls to M_CheckUnlockConditions

- For P_Ticker()'s calls to M_UpdateUnlockablesAndExtraEmblems
    - Do not check non-UCRP_REQUIRESPLAYING conditions
        - Controlled by a new `boolean doall` parameter to M_UpdateUnlockablesAndExtraEmblems
        - Most other contexts have this as true
        - Forced true if update is meant to be silent
    - Only check UCRP_REQUIRESPLAYING conditions if a relevant property has been touched
        - Controlled by a new `boolean checkthisframe` property on roundcondition_t
        - Set in all contexts where roundcondition_t is modified
        - Would also be set on lap change, but that case is already covered by the following
- Check all conditions, both UCRP_REQUIRESPLAYING and not, on:
    - local player K_HandleLapIncrement
    - local player P_DoPlayerExit
    - local player P_DoTimeOver
    - Controlled by a new `boolean deferredconditioncheck` property on gamedata_t
This commit is contained in:
toaster 2023-03-12 13:52:28 +00:00
parent 5a9281ecfb
commit 01f6eb71f5
19 changed files with 106 additions and 43 deletions

View file

@ -337,6 +337,9 @@ struct botvars_t
struct roundconditions_t
{
// Reduce the number of checks by only updating when this is true
boolean checkthisframe;
// Trivial Yes/no events across multiple UCRP's
boolean fell_off;
boolean touched_offroad;

View file

@ -1083,7 +1083,7 @@ void F_GameEvaluationTicker(void)
{
++gamedata->timesBeaten;
M_UpdateUnlockablesAndExtraEmblems(true);
M_UpdateUnlockablesAndExtraEmblems(true, true);
G_SaveGameData(true);
}
else

View file

@ -4194,7 +4194,7 @@ void G_SaveDemo(void)
if (gamedata->eversavedreplay == false)
{
gamedata->eversavedreplay = true;
M_UpdateUnlockablesAndExtraEmblems(true);
M_UpdateUnlockablesAndExtraEmblems(true, true);
G_SaveGameData(true);
}
}

View file

@ -667,7 +667,7 @@ void G_UpdateRecords(void)
S_StartSound(NULL, sfx_ncitem);
}
M_UpdateUnlockablesAndExtraEmblems(true);
M_UpdateUnlockablesAndExtraEmblems(true, true);
gamedata->deferredsave = true;
}
@ -3838,7 +3838,7 @@ static void G_UpdateVisited(void)
if ((earnedEmblems = M_CompletionEmblems()))
CONS_Printf(M_GetText("\x82" "Earned %hu emblem%s for level completion.\n"), (UINT16)earnedEmblems, earnedEmblems > 1 ? "s" : "");
M_UpdateUnlockablesAndExtraEmblems(true);
M_UpdateUnlockablesAndExtraEmblems(true, true);
G_SaveGameData(true);
}
@ -3930,7 +3930,7 @@ static void G_GetNextMap(void)
if (gamedata->everseenspecial == false)
{
gamedata->everseenspecial = true;
M_UpdateUnlockablesAndExtraEmblems(true);
M_UpdateUnlockablesAndExtraEmblems(true, true);
G_SaveGameData(true);
}
}
@ -4158,7 +4158,7 @@ static void G_DoCompleted(void)
gamedata->pendingkeyrounds++;
// Done before forced addition of PF_NOCONTEST to make UCRP_NOCONTEST harder to achieve
M_UpdateUnlockablesAndExtraEmblems(true);
M_UpdateUnlockablesAndExtraEmblems(true, true);
gamedata->deferredsave = true;
}
@ -4528,7 +4528,7 @@ void G_LoadGameData(void)
{
// Don't load at all.
// The following used to be in M_ClearSecrets, but that was silly.
M_UpdateUnlockablesAndExtraEmblems(false);
M_UpdateUnlockablesAndExtraEmblems(false, true);
return;
}
@ -4764,7 +4764,7 @@ void G_LoadGameData(void)
gamedata->loaded = true;
// Silent update unlockables in case they're out of sync with conditions
M_UpdateUnlockablesAndExtraEmblems(false);
M_UpdateUnlockablesAndExtraEmblems(false, true);
return;
}

View file

@ -414,7 +414,10 @@ boolean K_LandMineCollide(mobj_t *t1, mobj_t *t2)
if (t1->health > 1)
{
if (t1->target && t1->target->player)
{
t1->target->player->roundconditions.landmine_dunk = true;
t1->target->player->roundconditions.checkthisframe = true;
}
S_StartSound(t2, sfx_bsnipe);
}

View file

@ -1133,8 +1133,12 @@ static void K_UpdateOffroad(player_t *player)
if (player->offroad > offroadstrength)
player->offroad = offroadstrength;
if (player->offroad > (2*offroadstrength) / TICRATE)
if (player->roundconditions.touched_offroad == false
&& player->offroad > (2*offroadstrength) / TICRATE)
{
player->roundconditions.touched_offroad = true;
player->roundconditions.checkthisframe = true;
}
}
else
player->offroad = 0;
@ -4233,8 +4237,12 @@ void K_ApplyTripWire(player_t *player, tripwirestate_t state)
if (state == TRIPSTATE_PASSED)
{
S_StartSound(player->mo, sfx_ssa015);
if (player->hyudorotimer > 0)
if (player->roundconditions.tripwire_hyuu == false
&& player->hyudorotimer > 0)
{
player->roundconditions.tripwire_hyuu = true;
player->roundconditions.checkthisframe = true;
}
}
else if (state == TRIPSTATE_BLOCKED)
{
@ -5903,8 +5911,12 @@ void K_DoSneaker(player_t *player, INT32 type)
{
const fixed_t intendedboost = FRACUNIT/2;
if (player->floorboost != 0)
if (player->roundconditions.touched_sneakerpanel == false
&& player->floorboost != 0)
{
player->roundconditions.touched_sneakerpanel = true;
player->roundconditions.checkthisframe = true;
}
if (player->floorboost == 0 || player->floorboost == 3)
{

View file

@ -290,7 +290,7 @@ void K_FinishCeremony(void)
podiumData.ranking = true;
// Play the noise now
M_UpdateUnlockablesAndExtraEmblems(true);
M_UpdateUnlockablesAndExtraEmblems(true, true);
G_SaveGameData(true);
}

View file

@ -427,7 +427,7 @@ void K_CashInPowerLevels(void)
if (gamedataupdate)
{
M_UpdateUnlockablesAndExtraEmblems(true);
M_UpdateUnlockablesAndExtraEmblems(true, true);
G_SaveGameData(true);
}
@ -643,7 +643,7 @@ void K_PlayerForfeit(UINT8 playerNum, boolean pointLoss)
{
pr->powerlevels[powerType] = yourPower + inc;
M_UpdateUnlockablesAndExtraEmblems(true);
M_UpdateUnlockablesAndExtraEmblems(true, true);
G_SaveGameData(true);
}
}

View file

@ -1530,7 +1530,7 @@ static boolean M_CheckUnlockConditions(player_t *player)
return ret;
}
boolean M_UpdateUnlockablesAndExtraEmblems(boolean loud)
boolean M_UpdateUnlockablesAndExtraEmblems(boolean loud, boolean doall)
{
UINT16 i = 0, response = 0, newkeys = 0;
@ -1546,16 +1546,27 @@ boolean M_UpdateUnlockablesAndExtraEmblems(boolean loud)
// Done first so that emblems are ready before check
M_CheckLevelEmblems();
M_CompletionEmblems();
doall = true;
}
response = M_CheckUnlockConditions(NULL);
while ((gamedata->keyspending + gamedata->chaokeys + gamedata->usedkeys) < GDMAX_CHAOKEYS
&& ((gamedata->pendingkeyrounds + gamedata->pendingkeyroundoffset)/GDCONVERT_ROUNDSTOKEY) > gamedata->keyspending)
if (gamedata->deferredconditioncheck == true)
{
gamedata->keyspending++;
newkeys++;
response |= true;
// Handle deferred all-condition checks
gamedata->deferredconditioncheck = false;
doall = true;
}
if (doall)
{
response = M_CheckUnlockConditions(NULL);
while ((gamedata->keyspending + gamedata->chaokeys + gamedata->usedkeys) < GDMAX_CHAOKEYS
&& ((gamedata->pendingkeyrounds + gamedata->pendingkeyroundoffset)/GDCONVERT_ROUNDSTOKEY) > gamedata->keyspending)
{
gamedata->keyspending++;
newkeys++;
response |= true;
}
}
if (!demo.playback && Playing() && (gamestate == GS_LEVEL || K_PodiumRanking() == true))
@ -1566,7 +1577,10 @@ boolean M_UpdateUnlockablesAndExtraEmblems(boolean loud)
continue;
if (players[g_localplayers[i]].spectator)
continue;
if (!doall && players[g_localplayers[i]].roundconditions.checkthisframe == false)
continue;
response |= M_CheckUnlockConditions(&players[g_localplayers[i]]);
players[g_localplayers[i]].roundconditions.checkthisframe = false;
}
}

View file

@ -246,6 +246,7 @@ struct gamedata_t
// WHENEVER OR NOT WE'RE READY TO SAVE
boolean loaded;
boolean deferredsave;
boolean deferredconditioncheck;
// CONDITION SETS ACHIEVED
boolean achieved[MAXCONDITIONSETS];
@ -327,7 +328,7 @@ void M_ClearStats(void);
// Updating conditions and unlockables
boolean M_CheckCondition(condition_t *cn, player_t *player);
boolean M_UpdateUnlockablesAndExtraEmblems(boolean loud);
boolean M_UpdateUnlockablesAndExtraEmblems(boolean loud, boolean doall);
#define PENDING_CHAOKEYS (UINT16_MAX-1)
UINT16 M_GetNextAchievedUnlock(void);

View file

@ -205,7 +205,7 @@ menu_t *M_InterruptMenuWithChallenges(menu_t *desiredmenu)
{
UINT16 i, newunlock;
M_UpdateUnlockablesAndExtraEmblems(false);
M_UpdateUnlockablesAndExtraEmblems(false, true);
newunlock = M_GetNextAchievedUnlock();
@ -397,7 +397,7 @@ void M_ChallengesTick(void)
{
// Unlock animation... also tied directly to the actual unlock!
gamedata->unlocked[challengesmenu.currentunlock] = true;
M_UpdateUnlockablesAndExtraEmblems(true);
M_UpdateUnlockablesAndExtraEmblems(true, true);
// Update shown description just in case..?
challengesmenu.unlockcondition = M_BuildConditionSetString(challengesmenu.currentunlock);

View file

@ -66,7 +66,7 @@ static void M_EraseDataResponse(INT32 ch)
if (optionsmenu.erasecontext & EC_CHALLENGES)
M_ClearSecrets();
M_UpdateUnlockablesAndExtraEmblems(false);
M_UpdateUnlockablesAndExtraEmblems(false, true);
F_StartIntro();
M_ClearMenus(true);

View file

@ -552,7 +552,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
if (P_IsLocalPlayer(player) && !gamedata->collected[special->health-1])
{
gamedata->collected[special->health-1] = gotcollected = true;
if (!M_UpdateUnlockablesAndExtraEmblems(true))
if (!M_UpdateUnlockablesAndExtraEmblems(true, true))
S_StartSound(NULL, sfx_ncitem);
gamedata->deferredsave = true;
}
@ -1938,7 +1938,11 @@ static boolean P_KillPlayer(player_t *player, mobj_t *inflictor, mobj_t *source,
{
case DMG_DEATHPIT:
// Respawn kill types
player->roundconditions.fell_off = true;
if (player->roundconditions.fell_off == true)
{
player->roundconditions.fell_off = true;
player->roundconditions.checkthisframe = true;
}
K_DoIngameRespawn(player);
player->mo->health -= K_DestroyBumpers(player, 1);
return false;
@ -2062,9 +2066,11 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
case MT_SPB:
spbpop = (damagetype & DMG_TYPEMASK) == DMG_VOLTAGE;
if (spbpop && source && source->player)
if (spbpop && source && source->player
&& source->player->roundconditions.spb_neuter == false)
{
source->player->roundconditions.spb_neuter = true;
source->player->roundconditions.checkthisframe = true;
}
break;
@ -2142,10 +2148,14 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (inflictor && source && source->player)
{
if (P_IsKartFieldItem(source->type)
&& target->player->airtime > TICRATE/2
&& source->player->airtime > TICRATE/2)
if (source->player->roundconditions.hit_midair == false
&& P_IsKartFieldItem(source->type)
&& target->player->airtime > TICRATE/2
&& source->player->airtime > TICRATE/2)
{
source->player->roundconditions.hit_midair = true;
source->player->roundconditions.checkthisframe = true;
}
}
// Instant-Death

View file

@ -3426,7 +3426,19 @@ void P_MobjCheckWater(mobj_t *mobj)
return;
}
p->roundconditions.wet_player |= (mobj->eflags & (MFE_TOUCHWATER|MFE_UNDERWATER|MFE_GOOWATER));
if (!(p->roundconditions.wet_player & MFE_TOUCHWATER)
&& (mobj->eflags & MFE_TOUCHWATER))
{
p->roundconditions.wet_player |= MFE_TOUCHWATER;
p->roundconditions.checkthisframe = true;
}
if (!(p->roundconditions.wet_player & MFE_UNDERWATER)
&& (mobj->eflags & MFE_UNDERWATER))
{
p->roundconditions.wet_player |= MFE_UNDERWATER;
p->roundconditions.checkthisframe = true;
}
}
if (mobj->flags & MF_APPLYTERRAIN)

View file

@ -7965,7 +7965,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
{
mapheaderinfo[gamemap-1]->mapvisited |= MV_VISITED;
M_UpdateUnlockablesAndExtraEmblems(true);
M_UpdateUnlockablesAndExtraEmblems(true, true);
G_SaveGameData(true);
}

View file

@ -2115,6 +2115,12 @@ static void K_HandleLapIncrement(player_t *player)
}
lastLowestLap = lowestLap;
if (P_IsLocalPlayer(player))
{
player->roundconditions.checkthisframe = true;
gamedata->deferredconditioncheck = true;
}
}
else if (player->starpostnum)
{
@ -3427,12 +3433,7 @@ boolean P_ProcessSpecial(activator_t *activator, INT16 special, INT32 *args, cha
}
mo->player->roundconditions.unlocktriggers |= flag;
// Unlocked something?
if (!demo.playback && M_UpdateUnlockablesAndExtraEmblems(true))
{
gamedata->deferredsave = true; // only save if unlocked something
}
mo->player->roundconditions.checkthisframe = true;
}
}
break;

View file

@ -618,7 +618,7 @@ void P_Ticker(boolean run)
ps_playerthink_time = I_GetPreciseTime() - ps_playerthink_time;
// TODO would this be laggy with more conditions in play...
if (((!demo.playback && leveltime > introtime && M_UpdateUnlockablesAndExtraEmblems(true))
if (((!demo.playback && leveltime > introtime && M_UpdateUnlockablesAndExtraEmblems(true, false))
|| (gamedata && gamedata->deferredsave)))
G_SaveGameData(true);
}

View file

@ -521,9 +521,10 @@ INT32 P_GivePlayerRings(player_t *player, INT32 num_rings)
player->rings += num_rings;
if (player->rings < 0)
if (player->roundconditions.debt_rings == false && player->rings < 0)
{
player->roundconditions.debt_rings = true;
player->roundconditions.checkthisframe = true;
}
return num_rings;
@ -1281,7 +1282,11 @@ void P_DoPlayerExit(player_t *player)
return;
if (P_IsLocalPlayer(player) && (!player->spectator && !demo.playback))
{
legitimateexit = true;
player->roundconditions.checkthisframe = true;
gamedata->deferredconditioncheck = true;
}
if (G_GametypeUsesLives() && losing)
{
@ -3819,6 +3824,8 @@ void P_DoTimeOver(player_t *player)
if (P_IsLocalPlayer(player) && !demo.playback)
{
legitimateexit = true; // SRB2kart: losing a race is still seeing it through to the end :p
player->roundconditions.checkthisframe = true;
gamedata->deferredconditioncheck = true;
}
if (netgame && !player->bot && !(gametyperules & GTR_BOSS))

View file

@ -818,7 +818,7 @@ UINT16 W_InitFile(const char *filename, boolean mainfile, boolean startup)
if ((mainfile == false) && (gamedata != NULL) && (gamedata->everloadedaddon == false))
{
gamedata->everloadedaddon = true;
M_UpdateUnlockablesAndExtraEmblems(true);
M_UpdateUnlockablesAndExtraEmblems(true, true);
G_SaveGameData(true);
}