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