Add ring shooter tire grabbers + more player logic

This commit is contained in:
Sally Coolatta 2023-04-12 21:08:45 -04:00
parent d28601fd52
commit 4e7b6f0cc3
7 changed files with 366 additions and 60 deletions

View file

@ -2776,6 +2776,7 @@ void CL_ClearPlayer(INT32 playernum)
P_SetTarget(&players[playernum].hoverhyudoro, NULL);
P_SetTarget(&players[playernum].stumbleIndicator, NULL);
P_SetTarget(&players[playernum].sliptideZipIndicator, NULL);
P_SetTarget(&players[playernum].ringShooter, NULL);
}
// Handle parties.

View file

@ -505,7 +505,8 @@ struct player_t
UINT32 distancetofinish;
waypoint_t *currentwaypoint;
waypoint_t *nextwaypoint;
respawnvars_t respawn; // Respawn info
respawnvars_t respawn; // Respawn info
mobj_t *ringShooter; // DEZ respawner object
tic_t airtime; // Used to track just air time, but has evolved over time into a general "karted" timer. Rename this variable?
UINT8 startboost; // (0 to 125) - Boost you get from start of race or respawn drop dash

View file

@ -2645,6 +2645,7 @@ void G_PlayerReborn(INT32 player, boolean betweenmaps)
P_SetTarget(&players[player].follower, NULL);
P_SetTarget(&players[player].awayview.mobj, NULL);
P_SetTarget(&players[player].stumbleIndicator, NULL);
P_SetTarget(&players[player].ringShooter, NULL);
P_SetTarget(&players[player].followmobj, NULL);
hoverhyudoro = players[player].hoverhyudoro;

View file

@ -107,8 +107,9 @@ void Obj_BeginDropTargetMorph(mobj_t *target, skincolornum_t color);
boolean Obj_DropTargetMorphThink(mobj_t *morph);
/* Ring Shooter */
void Obj_RingShooterThinker(mobj_t *mo);
boolean Obj_RingShooterThinker(mobj_t *mo);
void Obj_RingShooterInput(player_t *player);
void Obj_RingShooterDelete(mobj_t *mo);
#ifdef __cplusplus
} // extern "C"

View file

@ -25,33 +25,76 @@
#include "../k_waypoint.h"
#include "../r_skins.h"
#include "../k_respawn.h"
#include "../lua_hook.h"
#define RS_FUSE_TIME (4*TICRATE)
static void ActivateRingShooter(mobj_t *mo)
{
mobj_t *part = mo->tracer;
#define RS_GRABBER_START (16 << FRACBITS)
#define RS_GRABBER_SLIDE (RS_GRABBER_START >> 4)
#define RS_GRABBER_EXTRA (18 << FRACBITS)
while (!P_MobjWasRemoved(part->tracer))
{
part = part->tracer;
part->renderflags &= ~RF_DONTDRAW;
part->frame += 4;
}
}
#define RS_KARTED_INC (3)
#define rs_base_scalespeed(o) ((o)->scalespeed)
#define rs_base_scalestate(o) ((o)->threshold)
#define rs_base_xscale(o) ((o)->extravalue1)
#define rs_base_yscale(o) ((o)->extravalue2)
#define rs_base_playerid(o) ((o)->lastlook)
#define rs_base_karted(o) ((o)->movecount)
#define rs_base_grabberdist(o) ((o)->movefactor)
#define rs_base_canceled(o) ((o)->cvmem)
#define rs_part_xoffset(o) ((o)->extravalue1)
#define rs_part_yoffset(o) ((o)->extravalue2)
static void RemoveRingShooterPointer(mobj_t *base)
{
player_t *player = NULL;
if (rs_base_playerid(base) < 0 || rs_base_playerid(base) >= MAXPLAYERS)
{
// No pointer set
return;
}
// NULL the player's pointer.
player = &players[ rs_base_playerid(base) ];
P_SetTarget(&player->ringShooter, NULL);
// Remove our player ID
rs_base_playerid(base) = -1;
}
static void ChangeRingShooterPointer(mobj_t *base, player_t *player)
{
// Remove existing pointer first.
RemoveRingShooterPointer(base);
if (player == NULL)
{
// Just remove it.
return;
}
// Set new player pointer.
P_SetTarget(&player->ringShooter, base);
// Set new player ID.
rs_base_playerid(base) = (player - players);
}
static void ScalePart(mobj_t *part, mobj_t *base)
{
part->spritexscale = rs_base_xscale(base);
part->spriteyscale = rs_base_yscale(base);
if (part->type == MT_TIREGRABBER)
{
part->spritexscale /= 2;
part->spriteyscale /= 2;
}
}
static void MovePart(mobj_t *part, mobj_t *base, mobj_t *refNipple)
@ -64,12 +107,43 @@ static void MovePart(mobj_t *part, mobj_t *base, mobj_t *refNipple)
);
}
static void ShowHidePart(mobj_t *part, mobj_t *base)
{
part->renderflags = (part->renderflags & ~RF_DONTDRAW) | (base->renderflags & RF_DONTDRAW);
}
static fixed_t GetTireDist(mobj_t *base)
{
return -(RS_GRABBER_EXTRA + rs_base_grabberdist(base));
}
static void MoveTire(mobj_t *part, mobj_t *base)
{
const fixed_t dis = FixedMul(GetTireDist(base), base->scale);
const fixed_t c = FINECOSINE(part->angle >> ANGLETOFINESHIFT);
const fixed_t s = FINESINE(part->angle >> ANGLETOFINESHIFT);
P_MoveOrigin(
part,
base->x + FixedMul(dis, c),
base->y + FixedMul(dis, s),
part->z
);
}
// I've tried to reduce redundancy as much as I can,
// but check K_SpawnRingShooter if you edit this
static void UpdateRingShooterParts(mobj_t *mo)
{
mobj_t *part, *refNipple;
part = mo;
while (!P_MobjWasRemoved(part->target))
{
part = part->target;
ScalePart(part, mo);
MoveTire(part, mo);
}
part = mo;
while (!P_MobjWasRemoved(part->hprev))
{
@ -92,6 +166,47 @@ static void UpdateRingShooterParts(mobj_t *mo)
ScalePart(part, mo);
}
static void UpdateRingShooterPartsVisibility(mobj_t *mo)
{
mobj_t *part;
part = mo;
while (!P_MobjWasRemoved(part->target))
{
part = part->target;
ShowHidePart(part, mo);
}
part = mo;
while (!P_MobjWasRemoved(part->hprev))
{
part = part->hprev;
ShowHidePart(part, mo);
}
part = mo;
while (!P_MobjWasRemoved(part->hnext))
{
part = part->hnext;
ShowHidePart(part, mo);
}
part = mo->tracer;
ShowHidePart(part, mo);
}
static void ActivateRingShooter(mobj_t *mo)
{
mobj_t *part = mo->tracer;
while (!P_MobjWasRemoved(part->tracer))
{
part = part->tracer;
part->renderflags &= ~RF_DONTDRAW;
part->frame += 4;
}
}
static boolean RingShooterInit(mobj_t *mo)
{
if (rs_base_scalestate(mo) == -1)
@ -129,10 +244,26 @@ static boolean RingShooterInit(mobj_t *mo)
rs_base_xscale(mo) -= rs_base_scalespeed(mo);
if (rs_base_yscale(mo) >= FRACUNIT)
{
rs_base_scalestate(mo) = -1;
rs_base_scalestate(mo)++;
rs_base_xscale(mo) = rs_base_yscale(mo) = FRACUNIT;
}
break;
}
case 3:
{
rs_base_grabberdist(mo) -= RS_GRABBER_SLIDE;
if (rs_base_grabberdist(mo) <= 0)
{
rs_base_scalestate(mo) = -1;
rs_base_grabberdist(mo) = 0;
ActivateRingShooter(mo);
}
break;
}
default:
{
rs_base_scalestate(mo) = 0; // fix invalid states
break;
}
}
@ -206,13 +337,87 @@ static void RingShooterFlicker(mobj_t *mo)
part->target->frame = (part->target->frame & ~FF_TRANSMASK) | trans;
}
void Obj_RingShooterThinker(mobj_t *mo)
boolean Obj_RingShooterThinker(mobj_t *mo)
{
if (P_MobjWasRemoved(mo->tracer) || RingShooterInit(mo))
return;
if (RingShooterInit(mo) == true)
{
return true;
}
RingShooterCountdown(mo);
RingShooterFlicker(mo);
if (mo->fuse > 0)
{
mo->fuse--;
if (mo->fuse == 0)
{
P_RemoveMobj(mo);
return false;
}
}
if (rs_base_canceled(mo) != 0)
{
rs_base_karted(mo) += RS_KARTED_INC;
if (P_MobjWasRemoved(mo->tracer) == false)
{
RingShooterCountdown(mo);
RingShooterFlicker(mo);
}
}
if (mo->fuse < TICRATE)
{
if (leveltime & 1)
{
mo->renderflags |= RF_DONTDRAW;
}
else
{
mo->renderflags &= ~RF_DONTDRAW;
}
UpdateRingShooterPartsVisibility(mo);
}
return true;
}
void Obj_RingShooterDelete(mobj_t *mo)
{
mobj_t *part;
RemoveRingShooterPointer(mo);
part = mo->target;
while (P_MobjWasRemoved(part) == false)
{
mobj_t *delete = part;
part = part->target;
P_RemoveMobj(delete);
}
part = mo->hprev;
while (P_MobjWasRemoved(part) == false)
{
mobj_t *delete = part;
part = part->hprev;
P_RemoveMobj(delete);
}
part = mo->hnext;
while (P_MobjWasRemoved(part) == false)
{
mobj_t *delete = part;
part = part->hnext;
P_RemoveMobj(delete);
}
part = mo->tracer;
if (P_MobjWasRemoved(part) == false)
{
P_RemoveMobj(part);
}
}
static boolean AllowRingShooter(player_t *player)
@ -254,8 +459,11 @@ static void SpawnRingShooter(player_t *player)
vector2_t offset;
SINT8 i;
rs_base_playerid(base) = -1;
rs_base_karted(base) = -(RS_KARTED_INC * TICRATE); // wait for "3"
rs_base_grabberdist(base) = RS_GRABBER_START;
K_FlipFromObject(base, mo);
P_SetTarget(&base->target, mo);
P_SetScale(base, base->destscale = FixedMul(base->destscale, scale));
base->angle = mo->angle;
base->scalespeed = FRACUNIT/2;
@ -264,10 +472,11 @@ static void SpawnRingShooter(player_t *player)
base->fuse = RS_FUSE_TIME;
// the ring shooter object itself is invisible and acts as the thinker
// each ring shooter uses three linked lists to keep track of its parts
// each ring shooter uses four linked lists to keep track of its parts
// the hprev chain stores the two NIPPLE BARS
// the hnext chain stores the four sides of the box
// the tracer chain stores the screen and the screen layers
// the target chain stores the tire grabbers
// spawn the RING NIPPLES
part = base;
@ -343,14 +552,66 @@ static void SpawnRingShooter(player_t *player)
P_SetMobjState(part, S_RINGSHOOTER_NUMBERBACK + i);
part->renderflags |= RF_DONTDRAW;
}
// spawn the grabbers
part = base;
angle = base->angle + ANGLE_45;
for (i = 0; i < 4; i++)
{
const fixed_t dis = GetTireDist(base);
P_SetTarget(
&part->target,
P_SpawnMobjFromMobj(
base,
P_ReturnThrustX(NULL, angle, dis),
P_ReturnThrustY(NULL, angle, dis),
0,
MT_TIREGRABBER
)
);
part = part->target;
P_SetTarget(&part->tracer, base);
angle -= ANGLE_90;
part->angle = angle;
part->extravalue1 = part->extravalue2 = 0;
part->old_spriteyscale = part->spriteyscale = 0;
}
ChangeRingShooterPointer(base, player);
}
void Obj_RingShooterInput(player_t *player)
{
mobj_t *const base = player->ringShooter;
if (AllowRingShooter(player) == true
&& (player->cmd.buttons & BT_RESPAWN) == BT_RESPAWN
&& (player->oldcmd.buttons & BT_RESPAWN) == 0)
&& (player->cmd.buttons & BT_RESPAWN) == BT_RESPAWN)
{
SpawnRingShooter(player);
if (P_MobjWasRemoved(base) == true)
{
SpawnRingShooter(player);
return;
}
if (rs_base_canceled(base) != 0)
{
if (base->fuse < TICRATE)
{
base->renderflags &= ~RF_DONTDRAW;
UpdateRingShooterPartsVisibility(base);
}
base->fuse = RS_FUSE_TIME;
}
}
else if (P_MobjWasRemoved(base) == false)
{
if (rs_base_scalestate(base) != -1)
{
// We released during the intro animation.
// Cancel it entirely.
rs_base_canceled(base) = 1;
}
}
}

