Make stepnormal available to the above functions, fixes some discrepancies in QC...
[xonotic/xonotic-data.pk3dir.git] / qcsrc / common / physics / movetypes / walk.qc
1 #include "walk.qh"
2 void _Movetype_Physics_Walk(entity this, float dt)  // SV_WalkMove
3 {
4         // if frametime is 0 (due to client sending the same timestamp twice), don't move
5         if (dt <= 0)
6                 return;
7
8         if (GAMEPLAYFIX_UNSTICKPLAYERS(this))
9                 _Movetype_CheckStuck(this);
10
11         bool applygravity = (!_Movetype_CheckWater(this) && this.move_movetype == MOVETYPE_WALK && !(this.flags & FL_WATERJUMP));
12
13         _Movetype_CheckVelocity(this);
14
15         // do a regular slide move unless it looks like you ran into a step
16         bool oldonground = IS_ONGROUND(this);
17
18         vector start_origin = this.origin;
19         vector start_velocity = this.velocity;
20
21         if(PHYS_WALLCLIP(this) && this.pm_time)
22         {
23                 if(dt >= this.pm_time || (this.flags & FL_WATERJUMP))
24                         this.pm_time = 0;
25                 else
26                         this.pm_time -= dt;
27         }
28
29         int clip = _Movetype_FlyMove(this, dt, applygravity, false, GAMEPLAYFIX_STEPMULTIPLETIMES(this) ? PHYS_STEPHEIGHT(this) : 0);
30
31         if (GAMEPLAYFIX_DOWNTRACEONGROUND(this) && !(clip & 1))
32         {
33                 // only try this if there was no floor in the way in the trace (no,
34                 // this check seems to be not REALLY necessary, because if clip & 1,
35                 // our trace will hit that thing too)
36                 vector upmove = this.origin + '0 0 1';
37                 vector downmove = this.origin - '0 0 1';
38                 int type;
39                 if (this.move_movetype == MOVETYPE_FLYMISSILE)
40                         type = MOVE_MISSILE;
41                 else if (this.move_movetype == MOVETYPE_FLY_WORLDONLY)
42                         type = MOVE_WORLDONLY;
43                 else if (this.solid == SOLID_TRIGGER || this.solid == SOLID_NOT)
44                         type = MOVE_NOMONSTERS;
45                 else type = MOVE_NORMAL;
46                 tracebox(upmove, this.mins, this.maxs, downmove, type, this);
47                 if (trace_fraction < 1 && trace_plane_normal.z > 0.7)
48                         clip |= 1;  // but we HAVE found a floor
49         }
50
51         // if the move did not hit the ground at any point, we're not on ground
52         if (!(clip & 1))
53                 UNSET_ONGROUND(this);
54         else if(PHYS_WALLCLIP(this) && !this.groundentity && (PHYS_WALLCLIP(this) == 2 || start_velocity.z < -200)) // don't do landing time if we were just going down a slope
55                 this.pm_time = 0.25;
56
57         _Movetype_CheckVelocity(this);
58         _Movetype_LinkEdict(this, true);
59
60         if (clip & 8)  // teleport
61                 return;
62
63         if (this.flags & FL_WATERJUMP)
64                 return;
65
66         if (PHYS_NOSTEP(this))
67                 return;
68
69         vector originalorigin = this.origin;
70         vector originalvelocity = this.velocity;
71         // originalmove_clip = clip;
72         int originalflags = this.flags;
73         entity originalmove_groundentity = this.groundentity;
74
75         // if move didn't block on a step, return
76         if (clip & 2)
77         {
78                 // if move was not trying to move into the step, return
79                 if (fabs(start_velocity.x) < 0.03125 && fabs(start_velocity.y) < 0.03125)
80                         return;
81
82                 if (this.move_movetype != MOVETYPE_FLY)
83                 {
84                         // return if gibbed by a trigger
85                         if (this.move_movetype != MOVETYPE_WALK)
86                                 return;
87
88                         // return if attempting to jump while airborn (unless sv_jumpstep)
89                         if (!PHYS_JUMPSTEP(this))
90                                 if (!oldonground && this.waterlevel == 0)
91                                         return;
92                 }
93
94                 // try moving up and forward to go up a step
95                 // back to start pos
96                 this.origin = start_origin;
97                 this.velocity = start_velocity;
98
99                 // move up
100                 vector upmove = '0 0 1' * PHYS_STEPHEIGHT(this);
101                 if(!_Movetype_PushEntity(this, upmove, true, true))
102                 {
103                         // we got teleported when upstepping... must abort the move
104                         return;
105                 }
106
107                 // move forward
108                 this.velocity_z = 0;
109                 clip = _Movetype_FlyMove(this, dt, applygravity, true, 0);
110                 this.velocity_z += start_velocity.z;
111                 if (clip & 8)
112                 {
113                         // we got teleported when upstepping... must abort the move
114                         // note that z velocity handling may not be what QC expects here, but we cannot help it
115                         return;
116                 }
117
118                 _Movetype_CheckVelocity(this);
119                 _Movetype_LinkEdict(this, true);
120
121                 // check for stuckness, possibly due to the limited precision of floats
122                 // in the clipping hulls
123                 if (clip
124                     && fabs(originalorigin.y - this.origin.y) < 0.03125
125                     && fabs(originalorigin.x - this.origin.x) < 0.03125)
126                 {
127                         // Con_Printf("wall\n");
128                         // stepping up didn't make any progress, revert to original move
129                         this.origin = originalorigin;
130                         this.velocity = originalvelocity;
131                         // clip = originalmove_clip;
132                         this.flags = originalflags;
133                         this.groundentity = originalmove_groundentity;
134                         // now try to unstick if needed
135                         // clip = SV_TryUnstick (ent, oldvel);
136                         return;
137                 }
138
139                 // Con_Printf("step - ");
140
141                 // extra friction based on view angle
142                 if ((clip & 2) && PHYS_WALLFRICTION(this))
143                         _Movetype_WallFriction(this, move_stepnormal);
144         }
145         // don't do the down move if stepdown is disabled, moving upward, not in water, or the move started offground or ended onground
146         else if (!GAMEPLAYFIX_STEPDOWN(this) || this.waterlevel >= 3 || start_velocity.z >= (1.0 / 32.0) || !oldonground || IS_ONGROUND(this))
147         {
148                 return;
149         }
150
151         // move down
152         vector downmove = '0 0 0';
153         downmove.z = -PHYS_STEPHEIGHT(this) + start_velocity.z * dt;
154         if(!_Movetype_PushEntity(this, downmove, true, true))
155         {
156                 // we got teleported when downstepping... must abort the move
157                 return;
158         }
159
160         if (trace_fraction < 1 && trace_plane_normal.z > 0.7)
161         {
162                 // this has been disabled so that you can't jump when you are stepping
163                 // up while already jumping (also known as the Quake2 double jump bug)
164                 // LordHavoc: disabled this check so you can walk on monsters/players
165                 //if (PRVM_serveredictfloat(ent, solid) == SOLID_BSP)
166                 if(GAMEPLAYFIX_STEPDOWN(this) == 2)
167                 {
168                         SET_ONGROUND(this);
169                         this.groundentity = trace_ent;
170                 }
171         }
172         else
173         {
174                 // Con_Printf("slope\n");
175                 // if the push down didn't end up on good ground, use the move without
176                 // the step up.  This happens near wall / slope combinations, and can
177                 // cause the player to hop up higher on a slope too steep to climb
178                 this.origin = originalorigin;
179                 this.velocity = originalvelocity;
180                 this.flags = originalflags;
181                 this.groundentity = originalmove_groundentity;
182         }
183
184         _Movetype_CheckVelocity(this);
185         _Movetype_LinkEdict(this, true);
186 }