Properly separate SPB & Shrink cooldowns

Also refactors some of the result -> type & amount code
This commit is contained in:
Sally Coolatta 2022-09-23 03:35:18 -04:00
parent 3a21f60ce1
commit f89d8d15c2
14 changed files with 155 additions and 176 deletions

View file

@ -707,7 +707,7 @@ extern boolean comeback;
extern SINT8 battlewanted[4];
extern tic_t wantedcalcdelay;
extern tic_t indirectitemcooldown;
extern tic_t itemCooldowns[NUMKARTITEMS - 1];
extern tic_t mapreset;
extern boolean thwompsactive;
extern UINT8 lastLowestLap;

View file

@ -317,7 +317,7 @@ SINT8 pickedvote; // What vote the host rolls
// Server-sided, synched variables
SINT8 battlewanted[4]; // WANTED players in battle, worth x2 points
tic_t wantedcalcdelay; // Time before it recalculates WANTED
tic_t indirectitemcooldown; // Cooldown before any more Shrink, SPB, or any other item that works indirectly is awarded
tic_t itemCooldowns[NUMKARTITEMS - 1]; // Cooldowns to prevent item spawning
tic_t mapreset; // Map reset delay when enough players have joined an empty game
boolean thwompsactive; // Thwomps activate on lap 2
UINT8 lastLowestLap; // Last lowest lap, for activating race lap executors

View file

@ -4607,6 +4607,7 @@ static void K_drawDistributionDebugger(void)
0,
stplyr->bot, (stplyr->bot && stplyr->botvars.rival)
);
INT32 amount = 1;
if (itemodds <= 0)
continue;
@ -4615,27 +4616,9 @@ static void K_drawDistributionDebugger(void)
V_DrawThinString(x+11, y+31, V_SNAPTOTOP, va("%d", itemodds));
// Display amount for multi-items
if (i >= NUMKARTITEMS)
amount = K_ItemResultToAmount(i);
if (amount > 1)
{
INT32 amount;
switch (i)
{
case KRITEM_TENFOLDBANANA:
amount = 10;
break;
case KRITEM_QUADORBINAUT:
amount = 4;
break;
case KRITEM_DUALJAWZ:
amount = 2;
break;
case KRITEM_DUALSNEAKER:
amount = 2;
break;
default:
amount = 3;
break;
}
V_DrawString(x+24, y+31, V_ALLOWLOWERCASE|V_SNAPTOTOP, va("x%d", amount));
}

View file

@ -47,7 +47,6 @@
// encoremode is Encore Mode (duh), bool
// comeback is Battle Mode's karma comeback, also bool
// battlewanted is an array of the WANTED player nums, -1 for no player in that slot
// indirectitemcooldown is timer before anyone's allowed another Shrink/SPB
// mapreset is set when enough players fill an empty server
void K_TimerReset(void)
@ -448,6 +447,111 @@ INT32 K_GetShieldFromItem(INT32 item)
}
}
SINT8 K_ItemResultToType(SINT8 getitem)
{
if (getitem <= 0 || getitem >= NUMKARTRESULTS) // Sad (Fallback)
{
if (getitem != 0)
{
CONS_Printf("ERROR: K_GetItemResultToItemType - Item roulette gave bad item (%d) :(\n", getitem);
}
return KITEM_SAD;
}
if (getitem >= NUMKARTITEMS)
{
switch (getitem)
{
case KRITEM_DUALSNEAKER:
case KRITEM_TRIPLESNEAKER:
return KITEM_SNEAKER;
case KRITEM_TRIPLEBANANA:
case KRITEM_TENFOLDBANANA:
return KITEM_BANANA;
case KRITEM_TRIPLEORBINAUT:
case KRITEM_QUADORBINAUT:
return KITEM_ORBINAUT;
case KRITEM_DUALJAWZ:
return KITEM_JAWZ;
default:
I_Error("Bad item cooldown redirect for result %d\n", getitem);
break;
}
}
return getitem;
}
UINT8 K_ItemResultToAmount(SINT8 getitem)
{
switch (getitem)
{
case KRITEM_DUALSNEAKER:
case KRITEM_DUALJAWZ:
return 2;
case KRITEM_TRIPLESNEAKER:
case KRITEM_TRIPLEBANANA:
case KRITEM_TRIPLEORBINAUT:
return 3;
case KRITEM_QUADORBINAUT:
return 4;
case KITEM_BALLHOG: // Not a special result, but has a special amount
return 5;
case KRITEM_TENFOLDBANANA:
return 10;
default:
return 1;
}
}
tic_t K_GetItemCooldown(SINT8 itemResult)
{
SINT8 itemType = K_ItemResultToType(itemResult);
if (itemType < 1 || itemType >= NUMKARTITEMS)
{
return 0;
}
return itemCooldowns[itemType - 1];
}
void K_SetItemCooldown(SINT8 itemResult, tic_t time)
{
SINT8 itemType = K_ItemResultToType(itemResult);
if (itemType < 1 || itemType >= NUMKARTITEMS)
{
return;
}
itemCooldowns[itemType - 1] = max(itemCooldowns[itemType - 1], time);
}
void K_RunItemCooldowns(void)
{
size_t i;
for (i = 0; i < NUMKARTITEMS-1; i++)
{
if (itemCooldowns[i] > 0)
{
itemCooldowns[i]--;
}
}
}
/** \brief Item Roulette for Kart
\param player player
@ -457,61 +561,16 @@ INT32 K_GetShieldFromItem(INT32 item)
*/
static void K_KartGetItemResult(player_t *player, SINT8 getitem)
{
if (getitem == KITEM_SPB) // Indirect items
if (getitem == KITEM_SPB || getitem == KITEM_SHRINK)
{
indirectitemcooldown = 20*TICRATE;
K_SetItemCooldown(getitem, 20*TICRATE);
}
player->botvars.itemdelay = TICRATE;
player->botvars.itemconfirm = 0;
switch (getitem)
{
// Special roulettes first, then the generic ones are handled by default
case KRITEM_DUALSNEAKER: // Sneaker x2
player->itemtype = KITEM_SNEAKER;
player->itemamount = 2;
break;
case KRITEM_TRIPLESNEAKER: // Sneaker x3
player->itemtype = KITEM_SNEAKER;
player->itemamount = 3;
break;
case KRITEM_TRIPLEBANANA: // Banana x3
player->itemtype = KITEM_BANANA;
player->itemamount = 3;
break;
case KRITEM_TENFOLDBANANA: // Banana x10
player->itemtype = KITEM_BANANA;
player->itemamount = 10;
break;
case KRITEM_TRIPLEORBINAUT: // Orbinaut x3
player->itemtype = KITEM_ORBINAUT;
player->itemamount = 3;
break;
case KRITEM_QUADORBINAUT: // Orbinaut x4
player->itemtype = KITEM_ORBINAUT;
player->itemamount = 4;
break;
case KRITEM_DUALJAWZ: // Jawz x2
player->itemtype = KITEM_JAWZ;
player->itemamount = 2;
break;
case KITEM_BALLHOG: // Ballhog x5
player->itemtype = KITEM_BALLHOG;
player->itemamount = 5;
break;
default:
if (getitem <= 0 || getitem >= NUMKARTRESULTS) // Sad (Fallback)
{
if (getitem != 0)
CONS_Printf("ERROR: P_KartGetItemResult - Item roulette gave bad item (%d) :(\n", getitem);
player->itemtype = KITEM_SAD;
}
else
player->itemtype = getitem;
player->itemamount = 1;
break;
}
player->itemtype = K_ItemResultToType(getitem);
player->itemamount = K_ItemResultToAmount(getitem);
}
fixed_t K_ItemOddsScale(UINT8 playerCount)
@ -591,7 +650,6 @@ INT32 K_KartGetItemOdds(
boolean powerItem = false;
boolean cooldownOnStart = false;
boolean indirectItem = false;
boolean notNearEnd = false;
INT32 shieldtype = KSHIELD_NONE;
@ -600,7 +658,15 @@ INT32 K_KartGetItemOdds(
I_Assert(KartItemCVars[NUMKARTRESULTS-2] != NULL); // Make sure this exists
if (!KartItemCVars[item-1]->value && !modeattacking)
{
return 0;
}
if (K_GetItemCooldown(item) > 0)
{
// Cooldown is still running, don't give another.
return 0;
}
/*
if (bot)
@ -719,7 +785,6 @@ INT32 K_KartGetItemOdds(
case KITEM_SPB:
cooldownOnStart = true;
indirectItem = true;
notNearEnd = true;
if (firstDist < ENDDIST*2 // No SPB when 1st is almost done
@ -775,12 +840,8 @@ INT32 K_KartGetItemOdds(
return newodds;
}
if ((indirectItem == true) && (indirectitemcooldown > 0))
{
// Too many items that act indirectly in a match can feel kind of bad.
newodds = 0;
}
else if ((cooldownOnStart == true) && (leveltime < (30*TICRATE)+starttime))
if ((cooldownOnStart == true) && (leveltime < (30*TICRATE)+starttime))
{
// This item should not appear at the beginning of a race. (Usually really powerful crowd-breaking items)
newodds = 0;
@ -946,7 +1007,7 @@ boolean K_ForcedSPB(player_t *player)
return false;
}
if (indirectitemcooldown > 0)
if (itemCooldowns[KITEM_SPB - 1] > 0)
{
return false;
}
@ -6436,46 +6497,8 @@ mobj_t *K_CreatePaperItem(fixed_t x, fixed_t y, fixed_t z, angle_t angle, SINT8
// K_KartGetItemResult requires a player
// but item roulette will need rewritten to change this
switch (i)
{
// Special roulettes first, then the generic ones are handled by default
case KRITEM_DUALSNEAKER: // Sneaker x2
newType = KITEM_SNEAKER;
newAmount = 2;
break;
case KRITEM_TRIPLESNEAKER: // Sneaker x3
newType = KITEM_SNEAKER;
newAmount = 3;
break;
case KRITEM_TRIPLEBANANA: // Banana x3
newType = KITEM_BANANA;
newAmount = 3;
break;
case KRITEM_TENFOLDBANANA: // Banana x10
newType = KITEM_BANANA;
newAmount = 10;
break;
case KRITEM_TRIPLEORBINAUT: // Orbinaut x3
newType = KITEM_ORBINAUT;
newAmount = 3;
break;
case KRITEM_QUADORBINAUT: // Orbinaut x4
newType = KITEM_ORBINAUT;
newAmount = 4;
break;
case KRITEM_DUALJAWZ: // Jawz x2
newType = KITEM_JAWZ;
newAmount = 2;
break;
case KITEM_BALLHOG: // Ballhog x5
newType = KITEM_BALLHOG;
newAmount = 5;
break;
default:
newType = i;
newAmount = 1;
break;
}
newType = K_ItemResultToType(i);
newAmount = K_ItemResultToAmount(i);
if (newAmount > 1)
{
@ -10701,9 +10724,10 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
if (spbplace == -1 || player->position != spbplace)
player->pflags &= ~PF_RINGLOCK; // reset ring lock
if (player->itemtype == KITEM_SPB)
if (player->itemtype == KITEM_SPB
|| player->itemtype == KITEM_SHRINK)
{
indirectitemcooldown = 20*TICRATE;
K_SetItemCooldown(player->itemtype, 20*TICRATE);
}
if (player->hyudorotimer > 0)

View file

@ -50,6 +50,11 @@ UINT32 K_ScaleItemDistance(UINT32 distance, UINT8 numPlayers);
INT32 K_KartGetItemOdds(UINT8 pos, SINT8 item, UINT32 ourDist, fixed_t mashed, boolean bot, boolean rival);
boolean K_ForcedSPB(player_t *player);
INT32 K_GetShieldFromItem(INT32 item);
SINT8 K_ItemResultToType(SINT8 getitem);
UINT8 K_ItemResultToAmount(SINT8 getitem);
tic_t K_GetItemCooldown(SINT8 itemResult);
void K_SetItemCooldown(SINT8 itemResult, tic_t time);
void K_RunItemCooldowns(void);
fixed_t K_GetMobjWeight(mobj_t *mobj, mobj_t *against);
boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2);
boolean K_KartSolidBounce(mobj_t *bounceMobj, mobj_t *solidMobj);

View file

@ -3366,34 +3366,14 @@ void M_DrawItemToggles(void)
cv = KartItemCVars[currentMenu->menuitems[thisitem].mvar1-1];
translucent = (cv->value ? 0 : V_TRANSLUCENT);
switch (currentMenu->menuitems[thisitem].mvar1)
{
case KRITEM_DUALSNEAKER:
case KRITEM_DUALJAWZ:
drawnum = 2;
break;
case KRITEM_TRIPLESNEAKER:
case KRITEM_TRIPLEBANANA:
case KRITEM_TRIPLEORBINAUT:
drawnum = 3;
break;
case KRITEM_QUADORBINAUT:
drawnum = 4;
break;
case KRITEM_TENFOLDBANANA:
drawnum = 10;
break;
default:
drawnum = 0;
break;
}
drawnum = K_ItemResultToAmount(currentMenu->menuitems[thisitem].mvar1);
if (cv->value)
V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISBG", PU_CACHE));
else
V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISBGD", PU_CACHE));
if (drawnum != 0)
if (drawnum > 1)
{
V_DrawScaledPatch(x, y, 0, W_CachePatchName("K_ISMUL", PU_CACHE));
V_DrawScaledPatch(x, y, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[thisitem].mvar1, true), PU_CACHE));
@ -3433,30 +3413,14 @@ void M_DrawItemToggles(void)
cv = KartItemCVars[currentMenu->menuitems[itemOn].mvar1-1];
translucent = (cv->value ? 0 : V_TRANSLUCENT);
switch (currentMenu->menuitems[itemOn].mvar1)
{
case KRITEM_DUALSNEAKER:
case KRITEM_DUALJAWZ:
drawnum = 2;
break;
case KRITEM_TRIPLESNEAKER:
case KRITEM_TRIPLEBANANA:
drawnum = 3;
break;
case KRITEM_TENFOLDBANANA:
drawnum = 10;
break;
default:
drawnum = 0;
break;
}
drawnum = K_ItemResultToAmount(currentMenu->menuitems[itemOn].mvar1);
if (cv->value)
V_DrawScaledPatch(onx-1, ony-2, 0, W_CachePatchName("K_ITBG", PU_CACHE));
else
V_DrawScaledPatch(onx-1, ony-2, 0, W_CachePatchName("K_ITBGD", PU_CACHE));
if (drawnum != 0)
if (drawnum > 1)
{
V_DrawScaledPatch(onx-1, ony-2, 0, W_CachePatchName("K_ITMUL", PU_CACHE));
V_DrawScaledPatch(onx-1, ony-2, translucent, W_CachePatchName(K_GetItemPatch(currentMenu->menuitems[itemOn].mvar1, false), PU_CACHE));

View file

@ -375,9 +375,6 @@ int LUA_PushGlobals(lua_State *L, const char *word)
} else if (fastcmp(word,"wantedcalcdelay")) {
lua_pushinteger(L, wantedcalcdelay);
return 1;
} else if (fastcmp(word,"indirectitemcooldown")) {
lua_pushinteger(L, indirectitemcooldown);
return 1;
} else if (fastcmp(word,"thwompsactive")) {
lua_pushboolean(L, thwompsactive);
return 1;
@ -463,8 +460,6 @@ int LUA_WriteGlobals(lua_State *L, const char *word)
racecountdown = (tic_t)luaL_checkinteger(L, 2);
else if (fastcmp(word,"exitcountdown"))
exitcountdown = (tic_t)luaL_checkinteger(L, 2);
else if (fastcmp(word,"indirectitemcooldown"))
indirectitemcooldown = (tic_t)luaL_checkinteger(L, 2);
else
return 0;

View file

@ -439,6 +439,8 @@ void Obj_PohbeeThinker(mobj_t *pohbee)
{
mobj_t *gun = NULL;
K_SetItemCooldown(KITEM_SHRINK, 20*TICRATE);
pohbee->momx = pohbee->momy = pohbee->momz = 0;
pohbee->spritexscale = pohbee->spriteyscale = 2*FRACUNIT;

View file

@ -766,7 +766,7 @@ void Obj_SPBThink(mobj_t *spb)
return;
}
indirectitemcooldown = 20*TICRATE;
K_SetItemCooldown(KITEM_SPB, 20*TICRATE);
ghost = P_SpawnGhostMobj(spb);
ghost->fuse = 3;

View file

@ -6743,7 +6743,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
break;
case KITEM_SPB:
case KITEM_SHRINK:
indirectitemcooldown = 20*TICRATE;
K_SetItemCooldown(mobj->threshold, 20*TICRATE);
/* FALLTHRU */
default:
mobj->sprite = SPR_ITEM;

View file

@ -4560,7 +4560,8 @@ static void P_NetArchiveMisc(boolean resending)
WRITEFIXED(save_p, battleovertime.z);
WRITEUINT32(save_p, wantedcalcdelay);
WRITEUINT32(save_p, indirectitemcooldown);
for (i = 0; i < NUMKARTITEMS-1; i++)
WRITEUINT32(save_p, itemCooldowns[i]);
WRITEUINT32(save_p, mapreset);
WRITEUINT8(save_p, spectateGriefed);
@ -4723,7 +4724,8 @@ static inline boolean P_NetUnArchiveMisc(boolean reloading)
battleovertime.z = READFIXED(save_p);
wantedcalcdelay = READUINT32(save_p);
indirectitemcooldown = READUINT32(save_p);
for (i = 0; i < NUMKARTITEMS-1; i++)
itemCooldowns[i] = READUINT32(save_p);
mapreset = READUINT32(save_p);
spectateGriefed = READUINT8(save_p);

View file

@ -4022,6 +4022,8 @@ static void P_InitPlayers(void)
static void P_InitGametype(void)
{
size_t i;
spectateGriefed = 0;
K_CashInPowerLevels(); // Pushes power level changes even if intermission was skipped
@ -4046,7 +4048,10 @@ static void P_InitGametype(void)
}
wantedcalcdelay = wantedfrequency*2;
indirectitemcooldown = 0;
for (i = 0; i < NUMKARTITEMS-1; i++)
itemCooldowns[i] = 0;
mapreset = 0;
thwompsactive = false;

View file

@ -683,8 +683,7 @@ void P_Ticker(boolean run)
if (exitcountdown > 1)
exitcountdown--;
if (indirectitemcooldown > 0)
indirectitemcooldown--;
K_RunItemCooldowns();
K_BossInfoTicker();

View file

@ -2592,7 +2592,7 @@ void P_NukeEnemies(mobj_t *inflictor, mobj_t *source, fixed_t radius)
if (mo->type == MT_SPB) // If you destroy a SPB, you don't get the luxury of a cooldown.
{
spbplace = -1;
indirectitemcooldown = 0;
itemCooldowns[KITEM_SPB - 1] = 0;
}
if (mo->flags & MF_BOSS) //don't OHKO bosses nor players!