View file

@ -6642,7 +6642,10 @@ static void P_MobjSceneryThink(mobj_t *mobj)
}
break;
case MT_RINGSHOOTER:
Obj_RingShooterThinker(mobj);
if (Obj_RingShooterThinker(mobj) == false)
{
return;
}
break;
case MT_SPINDASHWIND:
case MT_DRIFTELECTRICSPARK:
@ -11143,26 +11146,10 @@ void P_RemoveMobj(mobj_t *mobj)
iquetail = (iquetail+1)&(ITEMQUESIZE-1);
}
if (mobj->type == MT_KARMAHITBOX) // Remove linked list objects for certain types
{
mobj_t *cur = mobj->hnext;
while (cur && !P_MobjWasRemoved(cur))
{
mobj_t *prev = cur; // Kind of a dumb var, but we need to set cur before we remove the mobj
cur = cur->hnext;
P_RemoveMobj(prev);
}
}
if (mobj->type == MT_OVERLAY)
P_RemoveOverlay(mobj);
if (mobj->type == MT_SPB)
spbplace = -1;
if (P_IsTrackerType(mobj->type))
{
P_RemoveTracker(mobj);
}
if (mobj->player && mobj->player->followmobj)
{
@ -11170,19 +11157,56 @@ void P_RemoveMobj(mobj_t *mobj)
P_SetTarget(&mobj->player->followmobj, NULL);
}
if (mobj->type == MT_SHRINK_POHBEE)
// Remove linked list objects for certain types
switch (mobj->type)
{
Obj_PohbeeRemoved(mobj);
}
case MT_KARMAHITBOX:
{
mobj_t *cur = mobj->hnext;
if (mobj->type == MT_SHRINK_GUN)
{
Obj_ShrinkGunRemoved(mobj);
}
while (cur && !P_MobjWasRemoved(cur))
{
mobj_t *prev = cur; // Kind of a dumb var, but we need to set cur before we remove the mobj
cur = cur->hnext;
P_RemoveMobj(prev);
}
if (mobj->type == MT_SPECIAL_UFO_PIECE)
{
Obj_UFOPieceRemoved(mobj);
break;
}
case MT_OVERLAY:
{
P_RemoveOverlay(mobj);
break;
}
case MT_SPB:
{
spbplace = -1;
break;
}
case MT_SHRINK_POHBEE:
{
Obj_PohbeeRemoved(mobj);
break;
}
case MT_SHRINK_GUN:
{
Obj_ShrinkGunRemoved(mobj);
break;
}
case MT_SPECIAL_UFO_PIECE:
{
Obj_UFOPieceRemoved(mobj);
break;
}
case MT_RINGSHOOTER:
{
Obj_RingShooterDelete(mobj);
break;
}
default:
{
break;
}
}
mobj->health = 0; // Just because

