Merge branch 'battle-fixes-friday' into 'master'

Battle Fixes Friday

Closes #901, #890, #865, #891, #883, #887, #885, and #888

See merge request KartKrew/Kart!1829
This commit is contained in:
Oni 2024-01-13 02:21:19 +00:00
commit 1aaac393c1
15 changed files with 281 additions and 49 deletions

View file

@ -2802,9 +2802,9 @@ mapthing_t *G_FindMapStart(INT32 playernum)
if (K_PodiumSequence() == true) if (K_PodiumSequence() == true)
spawnpoint = G_FindPodiumStart(playernum); spawnpoint = G_FindPodiumStart(playernum);
// -- Time Attack -- // -- Time Attack / Battle duels --
// Order: Race->DM->CTF // Order: Race->DM->CTF
else if (K_TimeAttackRules() == true) else if (K_TimeAttackRules() == true || ((gametyperules & GTR_BATTLESTARTS) && inDuel))
spawnpoint = G_FindRaceStartOrFallback(playernum); spawnpoint = G_FindRaceStartOrFallback(playernum);
// -- CTF -- // -- CTF --

View file

@ -43,16 +43,15 @@ void K_drawKart2PTimestamp(void)
void K_drawKart4PTimestamp(void) void K_drawKart4PTimestamp(void)
{ {
Draw row = Draw(154, 0).flags(kHudFlags).font(Draw::Font::kZVote).align(Draw::Align::kCenter); Draw row = Draw(159, 0).flags(kHudFlags).font(Draw::Font::kZVote).align(Draw::Align::kCenter);
auto draw = [](const Draw& row, tic_t time) auto draw = [](const Draw& row, tic_t time)
{ {
row.patch("K_STTIMS"); row.text("{:03}", time / TICRATE);
row.xy(5, 12).text("{:03}", time / TICRATE);
}; };
auto time_of = [](int k) -> tic_t { return k <= r_splitscreen ? player_timer(&players[displayplayers[k]]) : 0u; }; auto time_of = [](int k) -> tic_t { return k <= r_splitscreen ? player_timer(&players[displayplayers[k]]) : 0u; };
draw(row.y(1).flags(V_SNAPTOTOP), std::max(time_of(0), time_of(1))); draw(row.y(1).flags(V_SNAPTOTOP), std::max(time_of(0), time_of(1)));
draw(row.y(178).flags(V_SNAPTOBOTTOM), std::max(time_of(2), time_of(3))); draw(row.y(191).flags(V_SNAPTOBOTTOM), std::max(time_of(2), time_of(3)));
} }

View file

