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