Add (mostly) finalized visuals for the Arrow Bullet

Adds an 'arrowbullet' parameter to player_t; most of the general precautions for that have been taken
This commit is contained in:
yamamama 2025-12-02 19:56:23 -05:00
parent 071478a6b9
commit 0aa54559f9
9 changed files with 96 additions and 3 deletions

View file

@ -669,6 +669,7 @@ struct player_t
INT16 altshrinktimeshit; // (Alt. Shrink) How many times were you flipped over while shrunk?
INT16 growcancel; // Duration of grow canceling
INT16 squishedtimer; // Duration of being squished
mobj_t *arrowbullet; // (Alt. Shrink) Arrow Bullet aura visual
UINT16 rocketsneakertimer; // Rocket Sneaker duration timer

View file

@ -650,5 +650,8 @@ _(SSWB)
_(GSPR)
_(SSWG)
// Arrow Bullet
_(AWBT)
// First person view sprites; this is a sprite so that it can be replaced by a specialized MD2 draw later
_(VIEW)

View file

@ -3618,3 +3618,6 @@ _(GHORIZ2)
_(GHORIZ3)
_(GHORIZ4)
// Arrow Bullet
_(ALTSHRINK_ARROWBULLET)

View file

@ -1407,7 +1407,7 @@ void K_SpawnNormalSpeedLines(player_t *player)
else if (player->tripwireLeniency)
{
// Make it pink+blue+big when you can go through tripwire
fast->color = (leveltime & 1) ? SKINCOLOR_LILAC : SKINCOLOR_JAWZ;
fast->color = (K_IsAltShrunk(player)) ? SKINCOLOR_PERIWINKLE : ((leveltime & 1) ? SKINCOLOR_LILAC : SKINCOLOR_JAWZ);
fast->colorized = true;
fast->renderflags |= RF_ADD;
}
@ -10501,8 +10501,17 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
}
if (player->growshrinktimer == 0)
{
player->altshrinktimeshit = 0;
if (player->arrowbullet && (!P_MobjWasRemoved(player->arrowbullet)))
{
P_SetTarget(&player->arrowbullet->target, NULL);
P_RemoveMobj(player->arrowbullet);
P_SetTarget(&player->arrowbullet, NULL);
}
}
if (player->growshrinktimer <= 0)
player->growcancel = -1;

View file

@ -357,6 +357,7 @@ enum player_e
player_growshrinktimer,
player_growcancel,
player_squishedtimer,
player_arrowbullet,
player_rocketsneakertimer,
player_invincibilitytimer,
player_maxinvincibilitytime,
@ -575,6 +576,7 @@ static const char *const player_opt[] = {
"growshrinktimer",
"growcancel",
"squishedtimer",
"arrowbullet",
"rocketsneakertimer",
"invincibilitytimer",
"maxinvincibilitytime",
@ -1071,6 +1073,9 @@ static int player_get(lua_State *L)
case player_squishedtimer:
lua_pushinteger(L, plr->squishedtimer);
break;
case player_arrowbullet:
LUA_PushUserdata(L, plr->arrowbullet, META_MOBJ);
break;
case player_rocketsneakertimer:
lua_pushinteger(L, plr->rocketsneakertimer);
break;
@ -1836,6 +1841,8 @@ static int player_set(lua_State *L)
plr->squishedtimer = squishtimer;
break;
}
case player_arrowbullet:
return NOSET;
case player_rocketsneakertimer:
plr->rocketsneakertimer = luaL_checkinteger(L, 3);
break;

View file

@ -323,6 +323,7 @@ void P_RunOverlays(void);
#define OV_DONTXYSCALE 1<<2
#define OV_DONTROLL 1<<3
#define OV_DONTBAKEOFFSET 1<<4
#define OV_DONTCOPYANGLE 1<<5
void P_HandleMinecartSegments(mobj_t *mobj);
void P_MobjThinker(mobj_t *mobj);

View file

@ -6718,7 +6718,11 @@ void P_RunOverlays(void)
mo->eflags = (mo->eflags & ~MFE_VERTICALFLIP) | (mo->target->eflags & MFE_VERTICALFLIP);
mo->scale = mo->destscale = FixedMul(mo->target->scale, mo->movefactor);
mo->angle = (mo->target->player ? mo->target->player->drawangle : mo->target->angle) + mo->movedir;
if (!(mo->threshold & OV_DONTCOPYANGLE))
{
mo->angle = (mo->target->player ? mo->target->player->drawangle : mo->target->angle) + mo->movedir;
}
if (!(mo->threshold & OV_DONTSCREENOFFSET))
{

View file

@ -686,6 +686,8 @@ static void P_NetSyncPlayers(savebuffer_t *save)
SYNC(players[i].growshrinktimer);
SYNC(players[i].growcancel);
SYNC(players[i].altshrinktimeshit);
RSYNC(players[i].arrowbullet);
SYNC(players[i].rocketsneakertimer);
@ -3776,6 +3778,7 @@ static void P_RelinkPointers(savebuffer_t *save)
RELINK(&players[i].currentwaypoint);
RELINK(&players[i].nextwaypoint);
RELINK(&players[i].shieldtracer);
RELINK(&players[i].arrowbullet);
}
}

View file

@ -64,6 +64,8 @@
#include "k_items.h"
#include "g_party.h"
#include "m_easing.h" // Arrow Bullet aura
#include "acs/interface.h"
#ifdef HW3SOUND
@ -2315,10 +2317,70 @@ void P_MovePlayer(player_t *player)
K_SpawnSparkleTrail(player->mo);
}
#define MINAURAPCT (cv_kartaltshrink_arrowbulletthres.value - (FRACUNIT / 4))
#define AURA_DIFF (max(1, (FRACUNIT << 1) - MINAURAPCT))
// The Arrow Bullet aura should spawn before you actually enter the Arrow Bullet state.
if (cv_kartaltshrink_arrowbullet.value && K_IsAltShrunk(player) && (K_GetSpeedPercentage(player) >= MINAURAPCT))
{
fixed_t aura_scalar = FixedDiv(min(max(0, K_GetSpeedPercentage(player) - MINAURAPCT), (FRACUNIT << 1)), AURA_DIFF);
INT32 auravis = 10 - FixedMul(7, Easing_OutCubic(aura_scalar, 0, FRACUNIT));
auravis = min(9, max(1, auravis)) << FF_TRANSSHIFT;
fixed_t aura_scale = Easing_OutCubic(aura_scalar, FRACHALF, FRACUNIT + FRACHALF);
if ((!player->arrowbullet) || (P_MobjWasRemoved(player->arrowbullet)))
{
mobj_t *newbullet = P_SpawnMobjFromMobj(player->mo, 0, 0, 0, MT_OVERLAY);
P_SetMobjState(newbullet, S_ALTSHRINK_ARROWBULLET);
newbullet->movefactor = aura_scale;
newbullet->threshold |= OV_DONTCOPYANGLE;
P_SetTarget(&newbullet->target, player->mo);
P_SetTarget(&player->arrowbullet, newbullet);
player->arrowbullet->angle = K_MomentumAngle(player->mo);
player->arrowbullet->sloperoll = player->mo->sloperoll;
player->arrowbullet->slopepitch = player->mo->slopepitch;
player->arrowbullet->frame &= ~FF_TRANSMASK;
player->arrowbullet->frame |= auravis;
player->arrowbullet->dispoffset = min(2, player->mo->dispoffset + 1);
}
else
{
player->arrowbullet->angle = K_MomentumAngle(player->mo);
player->arrowbullet->sloperoll = player->mo->sloperoll;
player->arrowbullet->slopepitch = player->mo->slopepitch;
player->arrowbullet->movefactor = aura_scale;
player->arrowbullet->frame &= ~FF_TRANSMASK;
player->arrowbullet->frame |= auravis;
player->arrowbullet->dispoffset = min(2, player->mo->dispoffset + 1);
}
}
else
{
if ((player->arrowbullet) && (!P_MobjWasRemoved(player->arrowbullet)))
{
P_SetTarget(&player->arrowbullet->target, NULL);
P_RemoveMobj(player->arrowbullet);
P_SetTarget(&player->arrowbullet, NULL);
}
}
if (K_AltShrinkArrowBulletCondition(player))
{
K_SpawnSparkleTrail(player->mo);
K_SpawnNormalSpeedLines(player);
}
#undef MINAURAPCT
#undef AURA_DIFF
if (player->wipeoutslow > 1 && (leveltime & 1))
K_SpawnWipeoutTrail(player->mo, false);