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:
Sal 2019-10-27 19:47:07 -04:00
commit 9ed7bf7626
7 changed files with 218 additions and 12 deletions

View file

@ -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

View file

@ -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)

View file

@ -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;
}

View file

@ -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

View file

@ -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);

View file

@ -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);

View file

@ -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();