Hardcode Ivo Balls

This commit is contained in:
James R 2023-11-25 04:54:59 -08:00
parent b36695db8d
commit 401321e310
6 changed files with 217 additions and 0 deletions

View file

@ -313,6 +313,14 @@ void Obj_IceCubeBurst(player_t *player);
void Obj_SidewaysFreezeThrusterInit(mobj_t *mobj);
void Obj_SidewaysFreezeThrusterThink(mobj_t *mobj);
/* Ivo Balls */
void Obj_IvoBallInit(mobj_t *mo);
void Obj_IvoBallThink(mobj_t *mo);
void Obj_IvoBallTouch(mobj_t *special, mobj_t *toucher);
void Obj_PatrolIvoBallInit(mobj_t *mo);
void Obj_PatrolIvoBallThink(mobj_t *mo);
void Obj_PatrolIvoBallTouch(mobj_t *special, mobj_t *toucher);
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -43,6 +43,7 @@ target_sources(SRB2SDL2 PRIVATE
charge.c
mega-barrier.cpp
frost-thrower.cpp
ivoball.cpp
)
add_subdirectory(versus)

162
src/objects/ivoball.cpp Normal file
View file

@ -0,0 +1,162 @@
// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2023 by Kart Krew.
//
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
//-----------------------------------------------------------------------------
//
// CREDITS
// Original Lua script by Callmore
// Edits by Ivo, Angular and Sal
// Hardcoded by jartha
//
#include <algorithm>
#include "../math/fixed.hpp"
#include "../math/vec.hpp"
#include "../mobj.hpp"
#include "../d_player.h"
#include "../doomdef.h"
#include "../doomstat.h"
#include "../k_objects.h"
#include "../p_local.h"
#include "../r_defs.h"
#include "../s_sound.h"
#include "../sounds.h"
#include "../tables.h"
using srb2::Mobj;
using srb2::math::Fixed;
using srb2::math::Vec2;
namespace
{
Vec2<Fixed> angle_vector(angle_t x)
{
return Vec2<Fixed> {FCOS(x), FSIN(x)};
}
struct IvoBall : Mobj
{
static constexpr tic_t kCooldown = TICRATE*2;
static constexpr tic_t kFlashTime = TICRATE/2;
static constexpr Fixed kRippleFactor = 128*FRACUNIT/3;
static constexpr Fixed kBobHeight = 8*FRACUNIT;
static constexpr tic_t kBobTime = kFlashTime * 16;
static constexpr int kFloat = 24;
void extravalue1() = delete;
tic_t timer() const { return mobj_t::extravalue1; }
void timer(tic_t n) { mobj_t::extravalue1 = n; }
void extravalue2() = delete;
fixed_t offset() const { return mobj_t::extravalue2; }
void offset(fixed_t n) { mobj_t::extravalue2 = n; }
void init()
{
Fixed wave{(x / mapobjectscale) + (y / mapobjectscale)};
offset(wave / kRippleFactor);
color = SKINCOLOR_TANGERINE;
sprzoff = kFloat * mapobjectscale;
}
void think()
{
if (timer())
{
timer(timer() - 1);
if (timer() == 0)
{
renderflags &= ~RF_DONTDRAW;
}
}
fixed_t ballTimer = leveltime + offset();
Fixed bob = kBobHeight * Fixed {FSIN((M_TAU_FIXED * kBobTime) * ballTimer)};
spriteyoffset = bob;
colorized = !((ballTimer / kFlashTime) & 1);
}
void touch(Mobj* toucher)
{
if (timer())
{
return;
}
renderflags |= RF_DONTDRAW;
timer(kCooldown);
toucher->player->ringboost += 30;
if (P_IsDisplayPlayer(toucher->player))
{
S_StartSoundAtVolume(nullptr, sfx_ivobal, 160);
}
}
};
struct PatrolIvoBall : IvoBall
{
void init()
{
Vec2<Fixed> v = angle_vector(angle) * Fixed {info->speed} * Fixed {mapobjectscale};
momx = -v.x;
momy = v.y;
IvoBall::init();
}
void think()
{
if (!P_TryMove(this, x + momx, y + momy, true, nullptr))
{
angle += ANGLE_180;
momx = -momx;
momy = -momy;
}
IvoBall::think();
}
};
}; // namespace
void Obj_IvoBallInit(mobj_t* mobj)
{
static_cast<IvoBall*>(mobj)->init();
}
void Obj_IvoBallThink(mobj_t* mobj)
{
static_cast<IvoBall*>(mobj)->think();
}
void Obj_IvoBallTouch(mobj_t* special, mobj_t* toucher)
{
static_cast<IvoBall*>(special)->touch(static_cast<Mobj*>(toucher));
}
void Obj_PatrolIvoBallInit(mobj_t* mobj)
{
static_cast<PatrolIvoBall*>(mobj)->init();
}
void Obj_PatrolIvoBallThink(mobj_t* mobj)
{
static_cast<PatrolIvoBall*>(mobj)->think();
}
void Obj_PatrolIvoBallTouch(mobj_t* special, mobj_t* toucher)
{
static_cast<PatrolIvoBall*>(special)->touch(static_cast<Mobj*>(toucher));
}

View file

@ -974,6 +974,18 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
return;
}
case MT_IVOBALL:
case MT_AIRIVOBALL:
{
Obj_IvoBallTouch(special, toucher);
return;
}
case MT_PATROLIVOBALL:
{
Obj_PatrolIvoBallTouch(special, toucher);
return;
}
default: // SOC or script pickup
P_SetTarget(&special->target, toucher);
break;

View file

@ -758,6 +758,18 @@ static BlockItReturn_t PIT_CheckThing(mobj_t *thing)
return BMIT_CONTINUE;
}
if (tm.thing->type == MT_PATROLIVOBALL)
{
if (!thing->player)
return BMIT_CONTINUE;
if (tm.thing->z > thing->z + thing->height)
return BMIT_CONTINUE; // overhead
if (tm.thing->z + tm.thing->height < thing->z)
return BMIT_CONTINUE; // underneath
Obj_PatrolIvoBallTouch(tm.thing, thing);
return BMIT_CONTINUE;
}
if (thing->type == MT_BATTLEUFO)
{
if (tm.thing->type != MT_PLAYER)

View file

@ -6825,6 +6825,17 @@ static void P_MobjSceneryThink(mobj_t *mobj)
}
break;
}
case MT_IVOBALL:
case MT_AIRIVOBALL:
{
Obj_IvoBallThink(mobj);
return;
}
case MT_PATROLIVOBALL:
{
Obj_PatrolIvoBallThink(mobj);
return;
}
case MT_VWREF:
case MT_VWREB:
{
@ -14454,6 +14465,17 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj)
Obj_SidewaysFreezeThrusterInit(mobj);
break;
}
case MT_IVOBALL:
case MT_AIRIVOBALL:
{
Obj_IvoBallInit(mobj);
break;
}
case MT_PATROLIVOBALL:
{
Obj_PatrolIvoBallInit(mobj);
break;
}
default:
break;
}