RingRacers/src/objects/exp.c
2025-06-12 12:52:55 -04:00

143 lines
No EOL
4.1 KiB
C

// DR. ROBOTNIK'S RING RACERS
//-----------------------------------------------------------------------------
// Copyright (C) 2025 by AJ "Tyron" Martinez.
// Copyright (C) 2025 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 amps.c
/// \brief EXP VFX code.
#include "../doomdef.h"
#include "../info.h"
#include "../k_objects.h"
#include "../p_local.h"
#include "../k_kart.h"
#include "../k_powerup.h"
#include "../m_random.h"
#include "../r_main.h"
#include "../m_easing.h"
#include "../s_sound.h"
#include "../sounds.h"
#define EXP_ARCTIME (8)
#define EXP_ORBIT (100)
static void ghostme(mobj_t *exp, player_t *player)
{
if (exp->cusval%2)
return;
mobj_t *ghost = P_SpawnGhostMobj(exp);
ghost->colorized = true;
ghost->color = player->skincolor;
ghost->renderflags |= RF_ADD;
ghost->fuse = 2;
}
void Obj_ExpThink (mobj_t *exp)
{
if (P_MobjWasRemoved(exp->target)
|| exp->target->health == 0
|| exp->target->destscale <= 1 // sealed star fall out
|| !exp->target->player)
{
P_RemoveMobj(exp);
}
else
{
mobj_t *mo = exp->target;
player_t *player = mo->player;
fixed_t dist, fakez;
angle_t hang, vang;
dist = P_AproxDistance(P_AproxDistance(exp->x - mo->x, exp->y - mo->y), exp->z - mo->z);
exp->renderflags |= RF_DONTDRAW;
exp->renderflags &= ~K_GetPlayerDontDrawFlag(player);
// K_MatchGenericExtraFlags(exp, mo);
exp->cusval++;
// bullshit copypaste orbit behavior
if (exp->threshold)
{
fixed_t orbit = (4*mo->scale) * (16 - exp->extravalue1);
P_SetScale(exp, (exp->destscale = mapobjectscale - ((mapobjectscale/28) * exp->extravalue1)));
exp->z = exp->target->z;
P_MoveOrigin(exp,
mo->x + FixedMul(orbit, FINECOSINE(exp->angle >> ANGLETOFINESHIFT)),
mo->y + FixedMul(orbit, FINESINE(exp->angle >> ANGLETOFINESHIFT)),
exp->z + mo->scale * 24 * P_MobjFlip(exp));
exp->momx = 0;
exp->momy = 0;
exp->momz = 0;
ghostme(exp, player);
exp->angle += ANG30;
exp->extravalue1++;
if (exp->extravalue1 >= 16)
P_RemoveMobj(exp);
return;
}
exp->angle += ANGLE_45/2;
UINT8 damper = 3;
fixed_t vert = dist/3;
fixed_t speed = 60*exp->scale;
if (exp->extravalue2) // Mode: going down, aim at the player and speed up / dampen stray movement
{
if (exp->extravalue1)
exp->extravalue1--;
exp->extravalue2++;
speed += exp->extravalue2 * exp->scale/2;
fakez = mo->z + (vert * exp->extravalue1 / EXP_ARCTIME);
damper = 1;
}
else // Mode: going up, aim above the player
{
exp->extravalue1++;
if (exp->extravalue1 >= EXP_ARCTIME)
exp->extravalue2 = 1;
fakez = mo->z + vert;
}
if (mo->flags & MFE_VERTICALFLIP)
fakez -= mo->height/2;
else
fakez += mo->height/2;
hang = R_PointToAngle2(exp->x, exp->y, mo->x, mo->y);
vang = R_PointToAngle2(exp->z, 0, fakez, dist);
exp->momx -= exp->momx>>(damper), exp->momy -= exp->momy>>(damper), exp->momz -= exp->momz>>(damper);
exp->momx += FixedMul(FINESINE(vang>>ANGLETOFINESHIFT), FixedMul(FINECOSINE(hang>>ANGLETOFINESHIFT), speed));
exp->momy += FixedMul(FINESINE(vang>>ANGLETOFINESHIFT), FixedMul(FINESINE(hang>>ANGLETOFINESHIFT), speed));
exp->momz += FixedMul(FINECOSINE(vang>>ANGLETOFINESHIFT), speed);
ghostme(exp, player);
if (dist < (EXP_ORBIT * exp->scale) && exp->extravalue2)
{
exp->threshold = TICRATE;
exp->extravalue1 = 0;
exp->extravalue2 = 0;
}
}
}