2016-05-18 00:42:11 +00:00
// SONIC ROBO BLAST 2
2014-11-19 00:45:57 +00:00
//-----------------------------------------------------------------------------
2016-05-18 00:42:11 +00:00
// Copyright (C) 2004 by Stephen McGranahan
// Copyright (C) 2015-2016 by Sonic Team Junior.
2014-11-19 00:45:57 +00:00
//
2016-05-18 00:42:11 +00:00
// This program is free software distributed under the
// terms of the GNU General Public License, version 2.
// See the 'LICENSE' file for more details.
2014-11-19 00:45:57 +00:00
//-----------------------------------------------------------------------------
2016-05-18 00:42:11 +00:00
/// \file p_slopes.c
/// \brief ZDoom + Eternity Engine Slopes, ported and enhanced by Kalaron
2014-11-19 00:45:57 +00:00
# include "doomdef.h"
# include "r_defs.h"
# include "r_state.h"
# include "m_bbox.h"
# include "z_zone.h"
2015-10-10 16:57:35 +00:00
# include "p_local.h"
2016-05-31 14:01:19 +00:00
# include "p_mobj.h"
2014-11-19 00:45:57 +00:00
# include "p_spec.h"
# include "p_slopes.h"
2015-08-04 03:15:59 +00:00
# include "p_setup.h"
2014-11-19 00:45:57 +00:00
# include "r_main.h"
# include "p_maputl.h"
# include "w_wad.h"
# ifdef ESLOPE
2015-08-03 22:39:33 +00:00
static pslope_t * slopelist = NULL ;
static UINT16 slopecount = 0 ;
2015-04-27 02:50:50 +00:00
// Calculate line normal
2016-01-03 16:33:45 +00:00
static void P_CalculateSlopeNormal ( pslope_t * slope ) {
2015-04-27 02:50:50 +00:00
slope - > normal . z = FINECOSINE ( slope - > zangle > > ANGLETOFINESHIFT ) ;
slope - > normal . x = - FixedMul ( FINESINE ( slope - > zangle > > ANGLETOFINESHIFT ) , slope - > d . x ) ;
slope - > normal . y = - FixedMul ( FINESINE ( slope - > zangle > > ANGLETOFINESHIFT ) , slope - > d . y ) ;
}
2015-08-04 03:15:59 +00:00
// With a vertex slope that has its vertices set, configure relevant slope info
2016-01-03 16:33:45 +00:00
static void P_ReconfigureVertexSlope ( pslope_t * slope )
2015-08-04 03:15:59 +00:00
{
vector3_t vec1 , vec2 ;
// Set slope normal
vec1 . x = ( slope - > vertices [ 1 ] - > x - slope - > vertices [ 0 ] - > x ) < < FRACBITS ;
vec1 . y = ( slope - > vertices [ 1 ] - > y - slope - > vertices [ 0 ] - > y ) < < FRACBITS ;
vec1 . z = ( slope - > vertices [ 1 ] - > z - slope - > vertices [ 0 ] - > z ) < < FRACBITS ;
vec2 . x = ( slope - > vertices [ 2 ] - > x - slope - > vertices [ 0 ] - > x ) < < FRACBITS ;
vec2 . y = ( slope - > vertices [ 2 ] - > y - slope - > vertices [ 0 ] - > y ) < < FRACBITS ;
vec2 . z = ( slope - > vertices [ 2 ] - > z - slope - > vertices [ 0 ] - > z ) < < FRACBITS ;
// ugggggggh fixed-point maaaaaaath
slope - > extent = max (
max ( max ( abs ( vec1 . x ) , abs ( vec1 . y ) ) , abs ( vec1 . z ) ) ,
max ( max ( abs ( vec2 . x ) , abs ( vec2 . y ) ) , abs ( vec2 . z ) )
) > > ( FRACBITS + 5 ) ;
vec1 . x / = slope - > extent ;
vec1 . y / = slope - > extent ;
vec1 . z / = slope - > extent ;
vec2 . x / = slope - > extent ;
vec2 . y / = slope - > extent ;
vec2 . z / = slope - > extent ;
FV3_Cross ( & vec1 , & vec2 , & slope - > normal ) ;
slope - > extent = R_PointToDist2 ( 0 , 0 , R_PointToDist2 ( 0 , 0 , slope - > normal . x , slope - > normal . y ) , slope - > normal . z ) ;
if ( slope - > normal . z < 0 )
slope - > extent = - slope - > extent ;
slope - > normal . x = FixedDiv ( slope - > normal . x , slope - > extent ) ;
slope - > normal . y = FixedDiv ( slope - > normal . y , slope - > extent ) ;
slope - > normal . z = FixedDiv ( slope - > normal . z , slope - > extent ) ;
// Set origin
slope - > o . x = slope - > vertices [ 0 ] - > x < < FRACBITS ;
slope - > o . y = slope - > vertices [ 0 ] - > y < < FRACBITS ;
slope - > o . z = slope - > vertices [ 0 ] - > z < < FRACBITS ;
if ( slope - > normal . x = = 0 & & slope - > normal . y = = 0 ) { // Set some defaults for a non-sloped "slope"
slope - > zangle = slope - > xydirection = 0 ;
slope - > zdelta = slope - > d . x = slope - > d . y = 0 ;
} else {
// Get direction vector
slope - > extent = R_PointToDist2 ( 0 , 0 , slope - > normal . x , slope - > normal . y ) ;
slope - > d . x = - FixedDiv ( slope - > normal . x , slope - > extent ) ;
slope - > d . y = - FixedDiv ( slope - > normal . y , slope - > extent ) ;
// Z delta
slope - > zdelta = FixedDiv ( slope - > extent , slope - > normal . z ) ;
// Get angles
slope - > xydirection = R_PointToAngle2 ( 0 , 0 , slope - > d . x , slope - > d . y ) + ANGLE_180 ;
2016-05-22 15:03:04 +00:00
slope - > zangle = InvAngle ( R_PointToAngle2 ( 0 , 0 , FRACUNIT , slope - > zdelta ) ) ;
2015-08-04 03:15:59 +00:00
}
}
2015-04-27 02:50:50 +00:00
// Recalculate dynamic slopes
void P_RunDynamicSlopes ( void ) {
pslope_t * slope ;
2015-08-03 22:39:33 +00:00
for ( slope = slopelist ; slope ; slope = slope - > next ) {
2015-04-27 02:50:50 +00:00
fixed_t zdelta ;
2015-08-03 22:39:33 +00:00
if ( slope - > flags & SL_NODYNAMIC )
continue ;
2015-04-27 02:50:50 +00:00
switch ( slope - > refpos ) {
case 1 : // front floor
zdelta = slope - > sourceline - > backsector - > floorheight - slope - > sourceline - > frontsector - > floorheight ;
2015-04-27 19:07:04 +00:00
slope - > o . z = slope - > sourceline - > frontsector - > floorheight ;
2015-04-27 02:50:50 +00:00
break ;
case 2 : // front ceiling
zdelta = slope - > sourceline - > backsector - > ceilingheight - slope - > sourceline - > frontsector - > ceilingheight ;
2015-04-27 19:07:04 +00:00
slope - > o . z = slope - > sourceline - > frontsector - > ceilingheight ;
2015-04-27 02:50:50 +00:00
break ;
case 3 : // back floor
zdelta = slope - > sourceline - > frontsector - > floorheight - slope - > sourceline - > backsector - > floorheight ;
2015-04-27 19:07:04 +00:00
slope - > o . z = slope - > sourceline - > backsector - > floorheight ;
2015-04-27 02:50:50 +00:00
break ;
case 4 : // back ceiling
zdelta = slope - > sourceline - > frontsector - > ceilingheight - slope - > sourceline - > backsector - > ceilingheight ;
2015-04-27 19:07:04 +00:00
slope - > o . z = slope - > sourceline - > backsector - > ceilingheight ;
2015-04-27 02:50:50 +00:00
break ;
2015-08-04 03:15:59 +00:00
case 5 : // vertices
{
mapthing_t * mt ;
2015-10-10 16:57:35 +00:00
size_t i ;
INT32 l ;
2015-08-04 03:15:59 +00:00
line_t * line ;
for ( i = 0 ; i < 3 ; i + + ) {
mt = slope - > vertices [ i ] ;
l = P_FindSpecialLineFromTag ( 799 , mt - > angle , - 1 ) ;
if ( l ! = - 1 ) {
line = & lines [ l ] ;
mt - > z = line - > frontsector - > floorheight > > FRACBITS ;
}
}
P_ReconfigureVertexSlope ( slope ) ;
}
continue ; // TODO
2015-04-27 02:50:50 +00:00
default :
I_Error ( " P_RunDynamicSlopes: slope has invalid type! " ) ;
}
if ( slope - > zdelta ! = FixedDiv ( zdelta , slope - > extent ) ) {
2015-05-23 03:07:07 +00:00
slope - > zdelta = FixedDiv ( zdelta , slope - > extent ) ;
2015-04-29 05:30:39 +00:00
slope - > zangle = R_PointToAngle2 ( 0 , 0 , slope - > extent , - zdelta ) ;
2015-04-27 02:50:50 +00:00
P_CalculateSlopeNormal ( slope ) ;
}
}
}
2014-11-19 00:45:57 +00:00
//
// P_MakeSlope
//
// Alocates and fill the contents of a slope structure.
//
2015-05-23 03:07:07 +00:00
static pslope_t * P_MakeSlope ( const vector3_t * o , const vector2_t * d ,
2015-08-03 22:39:33 +00:00
const fixed_t zdelta , UINT8 flags )
2014-11-19 00:45:57 +00:00
{
2015-04-27 02:50:50 +00:00
pslope_t * ret = Z_Malloc ( sizeof ( pslope_t ) , PU_LEVEL , NULL ) ;
memset ( ret , 0 , sizeof ( * ret ) ) ;
2014-11-19 00:45:57 +00:00
2015-05-23 03:07:07 +00:00
ret - > o . x = o - > x ;
ret - > o . y = o - > y ;
ret - > o . z = o - > z ;
2014-11-19 00:45:57 +00:00
2015-05-23 03:07:07 +00:00
ret - > d . x = d - > x ;
ret - > d . y = d - > y ;
2014-11-19 00:45:57 +00:00
2015-05-23 03:07:07 +00:00
ret - > zdelta = zdelta ;
2014-11-19 00:45:57 +00:00
2015-08-03 22:39:33 +00:00
ret - > flags = flags ;
// Add to the slope list
ret - > next = slopelist ;
slopelist = ret ;
slopecount + + ;
ret - > id = slopecount ;
2015-04-27 02:50:50 +00:00
return ret ;
2014-11-19 00:45:57 +00:00
}
//
// P_GetExtent
//
// Returns the distance to the first line within the sector that
// is intersected by a line parallel to the plane normal with the point (ox, oy)
//
2015-04-26 18:06:23 +00:00
static fixed_t P_GetExtent ( sector_t * sector , line_t * line )
2014-11-19 00:45:57 +00:00
{
// ZDoom code reference: v3float_t = vertex_t
2015-04-26 18:06:23 +00:00
fixed_t fardist = - FRACUNIT ;
size_t i ;
2014-11-19 00:45:57 +00:00
// Find furthest vertex from the reference line. It, along with the two ends
// of the line, will define the plane.
2015-04-26 18:06:23 +00:00
for ( i = 0 ; i < sector - > linecount ; i + + )
{
line_t * li = sector - > lines [ i ] ;
vertex_t tempv ;
fixed_t dist ;
// Don't compare to the slope line.
if ( li = = line )
continue ;
P_ClosestPointOnLine ( li - > v1 - > x , li - > v1 - > y , line , & tempv ) ;
dist = R_PointToDist2 ( tempv . x , tempv . y , li - > v1 - > x , li - > v1 - > y ) ;
if ( dist > fardist )
fardist = dist ;
2014-11-19 00:45:57 +00:00
2015-04-20 18:25:39 +00:00
// Okay, maybe do it for v2 as well?
2015-04-26 18:06:23 +00:00
P_ClosestPointOnLine ( li - > v2 - > x , li - > v2 - > y , line , & tempv ) ;
dist = R_PointToDist2 ( tempv . x , tempv . y , li - > v2 - > x , li - > v2 - > y ) ;
if ( dist > fardist )
fardist = dist ;
}
2015-04-19 21:54:20 +00:00
2014-11-19 00:45:57 +00:00
return fardist ;
}
//
// P_SpawnSlope_Line
//
// Creates one or more slopes based on the given line type and front/back
// sectors.
//
void P_SpawnSlope_Line ( int linenum )
{
// With dynamic slopes, it's fine to just leave this function as normal,
// because checking to see if a slope had changed will waste more memory than
// if the slope was just updated when called
line_t * line = lines + linenum ;
2015-04-26 18:06:23 +00:00
INT16 special = line - > special ;
2014-11-19 00:45:57 +00:00
pslope_t * fslope = NULL , * cslope = NULL ;
2015-05-23 03:07:07 +00:00
vector3_t origin , point ;
vector2_t direction ;
2015-04-26 18:06:23 +00:00
fixed_t nx , ny , dz , extent ;
2015-04-20 18:25:39 +00:00
2015-05-24 20:59:17 +00:00
boolean frontfloor = ( special = = 700 | | special = = 702 | | special = = 703 ) ;
boolean backfloor = ( special = = 710 | | special = = 712 | | special = = 713 ) ;
boolean frontceil = ( special = = 701 | | special = = 702 | | special = = 713 ) ;
boolean backceil = ( special = = 711 | | special = = 712 | | special = = 703 ) ;
2015-04-20 18:25:39 +00:00
2015-08-03 22:39:33 +00:00
UINT8 flags = 0 ; // Slope flags
if ( line - > flags & ML_NOSONIC )
flags | = SL_NOPHYSICS ;
if ( line - > flags & ML_NOTAILS )
flags | = SL_NODYNAMIC ;
if ( line - > flags & ML_NOKNUX )
flags | = SL_ANCHORVERTEX ;
2014-11-19 00:45:57 +00:00
if ( ! frontfloor & & ! backfloor & & ! frontceil & & ! backceil )
{
CONS_Printf ( " P_SpawnSlope_Line called with non-slope line special. \n " ) ;
return ;
}
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
if ( ! line - > frontsector | | ! line - > backsector )
{
CONS_Printf ( " P_SpawnSlope_Line used on a line without two sides. \n " ) ;
return ;
}
2015-04-20 18:25:39 +00:00
2015-04-26 18:06:23 +00:00
{
fixed_t len = R_PointToDist2 ( 0 , 0 , line - > dx , line - > dy ) ;
nx = FixedDiv ( line - > dy , len ) ;
ny = - FixedDiv ( line - > dx , len ) ;
}
origin . x = line - > v1 - > x + ( line - > v2 - > x - line - > v1 - > x ) / 2 ;
origin . y = line - > v1 - > y + ( line - > v2 - > y - line - > v1 - > y ) / 2 ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
// For FOF slopes, make a special function to copy to the xy origin & direction relative to the position of the FOF on the map!
if ( frontfloor | | frontceil )
{
2015-05-17 04:55:49 +00:00
line - > frontsector - > hasslope = true ; // Tell the software renderer that we're sloped
2015-04-26 18:06:23 +00:00
origin . z = line - > backsector - > floorheight ;
direction . x = nx ;
direction . y = ny ;
2015-04-20 18:25:39 +00:00
2015-04-26 18:06:23 +00:00
extent = P_GetExtent ( line - > frontsector , line ) ;
2015-04-20 18:25:39 +00:00
2015-04-26 18:06:23 +00:00
if ( extent < 0 )
2014-11-19 00:45:57 +00:00
{
CONS_Printf ( " P_SpawnSlope_Line failed to get frontsector extent on line number %i \n " , linenum ) ;
return ;
}
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
// reposition the origin according to the extent
2015-04-26 18:06:23 +00:00
point . x = origin . x + FixedMul ( direction . x , extent ) ;
point . y = origin . y + FixedMul ( direction . y , extent ) ;
2014-11-19 00:45:57 +00:00
direction . x = - direction . x ;
direction . y = - direction . y ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
// TODO: We take origin and point 's xy values and translate them to the center of an FOF!
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
if ( frontfloor )
{
2015-10-10 16:57:35 +00:00
fixed_t highest , lowest ;
size_t l ;
2015-04-26 18:06:23 +00:00
point . z = line - > frontsector - > floorheight ; // Startz
2015-04-29 05:30:39 +00:00
dz = FixedDiv ( origin . z - point . z , extent ) ; // Destinationz
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
// In P_SpawnSlopeLine the origin is the centerpoint of the sourcelinedef
2015-04-20 18:25:39 +00:00
fslope = line - > frontsector - > f_slope =
2015-08-03 22:39:33 +00:00
P_MakeSlope ( & point , & direction , dz , flags ) ;
2015-04-27 02:50:50 +00:00
// Set up some shit
fslope - > extent = extent ;
fslope - > refpos = 1 ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
// Now remember that f_slope IS a vector
// fslope->o = origin 3D point 1 of the vector
// fslope->d = destination 3D point 2 of the vector
// fslope->normal is a 3D line perpendicular to the 3D vector
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
// Sync the linedata of the line that started this slope
2016-05-31 16:07:28 +00:00
// TODO: Anything special for control sector based slopes later?
2015-04-26 18:06:23 +00:00
fslope - > sourceline = line ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
// To find the real highz/lowz of a slope, you need to check all the vertexes
// in the slope's sector with P_GetZAt to get the REAL lowz & highz
// Although these slopes are set by floorheights the ANGLE is what a slope is,
// so technically any slope can extend on forever (they are just bound by sectors)
// *You can use sourceline as a reference to see if two slopes really are the same
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
// Default points for high and low
2015-10-10 16:57:35 +00:00
highest = point . z > origin . z ? point . z : origin . z ;
lowest = point . z < origin . z ? point . z : origin . z ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
// Now check to see what the REAL high and low points of the slope inside the sector
2015-04-26 18:06:23 +00:00
// TODO: Is this really needed outside of FOFs? -Red
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
for ( l = 0 ; l < line - > frontsector - > linecount ; l + + )
{
2015-04-26 18:06:23 +00:00
fixed_t height = P_GetZAt ( line - > frontsector - > f_slope , line - > frontsector - > lines [ l ] - > v1 - > x , line - > frontsector - > lines [ l ] - > v1 - > y ) ;
if ( height > highest )
highest = height ;
2015-04-20 18:25:39 +00:00
2015-04-26 18:06:23 +00:00
if ( height < lowest )
lowest = height ;
2014-11-19 00:45:57 +00:00
}
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
// Sets extra clipping data for the frontsector's slope
2015-04-26 18:06:23 +00:00
fslope - > highz = highest ;
fslope - > lowz = lowest ;
2015-04-20 18:25:39 +00:00
2015-04-27 02:50:50 +00:00
fslope - > zangle = R_PointToAngle2 ( 0 , origin . z , extent , point . z ) ;
2015-04-26 18:06:23 +00:00
fslope - > xydirection = R_PointToAngle2 ( origin . x , origin . y , point . x , point . y ) ;
2015-04-27 02:50:50 +00:00
P_CalculateSlopeNormal ( fslope ) ;
2014-11-19 00:45:57 +00:00
}
if ( frontceil )
{
2015-10-10 16:57:35 +00:00
fixed_t highest , lowest ;
size_t l ;
2015-04-29 05:30:39 +00:00
origin . z = line - > backsector - > ceilingheight ;
2015-04-26 18:06:23 +00:00
point . z = line - > frontsector - > ceilingheight ;
2015-04-29 05:30:39 +00:00
dz = FixedDiv ( origin . z - point . z , extent ) ;
2015-04-20 18:25:39 +00:00
cslope = line - > frontsector - > c_slope =
2015-08-03 22:39:33 +00:00
P_MakeSlope ( & point , & direction , dz , flags ) ;
2015-04-20 18:25:39 +00:00
2015-04-27 02:50:50 +00:00
// Set up some shit
cslope - > extent = extent ;
cslope - > refpos = 2 ;
2014-11-19 00:45:57 +00:00
// Sync the linedata of the line that started this slope
2016-05-31 16:07:28 +00:00
// TODO: Anything special for control sector based slopes later?
2015-04-26 18:06:23 +00:00
cslope - > sourceline = line ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
// Remember the way the slope is formed
2015-10-10 16:57:35 +00:00
highest = point . z > origin . z ? point . z : origin . z ;
lowest = point . z < origin . z ? point . z : origin . z ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
for ( l = 0 ; l < line - > frontsector - > linecount ; l + + )
{
2015-04-26 18:06:23 +00:00
fixed_t height = P_GetZAt ( line - > frontsector - > c_slope , line - > frontsector - > lines [ l ] - > v1 - > x , line - > frontsector - > lines [ l ] - > v1 - > y ) ;
2015-04-20 18:25:39 +00:00
2015-04-26 18:06:23 +00:00
if ( height > highest )
highest = height ;
if ( height < lowest )
lowest = height ;
2014-11-19 00:45:57 +00:00
}
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
// This line special sets extra clipping data for the frontsector's slope
2015-04-26 18:06:23 +00:00
cslope - > highz = highest ;
cslope - > lowz = lowest ;
2015-04-27 02:50:50 +00:00
cslope - > zangle = R_PointToAngle2 ( 0 , origin . z , extent , point . z ) ;
2015-04-26 18:06:23 +00:00
cslope - > xydirection = R_PointToAngle2 ( origin . x , origin . y , point . x , point . y ) ;
2015-04-27 02:50:50 +00:00
P_CalculateSlopeNormal ( cslope ) ;
2014-11-19 00:45:57 +00:00
}
}
if ( backfloor | | backceil )
{
2015-05-17 04:55:49 +00:00
line - > backsector - > hasslope = true ; // Tell the software renderer that we're sloped
2015-04-26 18:06:23 +00:00
origin . z = line - > frontsector - > floorheight ;
2014-11-19 00:45:57 +00:00
// Backsector
2015-04-26 18:06:23 +00:00
direction . x = - nx ;
direction . y = - ny ;
2015-04-20 18:25:39 +00:00
2015-04-26 18:06:23 +00:00
extent = P_GetExtent ( line - > backsector , line ) ;
2015-04-20 18:25:39 +00:00
2015-04-26 18:06:23 +00:00
if ( extent < 0 )
2014-11-19 00:45:57 +00:00
{
CONS_Printf ( " P_SpawnSlope_Line failed to get backsector extent on line number %i \n " , linenum ) ;
return ;
}
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
// reposition the origin according to the extent
2015-04-26 18:06:23 +00:00
point . x = origin . x + FixedMul ( direction . x , extent ) ;
point . y = origin . y + FixedMul ( direction . y , extent ) ;
2014-11-19 00:45:57 +00:00
direction . x = - direction . x ;
direction . y = - direction . y ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
if ( backfloor )
{
2015-10-10 16:57:35 +00:00
fixed_t highest , lowest ;
size_t l ;
2015-04-26 18:06:23 +00:00
point . z = line - > backsector - > floorheight ;
2015-04-29 05:30:39 +00:00
dz = FixedDiv ( origin . z - point . z , extent ) ;
2015-04-20 18:25:39 +00:00
fslope = line - > backsector - > f_slope =
2015-08-03 22:39:33 +00:00
P_MakeSlope ( & point , & direction , dz , flags ) ;
2015-04-27 02:50:50 +00:00
// Set up some shit
fslope - > extent = extent ;
fslope - > refpos = 3 ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
// Sync the linedata of the line that started this slope
2016-05-31 16:07:28 +00:00
// TODO: Anything special for control sector based slopes later?
2015-04-26 18:06:23 +00:00
fslope - > sourceline = line ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
// Remember the way the slope is formed
2015-10-10 16:57:35 +00:00
highest = point . z > origin . z ? point . z : origin . z ;
lowest = point . z < origin . z ? point . z : origin . z ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
for ( l = 0 ; l < line - > backsector - > linecount ; l + + )
{
2015-04-26 18:06:23 +00:00
fixed_t height = P_GetZAt ( line - > backsector - > f_slope , line - > backsector - > lines [ l ] - > v1 - > x , line - > backsector - > lines [ l ] - > v1 - > y ) ;
2015-04-20 18:25:39 +00:00
2015-04-26 18:06:23 +00:00
if ( height > highest )
highest = height ;
if ( height < lowest )
lowest = height ;
2014-11-19 00:45:57 +00:00
}
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
// This line special sets extra clipping data for the frontsector's slope
2015-04-26 18:06:23 +00:00
fslope - > highz = highest ;
fslope - > lowz = lowest ;
2015-04-29 05:30:39 +00:00
fslope - > zangle = R_PointToAngle2 ( 0 , origin . z , extent , point . z ) ;
fslope - > xydirection = R_PointToAngle2 ( origin . x , origin . y , point . x , point . y ) ;
2015-04-27 02:50:50 +00:00
P_CalculateSlopeNormal ( fslope ) ;
2014-11-19 00:45:57 +00:00
}
if ( backceil )
{
2015-10-10 16:57:35 +00:00
fixed_t highest , lowest ;
size_t l ;
2015-04-29 05:30:39 +00:00
origin . z = line - > frontsector - > ceilingheight ;
2015-04-26 18:06:23 +00:00
point . z = line - > backsector - > ceilingheight ;
2015-04-29 05:30:39 +00:00
dz = FixedDiv ( origin . z - point . z , extent ) ;
2015-04-20 18:25:39 +00:00
cslope = line - > backsector - > c_slope =
2015-08-03 22:39:33 +00:00
P_MakeSlope ( & point , & direction , dz , flags ) ;
2015-04-20 18:25:39 +00:00
2015-04-27 02:50:50 +00:00
// Set up some shit
cslope - > extent = extent ;
cslope - > refpos = 4 ;
2014-11-19 00:45:57 +00:00
// Sync the linedata of the line that started this slope
2016-05-31 16:07:28 +00:00
// TODO: Anything special for control sector based slopes later?
2015-04-26 18:06:23 +00:00
cslope - > sourceline = line ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
// Remember the way the slope is formed
2015-10-10 16:57:35 +00:00
highest = point . z > origin . z ? point . z : origin . z ;
lowest = point . z < origin . z ? point . z : origin . z ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
for ( l = 0 ; l < line - > backsector - > linecount ; l + + )
{
2015-04-26 18:06:23 +00:00
fixed_t height = P_GetZAt ( line - > backsector - > c_slope , line - > backsector - > lines [ l ] - > v1 - > x , line - > backsector - > lines [ l ] - > v1 - > y ) ;
2015-04-20 18:25:39 +00:00
2015-04-26 18:06:23 +00:00
if ( height > highest )
highest = height ;
if ( height < lowest )
lowest = height ;
2014-11-19 00:45:57 +00:00
}
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
// This line special sets extra clipping data for the backsector's slope
2015-04-26 18:06:23 +00:00
cslope - > highz = highest ;
cslope - > lowz = lowest ;
2015-04-27 02:50:50 +00:00
cslope - > zangle = R_PointToAngle2 ( 0 , origin . z , extent , point . z ) ;
2015-04-26 18:06:23 +00:00
cslope - > xydirection = R_PointToAngle2 ( origin . x , origin . y , point . x , point . y ) ;
2015-04-27 02:50:50 +00:00
P_CalculateSlopeNormal ( cslope ) ;
2014-11-19 00:45:57 +00:00
}
}
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
if ( ! line - > tag )
return ;
}
2015-08-04 03:15:59 +00:00
//
// P_NewVertexSlope
//
// Creates a new slope from three vertices with the specified IDs
//
2016-01-03 16:33:45 +00:00
static pslope_t * P_NewVertexSlope ( INT16 tag1 , INT16 tag2 , INT16 tag3 , UINT8 flags )
2015-08-04 03:15:59 +00:00
{
size_t i ;
mapthing_t * mt = mapthings ;
pslope_t * ret = Z_Malloc ( sizeof ( pslope_t ) , PU_LEVEL , NULL ) ;
memset ( ret , 0 , sizeof ( * ret ) ) ;
// Start by setting flags
ret - > flags = flags ;
// Now set up the vertex list
ret - > vertices = Z_Malloc ( 3 * sizeof ( mapthing_t ) , PU_LEVEL , NULL ) ;
memset ( ret - > vertices , 0 , 3 * sizeof ( mapthing_t ) ) ;
// And... look for the vertices in question.
for ( i = 0 ; i < nummapthings ; i + + , mt + + ) {
if ( mt - > type ! = 750 ) // Haha, I'm hijacking the old Chaos Spawn thingtype for something!
continue ;
if ( ! ret - > vertices [ 0 ] & & mt - > angle = = tag1 )
ret - > vertices [ 0 ] = mt ;
else if ( ! ret - > vertices [ 1 ] & & mt - > angle = = tag2 )
ret - > vertices [ 1 ] = mt ;
else if ( ! ret - > vertices [ 2 ] & & mt - > angle = = tag3 )
ret - > vertices [ 2 ] = mt ;
}
// Now set heights for each vertex, because they haven't been set yet
for ( i = 0 ; i < 3 ; i + + ) {
mt = ret - > vertices [ i ] ;
2016-05-31 16:07:28 +00:00
if ( ! mt ) // If a vertex wasn't found, it's game over. There's nothing you can do to recover (except maybe try and kill the slope instead - TODO?)
2016-06-01 18:52:12 +00:00
I_Error ( " P_NewVertexSlope: Slope vertex %s (for linedef tag %d) not found! " , sizeu1 ( i ) , tag1 ) ;
2015-08-04 03:15:59 +00:00
if ( mt - > extrainfo )
mt - > z = mt - > options ;
else
mt - > z = ( R_PointInSubsector ( mt - > x < < FRACBITS , mt - > y < < FRACBITS ) - > sector - > floorheight > > FRACBITS ) + ( mt - > options > > ZSHIFT ) ;
}
P_ReconfigureVertexSlope ( ret ) ;
ret - > refpos = 5 ;
// Add to the slope list
ret - > next = slopelist ;
slopelist = ret ;
slopecount + + ;
ret - > id = slopecount ;
return ret ;
}
2014-11-19 00:45:57 +00:00
//
// P_CopySectorSlope
//
// Searches through tagged sectors and copies
//
void P_CopySectorSlope ( line_t * line )
{
sector_t * fsec = line - > frontsector ;
int i , special = line - > special ;
// Check for copy linedefs
for ( i = - 1 ; ( i = P_FindSectorFromLineTag ( line , i ) ) > = 0 ; )
{
sector_t * srcsec = sectors + i ;
2015-05-24 20:59:17 +00:00
if ( ( special - 719 ) & 1 & & ! fsec - > f_slope & & srcsec - > f_slope )
2015-04-26 18:06:23 +00:00
fsec - > f_slope = srcsec - > f_slope ; //P_CopySlope(srcsec->f_slope);
2015-05-24 20:59:17 +00:00
if ( ( special - 719 ) & 2 & & ! fsec - > c_slope & & srcsec - > c_slope )
2015-04-26 18:06:23 +00:00
fsec - > c_slope = srcsec - > c_slope ; //P_CopySlope(srcsec->c_slope);
2014-11-19 00:45:57 +00:00
}
2015-05-17 04:55:49 +00:00
fsec - > hasslope = true ;
2014-11-19 00:45:57 +00:00
line - > special = 0 ; // Linedef was use to set slopes, it finished its job, so now make it a normal linedef
}
2015-08-03 23:06:42 +00:00
//
// P_SlopeById
//
// Looks in the slope list for a slope with a specified ID. Mostly useful for netgame sync
//
pslope_t * P_SlopeById ( UINT16 id )
{
pslope_t * ret ;
for ( ret = slopelist ; ret & & ret - > id ! = id ; ret = ret - > next ) ;
return ret ;
}
2015-05-16 05:02:01 +00:00
// Reset the dynamic slopes pointer, and read all of the fancy schmancy slopes
void P_ResetDynamicSlopes ( void ) {
size_t i ;
2016-05-31 14:01:19 +00:00
# ifdef ESLOPE_TYPESHIM // Rewrite old specials to new ones, and give a console warning
2015-05-24 20:59:17 +00:00
boolean warned = false ;
# endif
2015-05-16 05:02:01 +00:00
2015-08-03 22:39:33 +00:00
slopelist = NULL ;
slopecount = 0 ;
2015-05-16 05:02:01 +00:00
// We'll handle copy slopes later, after all the tag lists have been made.
// Yes, this means copied slopes won't affect things' spawning heights. Too bad for you.
for ( i = 0 ; i < numlines ; i + + )
{
switch ( lines [ i ] . special )
{
2016-05-31 14:01:19 +00:00
# ifdef ESLOPE_TYPESHIM // Rewrite old specials to new ones, and give a console warning
2015-05-24 20:59:17 +00:00
# define WARNME if (!warned) {warned = true; CONS_Alert(CONS_WARNING, "This level uses old slope specials.\nA conversion will be needed before 2.2's release.\n");}
2015-05-16 05:02:01 +00:00
case 386 :
case 387 :
case 388 :
2015-05-24 20:59:17 +00:00
lines [ i ] . special + = 700 - 386 ;
WARNME
P_SpawnSlope_Line ( i ) ;
break ;
2015-05-16 05:02:01 +00:00
case 389 :
case 390 :
case 391 :
case 392 :
2015-05-24 20:59:17 +00:00
lines [ i ] . special + = 710 - 389 ;
WARNME
P_SpawnSlope_Line ( i ) ;
break ;
2015-05-16 05:02:01 +00:00
case 393 :
2015-05-24 20:59:17 +00:00
lines [ i ] . special = 703 ;
WARNME
P_SpawnSlope_Line ( i ) ;
break ;
case 394 :
case 395 :
case 396 :
lines [ i ] . special + = 720 - 394 ;
WARNME
break ;
# endif
case 700 :
case 701 :
case 702 :
case 703 :
case 710 :
case 711 :
case 712 :
case 713 :
2015-05-16 05:02:01 +00:00
P_SpawnSlope_Line ( i ) ;
break ;
2015-08-04 03:15:59 +00:00
case 704 :
2015-08-04 04:09:50 +00:00
case 705 :
case 714 :
case 715 :
2015-08-04 03:15:59 +00:00
{
2015-08-04 04:09:50 +00:00
pslope_t * * slopetoset ;
size_t which = lines [ i ] . special ;
2015-08-04 03:15:59 +00:00
UINT8 flags = SL_VERTEXSLOPE ;
if ( lines [ i ] . flags & ML_NOSONIC )
flags | = SL_NOPHYSICS ;
if ( ! ( lines [ i ] . flags & ML_NOTAILS ) )
flags | = SL_NODYNAMIC ;
2015-08-04 04:09:50 +00:00
if ( which = = 704 )
{
slopetoset = & lines [ i ] . frontsector - > f_slope ;
which = 0 ;
}
else if ( which = = 705 )
{
slopetoset = & lines [ i ] . frontsector - > c_slope ;
which = 0 ;
}
else if ( which = = 714 )
{
slopetoset = & lines [ i ] . backsector - > f_slope ;
which = 1 ;
}
else // 715
{
slopetoset = & lines [ i ] . backsector - > c_slope ;
which = 1 ;
}
2015-08-04 03:15:59 +00:00
if ( lines [ i ] . flags & ML_NOKNUX )
2015-08-04 04:09:50 +00:00
* slopetoset = P_NewVertexSlope ( lines [ i ] . tag , sides [ lines [ i ] . sidenum [ which ] ] . textureoffset > > FRACBITS ,
sides [ lines [ i ] . sidenum [ which ] ] . rowoffset > > FRACBITS , flags ) ;
2015-08-04 03:15:59 +00:00
else
2015-08-04 04:09:50 +00:00
* slopetoset = P_NewVertexSlope ( lines [ i ] . tag , lines [ i ] . tag , lines [ i ] . tag , flags ) ;
2015-08-04 03:15:59 +00:00
2015-08-04 04:09:50 +00:00
sides [ lines [ i ] . sidenum [ which ] ] . sector - > hasslope = true ;
2015-08-04 03:15:59 +00:00
}
break ;
2015-05-16 05:02:01 +00:00
default :
break ;
}
}
}
2014-11-19 00:45:57 +00:00
// ============================================================================
//
// Various utilities related to slopes
//
//
// P_GetZAt
//
// Returns the height of the sloped plane at (x, y) as a fixed_t
//
fixed_t P_GetZAt ( pslope_t * slope , fixed_t x , fixed_t y )
{
fixed_t dist = FixedMul ( x - slope - > o . x , slope - > d . x ) +
FixedMul ( y - slope - > o . y , slope - > d . y ) ;
return slope - > o . z + FixedMul ( dist , slope - > zdelta ) ;
}
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
2015-04-29 05:35:54 +00:00
//
// P_QuantizeMomentumToSlope
//
// When given a vector, rotates it and aligns it to a slope
2015-05-23 03:07:07 +00:00
void P_QuantizeMomentumToSlope ( vector3_t * momentum , pslope_t * slope )
2015-04-29 05:35:54 +00:00
{
2016-05-31 15:24:51 +00:00
vector3_t axis ; // Fuck you, C90.
2016-05-31 14:01:19 +00:00
if ( slope - > flags & SL_NOPHYSICS )
return ; // No physics, no quantizing.
2016-05-31 15:01:05 +00:00
2015-04-29 05:35:54 +00:00
axis . x = - slope - > d . y ;
axis . y = slope - > d . x ;
axis . z = 0 ;
2015-05-23 03:07:07 +00:00
FV3_Rotate ( momentum , & axis , slope - > zangle > > ANGLETOFINESHIFT ) ;
2015-04-29 05:35:54 +00:00
}
//
// P_SlopeLaunch
//
// Handles slope ejection for objects
void P_SlopeLaunch ( mobj_t * mo )
{
2016-05-31 14:01:19 +00:00
if ( ! ( mo - > standingslope - > flags & SL_NOPHYSICS ) ) // If there's physics, time for launching.
{
// Double the pre-rotation Z, then halve the post-rotation Z. This reduces the
// vertical launch given from slopes while increasing the horizontal launch
// given. Good for SRB2's gravity and horizontal speeds.
vector3_t slopemom ;
slopemom . x = mo - > momx ;
slopemom . y = mo - > momy ;
slopemom . z = mo - > momz * 2 ;
P_QuantizeMomentumToSlope ( & slopemom , mo - > standingslope ) ;
mo - > momx = slopemom . x ;
mo - > momy = slopemom . y ;
mo - > momz = slopemom . z / 2 ;
}
2016-05-31 15:01:05 +00:00
2015-04-30 05:32:44 +00:00
//CONS_Printf("Launched off of slope.\n");
2015-04-29 05:35:54 +00:00
mo - > standingslope = NULL ;
}
2015-05-13 21:15:32 +00:00
// Function to help handle landing on slopes
void P_HandleSlopeLanding ( mobj_t * thing , pslope_t * slope )
2016-05-31 15:01:05 +00:00
{
2016-05-31 15:24:51 +00:00
vector3_t mom ; // Ditto.
2016-05-31 14:01:19 +00:00
if ( slope - > flags & SL_NOPHYSICS ) { // No physics, no need to make anything complicated.
if ( P_MobjFlip ( thing ) * ( thing - > momz ) < 0 ) { // falling, land on slope
thing - > momz = - P_MobjFlip ( thing ) ;
thing - > standingslope = slope ;
}
return ;
}
2015-05-13 21:15:32 +00:00
mom . x = thing - > momx ;
mom . y = thing - > momy ;
mom . z = thing - > momz * 2 ;
2016-06-02 15:42:07 +00:00
//CONS_Printf("Landing on slope\n");
2015-05-15 17:35:54 +00:00
2015-05-13 21:15:32 +00:00
// Reverse quantizing might could use its own function later
slope - > zangle = ANGLE_MAX - slope - > zangle ;
P_QuantizeMomentumToSlope ( & mom , slope ) ;
slope - > zangle = ANGLE_MAX - slope - > zangle ;
if ( P_MobjFlip ( thing ) * mom . z < 0 ) { // falling, land on slope
thing - > momx = mom . x ;
thing - > momy = mom . y ;
thing - > momz = - P_MobjFlip ( thing ) ;
2015-05-15 17:35:54 +00:00
thing - > standingslope = slope ;
2015-05-13 21:15:32 +00:00
}
}
2015-04-29 05:35:54 +00:00
// https://yourlogicalfallacyis.com/slippery-slope
// Handles sliding down slopes, like if they were made of butter :)
void P_ButteredSlope ( mobj_t * mo )
{
fixed_t thrust ;
if ( ! mo - > standingslope )
return ;
2016-05-31 15:01:05 +00:00
2016-05-31 14:01:19 +00:00
if ( mo - > standingslope - > flags & SL_NOPHYSICS )
return ; // No physics, no butter.
2015-04-29 05:35:54 +00:00
2016-02-23 22:53:24 +00:00
if ( mo - > flags & ( MF_NOCLIPHEIGHT | MF_NOGRAVITY ) )
return ; // don't slide down slopes if you can't touch them or you're not affected by gravity
2015-05-20 18:18:41 +00:00
if ( mo - > player ) {
if ( abs ( mo - > standingslope - > zdelta ) < FRACUNIT / 4 & & ! ( mo - > player - > pflags & PF_SPINNING ) )
return ; // Don't slide on non-steep slopes unless spinning
if ( abs ( mo - > standingslope - > zdelta ) < FRACUNIT / 2 & & ! ( mo - > player - > rmomx | | mo - > player - > rmomy ) )
return ; // Allow the player to stand still on slopes below a certain steepness
}
2015-04-29 05:35:54 +00:00
2015-04-30 05:32:44 +00:00
thrust = FINESINE ( mo - > standingslope - > zangle > > ANGLETOFINESHIFT ) * 3 / 2 * ( mo - > eflags & MFE_VERTICALFLIP ? 1 : - 1 ) ;
2015-04-29 05:35:54 +00:00
2015-05-20 18:18:41 +00:00
if ( mo - > player & & ( mo - > player - > pflags & PF_SPINNING ) ) {
fixed_t mult = 0 ;
if ( mo - > momx | | mo - > momy ) {
angle_t angle = R_PointToAngle2 ( 0 , 0 , mo - > momx , mo - > momy ) - mo - > standingslope - > xydirection ;
if ( P_MobjFlip ( mo ) * mo - > standingslope - > zdelta < 0 )
angle ^ = ANGLE_180 ;
mult = FINECOSINE ( angle > > ANGLETOFINESHIFT ) ;
}
thrust = FixedMul ( thrust , FRACUNIT * 2 / 3 + mult / 8 ) ;
}
2015-04-30 05:32:44 +00:00
if ( mo - > momx | | mo - > momy ) // Slightly increase thrust based on the object's speed
thrust = FixedMul ( thrust , FRACUNIT + P_AproxDistance ( mo - > momx , mo - > momy ) / 16 ) ;
// This makes it harder to zigzag up steep slopes, as well as allows greater top speed when rolling down
2015-04-29 05:35:54 +00:00
2016-06-02 15:42:07 +00:00
// Let's get the gravity strength for the object...
2016-06-02 15:09:33 +00:00
thrust = FixedMul ( thrust , abs ( P_GetMobjGravity ( mo ) ) ) ;
2016-06-02 15:51:12 +00:00
// ... and its friction against the ground for good measure (divided by original friction to keep behaviour for normal slopes the same).
thrust = FixedMul ( thrust , FixedDiv ( mo - > friction , ORIG_FRICTION ) ) ;
2016-06-02 15:09:33 +00:00
2015-04-29 05:35:54 +00:00
P_Thrust ( mo , mo - > standingslope - > xydirection , thrust ) ;
}
2014-11-19 00:45:57 +00:00
// EOF
# endif // #ifdef ESLOPE