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