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