From dd7f6b17dd5b70edf92e14e2ba620044172a9c85 Mon Sep 17 00:00:00 2001 From: James R Date: Sat, 19 Aug 2023 03:28:41 -0700 Subject: [PATCH] Add fuse behavior to emerald orbit, Battle collect animation - Battle emeralds orbit into the player's body upon collection - Emerald shrinks down to a speck - Orbiting speed increases over time - Player's emerald flags altered at the end of the animation --- src/k_objects.h | 3 +- src/objects/emerald.c | 68 +++++++++++++++++++++++++++++++++++++++++-- src/objects/ufo.c | 2 +- src/p_inter.c | 11 +++++-- src/p_mobj.c | 6 ++++ 5 files changed, 83 insertions(+), 7 deletions(-) diff --git a/src/k_objects.h b/src/k_objects.h index 513f88fdb..3cb031229 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -207,7 +207,8 @@ void Obj_SneakerPanelCollide(mobj_t *pad, mobj_t *mo); /* Emerald */ void Obj_SpawnEmeraldSparks(mobj_t *source); void Obj_EmeraldThink(mobj_t *emerald); -void Obj_BeginEmeraldOrbit(mobj_t *emerald, mobj_t *target, fixed_t radius, INT32 revolution_time); +void Obj_BeginEmeraldOrbit(mobj_t *emerald, mobj_t *target, fixed_t radius, INT32 revolution_time, tic_t fuse); +void Obj_GiveEmerald(mobj_t *emerald); #ifdef __cplusplus } // extern "C" diff --git a/src/objects/emerald.c b/src/objects/emerald.c index 6ef557b12..4c428ea12 100644 --- a/src/objects/emerald.c +++ b/src/objects/emerald.c @@ -4,6 +4,7 @@ #include "../m_random.h" #include "../p_local.h" #include "../r_main.h" +#include "../s_sound.h" #include "../tables.h" #define emerald_type(o) ((o)->extravalue1) @@ -12,6 +13,11 @@ #define emerald_start_radius(o) ((o)->movecount) #define emerald_target_radius(o) ((o)->extravalue2) #define emerald_z_shift(o) ((o)->reactiontime) +#define emerald_scale_rate(o) ((o)->movefactor) + +// Think of this like EMERALD_SPEED_UP / EMERALD_SPEED_UP_RATE +#define EMERALD_SPEED_UP (1) // speed up by this much... +#define EMERALD_SPEED_UP_RATE (1) // ...every N tics void Obj_SpawnEmeraldSparks(mobj_t *mobj) { @@ -60,7 +66,10 @@ static fixed_t get_current_radius(mobj_t *emerald) static fixed_t get_bob(mobj_t *emerald) { - angle_t phase = get_elapsed(emerald) * ((ANGLE_MAX / get_revolve_time(emerald)) / 2); + // With a fuse, the emerald experiences "speed up" and the + // scale also shrinks. All of these these effects caused + // the bob phase shift to look disproportioned. + angle_t phase = emerald->fuse ? 0 : get_elapsed(emerald) * ((ANGLE_MAX / get_revolve_time(emerald)) / 2); return FixedMul(30 * mapobjectscale, FSIN(emerald->angle + phase)); } @@ -77,6 +86,27 @@ static fixed_t get_target_z(mobj_t *emerald) return center_of(emerald->target) + get_bob(emerald) + shift; } +static void speed_up(mobj_t *emerald) +{ + // Revolution time shouldn't decrease below zero. + if (emerald_revolution_time(emerald) <= EMERALD_SPEED_UP) + { + return; + } + + if (get_elapsed(emerald) % EMERALD_SPEED_UP_RATE) + { + return; + } + + // Decrease the fuse proportionally to the revolution time. + const fixed_t ratio = (emerald->fuse * FRACUNIT) / emerald_revolution_time(emerald); + + emerald_revolution_time(emerald) -= EMERALD_SPEED_UP; + + emerald->fuse = max(1, (emerald_revolution_time(emerald) * ratio) / FRACUNIT); +} + static void Obj_EmeraldOrbitPlayer(mobj_t *emerald) { fixed_t r = get_current_radius(emerald); @@ -91,6 +121,13 @@ static void Obj_EmeraldOrbitPlayer(mobj_t *emerald) ); emerald->angle += ANGLE_MAX / get_revolve_time(emerald); + + if (emerald->fuse > 0) + { + speed_up(emerald); + + P_InstaScale(emerald, emerald->fuse * emerald_scale_rate(emerald)); + } } void Obj_EmeraldThink(mobj_t *emerald) @@ -126,7 +163,7 @@ void Obj_EmeraldThink(mobj_t *emerald) K_BattleOvertimeKiller(emerald); } -void Obj_BeginEmeraldOrbit(mobj_t *emerald, mobj_t *target, fixed_t radius, INT32 revolution_time) +void Obj_BeginEmeraldOrbit(mobj_t *emerald, mobj_t *target, fixed_t radius, INT32 revolution_time, tic_t fuse) { P_SetTarget(&emerald->target, target); @@ -136,9 +173,36 @@ void Obj_BeginEmeraldOrbit(mobj_t *emerald, mobj_t *target, fixed_t radius, INT3 emerald_start_radius(emerald) = R_PointToDist2(target->x, target->y, emerald->x, emerald->y); emerald_target_radius(emerald) = radius; + emerald->fuse = fuse; + + if (fuse) + { + emerald_scale_rate(emerald) = emerald->scale / fuse; + } + emerald->angle = R_PointToAngle2(target->x, target->y, emerald->x, emerald->y); emerald_z_shift(emerald) = emerald->z - get_target_z(emerald); emerald->flags |= MF_NOGRAVITY | MF_NOCLIP | MF_NOCLIPTHING | MF_NOCLIPHEIGHT; emerald->shadowscale = 0; } + +void Obj_GiveEmerald(mobj_t *emerald) +{ + if (P_MobjWasRemoved(emerald->target)) + { + return; + } + + player_t *player = emerald->target->player; + + if (!player) + { + return; + } + + player->emeralds |= emerald_type(emerald); + K_CheckEmeralds(player); + + S_StartSound(emerald->target, emerald->info->deathsound); +} diff --git a/src/objects/ufo.c b/src/objects/ufo.c index 0ed90df50..6a9f4bbdc 100644 --- a/src/objects/ufo.c +++ b/src/objects/ufo.c @@ -883,7 +883,7 @@ boolean Obj_UFOEmeraldCollect(mobj_t *ufo, mobj_t *toucher) const int kScaleTics = 16; // Emerald will now orbit the player - Obj_BeginEmeraldOrbit(emerald, toucher, 100 * mapobjectscale, 64); + Obj_BeginEmeraldOrbit(emerald, toucher, 100 * mapobjectscale, 64, 0); // Scale down because the emerald is huge // Super Emerald needs to be scaled down further diff --git a/src/p_inter.c b/src/p_inter.c index fb2a7a071..7b1e9cd2e 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -464,9 +464,14 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) if (toucher->hitlag > 0) return; - player->emeralds |= special->extravalue1; - K_CheckEmeralds(player); - break; + // Emerald will now orbit the player + + { + const tic_t orbit = 2*TICRATE; + Obj_BeginEmeraldOrbit(special, toucher, toucher->radius, orbit, orbit * 20); + } + + return; case MT_SPECIAL_UFO: if (Obj_UFOEmeraldCollect(special, toucher) == false) { diff --git a/src/p_mobj.c b/src/p_mobj.c index 47d20059b..de0e233f5 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -9825,6 +9825,12 @@ static boolean P_FuseThink(mobj_t *mobj) break; } + case MT_EMERALD: + { + Obj_GiveEmerald(mobj); + P_RemoveMobj(mobj); + return false; + } case MT_PLAYER: break; // don't remove default: