diff --git a/src/dehacked.c b/src/dehacked.c index 60d61903a..8507a1b03 100644 --- a/src/dehacked.c +++ b/src/dehacked.c @@ -7898,6 +7898,8 @@ static const char *const MOBJTYPE_LIST[] = { // array length left dynamic for s "MT_DEZLASER", "MT_WAYPOINT", + "MT_WAYPOINT_RISER", + "MT_WAYPOINT_ANCHOR", "MT_RANDOMAUDIENCE", diff --git a/src/info.c b/src/info.c index 9c9759f31..7bed0a78d 100644 --- a/src/info.c +++ b/src/info.c @@ -16528,6 +16528,60 @@ mobjinfo_t mobjinfo[NUMMOBJTYPES] = S_NULL // raisestate }, + { // MT_WAYPOINT_RISER + 2002, // doomednum + S_INVISIBLE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 100, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 1*FRACUNIT, // radius + 2*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY, // flags + S_NULL // raisestate + }, + + { // MT_WAYPOINT_ANCHOR + 2003, // doomednum + S_INVISIBLE, // spawnstate + 1000, // spawnhealth + S_NULL, // seestate + sfx_None, // seesound + 0, // reactiontime + sfx_None, // attacksound + S_NULL, // painstate + 100, // painchance + sfx_None, // painsound + S_NULL, // meleestate + S_NULL, // missilestate + S_NULL, // deathstate + S_NULL, // xdeathstate + sfx_None, // deathsound + 0, // speed + 1*FRACUNIT, // radius + 2*FRACUNIT, // height + 0, // display offset + 100, // mass + 0, // damage + sfx_None, // activesound + MF_NOBLOCKMAP|MF_NOCLIP|MF_NOGRAVITY|MF_SCENERY, // flags + S_NULL // raisestate + }, + { // MT_RANDOMAUDIENCE 1488, // doomednum S_RANDOMAUDIENCE, // spawnstate diff --git a/src/info.h b/src/info.h index ca2f71def..f86fed973 100644 --- a/src/info.h +++ b/src/info.h @@ -4829,6 +4829,8 @@ typedef enum mobj_type MT_DEZLASER, MT_WAYPOINT, + MT_WAYPOINT_RISER, + MT_WAYPOINT_ANCHOR, MT_RANDOMAUDIENCE, diff --git a/src/k_waypoint.c b/src/k_waypoint.c index a70e3a249..f32cf68b0 100644 --- a/src/k_waypoint.c +++ b/src/k_waypoint.c @@ -16,6 +16,7 @@ #include "d_netcmd.h" #include "p_local.h" #include "p_tick.h" +#include "r_local.h" #include "z_zone.h" #include "g_game.h" @@ -1770,3 +1771,176 @@ void K_ClearWaypoints(void) numwaypointmobjs = 0U; circuitlength = 0U; } + +/*-------------------------------------------------- + static boolean K_RaiseWaypoint( + mobj_t *const waypointmobj, + const mobj_t *const riser) + + Raise a waypoint according a waypoint riser thing. + + Input Arguments:- + waypointmobj - The mobj of the waypoint to raise + riser - The waypoint riser mobj + + Return:- + True if the waypoint was risen, false if not. +--------------------------------------------------*/ + +static boolean K_RaiseWaypoint( + mobj_t *const waypointmobj, + const mobj_t *const riser) +{ + fixed_t x; + fixed_t y; + + const sector_t *sector; + ffloor_t *rover; + + boolean descending; + + fixed_t sort; + fixed_t z; + + if ( + !( riser->spawnpoint->options & MTF_OBJECTSPECIAL ) || + riser->spawnpoint->angle == waypointmobj->spawnpoint->angle + ){ + if (( riser->spawnpoint->options & MTF_AMBUSH )) + { + waypointmobj->z = riser->z; + } + else + { + x = waypointmobj->x; + y = waypointmobj->y; + + descending = ( riser->spawnpoint->options & MTF_OBJECTFLIP ); + + sector = waypointmobj->subsector->sector; + + if (descending) + sort = sector->ceilingheight; + else + sort = sector->floorheight; + + for ( + rover = sector->ffloors; + rover; + rover = rover->next + ){ + if (descending) + { + z = P_GetFOFBottomZAt(rover, x, y); + + if (z > riser->z && z < sort) + sort = z; + } + else + { + z = P_GetFOFTopZAt(rover, x, y); + + if (z < riser->z && z > sort) + sort = z; + } + } + + waypointmobj->z = sort; + } + + return true; + } + else + return false; +} + +/*-------------------------------------------------- + static boolean K_AnchorWaypointRadius( + mobj_t *const waypointmobj, + const mobj_t *const anchor) + + Adjust a waypoint's radius by distance from an "anchor". + + Input Arguments:- + waypointmobj - The mobj of the waypoint whose radius to adjust + riser - The waypoint anchor mobj + + Return:- + True if the waypoint's radius was adjusted, false if not. +--------------------------------------------------*/ + +static boolean K_AnchorWaypointRadius( + mobj_t *const waypointmobj, + const mobj_t *const anchor) +{ + if (anchor->spawnpoint->angle == waypointmobj->spawnpoint->angle) + { + waypointmobj->radius = R_PointToDist2( + waypointmobj->x, waypointmobj->y, + anchor->x, anchor->y); + + return true; + } + else + return false; +} + +/*-------------------------------------------------- + void K_AdjustWaypointsParameters(void) + + See header file for description. +--------------------------------------------------*/ + +void K_AdjustWaypointsParameters (void) +{ + mobj_t *waypointmobj; + const mobj_t *riser; + + const thinker_t *th; + const mobj_t *anchor; + + const sector_t *sector; + + for ( + waypointmobj = waypointcap; + waypointmobj; + waypointmobj = waypointmobj->tracer + ){ + sector = waypointmobj->subsector->sector; + + for ( + riser = sector->thinglist; + riser; + riser = riser->snext + ){ + if (riser->type == MT_WAYPOINT_RISER) + { + if (K_RaiseWaypoint(waypointmobj, riser)) + break; + } + } + } + + for ( + th = thinkercap.next; + th != &thinkercap; + th = th->next + ){ + if (th->function.acp1 == (actionf_p1)P_MobjThinker) + { + anchor = (const mobj_t *)th; + + if (anchor->type == MT_WAYPOINT_ANCHOR) + { + for ( + waypointmobj = waypointcap; + waypointmobj; + waypointmobj = waypointmobj->tracer + ){ + if (K_AnchorWaypointRadius(waypointmobj, anchor)) + break; + } + } + } + } +} diff --git a/src/k_waypoint.h b/src/k_waypoint.h index f1a678603..0017c443e 100644 --- a/src/k_waypoint.h +++ b/src/k_waypoint.h @@ -345,4 +345,14 @@ boolean K_SetupWaypointList(void); void K_ClearWaypoints(void); -#endif \ No newline at end of file +/*-------------------------------------------------- + void K_AdjustWaypointsParameters(void) + + Adjusts waypoint parameters after P_SpawnSpecials. This is for + raising waypoints to an FOF, which requires that the FOF is + already spawned. +--------------------------------------------------*/ + +void K_AdjustWaypointsParameters (void); + +#endif diff --git a/src/p_local.h b/src/p_local.h index 0d7d3ec3e..a45119a18 100644 --- a/src/p_local.h +++ b/src/p_local.h @@ -355,6 +355,12 @@ boolean PIT_PushableMoved(mobj_t *thing); boolean P_DoSpring(mobj_t *spring, mobj_t *object); +fixed_t P_GetFOFTopZAt (ffloor_t *rover, fixed_t x, fixed_t y); +fixed_t P_GetFOFBottomZAt (ffloor_t *rover, fixed_t x, fixed_t y); + +fixed_t P_VeryTopOfFOF (ffloor_t *rover); +fixed_t P_VeryBottomOfFOF (ffloor_t *rover); + // // P_SETUP // diff --git a/src/p_map.c b/src/p_map.c index 9a3864f2c..a6306bb19 100644 --- a/src/p_map.c +++ b/src/p_map.c @@ -4749,3 +4749,51 @@ fixed_t P_FloorzAtPos(fixed_t x, fixed_t y, fixed_t z, fixed_t height) return floorz; } + +fixed_t +P_GetFOFTopZAt (ffloor_t *rover, fixed_t x, fixed_t y) +{ + (void)x; + (void)y; +#ifdef ESLOPE + if (*rover->t_slope) + return P_GetZAt(*rover->t_slope, x, y); + else +#endif + return *rover->topheight; +} + +fixed_t +P_GetFOFBottomZAt (ffloor_t *rover, fixed_t x, fixed_t y) +{ + (void)x; + (void)y; +#ifdef ESLOPE + if (*rover->b_slope) + return P_GetZAt(*rover->b_slope, x, y); + else +#endif + return *rover->bottomheight; +} + +fixed_t +P_VeryTopOfFOF (ffloor_t *rover) +{ +#ifdef ESLOPE + if (*rover->t_slope) + return (*rover->t_slope)->highz; + else +#endif + return *rover->topheight; +} + +fixed_t +P_VeryBottomOfFOF (ffloor_t *rover) +{ +#ifdef ESLOPE + if (*rover->b_slope) + return (*rover->b_slope)->lowz; + else +#endif + return *rover->bottomheight; +} diff --git a/src/p_setup.c b/src/p_setup.c index d569c6452..0708379ed 100644 --- a/src/p_setup.c +++ b/src/p_setup.c @@ -3126,6 +3126,8 @@ boolean P_SetupLevel(boolean skipprecip) // set up world state P_SpawnSpecials(fromnetsave); + K_AdjustWaypointsParameters(); + if (loadprecip) // ugly hack for P_NetUnArchiveMisc (and P_LoadNetGame) P_SpawnPrecipitation(); diff --git a/src/p_slopes.c b/src/p_slopes.c index 03c1205f6..0825ebca6 100644 --- a/src/p_slopes.c +++ b/src/p_slopes.c @@ -764,7 +764,6 @@ fixed_t P_GetZAt(pslope_t *slope, fixed_t x, fixed_t y) return slope->o.z + FixedMul(dist, slope->zdelta); } - // // P_QuantizeMomentumToSlope // diff --git a/src/p_spec.c b/src/p_spec.c index ee3e4851f..ad711fb8b 100644 --- a/src/p_spec.c +++ b/src/p_spec.c @@ -5350,6 +5350,72 @@ static ffloor_t *P_AddFakeFloor(sector_t *sec, sector_t *sec2, line_t *master, f return ffloor; } +static fixed_t +Floor_height (sector_t *s, fixed_t x, fixed_t y) +{ +#ifdef ESLOPE + return s->f_slope ? P_GetZAt(s->f_slope, x, y) : s->floorheight; +#else + (void)x; + (void)y; + return s->floorheight; +#endif +} + +static fixed_t +Ceiling_height (sector_t *s, fixed_t x, fixed_t y) +{ +#ifdef ESLOPE + return s->c_slope ? P_GetZAt(s->c_slope, x, y) : s->ceilingheight; +#else + (void)x; + (void)y; + return s->ceilingheight; +#endif +} + +static void +P_RaiseTaggedThingsToFakeFloor ( + UINT16 type, + INT16 tag, + sector_t *control +){ + sector_t *target; + + mobj_t *mo; + mapthing_t *mthing; + + fixed_t offset; + + size_t i; + + for (i = 0; i < control->numattached; ++i) + { + target = §ors[control->attached[i]]; + + for (mo = target->thinglist; mo; mo = mo->snext) + { + mthing = mo->spawnpoint; + + if ( + mthing->type == type && + mthing->angle == tag + ){ + if (( mo->flags2 & MF2_OBJECTFLIP )) + { + offset = ( mo->ceilingz - mo->info->height ) - mo->z; + mo->z = ( Floor_height(control, mo->x, mo->y) - mo->info->height ) - offset; + } + else + { + offset = mo->z - mo->floorz; + mo->z = Ceiling_height(control, mo->x, mo->y) + offset; + } + } + } + } +} + // // SPECIAL SPAWNING // @@ -6813,6 +6879,22 @@ void P_SpawnSpecials(INT32 fromnetsave) } } + /* some things have to be done after FOF spawn */ + + for (i = 0; i < numlines; ++i) + { + switch (lines[i].special) + { + case 80: // Raise tagged things by type to this FOF + P_RaiseTaggedThingsToFakeFloor( + ( sides[lines[i].sidenum[0]].textureoffset >> FRACBITS ), + lines[i].tag, + lines[i].frontsector + ); + break; + } + } + // Allocate each list for (i = 0; i < numsectors; i++) if(secthinkers[i].thinkers)