@ -5601,7 +5601,7 @@ state_t states[NUMSTATES] =
{SPR_UFOS, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SPECIAL_UFO_STEM {SPR_UFOS, 0, -1, {NULL}, 0, 0, S_NULL}, // S_SPECIAL_UFO_STEM
{SPR_GBOM, FF_ANIMATE, -1, {NULL}, 3, 1, S_NULL}, // S_GACHABOM {SPR_GBOM, FF_ANIMATE, -1, {NULL}, 3, 1, S_NULL}, // S_GACHABOM
{SPR_GBOM, FF_INVERT, 2, {NULL}, 0, 0, S_NULL}, // S_GACHABOM_DEAD {SPR_GBOM, FF_INVERT, 175, {NULL}, 0, 0, S_NULL}, // S_GACHABOM_DEAD
{SPR_NULL, 0, 1, {NULL}, 0, 0, S_GACHABOM_EXPLOSION_2}, {SPR_NULL, 0, 1, {NULL}, 0, 0, S_GACHABOM_EXPLOSION_2},
{SPR_GCHX, 0|FF_PAPERSPRITE|FF_ANIMATE, 14, {NULL}, 6, 2, S_GACHABOM_EXPLOSION_3A}, // S_GACHABOM_EXPLOSION_2 {SPR_GCHX, 0|FF_PAPERSPRITE|FF_ANIMATE, 14, {NULL}, 6, 2, S_GACHABOM_EXPLOSION_3A}, // S_GACHABOM_EXPLOSION_2

View file

@ -150,7 +150,7 @@ void K_CheckBumpers(void)
} }
} }
if (numingame - eliminated <= 2 && battleovertime.enabled && battleovertime.radius <= BARRIER_MIN_RADIUS) if (numingame - eliminated == 2 && battleovertime.enabled && battleovertime.radius <= BARRIER_MIN_RADIUS)
{ {
Music_Stop("battle_overtime"); Music_Stop("battle_overtime");
S_StartSound(NULL, sfx_kc4b); // Loud noise helps mask transition S_StartSound(NULL, sfx_kc4b); // Loud noise helps mask transition

View file

@ -860,7 +860,8 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim)
attacker->momx = attacker->momy = 0; attacker->momx = attacker->momy = 0;
P_Thrust(attacker, thrangle, mapobjectscale*7); P_Thrust(attacker, thrangle, mapobjectscale*7);
P_DamageMobj(attacker, victim, victim, 1, DMG_TUMBLE); // target is inflictor: hack to let invincible players lose to guard
P_DamageMobj(attacker, attacker, victim, 1, DMG_TUMBLE);
// A little extra juice, so successful reads are usually positive or zero on spheres. // A little extra juice, so successful reads are usually positive or zero on spheres.
victimPlayer->spheres = std::min(victimPlayer->spheres + 10, 40); victimPlayer->spheres = std::min(victimPlayer->spheres + 10, 40);
@ -883,7 +884,7 @@ boolean K_InstaWhipCollide(mobj_t *shield, mobj_t *victim)
P_PlayVictorySound(victim); P_PlayVictorySound(victim);
P_DamageMobj(attacker, victim, victim, 1, DMG_TUMBLE); P_DamageMobj(attacker, attacker, victim, 1, DMG_TUMBLE);
S_StartSound(victim, sfx_mbv92); S_StartSound(victim, sfx_mbv92);
K_AddHitLag(attacker, victimHitlag, true); K_AddHitLag(attacker, victimHitlag, true);

View file

@ -10,8 +10,11 @@
/// \brief HUD drawing functions exclusive to Kart /// \brief HUD drawing functions exclusive to Kart
#include <algorithm> #include <algorithm>
#include <array>
#include <vector> #include <vector>
#include "v_draw.hpp"
#include "k_hud.h" #include "k_hud.h"
#include "k_kart.h" #include "k_kart.h"
#include "k_battle.h" #include "k_battle.h"
@ -111,6 +114,10 @@ static patch_t *kp_rankemerald;
static patch_t *kp_rankemeraldflash; static patch_t *kp_rankemeraldflash;
static patch_t *kp_rankemeraldback; static patch_t *kp_rankemeraldback;
static patch_t *kp_goal[2][2]; // [skull][4p]
static patch_t *kp_goalrod[2]; // [4p]
static patch_t *kp_goaltext1p;
static patch_t *kp_battlewin; static patch_t *kp_battlewin;
static patch_t *kp_battlecool; static patch_t *kp_battlecool;
static patch_t *kp_battlelose; static patch_t *kp_battlelose;
@ -452,6 +459,15 @@ void K_LoadKartHUDGraphics(void)
HU_UpdatePatch(&kp_rankemeraldflash, "K_EMERW"); HU_UpdatePatch(&kp_rankemeraldflash, "K_EMERW");
HU_UpdatePatch(&kp_rankemeraldback, "K_EMERBK"); HU_UpdatePatch(&kp_rankemeraldback, "K_EMERBK");
// Battle goal
HU_UpdatePatch(&kp_goal[0][0], "K_ST1GLA");
HU_UpdatePatch(&kp_goal[1][0], "K_ST1GLB");
HU_UpdatePatch(&kp_goal[0][1], "K_ST4GLA");
HU_UpdatePatch(&kp_goal[1][1], "K_ST4GLB");
HU_UpdatePatch(&kp_goalrod[0], "K_ST1GLD");
HU_UpdatePatch(&kp_goalrod[1], "K_ST4GLD");
HU_UpdatePatch(&kp_goaltext1p, "K_ST1GLC");
// Battle graphics // Battle graphics
HU_UpdatePatch(&kp_battlewin, "K_BWIN"); HU_UpdatePatch(&kp_battlewin, "K_BWIN");
HU_UpdatePatch(&kp_battlecool, "K_BCOOL"); HU_UpdatePatch(&kp_battlecool, "K_BCOOL");
@ -1228,6 +1244,7 @@ static void K_initKartHUD(void)
STCD_Y = BASEVIDHEIGHT/4; STCD_Y = BASEVIDHEIGHT/4;
MINI_X -= 16;
MINI_Y = (BASEVIDHEIGHT/2); MINI_Y = (BASEVIDHEIGHT/2);
if (r_splitscreen > 1) // 3P/4P Small Splitscreen if (r_splitscreen > 1) // 3P/4P Small Splitscreen
@ -2196,24 +2213,42 @@ static void K_DrawKartPositionNum(UINT8 num)
); );
} }
static boolean K_drawKartPositionFaces(void) struct PositionFacesInfo
{ {
// FACE_X = 15; // 15 INT32 ranklines = 0;
// FACE_Y = 72; // 72 INT32 strank = -1;
INT32 numplayersingame = 0;
INT32 rankplayer[MAXPLAYERS] = {};
INT32 Y = FACE_Y-9; // -9 to offset where it's being drawn if there are more than one PositionFacesInfo();
INT32 i, j, ranklines, strank = -1; void draw_1p();
boolean completed[MAXPLAYERS]; void draw_4p_battle(int x, int y, INT32 flags);
INT32 rankplayer[MAXPLAYERS];
INT32 bumperx, emeraldx, numplayersingame = 0;
INT32 xoff, yoff, flipflag = 0;
UINT8 workingskin;
UINT8 *colormap;
UINT32 skinflags;
ranklines = 0; UINT32 top_score() const { return players[rankplayer[0]].roundscore; }
memset(completed, 0, sizeof (completed)); bool near_goal() const { return g_pointlimit - 5 <= top_score(); }
memset(rankplayer, 0, sizeof (rankplayer)); skincolornum_t vomit_color() const
{
if (!near_goal())
{
return SKINCOLOR_NONE;
}
constexpr int kCycleSpeed = 4;
constexpr std::array<skincolornum_t, 6> kColors = {
SKINCOLOR_RED,
SKINCOLOR_VOMIT,
SKINCOLOR_YELLOW,
SKINCOLOR_GREEN,
SKINCOLOR_JET,
SKINCOLOR_MOONSET,
};
return kColors[leveltime / kCycleSpeed % kColors.size()];
}
};
PositionFacesInfo::PositionFacesInfo()
{
INT32 i, j;
for (i = 0; i < MAXPLAYERS; i++) for (i = 0; i < MAXPLAYERS; i++)
{ {
@ -2226,10 +2261,9 @@ static boolean K_drawKartPositionFaces(void)
} }
if (numplayersingame <= 1) if (numplayersingame <= 1)
return true; return;
if (!LUA_HudEnabled(hud_minirankings)) boolean completed[MAXPLAYERS] = {};
return false; // Don't proceed but still return true for free play above if HUD is disabled.
for (j = 0; j < numplayersingame; j++) for (j = 0; j < numplayersingame; j++)
{ {
@ -2258,8 +2292,24 @@ static boolean K_drawKartPositionFaces(void)
ranklines++; ranklines++;
} }
}
if (ranklines < 5) void PositionFacesInfo::draw_1p()
{
// FACE_X = 15; // 15
// FACE_Y = 72; // 72
INT32 Y = FACE_Y-9; // -9 to offset where it's being drawn if there are more than one
INT32 i, j;
INT32 bumperx, emeraldx;
INT32 xoff, yoff, flipflag = 0;
UINT8 workingskin;
UINT8 *colormap;
UINT32 skinflags;
if (gametyperules & GTR_POINTLIMIT) // playing battle
Y += (9*5) - 5; // <-- arbitrary calculation
else if (ranklines < 5)
Y += (9*ranklines); Y += (9*ranklines);
else else
Y += (9*5); Y += (9*5);
@ -2267,7 +2317,54 @@ static boolean K_drawKartPositionFaces(void)
ranklines--; ranklines--;
i = ranklines; i = ranklines;
if ((gametyperules & GTR_POINTLIMIT) || strank <= 2) // too close to the top, or playing battle, or a spectator? would have had (strank == -1) called out, but already caught by (strank <= 2) if (gametyperules & GTR_POINTLIMIT) // playing battle
{
// 3 lines max in Battle
if (i > 2)
i = 2;
ranklines = 0;
// You must appear on the leaderboard, even if you don't rank top 3
if (strank > i)
{
strank = i;
rankplayer[strank] = stplyr - players;
}
// Draw GOAL
UINT8 skull = g_pointlimit <= stplyr->roundscore;
INT32 height = i*18;
INT32 GOAL_Y = Y-height;
colormap = nullptr;
if (skincolornum_t vomit = vomit_color())
{
colormap = R_GetTranslationColormap(TC_DEFAULT, vomit, GTC_CACHE);
}
V_DrawMappedPatch(FACE_X-5, GOAL_Y-32, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, kp_goal[skull][0], colormap);
// Flashing KO
if (skull)
{
if (leveltime % 16 < 8)
V_DrawScaledPatch(FACE_X-5, GOAL_Y-32, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, kp_goaltext1p);
}
else
{
using srb2::Draw;
Draw(FACE_X+8.5, GOAL_Y-15)
.font(Draw::Font::kZVote)
.align(Draw::Align::kCenter)
.flags(V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT)
.text("{:02}", g_pointlimit);
}
// Line cutting behind rank faces
V_DrawScaledPatch(FACE_X+6, GOAL_Y, V_HUDTRANS|V_SLIDEIN|V_SNAPTOLEFT, kp_goalrod[0]);
}
else if (strank <= 2) // too close to the top, or a spectator? would have had (strank == -1) called out, but already caught by (strank <= 2)
{ {
if (i > 4) // could be both... if (i > 4) // could be both...
i = 4; i = 4;
@ -2400,6 +2497,82 @@ static boolean K_drawKartPositionFaces(void)
Y -= 18; Y -= 18;
} }
}
void PositionFacesInfo::draw_4p_battle(int x, int y, INT32 flags)
{
using srb2::Draw;
Draw row = Draw(x, y).flags(V_HUDTRANS | V_SLIDEIN | flags).font(Draw::Font::kPing);
UINT8 skull = []
{
int party = G_PartySize(consoleplayer);
for (int i = 0; i < party; ++i)
{
// Is any party member about to win?
if (g_pointlimit <= players[G_PartyMember(consoleplayer, i)].roundscore)
{
return 1;
}
}
return 0;
}();
skincolornum_t vomit = vomit_color();
(vomit ? row.colormap(vomit) : row).patch(kp_goal[skull][1]);
if (!skull)
{
row.xy(8.5, 5).align(Draw::Align::kCenter).text("{:02}", g_pointlimit);
}
row.xy(7, 18).patch(kp_goalrod[1]);
auto head = [&](Draw col, int i)
{
const player_t& p = players[rankplayer[i]];
col.colormap(p.skin, static_cast<skincolornum_t>(p.skincolor)).patch(faceprefix[p.skin][FACE_MINIMAP]);
bool dance = g_pointlimit <= p.roundscore;
bool flash = dance && leveltime % 8 < 4;
(
flash ?
col.xy(8, 6).colorize(SKINCOLOR_TANGERINE).flags(V_STRINGDANCE) :
col.xy(8, 6).flags(dance ? V_STRINGDANCE : 0)
).text("{:02}", p.roundscore);
};
// Draw top 2 players
head(row.xy(2, 31), 1);
head(row.xy(2, 18), 0);
}
static boolean K_drawKartPositionFaces(void)
{
PositionFacesInfo state{};
if (state.numplayersingame <= 1)
return true;
if (!LUA_HudEnabled(hud_minirankings))
return false; // Don't proceed but still return true for free play above if HUD is disabled.
switch (r_splitscreen)
{
case 0:
state.draw_1p();
break;
case 1:
state.draw_4p_battle(292, 78, V_SNAPTORIGHT);
break;
case 2:
case 3:
state.draw_4p_battle(152, 9, V_SNAPTOTOP);
state.draw_4p_battle(152, 147, V_SNAPTOBOTTOM);
break;
}
return false; return false;
} }
@ -5507,6 +5680,11 @@ void K_drawKartHUD(void)
{ {
K_drawKart2PTimestamp(); K_drawKart2PTimestamp();
} }
if (viewnum == r_splitscreen && gametyperules & GTR_POINTLIMIT)
{
K_drawKartPositionFaces();
}
} }
else if (viewnum == r_splitscreen) else if (viewnum == r_splitscreen)
{ {
@ -5514,6 +5692,11 @@ void K_drawKartHUD(void)
{ {
K_drawKart4PTimestamp(); K_drawKart4PTimestamp();
} }
if (gametyperules & GTR_POINTLIMIT)
{
K_drawKartPositionFaces();
}
} }
} }
@ -5550,7 +5733,7 @@ void K_drawKartHUD(void)
} }
else if (freecam) else if (freecam)
; ;
else if ((gametyperules & GTR_POWERSTONES)) else if ((gametyperules & GTR_POWERSTONES) && !K_PlayerTallyActive(stplyr))
{ {
if (!battleprisons) if (!battleprisons)
K_drawKartEmeralds(); K_drawKartEmeralds();

View file

@ -82,7 +82,7 @@ struct TargetTracking
return player_emeralds_color(); return player_emeralds_color();
case MT_SUPER_FLICKY: case MT_SUPER_FLICKY:
return static_cast<skincolornum_t>(Obj_SuperFlickyOwner(mobj)->color); return Obj_SuperFlickyOwner(mobj) ? static_cast<skincolornum_t>(Obj_SuperFlickyOwner(mobj)->color) : SKINCOLOR_NONE;
default: default:
return SKINCOLOR_NONE; return SKINCOLOR_NONE;

View file

@ -3550,11 +3550,6 @@ UINT16 K_GetKartFlashing(const player_t *player)
{ {
UINT16 tics = flashingtics; UINT16 tics = flashingtics;
if (gametyperules & GTR_BUMPERS)
{
return 0;
}
if (player == NULL) if (player == NULL)
{ {
return tics; return tics;
@ -3564,6 +3559,16 @@ UINT16 K_GetKartFlashing(const player_t *player)
return tics; return tics;
} }
void K_UpdateDamageFlashing(player_t *player, UINT16 tics)
{
if (gametyperules & GTR_BUMPERS)
{
return;
}
player->flashing = tics;
}
boolean K_PlayerShrinkCheat(const player_t *player) boolean K_PlayerShrinkCheat(const player_t *player)
{ {
return ( return (
@ -3826,7 +3831,7 @@ void K_DoGuardBreak(mobj_t *t1, mobj_t *t2) {
if (P_PlayerInPain(t2->player)) if (P_PlayerInPain(t2->player))
return; return;
t1->player->instaWhipCharge = 0; t1->player->defenseLockout = 1;
S_StartSound(t1, sfx_gbrk); S_StartSound(t1, sfx_gbrk);
K_AddHitLag(t1, 24, true); K_AddHitLag(t1, 24, true);
@ -8391,9 +8396,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
if (player->spinouttimer != 0) if (player->spinouttimer != 0)
{ {
if (( player->spinouttype & KSPIN_IFRAMES ) == 0) if (( player->spinouttype & KSPIN_IFRAMES ) == 0)
player->flashing = 0; K_UpdateDamageFlashing(player, 0);
else else
player->flashing = K_GetKartFlashing(player); K_UpdateDamageFlashing(player, K_GetKartFlashing(player));
} }
if (player->spinouttimer) if (player->spinouttimer)
@ -8569,7 +8574,9 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
S_StartSound(player->mo, sfx_s1af); S_StartSound(player->mo, sfx_s1af);
player->oldGuard = true; player->oldGuard = true;
player->instaWhipCharge = 0;
if (!K_PowerUpRemaining(player, POWERUP_BARRIER))
player->instaWhipCharge = 0;
} }
else if (player->oldGuard) else if (player->oldGuard)
{ {
@ -10785,6 +10792,11 @@ boolean K_PlayerGuard(const player_t *player)
return false; return false;
} }
if (P_PlayerInPain(player) == true)
{
return false;
}
if (K_PowerUpRemaining(player, POWERUP_BARRIER)) if (K_PowerUpRemaining(player, POWERUP_BARRIER))
{ {
return true; return true;
@ -10809,7 +10821,6 @@ boolean K_PlayerGuard(const player_t *player)
if (K_PressingEBrake(player) == true if (K_PressingEBrake(player) == true
&& (player->drift == 0 || P_IsObjectOnGround(player->mo) == false) && (player->drift == 0 || P_IsObjectOnGround(player->mo) == false)
&& P_PlayerInPain(player) == false
&& player->spindashboost == 0 && player->spindashboost == 0
&& player->nocontrol == 0) && player->nocontrol == 0)
{ {
@ -11676,10 +11687,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
else else
{ {
player->instaWhipCharge = 0; player->instaWhipCharge = 0;
player->defenseLockout = PUNISHWINDOW;
if (!K_PowerUpRemaining(player, POWERUP_BARRIER)) if (!K_PowerUpRemaining(player, POWERUP_BARRIER))
{ {
player->defenseLockout = INSTAWHIP_CHARGETIME; player->defenseLockout = PUNISHWINDOW;
} }
S_StartSound(player->mo, sfx_iwhp); S_StartSound(player->mo, sfx_iwhp);

View file

@ -192,6 +192,7 @@ fixed_t K_GetKartSpeedFromStat(UINT8 kartspeed);
fixed_t K_GetKartSpeed(const player_t *player, boolean doboostpower, boolean dorubberbanding); fixed_t K_GetKartSpeed(const player_t *player, boolean doboostpower, boolean dorubberbanding);
fixed_t K_GetKartAccel(const player_t *player); fixed_t K_GetKartAccel(const player_t *player);
UINT16 K_GetKartFlashing(const player_t *player); UINT16 K_GetKartFlashing(const player_t *player);
void K_UpdateDamageFlashing(player_t *player, UINT16 tics);
boolean K_PlayerShrinkCheat(const player_t *player); boolean K_PlayerShrinkCheat(const player_t *player);
void K_UpdateShrinkCheat(player_t *player); void K_UpdateShrinkCheat(player_t *player);
boolean K_KartKickstart(const player_t *player); boolean K_KartKickstart(const player_t *player);

View file

@ -284,12 +284,13 @@ boolean Obj_OrbinautJawzCollide(mobj_t *t1, mobj_t *t2)
S_StartSound(t1, t1->info->deathsound); S_StartSound(t1, t1->info->deathsound);
P_KillMobj(t1, t2, t2, DMG_NORMAL); P_KillMobj(t1, t2, t2, DMG_NORMAL);
if (t1->type == MT_GACHABOM) if (t1->type == MT_GACHABOM && !P_MobjWasRemoved(orbinaut_owner(t1)))
{ {
// Instead of flying out at an angle when // Instead of flying out at an angle when
// destroyed, spawn an explosion and eventually // destroyed, spawn an explosion and eventually
// return to sender. The original Gachabom will be // return to sender. The original Gachabom will be
// removed next tic (see deathstate). // removed next tic (see deathstate).
t1->tics = 2;
Obj_SpawnGachaBomRebound(t1, orbinaut_owner(t1)); Obj_SpawnGachaBomRebound(t1, orbinaut_owner(t1));
} }
else else

View file

@ -273,6 +273,8 @@ struct Flicky : mobj_t
bool stunned() const { return mode() == Mode::kStunned || mode() == Mode::kWeak; } bool stunned() const { return mode() == Mode::kStunned || mode() == Mode::kWeak; }
bool owner_in_pain() const { return source()->player && P_PlayerInPain(source()->player); }
void light_up(bool n) void light_up(bool n)
{ {
if (n) if (n)
@ -613,6 +615,25 @@ struct Flicky : mobj_t
S_StartSound(this, sfx_s3k9f); S_StartSound(this, sfx_s3k9f);
} }
void try_nerf()
{
if (owner_in_pain())
{
mode(Mode::kWeak);
delay(2);
nerf();
flags |= MF_NOGRAVITY;
}
}
void preserve_nerf()
{
if (owner_in_pain())
{
delay(1);
}
}
void whip() void whip()
{ {
reflect(); reflect();
@ -772,6 +793,7 @@ void Obj_SuperFlickyThink(mobj_t* mobj)
break; break;
case Flicky::Mode::kHunting: case Flicky::Mode::kHunting:
x->try_nerf();
x->chase(); x->chase();
break; break;
@ -779,6 +801,7 @@ void Obj_SuperFlickyThink(mobj_t* mobj)
break; break;
case Flicky::Mode::kWeak: case Flicky::Mode::kWeak:
x->preserve_nerf();
x->chase(); x->chase();
break; break;
} }

View file

@ -402,6 +402,7 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
return; return;
K_GivePowerUp(player, special->threshold, special->movecount); K_GivePowerUp(player, special->threshold, special->movecount);
player->flashing = 2*TICRATE;
} }
else else
{ {
@ -3076,6 +3077,12 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
invincible = false; invincible = false;
} }
// Hack for instawhip-guard counter, lets invincible players lose to guard
if (inflictor == target)
{
invincible = false;
}
// TODO: doing this from P_DamageMobj limits punting to objects that damage the player. // TODO: doing this from P_DamageMobj limits punting to objects that damage the player.
// And it may be kind of yucky. // And it may be kind of yucky.
// But this is easier than accounting for every condition in PIT_CheckThing! // But this is easier than accounting for every condition in PIT_CheckThing!
@ -3334,7 +3341,7 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
if (type != DMG_STUMBLE && type != DMG_WHUMBLE) if (type != DMG_STUMBLE && type != DMG_WHUMBLE)
{ {
if (type != DMG_STING) if (type != DMG_STING)
player->flashing = K_GetKartFlashing(player); K_UpdateDamageFlashing(player, K_GetKartFlashing(player));
player->ringburst += ringburst; player->ringburst += ringburst;

View file

@ -4411,7 +4411,9 @@ void P_PlayerThink(player_t *player)
// Strength counts up to diminish fade. // Strength counts up to diminish fade.
if (player->flashing && player->flashing < UINT16_MAX && if (player->flashing && player->flashing < UINT16_MAX &&
(player->spectator || !P_PlayerInPain(player))) (player->spectator || !P_PlayerInPain(player)) &&
// Battle: flashing tics do not decrease in the air
(!(gametyperules & GTR_BUMPERS) || P_IsObjectOnGround(player->mo)))
{ {
player->flashing--; player->flashing--;
} }

View file

@ -256,8 +256,8 @@ private:
static fixed_t font_width(Font font, INT32 flags, const char* string); static fixed_t font_width(Font font, INT32 flags, const char* string);
}; };
#include "v_draw_setter.hpp"
}; // namespace srb2 }; // namespace srb2
#include "v_draw_setter.hpp"
#endif // __V_DRAW_HPP__ #endif // __V_DRAW_HPP__

View file

@ -12,6 +12,9 @@
#include "r_draw.h" // R_GetTranslationColormap #include "r_draw.h" // R_GetTranslationColormap
namespace srb2
{
inline Draw::Chain& Draw::Chain::x(float x) inline Draw::Chain& Draw::Chain::x(float x)
{ {
x_ += x; x_ += x;
@ -115,4 +118,6 @@ inline Draw::Chain& Draw::Chain::colorize(skincolornum_t color)
return colormap(R_GetTranslationColormap(TC_RAINBOW, color, GTC_CACHE)); return colormap(R_GetTranslationColormap(TC_RAINBOW, color, GTC_CACHE));
} }
}; // namespace srb2
#endif // __V_DRAW_SETTER_HPP__ #endif // __V_DRAW_SETTER_HPP__