Xonotic QuakeC
The free, fast arena FPS with crisp movement and a wide array of weapons
main.qc
Go to the documentation of this file.
1#include "main.qh"
2
4#include <client/draw.qh>
5#include <client/hud/_mod.qh>
10#include <client/items/items.qh>
11#include <client/mapvoting.qh>
13#include <client/shownames.qh>
14#include <client/view.qh>
19#include <common/effects/all.qh>
22#include <common/ent_cs.qh>
24#include <common/items/_mod.qh>
25#include <common/mapinfo.qh>
29#include <common/net_linked.qh>
30#include <common/net_notice.qh>
31#include <common/scores.qh>
36
37// --------------------------------------------------------------------------
38// BEGIN REQUIRED CSQC FUNCTIONS
39//include "main.qh"
40
41#define DP_CSQC_ENTITY_REMOVE_IS_B0RKED
42
43// CSQC_Init : Called every time the CSQC code is initialized (essentially at map load)
44// Useful for precaching things
45
46void CSQC_Init(float apilevel, string enginename, float engineversion)
47{
48 prvm_language = strzone(cvar_string("prvm_language"));
49
50#ifdef WATERMARK
51 LOG_TRACEF("^4CSQC Build information: ^1%s", WATERMARK);
52#endif
53
55
56 {
57 int i = 0;
58 for ( ; i < 255; ++i)
59 if (getplayerkeyvalue(i, "viewentity") == "")
60 break;
61 maxclients = i;
62 }
63
64 // needs to be done so early because of the constants they create
68
69 binddb = db_create();
70 tempdb = db_create();
71 ClientProgsDB = db_load("client.db");
72
74
75 //registercommand("hud_configure");
76 //registercommand("hud_save");
77 //registercommand("menu_action");
78
80
81 registercvar("hud_usecsqc", "1");
82 registercvar("scoreboard_columns", "default");
83
84 registercvar("cl_nade_type", "3");
85 registercvar("cl_pokenade_type", "zombie");
86
87 registercvar("cl_jumpspeedcap_min", "");
88 registercvar("cl_jumpspeedcap_max", "");
89
90 registercvar("cl_shootfromfixedorigin", "");
91
92 registercvar("cl_multijump", "-1");
93
94 registercvar("cl_dodging", "0");
95
96 registercvar("cl_autoswitch_cts", "-1");
97
98 registercvar("cl_spawn_near_teammate", "1");
99
100 registercvar("cl_weapon_switch_reload", "1");
101 registercvar("cl_weapon_switch_fallback_to_impulse", "1");
102
103 registercvar("cl_allow_uidranking", "1");
104
106 cvar_set("cl_lockview", "0");
107
108 if (cvar_type("_scoreboard_team_selection_available") & CVAR_TYPEFLAG_EXISTS)
109 cvar_settemp("_scoreboard_team_selection_available", "1");
110 cvar_set("_scoreboard_team_selection", "0"); // in case it has been left set to 1
111
112 // XONRELEASE: default values for <= 0.8.6 can be removed after next release
113 registercvar("hud_panel_checkpoints_pos", "0.700000 0.190000");
114 registercvar("hud_panel_checkpoints_size", "0.250000 0.170000");
115
116 gametype = NULL;
117
118 postinit = false;
119
120 calledhooks = 0;
121
122 teams = Sort_Spawn();
124
125 GetTeam(NUM_SPECTATOR, true); // add specs first
126
127 for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w)
128 weapon_accuracy[w] = -1;
129
130 // precaches
131
133 {
134 precache_pic("gfx/reticle_normal");
135 // weapon reticles are precached in weapon files
136 }
137
138 {
139 get_mi_min_max_texcoords(1); // try the CLEVER way first
140 minimapname = strcat("gfx/", mi_shortname, "_radar");
141
142 if (precache_pic(minimapname) == "")
143 {
144 // but maybe we have a non-clever minimap
145 minimapname = strcat("gfx/", mi_shortname, "_mini");
146 if (precache_pic(minimapname) == "")
147 minimapname = ""; // FAIL
148 else
149 get_mi_min_max_texcoords(0); // load new texcoords
150 }
151
152 mi_center = (mi_min + mi_max) * 0.5;
155 }
156
159}
160
161// CSQC_Shutdown : Called every time the CSQC code is shutdown (changing maps, quitting, etc)
163{
165
166 delete(teams);
167 delete(players);
171 db_dump(ClientProgsDB, "client.db");
172 else
173 db_save(ClientProgsDB, "client.db");
175
176 if(camera_active)
177 cvar_set("chase_active",ftos(chase_active_backup));
178
179 // unset the event chasecam's chase_active
181 cvar_set("chase_active", "0");
182
184 cvar_set("r_drawviewmodel", "0");
185
186 cvar_set("slowmo", cvar_defstring("slowmo")); // reset it back to 'default'
187
188 // if _cl_hook_gamestart wasn't called with an actual gametype
189 // before CSQC VM shutdown then call it with nop fallback here
190 if (!(calledhooks & HOOK_START) && !isdemo())
191 localcmd("\n_cl_hook_gamestart nop\n");
192
193 // fire game or demo end hooks when CSQC VM shuts down
194 if (!(calledhooks & HOOK_END))
195 {
196 // call gameend hook if it hasn't somehow yet fired by intermission starting
197 if (!isdemo())
198 {
199 localcmd("\ncl_hook_gameend\n");
200
201 // NOTE: using localcmd here to ensure it's executed AFTER cl_hook_gameend
202 // earlier versions of the game abuse the hook to set this cvar
203 int gamecount = cvar("cl_matchcount");
204 localcmd(strcat("cl_matchcount ", itos(gamecount + 1), "\n"));
205 //cvar_set("cl_matchcount", itos(gamecount + 1));
206 }
207 else
208 localcmd("\ncl_hook_demoend\n");
209
210 calledhooks |= HOOK_END; // mark the hook as having fired
211 }
212
213 localcmd("\ncl_hook_shutdown\n");
214
215 localcmd("\n-button12\n");
216
218
221
223}
224
226{
227 entity e;
229 for(e = prev.sort_next; e; prev = e, e = e.sort_next)
230 {
231 if(prev != e.sort_prev)
232 error(strcat("sort list chain error\nplease submit the output of 'prvm_edicts client' to the developers"));
233 }
234
235 prev = teams;
236 for(e = prev.sort_next; e; prev = e, e = e.sort_next)
237 {
238 if(prev != e.sort_prev)
239 error(strcat("sort list chain error\nplease submit the output of 'prvm_edicts client' to the developers"));
240 }
241}
242
244{
245 entity pl;
246 AuditLists();
247 for(pl = players.sort_next; pl; pl = pl.sort_next)
248 if(pl == player)
249 error("Player already registered!");
250 player.sort_next = players.sort_next;
251 player.sort_prev = players;
252 if(players.sort_next)
253 players.sort_next.sort_prev = player;
254 players.sort_next = player;
255 AuditLists();
256 return true;
257}
258
260{
261 entity pl, parent;
262 AuditLists();
263 parent = players;
264 for(pl = players.sort_next; pl && pl != player; pl = pl.sort_next)
265 parent = pl;
266
267 if(!pl)
268 {
269 error("Trying to remove a player which is not in the playerlist!");
270 return;
271 }
272 parent.sort_next = player.sort_next;
273 if(player.sort_next)
274 player.sort_next.sort_prev = parent;
275 AuditLists();
276}
277
279{
280 AuditLists();
281 entity ent = e.sort_next;
282 while(ent)
283 {
284 SORT_SWAP(ent, e);
285 ent = e.sort_next;
286 }
287 AuditLists();
288}
289
291{
292 assert_once(Team.team, eprint(Team));
293 entity tm;
294 AuditLists();
295 for(tm = teams.sort_next; tm; tm = tm.sort_next)
296 if(tm == Team)
297 error("Team already registered!");
298 Team.sort_next = teams.sort_next;
299 Team.sort_prev = teams;
300 if(teams.sort_next)
301 teams.sort_next.sort_prev = Team;
302 teams.sort_next = Team;
303 if(Team.team && Team.team != NUM_SPECTATOR)
304 ++team_count;
305 AuditLists();
306 return true;
307}
308
310{
311 entity tm, parent;
312 AuditLists();
313 parent = teams;
314 for(tm = teams.sort_next; tm && tm != Team; tm = tm.sort_next)
315 parent = tm;
316
317 if(!tm)
318 {
319 LOG_INFO(_("Trying to remove a team which is not in the teamlist!"));
320 return;
321 }
322 parent.sort_next = Team.sort_next;
323 if(Team.sort_next)
324 Team.sort_next.sort_prev = parent;
325 if(Team.team && Team.team != NUM_SPECTATOR)
326 --team_count;
327 AuditLists();
328}
329
330entity GetTeam(int Team, bool add)
331{
332 TC(int, Team); TC(bool, add);
333 int num = (Team == NUM_SPECTATOR) ? 16 : Team;
334 if(teamslots[num])
335 return teamslots[num];
336 if (!add)
337 return NULL;
338 entity tm = new_pure(team);
339 tm.team = Team;
340 teamslots[num] = tm;
341 RegisterTeam(tm);
342 return tm;
343}
344
345.float has_team;
346bool SetTeam(entity o, int Team)
347{
348 TC(int, Team);
349 //devassert_once(Team);
350 entity tm;
351 if(teamplay)
352 {
353 switch(Team)
354 {
355 case -1:
356 case NUM_TEAM_1:
357 case NUM_TEAM_2:
358 case NUM_TEAM_3:
359 case NUM_TEAM_4:
360 break;
361 default:
362 if(GetTeam(Team, false) == NULL)
363 {
364 LOG_TRACEF("trying to switch to unsupported team %d", Team);
365 Team = NUM_SPECTATOR;
366 }
367 break;
368 }
369 }
370 else
371 {
372 switch(Team)
373 {
374 case -1:
375 case 0:
376 break;
377 default:
378 if(GetTeam(Team, false) == NULL)
379 {
380 LOG_TRACEF("trying to switch to unsupported team %d", Team);
381 Team = NUM_SPECTATOR;
382 }
383 break;
384 }
385 }
386 if(Team == -1) // leave
387 {
388 if(o.has_team)
389 {
390 tm = GetTeam(o.team, false);
391 --tm.team_size;
392 o.has_team = 0;
393 return true;
394 }
395 }
396 else
397 {
398 if (!o.has_team)
399 {
400 o.team = Team;
401 tm = GetTeam(Team, true);
402 ++tm.team_size;
403 o.has_team = 1;
404 return true;
405 }
406 else if(Team != o.team)
407 {
408 tm = GetTeam(o.team, false);
409 --tm.team_size;
410 o.team = Team;
411 tm = GetTeam(Team, true);
412 ++tm.team_size;
413 return true;
414 }
415 }
416 return false;
417}
418
420{
421 int i;
422 entity e;
423 for(i = 0; i < maxclients; ++i)
424 {
425 e = playerslots[i];
426 if(entcs_GetName(i) == "")
427 {
428 if(e.sort_prev)
429 {
430 // player disconnected
431 SetTeam(e, -1);
432 RemovePlayer(e);
433 e.sort_prev = NULL;
434 //e.gotscores = 0;
435 }
436 }
437 else
438 {
439 if (!e.sort_prev)
440 {
441 // player connected
442 if (!e)
443 {
444 playerslots[i] = e = new_pure(playerslot);
445 }
446 e.sv_entnum = i;
447 e.ping = 0;
448 e.ping_packetloss = 0;
449 e.ping_movementloss = 0;
450 //e.gotscores = 0; // we might already have the scores...
451 int t = entcs_GetScoreTeam(i);
452 if (t) SetTeam(e, t); // will not hurt; later updates come with Scoreboard_UpdatePlayerTeams
455 }
456 }
457 }
458 this.nextthink = time + 0.2;
459}
460
462{
463 entity playerchecker = new_pure(playerchecker);
464 setthink(playerchecker, Playerchecker_Think);
465 playerchecker.nextthink = time + 0.2;
466
467 TrueAim_Init();
468
469 // this can't be called in CSQC_Init as it'd send cvars too early
470 ReplicateVars_Start();
471
472 postinit = true;
473}
474
476{
477 localcmd("-fire\n");
478 localcmd("-fire2\n");
479 localcmd("-use\n");
480 localcmd("-hook\n");
481 localcmd("-jump\n");
482 localcmd("-forward\n");
483 localcmd("-back\n");
484 localcmd("-moveleft\n");
485 localcmd("-moveright\n");
486}
487
488// CSQC_InputEvent : Used to perform actions based on any key pressed, key released and mouse on the client.
489// Return value should be 1 if CSQC handled the input, otherwise return 0 to have the input passed to the engine.
490// All keys are in ascii.
491// bInputType = 0 is key pressed, 1 is key released, 2 and 3 are mouse input.
492// In the case of keyboard input, nPrimary is the ascii code, and nSecondary is 0.
493// In the case of mouse input, nPrimary is xdelta, nSecondary is ydelta.
494// In the case of mouse input after a setcursormode(1) call, nPrimary is xpos, nSecondary is ypos.
495float CSQC_InputEvent(int bInputType, float nPrimary, float nSecondary)
496{
497 TC(int, bInputType);
498 bool override = false;
499
500 override |= HUD_Scoreboard_InputEvent(bInputType, nPrimary, nSecondary);
501 if (override)
502 return true;
503
504 override |= HUD_Panel_InputEvent(bInputType, nPrimary, nSecondary);
505 if (override)
506 return true;
507
508 override |= View_InputEvent(bInputType, nPrimary, nSecondary);
509 if (override)
510 return true;
511
512 override |= HUD_Panel_Chat_InputEvent(bInputType, nPrimary, nSecondary);
513
514 override |= QuickMenu_InputEvent(bInputType, nPrimary, nSecondary);
515
516 override |= HUD_Radar_InputEvent(bInputType, nPrimary, nSecondary);
517
518 override |= MapVote_InputEvent(bInputType, nPrimary, nSecondary);
519
520 override |= HUD_Minigame_InputEvent(bInputType, nPrimary, nSecondary);
521
522 if(override)
523 return true;
524
525 if(bInputType == 3 || bInputType == 2)
526 return false;
527
528 // at this point bInputType can only be 0 or 1 (key pressed or released)
529 bool key_pressed = (bInputType == 0);
530
531 if(key_pressed) {
532 if(nPrimary == K_ALT) hudShiftState |= S_ALT;
533 if(nPrimary == K_CTRL) hudShiftState |= S_CTRL;
534 if(nPrimary == K_SHIFT) hudShiftState |= S_SHIFT;
535 if(nPrimary == K_TAB) hudShiftState |= S_TAB;
536 }
537 else {
538 if(nPrimary == K_ALT) hudShiftState &= ~S_ALT;
539 if(nPrimary == K_CTRL) hudShiftState &= ~S_CTRL;
540 if(nPrimary == K_SHIFT) hudShiftState &= ~S_SHIFT;
541 if(nPrimary == K_TAB) hudShiftState &= ~S_TAB;
542 }
543
544 // NOTE: Shift-Escape must be filtered out because it's the hardcoded console shortcut
545 if (nPrimary == K_ESCAPE && !(hudShiftState & S_SHIFT) && key_pressed)
546 {
547 if (hudShiftState & S_TAB)
548 {
550 return true;
551 }
552 if (autocvar_menu_gamemenu && !isdemo() && cvar("_menu_gamemenu_dialog_available"))
553 {
554 localcmd("\nmenu_showgamemenudialog\n");
555 return true;
556 }
557 }
558
559 return false;
560}
561
562// END REQUIRED CSQC FUNCTIONS
563// --------------------------------------------------------------------------
564
565// --------------------------------------------------------------------------
566// BEGIN OPTIONAL CSQC FUNCTIONS
569{
570 if(this.owner) {
571 SetTeam(this.owner, -1);
572 this.owner.gotscores = 0;
573 FOREACH(Scores, true, {
574 this.owner.(scores(it)) = 0; // clear all scores
575 });
576 this.owner.ready = 0;
577 this.owner.eliminated = 0;
578 this.owner.ignored = false;
579 this.owner.colormap = 0;
580 // TODO add a hook to reset this Survival field
581 this.owner.survival_status = 0;
582 }
583}
584
585NET_HANDLE(ENT_CLIENT_SCORES, bool isnew)
586{
587 make_pure(this);
588 entity o;
589
590 // damnit -.- don't want to go change every single .sv_entnum in hud.qc AGAIN
591 // (no I've never heard of M-x replace-string, sed, or anything like that)
592 bool isNew = !this.owner; // workaround for DP bug
593 int n = ReadByte()-1;
594
595#ifdef DP_CSQC_ENTITY_REMOVE_IS_B0RKED
596 if(!isNew && n != this.sv_entnum)
597 {
598 //print("A CSQC entity changed its owner!\n");
599 LOG_INFOF("A CSQC entity changed its owner! (edict: %d, classname: %s)", etof(this), this.classname);
600 isNew = true;
601 Ent_Remove(this);
602 }
603#endif
604
605 this.sv_entnum = n;
606
607 o = playerslots[this.sv_entnum];
608 if (!o)
609 {
610 o = playerslots[this.sv_entnum] = new_pure(playerslot);
611 }
612 this.owner = o;
613 o.sv_entnum = this.sv_entnum;
614 o.gotscores = 1;
615
616 //if (!o.sort_prev)
617 // RegisterPlayer(o);
618 //playerchecker will do this for us later, if it has not already done so
619
620 int sf = ReadShort();
621 int lf = ReadShort();
622 FOREACH(Scores, true, {
623 int p = BIT(i % 16);
624 if (sf & p)
625 {
626 if (lf & p)
627 o.(scores(it)) = ReadInt24_t();
628 else
629 o.(scores(it)) = ReadChar();
630 }
631 });
632
633 return = true;
634
635 if(o.sort_prev)
636 Scoreboard_UpdatePlayerPos(o); // if not registered, we cannot do this yet!
637
638 this.entremove = Ent_RemovePlayerScore;
639}
640
641NET_HANDLE(ENT_CLIENT_TEAMSCORES, bool isnew)
642{
643 make_pure(this);
644 int i;
645
646 this.team = ReadByte();
647 entity o = this.owner = GetTeam(this.team, true); // these team numbers can always be trusted
648
649#if MAX_TEAMSCORE <= 8
650 int sf = ReadByte();
651 int lf = ReadByte();
652#else
653 int sf = ReadShort();
654 int lf = ReadShort();
655#endif
656 for(i = 0; i < MAX_TEAMSCORE; ++i)
657 if(sf & BIT(i))
658 {
659 if(lf & BIT(i))
660 o.(teamscores(i)) = ReadInt24_t();
661 else
662 o.(teamscores(i)) = ReadChar();
663 }
664
665 return = true;
666
668}
669
671{
672 for (entity pl = players.sort_next; pl; pl = pl.sort_next)
673 pl.ignored = false;
674
676
677 if (ignore_list == "")
678 return;
679
681 {
682 bool found = false;
683 int ignore_id = stoi(it);
684 for (entity pl = players.sort_next; pl; pl = pl.sort_next)
685 {
686 if (ignore_id == pl.sv_entnum + 1)
687 {
688 pl.ignored = true;
689 found = true;
690 break;
691 }
692 }
693 // when an ignored player is not found, it means their playerslot is not initialized yet
694 if (!found)
695 ignore_list_apply_time = time + 0.5; // retry after a while
696 });
697
698 if (ignore_list_apply_time == 0) // ignore_list applied
700}
701
702NET_HANDLE(ENT_CLIENT_CLIENTDATA, bool isnew)
703{
704 make_pure(this);
705 int newspectatee_status;
706
707 int f = ReadByte();
708
710
711 if(f & BIT(1))
712 {
713 newspectatee_status = ReadByte();
714 if(newspectatee_status == player_localnum + 1)
715 newspectatee_status = -1; // observing
716 }
717 else
718 newspectatee_status = 0;
719
720 spectatorbutton_zoom = (f & BIT(2));
721 observe_blocked = (f & BIT(3));
722
723 if(f & BIT(4))
724 {
726
727 float i, slot;
728
729 for(i = 0; i < MAX_SPECTATORS; ++i)
730 spectatorlist[i] = 0; // reset list first
731
732 int limit = min(num_spectators, MAX_SPECTATORS);
733 for(i = 0; i < limit; ++i)
734 {
735 slot = ReadByte();
736 spectatorlist[i] = slot - 1;
737 }
738 }
739 else
740 {
741 for(int j = 0; j < MAX_SPECTATORS; ++j)
742 spectatorlist[j] = 0; // reset list if showspectators has been turned off
743 num_spectators = 0;
744 }
745
746 return = true;
747
748 if(newspectatee_status != spectatee_status)
749 {
752 }
754 {
755 if ( (spectatee_status == -1 && newspectatee_status > 0) //before observing, now spectating
756 || (spectatee_status > 0 && newspectatee_status > 0 && spectatee_status != newspectatee_status) //changed spectated player
757 )
758 prev_p_health = -1;
759 else if(spectatee_status && !newspectatee_status) //before observing/spectating, now playing
760 prev_health = -1;
761 }
762 spectatee_status = newspectatee_status;
763
764 // we could get rid of spectatee_status, and derive it from player_localentnum and player_localnum
765
766 teamnagger = (f & 0x60) >> 5; // 0x60 = BIT(5) | BIT(6)
767
768 if (f & BIT(7))
769 {
772 }
773}
774
775NET_HANDLE(ENT_CLIENT_NAGGER, bool isnew)
776{
777 make_pure(this);
778
779 int nags = ReadByte(); // NAGS NAGS NAGS NAGS NAGS NAGS NADZ NAGS NAGS NAGS
780
781 if(!(nags & BIT(2)))
782 {
784 vote_active = 0;
785 }
786 else
787 {
788 vote_active = 1;
789 }
790
791 if(nags & BIT(6))
792 {
796 vote_highlighted = ReadChar();
797 }
798
799 if(nags & BIT(7))
800 {
802 }
803
804 if(nags & BIT(0))
805 for(int i = 0; i < maxclients;)
806 for(int f = ReadByte(), b = 0; b < 8 && i < maxclients; ++b, ++i)
807 if(playerslots[i])
808 playerslots[i].ready = f & BIT(b);
809
810 return = true;
811
812 ready_waiting = (nags & BIT(0));
813 ready_waiting_for_me = (nags & BIT(1));
814 vote_waiting = (nags & BIT(2));
815 vote_waiting_for_me = (nags & BIT(3));
816 warmup_stage = (nags & BIT(4));
817}
818
819NET_HANDLE(ENT_CLIENT_ELIMINATEDPLAYERS, bool isnew)
820{
821 make_pure(this);
822 for (int j = 0; j < maxclients; ++j) {
823 if (playerslots[j]) {
824 playerslots[j].eliminated = true;
825 }
826 }
827 for (int i = 1; i <= maxclients; i += 8) {
828 int f = ReadByte();
829 for (int b = 0; b < 8; ++b) {
830 if (f & BIT(b)) continue;
831 int j = i - 1 + b;
832 if (playerslots[j]) {
833 playerslots[j].eliminated = false;
834 }
835 }
836 }
837 return true;
838}
839
840NET_HANDLE(ENT_CLIENT_RANDOMSEED, bool isnew)
841{
842 make_pure(this);
844 float s = ReadShort();
845 psrandom(s);
846 return true;
847}
848
849NET_HANDLE(ENT_CLIENT_ACCURACY, bool isnew)
850{
851 make_pure(this);
852 int sf = ReadInt24_t();
853 if (sf == 0) {
854 for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w)
855 weapon_accuracy[w] = -1;
856 return true;
857 }
858
859 int f = 1;
860 for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w) {
861 if (sf & f) {
862 int b = ReadByte();
863 if (b == 0)
864 weapon_accuracy[w] = -1;
865 else if (b == 255)
866 weapon_accuracy[w] = 1.0; // no better error handling yet, sorry
867 else
868 weapon_accuracy[w] = (b - 1.0) / 100.0;
869 }
870 f = (f == 0x800000) ? 1 : f * 2;
871 }
872 return true;
873}
874
875// CSQC_Ent_Update : Called every frame that the server has indicated an update to the SSQC / CSQC entity has occured.
876// The parameter isnew reflects if the entity is "new" to the client, meaning it just came into the client's PVS.
877void CSQC_Ent_Update(entity this, bool isnew)
878{
879 this.sourceLoc = __FILE__":"STR(__LINE__);
880 int t = ReadByte();
881
882 // set up the "time" global for received entities to be correct for interpolation purposes
883 float savetime = time;
884 if(servertime)
885 {
887 }
888 else
889 {
891 serverdeltatime = STAT(MOVEVARS_TICRATE) * STAT(MOVEVARS_TIMESCALE);
893 }
894
895#ifdef DP_CSQC_ENTITY_REMOVE_IS_B0RKED
896 if (this.enttype)
897 {
898 if (t != this.enttype || isnew)
899 {
900 LOG_INFOF("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)", etof(this), this.entnum, this.enttype, t);
901 Ent_Remove(this);
902 ONREMOVE(this);
903 clearentity(this);
904 isnew = true;
905 }
906 }
907 else
908 {
909 if (!isnew)
910 {
911 LOG_INFOF("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)", etof(this), this.entnum, t);
912 isnew = true;
913 }
914 }
915#endif
916 this.enttype = t;
917 bool done = false;
918 FOREACH(LinkedEntities, it.m_id == t, {
919 if (isnew) this.classname = it.netname;
920 if (autocvar_developer_csqcentities)
921 LOG_INFOF("CSQC_Ent_Update(%i, %d) at %f {.entnum=%d, .enttype=%d} t=%s (%d)", this, isnew, savetime, this.entnum, this.enttype, this.classname, t);
922 done = it.m_read(this, NULL, isnew);
923 MUTATOR_CALLHOOK(Ent_Update, this, isnew);
924 break;
925 });
926 time = savetime;
927 if (!done)
928 {
929 LOG_FATALF("CSQC_Ent_Update(%i, %d) at %f {.entnum=%d, .enttype=%d} t=%s (%d)", this, isnew, savetime, this.entnum, this.enttype, this.classname, t);
930 }
931}
932
933// Destructor, but does NOT deallocate the entity by calling remove(). Also
934// used when an entity changes its type. For an entity that someone interacts
935// with others, make sure it can no longer do so.
937{
938 if(this.entremove) this.entremove(this);
939
940 if(this.skeletonindex)
941 {
942 skel_delete(this.skeletonindex);
943 this.skeletonindex = 0;
944 }
945
946 if(this.snd_looping > 0)
947 {
949 this.snd_looping = 0;
950 }
951
952 this.enttype = 0;
953 this.classname = "";
954 this.draw = func_null;
955 this.entremove = func_null;
956 // TODO possibly set more stuff to defaults
957}
958// CSQC_Ent_Remove : Called when the server requests a SSQC / CSQC entity to be removed. Essentially call remove(this) as well.
960{
961 if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Ent_Remove() with this=%i {.entnum=%d, .enttype=%d}", this, this.entnum, this.enttype);
962 if (wasfreed(this))
963 {
964 LOG_WARN("CSQC_Ent_Remove called for already removed entity. Packet loss?");
965 return;
966 }
967 if (this.enttype) Ent_Remove(this);
968 delete(this);
969}
970
972{
973 // fire game or demo start hooks here
974 if (!(calledhooks & HOOK_START))
975 {
976 if (!isdemo())
977 localcmd("\n_cl_hook_gamestart ", MapInfo_Type_ToString(gametype), "\n");
978 else
979 localcmd("\ncl_hook_demostart\n");
980
981 calledhooks |= HOOK_START; // mark start hook as fired
982 }
983}
984
985// CSQC_Parse_StuffCmd : Provides the stuffcmd string in the first parameter that the server provided. To execute standard behavior, simply execute localcmd with the string.
986void CSQC_Parse_StuffCmd(string strMessage)
987{
988 if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Parse_StuffCmd(\"%s\")", strMessage);
989 localcmd(strMessage);
990}
991
992// CSQC_Parse_Print : Provides the print string in the first parameter that the server provided. To execute standard behavior, simply execute print with the string.
993void CSQC_Parse_Print(string strMessage)
994{
995 if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Parse_Print(\"%s\")", strMessage);
996 print(ColorTranslateRGB(strMessage));
997}
998
999// CSQC_Parse_CenterPrint : Provides the centerprint_AddStandard string in the first parameter that the server provided.
1000void CSQC_Parse_CenterPrint(string strMessage)
1001{
1002 if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Parse_CenterPrint(\"%s\")", strMessage);
1003 centerprint_AddStandard(strMessage);
1004}
1005
1006// CSQC_Parse_TempEntity : Handles all temporary entity network data in the CSQC layer.
1007// You must ALWAYS first acquire the temporary ID, which is sent as a byte.
1008// Return value should be 1 if CSQC handled the temporary entity, otherwise return 0 to have the engine process the event.
1010{
1011 // Acquire TE ID
1012 int nTEID = ReadByte();
1013
1014 FOREACH(TempEntities, it.m_id == nTEID, {
1015 if (autocvar_developer_csqcentities)
1016 LOG_INFOF("CSQC_Parse_TempEntity() nTEID=%s (%d)", it.netname, nTEID);
1017 return it.m_read(NULL, NULL, true);
1018 });
1019
1021 LOG_INFOF("CSQC_Parse_TempEntity() with nTEID=%d", nTEID);
1022
1023 // No special logic for this temporary entity; return 0 so the engine can handle it
1024 return false;
1025}
1026
1031{
1033 {
1035 cvar_set("r_drawfog", "0");
1036 }
1037 else if (forcefog != "")
1038 {
1039 // using cvar_set as it's faster and safer than a command
1040 if (!autocvar_r_drawfog)
1041 cvar_set("r_drawfog", "1");
1043 cvar_set("r_fog_exp2", "0");
1044 localcmd(sprintf("\nfog %s\n", forcefog));
1045 }
1046}
1047
1049NET_HANDLE(ENT_CLIENT_SCORES_INFO, bool isnew)
1050{
1051 make_pure(this);
1052 gametype = ReadRegistered(Gametypes);
1056 FOREACH(Scores, true, {
1058 scores_flags(it) = ReadByte();
1059 });
1060 for (int i = 0; i < MAX_TEAMSCORE; ++i)
1061 {
1064 }
1065 bool welcome_msg_too = ReadByte();
1066 if (welcome_msg_too)
1068 return = true;
1070 Gametype_Init();
1071}
1072
1073NET_HANDLE(ENT_CLIENT_INIT, bool isnew)
1074{
1075 nb_pb_period = ReadByte() / 32; //Accuracy of 1/32th
1076
1085
1087
1088 armorblockpercent = ReadByte() / 255.0;
1089 damagepush_speedfactor = ReadByte() / 255.0;
1090
1092
1093 g_trueaim_minrange = ReadCoord();
1094
1095 return = true;
1096
1097 MUTATOR_CALLHOOK(Ent_Init);
1098
1099 if (!postinit) PostInit();
1100}
1101
1102float GetSpeedUnitFactor(int speed_unit)
1103{
1104 switch(speed_unit)
1105 {
1106 default:
1107 case 1: return 1.0;
1108 case 2: return 0.0254;
1109 case 3: return 0.0254 * 3.6;
1110 case 4: return 0.0254 * 3.6 * 0.6213711922;
1111 case 5: return 0.0254 * 1.943844492; // 1 m/s = 1.943844492 knots, because 1 knot = 1.852 km/h
1112 }
1113}
1114
1115string GetSpeedUnit(int speed_unit)
1116{
1117 switch(speed_unit)
1118 {
1119 // translator-friendly strings without the initial space
1120 default:
1121 case 1: return strcat(" ", _("qu/s"));
1122 case 2: return strcat(" ", _("m/s"));
1123 case 3: return strcat(" ", _("km/h"));
1124 case 4: return strcat(" ", _("mph"));
1125 case 5: return strcat(" ", _("knots"));
1126 }
1127}
1128
1129NET_HANDLE(TE_CSQC_RACE, bool isNew)
1130{
1131 int b = ReadByte();
1132
1133 switch (b)
1134 {
1140 string pbestname = ReadString();
1145 {
1149 }
1150 else
1151 strcpy(race_previousbestname, pbestname);
1152
1154
1155 if(race_checkpoint == 0 || race_checkpoint == 254)
1156 {
1158 race_laptime = time; // valid
1159 }
1160 break;
1161
1163 race_laptime = 0;
1165 break;
1166
1168 race_laptime = ReadCoord();
1169 race_checkpointtime = -99999;
1170 // fall through
1173
1175 if(b != RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING) // not while spectating (matches server)
1177 string newname = ReadString();
1179 if(b != RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING) // not while spectating (matches server)
1182 {
1185 race_mybesttime = 0;
1186 race_mybestspeed = 0;
1188 }
1189 else
1190 strcpy(race_nextbestname, newname);
1191 break;
1192
1200 int who = ReadByte();
1201 if(who)
1203 else
1204 strcpy(race_mycheckpointenemy, ""); // TODO: maybe string_null works fine here?
1205 break;
1206
1214 int what = ReadByte();
1215 if(what)
1217 else
1218 strcpy(race_othercheckpointenemy, ""); // TODO: maybe string_null works fine here?
1219 break;
1220
1224 race_penaltytime = ReadShort();
1225 string reason = ReadString();
1226 if (reason == "missing a checkpoint")
1227 reason = _("missing a checkpoint");
1228 strcpy(race_penaltyreason, reason);
1231 break;
1232
1235 break;
1239 break;
1243 break;
1246 break;
1248 float prevpos, del;
1249 int pos = ReadShort();
1250 prevpos = ReadShort();
1251 del = ReadShort();
1252
1253 // move other rankings out of the way
1254 int i;
1255 if (prevpos) {
1256 int m = min(prevpos, RANKINGS_DISPLAY_CNT);
1257 for (i=m-1; i>pos-1; --i) {
1258 grecordtime[i] = grecordtime[i-1];
1260 }
1261 } else if (del) { // a record has been deleted by the admin
1262 for (i=pos-1; i<= RANKINGS_DISPLAY_CNT-1; ++i) {
1263 if (i == RANKINGS_DISPLAY_CNT-1) { // clear out last record
1264 grecordtime[i] = 0;
1266 }
1267 else {
1268 grecordtime[i] = grecordtime[i+1];
1270 }
1271 }
1272 } else { // player has no ranked record yet
1273 for (i=RANKINGS_DISPLAY_CNT-1;i>pos-1;--i) {
1274 grecordtime[i] = grecordtime[i-1];
1276 }
1277 }
1278
1280 // kick off the player who fell from the last displayed position
1283 }
1284
1285 // store new ranking
1286 strcpy(grecordholder[pos-1], ReadString());
1287 grecordtime[pos-1] = ReadInt24_t();
1288 if(strdecolorize(grecordholder[pos-1]) == strdecolorize(entcs_GetName(player_localnum)))
1289 race_myrank = pos;
1290 break;
1292 race_status = ReadShort();
1294 }
1295 return true;
1296}
1297
1298NET_HANDLE(TE_CSQC_PINGPLREPORT, bool isNew)
1299{
1300 int i = ReadByte();
1301 int pi = ReadShort();
1302 int pl = ReadByte();
1303 int ml = ReadByte();
1304 return = true;
1305 entity e = playerslots[i];
1306 if (!e) return;
1307 e.ping = pi;
1308 e.ping_packetloss = pl / 255.0;
1309 e.ping_movementloss = ml / 255.0;
1310}
1311
1312NET_HANDLE(TE_CSQC_WEAPONCOMPLAIN, bool isNew)
1313{
1314 int weapon_id = ReadByte();
1315 complain_weapon = REGISTRY_GET(Weapons, weapon_id);
1317 return = true;
1318
1320 weapontime = time; // ping the weapon panel
1321
1322 switch(complain_weapon_type)
1323 {
1324 case 0: Local_Notification(MSG_MULTI, ITEM_WEAPON_NOAMMO, weapon_id); break;
1325 case 1: Local_Notification(MSG_MULTI, ITEM_WEAPON_DONTHAVE, weapon_id); break;
1326 default: Local_Notification(MSG_MULTI, ITEM_WEAPON_UNAVAILABLE, weapon_id); break;
1327 }
1328}
1329
1331{
1332 return build_mutator_list(s);
1333}
1334
1336{
1337 if (s == "") return s;
1338 if (s == "All Weapons Arena") return _("All Weapons Arena");
1339 if (s == "All Available Weapons Arena") return _("All Available Weapons Arena");
1340 if (s == "Most Weapons Arena") return _("Most Weapons Arena");
1341 if (s == "Most Available Weapons Arena") return _("Most Available Weapons Arena");
1342 if (s == "Dev All Weapons Arena") return s; // development option, do not translate
1343 if (s == "Dev All Available Weapons Arena") return s; // development option, do not translate
1344 if (s == "No Weapons Arena") return _("No Weapons Arena");
1345
1346 int n = tokenizebyseparator(s, " & ");
1347 string wpn_list = "";
1348 for (int i = 0; i < n; ++i)
1349 {
1350 Weapon wep = Weapon_from_name(argv(i));
1351 if (wep == WEP_Null)
1352 LOG_INFO("^3Warning: ^7server sent an invalid weapon name\n");
1353 wpn_list = cons_mid(wpn_list, " & ", wep.m_name);
1354 }
1355 if (wpn_list != "")
1356 return sprintf(_("%s Arena"), wpn_list);
1357 else
1358 return _("No Weapons Arena");
1359}
1360
1361string GetVersionMessage(string hostversion, bool version_mismatch, bool version_check)
1362{
1363 string xonotic_hostversion = strcat("Xonotic ", hostversion);
1364 if (version_mismatch)
1365 {
1366 if(!version_check)
1367 return strcat(sprintf(_("This is %s"), xonotic_hostversion), "\n^3",
1368 _("Your client version is outdated."), "\n\n\n",
1369 _("### YOU WON'T BE ABLE TO PLAY ON THIS SERVER ###"), "\n\n\n",
1370 _("Please update!"));
1371 else
1372 return strcat(sprintf(_("This is %s"), xonotic_hostversion), "\n^3",
1373 _("This server is using an outdated Xonotic version."), "\n\n\n",
1374 _("### THIS SERVER IS INCOMPATIBLE AND THUS YOU CANNOT JOIN ###"));
1375 }
1376 return sprintf(_("Welcome to %s"), xonotic_hostversion);
1377}
1378
1380{
1381 int flags = ReadByte();
1382
1383 campaign = flags & 1;
1384 if (campaign)
1385 {
1386 int campaign_level = ReadByte();
1387 // Menu can't build the whole campaign message because it lacks getcommandkey and CCR
1388 // so we build part of the message here and let the menu insert the level description
1389 // (that client doesn't know) by replacing the keyword _LEVEL_DESC
1390 string key = getcommandkey(_("jump"), "+jump");
1391 string msg = strcat(
1392 CCR("^F1"), sprintf(_("Level %d:"), campaign_level),
1393 sprintf(CCR(" ^BG%s\n\n"), "_LEVEL_DESC"),
1394 sprintf(CCR(_("^BGPress ^F2%s^BG to enter the game")), key));
1395 msg = MakeConsoleSafe(strreplace("\n", "\\n", msg));
1396 string welcomedialog_args = strcat("CAMPAIGN ", itos(campaign_level), " \"", msg, "\"");
1397
1398 localcmd("\nmenu_cmd directmenu Welcome ", welcomedialog_args, "\n");
1399 return true;
1400 }
1401
1403 string hostversion = ReadString();
1404 bool version_mismatch = flags & 2;
1405 bool version_check = flags & 4;
1407 MapInfo_Map_author = flags & 8 ? ReadString() : "";
1410 string modifications = translate_modifications(ReadString());
1411 string weaponarena_list = translate_weaponarena(ReadString());
1412 string cache_mutatormsg = ReadString();
1413 string motd = ReadString();
1414
1415 string msg = GetVersionMessage(hostversion, version_mismatch, version_check);
1416
1417 msg = strcat(msg, "\n\n", _("Gametype:"), " ^1", MapInfo_Type_ToText(gametype), "\n");
1418
1419 msg = strcat(msg, "\n", _("Map:"), " ", MapInfo_Map_titlestring, "\n");
1420 if (flags & 8)
1421 msg = strcat(msg, "^9", _("by:"), " ", MapInfo_Map_author, "\n");
1422
1424 {
1425 msg = strcat(msg, "\n", _("This match supports"), " ^5");
1427 msg = strcat(msg, sprintf(_("%d players"), srv_maxplayers), "\n");
1428 else if (srv_minplayers && srv_maxplayers)
1429 msg = strcat(msg, sprintf(_("%d to %d players"), srv_minplayers, srv_maxplayers), "\n");
1430 else if (srv_maxplayers)
1431 msg = strcat(msg, sprintf(_("%d players maximum"), srv_maxplayers), "\n");
1432 else
1433 msg = strcat(msg, sprintf(_("%d players minimum"), srv_minplayers), "\n");
1434 }
1435
1436 modifications = cons_mid(modifications, ", ", weaponarena_list);
1437 if(modifications != "")
1438 msg = strcat(msg, "\n", _("Active modifications:"), " ^3", modifications, "\n");
1439
1440 if (cache_mutatormsg != "")
1441 msg = strcat(msg, "\n", _("Special gameplay tips:"), " ^7", cache_mutatormsg, "\n");
1442 string mutator_msg = "";
1443 MUTATOR_CALLHOOK(BuildGameplayTipsString, mutator_msg);
1444 mutator_msg = M_ARGV(0, string);
1445 msg = strcat(msg, mutator_msg); // trust that the mutator will do proper formatting
1446
1447 if (motd != "")
1448 msg = strcat(msg, "\n^9↓ ", _("Server's message"), " ↓\n", motd);
1449
1450 strcpy(welcome_msg, msg);
1451 welcome_msg_menu_check_maxtime = time + 1; // wait for menu to load before showing the welcome dialog
1452 return true;
1453}
1454
1456{
1458 return;
1459
1460 // if want dialog check if menu is initialized but for a short time
1461 if (cvar("_menu_initialized") == 2 || time > welcome_msg_menu_check_maxtime)
1462 {
1463 if (cvar("_menu_welcome_dialog_available"))
1464 {
1465 string welcomedialog_args = strcat("HOSTNAME \"", hostname, "\"");
1466 string msg = MakeConsoleSafe(strreplace("\n", "\\n", welcome_msg));
1467 welcomedialog_args = strcat(welcomedialog_args, " WELCOME \"", msg, "\"");
1468
1470 {
1471 if (cvar("_menu_cmd_closemenu_available"))
1472 {
1473 // initialize the dialog without opening it
1474 localcmd("\nmenu_cmd closemenu Welcome ", welcomedialog_args, "\n");
1475 }
1476 else
1477 {
1478 // legacy code for clients with old menus
1479 // since togglemenu 0 doesn't close the dialog but only hides it,
1480 // playing back a demo the Welcome dialog will pop up on the first ESC press
1481 localcmd("\nmenu_cmd directmenu Welcome ", welcomedialog_args, "\n");
1482 // close it after it's been initialized so it can still be opened manually
1483 localcmd("\ntogglemenu 0\n");
1484 }
1485 }
1486 else
1487 localcmd("\nmenu_cmd directmenu Welcome ", welcomedialog_args, "\n");
1488 }
1489
1492 }
1493}
1494
1495NET_HANDLE(TE_CSQC_SERVERWELCOME, bool isNew)
1496{
1497 return net_handle_ServerWelcome();
1498}
1499
1500string _getcommandkey(string cmd_name, string command, bool forcename)
1501{
1503 return cmd_name;
1504
1505 string key, keys = db_get(binddb, command);
1506 int n, j, found = 0;
1507 float k;
1508
1509 if (keys == "")
1510 {
1511 const bool joy_active = cvar("joy_active");
1512 n = tokenize(findkeysforcommand(command, 0)); // uses '...' strings
1513 for (j = 0; j < n; ++j)
1514 {
1515 k = stof(argv(j));
1516 if (k == -1)
1517 continue;
1518 key = keynumtostring(k);
1519 if (!joy_active && startsWith(key, "JOY"))
1520 continue;
1521
1522 keys = cons_mid(keys, ", ", translate_key(key));
1523
1525 break;
1526 }
1527 if (keys == "")
1528 keys = "NO_KEY";
1529 db_put(binddb, command, keys);
1530 }
1531
1532 if (keys == "NO_KEY")
1533 {
1534 if (autocvar_hud_showbinds > 1)
1535 return sprintf(_("%s (not bound)"), cmd_name);
1536 else
1537 return cmd_name;
1538 }
1539 else if (autocvar_hud_showbinds > 1 || forcename)
1540 return sprintf("%s (%s)", cmd_name, keys);
1541 return keys;
1542}
1543
1545void URI_Get_Callback(int id, int status, string data)
1546{
1547 TC(int, id); TC(int, status);
1548 if(url_URI_Get_Callback(id, status, data))
1549 {
1550 // handled
1551 }
1552 else if (id == URI_GET_DISCARD)
1553 {
1554 // discard
1555 }
1556 else if (id >= URI_GET_CURL && id <= URI_GET_CURL_END)
1557 {
1558 // sv_cmd curl
1559 Curl_URI_Get_Callback(id, status, data);
1560 }
1561 else
1562 {
1563 LOG_INFOF("Received HTTP request data for an invalid id %d.", id);
1564 }
1565}
entity parent
Definition animhost.qc:7
vector arc_shotorigin[4]
Definition arc.qh:108
#define MUTATOR_CALLHOOK(id,...)
Definition base.qh:143
#define BIT(n)
Only ever assign into the first 24 bits in QC (so max is BIT(23)).
Definition bits.qh:8
void centerprint_AddStandard(string strMessage)
void CheckEngineExtensions(void)
var entity(vector mins, vector maxs,.entity tofield) findbox_tofield_OrFallback
void ConsoleCommand_macro_init()
Definition cl_cmd.qc:605
void deactivate_minigame()
#define ReadString
void HUD_MinigameMenu_Close(entity this, entity actor, entity trigger)
float HUD_Minigame_InputEvent(float bInputType, float nPrimary, float nSecondary)
float nb_pb_period
Definition cl_nexball.qh:7
fields which are explicitly/manually set are marked with "M", fields set automatically are marked wit...
Definition weapon.qh:42
string m_name
M: wepname : human readable name.
Definition weapon.qh:86
#define draw_endBoldFont()
Definition draw.qh:5
float HUD_Panel_Chat_InputEvent(float bInputType, float nPrimary, float nSecondary)
Definition chat.qc:14
string _getcommandkey(string cmd_name, string command, bool forcename)
Definition main.qc:1500
void Fog_Force()
Definition main.qc:1030
void CSQC_Parse_CenterPrint(string strMessage)
Definition main.qc:1000
void Ent_Remove(entity this)
Definition main.qc:936
void RemovePlayer(entity player)
Definition main.qc:259
string GetVersionMessage(string hostversion, bool version_mismatch, bool version_check)
Definition main.qc:1361
void AuditLists()
Definition main.qc:225
void Gametype_Init()
Definition main.qc:971
float has_team
Definition main.qc:345
void Welcome_Message_Show_Try()
Definition main.qc:1455
string GetSpeedUnit(int speed_unit)
Definition main.qc:1115
void Release_Common_Keys()
Definition main.qc:475
void PostInit()
Definition main.qc:461
int survival_status
Definition main.qc:567
void Ent_RemovePlayerScore(entity this)
Definition main.qc:568
bool net_handle_ServerWelcome()
Definition main.qc:1379
float RegisterTeam(entity Team)
Definition main.qc:290
void Playerchecker_Think(entity this)
Definition main.qc:419
bool CSQC_Parse_TempEntity()
Definition main.qc:1009
string translate_modifications(string s)
Definition main.qc:1330
void CSQC_Parse_Print(string strMessage)
Definition main.qc:993
string translate_weaponarena(string s)
Definition main.qc:1335
entity GetTeam(int Team, bool add)
Definition main.qc:330
void MoveToLast(entity e)
Definition main.qc:278
void Shutdown()
Definition main.qc:162
bool autocvar_r_fog_exp2
Definition main.qc:1028
string forcefog
Definition main.qc:1029
bool SetTeam(entity o, int Team)
Definition main.qc:346
void URI_Get_Callback(int id, int status, string data)
engine callback
Definition main.qc:1545
void CSQC_Parse_StuffCmd(string strMessage)
Definition main.qc:986
float RegisterPlayer(entity player)
Definition main.qc:243
bool autocvar_r_drawfog
Definition main.qc:1027
void RemoveTeam(entity Team)
Definition main.qc:309
void ignore_list_apply()
Definition main.qc:670
float GetSpeedUnitFactor(int speed_unit)
Definition main.qc:1102
int enttype
Definition main.qh:185
entity playerslots[255]
Definition main.qh:84
float g_trueaim_minrange
Definition main.qh:171
int ClientProgsDB
Definition main.qh:204
float spectatee_status_changed_time
Definition main.qh:198
int srv_maxplayers
Definition main.qh:126
bool autocvar_developer_csqcentities
Definition main.qh:14
bool autocvar_cl_db_saveasdump
Definition main.qh:6
bool autocvar_cl_welcome
Definition main.qh:31
bool vote_waiting_for_me
Definition main.qh:146
float grecordtime[RANKINGS_CNT]
Definition main.qh:82
int calledhooks
Definition main.qh:164
bool autocvar_cl_race_cptimes_onlyself
Definition main.qh:29
bool ready_waiting
Definition main.qh:143
bool autocvar_menu_gamemenu
Definition main.qh:34
string hostname
Definition main.qh:123
entity players
Definition main.qh:57
entity owner
Definition main.qh:87
int spectatorlist[MAX_SPECTATORS]
Definition main.qh:178
float armorblockpercent
Definition main.qh:160
string gametype_custom_name
Definition main.qh:44
bool postinit
Definition main.qh:42
int binddb
Definition main.qh:191
#define getcommandkey(cmd_name, command)
Definition main.qh:137
float chase_active_backup
Definition main.qh:154
float welcome_msg_menu_check_maxtime
Definition main.qh:127
bool autocvar_hud_showbinds
Definition main.qh:11
bool observe_blocked
Definition main.qh:115
const int HOOK_START
Definition main.qh:165
entity teamslots[17]
Definition main.qh:85
int spectatee_status
the -1 disables HUD panels before CSQC receives necessary data
Definition main.qh:197
string ignore_list
Definition main.qh:130
string grecordholder[RANKINGS_CNT]
Definition main.qh:81
bool warmup_stage
Definition main.qh:120
entity gametype
Definition main.qh:43
int sv_entnum
Definition main.qh:186
int tempdb
Definition main.qh:203
vector mi_scale
Definition main.qh:38
int serverflags
Definition main.qh:211
vector mi_center
Definition main.qh:37
vector hook_shotorigin[4]
Definition main.qh:205
bool vote_waiting
Definition main.qh:145
float team_count
Definition main.qh:59
float RANKINGS_DISPLAY_CNT
Definition main.qh:80
string vote_called_vote
Definition main.qh:142
int team
Definition main.qh:188
float damagepush_speedfactor
Definition main.qh:161
const int HOOK_END
Definition main.qh:166
bool autocvar_hud_showbinds_limit
Definition main.qh:12
entity teams
Definition main.qh:58
int num_spectators
Definition main.qh:176
int srv_minplayers
Definition main.qh:125
float serverdeltatime
Definition main.qh:207
string minimapname
Definition main.qh:40
float camera_active
Definition main.qh:153
float serverprevtime
Definition main.qh:207
bool spectatorbutton_zoom
Definition main.qh:114
bool ignore_list_apply_time
Definition main.qh:131
bool campaign
Definition main.qh:122
string welcome_msg
Definition main.qh:124
bool ready_waiting_for_me
Definition main.qh:144
const int MAX_SPECTATORS
Definition main.qh:177
float MapVote_InputEvent(int bInputType, float nPrimary, float nSecondary)
Definition mapvoting.qc:930
#define M_ARGV(x, type)
Definition events.qh:17
#define scores_label(this)
Definition scores.qh:146
#define MAX_TEAMSCORE
Definition scores.qh:149
#define teamscores_flags(i)
Definition scores.qh:156
#define teamscores_label(i)
Definition scores.qh:154
#define scores_flags(this)
Definition scores.qh:147
void get_mi_min_max_texcoords(float mode)
Definition util.qc:764
string translate_key(string key)
Definition util.qc:1610
float cvar_settemp(string tmp_cvar, string tmp_value)
Definition util.qc:807
vector decompressShotOrigin(int f)
Definition util.qc:1375
string mi_shortname
Definition util.qh:126
vector mi_min
Definition util.qh:127
vector mi_max
Definition util.qh:128
void TrueAim_Init()
Definition crosshair.qc:44
bool autocvar_cl_reticle
Definition crosshair.qh:3
string classname
float flags
float maxclients
float player_localnum
float CVAR_TYPEFLAG_EXISTS
float skeletonindex
float time
float nextthink
float intermission
float entnum
int snd_looping
float autocvar_cl_jetpack_attenuation
ERASEABLE string MakeConsoleSafe(string input)
escape the string to make it safe for consoles
Definition cvar.qh:24
#define tokenizebyseparator
string entcs_GetName(int i)
Definition ent_cs.qh:151
int entcs_GetScoreTeam(int i)
Same as entcs_GetTeam, but returns -1 for no team in teamplay.
Definition ent_cs.qh:141
void Curl_URI_Get_Callback(int id, float status, string data)
Definition generic.qc:31
Weapons
Definition guide.qh:113
bool autocvar_hud_panel_healtharmor_progressbar_gfx
void LoadMenuSkinValues()
Definition hud.qc:42
int vote_highlighted
Definition hud.qh:96
int vote_nocount
Definition hud.qh:94
float HUD_Radar_InputEvent(float bInputType, float nPrimary, float nSecondary)
int vote_needed
Definition hud.qh:95
int vote_active
Definition hud.qh:98
int complain_weapon_type
Definition hud.qh:114
const int S_SHIFT
Definition hud.qh:129
int hudShiftState
Definition hud.qh:128
const int S_ALT
Definition hud.qh:131
int teamnagger
Definition hud.qh:126
float hud_dynamic_shake_factor
Definition hud.qh:214
string autocvar_hud_skin
Definition hud.qh:203
int vote_yescount
Definition hud.qh:93
entity complain_weapon
Definition hud.qh:113
int prev_health
Definition hud.qh:243
void HUD_ModIcons_SetFunc()
Definition modicons.qc:19
float complain_weapon_time
Definition hud.qh:115
int weapon_accuracy[REGISTRY_MAX(Weapons)]
Definition hud.qh:111
string hud_skin_path
Definition hud.qh:136
int prev_p_health
Definition hud.qh:246
float weapontime
Definition hud.qh:122
const int S_TAB
Definition hud.qh:132
const int S_CTRL
Definition hud.qh:130
float HUD_Panel_InputEvent(float bInputType, float nPrimary, float nSecondary)
string prvm_language
Definition i18n.qh:8
prev
Definition all.qh:73
#define stoi(s)
Definition int.qh:4
#define itos(i)
Definition int.qh:6
#define FOREACH_WORD(words, cond, body)
Definition iter.qh:33
#define FOREACH(list, cond, body)
Definition iter.qh:19
float K_SHIFT
Definition keycodes.qc:22
float K_CTRL
Definition keycodes.qc:21
float K_ALT
Definition keycodes.qc:20
float K_TAB
Definition keycodes.qc:7
float K_ESCAPE
Definition keycodes.qc:9
#define CSQC_Init
Definition _all.inc:290
#define CSQC_InputEvent
Definition _all.inc:305
#define CSQC_Ent_Remove
Definition _all.inc:316
#define TC(T, sym)
Definition _all.inc:82
#define CSQC_Ent_Update
Definition _all.inc:313
#define ReadFloat()
Definition net.qh:349
#define NET_HANDLE(id, param)
Definition net.qh:15
float servertime
Definition net.qh:330
int ReadInt24_t()
Definition net.qh:338
#define ReadRegistered(r)
Definition net.qh:291
int ReadByte()
const int REPLICATEVARS_DESTROY
Definition replicate.qh:6
#define STAT(...)
Definition stats.qh:82
void WarpZone_Shutdown()
Definition client.qc:289
#define LOG_FATALF(...)
Definition log.qh:54
#define LOG_TRACEF(...)
Definition log.qh:77
#define LOG_INFO(...)
Definition log.qh:65
#define LOG_INFOF(...)
Definition log.qh:66
#define LOG_WARN(...)
Definition log.qh:61
#define assert_once(expr,...)
Definition log.qh:11
#define STR(it)
Definition macro.qh:20
ERASEABLE void db_close(int db)
Definition map.qh:84
ERASEABLE int db_load(string filename)
Definition map.qh:35
ERASEABLE int db_create()
Definition map.qh:25
ERASEABLE void db_save(int db, string filename)
Definition map.qh:8
ERASEABLE string db_get(int db, string key)
Definition map.qh:91
ERASEABLE void db_put(int db, string key, string value)
Definition map.qh:101
ERASEABLE void db_dump(int db, string filename)
Definition map.qh:69
string MapInfo_Type_ToString(Gametype t)
Definition mapinfo.qc:655
string MapInfo_Type_ToText(Gametype t)
Definition mapinfo.qc:660
float _MapInfo_GetTeamPlayBool(Gametype t)
Definition mapinfo.qc:538
string MapInfo_Map_author
Definition mapinfo.qh:10
string MapInfo_Map_titlestring
Definition mapinfo.qh:8
string cmd_name
Definition events.qh:12
float registercvar(string name, string value, float flags)
void localcmd(string command,...)
void cvar_set(string name, string value)
float isdemo()
float stof(string val,...)
float cvar(string name)
string keynumtostring(float keynum)
string precache_pic(string name,...)
const string cvar_string(string name)
float min(float f,...)
string ftos(float f)
void eprint(entity e)
void print(string text,...)
const string cvar_defstring(string name)
float tokenize(string s)
string strzone(string s)
string argv(float n)
#define etof(e)
Definition misc.qh:25
@ RACE_NET_CHECKPOINT_HIT_RACE_BY_OPPONENT
Definition net_linked.qh:18
@ RACE_NET_SPEED_AWARD_BEST
Definition net_linked.qh:24
@ RACE_NET_CHECKPOINT_NEXT_QUALIFYING
Definition net_linked.qh:16
@ RACE_NET_PENALTY_QUALIFYING
Definition net_linked.qh:21
@ RACE_NET_SPEED_AWARD
Definition net_linked.qh:23
@ RACE_NET_CHECKPOINT_CLEAR
Definition net_linked.qh:15
@ RACE_NET_SERVER_RANKINGS
Definition net_linked.qh:25
@ RACE_NET_RANKINGS_CNT
Definition net_linked.qh:29
@ RACE_NET_PENALTY_RACE
Definition net_linked.qh:20
@ RACE_NET_CHECKPOINT_HIT_RACE
Definition net_linked.qh:17
@ RACE_NET_SERVER_RECORD
Definition net_linked.qh:22
@ RACE_NET_SERVER_STATUS
Definition net_linked.qh:26
@ RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING
Definition net_linked.qh:19
@ RACE_NET_CHECKPOINT_HIT_QUALIFYING
Definition net_linked.qh:14
var void func_null()
strcat(_("^F4Countdown stopped!"), "\n^BG", _("Teams are too unbalanced."))
void Local_Notification(MSG net_type, Notification net_name,...count)
Definition all.qc:1236
void ReplicateVars(bool would_destroy)
Definition all.qh:895
#define make_pure(e)
direct use is
Definition oo.qh:13
void clearentity(entity e)
Definition oo.qh:97
#define new_pure(class)
purely logical entities (not linked to the area grid)
Definition oo.qh:67
string sourceLoc
Location entity was spawned from in source.
Definition oo.qh:27
#define NULL
Definition post.qh:14
#define error
Definition pre.qh:6
bool QuickMenu_InputEvent(int bInputType, float nPrimary, float nSecondary)
Definition quickmenu.qc:485
float race_myrank
Definition racetimer.qh:49
float race_othercheckpointtime
Definition racetimer.qh:42
string race_othercheckpointenemy
Definition racetimer.qh:45
float race_nextcheckpoint
Definition racetimer.qh:19
float race_othercheckpoint
Definition racetimer.qh:41
float race_penaltyaccumulator
Definition racetimer.qh:25
float race_speedaward_alltimebest
Definition racetimer.qh:32
float race_server_record
Definition racetimer.qh:29
float race_mycheckpointlapsdelta
Definition racetimer.qh:39
string race_penaltyreason
Definition racetimer.qh:28
string race_speedaward_holder
Definition racetimer.qh:31
string race_speedaward_alltimebest_holder
Definition racetimer.qh:33
string race_status_name
Definition racetimer.qh:48
bool scoreboard_showscores_force
Definition racetimer.qh:46
float race_nextbestspeed
Definition racetimer.qh:21
string race_nextbestname
Definition racetimer.qh:24
float race_mybestspeed
Definition racetimer.qh:23
float race_checkpoint
Definition racetimer.qh:8
string race_mycheckpointenemy
Definition racetimer.qh:40
float race_othercheckpointdelta
Definition racetimer.qh:43
float race_previousbesttime
Definition racetimer.qh:16
float race_nextbesttime
Definition racetimer.qh:20
float race_mypreviousbesttime
Definition racetimer.qh:17
float race_time
Definition racetimer.qh:9
float race_penaltytime
Definition racetimer.qh:27
float race_status
Definition racetimer.qh:47
float race_mybesttime
Definition racetimer.qh:22
float race_timebestspeed
Definition racetimer.qh:11
float race_timespeed
Definition racetimer.qh:10
float race_mycheckpoint
Definition racetimer.qh:36
float race_checkpointtime
Definition racetimer.qh:13
float race_mycheckpointtime
Definition racetimer.qh:37
float race_othercheckpointlapsdelta
Definition racetimer.qh:44
float race_penaltyeventtime
Definition racetimer.qh:26
float race_mycheckpointdelta
Definition racetimer.qh:38
string race_previousbestname
Definition racetimer.qh:18
float race_speedaward
Definition racetimer.qh:30
float race_laptime
Definition racetimer.qh:12
void psrandom(float seed)
Definition random.qc:135
#define prandom_debug()
Definition random.qh:44
#define REGISTRY_GET(id, i)
Definition registry.qh:43
void Scoreboard_UpdatePlayerPos(entity player)
void Scoreboard_InitScores()
float HUD_Scoreboard_InputEvent(float bInputType, float nPrimary, float nSecondary)
void Scoreboard_UI_Enable(int mode)
void Scoreboard_UpdateTeamPos(entity Team)
#define setthink(e, f)
float campaign_level
Definition campaign.qc:17
ERASEABLE entity Sort_Spawn()
Definition sortlist.qc:4
#define SORT_SWAP(a, b)
Swap two neighbours in a sortlist.
Definition sortlist.qh:14
const float VOL_BASE
Definition sound.qh:36
#define sound(e, c, s, v, a)
Definition sound.qh:52
#define static_init_late()
Definition static.qh:38
#define static_init_precache()
Definition static.qh:43
#define static_init()
Definition static.qh:33
void ONREMOVE(entity this)
ERASEABLE string ColorTranslateRGB(string s)
Definition string.qh:196
#define strfree(this)
Definition string.qh:59
string CCR(string input)
color code replace, place inside of sprintf and parse the string
Definition string.qh:216
ERASEABLE string cons_mid(string a, string mid, string b)
Definition string.qh:284
#define startsWith(haystack, needle)
Definition string.qh:236
#define strcpy(this, s)
Definition string.qh:52
const int NUM_TEAM_2
Definition teams.qh:14
const int NUM_SPECTATOR
Definition teams.qh:23
const int NUM_TEAM_4
Definition teams.qh:16
const int NUM_TEAM_3
Definition teams.qh:15
bool teamplay
Definition teams.qh:59
const int NUM_TEAM_1
Definition teams.qh:13
ERASEABLE float url_URI_Get_Callback(int id, float status, string data)
Definition urllib.qc:28
const int URI_GET_CURL
Definition urllib.qh:7
const int URI_GET_DISCARD
Definition urllib.qh:4
const int URI_GET_CURL_END
Definition urllib.qh:8
bool View_InputEvent(int bInputType, float nPrimary, float nSecondary)
Definition view.qc:465
bool autocvar_cl_orthoview
Definition view.qh:21
bool autocvar_cl_orthoview_nofog
Definition view.qh:22
int autocvar_chase_active
Definition view.qh:17
bool autocvar_r_drawviewmodel
Definition view.qh:97
bool autocvar_cl_lockview
Definition view.qh:20
Weapon Weapon_from_name(string s)
Definition all.qh:144
#define WEP_LAST
Definition all.qh:343
const int WEP_FIRST
Definition all.qh:342
string cache_mutatormsg
Definition world.qh:69