Merge branch 'refactor-kitemcap' into 'master'

Refactor kitemcap

See merge request KartKrew/Kart!955
This commit is contained in:
James R 2023-02-22 11:23:51 +00:00
commit 923b8414a1
10 changed files with 339 additions and 368 deletions

View file

@ -121,6 +121,7 @@ add_executable(SRB2SDL2 MACOSX_BUNDLE WIN32
k_grandprix.c
k_boss.c
k_hud.c
k_hud_track.cpp
k_menufunc.c
k_menudraw.c
k_terrain.c

View file

@ -1094,7 +1094,7 @@ static void K_BotItemJawz(player_t *player, ticcmd_t *cmd)
target = &players[lastTarg];
// Make sure no other Jawz are targetting this player.
for (mobj = kitemcap; mobj; mobj = next)
for (mobj = trackercap; mobj; mobj = next)
{
next = mobj->itnext;

View file

@ -174,10 +174,11 @@ static patch_t *kp_bossret[4];
static patch_t *kp_trickcool[2];
static patch_t *kp_capsuletarget_arrow[2][2];
static patch_t *kp_capsuletarget_icon[2];
static patch_t *kp_capsuletarget_far[2];
static patch_t *kp_capsuletarget_near[8];
patch_t *kp_capsuletarget_arrow[2][2];
patch_t *kp_capsuletarget_icon[2];
patch_t *kp_capsuletarget_far[2];
patch_t *kp_capsuletarget_far_text[2];
patch_t *kp_capsuletarget_near[8];
void K_LoadKartHUDGraphics(void)
{
@ -665,6 +666,13 @@ void K_LoadKartHUDGraphics(void)
}
}
sprintf(buffer, "HUDCAPDx");
for (i = 0; i < 2; i++)
{
buffer[7] = '0'+i;
HU_UpdatePatch(&kp_capsuletarget_far_text[i], "%s", buffer);
}
sprintf(buffer, "HUDCAPCx");
for (i = 0; i < 2; i++)
{
@ -832,7 +840,7 @@ INT32 POSI2_X, POSI2_Y;
INT32 TCOOL_X, TCOOL_Y;
// This version of the function was prototyped in Lua by Nev3r ... a HUGE thank you goes out to them!
void K_ObjectTracking(trackingResult_t *result, vector3_t *point, boolean reverse)
void K_ObjectTracking(trackingResult_t *result, const vector3_t *point, boolean reverse)
{
#define NEWTAN(x) FINETANGENT(((x + ANGLE_90) >> ANGLETOFINESHIFT) & 4095) // tan function used by Lua
#define NEWCOS(x) FINECOSINE((x >> ANGLETOFINESHIFT) & FINEMASK)
@ -3175,217 +3183,6 @@ static void K_DrawWeakSpot(weakspotdraw_t *ws)
V_DrawFixedPatch(ws->x, ws->y, FRACUNIT, 0, kp_bossret[j+1], colormap);
}
typedef struct capsuletracking_s
{
mobj_t *mobj;
vector3_t point;
fixed_t camDist;
} capsuletracking_t;
static void K_DrawCapsuleTracking(capsuletracking_t *caps)
{
trackingResult_t result = {0};
INT32 timer = 0;
K_ObjectTracking(&result, &caps->point, false);
if (result.onScreen == false)
{
// Off-screen, draw alongside the borders of the screen.
// Probably the most complicated thing.
INT32 scrVal = 240;
vector2_t screenSize = {0};
INT32 borderSize = 7;
vector2_t borderWin = {0};
vector2_t borderDir = {0};
fixed_t borderLen = FRACUNIT;
vector2_t arrowDir = {0};
vector2_t arrowPos = {0};
patch_t *arrowPatch = NULL;
INT32 arrowFlags = 0;
vector2_t capsulePos = {0};
patch_t *capsulePatch = NULL;
timer = (leveltime / 3);
screenSize.x = vid.width / vid.dupx;
screenSize.y = vid.height / vid.dupy;
if (r_splitscreen >= 2)
{
// Half-wide screens
screenSize.x >>= 1;
borderSize >>= 1;
}
if (r_splitscreen >= 1)
{
// Half-tall screens
screenSize.y >>= 1;
}
scrVal = max(screenSize.x, screenSize.y) - 80;
borderWin.x = screenSize.x - borderSize;
borderWin.y = screenSize.y - borderSize;
arrowDir.x = 0;
arrowDir.y = P_MobjFlip(caps->mobj) * FRACUNIT;
// Simply pointing towards the result doesn't work, so inaccurate hack...
borderDir.x = FixedMul(
FixedMul(
FINESINE((-result.angle >> ANGLETOFINESHIFT) & FINEMASK),
FINECOSINE((-result.pitch >> ANGLETOFINESHIFT) & FINEMASK)
),
result.fov
);
borderDir.y = FixedMul(
FINESINE((-result.pitch >> ANGLETOFINESHIFT) & FINEMASK),
result.fov
);
borderLen = R_PointToDist2(0, 0, borderDir.x, borderDir.y);
if (borderLen > 0)
{
borderDir.x = FixedDiv(borderDir.x, borderLen);
borderDir.y = FixedDiv(borderDir.y, borderLen);
}
else
{
// Eh just put it at the bottom.
borderDir.x = 0;
borderDir.y = FRACUNIT;
}
capsulePatch = kp_capsuletarget_icon[timer & 1];
if (abs(borderDir.x) > abs(borderDir.y))
{
// Horizontal arrow
arrowPatch = kp_capsuletarget_arrow[1][timer & 1];
arrowDir.y = 0;
if (borderDir.x < 0)
{
// LEFT
arrowDir.x = -FRACUNIT;
}
else
{
// RIGHT
arrowDir.x = FRACUNIT;
}
}
else
{
// Vertical arrow
arrowPatch = kp_capsuletarget_arrow[0][timer & 1];
arrowDir.x = 0;
if (borderDir.y < 0)
{
// UP
arrowDir.y = -FRACUNIT;
}
else
{
// DOWN
arrowDir.y = FRACUNIT;
}
}
arrowPos.x = (screenSize.x >> 1) + FixedMul(scrVal, borderDir.x);
arrowPos.y = (screenSize.y >> 1) + FixedMul(scrVal, borderDir.y);
arrowPos.x = min(max(arrowPos.x, borderSize), borderWin.x) * FRACUNIT;
arrowPos.y = min(max(arrowPos.y, borderSize), borderWin.y) * FRACUNIT;
capsulePos.x = arrowPos.x - (arrowDir.x * 12);
capsulePos.y = arrowPos.y - (arrowDir.y * 12);
arrowPos.x -= (arrowPatch->width << FRACBITS) >> 1;
arrowPos.y -= (arrowPatch->height << FRACBITS) >> 1;
capsulePos.x -= (capsulePatch->width << FRACBITS) >> 1;
capsulePos.y -= (capsulePatch->height << FRACBITS) >> 1;
if (arrowDir.x < 0)
{
arrowPos.x += arrowPatch->width << FRACBITS;
arrowFlags |= V_FLIP;
}
if (arrowDir.y < 0)
{
arrowPos.y += arrowPatch->height << FRACBITS;
arrowFlags |= V_VFLIP;
}
V_DrawFixedPatch(
capsulePos.x, capsulePos.y,
FRACUNIT,
V_SPLITSCREEN,
capsulePatch, NULL
);
V_DrawFixedPatch(
arrowPos.x, arrowPos.y,
FRACUNIT,
V_SPLITSCREEN | arrowFlags,
arrowPatch, NULL
);
}
else
{
// Draw simple overlay.
const fixed_t farDistance = 1280*mapobjectscale;
boolean useNear = (caps->camDist < farDistance);
patch_t *capsulePatch = NULL;
vector2_t capsulePos = {0};
boolean visible = P_CheckSight(stplyr->mo, caps->mobj);
if (visible == false && (leveltime & 1))
{
// Flicker when not visible.
return;
}
capsulePos.x = result.x;
capsulePos.y = result.y;
if (useNear == true)
{
timer = (leveltime / 2);
capsulePatch = kp_capsuletarget_near[timer % 8];
}
else
{
timer = (leveltime / 3);
capsulePatch = kp_capsuletarget_far[timer & 1];
}
capsulePos.x -= (capsulePatch->width << FRACBITS) >> 1;
capsulePos.y -= (capsulePatch->height << FRACBITS) >> 1;
V_DrawFixedPatch(
capsulePos.x, capsulePos.y,
FRACUNIT,
V_SPLITSCREEN,
capsulePatch, NULL
);
}
}
static void K_drawKartNameTags(void)
{
const fixed_t maxdistance = 8192*mapobjectscale;
@ -3485,84 +3282,7 @@ static void K_drawKartNameTags(void)
}
}
if (battlecapsules == true)
{
#define MAX_CAPSULE_HUD 32
capsuletracking_t capsuleList[MAX_CAPSULE_HUD];
size_t capsuleListLen = 0;
mobj_t *mobj = NULL;
mobj_t *next = NULL;
for (mobj = kitemcap; mobj; mobj = next)
{
capsuletracking_t *caps = NULL;
next = mobj->itnext;
if (mobj->health <= 0)
{
continue;
}
if (mobj->type != MT_BATTLECAPSULE)
{
continue;
}
caps = &capsuleList[capsuleListLen];
caps->mobj = mobj;
caps->point.x = R_InterpolateFixed(mobj->old_x, mobj->x);
caps->point.y = R_InterpolateFixed(mobj->old_y, mobj->y);
caps->point.z = R_InterpolateFixed(mobj->old_z, mobj->z);
caps->point.z += (mobj->height >> 1);
caps->camDist = R_PointToDist2(c.x, c.y, caps->point.x, caps->point.y);
capsuleListLen++;
if (capsuleListLen >= MAX_CAPSULE_HUD)
{
break;
}
}
if (capsuleListLen > 0)
{
// Sort by distance from camera.
if (capsuleListLen > 1)
{
for (i = 0; i < capsuleListLen-1; i++)
{
size_t swap = i;
for (j = i + 1; j < capsuleListLen; j++)
{
capsuletracking_t *cj = &capsuleList[j];
capsuletracking_t *cSwap = &capsuleList[swap];
if (cj->camDist > cSwap->camDist)
{
swap = j;
}
}
if (swap != i)
{
capsuletracking_t temp = capsuleList[swap];
capsuleList[swap] = capsuleList[i];
capsuleList[i] = temp;
}
}
}
for (i = 0; i < capsuleListLen; i++)
{
K_DrawCapsuleTracking(&capsuleList[i]);
}
}
#undef MAX_CAPSULE_HUD
}
K_drawTargetHUD(&c, stplyr);
for (i = 0; i < MAXPLAYERS; i++)
{
@ -3927,7 +3647,7 @@ static void K_drawKartMinimap(void)
}
// draw minimap-pertinent objects
for (mobj = kitemcap; mobj; mobj = next)
for (mobj = trackercap; mobj; mobj = next)
{
next = mobj->itnext;

View file

@ -34,7 +34,7 @@ struct trackingResult_t
fixed_t fov;
};
void K_ObjectTracking(trackingResult_t *result, vector3_t *point, boolean reverse);
void K_ObjectTracking(trackingResult_t *result, const vector3_t *point, boolean reverse);
const char *K_GetItemPatch(UINT8 item, boolean tiny);
void K_LoadKartHUDGraphics(void);
@ -44,8 +44,14 @@ void K_drawKartTimestamp(tic_t drawtime, INT32 TX, INT32 TY, INT32 splitflags, U
void K_DrawTabRankings(INT32 x, INT32 y, playersort_t *tab, INT32 scorelines, INT32 whiteplayer, INT32 hilicol);
void K_DrawMapThumbnail(INT32 x, INT32 y, INT32 width, UINT32 flags, UINT16 map, UINT8 *colormap);
void K_DrawLikeMapThumbnail(INT32 x, INT32 y, INT32 width, UINT32 flags, patch_t *patch, UINT8 *colormap);
void K_drawTargetHUD(const vector3_t *origin, player_t *player);
extern patch_t *kp_facehighlight[8];
extern patch_t *kp_capsuletarget_arrow[2][2];
extern patch_t *kp_capsuletarget_icon[2];
extern patch_t *kp_capsuletarget_far[2];
extern patch_t *kp_capsuletarget_far_text[2];
extern patch_t *kp_capsuletarget_near[8];
#ifdef __cplusplus
} // extern "C"

270
src/k_hud_track.cpp Normal file
View file

@ -0,0 +1,270 @@
#include <algorithm>
#include <cstddef>
#include <vector>
#include "k_hud.h"
#include "m_fixed.h"
#include "p_local.h"
#include "p_mobj.h"
#include "r_fps.h"
#include "r_main.h"
#include "v_video.h"
namespace
{
struct TargetTracking
{
mobj_t* mobj;
vector3_t point;
fixed_t camDist;
};
void K_DrawTargetTracking(const TargetTracking& target)
{
trackingResult_t result = {};
int32_t timer = 0;
K_ObjectTracking(&result, &target.point, false);
if (result.onScreen == false)
{
// Off-screen, draw alongside the borders of the screen.
// Probably the most complicated thing.
int32_t scrVal = 240;
vector2_t screenSize = {};
int32_t borderSize = 7;
vector2_t borderWin = {};
vector2_t borderDir = {};
fixed_t borderLen = FRACUNIT;
vector2_t arrowDir = {};
vector2_t arrowPos = {};
patch_t* arrowPatch = nullptr;
int32_t arrowFlags = 0;
vector2_t targetPos = {};
patch_t* targetPatch = nullptr;
timer = (leveltime / 3);
screenSize.x = vid.width / vid.dupx;
screenSize.y = vid.height / vid.dupy;
if (r_splitscreen >= 2)
{
// Half-wide screens
screenSize.x >>= 1;
borderSize >>= 1;
}
if (r_splitscreen >= 1)
{
// Half-tall screens
screenSize.y >>= 1;
}
scrVal = std::max(screenSize.x, screenSize.y) - 80;
borderWin.x = screenSize.x - borderSize;
borderWin.y = screenSize.y - borderSize;
arrowDir.x = 0;
arrowDir.y = P_MobjFlip(target.mobj) * FRACUNIT;
// Simply pointing towards the result doesn't work, so inaccurate hack...
borderDir.x = FixedMul(
FixedMul(
FINESINE((-result.angle >> ANGLETOFINESHIFT) & FINEMASK),
FINECOSINE((-result.pitch >> ANGLETOFINESHIFT) & FINEMASK)
),
result.fov
);
borderDir.y = FixedMul(FINESINE((-result.pitch >> ANGLETOFINESHIFT) & FINEMASK), result.fov);
borderLen = R_PointToDist2(0, 0, borderDir.x, borderDir.y);
if (borderLen > 0)
{
borderDir.x = FixedDiv(borderDir.x, borderLen);
borderDir.y = FixedDiv(borderDir.y, borderLen);
}
else
{
// Eh just put it at the bottom.
borderDir.x = 0;
borderDir.y = FRACUNIT;
}
targetPatch = kp_capsuletarget_icon[timer & 1];
if (abs(borderDir.x) > abs(borderDir.y))
{
// Horizontal arrow
arrowPatch = kp_capsuletarget_arrow[1][timer & 1];
arrowDir.y = 0;
if (borderDir.x < 0)
{
// LEFT
arrowDir.x = -FRACUNIT;
}
else
{
// RIGHT
arrowDir.x = FRACUNIT;
}
}
else
{
// Vertical arrow
arrowPatch = kp_capsuletarget_arrow[0][timer & 1];
arrowDir.x = 0;
if (borderDir.y < 0)
{
// UP
arrowDir.y = -FRACUNIT;
}
else
{
// DOWN
arrowDir.y = FRACUNIT;
}
}
arrowPos.x = (screenSize.x >> 1) + FixedMul(scrVal, borderDir.x);
arrowPos.y = (screenSize.y >> 1) + FixedMul(scrVal, borderDir.y);
arrowPos.x = std::clamp(arrowPos.x, borderSize, borderWin.x) * FRACUNIT;
arrowPos.y = std::clamp(arrowPos.y, borderSize, borderWin.y) * FRACUNIT;
targetPos.x = arrowPos.x - (arrowDir.x * 12);
targetPos.y = arrowPos.y - (arrowDir.y * 12);
arrowPos.x -= (arrowPatch->width << FRACBITS) >> 1;
arrowPos.y -= (arrowPatch->height << FRACBITS) >> 1;
targetPos.x -= (targetPatch->width << FRACBITS) >> 1;
targetPos.y -= (targetPatch->height << FRACBITS) >> 1;
if (arrowDir.x < 0)
{
arrowPos.x += arrowPatch->width << FRACBITS;
arrowFlags |= V_FLIP;
}
if (arrowDir.y < 0)
{
arrowPos.y += arrowPatch->height << FRACBITS;
arrowFlags |= V_VFLIP;
}
V_DrawFixedPatch(targetPos.x, targetPos.y, FRACUNIT, V_SPLITSCREEN, targetPatch, nullptr);
V_DrawFixedPatch(arrowPos.x, arrowPos.y, FRACUNIT, V_SPLITSCREEN | arrowFlags, arrowPatch, nullptr);
}
else
{
// Draw simple overlay.
const fixed_t farDistance = 1280 * mapobjectscale;
bool useNear = (target.camDist < farDistance);
vector2_t targetPos = {};
bool visible = P_CheckSight(stplyr->mo, target.mobj);
if (visible == false && (leveltime & 1))
{
// Flicker when not visible.
return;
}
targetPos.x = result.x;
targetPos.y = result.y;
auto draw = [&](patch_t* patch)
{
V_DrawFixedPatch(
targetPos.x - ((patch->width << FRACBITS) >> 1),
targetPos.y - ((patch->height << FRACBITS) >> 1),
FRACUNIT,
V_SPLITSCREEN,
patch,
nullptr
);
};
if (useNear == true)
{
timer = (leveltime / 2);
draw(kp_capsuletarget_near[timer % 8]);
}
else
{
timer = (leveltime / 3);
draw(kp_capsuletarget_far[timer & 1]);
if (r_splitscreen <= 1)
{
draw(kp_capsuletarget_far_text[timer & 1]);
}
}
}
}
bool is_object_tracking_target(const mobj_t* mobj)
{
switch (mobj->type)
{
case MT_BATTLECAPSULE:
case MT_SPECIAL_UFO:
return true;
default:
return false;
}
}
}; // namespace
void K_drawTargetHUD(const vector3_t* origin, player_t* player)
{
std::vector<TargetTracking> targetList;
mobj_t* mobj = nullptr;
mobj_t* next = nullptr;
for (mobj = trackercap; mobj; mobj = next)
{
next = mobj->itnext;
if (mobj->health <= 0)
{
continue;
}
if (is_object_tracking_target(mobj) == false)
{
continue;
}
vector3_t pos = {
R_InterpolateFixed(mobj->old_x, mobj->x),
R_InterpolateFixed(mobj->old_y, mobj->y),
R_InterpolateFixed(mobj->old_z, mobj->z) + (mobj->height >> 1),
};
targetList.push_back({mobj, pos, R_PointToDist2(origin->x, origin->y, pos.x, pos.y)});
}
// Sort by distance from camera. Further trackers get
// drawn first so nearer ones draw over them.
std::sort(targetList.begin(), targetList.end(), [](const auto& a, const auto& b) { return a.camDist > b.camDist; });
std::for_each(targetList.cbegin(), targetList.cend(), K_DrawTargetTracking);
}

View file

@ -5816,7 +5816,7 @@ static void K_DoShrink(player_t *user)
mobj_t *mobj, *next;
// kill everything in the kitem list while we're at it:
for (mobj = kitemcap; mobj; mobj = next)
for (mobj = trackercap; mobj; mobj = next)
{
next = mobj->itnext;
@ -6108,7 +6108,6 @@ void K_DropHnextList(player_t *player, boolean keepshields)
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;

View file

@ -53,9 +53,13 @@ consvar_t cv_movebob = CVAR_INIT ("movebob", "1.0", CV_FLOAT|CV_SAVE, CV_BobSpee
actioncache_t actioncachehead;
static mobj_t *overlaycap = NULL;
mobj_t *kitemcap = NULL; // Used for Kart offensive items (the ones that can get removed by sizedown)
mobj_t *waypointcap = NULL;
// Used as a fast iterator to certain objects that help bot
// AI, need HUD tracking or appear on the minimap. It's pretty
// general purpose.
mobj_t *trackercap = NULL;
void P_InitCachedActions(void)
{
actioncachehead.prev = actioncachehead.next = &actioncachehead;
@ -5206,30 +5210,6 @@ boolean P_IsKartFieldItem(INT32 type)
}
}
boolean P_IsKartItem(INT32 type)
{
switch (type)
{
case MT_EGGMANITEM_SHIELD:
case MT_BANANA_SHIELD:
case MT_DROPTARGET_SHIELD:
case MT_ORBINAUT_SHIELD:
case MT_JAWZ_SHIELD:
case MT_SSMINE_SHIELD:
case MT_SINK_SHIELD:
case MT_HYUDORO:
return true;
// Primarily for minimap data, handle with care
case MT_SPB:
case MT_BATTLECAPSULE:
return true;
default:
return P_IsKartFieldItem(type);
}
}
boolean K_IsMissileOrKartItem(mobj_t *mo)
{
if (mo->flags & MF_MISSILE)
@ -5256,16 +5236,34 @@ boolean P_CanDeleteKartItem(INT32 type)
return P_IsKartFieldItem(type);
}
// Called when a kart item "thinks"
void P_AddKartItem(mobj_t *thing)
static boolean P_IsTrackerType(INT32 type)
{
switch (type)
{
// Bots need to know if another Jawz is targetting a player
case MT_JAWZ:
return true;
// Primarily for minimap data, handle with care
case MT_SPB:
case MT_BATTLECAPSULE:
case MT_SPECIAL_UFO:
return true;
default:
return false;
}
}
static void P_LinkTracker(mobj_t *thing)
{
I_Assert(thing != NULL);
if (kitemcap == NULL)
P_SetTarget(&kitemcap, thing);
if (trackercap == NULL)
P_SetTarget(&trackercap, thing);
else {
mobj_t *mo;
for (mo = kitemcap; mo && mo->itnext; mo = mo->itnext)
for (mo = trackercap; mo && mo->itnext; mo = mo->itnext)
;
I_Assert(mo != NULL);
@ -5276,12 +5274,12 @@ void P_AddKartItem(mobj_t *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)
// Called only when a tracker is removed
// Keeps the itnext list from corrupting.
static void P_RemoveTracker(mobj_t *thing)
{
mobj_t *mo, **p;
for (mo = *(p = &kitemcap); mo; mo = *(p = &mo->itnext))
for (mo = *(p = &trackercap); mo; mo = *(p = &mo->itnext))
{
if (mo != thing)
continue;
@ -5292,20 +5290,6 @@ static void P_RemoveKartItem(mobj_t *thing)
}
}
// 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
@ -9808,9 +9792,6 @@ void P_MobjThinker(mobj_t *mobj)
K_HandleDirectionalInfluence(mobj->player);
}
if (P_IsKartItem(mobj->type)) // mobj is a kart item we want on the list:
P_AddKartItem(mobj); // add to kitem list
return;
}
@ -10051,9 +10032,6 @@ void P_MobjThinker(mobj_t *mobj)
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);
@ -10967,6 +10945,10 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type)
R_AddMobjInterpolator(mobj);
if (P_IsTrackerType(mobj->type))
P_LinkTracker(mobj);
return mobj;
}
@ -11109,8 +11091,8 @@ void P_RemoveMobj(mobj_t *mobj)
if (mobj->type == MT_SPB)
spbplace = -1;
if (P_IsKartItem(mobj->type))
P_RemoveKartItem(mobj);
if (P_IsTrackerType(mobj->type))
P_RemoveTracker(mobj);
if (mobj->player && mobj->player->followmobj)
{

View file

@ -356,7 +356,7 @@ struct mobj_t
mobj_t *hnext;
mobj_t *hprev;
// One last pointer for kart item lists
// One last pointer for trackers lists
mobj_t *itnext;
INT32 health; // for player this is rings + 1 -- no it isn't, not any more!!
@ -504,20 +504,16 @@ struct actioncache_t
extern actioncache_t actioncachehead;
extern mobj_t *kitemcap;
extern mobj_t *trackercap;
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_IsKartFieldItem(INT32 type);
boolean P_IsKartItem(INT32 type);
boolean K_IsMissileOrKartItem(mobj_t *mo);
boolean P_CanDeleteKartItem(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

@ -2195,7 +2195,7 @@ static void SaveMobjThinker(savebuffer_t *save, const thinker_t *th, const UINT8
diff2 |= MD2_DISPOFFSET;
if (mobj == waypointcap)
diff2 |= MD2_WAYPOINTCAP;
if (mobj == kitemcap)
if (mobj == trackercap)
diff2 |= MD2_KITEMCAP;
if (mobj->itnext)
diff2 |= MD2_ITNEXT;
@ -3614,7 +3614,7 @@ static thinker_t* LoadMobjThinker(savebuffer_t *save, actionf_p1 thinker)
P_SetTarget(&waypointcap, mobj);
if (diff2 & MD2_KITEMCAP)
P_SetTarget(&kitemcap, mobj);
P_SetTarget(&trackercap, mobj);
R_AddMobjInterpolator(mobj);
@ -4255,7 +4255,7 @@ static void P_NetUnArchiveThinkers(savebuffer_t *save)
P_InitThinkers();
// Oh my god don't blast random memory with our reference counts.
waypointcap = kitemcap = NULL;
waypointcap = trackercap = NULL;
for (i = 0; i <= 15; i++)
{
skyboxcenterpnts[i] = skyboxviewpnts[i] = NULL;

View file

@ -210,7 +210,7 @@ void P_InitThinkers(void)
{
UINT8 i;
waypointcap = NULL;
kitemcap = NULL;
trackercap = NULL;
for (i = 0; i < NUM_THINKERLISTS; i++)
thlist[i].prev = thlist[i].next = &thlist[i];
}
@ -636,9 +636,6 @@ void P_Ticker(boolean run)
if (!demo.playback) // Don't increment if a demo is playing.
gamedata->totalplaytime++;
// formality so kitemcap gets updated properly each frame.
P_RunKartItems();
if (run)
{
ps_thinkertime = I_GetPreciseTime();