]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/client/movetypes.qc
the next batch of weapons using the new projectile code: grenade launcher, electro...
[divverent/nexuiz.git] / data / qcsrc / client / movetypes.qc
1 .entity move_groundentity;
2 .float move_suspendedinair;
3 .float move_didgravity;
4
5 void _Movetype_CheckVelocity() // SV_CheckVelocity
6 {
7 }
8
9 float _Movetype_CheckWater() // SV_CheckWater
10 {
11         return FALSE;
12 }
13
14 void _Movetype_CheckWaterTransition() // SV_CheckWaterTransition
15 {
16 }
17
18 void _Movetype_Impact(entity oth) // SV_Impact
19 {
20         if(self.move_moveflags & MOVEFLAG_STOPONIMPACT)
21         {
22                 // don't CLIP the velocity, but stop ENTIRELY
23                 self.velocity = '0 0 0';
24                 self.avelocity = '0 0 0';
25         }
26 }
27
28 void _Movetype_LinkEdict(float touch_triggers) // SV_LinkEdict
29 {
30 }
31
32 float _Movetype_TestEntityPosition(vector ofs) // SV_TestEntityPosition
33 {
34         vector org;
35         float cont;
36         org = self.move_origin + ofs;
37         
38         cont = self.dphitcontentsmask;
39         self.dphitcontentsmask = DPCONTENTS_SOLID;
40         tracebox(self.move_origin, self.mins, self.maxs, self.move_origin, MOVE_NOMONSTERS, self);
41         self.dphitcontentsmask = cont;
42
43         if(trace_startsolid)
44                 return TRUE;
45
46         if(vlen(trace_endpos - self.move_origin) > 0.0001)
47                 self.move_origin = trace_endpos;
48         return FALSE;
49 }
50
51 float _Movetype_UnstickEntity() // SV_UnstickEntity
52 {
53         if(!_Movetype_TestEntityPosition('0 0 0'))
54                 return TRUE;
55         if(!_Movetype_TestEntityPosition('-1 0 0')) goto success;
56         if(!_Movetype_TestEntityPosition('1 0 0')) goto success;
57         if(!_Movetype_TestEntityPosition('0 -1 0')) goto success;
58         if(!_Movetype_TestEntityPosition('0 1 0')) goto success;
59         if(!_Movetype_TestEntityPosition('-1 -1 0')) goto success;
60         if(!_Movetype_TestEntityPosition('1 -1 0')) goto success;
61         if(!_Movetype_TestEntityPosition('-1 1 0')) goto success;
62         if(!_Movetype_TestEntityPosition('1 1 0')) goto success;
63         float i;
64         for(i = 1; i <= 17; ++i)
65         {
66                 if(!_Movetype_TestEntityPosition('0 0 -1' * i)) goto success;
67                 if(!_Movetype_TestEntityPosition('0 0 1' * i)) goto success;
68         }
69         dprint("Some entity is stuck\n");
70         return FALSE;
71 :success
72         dprint("Unstuck some entity\n");
73         _Movetype_LinkEdict(TRUE);
74         return TRUE;
75 }
76
77 vector _Movetype_ClipVelocity(vector vel, vector norm, float f) // SV_ClipVelocity
78 {
79         vel = vel - ((vel * norm) * norm) * f;
80
81         if(vel_x > -0.1 && vel_x < 0.1) vel_x = 0;
82         if(vel_y > -0.1 && vel_y < 0.1) vel_y = 0;
83         if(vel_z > -0.1 && vel_z < 0.1) vel_z = 0;
84
85         return vel;
86 }
87
88 void _Movetype_PushEntityTrace(vector push)
89 {
90         vector end;
91         float type;
92
93         end = self.move_origin + push;
94
95         if(self.move_movetype == MOVETYPE_FLYMISSILE)
96                 type = MOVE_MISSILE;
97         else if(self.solid == SOLID_TRIGGER || self.solid == SOLID_NOT)
98                 type = MOVE_NOMONSTERS;
99         else
100                 type = MOVE_NORMAL;
101
102         tracebox(self.move_origin, self.mins, self.maxs, end, type, self);
103 }
104
105 float _Movetype_PushEntity(vector push, float failonstartsolid) // SV_PushEntity
106 {
107         _Movetype_PushEntityTrace(push);
108
109         if(trace_startsolid && failonstartsolid)
110                 return trace_fraction;
111
112         self.move_origin = trace_endpos;
113
114         if(self.solid >= SOLID_TRIGGER && trace_ent && (!(self.move_flags & FL_ONGROUND) || (self.move_groundentity != trace_ent)))
115                 _Movetype_Impact(trace_ent);
116
117         return trace_fraction;
118 }
119
120 void _Movetype_Physics_Toss(float dt) // SV_Physics_Toss
121 {
122         if(self.move_flags & FL_ONGROUND)
123         {
124                 if(self.velocity_z >= 1/32)
125                         self.move_flags &~= FL_ONGROUND;
126                 else if(!self.move_groundentity)
127                         return;
128                 else if(self.move_suspendedinair && wasfreed(self.move_groundentity))
129                 {
130                         self.move_groundentity = world;
131                         return;
132                 }
133         }
134
135         self.move_suspendedinair = FALSE;
136
137         _Movetype_CheckVelocity();
138
139         if(self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS)
140         {
141                 self.move_didgravity = TRUE;
142                 self.move_velocity_z -= dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);
143         }
144
145         self.move_angles = self.move_angles + self.move_avelocity * dt;
146
147         vector move;
148         move = self.move_velocity * dt;
149
150         _Movetype_PushEntity(move, TRUE);
151         if(wasfreed(self))
152                 return;
153         
154         if(trace_startsolid)
155         {
156                 _Movetype_UnstickEntity();
157                 _Movetype_PushEntity(move, FALSE);
158                 if(wasfreed(self))
159                         return;
160         }
161
162         if(trace_fraction < 1)
163         {
164                 if(self.move_movetype == MOVETYPE_BOUNCEMISSILE)
165                 {
166                         self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 2.0);
167                         self.move_flags &~= FL_ONGROUND;
168                 }
169                 else if(self.move_movetype == MOVETYPE_BOUNCE)
170                 {
171                         self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 1.5);
172
173                         float d;
174                         d = trace_plane_normal * self.move_velocity;
175                         if(trace_plane_normal_z > 0.7 && d < 60 && d > -60)
176                         {
177                                 self.move_flags |= FL_ONGROUND;
178                                 self.move_groundentity = trace_ent;
179                                 self.move_velocity = '0 0 0';
180                                 self.move_avelocity = '0 0 0';
181                         }
182                         else
183                                 self.move_flags &~= FL_ONGROUND;
184                 }
185                 else
186                 {
187                         self.move_velocity = _Movetype_ClipVelocity(self.move_velocity, trace_plane_normal, 1.0);
188                         if(trace_plane_normal_z > 0.7)
189                         {
190                                 self.move_flags |= FL_ONGROUND;
191                                 self.move_groundentity = trace_ent;
192                                 if(trace_ent.solid == SOLID_BSP)
193                                         self.move_suspendedinair = TRUE;
194                                 self.move_velocity = '0 0 0';
195                                 self.move_avelocity = '0 0 0';
196                         }
197                         else
198                                 self.move_flags &~= FL_ONGROUND;
199                 }
200         }
201
202         _Movetype_CheckWaterTransition();
203 }
204
205 void Movetype_Physics(float matchserver) // SV_Physics_Entity
206 {
207         float n, i, dt, movedt;
208
209         dt = time - self.move_time;
210
211         if(matchserver)
212         {
213                 movedt = ticrate;
214                 n = max(0, floor(dt / ticrate));
215                 dt -= n * ticrate;
216                 self.move_time += n * ticrate;
217         }
218         else
219         {
220                 movedt = dt;
221                 dt = 0;
222                 n = 1;
223                 self.move_time = time;
224         }
225
226         //self.move_didgravity = ((self.move_movetype == MOVETYPE_BOUNCE || self.move_movetype == MOVETYPE_TOSS) && !(self.move_flags & FL_ONGROUND));
227         // we use the field as set by the last run of this
228
229         for(i = 0; i < n; ++i)
230         {
231                 self.move_didgravity = FALSE;
232                 switch(self.move_movetype)
233                 {
234                         case MOVETYPE_PUSH:
235                         case MOVETYPE_FAKEPUSH:
236                                 error("SV_Physics_Pusher not implemented");
237                                 break;
238                         case MOVETYPE_NONE:
239                                 break;
240                         case MOVETYPE_FOLLOW:
241                                 error("SV_Physics_Follow not implemented");
242                                 break;
243                         case MOVETYPE_NOCLIP:
244                                 _Movetype_CheckWater();
245                                 self.move_origin = self.move_origin + ticrate * self.move_velocity;
246                                 self.move_angles = self.move_angles + ticrate * self.move_avelocity;
247                                 _Movetype_LinkEdict(FALSE);
248                                 break;
249                         case MOVETYPE_STEP:
250                                 error("SV_Physics_Step not implemented");
251                                 break;
252                         case MOVETYPE_WALK:
253                                 error("SV_Physics_Walk not implemented");
254                                 break;
255                         case MOVETYPE_TOSS:
256                         case MOVETYPE_BOUNCE:
257                         case MOVETYPE_BOUNCEMISSILE:
258                         case MOVETYPE_FLYMISSILE:
259                         case MOVETYPE_FLY:
260                                 _Movetype_Physics_Toss(movedt);
261                                 break;
262                 }
263         }
264
265         self.avelocity = self.move_avelocity;
266
267         if(dt > 0)
268         {
269                 // now continue the move from move_time to time
270                 self.velocity = self.move_velocity;
271                 if(self.move_didgravity)
272                         self.velocity_z -= dt * self.gravity * getstatf(STAT_MOVEVARS_GRAVITY);
273
274                 self.angles = self.move_angles + dt * self.avelocity;
275
276                 if(self.movetype != MOVETYPE_NOCLIP)
277                 {
278                         _Movetype_PushEntityTrace(dt * self.velocity);
279                         if(!trace_startsolid)
280                                 self.origin = trace_endpos;
281                 }
282                 else
283                         self.origin = self.move_origin + dt * self.velocity;
284         }
285         else
286         {
287                 self.velocity = self.move_velocity;
288                 self.angles = self.move_angles;
289                 self.origin = self.move_origin;
290         }
291 }