mirror of
https://github.com/KartKrewDev/RingRacers.git
synced 2025-10-30 08:01:28 +00:00
Move ring shooter to its own file
This commit is contained in:
parent
668d832ca1
commit
319cee4afa
7 changed files with 357 additions and 299 deletions
|
|
@ -506,7 +506,7 @@ struct player_t
|
||||||
waypoint_t *currentwaypoint;
|
waypoint_t *currentwaypoint;
|
||||||
waypoint_t *nextwaypoint;
|
waypoint_t *nextwaypoint;
|
||||||
respawnvars_t respawn; // Respawn info
|
respawnvars_t respawn; // Respawn info
|
||||||
tic_t airtime; // Keep track of how long you've been in the air
|
tic_t airtime; // Used to track just air time, but has evolved over time into a general "karted" timer. Rename this variable?
|
||||||
UINT8 startboost; // (0 to 125) - Boost you get from start of race or respawn drop dash
|
UINT8 startboost; // (0 to 125) - Boost you get from start of race or respawn drop dash
|
||||||
|
|
||||||
UINT16 flashing;
|
UINT16 flashing;
|
||||||
|
|
|
||||||
138
src/k_kart.c
138
src/k_kart.c
|
|
@ -11388,14 +11388,7 @@ void K_MoveKartPlayer(player_t *player, boolean onground)
|
||||||
player->pflags &= ~PF_AIRFAILSAFE;
|
player->pflags &= ~PF_AIRFAILSAFE;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (K_AllowRingShooter(player) == true)
|
Obj_RingShooterInput(player);
|
||||||
{
|
|
||||||
if ((cmd->buttons & BT_RESPAWN)
|
|
||||||
&& !(player->oldcmd.buttons & BT_RESPAWN))
|
|
||||||
{
|
|
||||||
K_SpawnRingShooter(player);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void K_CheckSpectateStatus(void)
|
void K_CheckSpectateStatus(void)
|
||||||
|
|
@ -11783,132 +11776,3 @@ boolean K_Cooperative(void)
|
||||||
}
|
}
|
||||||
|
|
||||||
//}
|
//}
|
||||||
|
|
||||||
boolean K_AllowRingShooter(player_t *player)
|
|
||||||
{
|
|
||||||
const fixed_t minSpeed = 6 * player->mo->scale;
|
|
||||||
|
|
||||||
if (player->respawn.state != RESPAWNST_NONE
|
|
||||||
&& player->respawn.init == true)
|
|
||||||
{
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (player->drift == 0
|
|
||||||
&& player->justbumped == 0
|
|
||||||
&& player->spindashboost == 0
|
|
||||||
&& player->nocontrol == 0
|
|
||||||
&& player->fastfall == 0
|
|
||||||
&& player->speed < minSpeed
|
|
||||||
&& P_PlayerInPain(player) == false
|
|
||||||
&& P_IsObjectOnGround(player->mo) == true)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
// I've tried to reduce redundancy as much as I can,
|
|
||||||
// but check P_UpdateRingShooterParts if you edit this
|
|
||||||
void K_SpawnRingShooter(player_t *player)
|
|
||||||
{
|
|
||||||
const fixed_t scale = 2*FRACUNIT;
|
|
||||||
mobjinfo_t *info = &mobjinfo[MT_RINGSHOOTER_PART];
|
|
||||||
mobj_t *mo = player->mo;
|
|
||||||
mobj_t *base = P_SpawnMobj(mo->x, mo->y, mo->z, MT_RINGSHOOTER);
|
|
||||||
mobj_t *part, *refNipple;
|
|
||||||
UINT32 frameNum;
|
|
||||||
angle_t angle;
|
|
||||||
vector2_t offset;
|
|
||||||
SINT8 i;
|
|
||||||
|
|
||||||
K_FlipFromObject(base, mo);
|
|
||||||
P_SetTarget(&base->target, mo);
|
|
||||||
P_SetScale(base, base->destscale = FixedMul(base->destscale, scale));
|
|
||||||
base->angle = mo->angle;
|
|
||||||
base->scalespeed = FRACUNIT/2;
|
|
||||||
base->extravalue1 = FRACUNIT; // horizontal scale
|
|
||||||
base->extravalue2 = 0; // vertical scale
|
|
||||||
|
|
||||||
// the ring shooter object itself is invisible and acts as the thinker
|
|
||||||
// each ring shooter uses three linked lists to keep track of its parts
|
|
||||||
// the hprev chain stores the two NIPPLE BARS
|
|
||||||
// the hnext chain stores the four sides of the box
|
|
||||||
// the tracer chain stores the screen and the screen layers
|
|
||||||
|
|
||||||
// spawn the RING NIPPLES
|
|
||||||
part = base;
|
|
||||||
frameNum = 0;
|
|
||||||
FV2_Load(&offset, -96*FRACUNIT, 160*FRACUNIT);
|
|
||||||
FV2_Divide(&offset, scale);
|
|
||||||
for (i = -1; i < 2; i += 2)
|
|
||||||
{
|
|
||||||
P_SetTarget(&part->hprev, P_SpawnMobjFromMobj(base,
|
|
||||||
P_ReturnThrustX(NULL, base->angle - ANGLE_90, i*offset.x) + P_ReturnThrustX(NULL, base->angle, offset.y),
|
|
||||||
P_ReturnThrustY(NULL, base->angle - ANGLE_90, i*offset.x) + P_ReturnThrustY(NULL, base->angle, offset.y),
|
|
||||||
0, MT_RINGSHOOTER_PART));
|
|
||||||
P_SetTarget(&part->hprev->hnext, part);
|
|
||||||
part = part->hprev;
|
|
||||||
P_SetTarget(&part->target, base);
|
|
||||||
|
|
||||||
part->angle = base->angle - i * ANGLE_45;
|
|
||||||
P_SetMobjState(part, S_RINGSHOOTER_NIPPLES);
|
|
||||||
part->frame += frameNum;
|
|
||||||
part->flags |= MF_NOTHINK;
|
|
||||||
part->old_spriteyscale = part->spriteyscale = 0;
|
|
||||||
frameNum++;
|
|
||||||
}
|
|
||||||
refNipple = part; // keep the second ring nipple; its position will be referenced by the box
|
|
||||||
|
|
||||||
// spawn the box
|
|
||||||
part = base;
|
|
||||||
frameNum = 0;
|
|
||||||
angle = base->angle + ANGLE_90;
|
|
||||||
FV2_Load(&offset, offset.x - info->radius, offset.y - info->radius); // set the new origin to the centerpoint of the box
|
|
||||||
FV2_Load(&offset,
|
|
||||||
P_ReturnThrustX(NULL, base->angle - ANGLE_90, offset.x) + P_ReturnThrustX(NULL, base->angle, offset.y),
|
|
||||||
P_ReturnThrustY(NULL, base->angle - ANGLE_90, offset.x) + P_ReturnThrustY(NULL, base->angle, offset.y)); // transform it relative to the base
|
|
||||||
for (i = 0; i < 4; i++)
|
|
||||||
{
|
|
||||||
P_SetTarget(&part->hnext, P_SpawnMobjFromMobj(base,
|
|
||||||
offset.x + P_ReturnThrustX(NULL, angle, info->radius),
|
|
||||||
offset.y + P_ReturnThrustY(NULL, angle, info->radius),
|
|
||||||
0, MT_RINGSHOOTER_PART));
|
|
||||||
P_SetTarget(&part->hnext->hprev, part);
|
|
||||||
part = part->hnext;
|
|
||||||
P_SetTarget(&part->target, base);
|
|
||||||
|
|
||||||
if (i == 2)
|
|
||||||
frameNum++;
|
|
||||||
frameNum ^= FF_HORIZONTALFLIP;
|
|
||||||
angle -= ANGLE_90;
|
|
||||||
part->angle = angle;
|
|
||||||
part->frame += frameNum;
|
|
||||||
part->extravalue1 = part->x - refNipple->x;
|
|
||||||
part->extravalue2 = part->y - refNipple->y;
|
|
||||||
part->flags |= MF_NOTHINK;
|
|
||||||
part->old_spriteyscale = part->spriteyscale = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// spawn the screen
|
|
||||||
part = P_SpawnMobjFromMobj(base, offset.x, offset.y, 0, MT_RINGSHOOTER_SCREEN);
|
|
||||||
P_SetTarget(&base->tracer, part);
|
|
||||||
P_SetTarget(&part->target, base);
|
|
||||||
part->angle = base->angle - ANGLE_45;
|
|
||||||
part->extravalue1 = part->x - refNipple->x;
|
|
||||||
part->extravalue2 = part->y - refNipple->y;
|
|
||||||
part->flags |= MF_NOTHINK;
|
|
||||||
part->old_spriteyscale = part->spriteyscale = 0;
|
|
||||||
|
|
||||||
// spawn the screen numbers
|
|
||||||
for (i = 0; i < 2; i++)
|
|
||||||
{
|
|
||||||
P_SetTarget(&part->tracer, P_SpawnMobjFromMobj(part, 0, 0, 0, MT_OVERLAY));
|
|
||||||
P_SetTarget(&part->tracer->target, part);
|
|
||||||
part = part->tracer;
|
|
||||||
part->angle = part->target->angle;
|
|
||||||
P_SetMobjState(part, S_RINGSHOOTER_NUMBERBACK + i);
|
|
||||||
part->renderflags |= RF_DONTDRAW;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
||||||
|
|
@ -189,8 +189,6 @@ boolean K_IsSPBInGame(void);
|
||||||
void K_KartEbrakeVisuals(player_t *p);
|
void K_KartEbrakeVisuals(player_t *p);
|
||||||
void K_HandleDirectionalInfluence(player_t *player);
|
void K_HandleDirectionalInfluence(player_t *player);
|
||||||
fixed_t K_DefaultPlayerRadius(player_t *player);
|
fixed_t K_DefaultPlayerRadius(player_t *player);
|
||||||
boolean K_AllowRingShooter(player_t *player);
|
|
||||||
void K_SpawnRingShooter(player_t *player);
|
|
||||||
|
|
||||||
// sound stuff for lua
|
// sound stuff for lua
|
||||||
void K_PlayAttackTaunt(mobj_t *source);
|
void K_PlayAttackTaunt(mobj_t *source);
|
||||||
|
|
|
||||||
|
|
@ -106,6 +106,10 @@ void Obj_LoopEndpointCollide(mobj_t *special, mobj_t *toucher);
|
||||||
void Obj_BeginDropTargetMorph(mobj_t *target, skincolornum_t color);
|
void Obj_BeginDropTargetMorph(mobj_t *target, skincolornum_t color);
|
||||||
boolean Obj_DropTargetMorphThink(mobj_t *morph);
|
boolean Obj_DropTargetMorphThink(mobj_t *morph);
|
||||||
|
|
||||||
|
/* Ring Shooter */
|
||||||
|
void Obj_RingShooterThinker(mobj_t *mo);
|
||||||
|
void Obj_RingShooterInput(player_t *player);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
} // extern "C"
|
} // extern "C"
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
|
|
@ -14,4 +14,5 @@ target_sources(SRB2SDL2 PRIVATE
|
||||||
item-spot.c
|
item-spot.c
|
||||||
loops.c
|
loops.c
|
||||||
drop-target.c
|
drop-target.c
|
||||||
|
ring-shooter.c
|
||||||
)
|
)
|
||||||
|
|
|
||||||
349
src/objects/ring-shooter.c
Normal file
349
src/objects/ring-shooter.c
Normal file
|
|
@ -0,0 +1,349 @@
|
||||||
|
// DR. ROBOTNIK'S RING RACERS
|
||||||
|
//-----------------------------------------------------------------------------
|
||||||
|
// Copyright (C) by Sally "TehRealSalt" Cochenour
|
||||||
|
// Copyright (C) by "Lach"
|
||||||
|
// Copyright (C) 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 ring-shooter.c
|
||||||
|
/// \brief DEZ "Ring Shooter" respawner object
|
||||||
|
|
||||||
|
#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 "../r_skins.h"
|
||||||
|
#include "../k_respawn.h"
|
||||||
|
|
||||||
|
#define RS_FUSE_TIME (4*TICRATE)
|
||||||
|
|
||||||
|
static void ActivateRingShooter(mobj_t *mo)
|
||||||
|
{
|
||||||
|
mobj_t *part = mo->tracer;
|
||||||
|
|
||||||
|
while (!P_MobjWasRemoved(part->tracer))
|
||||||
|
{
|
||||||
|
part = part->tracer;
|
||||||
|
part->renderflags &= ~RF_DONTDRAW;
|
||||||
|
part->frame += 4;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
#define scaleSpeed mo->scalespeed
|
||||||
|
#define scaleState mo->threshold
|
||||||
|
#define xScale mo->extravalue1
|
||||||
|
#define yScale mo->extravalue2
|
||||||
|
#define xOffset part->extravalue1
|
||||||
|
#define yOffset part->extravalue2
|
||||||
|
#define SCALEPART part->spritexscale = xScale; part->spriteyscale = yScale;
|
||||||
|
#define MOVEPART P_MoveOrigin(part, refNipple->x + FixedMul(xOffset, xScale), refNipple->y + FixedMul(yOffset, xScale), part->z);
|
||||||
|
|
||||||
|
// I've tried to reduce redundancy as much as I can,
|
||||||
|
// but check K_SpawnRingShooter if you edit this
|
||||||
|
static void UpdateRingShooterParts(mobj_t *mo)
|
||||||
|
{
|
||||||
|
mobj_t *part, *refNipple;
|
||||||
|
|
||||||
|
part = mo;
|
||||||
|
while (!P_MobjWasRemoved(part->hprev))
|
||||||
|
{
|
||||||
|
part = part->hprev;
|
||||||
|
SCALEPART
|
||||||
|
}
|
||||||
|
refNipple = part;
|
||||||
|
|
||||||
|
part = mo;
|
||||||
|
while (!P_MobjWasRemoved(part->hnext))
|
||||||
|
{
|
||||||
|
part = part->hnext;
|
||||||
|
MOVEPART
|
||||||
|
SCALEPART
|
||||||
|
}
|
||||||
|
|
||||||
|
part = mo->tracer;
|
||||||
|
part->z = mo->z + FixedMul(refNipple->height, yScale);
|
||||||
|
MOVEPART
|
||||||
|
SCALEPART
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean RingShooterInit(mobj_t *mo)
|
||||||
|
{
|
||||||
|
if (scaleState == -1)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (scaleState)
|
||||||
|
{
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
yScale += scaleSpeed;
|
||||||
|
if (yScale >= FRACUNIT)
|
||||||
|
{
|
||||||
|
//xScale -= scaleSpeed;
|
||||||
|
scaleState++;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 1:
|
||||||
|
{
|
||||||
|
scaleSpeed -= FRACUNIT/5;
|
||||||
|
yScale += scaleSpeed;
|
||||||
|
xScale -= scaleSpeed;
|
||||||
|
if (yScale < 3*FRACUNIT/4)
|
||||||
|
{
|
||||||
|
scaleState ++;
|
||||||
|
scaleSpeed = FRACUNIT >> 2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 2:
|
||||||
|
{
|
||||||
|
yScale += scaleSpeed;
|
||||||
|
xScale -= scaleSpeed;
|
||||||
|
if (yScale >= FRACUNIT)
|
||||||
|
{
|
||||||
|
scaleState = -1;
|
||||||
|
xScale = yScale = FRACUNIT;
|
||||||
|
ActivateRingShooter(mo);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
UpdateRingShooterParts(mo);
|
||||||
|
return scaleState != -1;
|
||||||
|
}
|
||||||
|
#undef scaleSpeed
|
||||||
|
#undef scaleState
|
||||||
|
#undef xScale
|
||||||
|
#undef yScale
|
||||||
|
#undef xOffset
|
||||||
|
#undef yOffset
|
||||||
|
#undef MOVEPART
|
||||||
|
#undef SCALEPART
|
||||||
|
|
||||||
|
static void RingShooterCountdown(mobj_t *mo)
|
||||||
|
{
|
||||||
|
mobj_t *part = mo->tracer;
|
||||||
|
|
||||||
|
if (mo->reactiontime == -1)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (--mo->reactiontime > 0)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
while (!P_MobjWasRemoved(part->tracer))
|
||||||
|
{
|
||||||
|
part = part->tracer;
|
||||||
|
part->frame--;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch ((part->frame & FF_FRAMEMASK) - (part->state->frame & FF_FRAMEMASK))
|
||||||
|
{
|
||||||
|
case -1:
|
||||||
|
{
|
||||||
|
mo->reactiontime = -1;
|
||||||
|
part->skin = mo->skin;
|
||||||
|
P_SetMobjState(part, S_RINGSHOOTER_FACE);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
case 0:
|
||||||
|
{
|
||||||
|
mo->reactiontime = TICRATE;
|
||||||
|
S_StartSound(mo, mo->info->deathsound);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
default:
|
||||||
|
{
|
||||||
|
mo->reactiontime = TICRATE;
|
||||||
|
S_StartSound(mo, mo->info->painsound);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void RingShooterFlicker(mobj_t *mo)
|
||||||
|
{
|
||||||
|
UINT32 trans;
|
||||||
|
mobj_t *part = mo->tracer;
|
||||||
|
|
||||||
|
while (!P_MobjWasRemoved(part->tracer))
|
||||||
|
{
|
||||||
|
part = part->tracer;
|
||||||
|
}
|
||||||
|
|
||||||
|
part->renderflags ^= RF_DONTDRAW;
|
||||||
|
if (part->renderflags & RF_DONTDRAW)
|
||||||
|
{
|
||||||
|
trans = FF_TRANS50;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
trans = 0;
|
||||||
|
}
|
||||||
|
part->target->frame = (part->target->frame & ~FF_TRANSMASK) | trans;
|
||||||
|
}
|
||||||
|
|
||||||
|
void Obj_RingShooterThinker(mobj_t *mo)
|
||||||
|
{
|
||||||
|
if (P_MobjWasRemoved(mo->tracer) || RingShooterInit(mo))
|
||||||
|
return;
|
||||||
|
|
||||||
|
RingShooterCountdown(mo);
|
||||||
|
RingShooterFlicker(mo);
|
||||||
|
}
|
||||||
|
|
||||||
|
static boolean AllowRingShooter(player_t *player)
|
||||||
|
{
|
||||||
|
const fixed_t minSpeed = 6 * player->mo->scale;
|
||||||
|
|
||||||
|
if (player->respawn.state != RESPAWNST_NONE
|
||||||
|
&& player->respawn.init == true)
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (player->drift == 0
|
||||||
|
&& player->justbumped == 0
|
||||||
|
&& player->spindashboost == 0
|
||||||
|
&& player->nocontrol == 0
|
||||||
|
&& player->fastfall == 0
|
||||||
|
&& player->speed < minSpeed
|
||||||
|
&& P_PlayerInPain(player) == false
|
||||||
|
&& P_IsObjectOnGround(player->mo) == true)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// I've tried to reduce redundancy as much as I can,
|
||||||
|
// but check P_UpdateRingShooterParts if you edit this
|
||||||
|
static void SpawnRingShooter(player_t *player)
|
||||||
|
{
|
||||||
|
const fixed_t scale = 2*FRACUNIT;
|
||||||
|
mobjinfo_t *info = &mobjinfo[MT_RINGSHOOTER_PART];
|
||||||
|
mobj_t *mo = player->mo;
|
||||||
|
mobj_t *base = P_SpawnMobj(mo->x, mo->y, mo->z, MT_RINGSHOOTER);
|
||||||
|
mobj_t *part, *refNipple;
|
||||||
|
UINT32 frameNum;
|
||||||
|
angle_t angle;
|
||||||
|
vector2_t offset;
|
||||||
|
SINT8 i;
|
||||||
|
|
||||||
|
K_FlipFromObject(base, mo);
|
||||||
|
P_SetTarget(&base->target, mo);
|
||||||
|
P_SetScale(base, base->destscale = FixedMul(base->destscale, scale));
|
||||||
|
base->angle = mo->angle;
|
||||||
|
base->scalespeed = FRACUNIT/2;
|
||||||
|
base->extravalue1 = FRACUNIT; // horizontal scale
|
||||||
|
base->extravalue2 = 0; // vertical scale
|
||||||
|
base->fuse = RS_FUSE_TIME;
|
||||||
|
|
||||||
|
// the ring shooter object itself is invisible and acts as the thinker
|
||||||
|
// each ring shooter uses three linked lists to keep track of its parts
|
||||||
|
// the hprev chain stores the two NIPPLE BARS
|
||||||
|
// the hnext chain stores the four sides of the box
|
||||||
|
// the tracer chain stores the screen and the screen layers
|
||||||
|
|
||||||
|
// spawn the RING NIPPLES
|
||||||
|
part = base;
|
||||||
|
frameNum = 0;
|
||||||
|
FV2_Load(&offset, -96*FRACUNIT, 160*FRACUNIT);
|
||||||
|
FV2_Divide(&offset, scale);
|
||||||
|
for (i = -1; i < 2; i += 2)
|
||||||
|
{
|
||||||
|
P_SetTarget(&part->hprev, P_SpawnMobjFromMobj(base,
|
||||||
|
P_ReturnThrustX(NULL, base->angle - ANGLE_90, i*offset.x) + P_ReturnThrustX(NULL, base->angle, offset.y),
|
||||||
|
P_ReturnThrustY(NULL, base->angle - ANGLE_90, i*offset.x) + P_ReturnThrustY(NULL, base->angle, offset.y),
|
||||||
|
0, MT_RINGSHOOTER_PART));
|
||||||
|
P_SetTarget(&part->hprev->hnext, part);
|
||||||
|
part = part->hprev;
|
||||||
|
P_SetTarget(&part->target, base);
|
||||||
|
|
||||||
|
part->angle = base->angle - i * ANGLE_45;
|
||||||
|
P_SetMobjState(part, S_RINGSHOOTER_NIPPLES);
|
||||||
|
part->frame += frameNum;
|
||||||
|
part->flags |= MF_NOTHINK;
|
||||||
|
part->old_spriteyscale = part->spriteyscale = 0;
|
||||||
|
frameNum++;
|
||||||
|
}
|
||||||
|
refNipple = part; // keep the second ring nipple; its position will be referenced by the box
|
||||||
|
|
||||||
|
// spawn the box
|
||||||
|
part = base;
|
||||||
|
frameNum = 0;
|
||||||
|
angle = base->angle + ANGLE_90;
|
||||||
|
FV2_Load(&offset, offset.x - info->radius, offset.y - info->radius); // set the new origin to the centerpoint of the box
|
||||||
|
FV2_Load(&offset,
|
||||||
|
P_ReturnThrustX(NULL, base->angle - ANGLE_90, offset.x) + P_ReturnThrustX(NULL, base->angle, offset.y),
|
||||||
|
P_ReturnThrustY(NULL, base->angle - ANGLE_90, offset.x) + P_ReturnThrustY(NULL, base->angle, offset.y)); // transform it relative to the base
|
||||||
|
for (i = 0; i < 4; i++)
|
||||||
|
{
|
||||||
|
P_SetTarget(&part->hnext, P_SpawnMobjFromMobj(base,
|
||||||
|
offset.x + P_ReturnThrustX(NULL, angle, info->radius),
|
||||||
|
offset.y + P_ReturnThrustY(NULL, angle, info->radius),
|
||||||
|
0, MT_RINGSHOOTER_PART));
|
||||||
|
P_SetTarget(&part->hnext->hprev, part);
|
||||||
|
part = part->hnext;
|
||||||
|
P_SetTarget(&part->target, base);
|
||||||
|
|
||||||
|
if (i == 2)
|
||||||
|
frameNum++;
|
||||||
|
frameNum ^= FF_HORIZONTALFLIP;
|
||||||
|
angle -= ANGLE_90;
|
||||||
|
part->angle = angle;
|
||||||
|
part->frame += frameNum;
|
||||||
|
part->extravalue1 = part->x - refNipple->x;
|
||||||
|
part->extravalue2 = part->y - refNipple->y;
|
||||||
|
part->flags |= MF_NOTHINK;
|
||||||
|
part->old_spriteyscale = part->spriteyscale = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// spawn the screen
|
||||||
|
part = P_SpawnMobjFromMobj(base, offset.x, offset.y, 0, MT_RINGSHOOTER_SCREEN);
|
||||||
|
P_SetTarget(&base->tracer, part);
|
||||||
|
P_SetTarget(&part->target, base);
|
||||||
|
part->angle = base->angle - ANGLE_45;
|
||||||
|
part->extravalue1 = part->x - refNipple->x;
|
||||||
|
part->extravalue2 = part->y - refNipple->y;
|
||||||
|
part->flags |= MF_NOTHINK;
|
||||||
|
part->old_spriteyscale = part->spriteyscale = 0;
|
||||||
|
|
||||||
|
// spawn the screen numbers
|
||||||
|
for (i = 0; i < 2; i++)
|
||||||
|
{
|
||||||
|
P_SetTarget(&part->tracer, P_SpawnMobjFromMobj(part, 0, 0, 0, MT_OVERLAY));
|
||||||
|
P_SetTarget(&part->tracer->target, part);
|
||||||
|
part = part->tracer;
|
||||||
|
part->angle = part->target->angle;
|
||||||
|
P_SetMobjState(part, S_RINGSHOOTER_NUMBERBACK + i);
|
||||||
|
part->renderflags |= RF_DONTDRAW;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void Obj_RingShooterInput(player_t *player)
|
||||||
|
{
|
||||||
|
if (AllowRingShooter(player) == true
|
||||||
|
&& (player->cmd.buttons & BT_RESPAWN) == BT_RESPAWN
|
||||||
|
&& (player->oldcmd.buttons & BT_RESPAWN) == 0)
|
||||||
|
{
|
||||||
|
SpawnRingShooter(player);
|
||||||
|
}
|
||||||
|
}
|
||||||
160
src/p_mobj.c
160
src/p_mobj.c
|
|
@ -4550,164 +4550,6 @@ static void P_SpawnItemCapsuleParts(mobj_t *mobj)
|
||||||
#undef ANG_CAPSULE
|
#undef ANG_CAPSULE
|
||||||
#undef ROTATIONSPEED
|
#undef ROTATIONSPEED
|
||||||
|
|
||||||
// ------------
|
|
||||||
// RING SHOOTER
|
|
||||||
// ------------
|
|
||||||
|
|
||||||
static void P_ActivateRingShooter(mobj_t *mo)
|
|
||||||
{
|
|
||||||
mobj_t *part = mo->tracer;
|
|
||||||
|
|
||||||
while (!P_MobjWasRemoved(part->tracer))
|
|
||||||
{
|
|
||||||
part = part->tracer;
|
|
||||||
part->renderflags &= ~RF_DONTDRAW;
|
|
||||||
part->frame += 4;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#define scaleSpeed mo->scalespeed
|
|
||||||
#define scaleState mo->threshold
|
|
||||||
#define xScale mo->extravalue1
|
|
||||||
#define yScale mo->extravalue2
|
|
||||||
#define xOffset part->extravalue1
|
|
||||||
#define yOffset part->extravalue2
|
|
||||||
#define SCALEPART part->spritexscale = xScale; part->spriteyscale = yScale;
|
|
||||||
#define MOVEPART P_MoveOrigin(part, refNipple->x + FixedMul(xOffset, xScale), refNipple->y + FixedMul(yOffset, xScale), part->z);
|
|
||||||
|
|
||||||
// I've tried to reduce redundancy as much as I can,
|
|
||||||
// but check K_SpawnRingShooter if you edit this
|
|
||||||
static void P_UpdateRingShooterParts(mobj_t *mo)
|
|
||||||
{
|
|
||||||
mobj_t *part, *refNipple;
|
|
||||||
|
|
||||||
part = mo;
|
|
||||||
while (!P_MobjWasRemoved(part->hprev))
|
|
||||||
{
|
|
||||||
part = part->hprev;
|
|
||||||
SCALEPART
|
|
||||||
}
|
|
||||||
refNipple = part;
|
|
||||||
|
|
||||||
part = mo;
|
|
||||||
while (!P_MobjWasRemoved(part->hnext))
|
|
||||||
{
|
|
||||||
part = part->hnext;
|
|
||||||
MOVEPART
|
|
||||||
SCALEPART
|
|
||||||
}
|
|
||||||
|
|
||||||
part = mo->tracer;
|
|
||||||
part->z = mo->z + FixedMul(refNipple->height, yScale);
|
|
||||||
MOVEPART
|
|
||||||
SCALEPART
|
|
||||||
}
|
|
||||||
|
|
||||||
static boolean P_RingShooterInit(mobj_t *mo)
|
|
||||||
{
|
|
||||||
if (scaleState == -1)
|
|
||||||
return false;
|
|
||||||
|
|
||||||
switch (scaleState) {
|
|
||||||
case 0:
|
|
||||||
yScale += scaleSpeed;
|
|
||||||
if (yScale >= FRACUNIT)
|
|
||||||
{
|
|
||||||
//xScale -= scaleSpeed;
|
|
||||||
scaleState++;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 1:
|
|
||||||
scaleSpeed -= FRACUNIT/5;
|
|
||||||
yScale += scaleSpeed;
|
|
||||||
xScale -= scaleSpeed;
|
|
||||||
if (yScale < 3*FRACUNIT/4)
|
|
||||||
{
|
|
||||||
scaleState ++;
|
|
||||||
scaleSpeed = FRACUNIT >> 2;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
case 2:
|
|
||||||
yScale += scaleSpeed;
|
|
||||||
xScale -= scaleSpeed;
|
|
||||||
if (yScale >= FRACUNIT)
|
|
||||||
{
|
|
||||||
scaleState = -1;
|
|
||||||
xScale = yScale = FRACUNIT;
|
|
||||||
P_ActivateRingShooter(mo);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
P_UpdateRingShooterParts(mo);
|
|
||||||
return scaleState != -1;
|
|
||||||
}
|
|
||||||
#undef scaleSpeed
|
|
||||||
#undef scaleState
|
|
||||||
#undef xScale
|
|
||||||
#undef yScale
|
|
||||||
#undef xOffset
|
|
||||||
#undef yOffset
|
|
||||||
#undef MOVEPART
|
|
||||||
#undef SCALEPART
|
|
||||||
|
|
||||||
static void P_RingShooterCountdown(mobj_t *mo)
|
|
||||||
{
|
|
||||||
mobj_t *part = mo->tracer;
|
|
||||||
|
|
||||||
if (mo->reactiontime == -1)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if (--mo->reactiontime > 0)
|
|
||||||
return;
|
|
||||||
|
|
||||||
while (!P_MobjWasRemoved(part->tracer))
|
|
||||||
{
|
|
||||||
part = part->tracer;
|
|
||||||
part->frame--;
|
|
||||||
}
|
|
||||||
|
|
||||||
switch ((part->frame & FF_FRAMEMASK) - (part->state->frame & FF_FRAMEMASK)) {
|
|
||||||
case -1:
|
|
||||||
mo->reactiontime = -1;
|
|
||||||
part->skin = mo->skin;
|
|
||||||
P_SetMobjState(part, S_RINGSHOOTER_FACE);
|
|
||||||
break;
|
|
||||||
case 0:
|
|
||||||
mo->reactiontime = TICRATE;
|
|
||||||
S_StartSound(mo, mo->info->deathsound);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
mo->reactiontime = TICRATE;
|
|
||||||
S_StartSound(mo, mo->info->painsound);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
static void P_RingShooterFlicker(mobj_t *mo)
|
|
||||||
{
|
|
||||||
UINT32 trans;
|
|
||||||
mobj_t *part = mo->tracer;
|
|
||||||
|
|
||||||
while (!P_MobjWasRemoved(part->tracer))
|
|
||||||
part = part->tracer;
|
|
||||||
|
|
||||||
part->renderflags ^= RF_DONTDRAW;
|
|
||||||
if (part->renderflags & RF_DONTDRAW)
|
|
||||||
trans = FF_TRANS50;
|
|
||||||
else
|
|
||||||
trans = 0;
|
|
||||||
part->target->frame = (part->target->frame & ~FF_TRANSMASK) | trans;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void P_RingShooterThinker(mobj_t *mo)
|
|
||||||
{
|
|
||||||
if (P_MobjWasRemoved(mo->tracer) || P_RingShooterInit(mo))
|
|
||||||
return;
|
|
||||||
|
|
||||||
P_RingShooterCountdown(mo);
|
|
||||||
P_RingShooterFlicker(mo);
|
|
||||||
}
|
|
||||||
|
|
||||||
//
|
//
|
||||||
// P_BossTargetPlayer
|
// P_BossTargetPlayer
|
||||||
// If closest is true, find the closest player.
|
// If closest is true, find the closest player.
|
||||||
|
|
@ -6800,7 +6642,7 @@ static void P_MobjSceneryThink(mobj_t *mobj)
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MT_RINGSHOOTER:
|
case MT_RINGSHOOTER:
|
||||||
P_RingShooterThinker(mobj);
|
Obj_RingShooterThinker(mobj);
|
||||||
break;
|
break;
|
||||||
case MT_SPINDASHWIND:
|
case MT_SPINDASHWIND:
|
||||||
case MT_DRIFTELECTRICSPARK:
|
case MT_DRIFTELECTRICSPARK:
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue