RingRacers/src/objects/manta-ring.c
Sally Coolatta 60e80d876d Improve quake effects
- Quake epicenter + radius now work.
- Since quake epicenter works, removed the display player check on all of the quakes, so other players can feel them.
- Multiple quake effects are stored in a linked list and dynamically created/freed, so they can stack together.
- Made in china
- Made the quake effects only work on the z axis.
- Quakes now alternate their intensity and dampen it over time, instead of randomly picking values.
- Added quake effects for offroad and stair-jank
- Disabled quakes in reducevfx
- Removed actionmovie and windowquake (sorry jartha)
2023-05-01 14:24:32 -04:00

304 lines
6.2 KiB
C

// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2022 by Sally "TehRealSalt" Cochenour
// Copyright (C) 2022 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.
//-----------------------------------------------------------------------------
/// \file manta-ring.c
/// \brief SPB Juicebox rings. See spb.c for their spawning.
#include "../doomdef.h"
#include "../doomstat.h"
#include "../info.h"
#include "../k_kart.h"
#include "../k_objects.h"
#include "../m_random.h"
#include "../p_local.h"
#include "../r_main.h"
#include "../s_sound.h"
#include "../g_game.h"
#include "../z_zone.h"
#include "../k_waypoint.h"
#include "../k_respawn.h"
#define MANTA_RACETIME (90)
#define MANTA_MINTIME (15)
#define MANTA_SPRINTTIME (60)
#define MANTA_ALIVEGATE (0)
#define MANTA_DEADGATE (FF_TRANS80)
#define MANTA_SIZE (2 * FRACUNIT)
#define MANTA_SIZEUP (10)
#define MANTA_SIZESTRENGTH (1500)
#define MANTA_MAXRAMP (80)
#define MANTA_COLLIDE (80 * FRACUNIT)
#define MANTA_TURBO (40)
#define MANTA_FASTRAMP (17)
#define MANTA_MINPWR (10)
#define manta_delay(o) ((o)->fuse)
#define manta_timealive(o) ((o)->movecount)
#define manta_boostval(o) ((o)->extravalue1)
#define manta_laps(o) ((o)->extravalue2)
#define manta_touched(o) ((o)->cusval)
#define manta_owner(o) ((o)->target)
#define manta_chase(o) ((o)->tracer)
static boolean MantaAlreadyTouched(mobj_t *manta, player_t *player)
{
INT32 touchFlag = 0;
if (manta_chase(manta) != NULL && P_MobjWasRemoved(manta_chase(manta)) == false
&& player->mo == manta_chase(manta))
{
return true;
}
#if 0
if (manta_laps(manta) < player->laps)
{
return true;
}
#endif
touchFlag = 1 << (player - players);
return (manta_touched(manta) & touchFlag);
}
static void Obj_MantaCollide(mobj_t *manta, mobj_t *other)
{
// Could hook this into actual mobj collide if desired.
fixed_t distance = INT32_MAX;
fixed_t size = INT32_MAX;
INT32 addBoost = 0;
INT32 touchFlag = 0;
size_t i;
distance = P_AproxDistance(P_AproxDistance(
other->x - manta->x,
other->y - manta->y),
other->z - manta->z) - other->radius - manta->radius;
size = FixedMul(MANTA_COLLIDE, mapobjectscale);
if (distance > size)
{
return;
}
if (other->player != NULL) // Just in case other objects should be added?
{
if (MantaAlreadyTouched(manta, other->player))
{
return;
}
touchFlag = 1 << (other->player - players);
}
addBoost = manta_boostval(manta);
if (manta_timealive(manta) < MANTA_FASTRAMP)
{
// Ramp up to max power.
addBoost = FixedMul(addBoost * FRACUNIT, (manta_timealive(manta) * FRACUNIT) / MANTA_FASTRAMP);
// Convert to integer
addBoost = (addBoost + (FRACUNIT/2)) / FRACUNIT;
// Cap it
addBoost = max(MANTA_MINPWR, addBoost);
}
if (other->player != NULL)
{
UINT8 snd = 0;
if (other->player->speedboost > FRACUNIT/4)
{
snd = other->player->gateSound;
other->player->gateSound++;
if (other->player->gateSound > 4)
{
other->player->gateSound = 4;
}
}
else
{
other->player->gateSound = 0;
}
K_SpawnDriftBoostExplosion(other->player, 3);
K_SpawnDriftElectricSparks(other->player, SKINCOLOR_CRIMSON, true);
for (i = 0; i < 5; i++)
{
S_StopSoundByID(other, sfx_gate01 + i);
}
S_StartSound(other, sfx_gate01 + snd);
other->player->gateBoost += addBoost/2;
P_StartQuakeFromMobj(6, 12 * other->scale, 512 * other->scale, other);
}
if (touchFlag > 0)
{
manta_touched(manta) |= touchFlag;
}
}
static void RunMantaCollide(mobj_t *manta)
{
INT32 i;
for (i = 0; i < MAXPLAYERS; i++)
{
player_t *player = NULL;
if (playeringame[i] == false)
{
// Invalid
continue;
}
player = &players[i];
if (player->spectator == true)
{
// Not playing.
continue;
}
if (player->mo == NULL || P_MobjWasRemoved(player->mo) == true)
{
// Invalid object
continue;
}
if (player->mo == manta_chase(manta))
{
// Don't allow the person being chased to touch this.
continue;
}
Obj_MantaCollide(manta, player->mo);
}
}
static void RunMantaVisual(mobj_t *manta)
{
INT32 i;
if (manta->fuse < 5*TICRATE)
{
if (leveltime & 1)
{
manta->renderflags |= RF_DONTDRAW;
}
else
{
manta->renderflags &= ~RF_DONTDRAW;
}
}
for (i = 0; i <= r_splitscreen; i++)
{
const UINT8 pID = displayplayers[i];
player_t *player = &players[pID];
if (MantaAlreadyTouched(manta, player) == false)
{
break;
}
}
if (i > r_splitscreen)
{
manta->frame = (manta->frame & ~FF_TRANSMASK) | MANTA_DEADGATE;
}
else
{
manta->frame = (manta->frame & ~FF_TRANSMASK) | MANTA_ALIVEGATE;
}
}
void Obj_MantaRingThink(mobj_t *manta)
{
RunMantaVisual(manta);
if (manta_delay(manta) % MANTA_SIZEUP == 0)
{
manta->destscale += FixedMul(MANTA_SIZESTRENGTH, mapobjectscale);
manta_boostval(manta) = min(MANTA_MAXRAMP, manta_boostval(manta) + 1);
}
manta_timealive(manta)++;
RunMantaCollide(manta);
}
mobj_t *Obj_MantaRingCreate(mobj_t *spb, mobj_t *owner, mobj_t *chase)
{
mobj_t *manta = NULL;
INT32 delay = 0;
manta = P_SpawnMobjFromMobj(spb, 0, 0, 0, MT_MANTARING);
manta->color = SKINCOLOR_KETCHUP;
manta->destscale = FixedMul(MANTA_SIZE, spb->scale);
P_SetScale(manta, manta->destscale);
manta->angle = R_PointToAngle2(0, 0, spb->momx, spb->momy) + ANGLE_90;
// Set boost value
manta_boostval(manta) = MANTA_TURBO;
// Set despawn delay
delay = max(MANTA_MINTIME, MANTA_RACETIME / mapheaderinfo[gamemap - 1]->numlaps);
if (mapheaderinfo[gamemap - 1]->levelflags & LF_SECTIONRACE)
{
delay = MANTA_SPRINTTIME;
}
manta_delay(manta) = delay * TICRATE;
// Default if neither object exists
manta_laps(manta) = INT32_MAX;
// Set owner
if (owner != NULL && P_MobjWasRemoved(owner) == false)
{
P_SetTarget(&manta_owner(manta), owner);
if (owner->player != NULL)
{
// Default if chaser doesn't exist
manta_laps(manta) = owner->player->laps;
}
}
// Set chaser
if (chase != NULL && P_MobjWasRemoved(chase) == false)
{
P_SetTarget(&manta_chase(manta), chase);
if (chase->player != NULL)
{
manta_laps(manta) = chase->player->laps;
}
}
return manta;
}