]> git.xonotic.org Git - xonotic/xonotic-data.pk3dir.git/blob - qcsrc/server/cl_impulse.qc
Merge branch 'master' into TimePath/items
[xonotic/xonotic-data.pk3dir.git] / qcsrc / server / cl_impulse.qc
1 #include "round_handler.qh"
2
3 #include "bot/waypoints.qh"
4
5 #include "weapons/throwing.qh"
6 #include "command/common.qh"
7 #include "cheats.qh"
8 #include "bot/navigation.qh"
9 #include "weapons/selection.qh"
10 #include "weapons/tracing.qh"
11 #include "weapons/weaponsystem.qh"
12
13 #include "../common/minigames/sv_minigames.qh"
14
15 #include "../common/weapons/all.qh"
16 #include "../common/vehicles/sv_vehicles.qh"
17
18 #include "../common/mutators/mutator/waypoints/waypointsprites.qh"
19
20 .entity vehicle;
21
22 /**
23  * Impulse map:
24  *
25  * 0 reserved (no input)
26  * 1 to 9, 14: weapon shortcuts
27  * 10: next weapon according to linear list
28  * 11: most recently used weapon
29  * 12: previous weapon according to linear list
30  * 13: best weapon according to priority list
31  * 15: next weapon according to priority list
32  * 16: previous weapon according to priority list
33  * 17: throw weapon
34  * 18: next weapon according to sbar_hudselector 1 list
35  * 19: previous weapon according to sbar_hudselector 1 list
36  * 20: reload if needed
37  *
38  * 30 to 39: create waypoints
39  * 47: clear personal waypoints
40  * 48: clear team waypoints
41  *
42  * 99: loaded
43  *
44  * 140: moving clone
45  * 141: ctf speedrun
46  * 142: fixed clone
47  * 143: emergency teleport
48  * 148: unfairly eliminate
49  *
50  * TODO:
51  * 200 to 209: prev weapon shortcuts
52  * 210 to 219: best weapon shortcuts
53  * 220 to 229: next weapon shortcuts
54  * 230 to 253: individual weapons (up to 24)
55  */
56
57 void ImpulseCommands (void)
58 {SELFPARAM();
59         int imp;
60         vector org;
61         float i;
62         float m;
63         entity e, e2;
64
65         imp = self.impulse;
66         if (!imp || gameover)
67                 return;
68         self.impulse = 0;
69
70         if ( self.active_minigame )
71         if ( MinigameImpulse(imp) )
72                 return;
73
74         // allow only weapon change impulses when not in round time
75         if(round_handler_IsActive() && !round_handler_IsRoundStarted())
76         if(imp == 17 || (imp >= 20 && imp < 200) || imp > 253)
77                 return;
78
79         if (timeout_status == TIMEOUT_ACTIVE) //don't allow any impulses while the game is paused
80                 return;
81
82         if(self.vehicle)
83         if(self.vehicle.deadflag == DEAD_NO)
84         {
85                 if(self.vehicle.vehicles_impulse)
86                 if(self.vehicle.vehicles_impulse(imp))
87                         return;
88                 if(vehicle_impulse(imp))
89                         return;
90         }
91
92         if(CheatImpulse(imp))
93         {
94         }
95         else if (imp >= 1 && imp <= 9)
96         {
97                 // weapon switching impulses
98                 if(self.deadflag == DEAD_NO)
99                         W_NextWeaponOnImpulse(imp);
100                 //else
101                 //      self.impulse = imp; // retry in next frame
102         }
103         else if(imp >= 10 && imp <= 20)
104         {
105                 if(!self.vehicle)
106                 if(self.deadflag == DEAD_NO)
107                 {
108                         switch(imp)
109                         {
110                                 case 10:
111                                         W_NextWeapon(0);
112                                         break;
113                                 case 11:
114                                         W_LastWeapon();
115                                         break;
116                                 case 12:
117                                         W_PreviousWeapon(0);
118                                         break;
119                                 case 13:
120                                         W_SwitchWeapon(w_getbestweapon(self));
121                                         break;
122                                 case 14:
123                                         W_NextWeaponOnImpulse(0);
124                                         break;
125                                 case 15:
126                                         W_NextWeapon(2);
127                                         break;
128                                 case 16:
129                                         W_PreviousWeapon(2);
130                                         break;
131                                 case 17:
132                                         W_ThrowWeapon(W_CalculateProjectileVelocity(self.velocity, v_forward * 750, false), '0 0 0', true);
133                                         break;
134                                 case 18:
135                                         W_NextWeapon(1);
136                                         break;
137                                 case 19:
138                                         W_PreviousWeapon(1);
139                                         break;
140                                 case 20:
141                                         if(!forbidWeaponUse(self)) {
142                                                 Weapon w = get_weaponinfo(self.weapon);
143                                                 w.wr_reload(w);
144                                         }
145                                         break;
146                         }
147                 }
148                 else
149                         self.impulse = imp; // retry in next frame
150         }
151         else if(imp == 21)
152         {
153                 PlayerUseKey ();
154         }
155         else if(imp >= 200 && imp <= 229)
156         {
157                 if(!self.vehicle)
158                 if(self.deadflag == DEAD_NO)
159                 {
160                         // custom order weapon cycling
161                         int i = imp % 10;
162                         m = (imp - (210 + i)); // <0 for prev, =0 for best, >0 for next
163                         W_CycleWeapon(self.(cvar_cl_weaponpriorities[i]), m);
164                 }
165                 else
166                         self.impulse = imp; // retry in next frame
167         }
168         else if(imp >= WEP_IMPULSE_BEGIN && imp <= WEP_IMPULSE_END)
169         {
170                 if(!self.vehicle)
171                 if(self.deadflag == DEAD_NO)
172                         W_SwitchWeapon (imp - WEP_IMPULSE_BEGIN + WEP_FIRST);
173                 else
174                         self.impulse = imp; // retry in next frame
175         }
176         // deploy waypoints
177         else if (imp >= 30 && imp <= 49)
178         {
179                 entity wp;
180                 switch(imp)
181                 {
182                         case 30:
183                                 wp = WaypointSprite_DeployPersonal(WP_Waypoint, self.origin, RADARICON_WAYPOINT);
184                                 if(wp)
185                                         WaypointSprite_Ping(wp);
186                                 sprint(self, "personal waypoint spawned at location\n");
187                                 break;
188                         case 31:
189                                 WarpZone_crosshair_trace(self);
190                                 wp = WaypointSprite_DeployPersonal(WP_Waypoint, trace_endpos, RADARICON_WAYPOINT);
191                                 if(wp)
192                                         WaypointSprite_Ping(wp);
193                                 sprint(self, "personal waypoint spawned at crosshair\n");
194                                 break;
195                         case 32:
196                                 if(vlen(self.death_origin))
197                                 {
198                                         wp = WaypointSprite_DeployPersonal(WP_Waypoint, self.death_origin, RADARICON_WAYPOINT);
199                                         if(wp)
200                                                 WaypointSprite_Ping(wp);
201                                         sprint(self, "personal waypoint spawned at death location\n");
202                                 }
203                                 break;
204                         case 33:
205                                 if(self.deadflag == DEAD_NO && teamplay)
206                                 {
207                                         if (!MUTATOR_CALLHOOK(HelpMePing, self))
208                                         {
209                                                 wp = WaypointSprite_Attach(WP_Helpme, true, RADARICON_HELPME);
210                                                 if(!wp)
211                                                         WaypointSprite_HelpMePing(self.waypointsprite_attachedforcarrier);
212                                                 else
213                                                         WaypointSprite_Ping(wp);
214                                         }
215                                         sprint(self, "HELP ME attached\n");
216                                 }
217                                 break;
218                         case 34:
219                                 wp = WaypointSprite_DeployFixed(WP_Here, false, self.origin, RADARICON_HERE);
220                                 if(wp)
221                                         WaypointSprite_Ping(wp);
222                                 sprint(self, "HERE spawned at location\n");
223                                 break;
224                         case 35:
225                                 WarpZone_crosshair_trace(self);
226                                 wp = WaypointSprite_DeployFixed(WP_Here, false, trace_endpos, RADARICON_HERE);
227                                 if(wp)
228                                         WaypointSprite_Ping(wp);
229                                 sprint(self, "HERE spawned at crosshair\n");
230                                 break;
231                         case 36:
232                                 if(vlen(self.death_origin))
233                                 {
234                                         wp = WaypointSprite_DeployFixed(WP_Here, false, self.death_origin, RADARICON_HERE);
235                                         if(wp)
236                                                 WaypointSprite_Ping(wp);
237                                         sprint(self, "HERE spawned at death location\n");
238                                 }
239                                 break;
240                         case 37:
241                                 wp = WaypointSprite_DeployFixed(WP_Danger, false, self.origin, RADARICON_DANGER);
242                                 if(wp)
243                                         WaypointSprite_Ping(wp);
244                                 sprint(self, "DANGER spawned at location\n");
245                                 break;
246                         case 38:
247                                 WarpZone_crosshair_trace(self);
248                                 wp = WaypointSprite_DeployFixed(WP_Danger, false, trace_endpos, RADARICON_DANGER);
249                                 if(wp)
250                                         WaypointSprite_Ping(wp);
251                                 sprint(self, "DANGER spawned at crosshair\n");
252                                 break;
253                         case 39:
254                                 if(vlen(self.death_origin))
255                                 {
256                                         wp = WaypointSprite_DeployFixed(WP_Danger, false, self.death_origin, RADARICON_DANGER);
257                                         if(wp)
258                                                 WaypointSprite_Ping(wp);
259                                         sprint(self, "DANGER spawned at death location\n");
260                                 }
261                                 break;
262                         case 47:
263                                 WaypointSprite_ClearPersonal();
264                                 if(self.personal)
265                                 {
266                                         remove(self.personal);
267                                         self.personal = world;
268                                 }
269                                 sprint(self, "personal waypoint cleared\n");
270                                 break;
271                         case 48:
272                                 WaypointSprite_ClearOwned();
273                                 if(self.personal)
274                                 {
275                                         remove(self.personal);
276                                         self.personal = world;
277                                 }
278                                 sprint(self, "all waypoints cleared\n");
279                                 break;
280                 }
281         }
282         else if(imp >= 103 && imp <= 107)
283         {
284                 if(autocvar_g_waypointeditor)
285                 {
286                         switch(imp)
287                         {
288                                 case 103:
289                                         waypoint_schedulerelink(waypoint_spawn(self.origin, self.origin, 0));
290                                         bprint(strcat("Waypoint spawned at ",vtos(self.origin),"\n"));
291                                         break;
292                                 case 104:
293                                         e = navigation_findnearestwaypoint(self, false);
294                                         if (e)
295                                         if (!(e.wpflags & WAYPOINTFLAG_GENERATED))
296                                         {
297                                                 bprint(strcat("Waypoint removed at ",vtos(e.origin),"\n"));
298                                                 waypoint_remove(e);
299                                         }
300                                         break;
301                                 case 105:
302                                         waypoint_schedulerelinkall();
303                                         break;
304                                 case 106:
305                                         waypoint_saveall();
306                                         break;
307                                 case 107:
308                                         for(e = findchain(classname, "waypoint"); e; e = e.chain)
309                                         {
310                                                 e.colormod = '0.5 0.5 0.5';
311                                                 e.effects &= ~(EF_NODEPTHTEST | EF_RED | EF_BLUE);
312                                         }
313                                         e2 = navigation_findnearestwaypoint(self, false);
314                                         navigation_markroutes(e2);
315                                         i = 0;
316                                         m = 0;
317                                         for(e = findchain(classname, "waypoint"); e; e = e.chain)
318                                         {
319                                                 if(e.wpcost >= 10000000)
320                                                 {
321                                                         LOG_INFO("unreachable: ", etos(e), " ", vtos(e.origin), "\n");
322                                                         e.colormod_z = 8;
323                                                         e.effects |= EF_NODEPTHTEST | EF_BLUE;
324                                                         ++i;
325                                                         ++m;
326                                                 }
327                                         }
328                                         if(i)
329                                                 LOG_INFO(ftos(i), " waypoints cannot be reached from here in any way (marked with blue light)\n");
330                                         navigation_markroutes_inverted(e2);
331                                         i = 0;
332                                         for(e = findchain(classname, "waypoint"); e; e = e.chain)
333                                         {
334                                                 if(e.wpcost >= 10000000)
335                                                 {
336                                                         LOG_INFO("cannot reach me: ", etos(e), " ", vtos(e.origin), "\n");
337                                                         e.colormod_x = 8;
338                                                         if(!(e.effects & EF_NODEPTHTEST)) // not already reported before
339                                                                 ++m;
340                                                         e.effects |= EF_NODEPTHTEST | EF_RED;
341                                                         ++i;
342                                                 }
343                                         }
344                                         if(i)
345                                                 LOG_INFO(ftos(i), " waypoints cannot walk to here in any way (marked with red light)\n");
346                                         if(m)
347                                                 LOG_INFO(ftos(m), " waypoints have been marked total\n");
348                                         i = 0;
349                                         for(e = findchain(classname, "info_player_deathmatch"); e; e = e.chain)
350                                         {
351                                                 org = e.origin;
352                                                 tracebox(e.origin, PL_MIN, PL_MAX, e.origin - '0 0 512', MOVE_NOMONSTERS, world);
353                                                 setorigin(e, trace_endpos);
354                                                 if(navigation_findnearestwaypoint(e, false))
355                                                 {
356                                                         setorigin(e, org);
357                                                         e.effects &= ~EF_NODEPTHTEST;
358                                                         e.model = "";
359                                                 }
360                                                 else
361                                                 {
362                                                         setorigin(e, org);
363                                                         LOG_INFO("spawn without waypoint: ", etos(e), " ", vtos(e.origin), "\n");
364                                                         e.effects |= EF_NODEPTHTEST;
365                                                         _setmodel(e, self.model);
366                                                         e.frame = self.frame;
367                                                         e.skin = self.skin;
368                                                         e.colormod = '8 0.5 8';
369                                                         setsize(e, '0 0 0', '0 0 0');
370                                                         ++i;
371                                                 }
372                                         }
373                                         if(i)
374                                                 LOG_INFO(ftos(i), " spawnpoints have no nearest waypoint (marked by player model)\n");
375                                         i = 0;
376                                         entity start;
377                                         start = findchainflags(flags, FL_ITEM);
378                                         for(e = start; e; e = e.chain)
379                                         {
380                                                 e.effects &= ~(EF_NODEPTHTEST | EF_RED | EF_BLUE);
381                                                 e.colormod = '0.5 0.5 0.5';
382                                         }
383                                         for(e = start; e; e = e.chain)
384                                         {
385                                                 if(navigation_findnearestwaypoint(e, false))
386                                                 {
387                                                 }
388                                                 else
389                                                 {
390                                                         LOG_INFO("item without waypoint: ", etos(e), " ", vtos(e.origin), "\n");
391                                                         e.effects |= EF_NODEPTHTEST | EF_RED;
392                                                         e.colormod_x = 8;
393                                                         ++i;
394                                                 }
395                                         }
396                                         if(i)
397                                                 LOG_INFO(ftos(i), " items have no nearest waypoint and cannot be walked away from (marked with red light)\n");
398                                         i = 0;
399                                         for(e = start; e; e = e.chain)
400                                         {
401                                                 org = e.origin;
402                                                 if(navigation_findnearestwaypoint(e, true))
403                                                 {
404                                                 }
405                                                 else
406                                                 {
407                                                         LOG_INFO("item without waypoint: ", etos(e), " ", vtos(e.origin), "\n");
408                                                         e.effects |= EF_NODEPTHTEST | EF_BLUE;
409                                                         e.colormod_z = 8;
410                                                         ++i;
411                                                 }
412                                         }
413                                         if(i)
414                                                 LOG_INFO(ftos(i), " items have no nearest waypoint and cannot be walked to (marked with blue light)\n");
415                                         break;
416                         }
417                 }
418         }
419 }