diff --git a/src/deh_soc.c b/src/deh_soc.c index d8adff53e..27442f28f 100644 --- a/src/deh_soc.c +++ b/src/deh_soc.c @@ -2643,6 +2643,22 @@ static void readcondition(UINT16 set, UINT32 id, char *word2) // Force at head of the list? x1 = (params[2] && (params[2][0] == 'Y' || params[2][0] == 'T')) ? 1 : 0; } + else if (fastcmp(params[0], "PRISONEGGCD")) + { + ty = UC_PRISONEGGCD; + re = NEXTMAP_INVALID; + + if (params[1]) + { + re = G_MapNumber(params[1]); + + if (re >= nummapheaders) + { + deh_warning("Invalid level %s for condition ID %d", params[1], id+1); + return; + } + } + } else if ((offset=0) || fastcmp(params[0], "AND") || (++offset && fastcmp(params[0], "COMMA"))) { diff --git a/src/deh_tables.c b/src/deh_tables.c index fcb3b090b..970d73958 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -1218,10 +1218,8 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_EMERALDFLARE1", - // Emerald hunt shards - "S_SHRD1", - "S_SHRD2", - "S_SHRD3", + // Prison Egg Drops + "S_PRISONEGGDROP_CD", // Bubble Source "S_BUBBLES1", @@ -4841,8 +4839,7 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t "MT_EMERALD", "MT_EMERALDSPARK", "MT_EMERALDFLARE", - "MT_EMERHUNT", // Emerald Hunt - "MT_EMERALDSPAWN", // Emerald spawner w/ delay + "MT_PRISONEGGDROP", // Springs and others "MT_FAN", diff --git a/src/g_game.c b/src/g_game.c index ce2f31a00..fb320fc83 100644 --- a/src/g_game.c +++ b/src/g_game.c @@ -4425,7 +4425,7 @@ void G_LoadGameSettings(void) } #define GD_VERSIONCHECK 0xBA5ED123 // Change every major version, as usual -#define GD_VERSIONMINOR 7 // Change every format update +#define GD_VERSIONMINOR 8 // Change every format update // You can't rearrange these without a special format update typedef enum @@ -4583,6 +4583,13 @@ void G_LoadGameData(void) save.p += 4; // no direct equivalent to matchesplayed } + // Prison Egg Pickups + if (versionMinor >= 8) + { + gamedata->thisprisoneggpickup = READUINT16(save.p); + gamedata->prisoneggstothispickup = READUINT16(save.p); + } + { // Quick & dirty hash for what mod this save file is for. UINT32 modID = READUINT32(save.p); @@ -5090,6 +5097,7 @@ void G_SaveGameData(void) (4*GDGT_MAX)+ 4+1+2+2+ 4+ + 2+2+ 4+ (MAXEMBLEMS+(MAXUNLOCKABLES*2)+MAXCONDITIONSETS)+ 4+2); @@ -5256,6 +5264,10 @@ void G_SaveGameData(void) WRITEUINT32(save.p, everflags); // 4 } + // Prison Egg Pickups + WRITEUINT16(save.p, gamedata->thisprisoneggpickup); // 2 + WRITEUINT16(save.p, gamedata->prisoneggstothispickup); // 2 + WRITEUINT32(save.p, quickncasehash(timeattackfolder, 64)); // 4 // To save space, use one bit per collected/achieved/unlocked flag diff --git a/src/info.c b/src/info.c index 82ea4fbf4..1a8b0d47d 100644 --- a/src/info.c +++ b/src/info.c @@ -148,7 +148,9 @@ char sprnames[NUMSPRITES + 1][5] = "EMRC", // Chaos Emeralds "SEMR", // Super Emeralds "ESPK", - "SHRD", // Emerald Hunt + + // Prison Egg Drops + "ALTM", // Interactive Objects "BBLS", // water bubble source @@ -1920,10 +1922,8 @@ state_t states[NUMSTATES] = {SPR_LENS, FF_FULLBRIGHT|FF_ADD|FF_TRANS10|FF_ANIMATE|11, 8, {NULL}, 7, 1, S_GAINAX_MID2}, // S_EMERALDFLARE1 - // Emerald hunt shards - {SPR_SHRD, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SHRD1 - {SPR_SHRD, 1, -1, {NULL}, 0, 0, S_NULL}, // S_SHRD2 - {SPR_SHRD, 2, -1, {NULL}, 0, 0, S_NULL}, // S_SHRD3 + // Prison Egg Drops + {SPR_ALTM, 0|FF_PAPERSPRITE, -1, {NULL}, 0, 0, S_NULL}, // S_PRISONEGGDROP_CD // Bubble Source {SPR_BBLS, 0, 8, {A_BubbleSpawn}, 2048, 0, S_BUBBLES2}, // S_BUBBLES1 @@ -8482,9 +8482,9 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, - { // MT_EMERHUNT - 320, // doomednum - S_SHRD1, // spawnstate + { // MT_PRISONEGGDROP + -1, // doomednum + S_INVISIBLE, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -8495,44 +8495,17 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_SPRK1, // deathstate - S_NULL, // xdeathstate - sfx_cgot, // deathsound - 8, // speed - 12*FRACUNIT, // radius - 42*FRACUNIT, // height - 0, // display offset - 4, // mass - 0, // damage - sfx_None, // activesound - MF_SPECIAL|MF_NOGRAVITY, // flags - S_NULL // raisestate - }, - - { // MT_EMERALDSPAWN - 321, // doomednum - S_INVISIBLE, // spawnstate - 1000, // spawnhealth - S_NULL, // seestate - sfx_None, // seesound - 0, // reactiontime - sfx_None, // attacksound - S_NULL, // painstate - 0, // painchance - sfx_None, // painsound - S_NULL, // meleestate - S_NULL, // missilestate S_NULL, // deathstate S_NULL, // xdeathstate - sfx_None, // deathsound + sfx_s3k9c, // deathsound 0, // speed - 8, // radius - 8, // height + 65*FRACUNIT, // radius + 130*FRACUNIT, // height 0, // display offset - 10, // mass + 16, // mass 0, // damage sfx_None, // activesound - MF_NOBLOCKMAP|MF_NOGRAVITY|MF_NOSECTOR, // flags + MF_SPECIAL|MF_PICKUPFROMBELOW|MF_DONTENCOREMAP, // flags S_NULL // raisestate }, diff --git a/src/info.h b/src/info.h index 1308a9c15..f9a221151 100644 --- a/src/info.h +++ b/src/info.h @@ -703,7 +703,9 @@ typedef enum sprite SPR_EMRC, // Chaos Emeralds SPR_SEMR, // Super Emeralds SPR_ESPK, - SPR_SHRD, // Emerald Hunt + + // Prison Egg Drops + SPR_ALTM, // Interactive Objects SPR_BBLS, // water bubble source @@ -2400,10 +2402,8 @@ typedef enum state S_EMERALDFLARE1, - // Emerald hunt shards - S_SHRD1, - S_SHRD2, - S_SHRD3, + // Prison Egg Drops + S_PRISONEGGDROP_CD, // Bubble Source S_BUBBLES1, @@ -6062,8 +6062,7 @@ typedef enum mobj_type MT_EMERALD, MT_EMERALDSPARK, MT_EMERALDFLARE, - MT_EMERHUNT, // Emerald Hunt - MT_EMERALDSPAWN, // Emerald spawner w/ delay + MT_PRISONEGGDROP, // Springs and others MT_FAN, diff --git a/src/k_kart.c b/src/k_kart.c index 104c93318..be368aa19 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -267,6 +267,22 @@ void K_TimerInit(void) { K_SpawnDuelOnlyItems(); } + + if ( + battleprisons == true + && grandprixinfo.gp == true + && netgame == false + && gamedata->thisprisoneggpickup_cached != NULL + && gamedata->prisoneggstothispickup == 0 + && maptargets > 1 + ) + { + // This calculation is like this so... + // - You can't get a Prison Egg Drop on the last broken target + // - If it were 0 at minimum there'd be a slight bias towards the start of the round + // - This is bad because it benefits CD farming like in Brawl :D + gamedata->prisoneggstothispickup = 1 + M_RandomKey(maptargets - 1); + } } UINT32 K_GetPlayerDontDrawFlag(player_t *player) diff --git a/src/m_cond.c b/src/m_cond.c index c203f923a..6472f7bb6 100644 --- a/src/m_cond.c +++ b/src/m_cond.c @@ -679,6 +679,14 @@ void M_ClearSecrets(void) gamedata->numspraycans = 0; gamedata->gotspraycans = 0; + Z_Free(gamedata->prisoneggpickups); + gamedata->prisoneggpickups = NULL; + gamedata->numprisoneggpickups = 0; + gamedata->gettableprisoneggpickups = 0; + gamedata->thisprisoneggpickup = MAXCONDITIONSETS; + gamedata->thisprisoneggpickup_cached = NULL; + gamedata->thisprisoneggpickupgrabbed = false; + UINT16 i, j; for (i = 0; i < nummapheaders; i++) { @@ -713,7 +721,9 @@ void M_ClearSecrets(void) gamedata->pendingkeyrounds = 0; gamedata->pendingkeyroundoffset = 0; gamedata->keyspending = 0; - gamedata->chaokeys = 3; // Start with 3 !! + + gamedata->chaokeys = GDINIT_CHAOKEYS; + gamedata->prisoneggstothispickup = GDINIT_PRISONSTOPRIZE; } // For lack of a better idea on where to put this @@ -835,6 +845,171 @@ static void M_AssignSpraycans(void) } } +static void M_InitPrisonEggPickups(void) +{ + // Init ordered list of skincolors + UINT16 temppickups[MAXCONDITIONSETS]; + UINT16 listlen = 0; + + UINT32 i, j; + conditionset_t *c; + condition_t *cn; + + for (i = 0; i < MAXCONDITIONSETS; ++i) + { + // Optimisation - unlike Spray Cans, these are rebuilt every game launch/savedata wipe. + // Therefore, we don't need to re-store the ones that have been achieved. + if (gamedata->achieved[i]) + continue; + + c = &conditionSets[i]; + if (!c->numconditions) + continue; + + for (j = 0; j < c->numconditions; ++j) + { + cn = &c->condition[j]; + if (cn->type != UC_PRISONEGGCD) + continue; + + temppickups[listlen] = i; + listlen++; + break; + } + } + + if (!listlen) + { + return; + } + + // This list doesn't need to be shuffled because it's always being randomly grabbed. + // (Unlike Spray Cans, you don't know which CD you miss out on.) + + gamedata->prisoneggpickups = Z_Realloc( + gamedata->prisoneggpickups, + sizeof(UINT16) * listlen, + PU_STATIC, + NULL); + + while (gamedata->numprisoneggpickups < listlen) + { + gamedata->prisoneggpickups[gamedata->numprisoneggpickups] + = temppickups[gamedata->numprisoneggpickups]; + gamedata->numprisoneggpickups++; + } + + M_UpdateNextPrisonEggPickup(); +} + +void M_UpdateNextPrisonEggPickup(void) +{ + UINT16 i = gamedata->gettableprisoneggpickups, j, swap; + + conditionset_t *c; + condition_t *cn; + + boolean firstrun = true; + +cacheprisoneggpickup: + + // Check if the current roll is fine + gamedata->thisprisoneggpickup_cached = NULL; + if (gamedata->thisprisoneggpickup < MAXCONDITIONSETS) + { + //CONS_Printf("CACHE TEST: thisprisoneggpickup is set to %u\n", gamedata->thisprisoneggpickup); + if (gamedata->achieved[gamedata->thisprisoneggpickup] == false) + { + c = &conditionSets[gamedata->thisprisoneggpickup]; + if (c->numconditions) + { + for (j = 0; j < c->numconditions; ++j) + { + cn = &c->condition[j]; + if (cn->type != UC_PRISONEGGCD) + continue; + + if (cn->requirement < nummapheaders && M_MapLocked(cn->requirement+1)) + continue; + + // Good! Attach the cache. + gamedata->thisprisoneggpickup_cached = cn; + //CONS_Printf(" successfully set to cn!\n"); + break; + } + } + } + + if (gamedata->thisprisoneggpickup_cached == NULL) + { + gamedata->thisprisoneggpickup = MAXCONDITIONSETS; + gamedata->thisprisoneggpickupgrabbed = false; + } + } + + if (firstrun && gamedata->numprisoneggpickups && gamedata->thisprisoneggpickup == MAXCONDITIONSETS) + { + for (; i < gamedata->numprisoneggpickups; i++) + { + if (gamedata->achieved[gamedata->prisoneggpickups[i]] == false) + { + c = &conditionSets[gamedata->prisoneggpickups[i]]; + if (c->numconditions) + { + for (j = 0; j < c->numconditions; ++j) + { + cn = &c->condition[j]; + if (cn->type != UC_PRISONEGGCD) + continue; + + // Locked associated map? Keep in the rear end dimension! + if (cn->requirement < nummapheaders && M_MapLocked(cn->requirement+1)) + break; // not continue intentionally + + // Okay, this should be available. + // Bring to the front! + swap = gamedata->prisoneggpickups[gamedata->gettableprisoneggpickups]; + gamedata->prisoneggpickups[gamedata->gettableprisoneggpickups] = + gamedata->prisoneggpickups[i]; + gamedata->prisoneggpickups[i] = swap; + + gamedata->gettableprisoneggpickups++; + + break; + } + + if (j < c->numconditions) + continue; + } + } + + // Fell all the way through? + // Push this all the way to the back, and lop it off! + + swap = gamedata->prisoneggpickups[gamedata->numprisoneggpickups]; + gamedata->prisoneggpickups[gamedata->numprisoneggpickups] = + gamedata->prisoneggpickups[i]; + gamedata->prisoneggpickups[i] = swap; + + gamedata->numprisoneggpickups--; + i--; // We run the loop again for this entry + } + + if (gamedata->gettableprisoneggpickups) + { + gamedata->thisprisoneggpickup = + gamedata->prisoneggpickups[ + M_RandomKey(gamedata->gettableprisoneggpickups) + ]; + + firstrun = false; + goto cacheprisoneggpickup; + } + } + + //CONS_Printf("thisprisoneggpickup = %u (MAXCONDITIONSETS is %u)\n", gamedata->thisprisoneggpickup, MAXCONDITIONSETS); +} + static void M_PrecacheLevelLocks(void) { UINT16 i, j; @@ -908,6 +1083,9 @@ void M_FinaliseGameData(void) // Place the spraycans, which CAN'T be done lazily. M_AssignSpraycans(); + // You could probably do the Prison Egg Pickups lazily, but it'd be a lagspike mid-combat. + M_InitPrisonEggPickups(); + // Don't consider loaded until it's a success! // It used to do this much earlier, but this would cause the gamedata // to save over itself when it I_Errors from corruption, which can @@ -1160,6 +1338,7 @@ boolean M_CheckCondition(condition_t *cn, player_t *player) return false; case UC_PASSWORD: return (cn->stringvar == NULL); + case UC_SPRAYCAN: { if (cn->requirement <= 0 @@ -1174,6 +1353,9 @@ boolean M_CheckCondition(condition_t *cn, player_t *player) return (gamedata->spraycans[can_id].map < nummapheaders); } + case UC_PRISONEGGCD: + return ((gamedata->thisprisoneggpickupgrabbed == true) && (cn == gamedata->thisprisoneggpickup_cached)); + // Just for string building case UC_AND: case UC_COMMA: @@ -1748,6 +1930,7 @@ static const char *M_GetConditionString(condition_t *cn) return NULL; case UC_PASSWORD: return "enter a secret password"; + case UC_SPRAYCAN: { if (cn->requirement <= 0 @@ -1771,6 +1954,10 @@ static const char *M_GetConditionString(condition_t *cn) return va("grab %d Spray Cans", can_id + 1); } + case UC_PRISONEGGCD: + // :butterfly: "alternatively you could say 'grab a hot toooon' or 'smooth beeat'" + return "BONUS ROUND: grab a prize from a Prison Egg"; + case UC_AND: return "&"; case UC_COMMA: @@ -2161,6 +2348,8 @@ boolean M_UpdateUnlockablesAndExtraEmblems(boolean loud, boolean doall) { response = M_CheckUnlockConditions(NULL); + M_UpdateNextPrisonEggPickup(); + if (gamedata->pendingkeyrounds == 0 || (gamedata->chaokeys >= GDMAX_CHAOKEYS)) { diff --git a/src/m_cond.h b/src/m_cond.h index 4d5fce77b..fedb6cd58 100644 --- a/src/m_cond.h +++ b/src/m_cond.h @@ -63,6 +63,8 @@ typedef enum UC_SPRAYCAN, // Grab a spraycan + UC_PRISONEGGCD, // Grab a CD from a Prison Egg + // Just for string building UC_AND, UC_COMMA, @@ -246,6 +248,9 @@ typedef enum { #define GDCONVERT_ROUNDSTOKEY 32 +#define GDINIT_CHAOKEYS 3 // Start with 3 Chao Keys !! +#define GDINIT_PRISONSTOPRIZE 30 // 30 Prison Eggs to your [Wild Prize] !! + typedef enum { GDGT_RACE, GDGT_BATTLE, @@ -287,6 +292,15 @@ struct gamedata_t UINT16 gotspraycans; candata_t* spraycans; + // PRISON EGG PICKUPS + UINT16 numprisoneggpickups; + UINT16 gettableprisoneggpickups; + UINT16 thisprisoneggpickup; + condition_t *thisprisoneggpickup_cached; + boolean thisprisoneggpickupgrabbed; + UINT16 prisoneggstothispickup; + UINT16* prisoneggpickups; + // CHALLENGE GRID UINT16 challengegridwidth; UINT16 *challengegrid; @@ -375,6 +389,8 @@ boolean M_UpdateUnlockablesAndExtraEmblems(boolean loud, boolean doall); #define PENDING_CHAOKEYS (UINT16_MAX-1) UINT16 M_GetNextAchievedUnlock(boolean canskipchaokeys); +void M_UpdateNextPrisonEggPickup(void); + UINT16 M_CheckLevelEmblems(void); UINT16 M_CompletionEmblems(void); diff --git a/src/p_floor.c b/src/p_floor.c index 2d25e8208..4b96192c8 100644 --- a/src/p_floor.c +++ b/src/p_floor.c @@ -980,7 +980,6 @@ static mobj_t *SearchMarioNode(msecnode_t *node) case MT_THOK: case MT_GHOST: case MT_OVERLAY: - case MT_EMERALDSPAWN: case MT_ELEMENTAL_ORB: case MT_ATTRACT_ORB: case MT_FORCE_ORB: diff --git a/src/p_inter.c b/src/p_inter.c index 718959b1a..a94daafab 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -800,6 +800,49 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) return; } + case MT_PRISONEGGDROP: + { + if (demo.playback) + { + // Never collect emblems in replays. + return; + } + + if (player->bot) + { + // Your nefarious opponent puppy can't grab these for you. + return; + } + + if (!P_IsLocalPlayer(player)) + { + // Must be party. + return; + } + + if (special->hitlag || special->scale < mapobjectscale/2) + { + // Don't get during the initial activation + return; + } + + if ( + grandprixinfo.gp == true // Bonus Round + && netgame == false // game design + makes it easier to implement + && gamedata->thisprisoneggpickup_cached != NULL + ) + { + gamedata->thisprisoneggpickupgrabbed = true; + gamedata->prisoneggstothispickup = GDINIT_PRISONSTOPRIZE; + + if (!M_UpdateUnlockablesAndExtraEmblems(true, true)) + S_StartSound(NULL, sfx_ncitem); + gamedata->deferredsave = true; + } + + break; + } + case MT_LSZ_BUNGEE: Obj_BungeeSpecial(special, player); return; @@ -936,6 +979,11 @@ static void P_AddBrokenPrison(mobj_t *target, mobj_t *source) K_SpawnBattlePoints(source->player, NULL, 1); } + if (gamedata->prisoneggstothispickup) + { + gamedata->prisoneggstothispickup--; + } + if (++numtargets >= maptargets) { P_DoAllPlayersExit(0, (grandprixinfo.gp == true)); @@ -948,6 +996,55 @@ static void P_AddBrokenPrison(mobj_t *target, mobj_t *source) extratimeintics += 10*TICRATE; secretextratime = TICRATE/2; } + + if ( + grandprixinfo.gp == true // Bonus Round + && demo.playback == false // Not playback + && netgame == false // game design + makes it easier to implement + && gamedata->thisprisoneggpickup_cached != NULL + && gamedata->prisoneggstothispickup == 0 + && gamedata->thisprisoneggpickupgrabbed == false + ) + { + // Will be 0 for the next level + gamedata->prisoneggstothispickup = (maptargets - numtargets); + + mobj_t *secretpickup = P_SpawnMobj( + target->x, target->y, + target->z + ( + target->height + - FixedMul(mobjinfo[MT_PRISONEGGDROP].height, mapobjectscale) + ), + MT_PRISONEGGDROP + ); + + if (secretpickup) + { + secretpickup->hitlag = target->hitlag; + + P_SetScale(secretpickup, mapobjectscale/TICRATE); + // secretpickup->destscale = mapobjectscale; -- safe assumption it's already set? + secretpickup->scalespeed = (2*mapobjectscale)/(3*TICRATE); + + // NOT from the target - just in case it's just been placed on the ceiling as a gimmick + K_FlipFromObject(secretpickup, source); + + // Okay these have to use M_Random because replays... + // The spawning of these won't be recorded back! + const angle_t launchangle = FixedAngle(M_RandomRange(60, 80) * FRACUNIT); + const fixed_t launchmomentum = 20 * mapobjectscale; + + secretpickup->momz = P_MobjFlip(target) // THIS one uses target! + * P_ReturnThrustY(secretpickup, launchangle, launchmomentum); + + secretpickup->angle = FixedAngle(M_RandomKey(360) * FRACUNIT); + + P_InstaThrust( + secretpickup, secretpickup->angle, + P_ReturnThrustX(secretpickup, launchangle, launchmomentum) + ); + } + } } } diff --git a/src/p_mobj.c b/src/p_mobj.c index ca783b256..3c6cbffa7 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7638,6 +7638,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) break; } case MT_EMERALD: + { Obj_EmeraldThink(mobj); if (P_MobjWasRemoved(mobj)) @@ -7645,6 +7646,56 @@ static boolean P_MobjRegularThink(mobj_t *mobj) return false; } break; + } + case MT_PRISONEGGDROP: + { + // If it gets any more complicated than this I'll make an objects/prisoneggdrop.c file, promise + // ~toast 121023 + + statenum_t teststate = S_NULL; + + if (mobj->flags2 & MF2_AMBUSH) + { + if (P_IsObjectOnGround(mobj)) + { + if (P_CheckDeathPitCollide(mobj)) + { + P_RemoveMobj(mobj); + return false; + } + + mobj->momx = mobj->momy = 0; + } + + teststate = (mobj->state-states); + } + else if (!netgame) + { + if (gamedata->thisprisoneggpickup_cached->type == UC_PRISONEGGCD) + { + teststate = S_PRISONEGGDROP_CD; + } + + P_SetMobjState(mobj, teststate); + + if (P_MobjWasRemoved(mobj)) + { + return false; + } + + S_StartSound(NULL, sfx_cdsprk); + + mobj->z += P_MobjFlip(mobj); + mobj->flags2 |= MF2_AMBUSH; + } + + if (teststate == S_PRISONEGGDROP_CD) + { + mobj->angle += ANGLE_MAX/TICRATE; + } + + break; + } case MT_EMERALDFLARE: Obj_EmeraldFlareThink(mobj); diff --git a/src/p_saveg.c b/src/p_saveg.c index 1ac21c929..523f9a5fb 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -2708,6 +2708,10 @@ boolean TypeIsNetSynced(mobjtype_t type) if (type == MT_HORNCODE) return false; + // MT_PRISONEGGDROP: Yeah these are completely local + if (type == MT_PRISONEGGDROP) + return false; + return true; } diff --git a/src/sounds.c b/src/sounds.c index afacfee07..52f44a70a 100644 --- a/src/sounds.c +++ b/src/sounds.c @@ -1193,6 +1193,7 @@ sfxinfo_t S_sfx[NUMSFX] = {"horn00", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "/"}, // HORNCODE {"melody", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "/"}, // Mystic Melody + {"cdsprk", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "/"}, // Prison Egg CD sparkling {"monch", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""}, {"etexpl", false, 255, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Game crash"}, diff --git a/src/sounds.h b/src/sounds.h index ed959274a..769abc803 100644 --- a/src/sounds.h +++ b/src/sounds.h @@ -1263,6 +1263,7 @@ typedef enum sfx_horn00, sfx_melody, + sfx_cdsprk, sfx_monch, sfx_etexpl,