2015-04-20 18:25:39 +00:00
// Emacs style mode select -*- C++ -*-
2014-11-19 00:45:57 +00:00
//-----------------------------------------------------------------------------
//
// Copyright(C) 2004 Stephen McGranahan
//
// This program is free software; you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation; either version 2 of the License, or
// (at your option) any later version.
2015-04-20 18:25:39 +00:00
//
2014-11-19 00:45:57 +00:00
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
2015-04-20 18:25:39 +00:00
//
2014-11-19 00:45:57 +00:00
// You should have received a copy of the GNU General Public License
// along with this program; if not, write to the Free Software
// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
//
//--------------------------------------------------------------------------
//
// DESCRIPTION:
// Slopes
// SoM created 05/10/09
// ZDoom + Eternity Engine Slopes, ported and enhanced by Kalaron
//
//-----------------------------------------------------------------------------
# include "doomdef.h"
# include "r_defs.h"
# include "r_state.h"
# include "m_bbox.h"
# include "z_zone.h"
# include "p_spec.h"
# include "p_slopes.h"
# include "r_main.h"
# include "p_maputl.h"
# include "w_wad.h"
# ifdef ESLOPE
2015-04-27 02:50:50 +00:00
static pslope_t * dynslopes = NULL ;
// Calculate line normal
void P_CalculateSlopeNormal ( pslope_t * slope ) {
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 ) ;
}
// Recalculate dynamic slopes
void P_RunDynamicSlopes ( void ) {
pslope_t * slope ;
for ( slope = dynslopes ; slope ; slope = slope - > next ) {
fixed_t zdelta ;
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 ;
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-04-27 02:50:50 +00:00
const fixed_t zdelta , boolean dynamic )
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-04-27 02:50:50 +00:00
if ( dynamic ) { // Add to the dynamic slopes list
ret - > next = dynslopes ;
dynslopes = ret ;
}
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.
// SRB2CBTODO: Use a formula to get the slope to slide objects depending on how steep
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.
// Kalaron: Check if dynamic slopes need recalculation
//
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
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 ) ;
}
2014-11-19 00:45:57 +00:00
// SRB2CBTODO: Transform origin relative to the bounds of an individual FOF
2015-04-26 18:06:23 +00:00
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-04-20 18:25:39 +00:00
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-05-16 05:04:19 +00:00
P_MakeSlope ( & point , & direction , dz , ! ( line - > flags & ML_NOTAILS ) ) ;
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
// SRB2CBTODO: Anything special for remote(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
fixed_t highest = point . z > origin . z ? point . z : origin . z ;
fixed_t 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
2014-11-19 00:45:57 +00:00
size_t l ;
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-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-05-16 05:04:19 +00:00
P_MakeSlope ( & point , & direction , dz , ! ( line - > flags & ML_NOTAILS ) ) ;
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
// SRB2CBTODO: Anything special for remote(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
fixed_t highest = point . z > origin . z ? point . z : origin . z ;
fixed_t lowest = point . z < origin . z ? point . z : origin . z ;
size_t l ;
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-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-05-16 05:04:19 +00:00
P_MakeSlope ( & point , & direction , dz , ! ( line - > flags & ML_NOTAILS ) ) ;
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
// SRB2CBTODO: Anything special for remote(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
fixed_t highest = point . z > origin . z ? point . z : origin . z ;
fixed_t lowest = point . z < origin . z ? point . z : origin . z ;
size_t l ;
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-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-05-16 05:04:19 +00:00
P_MakeSlope ( & point , & direction , dz , ! ( line - > flags & ML_NOTAILS ) ) ;
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
// SRB2CBTODO: Anything special for remote(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
fixed_t highest = point . z > origin . z ? point . z : origin . z ;
fixed_t 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
size_t l ;
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 ;
}
//
// 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-04-27 02:50:50 +00:00
# ifdef SPRINGCLEAN
2014-11-19 00:45:57 +00:00
# include "byteptr.h"
# include "p_setup.h"
# include "p_local.h"
//==========================================================================
//
// P_SetSlopesFromVertexHeights
//
//==========================================================================
void P_SetSlopesFromVertexHeights ( lumpnum_t lumpnum )
{
mapthing_t * mt ;
boolean vt_found = false ;
size_t i , j , k , l , q ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
//size_t i;
//mapthing_t *mt;
char * data ;
char * datastart ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
// SRB2CBTODO: WHAT IS (5 * sizeof (short))?! It = 10
// anything else seems to make a map not load properly,
// but this hard-coded value MUST have some reason for being what it is
size_t snummapthings = W_LumpLength ( lumpnum ) / ( 5 * sizeof ( short ) ) ;
mapthing_t * smapthings = Z_Calloc ( snummapthings * sizeof ( * smapthings ) , PU_LEVEL , NULL ) ;
fixed_t x , y ;
sector_t * sector ;
// Spawn axis points first so they are
// at the front of the list for fast searching.
data = datastart = W_CacheLumpNum ( lumpnum , PU_LEVEL ) ;
mt = smapthings ;
for ( i = 0 ; i < snummapthings ; i + + , mt + + )
{
mt - > x = READINT16 ( data ) ;
mt - > y = READINT16 ( data ) ;
mt - > angle = READINT16 ( data ) ;
mt - > type = READINT16 ( data ) ;
mt - > options = READINT16 ( data ) ;
// mt->z hasn't been set yet!
//mt->extrainfo = (byte)(mt->type >> 12); // slope things are special, they have a bigger range of types
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
//mt->type &= 4095; // SRB2CBTODO: WHAT IS THIS???? Mobj type limits?!!!!
x = mt - > x * FRACUNIT ;
y = mt - > y * FRACUNIT ;
sector = R_PointInSubsector ( x , y ) - > sector ;
// Z for objects
2015-04-20 18:25:39 +00:00
# ifdef ESLOPE
2014-11-19 00:45:57 +00:00
if ( sector - > f_slope )
mt - > z = ( short ) ( P_GetZAt ( sector - > f_slope , x , y ) > > FRACBITS ) ;
else
# endif
mt - > z = ( short ) ( sector - > floorheight > > FRACBITS ) ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
mt - > z = mt - > z + ( mt - > options > > ZSHIFT ) ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
if ( mt - > type = = THING_VertexFloorZ | | mt - > type = = THING_VertexCeilingZ ) // THING_VertexFloorZ
{
for ( l = 0 ; l < numvertexes ; l + + )
{
if ( vertexes [ l ] . x = = mt - > x * FRACUNIT & & vertexes [ l ] . y = = mt - > y * FRACUNIT )
{
2015-04-20 18:25:39 +00:00
if ( mt - > type = = THING_VertexFloorZ )
2014-11-19 00:45:57 +00:00
{
vertexes [ l ] . z = mt - > z * FRACUNIT ;
//I_Error("Z value: %i", vertexes[l].z/FRACUNIT);
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
}
2015-04-20 18:25:39 +00:00
else
2014-11-19 00:45:57 +00:00
{
vertexes [ l ] . z = mt - > z * FRACUNIT ; // celing floor
}
vt_found = true ;
}
}
//mt->type = 0; // VPHYSICS: Dynamic slopes
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
if ( vt_found )
{
for ( k = 0 ; k < numsectors ; k + + )
{
sector_t * sec = & sectors [ k ] ;
if ( sec - > linecount ! = 3 ) continue ; // only works with triangular sectors
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
v3float_t vt1 , vt2 , vt3 ; // cross = ret->normalf
v3float_t vec1 , vec2 ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
int vi1 , vi2 , vi3 ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
vi1 = ( int ) ( sec - > lines [ 0 ] - > v1 - vertexes ) ;
vi2 = ( int ) ( sec - > lines [ 0 ] - > v2 - vertexes ) ;
vi3 = ( sec - > lines [ 1 ] - > v1 = = sec - > lines [ 0 ] - > v1 | | sec - > lines [ 1 ] - > v1 = = sec - > lines [ 0 ] - > v2 ) ?
( int ) ( sec - > lines [ 1 ] - > v2 - vertexes ) : ( int ) ( sec - > lines [ 1 ] - > v1 - vertexes ) ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
//if (vertexes[vi1].z)
// I_Error("OSNAP %i", vertexes[vi1].z/FRACUNIT);
//if (vertexes[vi2].z)
// I_Error("OSNAP %i", vertexes[vi2].z/FRACUNIT);
//if (vertexes[vi3].z)
// I_Error("OSNAP %i", vertexes[vi3].z/FRACUNIT);
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
//I_Error("%i, %i", mt->z*FRACUNIT, vertexes[vi1].z);
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
//I_Error("%i, %i, %i", mt->x, mt->y, mt->z);
//P_SpawnMobj(mt->x*FRACUNIT, mt->y*FRACUNIT, mt->z*FRACUNIT, MT_RING);
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
// TODO: Make sure not to spawn in the same place 2x! (we need an object in every vertex of the
// triangle sector to setup the real vertex slopes
// Check for the vertexes of all sectors
for ( q = 0 ; q < numvertexes ; q + + )
{
if ( vertexes [ q ] . x = = mt - > x * FRACUNIT & & vertexes [ q ] . y = = mt - > y * FRACUNIT )
{
//I_Error("yeah %i", vertexes[q].z);
P_SpawnMobj ( vertexes [ q ] . x , vertexes [ q ] . y , vertexes [ q ] . z , MT_RING ) ;
#if 0
if ( ( mt - > y * FRACUNIT = = vertexes [ vi1 ] . y & & mt - > x * FRACUNIT = = vertexes [ vi1 ] . x & & mt - > z * FRACUNIT = = vertexes [ vi1 ] . z )
& & ! ( mt - > y * FRACUNIT = = vertexes [ vi2 ] . y & & mt - > x * FRACUNIT = = vertexes [ vi2 ] . x & & mt - > z * FRACUNIT = = vertexes [ vi2 ] . z )
& & ! ( mt - > y * FRACUNIT = = vertexes [ vi3 ] . y & & mt - > x * FRACUNIT = = vertexes [ vi3 ] . x & & mt - > z * FRACUNIT = = vertexes [ vi3 ] . z ) )
P_SpawnMobj ( vertexes [ vi1 ] . x , vertexes [ vi1 ] . y , vertexes [ vi1 ] . z , MT_RING ) ;
else if ( ( mt - > y * FRACUNIT = = vertexes [ vi2 ] . y & & mt - > x * FRACUNIT = = vertexes [ vi2 ] . x & & mt - > z * FRACUNIT = = vertexes [ vi2 ] . z )
& & ! ( mt - > y * FRACUNIT = = vertexes [ vi1 ] . y & & mt - > x * FRACUNIT = = vertexes [ vi1 ] . x & & mt - > z * FRACUNIT = = vertexes [ vi1 ] . z )
& & ! ( mt - > y * FRACUNIT = = vertexes [ vi3 ] . y & & mt - > x * FRACUNIT = = vertexes [ vi3 ] . x & & mt - > z * FRACUNIT = = vertexes [ vi3 ] . z ) )
P_SpawnMobj ( vertexes [ vi2 ] . x , vertexes [ vi2 ] . y , vertexes [ vi2 ] . z , MT_BOUNCETV ) ;
else if ( ( mt - > y * FRACUNIT = = vertexes [ vi3 ] . y & & mt - > x * FRACUNIT = = vertexes [ vi3 ] . x & & mt - > z * FRACUNIT = = vertexes [ vi3 ] . z )
& & ! ( mt - > y * FRACUNIT = = vertexes [ vi2 ] . y & & mt - > x * FRACUNIT = = vertexes [ vi2 ] . x & & mt - > z * FRACUNIT = = vertexes [ vi2 ] . z )
& & ! ( mt - > y * FRACUNIT = = vertexes [ vi1 ] . y & & mt - > x * FRACUNIT = = vertexes [ vi1 ] . x & & mt - > z * FRACUNIT = = vertexes [ vi1 ] . z ) )
P_SpawnMobj ( vertexes [ vi3 ] . x , vertexes [ vi3 ] . y , vertexes [ vi3 ] . z , MT_GFZFLOWER1 ) ;
else
# endif
continue ;
}
}
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
vt1 . x = FIXED_TO_FLOAT ( vertexes [ vi1 ] . x ) ;
vt1 . y = FIXED_TO_FLOAT ( vertexes [ vi1 ] . y ) ;
vt2 . x = FIXED_TO_FLOAT ( vertexes [ vi2 ] . x ) ;
vt2 . y = FIXED_TO_FLOAT ( vertexes [ vi2 ] . y ) ;
vt3 . x = FIXED_TO_FLOAT ( vertexes [ vi3 ] . x ) ;
vt3 . y = FIXED_TO_FLOAT ( vertexes [ vi3 ] . y ) ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
for ( j = 0 ; j < 2 ; j + + )
{
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
fixed_t z3 ;
//I_Error("Lo hicimos");
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
vt1 . z = mt - > z ; //FIXED_TO_FLOAT(j==0 ? sec->floorheight : sec->ceilingheight);
vt2 . z = mt - > z ; //FIXED_TO_FLOAT(j==0? sec->floorheight : sec->ceilingheight);
z3 = mt - > z ; //j==0? sec->floorheight : sec->ceilingheight; // Destination height
vt3 . z = FIXED_TO_FLOAT ( z3 ) ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
if ( P_PointOnLineSide ( vertexes [ vi3 ] . x , vertexes [ vi3 ] . y , sec - > lines [ 0 ] ) = = 0 )
{
vec1 . x = vt2 . x - vt3 . x ;
vec1 . y = vt2 . y - vt3 . y ;
vec1 . z = vt2 . z - vt3 . z ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
vec2 . x = vt1 . x - vt3 . x ;
vec2 . y = vt1 . y - vt3 . y ;
vec2 . z = vt1 . z - vt3 . z ;
}
else
{
vec1 . x = vt1 . x - vt3 . x ;
vec1 . y = vt1 . y - vt3 . y ;
vec1 . z = vt1 . z - vt3 . z ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
vec2 . x = vt2 . x - vt3 . x ;
vec2 . y = vt2 . y - vt3 . y ;
vec2 . z = vt2 . z - vt3 . z ;
}
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
pslope_t * ret = Z_Malloc ( sizeof ( pslope_t ) , PU_LEVEL , NULL ) ;
memset ( ret , 0 , sizeof ( * ret ) ) ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
{
M_CrossProduct3f ( & ret - > normalf , & vec1 , & vec2 ) ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
// Cross product length
float len = ( float ) sqrt ( ret - > normalf . x * ret - > normalf . x +
2015-04-20 18:25:39 +00:00
ret - > normalf . y * ret - > normalf . y +
2014-11-19 00:45:57 +00:00
ret - > normalf . z * ret - > normalf . z ) ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
if ( len = = 0 )
{
// Only happens when all vertices in this sector are on the same line.
// Let's just ignore this case.
//CONS_Printf("Slope thing at (%d,%d) lies directly on its target line.\n", (int)(x>>16), (int)(y>>16));
return ;
}
// cross/len
ret - > normalf . x / = len ;
ret - > normalf . y / = len ;
ret - > normalf . z / = len ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
// ZDoom cross = ret->normalf
// Fix backward normals
if ( ( ret - > normalf . z < 0 & & j = = 0 ) | | ( ret - > normalf . z > 0 & & j = = 1 ) )
{
// cross = -cross
ret - > normalf . x = - ret - > normalf . x ;
ret - > normalf . y = - ret - > normalf . x ;
ret - > normalf . z = - ret - > normalf . x ;
2015-04-20 18:25:39 +00:00
}
2014-11-19 00:45:57 +00:00
}
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
secplane_t * srcplane = Z_Calloc ( sizeof ( * srcplane ) , PU_LEVEL , NULL ) ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
srcplane - > a = FLOAT_TO_FIXED ( ret - > normalf . x ) ;
srcplane - > b = FLOAT_TO_FIXED ( ret - > normalf . y ) ;
srcplane - > c = FLOAT_TO_FIXED ( ret - > normalf . z ) ;
2015-04-26 03:22:50 +00:00
//srcplane->ic = FixedDiv(FRACUNIT, srcplane->c);
2014-11-19 00:45:57 +00:00
srcplane - > d = - TMulScale16 ( srcplane - > a , vertexes [ vi3 ] . x ,
srcplane - > b , vertexes [ vi3 ] . y ,
srcplane - > c , z3 ) ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
if ( j = = 0 )
{
sec - > f_slope = ret ;
sec - > f_slope - > secplane = * srcplane ;
}
else if ( j = = 1 )
{
sec - > c_slope = ret ;
sec - > c_slope - > secplane = * srcplane ;
}
}
2015-04-20 18:25:39 +00:00
}
2014-11-19 00:45:57 +00:00
}
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
}
}
Z_Free ( datastart ) ;
2015-04-20 18:25:39 +00:00
2014-11-19 00:45:57 +00:00
}
2015-04-27 02:50:50 +00:00
# endif
2014-11-19 00:45:57 +00:00
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 ;
2015-05-24 20:59:17 +00:00
# if 1 // Rewrite old specials to new ones, and give a console warning
boolean warned = false ;
# endif
2015-05-16 05:02:01 +00:00
dynslopes = NULL ;
// 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 )
{
2015-05-24 20:59:17 +00:00
# if 1 // Rewrite old specials to new ones, and give a console warning
# 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 ;
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
{
2015-05-23 03:07:07 +00:00
vector3_t axis ;
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 )
{
// 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.
2015-05-23 03:07:07 +00:00
vector3_t slopemom ;
2015-04-29 05:35:54 +00:00
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 ;
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 )
{
2015-05-23 03:07:07 +00:00
vector3_t mom ;
2015-05-13 21:15:32 +00:00
mom . x = thing - > momx ;
mom . y = thing - > momy ;
mom . z = thing - > momz * 2 ;
2015-05-15 17:35:54 +00:00
//CONS_Printf("langing on slope\n");
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 ;
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 ) ;
}
2015-05-21 00:08:49 +00:00
//CONS_Printf("%d\n", mult);
2015-05-20 18:18:41 +00:00
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
// Multiply by gravity
thrust = FixedMul ( thrust , FRACUNIT / 2 ) ; // TODO actually get this
P_Thrust ( mo , mo - > standingslope - > xydirection , thrust ) ;
}
2014-11-19 00:45:57 +00:00
// EOF
# endif // #ifdef ESLOPE