]> icculus.org git repositories - divverent/nexuiz.git/blob - data/qcsrc/server/cl_impulse.qc
put the Port-O-Launch on impulse 14 (key 0)
[divverent/nexuiz.git] / data / qcsrc / server / cl_impulse.qc
1 .vector personal_v_angle; // view angles to restore on impulse 77
2 .vector personal_velocity; // velocity to restore on impulse 77
3
4 void CopyBody(float keepvelocity);
5
6 // changes by LordHavoc on 03/30/04
7 // cleaned up dummy code
8 // dummies are now removed eventually after being gibbed (norespawn = TRUE)
9 // dummy impulse now checks sv_cheats to prevent players from overwhelming server with dummies
10 // dummies now use player code where possible
11
12 void player_anim (void);
13 void DummyThink(void)
14 {
15         self.think = DummyThink;
16         self.nextthink = time;
17         SV_PlayerPhysics();
18         PlayerPreThink();
19         //player_anim();
20         PlayerPostThink();
21 }
22
23 // from dpmod
24 void printsurfaceinfo(entity e, vector v)
25 {
26         local float surfnum, numpoints, vnum;
27         local string s;
28         local vector n;
29         surfnum = getsurfacenearpoint(e, v);
30         if (surfnum >= 0)
31         {
32                 sprint(self, "texture: ");
33                 s = getsurfacetexture(e, surfnum);
34                 sprint(self, s);
35                 sprint(self, " normal: ");
36                 n = getsurfacenormal(e, surfnum);
37                 sprint(self, vtos(n));
38                 sprint(self, " ");
39                 numpoints = getsurfacenumpoints(e, surfnum);
40                 sprint(self, ftos(numpoints));
41                 sprint(self, " verts:");
42                 vnum = 0;
43                 while (vnum < numpoints)
44                 {
45                         sprint(self, " ");
46                         n = getsurfacepoint(e, surfnum, vnum);
47                         sprint(self, vtos(n));
48                         vnum = vnum + 1;
49                 }
50                 sprint(self, " point tested: ");
51                 sprint(self, vtos(v));
52                 sprint(self, " nearest point on surface: ");
53                 n = getsurfaceclippedpoint(e, surfnum, v);
54                 sprint(self, vtos(n));
55                 sprint(self, "\n");
56         }
57 };
58
59 /*
60  * Impulse map:
61  *
62  * 0 reserved (no input)
63  * 1 to 9: weapon shortcuts
64  * 10: next weapon
65  * 11: most recently used weapon
66  * 12: previous weapon
67  * 13: best weapon
68  * 17: throw weapon
69  *
70  * 30 to 39: create waypoints
71  * 47: clear personal waypoints
72  * 48: clear team waypoints
73  * 49: turn base waypoints on/off
74  *
75  * 99: loaded
76  *
77  * 140: moving clone
78  * 141: ctf speedrun
79  * 142: fixed clone
80  * 143: emergency teleport
81  * 144: printsurfaceinfo
82  * 145: distance
83  *
84  * TODO:
85  * 200 to 209: prev weapon shortcuts
86  * 210 to 219: best weapon shortcuts
87  * 220 to 229: next weapon shortcuts
88  * 230 to 253: individual weapons (up to 24)
89  */
90
91 void ImpulseCommands (void)
92 {
93         local float imp;
94         vector start, end, enddown;
95         float i;
96         float m;
97         float good, evil, evilsurf;
98         float maxattempts;
99         vector org, delta;
100         float wep;
101         entity e;
102
103         imp = self.impulse;
104         if (!imp || gameover)
105                 return;
106         self.impulse = 0;
107
108         if (timeoutStatus == 2) //don't allow any impulses while the game is paused
109                 return;
110
111         if (imp >= 1 && imp <= 9)
112         {
113                 // weapon switching impulses
114                 if(self.deadflag == DEAD_NO)
115                         W_NextWeaponOnImpulse(imp);
116                 else
117                         self.impulse = imp; // retry in next frame
118         }
119         else if(imp >= 10 && imp <= 17)
120         {
121                 if(self.deadflag == DEAD_NO)
122                 {
123                         switch(imp)
124                         {
125                                 case 10:
126                                         W_NextWeapon ();
127                                         break;
128                                 case 11:
129                                         W_SwitchWeapon (self.cnt); // previously used
130                                         break;
131                                 case 12:
132                                         W_PreviousWeapon ();
133                                         break;
134                                 case 13:
135                                         W_SwitchWeapon (w_getbestweapon(self));
136                                         break;
137                                 case 14:
138                                         W_NextWeaponOnImpulse(0);
139                                         break;
140                                 case 17:
141                                         if (!g_minstagib)
142                                                 W_ThrowWeapon(W_CalculateProjectileVelocity(self.velocity, v_forward * 750), '0 0 0', TRUE);
143                                         break;
144                                 }
145                 }
146                 else
147                         self.impulse = imp; // retry in next frame
148         }
149         else if(imp >= 200 && imp <= 229)
150         {
151                 if(self.deadflag == DEAD_NO)
152                 {
153                         // custom order weapon cycling
154                         i = mod(imp, 10);
155                         m = (imp - (210 + i)); // <0 for prev, =0 for best, >0 for next
156                         W_CycleWeapon(self.(cvar_cl_weaponpriorities[i]), m);
157                 }
158                 else
159                         self.impulse = imp; // retry in next frame
160         }
161         else if(imp >= 230 && imp <= 253)
162         {
163                 if(self.deadflag == DEAD_NO)
164                         W_SwitchWeapon (imp - 230 + WEP_FIRST);
165                 else
166                         self.impulse = imp; // retry in next frame
167         }
168         // deploy waypoints
169         else if (imp >= 30 && imp <= 49)
170         {
171                 switch(imp)
172                 {
173                         case 30:
174                                 WaypointSprite_DeployPersonal("waypoint", self.origin);
175                                 self.personal_v_angle = self.v_angle;
176                                 self.personal_velocity = self.velocity;
177                                 sprint(self, "personal waypoint spawned at location\n");
178                                 break;
179                         case 31:
180                                 WaypointSprite_DeployPersonal("waypoint", self.cursor_trace_endpos);
181                                 self.personal_v_angle = self.v_angle;
182                                 self.personal_velocity = '0 0 0';
183                                 sprint(self, "personal waypoint spawned at crosshair\n");
184                                 break;
185                         case 32:
186                                 if(vlen(self.death_origin))
187                                 {
188                                         WaypointSprite_DeployPersonal("waypoint", self.death_origin);
189                                         self.personal_v_angle = self.v_angle;
190                                         self.personal_velocity = '0 0 0';
191                                         sprint(self, "personal waypoint spawned at death location\n");
192                                 }
193                                 break;
194                         case 33:
195                                 if(self.deadflag == DEAD_NO && teams_matter)
196                                 {
197                                         WaypointSprite_Attach("helpme", TRUE);
198                                         sprint(self, "HELP ME attached\n");
199                                 }
200                                 break;
201                         case 34:
202                                 WaypointSprite_DeployFixed("here", FALSE, self.origin);
203                                 sprint(self, "HERE spawned at location\n");
204                                 break;
205                         case 35:
206                                 WaypointSprite_DeployFixed("here", FALSE, self.cursor_trace_endpos);
207                                 sprint(self, "HERE spawned at crosshair\n");
208                                 break;
209                         case 36:
210                                 if(vlen(self.death_origin))
211                                 {
212                                         WaypointSprite_DeployFixed("here", FALSE, self.death_origin);
213                                         sprint(self, "HERE spawned at death location\n");
214                                 }
215                                 break;
216                         case 37:
217                                 WaypointSprite_DeployFixed("danger", FALSE, self.origin);
218                                 sprint(self, "DANGER spawned at location\n");
219                                 break;
220                         case 38:
221                                 WaypointSprite_DeployFixed("danger", FALSE, self.cursor_trace_endpos);
222                                 sprint(self, "DANGER spawned at crosshair\n");
223                                 break;
224                         case 39:
225                                 if(vlen(self.death_origin))
226                                 {
227                                         WaypointSprite_DeployFixed("danger", FALSE, self.death_origin);
228                                         sprint(self, "DANGER spawned at death location\n");
229                                 }
230                                 break;
231                         case 47:
232                                 WaypointSprite_ClearPersonal();
233                                 sprint(self, "personal waypoint cleared\n");
234                                 break;
235                         case 48:
236                                 WaypointSprite_ClearOwned();
237                                 sprint(self, "all waypoints cleared\n");
238                                 break;
239                         case 49:
240                                 self.cvar_cl_hidewaypoints = !(self.cvar_cl_hidewaypoints);
241                                 sprint(self, "fixed waypoints now ");
242                                 if(self.cvar_cl_hidewaypoints)
243                                         sprint(self, "OFF\n");
244                                 else
245                                         sprint(self, "ON\n");
246                                 break;
247                 }
248         }
249         else if(imp >= 140 && imp <= 149 || imp == 99) // 10 cheats ought to be enough for anyone
250         {
251                 if(sv_cheats)
252                 if(self.deadflag == DEAD_NO)
253                 {
254                         switch(imp)
255                         {
256                                 case 99:
257                                         self.weapons |= WEPBIT_ALL;
258                                         self.ammo_shells = g_pickup_shells_max;
259                                         self.ammo_nails = g_pickup_nails_max;
260                                         self.ammo_rockets = g_pickup_rockets_max;
261                                         self.ammo_cells = g_pickup_cells_max;
262                                         self.health = g_pickup_healthsmall_max;
263                                         self.armorvalue = g_pickup_armorsmall_max;
264                                         self.pauserotarmor_finished = time + cvar("g_balance_pause_armor_rot_spawn");
265                                         self.pauserothealth_finished = time + cvar("g_balance_pause_health_rot_spawn");
266                                         self.pauseregen_finished = time + cvar("g_balance_pause_health_regen_spawn");
267                                         // precache weapon models/sounds
268                                         wep = WEP_FIRST;
269                                         while (wep <= WEP_LAST)
270                                         {
271                                                 weapon_action(wep, WR_PRECACHE);
272                                                 wep = wep + 1;
273                                         }
274                                         break;
275                                 case 140:
276                                         makevectors (self.v_angle);
277                                         self.velocity = self.velocity + v_forward * 300;
278                                         CopyBody(1);
279                                         self.lip += 1;
280                                         self.velocity = self.velocity - v_forward * 300;
281                                         break;
282                                 case 141:
283                                         if(self.waypointsprite_deployed_personal)
284                                         {
285                                                 self.speedrunning = TRUE;
286                                                 tracebox(self.waypointsprite_deployed_personal.origin, self.mins, self.maxs, self.waypointsprite_deployed_personal.origin, MOVE_WORLDONLY, self);
287                                                 if(trace_startsolid)
288                                                 {
289                                                         sprint(self, "Cannot move there, cheater - only waypoints set using g_waypointsprite_personal work\n");
290                                                 }
291                                                 else
292                                                 {
293                                                         // Abort speedrun, teleport back
294                                                         setorigin(self, self.waypointsprite_deployed_personal.origin);
295                                                         self.oldvelocity = self.velocity = self.personal_velocity;
296                                                         self.angles = self.personal_v_angle;
297                                                         self.fixangle = TRUE;
298                                                         if(self.flagcarried)
299                                                         {
300                                                                 bprint("The ", self.flagcarried.netname, " was returned to base by its carrier\n");
301                                                                 ReturnFlag(self.flagcarried);
302                                                         }
303                                                 }
304                                                 self.ammo_rockets = 999;
305                                                 self.ammo_nails = 999;
306                                                 self.ammo_cells = 999;
307                                                 self.ammo_shells = 999;
308                                                 self.health = start_health;
309                                                 self.armorvalue = start_armorvalue;
310                                                 self.weapons |= weaponsInMap;
311                                                 self.pauserotarmor_finished = time + cvar("g_balance_pause_armor_rot_spawn");
312                                                 self.pauserothealth_finished = time + cvar("g_balance_pause_health_rot_spawn");
313                                                 self.pauseregen_finished = time + cvar("g_balance_pause_health_regen_spawn");
314                                         }
315                                         else if(self.deadflag != DEAD_NO)
316                                                 sprint(self, "UR DEAD AHAHAH))\n");
317                                         else
318                                                 sprint(self, "No waypoint set, cheater (use g_waypointsprite_personal to set one)\n");
319                                         break;
320                                 case 142:
321                                         CopyBody(0);
322                                         self.lip += 1;
323                                         break;
324                                 case 143:
325                                         good = DPCONTENTS_SOLID | DPCONTENTS_CORPSE | DPCONTENTS_PLAYERCLIP;
326                                         evil = DPCONTENTS_SLIME | DPCONTENTS_LAVA | DPCONTENTS_SKY | DPCONTENTS_BODY | DPCONTENTS_DONOTENTER;
327                                         evilsurf = Q3SURFACEFLAG_SKY;
328
329                                         m = self.dphitcontentsmask;
330                                         self.dphitcontentsmask = good | evil;
331
332                                         org = world.mins;
333                                         delta = world.maxs - world.mins;
334
335                                         maxattempts = ((sv_cheats >= 2) ? 100000 : 100);
336
337                                         for(i = 0; i < maxattempts; ++i)
338                                         {
339                                                 start_x = org_x + random() * delta_x;
340                                                 start_y = org_y + random() * delta_y;
341                                                 start_z = org_z + random() * delta_z;
342
343                                                 // rule 1: start inside world bounds, and outside
344                                                 // solid, and don't start from somewhere where you can
345                                                 // fall down to evil
346                                                 tracebox(start, self.mins, self.maxs, start - '0 0 1' * delta_z, MOVE_NORMAL, self);
347                                                 if(trace_fraction >= 1)
348                                                         continue;
349                                                 if(trace_startsolid)
350                                                         continue;
351                                                 dprint("hit contents ", ftos(trace_dphitcontents), "\n");
352                                                 if(trace_dphitcontents & evil)
353                                                         continue;
354                                                 if(trace_dphitq3surfaceflags & evilsurf)
355                                                         continue;
356
357                                                 // rule 2: if we are too high, lower the point
358                                                 if(trace_fraction * delta_z > 1024)
359                                                         start = trace_endpos + '0 0 1024';
360                                                 enddown = trace_endpos;
361
362                                                 // these can be traceLINES as we already verified the starting box
363                                                 traceline(start, start + '1 0 0' * delta_x, MOVE_NORMAL, self);
364                                                 if(trace_fraction >= 1)
365                                                         continue;
366                                                 traceline(start, start - '1 0 0' * delta_x, MOVE_NORMAL, self);
367                                                 if(trace_fraction >= 1)
368                                                         continue;
369                                                 traceline(start, start + '0 1 0' * delta_y, MOVE_NORMAL, self);
370                                                 if(trace_fraction >= 1)
371                                                         continue;
372                                                 traceline(start, start - '0 1 0' * delta_y, MOVE_NORMAL, self);
373                                                 if(trace_fraction >= 1)
374                                                         continue;
375                                                 traceline(start, start + '0 0 1' * delta_z, MOVE_NORMAL, self);
376                                                 if(trace_fraction >= 1)
377                                                         continue;
378
379                                                 end_x = org_x + random() * delta_x;
380                                                 end_y = org_y + random() * delta_y;
381                                                 end_z = org_z + random() * delta_z;
382                                                 end = start + normalize(end - start) * vlen(delta);
383
384                                                 // rule 3: start TO end must not be too short
385                                                 tracebox(start, self.mins, self.maxs, end, MOVE_NORMAL, self);
386                                                 if(trace_startsolid)
387                                                         continue;
388                                                 if(trace_fraction < 256 / vlen(delta))
389                                                         continue;
390
391                                                 // rule 4: don't want to look at sky
392                                                 if(trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
393                                                         continue;
394
395                                                 // rule 5: we must not end up in trigger_hurt
396                                                 if(tracebox_hits_trigger_hurt(start, self.mins, self.maxs, enddown))
397                                                 {
398                                                         dprint("trigger_hurt! ouch! and nothing else could find it!\n");
399                                                         continue;
400                                                 }
401
402                                                 break;
403                                         }
404
405                                         if(i < maxattempts)
406                                         {
407                                                 self.origin = start;
408                                                 self.angles = vectoangles(end - start);
409                                                 self.angles_x = -self.angles_x;
410                                                 self.fixangle = TRUE;
411                                                 self.velocity = '0 0 0';
412                                                 dprint("Needed ", ftos(i + 1), " attempts\n");
413                                         }
414                                         else
415                                                 sprint(self, "Emergency teleport could not find a good location, forget it!\n");
416
417                                         self.dphitcontentsmask = m;
418                                         break;
419                                 case 144:
420                                         makevectors(self.v_angle);
421                                         traceline(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * MAX_SHOT_DISTANCE, FALSE, self);
422                                         if (trace_fraction < 1)
423                                                 printsurfaceinfo(trace_ent, trace_endpos);
424                                         break;
425                                 case 145:
426                                         makevectors(self.v_angle);
427                                         traceline(self.origin + self.view_ofs, self.origin + self.view_ofs + v_forward * 65536, FALSE, self);
428                                         sprint(self, strcat("distance: ", ftos(fabs(vlen(trace_endpos - (self.origin + self.view_ofs)))), "\n"));
429                                         break;
430                         }
431                 }
432         }
433         else if(imp >= 103 && imp <= 106)
434         {
435                 if(cvar("g_waypointeditor"))
436                 {
437                         switch(imp)
438                         {
439                                 case 103:
440                                         waypoint_schedulerelink(waypoint_spawn(self.origin, self.origin, 0));
441                                         break;
442                                 case 104:
443                                         e = navigation_findnearestwaypoint(self, FALSE);
444                                         if (e)
445                                                 waypoint_remove(e);
446                                         break;
447                                 case 105:
448                                         waypoint_schedulerelinkall();
449                                         break;
450                                 case 106:
451                                         waypoint_saveall();
452                                         break;
453                         }
454                 }
455         }
456
457         //TetrisImpulses(imp);
458 }