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