diff --git a/src/k_battle.c b/src/k_battle.c index 31cd4b39d..66e98561c 100644 --- a/src/k_battle.c +++ b/src/k_battle.c @@ -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; +} diff --git a/src/k_battle.h b/src/k_battle.h index f5a7547aa..923367cda 100644 --- a/src/k_battle.h +++ b/src/k_battle.h @@ -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" diff --git a/src/k_objects.h b/src/k_objects.h index a796c021c..cba2f4618 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -86,6 +86,7 @@ UINT32 K_GetSpecialUFODistance(void); /* 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 +202,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 diff --git a/src/objects/CMakeLists.txt b/src/objects/CMakeLists.txt index 4eaa1d2f5..d7c6abccb 100644 --- a/src/objects/CMakeLists.txt +++ b/src/objects/CMakeLists.txt @@ -27,4 +27,5 @@ target_sources(SRB2SDL2 PRIVATE symbol.c dash-rings.c sneaker-panel.c + emerald.c ) diff --git a/src/objects/battle-ufo.cpp b/src/objects/battle-ufo.cpp index b7aff6296..ea53e2bf8 100644 --- a/src/objects/battle-ufo.cpp +++ b/src/objects/battle-ufo.cpp @@ -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) diff --git a/src/objects/emerald.c b/src/objects/emerald.c new file mode 100644 index 000000000..9ab42c75a --- /dev/null +++ b/src/objects/emerald.c @@ -0,0 +1,39 @@ +#include "../k_battle.h" +#include "../k_objects.h" +#include "../info.h" +#include "../m_random.h" +#include "../p_local.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; +} + +void Obj_EmeraldThink(mobj_t *emerald) +{ + if (emerald->threshold > 0) + { + emerald->threshold--; + } + + A_AttractChase(emerald); + + Obj_SpawnEmeraldSparks(emerald); + + K_BattleOvertimeKiller(emerald); +} diff --git a/src/objects/monitor.c b/src/objects/monitor.c index acde862a1..70ab1589d 100644 --- a/src/objects/monitor.c +++ b/src/objects/monitor.c @@ -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) { diff --git a/src/objects/ufo.c b/src/objects/ufo.c index a06c6021d..9ed38ca74 100644 --- a/src/objects/ufo.c +++ b/src/objects/ufo.c @@ -467,19 +467,7 @@ static void UFOEmeraldVFX(mobj_t *ufo) ufo->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(ufo); } static boolean UFOHumPlaying(mobj_t *ufo) { diff --git a/src/p_mobj.c b/src/p_mobj.c index 253e13209..d3723e77a 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -7550,48 +7550,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: @@ -8466,19 +8437,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: