Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
cheats.qc
Go to the documentation of this file.
1#include "cheats.qh"
2
3#include "weapons/tracing.qh"
4#include <common/constants.qh>
16#include <common/stats.qh>
17#include <common/util.qh>
24#include <server/client.qh>
25#include <server/clientkill.qh>
26#include <server/damage.qh>
27#include <server/main.qh>
29#include <server/player.qh>
30#include <server/race.qh>
31#include <server/world.qh>
32
33#ifdef NOCHEATS
34
35float CheatImpulse(entity this, int imp) { return 0; }
36float CheatCommand(entity this, int argc) { return 0; }
37float CheatFrame(entity this) { return 0; }
38void CheatInit() { cheatcount_total = world.cheatcount; }
39void CheatShutdown() { }
40void Drag_MoveDrag(entity from, entity to) { }
41
42#else
43
46
47
48
53
55{
56}
57
58// the cheat gets passed as argument for possible future ACL checking
59float CheatsAllowed(entity this, float imp, int argc, float cheatframe, bool logattempt, bool ignoredead)
60{
61 if(!ignoredead && IS_DEAD(this))
62 return 0;
63 if(gamestart_sv_cheats < 2 && !IS_PLAYER(this))
64 return 0;
65
66 if(imp == CHIMPULSE_CLONE_MOVING.impulse || imp == CHIMPULSE_CLONE_STANDING.impulse)
67 if(this.lip < autocvar_sv_clones)
68 return 1;
69
70 // haha
71 if(this.maycheat)
72 return 1;
73
75 return 1;
76
77 if (logattempt)
78 {
79 // if we get here, player is not allowed to cheat. Log it.
80 if(imp)
81 bprintf("Player %s^7 tried to use cheat 'impulse %d'\n", playername(this.netname, this.team, false), imp);
82 else if(argc)
83 bprintf("Player %s^7 tried to use cheat '%s'\n", playername(this.netname, this.team, false), argv(0));
84 else if(cheatframe)
85 bprintf("Player %s^7 tried to use cheat frame %d\n", playername(this.netname, this.team, false), cheatframe);
86 else
87 bprintf("Player %s^7 tried to use an unknown cheat\n", playername(this.netname, this.team, false));
88 }
89 return 0;
90}
91
92#define BEGIN_CHEAT_FUNCTION() \
93 float cheating = 0, attempting = 0
94#define DID_CHEAT() \
95 ++cheating
96#define ADD_CHEATS(e,n) \
97 cheatcount_total += n; \
98 e.cheatcount += n
99#define END_CHEAT_FUNCTION() \
100 ADD_CHEATS(this, cheating); \
101 return attempting
102#define IS_CHEAT(ent,i,argc,fr) \
103 if((++attempting, !CheatsAllowed(ent,i,argc,fr,true,false))) \
104 break
105
108{
109 entity e = find(NULL, targetname, this.target);
110 if(!e)
111 {
112 objerror(this, "Missing target. FAIL!");
113 return;
114 }
115 vector a = vectoangles(e.origin - this.origin);
116 a.x = -a.x; // don't ask
117 this.angles_x = a.x;
118 this.angles_y = a.y;
119 // we leave Rick Roll alone
120}
121spawnfunc(info_autoscreenshot)
122{
123 // this one just has to exist
125 {
126 objerror(this, "Too many info_autoscreenshot entitites. FAIL!");
127 return;
128 }
129 if(this.target != "")
131
135}
136
137float CheatImpulse(entity this, int imp)
138{
140 switch(imp)
141 {
142 entity e, e2;
143
144 case CHIMPULSE_SPEEDRUN_INIT.impulse: // deploy personal waypoint
145 // shared with regular waypoint init, so this is not a cheat by itself
146 if(!this.personal)
147 {
148 this.personal = new(personal_wp);
149 }
150 this.personal.origin = this.origin;
151 this.personal.v_angle = this.v_angle;
152 this.personal.velocity = this.velocity;
153 SetResource(this.personal, RES_ROCKETS, GetResource(this, RES_ROCKETS));
154 SetResource(this.personal, RES_BULLETS, GetResource(this, RES_BULLETS));
155 SetResource(this.personal, RES_CELLS, GetResource(this, RES_CELLS));
156 SetResource(this.personal, RES_SHELLS, GetResource(this, RES_SHELLS));
157 SetResource(this.personal, RES_FUEL, GetResource(this, RES_FUEL));
158 SetResource(this.personal, RES_HEALTH, max(1, GetResource(this, RES_HEALTH)));
160 STAT(WEAPONS, this.personal) = STAT(WEAPONS, this);
162 this.personal.items = this.items;
163 this.personal.pauserotarmor_finished = this.pauserotarmor_finished;
164 this.personal.pauserothealth_finished = this.pauserothealth_finished;
165 this.personal.pauserotfuel_finished = this.pauserotfuel_finished;
166 this.personal.pauseregen_finished = this.pauseregen_finished;
167 this.personal.teleport_time = time;
168 break; // this part itself doesn't cheat, so let's not count this
169 case CHIMPULSE_CLONE_MOVING.impulse:
170 IS_CHEAT(this, imp, 0, 0);
171 makevectors (this.v_angle);
172 this.velocity += v_forward * 300;
173 CopyBody(this, 1);
174 ++this.lip;
175 this.velocity -= v_forward * 300;
176 DID_CHEAT();
177 break;
178 case CHIMPULSE_CLONE_STANDING.impulse:
179 IS_CHEAT(this, imp, 0, 0);
180 CopyBody(this, 0);
181 ++this.lip;
182 DID_CHEAT();
183 break;
184 case CHIMPULSE_GIVE_ALL.impulse:
185 IS_CHEAT(this, imp, 0, 0);
186 CheatCommand(this, tokenize_console("give all"));
187 break; // already counted as cheat
188 case CHIMPULSE_SPEEDRUN.impulse:
190 IS_CHEAT(this, imp, 0, 0);
191 if(this.personal)
192 {
193 this.speedrunning = true;
194 tracebox(this.personal.origin, this.mins, this.maxs, this.personal.origin, MOVE_WORLDONLY, this);
196 {
197 sprint(this, "Cannot move there, cheater - only waypoints set using g_waypointsprite_personal work\n");
198 }
199 else
200 {
201 // Abort speedrun, teleport back
202 setorigin(this, this.personal.origin);
203 this.oldvelocity = this.velocity = this.personal.velocity;
204 this.angles = this.personal.v_angle;
205 this.fixangle = true;
206
207 MUTATOR_CALLHOOK(AbortSpeedrun, this);
208 }
209
210 SetResource(this, RES_ROCKETS, GetResource(this.personal, RES_ROCKETS));
211 SetResource(this, RES_BULLETS, GetResource(this.personal, RES_BULLETS));
212 SetResource(this, RES_CELLS, GetResource(this.personal, RES_CELLS));
213 SetResource(this, RES_SHELLS, GetResource(this.personal, RES_SHELLS));
214 SetResource(this, RES_FUEL, GetResource(this.personal, RES_FUEL));
215 SetResource(this, RES_HEALTH, GetResource(this.personal, RES_HEALTH));
217 STAT(WEAPONS, this) = STAT(WEAPONS, this.personal);
218 this.items = this.personal.items;
219 this.pauserotarmor_finished = time + this.personal.pauserotarmor_finished - this.personal.teleport_time;
220 this.pauserothealth_finished = time + this.personal.pauserothealth_finished - this.personal.teleport_time;
221 this.pauserotfuel_finished = time + this.personal.pauserotfuel_finished - this.personal.teleport_time;
222 this.pauseregen_finished = time + this.personal.pauseregen_finished - this.personal.teleport_time;
223 StatusEffects_copy(this.personal, this.statuseffects, this.personal.teleport_time);
225
227 DID_CHEAT();
228 break;
229 }
230 if(IS_DEAD(this))
231 sprint(this, "UR DEAD AHAHAH))\n");
232 else
233 sprint(this, "No waypoint set, cheater (use g_waypointsprite_personal to set one)\n");
234 break;
235 case CHIMPULSE_TELEPORT.impulse:
236 IS_CHEAT(this, imp, 0, 0);
238 {
239 e = find(NULL, classname, "info_autoscreenshot");
240 if(e)
241 {
242 sprint(this, "Emergency teleport used info_autoscreenshot location\n");
243 setorigin(this, e.origin);
244 this.angles = e.angles;
245 delete(e);
246 // should we? this.angles_x = -this.angles_x;
247 this.fixangle = true;
248 this.velocity = '0 0 0';
249 DID_CHEAT();
250 break;
251 }
252 }
254 {
255 sprint(this, "Emergency teleport used random location\n");
256 this.angles_x = -this.angles.x;
257 this.fixangle = true;
258 this.velocity = '0 0 0';
259 DID_CHEAT();
260 break;
261 }
262 sprint(this, "Emergency teleport could not find a good location, forget it!\n");
263 break;
264 case CHIMPULSE_R00T.impulse:
265 IS_CHEAT(this, imp, 0, 0);
267 FOREACH_CLIENT(IS_PLAYER(it) && !IS_DEAD(it) && DIFF_TEAM(it, this), { RandomSelection_AddEnt(it, 1, 1); });
270 else
271 e = this;
272
273 Send_Effect(EFFECT_ROCKET_EXPLODE, e.origin, '0 0 0', 1);
274 sound(e, CH_SHOTS, SND_ROCKET_IMPACT, VOL_BASE, ATTEN_NORM);
275
276 e2 = spawn();
277 setorigin(e2, e.origin);
278 RadiusDamage(e2, this, 1000, 0, 128, NULL, NULL, 500, DEATH_CHEAT.m_id, DMG_NOWEP, e);
279 delete(e2);
280
281 LOG_INFO("404 Sportsmanship not found.");
282 DID_CHEAT();
283 break;
284 }
285
287}
288
290float CheatCommand(entity this, int argc)
291{
293 string cmd = argv(0);
294 switch(cmd)
295 {
296 float effectnum, f;
297 vector start, end;
298
299 case "pointparticles":
300 IS_CHEAT(this, 0, argc, 0);
301 if(argc == 5)
302 {
303 f = stof(argv(2));
304 crosshair_trace(this);
305 start = (1-f) * this.origin + f * trace_endpos;
306 end = stov(argv(3));
307 f = stof(argv(4));
308 Send_Effect_(argv(1), start, end, f);
309 DID_CHEAT();
310 break;
311 }
312 sprint(this, "Usage:^3 sv_cheats 1; restart; cmd pointparticles <effectname> <position> <velocity> <countmultiplier>\n");
313 sprint(this, " Where <position> is a number from 0 to 1 representing distance on the crosshair line,\n");
314 sprint(this, " and <velocity> is a vector \"x y z\"\n");
315 break;
316 case "trailparticles":
317 IS_CHEAT(this, 0, argc, 0);
318 if(argc == 2)
319 {
320 // arguments:
321 // effectname
322 effectnum = _particleeffectnum(argv(1));
323 W_SetupShot(this, weaponentities[0], false, false, SND_Null, CH_WEAPON_A, 0, 0);
325 __trailparticles(this, effectnum, w_shotorg, trace_endpos);
326 DID_CHEAT();
327 break;
328 }
329 sprint(this, "Usage: sv_cheats 1; restart; cmd trailparticles <effectname>\n");
330 break;
331 case "make":
332 IS_CHEAT(this, 0, argc, 0);
333 if(argc == 3)
334 {
335 f = stof(argv(2));
336 W_SetupShot(this, weaponentities[0], false, false, SND_Null, CH_WEAPON_A, 0, 0);
337 traceline(w_shotorg, w_shotorg + w_shotdir * 2048, MOVE_NORMAL, this);
339 {
340 sprint(this, "cannot make stuff there (bad surface)\n");
341 }
342 else
343 {
344 entity e = new(func_breakable);
345 e.model = strzone(argv(1));
346 e.mdl = "rocket_explode";
347 SetResourceExplicit(e, RES_HEALTH, 1000);
348 setorigin(e, trace_endpos);
349 e.effects = EF_NOMODELFLAGS;
350 if(f == 1)
351 {
353 e.angles = AnglesTransform_ApplyToAngles(e.angles, '-90 0 0'); // so unrotated models work
354 }
356 // now, is it valid?
357 if(f == 0)
358 {
359 tracebox(e.origin, e.mins, e.maxs, e.origin, MOVE_NORMAL, e);
361 {
362 delete(e);
363 sprint(this, "cannot make stuff there (no space)\n");
364 }
365 else
366 DID_CHEAT();
367 }
368 else
369 DID_CHEAT();
370 }
371 }
372 else
373 {
374 sprint(this, "Usage:^3 sv_cheats 1; restart; cmd make <modelname> <mode>\n");
375 sprint(this, " where <mode> can be 0, 1 or 2\n");
376 }
377 break;
378 case "penalty":
379 IS_CHEAT(this, 0, argc, 0);
380 if(argc == 3)
381 {
382 race_ImposePenaltyTime(this, stof(argv(1)), argv(2));
383 DID_CHEAT();
384 break;
385 }
386 sprint(this, "Usage:^3 sv_cheats 1; restart; cmd penalty <duration> <reason>))\n");
387 break;
388 case "dragbox_spawn": {
389 IS_CHEAT(this, 0, argc, 0);
390 entity e = new(dragbox_box);
392 e.nextthink = time;
393 e.solid = -1; // black
394 setmodel(e, MDL_Null); // network it
395 if(argc == 4)
396 e.cnt = stof(argv(1));
397 else
398 e.cnt = max(0, drag_lastcnt);
399
400 e.aiment = new(dragbox_corner_1);
401 e.aiment.owner = e;
402 setmodel(e.aiment, MDL_MARKER);
403 e.aiment.skin = 0;
404 setsize(e.aiment, '0 0 0', '0 0 0');
405 if(argc == 4)
406 setorigin(e.aiment, stov(argv(2)));
407 else
408 {
409 crosshair_trace(this);
410 setorigin(e.aiment, trace_endpos);
411 }
412
413 e.enemy = new(dragbox_corner_2);
414 e.enemy.owner = e;
415 setmodel(e.enemy, MDL_MARKER);
416 e.enemy.skin = 1;
417 setsize(e.enemy, '0 0 0', '0 0 0');
418 end = normalize(this.origin + this.view_ofs - e.aiment.origin);
419 end.x = (end.x > 0) * 2 - 1;
420 end.y = (end.y > 0) * 2 - 1;
421 end.z = (end.z > 0) * 2 - 1;
422 if(argc == 4)
423 setorigin(e.enemy, stov(argv(3)));
424 else
425 setorigin(e.enemy, e.aiment.origin + 32 * end);
426
427 e.killindicator = new(drag_digit);
428 e.killindicator.owner = e;
429 setattachment(e.killindicator, e, "");
430 setorigin(e.killindicator, '0 0 -8');
431 e.killindicator.killindicator = new(drag_digit);
432 e.killindicator.killindicator.owner = e;
433 setattachment(e.killindicator.killindicator, e, "");
434 setorigin(e.killindicator.killindicator, '0 0 8');
435 DID_CHEAT();
436 break;
437 }
438 case "dragpoint_spawn": {
439 IS_CHEAT(this, 0, argc, 0);
440 entity e = new(dragpoint);
442 e.nextthink = time;
443 e.solid = 0; // nothing special
444 setmodel(e, MDL_MARKER);
445 setsize(e, STAT(PL_MIN, this), STAT(PL_MAX, this));
446 e.skin = 2;
447 if(argc == 3)
448 e.cnt = stof(argv(1));
449 else
450 e.cnt = drag_lastcnt;
451 if(argc == 3)
452 setorigin(e, stov(argv(2)));
453 else
454 {
455 crosshair_trace(this);
456 setorigin(e, trace_endpos + normalize(this.origin + this.view_ofs - trace_endpos));
458 }
459
460 e.killindicator = new(drag_digit);
461 e.killindicator.owner = e;
462 setattachment(e.killindicator, e, "");
463 setorigin(e.killindicator, '0 0 40');
464 e.killindicator.killindicator = new(drag_digit);
465 e.killindicator.killindicator.owner = e;
466 setattachment(e.killindicator.killindicator, e, "");
467 setorigin(e.killindicator.killindicator, '0 0 56');
468 DID_CHEAT();
469 break;
470 }
471 case "drag_remove":
472 IS_CHEAT(this, 0, argc, 0);
474 crosshair_trace(this);
475 for(entity e = NULL; (e = find(e, classname, "dragbox_box")); )
476 RandomSelection_AddEnt(e, 1, 1 / vlen(e.origin + (e.mins + e.maxs) * 0.5 - trace_endpos));
477 for(entity e = NULL; (e = find(e, classname, "dragpoint")); )
478 RandomSelection_AddEnt(e, 1, 1 / vlen(e.origin + (e.mins + e.maxs) * 0.5 - trace_endpos));
480 {
481 delete(RandomSelection_chosen_ent.killindicator.killindicator);
482 delete(RandomSelection_chosen_ent.killindicator);
484 delete(RandomSelection_chosen_ent.aiment);
486 delete(RandomSelection_chosen_ent.enemy);
488 }
489 DID_CHEAT();
490 break;
491 case "drag_setcnt":
492 IS_CHEAT(this, 0, argc, 0);
493 if(argc == 2)
494 {
496 crosshair_trace(this);
497 for(entity e = NULL; (e = find(e, classname, "dragbox_box")); )
498 RandomSelection_AddEnt(e, 1, 1 / vlen(e.origin + (e.mins + e.maxs) * 0.5 - trace_endpos));
499 for(entity e = NULL; (e = find(e, classname, "dragpoint")); )
500 RandomSelection_AddEnt(e, 1, 1 / vlen(e.origin + (e.mins + e.maxs) * 0.5 - trace_endpos));
502 {
503 if(substring(argv(1), 0, 1) == "*")
505 else
507 }
508 DID_CHEAT();
509 break;
510 }
511 sprint(this, "Usage:^3 sv_cheats 1; restart; cmd dragbox_setcnt <cnt>\n");
512 break;
513 case "drag_save":
514 IS_CHEAT(this, 0, argc, 0);
515 if(argc == 2)
516 {
517 f = fopen(argv(1), FILE_WRITE);
518 fputs(f, "cmd drag_clear\n");
519 for(entity e = NULL; (e = find(e, classname, "dragbox_box")); )
520 {
521 fputs(f, strcat("cmd dragbox_spawn ", ftos(e.cnt), " \"", vtos(e.aiment.origin), "\" \"", vtos(e.enemy.origin), "\"\n"));
522 }
523 for(entity e = NULL; (e = find(e, classname, "dragpoint")); )
524 {
525 fputs(f, strcat("cmd dragpoint_spawn ", ftos(e.cnt), " \"", vtos(e.origin), "\"\n"));
526 }
527 fclose(f);
528 DID_CHEAT();
529 break;
530 }
531 sprint(this, "Usage:^3 sv_cheats 1; restart; cmd dragbox_save <filename>\n");
532 break;
533 case "drag_saveraceent":
534 IS_CHEAT(this, 0, argc, 0);
535 if(argc == 2)
536 {
537 f = fopen(argv(1), FILE_WRITE);
538 for(entity e = NULL; (e = find(e, classname, "dragbox_box")); )
539 {
540 fputs(f, "{\n");
541 fputs(f, "\"classname\" \"trigger_race_checkpoint\"\n");
542 fputs(f, strcat("\"origin\" \"", ftos(e.absmin.x), " ", ftos(e.absmin.y), " ", ftos(e.absmin.z), "\"\n"));
543 fputs(f, strcat("\"maxs\" \"", ftos(e.absmax.x - e.absmin.x), " ", ftos(e.absmax.y - e.absmin.y), " ", ftos(e.absmax.z - e.absmin.z), "\"\n"));
544 fputs(f, strcat("\"cnt\" \"", ftos(e.cnt), "\"\n"));
545 fputs(f, strcat("\"targetname\" \"checkpoint", ftos(e.cnt), "\"\n"));
546 fputs(f, "}\n");
547 }
548 for(entity e = NULL; (e = find(e, classname, "dragpoint")); )
549 {
550 start = '0 0 0';
551 effectnum = 0;
552 for(entity ent = NULL; (ent = find(ent, classname, "dragbox_box")); )
553 {
554 if((e.cnt <= 0 && ent.cnt == 0) || e.cnt == ent.cnt)
555 {
556 start += ent.origin;
557 ++effectnum;
558 }
559 }
560 start *= 1 / effectnum;
561 fputs(f, "{\n");
562 fputs(f, "\"classname\" \"info_player_race\"\n");
563 fputs(f, strcat("\"angle\" \"", ftos(vectoyaw(start - e.origin)), "\"\n"));
564 fputs(f, strcat("\"origin\" \"", ftos(e.origin.x), " ", ftos(e.origin.y), " ", ftos(e.origin.z), "\"\n"));
565 if(e.cnt == -2)
566 {
567 fputs(f, "\"target\" \"checkpoint0\"\n");
568 fputs(f, "\"race_place\" \"0\"\n");
569 }
570 else if(e.cnt == -1)
571 {
572 fputs(f, "\"target\" \"checkpoint0\"\n");
573 fputs(f, "\"race_place\" \"-1\"\n");
574 }
575 else
576 {
577 fputs(f, strcat("\"target\" \"checkpoint", ftos(e.cnt), "\"\n"));
578 if(e.cnt == 0)
579 {
580 // these need race_place
581 // counting...
582 effectnum = 1;
583 for(entity ent = NULL; (ent = find(ent, classname, "dragpoint")); )
584 if(ent.cnt == 0)
585 {
586 if(vlen2(ent.origin - start) < vlen2(e.origin - start))
587 ++effectnum;
588 else if(vlen2(ent.origin - start) == vlen2(e.origin - start) && etof(ent) < etof(e))
589 ++effectnum;
590 }
591 fputs(f, strcat("\"race_place\" \"", ftos(effectnum), "\"\n"));
592 }
593 }
594 fputs(f, "}\n");
595 }
596 fclose(f);
597 DID_CHEAT();
598 break;
599 }
600 sprint(this, "Usage:^3 sv_cheats 1; restart; cmd dragbox_save <filename>\n");
601 break;
602 case "drag_clear":
603 IS_CHEAT(this, 0, argc, 0);
604 for(entity e = NULL; (e = find(e, classname, "dragbox_box")); )
605 delete(e);
606 for(entity e = NULL; (e = find(e, classname, "dragbox_corner_1")); )
607 delete(e);
608 for(entity e = NULL; (e = find(e, classname, "dragbox_corner_2")); )
609 delete(e);
610 for(entity e = NULL; (e = find(e, classname, "dragpoint")); )
611 delete(e);
612 for(entity e = NULL; (e = find(e, classname, "drag_digit")); )
613 delete(e);
614 DID_CHEAT();
615 break;
616 case "god":
617 IS_CHEAT(this, 0, argc, 0);
619 if(this.flags & FL_GODMODE)
620 {
621 sprint(this, "godmode ON\n");
622 DID_CHEAT();
623 }
624 else
625 sprint(this, "godmode OFF\n");
626 break;
627 case "notarget":
628 IS_CHEAT(this, 0, argc, 0);
630 if(this.flags & FL_NOTARGET)
631 {
632 sprint(this, "notarget ON\n");
633 DID_CHEAT();
634 }
635 else
636 sprint(this, "notarget OFF\n");
637 break;
638 case "noclip":
639 IS_CHEAT(this, 0, argc, 0);
641 {
643 sprint(this, "noclip ON\n");
644 DID_CHEAT();
645 }
646 else
647 {
649 sprint(this, "noclip OFF\n");
650 }
651 break;
652 case "fly":
653 IS_CHEAT(this, 0, argc, 0);
654 if(this.move_movetype != MOVETYPE_FLY)
655 {
657 sprint(this, "flymode ON\n");
658 DID_CHEAT();
659 }
660 else
661 {
663 sprint(this, "flymode OFF\n");
664 }
665 break;
666 case "give":
667 IS_CHEAT(this, 0, argc, 0);
668 if(GiveItems(this, 1, argc))
669 DID_CHEAT();
670 break;
671 case "usetarget":
672 IS_CHEAT(this, 0, argc, 0);
673 entity e = spawn();
674 e.target = argv(1);
675 SUB_UseTargets(e, this, NULL);
676 delete(e);
677 DID_CHEAT();
678 break;
679 case "killtarget":
680 IS_CHEAT(this, 0, argc, 0);
681 entity e2 = spawn();
682 e2.killtarget = argv(1);
683 SUB_UseTargets(e2, this, NULL);
684 delete(e2);
685 DID_CHEAT();
686 break;
687 case "teleporttotarget":
688 IS_CHEAT(this, 0, argc, 0);
689 entity ent = new(cheattriggerteleport);
690 setorigin(ent, ent.origin);
691 ent.target = argv(1);
693 if(!wasfreed(ent))
694 {
695 Simple_TeleportPlayer(ent, this);
696 delete(ent);
697 DID_CHEAT();
698 }
699 break;
700 }
701
703}
704
706
708{
710
711 // Dragging can be used as either a cheat, or a function for some objects. If sv_cheats is active,
712 // the cheat dragging is used (unlimited pickup range and any entity can be carried). If sv_cheats
713 // is disabled, normal dragging is used (limited pickup range and only dragable objects can be carried),
714 // grabbing itself no longer being accounted as cheating.
715
716 switch(0)
717 {
718 default:
720 {
721 // use cheat dragging if cheats are enabled
722 //if(Drag_IsDragging(this))
723 //crosshair_trace_plusvisibletriggers(this);
724 Drag(this, true, true);
725 }
726 else
727 {
728 Drag(this, false, false); // execute dragging
729 }
730 break;
731 }
732
734}
735
736
737
738
739
740// ENTITY DRAGGING
741
742// on dragger:
744.float dragspeed; // speed of mouse wheel action
745.float dragdistance; // distance of dragentity's draglocalvector from view_ofs
746.vector draglocalvector; // local attachment vector of the dragentity
748// on draggee:
749.entity draggedby;
751
752float Drag(entity this, float force_allow_pick, float ischeat)
753{
755
756 // returns true when an entity has been picked up
757 // If pick is true, the object can also be picked up if it's not being held already
758 // If pick is false, only keep dragging the object if it's already being held
759
760 switch(0)
761 {
762 default:
763 if(Drag_IsDragging(this))
764 {
765 if(PHYS_INPUT_BUTTON_DRAG(this))
766 {
767 if(CS(this).impulse == 10 || CS(this).impulse == 15 || CS(this).impulse == 18)
768 {
769 Drag_MoveForward(this);
770 CS(this).impulse = 0;
771 }
772 else if(CS(this).impulse == 12 || CS(this).impulse == 16 || CS(this).impulse == 19)
773 {
774 Drag_MoveBackward(this);
775 CS(this).impulse = 0;
776 }
777 else if(CS(this).impulse >= 1 && CS(this).impulse <= 9)
778 {
779 Drag_SetSpeed(this, CS(this).impulse - 1);
780 }
781 else if(CS(this).impulse == 14)
782 {
783 Drag_SetSpeed(this, 9);
784 }
785
786 if(frametime)
787 Drag_Update(this);
788 }
789 else
790 {
791 Drag_Finish(this);
792 }
793 }
794 else if(Drag_CanDrag(this) && PHYS_INPUT_BUTTON_DRAG(this))
795 {
797 entity e = trace_ent;
798 float pick = force_allow_pick;
799 if (e && !pick && vdist(this.origin - e.origin, <=, autocvar_g_grab_range))
800 {
801 // pick is true if the object can be picked up. While an object is being carried, the Drag() function
802 // must execute for it either way, otherwise it would cause bugs if it went out of the player's trace.
803 // This also makes sure that an object can only pe picked up if in range, but does not get dropped if
804 // it goes out of range while slinging it around.
805
806 switch(e.grab)
807 {
808 case 0: // can't grab
809 break;
810 case 1: // owner can grab
811 if(e.owner == this || e.realowner == this)
812 pick = true;
813 break;
814 case 2: // owner and teammates can grab
815 if(SAME_TEAM(e.owner, this) || SAME_TEAM(e.realowner, this) || e.team == this.team)
816 pick = true;
817 break;
818 case 3: // anyone can grab
819 pick = true;
820 break;
821 default:
822 break;
823 }
824 }
825 // Find e and pick
826 if(e && pick && Drag_IsDraggable(e, this))
827 {
828 if(ischeat)
829 IS_CHEAT(this, 0, 0, CHRAME_DRAG);
830 if(e.draggedby)
831 Drag_Finish(e.draggedby);
832 if(e.tag_entity)
834 Drag_Begin(this, e, trace_endpos);
835 if(ischeat)
836 DID_CHEAT();
837 return true;
838 }
839 }
840 break;
841 }
842 return false;
843}
844
845void Drag_Begin(entity dragger, entity draggee, vector touchpoint)
846{
847 float tagscale;
848
849 draggee.dragmovetype = draggee.move_movetype;
850 draggee.draggravity = draggee.gravity;
851 set_movetype(draggee, MOVETYPE_WALK);
852 draggee.gravity = 0.00001;
853 UNSET_ONGROUND(draggee);
854 draggee.draggedby = dragger;
855
856 dragger.dragentity = draggee;
857
858 dragger.dragdistance = vlen(touchpoint - dragger.origin - dragger.view_ofs);
859 dragger.draglocalangle = draggee.angles.y - dragger.v_angle.y;
860 touchpoint -= gettaginfo(draggee, 0);
861 tagscale = (vlen(v_forward) ** -2);
862 dragger.draglocalvector_x = touchpoint * v_forward * tagscale;
863 dragger.draglocalvector_y = touchpoint * v_right * tagscale;
864 dragger.draglocalvector_z = touchpoint * v_up * tagscale;
865
866 dragger.dragspeed = 64;
867}
868
869void Drag_Finish(entity dragger)
870{
871 entity draggee = dragger.dragentity;
872 if(dragger)
873 dragger.dragentity = NULL;
874 draggee.draggedby = NULL;
875 set_movetype(draggee, draggee.dragmovetype);
876 draggee.gravity = draggee.draggravity;
877
878 switch(draggee.move_movetype)
879 {
880 case MOVETYPE_TOSS:
881 case MOVETYPE_WALK:
882 case MOVETYPE_STEP:
884 case MOVETYPE_BOUNCE:
886 case MOVETYPE_PHYSICS:
887 break;
888 default:
889 draggee.velocity = '0 0 0';
890 break;
891 }
892
893 if((draggee.flags & FL_ITEM) && (vdist(draggee.velocity, <, 32)))
894 {
895 draggee.velocity = '0 0 0';
896 SET_ONGROUND(draggee); // floating items are FUN
897 }
898}
899
900bool drag_undraggable(entity draggee, entity dragger)
901{
902 // stuff probably shouldn't need this, we should figure out why they do!
903 // exceptions of course are observers and weapon entities, where things mess up
904 return false;
905}
906
907float Drag_IsDraggable(entity draggee, entity dragger)
908{
909 // TODO add more checks for bad stuff here
910 if(draggee == NULL)
911 return false;
912 if(draggee.classname == "door") // FIXME find out why these must be excluded, or work around the problem (trying to drag these causes like 4 fps)
913 return false; // probably due to BSP collision
914 //if(draggee.model == "")
915 // return false;
916
917 return ((draggee.draggable) ? draggee.draggable(draggee, dragger) : true);
918}
919
921{
922 // TODO add more checks for bad stuff here
923 if(substring(draggee.model, 0, 1) == "*")
924 return false;
925 return true;
926}
927
929{
930 dragger.dragdistance += dragger.dragspeed;
931}
932
933void Drag_SetSpeed(entity dragger, float s)
934{
935 dragger.dragspeed = (2 ** s);
936}
937
939{
940 dragger.dragdistance = max(0, dragger.dragdistance - dragger.dragspeed);
941}
942
943void Drag_Update(entity dragger)
944{
945 entity draggee = dragger.dragentity;
946 UNSET_ONGROUND(draggee);
947
948 vector curorigin = gettaginfo(draggee, 0);
949 curorigin += v_forward * dragger.draglocalvector.x + v_right * dragger.draglocalvector.y + v_up * dragger.draglocalvector.z;
950 makevectors(dragger.v_angle);
951 vector neworigin = dragger.origin + dragger.view_ofs + v_forward * dragger.dragdistance;
952 vector goodvelocity = (neworigin - curorigin) * (1 / frametime);
953
954 while(draggee.angles.y - dragger.v_angle.y - dragger.draglocalangle > 180)
955 dragger.draglocalangle += 360;
956 while(draggee.angles.y - dragger.v_angle.y - dragger.draglocalangle <= -180)
957 dragger.draglocalangle -= 360;
958
959 float f = min(frametime * 10, 1);
960 draggee.velocity = draggee.velocity * (1 - f) + goodvelocity * f;
961
962 if(Drag_MayChangeAngles(draggee))
963 draggee.angles_y = draggee.angles.y * (1 - f) + (dragger.v_angle.y + dragger.draglocalangle) * f;
964
965 draggee.ltime = max(servertime + serverframetime, draggee.ltime); // fixes func_train breakage
966
967 vector vecs = '0 0 0';
968 .entity weaponentity = weaponentities[0]; // TODO: unhardcode
969 if(dragger.(weaponentity).movedir.x > 0)
970 vecs = dragger.(weaponentity).movedir;
971
972 vector dv = v_right * -vecs_y + v_up * vecs_z;
973
974 te_lightning1(draggee, dragger.origin + dragger.view_ofs + dv, curorigin);
975}
976
977float Drag_CanDrag(entity dragger)
978{
979 return (!IS_DEAD(dragger)) || (IS_PLAYER(dragger));
980}
981
983{
984 if(!dragger.dragentity)
985 return false;
986 if(wasfreed(dragger.dragentity) || dragger.dragentity.draggedby != dragger)
987 {
988 dragger.dragentity = NULL;
989 return false;
990 }
991 if(!Drag_CanDrag(dragger) || !Drag_IsDraggable(dragger.dragentity, dragger))
992 {
993 Drag_Finish(dragger);
994 return false;
995 }
996 return true;
997}
998
1000{
1001 if(from.draggedby)
1002 {
1003 to.draggedby = from.draggedby;
1004 to.draggedby.dragentity = to;
1005 from.draggedby = NULL;
1006 }
1007}
1008
1010{
1011 if(this.aiment && this.enemy)
1012 {
1013 this.origin_x = (this.aiment.origin.x + this.enemy.origin.x) * 0.5;
1014 this.origin_y = (this.aiment.origin.y + this.enemy.origin.y) * 0.5;
1015 this.origin_z = (this.aiment.origin.z + this.enemy.origin.z) * 0.5;
1016 this.maxs_x = fabs(this.aiment.origin.x - this.enemy.origin.x) * 0.5;
1017 this.maxs_y = fabs(this.aiment.origin.y - this.enemy.origin.y) * 0.5;
1018 this.maxs_z = fabs(this.aiment.origin.z - this.enemy.origin.z) * 0.5;
1019 this.mins = -1 * this.maxs;
1020 setorigin(this, this.origin);
1021 setsize(this, this.mins, this.maxs); // link edict
1022 }
1023
1024 if(this.cnt == -1) // actually race_place -1
1025 {
1026 // show "10 10" for qualifying spawns
1027 setmodel(this.killindicator, MDL_NUM(10));
1028 setmodel(this.killindicator.killindicator, MDL_NUM(10));
1029 }
1030 else if(this.cnt == -2) // actually race_place 0
1031 {
1032 // show "10 0" for loser spawns
1033 setmodel(this.killindicator, MDL_NUM(10));
1034 setmodel(this.killindicator.killindicator, MDL_NUM(0));
1035 }
1036 else
1037 {
1038 setmodel(this.killindicator, MDL_NUM(this.cnt % 10));
1039 setmodel(this.killindicator.killindicator, MDL_NUM(floor(this.cnt / 10)));
1040 }
1041
1042 this.nextthink = time;
1043}
1044
1045#endif
vector AnglesTransform_ApplyToAngles(vector transform, vector v)
#define fixedvectoangles2
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
void func_breakable_setup(entity this)
Definition breakable.qc:317
void CheatShutdown()
Definition cheats.qc:54
#define END_CHEAT_FUNCTION()
Definition cheats.qc:99
float Drag_CanDrag(entity dragger)
Definition cheats.qc:977
void Drag_MoveBackward(entity dragger)
Definition cheats.qc:938
float CheatCommand(entity this, int argc)
Definition cheats.qc:290
bool maycheat
Definition cheats.qc:44
void CheatInit()
Definition cheats.qc:49
void DragBox_Think(entity this)
Definition cheats.qc:1009
#define DID_CHEAT()
Definition cheats.qc:94
float draglocalangle
Definition cheats.qc:747
void Drag_MoveDrag(entity from, entity to)
Definition cheats.qc:999
#define IS_CHEAT(ent, i, argc, fr)
Definition cheats.qc:102
float dragmovetype
Definition cheats.qc:750
float dragspeed
Definition cheats.qc:744
float draggravity
Definition cheats.qc:743
float dragdistance
Definition cheats.qc:745
#define BEGIN_CHEAT_FUNCTION()
Definition cheats.qc:92
entity dragentity
Definition cheats.qc:705
float Drag(entity this, float force_allow_pick, float ischeat)
Definition cheats.qc:752
void info_autoscreenshot_findtarget(entity this)
Definition cheats.qc:107
void Drag_Finish(entity dragger)
Definition cheats.qc:869
float Drag_MayChangeAngles(entity draggee)
Definition cheats.qc:920
float CheatImpulse(entity this, int imp)
Definition cheats.qc:137
void Drag_Update(entity dragger)
Definition cheats.qc:943
void Drag_Begin(entity dragger, entity draggee, vector touchpoint)
Definition cheats.qc:845
float Drag_IsDraggable(entity draggee, entity dragger)
Definition cheats.qc:907
void Drag_SetSpeed(entity dragger, float s)
Definition cheats.qc:933
void Drag_MoveForward(entity dragger)
Definition cheats.qc:928
float CheatFrame(entity this)
Definition cheats.qc:707
bool drag_undraggable(entity draggee, entity dragger)
Definition cheats.qc:900
vector draglocalvector
Definition cheats.qc:746
float num_autoscreenshot
Definition cheats.qc:106
float CheatsAllowed(entity this, float imp, int argc, float cheatframe, bool logattempt, bool ignoredead)
Definition cheats.qc:59
float drag_lastcnt
Definition cheats.qc:289
float gamestart_sv_cheats
Definition cheats.qc:45
float Drag_IsDragging(entity dragger)
Definition cheats.qc:982
float cheatcount_total
Definition cheats.qh:10
const float CHRAME_DRAG
Definition cheats.qh:19
int autocvar_sv_cheats
Definition cheats.qh:5
int autocvar_sv_clones
Definition cheats.qh:8
bool speedrunning
Definition cheats.qh:22
int autocvar_g_max_info_autoscreenshot
Definition cheats.qh:7
entity personal
Definition cheats.qh:24
float autocvar_g_grab_range
Definition cheats.qh:6
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
void SetResource(entity e, Resource res_type, float amount)
Sets the current amount of resource the given entity will have.
float GetResource(entity e, Resource res_type)
Returns the current amount of resource the given entity has.
bool SetResourceExplicit(entity e, Resource res_type, float amount)
Sets the resource amount of an entity without calling any hooks.
string netname
Definition powerups.qc:20
float cnt
Definition powerups.qc:24
int team
Definition main.qh:188
entity killindicator
Definition clientkill.qh:7
#define setmodel(this, m)
Definition model.qh:26
int items
Definition player.qh:226
#define IS_DEAD(s)
Definition player.qh:244
vector v_angle
Definition player.qh:236
#define IS_PLAYER(s)
Definition player.qh:242
#define PHYS_INPUT_BUTTON_DRAG(s)
Definition player.qh:159
string playername(string thename, int teamid, bool team_colorize)
Definition util.qc:2178
void detach_sameorigin(entity e)
Definition util.qc:2097
#define bprintf(...)
Definition util.qh:232
const int FL_NOTARGET
Definition constants.qh:76
const int INITPRIO_FINDTARGET
Definition constants.qh:96
const int FL_GODMODE
Definition constants.qh:75
const vector PL_CROUCH_MIN_CONST
Definition constants.qh:58
const vector PL_CROUCH_MAX_CONST
Definition constants.qh:57
const int FL_ITEM
Definition constants.qh:77
vector v_up
string classname
float Q3SURFACEFLAG_SKY
float flags
float DPCONTENTS_SKY
entity trace_ent
float DPCONTENTS_DONOTENTER
float DPCONTENTS_SOLID
float frametime
const float MOVE_NORMAL
float DPCONTENTS_CORPSE
vector mins
vector velocity
float DPCONTENTS_BODY
const float FILE_WRITE
float DPCONTENTS_PLAYERCLIP
float DPCONTENTS_SLIME
float time
vector v_right
vector trace_endpos
float trace_startsolid
vector maxs
float nextthink
float MOVE_WORLDONLY
float trace_dphitq3surfaceflags
vector v_forward
vector origin
float trace_fraction
float DPCONTENTS_LAVA
float Q3SURFACEFLAG_NOIMPACT
vector trace_plane_normal
#define spawn
float RadiusDamage(entity inflictor, entity attacker, float coredamage, float edgedamage, float rad, entity cantbe, entity mustbe, float forceintensity, int deathtype,.entity weaponentity, entity directhitentity)
Definition damage.qc:943
#define DMG_NOWEP
Definition damage.qh:104
float EF_NOMODELFLAGS
#define tokenize_console
void Send_Effect_(string eff_name, vector eff_loc, vector eff_vel, int eff_cnt)
Definition all.qc:125
void Send_Effect(entity eff, vector eff_loc, vector eff_vel, int eff_cnt)
Definition all.qc:120
RES_ARMOR
Definition ent_cs.qc:130
ent angles
Definition ent_cs.qc:121
angles_y
Definition ent_cs.qc:119
ERASEABLE entity IL_PUSH(IntrusiveList this, entity it)
Push to tail.
void SUB_UseTargets(entity this, entity actor, entity trigger)
Definition triggers.qc:344
float servertime
Definition net.qh:330
#define STAT(...)
Definition stats.qh:82
#define move_out_of_solid(e)
Definition common.qh:110
#define BITXOR_ASSIGN(a, b)
Definition common.qh:107
#define LOG_INFO(...)
Definition log.qh:65
vector movedir
Definition viewloc.qh:18
void fclose(float fhandle)
float stof(string val,...)
void fputs(float fhandle, string s)
string substring(string s, float start, float length)
void sprint(float clientnum, string text,...)
float fopen(string filename, float mode)
entity find(entity start,.string field, string match)
float vectoyaw(vector v)
vector stov(string s)
float vlen(vector v)
vector vectoangles(vector v)
void cmd(string command,...)
string vtos(vector v)
float min(float f,...)
vector normalize(vector v)
string ftos(float f)
float fabs(float f)
float floor(float f)
string strzone(string s)
string argv(float n)
float max(float f,...)
#define etof(e)
Definition misc.qh:25
Model MDL_NUM(int i)
Definition all.inc:229
void set_movetype(entity this, int mt)
Definition movetypes.qc:4
const int MOVETYPE_STEP
Definition movetypes.qh:133
const int MOVETYPE_WALK
Definition movetypes.qh:132
const int MOVETYPE_FLYMISSILE
Definition movetypes.qh:138
#define SET_ONGROUND(s)
Definition movetypes.qh:17
entity aiment
Definition movetypes.qh:90
const int MOVETYPE_BOUNCEMISSILE
Definition movetypes.qh:140
float move_movetype
Definition movetypes.qh:76
#define UNSET_ONGROUND(s)
Definition movetypes.qh:18
const int MOVETYPE_PHYSICS
Definition movetypes.qh:142
const int MOVETYPE_NOCLIP
Definition movetypes.qh:137
const int MOVETYPE_FLY
Definition movetypes.qh:134
const int MOVETYPE_TOSS
Definition movetypes.qh:135
const int MOVETYPE_BOUNCE
Definition movetypes.qh:139
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
#define NULL
Definition post.qh:14
#define world
Definition post.qh:15
#define makevectors
Definition post.qh:21
#define gettaginfo
Definition post.qh:32
#define objerror
Definition pre.qh:8
vector view_ofs
Definition progsdefs.qc:151
float fixangle
Definition progsdefs.qc:160
float impulse
Definition progsdefs.qc:158
ERASEABLE void RandomSelection_Init()
Definition random.qc:4
#define RandomSelection_AddEnt(e, weight, priority)
Definition random.qh:14
entity RandomSelection_chosen_ent
Definition random.qh:5
#define setthink(e, f)
vector
Definition self.qh:92
IntrusiveList g_observepoints
Definition client.qh:371
float pauserotfuel_finished
Definition client.qh:340
float pauseregen_finished
Definition client.qh:337
float pauserothealth_finished
Definition client.qh:338
float pauserotarmor_finished
Definition client.qh:339
int int int imp
Definition impulse.qc:90
float GiveItems(entity e, float beginarg, float endarg)
Definition items.qc:1435
vector oldvelocity
Definition main.qh:42
float serverframetime
Definition main.qh:39
void CopyBody(entity this, float keepvelocity)
Definition player.qc:64
void race_ImposePenaltyTime(entity pl, float penalty, string reason)
Definition race.qc:1275
bool autocvar_g_allow_checkpoints
Definition race.qh:3
const float VOL_BASE
Definition sound.qh:36
const int CH_SHOTS
Definition sound.qh:14
const int CH_WEAPON_A
Definition sound.qh:7
const float ATTEN_NORM
Definition sound.qh:30
#define sound(e, c, s, v, a)
Definition sound.qh:52
#define spawnfunc(id)
Definition spawnfunc.qh:96
ClientState CS(Client this)
Definition state.qh:47
void StatusEffects_copy(StatusEffect this, entity store, float time_offset)
StatusEffect statuseffects
Entity statuseffects.
void StatusEffects_update(entity e)
float lip
Definition subs.qh:40
entity enemy
Definition sv_ctf.qh:153
entity draggedby
Header file that describes the resource system.
#define SAME_TEAM(a, b)
Definition teams.qh:241
#define DIFF_TEAM(a, b)
Definition teams.qh:242
void teleport_findtarget(entity this)
entity Simple_TeleportPlayer(entity teleporter, entity player)
void crosshair_trace(entity pl)
Definition tracing.qc:542
void crosshair_trace_plusvisibletriggers(entity pl)
Definition tracing.qc:547
vector w_shotdir
Definition tracing.qh:20
vector w_shotorg
Definition tracing.qh:19
#define W_SetupShot(ent, wepent, antilag, recoil, snd, chan, maxdamage, deathtype)
Definition tracing.qh:34
string targetname
Definition triggers.qh:56
string target
Definition triggers.qh:55
#define FOREACH_CLIENT(cond, body)
Definition utils.qh:52
#define vlen2(v)
Definition vector.qh:4
#define vdist(v, cmp, f)
Vector distance comparison, avoids sqrt()
Definition vector.qh:8
int max_shot_distance
Definition weapon.qh:245
entity weaponentities[MAX_WEAPONSLOTS]
Definition weapon.qh:17
float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
Definition world.qc:1252
void InitializeEntity(entity e, void(entity this) func, int order)
Definition world.qc:2230