mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2026-01-20 21:52:33 +00:00
Merge branch 'spb-waypoints' into 'sal-waypoints'
Fix SPB pathing + other SPB features + Sizedown item removal while we're at it See merge request KartKrew/Kart!188
This commit is contained in:
commit
9ed7bf7626
7 changed files with 218 additions and 12 deletions
|
|
@ -16003,7 +16003,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
|
|||
S_SPB_DEAD, // deathstate
|
||||
S_NULL, // xdeathstate
|
||||
sfx_s3k5d, // deathsound
|
||||
96*FRACUNIT, // speed
|
||||
64*FRACUNIT, // speed
|
||||
24*FRACUNIT, // radius
|
||||
48*FRACUNIT, // height
|
||||
0, // display offset
|
||||
|
|
|
|||
57
src/k_kart.c
57
src/k_kart.c
|
|
@ -2109,7 +2109,7 @@ void K_RespawnChecker(player_t *player)
|
|||
{
|
||||
while (lasersteps)
|
||||
{
|
||||
|
||||
|
||||
stepha = R_PointToAngle2(laserx, lasery, destx, desty);
|
||||
stepva = R_PointToAngle2(0, laserz, P_AproxDistance(laserx - destx, lasery - desty), destz);
|
||||
|
||||
|
|
@ -4207,6 +4207,7 @@ void K_DoSneaker(player_t *player, INT32 type)
|
|||
static void K_DoShrink(player_t *user)
|
||||
{
|
||||
INT32 i;
|
||||
mobj_t *mobj, *next;
|
||||
|
||||
S_StartSound(user->mo, sfx_kc46); // Sound the BANG!
|
||||
user->pflags |= PF_ATTACKDOWN;
|
||||
|
|
@ -4244,6 +4245,43 @@ static void K_DoShrink(player_t *user)
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
// kill everything in the kitem list while we're at it:
|
||||
for (mobj = kitemcap; mobj; mobj = next)
|
||||
{
|
||||
next = mobj->itnext;
|
||||
|
||||
// check if the item is being held by a player behind us before removing it.
|
||||
// check if the item is a "shield" first, bc i'm p sure thrown items keep the player that threw em as target anyway
|
||||
|
||||
if (mobj->type == MT_BANANA_SHIELD || mobj->type == MT_JAWZ_SHIELD ||
|
||||
mobj->type == MT_SSMINE_SHIELD || mobj->type == MT_EGGMANITEM_SHIELD ||
|
||||
mobj->type == MT_SINK_SHIELD || mobj->type == MT_ORBINAUT_SHIELD)
|
||||
{
|
||||
if (mobj->target && mobj->target->player)
|
||||
{
|
||||
if (mobj->target->player->kartstuff[k_position] > user->kartstuff[k_position])
|
||||
continue; // this guy's behind us, don't take his stuff away!
|
||||
}
|
||||
}
|
||||
|
||||
// @TODO: This should probably go into the P_KillMobj code for items?
|
||||
|
||||
if (mobj->eflags & MFE_VERTICALFLIP)
|
||||
mobj->z -= mobj->height;
|
||||
else
|
||||
mobj->z += mobj->height;
|
||||
|
||||
S_StartSound(mobj, mobj->info->deathsound);
|
||||
P_KillMobj(mobj, user->mo, user->mo);
|
||||
|
||||
P_SetObjectMomZ(mobj, 8*FRACUNIT, false);
|
||||
P_InstaThrust(mobj, (angle_t)P_RandomRange(0, 359)*ANG1, 16*FRACUNIT);
|
||||
|
||||
if (mobj->type == MT_SPB)
|
||||
spbplace = -1;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -4416,6 +4454,7 @@ void K_DropHnextList(player_t *player)
|
|||
|
||||
dropwork = P_SpawnMobj(work->x, work->y, work->z, type);
|
||||
P_SetTarget(&dropwork->target, player->mo);
|
||||
P_AddKartItem(dropwork); // needs to be called here so shrink can bust items off players in front of the user.
|
||||
dropwork->angle = work->angle;
|
||||
dropwork->flags2 = work->flags2;
|
||||
dropwork->flags |= MF_NOCLIPTHING;
|
||||
|
|
@ -5744,7 +5783,7 @@ static waypoint_t *K_GetPlayerNextWaypoint(player_t *player, boolean closest)
|
|||
R_PointToAngle2(player->mo->x, player->mo->y, waypoint->mobj->x, waypoint->mobj->y);
|
||||
angle_t angledelta = ANGLE_MAX;
|
||||
|
||||
if (player->mo->momx != 0 || player->mo->momy != 0)
|
||||
if (player->mo->momx != 0 || player->mo->momy != 0)
|
||||
{
|
||||
// Default to facing angle if you're not moving, but use momentum angle otherwise.
|
||||
playerangle = R_PointToAngle2(0, 0, player->mo->momx, player->mo->momy);
|
||||
|
|
@ -9489,7 +9528,8 @@ static void K_drawKartMinimap(void)
|
|||
UINT8 skin = 0;
|
||||
UINT8 *colormap = NULL;
|
||||
SINT8 localplayers[4];
|
||||
SINT8 numlocalplayers = 0;
|
||||
SINT8 numlocalplayers = 0;
|
||||
mobj_t *mobj, *next; // for SPB drawing (or any other item(s) we may wanna draw, I dunno!)
|
||||
|
||||
// Draw the HUD only when playing in a level.
|
||||
// hu_stuff needs this, unlike st_stuff.
|
||||
|
|
@ -9674,7 +9714,16 @@ static void K_drawKartMinimap(void)
|
|||
if ((G_RaceGametype() && players[localplayers[i]].kartstuff[k_position] == spbplace)
|
||||
|| (G_BattleGametype() && K_IsPlayerWanted(&players[localplayers[i]])))
|
||||
K_drawKartMinimapIcon(players[localplayers[i]].mo->x, players[localplayers[i]].mo->y, x, y, splitflags, kp_wantedreticle, NULL, AutomapPic);
|
||||
}
|
||||
}
|
||||
|
||||
// draw SPB(s?)
|
||||
for (mobj = kitemcap; mobj; mobj = next)
|
||||
{
|
||||
next = mobj->itnext;
|
||||
if (mobj->type == MT_SPB)
|
||||
K_drawKartMinimapIcon(mobj->x, mobj->y, x, y, splitflags, kp_ringspblocksmall[14 + leveltime%4 /2], NULL, AutomapPic);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
static void K_drawKartStartCountdown(void)
|
||||
|
|
|
|||
|
|
@ -8495,11 +8495,15 @@ static void SpawnSPBTrailRings(mobj_t *actor)
|
|||
void A_SPBChase(mobj_t *actor)
|
||||
{
|
||||
player_t *player = NULL;
|
||||
player_t *scplayer = NULL; // secondary target for seeking
|
||||
UINT8 i;
|
||||
UINT8 bestrank = UINT8_MAX;
|
||||
fixed_t dist;
|
||||
angle_t hang, vang;
|
||||
fixed_t wspeed, xyspeed, zspeed;
|
||||
fixed_t pdist = 1536<<FRACBITS; // best player distance when seeking
|
||||
angle_t pangle; // angle between us and the player
|
||||
|
||||
#ifdef HAVE_BLUA
|
||||
if (LUA_CallAction("A_SPBChase", actor))
|
||||
return;
|
||||
|
|
@ -8714,6 +8718,7 @@ void A_SPBChase(mobj_t *actor)
|
|||
waypoint_t *lastwaypoint = NULL;
|
||||
waypoint_t *bestwaypoint = NULL;
|
||||
waypoint_t *nextwaypoint = NULL;
|
||||
waypoint_t *tempwaypoint = NULL;
|
||||
|
||||
actor->lastlook = -1; // Just make sure this is reset
|
||||
|
||||
|
|
@ -8732,13 +8737,22 @@ void A_SPBChase(mobj_t *actor)
|
|||
dist = P_AproxDistance(P_AproxDistance(actor->x-actor->tracer->x, actor->y-actor->tracer->y), actor->z-actor->tracer->z);
|
||||
|
||||
// Move along the waypoints until you get close enough
|
||||
if (actor->cusval > -1)
|
||||
if (actor->cusval > -1 && actor->extravalue2 > 0)
|
||||
{
|
||||
// Previously set nextwaypoint
|
||||
lastwaypoint = K_GetWaypointFromIndex((size_t)actor->cusval);
|
||||
}
|
||||
tempwaypoint = K_GetBestWaypointTouchingMobj(actor);
|
||||
// check if the tempwaypoint corresponds to lastwaypoint's next ID at least;
|
||||
// This is to avoid situations where the SPB decides to suicide jump down a bridge because it found a COMPLETELY unrelated waypoint down there.
|
||||
|
||||
bestwaypoint = K_GetBestWaypointTouchingMobj(actor);
|
||||
if (K_GetWaypointID(tempwaypoint) == K_GetWaypointNextID(lastwaypoint) || K_GetWaypointID(tempwaypoint) == K_GetWaypointID(lastwaypoint))
|
||||
// either our previous or curr waypoint ID, sure, take it
|
||||
bestwaypoint = tempwaypoint;
|
||||
else
|
||||
bestwaypoint = K_GetWaypointFromIndex((size_t)actor->extravalue2); // keep going from the PREVIOUS wp.
|
||||
}
|
||||
else
|
||||
bestwaypoint = K_GetBestWaypointTouchingMobj(actor);
|
||||
|
||||
if (bestwaypoint == NULL && lastwaypoint == NULL)
|
||||
{
|
||||
|
|
@ -8767,6 +8781,7 @@ void A_SPBChase(mobj_t *actor)
|
|||
nextwaypoint = lastwaypoint;
|
||||
}
|
||||
|
||||
|
||||
if (nextwaypoint != NULL)
|
||||
{
|
||||
const fixed_t xywaypointdist = P_AproxDistance(
|
||||
|
|
@ -8776,6 +8791,7 @@ void A_SPBChase(mobj_t *actor)
|
|||
vang = R_PointToAngle2(0, actor->z, xywaypointdist, nextwaypoint->mobj->z);
|
||||
|
||||
actor->cusval = (INT32)K_GetWaypointHeapIndex(nextwaypoint);
|
||||
actor->extravalue2 = (INT32)K_GetWaypointHeapIndex(bestwaypoint); // save our last best, used above.
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
@ -8816,10 +8832,36 @@ void A_SPBChase(mobj_t *actor)
|
|||
actor->movedir += input;
|
||||
}
|
||||
|
||||
|
||||
actor->momx = FixedMul(FixedMul(xyspeed, FINECOSINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT));
|
||||
actor->momy = FixedMul(FixedMul(xyspeed, FINESINE(actor->angle>>ANGLETOFINESHIFT)), FINECOSINE(actor->movedir>>ANGLETOFINESHIFT));
|
||||
actor->momz = FixedMul(zspeed, FINESINE(actor->movedir>>ANGLETOFINESHIFT));
|
||||
|
||||
// see if a player is near us, if they are, try to hit them by slightly thrusting towards them, otherwise, bleh!
|
||||
for (i=0; i < MAXPLAYERS; i++)
|
||||
{
|
||||
if (!playeringame[i] || players[i].spectator || players[i].exiting)
|
||||
continue; // not in-game
|
||||
|
||||
if (R_PointToDist2(actor->x, actor->y, players[i].mo->x, players[i].mo->y) < pdist)
|
||||
{
|
||||
pdist = R_PointToDist2(actor->x, actor->y, players[i].mo->x, players[i].mo->y);
|
||||
scplayer = &players[i]; // it doesn't matter if we override this guy now.
|
||||
}
|
||||
}
|
||||
|
||||
// different player from our main target, try and ram into em~!
|
||||
if (scplayer && scplayer != player)
|
||||
{
|
||||
pangle = actor->angle - R_PointToAngle2(actor->x, actor->y,scplayer->mo->x, scplayer->mo->y);
|
||||
// check if the angle wouldn't make us LOSE speed...
|
||||
if ((INT32)pangle/ANG1 >= -80 && (INT32)pangle/ANG1 <= 80) // allow for around 80 degrees
|
||||
{
|
||||
// Thrust us towards the guy, try to screw em up!
|
||||
P_Thrust(actor, R_PointToAngle2(actor->x, actor->y, scplayer->mo->x, scplayer->mo->y), actor->movefactor/4); // not too fast though.
|
||||
}
|
||||
}
|
||||
|
||||
// Spawn a trail of rings behind the SPB!
|
||||
SpawnSPBTrailRings(actor);
|
||||
|
||||
|
|
@ -8832,6 +8874,13 @@ void A_SPBChase(mobj_t *actor)
|
|||
}
|
||||
}
|
||||
|
||||
// Finally, no matter what, the spb should not be able to be under the ground, or above the ceiling;
|
||||
if (actor->z < actor->floorz)
|
||||
actor->z = actor->floorz;
|
||||
else if (actor->z > actor->ceilingz - actor->height)
|
||||
actor->z = actor->ceilingz - actor->height;
|
||||
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
|
|||
75
src/p_mobj.c
75
src/p_mobj.c
|
|
@ -48,6 +48,7 @@ actioncache_t actioncachehead;
|
|||
|
||||
static mobj_t *overlaycap = NULL;
|
||||
static mobj_t *shadowcap = NULL;
|
||||
mobj_t *kitemcap = NULL; // Used for Kart offensive items (the ones that can get removed by sizedown)
|
||||
mobj_t *waypointcap = NULL;
|
||||
|
||||
void P_InitCachedActions(void)
|
||||
|
|
@ -6101,6 +6102,71 @@ static boolean P_AddShield(mobj_t *thing)
|
|||
return true;
|
||||
}*/
|
||||
|
||||
|
||||
// Kartitem stuff.
|
||||
boolean P_IsKartItem(INT32 type)
|
||||
{
|
||||
if (type == MT_EGGMANITEM || type == MT_EGGMANITEM_SHIELD ||
|
||||
type == MT_BANANA || type == MT_BANANA_SHIELD ||
|
||||
type == MT_ORBINAUT || type == MT_ORBINAUT_SHIELD ||
|
||||
type == MT_JAWZ || type == MT_JAWZ_DUD || type == MT_JAWZ_SHIELD ||
|
||||
type == MT_SSMINE || type == MT_SSMINE_SHIELD ||
|
||||
type == MT_SINK || type == MT_SINK_SHIELD ||
|
||||
type == MT_FLOATINGITEM || type == MT_SPB)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
// Called when a kart item "thinks"
|
||||
void P_AddKartItem(mobj_t *thing)
|
||||
{
|
||||
I_Assert(thing != NULL);
|
||||
|
||||
if (kitemcap == NULL)
|
||||
P_SetTarget(&kitemcap, thing);
|
||||
else {
|
||||
mobj_t *mo;
|
||||
for (mo = kitemcap; mo && mo->itnext; mo = mo->itnext)
|
||||
;
|
||||
|
||||
I_Assert(mo != NULL);
|
||||
I_Assert(mo->itnext == NULL);
|
||||
|
||||
P_SetTarget(&mo->itnext, thing);
|
||||
}
|
||||
P_SetTarget(&thing->itnext, NULL);
|
||||
}
|
||||
|
||||
// Called only when a kart item is removed
|
||||
// Keeps the hnext list from corrupting.
|
||||
static void P_RemoveKartItem(mobj_t *thing)
|
||||
{
|
||||
mobj_t *mo;
|
||||
for (mo = kitemcap; mo; mo = mo->itnext)
|
||||
if (mo->itnext == thing)
|
||||
{
|
||||
P_SetTarget(&mo->itnext, thing->itnext);
|
||||
P_SetTarget(&thing->itnext, NULL);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Doesn't actually do anything since items have their own thinkers,
|
||||
// but this is necessary for the sole purpose of updating kitemcap
|
||||
void P_RunKartItems(void)
|
||||
{
|
||||
mobj_t *mobj, *next;
|
||||
|
||||
for (mobj = kitemcap; mobj; mobj = next)
|
||||
{
|
||||
next = mobj->itnext;
|
||||
P_SetTarget(&mobj->itnext, NULL);
|
||||
}
|
||||
P_SetTarget(&kitemcap, NULL);
|
||||
}
|
||||
|
||||
|
||||
void P_RunOverlays(void)
|
||||
{
|
||||
// run overlays
|
||||
|
|
@ -9961,6 +10027,12 @@ for (i = ((mobj->flags2 & MF2_STRONGBOX) ? strongboxamt : weakboxamt); i; --i) s
|
|||
}
|
||||
}
|
||||
|
||||
if (P_MobjWasRemoved(mobj))
|
||||
return; // obligatory paranoia check
|
||||
|
||||
if (P_IsKartItem(mobj->type)) // mobj is a kart item we want on the list:
|
||||
P_AddKartItem(mobj); // add to kitem list
|
||||
|
||||
// Can end up here if a player dies.
|
||||
if (mobj->player)
|
||||
P_CyclePlayerMobjState(mobj);
|
||||
|
|
@ -10887,6 +10959,9 @@ void P_RemoveMobj(mobj_t *mobj)
|
|||
if (mobj->type == MT_SPB)
|
||||
spbplace = -1;
|
||||
|
||||
if (P_IsKartItem(mobj->type))
|
||||
P_RemoveKartItem(mobj);
|
||||
|
||||
mobj->health = 0; // Just because
|
||||
|
||||
// unlink from sector and block lists
|
||||
|
|
|
|||
|
|
@ -321,6 +321,9 @@ typedef struct mobj_s
|
|||
struct mobj_s *hnext;
|
||||
struct mobj_s *hprev;
|
||||
|
||||
// One last pointer for kart item lists
|
||||
struct mobj_s *itnext;
|
||||
|
||||
mobjtype_t type;
|
||||
const mobjinfo_t *info; // &mobjinfo[mobj->type]
|
||||
|
||||
|
|
@ -436,12 +439,18 @@ typedef struct actioncache_s
|
|||
|
||||
extern actioncache_t actioncachehead;
|
||||
|
||||
extern mobj_t *kitemcap;
|
||||
extern mobj_t *waypointcap;
|
||||
|
||||
void P_InitCachedActions(void);
|
||||
void P_RunCachedActions(void);
|
||||
void P_AddCachedAction(mobj_t *mobj, INT32 statenum);
|
||||
|
||||
// kartitem stuff: Returns true if the specified 'type' is one of the kart item constants we want in the kitemcap list
|
||||
boolean P_IsKartItem(INT32 type);
|
||||
void P_AddKartItem(mobj_t *thing); // needs to be called in k_kart.c
|
||||
void P_RunKartItems(void);
|
||||
|
||||
// check mobj against water content, before movement code
|
||||
void P_MobjCheckWater(mobj_t *mobj);
|
||||
|
||||
|
|
|
|||
|
|
@ -957,9 +957,11 @@ typedef enum
|
|||
MD2_HNEXT = 1<<7,
|
||||
MD2_HPREV = 1<<8,
|
||||
MD2_COLORIZED = 1<<9,
|
||||
MD2_WAYPOINTCAP = 1<<10
|
||||
MD2_WAYPOINTCAP = 1<<10,
|
||||
MD2_KITEMCAP = 1<<11,
|
||||
MD2_ITNEXT = 1<<12
|
||||
#ifdef ESLOPE
|
||||
, MD2_SLOPE = 1<<11
|
||||
, MD2_SLOPE = 1<<13
|
||||
#endif
|
||||
} mobj_diff2_t;
|
||||
|
||||
|
|
@ -1151,6 +1153,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
|
|||
diff2 |= MD2_HNEXT;
|
||||
if (mobj->hprev)
|
||||
diff2 |= MD2_HPREV;
|
||||
if (mobj->itnext)
|
||||
diff2 |= MD2_ITNEXT;
|
||||
#ifdef ESLOPE
|
||||
if (mobj->standingslope)
|
||||
diff2 |= MD2_SLOPE;
|
||||
|
|
@ -1159,6 +1163,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
|
|||
diff2 |= MD2_COLORIZED;
|
||||
if (mobj == waypointcap)
|
||||
diff2 |= MD2_WAYPOINTCAP;
|
||||
if (mobj == kitemcap)
|
||||
diff2 |= MD2_KITEMCAP;
|
||||
if (diff2 != 0)
|
||||
diff |= MD_MORE;
|
||||
|
||||
|
|
@ -1274,6 +1280,8 @@ static void SaveMobjThinker(const thinker_t *th, const UINT8 type)
|
|||
WRITEUINT32(save_p, mobj->hnext->mobjnum);
|
||||
if (diff2 & MD2_HPREV)
|
||||
WRITEUINT32(save_p, mobj->hprev->mobjnum);
|
||||
if (diff2 & MD2_ITNEXT)
|
||||
WRITEUINT32(save_p, mobj->itnext->mobjnum);
|
||||
#ifdef ESLOPE
|
||||
if (diff2 & MD2_SLOPE)
|
||||
WRITEUINT16(save_p, mobj->standingslope->id);
|
||||
|
|
@ -2151,6 +2159,8 @@ static void LoadMobjThinker(actionf_p1 thinker)
|
|||
mobj->hnext = (mobj_t *)(size_t)READUINT32(save_p);
|
||||
if (diff2 & MD2_HPREV)
|
||||
mobj->hprev = (mobj_t *)(size_t)READUINT32(save_p);
|
||||
if (diff2 & MD2_ITNEXT)
|
||||
mobj->itnext = (mobj_t *)(size_t)READUINT32(save_p);
|
||||
#ifdef ESLOPE
|
||||
if (diff2 & MD2_SLOPE)
|
||||
{
|
||||
|
|
@ -2192,6 +2202,9 @@ static void LoadMobjThinker(actionf_p1 thinker)
|
|||
if (diff2 & MD2_WAYPOINTCAP)
|
||||
P_SetTarget(&waypointcap, mobj);
|
||||
|
||||
if (diff2 & MD2_KITEMCAP)
|
||||
P_SetTarget(&kitemcap, mobj);
|
||||
|
||||
mobj->info = (mobjinfo_t *)next; // temporarily, set when leave this function
|
||||
}
|
||||
|
||||
|
|
@ -3044,6 +3057,13 @@ static void P_RelinkPointers(void)
|
|||
if (!(mobj->hprev = P_FindNewPosition(temp)))
|
||||
CONS_Debug(DBG_GAMELOGIC, "hprev not found on %d\n", mobj->type);
|
||||
}
|
||||
if (mobj->itnext)
|
||||
{
|
||||
temp = (UINT32)(size_t)mobj->itnext;
|
||||
mobj->itnext = NULL;
|
||||
if (!(mobj->itnext = P_FindNewPosition(temp)))
|
||||
CONS_Debug(DBG_GAMELOGIC, "itnext not found on %d\n", mobj->type);
|
||||
}
|
||||
if (mobj->player && mobj->player->capsule)
|
||||
{
|
||||
temp = (UINT32)(size_t)mobj->player->capsule;
|
||||
|
|
@ -3324,7 +3344,7 @@ static void P_NetArchiveMisc(void)
|
|||
WRITEUINT32(save_p, hyubgone);
|
||||
WRITEUINT32(save_p, mapreset);
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
WRITEINT16(save_p, nospectategrief[i]);
|
||||
|
||||
WRITEUINT8(save_p, thwompsactive);
|
||||
|
|
@ -3447,7 +3467,7 @@ static inline boolean P_NetUnArchiveMisc(void)
|
|||
hyubgone = READUINT32(save_p);
|
||||
mapreset = READUINT32(save_p);
|
||||
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
for (i = 0; i < MAXPLAYERS; i++)
|
||||
nospectategrief[i] = READINT16(save_p);
|
||||
|
||||
thwompsactive = (boolean)READUINT8(save_p);
|
||||
|
|
|
|||
|
|
@ -183,6 +183,7 @@ void P_InitThinkers(void)
|
|||
{
|
||||
thinkercap.prev = thinkercap.next = &thinkercap;
|
||||
waypointcap = NULL;
|
||||
kitemcap = NULL;
|
||||
}
|
||||
|
||||
//
|
||||
|
|
@ -639,6 +640,9 @@ void P_Ticker(boolean run)
|
|||
if (runemeraldmanager)
|
||||
P_EmeraldManager(); // Power stone mode*/
|
||||
|
||||
// formality so kitemcap gets updated properly each frame.
|
||||
P_RunKartItems();
|
||||
|
||||
if (run)
|
||||
{
|
||||
P_RunThinkers();
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue