Merge branch 'taller-items' into 'master'

Improved item hitboxes and emerald collect animation in Sealed Stars + other emerald polish

See merge request KartKrew/Kart!1395
This commit is contained in:
Oni 2023-08-13 14:55:31 +00:00
commit 1385a192e1
12 changed files with 206 additions and 96 deletions

View file

@ -1851,12 +1851,12 @@ state_t states[NUMSTATES] =
{SPR_EMBM, 25, -1, {NULL}, 0, 0, S_NULL}, // S_EMBLEM26
// Chaos Emeralds
{SPR_EMRC, FF_SEMIBRIGHT, 1, {NULL}, 0, 0, S_CHAOSEMERALD2}, // S_CHAOSEMERALD1
{SPR_EMRC, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_CHAOSEMERALD2}, // S_CHAOSEMERALD1
{SPR_EMRC, FF_FULLBRIGHT|FF_ADD, 1, {NULL}, 0, 0, S_CHAOSEMERALD1}, // S_CHAOSEMERALD2
{SPR_EMRC, FF_FULLBRIGHT|1, -1, {NULL}, 1, 0, S_NULL}, // S_CHAOSEMERALD_UNDER
// Super Emeralds
{SPR_SEMR, FF_SEMIBRIGHT, 1, {NULL}, 0, 0, S_SUPEREMERALD2}, // S_SUPEREMERALD1
{SPR_SEMR, FF_FULLBRIGHT, 1, {NULL}, 0, 0, S_SUPEREMERALD2}, // S_SUPEREMERALD1
{SPR_SEMR, FF_FULLBRIGHT|FF_ADD, 1, {NULL}, 0, 0, S_SUPEREMERALD1}, // S_SUPEREMERALD2
{SPR_SEMR, FF_FULLBRIGHT|1, -1, {NULL}, 1, 0, S_NULL}, // S_SUPEREMERALD_UNDER
@ -23700,7 +23700,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_kc2e, // deathsound
0, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
64*FRACUNIT, // height
0, // display offset
100, // mass
1, // damage
@ -23754,7 +23754,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // deathsound
0, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
64*FRACUNIT, // height
0, // display offset
100, // mass
1, // damage
@ -23835,7 +23835,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_s3k5d, // deathsound
28*FRACUNIT, // speed
24*FRACUNIT, // radius
32*FRACUNIT, // height
64*FRACUNIT, // height
0, // display offset
100, // mass
1, // damage
@ -23889,7 +23889,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_s3k5d, // deathsound
28*FRACUNIT, // speed
16*FRACUNIT, // radius
32*FRACUNIT, // height
64*FRACUNIT, // height
0, // display offset
100, // mass
1, // damage
@ -24213,7 +24213,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_hogbom, // deathsound
40*FRACUNIT, // speed
26*FRACUNIT, // radius
32*FRACUNIT, // height
64*FRACUNIT, // height
0, // display offset
100, // mass
1, // damage
@ -24888,7 +24888,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_s3k5d, // deathsound
28*FRACUNIT, // speed
24*FRACUNIT, // radius
32*FRACUNIT, // height
64*FRACUNIT, // height
0, // display offset
100, // mass
1, // damage
@ -30131,7 +30131,7 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] =
sfx_None, // deathsound
0, // speed
108*FRACUNIT, // radius
72*FRACUNIT, // height
180*FRACUNIT, // height
0, // display offset
16, // mass
0, // damage

View file

@ -853,3 +853,22 @@ INT32 K_BumpersToHealth(UINT8 bumpers)
{
return (bumpers + 1);
}
boolean K_BattleOvertimeKiller(mobj_t *mobj)
{
if (battleovertime.enabled < 10*TICRATE)
{
return false;
}
fixed_t distance = R_PointToDist2(mobj->x, mobj->y, battleovertime.x, battleovertime.y);
if (distance <= battleovertime.radius)
{
return false;
}
P_KillMobj(mobj, NULL, NULL, DMG_NORMAL);
return true;
}

View file

@ -51,6 +51,7 @@ void K_SpawnPlayerBattleBumpers(player_t *p);
void K_BattleInit(boolean singleplayercontext);
UINT8 K_Bumpers(player_t *player);
INT32 K_BumpersToHealth(UINT8 bumpers);
boolean K_BattleOvertimeKiller(mobj_t *mobj);
#ifdef __cplusplus
} // extern "C"

View file

@ -8,6 +8,7 @@
#include "k_hud.h"
#include "k_kart.h"
#include "k_objects.h"
#include "k_specialstage.h"
#include "m_fixed.h"
#include "p_local.h"
#include "p_mobj.h"
@ -374,9 +375,6 @@ bool is_object_tracking_target(const mobj_t* mobj)
case MT_CDUFO:
return battleprisons;
case MT_SPECIAL_UFO:
return true;
case MT_PLAYER:
return is_player_tracking_target(mobj->player);
@ -384,7 +382,7 @@ bool is_object_tracking_target(const mobj_t* mobj)
return inDuel == false && battleovertime.enabled;
case MT_EMERALD:
return is_player_tracking_target();
return (specialstageinfo.valid && specialstageinfo.ufo) || is_player_tracking_target();
case MT_MONITOR:
return is_player_tracking_target() && Obj_MonitorGetEmerald(mobj) != 0;

View file

@ -8640,6 +8640,7 @@ void K_KartPlayerAfterThink(player_t *player)
}
ret = P_SpawnMobj(targ->x, targ->y, targ->z, MT_PLAYERRETICULE);
ret->sprzoff = targ->sprzoff;
ret->old_x = targ->old_x;
ret->old_y = targ->old_y;
ret->old_z = targ->old_z;

View file

@ -82,10 +82,12 @@ void Obj_UFOPieceDead(mobj_t *piece);
void Obj_UFOPieceRemoved(mobj_t *piece);
mobj_t *Obj_CreateSpecialUFO(void);
UINT32 K_GetSpecialUFODistance(void);
void Obj_UFOEmeraldThink(mobj_t *emerald);
/* Monitors */
mobj_t *Obj_SpawnMonitor(mobj_t *origin, UINT8 numItemTypes, UINT8 emerald);
void Obj_MonitorSpawnParts(mobj_t *monitor);
void Obj_MonitorThink(mobj_t *monitor);
void Obj_MonitorPartThink(mobj_t *part);
fixed_t Obj_MonitorGetDamage(mobj_t *monitor, mobj_t *inflictor, UINT8 damagetype);
void Obj_MonitorOnDamage(mobj_t *monitor, mobj_t *inflictor, INT32 damage);
@ -201,6 +203,10 @@ void Obj_SneakerPanelSpawn(mobj_t *mobj);
void Obj_SneakerPanelSetup(mobj_t *mobj, mapthing_t *mthing);
void Obj_SneakerPanelCollide(mobj_t *pad, mobj_t *mo);
/* Emerald */
void Obj_SpawnEmeraldSparks(mobj_t *source);
void Obj_EmeraldThink(mobj_t *emerald);
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -27,4 +27,5 @@ target_sources(SRB2SDL2 PRIVATE
symbol.c
dash-rings.c
sneaker-panel.c
emerald.c
)

View file

@ -137,6 +137,8 @@ void Obj_BattleUFOThink(mobj_t *mobj)
{
Obj_PointPlayersToXY(mobj->x, mobj->y);
}
K_BattleOvertimeKiller(mobj);
}
void Obj_BattleUFODeath(mobj_t *mobj)

86
src/objects/emerald.c Normal file
View file

@ -0,0 +1,86 @@
#include "../k_battle.h"
#include "../k_objects.h"
#include "../info.h"
#include "../m_random.h"
#include "../p_local.h"
#include "../tables.h"
void Obj_SpawnEmeraldSparks(mobj_t *mobj)
{
if (leveltime % 3 != 0)
{
return;
}
mobj_t *sparkle = P_SpawnMobjFromMobj(
mobj,
P_RandomRange(PR_SPARKLE, -48, 48) * FRACUNIT,
P_RandomRange(PR_SPARKLE, -48, 48) * FRACUNIT,
P_RandomRange(PR_SPARKLE, 0, 64) * FRACUNIT,
MT_EMERALDSPARK
);
sparkle->color = mobj->color;
sparkle->momz += 8 * mobj->scale * P_MobjFlip(mobj);
sparkle->sprzoff = mobj->sprzoff;
}
static void Obj_EmeraldOrbitPlayer(mobj_t *emerald)
{
const int kOrbitTics = 64;
const int kPhaseTics = 128;
const fixed_t orbit_radius = 100 * mapobjectscale;
const fixed_t orbit_height = 30 * mapobjectscale;
mobj_t *targ = emerald->target;
angle_t a = emerald->angle;
fixed_t x = FixedMul(orbit_radius, FCOS(a));
fixed_t y = FixedMul(orbit_radius, FSIN(a));
angle_t phase = (ANGLE_MAX / kPhaseTics) * (leveltime % kPhaseTics);
P_MoveOrigin(
emerald,
targ->x + x,
targ->y + y,
targ->z + targ->height + FixedMul(orbit_height, FSIN(a + phase))
);
emerald->angle += ANGLE_MAX / kOrbitTics;
}
void Obj_EmeraldThink(mobj_t *emerald)
{
if (!P_MobjWasRemoved(emerald->target))
{
switch (emerald->target->type)
{
case MT_SPECIAL_UFO:
Obj_UFOEmeraldThink(emerald);
break;
case MT_PLAYER:
Obj_EmeraldOrbitPlayer(emerald);
break;
default:
break;
}
return;
}
if (emerald->threshold > 0)
{
emerald->threshold--;
}
A_AttractChase(emerald);
Obj_SpawnEmeraldSparks(emerald);
K_BattleOvertimeKiller(emerald);
}

View file

@ -495,6 +495,17 @@ Obj_SpawnMonitor
return monitor;
}
void
Obj_MonitorThink (mobj_t *monitor)
{
if (Obj_MonitorGetEmerald(monitor))
{
Obj_SpawnEmeraldSparks(monitor);
}
K_BattleOvertimeKiller(monitor);
}
void
Obj_MonitorPartThink (mobj_t *part)
{

View file

@ -58,6 +58,8 @@
#define ufo_intangible(o) ((o)->cusval)
#define ufo_emerald(o) ((o)->tracer)
enum
{
UFO_PIECE_TYPE_POD,
@ -459,27 +461,15 @@ static void UFOMove(mobj_t *ufo)
}
}
static void UFOEmeraldVFX(mobj_t *ufo)
static void UFOEmeraldVFX(mobj_t *emerald)
{
const INT32 bobS = 32;
const angle_t bobA = (leveltime & (bobS - 1)) * (ANGLE_MAX / bobS);
const fixed_t bobH = 16 * ufo->scale;
const fixed_t bobH = 16 * emerald->scale;
ufo->sprzoff = FixedMul(bobH, FINESINE(bobA >> ANGLETOFINESHIFT));
emerald->sprzoff = FixedMul(bobH, FINESINE(bobA >> ANGLETOFINESHIFT));
if (leveltime % 3 == 0)
{
mobj_t *sparkle = P_SpawnMobjFromMobj(
ufo,
P_RandomRange(PR_SPARKLE, -48, 48) * FRACUNIT,
P_RandomRange(PR_SPARKLE, -48, 48) * FRACUNIT,
(P_RandomRange(PR_SPARKLE, 0, 64) * FRACUNIT) + FixedDiv(ufo->sprzoff, ufo->scale),
MT_EMERALDSPARK
);
sparkle->color = ufo->color;
sparkle->momz += 8 * ufo->scale * P_MobjFlip(ufo);
}
Obj_SpawnEmeraldSparks(emerald);
}
static boolean UFOHumPlaying(mobj_t *ufo) {
@ -516,8 +506,6 @@ void Obj_SpecialUFOThinker(mobj_t *ufo)
if (UFOEmeraldChase(ufo) == true)
{
// Spawn emerald sparkles
UFOEmeraldVFX(ufo);
ufo_collectdelay(ufo)--;
}
else
@ -868,6 +856,8 @@ void Obj_PlayerUFOCollide(mobj_t *ufo, mobj_t *other)
boolean Obj_UFOEmeraldCollect(mobj_t *ufo, mobj_t *toucher)
{
mobj_t *emerald = ufo_emerald(ufo);
if (toucher->player != NULL)
{
if (P_CanPickupItem(toucher->player, 0) == false)
@ -888,7 +878,19 @@ boolean Obj_UFOEmeraldCollect(mobj_t *ufo, mobj_t *toucher)
ACS_RunEmeraldScript(toucher);
CONS_Printf("You win!\n");
if (!P_MobjWasRemoved(emerald))
{
const int kScaleTics = 16;
// Emerald will now orbit the player
P_SetTarget(&emerald->target, toucher);
// Scale down because the emerald is huge
// Super Emerald needs to be scaled down further
emerald->destscale = emerald->scale / (ufo_emeraldnum(ufo) > 7 ? 3 : 2);
emerald->scalespeed = abs(emerald->destscale - emerald->scale) / kScaleTics;
}
return true;
}
@ -1026,43 +1028,49 @@ static mobj_t *InitSpecialUFO(waypoint_t *start)
// Adjustable Special Stage emerald color/shape
{
overlay = P_SpawnMobjFromMobj(ufo, 0, 0, 0, MT_OVERLAY);
mobj_t *emerald = P_SpawnMobjFromMobj(ufo, 0, 0, 0, MT_EMERALD);
ufo->color = SKINCOLOR_CHAOSEMERALD1;
emerald->flags |= MF_NOGRAVITY | MF_NOCLIP | MF_NOCLIPTHING | MF_NOCLIPHEIGHT;
overlay = P_SpawnMobjFromMobj(emerald, 0, 0, 0, MT_OVERLAY);
emerald->color = SKINCOLOR_CHAOSEMERALD1;
i = ufo_emeraldnum(ufo) = P_GetNextEmerald();
if (i > 0)
{
ufo->color += (i - 1) % 7;
emerald->color += (i - 1) % 7;
if (i > 7)
{
// Super Emeralds
P_SetMobjState(ufo, S_SUPEREMERALD1);
P_SetMobjState(emerald, S_SUPEREMERALD1);
P_SetMobjState(overlay, S_SUPEREMERALD_UNDER);
}
else
{
// Chaos Emerald
P_SetMobjState(ufo, S_CHAOSEMERALD1);
P_SetMobjState(emerald, S_CHAOSEMERALD1);
P_SetMobjState(overlay, S_CHAOSEMERALD_UNDER);
}
}
else
{
// Prize -- todo, currently using standard Emerald
P_SetMobjState(ufo, S_CHAOSEMERALD1);
P_SetMobjState(emerald, S_CHAOSEMERALD1);
P_SetMobjState(overlay, S_CHAOSEMERALD_UNDER);
}
if (P_MobjWasRemoved(ufo)) // uh oh !
{
// Attempted crash prevention with custom SOC
return NULL;
}
P_SetTarget(&emerald->target, ufo);
P_SetTarget(&ufo_emerald(ufo), emerald);
overlay->color = ufo->color;
P_SetTarget(&overlay->target, ufo);
ufo->color = emerald->color; // for minimap
overlay->color = emerald->color;
P_SetTarget(&overlay->target, emerald);
// UFO needs this so Jawz reticle lines up!
ufo->sprzoff = 32 * mapobjectscale;
emerald->sprzoff = ufo->sprzoff;
}
// Create UFO pieces.
@ -1184,3 +1192,16 @@ UINT32 K_GetSpecialUFODistance(void)
return UINT32_MAX;
}
void Obj_UFOEmeraldThink(mobj_t *emerald)
{
mobj_t *ufo = emerald->target;
P_MoveOrigin(emerald, ufo->x, ufo->y, ufo->z);
if (UFOEmeraldChase(ufo) == true)
{
// Spawn emerald sparkles
UFOEmeraldVFX(emerald);
}
}

View file

@ -5325,7 +5325,6 @@ static boolean P_IsTrackerType(INT32 type)
case MT_SPB:
case MT_BATTLECAPSULE:
case MT_CDUFO:
case MT_SPECIAL_UFO:
return true;
// Players sometimes get targeted with HUD tracking
@ -7550,48 +7549,19 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
break;
}
case MT_EMERALD:
{
if (mobj->threshold > 0)
mobj->threshold--;
Obj_EmeraldThink(mobj);
A_AttractChase(mobj);
if (P_MobjWasRemoved(mobj))
{
return false;
}
/*FALLTHRU*/
break;
case MT_MONITOR:
Obj_MonitorThink(mobj);
if (P_MobjWasRemoved(mobj))
{
if (battleovertime.enabled >= 10*TICRATE)
{
fixed_t distance = R_PointToDist2(mobj->x, mobj->y, battleovertime.x, battleovertime.y);
if (distance > battleovertime.radius)
{
// Delete emeralds to let them reappear
P_KillMobj(mobj, NULL, NULL, DMG_NORMAL);
return false;
}
}
// Don't spawn sparkles on a monitor with no
// emerald inside
if (mobj->type == MT_MONITOR &&
Obj_MonitorGetEmerald(mobj) == 0)
{
break;
}
if (leveltime % 3 == 0)
{
mobj_t *sparkle = P_SpawnMobjFromMobj(
mobj,
P_RandomRange(PR_SPARKLE, -48, 48) * FRACUNIT,
P_RandomRange(PR_SPARKLE, -48, 48) * FRACUNIT,
P_RandomRange(PR_SPARKLE, 0, 64) * FRACUNIT,
MT_EMERALDSPARK
);
sparkle->color = mobj->color;
sparkle->momz += 8 * mobj->scale * P_MobjFlip(mobj);
}
return false;
}
break;
case MT_DRIFTEXPLODE:
@ -7910,6 +7880,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
return false;
}
P_MoveOrigin(mobj, mobj->target->x, mobj->target->y, mobj->target->z);
mobj->sprzoff = mobj->target->sprzoff;
mobj->old_x = mobj->target->old_x;
mobj->old_y = mobj->target->old_y;
mobj->old_z = mobj->target->old_z;
@ -8465,19 +8436,12 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
}
case MT_BATTLEUFO:
{
if (battleovertime.enabled >= 10*TICRATE)
{
fixed_t distance = R_PointToDist2(mobj->x, mobj->y, battleovertime.x, battleovertime.y);
if (distance > battleovertime.radius)
{
// Delete emeralds to let them reappear
P_KillMobj(mobj, NULL, NULL, DMG_NORMAL);
return false;
}
}
Obj_BattleUFOThink(mobj);
if (P_MobjWasRemoved(mobj))
{
return false;
}
break;
}
case MT_BATTLEUFO_LEG: