From b937b1a7bc4ecf1c16173cfd1630346b8a503fdb Mon Sep 17 00:00:00 2001 From: toaster Date: Thu, 5 Oct 2023 14:36:00 +0100 Subject: [PATCH] Add UCRP_MAKERETIRE - `Condition1 = MakeRetire Eggrobo` - Fires when: - Not a cooperative context - You've finished in good standing - Another player has both - PF_NOCONTEST - The skin specified in the condition Also makes rivalname-handling for K_InitGrandPrixBots `const char *`, since the author of this commit had to reference that code. --- src/deh_soc.c | 7 ++++++ src/k_grandprix.c | 2 +- src/m_cond.c | 63 +++++++++++++++++++++++++++++++++++++++++++++++ src/m_cond.h | 2 ++ 4 files changed, 73 insertions(+), 1 deletion(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index 76488462e..b80c6d16c 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -2777,6 +2777,13 @@ static void readcondition(UINT16 set, UINT32 id, char *word2) //PARAMCHECK(1); ty = UCRP_FINISHCOOL + offset; } + else if (fastcmp(params[0], "MAKERETIRE")) + { + PARAMCHECK(1); + ty = UCRP_MAKERETIRE; + stringvar = Z_StrDup(params[1]); + re = -1; + } else if ((offset=0) || fastcmp(params[0], "FINISHPLACE") || (++offset && fastcmp(params[0], "FINISHPLACEEXACT"))) { diff --git a/src/k_grandprix.c b/src/k_grandprix.c index f43c82656..f6520ef7a 100644 --- a/src/k_grandprix.c +++ b/src/k_grandprix.c @@ -217,7 +217,7 @@ void K_InitGrandPrixBots(void) for (j = 0; j < numplayers; j++) { player_t *p = &players[competitors[j]]; - char *rivalname = skins[p->skin].rivals[i]; + const char *rivalname = skins[p->skin].rivals[i]; INT32 rivalnum = R_SkinAvailable(rivalname); // Intentionally referenced before (currently dummied out) unlock check. Such a tease! diff --git a/src/m_cond.c b/src/m_cond.c index b0fb857b4..f4de68b5b 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -864,6 +864,7 @@ void M_UpdateConditionSetsPending(void) { case UC_CHARACTERWINS: case UCRP_ISCHARACTER: + case UCRP_MAKERETIRE: { cn->requirement = R_SkinAvailable(cn->stringvar); @@ -1153,6 +1154,58 @@ boolean M_CheckCondition(condition_t *cn, player_t *player) && numtargets >= maptargets); case UCRP_NOCONTEST: return (player->pflags & PF_NOCONTEST); + + case UCRP_MAKERETIRE: + { + // You can't "make" someone retire in coop. + if (K_Cooperative() == true) + { + return false; + } + + // The following is basically UCRP_FINISHCOOL, + // but without the M_NotFreePlay check since this + // condition is already dependent on other players. + if ((player->exiting + && !(player->pflags & PF_NOCONTEST) + && !K_IsPlayerLosing(player)) == false) + { + return false; + } + + UINT8 i; + for (i = 0; i < MAXPLAYERS; i++) + { + if (playeringame[i] == false) + { + continue; + } + + // This player is ME! + if (player == players+i) + { + continue; + } + + // This player didn't NO CONTEST. + if (!(players[i].pflags & PF_NOCONTEST)) + { + continue; + } + + // This player doesn't have the right skin. + if (players[i].skin != cn->requirement) + { + continue; + } + + // Okay, the right player is dead! + break; + } + + return (i != MAXPLAYERS); + } + case UCRP_FINISHPLACE: return (player->exiting && !(player->pflags & PF_NOCONTEST) @@ -1748,6 +1801,16 @@ static const char *M_GetConditionString(condition_t *cn) return "break every prison"; case UCRP_NOCONTEST: return "NO CONTEST"; + + case UCRP_MAKERETIRE: + { + if (cn->requirement < 0 || !skins[cn->requirement].realname[0]) + return va("INVALID CHAR CONDITION \"%d:%d\"", cn->type, cn->requirement); + + work = M_GetConditionCharacter(cn->requirement, false); + return va("make %s retire", work); + } + case UCRP_FINISHPLACE: case UCRP_FINISHPLACEEXACT: return va("finish in %d%s%s", cn->requirement, M_GetNthType(cn->requirement), diff --git a/src/m_cond.h b/src/m_cond.h index 164658427..e8670888f 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -89,6 +89,8 @@ typedef enum UCRP_FINISHALLPRISONS, // Break all prisons UCRP_NOCONTEST, // No Contest + UCRP_MAKERETIRE, // Make another player of [skin] No Contest + UCRP_FINISHPLACE, // Finish at least [place] UCRP_FINISHPLACEEXACT, // Finish at [place] exactly