stacking pt.3: start work on chaining
This commit is contained in:
parent
7091195a95
commit
f0b6ef89eb
11 changed files with 269 additions and 19 deletions
|
|
@ -152,6 +152,7 @@ static void KartComeback_OnChange(void);
|
|||
static void KartEliminateLast_OnChange(void);
|
||||
static void KartRings_OnChange(void);
|
||||
static void KartStacking_OnChange(void);
|
||||
static void KartChaining_OnChange(void);
|
||||
static void KartItemBreaker_OnChange(void);
|
||||
|
||||
static void Schedule_OnChange(void);
|
||||
|
|
@ -442,6 +443,7 @@ consvar_t cv_karteliminatelast = CVAR_INIT ("karteliminatelast", "Yes", CV_NETVA
|
|||
// Toggles for new features
|
||||
consvar_t cv_kartrings = CVAR_INIT ("kartrings", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartRings_OnChange);
|
||||
consvar_t cv_kartstacking = CVAR_INIT ("kartstacking", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartStacking_OnChange);
|
||||
consvar_t cv_kartchaining = CVAR_INIT ("kartchaining", "No", CV_NETVAR|CV_CALL|CV_NOINIT, CV_YesNo, KartChaining_OnChange);
|
||||
|
||||
consvar_t cv_kartitembreaker = CVAR_INIT ("kartitembreaker", "No", CV_NETVAR|CV_CHEAT|CV_CALL|CV_NOINIT, CV_YesNo, KartItemBreaker_OnChange);
|
||||
|
||||
|
|
@ -6943,11 +6945,11 @@ static void KartRings_OnChange(void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (cv_kartrings.value)
|
||||
if (!K_RingsActive() && cv_kartrings.value)
|
||||
{
|
||||
CONS_Printf(M_GetText("Rings will be turned \"On\" Next Round.\n"));
|
||||
}
|
||||
else
|
||||
else if (K_RingsActive() && !cv_kartrings.value)
|
||||
{
|
||||
CONS_Printf(M_GetText("Rings will be turned \"Off\" Next Round.\n"));
|
||||
}
|
||||
|
|
@ -6960,13 +6962,62 @@ static void KartStacking_OnChange(void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (cv_kartstacking.value)
|
||||
if (!stackingactive && cv_kartstacking.value)
|
||||
{
|
||||
CONS_Printf(M_GetText("Boost Stacking will be turned \"On\" Next Round.\n"));
|
||||
if (leveltime < starttime)
|
||||
{
|
||||
stackingactive = true;
|
||||
CONS_Printf(M_GetText("Boost Stacking has been turned \"On\".\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf(M_GetText("Boost Stacking will be turned \"On\" next round.\n"));
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (stackingactive && !cv_kartstacking.value)
|
||||
{
|
||||
CONS_Printf(M_GetText("Boost Stacking will be turned \"Off\" Next Round.\n"));
|
||||
if (leveltime < starttime)
|
||||
{
|
||||
stackingactive = false;
|
||||
CONS_Printf(M_GetText("Boost Stacking has been turned \"Off\".\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf(M_GetText("Boost Stacking will be turned \"Off\" next round.\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void KartChaining_OnChange(void)
|
||||
{
|
||||
if (K_CanChangeRules() == false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!chainingactive && cv_kartchaining.value)
|
||||
{
|
||||
if (leveltime < starttime)
|
||||
{
|
||||
chainingactive = true;
|
||||
CONS_Printf(M_GetText("Boost Chaining has been turned \"On\".\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf(M_GetText("Boost Chaining will be turned \"On\" Next Round.\n"));
|
||||
}
|
||||
}
|
||||
else if (chainingactive && !cv_kartstacking.value)
|
||||
{
|
||||
if (leveltime < starttime)
|
||||
{
|
||||
chainingactive = false;
|
||||
CONS_Printf(M_GetText("Boost Chaining has been turned \"Off\".\n"));
|
||||
}
|
||||
else
|
||||
{
|
||||
CONS_Printf(M_GetText("Boost Chaining will be turned \"Off\" next round.\n"));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -6977,11 +7028,16 @@ static void KartItemBreaker_OnChange(void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (cv_kartitembreaker.value)
|
||||
if (!multiplayer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!itembreaker && cv_kartitembreaker.value)
|
||||
{
|
||||
CONS_Printf(M_GetText("Singleplayer Item Breaker will be turned \"On\" Next Round.\n"));
|
||||
}
|
||||
else
|
||||
else if (itembreaker && !cv_kartitembreaker.value)
|
||||
{
|
||||
CONS_Printf(M_GetText("Singleplayer Item Breaker will be turned \"Off\" Next Round.\n"));
|
||||
}
|
||||
|
|
|
|||
|
|
@ -97,6 +97,7 @@ extern consvar_t cv_karteliminatelast;
|
|||
extern consvar_t cv_kartusepwrlv;
|
||||
extern consvar_t cv_kartrings;
|
||||
extern consvar_t cv_kartstacking;
|
||||
extern consvar_t cv_kartchaining;
|
||||
extern consvar_t cv_kartitembreaker;
|
||||
extern consvar_t cv_kartwalltransfer;
|
||||
extern consvar_t cv_kartpurpledrift;
|
||||
|
|
|
|||
|
|
@ -633,6 +633,7 @@ struct player_t
|
|||
|
||||
UINT16 sneakertimer; // Duration of a Sneaker Boost (from Sneakers or level boosters)
|
||||
UINT8 floorboost; // (0 to 3) - Prevents Sneaker sounds for a brief duration when triggered by a floor panel
|
||||
UINT16 chaintimer; // Stores current chain timer length.
|
||||
|
||||
UINT8 boostcharge; // Charge during race start
|
||||
|
||||
|
|
|
|||
138
src/k_kart.c
138
src/k_kart.c
|
|
@ -254,6 +254,7 @@ void K_RegisterKartStuff(void)
|
|||
|
||||
CV_RegisterVar(&cv_kartrings);
|
||||
CV_RegisterVar(&cv_kartstacking);
|
||||
CV_RegisterVar(&cv_kartchaining);
|
||||
CV_RegisterVar(&cv_kartitembreaker);
|
||||
|
||||
CV_RegisterVar(&cv_newspeedometer);
|
||||
|
|
@ -7007,6 +7008,101 @@ static void K_TireGreaseEffect(player_t *player)
|
|||
S_StartSound(player->mo, sfx_screec);
|
||||
}
|
||||
|
||||
boolean K_BoostChain(player_t *player, INT32 timer)
|
||||
{
|
||||
if (!chainingactive)
|
||||
{
|
||||
// You can't chain why bother?
|
||||
return false;
|
||||
}
|
||||
|
||||
if (timer > player->chaintimer)
|
||||
{
|
||||
// Just what I needed! - Toad
|
||||
player->chaintimer = timer;
|
||||
}
|
||||
|
||||
if (player->chaintimer)
|
||||
{
|
||||
// You can continue chaining!
|
||||
return true;
|
||||
}
|
||||
|
||||
// Aw shucks, time to drop the chain....
|
||||
return false;
|
||||
}
|
||||
|
||||
INT32 K_ChainOrDeincrementTime(player_t *player, INT32 timer, INT32 deincrement)
|
||||
{
|
||||
if (K_BoostChain(player, timer))
|
||||
{
|
||||
// Its time to chain.
|
||||
return max(1, timer - deincrement);
|
||||
}
|
||||
|
||||
// Continue to drain the timer as normal.
|
||||
return timer - deincrement;
|
||||
}
|
||||
|
||||
// Get the tic inverse sum using kartspeed, kartweight and your number of boosts.
|
||||
static INT32 ticinversesum(UINT8 kartspeed, UINT8 kartweight, UINT8 grade)
|
||||
{
|
||||
return (TICRATE / kartspeed) + (TICRATE / CLAMP(kartweight, 1, 5)) + grade;
|
||||
}
|
||||
|
||||
// Get the maximum required stacks needed for the ringnerf based on kartspeed and kartweight
|
||||
static INT32 statrangemap(UINT8 kartspeed, UINT8 kartweight)
|
||||
{
|
||||
INT32 scaledsw = (9 - kartspeed) + (9 - kartweight);
|
||||
|
||||
fixed_t scaled_input = (scaledsw)*FRACUNIT/16;
|
||||
|
||||
// Scale the result to be within range [2, 4]
|
||||
fixed_t result = 4*FRACUNIT - (FixedMul(scaled_input, 2*FRACUNIT));
|
||||
|
||||
// Stay within range please!
|
||||
if (result < 2*FRACUNIT)
|
||||
result = 2*FRACUNIT;
|
||||
if (result > 4*FRACUNIT)
|
||||
result = 4*FRACUNIT;
|
||||
|
||||
result = result >> FRACBITS;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static void K_HandleRingDeincrement(player_t *player, boolean chainnerf)
|
||||
{
|
||||
// Aggressively reduce extreme ringboost duration.
|
||||
// Less aggressive for accel types.
|
||||
UINT8 roller = TICRATE;
|
||||
UINT16 finalringtimer;
|
||||
roller += 4*(8-player->kartspeed);
|
||||
|
||||
finalringtimer = max((player->ringboost / roller), 1);
|
||||
|
||||
if (chainnerf)
|
||||
{
|
||||
UINT8 requiredgrade = statrangemap(player->kartspeed, player->kartweight);
|
||||
|
||||
if (player->numboosts >= requiredgrade)
|
||||
{
|
||||
INT32 insum = ticinversesum(player->kartspeed, player->kartweight, player->numboosts);
|
||||
INT32 subring = (player->ringboost*2)/insum;
|
||||
|
||||
if (player->kartspeed == 1)
|
||||
{
|
||||
// fuck off chao you aren't chaining an entire race.
|
||||
subring = (player->ringboost*4)/insum;
|
||||
}
|
||||
|
||||
finalringtimer -= subring;
|
||||
}
|
||||
}
|
||||
|
||||
player->ringboost = K_ChainOrDeincrementTime(player, player->ringboost, finalringtimer);
|
||||
}
|
||||
|
||||
/** \brief Decreases various kart timers and powers per frame. Called in P_PlayerThink in p_user.c
|
||||
|
||||
\param player player object passed from P_PlayerThink
|
||||
|
|
@ -7196,18 +7292,13 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
player->ringboost = 0;
|
||||
else if (player->ringboost)
|
||||
{
|
||||
// Aggressively reduce extreme ringboost duration.
|
||||
// Less aggressive for accel types.
|
||||
|
||||
UINT8 roller = TICRATE;
|
||||
roller += 4*(8-player->kartspeed);
|
||||
|
||||
player->ringboost -= max((player->ringboost / roller), 1);
|
||||
K_HandleRingDeincrement(player, chainingactive);
|
||||
}
|
||||
|
||||
if (player->sneakertimer)
|
||||
{
|
||||
player->sneakertimer--;
|
||||
player->sneakertimer = K_ChainOrDeincrementTime(player, player->sneakertimer, 1);
|
||||
|
||||
if (player->sneakertimer <= 0)
|
||||
{
|
||||
player->mo->flags2 &= ~MF2_WATERRUN;
|
||||
|
|
@ -7222,10 +7313,10 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
player->floorboost--;
|
||||
|
||||
if (player->driftboost)
|
||||
player->driftboost--;
|
||||
player->driftboost = K_ChainOrDeincrementTime(player, player->driftboost, 1);
|
||||
|
||||
if (player->startboost > 0)
|
||||
player->startboost--;
|
||||
player->startboost = K_ChainOrDeincrementTime(player, player->startboost, 1);
|
||||
|
||||
if (player->invincibilitytimer)
|
||||
player->invincibilitytimer--;
|
||||
|
|
@ -7324,7 +7415,10 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
player->outruntime--;
|
||||
|
||||
if (player->tiregrease > 0)
|
||||
player->tiregrease--;;
|
||||
player->tiregrease--;
|
||||
|
||||
if (player->chaintimer)
|
||||
player->chaintimer--;
|
||||
|
||||
if (player->itemblink && player->itemblink-- <= 0)
|
||||
{
|
||||
|
|
@ -10434,6 +10528,28 @@ boolean K_RingsActive(void)
|
|||
return true;
|
||||
}
|
||||
|
||||
boolean K_StackingActive(void)
|
||||
{
|
||||
if (stackingactive)
|
||||
{
|
||||
// Booststacking is enabled!
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean K_ChainingActive(void)
|
||||
{
|
||||
if (chainingactive)
|
||||
{
|
||||
// Boostchaining is enabled!
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
boolean K_UsingLegacyCheckpoints(void)
|
||||
{
|
||||
if (numbosswaypoints > 0)
|
||||
|
|
|
|||
|
|
@ -194,6 +194,8 @@ void K_UnsetItemOut(player_t *player);
|
|||
boolean K_SafeRespawnPosition(mobj_t * mo);
|
||||
|
||||
boolean K_RingsActive(void);
|
||||
boolean K_StackingActive(void);
|
||||
boolean K_ChainingActive(void);
|
||||
boolean K_UsingLegacyCheckpoints(void);
|
||||
|
||||
void K_UpdateMobjItemOverlay(mobj_t *part, SINT8 itemType, UINT8 itemCount);
|
||||
|
|
|
|||
|
|
@ -3985,6 +3985,20 @@ static int lib_kRingsActive(lua_State *L)
|
|||
return 1;
|
||||
}
|
||||
|
||||
// Checks if Stacking is active.
|
||||
static int lib_kStackingActive(lua_State *L)
|
||||
{
|
||||
lua_pushboolean(L, K_StackingActive());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Checks if Chaining is active.
|
||||
static int lib_kChainingActive(lua_State *L)
|
||||
{
|
||||
lua_pushboolean(L, K_ChainingActive());
|
||||
return 1;
|
||||
}
|
||||
|
||||
// Checks if current map is using legacy boss3 bassed checkpoints. Useful for map compat.
|
||||
static int lib_kUsingLegacyCheckpoints(lua_State *L)
|
||||
{
|
||||
|
|
@ -4317,6 +4331,8 @@ static luaL_Reg lib[] = {
|
|||
{"K_GetCollideAngle",lib_kGetCollideAngle},
|
||||
|
||||
{"K_RingsActive",lib_kRingsActive},
|
||||
{"K_StackingActive",lib_kStackingActive},
|
||||
{"K_ChainingActive",lib_kChainingActive},
|
||||
{"K_UsingLegacyCheckpoints",lib_kUsingLegacyCheckpoints},
|
||||
{"K_DoBoost",lib_kDoBoost},
|
||||
{"K_ClearBoost",lib_kClearBoost},
|
||||
|
|
|
|||
|
|
@ -229,6 +229,9 @@ enum player_e
|
|||
player_speedboost,
|
||||
player_accelboost,
|
||||
player_boostangle,
|
||||
player_boostinfo,
|
||||
player_numsneakers,
|
||||
player_numboosts,
|
||||
player_tripwireState,
|
||||
player_tripwirePass,
|
||||
player_tripwireLeniency,
|
||||
|
|
@ -261,6 +264,7 @@ enum player_e
|
|||
player_stolentimer,
|
||||
player_sneakertimer,
|
||||
player_floorboost,
|
||||
player_chaintimer,
|
||||
player_growshrinktimer,
|
||||
player_growcancel,
|
||||
player_squishedtimer,
|
||||
|
|
@ -398,6 +402,9 @@ static const char *const player_opt[] = {
|
|||
"speedboost",
|
||||
"accelboost",
|
||||
"boostangle",
|
||||
"boostinfo",
|
||||
"numsneakers",
|
||||
"numboosts",
|
||||
"tripwireState",
|
||||
"tripwirePass",
|
||||
"tripwireLeniency",
|
||||
|
|
@ -430,6 +437,7 @@ static const char *const player_opt[] = {
|
|||
"stolentimer",
|
||||
"sneakertimer",
|
||||
"floorboost",
|
||||
"chaintimer",
|
||||
"growshrinktimer",
|
||||
"growcancel",
|
||||
"squishedtimer",
|
||||
|
|
@ -699,6 +707,15 @@ static int player_get(lua_State *L)
|
|||
case player_boostangle:
|
||||
lua_pushangle(L, plr->boostangle);
|
||||
break;
|
||||
case player_boostinfo:
|
||||
luaL_error(L, "Don't directly read boostinfo. Use speedboost, accelboost and numboosts instead,\n");
|
||||
break;
|
||||
case player_numsneakers:
|
||||
lua_pushinteger(L, plr->numsneakers);
|
||||
break;
|
||||
case player_numboosts:
|
||||
lua_pushinteger(L, plr->numboosts);
|
||||
break;
|
||||
case player_tripwireState:
|
||||
lua_pushinteger(L, plr->tripwireState);
|
||||
break;
|
||||
|
|
@ -795,6 +812,9 @@ static int player_get(lua_State *L)
|
|||
case player_floorboost:
|
||||
lua_pushinteger(L, plr->floorboost);
|
||||
break;
|
||||
case player_chaintimer:
|
||||
lua_pushinteger(L, plr->chaintimer);
|
||||
break;
|
||||
case player_growshrinktimer:
|
||||
lua_pushinteger(L, plr->growshrinktimer);
|
||||
break;
|
||||
|
|
@ -1281,6 +1301,15 @@ static int player_set(lua_State *L)
|
|||
case player_boostangle:
|
||||
plr->boostangle = luaL_checkangle(L, 3);
|
||||
break;
|
||||
case player_boostinfo:
|
||||
NOSET;
|
||||
break;
|
||||
case player_numsneakers:
|
||||
plr->numsneakers = luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case player_numboosts:
|
||||
plr->numboosts = luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case player_tripwireState:
|
||||
plr->tripwireState = luaL_checkinteger(L, 3);
|
||||
break;
|
||||
|
|
@ -1377,6 +1406,9 @@ static int player_set(lua_State *L)
|
|||
case player_floorboost:
|
||||
plr->floorboost = luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case player_chaintimer:
|
||||
plr->chaintimer = luaL_checkinteger(L, 3);
|
||||
break;
|
||||
case player_growshrinktimer:
|
||||
plr->growshrinktimer = luaL_checkinteger(L, 3);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -360,6 +360,15 @@ int LUA_PushGlobals(lua_State *L, const char *word)
|
|||
} else if (fastcmp(word,"battleprisons")) {
|
||||
lua_pushinteger(L, itembreaker);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"ringsactive")) {
|
||||
lua_pushinteger(L, ringsactive);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"stackingactive")) {
|
||||
lua_pushinteger(L, stackingactive);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"chainingactive")) {
|
||||
lua_pushinteger(L, chainingactive);
|
||||
return 1;
|
||||
} else if (fastcmp(word,"hyubgone")) {
|
||||
lua_pushinteger(L, hyubgone);
|
||||
return 1;
|
||||
|
|
@ -481,6 +490,12 @@ int LUA_WriteGlobals(lua_State *L, const char *word)
|
|||
introtime = (tic_t)luaL_checkinteger(L, 2);
|
||||
else if (fastcmp(word,"itembreaker"))
|
||||
itembreaker = (boolean)luaL_checkinteger(L, 2);
|
||||
else if (fastcmp(word,"battleprisons"))
|
||||
itembreaker = (boolean)luaL_checkinteger(L, 2);
|
||||
else if (fastcmp(word,"chainingactive"))
|
||||
stackingactive = (boolean)luaL_checkinteger(L, 2);
|
||||
else if (fastcmp(word,"chainingactive"))
|
||||
chainingactive = (boolean)luaL_checkinteger(L, 2);
|
||||
else if (fastcmp(word,"gamespeed"))
|
||||
gamespeed = (UINT8)luaL_checkinteger(L, 2);
|
||||
else if (fastcmp(word,"nummapboxes"))
|
||||
|
|
|
|||
|
|
@ -579,6 +579,7 @@ extern INT32 numstarposts;
|
|||
extern INT32 numbosswaypoints;
|
||||
extern boolean ringsactive;
|
||||
extern boolean stackingactive;
|
||||
extern boolean chainingactive;
|
||||
extern UINT16 bossdisabled;
|
||||
extern boolean stoppedclock;
|
||||
|
||||
|
|
|
|||
|
|
@ -319,6 +319,7 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
|
||||
WRITEUINT16(save->p, players[i].sneakertimer);
|
||||
WRITEUINT8(save->p, players[i].floorboost);
|
||||
WRITEUINT16(save->p, players[i].chaintimer);
|
||||
|
||||
WRITEUINT8(save->p, players[i].boostcharge);
|
||||
|
||||
|
|
@ -631,6 +632,7 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
|
||||
players[i].sneakertimer = READUINT16(save->p);
|
||||
players[i].floorboost = READUINT8(save->p);
|
||||
players[i].chaintimer = READUINT16(save->p);
|
||||
|
||||
players[i].boostcharge = READUINT8(save->p);
|
||||
|
||||
|
|
@ -5084,6 +5086,7 @@ static void P_NetArchiveMisc(savebuffer_t *save, boolean resending)
|
|||
WRITEUINT16(save->p, bossdisabled);
|
||||
WRITEUINT8(save->p, ringsactive);
|
||||
WRITEUINT8(save->p, stackingactive);
|
||||
WRITEUINT8(save->p, chainingactive);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
|
|
@ -5254,6 +5257,7 @@ FUNCINLINE static ATTRINLINE boolean P_NetUnArchiveMisc(savebuffer_t *save, bool
|
|||
bossdisabled = READUINT16(save->p);
|
||||
ringsactive = READUINT8(save->p);
|
||||
stackingactive = READUINT8(save->p);
|
||||
chainingactive = READUINT8(save->p);
|
||||
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -144,6 +144,7 @@ INT32 numstarposts;
|
|||
INT32 numbosswaypoints;
|
||||
boolean ringsactive;
|
||||
boolean stackingactive;
|
||||
boolean chainingactive;
|
||||
UINT16 bossdisabled;
|
||||
boolean stoppedclock;
|
||||
boolean levelloading;
|
||||
|
|
@ -7889,6 +7890,11 @@ static void P_InitLevelSettings(boolean reloadinggamestate)
|
|||
else
|
||||
stackingactive = false;
|
||||
|
||||
if (cv_kartchaining.value)
|
||||
chainingactive = true;
|
||||
else
|
||||
chainingactive = false;
|
||||
|
||||
// emerald hunt
|
||||
hunt1 = hunt2 = hunt3 = NULL;
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue