From fb91a9a0f7b4276784cbdd3bbc6543a20e42e408 Mon Sep 17 00:00:00 2001 From: Lat Date: Thu, 21 Sep 2023 15:42:10 +0200 Subject: [PATCH] DLZ rocket hardcode --- src/d_player.h | 4 +- src/k_kart.c | 3 + src/k_objects.h | 6 ++ src/objects/CMakeLists.txt | 1 + src/objects/dlzrocket.c | 190 +++++++++++++++++++++++++++++++++++++ src/p_inter.c | 6 +- src/p_map.c | 12 ++- src/p_mobj.c | 5 +- src/p_saveg.c | 12 +-- 9 files changed, 226 insertions(+), 13 deletions(-) create mode 100644 src/objects/dlzrocket.c diff --git a/src/d_player.h b/src/d_player.h index ad2bb6965..dd5040d64 100644 --- a/src/d_player.h +++ b/src/d_player.h @@ -744,9 +744,9 @@ struct player_t tic_t lasthover; // used for the hover mobjs // rockets - boolean dlzrocket; // true if latched onto a dlz rocket. + tic_t dlzrocket; // counts up as we stay on a rocket. angle_t dlzrocketangle; // current travel angle with the rocket. - angle_t dlzrocketanglev; // current vertical travel angle with the rocket. + INT32 dlzrocketanglev; // current vertical travel angle with the rocket. signed instead of angle_t. fixed_t dlzrocketspd; // current rocket travel speed. // seasaws (variables are shared with other seasaw-like objects) diff --git a/src/k_kart.c b/src/k_kart.c index de0575c70..f68772976 100644 --- a/src/k_kart.c +++ b/src/k_kart.c @@ -11845,6 +11845,9 @@ void K_MoveKartPlayer(player_t *player, boolean onground) if (player->bungee) Obj_playerBungeeThink(player); + + if (player->dlzrocket) + Obj_playerDLZRocket(player); } void K_CheckSpectateStatus(boolean considermapreset) diff --git a/src/k_objects.h b/src/k_objects.h index 5e1b054aa..c788f314e 100644 --- a/src/k_objects.h +++ b/src/k_objects.h @@ -247,6 +247,12 @@ void Obj_playerBungeeThink(player_t *p); // player interaction with the bungee void Obj_EggBallSpawnerThink(mobj_t *mo); void Obj_EggBallThink(mobj_t *mo); +/* DLZ Rockets */ +void Obj_DLZRocketSpawn(mobj_t *mo); +void Obj_DLZRocketSpecial(mobj_t *mo, player_t *p); // touch activation +void Obj_playerDLZRocket(player_t *p); // player looping thinker +void Obj_DLZRocketDismount(player_t *p); // used in p_map.c to get off the rocket when we cross transfer lines. + #ifdef __cplusplus } // extern "C" #endif diff --git a/src/objects/CMakeLists.txt b/src/objects/CMakeLists.txt index 7abf26105..22f846836 100644 --- a/src/objects/CMakeLists.txt +++ b/src/objects/CMakeLists.txt @@ -32,5 +32,6 @@ target_sources(SRB2SDL2 PRIVATE rideroid.c bungee.c eggball.c + dlzrocket.c shadow.cpp ) diff --git a/src/objects/dlzrocket.c b/src/objects/dlzrocket.c new file mode 100644 index 000000000..c45e9f60c --- /dev/null +++ b/src/objects/dlzrocket.c @@ -0,0 +1,190 @@ +// 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 dlzrocket.c +/// \brief Dead Line Zone free flight rockets! They cool af doe. + +#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" +#include "../k_collide.h" + +#define DLZROCKETDIST 96 +#define DLZROCKETSPEED 80 +#define DLZROCKETTURNSPEED ((ANG1*3)/2) +#define DLZROCKETVERTSPEED (ANG1) +#define DLZROCKETMAXVERT (ANG1*60) + +void Obj_DLZRocketSpawn(mobj_t *mo) +{ + UINT8 i; + angle_t an = mo->angle + ANGLE_90; + + for (i = 0; i < 2; i++) + { + fixed_t x = mo->x + FixedMul(mapobjectscale, DLZROCKETDIST*FINECOSINE(an>>ANGLETOFINESHIFT)); + fixed_t y = mo->y + FixedMul(mapobjectscale, DLZROCKETDIST*FINESINE(an>>ANGLETOFINESHIFT)); + + mobj_t *r = P_SpawnMobj(x, y, mo->z, MT_THOK); + P_SetMobjState(r, i ? S_DLZROCKET_L : S_DLZROCKET_R); + P_SetScale(r, (mapobjectscale*3)/2); + r->angle = mo->angle; + r->tics = -1; + + an += ANGLE_180; + } +} + +void Obj_DLZRocketDismount(player_t *p) +{ + // we aren't mounted on one. + if (!p->dlzrocket) + return; + + p->dlzrocket = 0; + K_SpawnMineExplosion(p->mo, p->mo->color, 3); + S_StartSound(p->mo, sfx_s3k4e); +} + +// touching the rocket, initialize player vars etc... +void Obj_DLZRocketSpecial(mobj_t *mo, player_t *p) +{ + if (p->dlzrocket) // already on one, don't bother resetting, duh. + return; + + p->mo->z = mo->z + 16*P_MobjFlip(p->mo)*mapobjectscale; + P_SetPlayerAngle(p->mo->player, mo->angle); + p->dlzrocket = true; + p->dlzrocketangle = mo->angle; + p->dlzrocketanglev = 0; + p->dlzrocketspd = DLZROCKETSPEED; + + p->spinouttimer = 0; + p->wipeoutslow = 0; + + S_StartSound(mo, sfx_s262); +} + +void Obj_playerDLZRocket(player_t *p) +{ + + fixed_t maxspd = DLZROCKETSPEED; + angle_t visangle; + UINT8 i, j; + + p->dlzrocket++; + + // helper arrows at the start of the ride to tell players they can move freely + if (p->dlzrocket < TICRATE*2 + && leveltime%10 < 5) + { + mobj_t *arr = P_SpawnMobj(p->mo->x, p->mo->y, p->mo->z, MT_THOK); + arr->sprite = SPR_DLZA; + arr->frame = FF_FULLBRIGHT; + P_SetScale(arr, 2*mapobjectscale); + arr->tics = 2; + } + + + // calc max speed + if (p->ringboost) + maxspd += 10; + + // set player speed + if (p->dlzrocketspd < maxspd) + p->dlzrocketspd++; + else if (p->dlzrocketspd > maxspd) + p->dlzrocket--; + + + // so long as PF_STASIS is applied, let the angle be overwritten freely. + // this is used by seasaws but can be used for misc modding purposes too. + if (p->pflags & PF_STASIS) + p->dlzrocketangle = p->mo->angle; + else + { + SINT8 turndir = 0; + P_SetPlayerAngle(p->mo->player, p->dlzrocketangle); + + if (p->cmd.turning > 0) + turndir = 1; + else if (p->cmd.turning < 0) + turndir = -1; + + p->dlzrocketangle += turndir*DLZROCKETTURNSPEED; + + if (p->cmd.throwdir > 0) + p->dlzrocketanglev = min(DLZROCKETMAXVERT, p->dlzrocketanglev + DLZROCKETVERTSPEED); + else if (p->cmd.throwdir < 0) + p->dlzrocketanglev = max(-DLZROCKETMAXVERT, p->dlzrocketanglev - DLZROCKETVERTSPEED); + + } + + // angle correction on ceilings (THIS CODE LOOKS AWFUL AND IT CAN PROBABLY BE DONE BETTER......) + if ( (!(p->mo->eflags & MFE_VERTICALFLIP) && (p->mo->z+p->mo->height >= p->mo->ceilingz)) + || (p->mo->eflags & MFE_VERTICALFLIP && p->mo->z <= p->mo->floorz)) + if ( (!(p->mo->eflags & MFE_VERTICALFLIP) && p->dlzrocketanglev > 0) + || (p->mo->eflags & MFE_VERTICALFLIP && p->dlzrocketanglev < 0)) + p->dlzrocketanglev = 0; + + + if (!(p->pflags & PF_STASIS)) + { + angle_t van = p->dlzrocketanglev /4; + P_InstaThrust(p->mo, p->dlzrocketangle, FixedMul(mapobjectscale, p->dlzrocketspd*FINECOSINE(van>>ANGLETOFINESHIFT))); + p->mo->momz = FixedMul(mapobjectscale, p->dlzrocketspd*FINESINE((angle_t)p->dlzrocketanglev>>ANGLETOFINESHIFT)); + } + + if (leveltime%4 == 0) + S_StartSound(p->mo, sfx_s1c8); + + // finally, visuals. + visangle = p->mo->angle + ANGLE_90; + + for (i = 0; i < 2; i++) + { + fixed_t x = p->mo->x + FixedMul(mapobjectscale, 56*FINECOSINE(visangle>>ANGLETOFINESHIFT)); + fixed_t y = p->mo->y + FixedMul(mapobjectscale, 56*FINESINE(visangle>>ANGLETOFINESHIFT)); + mobj_t *r = P_SpawnMobj(x, y, p->mo->z + 16*mapobjectscale, MT_THOK); + r->fuse = 2; + P_SetMobjState(r, i ? S_DLZROCKET_L : S_DLZROCKET_R); + P_SetScale(r, (mapobjectscale*3)/2); + r->angle = p->mo->angle; + + for (j = 0; j < 2; j++) + { + fixed_t xoffs = P_RandomRange(PR_FUZZ, -6, 6)*mapobjectscale; + fixed_t yoffs = P_RandomRange(PR_FUZZ, -6, 6)*mapobjectscale; + fixed_t soffs = P_RandomRange(PR_FUZZ, 0, 3); + + mobj_t *expl = P_SpawnMobj(r->x + xoffs, r->y + yoffs, r->z + xoffs, MT_THOK); + P_SetMobjState(expl, S_QUICKBOOM1+soffs); + expl->color = p->mo->color; + P_SetScale(expl, mapobjectscale); + expl->destscale = 2*mapobjectscale; + + } + visangle += ANGLE_180; + } + + if ((p->dlzrocket > 10 && (P_IsObjectOnGround(p->mo) || p->mo->eflags & MFE_JUSTBOUNCEDWALL)) + || p->spinouttimer || p->wipeoutslow || p->tumbleHeight) + Obj_DLZRocketDismount(p); + +} \ No newline at end of file diff --git a/src/p_inter.c b/src/p_inter.c index 4be5b08f0..dc6df0844 100644 --- a/src/p_inter.c +++ b/src/p_inter.c @@ -820,7 +820,11 @@ void P_TouchSpecialThing(mobj_t *special, mobj_t *toucher, boolean heightcheck) case MT_RAINBOWDASHRING: Obj_DashRingTouch(special, player); return; - + + case MT_DLZ_ROCKET: + Obj_DLZRocketSpecial(special, player); + return; + default: // SOC or script pickup P_SetTarget(&special->target, toucher); break; diff --git a/src/p_map.c b/src/p_map.c index 25e1b6178..e39c7fd29 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -1879,10 +1879,16 @@ static BlockItReturn_t PIT_CheckLine(line_t *ld) } // a bit of a hacky behaviour, but not that I know where else it would go. - if (tm.thing->type == MT_RIDEROID - && tm.blockingline->flags & ML_TFERLINE) + if (tm.blockingline->flags & ML_TFERLINE) { - Obj_getPlayerOffRideroid(tm.thing); + if (tm.thing->type == MT_RIDEROID) + { + Obj_getPlayerOffRideroid(tm.thing); + } + else if (tm.thing->type == MT_PLAYER && tm.thing->player && tm.thing->player->dlzrocket) + { + Obj_DLZRocketDismount(tm.thing->player); + } } if (!ld->backsector) // one sided line diff --git a/src/p_mobj.c b/src/p_mobj.c index 80394d5af..f50e4e687 100644 --- a/src/p_mobj.c +++ b/src/p_mobj.c @@ -11160,7 +11160,10 @@ mobj_t *P_SpawnMobj(fixed_t x, fixed_t y, fixed_t z, mobjtype_t type) break; case MT_RIDEROIDNODE: Obj_RideroidNodeSpawn(mobj); - break; + break; + case MT_DLZ_ROCKET: + Obj_DLZRocketSpawn(mobj); + break; case MT_SNEAKERPANEL: Obj_SneakerPanelSpawn(mobj); break; diff --git a/src/p_saveg.c b/src/p_saveg.c index 19d03b8b2..0c3ff7596 100644 --- a/src/p_saveg.c +++ b/src/p_saveg.c @@ -567,9 +567,9 @@ static void P_NetArchivePlayers(savebuffer_t *save) WRITEUINT32(save->p, players[i].lasthover); - WRITEUINT8(save->p, players[i].dlzrocket); - WRITEUINT32(save->p, players[i].dlzrocketangle); - WRITEUINT32(save->p, players[i].dlzrocketanglev); + WRITEUINT32(save->p, players[i].dlzrocket); + WRITEANGLE(save->p, players[i].dlzrocketangle); + WRITEINT32(save->p, players[i].dlzrocketanglev); WRITEUINT32(save->p, players[i].dlzrocketspd); WRITEUINT8(save->p, players[i].seasaw); @@ -1068,9 +1068,9 @@ static void P_NetUnArchivePlayers(savebuffer_t *save) players[i].lasthover = READUINT32(save->p); - players[i].dlzrocket = READUINT8(save->p); - players[i].dlzrocketangle = READUINT32(save->p); - players[i].dlzrocketanglev = READUINT32(save->p); + players[i].dlzrocket = READUINT32(save->p); + players[i].dlzrocketangle = READANGLE(save->p); + players[i].dlzrocketanglev = READINT32(save->p); players[i].dlzrocketspd = READUINT32(save->p); players[i].seasaw = READUINT8(save->p);