mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-04-05 01:38:13 +00:00
Merge branch 'master' into ufo-master-difficulty
This commit is contained in:
commit
1286579457
47 changed files with 1008 additions and 251 deletions
|
|
@ -3738,8 +3738,6 @@ static void Got_AddPlayer(const UINT8 **p, INT32 playernum)
|
|||
|
||||
CONS_Debug(DBG_NETPLAY, "addplayer: %d %d\n", node, newplayernum);
|
||||
|
||||
//G_SpectatePlayerOnJoin(newplayernum); -- caused desyncs in this spot :(
|
||||
|
||||
if (newplayernum+1 > doomcom->numslots)
|
||||
doomcom->numslots = (INT16)(newplayernum+1);
|
||||
|
||||
|
|
@ -3793,6 +3791,13 @@ static void Got_AddPlayer(const UINT8 **p, INT32 playernum)
|
|||
players[newplayernum].splitscreenindex = splitscreenplayer;
|
||||
players[newplayernum].bot = false;
|
||||
|
||||
// Previously called at the top of this function, commented as
|
||||
// "caused desyncs in this spot :(". But we can't do this in
|
||||
// G_PlayerReborn, since that only runs for level contexts and
|
||||
// allows people to party-crash the vote screen even when
|
||||
// maxplayers is too low for them. Let's try it here...?
|
||||
G_SpectatePlayerOnJoin(newplayernum);
|
||||
|
||||
if (node == mynode && splitscreenplayer == 0)
|
||||
S_AttemptToRestoreMusic(); // Earliest viable point
|
||||
|
||||
|
|
@ -5397,7 +5402,7 @@ static void FuzzTiccmd(ticcmd_t* target)
|
|||
{
|
||||
target->buttons |= BT_ACCELERATE;
|
||||
target->buttons &= ~BT_LOOKBACK;
|
||||
target->buttons &= ~BT_RESPAWN;
|
||||
target->buttons &= ~BT_BAIL;
|
||||
target->buttons &= ~BT_BRAKE;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -135,11 +135,12 @@ typedef enum
|
|||
|
||||
typedef enum
|
||||
{
|
||||
PF2_SELFMUTE = 1<<1,
|
||||
PF2_SELFDEAFEN = 1<<2,
|
||||
PF2_SERVERMUTE = 1<<3,
|
||||
PF2_SERVERDEAFEN = 1<<4,
|
||||
PF2_STRICTFASTFALL = 1<<5,
|
||||
PF2_SELFMUTE = 1<<1,
|
||||
PF2_SELFDEAFEN = 1<<2,
|
||||
PF2_SERVERMUTE = 1<<3,
|
||||
PF2_SERVERDEAFEN = 1<<4,
|
||||
PF2_STRICTFASTFALL = 1<<5,
|
||||
PF2_ALWAYSDAMAGED = 1<<6,
|
||||
} pflags2_t;
|
||||
|
||||
typedef enum
|
||||
|
|
@ -430,6 +431,8 @@ struct botvars_t
|
|||
tic_t rouletteTimeout; // If it takes too long to decide, try lowering priority until we find something valid.
|
||||
|
||||
angle_t predictionError; // How bad is our momentum angle relative to where we're trying to go?
|
||||
angle_t recentDeflection; // How long have we been going straight? (See k_bot.h)
|
||||
angle_t lastAngle;
|
||||
};
|
||||
|
||||
// player_t struct for round-specific condition tracking
|
||||
|
|
@ -738,7 +741,7 @@ struct player_t
|
|||
UINT8 tumbleBounces;
|
||||
UINT16 tumbleHeight; // In *mobjscaled* fracunits, or mfu, not raw fu
|
||||
UINT16 stunned; // Number of tics during which rings cannot be picked up
|
||||
UINT8 stunnedCombo; // Number of hits sustained while stunned, reduces consecutive stun penalties
|
||||
mobj_t *flybot; // One Flybot767 circling the player while stunned
|
||||
UINT8 justDI; // Turn-lockout timer to briefly prevent unintended turning after DI, resets when actionable or no input
|
||||
boolean flipDI; // Bananas flip the DI direction. Was a bug, but it made bananas much more interesting.
|
||||
|
||||
|
|
@ -1079,6 +1082,10 @@ struct player_t
|
|||
UINT16 progressivethrust; // When getting beat up in GTR_BUMPERS, speed up the longer you've been out of control.
|
||||
UINT8 ringvisualwarning; // Check with > 1, not >= 1! Set when put in debt, counts down and holds at 1 when still in debt.
|
||||
|
||||
UINT32 bailcharge;
|
||||
UINT32 baildrop;
|
||||
boolean bailquake;
|
||||
|
||||
boolean analoginput; // Has an input been recorded that requires analog usage? For input display.
|
||||
|
||||
boolean markedfordeath;
|
||||
|
|
|
|||
|
|
@ -32,12 +32,13 @@ typedef enum
|
|||
BT_BRAKE = 1<<3, // Brake
|
||||
BT_ATTACK = 1<<4, // Use Item
|
||||
BT_LOOKBACK = 1<<5, // Look Backward
|
||||
BT_RESPAWN = 1<<6, // Respawn
|
||||
BT_BAIL = 1<<6, // Bail
|
||||
BT_VOTE = 1<<7, // Vote
|
||||
BT_SPINDASH = 1<<8, // Spindash
|
||||
|
||||
BT_EBRAKEMASK = (BT_ACCELERATE|BT_BRAKE),
|
||||
BT_SPINDASHMASK = (BT_ACCELERATE|BT_BRAKE|BT_DRIFT),
|
||||
BT_RESPAWNMASK = (BT_EBRAKEMASK|BT_BAIL),
|
||||
|
||||
// free: 1<<9 to 1<<12
|
||||
|
||||
|
|
|
|||
|
|
@ -1574,6 +1574,13 @@ const char *const STATE_LIST[] = { // array length left dynamic for sanity testi
|
|||
"S_BLOCKRING",
|
||||
"S_BLOCKBODY",
|
||||
|
||||
"S_BAIL",
|
||||
"S_BAIB1",
|
||||
"S_BAIB2",
|
||||
"S_BAIB3",
|
||||
"S_BAIC",
|
||||
"S_BAILCHARGE",
|
||||
|
||||
"S_AMPRING",
|
||||
"S_AMPBODY",
|
||||
"S_AMPAURA",
|
||||
|
|
@ -3564,6 +3571,10 @@ const char *const MOBJTYPE_LIST[] = { // array length left dynamic for sanity t
|
|||
"MT_BLOCKRING",
|
||||
"MT_BLOCKBODY",
|
||||
|
||||
"MT_BAIL",
|
||||
"MT_BAILCHARGE",
|
||||
"MT_BAILSPARKLE",
|
||||
|
||||
"MT_AMPRING",
|
||||
"MT_AMPBODY",
|
||||
"MT_AMPAURA",
|
||||
|
|
@ -5048,11 +5059,12 @@ struct int_const_s const INT_CONST[] = {
|
|||
{"BT_BRAKE",BT_BRAKE},
|
||||
{"BT_ATTACK",BT_ATTACK},
|
||||
{"BT_LOOKBACK",BT_LOOKBACK},
|
||||
{"BT_RESPAWN",BT_RESPAWN},
|
||||
{"BT_BAIL",BT_BAIL},
|
||||
{"BT_VOTE",BT_VOTE},
|
||||
{"BT_SPINDASH",BT_SPINDASH}, // Real button now, but triggers the macro same as always.
|
||||
{"BT_EBRAKEMASK",BT_EBRAKEMASK}, // Macro button
|
||||
{"BT_SPINDASHMASK",BT_SPINDASHMASK}, // Macro button
|
||||
{"BT_RESPAWNMASK",BT_RESPAWNMASK}, // Macro button
|
||||
{"BT_LUAA",BT_LUAA}, // Lua customizable
|
||||
{"BT_LUAB",BT_LUAB}, // Lua customizable
|
||||
{"BT_LUAC",BT_LUAC}, // Lua customizable
|
||||
|
|
|
|||
|
|
@ -747,9 +747,9 @@ extern int
|
|||
// Exp
|
||||
#define EXP_STABLERATE 3*FRACUNIT/10 // how low is your placement before losing XP? 4*FRACUNIT/10 = top 40% of race will gain
|
||||
#define EXP_POWER 3*FRACUNIT/100 // adjust to change overall xp volatility
|
||||
#define MINEXP 25 // The min value target
|
||||
#define TARGETEXP 120 // Used for grading ...
|
||||
#define MAXEXP 120 // The max value displayed by the hud and in the tally screen and GP results screen
|
||||
#define EXP_MIN 25 // The min value target
|
||||
#define EXP_TARGET 120 // Used for grading ...
|
||||
#define EXP_MAX 120 // The max value displayed by the hud and in the tally screen and GP results screen
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
|
|
|
|||
|
|
@ -198,6 +198,8 @@ typedef enum
|
|||
GRADE_S
|
||||
} gp_rank_e;
|
||||
|
||||
#define SEALED_STAR_ENTRY (370*FRACUNIT/400)
|
||||
|
||||
struct cupwindata_t
|
||||
{
|
||||
UINT8 best_placement;
|
||||
|
|
|
|||
|
|
@ -404,10 +404,7 @@ class TiccmdBuilder
|
|||
map(gc_item, BT_ATTACK); // fire
|
||||
|
||||
map(gc_lookback, BT_LOOKBACK); // rear view
|
||||
if (!modeattacking)
|
||||
{
|
||||
map(gc_respawn, BT_RESPAWN | (freecam() ? 0 : BT_EBRAKEMASK)); // respawn
|
||||
}
|
||||
map(gc_bail, BT_BAIL); // bail
|
||||
map(gc_vote, BT_VOTE); // mp general function button
|
||||
|
||||
// lua buttons a thru c
|
||||
|
|
|
|||
|
|
@ -2313,7 +2313,8 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
|
|||
jointime = players[player].jointime;
|
||||
if (jointime <= 1)
|
||||
{
|
||||
G_SpectatePlayerOnJoin(player);
|
||||
// Now called in Got_AddPlayer. In case of weirdness, break glass.
|
||||
// G_SpectatePlayerOnJoin(player);
|
||||
betweenmaps = true;
|
||||
}
|
||||
|
||||
|
|
@ -4381,7 +4382,7 @@ void G_GetNextMap(void)
|
|||
&& grandprixinfo.gamespeed >= KARTSPEED_NORMAL)
|
||||
{
|
||||
// On A rank pace? Then you get a chance for S rank!
|
||||
permitrank = (K_CalculateGPGrade(&grandprixinfo.rank) >= GRADE_A);
|
||||
permitrank = (K_CalculateGPPercent(&grandprixinfo.rank) >= SEALED_STAR_ENTRY);
|
||||
|
||||
// If you're on Master, a win floats you to rank-restricted levels for free.
|
||||
// (This is a different class of challenge!)
|
||||
|
|
|
|||
|
|
@ -123,7 +123,7 @@ typedef enum
|
|||
gc_lookback = gc_b,
|
||||
gc_spindash = gc_c,
|
||||
gc_brake = gc_x,
|
||||
gc_respawn = gc_y,
|
||||
gc_bail = gc_y,
|
||||
gc_vote = gc_z,
|
||||
gc_item = gc_l,
|
||||
gc_drift = gc_r,
|
||||
|
|
|
|||
|
|
@ -113,7 +113,7 @@ void K_DrawInputDisplay(float x, float y, INT32 flags, char mode, UINT8 pid, boo
|
|||
box.patch(but('B', gc_b, BT_LOOKBACK));
|
||||
box.patch(but('C', gc_c, BT_SPINDASH));
|
||||
box.patch(but('X', gc_x, BT_BRAKE));
|
||||
box.patch(but('Y', gc_y, BT_RESPAWN));
|
||||
box.patch(but('Y', gc_y, BT_BAIL));
|
||||
box.patch(but('Z', gc_z, BT_VOTE));
|
||||
box.patch(but('L', gc_l, BT_ATTACK));
|
||||
box.patch(but('R', gc_r, BT_DRIFT));
|
||||
|
|
|
|||
|
|
@ -198,7 +198,7 @@ void K_drawSpectatorHUD(boolean director)
|
|||
}
|
||||
else
|
||||
{
|
||||
bool press = D_LocalTiccmd(viewnum)->buttons & BT_RESPAWN;
|
||||
bool press = D_LocalTiccmd(viewnum)->buttons & BT_BAIL;
|
||||
const char* label = (press && I_GetTime() % 16 < 8) ? "> <" : ">< ";
|
||||
|
||||
list.insert({{label, press ? "<y_pressed>" : "<y>"}, {"Exit", "<c_animated>"}});
|
||||
|
|
|
|||
96
src/info.c
96
src/info.c
|
|
@ -334,6 +334,11 @@ char sprnames[NUMSPRITES + 1][5] =
|
|||
"GRNG", // Guard ring
|
||||
"GBDY", // Guard body
|
||||
|
||||
"BAIL", // Bail charge
|
||||
"BAIB", // Bail after effect
|
||||
"BAIC", // Bail sparkle
|
||||
"TECH", // Bail tech charge
|
||||
|
||||
"TRC1", // Charge aura
|
||||
"TRC2", // Charge fall
|
||||
"TRC3", // Charge flicker/sparks
|
||||
|
|
@ -2160,6 +2165,16 @@ state_t states[NUMSTATES] =
|
|||
{SPR_GRNG, FF_FULLBRIGHT|FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_BLOCKRING
|
||||
{SPR_GBDY, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_BLOCKBODY
|
||||
|
||||
// why can we not use actions on spawn? I'd love to fix it but I imagine all sorts of crazy pain if I change something fundamental like that
|
||||
{SPR_BAIL, FF_FULLBRIGHT|FF_ANIMATE|0, 9, {NULL}, 8, 1, S_BAIB1}, // S_BAIL
|
||||
{SPR_BAIB, 0, 0, {A_PlaySound}, sfx_gshb2, 2, S_BAIB2}, // S_BAIB1
|
||||
{SPR_BAIB, 0, 0, {A_PlaySound}, sfx_gshbd, 2, S_BAIB3}, // S_BAIB2
|
||||
{SPR_BAIB, FF_FULLBRIGHT|FF_ANIMATE|0, 10, {NULL}, 9, 1, S_NULL}, // S_BAIB3
|
||||
|
||||
{SPR_BAIC, FF_FULLBRIGHT|FF_ANIMATE|0, 11, {NULL}, 10, 1, S_NULL}, // S_BAIC
|
||||
|
||||
{SPR_TECH, 1, -1, {NULL}, 41, 1, S_NULL}, // S_BAILCHARGE
|
||||
|
||||
{SPR_AMPB, FF_FULLBRIGHT|FF_PAPERSPRITE|0, -1, {NULL}, 0, 0, S_NULL}, // S_AMPRING
|
||||
{SPR_AMPC, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_AMPBODY
|
||||
{SPR_AMPD, FF_FULLBRIGHT|FF_ANIMATE|0, -1, {NULL}, 4, 2, S_NULL}, // S_AMPAURA
|
||||
|
|
@ -13745,6 +13760,87 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_BAIL
|
||||
-1, // doomednum
|
||||
S_BAIL, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
67*FRACUNIT, // radius
|
||||
67*FRACUNIT, // height
|
||||
1, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_BAILCHARGE
|
||||
-1, // doomednum
|
||||
S_BAILCHARGE, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
67*FRACUNIT, // radius
|
||||
67*FRACUNIT, // height
|
||||
1, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_DONTENCOREMAP, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_BAILSPARKLE
|
||||
-1, // doomednum
|
||||
S_BAIC, // spawnstate
|
||||
1000, // spawnhealth
|
||||
S_NULL, // seestate
|
||||
sfx_None, // seesound
|
||||
0, // reactiontime
|
||||
sfx_None, // attacksound
|
||||
S_NULL, // painstate
|
||||
0, // painchance
|
||||
sfx_None, // painsound
|
||||
S_NULL, // meleestate
|
||||
S_NULL, // missilestate
|
||||
S_NULL, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_None, // deathsound
|
||||
0, // speed
|
||||
67*FRACUNIT, // radius
|
||||
67*FRACUNIT, // height
|
||||
1, // display offset
|
||||
100, // mass
|
||||
0, // damage
|
||||
sfx_None, // activesound
|
||||
MF_NOGRAVITY|MF_NOCLIPHEIGHT|MF_NOCLIPTHING|MF_DONTENCOREMAP|MF_SCENERY, // flags
|
||||
S_NULL // raisestate
|
||||
},
|
||||
|
||||
{ // MT_AMPRING
|
||||
-1, // doomednum
|
||||
S_AMPRING, // spawnstate
|
||||
|
|
|
|||
16
src/info.h
16
src/info.h
|
|
@ -875,6 +875,11 @@ typedef enum sprite
|
|||
SPR_GRNG, // Guard ring
|
||||
SPR_GBDY, // Guard body
|
||||
|
||||
SPR_BAIL, // Bail charge
|
||||
SPR_BAIB, // Bail after effect
|
||||
SPR_BAIC, // Bail sparkle
|
||||
SPR_TECH, // Bail tech charge
|
||||
|
||||
SPR_TRC1, // Charge aura
|
||||
SPR_TRC2, // Charge fall
|
||||
SPR_TRC3, // Charge flicker/sparks
|
||||
|
|
@ -2629,6 +2634,13 @@ typedef enum state
|
|||
S_BLOCKRING,
|
||||
S_BLOCKBODY,
|
||||
|
||||
S_BAIL,
|
||||
S_BAIB1,
|
||||
S_BAIB2,
|
||||
S_BAIB3,
|
||||
S_BAIC,
|
||||
S_BAILCHARGE,
|
||||
|
||||
S_AMPRING,
|
||||
S_AMPBODY,
|
||||
S_AMPAURA,
|
||||
|
|
@ -4646,6 +4658,10 @@ typedef enum mobj_type
|
|||
MT_BLOCKRING,
|
||||
MT_BLOCKBODY,
|
||||
|
||||
MT_BAIL,
|
||||
MT_BAILCHARGE,
|
||||
MT_BAILSPARKLE,
|
||||
|
||||
MT_AMPRING,
|
||||
MT_AMPBODY,
|
||||
MT_AMPAURA,
|
||||
|
|
|
|||
|
|
@ -586,7 +586,7 @@ const botcontroller_t *K_GetBotController(const mobj_t *mobj)
|
|||
fixed_t K_BotMapModifier(void)
|
||||
{
|
||||
// fuck it we ball
|
||||
// return 10*FRACUNIT/10;
|
||||
return 5*FRACUNIT/10;
|
||||
|
||||
constexpr INT32 complexity_scale = 10000;
|
||||
fixed_t modifier_max = (10 * FRACUNIT / 10) - FRACUNIT;
|
||||
|
|
@ -690,9 +690,9 @@ fixed_t K_BotRubberband(const player_t *player)
|
|||
|
||||
// Allow the status quo to assert itself a bit. Bots get most of their speed from their
|
||||
// mechanics adjustments, not from items, so kill some bot speed if they've got bad EXP.
|
||||
if (player->gradingfactor < FRACUNIT && !(player->botvars.rival))
|
||||
if (player->gradingfactor < FRACUNIT && !(player->botvars.rival) && player->botvars.difficulty > 1)
|
||||
{
|
||||
UINT8 levelreduce = 3; // How much to drop the "effective level" of bots that are consistently behind
|
||||
UINT8 levelreduce = std::min<UINT8>(3, player->botvars.difficulty); // How much to drop the "effective level" of bots that are consistently behind
|
||||
expreduce = Easing_Linear((K_EffectiveGradingFactor(player) - MINGRADINGFACTOR) * 2, levelreduce*FRACUNIT, 0);
|
||||
}
|
||||
|
||||
|
|
@ -823,12 +823,23 @@ fixed_t K_BotRubberband(const player_t *player)
|
|||
fixed_t K_UpdateRubberband(player_t *player)
|
||||
{
|
||||
fixed_t dest = K_BotRubberband(player);
|
||||
|
||||
fixed_t deflect = player->botvars.recentDeflection;
|
||||
if (deflect > BOTMAXDEFLECTION)
|
||||
deflect = BOTMAXDEFLECTION;
|
||||
|
||||
dest = FixedMul(dest, Easing_Linear(
|
||||
FixedDiv(deflect, BOTMAXDEFLECTION),
|
||||
BOTSTRAIGHTSPEED,
|
||||
BOTTURNSPEED
|
||||
));
|
||||
|
||||
fixed_t ret = player->botvars.rubberband;
|
||||
|
||||
UINT8 ease_soften = 8;
|
||||
UINT8 ease_soften = (ret > dest) ? 3 : 8;
|
||||
|
||||
if (player->botvars.bumpslow && dest > ret)
|
||||
ease_soften *= 10;
|
||||
ease_soften = 80;
|
||||
|
||||
// Ease into the new value.
|
||||
ret += (dest - player->botvars.rubberband) / ease_soften;
|
||||
|
|
@ -1792,7 +1803,7 @@ static void K_BuildBotTiccmdNormal(player_t *player, ticcmd_t *cmd)
|
|||
if (K_TryRingShooter(player, botController) == true && player->botvars.respawnconfirm >= BOTRESPAWNCONFIRM)
|
||||
{
|
||||
// We want to respawn. Simply hold Y and stop here!
|
||||
cmd->buttons |= (BT_RESPAWN | BT_EBRAKEMASK);
|
||||
cmd->buttons |= BT_RESPAWNMASK;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -2123,6 +2134,21 @@ void K_UpdateBotGameplayVars(player_t *player)
|
|||
}
|
||||
}
|
||||
|
||||
angle_t mangle = K_MomentumAngleEx(player->mo, 5*mapobjectscale); // magic threshold
|
||||
angle_t langle = player->botvars.lastAngle;
|
||||
angle_t dangle = 0;
|
||||
if (mangle >= langle)
|
||||
dangle = mangle - langle;
|
||||
else
|
||||
dangle = langle - mangle;
|
||||
// Writing this made me move my tongue around in my mouth
|
||||
|
||||
UINT32 smo = BOTANGLESAMPLES - 1;
|
||||
|
||||
player->botvars.recentDeflection = (smo * player->botvars.recentDeflection / BOTANGLESAMPLES) + (dangle / BOTANGLESAMPLES);
|
||||
|
||||
player->botvars.lastAngle = mangle;
|
||||
|
||||
const botcontroller_t *botController = K_GetBotController(player->mo);
|
||||
if (K_TryRingShooter(player, botController) == true)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ extern "C" {
|
|||
|
||||
// How many tics in a row do you need to turn in this direction before we'll let you turn.
|
||||
// Made it as small as possible without making it look like the bots are twitching constantly.
|
||||
#define BOTTURNCONFIRM 4
|
||||
#define BOTTURNCONFIRM 1
|
||||
|
||||
// How many tics with only one spindash-viable condition before we'll let you spindash.
|
||||
#define BOTSPINDASHCONFIRM (4*TICRATE)
|
||||
|
|
@ -46,6 +46,11 @@ extern "C" {
|
|||
// How long it takes for a Lv.1 bot to decide to pick an item.
|
||||
#define BOT_ITEM_DECISION_TIME (2*TICRATE)
|
||||
|
||||
#define BOTSTRAIGHTSPEED (80*FRACUNIT/100) // How fast we move when at 0 deflection.
|
||||
#define BOTTURNSPEED (100*FRACUNIT/100) // How fast we move when at MAXDEFLECTION deflection.
|
||||
#define BOTANGLESAMPLES (TICRATE) // Time period to average over. Higher values produce lower peaks that last longer.
|
||||
#define BOTMAXDEFLECTION (ANG1*3) // Measured in "degrees per tic" here, use debugbots.
|
||||
|
||||
// Point for bots to aim for
|
||||
struct botprediction_t
|
||||
{
|
||||
|
|
|
|||
|
|
@ -885,18 +885,28 @@ boolean K_BubbleShieldCollide(mobj_t *t1, mobj_t *t2)
|
|||
thing = oldthing;
|
||||
P_SetTarget(&g_tm.thing, oldg_tm.thing);*/
|
||||
|
||||
boolean hit = false;
|
||||
|
||||
if (K_KartBouncing(t2, t1->target) == true)
|
||||
{
|
||||
if (t2->player && t1->target && t1->target->player)
|
||||
{
|
||||
K_PvPTouchDamage(t2, t1->target);
|
||||
hit = K_PvPTouchDamage(t2, t1->target);
|
||||
}
|
||||
|
||||
// Don't play from t1 else it gets cut out... for some reason.
|
||||
S_StartSound(t2, sfx_s3k44);
|
||||
}
|
||||
|
||||
return true;
|
||||
if (hit && (gametyperules & GTR_BUMPERS))
|
||||
{
|
||||
K_PopBubbleShield(t1->target->player);
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (K_BubbleShieldCanReflect(t1, t2))
|
||||
|
|
@ -1158,6 +1168,27 @@ boolean K_PvPTouchDamage(mobj_t *t1, mobj_t *t2)
|
|||
return false;
|
||||
}
|
||||
|
||||
|
||||
boolean guard1 = K_PlayerGuard(t1->player);
|
||||
boolean guard2 = K_PlayerGuard(t2->player);
|
||||
|
||||
// Bubble Shield physically extends past guard when inflated,
|
||||
// makes some sense to suppress this behavior
|
||||
if (t1->player->bubbleblowup)
|
||||
guard1 = false;
|
||||
if (t2->player->bubbleblowup)
|
||||
guard2 = false;
|
||||
|
||||
if (guard1 && guard2)
|
||||
K_DoPowerClash(t1, t2);
|
||||
else if (guard1)
|
||||
K_DoGuardBreak(t1, t2);
|
||||
else if (guard2)
|
||||
K_DoGuardBreak(t2, t1);
|
||||
|
||||
if (guard1 || guard2)
|
||||
return false;
|
||||
|
||||
// Clash instead of damage if both parties have any of these conditions
|
||||
auto canClash = [](mobj_t *t1, mobj_t *t2)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -546,7 +546,7 @@ void K_HandleFollower(player_t *player)
|
|||
}
|
||||
|
||||
// Sal: Turn the follower around when looking backwards.
|
||||
if ( player->cmd.buttons & BT_LOOKBACK )
|
||||
if (K_GetKartButtons(player) & BT_LOOKBACK)
|
||||
{
|
||||
destAngle += ANGLE_180;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,6 +34,9 @@ void K_AddHitLag(mobj_t *mo, INT32 tics, boolean fromDamage)
|
|||
return;
|
||||
}
|
||||
|
||||
if (mo->player && mo->player->overshield)
|
||||
tics = min(tics, 3);
|
||||
|
||||
mo->hitlag += tics;
|
||||
mo->hitlag = min(mo->hitlag, MAXHITLAGTICS);
|
||||
|
||||
|
|
|
|||
|
|
@ -4876,7 +4876,7 @@ static void K_drawKartPlayerCheck(void)
|
|||
return;
|
||||
}
|
||||
|
||||
if (stplyr->cmd.buttons & BT_LOOKBACK)
|
||||
if (K_GetKartButtons(stplyr) & BT_LOOKBACK)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
|
@ -7095,7 +7095,8 @@ static void K_DrawBotDebugger(void)
|
|||
V_DrawSmallString(8, 66, 0, va("Complexity: %d", K_GetTrackComplexity()));
|
||||
V_DrawSmallString(8, 70, 0, va("Bot modifier: %.2f", FixedToFloat(K_BotMapModifier())));
|
||||
|
||||
V_DrawSmallString(8, 76, 0, va("Prediction error: %d", bot->botvars.predictionError));
|
||||
V_DrawSmallString(8, 76, 0, va("Prediction error: %.2fdeg", FIXED_TO_FLOAT(FixedDiv(bot->botvars.predictionError, ANG1))));
|
||||
V_DrawSmallString(8, 80, 0, va("Recent deflection: %.2fdeg", FIXED_TO_FLOAT(FixedDiv(bot->botvars.recentDeflection, ANG1))));
|
||||
}
|
||||
|
||||
static void K_DrawGPRankDebugger(void)
|
||||
|
|
@ -7119,6 +7120,7 @@ static void K_DrawGPRankDebugger(void)
|
|||
}
|
||||
|
||||
grade = K_CalculateGPGrade(&grandprixinfo.rank);
|
||||
fixed_t percent = K_CalculateGPPercent(&grandprixinfo.rank);
|
||||
|
||||
V_DrawThinString(0, 0, V_SNAPTOTOP|V_SNAPTOLEFT,
|
||||
va("POS: %d / %d", grandprixinfo.rank.position, RANK_NEUTRAL_POSITION));
|
||||
|
|
@ -7132,6 +7134,8 @@ static void K_DrawGPRankDebugger(void)
|
|||
va("RINGS: %d / %d", grandprixinfo.rank.rings, grandprixinfo.rank.totalRings));
|
||||
V_DrawThinString(0, 60, V_SNAPTOTOP|V_SNAPTOLEFT,
|
||||
va("EMERALD: %s", (grandprixinfo.rank.specialWon == true) ? "YES" : "NO"));
|
||||
V_DrawThinString(0, 70, V_SNAPTOTOP|V_SNAPTOLEFT,
|
||||
va("PERCENT: %.2f", FixedToFloat(percent)));
|
||||
|
||||
switch (grade)
|
||||
{
|
||||
|
|
@ -7517,7 +7521,7 @@ void K_drawKartHUD(void)
|
|||
if (ta)
|
||||
{
|
||||
using srb2::Draw;
|
||||
Draw::TextElement text = Draw::TextElement().parse("<y> Restart");
|
||||
Draw::TextElement text = Draw::TextElement().parse("<z> Restart");
|
||||
Draw(BASEVIDWIDTH - 19, 2)
|
||||
.flags(flags | V_YELLOWMAP)
|
||||
.align(Draw::Align::kRight)
|
||||
|
|
|
|||
480
src/k_kart.c
480
src/k_kart.c
|
|
@ -72,13 +72,17 @@
|
|||
// comeback is Battle Mode's karma comeback, also bool
|
||||
// mapreset is set when enough players fill an empty server
|
||||
|
||||
static void K_PopBubbleShield(player_t *player)
|
||||
void K_PopBubbleShield(player_t *player)
|
||||
{
|
||||
if (player->curshield != KSHIELD_BUBBLE)
|
||||
return;
|
||||
|
||||
S_StartSound(player->mo, sfx_kc31);
|
||||
K_StripItems(player);
|
||||
K_AddHitLag(player->mo, 4, false);
|
||||
vector3_t offset = { 0, 0, 0 };
|
||||
K_SpawnSingleHitLagSpark(player->mo, &offset, player->mo->scale*2, 4, 0, player->skincolor);
|
||||
K_SpawnSingleHitLagSpark(player->mo, &offset, player->mo->scale*2, 4, 0, player->skincolor);
|
||||
player->bubbledrag = false;
|
||||
}
|
||||
|
||||
boolean K_ThunderDome(void)
|
||||
|
|
@ -1179,20 +1183,6 @@ boolean K_KartBouncing(mobj_t *mobj1, mobj_t *mobj2)
|
|||
|
||||
K_SpawnBumpForObjs(mobj1, mobj2);
|
||||
|
||||
if (mobj1->type == MT_PLAYER && mobj2->type == MT_PLAYER
|
||||
&& !mobj1->player->powerupVFXTimer && !mobj2->player->powerupVFXTimer)
|
||||
{
|
||||
boolean guard1 = K_PlayerGuard(mobj1->player);
|
||||
boolean guard2 = K_PlayerGuard(mobj2->player);
|
||||
|
||||
if (guard1 && guard2)
|
||||
K_DoPowerClash(mobj1, mobj2);
|
||||
else if (guard1)
|
||||
K_DoGuardBreak(mobj1, mobj2);
|
||||
else if (guard2)
|
||||
K_DoGuardBreak(mobj2, mobj1);
|
||||
}
|
||||
|
||||
K_PlayerJustBumped(mobj1->player);
|
||||
K_PlayerJustBumped(mobj2->player);
|
||||
|
||||
|
|
@ -1607,13 +1597,16 @@ static boolean K_TryDraft(player_t *player, mobj_t *dest, fixed_t minDist, fixed
|
|||
// How much this increments every tic biases toward acceleration! (min speed gets 1.5% per tic, max speed gets 0.5% per tic)
|
||||
if (player->draftpower < FRACUNIT)
|
||||
{
|
||||
fixed_t add = (FRACUNIT/200) + ((9 - player->kartspeed) * ((3*FRACUNIT)/1600));;
|
||||
fixed_t add = (FRACUNIT/200) + ((9 - player->kartspeed) * ((3*FRACUNIT)/1600));
|
||||
player->draftpower += add;
|
||||
|
||||
if (player->bot && (player->botvars.rival || cv_levelskull.value))
|
||||
if (player->bot)
|
||||
{
|
||||
// Double speed for the rival!
|
||||
player->draftpower += add;
|
||||
if (player->botvars.rival || cv_levelskull.value)
|
||||
player->draftpower += add;
|
||||
else if (dest->player->bot) // Reduce bot gluts.
|
||||
player->draftpower -= 3*add/4;
|
||||
}
|
||||
|
||||
if (gametyperules & GTR_CLOSERPLAYERS)
|
||||
|
|
@ -4066,8 +4059,16 @@ boolean K_KartKickstart(const player_t *player)
|
|||
|
||||
UINT16 K_GetKartButtons(const player_t *player)
|
||||
{
|
||||
return (player->cmd.buttons |
|
||||
(K_KartKickstart(player) ? BT_ACCELERATE : 0));
|
||||
UINT16 buttons = player->cmd.buttons;
|
||||
if ((buttons & BT_RESPAWNMASK) == BT_RESPAWNMASK)
|
||||
{
|
||||
buttons &= ~BT_LOOKBACK;
|
||||
}
|
||||
if (K_KartKickstart(player))
|
||||
{
|
||||
buttons = buttons | BT_ACCELERATE;
|
||||
}
|
||||
return buttons;
|
||||
}
|
||||
|
||||
SINT8 K_GetForwardMove(const player_t *player)
|
||||
|
|
@ -4553,12 +4554,16 @@ void K_DoPowerClash(mobj_t *t1, mobj_t *t2) {
|
|||
UINT8 lag1 = 5;
|
||||
UINT8 lag2 = 5;
|
||||
|
||||
boolean stripbubble = (gametyperules & GTR_BUMPERS);
|
||||
|
||||
// short-circuit instashield for vfx visibility
|
||||
if (t1->player)
|
||||
{
|
||||
t1->player->instashield = 1;
|
||||
t1->player->speedpunt += 20;
|
||||
lag1 -= min(lag1, t1->player->speedpunt/10);
|
||||
if (stripbubble && t1->player->curshield == KSHIELD_BUBBLE)
|
||||
K_PopBubbleShield(t1->player);
|
||||
}
|
||||
|
||||
if (t2->player)
|
||||
|
|
@ -4566,6 +4571,8 @@ void K_DoPowerClash(mobj_t *t1, mobj_t *t2) {
|
|||
t2->player->instashield = 1;
|
||||
t2->player->speedpunt += 20;
|
||||
lag2 -= min(lag1, t2->player->speedpunt/10);
|
||||
if (stripbubble && t2->player->curshield == KSHIELD_BUBBLE)
|
||||
K_PopBubbleShield(t2->player);
|
||||
}
|
||||
|
||||
S_StartSound(t1, sfx_parry);
|
||||
|
|
@ -4603,7 +4610,9 @@ void K_DoGuardBreak(mobj_t *t1, mobj_t *t2) {
|
|||
angle_t thrangle = R_PointToAngle2(t2->x, t2->y, t1->x, t1->y);
|
||||
P_Thrust(t1, thrangle, 7*mapobjectscale);
|
||||
|
||||
t1->player->pflags2 |= PF2_ALWAYSDAMAGED;
|
||||
P_DamageMobj(t1, t2, t2, 1, DMG_TUMBLE);
|
||||
t1->player->pflags2 &= ~PF2_ALWAYSDAMAGED;
|
||||
|
||||
clash = P_SpawnMobj((t1->x/2) + (t2->x/2), (t1->y/2) + (t2->y/2), (t1->z/2) + (t2->z/2), MT_GUARDBREAK);
|
||||
|
||||
|
|
@ -5180,6 +5189,8 @@ void K_UpdateWavedashIndicator(player_t *player)
|
|||
{
|
||||
mobj_t *mobj = NULL;
|
||||
|
||||
player->vortexBoost = 0;
|
||||
|
||||
if (player == NULL)
|
||||
{
|
||||
return;
|
||||
|
|
@ -5193,7 +5204,6 @@ void K_UpdateWavedashIndicator(player_t *player)
|
|||
if (player->wavedashIndicator == NULL || P_MobjWasRemoved(player->wavedashIndicator) == true)
|
||||
{
|
||||
K_InitWavedashIndicator(player);
|
||||
player->vortexBoost = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
@ -7768,6 +7778,30 @@ void K_PopPlayerShield(player_t *player)
|
|||
K_UnsetItemOut(player);
|
||||
}
|
||||
|
||||
static void K_DeleteHnextList(player_t *player)
|
||||
{
|
||||
mobj_t *work = player->mo, *nextwork;
|
||||
|
||||
if (work == NULL || P_MobjWasRemoved(work))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
nextwork = work->hnext;
|
||||
|
||||
while ((work = nextwork) && !(work == NULL || P_MobjWasRemoved(work)))
|
||||
{
|
||||
nextwork = work->hnext;
|
||||
|
||||
if (!work->health)
|
||||
continue; // taking care of itself
|
||||
|
||||
K_SpawnLandMineExplosion(work, player->skincolor, player->mo->hitlag);
|
||||
|
||||
P_RemoveMobj(work);
|
||||
}
|
||||
}
|
||||
|
||||
void K_DropHnextList(player_t *player)
|
||||
{
|
||||
mobj_t *work = player->mo, *nextwork, *dropwork;
|
||||
|
|
@ -9734,23 +9768,12 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
&& P_IsObjectOnGround(player->mo)
|
||||
)
|
||||
{
|
||||
// MEGA FUCKING HACK BECAUSE P_SAVEG MOBJS ARE FULL
|
||||
// Would updating player_saveflags to 32 bits have any negative consequences?
|
||||
// For now, player->stunned 16th bit is a flag to determine whether the flybots were spawned
|
||||
|
||||
// timer counts down at triple speed while spindashing
|
||||
player->stunned = (player->stunned & 0x8000) | max(0, (player->stunned & 0x7FFF) - (player->spindash ? 3 : 1));
|
||||
player->stunned = max(0, player->stunned - (player->spindash ? 3 : 1));
|
||||
|
||||
// when timer reaches 0, reset the flag and stun combo counter
|
||||
if ((player->stunned & 0x7FFF) == 0)
|
||||
// if the flybots aren't spawned, spawn them now!
|
||||
if (player->stunned != 0 && P_MobjWasRemoved(player->flybot))
|
||||
{
|
||||
player->stunned = 0;
|
||||
player->stunnedCombo = 0;
|
||||
}
|
||||
// otherwise if the flybots aren't spawned, spawn them now!
|
||||
else if ((player->stunned & 0x8000) == 0)
|
||||
{
|
||||
player->stunned |= 0x8000;
|
||||
Obj_SpawnFlybotsForPlayer(player);
|
||||
}
|
||||
}
|
||||
|
|
@ -9785,7 +9808,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
|
||||
// UINT16 oldringboost = player->ringboost;
|
||||
|
||||
if (player->superring == 0 || player->stunned)
|
||||
if (!player->baildrop && (player->superring == 0 || player->stunned))
|
||||
player->ringboost -= max((player->ringboost / roller), 1);
|
||||
else if (K_LegacyRingboost(player))
|
||||
player->ringboost--;
|
||||
|
|
@ -9976,6 +9999,51 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
}
|
||||
}
|
||||
|
||||
if (player->baildrop)
|
||||
{
|
||||
if (player->stunned & 0x8000)
|
||||
player->stunned = 0x8000 | BAILSTUN;
|
||||
else
|
||||
player->stunned = BAILSTUN;
|
||||
|
||||
mobj_t *pmo = player->mo;
|
||||
// particle spawn
|
||||
#define BAILSPARKLE_MAXBAIL 61 // amount of bail rings needed for max sparkle spawn frequency
|
||||
UINT32 baildropinversefreq = BAILSPARKLE_MAXBAIL - min(player->baildrop, BAILSPARKLE_MAXBAIL-6);
|
||||
UINT32 baildropmodulo = baildropinversefreq *5/3 /10;
|
||||
if ((leveltime % (1+baildropmodulo)) == 0)
|
||||
{
|
||||
mobj_t *sparkle = P_SpawnMobj(pmo->x + (P_RandomRange(PR_DECORATION, -40,40) * pmo->scale),
|
||||
pmo->y + (P_RandomRange(PR_DECORATION, -40,40) * pmo->scale),
|
||||
pmo->z + (pmo->height/2) + (P_RandomRange(PR_DECORATION, -40,40) * pmo->scale),
|
||||
MT_BAILSPARKLE);
|
||||
|
||||
sparkle->scale = pmo->scale;
|
||||
sparkle->angle = pmo->angle;
|
||||
sparkle->momx = 3*pmo->momx/4;
|
||||
sparkle->momy = 3*pmo->momy/4;
|
||||
sparkle->momz = 3*P_GetMobjZMovement(pmo)/4;
|
||||
K_MatchGenericExtraFlags(sparkle, pmo);
|
||||
sparkle->renderflags = (pmo->renderflags & ~RF_TRANSMASK);//|RF_TRANS20|RF_ADD;
|
||||
}
|
||||
|
||||
if ((player->baildrop % BAIL_DROPFREQUENCY) == 0)
|
||||
{
|
||||
P_FlingBurst(player, K_MomentumAngle(pmo), MT_FLINGRING, 10*TICRATE, FRACUNIT, player->baildrop/BAIL_DROPFREQUENCY);
|
||||
S_StartSound(pmo, sfx_gshad);
|
||||
}
|
||||
|
||||
player->baildrop--;
|
||||
if (player->baildrop == 0)
|
||||
player->ringboost /= 3;
|
||||
}
|
||||
|
||||
if (player->bailquake && !player->mo->hitlag) // quake as soon as we leave hitlag
|
||||
{
|
||||
P_StartQuakeFromMobj(7, 50 * player->mo->scale, 2048 * player->mo->scale, player->mo);
|
||||
player->bailquake = false;
|
||||
}
|
||||
|
||||
// The precise ordering of start-of-level made me want to cut my head off,
|
||||
// so let's try this instead. Whatever!
|
||||
if (leveltime <= starttime || player->gradingpointnum == 0)
|
||||
|
|
@ -10057,7 +10125,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
K_RemoveGrowShrink(player);
|
||||
}
|
||||
|
||||
if (player->respawn.state != RESPAWNST_MOVE && (player->cmd.buttons & BT_RESPAWN) == BT_RESPAWN)
|
||||
if (player->respawn.state != RESPAWNST_MOVE && (player->cmd.buttons & BT_RESPAWNMASK) == BT_RESPAWNMASK)
|
||||
{
|
||||
player->finalfailsafe++; // Decremented by ringshooter to "freeze" this timer
|
||||
// Part-way through the auto-respawn timer, you can tap Ring Shooter to respawn early
|
||||
|
|
@ -10143,7 +10211,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
|
||||
if (player->nextringaward >= ringrate)
|
||||
{
|
||||
if (player->instaWhipCharge)
|
||||
if (player->instaWhipCharge || player->baildrop || player->bailcharge)
|
||||
{
|
||||
// Store award rings to do diabolical horseshit with later.
|
||||
player->nextringaward = ringrate;
|
||||
|
|
@ -10309,6 +10377,8 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
|
|||
if (player->powerupVFXTimer > 0)
|
||||
{
|
||||
player->powerupVFXTimer--;
|
||||
if (player->powerupVFXTimer == 0)
|
||||
player->mo->flags &= ~MF_NOCLIPTHING;
|
||||
}
|
||||
|
||||
if (player->dotrickfx && !player->mo->hitlag)
|
||||
|
|
@ -13883,6 +13953,106 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
}
|
||||
|
||||
|
||||
if ((player->cmd.buttons & BT_BAIL) && (player->cmd.buttons & BT_RESPAWNMASK) != BT_RESPAWNMASK && ((player->itemtype && player->itemamount) || (player->rings > 0) || player->superring > 0 || player->pickuprings > 0 || player->itemRoulette.active))
|
||||
{
|
||||
boolean grounded = P_IsObjectOnGround(player->mo);
|
||||
onground && player->tumbleBounces == 0 ? player->bailcharge += 2 : player->bailcharge++; // charge twice as fast on the ground
|
||||
if ((P_PlayerInPain(player) && player->bailcharge == 1) || (grounded && P_PlayerInPain(player) && player->bailcharge == 2)) // this is brittle ..
|
||||
{
|
||||
mobj_t *bail = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_BAILCHARGE);
|
||||
S_StartSound(bail, sfx_gshb9); // I tried to use info.c, but you can't play sounds on mobjspawn via A_PlaySound
|
||||
S_StartSound(bail, sfx_kc4e);
|
||||
P_SetTarget(&bail->target, player->mo);
|
||||
bail->renderflags |= RF_FULLBRIGHT; // set fullbright here, were gonna animate frames in the thinker and it saves us from setting FF_FULLBRIGHT every frame
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
player->bailcharge = 0;
|
||||
}
|
||||
|
||||
if ((!P_PlayerInPain(player) && player->bailcharge >= 5) || player->bailcharge >= BAIL_MAXCHARGE)
|
||||
{
|
||||
player->bailcharge = 0;
|
||||
|
||||
mobj_t *bail = P_SpawnMobj(player->mo->x, player->mo->y, player->mo->z + player->mo->height/2, MT_BAIL);
|
||||
P_SetTarget(&bail->target, player->mo);
|
||||
|
||||
UINT32 debtrings = 20;
|
||||
if (player->rings < 0)
|
||||
{
|
||||
debtrings -= player->rings;
|
||||
player->rings = 0;
|
||||
}
|
||||
|
||||
UINT32 totalrings = player->rings + player->superring + player->pickuprings;
|
||||
if (BAIL_CREDIT_DEBTRINGS)
|
||||
totalrings += debtrings;
|
||||
totalrings = max(totalrings, 0);
|
||||
UINT32 bailboost = FixedInt(FixedMul(totalrings*FRACUNIT, BAIL_BOOST));
|
||||
UINT32 baildrop = FixedInt(FixedMul((totalrings)*FRACUNIT, BAIL_DROP));
|
||||
|
||||
if (player->itemRoulette.active)
|
||||
{
|
||||
player->itemRoulette.active = false;
|
||||
}
|
||||
|
||||
K_PopPlayerShield(player);
|
||||
K_DeleteHnextList(player);
|
||||
K_DropItems(player);
|
||||
|
||||
player->itemamount = 0;
|
||||
player->itemtype = 0;
|
||||
|
||||
/*
|
||||
if (player->itemamount)
|
||||
{
|
||||
K_DropPaperItem(player, player->itemtype, player->itemamount);
|
||||
player->itemtype = player->itemamount = 0;
|
||||
}
|
||||
*/
|
||||
|
||||
player->rings = -20;
|
||||
player->superring = 0;
|
||||
player->pickuprings = 0;
|
||||
player->ringboxaward = 0;
|
||||
player->ringboxdelay = 0;
|
||||
|
||||
player->superringdisplay = 0;
|
||||
player->superringalert = 0;
|
||||
player->superringpeak = 0;
|
||||
|
||||
player->counterdash += TICRATE/8;
|
||||
|
||||
player->ringboost += bailboost * (3+K_GetKartRingPower(player, true));
|
||||
player->baildrop = baildrop * BAIL_DROPFREQUENCY + 1;
|
||||
|
||||
K_AddHitLag(player->mo, TICRATE/4, false);
|
||||
player->bailquake = true; // set for a one time quake effect as soon as hitlag ends
|
||||
|
||||
if (P_PlayerInPain(player))
|
||||
{
|
||||
player->spinouttimer = 0;
|
||||
player->spinouttype = 0;
|
||||
player->tumbleBounces = 0;
|
||||
player->pflags &= ~PF_TUMBLELASTBOUNCE;
|
||||
player->mo->rollangle = 0;
|
||||
P_ResetPitchRoll(player->mo);
|
||||
}
|
||||
|
||||
INT32 fls = K_GetEffectiveFollowerSkin(player);
|
||||
if (player->follower && fls >= 0 && fls < numfollowers)
|
||||
{
|
||||
const follower_t *fl = &followers[fls];
|
||||
S_StartSound(NULL, fl->hornsound);
|
||||
}
|
||||
|
||||
if (player->amps > 0)
|
||||
K_DefensiveOverdrive(player);
|
||||
|
||||
S_StartSound(player->mo, sfx_kc33);
|
||||
}
|
||||
|
||||
if (player && player->mo && K_PlayerCanUseItem(player))
|
||||
{
|
||||
// First, the really specific, finicky items that function without the item being directly in your item slot.
|
||||
|
|
@ -14551,7 +14721,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
|||
S_StartSound(player->mo, sfx_s3k75);
|
||||
|
||||
player->bubbleblowup++;
|
||||
player->bubblecool = player->bubbleblowup*4;
|
||||
player->bubblecool = player->bubbleblowup * (gametyperules & GTR_BUMPERS ? 6 : 4);
|
||||
|
||||
if (player->bubbleblowup > bubbletime*2)
|
||||
{
|
||||
|
|
@ -15960,111 +16130,115 @@ boolean K_PlayerCanUseItem(player_t *player)
|
|||
return (player->mo->health > 0 && !player->spectator && !P_PlayerInPain(player) && !mapreset && leveltime > introtime);
|
||||
}
|
||||
|
||||
fixed_t K_GetGradingFactorAdjustment(player_t *player)
|
||||
// ===
|
||||
// THE EXP ZONE
|
||||
// ===
|
||||
|
||||
static boolean K_IsValidOpponent(player_t *me, player_t *them)
|
||||
{
|
||||
fixed_t power = EXP_POWER; // adjust to change overall xp volatility
|
||||
const fixed_t stablerate = EXP_STABLERATE; // how low is your placement before losing XP? 4*FRACUNIT/10 = top 40% of race will gain
|
||||
fixed_t result = 0;
|
||||
UINT8 i = (them - players);
|
||||
|
||||
if (!playeringame[i] || players[i].spectator)
|
||||
return false;
|
||||
if (me == them)
|
||||
return false;
|
||||
if (G_SameTeam(me, them))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static UINT8 K_Opponents(player_t *player)
|
||||
{
|
||||
UINT8 opponents = 0; // players we are competing against
|
||||
|
||||
for (UINT8 i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (K_IsValidOpponent(player, &players[i]))
|
||||
opponents++;
|
||||
}
|
||||
|
||||
return opponents;
|
||||
}
|
||||
|
||||
static fixed_t K_GradingFactorPower(player_t *player)
|
||||
{
|
||||
fixed_t power = EXP_POWER; // adjust to change overall exp volatility
|
||||
UINT8 opponents = K_Opponents(player);
|
||||
|
||||
if (g_teamplay)
|
||||
power = 3 * power / 4;
|
||||
|
||||
INT32 live_players = 0; // players we are competing against
|
||||
if (opponents < 8)
|
||||
power += (8 - opponents) * power/4;
|
||||
|
||||
return power;
|
||||
}
|
||||
|
||||
static fixed_t K_GradingFactorGainPerWin(player_t *player)
|
||||
{
|
||||
return K_GradingFactorPower(player);
|
||||
}
|
||||
|
||||
static fixed_t K_GradingFactorDrainPerCheckpoint(player_t *player)
|
||||
{
|
||||
// EXP_STABLERATE: How low do you have to place before losing gradingfactor? 4*FRACUNIT/10 = top 40% of race gains, 60% loses.
|
||||
UINT8 opponents = K_Opponents(player);
|
||||
fixed_t power = K_GradingFactorPower(player);
|
||||
return FixedMul(power, FixedMul(opponents*FRACUNIT, FRACUNIT - EXP_STABLERATE));
|
||||
}
|
||||
|
||||
fixed_t K_GetGradingFactorAdjustment(player_t *player)
|
||||
{
|
||||
fixed_t result = 0;
|
||||
|
||||
// Increase gradingfactor for each player you're beating...
|
||||
for (INT32 i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator || player == players+i)
|
||||
if (!K_IsValidOpponent(player, &players[i]))
|
||||
continue;
|
||||
|
||||
if (G_SameTeam(player, &players[i]) == true)
|
||||
{
|
||||
// You don't win/lose against your teammates.
|
||||
continue;
|
||||
}
|
||||
|
||||
live_players++;
|
||||
}
|
||||
|
||||
if (live_players < 8)
|
||||
{
|
||||
power += (8 - live_players) * power/4;
|
||||
}
|
||||
|
||||
// Increase XP for each player you're beating...
|
||||
for (INT32 i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator || player == players+i)
|
||||
continue;
|
||||
|
||||
if (G_SameTeam(player, &players[i]) == true)
|
||||
{
|
||||
// You don't win/lose against your teammates.
|
||||
continue;
|
||||
}
|
||||
|
||||
if (player->position < players[i].position)
|
||||
result += power;
|
||||
result += K_GradingFactorGainPerWin(player);
|
||||
}
|
||||
|
||||
// ...then take all of the XP you could possibly have earned,
|
||||
// ...then take all of the gradingfactor you could possibly have earned,
|
||||
// and lose it proportional to the stable rate. If you're below
|
||||
// the stable threshold, this results in you losing XP.
|
||||
result -= FixedMul(power, FixedMul(live_players*FRACUNIT, FRACUNIT - stablerate));
|
||||
// the stable threshold, this results in you losing gradingfactor
|
||||
result -= K_GradingFactorDrainPerCheckpoint(player);
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
fixed_t K_GetGradingFactorMinMax(UINT32 gradingpointnum, boolean max)
|
||||
fixed_t K_GetGradingFactorMinMax(player_t *player, boolean max)
|
||||
{
|
||||
// Create a dummy player structure for the theoretical last-place player
|
||||
player_t dummy_player;
|
||||
memset(&dummy_player, 0, sizeof(player_t));
|
||||
dummy_player.gradingfactor = FRACUNIT; // Start at 1.0
|
||||
fixed_t factor = FRACUNIT; // Starting gradingfactor
|
||||
UINT8 opponents = K_Opponents(player);
|
||||
UINT8 winning = (max) ? opponents : 0;
|
||||
|
||||
if (G_GametypeHasTeams())
|
||||
for (UINT8 i = 0; i < player->gradingpointnum; i++) // For each gradingpoint you've reached...
|
||||
{
|
||||
const UINT8 orange_count = G_CountTeam(TEAM_ORANGE);
|
||||
const UINT8 blue_count = G_CountTeam(TEAM_BLUE);
|
||||
if (orange_count <= blue_count)
|
||||
{
|
||||
dummy_player.team = TEAM_ORANGE;
|
||||
}
|
||||
else
|
||||
{
|
||||
dummy_player.team = TEAM_BLUE;
|
||||
}
|
||||
dummy_player.position = max ? 0 : D_NumPlayersInRace() + 1; // Ensures that all enemy players are counted, and our dummy won't overlap
|
||||
for (UINT8 j = 0; j < winning; j++)
|
||||
factor += K_GradingFactorGainPerWin(player); // If max, increase gradingfactor for each player you could have been beating.
|
||||
factor -= K_GradingFactorDrainPerCheckpoint(player); // Then, drain like usual.
|
||||
}
|
||||
else
|
||||
{
|
||||
dummy_player.position = max ? 1 : D_NumPlayersInRace();
|
||||
}
|
||||
|
||||
// Apply the adjustment for each grading point
|
||||
for (UINT32 i = 0; i < gradingpointnum; i++)
|
||||
{
|
||||
dummy_player.gradingfactor += K_GetGradingFactorAdjustment(&dummy_player);
|
||||
}
|
||||
return dummy_player.gradingfactor;
|
||||
|
||||
return factor;
|
||||
}
|
||||
|
||||
UINT16 K_GetEXP(player_t *player)
|
||||
{
|
||||
UINT32 numgradingpoints = K_GetNumGradingPoints();
|
||||
UINT16 targetminexp = (MINEXP*player->gradingpointnum/max(1,numgradingpoints)); // about what a last place player should be at this stage of the race
|
||||
UINT16 targetexp = (MAXEXP*player->gradingpointnum/max(1,numgradingpoints)); // about what a 1.0 factor should be at this stage of the race
|
||||
fixed_t factormin = K_GetGradingFactorMinMax(player->gradingpointnum, false);
|
||||
fixed_t factormax = K_GetGradingFactorMinMax(player->gradingpointnum, true);
|
||||
fixed_t clampedfactor = max(factormin, min(factormax, player->gradingfactor));
|
||||
fixed_t range = factormax - factormin;
|
||||
fixed_t normalizedfactor = FixedDiv(clampedfactor - factormin, range);
|
||||
fixed_t easedexp = Easing_Linear(normalizedfactor, targetminexp, targetexp);
|
||||
// fixed_t easedexp = Easing_Linear(normalizedfactor, MINEXP*FRACUNIT, MAXEXP*FRACUNIT);
|
||||
UINT16 exp = easedexp;
|
||||
// CONS_Printf("Player %s numgradingpoints=%d targetminexp=%d targetexp=%d factormin=%.2f factormax=%.2f clampedfactor=%.2f normalizedfactor=%.2f easedexp=%d\n",
|
||||
// player_names[player - players], numgradingpoints, targetminexp, targetexp, FIXED_TO_FLOAT(factormin), FIXED_TO_FLOAT(factormax),
|
||||
// FIXED_TO_FLOAT(clampedfactor), FIXED_TO_FLOAT(normalizedfactor), easedexp);
|
||||
// UINT16 exp = (player->gradingfactor*100)>>FRACBITS;
|
||||
fixed_t targetminexp = (EXP_MIN*player->gradingpointnum<<FRACBITS) / max(1,numgradingpoints); // about what a last place player should be at this stage of the race
|
||||
fixed_t targetmaxexp = (EXP_MAX*player->gradingpointnum<<FRACBITS) / max(1,numgradingpoints); // about what a 1.0 factor should be at this stage of the race
|
||||
fixed_t factormin = K_GetGradingFactorMinMax(player, false);
|
||||
fixed_t factormax = K_GetGradingFactorMinMax(player, true);
|
||||
|
||||
UINT16 exp = FixedRescale(player->gradingfactor, factormin, factormax, Easing_Linear, targetminexp, targetmaxexp)>>FRACBITS;
|
||||
|
||||
// CONS_Printf("Player %s numgradingpoints=%d gradingpoint=%d targetminexp=%d targetmaxexp=%d factor=%.2f factormin=%.2f factormax=%.2f exp=%d\n",
|
||||
// player_names[player - players], numgradingpoints, player->gradingpointnum, targetminexp, targetmaxexp, FIXED_TO_FLOAT(player->gradingfactor), FIXED_TO_FLOAT(factormin), FIXED_TO_FLOAT(factormax), exp);
|
||||
|
||||
return exp;
|
||||
}
|
||||
|
||||
|
|
@ -16076,6 +16250,10 @@ UINT32 K_GetNumGradingPoints(void)
|
|||
return numlaps * (1 + Obj_GetCheckpointCount());
|
||||
}
|
||||
|
||||
// ===
|
||||
// END EXP ZONE
|
||||
// ===
|
||||
|
||||
void K_BotHitPenalty(player_t *player)
|
||||
{
|
||||
if (K_PlayerUsesBotMovement(player))
|
||||
|
|
@ -16301,4 +16479,70 @@ fixed_t K_TeamComebackMultiplier(player_t *player)
|
|||
return multiplier;
|
||||
}
|
||||
|
||||
void K_ApplyStun(player_t *player, mobj_t *inflictor, mobj_t *source, ATTRUNUSED INT32 damage, ATTRUNUSED UINT8 damagetype)
|
||||
{
|
||||
#define BASE_STUN_TICS_MIN (4 * TICRATE)
|
||||
#define BASE_STUN_TICS_MAX (10 * TICRATE)
|
||||
#define MAX_STUN_REDUCTION (FRACUNIT/2)
|
||||
#define STUN_REDUCTION_DISTANCE (20000)
|
||||
INT32 stunTics = 0;
|
||||
UINT8 numPlayers = 0;
|
||||
UINT8 i;
|
||||
|
||||
// calculate the number of players playing
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (playeringame[i] && !players[i].spectator)
|
||||
{
|
||||
numPlayers++;
|
||||
}
|
||||
}
|
||||
|
||||
// calculate base stun tics
|
||||
stunTics = Easing_Linear((player->kartweight - 1) * FRACUNIT / 8, BASE_STUN_TICS_MAX, BASE_STUN_TICS_MIN);
|
||||
|
||||
// reduce stun in games with more than 8 players
|
||||
if (numPlayers > 8)
|
||||
{
|
||||
stunTics -= 6 * (numPlayers - 8);
|
||||
}
|
||||
|
||||
// 1/3 stun values in battle
|
||||
if (gametyperules & GTR_SPHERES)
|
||||
{
|
||||
stunTics /= 3;
|
||||
}
|
||||
|
||||
if (source && source->player)
|
||||
{
|
||||
// hits scored by players apply full stun
|
||||
;
|
||||
}
|
||||
else if (inflictor && (P_IsKartItem(inflictor->type) || P_IsKartFieldItem(inflictor->type)))
|
||||
{
|
||||
// items not thrown by a player apply half stun
|
||||
stunTics /= 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
// all other hazards apply 1/4 stun
|
||||
stunTics /= 4;
|
||||
}
|
||||
|
||||
UINT32 dist = K_GetItemRouletteDistance(player, D_NumPlayersInRace());
|
||||
if (dist > STUN_REDUCTION_DISTANCE)
|
||||
dist = STUN_REDUCTION_DISTANCE;
|
||||
|
||||
fixed_t distfactor = FixedDiv(dist, STUN_REDUCTION_DISTANCE); // 0-1 as you approach STUN_REDUCTION_DISTANCE
|
||||
fixed_t stunfactor = Easing_Linear(distfactor, FRACUNIT, MAX_STUN_REDUCTION);
|
||||
stunTics = FixedMul(stunTics*FRACUNIT, stunfactor)/FRACUNIT;
|
||||
|
||||
player->stunned = max(stunTics, 0);
|
||||
|
||||
#undef BASE_STUN_TICS_MIN
|
||||
#undef BASE_STUN_TICS_MAX
|
||||
#undef MAX_STUN_REDUCTION
|
||||
#undef STUN_REDUCTION_DISTANCE
|
||||
}
|
||||
|
||||
//}
|
||||
|
|
|
|||
13
src/k_kart.h
13
src/k_kart.h
|
|
@ -44,6 +44,13 @@ Make sure this matches the actual number of states
|
|||
#define INSTAWHIP_TETHERBLOCK (TICRATE*4)
|
||||
#define PUNISHWINDOW (7*TICRATE/10)
|
||||
|
||||
#define BAIL_MAXCHARGE (84) // tics to bail when in painstate nad in air, on ground is half, if you touch this, also update Obj_BailChargeThink synced animation logic
|
||||
#define BAIL_DROP (FRACUNIT)
|
||||
#define BAIL_BOOST (FRACUNIT)
|
||||
#define BAIL_CREDIT_DEBTRINGS (true)
|
||||
#define BAIL_DROPFREQUENCY (2)
|
||||
#define BAILSTUN (TICRATE*10)
|
||||
|
||||
#define MAXCOMBOTHRUST (mapobjectscale*20)
|
||||
#define MAXCOMBOFLOAT (mapobjectscale*10)
|
||||
#define MINCOMBOTHRUST (mapobjectscale*2)
|
||||
|
|
@ -111,6 +118,8 @@ Make sure this matches the actual number of states
|
|||
|
||||
angle_t K_ReflectAngle(angle_t angle, angle_t against, fixed_t maxspeed, fixed_t yourspeed);
|
||||
|
||||
void K_PopBubbleShield(player_t *player);
|
||||
|
||||
boolean K_IsDuelItem(mobjtype_t type);
|
||||
boolean K_DuelItemAlwaysSpawns(mapthing_t *mt);
|
||||
boolean K_InRaceDuel(void);
|
||||
|
|
@ -325,7 +334,7 @@ boolean K_ThunderDome(void);
|
|||
boolean K_PlayerCanUseItem(player_t *player);
|
||||
|
||||
fixed_t K_GetGradingFactorAdjustment(player_t *player);
|
||||
fixed_t K_GetGradingFactorMinMax(UINT32 gradingpointnum, boolean max);
|
||||
fixed_t K_GetGradingFactorMinMax(player_t *player, boolean max);
|
||||
UINT16 K_GetEXP(player_t *player);
|
||||
|
||||
UINT32 K_GetNumGradingPoints(void);
|
||||
|
|
@ -340,6 +349,8 @@ boolean K_TryPickMeUp(mobj_t *m1, mobj_t *m2, boolean allowHostile);
|
|||
|
||||
fixed_t K_TeamComebackMultiplier(player_t *player);
|
||||
|
||||
void K_ApplyStun(player_t *player, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -465,8 +465,8 @@ boolean M_Responder(event_t *ev)
|
|||
// Special mid-game input behaviours
|
||||
if (Playing() && !demo.playback)
|
||||
{
|
||||
// Quick Retry (Y in modeattacking)
|
||||
if (modeattacking && G_PlayerInputDown(0, gc_respawn, splitscreen + 1) == true)
|
||||
// Quick Retry (Z in modeattacking)
|
||||
if (modeattacking && G_PlayerInputDown(0, gc_vote, splitscreen + 1) == true)
|
||||
{
|
||||
M_TryAgain(0);
|
||||
return true;
|
||||
|
|
|
|||
|
|
@ -153,6 +153,10 @@ void Obj_ChargeFallThink(mobj_t *charge);
|
|||
void Obj_ChargeReleaseThink(mobj_t *release);
|
||||
void Obj_ChargeExtraThink(mobj_t *extra);
|
||||
|
||||
/* Bail VFX */
|
||||
void Obj_BailThink(mobj_t *aura);
|
||||
void Obj_BailChargeThink(mobj_t *aura);
|
||||
|
||||
/* Ring Shooter */
|
||||
boolean Obj_RingShooterThinker(mobj_t *mo);
|
||||
boolean Obj_PlayerRingShooterFreeze(const player_t *player);
|
||||
|
|
@ -440,6 +444,7 @@ void Obj_DestroyedKartParticleLanding(mobj_t *part);
|
|||
void Obj_SpawnFlybotsForPlayer(player_t *player);
|
||||
void Obj_FlybotThink(mobj_t *flybot);
|
||||
void Obj_FlybotDeath(mobj_t *flybot);
|
||||
void Obj_FlybotRemoved(mobj_t *flybot);
|
||||
|
||||
/* Pulley */
|
||||
void Obj_PulleyThink(mobj_t *root);
|
||||
|
|
|
|||
|
|
@ -139,7 +139,7 @@ void podiumData_s::Init(void)
|
|||
constexpr INT32 numRaces = 5;
|
||||
for (INT32 i = 0; i < rank.numPlayers; i++)
|
||||
{
|
||||
rank.totalPoints += numRaces * K_CalculateGPRankPoints(MAXEXP, i+1, rank.totalPlayers);
|
||||
rank.totalPoints += numRaces * K_CalculateGPRankPoints(EXP_MAX, i+1, rank.totalPlayers);
|
||||
}
|
||||
rank.totalRings = numRaces * rank.numPlayers * 20;
|
||||
|
||||
|
|
@ -180,7 +180,7 @@ void podiumData_s::Init(void)
|
|||
}
|
||||
default:
|
||||
{
|
||||
lvl->totalExp = TARGETEXP;
|
||||
lvl->totalExp = EXP_TARGET;
|
||||
texp += lvl->totalExp * rank.numPlayers;
|
||||
break;
|
||||
}
|
||||
|
|
@ -203,7 +203,7 @@ void podiumData_s::Init(void)
|
|||
dta->rings = M_RandomRange(0, 20);
|
||||
rgs += dta->rings;
|
||||
|
||||
dta->exp = M_RandomRange(MINEXP, MAXEXP);
|
||||
dta->exp = M_RandomRange(EXP_MIN, EXP_MAX);
|
||||
pexp += dta->exp;
|
||||
}
|
||||
|
||||
|
|
@ -727,8 +727,8 @@ void podiumData_s::Draw(void)
|
|||
// Colorize the crystal, just like we do for hud
|
||||
skincolornum_t overlaycolor = SKINCOLOR_MUSTARD;
|
||||
fixed_t stablerateinverse = FRACUNIT - EXP_STABLERATE;
|
||||
INT16 exp_range = MAXEXP-MINEXP;
|
||||
INT16 exp_offset = dta->exp-MINEXP;
|
||||
INT16 exp_range = EXP_MAX-EXP_MIN;
|
||||
INT16 exp_offset = dta->exp-EXP_MIN;
|
||||
fixed_t factor = (exp_offset*FRACUNIT) / exp_range; // 0.0 to 1.0 in fixed
|
||||
// amount of blue is how much factor is above EXP_STABLERATE, and amount of red is how much factor is below
|
||||
// assume that EXP_STABLERATE is within 0.0 to 1.0 in fixed
|
||||
|
|
@ -892,9 +892,9 @@ void podiumData_s::Draw(void)
|
|||
.patch("K_STEXP");
|
||||
|
||||
// Colorize the crystal for the totals, just like we do for in race hud
|
||||
fixed_t extraexpfactor = (MAXEXP*FRACUNIT) / TARGETEXP;
|
||||
fixed_t extraexpfactor = (EXP_MAX*FRACUNIT) / EXP_TARGET;
|
||||
INT16 totalExpMax = FixedMul(rank.totalExp*FRACUNIT, extraexpfactor) / FRACUNIT; // im just going to calculate it from target lol
|
||||
INT16 totalExpMin = rank.numPlayers*MINEXP;
|
||||
INT16 totalExpMin = rank.numPlayers*EXP_MIN;
|
||||
skincolornum_t overlaycolor = SKINCOLOR_MUSTARD;
|
||||
fixed_t stablerateinverse = FRACUNIT - EXP_STABLERATE;
|
||||
INT16 exp_range = totalExpMax-totalExpMin;
|
||||
|
|
|
|||
|
|
@ -65,9 +65,10 @@ void K_GivePowerUp(player_t* player, kartitems_t powerup, tic_t time)
|
|||
}
|
||||
|
||||
S_StartSound(NULL, sfx_gsha7l);
|
||||
player->flashing = 2*TICRATE;
|
||||
player->flashing = 3*TICRATE;
|
||||
player->mo->hitlag += BATTLE_POWERUP_VFX_TIME;
|
||||
player->powerupVFXTimer = BATTLE_POWERUP_VFX_TIME;
|
||||
player->mo->flags |= MF_NOCLIPTHING;
|
||||
Obj_SpawnPowerUpSpinner(player->mo, powerup, BATTLE_POWERUP_VFX_TIME);
|
||||
|
||||
g_darkness.start = leveltime;
|
||||
|
|
|
|||
|
|
@ -322,7 +322,7 @@ void gpRank_t::Init(void)
|
|||
// (Should this account for all coop players?)
|
||||
for (i = 0; i < numHumans; i++)
|
||||
{
|
||||
totalPoints += grandprixinfo.cup->numlevels * K_CalculateGPRankPoints(MAXEXP, i+1, totalPlayers);
|
||||
totalPoints += grandprixinfo.cup->numlevels * K_CalculateGPRankPoints(EXP_MAX, i+1, totalPlayers);
|
||||
}
|
||||
|
||||
totalRings = grandprixinfo.cup->numlevels * numHumans * 20;
|
||||
|
|
@ -332,7 +332,7 @@ void gpRank_t::Init(void)
|
|||
const INT32 cupLevelNum = grandprixinfo.cup->cachedlevels[i];
|
||||
if (cupLevelNum < nummapheaders && mapheaderinfo[cupLevelNum] != NULL)
|
||||
{
|
||||
exp += TARGETEXP;
|
||||
exp += EXP_TARGET;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -372,7 +372,7 @@ void gpRank_t::Rejigger(UINT16 removedmap, UINT16 removedgt, UINT16 addedmap, UI
|
|||
{
|
||||
for (i = 0; i < numPlayers; i++)
|
||||
{
|
||||
deltaPoints += K_CalculateGPRankPoints(MAXEXP, i + 1, totalPlayers);
|
||||
deltaPoints += K_CalculateGPRankPoints(EXP_MAX, i + 1, totalPlayers);
|
||||
}
|
||||
if (addedgt == GT_RACE)
|
||||
totalPoints += deltaPoints;
|
||||
|
|
@ -391,7 +391,7 @@ void gpRank_t::Rejigger(UINT16 removedmap, UINT16 removedgt, UINT16 addedmap, UI
|
|||
{
|
||||
if (removedgt == GT_RACE)
|
||||
{
|
||||
deltaExp -= TARGETEXP;
|
||||
deltaExp -= EXP_TARGET;
|
||||
}
|
||||
if ((gametypes[removedgt]->rules & GTR_SPHERES) == 0)
|
||||
{
|
||||
|
|
@ -408,7 +408,7 @@ void gpRank_t::Rejigger(UINT16 removedmap, UINT16 removedgt, UINT16 addedmap, UI
|
|||
{
|
||||
if (addedgt == GT_RACE)
|
||||
{
|
||||
deltaExp += TARGETEXP;
|
||||
deltaExp += EXP_TARGET;
|
||||
}
|
||||
if ((gametypes[addedgt]->rules & GTR_SPHERES) == 0)
|
||||
{
|
||||
|
|
@ -492,7 +492,7 @@ void gpRank_t::Update(void)
|
|||
|
||||
lvl->time = UINT32_MAX;
|
||||
|
||||
lvl->totalExp = TARGETEXP;
|
||||
lvl->totalExp = EXP_TARGET;
|
||||
lvl->totalPrisons = maptargets;
|
||||
|
||||
UINT8 i;
|
||||
|
|
@ -548,13 +548,10 @@ void K_UpdateGPRank(gpRank_t *rankData)
|
|||
rankData->Update();
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
gp_rank_e K_CalculateGPGrade(gpRank_t *rankData)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
gp_rank_e K_CalculateGPGrade(gpRank_t *rankData)
|
||||
{
|
||||
INT32 retGrade = GRADE_E;
|
||||
|
||||
{
|
||||
extern consvar_t cv_debugrank;
|
||||
|
||||
|
|
@ -564,6 +561,8 @@ gp_rank_e K_CalculateGPGrade(gpRank_t *rankData)
|
|||
}
|
||||
}
|
||||
|
||||
fixed_t percent = K_CalculateGPPercent(rankData);
|
||||
|
||||
static const fixed_t gradePercents[GRADE_A] = {
|
||||
7*FRACUNIT/20, // D: 35% or higher
|
||||
10*FRACUNIT/20, // C: 50% or higher
|
||||
|
|
@ -571,8 +570,31 @@ gp_rank_e K_CalculateGPGrade(gpRank_t *rankData)
|
|||
17*FRACUNIT/20 // A: 85% or higher
|
||||
};
|
||||
|
||||
INT32 retGrade = GRADE_E;
|
||||
for (retGrade = GRADE_E; retGrade < GRADE_A; retGrade++)
|
||||
{
|
||||
if (percent < gradePercents[retGrade])
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rankData->specialWon == true)
|
||||
{
|
||||
// Winning the Special Stage gives you
|
||||
// a free grade increase.
|
||||
retGrade++;
|
||||
}
|
||||
|
||||
return static_cast<gp_rank_e>(retGrade);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
gp_rank_e K_CalculateGPGrade(gpRank_t *rankData)
|
||||
|
||||
See header file for description.
|
||||
--------------------------------------------------*/
|
||||
fixed_t K_CalculateGPPercent(gpRank_t *rankData)
|
||||
{
|
||||
rankData->scorePosition = 0;
|
||||
rankData->scoreGPPoints = 0;
|
||||
rankData->scoreExp = 0;
|
||||
|
|
@ -625,22 +647,8 @@ gp_rank_e K_CalculateGPGrade(gpRank_t *rankData)
|
|||
rankData->scoreContinues;
|
||||
|
||||
const fixed_t percent = FixedDiv(rankData->scoreTotal, total);
|
||||
for (retGrade = GRADE_E; retGrade < GRADE_A; retGrade++)
|
||||
{
|
||||
if (percent < gradePercents[retGrade])
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (rankData->specialWon == true)
|
||||
{
|
||||
// Winning the Special Stage gives you
|
||||
// a free grade increase.
|
||||
retGrade++;
|
||||
}
|
||||
|
||||
return static_cast<gp_rank_e>(retGrade);
|
||||
return percent;
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -159,6 +159,7 @@ void K_UpdateGPRank(gpRank_t *rankData);
|
|||
--------------------------------------------------*/
|
||||
|
||||
gp_rank_e K_CalculateGPGrade(gpRank_t *rankData);
|
||||
fixed_t K_CalculateGPPercent(gpRank_t *rankData);
|
||||
|
||||
|
||||
/*--------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -347,7 +347,7 @@ void level_tally_t::Init(player_t *player)
|
|||
if (player->exp)
|
||||
{
|
||||
exp = player->exp;
|
||||
totalExp = TARGETEXP;
|
||||
totalExp = EXP_TARGET;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -262,8 +262,8 @@ static int player_get(lua_State *L)
|
|||
lua_pushinteger(L, plr->tumbleHeight);
|
||||
else if (fastcmp(field,"stunned"))
|
||||
lua_pushinteger(L, plr->stunned);
|
||||
else if (fastcmp(field,"stunnedcombo"))
|
||||
lua_pushinteger(L, plr->stunnedCombo);
|
||||
else if (fastcmp(field,"flybot"))
|
||||
LUA_PushUserdata(L, plr->flybot, META_MOBJ);
|
||||
else if (fastcmp(field,"justdi"))
|
||||
lua_pushinteger(L, plr->justDI);
|
||||
else if (fastcmp(field,"flipdi"))
|
||||
|
|
@ -284,6 +284,12 @@ static int player_get(lua_State *L)
|
|||
lua_pushboolean(L, plr->progressivethrust);
|
||||
else if (fastcmp(field,"ringvisualwarning"))
|
||||
lua_pushboolean(L, plr->ringvisualwarning);
|
||||
else if (fastcmp(field,"bailcharge"))
|
||||
lua_pushinteger(L, plr->bailcharge);
|
||||
else if (fastcmp(field,"baildrop"))
|
||||
lua_pushinteger(L, plr->baildrop);
|
||||
else if (fastcmp(field,"bailquake"))
|
||||
lua_pushboolean(L, plr->bailquake);
|
||||
else if (fastcmp(field,"dotrickfx"))
|
||||
lua_pushboolean(L, plr->dotrickfx);
|
||||
else if (fastcmp(field,"stingfx"))
|
||||
|
|
@ -896,8 +902,13 @@ static int player_set(lua_State *L)
|
|||
plr->tumbleHeight = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"stunned"))
|
||||
plr->stunned = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"stunnedcombo"))
|
||||
plr->stunnedCombo = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"flybot"))
|
||||
{
|
||||
mobj_t *mo = NULL;
|
||||
if (!lua_isnil(L, 3))
|
||||
mo = *((mobj_t **)luaL_checkudata(L, 3, META_MOBJ));
|
||||
P_SetTarget(&plr->flybot, mo);
|
||||
}
|
||||
else if (fastcmp(field,"justdi"))
|
||||
plr->justDI = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"flipdi"))
|
||||
|
|
@ -910,6 +921,12 @@ static int player_set(lua_State *L)
|
|||
plr->progressivethrust = luaL_checkboolean(L, 3);
|
||||
else if (fastcmp(field,"ringvisualwarning"))
|
||||
plr->ringvisualwarning = luaL_checkboolean(L, 3);
|
||||
else if (fastcmp(field,"bailcharge"))
|
||||
plr->bailcharge = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"baildrop"))
|
||||
plr->baildrop = luaL_checkinteger(L, 3);
|
||||
else if (fastcmp(field,"bailquake"))
|
||||
plr->bailquake = luaL_checkboolean(L, 3);
|
||||
else if (fastcmp(field,"analoginput"))
|
||||
plr->analoginput = luaL_checkboolean(L, 3);
|
||||
else if (fastcmp(field,"transfer"))
|
||||
|
|
|
|||
|
|
@ -430,3 +430,93 @@ const char *easing_funcnames[EASE_MAX] =
|
|||
|
||||
#undef COMMA
|
||||
#undef EASINGFUNC
|
||||
|
||||
// ==================
|
||||
// FEATURE RESCALING
|
||||
// ==================
|
||||
|
||||
/*--------------------------------------------------
|
||||
fixed_t Rescale(fixed_t value, fixed_t inmin, fixed_t inmax, easingfunc_t easing_func, fixed_t outmin, fixed_t outmax)
|
||||
|
||||
Rescales a feature value from [min, max] to [start, end] using
|
||||
a custom easing function pointer.
|
||||
|
||||
Input Arguments:-
|
||||
value - The input value to rescale
|
||||
inmin - Minimum value of the input range
|
||||
inmax - Maximum value of the input range
|
||||
easing_func - Pointer to the easing function to use
|
||||
outmin - Start value of the output range
|
||||
outmax - End value of the output range
|
||||
|
||||
Return:-
|
||||
The rescaled value using the specified easing function.
|
||||
--------------------------------------------------*/
|
||||
fixed_t FixedRescale(fixed_t value, fixed_t inmin, fixed_t inmax, easingfunc_t easing_func, fixed_t outmin, fixed_t outmax)
|
||||
{
|
||||
// Handle edge case where min == max
|
||||
if (inmin == inmax)
|
||||
return outmin;
|
||||
|
||||
// Clamp the input value to the range
|
||||
max(inmin, min(inmax, value));
|
||||
|
||||
// Normalize the value to [0, FRACUNIT] range
|
||||
fixed_t t = FixedDiv(value - inmin, inmax - inmin);
|
||||
|
||||
// Apply the easing function if provided
|
||||
if (easing_func != NULL)
|
||||
{
|
||||
return easing_func(t, outmin, outmax);
|
||||
}
|
||||
|
||||
// Fallback to linear if no function provided
|
||||
return Easing_Linear(t, outmin, outmax);
|
||||
}
|
||||
|
||||
/*--------------------------------------------------
|
||||
INT16 IntRescale(INT16 value, INT16 inmin, INT16 inmax, easingfunc_t easing_func, INT16 outmin, INT16 outmax)
|
||||
|
||||
Rescales a feature value from [min, max] to [start, end] using
|
||||
a custom easing function pointer.
|
||||
Can only take in up to INT16 because it uses fixed_t internally
|
||||
|
||||
Input Arguments:-
|
||||
value - The input value to rescale
|
||||
inmin - Minimum value of the input range
|
||||
inmax - Maximum value of the input range
|
||||
easing_func - Pointer to the easing function to use
|
||||
outmin - Start value of the output range
|
||||
outmax - End value of the output range
|
||||
|
||||
Return:-
|
||||
The rescaled value using the specified easing function.
|
||||
--------------------------------------------------*/
|
||||
INT16 IntRescale(INT16 value, INT16 inmin, INT16 inmax, easingfunc_t easing_func, INT16 outmin, INT16 outmax)
|
||||
{
|
||||
// Handle edge case where min == max
|
||||
if (inmin == inmax)
|
||||
return outmin;
|
||||
|
||||
// Clamp the input value to the range
|
||||
max(inmin, min(inmax, value));
|
||||
|
||||
// Conversion shit
|
||||
value = value<<FRACBITS;
|
||||
inmin = inmin<<FRACBITS;
|
||||
inmax = inmax<<FRACBITS;
|
||||
outmin = outmin<<FRACBITS;
|
||||
outmax = outmax<<FRACBITS;
|
||||
|
||||
// Normalize the value to [0, FRACUNIT] range
|
||||
fixed_t t = FixedDiv(value - inmin, inmax - inmin);
|
||||
|
||||
// Apply the easing function if provided
|
||||
if (easing_func != NULL)
|
||||
{
|
||||
return easing_func(t, outmin, outmax)>>FRACBITS;
|
||||
}
|
||||
|
||||
// Fallback to linear if no function provided
|
||||
return Easing_Linear(t, outmin, outmax)>>FRACBITS;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -105,6 +105,9 @@ EASINGFUNC(InOutBackParameterized) /* Easing_InOutBackParameterized */
|
|||
|
||||
#undef EASINGFUNC
|
||||
|
||||
fixed_t FixedRescale(fixed_t value, fixed_t inmin, fixed_t inmax, easingfunc_t easing_func, fixed_t outmin, fixed_t outmax);
|
||||
INT16 IntRescale(INT16 value, INT16 inmin, INT16 inmax, easingfunc_t easing_func, INT16 outmin, INT16 outmax);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -39,10 +39,10 @@ menuitem_t OPTIONS_ProfileControls[] = {
|
|||
{IT_CONTROL, "Brake / Go back", "Brake / Go back",
|
||||
"TLB_X", {.routine = M_ProfileSetControl}, gc_x, 0},
|
||||
|
||||
{IT_CONTROL, "Respawn", "Respawn",
|
||||
{IT_CONTROL, "Ring Bail", "Ring Bail / Burst",
|
||||
"TLB_Y", {.routine = M_ProfileSetControl}, gc_y, 0},
|
||||
|
||||
{IT_CONTROL, "Action", "Multiplayer quick-chat / quick-vote",
|
||||
{IT_CONTROL, "Action", "Quick-vote / Quick-chat / Time Attack Quick Restart",
|
||||
"TLB_Z", {.routine = M_ProfileSetControl}, gc_z, 0},
|
||||
|
||||
{IT_CONTROL, "Use Item", "Use item",
|
||||
|
|
|
|||
|
|
@ -66,6 +66,7 @@ target_sources(SRB2SDL2 PRIVATE
|
|||
flame-shield.cpp
|
||||
stone-shoe.cpp
|
||||
exp.c
|
||||
bail.c
|
||||
)
|
||||
|
||||
add_subdirectory(versus)
|
||||
|
|
|
|||
80
src/objects/bail.c
Normal file
80
src/objects/bail.c
Normal file
|
|
@ -0,0 +1,80 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2025 by AJ "Tyron" Martinez.
|
||||
// Copyright (C) 2025 by Kart Krew
|
||||
//
|
||||
// This program is free software distributed under the
|
||||
// terms of the GNU General Public License, version 2.
|
||||
// See the 'LICENSE' file for more details.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file bail.c
|
||||
/// \brief Charge VFX code.
|
||||
|
||||
#include "../doomdef.h"
|
||||
#include "../info.h"
|
||||
#include "../k_objects.h"
|
||||
#include "../info.h"
|
||||
#include "../k_kart.h"
|
||||
#include "../p_local.h"
|
||||
#include "../s_sound.h"
|
||||
|
||||
void Obj_BailThink (mobj_t *aura)
|
||||
{
|
||||
if (P_MobjWasRemoved(aura->target)
|
||||
|| aura->target->health == 0
|
||||
|| aura->target->destscale <= 1 // sealed star fall out
|
||||
|| !aura->target->player
|
||||
|| P_PlayerInPain(aura->target->player)) // if you got hit when starting to bail, cancel the VFX
|
||||
{
|
||||
P_RemoveMobj(aura);
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj_t *mo = aura->target;
|
||||
|
||||
aura->flags &= ~(MF_NOCLIPTHING);
|
||||
P_MoveOrigin(aura, mo->x, mo->y, mo->z + mo->height/2);
|
||||
aura->flags |= MF_NOCLIPTHING;
|
||||
|
||||
fixed_t baseScale = 12*mo->scale/10;
|
||||
|
||||
P_SetScale(aura, baseScale);
|
||||
|
||||
// make target player invisible during the effect, like the retro games
|
||||
if (aura->state == &states[S_BAIL])
|
||||
mo->renderflags |= RF_DONTDRAW;
|
||||
}
|
||||
}
|
||||
|
||||
void Obj_BailChargeThink (mobj_t *aura)
|
||||
{
|
||||
if (P_MobjWasRemoved(aura->target)
|
||||
|| aura->target->health == 0
|
||||
|| aura->target->destscale <= 1 // sealed star fall out
|
||||
|| !aura->target->player
|
||||
|| !aura->target->player->bailcharge)
|
||||
{
|
||||
P_RemoveMobj(aura);
|
||||
}
|
||||
else
|
||||
{
|
||||
mobj_t *mo = aura->target;
|
||||
player_t *player = mo->player;
|
||||
|
||||
// Follow player
|
||||
aura->flags &= ~(MF_NOCLIPTHING);
|
||||
P_MoveOrigin(aura, mo->x, mo->y, mo->z + mo->height/2);
|
||||
aura->flags |= MF_NOCLIPTHING;
|
||||
// aura->color = mo->color;
|
||||
|
||||
aura->frame = ((player->bailcharge-1)/2); // By syncing the frame with the charge timer here
|
||||
|
||||
fixed_t baseScale = 13*mo->scale/10;
|
||||
|
||||
P_SetScale(aura, baseScale);
|
||||
|
||||
mobj_t *ghost = P_SpawnGhostMobj(aura);
|
||||
ghost->renderflags = (ghost->renderflags & ~RF_TRANSMASK)|RF_ADD;
|
||||
ghost->fuse = 3;
|
||||
}
|
||||
}
|
||||
|
|
@ -43,6 +43,7 @@ void Obj_SpawnFlybotsForPlayer(player_t *player)
|
|||
{
|
||||
UINT8 i;
|
||||
mobj_t *mo = player->mo;
|
||||
mobj_t *hprev = mo;
|
||||
fixed_t radius = mo->radius;
|
||||
|
||||
for (i = 0; i < FLYBOT_QUANTITY; i++)
|
||||
|
|
@ -61,6 +62,17 @@ void Obj_SpawnFlybotsForPlayer(player_t *player)
|
|||
flybot->movedir = flybot->old_angle = flybot->angle = angle + ANGLE_90;
|
||||
flybot->old_z = SetFlybotZ(flybot);
|
||||
flybot->renderflags |= (i * RF_DONTDRAW);
|
||||
|
||||
if (hprev->player)
|
||||
{
|
||||
P_SetTarget(&player->flybot, flybot);
|
||||
}
|
||||
else
|
||||
{
|
||||
P_SetTarget(&hprev->hnext, flybot);
|
||||
P_SetTarget(&flybot->hprev, hprev);
|
||||
}
|
||||
hprev = flybot;
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -80,11 +92,18 @@ void Obj_FlybotThink(mobj_t *flybot)
|
|||
|
||||
if (mo->player)
|
||||
{
|
||||
if (((stunned = mo->player->stunned & 0x7FFF) == 0) || (mo->player->playerstate == PST_DEAD))
|
||||
if (((stunned = mo->player->stunned) == 0) || (mo->player->playerstate == PST_DEAD))
|
||||
{
|
||||
P_KillMobj(flybot, NULL, NULL, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
// If player is spindashing, spin faster to hint that stun is going down faster
|
||||
else if (mo->player->spindash)
|
||||
{
|
||||
speed *= 2;
|
||||
flybot->movedir += FLYBOT_BOB_FREQUENCY*2;
|
||||
}
|
||||
}
|
||||
|
||||
flybot->frame = flybot->frame & ~FF_TRANSMASK;
|
||||
|
|
@ -120,6 +139,11 @@ void Obj_FlybotDeath(mobj_t *flybot)
|
|||
|
||||
if (!P_MobjWasRemoved(mo))
|
||||
{
|
||||
if (mo->player && (flybot == mo->player->flybot))
|
||||
{
|
||||
P_SetTarget(&mo->player->flybot, NULL);
|
||||
}
|
||||
|
||||
mom.x = mo->momx;
|
||||
mom.y = mo->momy;
|
||||
mom.z = mo->momz;
|
||||
|
|
@ -140,3 +164,12 @@ void Obj_FlybotDeath(mobj_t *flybot)
|
|||
angle += ANGLE_90;
|
||||
}
|
||||
}
|
||||
|
||||
void Obj_FlybotRemoved(mobj_t *flybot)
|
||||
{
|
||||
mobj_t *mo = flybot->target;
|
||||
if (!P_MobjWasRemoved(mo) && mo->player && (flybot == mo->player->flybot))
|
||||
{
|
||||
P_SetTarget(&mo->player->flybot, NULL);
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -668,7 +668,7 @@ boolean Obj_PlayerRingShooterFreeze(const player_t *player)
|
|||
const mobj_t *base = player->ringShooter;
|
||||
|
||||
if (AllowRingShooter(player) == true
|
||||
&& (player->cmd.buttons & BT_RESPAWN) == BT_RESPAWN
|
||||
&& (player->cmd.buttons & BT_RESPAWNMASK) == BT_RESPAWNMASK
|
||||
&& P_MobjWasRemoved(base) == false)
|
||||
{
|
||||
return (rs_base_canceled(base) == 0);
|
||||
|
|
@ -682,7 +682,7 @@ void Obj_RingShooterInput(player_t *player)
|
|||
mobj_t *const base = player->ringShooter;
|
||||
|
||||
if (AllowRingShooter(player) == true
|
||||
&& (player->cmd.buttons & BT_RESPAWN) == BT_RESPAWN)
|
||||
&& (player->cmd.buttons & BT_RESPAWNMASK) == BT_RESPAWNMASK)
|
||||
{
|
||||
// "Freeze" final-failsafe timer if we're eligible to ringshooter, but don't reset it.
|
||||
if (player->finalfailsafe)
|
||||
|
|
|
|||
|
|
@ -3503,7 +3503,7 @@ void A_AttractChase(mobj_t *actor)
|
|||
|
||||
if (actor->extravalue1 && actor->type != MT_EMERALD) // SRB2Kart
|
||||
{
|
||||
if (!actor->target || P_MobjWasRemoved(actor->target) || !actor->target->player)
|
||||
if (!actor->target || P_MobjWasRemoved(actor->target) || !actor->target->player || actor->target->player->baildrop || actor->target->player->bailcharge)
|
||||
{
|
||||
P_RemoveMobj(actor);
|
||||
return;
|
||||
|
|
@ -12206,6 +12206,8 @@ void A_BallhogExplode(mobj_t *actor)
|
|||
mo2->destscale = mo2->scale;
|
||||
P_SetTarget(&mo2->target, actor->target);
|
||||
S_StartSound(mo2, actor->info->deathsound);
|
||||
|
||||
actor->fuse = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -723,6 +723,17 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
if (special->extravalue1)
|
||||
return;
|
||||
|
||||
// No picking up rings while SPB is targetting you
|
||||
if (player->pflags & PF_RINGLOCK)
|
||||
return;
|
||||
|
||||
// Prepping instawhip? Don't ruin it by collecting rings
|
||||
if (player->instaWhipCharge)
|
||||
return;
|
||||
|
||||
if (player->baildrop || player->bailcharge)
|
||||
return;
|
||||
|
||||
// Don't immediately pick up spilled rings
|
||||
if (special->threshold > 0 || P_PlayerInPain(player) || player->spindash) // player->spindash: Otherwise, players can pick up rings that are thrown out of them from invinc spindash penalty
|
||||
return;
|
||||
|
|
@ -3041,7 +3052,6 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
UINT8 type = (damagetype & DMG_TYPEMASK);
|
||||
const boolean hardhit = (type == DMG_EXPLODE || type == DMG_KARMA || type == DMG_TUMBLE); // This damage type can do evil stuff like ALWAYS combo
|
||||
INT16 ringburst = 5;
|
||||
UINT16 stunTics = 0;
|
||||
|
||||
// Check if the player is allowed to be damaged!
|
||||
// If not, then spawn the instashield effect instead.
|
||||
|
|
@ -3094,6 +3104,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
invincible = false;
|
||||
}
|
||||
|
||||
if (player->pflags2 && PF2_ALWAYSDAMAGED)
|
||||
{
|
||||
invincible = false;
|
||||
clash = false;
|
||||
}
|
||||
|
||||
// TODO: doing this from P_DamageMobj limits punting to objects that damage the player.
|
||||
// And it may be kind of yucky.
|
||||
// But this is easier than accounting for every condition in PIT_CheckThing!
|
||||
|
|
@ -3181,6 +3197,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
}
|
||||
}
|
||||
|
||||
if (inflictor && !P_MobjWasRemoved(inflictor) && inflictor->momx == 0 && inflictor->momy == 0 && inflictor->momz == 0)
|
||||
{
|
||||
// Probably a map hazard.
|
||||
allowcombo = false;
|
||||
}
|
||||
|
||||
if (allowcombo == false && (target->eflags & MFE_PAUSED))
|
||||
{
|
||||
return false;
|
||||
|
|
@ -3395,18 +3417,22 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
K_PopPlayerShield(player);
|
||||
}
|
||||
|
||||
if (!(gametyperules & GTR_SPHERES) && player->tripwireLeniency)
|
||||
boolean downgraded = false;
|
||||
|
||||
if (!(gametyperules & GTR_SPHERES) && player->tripwireLeniency && !P_PlayerInPain(player))
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case DMG_EXPLODE:
|
||||
type = DMG_TUMBLE;
|
||||
downgraded = true;
|
||||
break;
|
||||
case DMG_TUMBLE:
|
||||
softenTumble = true;
|
||||
break;
|
||||
case DMG_NORMAL:
|
||||
case DMG_WIPEOUT:
|
||||
downgraded = true;
|
||||
type = DMG_STUMBLE;
|
||||
player->ringburst += 5; // THERE IS SIMPLY NO HOPE AT THIS POINT
|
||||
K_PopPlayerShield(player);
|
||||
|
|
@ -3453,7 +3479,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
ringburst = 0;
|
||||
}
|
||||
|
||||
if (type != DMG_STUMBLE && type != DMG_WHUMBLE)
|
||||
if ((type != DMG_STUMBLE && type != DMG_WHUMBLE) || (type == DMG_STUMBLE && downgraded))
|
||||
{
|
||||
if (type != DMG_STING)
|
||||
player->flashing = K_GetKartFlashing(player);
|
||||
|
|
@ -3488,26 +3514,11 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
}
|
||||
|
||||
// Apply stun!
|
||||
// Feel free to move these calculations higher up if different damage sources should apply variable stun in future
|
||||
#define MIN_STUNTICS (4 * TICRATE)
|
||||
#define MAX_STUNTICS (10 * TICRATE)
|
||||
stunTics = Easing_Linear((player->kartweight - 1) * FRACUNIT / 8, MAX_STUNTICS, MIN_STUNTICS);
|
||||
stunTics >>= player->stunnedCombo; // consecutive hits add half as much stun as the previous hit
|
||||
|
||||
// 1/3 base stun values in battle
|
||||
if (gametyperules & GTR_SPHERES)
|
||||
if (type != DMG_STING)
|
||||
{
|
||||
stunTics /= 3;
|
||||
K_ApplyStun(player, inflictor, source, damage, damagetype);
|
||||
}
|
||||
|
||||
if (player->stunnedCombo < UINT8_MAX)
|
||||
{
|
||||
player->stunnedCombo++;
|
||||
}
|
||||
player->stunned = (player->stunned & 0x8000) | min(0x7FFF, (player->stunned & 0x7FFF) + stunTics);
|
||||
#undef MIN_STUNTICS
|
||||
#undef MAX_STUNTICS
|
||||
|
||||
K_DefensiveOverdrive(target->player);
|
||||
}
|
||||
}
|
||||
|
|
@ -3612,7 +3623,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
|
|||
#define RING_LAYER_SIDE_SIZE (3)
|
||||
#define RING_LAYER_SIZE (RING_LAYER_SIDE_SIZE * 2)
|
||||
|
||||
static void P_FlingBurst
|
||||
void P_FlingBurst
|
||||
( player_t *player,
|
||||
angle_t fa,
|
||||
mobjtype_t objType,
|
||||
|
|
|
|||
|
|
@ -549,6 +549,7 @@ void P_RampConstant(const BasicFF_t *FFInfo, INT32 Start, INT32 End);
|
|||
void P_SpecialStageDamage(player_t *player, mobj_t *inflictor, mobj_t *source);
|
||||
boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 damage, UINT8 damagetype);
|
||||
void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damagetype);
|
||||
void P_FlingBurst(player_t *player, angle_t fa, mobjtype_t objType, tic_t objFuse, fixed_t objScale, INT32 i);
|
||||
void P_PlayerRingBurst(player_t *player, INT32 num_rings); /// \todo better fit in p_user.c
|
||||
|
||||
void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck);
|
||||
|
|
|
|||
15
src/p_mobj.c
15
src/p_mobj.c
|
|
@ -8923,6 +8923,16 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
|
|||
Obj_BlockBodyThink(mobj);
|
||||
break;
|
||||
}
|
||||
case MT_BAIL:
|
||||
{
|
||||
Obj_BailThink(mobj);
|
||||
break;
|
||||
}
|
||||
case MT_BAILCHARGE:
|
||||
{
|
||||
Obj_BailChargeThink(mobj);
|
||||
break;
|
||||
}
|
||||
case MT_AMPRING:
|
||||
{
|
||||
Obj_AmpRingThink(mobj);
|
||||
|
|
@ -11855,6 +11865,11 @@ void P_RemoveMobj(mobj_t *mobj)
|
|||
Obj_UnlinkRocks(mobj);
|
||||
break;
|
||||
}
|
||||
case MT_FLYBOT767:
|
||||
{
|
||||
Obj_FlybotRemoved(mobj);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
{
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -72,8 +72,7 @@ static savebuffer_t *current_savebuffer;
|
|||
#define ARCHIVEBLOCK_WAYPOINTS 0x7F46498F
|
||||
#define ARCHIVEBLOCK_RNG 0x7FAAB5BD
|
||||
|
||||
// Note: This cannot be bigger
|
||||
// than an UINT16 (for now)
|
||||
// Note: This cannot have more than 32 entries
|
||||
typedef enum
|
||||
{
|
||||
AWAYVIEW = 0x0001,
|
||||
|
|
@ -93,6 +92,7 @@ typedef enum
|
|||
BARRIER = 0x4000,
|
||||
BALLHOGRETICULE = 0x8000,
|
||||
STONESHOE = 0x10000,
|
||||
FLYBOT = 0x20000,
|
||||
} player_saveflags;
|
||||
|
||||
static inline void P_ArchivePlayer(savebuffer_t *save)
|
||||
|
|
@ -368,6 +368,9 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
if (players[i].stoneShoe)
|
||||
flags |= STONESHOE;
|
||||
|
||||
if (players[i].flybot)
|
||||
flags |= FLYBOT;
|
||||
|
||||
WRITEUINT32(save->p, flags);
|
||||
|
||||
if (flags & SKYBOXVIEW)
|
||||
|
|
@ -418,6 +421,9 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
if (flags & STONESHOE)
|
||||
WRITEUINT32(save->p, players[i].stoneShoe->mobjnum);
|
||||
|
||||
if (flags & FLYBOT)
|
||||
WRITEUINT32(save->p, players[i].flybot->mobjnum);
|
||||
|
||||
WRITEUINT32(save->p, (UINT32)players[i].followitem);
|
||||
|
||||
WRITEUINT32(save->p, players[i].charflags);
|
||||
|
|
@ -464,7 +470,6 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
WRITEUINT8(save->p, players[i].tumbleBounces);
|
||||
WRITEUINT16(save->p, players[i].tumbleHeight);
|
||||
WRITEUINT16(save->p, players[i].stunned);
|
||||
WRITEUINT8(save->p, players[i].stunnedCombo);
|
||||
|
||||
WRITEUINT8(save->p, players[i].justDI);
|
||||
WRITEUINT8(save->p, players[i].flipDI);
|
||||
|
|
@ -667,6 +672,10 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
WRITEUINT16(save->p, players[i].progressivethrust);
|
||||
WRITEUINT8(save->p, players[i].ringvisualwarning);
|
||||
|
||||
WRITEUINT32(save->p, players[i].bailcharge);
|
||||
WRITEUINT32(save->p, players[i].baildrop);
|
||||
WRITEUINT8(save->p, players[i].bailquake);
|
||||
|
||||
WRITEUINT8(save->p, players[i].analoginput);
|
||||
|
||||
WRITEUINT8(save->p, players[i].markedfordeath);
|
||||
|
|
@ -756,7 +765,10 @@ static void P_NetArchivePlayers(savebuffer_t *save)
|
|||
WRITEUINT32(save->p, players[i].botvars.spindashconfirm);
|
||||
WRITEUINT32(save->p, players[i].botvars.respawnconfirm);
|
||||
WRITEUINT8(save->p, players[i].botvars.roulettePriority);
|
||||
WRITEUINT32(save->p, players[i].botvars.rouletteTimeout);
|
||||
WRITEINT32(save->p, players[i].botvars.rouletteTimeout);
|
||||
WRITEUINT32(save->p, players[i].botvars.predictionError);
|
||||
WRITEUINT32(save->p, players[i].botvars.recentDeflection);
|
||||
WRITEUINT32(save->p, players[i].botvars.lastAngle);
|
||||
|
||||
// itemroulette_t
|
||||
WRITEUINT8(save->p, players[i].itemRoulette.active);
|
||||
|
|
@ -1070,6 +1082,9 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
if (flags & STONESHOE)
|
||||
players[i].stoneShoe = (mobj_t *)(size_t)READUINT32(save->p);
|
||||
|
||||
if (flags & FLYBOT)
|
||||
players[i].flybot = (mobj_t *)(size_t)READUINT32(save->p);
|
||||
|
||||
players[i].followitem = (mobjtype_t)READUINT32(save->p);
|
||||
|
||||
//SetPlayerSkinByNum(i, players[i].skin);
|
||||
|
|
@ -1117,7 +1132,6 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
players[i].tumbleBounces = READUINT8(save->p);
|
||||
players[i].tumbleHeight = READUINT16(save->p);
|
||||
players[i].stunned = READUINT16(save->p);
|
||||
players[i].stunnedCombo = READUINT8(save->p);
|
||||
|
||||
players[i].justDI = READUINT8(save->p);
|
||||
players[i].flipDI = (boolean)READUINT8(save->p);
|
||||
|
|
@ -1319,6 +1333,10 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
players[i].progressivethrust = READUINT16(save->p);
|
||||
players[i].ringvisualwarning = READUINT8(save->p);
|
||||
|
||||
players[i].bailcharge = READUINT32(save->p);
|
||||
players[i].baildrop = READUINT32(save->p);
|
||||
players[i].bailquake = READUINT8(save->p);
|
||||
|
||||
players[i].analoginput = READUINT8(save->p);
|
||||
|
||||
players[i].markedfordeath = READUINT8(save->p);
|
||||
|
|
@ -1409,6 +1427,9 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
|
|||
players[i].botvars.respawnconfirm = READUINT32(save->p);
|
||||
players[i].botvars.roulettePriority = READUINT8(save->p);
|
||||
players[i].botvars.rouletteTimeout = READUINT32(save->p);
|
||||
players[i].botvars.predictionError = READUINT32(save->p);
|
||||
players[i].botvars.recentDeflection = READUINT32(save->p);
|
||||
players[i].botvars.lastAngle = READUINT32(save->p);
|
||||
|
||||
// itemroulette_t
|
||||
players[i].itemRoulette.active = (boolean)READUINT8(save->p);
|
||||
|
|
@ -6226,6 +6247,11 @@ static void P_RelinkPointers(void)
|
|||
if (!RelinkMobj(&players[i].stoneShoe))
|
||||
CONS_Debug(DBG_GAMELOGIC, "stoneShoe not found on player %d\n", i);
|
||||
}
|
||||
if (players[i].flybot)
|
||||
{
|
||||
if (!RelinkMobj(&players[i].flybot))
|
||||
CONS_Debug(DBG_GAMELOGIC, "flybot not found on player %d\n", i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -8698,7 +8698,7 @@ boolean P_LoadLevel(boolean fromnetsave, boolean reloadinggamestate)
|
|||
if (G_IsModeAttackRetrying() && !demo.playback)
|
||||
{
|
||||
nowtime = lastwipetic;
|
||||
while (G_PlayerInputDown(0, gc_respawn, splitscreen + 1) == true)
|
||||
while (G_PlayerInputDown(0, gc_vote, splitscreen + 1) == true)
|
||||
{
|
||||
while (!((nowtime = I_GetTime()) - lastwipetic))
|
||||
{
|
||||
|
|
|
|||
|
|
@ -1206,11 +1206,15 @@ void P_ButteredSlope(mobj_t *mo)
|
|||
// Let's get the gravity strength for the object...
|
||||
thrust = FixedMul(thrust, abs(P_GetMobjGravity(mo)));
|
||||
|
||||
if (mo->friction != ORIG_FRICTION)
|
||||
fixed_t basefriction = ORIG_FRICTION;
|
||||
if (mo->player)
|
||||
basefriction = K_PlayerBaseFriction(mo->player, ORIG_FRICTION);
|
||||
|
||||
if (mo->friction != basefriction && basefriction != 0)
|
||||
{
|
||||
// ... and its friction against the ground for good measure.
|
||||
// (divided by original friction to keep behaviour for normal slopes the same)
|
||||
thrust = FixedMul(thrust, FixedDiv(mo->friction, ORIG_FRICTION));
|
||||
thrust = FixedMul(thrust, FixedDiv(mo->friction, basefriction));
|
||||
|
||||
// Sal: Also consider movefactor of players.
|
||||
// We want ice to make slopes *really* funnel you in a specific direction.
|
||||
|
|
|
|||
|
|
@ -9635,7 +9635,7 @@ void P_DoQuakeOffset(UINT8 view, mappoint_t *viewPos, mappoint_t *offset)
|
|||
quake = quake->next;
|
||||
}
|
||||
|
||||
// Add level-based effects.
|
||||
// Add level-based effects
|
||||
if (P_MobjWasRemoved(viewer->mo) == false
|
||||
&& viewer->speed > viewer->mo->scale
|
||||
&& P_IsObjectOnGround(viewer->mo) == true)
|
||||
|
|
@ -9664,9 +9664,9 @@ void P_DoQuakeOffset(UINT8 view, mappoint_t *viewPos, mappoint_t *offset)
|
|||
maxShake = FixedMul(mapheaderinfo[gamemap-1]->cameraHeight, mapobjectscale) * 3 / 4;
|
||||
|
||||
// For 2p SPLITSCREEN SPECIFICALLY:
|
||||
// The view is pretty narrow, so move it back 1/4th of the way towards default camera height.
|
||||
// The view is pretty narrow, so move it back 3/20 of the way towards default camera height.
|
||||
else
|
||||
maxShake = FixedMul((mapheaderinfo[gamemap-1]->cameraHeight*3 + cv_cam_height[view].value)/4, mapobjectscale) * 3 / 4;
|
||||
maxShake = FixedMul((mapheaderinfo[gamemap-1]->cameraHeight*17 + cv_cam_height[view].value*3)/20, mapobjectscale) * 3 / 4;
|
||||
}
|
||||
|
||||
if (battle)
|
||||
|
|
|
|||
12
src/p_user.c
12
src/p_user.c
|
|
@ -3067,7 +3067,7 @@ void P_DemoCameraMovement(camera_t *cam, UINT8 num)
|
|||
}
|
||||
|
||||
// if you hold Y, you will lock on to displayplayer. (The last player you were ""f12-ing"")
|
||||
if (cam->freecam && cmd->buttons & BT_RESPAWN)
|
||||
if (cam->freecam && cmd->buttons & BT_BAIL)
|
||||
{
|
||||
lastp = &players[displayplayers[0]]; // Fun fact, I was trying displayplayers[0]->mo as if it was Lua like an absolute idiot.
|
||||
cam->angle = R_PointToAngle2(cam->x, cam->y, lastp->mo->x, lastp->mo->y);
|
||||
|
|
@ -3369,7 +3369,7 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
|
|||
if (P_CameraThinker(player, thiscam, resetcalled))
|
||||
return true;
|
||||
|
||||
lookback = ( player->cmd.buttons & BT_LOOKBACK );
|
||||
lookback = K_GetKartButtons(player) & BT_LOOKBACK;
|
||||
|
||||
camspeed = cv_cam_speed[num].value;
|
||||
camstill = cv_cam_still[num].value || player->seasaw; // RR: seasaws lock the camera so that it isn't disorienting.
|
||||
|
|
@ -3384,10 +3384,10 @@ boolean P_MoveChaseCamera(player_t *player, camera_t *thiscam, boolean resetcall
|
|||
camheight = FixedMul(mapheaderinfo[gamemap-1]->cameraHeight, cameraScale);
|
||||
|
||||
// For 2p SPLITSCREEN SPECIFICALLY:
|
||||
// The view is pretty narrow, so move it back 1/4th of the way towards default camera height.
|
||||
// The view is pretty narrow, so move it back 3/20 of the way towards default camera height.
|
||||
else {
|
||||
// CONS_Printf( "Camera values: %f / %f / %f \n", FixedToFloat(mapheaderinfo[gamemap-1]->cameraHeight), FixedToFloat(cv_cam_height[num].value), FixedToFloat(cameraScale) );
|
||||
camheight = FixedMul((mapheaderinfo[gamemap-1]->cameraHeight*3 + cv_cam_height[num].value)/4, cameraScale);
|
||||
camheight = FixedMul((mapheaderinfo[gamemap-1]->cameraHeight*17 + cv_cam_height[num].value*3)/20, cameraScale);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -4564,9 +4564,7 @@ void P_PlayerThink(player_t *player)
|
|||
|
||||
// Strength counts up to diminish fade.
|
||||
if (player->flashing && player->flashing < UINT16_MAX &&
|
||||
(player->spectator || !P_PlayerInPain(player)) &&
|
||||
// Battle: flashing tics do not decrease in the air
|
||||
(!(gametyperules & GTR_BUMPERS) || P_IsObjectOnGround(player->mo)))
|
||||
(player->spectator || !P_PlayerInPain(player)))
|
||||
{
|
||||
player->flashing--;
|
||||
}
|
||||
|
|
|
|||
10
src/sounds.c
10
src/sounds.c
|
|
@ -778,7 +778,7 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"kc30", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"kc31", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"kc32", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"kc33", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"kc33", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, //x8away
|
||||
{"kc34", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"kc35", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"kc36", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
|
|
@ -805,7 +805,7 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"kc4b", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"kc4c", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Pop-shot"},
|
||||
{"kc4d", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, "Power up"},
|
||||
{"kc4e", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"kc4e", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, //x8away
|
||||
{"kc4f", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"kc50", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"kc51", false, 64, 64, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
|
|
@ -1432,18 +1432,18 @@ sfxinfo_t S_sfx[NUMSFX] =
|
|||
{"gshaf", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"gshb0", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"gshb1", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"gshb2", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"gshb2", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, //x8away
|
||||
{"gshb3", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"gshb4", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"gshb5", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"gshb6", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"gshb7", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"gshb8", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"gshb9", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"gshb9", false, 64, 8, -1, NULL, 0, -1, -1, LUMPERROR, ""}, //x4away
|
||||
{"gshba", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"gshbb", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"gshbc", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"gshbd", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"gshbd", false, 64, 16, -1, NULL, 0, -1, -1, LUMPERROR, ""}, //x8away
|
||||
{"gshbe", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"gshbf", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
{"gshc0a", false, 64, 0, -1, NULL, 0, -1, -1, LUMPERROR, ""},
|
||||
|
|
|
|||
|
|
@ -400,14 +400,14 @@ static void Y_CalculateMatchData(UINT8 rankingsmode, void (*comparison)(INT32))
|
|||
if (roundqueue.position == roundqueue.size-1)
|
||||
{
|
||||
// On A rank pace? Then you get a chance for S rank!
|
||||
gp_rank_e rankforline = K_CalculateGPGrade(&grandprixinfo.rank);
|
||||
fixed_t rankforline = K_CalculateGPPercent(&grandprixinfo.rank);
|
||||
|
||||
data.showrank = (rankforline >= GRADE_A);
|
||||
data.showrank = (rankforline >= SEALED_STAR_ENTRY);
|
||||
|
||||
data.linemeter =
|
||||
(std::min(rankforline, GRADE_A)
|
||||
(std::min(rankforline, SEALED_STAR_ENTRY)
|
||||
* (2 * TICRATE)
|
||||
) / GRADE_A;
|
||||
) / SEALED_STAR_ENTRY;
|
||||
|
||||
// G_NextMap will float you to rank-restricted stages on Master wins.
|
||||
// Fudge the rank display.
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue