Merge pull request 'More flexible per-item cooldowns' (#168) from wdgaster into blankart-dev
Reviewed-on: https://codeberg.org/NepDisk/blankart/pulls/168
This commit is contained in:
commit
5d8579dd56
10 changed files with 235 additions and 18 deletions
|
|
@ -677,7 +677,7 @@ extern SINT8 mostwanted;
|
|||
extern SINT8 battlewanted[4];
|
||||
extern tic_t wantedcalcdelay;
|
||||
extern tic_t indirectitemcooldown;
|
||||
extern tic_t hyubgone;
|
||||
//extern tic_t hyubgone;
|
||||
extern tic_t mapreset;
|
||||
extern boolean thwompsactive;
|
||||
extern UINT8 lastLowestLap;
|
||||
|
|
|
|||
|
|
@ -439,8 +439,14 @@ void F_IntroTicker(void)
|
|||
}
|
||||
if (finalecount == 80)
|
||||
{
|
||||
char chars[5][10] = {"tails", "chao", "aiai", "sakura"};
|
||||
SINT8 random = M_RandomRange(0, 3);
|
||||
// I'm assuming these are all representative of a "dev character".
|
||||
// Tails: NepDisk
|
||||
// Chao: Alug
|
||||
// Aiai: GHG
|
||||
// Sakura: Anon
|
||||
// Doomguy: Minenice
|
||||
char chars[6][10] = {"tails", "chao", "aiai", "sakura", "doomguy"};
|
||||
SINT8 random = M_RandomRange(0, 4);
|
||||
sfxenum_t rsound = skins[R_SkinAvailable(chars[random])].soundsid[SKSKWIN];
|
||||
S_StartSound(NULL, sfx_flgcap);
|
||||
S_StartSound(NULL, rsound);
|
||||
|
|
|
|||
|
|
@ -60,6 +60,7 @@
|
|||
#include "k_grandprix.h"
|
||||
#include "k_boss.h"
|
||||
#include "k_bot.h"
|
||||
#include "k_odds.h"
|
||||
#include "doomstat.h"
|
||||
#include "acs/interface.h"
|
||||
#include "k_director.h"
|
||||
|
|
@ -299,7 +300,7 @@ SINT8 battlewanted[4]; // WANTED players in battle, worth x2 points
|
|||
SINT8 mostwanted; // The "most wanted" (first in line) player.
|
||||
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 hyubgone; // Cooldown before hyudoro is allowed to be rerolled
|
||||
// hyubgone was taken out back. See k_odds.c
|
||||
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
|
||||
|
|
|
|||
133
src/k_odds.c
133
src/k_odds.c
|
|
@ -152,6 +152,80 @@ static UINT8 K_KartItemOddsBattle[NUMKARTRESULTS][2] =
|
|||
{ 5, 1 } // Jawz x2
|
||||
};
|
||||
|
||||
// Cooldown time table; contains both base (index 0) and current (index 1)
|
||||
// times. Base times are in seconds, current times are in tics.
|
||||
tic_t ItemBGone[NUMKARTRESULTS][2] =
|
||||
{
|
||||
//BASE CURR
|
||||
{ 0, 0 }, // Null/Sad Face
|
||||
{ 0, 0 }, // Sneaker
|
||||
{ 0, 0 }, // Rocket Sneaker
|
||||
{ 0, 0 }, // Invincibility
|
||||
{ 0, 0 }, // Banana
|
||||
{ 10, 0 }, // Eggman Monitor
|
||||
{ 0, 0 }, // Orbinaut
|
||||
{ 5, 0 }, // Jawz
|
||||
{ 0, 0 }, // Mine
|
||||
{ 10, 0 }, // Ballhog
|
||||
{ 20, 0 }, // Self-Propelled Bomb
|
||||
{ 3, 0 }, // Grow
|
||||
{ 20, 0 }, // Shrink
|
||||
{ 0, 0 }, // Thunder Shield
|
||||
{ 20, 0 }, // Hyudoro
|
||||
{ 0, 0 }, // Pogo Spring
|
||||
{ 0, 0 }, // Kitchen Sink
|
||||
{ 0, 0 }, // Super Ring
|
||||
{ 0, 0 }, // Land Mine
|
||||
{ 5, 0 }, // Bubble Shield
|
||||
{ 8, 0 }, // Flame Shield
|
||||
{ 0, 0 }, // Sneaker x2
|
||||
{ 0, 0 }, // Sneaker x3
|
||||
{ 0, 0 }, // Banana x3
|
||||
{ 30, 0 }, // Banana x10
|
||||
{ 10, 0 }, // Orbinaut x3
|
||||
{ 20, 0 }, // Orbinaut x4
|
||||
{ 10, 0 } // Jawz x2
|
||||
};
|
||||
|
||||
// TODO: Vectorize all item tables and shove them into gamemode-uniqe pools (k_oddstable.cpp?).
|
||||
// Basically necessary for any hopes of easy SOC support in the near future.
|
||||
|
||||
/** \brief Sets the cooldown timer for an item. When active, the item is removed
|
||||
* from all players' item pools for some time.
|
||||
|
||||
\param item (SINT8) item to assign cooldown for
|
||||
\param time (tic_t) cooldown time
|
||||
|
||||
\return void
|
||||
*/
|
||||
void K_SetBGone(SINT8 item, tic_t time)
|
||||
{
|
||||
ItemBGone[item][GONER_CURRCOOLDOWN] = time;
|
||||
}
|
||||
|
||||
/** \brief Sets the cooldown timer for an item to its "base" (intended) time.
|
||||
|
||||
\param item (SINT8) item to assign base cooldown for
|
||||
|
||||
\return void
|
||||
*/
|
||||
void K_SetBGoneToBase(SINT8 item)
|
||||
{
|
||||
ItemBGone[item][GONER_CURRCOOLDOWN] = (ItemBGone[item][GONER_BASECOOLDOWN] * TICRATE);
|
||||
}
|
||||
|
||||
/** \brief Gets the cooldown timer for an item.
|
||||
|
||||
\param item (SINT8) item to retrieve cooldown for
|
||||
\param base (bool) if true, returns the "base" (intended) cooldown instead
|
||||
|
||||
\return (tic_t) cooldown time
|
||||
*/
|
||||
tic_t K_GetBGone(SINT8 item, boolean base)
|
||||
{
|
||||
return ItemBGone[item][base ? GONER_BASECOOLDOWN : GONER_CURRCOOLDOWN] * (base ? TICRATE : 1);
|
||||
}
|
||||
|
||||
// Magic number distance for use with item roulette tiers
|
||||
#define ACTIVEDISTVAR (K_UsingLegacyCheckpoints() ? DISTVAR_LEGACY : DISTVAR)
|
||||
|
||||
|
|
@ -288,8 +362,10 @@ static void K_KartGetItemResult(player_t *player, SINT8 getitem)
|
|||
if (getitem == KITEM_SPB || getitem == KITEM_SHRINK) // Indirect items
|
||||
indirectitemcooldown = 20*TICRATE;
|
||||
|
||||
if (getitem == KITEM_HYUDORO) // Hyudoro cooldown
|
||||
hyubgone = 20*TICRATE;
|
||||
if (K_GetBGone(getitem, true) > 0) // Item cooldowns
|
||||
{
|
||||
K_SetBGoneToBase(getitem);
|
||||
}
|
||||
|
||||
K_BotResetItemConfirm(player, true);
|
||||
|
||||
|
|
@ -378,7 +454,7 @@ UINT32 K_ScaleItemDistance(UINT32 distance, UINT8 numPlayers, boolean spbrush)
|
|||
#define MAXINVODDS ((MAXPROBABILITY * 2) * INVINDESPERATION)
|
||||
|
||||
// Odds value for Alt. Invin. to force itself on trailing players.
|
||||
#define INVFORCEODDS (3 * MAXINVODDS / 4)
|
||||
#define INVFORCEODDS (MAXINVODDS / 2)
|
||||
|
||||
static INT32 K_KartGetInvincibilityOdds(UINT32 dist)
|
||||
{
|
||||
|
|
@ -411,6 +487,47 @@ static INT32 K_KartGetInvincibilityOdds(UINT32 dist)
|
|||
return min(MAXINVODDS, finodds);
|
||||
}
|
||||
|
||||
// Assigns general cooldowns to shield items.
|
||||
void K_KartHandleShieldCooldown(SINT8 item)
|
||||
{
|
||||
INT32 i;
|
||||
|
||||
UINT8 pingame = 0, pexiting = 0;
|
||||
|
||||
INT32 shieldtype = KSHIELD_NONE;
|
||||
shieldtype = K_GetShieldFromItem(item);
|
||||
|
||||
if (shieldtype == KSHIELD_NONE)
|
||||
{
|
||||
// Not a shield!
|
||||
return;
|
||||
}
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
continue;
|
||||
|
||||
if (!(gametyperules & GTR_BUMPERS) || players[i].bumper)
|
||||
pingame++;
|
||||
|
||||
if (players[i].exiting)
|
||||
pexiting++;
|
||||
|
||||
if (((shieldtype == K_GetShieldFromItem(players[i].itemtype))
|
||||
|| (shieldtype == K_GetShieldFromPlayer(&players[i]))))
|
||||
{
|
||||
// If this shield has a cooldown, force-apply the cooldown preeemptively for
|
||||
// the entire time the shield is being held by a player.
|
||||
if (K_GetBGone(item, true) > 0)
|
||||
{
|
||||
K_SetBGoneToBase(item);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/** \brief Item Roulette for Kart
|
||||
|
||||
\param player player object passed from P_KartPlayerThink
|
||||
|
|
@ -674,9 +791,6 @@ INT32 K_KartGetItemOdds(
|
|||
break;
|
||||
case KITEM_HYUDORO:
|
||||
cooldownOnStart = true;
|
||||
|
||||
if (hyubgone > 0)
|
||||
newodds = 0;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
|
@ -688,7 +802,12 @@ INT32 K_KartGetItemOdds(
|
|||
return newodds;
|
||||
}
|
||||
|
||||
if ((indirectItem == true) && (indirectitemcooldown > 0))
|
||||
if (K_GetBGone(item, false) > 0)
|
||||
{
|
||||
// (Replaces hyubgone) This item is on cooldown; don't let it get rolled.
|
||||
newodds = 0;
|
||||
}
|
||||
else if ((indirectItem == true) && (indirectitemcooldown > 0))
|
||||
{
|
||||
// Too many items that act indirectly in a match can feel kind of bad.
|
||||
newodds = 0;
|
||||
|
|
|
|||
16
src/k_odds.h
16
src/k_odds.h
|
|
@ -36,6 +36,22 @@ extern "C" {
|
|||
|
||||
extern consvar_t *KartItemCVars[NUMKARTRESULTS-1];
|
||||
|
||||
// Goner; tracks how long an item should be "gone" for.
|
||||
// AKA a time-based cooldown so Hyudoro and whatever else piss off to prevent
|
||||
// spamming.
|
||||
|
||||
typedef enum goner_sect_e {
|
||||
GONER_BASECOOLDOWN = 0,
|
||||
GONER_CURRCOOLDOWN = 1,
|
||||
} goner_sect_t;
|
||||
|
||||
extern tic_t ItemBGone[NUMKARTRESULTS][2];
|
||||
|
||||
void K_SetBGone(SINT8 item, tic_t time);
|
||||
void K_SetBGoneToBase(SINT8 item);
|
||||
tic_t K_GetBGone(SINT8 item, boolean base);
|
||||
void K_KartHandleShieldCooldown(SINT8 item);
|
||||
|
||||
UINT32 K_CalculateInitalPDIS(const player_t *player, UINT8 pingame);
|
||||
UINT32 K_CalculatePDIS(const player_t *player, UINT8 numPlayers, boolean *spbrush);
|
||||
UINT8 K_FindUseodds(const player_t *player, fixed_t mashed, UINT32 pdis, UINT8 bestbumper, boolean spbrush);
|
||||
|
|
|
|||
|
|
@ -33,6 +33,7 @@
|
|||
#include "k_color.h"
|
||||
#include "k_hud.h"
|
||||
#include "k_waypoint.h"
|
||||
#include "k_odds.h"
|
||||
#include "d_netcmd.h" // IsPlayerAdmin
|
||||
#include "m_menu.h" // Player Setup menu color stuff
|
||||
#include "p_spec.h" // P_StartQuake
|
||||
|
|
@ -4110,10 +4111,48 @@ static int lib_kSetHyuCountdown(lua_State *L)
|
|||
{
|
||||
tic_t c = (tic_t)luaL_checkinteger(L, 1);
|
||||
NOHUD
|
||||
hyubgone = c;
|
||||
K_SetBGone(KITEM_HYUDORO, c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_kSetBGone(lua_State *L)
|
||||
{
|
||||
SINT8 item = (SINT8)luaL_checkinteger(L, 1);
|
||||
tic_t c = (tic_t)luaL_checkinteger(L, 2);
|
||||
NOHUD
|
||||
if (item < KITEM_SNEAKER || item > (NUMKARTRESULTS - 1))
|
||||
{
|
||||
luaL_error(L, "given item ID is outside bgone range");
|
||||
}
|
||||
K_SetBGone(item, c);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_kSetBGoneToBase(lua_State *L)
|
||||
{
|
||||
SINT8 item = (SINT8)luaL_checkinteger(L, 1);
|
||||
NOHUD
|
||||
if (item < KITEM_SNEAKER || item > (NUMKARTRESULTS - 1))
|
||||
{
|
||||
luaL_error(L, "given item ID is outside bgone range");
|
||||
}
|
||||
K_SetBGoneToBase(item);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int lib_kGetBGone(lua_State *L)
|
||||
{
|
||||
SINT8 item = (SINT8)luaL_checkinteger(L, 1);
|
||||
boolean base = lua_isnoneornil(L, 2) ? false : luaL_checkboolean(L, 2);
|
||||
NOHUD
|
||||
if (item < KITEM_SNEAKER || item > (NUMKARTRESULTS - 1))
|
||||
{
|
||||
luaL_error(L, "given item ID is outside bgone range");
|
||||
}
|
||||
lua_pushinteger(L, K_GetBGone(item, base));
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Checks if the floor closet floor under an object would be safe to respawn/land on.
|
||||
static int lib_kSafeRespawnPosition(lua_State *L)
|
||||
{
|
||||
|
|
@ -5302,6 +5341,9 @@ static luaL_Reg lib[] = {
|
|||
{"K_SetExitCountdown",lib_kSetExitCountdown},
|
||||
{"K_SetIndirectItemCooldown",lib_kSetIndirectItemCountdown},
|
||||
{"K_SetHyudoroCooldown",lib_kSetHyuCountdown},
|
||||
{"K_SetBGone", lib_kSetBGone},
|
||||
{"K_SetBGoneToBase", lib_kSetBGoneToBase},
|
||||
{"K_GetBGone", lib_kGetBGone},
|
||||
{"K_SafeRespawnPosition",lib_kSafeRespawnPosition},
|
||||
|
||||
{"K_GetCollideAngle",lib_kGetCollideAngle},
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@
|
|||
#include "p_slopes.h" // for P_SlopeById and slopelist
|
||||
#include "p_polyobj.h" // polyobj_t, PolyObjects
|
||||
#include "k_battle.h"
|
||||
#include "k_odds.h"
|
||||
#ifdef LUA_ALLOW_BYTECODE
|
||||
#include "d_netfil.h" // for LUA_DumpFile
|
||||
#endif
|
||||
|
|
@ -416,7 +417,7 @@ int LUA_PushGlobals(lua_State *L, const char *word)
|
|||
lua_pushinteger(L, invintype);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"hyubgone")) {
|
||||
lua_pushinteger(L, hyubgone);
|
||||
lua_pushinteger(L, K_GetBGone(KITEM_HYUDORO, false));
|
||||
return 1;
|
||||
} else if (fastcmp(word,"encoremode")) {
|
||||
lua_pushboolean(L, encoremode);
|
||||
|
|
@ -559,7 +560,9 @@ int LUA_WriteGlobals(lua_State *L, const char *word)
|
|||
else if (fastcmp(word,"indirectitemcooldown"))
|
||||
indirectitemcooldown = (tic_t)luaL_checkinteger(L, 2);
|
||||
else if (fastcmp(word,"hyubgone"))
|
||||
hyubgone = (tic_t)luaL_checkinteger(L, 2);
|
||||
{
|
||||
K_SetBGone(KITEM_HYUDORO, (tic_t)luaL_checkinteger(L, 2));
|
||||
}
|
||||
else if (fastcmp(word,"starttime"))
|
||||
starttime = (tic_t)luaL_checkinteger(L, 2);
|
||||
else if (fastcmp(word,"introtime"))
|
||||
|
|
|
|||
|
|
@ -41,6 +41,7 @@
|
|||
#include "k_battle.h"
|
||||
#include "k_pwrlv.h"
|
||||
#include "k_terrain.h"
|
||||
#include "k_odds.h"
|
||||
#include "acs/interface.h"
|
||||
#include "g_party.h"
|
||||
|
||||
|
|
@ -4260,7 +4261,14 @@ static boolean P_NetSyncMisc(savebuffer_t *save, boolean resending)
|
|||
|
||||
SYNC(wantedcalcdelay);
|
||||
SYNC(indirectitemcooldown);
|
||||
SYNC(hyubgone);
|
||||
|
||||
for (i = 0; i < NUMKARTRESULTS; i++)
|
||||
{
|
||||
// hyubgone
|
||||
//SYNC(ItemBGone[i][GONER_BASECOOLDOWN]);
|
||||
SYNC(ItemBGone[i][GONER_CURRCOOLDOWN]);
|
||||
}
|
||||
|
||||
SYNC(mapreset);
|
||||
|
||||
SYNC(spectateGriefed);
|
||||
|
|
|
|||
|
|
@ -103,6 +103,7 @@
|
|||
#include "k_terrain.h" // TRF_TRIPWIRE
|
||||
#include "k_brightmap.h"
|
||||
#include "k_director.h" // K_InitDirector
|
||||
#include "k_odds.h" // ItemBGone
|
||||
#include "acs/interface.h"
|
||||
#include "doomstat.h" // MAXMUSNAMES
|
||||
#include "k_mapuser.h"
|
||||
|
|
@ -8467,7 +8468,13 @@ static void P_InitGametype(void)
|
|||
|
||||
wantedcalcdelay = wantedfrequency*2;
|
||||
indirectitemcooldown = 0;
|
||||
hyubgone = 0;
|
||||
|
||||
for (i = 0; i < NUMKARTRESULTS; i++)
|
||||
{
|
||||
// hyubgone
|
||||
ItemBGone[i][GONER_CURRCOOLDOWN] = 0;
|
||||
}
|
||||
|
||||
mapreset = 0;
|
||||
|
||||
thwompsactive = false;
|
||||
|
|
|
|||
19
src/p_tick.c
19
src/p_tick.c
|
|
@ -41,6 +41,7 @@
|
|||
#include "k_director.h"
|
||||
#include "acs/interface.h"
|
||||
#include "k_bot.h" // K_BotTicker
|
||||
#include "k_odds.h" // ItemBGone
|
||||
|
||||
#ifdef PARANOIA
|
||||
#include "deh_tables.h" // MOBJTYPE_LIST
|
||||
|
|
@ -925,8 +926,22 @@ void P_Ticker(boolean run)
|
|||
if (indirectitemcooldown > 0)
|
||||
indirectitemcooldown--;
|
||||
|
||||
if (hyubgone > 0)
|
||||
hyubgone--;
|
||||
for (i = 0; i < NUMKARTRESULTS; i++)
|
||||
{
|
||||
// hyubgone
|
||||
if (K_GetBGone(i, false) > 0)
|
||||
{
|
||||
ItemBGone[i][GONER_CURRCOOLDOWN]--;
|
||||
}
|
||||
}
|
||||
|
||||
if (gametyperules & GTR_RACEODDS)
|
||||
{
|
||||
// Shield cooldowns
|
||||
K_KartHandleShieldCooldown(KITEM_THUNDERSHIELD);
|
||||
K_KartHandleShieldCooldown(KITEM_BUBBLESHIELD);
|
||||
K_KartHandleShieldCooldown(KITEM_FLAMESHIELD);
|
||||
}
|
||||
|
||||
K_BossInfoTicker();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue