diff --git a/src/k_hud_track.cpp b/src/k_hud_track.cpp index 138658bec..5b07a975f 100644 --- a/src/k_hud_track.cpp +++ b/src/k_hud_track.cpp @@ -382,7 +382,7 @@ bool is_object_tracking_target(const mobj_t* mobj) return inDuel == false && battleovertime.enabled; case MT_EMERALD: - return specialstageinfo.valid || 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; diff --git a/src/objects/emerald.c b/src/objects/emerald.c index a6502ec41..40524cd12 100644 --- a/src/objects/emerald.c +++ b/src/objects/emerald.c @@ -3,6 +3,7 @@ #include "../info.h" #include "../m_random.h" #include "../p_local.h" +#include "../tables.h" void Obj_SpawnEmeraldSparks(mobj_t *mobj) { @@ -24,6 +25,33 @@ void Obj_SpawnEmeraldSparks(mobj_t *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)) @@ -34,6 +62,10 @@ void Obj_EmeraldThink(mobj_t *emerald) Obj_UFOEmeraldThink(emerald); break; + case MT_PLAYER: + Obj_EmeraldOrbitPlayer(emerald); + break; + default: break; } diff --git a/src/objects/ufo.c b/src/objects/ufo.c index 4dc2ce153..f8e15c459 100644 --- a/src/objects/ufo.c +++ b/src/objects/ufo.c @@ -58,6 +58,8 @@ #define ufo_intangible(o) ((o)->cusval) +#define ufo_emerald(o) ((o)->tracer) + enum { UFO_PIECE_TYPE_POD, @@ -854,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) @@ -874,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; } @@ -1044,6 +1060,7 @@ static mobj_t *InitSpecialUFO(waypoint_t *start) } P_SetTarget(&emerald->target, ufo); + P_SetTarget(&ufo_emerald(ufo), emerald); ufo->color = emerald->color; // for minimap overlay->color = emerald->color;