Add toggle for legacy Invincibility

Also adds customizable time values for Alternative
This commit is contained in:
Anonimus 2025-06-03 13:33:59 -04:00
parent f2acaab98b
commit c07ccf475f
11 changed files with 157 additions and 70 deletions

View file

@ -186,6 +186,9 @@ extern CV_PossibleValue_t CV_Natural[];
#define KARTGP_MASTER 4 // Not a speed setting, gives hard speed with maxed out bots
#define KARTGP_NIGHTMARE 5 // Not a speed setting, gives expert speed with maxed out bots
extern CV_PossibleValue_t kartspeed_cons_t[];
// Invincibility types.
#define KARTINVIN_LEGACY 0
#define KARTINVIN_ALTERN 1
extern consvar_t cv_execversion;

View file

@ -154,6 +154,7 @@ static void KartStacking_OnChange(void);
static void KartChaining_OnChange(void);
static void KartSlipdash_OnChange(void);
static void KartItemBreaker_OnChange(void);
static void KartInvinType_OnChange(void);
static void Schedule_OnChange(void);
@ -462,8 +463,10 @@ consvar_t cv_kartstacking_sneaker_accelboost = CVAR_INIT ("vanillaboost_sneaker_
consvar_t cv_kartstacking_sneaker_maxgrade = CVAR_INIT ("vanillaboost_sneaker_maxgrade", "3", CV_NETVAR|CV_CHEAT, CV_Natural, NULL);
consvar_t cv_kartstacking_sneaker_stackable = CVAR_INIT ("vanillaboost_sneaker_stackable", "On", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_kartstacking_invincibility_speedboost = CVAR_INIT ("vanillaboost_invincibility_speedboost", "0.68", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_invincibility_accelboost = CVAR_INIT ("vanillaboost_invincibility_accelboost", "3.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_invincibility_legacyspeedboost = CVAR_INIT ("vanillaboost_invincibility_legacyspeedboost", "0.375", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_invincibility_legacyaccelboost = CVAR_INIT ("vanillaboost_invincibility_legacyaccelboost", "3.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_invincibility_alternatespeedboost = CVAR_INIT ("vanillaboost_invincibility_alternatespeedboost", "0.68", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_invincibility_alternateaccelboost = CVAR_INIT ("vanillaboost_invincibility_alternateaccelboost", "3.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartstacking_invincibility_stackable = CVAR_INIT ("vanillaboost_invincibility_stackable", "Off", CV_NETVAR, CV_OnOff, NULL);
consvar_t cv_kartstacking_grow_speedboost = CVAR_INIT ("vanillaboost_grow_speedboost", "0.2", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
@ -503,12 +506,19 @@ consvar_t cv_kartbumpspring = CVAR_INIT ("kartbumpspring", "No", CV_NETVAR, CV_Y
consvar_t cv_kartslipdash = CVAR_INIT ("kartslipdash", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartSlipdash_OnChange);
// Invincibility modifiers
static CV_PossibleValue_t invintype_cons_t[] = {{0, "Legacy"}, {1, "Alternative"}, {0, NULL}};
consvar_t cv_kartinvintype = CVAR_INIT ("kartinvintype", "Legacy", CV_NETVAR|CV_CALL, invintype_cons_t, KartInvinType_OnChange);
// How far the player must be from the cluster to begin frequently rolling Invincibility.
static CV_PossibleValue_t invindist_cons_t[] = {{1, "MIN"}, {32000, "MAX"}, {0, NULL}};
consvar_t cv_kartinvindist = CVAR_INIT ("kartinvindist", "8400", CV_NETVAR|CV_CHEAT, invindist_cons_t, NULL);
consvar_t cv_kartinvindistmul = CVAR_INIT ("kartinvindistmul", "0.54", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartinvin_maxtime = CVAR_INIT ("kartinvin_maxtime", "21.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
consvar_t cv_kartinvin_midtime = CVAR_INIT ("kartinvin_midtime", "14.0", CV_NETVAR|CV_CHEAT|CV_FLOAT, CV_Unsigned, NULL);
static CV_PossibleValue_t kartdebugitem_cons_t[] =
{
#define FOREACH( name, n ) { n, #name }
@ -7318,6 +7328,24 @@ static void KartItemBreaker_OnChange(void)
}
}
static void KartInvinType_OnChange(void)
{
if (K_CanChangeRules() == false)
{
return;
}
if (leveltime < starttime)
{
CONS_Printf(M_GetText("Invincibility type has been changed to \"%s\".\n"), cv_kartinvintype.string);
invintype = (UINT8)cv_kartinvintype.value;
}
else
{
CONS_Printf(M_GetText("Invincibility type will be changed to \"%s\" next round.\n"), cv_kartinvintype.string);
}
}
static void Schedule_OnChange(void)
{
size_t i;

View file

@ -138,8 +138,10 @@ extern consvar_t cv_kartstacking_sneaker_accelboost;
extern consvar_t cv_kartstacking_sneaker_maxgrade;
extern consvar_t cv_kartstacking_sneaker_stackable;
extern consvar_t cv_kartstacking_invincibility_speedboost;
extern consvar_t cv_kartstacking_invincibility_accelboost;
extern consvar_t cv_kartstacking_invincibility_legacyspeedboost;
extern consvar_t cv_kartstacking_invincibility_legacyaccelboost;
extern consvar_t cv_kartstacking_invincibility_alternatespeedboost;
extern consvar_t cv_kartstacking_invincibility_alternateaccelboost;
extern consvar_t cv_kartstacking_invincibility_stackable;
extern consvar_t cv_kartstacking_flame_speedval;
@ -171,8 +173,11 @@ extern consvar_t cv_kartpurpledrift;
extern consvar_t cv_kartbumpspark;
extern consvar_t cv_kartbumpspring;
extern consvar_t cv_kartslipdash;
extern consvar_t cv_kartinvintype;
extern consvar_t cv_kartinvindist;
extern consvar_t cv_kartinvindistmul;
extern consvar_t cv_kartinvin_maxtime;
extern consvar_t cv_kartinvin_midtime;
extern consvar_t cv_encorevotes;

View file

@ -664,6 +664,7 @@ extern INT32 cheats;
// SRB2kart
extern UINT8 numlaps;
extern UINT8 gamespeed;
extern UINT8 invintype;
extern boolean franticitems;
extern boolean encoremode, prevencoremode;
extern boolean comeback;

View file

@ -282,6 +282,7 @@ INT32 cheats; //for multiplayer cheat commands
// Cvars that we don't want changed mid-game
UINT8 numlaps; // Removed from Cvar hell
UINT8 gamespeed; // Game's current speed (or difficulty, or cc, or etc); 0 for easy, 1 for normal, 2 for hard
UINT8 invintype; // How Invincibility functions. 0 for Legacy/Vanilla, 1 for Alternative.
boolean encoremode = false; // Encore Mode currently enabled?
boolean prevencoremode;
boolean franticitems; // Frantic items currently enabled?

View file

@ -687,11 +687,6 @@ boolean K_SMKIceBlockCollide(mobj_t *t1, mobj_t *t2)
return false;
}
boolean K_CanInvincibilityDamage(UINT16 timer)
{
return (K_InvincibilityGradient(timer) > (FRACUNIT/2));
}
boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2)
{
const boolean flameT1 = ((t1->player->flamedash > 0) && (t1->player->flametimer > 0));
@ -700,8 +695,12 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2)
boolean t1Condition = false;
boolean t2Condition = false;
t1Condition = ((t1->player->invincibilitytimer > 0) && (K_CanInvincibilityDamage(t1->player->invincibilitytimer)));
t2Condition = ((t2->player->invincibilitytimer > 0) && (K_CanInvincibilityDamage(t2->player->invincibilitytimer)));
// Rim suggestion: Flipover damage is negligible at best, just cull it from Invincibility as a whole.
if (invintype == KARTINVIN_LEGACY)
{
t1Condition = (t1->player->invincibilitytimer > 0);
t2Condition = (t2->player->invincibilitytimer > 0);
}
if ((t1Condition == true || flameT1 == true) && (t2Condition == true || flameT2 == true))
{
@ -709,15 +708,18 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2)
K_DoInstashield(t2->player);
return false;
}
else if (t1Condition == true && t2Condition == false)
else if (invintype == KARTINVIN_LEGACY)
{
P_DamageMobj(t2, t1, t1, 1, DMG_FLIPOVER);
return true;
}
else if (t1Condition == false && t2Condition == true)
{
P_DamageMobj(t1, t2, t2, 1, DMG_FLIPOVER);
return true;
if (t1Condition == true && t2Condition == false)
{
P_DamageMobj(t2, t1, t1, 1, DMG_WIPEOUT);
return true;
}
else if (t1Condition == false && t2Condition == true)
{
P_DamageMobj(t1, t2, t2, 1, DMG_WIPEOUT);
return true;
}
}
t1Condition = (t1->scale > t2->scale + (mapobjectscale/8));

View file

@ -1873,7 +1873,7 @@ static boolean K_drawKartPositionFaces(void)
V_DrawMappedPatch(FACE_X, Y, V_HUDTRANS|V_SNAPTOLEFT, faceprefix[players[rankplayer[i]].skin][FACE_RANK], colormap);
if (players[rankplayer[i]].invincibilitytimer)
if ((players[rankplayer[i]].invincibilitytimer) && (invintype == KARTINVIN_ALTERN))
{
colormap = R_GetTranslationColormap(TC_RAINBOW, K_RainbowColor(leveltime / 2), GTC_CACHE);
invinchudtrans = K_InvincibilityHUDVisibility(players[rankplayer[i]].invincibilitytimer);
@ -3657,7 +3657,7 @@ static void K_drawKartMinimap(void)
colorizeplayer = players[i].mo->colorized;
if ((players[i].invincibilitytimer) && (K_InvincibilityGradient(players[i].invincibilitytimer) > (FRACUNIT/2)))
if ((players[i].invincibilitytimer) && ((K_InvincibilityGradient(players[i].invincibilitytimer) > (FRACUNIT/2)) || (invintype == KARTINVIN_LEGACY)))
{
usecolor = (K_RainbowColor(leveltime / 2));
colorizeplayer = true;
@ -3820,7 +3820,9 @@ static void K_drawKartMinimap(void)
colorizeplayer = players[localplayers[i]].mo->colorized;
if ((players[localplayers[i]].invincibilitytimer) && (K_InvincibilityGradient(players[localplayers[i]].invincibilitytimer) > (FRACUNIT/2)))
if ((players[localplayers[i]].invincibilitytimer) &&
((K_InvincibilityGradient(players[localplayers[i]].invincibilitytimer) >
(FRACUNIT / 2)) || (invintype == KARTINVIN_LEGACY)))
{
usecolor = (K_RainbowColor(leveltime / 2));
colorizeplayer = true;

View file

@ -312,8 +312,10 @@ void K_RegisterKartStuff(void)
CV_RegisterVar(&cv_kartstacking_sneaker_maxgrade);
CV_RegisterVar(&cv_kartstacking_sneaker_stackable);
CV_RegisterVar(&cv_kartstacking_invincibility_speedboost);
CV_RegisterVar(&cv_kartstacking_invincibility_accelboost);
CV_RegisterVar(&cv_kartstacking_invincibility_legacyspeedboost);
CV_RegisterVar(&cv_kartstacking_invincibility_legacyaccelboost);
CV_RegisterVar(&cv_kartstacking_invincibility_alternatespeedboost);
CV_RegisterVar(&cv_kartstacking_invincibility_alternateaccelboost);
CV_RegisterVar(&cv_kartstacking_invincibility_stackable);
CV_RegisterVar(&cv_kartstacking_grow_speedboost);
@ -352,9 +354,13 @@ void K_RegisterKartStuff(void)
CV_RegisterVar(&cv_kartslipdash);
CV_RegisterVar(&cv_kartinvintype);
CV_RegisterVar(&cv_kartinvindist);
CV_RegisterVar(&cv_kartinvindistmul);
CV_RegisterVar(&cv_kartinvin_maxtime);
CV_RegisterVar(&cv_kartinvin_midtime);
CV_RegisterVar(&cv_kartdriftsounds);
CV_RegisterVar(&cv_kartdriftefx);
CV_RegisterVar(&cv_driftsparkpulse);
@ -874,16 +880,19 @@ INT32 K_KartGetItemOdds(
notNearEnd = true;
break;
case KITEM_INVINCIBILITY:
// It's a power item, yes, but we don't want mashing to lessen
// its chances, so we lie to the game's face.
// Nonetheless, apply the start cooldown.
cooldownOnStart = true;
if (invintype == KARTINVIN_ALTERN)
{
// It's a power item, yes, but we don't want mashing to lessen
// its chances, so we lie to the game's face.
// Nonetheless, apply the start cooldown.
cooldownOnStart = true;
// Unique odds for Invincibility.
newodds = K_KartGetInvincibilityOdds(clusterDist);
newodds *= 4;
break;
// Unique odds for Invincibility.
newodds = K_KartGetInvincibilityOdds(clusterDist);
newodds *= 4;
break;
}
case KITEM_MINE:
case KITEM_GROW:
case KITEM_BUBBLESHIELD:
@ -1074,16 +1083,19 @@ INT32 K_KartGetLegacyItemOdds(UINT8 pos, SINT8 item, fixed_t clusterDist, fixed_
powerItem = true;
break;
case KITEM_INVINCIBILITY:
// It's a power item, yes, but we don't want mashing to lessen
// its chances, so we lie to the game's face.
// Nonetheless, apply the start cooldown.
cooldownOnStart = true;
if (invintype == KARTINVIN_ALTERN)
{
// It's a power item, yes, but we don't want mashing to lessen
// its chances, so we lie to the game's face.
// Nonetheless, apply the start cooldown.
cooldownOnStart = true;
// Unique odds for Invincibility.
newodds = K_KartGetInvincibilityOdds(clusterDist);
newodds *= 4;
break;
// Unique odds for Invincibility.
newodds = K_KartGetInvincibilityOdds(clusterDist);
newodds *= 4;
break;
}
case KITEM_MINE:
case KITEM_GROW:
case KITEM_BUBBLESHIELD:
@ -3640,10 +3652,10 @@ static fixed_t K_InvincibilityEasing(fixed_t x)
u = max(0, (u - FRACUNIT));
if (u < FRACUNIT)
return Easing_InCubic(u, FRACUNIT, 22 * FRACUNIT / 10);
return Easing_InCubic(u, FRACUNIT, (INVINMIDTIME/10));
return Easing_OutCubic(
min(FRACUNIT, FixedMul(u - FRACUNIT, FRACUNIT/4)), 22 * FRACUNIT / 10, 4 * FRACUNIT);
min(FRACUNIT, FixedMul(u - FRACUNIT, FRACUNIT/4)), (INVINMIDTIME/10), (INVINMAXTIME/10));
}
@ -3651,6 +3663,9 @@ UINT16 K_GetInvincibilityTime(player_t *player)
{
UINT32 i, pingame;
if (invintype == KARTINVIN_LEGACY)
return BASEINVINTIME;
pingame = 0;
for (i = 0; i < MAXPLAYERS; i++)
{
@ -3673,14 +3688,20 @@ UINT16 K_GetInvincibilityTime(player_t *player)
static fixed_t K_GetInvincibilitySpeed(UINT16 time)
{
if (invintype == KARTINVIN_LEGACY)
return INVINSPEEDBOOSTLGC;
fixed_t t = min(FRACUNIT, K_InvincibilityGradient(time));
return Easing_OutCubic(t, 0, INVINSPEEDBOOST);
return Easing_OutCubic(t, 0, INVINSPEEDBOOSTALT);
}
static fixed_t K_GetInvincibilityAccel(UINT16 time)
{
if (invintype == KARTINVIN_LEGACY)
return INVINACCELBOOSTLGC;
fixed_t t = min(FRACUNIT, K_InvincibilityGradient(time));
return Easing_OutCubic(t, 0, INVINACCELBOOST);
return Easing_OutCubic(t, 0, INVINACCELBOOSTALT);
}
static fixed_t diminish(fixed_t speedboost)
@ -5925,16 +5946,29 @@ void K_DoInvincibility(player_t *player, tic_t time)
overlay->destscale = player->mo->scale;
P_SetScale(overlay, player->mo->scale);
mobj_t *aura = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_OVERLAY);
P_SetTarget(&aura->target, player->mo);
aura->destscale = player->mo->scale;
P_SetScale(aura, player->mo->scale);
aura->extravalue2 = 1;
if (invintype == KARTINVIN_ALTERN)
{
mobj_t *aura = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z, MT_OVERLAY);
P_SetTarget(&aura->target, player->mo);
aura->destscale = player->mo->scale;
P_SetScale(aura, player->mo->scale);
aura->extravalue2 = 1;
}
}
// Don't punish a player for spamming.
// That sounds stupid, yes.
player->invincibilitytimer = max(player->invincibilitytimer, time);
if (invintype == KARTINVIN_ALTERN)
{
// Rim suggestion: Don't allow already invincible players to chain.
if (K_InvincibilityGradient(player->invincibilitytimer) < (FRACUNIT/2))
{
// Be nice to players at half-power or less.
player->invincibilitytimer = max(player->invincibilitytimer, time);
}
}
else
{
player->invincibilitytimer = time;
}
if (P_IsLocalPlayer(player) == true)
{
@ -7782,7 +7816,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
player->startboost = K_ChainOrDeincrementTime(player, player->startboost, 1, false);
if (player->invincibilitytimer)
{
{
player->invincibilitytimer--;
}
@ -8091,11 +8125,15 @@ void K_KartResetPlayerColor(player_t *player)
{
boolean skip = false;
//fullbright = true;
if (invintype == KARTINVIN_LEGACY)
{
fullbright = true;
// player->mo->color = K_RainbowColor(leveltime / 2);
// player->mo->colorized = true;
skip = true;
player->mo->color = K_RainbowColor(leveltime / 2);
player->mo->colorized = true;
skip = true;
}
if (skip)
{

View file

@ -71,6 +71,12 @@ extern vector3_t clusterpoint, clusterdtf;
// :)
#define MAXODDS 8
// Invincibility-related constants
#define INVINDIST K_RAGuard(cv_kartinvindist)
#define INVINDISTMUL K_RAGuard(cv_kartinvindistmul)
#define INVINMIDTIME K_RAGuard(cv_kartinvin_midtime)
#define INVINMAXTIME K_RAGuard(cv_kartinvin_maxtime)
// Precalculated constants for stacked boost diminishing
// *Somewhat* matches old calc but doesn't use arrays, which makes it faster and more memory efficent
#define DIMINISHPARAM K_RAGuard(cv_kartstacking_diminishparam)
@ -87,10 +93,10 @@ extern vector3_t clusterpoint, clusterdtf;
#define SNEAKERACCELBOOST K_RAGuard(cv_kartstacking_sneaker_accelboost)
#define MAXSNEAKERSTACK K_RAGuard(cv_kartstacking_sneaker_maxgrade)
#define SNEAKERSTACKABLE K_RAGuard(cv_kartstacking_sneaker_stackable)
#define INVINDIST K_RAGuard(cv_kartinvindist)
#define INVINDISTMUL K_RAGuard(cv_kartinvindistmul)
#define INVINSPEEDBOOST K_RAGuard(cv_kartstacking_invincibility_speedboost)
#define INVINACCELBOOST K_RAGuard(cv_kartstacking_invincibility_accelboost)
#define INVINSPEEDBOOSTLGC K_RAGuard(cv_kartstacking_invincibility_legacyspeedboost)
#define INVINACCELBOOSTLGC K_RAGuard(cv_kartstacking_invincibility_legacyaccelboost)
#define INVINSPEEDBOOSTALT K_RAGuard(cv_kartstacking_invincibility_alternatespeedboost)
#define INVINACCELBOOSTALT K_RAGuard(cv_kartstacking_invincibility_alternateaccelboost)
#define INVINSTACKABLE K_RAGuard(cv_kartstacking_invincibility_stackable)
#define GROWSPEEDBOOST K_RAGuard(cv_kartstacking_grow_speedboost)
#define GROWACCELBOOST K_RAGuard(cv_kartstacking_grow_accelboost)

View file

@ -7961,6 +7961,8 @@ static void P_InitLevelSettings(boolean reloadinggamestate)
if (cv_kartslipdash.value)
slipdashactive = true;
invintype = (UINT8)cv_kartinvintype.value;
// emerald hunt
hunt1 = hunt2 = hunt3 = NULL;

View file

@ -2242,13 +2242,12 @@ void P_MovePlayer(player_t *player)
K_SpawnBoostTrail(player);
if ((player->invincibilitytimer > 0) &&
((leveltime % max(1,
10 - FixedMul(9,
K_InvincibilityGradient(
player->invincibilitytimer)))) == 0))
{
K_SpawnSparkleTrail(player->mo);
}
(((leveltime %
max(1, 10 - FixedMul(9, K_InvincibilityGradient(player->invincibilitytimer)))) == 0) ||
(invintype == KARTINVIN_LEGACY)))
{
K_SpawnSparkleTrail(player->mo);
}
if (player->wipeoutslow > 1 && (leveltime & 1))
K_SpawnWipeoutTrail(player->mo, false);