View file

@ -63,14 +63,15 @@ savedata_t savedata;
// than an UINT16
typedef enum
{
AWAYVIEW = 0x01,
FOLLOWITEM = 0x02,
FOLLOWER = 0x04,
SKYBOXVIEW = 0x08,
SKYBOXCENTER = 0x10,
HOVERHYUDORO = 0x20,
STUMBLE = 0x40,
SLIPTIDEZIP = 0x80
AWAYVIEW = 0x0001,
FOLLOWITEM = 0x0002,
FOLLOWER = 0x0004,
SKYBOXVIEW = 0x0008,
SKYBOXCENTER = 0x0010,
HOVERHYUDORO = 0x0020,
STUMBLE = 0x0040,
SLIPTIDEZIP = 0x0080,
RINGSHOOTER = 0x0100
} player_saveflags;
static inline void P_ArchivePlayer(savebuffer_t *save)
@ -217,6 +218,9 @@ static void P_NetArchivePlayers(savebuffer_t *save)
if (players[i].sliptideZipIndicator)
flags |= SLIPTIDEZIP;
if (players[i].ringShooter)
flags |= RINGSHOOTER;
WRITEUINT16(save->p, flags);
if (flags & SKYBOXVIEW)
@ -240,6 +244,9 @@ static void P_NetArchivePlayers(savebuffer_t *save)
if (flags & SLIPTIDEZIP)
WRITEUINT32(save->p, players[i].sliptideZipIndicator->mobjnum);
if (flags & RINGSHOOTER)
WRITEUINT32(save->p, players[i].ringShooter->mobjnum);
WRITEUINT32(save->p, (UINT32)players[i].followitem);
WRITEUINT32(save->p, players[i].charflags);
@ -613,6 +620,9 @@ static void P_NetUnArchivePlayers(savebuffer_t *save)
if (flags & SLIPTIDEZIP)
players[i].sliptideZipIndicator = (mobj_t *)(size_t)READUINT32(save->p);
if (flags & RINGSHOOTER)
players[i].ringShooter = (mobj_t *)(size_t)READUINT32(save->p);
players[i].followitem = (mobjtype_t)READUINT32(save->p);
//SetPlayerSkinByNum(i, players[i].skin);
@ -4823,6 +4833,13 @@ static void P_RelinkPointers(void)
if (!P_SetTarget(&players[i].sliptideZipIndicator, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "sliptideZipIndicator not found on player %d\n", i);
}
if (players[i].ringShooter)
{
temp = (UINT32)(size_t)players[i].ringShooter;
players[i].ringShooter = NULL;
if (!P_SetTarget(&players[i].ringShooter, P_FindNewPosition(temp)))
CONS_Debug(DBG_GAMELOGIC, "ringShooter not found on player %d\n", i);
}
}
}