Ringbox: item respawn refactor + box visuals

This commit is contained in:
AJ Martinez 2023-06-26 06:36:37 -07:00
parent f371a21258
commit 45547607bd
8 changed files with 136 additions and 88 deletions

View file

@ -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",

View file

@ -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

View file

@ -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,

View file

@ -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;
}
}

View file

@ -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)

View file

@ -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;

View file

@ -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

View file

@ -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)