Merge branch 'battle-spectator-fix' into 'master'

Battle fixes for: spectators, whipping shields, S-Monitor, Super Flicky

Closes #869 and #848

See merge request KartKrew/Kart!1798
This commit is contained in:
Oni 2024-01-11 06:26:51 +00:00
commit 3ccdd42903
8 changed files with 110 additions and 49 deletions

View file

@ -802,6 +802,7 @@ consvar_t cv_capsuletest = OnlineCheat("capsuletest", "Off").values(capsuletest_
consvar_t cv_debugcheese = OnlineCheat("debugcheese", "Off").on_off().description("Disable checks that prevent farming item boxes"); consvar_t cv_debugcheese = OnlineCheat("debugcheese", "Off").on_off().description("Disable checks that prevent farming item boxes");
consvar_t cv_debugencorevote = OnlineCheat("debugencorevote", "Off").on_off().description("Force encore choice to appear on vote screen"); consvar_t cv_debugencorevote = OnlineCheat("debugencorevote", "Off").on_off().description("Force encore choice to appear on vote screen");
consvar_t cv_forcebots = OnlineCheat("forcebots", "No").yes_no().description("Force bots to appear, even in wrong game modes");
void ForceSkin_OnChange(void); void ForceSkin_OnChange(void);
consvar_t cv_forceskin = OnlineCheat("forcecharacter", "None").onchange(ForceSkin_OnChange).description("Force all players to use one character"); consvar_t cv_forceskin = OnlineCheat("forcecharacter", "None").onchange(ForceSkin_OnChange).description("Force all players to use one character");

View file

@ -44,6 +44,8 @@
#include "discord.h" // DRPC_UpdatePresence #include "discord.h" // DRPC_UpdatePresence
#include "i_net.h" // doomcom #include "i_net.h" // doomcom
extern "C" consvar_t cv_forcebots;
/*-------------------------------------------------- /*--------------------------------------------------
void K_SetBot(UINT8 playerNum, UINT8 skinnum, UINT8 difficulty, botStyle_e style) void K_SetBot(UINT8 playerNum, UINT8 skinnum, UINT8 difficulty, botStyle_e style)
@ -189,7 +191,7 @@ void K_UpdateMatchRaceBots(void)
} }
grabskins[usableskins] = MAXSKINS; grabskins[usableskins] = MAXSKINS;
if ((gametyperules & GTR_BOTS) == 0) if ((gametyperules & GTR_BOTS) == 0 && !cv_forcebots.value)
{ {
difficulty = 0; difficulty = 0;
} }

View file

@ -388,7 +388,7 @@ void K_UpdateGrandPrixBots(void)
continue; continue;
} }
players[i].spectator = !(gametyperules & GTR_BOTS) || (grandprixinfo.eventmode != GPEVENT_NONE); players[i].spectator = K_BotDefaultSpectator();
} }
if (grandprixinfo.wonround == false) if (grandprixinfo.wonround == false)
@ -901,6 +901,13 @@ boolean K_CanChangeRules(boolean allowdemos)
--------------------------------------------------*/ --------------------------------------------------*/
boolean K_BotDefaultSpectator(void) boolean K_BotDefaultSpectator(void)
{ {
extern consvar_t cv_forcebots;
if (cv_forcebots.value)
{
return false;
}
if (!(gametyperules & GTR_BOTS)) if (!(gametyperules & GTR_BOTS))
{ {
// This gametype does not support bots. // This gametype does not support bots.

View file

@ -224,6 +224,11 @@ bool is_player_tracking_target(player_t *player = stplyr)
return false; return false;
} }
if (player->spectator)
{
return false;
}
if (inDuel) if (inDuel)
{ {
// Always draw targets in 1v1 but don't draw player's // Always draw targets in 1v1 but don't draw player's

View file

@ -8603,7 +8603,7 @@ void K_KartPlayerThink(player_t *player, ticcmd_t *cmd)
} }
} }
if (player->invincibilitytimer && onground == true) if (player->invincibilitytimer && (onground == true || K_PowerUpRemaining(player, POWERUP_SMONITOR)))
player->invincibilitytimer--; player->invincibilitytimer--;
if (!player->invincibilitytimer) if (!player->invincibilitytimer)

View file

@ -34,6 +34,7 @@
#include "s_sound.h" #include "s_sound.h"
#include "st_stuff.h" #include "st_stuff.h"
#include "r_fps.h" #include "r_fps.h"
#include "g_party.h"
boolean level_tally_t::UseBonuses(void) boolean level_tally_t::UseBonuses(void)
{ {
@ -1382,7 +1383,8 @@ void K_TickPlayerTally(player_t *player)
void K_DrawPlayerTally(void) void K_DrawPlayerTally(void)
{ {
stplyr->tally.Draw(); // Draw the observer player's tally, not whoever they may be spectating
players[G_PartyMember(consoleplayer, R_GetViewNumber())].tally.Draw();
} }
boolean K_PlayerTallyActive(player_t *player) boolean K_PlayerTallyActive(player_t *player)

View file

@ -9,6 +9,8 @@
//----------------------------------------------------------------------------- //-----------------------------------------------------------------------------
/// \brief Super Flicky power-up, hunts other players /// \brief Super Flicky power-up, hunts other players
#include <algorithm>
#include "../d_player.h" #include "../d_player.h"
#include "../doomdef.h" #include "../doomdef.h"
#include "../g_game.h" #include "../g_game.h"
@ -72,6 +74,8 @@ constexpr tic_t kBlockTime = 5*TICRATE;
constexpr int kRiseTime = 1*TICRATE; constexpr int kRiseTime = 1*TICRATE;
constexpr int kRiseSpeed = 4; constexpr int kRiseSpeed = 4;
constexpr int kMinKnockback = 50;
// TODO: skincolor must be updated to 2.2 palette // TODO: skincolor must be updated to 2.2 palette
constexpr skincolornum_t kSuperStart = SKINCOLOR_SUPERGOLD1; constexpr skincolornum_t kSuperStart = SKINCOLOR_SUPERGOLD1;
constexpr skincolornum_t kSuperEnd = SKINCOLOR_SUPERGOLD5; constexpr skincolornum_t kSuperEnd = SKINCOLOR_SUPERGOLD5;
@ -200,7 +204,6 @@ struct Controller : mobj_t
} }
void search(); void search();
void range_check();
void collect(); void collect();
}; };
@ -315,6 +318,12 @@ struct Flicky : mobj_t
} }
else else
{ {
if (stunned())
{
unnerf();
mode(Mode::kHunting);
}
if (chasing() != next_target()) if (chasing() != next_target())
{ {
chasing(next_target()); chasing(next_target());
@ -322,15 +331,6 @@ struct Flicky : mobj_t
S_StartSound(this, sfx_fhurt2); S_StartSound(this, sfx_fhurt2);
} }
if (stunned())
{
light_up(true);
flags = info->flags;
mode(Mode::kHunting);
S_StartSound(this, sfx_s3k9f);
}
} }
} }
@ -385,6 +385,67 @@ struct Flicky : mobj_t
K_MatchGenericExtraFlags(fast, this); K_MatchGenericExtraFlags(fast, this);
} }
void range_check()
{
if (!chasing())
{
return;
}
if (FixedHypot(source()->x - chasing()->x, source()->y - chasing()->y) < kScaredRadius * mapobjectscale)
{
return;
}
if (chasing()->player)
{
P_SetTarget(&chasing()->player->flickyAttacker, nullptr);
}
next_target(nullptr);
chasing(nullptr);
if (controller()->mode() != Controller::Mode::kReturning)
{
for (Flicky* x = controller()->flicky(); x; x = x->next())
{
if (x != this)
{
continue;
}
controller()->chasing(nullptr);
controller()->mode(Controller::Mode::kReturning);
}
}
}
void relink()
{
Flicky* prev = nullptr;
for (Flicky* x = controller()->flicky(); x; x = x->next())
{
if (x == this)
{
return;
}
prev = x;
}
if (prev)
{
prev->next(this);
}
else
{
controller()->flicky(this);
}
next(nullptr);
}
void chase() void chase()
{ {
if (controller()->ending()) if (controller()->ending())
@ -392,6 +453,8 @@ struct Flicky : mobj_t
return; return;
} }
range_check();
vector3_t pos = chasing() ? vector3_t{chasing()->x, chasing()->y, P_GetMobjFeet(chasing())} : orbit_position(); vector3_t pos = chasing() ? vector3_t{chasing()->x, chasing()->y, P_GetMobjFeet(chasing())} : orbit_position();
angle_t th = R_PointToAngle2(x, y, pos.x, pos.y); angle_t th = R_PointToAngle2(x, y, pos.x, pos.y);
@ -448,7 +511,9 @@ struct Flicky : mobj_t
{ {
if (AngleDelta(th, R_PointToAngle2(x + momx, y + momy, pos.x, pos.y)) > ANG1) if (AngleDelta(th, R_PointToAngle2(x + momx, y + momy, pos.x, pos.y)) > ANG1)
{ {
unnerf();
mode(Mode::kReserved); mode(Mode::kReserved);
relink();
controller()->collect(); controller()->collect();
} }
else else
@ -506,7 +571,7 @@ struct Flicky : mobj_t
if (P_DamageMobj(mobj, this, source(), 1, DMG_NORMAL)) if (P_DamageMobj(mobj, this, source(), 1, DMG_NORMAL))
{ {
P_InstaThrust(mobj, K_MomentumAngleReal(this), FixedHypot(momx, momy)); P_InstaThrust(mobj, K_MomentumAngleReal(this), std::max(FixedHypot(momx, momy), kMinKnockback * mapobjectscale));
K_StumblePlayer(mobj->player); K_StumblePlayer(mobj->player);
mobj->player->spinouttimer = 1; // need invulnerability for one tic mobj->player->spinouttimer = 1; // need invulnerability for one tic
@ -540,6 +605,14 @@ struct Flicky : mobj_t
flags &= ~(MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT); flags &= ~(MF_NOGRAVITY|MF_NOCLIP|MF_NOCLIPHEIGHT);
} }
void unnerf()
{
light_up(true);
flags = info->flags;
S_StartSound(this, sfx_s3k9f);
}
void whip() void whip()
{ {
reflect(); reflect();
@ -641,7 +714,7 @@ void Controller::search()
flicky(flicky()->next()); flicky(flicky()->next());
} }
chasing(nearestMobj); chasing(flicky() ? nearestMobj : nullptr);
mode(Mode::kEnRoute); mode(Mode::kEnRoute);
// Update entire swarm // Update entire swarm
@ -653,39 +726,8 @@ void Controller::search()
} }
} }
void Controller::range_check()
{
if (!chasing())
{
return;
}
if (FixedHypot(source()->x - chasing()->x, source()->y - chasing()->y) < kScaredRadius * mapobjectscale)
{
return;
}
if (chasing()->player)
{
P_SetTarget(&chasing()->player->flickyAttacker, nullptr);
}
chasing(nullptr);
mode(Mode::kReturning);
for (Flicky* x = flicky(); x; x = x->next())
{
x->next_target(nullptr);
}
}
void Controller::collect() void Controller::collect()
{ {
if (mode() != Mode::kReturning)
{
return;
}
// Resume searching once all Flickys return // Resume searching once all Flickys return
for (Flicky* x = flicky(); x; x = x->next()) for (Flicky* x = flicky(); x; x = x->next())
{ {
@ -774,11 +816,9 @@ void Obj_SuperFlickyControllerThink(mobj_t* mobj)
break; break;
case Controller::Mode::kEnRoute: case Controller::Mode::kEnRoute:
x->range_check();
break; break;
case Controller::Mode::kAttached: case Controller::Mode::kAttached:
x->range_check();
x->search(); x->search();
break; break;

View file

@ -3327,6 +3327,10 @@ boolean P_DamageMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, INT32 da
K_PlayPainSound(target, source); K_PlayPainSound(target, source);
} }
else if (inflictor && inflictor->type == MT_INSTAWHIP)
{
K_PopPlayerShield(player);
}
if (gametyperules & GTR_BUMPERS) if (gametyperules & GTR_BUMPERS)
player->spheres = min(player->spheres + 10, 40); player->spheres = min(player->spheres + 10, 40);