Hardcode the remainder of the WPZ objects

This commit is contained in:
Lat 2023-09-23 17:05:21 +02:00
parent df31c65ebb
commit a710237fde
5 changed files with 502 additions and 0 deletions

View file

@ -273,6 +273,13 @@ void Obj_WPZTurbineThinker(mobj_t *mo);
void Obj_playerWPZTurbine(player_t *p);
void Obj_WPZBubbleThink(mobj_t *mo);
/* WPZ Fountains */
void Obj_WPZFountainThink(mobj_t *mo);
/* WPZ Kuragens */
void Obj_WPZKuragenThink(mobj_t *mo);
void Obj_WPZKuragenBombThink(mobj_t *mo);
#ifdef __cplusplus
} // extern "C"
#endif

View file

@ -36,5 +36,6 @@ target_sources(SRB2SDL2 PRIVATE
dlzseasaw.c
dlzothers.c
wpzturbine.c
wpzothers.c
shadow.cpp
)

97
src/objects/wpzothers.c Normal file
View file

@ -0,0 +1,97 @@
// 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 wpzturbine.c
/// \brief Water Palace Zone turbines and associated bubble object. Yep, this is going to suck.
#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"
// foutains
void Obj_WPZFountainThink(mobj_t *mo)
{
if (mo->state == &states[S_WPZFOUNTAIN]
&& !(mo->eflags & MFE_UNDERWATER))
P_SetMobjState(mo, S_WPZFOUNTAINANIM);
else if (mo->state == &states[S_WPZFOUNTAINANIM]
&& mo->eflags & MFE_UNDERWATER)
P_SetMobjState(mo, S_WPZFOUNTAIN);
}
// kuragens
void Obj_WPZKuragenThink(mobj_t *mo)
{
boolean active = false;
P_SetScale(mo, mapobjectscale*2);
if (!(mo->spawnpoint->options & 1 || mo->spawnpoint->thing_args[0])) // extra flag skips player checks, making it a decoration.
{
UINT8 i;
for (i = 0; i < MAXPLAYERS; i++)
{
player_t *p;
mobj_t *pmo;
if (!playeringame[i] || players[i].spectator)
continue;
p = &players[i];
pmo = p->mo;
if (R_PointToDist2(pmo->x, pmo->y, mo->x, mo->y) < mapobjectscale*6144)
{
active = true;
break;
}
}
}
if (active && mo->extravalue1)
{
mo->extravalue1--;
if (!mo->extravalue1)
{
mobj_t *b = P_SpawnMobj(mo->x, mo->y, mo->z, MT_KURAGENBOMB);
b->flags2 = mo->flags2 & MF2_OBJECTFLIP;
P_SetScale(b, mapobjectscale*2);
b->destscale = mapobjectscale*2;
mo->extravalue1 = TICRATE*5;
}
}
else
mo->extravalue1 = TICRATE*5/2;
}
// kuragen bomb
void Obj_WPZKuragenBombThink(mobj_t *mo)
{
if (P_IsObjectOnGround(mo))
{
P_SetScale(mo, mapobjectscale/2);
P_RadiusAttack(mo, mo, FRACUNIT*192, DMG_EXPLODE, false);
A_MineExplode(mo);
P_RemoveMobj(mo);
}
}

385
src/objects/wpzturbine.c Normal file
View file

@ -0,0 +1,385 @@
// 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 wpzturbine.c
/// \brief Water Palace Zone turbines and associated bubble object. Yep, this is going to suck.
#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"
// distance to spawn the fan from the center:
#define TURBINE_RADIUS 128
// default distance at which players activate the turbine:
#define TURBINE_RANGE (2048*FRACUNIT)
// default distance at which players spin away from the turbine
#define TURBINE_SPIN 1536
// spawns the hnext visual list for the turbine.
// whether we use it or not will depend on its flags.
void Obj_WPZTurbineSpawn(mobj_t *mo)
{
mobj_t *ptr = mo;
UINT8 i;
// spawn the visuals regardless of flags, make em invisible.
// we'll care about updating em if it's worth doing later.
for (i = 0; i < 8; i++)
{
mobj_t *vis = P_SpawnMobj(mo->x, mo->y, mo->z, MT_THOK);
P_SetMobjState(vis, S_INVISIBLE);
vis->tics = 4; // if we don't use it just despawn it later.
P_SetTarget(&ptr->hnext, vis);
ptr = vis;
}
}
// visually update the turbine's hnext visuals if need be.
static void Obj_WPZTurbineUpdate(mobj_t *mo)
{
angle_t ang = (angle_t)mo->extravalue1;
mapthing_t *mt = mo->spawnpoint;
if (!mt)
return;
// fans
if (!mt->thing_args[1])
{
UINT8 i;
mobj_t *ptr = mo;
for (i = 0; i < 8; i++)
{
fixed_t x = mo->x + FixedMul(mapobjectscale, TURBINE_RADIUS*FINECOSINE(ang>>ANGLETOFINESHIFT));
fixed_t y = mo->y + FixedMul(mapobjectscale, TURBINE_RADIUS*FINESINE(ang>>ANGLETOFINESHIFT));
// get the mobj
if (ptr && !P_MobjWasRemoved(ptr) && ptr->hnext && !P_MobjWasRemoved(ptr->hnext))
{
ptr = ptr->hnext;
P_MoveOrigin(ptr, x, y, mo->z);
ptr->tics = 4;
ptr->sprite = SPR_WPWL;
ptr->frame = 1|FF_PAPERSPRITE;
P_SetScale(ptr, mapobjectscale*4);
ptr->destscale = mapobjectscale*4;
ptr->angle = ang;
}
ang += (360/8)*ANG1;
}
}
// bubbles if we're underwater
if (mo->eflags & MFE_UNDERWATER && leveltime%(TICRATE/2) == 0)
{
INT32 dradius = TURBINE_SPIN;
INT32 bubbleradius;
angle_t bubbleang;
fixed_t bx, by, bz;
mobj_t *bubble;
if (mt->thing_args[7])
dradius = mt->thing_args[7];
bubbleradius = P_RandomRange(PR_FUZZ, dradius/4, dradius);
bubbleang = P_RandomRange(PR_FUZZ, 0, 359)*ANG1;
bx = mo->x + FixedMul(mapobjectscale, bubbleradius*FINECOSINE(bubbleang>>ANGLETOFINESHIFT));
by = mo->y + FixedMul(mapobjectscale, bubbleradius*FINECOSINE(bubbleang>>ANGLETOFINESHIFT));
bz = R_PointInSubsector(bx, by)->sector->floorheight;
bubble = P_SpawnMobj(bx, by, bz, MT_WATERPALACEBUBBLE);
bubble->fuse = TICRATE*10;
bubble->angle = bubbleang;
bubble->movecount = bubbleradius;
P_SetTarget(&bubble->tracer, mo);
}
}
void Obj_WPZTurbineThinker(mobj_t *mo)
{
UINT8 i;
mapthing_t *mt = mo->spawnpoint;
boolean opt1 = mt->thing_args[0] != 0;
fixed_t baseheight = (mt->thing_args[2]) ? (mt->thing_args[2]*FRACUNIT) : (mo->z+mapobjectscale*1024);
fixed_t sneakerheight = (mt->thing_args[3]) ? (mt->thing_args[3]*FRACUNIT) : (mo->z+mapobjectscale*1768);
fixed_t range = (mt->thing_args[7]) ? (mt->thing_args[7]*FRACUNIT) : (FixedMul(mapobjectscale, TURBINE_RANGE));
INT32 rotspeed = (mt->thing_args[5]) ? (mt->thing_args[5]*ANG1/10) : (ANG1*3); // not angle_t for negatives.
tic_t turbinetime = (mt->thing_args[4]) ? (mt->thing_args[4]) : (TICRATE*3);
SINT8 mult = (opt1) ? (-1) : (1);
mo->extravalue1 += rotspeed*mult;
// find players in range and take their phones.
for (i = 0; i < MAXPLAYERS; i++)
{
player_t *p;
mobj_t *pmo;
if (!playeringame[i] || players[i].spectator || K_isPlayerInSpecialState(&players[i]))
continue;
p = &players[i];
pmo = p->mo;
if (R_PointToDist2(pmo->x, pmo->y, mo->x, mo->y) < range
&& !p->turbine
&& !p->respawn.timer)
{
P_SetTarget(&pmo->tracer, mo);
p->turbine = turbinetime;
// to be fully honest i dont rememebr what i was on while writing this
// but it originally went by mo instead of pmo for angle??? how did it ever *work* ?
p->turbineangle = ANGLE_180 + R_PointToAngle2(0, 0, mo->momx, mo->momy);
if (!p->speed)
p->turbineangle = ANGLE_180 + mo->angle;
p->turbineangle += ANG1*45*mult;
p->turbineheight = baseheight;
p->turbinespd = false;
if (FixedDiv(p->speed, K_GetKartSpeed(p, false, false)) > FRACUNIT + FRACUNIT/3 // 133% speed
&& baseheight != sneakerheight)
{
p->turbineheight = sneakerheight;
p->turbinespd = true;
}
pmo->flags |= MF_NOCLIP;
}
}
Obj_WPZTurbineUpdate(mo);
}
// ported from my lua for convenience of not having to rewrite half the shit code.
static INT32 angtoint(angle_t a)
{
return a/ANG1;
}
// controls player while using a turbine.
// i do not remember what i smoked before writing the lua version of this code.
// it's a fucking mess what the fuck does half of this even DO
void Obj_playerWPZTurbine(player_t *p)
{
mobj_t *pmo = p->mo;
mobj_t *t = pmo->tracer;
mapthing_t *mt;
boolean opt1;
fixed_t dist = FixedMul(mapobjectscale, TURBINE_SPIN)*FRACUNIT;
INT32 speed = ANG1*3;
boolean mode = false;
boolean distreached;
fixed_t tx, ty, tz;
fixed_t momz;
if (!t || P_MobjWasRemoved(t))
{
p->turbine = false;
P_SetTarget(&pmo->tracer, NULL);
return; // wtf happened
}
mt = t->spawnpoint;
opt1 = (mt->thing_args[0] != 0);
if (mt->thing_args[6])
dist = mt->thing_args[6]*FRACUNIT;
if (mt->thing_args[5])
speed = mt->thing_args[5]*ANG1/10;
if (mt->thing_args[9])
mode = true;
distreached = R_PointToDist2(t->x, t->y, pmo->x, pmo->y) <= dist+32*mapobjectscale;
if (mode && !distreached)
p->turbineangle = (INT32)R_PointToAngle2(t->x, t->y, pmo->x, pmo->y);
p->spinouttimer = TICRATE;
pmo->pitch = 0;
// determine target x/y/z
tx = t->x + (dist/FRACUNIT)*FINECOSINE((angle_t)(p->turbineangle)>>ANGLETOFINESHIFT);
ty = t->y + (dist/FRACUNIT)*FINESINE((angle_t)(p->turbineangle)>>ANGLETOFINESHIFT);
tz = p->turbineheight;
//CONS_Printf("%d %d\n", tx/FRACUNIT, ty/FRACUNIT);
if (mode)
{
if (distreached)
{
P_MoveOrigin(pmo, tx, ty, pmo->z);
}
else
{
pmo->momx = FixedMul(FINECOSINE((angle_t)(p->turbineangle)>>ANGLETOFINESHIFT), -(max(p->speed, mapobjectscale*32)));
pmo->momy = FixedMul(FINESINE((angle_t)(p->turbineangle)>>ANGLETOFINESHIFT), -(max(p->speed, mapobjectscale*32)));
}
}
else
{
pmo->momx = (tx - pmo->x)/24 * (p->turbinespd ? 2 : 1);
pmo->momy = (ty - pmo->y)/24 * (p->turbinespd ? 2 : 1);
}
momz = (tz - pmo->z)/128 * (p->turbinespd+1);
if (mt->thing_args[8])
{
momz = (mt->thing_args[8]*FRACUNIT) * ((tz < pmo->z) ? -1 : 1);
if (momz < 0)
{
if (pmo->z + momz < tz)
{
momz = pmo->z - tz;
}
}
else if (momz > 0)
{
if (pmo->z + momz > tz)
{
momz = tz - pmo->z;
}
}
}
pmo->momz = momz;
p->turbineangle += (speed * (p->turbinespd ? 2 : 1)) * (opt1 ? -1 : 1);
P_SetPlayerAngle(p, (angle_t)p->turbineangle + ANGLE_90*(opt1 ? -1 : 1));
if (pmo->eflags & MFE_UNDERWATER)
{
fixed_t rx = pmo->x + P_RandomRange(PR_FUZZ, -64, 64)*mapobjectscale;
fixed_t ry = pmo->y + P_RandomRange(PR_FUZZ, -64, 64)*mapobjectscale;
fixed_t rz = pmo->z + P_RandomRange(PR_FUZZ, -64, 64)*mapobjectscale;
mobj_t *bubl = P_SpawnMobj(rx, ry, rz, MT_THOK);
P_SetScale(bubl, pmo->scale*2);
bubl->scalespeed = pmo->scale/12;
bubl->destscale = 1;
bubl->sprite = SPR_BUBL;
bubl->frame = 0;
bubl->tics = TICRATE;
}
if (pmo->momz < mapobjectscale*6)
{
INT32 myang = angtoint(pmo->angle);
angle_t exitangle = t->angle;
INT32 targetangle = angtoint(exitangle);
INT32 launchangle = myang-targetangle;
// WHAT WAS I SMOKING
if ( (opt1 && launchangle > -60 && launchangle < -45)
|| (!opt1 && launchangle > 45 && launchangle < 60))
{
P_SetPlayerAngle(p, targetangle*ANG1);
if (mode)
P_InstaThrust(pmo, targetangle*ANG1, 128*mapobjectscale);
else
{
fixed_t spd = FixedHypot(pmo->momx, pmo->momy);
P_InstaThrust(pmo, targetangle*ANG1, spd);
}
P_SetTarget(&pmo->tracer, NULL);
p->turbineheight = 0;
p->turbineangle = 0;
if (p->turbinespd)
pmo->momz = mapobjectscale*5 * (pmo->eflags & MFE_UNDERWATER ? 2 : 1);
if (pmo->eflags & MFE_UNDERWATER)
{
pmo->momz = mapobjectscale*5;
pmo->momx = (pmo->momx*17)/10;
pmo->momy = (pmo->momy*17)/10;
}
p->spinouttimer = 0;
pmo->flags &= ~MF_NOCLIP;
}
}
}
// bubbles that circle the turbine
void Obj_WPZBubbleThink(mobj_t *mo)
{
angle_t ang = mo->angle - ANGLE_90;
mobj_t *t = mo->tracer;
fixed_t tx, ty;
mapthing_t *mt;
// where
// where did it go
if (!t || P_MobjWasRemoved(t))
{
P_RemoveMobj(mo);
return;
}
mt = mo->spawnpoint;
if (!mt)
return;
mo->momz = mapobjectscale*16;
tx = mo->tracer->x + FixedMul(mapobjectscale, mo->movefactor*FINECOSINE(ang>>ANGLETOFINESHIFT));
ty = mo->tracer->y + FixedMul(mapobjectscale, mo->movefactor*FINESINE(ang>>ANGLETOFINESHIFT));
mo->momx = (tx - mo->x)/24;
mo->momy = (ty - mo->y)/24;
if (leveltime & 1)
{
fixed_t rx = mo->x + P_RandomRange(PR_FUZZ, -64, 64)*mapobjectscale;
fixed_t ry = mo->y + P_RandomRange(PR_FUZZ, -64, 64)*mapobjectscale;
fixed_t rz = mo->z + P_RandomRange(PR_FUZZ, -64, 64)*mapobjectscale;
mobj_t *bubl = P_SpawnMobj(rx, ry, rz, MT_THOK);
P_SetScale(bubl, mapobjectscale*4);
bubl->destscale = 1;
bubl->sprite = SPR_BUBL;
bubl->frame = 0;
bubl->tics = TICRATE;
}
mo->angle += 3*ANG1 * (mt->thing_args[0] ? -1 : 1);
}

View file

@ -9745,6 +9745,18 @@ static boolean P_MobjRegularThink(mobj_t *mobj)
Obj_WPZBubbleThink(mobj);
break;
case MT_WATERPALACEFOUNTAIN:
Obj_WPZFountainThink(mobj);
break;
case MT_KURAGEN:
Obj_WPZKuragenThink(mobj);
break;
case MT_KURAGENBOMB:
Obj_WPZKuragenBombThink(mobj);
break;
default:
// check mobj against possible water content, before movement code
P_MobjCheckWater(mobj);