mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Activate loop endpoints
This commit is contained in:
parent
583ef41ac9
commit
7738d6bb7c
5 changed files with 225 additions and 0 deletions
|
|
@ -92,6 +92,10 @@ boolean Obj_ItemSpotIsAvailable(const mobj_t *spot);
|
|||
void Obj_ItemSpotAssignMonitor(mobj_t *spot, mobj_t *monitor);
|
||||
void Obj_ItemSpotUpdate(mobj_t *spot);
|
||||
|
||||
/* Loops */
|
||||
void Obj_InitLoopCenter(mobj_t *center);
|
||||
void Obj_LoopEndpointCollide(mobj_t *special, mobj_t *toucher);
|
||||
|
||||
#ifdef __cplusplus
|
||||
} // extern "C"
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -12,4 +12,5 @@ target_sources(SRB2SDL2 PRIVATE
|
|||
ufo.c
|
||||
monitor.c
|
||||
item-spot.c
|
||||
loops.c
|
||||
)
|
||||
|
|
|
|||
211
src/objects/loops.c
Normal file
211
src/objects/loops.c
Normal file
|
|
@ -0,0 +1,211 @@
|
|||
// DR. ROBOTNIK'S RING RACERS
|
||||
//-----------------------------------------------------------------------------
|
||||
// Copyright (C) 2023 by James R.
|
||||
// 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.
|
||||
//-----------------------------------------------------------------------------
|
||||
/// \file loop-endpoint.c
|
||||
/// \brief Sonic loops, start and end points
|
||||
|
||||
#include "../doomdef.h"
|
||||
#include "../k_kart.h"
|
||||
#include "../taglist.h"
|
||||
#include "../p_local.h"
|
||||
#include "../p_setup.h"
|
||||
#include "../p_spec.h"
|
||||
#include "../r_main.h"
|
||||
#include "../k_objects.h"
|
||||
|
||||
#define end_anchor(o) ((o)->target)
|
||||
|
||||
#define center_max_revolution(o) ((o)->threshold)
|
||||
#define center_alpha(o) ((o)->target)
|
||||
#define center_beta(o) ((o)->tracer)
|
||||
|
||||
static inline boolean
|
||||
center_has_flip (const mobj_t *center)
|
||||
{
|
||||
return (center->flags2 & MF2_AMBUSH) == MF2_AMBUSH;
|
||||
}
|
||||
|
||||
static inline void
|
||||
center_set_flip
|
||||
( mobj_t * center,
|
||||
boolean mode)
|
||||
{
|
||||
center->flags2 = (center->flags2 & ~(MF2_AMBUSH)) |
|
||||
((mode != false) * MF2_AMBUSH);
|
||||
}
|
||||
|
||||
#define anchor_center(o) ((o)->target)
|
||||
#define anchor_other(o) ((o)->tracer)
|
||||
#define anchor_type(o) ((o)->reactiontime)
|
||||
|
||||
static void
|
||||
set_shiftxy
|
||||
( player_t * player,
|
||||
const mobj_t * a)
|
||||
{
|
||||
const mobj_t *b = anchor_other(a);
|
||||
|
||||
const fixed_t dx = (b->x - a->x);
|
||||
const fixed_t dy = (b->y - a->y);
|
||||
|
||||
const angle_t th =
|
||||
(R_PointToAngle2(0, 0, dx, dy) - a->angle);
|
||||
|
||||
const fixed_t adj = FixedMul(
|
||||
abs(FCOS(AbsAngle(th - ANGLE_90))),
|
||||
FixedHypot(dx, dy)) / 2;
|
||||
|
||||
vector2_t *xy = &player->loop.shift;
|
||||
|
||||
xy->x = FixedMul(FSIN(a->angle), adj);
|
||||
xy->y = FixedMul(FCOS(a->angle), adj);
|
||||
}
|
||||
|
||||
static void
|
||||
measure_clock
|
||||
( const mobj_t * center,
|
||||
const mobj_t * anchor,
|
||||
angle_t * pitch,
|
||||
fixed_t * radius)
|
||||
{
|
||||
const fixed_t dx = (anchor->x - center->x);
|
||||
const fixed_t dy = (anchor->y - center->y);
|
||||
const fixed_t dz = (anchor->z - center->z);
|
||||
|
||||
/* Translate the anchor point to be along a center line.
|
||||
This makes the horizontal position one dimensional
|
||||
relative to the center point. */
|
||||
const fixed_t xy = (
|
||||
FixedMul(dx, FCOS(anchor->angle)) +
|
||||
FixedMul(dy, FSIN(anchor->angle)));
|
||||
|
||||
/* The 3d position of the anchor point is then reduced to
|
||||
two axes and can be measured as an angle. */
|
||||
*pitch = R_PointToAngle2(0, 0, xy, dz) + ANGLE_90;
|
||||
*radius = FixedHypot(xy, dz);
|
||||
}
|
||||
|
||||
static boolean
|
||||
moving_toward_gate
|
||||
( const player_t * player,
|
||||
const mobj_t * anchor,
|
||||
angle_t pitch)
|
||||
{
|
||||
const fixed_t
|
||||
x = player->mo->momx,
|
||||
y = player->mo->momy,
|
||||
z = player->mo->momz,
|
||||
|
||||
zx = FixedMul(FCOS(anchor->angle), z),
|
||||
zy = FixedMul(FSIN(anchor->angle), z),
|
||||
|
||||
co = abs(FCOS(pitch)),
|
||||
si = abs(FSIN(pitch)),
|
||||
|
||||
dx = FixedMul(co, x) + FixedMul(si, zx),
|
||||
dy = FixedMul(co, y) + FixedMul(si, zy);
|
||||
|
||||
return AngleDelta(anchor->angle,
|
||||
R_PointToAngle2(0, 0, dx, dy)) < ANG60;
|
||||
}
|
||||
|
||||
static SINT8
|
||||
get_binary_direction
|
||||
( angle_t pitch,
|
||||
mobj_t * toucher)
|
||||
{
|
||||
const fixed_t si = FSIN(pitch);
|
||||
|
||||
if (abs(si) < abs(FCOS(pitch)))
|
||||
{
|
||||
// pitch = 0 points downward so offset 90 degrees
|
||||
// clockwise so 180 occurs at horizon
|
||||
return ((pitch + ANGLE_90) < ANGLE_180) ? 1 : -(1);
|
||||
}
|
||||
else
|
||||
{
|
||||
return intsign(si) * P_MobjFlip(toucher);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
Obj_InitLoopCenter (mobj_t *center)
|
||||
{
|
||||
const mapthing_t *mt = center->spawnpoint;
|
||||
|
||||
center_max_revolution(center) = mt->args[1] * FRACUNIT / 360;
|
||||
center_set_flip(center, mt->args[0]);
|
||||
}
|
||||
|
||||
void
|
||||
Obj_LoopEndpointCollide
|
||||
( mobj_t * end,
|
||||
mobj_t * toucher)
|
||||
{
|
||||
player_t *player = toucher->player;
|
||||
sonicloopvars_t *s = &player->loop;
|
||||
|
||||
mobj_t *anchor = end_anchor(end);
|
||||
mobj_t *center = anchor ? anchor_center(anchor) : NULL;
|
||||
|
||||
angle_t pitch;
|
||||
fixed_t radius;
|
||||
|
||||
/* predict movement for a smooth transition */
|
||||
const fixed_t px = toucher->x + toucher->momx;
|
||||
const fixed_t py = toucher->y + toucher->momy;
|
||||
|
||||
SINT8 flip;
|
||||
|
||||
if (P_MobjWasRemoved(center))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (player->loop.radius != 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
measure_clock(center, anchor, &pitch, &radius);
|
||||
|
||||
if (!moving_toward_gate(player, anchor, pitch))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (!P_MobjWasRemoved(anchor_other(anchor)))
|
||||
{
|
||||
set_shiftxy(player, anchor);
|
||||
}
|
||||
|
||||
flip = get_binary_direction(pitch, toucher);
|
||||
|
||||
s->yaw = anchor->angle;
|
||||
|
||||
s->origin.x = center->x - (anchor->x - px);
|
||||
s->origin.y = center->y - (anchor->y - py);
|
||||
s->origin.z = center->z;
|
||||
|
||||
s->radius = radius * flip;
|
||||
s->revolution = AngleFixed(pitch) / 360;
|
||||
|
||||
s->min_revolution = s->revolution;
|
||||
s->max_revolution = s->revolution +
|
||||
center_max_revolution(center) * flip;
|
||||
|
||||
s->flip = center_has_flip(center);
|
||||
|
||||
player->speed =
|
||||
3 * (player->speed + toucher->momz) / 2;
|
||||
|
||||
/* cancel the effects of K_Squish */
|
||||
toucher->spritexscale = FRACUNIT;
|
||||
toucher->spriteyscale = FRACUNIT;
|
||||
}
|
||||
|
|
@ -601,6 +601,10 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck)
|
|||
}
|
||||
return;
|
||||
|
||||
case MT_LOOPENDPOINT:
|
||||
Obj_LoopEndpointCollide(special, toucher);
|
||||
return;
|
||||
|
||||
default: // SOC or script pickup
|
||||
P_SetTarget(&special->target, toucher);
|
||||
break;
|
||||
|
|
|
|||
|
|
@ -13327,6 +13327,11 @@ static boolean P_SetupSpawnedMapThing(mapthing_t *mthing, mobj_t *mobj, boolean
|
|||
mobj->reactiontime++;
|
||||
break;
|
||||
}
|
||||
case MT_LOOPCENTERPOINT:
|
||||
{
|
||||
Obj_InitLoopCenter(mobj);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue