From 45547607bd33427230943185ae862d12707ab539 Mon Sep 17 00:00:00 2001 From: AJ Martinez Date: Mon, 26 Jun 2023 06:36:37 -0700 Subject: [PATCH] Ringbox: item respawn refactor + box visuals --- src/deh_tables.c | 17 ++++++++-- src/info.c | 22 ++++++++++--- src/info.h | 19 ++++++++--- src/k_kart.c | 2 +- src/objects/random-item.c | 20 +++++++++++- src/p_enemy.c | 54 ------------------------------- src/p_inter.c | 67 +++++++++++++++++++++++++++++++++++++-- src/p_mobj.c | 23 +++----------- 8 files changed, 136 insertions(+), 88 deletions(-) diff --git a/src/deh_tables.c b/src/deh_tables.c index 3cce64a49..d80bcf379 100644 --- a/src/deh_tables.c +++ b/src/deh_tables.c @@ -283,7 +283,6 @@ actionpointer_t actionpointers[] = {{A_ChangeHeight}, "A_CHANGEHEIGHT"}, // SRB2Kart - {{A_ItemPop}, "A_ITEMPOP"}, {{A_JawzExplode}, "A_JAWZEXPLODE"}, {{A_SSMineSearch}, "A_SSMINESEARCH"}, {{A_SSMineExplode}, "A_SSMINEEXPLODE"}, @@ -3223,7 +3222,20 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_RANDOMITEM10", "S_RANDOMITEM11", "S_RANDOMITEM12", - "S_DEADRANDOMITEM", + + // Ring Box + "S_RINGBOX1", + "S_RINGBOX2", + "S_RINGBOX3", + "S_RINGBOX4", + "S_RINGBOX5", + "S_RINGBOX6", + "S_RINGBOX7", + "S_RINGBOX8", + "S_RINGBOX9", + "S_RINGBOX10", + "S_RINGBOX11", + "S_RINGBOX12", // Sphere Box (for Battle) "S_SPHEREBOX1", @@ -3238,7 +3250,6 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi "S_SPHEREBOX10", "S_SPHEREBOX11", "S_SPHEREBOX12", - "S_DEADSPHEREBOX", // Random Item Pop "S_RANDOMITEMPOP1", diff --git a/src/info.c b/src/info.c index 05ce6aa36..0dc1b9c81 100644 --- a/src/info.c +++ b/src/info.c @@ -531,6 +531,7 @@ char sprnames[NUMSPRITES + 1][5] = //SRB2kart Sprites (sort later) "RNDM", // Random Item Box "SBOX", // Sphere Box (for Battle) + "RBOX", // Ring Box "RPOP", // Random Item Box Pop "ITRI", // Item Box Debris "ITPA", // Paper item backdrop @@ -3892,7 +3893,19 @@ state_t states[NUMSTATES] = {SPR_RNDM, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM11}, // S_RANDOMITEM10 {SPR_RNDM, 20|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM12}, // S_RANDOMITEM11 {SPR_RNDM, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RANDOMITEM1}, // S_RANDOMITEM12 - {SPR_NULL, 0, 0, {A_ItemPop}, 0, 0, S_RANDOMITEM1}, // S_DEADRANDOMITEM + + {SPR_RBOX, FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX2}, // S_RINGBOX1 + {SPR_RBOX, 2|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX3}, // S_RINGBOX2 + {SPR_RBOX, 4|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX4}, // S_RINGBOX3 + {SPR_RBOX, 6|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX5}, // S_RINGBOX4 + {SPR_RBOX, 8|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX6}, // S_RINGBOX5 + {SPR_RBOX, 10|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX7}, // S_RINGBOX6 + {SPR_RBOX, 12|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX8}, // S_RINGBOX7 + {SPR_RBOX, 14|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX9}, // S_RINGBOX8 + {SPR_RBOX, 16|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX10}, // S_RINGBOX9 + {SPR_RBOX, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX11}, // S_RINGBOX10 + {SPR_RBOX, 20|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX12}, // S_RINGBOX11 + {SPR_RBOX, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_RINGBOX1}, // S_RINGBOX12 {SPR_SBOX, FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX2}, // S_SPHEREBOX1 {SPR_SBOX, 2|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX3}, // S_SPHEREBOX2 @@ -3906,7 +3919,6 @@ state_t states[NUMSTATES] = {SPR_SBOX, 18|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX11}, // S_SPHEREBOX10 {SPR_SBOX, 20|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX12}, // S_SPHEREBOX11 {SPR_SBOX, 22|FF_FULLBRIGHT|FF_ANIMATE|FF_GLOBALANIM, 4, {NULL}, 1, 1, S_SPHEREBOX1}, // S_SPHEREBOX12 - {SPR_NULL, 0, 0, {A_ItemPop}, 1, 0, S_NULL}, // S_DEADSPHEREBOX {SPR_RPOP, FF_FULLBRIGHT, 5, {NULL}, 0, 0, S_RANDOMITEMPOP2}, // S_RANDOMITEMPOP1 {SPR_RPOP, FF_FULLBRIGHT|1, 5, {NULL}, 0, 0, S_RANDOMITEMPOP3}, // S_RANDOMITEMPOP2 @@ -22385,7 +22397,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = // SRB2kart MT's { // MT_RANDOMITEM 2000, // doomednum - S_RANDOMITEM1, // spawnstate + S_RINGBOX1, // spawnstate 1000, // spawnhealth S_NULL, // seestate sfx_None, // seesound @@ -22396,7 +22408,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_DEADRANDOMITEM, // deathstate + S_NULL, // deathstate S_NULL, // xdeathstate sfx_kc2e, // deathsound 60*FRACUNIT, // speed @@ -22423,7 +22435,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = sfx_None, // painsound S_NULL, // meleestate S_NULL, // missilestate - S_DEADSPHEREBOX, // deathstate + S_NULL, // deathstate S_NULL, // xdeathstate sfx_kc2e, // deathsound 60*FRACUNIT, // speed diff --git a/src/info.h b/src/info.h index ea28b56c8..d838eb532 100644 --- a/src/info.h +++ b/src/info.h @@ -277,7 +277,6 @@ enum actionnum A_DRAGONWING, A_DRAGONSEGMENT, A_CHANGEHEIGHT, - A_ITEMPOP, A_JAWZEXPLODE, A_SSMINESEARCH, A_SSMINEEXPLODE, @@ -550,7 +549,6 @@ void A_ChangeHeight(); // // SRB2Kart // -void A_ItemPop(); void A_JawzExplode(); void A_SSMineSearch(); void A_SSMineExplode(); @@ -1084,6 +1082,7 @@ typedef enum sprite // SRB2Kart SPR_RNDM, // Random Item Box SPR_SBOX, // Sphere Box (for Battle) + SPR_RBOX, // Ring Box SPR_RPOP, // Random Item Box Pop SPR_ITRI, // Item Box Debris SPR_ITPA, // Paper item backdrop @@ -4299,7 +4298,20 @@ typedef enum state S_RANDOMITEM10, S_RANDOMITEM11, S_RANDOMITEM12, - S_DEADRANDOMITEM, + + // Ring Box + S_RINGBOX1, + S_RINGBOX2, + S_RINGBOX3, + S_RINGBOX4, + S_RINGBOX5, + S_RINGBOX6, + S_RINGBOX7, + S_RINGBOX8, + S_RINGBOX9, + S_RINGBOX10, + S_RINGBOX11, + S_RINGBOX12, // Sphere Box (for Battle) S_SPHEREBOX1, @@ -4314,7 +4326,6 @@ typedef enum state S_SPHEREBOX10, S_SPHEREBOX11, S_SPHEREBOX12, - S_DEADSPHEREBOX, // Random Item Pop S_RANDOMITEMPOP1, diff --git a/src/k_kart.c b/src/k_kart.c index 1a02ad382..763e1e14a 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -10738,7 +10738,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->ringboxdelay == 0) { // TODO - K_AwardPlayerRings(player, 10 * player->ringboxaward, true); + K_AwardPlayerRings(player, 10 * (player->ringboxaward + 1), true); player->ringboxaward = 0; } } diff --git a/src/objects/random-item.c b/src/objects/random-item.c index cae20f752..623f2ab0c 100644 --- a/src/objects/random-item.c +++ b/src/objects/random-item.c @@ -102,8 +102,26 @@ void Obj_RandomItemVisuals(mobj_t *mobj) ItemBoxBob(mobj); ItemBoxScaling(mobj); item_vfxtimer(mobj)++; - if (mobj->fuse == 0) + + // Respawn flow, documented by a dumb asshole: + // P_TouchSpecialThing -> P_ItemPop sets fuse, NOCLIPTHING and DONTDRAW. + // P_FuseThink does visual flicker, and when fuse is 0, unsets NOCLIPTHING/DONTDRAW/etc... + // ...unless it's a map-start box from Battle, in which case it does nothing and waits for + // P_RespawnBattleBoxes to trigger the effect instead, since Battle boxes don't respawn until + // the player's cleared out a good portion of the map. + // + // Then extraval1 starts ticking up and triggers the transformation from Ringbox to Random Item. + if (mobj->fuse == 0 && !(mobj->flags & MF_NOCLIPTHING)) + { mobj->extravalue1++; + if (mobj->extravalue1 == TICRATE) + { + // Sync the position in RINGBOX and RANDOMITEM animations. + statenum_t animDelta = mobj->state - states - S_RINGBOX1; + P_SetMobjState(mobj, S_RANDOMITEM1 + (animDelta%12)); + } + } + } boolean Obj_RandomItemSpawnIn(mobj_t *mobj) diff --git a/src/p_enemy.c b/src/p_enemy.c index 4553e4fe5..64a13bf09 100644 --- a/src/p_enemy.c +++ b/src/p_enemy.c @@ -312,7 +312,6 @@ void A_ChangeHeight(mobj_t *actor); // // SRB2Kart // -void A_ItemPop(mobj_t *actor); void A_JawzExplode(mobj_t *actor); void A_SSMineSearch(mobj_t *actor); void A_SSMineExplode(mobj_t *actor); @@ -12972,59 +12971,6 @@ void A_ChangeHeight(mobj_t *actor) // SRB2Kart // -void A_ItemPop(mobj_t *actor) -{ - INT32 locvar1 = var1; - - if (LUA_CallAction(A_ITEMPOP, actor)) - return; - - if (!(actor->target && actor->target->player)) - { - if (cht_debug && !(actor->target && actor->target->player)) - CONS_Printf("ERROR: Powerup has no target!\n"); - return; - } - - // de-solidify - P_UnsetThingPosition(actor); - actor->flags &= ~MF_SOLID; - actor->flags |= MF_NOCLIP; - P_SetThingPosition(actor); - - // RF_DONTDRAW will flicker as the object's fuse gets - // closer to running out (see P_FuseThink) - actor->renderflags |= RF_DONTDRAW|RF_TRANS50; - actor->color = SKINCOLOR_GREY; - actor->colorized = true; - - Obj_SpawnItemDebrisEffects(actor, actor->target); - - if (locvar1 == 1) - { - P_GivePlayerSpheres(actor->target->player, actor->extravalue1); - } - else if (locvar1 == 0) - { - if (actor->extravalue1 >= TICRATE) - K_StartItemRoulette(actor->target->player, false); - else - K_StartItemRoulette(actor->target->player, true); - } - - actor->extravalue1 = 0; - - // Here at mapload in battle? - if (!(gametyperules & GTR_CIRCUIT) && (actor->flags2 & MF2_BOSSNOTRAP)) - { - numgotboxes++; - - // do not flicker back in just yet, handled by - // P_RespawnBattleBoxes eventually - P_SetMobjState(actor, S_INVISIBLE); - } -} - void A_JawzExplode(mobj_t *actor) { INT32 shrapnel = 2; diff --git a/src/p_inter.c b/src/p_inter.c index 58dd878fc..971b08f1c 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -186,6 +186,61 @@ boolean P_EmblemWasCollected(INT32 emblemID) return gamedata->collected[emblemID]; } +static void P_ItemPop(mobj_t *actor) +{ + /* + INT32 locvar1 = var1; + + if (LUA_CallAction(A_ITEMPOP, actor)) + return; + + if (!(actor->target && actor->target->player)) + { + if (cht_debug && !(actor->target && actor->target->player)) + CONS_Printf("ERROR: Powerup has no target!\n"); + return; + } + */ + + P_SetMobjState(actor, S_RINGBOX1); + actor->extravalue1 = 0; + + // de-solidify + actor->flags |= MF_NOCLIPTHING; + + // RF_DONTDRAW will flicker as the object's fuse gets + // closer to running out (see P_FuseThink) + actor->renderflags |= RF_DONTDRAW|RF_TRANS50; + actor->color = SKINCOLOR_GREY; + actor->colorized = true; + + Obj_SpawnItemDebrisEffects(actor, actor->target); + + /* + if (locvar1 == 1) + { + P_GivePlayerSpheres(actor->target->player, actor->extravalue1); + } + else if (locvar1 == 0) + { + if (actor->extravalue1 >= TICRATE) + K_StartItemRoulette(actor->target->player, false); + else + K_StartItemRoulette(actor->target->player, true); + } + */ + + // Here at mapload in battle? + if (!(gametyperules & GTR_CIRCUIT) && (actor->flags2 & MF2_BOSSNOTRAP)) + { + numgotboxes++; + + // do not flicker back in just yet, handled by + // P_RespawnBattleBoxes eventually + P_SetMobjState(actor, S_INVISIBLE); + } +} + /** Takes action based on a ::MF_SPECIAL thing touched by a player. * Actually, this just checks a few things (heights, toucher->player, no * objectplace, no dead or disappearing things) @@ -300,7 +355,13 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->momx = special->momy = special->momz = 0; P_SetTarget(&special->target, toucher); - P_KillMobj(special, toucher, toucher, DMG_NORMAL); + // P_KillMobj(special, toucher, toucher, DMG_NORMAL); + if (special->extravalue1 >= TICRATE) + K_StartItemRoulette(player, false); + else + K_StartItemRoulette(player, true); + P_ItemPop(special); + special->fuse = TICRATE; return; case MT_SPHEREBOX: if (!P_CanPickupItem(player, 0)) @@ -308,7 +369,9 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) special->momx = special->momy = special->momz = 0; P_SetTarget(&special->target, toucher); - P_KillMobj(special, toucher, toucher, DMG_NORMAL); + // P_KillMobj(special, toucher, toucher, DMG_NORMAL); + P_ItemPop(special); + P_GivePlayerSpheres(player, special->extravalue1); return; case MT_ITEMCAPSULE: if (special->scale < special->extravalue1) // don't break it while it's respawning diff --git a/src/p_mobj.c b/src/p_mobj.c index 4be545796..c44411461 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9710,7 +9710,7 @@ static boolean P_FuseThink(mobj_t *mobj) case MT_RANDOMITEM: if (mobj->flags2 & MF2_DONTRESPAWN) { - ; + P_RemoveMobj(mobj); } else if (!(gametyperules & GTR_CIRCUIT) && (mobj->state == &states[S_INVISIBLE])) { @@ -9718,23 +9718,10 @@ static boolean P_FuseThink(mobj_t *mobj) } else { - mobj_t *newmobj; - - // Respawn from mapthing if you have one! - if (mobj->spawnpoint) - { - P_SpawnMapThing(mobj->spawnpoint); - newmobj = mobj->spawnpoint->mobj; // this is set to the new mobj in P_SpawnMapThing - } - else - newmobj = P_SpawnMobj(mobj->x, mobj->y, mobj->z, mobj->type); - - // Transfer flags2 (strongbox, objectflip, bossnotrap) - newmobj->flags2 = mobj->flags2; - newmobj->extravalue1 = 0; + mobj->flags &= ~MF_NOCLIPTHING; + mobj->renderflags &= ~(RF_DONTDRAW|RF_TRANSMASK); } - P_RemoveMobj(mobj); // make sure they disappear return false; case MT_ITEMCAPSULE: if (mobj->spawnpoint) @@ -11569,11 +11556,11 @@ void P_RespawnBattleBoxes(void) if (box->type != MT_RANDOMITEM || (box->flags2 & MF2_DONTRESPAWN) - || box->health > 0 + || !(box->flags & MF_NOCLIPTHING) || box->fuse) continue; // only popped items - box->fuse = TICRATE; // flicker back in (A_ItemPop preps this effect) + box->fuse = TICRATE; // flicker back in P_SetMobjState(box, box->info->raisestate); if (numgotboxes > 0)