From 303d636f8e31358f63bb9b31ffef290fb74144b5 Mon Sep 17 00:00:00 2001 From: Sally Coolatta Date: Mon, 28 Feb 2022 10:58:18 -0500 Subject: [PATCH] Individual emblems mode --- src/deh_soc.c | 4 ++ src/doomstat.h | 3 ++ src/g_game.c | 1 + src/p_inter.c | 100 ++++++++++++++++++++++++++++++++++++++++++------- src/p_local.h | 2 + src/p_mobj.c | 48 ++++++------------------ src/p_setup.c | 2 +- src/st_stuff.c | 3 +- 8 files changed, 110 insertions(+), 53 deletions(-) diff --git a/src/deh_soc.c b/src/deh_soc.c index 81adbc9d2..f2f3e04b8 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -3839,6 +3839,10 @@ void readmaincfg(MYFILE *f) { useContinues = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y'); } + else if (fastcmp(word, "SHAREEMBLEMS")) + { + shareEmblems = (UINT8)(value || word2[0] == 'T' || word2[0] == 'Y'); + } else if (fastcmp(word, "GAMEDATA")) { diff --git a/src/doomstat.h b/src/doomstat.h index 5875bd01f..a812cc304 100644 --- a/src/doomstat.h +++ b/src/doomstat.h @@ -543,9 +543,12 @@ extern UINT8 useBlackRock; extern UINT8 use1upSound; extern UINT8 maxXtraLife; // Max extra lives from rings + extern UINT8 useContinues; #define continuesInSession (!multiplayer && (ultimatemode || (useContinues && !marathonmode) || (!modeattacking && !(cursaveslot > 0)))) +extern UINT8 shareEmblems; + extern mobj_t *hunt1, *hunt2, *hunt3; // Emerald hunt locations // For racing diff --git a/src/g_game.c b/src/g_game.c index 854bf9bbb..066b43cad 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -215,6 +215,7 @@ UINT8 ammoremovaltics = 2*TICRATE; UINT8 use1upSound = 0; UINT8 maxXtraLife = 2; // Max extra lives from rings UINT8 useContinues = 0; // Set to 1 to enable continues outside of no-save scenarioes +UINT8 shareEmblems = 0; // Set to 1 to share all picked up emblems in multiplayer UINT8 introtoplay; UINT8 creditscutscene; diff --git a/src/p_inter.c b/src/p_inter.c index f2d20912f..02ae222e3 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -164,6 +164,62 @@ boolean P_CanPickupItem(player_t *player, boolean weapon) return true; } +boolean P_CanPickupEmblem(player_t *player, INT32 emblemID) +{ + emblem_t *emblem = NULL; + + if (emblemID < 0 || emblemID >= numemblems) + { + // Invalid emblem ID, can't pickup. + return false; + } + + emblem = &emblemlocations[emblemID]; + + if (demoplayback) + { + // Never collect emblems in replays. + return false; + } + + if (player->bot && player->bot != BOT_MPAI) + { + // Your little lap-dog can't grab these for you. + return false; + } + + if (emblem->type == ET_SKIN) + { + INT32 skinnum = M_EmblemSkinNum(emblem); + + if (player->skin != skinnum) + { + // Incorrect skin to pick up this emblem. + return false; + } + } + + return true; +} + +boolean P_EmblemWasCollected(INT32 emblemID) +{ + if (emblemID < 0 || emblemID >= numemblems) + { + // Invalid emblem ID, can't pickup. + return true; + } + + if (shareEmblems && !serverGamedata->collected[emblemID]) + { + // It can be worth collecting again if we're sharing emblems + // and the server doesn't have it. + return false; + } + + return clientGamedata->collected[emblemID]; +} + // // P_DoNightsScore // @@ -738,25 +794,41 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) // Secret emblem thingy case MT_EMBLEM: { - if (demoplayback || (player->bot && player->bot != BOT_MPAI) || special->health <= 0 || special->health > MAXEMBLEMS) - return; + mobj_t *spark = NULL; + boolean prevCollected; - if (emblemlocations[special->health-1].type == ET_SKIN) + if (!P_CanPickupEmblem(player, special->health - 1)) { - INT32 skinnum = M_EmblemSkinNum(&emblemlocations[special->health-1]); - - if (player->skin != skinnum) - { - return; - } + return; } - clientGamedata->collected[special->health-1] = serverGamedata->collected[special->health-1] = true; + prevCollected = P_EmblemWasCollected(special->health - 1); - M_SilentUpdateUnlockablesAndEmblems(serverGamedata); - M_UpdateUnlockablesAndExtraEmblems(clientGamedata); - G_SaveGameData(clientGamedata); - break; + if (((player - players) == serverplayer) || shareEmblems) + { + serverGamedata->collected[special->health-1] = true; + M_SilentUpdateUnlockablesAndEmblems(serverGamedata); + } + + if (P_IsLocalPlayer(player) || shareEmblems) + { + clientGamedata->collected[special->health-1] = true; + M_UpdateUnlockablesAndExtraEmblems(clientGamedata); + G_SaveGameData(clientGamedata); + } + + // This always spawns the object to prevent mobjnum issues, + // but makes the effect invisible to whoever it doesn't matter to. + spark = P_SpawnMobjFromMobj(special, 0, 0, 0, MT_SPARK); + if (prevCollected == false && P_EmblemWasCollected(special->health - 1) == true) + { + S_StartSound(special, special->info->deathsound); + } + else + { + spark->flags2 |= MF2_DONTDRAW; + } + return; } // CTF Flags diff --git a/src/p_local.h b/src/p_local.h index cc060e4ee..3c84d6fe2 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -510,6 +510,8 @@ void P_ClearStarPost(INT32 postnum); void P_ResetStarposts(void); boolean P_CanPickupItem(player_t *player, boolean weapon); +boolean P_CanPickupEmblem(player_t *player, INT32 emblemID); +boolean P_EmblemWasCollected(INT32 emblemID); void P_DoNightsScore(player_t *player); void P_DoMatchSuper(player_t *player); diff --git a/src/p_mobj.c b/src/p_mobj.c index 6563e6f0a..f198a1a69 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9716,6 +9716,11 @@ static boolean P_MobjRegularThink(mobj_t *mobj) A_AttractChase(mobj); break; case MT_EMBLEM: + if (P_EmblemWasCollected(mobj->health - 1) || !P_CanPickupEmblem(&players[consoleplayer], mobj->health - 1)) + mobj->frame |= (tr_trans50 << FF_TRANSSHIFT); + else + mobj->frame &= ~FF_TRANSMASK; + if (mobj->flags2 & MF2_NIGHTSPULL) P_NightsItemChase(mobj); break; @@ -12146,7 +12151,6 @@ static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj) INT32 j; emblem_t* emblem = M_GetLevelEmblems(gamemap); skincolornum_t emcolor; - boolean validEmblem = true; while (emblem) { @@ -12171,47 +12175,19 @@ static boolean P_SetupEmblem(mapthing_t *mthing, mobj_t *mobj) emcolor = M_GetEmblemColor(&emblemlocations[j]); // workaround for compiler complaint about bad function casting mobj->color = (UINT16)emcolor; - validEmblem = true; + mobj->frame &= ~FF_TRANSMASK; - if (!netgame) + if (emblemlocations[j].type == ET_GLOBAL) { - validEmblem = !serverGamedata->collected[j]; - - if (emblemlocations[j].type == ET_SKIN && !multiplayer) + mobj->reactiontime = emblemlocations[j].var; + if (emblemlocations[j].var & GE_NIGHTSITEM) { - INT32 skinnum = M_EmblemSkinNum(&emblemlocations[j]); - - if (players[0].skin != skinnum) - { - validEmblem = false; - } + mobj->flags |= MF_NIGHTSITEM; + mobj->flags &= ~MF_SPECIAL; + mobj->flags2 |= MF2_DONTDRAW; } } - if (validEmblem == false) - { - P_UnsetThingPosition(mobj); - mobj->flags |= MF_NOCLIP; - mobj->flags &= ~MF_SPECIAL; - mobj->flags |= MF_NOBLOCKMAP; - mobj->frame |= (tr_trans50 << FF_TRANSSHIFT); - P_SetThingPosition(mobj); - } - else - { - mobj->frame &= ~FF_TRANSMASK; - - if (emblemlocations[j].type == ET_GLOBAL) - { - mobj->reactiontime = emblemlocations[j].var; - if (emblemlocations[j].var & GE_NIGHTSITEM) - { - mobj->flags |= MF_NIGHTSITEM; - mobj->flags &= ~MF_SPECIAL; - mobj->flags2 |= MF2_DONTDRAW; - } - } - } return true; } diff --git a/src/p_setup.c b/src/p_setup.c index 70a2c0a8b..74645e877 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -876,7 +876,7 @@ static void P_SpawnMapThings(boolean spawnemblems) size_t i; mapthing_t *mt; - // Spawn axis points first so they are at the front of the list for fast searching. + // Spawn axis points first so they are at the front of the list for fast searching. for (i = 0, mt = mapthings; i < nummapthings; i++, mt++) { switch (mt->type) diff --git a/src/st_stuff.c b/src/st_stuff.c index 1f0ca277f..986b71219 100644 --- a/src/st_stuff.c +++ b/src/st_stuff.c @@ -2563,9 +2563,8 @@ static void ST_doItemFinderIconsAndSound(void) emblems[stemblems++] = i; - if (!(clientGamedata->collected[i] && serverGamedata->collected[i])) + if (!P_EmblemWasCollected(i)) { - // It can be worth collecting again if the server doesn't have it. ++stunfound; }