/
p_maputl.c
192 lines (155 loc) · 6.24 KB
/
p_maputl.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
/**\file
*\section License
* License: GPL
* Online License Link: http://www.gnu.org/licenses/gpl.html
*
*\author Copyright © 2003-2008 Jaakko Keränen <jaakko.keranen@iki.fi>
*\author Copyright © 2006-2008 Daniel Swanson <danij@dengine.net>
*\author Copyright © 1999 by Chi Hoang, Lee Killough, Jim Flynn, Rand Phares, Ty Halderman (PrBoom 2.2.6)
*\author Copyright © 1999-2000 by Jess Haas, Nicolas Kalkhof, Colin Phipps, Florian Schulze (PrBoom 2.2.6)
*
* 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.
*
* 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.
*
* 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., 51 Franklin St, Fifth Floor,
* Boston, MA 02110-1301 USA
*/
/**
* p_maputl.c: Movement/collision map utility functions.
*/
// HEADER FILES ------------------------------------------------------------
#include <stdlib.h>
#include <math.h>
#include "jdoom64.h"
#include "dmu_lib.h"
#include "p_map.h"
// MACROS ------------------------------------------------------------------
// TYPES -------------------------------------------------------------------
// EXTERNAL FUNCTION PROTOTYPES --------------------------------------------
// PUBLIC FUNCTION PROTOTYPES ----------------------------------------------
// PRIVATE FUNCTION PROTOTYPES ---------------------------------------------
// EXTERNAL DATA DECLARATIONS ----------------------------------------------
// PUBLIC DATA DEFINITIONS -------------------------------------------------
// PRIVATE DATA DEFINITIONS ------------------------------------------------
// CODE --------------------------------------------------------------------
/**
* Apply "torque" to objects hanging off of ledges, so that they fall off.
* It's not really torque, since Doom has no concept of rotation, but it's
* a convincing effect which avoids anomalies such as lifeless objects
* hanging more than halfway off of ledges, and allows objects to roll off
* of the edges of moving lifts, or to slide up and then back down stairs,
* or to fall into a ditch.
*
* If more than one linedef is contacted, the effects are cumulative, so
* balancing is possible.
*/
static boolean PIT_ApplyTorque(linedef_t *ld, void *data)
{
mobj_t *mo = tmThing;
float dist;
sector_t *frontsec, *backsec;
float ffloor, bfloor;
float dx, dy;
if(tmThing->player)
return true; // Skip players!
frontsec = P_GetPtrp(ld, DMU_FRONT_SECTOR);
backsec = P_GetPtrp(ld, DMU_BACK_SECTOR);
if(!frontsec || !backsec)
return true; // Shouldn't ever happen.
ffloor = P_GetFloatp(frontsec, DMU_FLOOR_HEIGHT);
bfloor = P_GetFloatp(backsec, DMU_FLOOR_HEIGHT);
dx = P_GetFloatp(ld, DMU_DX);
dy = P_GetFloatp(ld, DMU_DY);
// Lever-arm:
dist =
+dx * mo->pos[VY] -
dy * mo->pos[VX] -
dx * (P_GetFloatp(P_GetPtrp(ld, DMU_VERTEX0), DMU_Y)) +
dy * (P_GetFloatp(P_GetPtrp(ld, DMU_VERTEX0), DMU_X));
if((dist < 0 && ffloor < mo->pos[VZ] && bfloor >= mo->pos[VZ]) ||
(dist >= 0 && bfloor < mo->pos[VZ] && ffloor >= mo->pos[VZ]))
{
// At this point, we know that the object straddles a two-sided
// linedef, and that the object's center of mass is above-ground.
float x = fabs(dx), y = fabs(dy);
if(y > x)
{
float tmp = x;
x = y;
y = tmp;
}
y = FIX2FLT(finesine[(tantoangle[FLT2FIX(y / x) >> DBITS] +
ANG90) >> ANGLETOFINESHIFT]);
/**
* Momentum is proportional to distance between the object's center
* of mass and the pivot linedef.
*
* It is scaled by 2^(OVERDRIVE - gear). When gear is increased, the
* momentum gradually decreases to 0 for the same amount of
* pseudotorque, so that oscillations are prevented, yet it has a
* chance to reach equilibrium.
*/
if(mo->gear < OVERDRIVE)
dist = (dist * FIX2FLT(FLT2FIX(y) << -(mo->gear - OVERDRIVE))) / x;
else
dist = (dist * FIX2FLT(FLT2FIX(y) >> +(mo->gear - OVERDRIVE))) / x;
// Apply momentum away from the pivot linedef.
x = dy * dist;
y = dx * dist;
// Avoid moving too fast all of a sudden (step into "overdrive").
dist = (x * x) + (y * y);
while(dist > 4 && mo->gear < MAXGEAR)
{
++mo->gear;
x /= 2;
y /= 2;
dist /= 2;
}
mo->mom[MX] -= x;
mo->mom[MY] += y;
}
return true;
}
/**
* Applies "torque" to objects, based on all contacted linedefs.
* $dropoff_fix
*/
void P_ApplyTorque(mobj_t *mo)
{
int flags = mo->intFlags;
// Corpse sliding anomalies, made configurable.
if(!cfg.slidingCorpses)
return;
tmThing = mo;
// Use VALIDCOUNT to prevent checking the same line twice.
VALIDCOUNT++;
P_MobjLinesIterator(mo, PIT_ApplyTorque, 0);
// If any momentum, mark object as 'falling' using engine-internal
// flags.
if(mo->mom[MX] != 0 || mo->mom[MY] != 0)
mo->intFlags |= MIF_FALLING;
else
// Clear the engine-internal flag indicating falling object.
mo->intFlags &= ~MIF_FALLING;
/**
* If the object has been moving, step up the gear. This helps reach
* equilibrium and avoid oscillations.
*
* DOOM has no concept of potential energy, much less of rotation, so we
* have to creatively simulate these systems somehow :)
*/
// If not falling for a while, reset it to full strength.
if(!((mo->intFlags | flags) & MIF_FALLING))
mo->gear = 0;
else if(mo->gear < MAXGEAR) // Else if not at max gear, move up a gear.
mo->gear++;
}