From a24e9bb19f9d1bb738334f013dd6d5451cf061e3 Mon Sep 17 00:00:00 2001 From: SteelT Date: Tue, 27 Jun 2023 22:53:16 -0400 Subject: [PATCH] Add basic Battle UFO object functionality --- src/k_objects.h | 6 ++++ src/objects/CMakeLists.txt | 1 + src/objects/battle-ufo.c | 68 ++++++++++++++++++++++++++++++++++++++ src/p_inter.c | 6 ++-- src/p_mobj.c | 17 ++++++++-- 5 files changed, 94 insertions(+), 4 deletions(-) create mode 100644 src/objects/battle-ufo.c diff --git a/src/k_objects.h b/src/k_objects.h index b5cbb6e70..ec7093e44 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -161,6 +161,12 @@ void Obj_SuperFlickyPlayerCollide(mobj_t *flicky, mobj_t *player); void Obj_SuperFlickyLanding(mobj_t *flicky); boolean Obj_IsSuperFlickyWhippable(const mobj_t *flicky); +/* Battle/Power-UP UFO */ +void Obj_BattleUFOLegThink(mobj_t *leg); +void Obj_BattleUFOThink(mobj_t *ufo); +void Obj_SpawnBattleUFOLegs(mobj_t *ufo); +void Obj_BattleUFODeath(mobj_t *ufo); + /* Power-Up Aura */ void Obj_SpawnPowerUpAura(player_t* player); void Obj_PowerUpAuraThink(mobj_t* mobj); diff --git a/src/objects/CMakeLists.txt b/src/objects/CMakeLists.txt index 2c1e68030..f85b01ee4 100644 --- a/src/objects/CMakeLists.txt +++ b/src/objects/CMakeLists.txt @@ -22,5 +22,6 @@ target_sources(SRB2SDL2 PRIVATE gachabom-rebound.cpp servant-hand.c super-flicky.cpp + battle-ufo.c powerup-aura.cpp ) diff --git a/src/objects/battle-ufo.c b/src/objects/battle-ufo.c new file mode 100644 index 000000000..b3d4ad7be --- /dev/null +++ b/src/objects/battle-ufo.c @@ -0,0 +1,68 @@ +#include "../doomdef.h" +#include "../p_local.h" +#include "../k_objects.h" + +#define BATTLEUFO_LEG_ZOFFS (3*FRACUNIT) // Spawn height offset from the body +#define BATTLEUFO_LEGS (3) // Number of UFO legs to spawn +#define BATTLEUFO_BOB_AMP (4) // UFO bob strength +#define BATTLEUFO_BOB_SPEED (TICRATE*2) // UFO bob speed + +void Obj_BattleUFOThink(mobj_t *ufo) +{ + // Copied and slightly modified from k_kart.c + fixed_t sine = FixedMul(ufo->scale, BATTLEUFO_BOB_AMP * FINESINE((((M_TAU_FIXED * BATTLEUFO_BOB_SPEED) * leveltime) >> ANGLETOFINESHIFT) & FINEMASK)); + fixed_t targz = FixedMul(ufo->scale, sine) * P_MobjFlip(ufo); + ufo->momz = targz; +} + +void Obj_BattleUFODeath(mobj_t *ufo) +{ + ufo->momz = -(8*mapobjectscale)/2; + ufo->fuse = TICRATE; +} + +void Obj_SpawnBattleUFOLegs(mobj_t *ufo) +{ + INT32 i; + angle_t ang = 0; + const fixed_t angle_factor = ANGLE_MAX / BATTLEUFO_LEGS; + + for (i = 0; i < BATTLEUFO_LEGS; i++) + { + mobj_t *leg = P_SpawnMobjFromMobj(ufo, 0, 0, BATTLEUFO_LEG_ZOFFS, MT_BATTLEUFO_LEG); + P_SetTarget(&leg->target, ufo); + ang += angle_factor; + leg->angle = ang; + } +} + +void Obj_BattleUFOLegThink(mobj_t *leg) +{ + if (!leg->target || P_MobjWasRemoved(leg->target)) + { + P_RemoveMobj(leg); + return; + } + + // Rotate around the UFO + if (leg->target->health > 0) + { + leg->angle += FixedAngle(leg->info->speed); + + const angle_t fa = leg->angle>>ANGLETOFINESHIFT; + const fixed_t radius = FixedMul(14*leg->info->speed, leg->target->scale); + fixed_t x = leg->target->x + FixedMul(FINECOSINE(fa),radius); + fixed_t y = leg->target->y + FixedMul(FINESINE(fa),radius); + + // TODO: Take gravflip into account + P_MoveOrigin(leg, x, y, leg->z); + } + + leg->momz = leg->target->momz; + + if (leg->target->hitlag) + { + leg->hitlag = leg->target->hitlag; + leg->eflags |= (leg->target->eflags & MFE_DAMAGEHITLAG); + } +} diff --git a/src/p_inter.c b/src/p_inter.c index 86de35c03..a4ebc3b95 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -799,7 +799,7 @@ void P_CheckTimeLimit(void) { if (((timelimitintics + starttime - leveltime) % TICRATE) == 0) S_StartSound(NULL, sfx_s3ka7); - } + } } return; } @@ -1725,7 +1725,9 @@ void P_KillMobj(mobj_t *target, mobj_t *inflictor, mobj_t *source, UINT8 damaget case MT_MONITOR: Obj_MonitorOnDeath(target); break; - + case MT_BATTLEUFO: + Obj_BattleUFODeath(target); + break; default: break; } diff --git a/src/p_mobj.c b/src/p_mobj.c index 5e89fefbf..8518b8b7b 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -8069,7 +8069,7 @@ static boolean P_MobjRegularThink(mobj_t *mobj) // cusval: responsible for disappear FX (should only happen once) // S_MAGICANBOX: sides, starting angle is set in the spawner (SetRandomFakePlayerSkin) - // S_MAGICIANBOX_TOP, S_MAGICIANBOX_BOTTOM: splats with their own offset sprite sets + // S_MAGICIANBOX_TOP, S_MAGICIANBOX_BOTTOM: splats with their own offset sprite sets mobj->extravalue2--; @@ -8436,6 +8436,16 @@ static boolean P_MobjRegularThink(mobj_t *mobj) Obj_ItemDebrisThink(mobj); break; } + case MT_BATTLEUFO: + { + Obj_BattleUFOThink(mobj); + break; + } + case MT_BATTLEUFO_LEG: + { + Obj_BattleUFOLegThink(mobj); + break; + } case MT_ROCKETSNEAKER: if (!mobj->target || !mobj->target->health) { @@ -10920,6 +10930,9 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) case MT_SPHEREBOX: Obj_RandomItemSpawn(mobj); break; + case MT_BATTLEUFO: + Obj_SpawnBattleUFOLegs(mobj); + break; default: break; } @@ -12268,7 +12281,7 @@ static mobjtype_t P_GetMobjtypeSubstitute(mapthing_t *mthing, mobjtype_t i) if ((i == MT_RANDOMITEM) && (gametyperules & (GTR_PAPERITEMS|GTR_CIRCUIT)) == (GTR_PAPERITEMS|GTR_CIRCUIT)) return MT_PAPERITEMSPOT; - + return i; }