diff --git a/src/d_player.h b/src/d_player.h index a96102ecd..0bc1d43bc 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -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; diff --git a/src/f_finale.c b/src/f_finale.c index 6e936c9d4..0a802459d 100644 --- a/src/f_finale.c +++ b/src/f_finale.c @@ -1083,7 +1083,7 @@ void F_GameEvaluationTicker(void) { ++gamedata->timesBeaten; - M_UpdateUnlockablesAndExtraEmblems(true); + M_UpdateUnlockablesAndExtraEmblems(true, true); G_SaveGameData(true); } else diff --git a/src/g_demo.c b/src/g_demo.c index f9b088ea4..4c9a80d94 100644 --- a/src/g_demo.c +++ b/src/g_demo.c @@ -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); } } diff --git a/src/g_game.c b/src/g_game.c index 066f96909..67a971614 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -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; } diff --git a/src/k_collide.c b/src/k_collide.c index 43e2c04ed..0116f0d49 100644 --- a/src/k_collide.c +++ b/src/k_collide.c @@ -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); } diff --git a/src/k_kart.c b/src/k_kart.c index deb1227ab..c32a67091 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -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) { diff --git a/src/k_podium.c b/src/k_podium.c index 807b7f5a4..1bb5d9968 100644 --- a/src/k_podium.c +++ b/src/k_podium.c @@ -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); } diff --git a/src/k_pwrlv.c b/src/k_pwrlv.c index 3bc2466d6..f4b307cfd 100644 --- a/src/k_pwrlv.c +++ b/src/k_pwrlv.c @@ -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); } } diff --git a/src/m_cond.c b/src/m_cond.c index 26e43d797..eb5fbc537 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -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; } } diff --git a/src/m_cond.h b/src/m_cond.h index f908cb1d0..d3b2b73dc 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -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); diff --git a/src/menus/extras-challenges.c b/src/menus/extras-challenges.c index 30229499d..5289d3972 100644 --- a/src/menus/extras-challenges.c +++ b/src/menus/extras-challenges.c @@ -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); diff --git a/src/menus/options-data-erase-1.c b/src/menus/options-data-erase-1.c index 15c727b05..3a40ed70f 100644 --- a/src/menus/options-data-erase-1.c +++ b/src/menus/options-data-erase-1.c @@ -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); diff --git a/src/p_inter.c b/src/p_inter.c index 05579b61c..f4f612101 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -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 diff --git a/src/p_mobj.c b/src/p_mobj.c index a0f7b268b..a456234e4 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -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) diff --git a/src/p_setup.c b/src/p_setup.c index 64b217225..bf3a0f358 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -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); } diff --git a/src/p_spec.c b/src/p_spec.c index 2ebda0d68..e9ad66d67 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -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; diff --git a/src/p_tick.c b/src/p_tick.c index f45eecf4a..1a5ae508c 100644 --- a/src/p_tick.c +++ b/src/p_tick.c @@ -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); } diff --git a/src/p_user.c b/src/p_user.c index f957eabf9..29ffbd94a 100644 --- a/src/p_user.c +++ b/src/p_user.c @@ -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)) diff --git a/src/w_wad.c b/src/w_wad.c index e0c19e7e5..481ef672e 100644 --- a/src/w_wad.c +++ b/src/w_wad.c @@ -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); }