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;
228 entity prev;
229
230 prev = players;
231 for(e = prev.sort_next; e; prev = e, e = e.sort_next)
232 {
233 if(prev != e.sort_prev)
234 error(strcat("sort list chain error\nplease submit the output of 'prvm_edicts client' to the developers"));
235 }
236
237 prev = teams;
238 for(e = prev.sort_next; e; prev = e, e = e.sort_next)
239 {
240 if(prev != e.sort_prev)
241 error(strcat("sort list chain error\nplease submit the output of 'prvm_edicts client' to the developers"));
242 }
243}
244
246{
247 entity pl;
248 AuditLists();
249 for(pl = players.sort_next; pl; pl = pl.sort_next)
250 if(pl == player)
251 error("Player already registered!");
252 player.sort_next = players.sort_next;
253 player.sort_prev = players;
254 if(players.sort_next)
255 players.sort_next.sort_prev = player;
256 players.sort_next = player;
257 AuditLists();
258 return true;
259}
260
262{
263 entity pl, parent;
264 AuditLists();
265 parent = players;
266 for(pl = players.sort_next; pl && pl != player; pl = pl.sort_next)
267 parent = pl;
268
269 if(!pl)
270 {
271 error("Trying to remove a player which is not in the playerlist!");
272 return;
273 }
274 parent.sort_next = player.sort_next;
275 if(player.sort_next)
276 player.sort_next.sort_prev = parent;
277 AuditLists();
278}
279
281{
282 AuditLists();
283 entity ent = e.sort_next;
284 while(ent)
285 {
286 SORT_SWAP(ent, e);
287 ent = e.sort_next;
288 }
289 AuditLists();
290}
291
293{
294 assert_once(Team.team, eprint(Team));
295 entity tm;
296 AuditLists();
297 for(tm = teams.sort_next; tm; tm = tm.sort_next)
298 if(tm == Team)
299 error("Team already registered!");
300 Team.sort_next = teams.sort_next;
301 Team.sort_prev = teams;
302 if(teams.sort_next)
303 teams.sort_next.sort_prev = Team;
304 teams.sort_next = Team;
305 if(Team.team && Team.team != NUM_SPECTATOR)
306 ++team_count;
307 AuditLists();
308 return true;
309}
310
312{
313 entity tm, parent;
314 AuditLists();
315 parent = teams;
316 for(tm = teams.sort_next; tm && tm != Team; tm = tm.sort_next)
317 parent = tm;
318
319 if(!tm)
320 {
321 LOG_INFO(_("Trying to remove a team which is not in the teamlist!"));
322 return;
323 }
324 parent.sort_next = Team.sort_next;
325 if(Team.sort_next)
326 Team.sort_next.sort_prev = parent;
327 if(Team.team && Team.team != NUM_SPECTATOR)
328 --team_count;
329 AuditLists();
330}
331
332entity GetTeam(int Team, bool add)
333{
334 TC(int, Team); TC(bool, add);
335 int num = (Team == NUM_SPECTATOR) ? 16 : Team;
336 if(teamslots[num])
337 return teamslots[num];
338 if (!add)
339 return NULL;
340 entity tm = new_pure(team);
341 tm.team = Team;
342 teamslots[num] = tm;
343 RegisterTeam(tm);
344 return tm;
345}
346
347.float has_team;
348bool SetTeam(entity o, int Team)
349{
350 TC(int, Team);
351 //devassert_once(Team);
352 entity tm;
353 if(teamplay)
354 {
355 switch(Team)
356 {
357 case -1:
358 case NUM_TEAM_1:
359 case NUM_TEAM_2:
360 case NUM_TEAM_3:
361 case NUM_TEAM_4:
362 break;
363 default:
364 if(GetTeam(Team, false) == NULL)
365 {
366 LOG_TRACEF("trying to switch to unsupported team %d", Team);
367 Team = NUM_SPECTATOR;
368 }
369 break;
370 }
371 }
372 else
373 {
374 switch(Team)
375 {
376 case -1:
377 case 0:
378 break;
379 default:
380 if(GetTeam(Team, false) == NULL)
381 {
382 LOG_TRACEF("trying to switch to unsupported team %d", Team);
383 Team = NUM_SPECTATOR;
384 }
385 break;
386 }
387 }
388 if(Team == -1) // leave
389 {
390 if(o.has_team)
391 {
392 tm = GetTeam(o.team, false);
393 tm.team_size -= 1;
394 o.has_team = 0;
395 return true;
396 }
397 }
398 else
399 {
400 if (!o.has_team)
401 {
402 o.team = Team;
403 tm = GetTeam(Team, true);
404 tm.team_size += 1;
405 o.has_team = 1;
406 return true;
407 }
408 else if(Team != o.team)
409 {
410 tm = GetTeam(o.team, false);
411 tm.team_size -= 1;
412 o.team = Team;
413 tm = GetTeam(Team, true);
414 tm.team_size += 1;
415 return true;
416 }
417 }
418 return false;
419}
420
422{
423 int i;
424 entity e;
425 for(i = 0; i < maxclients; ++i)
426 {
427 e = playerslots[i];
428 if(entcs_GetName(i) == "")
429 {
430 if(e.sort_prev)
431 {
432 // player disconnected
433 SetTeam(e, -1);
434 RemovePlayer(e);
435 e.sort_prev = NULL;
436 //e.gotscores = 0;
437 }
438 }
439 else
440 {
441 if (!e.sort_prev)
442 {
443 // player connected
444 if (!e)
445 {
446 playerslots[i] = e = new_pure(playerslot);
447 }
448 e.sv_entnum = i;
449 e.ping = 0;
450 e.ping_packetloss = 0;
451 e.ping_movementloss = 0;
452 //e.gotscores = 0; // we might already have the scores...
453 int t = entcs_GetScoreTeam(i);
454 if (t) SetTeam(e, t); // will not hurt; later updates come with Scoreboard_UpdatePlayerTeams
457 }
458 }
459 }
460 this.nextthink = time + 0.2;
461}
462
464{
465 entity playerchecker = new_pure(playerchecker);
466 setthink(playerchecker, Playerchecker_Think);
467 playerchecker.nextthink = time + 0.2;
468
469 TrueAim_Init();
470
471 // this can't be called in CSQC_Init as it'd send cvars too early
472 ReplicateVars_Start();
473
474 postinit = true;
475}
476
478{
479 localcmd("-fire\n");
480 localcmd("-fire2\n");
481 localcmd("-use\n");
482 localcmd("-hook\n");
483 localcmd("-jump\n");
484 localcmd("-forward\n");
485 localcmd("-back\n");
486 localcmd("-moveleft\n");
487 localcmd("-moveright\n");
488}
489
490// CSQC_InputEvent : Used to perform actions based on any key pressed, key released and mouse on the client.
491// Return value should be 1 if CSQC handled the input, otherwise return 0 to have the input passed to the engine.
492// All keys are in ascii.
493// bInputType = 0 is key pressed, 1 is key released, 2 and 3 are mouse input.
494// In the case of keyboard input, nPrimary is the ascii code, and nSecondary is 0.
495// In the case of mouse input, nPrimary is xdelta, nSecondary is ydelta.
496// In the case of mouse input after a setcursormode(1) call, nPrimary is xpos, nSecondary is ypos.
497float CSQC_InputEvent(int bInputType, float nPrimary, float nSecondary)
498{
499 TC(int, bInputType);
500 bool override = false;
501
502 override |= HUD_Scoreboard_InputEvent(bInputType, nPrimary, nSecondary);
503 if (override)
504 return true;
505
506 override |= HUD_Panel_InputEvent(bInputType, nPrimary, nSecondary);
507 if (override)
508 return true;
509
510 override |= View_InputEvent(bInputType, nPrimary, nSecondary);
511 if (override)
512 return true;
513
514 override |= HUD_Panel_Chat_InputEvent(bInputType, nPrimary, nSecondary);
515
516 override |= QuickMenu_InputEvent(bInputType, nPrimary, nSecondary);
517
518 override |= HUD_Radar_InputEvent(bInputType, nPrimary, nSecondary);
519
520 override |= MapVote_InputEvent(bInputType, nPrimary, nSecondary);
521
522 override |= HUD_Minigame_InputEvent(bInputType, nPrimary, nSecondary);
523
524 if(override)
525 return true;
526
527 if(bInputType == 3 || bInputType == 2)
528 return false;
529
530 // at this point bInputType can only be 0 or 1 (key pressed or released)
531 bool key_pressed = (bInputType == 0);
532
533 if(key_pressed) {
534 if(nPrimary == K_ALT) hudShiftState |= S_ALT;
535 if(nPrimary == K_CTRL) hudShiftState |= S_CTRL;
536 if(nPrimary == K_SHIFT) hudShiftState |= S_SHIFT;
537 if(nPrimary == K_TAB) hudShiftState |= S_TAB;
538 }
539 else {
540 if(nPrimary == K_ALT) hudShiftState &= ~S_ALT;
541 if(nPrimary == K_CTRL) hudShiftState &= ~S_CTRL;
542 if(nPrimary == K_SHIFT) hudShiftState &= ~S_SHIFT;
543 if(nPrimary == K_TAB) hudShiftState &= ~S_TAB;
544 }
545
546 // NOTE: Shift-Escape must be filtered out because it's the hardcoded console shortcut
547 if (nPrimary == K_ESCAPE && !(hudShiftState & S_SHIFT) && key_pressed)
548 {
549 if (hudShiftState & S_TAB)
550 {
552 return true;
553 }
554 if (autocvar_menu_gamemenu && !isdemo() && cvar("_menu_gamemenu_dialog_available"))
555 {
556 localcmd("\nmenu_showgamemenudialog\n");
557 return true;
558 }
559 }
560
561 return false;
562}
563
564// END REQUIRED CSQC FUNCTIONS
565// --------------------------------------------------------------------------
566
567// --------------------------------------------------------------------------
568// BEGIN OPTIONAL CSQC FUNCTIONS
571{
572 if(this.owner) {
573 SetTeam(this.owner, -1);
574 this.owner.gotscores = 0;
575 FOREACH(Scores, true, {
576 this.owner.(scores(it)) = 0; // clear all scores
577 });
578 this.owner.ready = 0;
579 this.owner.eliminated = 0;
580 this.owner.ignored = false;
581 this.owner.colormap = 0;
582 // TODO add a hook to reset this Survival field
583 this.owner.survival_status = 0;
584 }
585}
586
587NET_HANDLE(ENT_CLIENT_SCORES, bool isnew)
588{
589 make_pure(this);
590 entity o;
591
592 // damnit -.- don't want to go change every single .sv_entnum in hud.qc AGAIN
593 // (no I've never heard of M-x replace-string, sed, or anything like that)
594 bool isNew = !this.owner; // workaround for DP bug
595 int n = ReadByte()-1;
596
597#ifdef DP_CSQC_ENTITY_REMOVE_IS_B0RKED
598 if(!isNew && n != this.sv_entnum)
599 {
600 //print("A CSQC entity changed its owner!\n");
601 LOG_INFOF("A CSQC entity changed its owner! (edict: %d, classname: %s)", etof(this), this.classname);
602 isNew = true;
603 Ent_Remove(this);
604 }
605#endif
606
607 this.sv_entnum = n;
608
609 o = playerslots[this.sv_entnum];
610 if (!o)
611 {
612 o = playerslots[this.sv_entnum] = new_pure(playerslot);
613 }
614 this.owner = o;
615 o.sv_entnum = this.sv_entnum;
616 o.gotscores = 1;
617
618 //if (!o.sort_prev)
619 // RegisterPlayer(o);
620 //playerchecker will do this for us later, if it has not already done so
621
622 int sf = ReadShort();
623 int lf = ReadShort();
624 FOREACH(Scores, true, {
625 int p = BIT(i % 16);
626 if (sf & p)
627 {
628 if (lf & p)
629 o.(scores(it)) = ReadInt24_t();
630 else
631 o.(scores(it)) = ReadChar();
632 }
633 });
634
635 return = true;
636
637 if(o.sort_prev)
638 Scoreboard_UpdatePlayerPos(o); // if not registered, we cannot do this yet!
639
640 this.entremove = Ent_RemovePlayerScore;
641}
642
643NET_HANDLE(ENT_CLIENT_TEAMSCORES, bool isnew)
644{
645 make_pure(this);
646 int i;
647
648 this.team = ReadByte();
649 entity o = this.owner = GetTeam(this.team, true); // these team numbers can always be trusted
650
651#if MAX_TEAMSCORE <= 8
652 int sf = ReadByte();
653 int lf = ReadByte();
654#else
655 int sf = ReadShort();
656 int lf = ReadShort();
657#endif
658 for(i = 0; i < MAX_TEAMSCORE; ++i)
659 if(sf & BIT(i))
660 {
661 if(lf & BIT(i))
662 o.(teamscores(i)) = ReadInt24_t();
663 else
664 o.(teamscores(i)) = ReadChar();
665 }
666
667 return = true;
668
670}
671
673{
674 for (entity pl = players.sort_next; pl; pl = pl.sort_next)
675 pl.ignored = false;
676
678
679 if (ignore_list == "")
680 return;
681
683 {
684 bool found = false;
685 int ignore_id = stoi(it);
686 for (entity pl = players.sort_next; pl; pl = pl.sort_next)
687 {
688 if (ignore_id == pl.sv_entnum + 1)
689 {
690 pl.ignored = true;
691 found = true;
692 break;
693 }
694 }
695 // when an ignored player is not found, it means their playerslot is not initialized yet
696 if (!found)
697 ignore_list_apply_time = time + 0.5; // retry after a while
698 });
699
700 if (ignore_list_apply_time == 0) // ignore_list applied
702}
703
704NET_HANDLE(ENT_CLIENT_CLIENTDATA, bool isnew)
705{
706 make_pure(this);
707 int newspectatee_status;
708
709 int f = ReadByte();
710
712
713 if(f & BIT(1))
714 {
715 newspectatee_status = ReadByte();
716 if(newspectatee_status == player_localnum + 1)
717 newspectatee_status = -1; // observing
718 }
719 else
720 newspectatee_status = 0;
721
722 spectatorbutton_zoom = (f & BIT(2));
723 observe_blocked = (f & BIT(3));
724
725 if(f & BIT(4))
726 {
728
729 float i, slot;
730
731 for(i = 0; i < MAX_SPECTATORS; ++i)
732 spectatorlist[i] = 0; // reset list first
733
734 int limit = min(num_spectators, MAX_SPECTATORS);
735 for(i = 0; i < limit; ++i)
736 {
737 slot = ReadByte();
738 spectatorlist[i] = slot - 1;
739 }
740 }
741 else
742 {
743 for(int j = 0; j < MAX_SPECTATORS; ++j)
744 spectatorlist[j] = 0; // reset list if showspectators has been turned off
745 num_spectators = 0;
746 }
747
748 return = true;
749
750 if(newspectatee_status != spectatee_status)
751 {
754 }
756 {
757 if ( (spectatee_status == -1 && newspectatee_status > 0) //before observing, now spectating
758 || (spectatee_status > 0 && newspectatee_status > 0 && spectatee_status != newspectatee_status) //changed spectated player
759 )
760 prev_p_health = -1;
761 else if(spectatee_status && !newspectatee_status) //before observing/spectating, now playing
762 prev_health = -1;
763 }
764 spectatee_status = newspectatee_status;
765
766 // we could get rid of spectatee_status, and derive it from player_localentnum and player_localnum
767
768 teamnagger = (f & 0x60) >> 5; // 0x60 = BIT(5) | BIT(6)
769
770 if (f & BIT(7))
771 {
774 }
775}
776
777NET_HANDLE(ENT_CLIENT_NAGGER, bool isnew)
778{
779 make_pure(this);
780
781 int nags = ReadByte(); // NAGS NAGS NAGS NAGS NAGS NAGS NADZ NAGS NAGS NAGS
782
783 if(!(nags & BIT(2)))
784 {
786 vote_active = 0;
787 }
788 else
789 {
790 vote_active = 1;
791 }
792
793 if(nags & BIT(6))
794 {
798 vote_highlighted = ReadChar();
799 }
800
801 if(nags & BIT(7))
802 {
804 }
805
806 if(nags & BIT(0))
807 for(int i = 0; i < maxclients;)
808 for(int f = ReadByte(), b = 0; b < 8 && i < maxclients; ++b, ++i)
809 if(playerslots[i])
810 playerslots[i].ready = f & BIT(b);
811
812 return = true;
813
814 ready_waiting = (nags & BIT(0));
815 ready_waiting_for_me = (nags & BIT(1));
816 vote_waiting = (nags & BIT(2));
817 vote_waiting_for_me = (nags & BIT(3));
818 warmup_stage = (nags & BIT(4));
819}
820
821NET_HANDLE(ENT_CLIENT_ELIMINATEDPLAYERS, bool isnew)
822{
823 make_pure(this);
824 int sf = 0;
825 serialize(byte, 0, sf);
826 if (sf & 1) {
827 for (int j = 0; j < maxclients; ++j) {
828 if (playerslots[j]) {
829 playerslots[j].eliminated = true;
830 }
831 }
832 for (int i = 1; i <= maxclients; i += 8) {
833 int f = 0;
834 serialize(byte, 0, f);
835 for (int b = 0; b < 8; ++b) {
836 if (f & BIT(b)) continue;
837 int j = i - 1 + b;
838 if (playerslots[j]) {
839 playerslots[j].eliminated = false;
840 }
841 }
842 }
843 }
844 return true;
845}
846
847NET_HANDLE(ENT_CLIENT_RANDOMSEED, bool isnew)
848{
849 make_pure(this);
851 float s = ReadShort();
852 psrandom(s);
853 return true;
854}
855
856NET_HANDLE(ENT_CLIENT_ACCURACY, bool isnew)
857{
858 make_pure(this);
859 int sf = ReadInt24_t();
860 if (sf == 0) {
861 for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w)
862 weapon_accuracy[w] = -1;
863 return true;
864 }
865
866 int f = 1;
867 for (int w = 0; w <= WEP_LAST - WEP_FIRST; ++w) {
868 if (sf & f) {
869 int b = ReadByte();
870 if (b == 0)
871 weapon_accuracy[w] = -1;
872 else if (b == 255)
873 weapon_accuracy[w] = 1.0; // no better error handling yet, sorry
874 else
875 weapon_accuracy[w] = (b - 1.0) / 100.0;
876 }
877 f = (f == 0x800000) ? 1 : f * 2;
878 }
879 return true;
880}
881
882// CSQC_Ent_Update : Called every frame that the server has indicated an update to the SSQC / CSQC entity has occured.
883// The parameter isnew reflects if the entity is "new" to the client, meaning it just came into the client's PVS.
884void CSQC_Ent_Update(entity this, bool isnew)
885{
886 this.sourceLoc = __FILE__":"STR(__LINE__);
887 int t = ReadByte();
888
889 // set up the "time" global for received entities to be correct for interpolation purposes
890 float savetime = time;
891 if(servertime)
892 {
894 }
895 else
896 {
898 serverdeltatime = STAT(MOVEVARS_TICRATE) * STAT(MOVEVARS_TIMESCALE);
900 }
901
902#ifdef DP_CSQC_ENTITY_REMOVE_IS_B0RKED
903 if (this.enttype)
904 {
905 if (t != this.enttype || isnew)
906 {
907 LOG_INFOF("A CSQC entity changed its type! (edict: %d, server: %d, type: %d -> %d)", etof(this), this.entnum, this.enttype, t);
908 Ent_Remove(this);
909 ONREMOVE(this);
910 clearentity(this);
911 isnew = true;
912 }
913 }
914 else
915 {
916 if (!isnew)
917 {
918 LOG_INFOF("A CSQC entity appeared out of nowhere! (edict: %d, server: %d, type: %d)", etof(this), this.entnum, t);
919 isnew = true;
920 }
921 }
922#endif
923 this.enttype = t;
924 bool done = false;
925 FOREACH(LinkedEntities, it.m_id == t, {
926 if (isnew) this.classname = it.netname;
927 if (autocvar_developer_csqcentities)
928 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);
929 done = it.m_read(this, NULL, isnew);
930 MUTATOR_CALLHOOK(Ent_Update, this, isnew);
931 break;
932 });
933 time = savetime;
934 if (!done)
935 {
936 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);
937 }
938}
939
940// Destructor, but does NOT deallocate the entity by calling remove(). Also
941// used when an entity changes its type. For an entity that someone interacts
942// with others, make sure it can no longer do so.
944{
945 if(this.entremove) this.entremove(this);
946
947 if(this.skeletonindex)
948 {
949 skel_delete(this.skeletonindex);
950 this.skeletonindex = 0;
951 }
952
953 if(this.snd_looping > 0)
954 {
956 this.snd_looping = 0;
957 }
958
959 this.enttype = 0;
960 this.classname = "";
961 this.draw = func_null;
962 this.entremove = func_null;
963 // TODO possibly set more stuff to defaults
964}
965// CSQC_Ent_Remove : Called when the server requests a SSQC / CSQC entity to be removed. Essentially call remove(this) as well.
967{
968 if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Ent_Remove() with this=%i {.entnum=%d, .enttype=%d}", this, this.entnum, this.enttype);
969 if (wasfreed(this))
970 {
971 LOG_WARN("CSQC_Ent_Remove called for already removed entity. Packet loss?");
972 return;
973 }
974 if (this.enttype) Ent_Remove(this);
975 delete(this);
976}
977
979{
980 // fire game or demo start hooks here
981 if (!(calledhooks & HOOK_START))
982 {
983 if (!isdemo())
984 localcmd("\n_cl_hook_gamestart ", MapInfo_Type_ToString(gametype), "\n");
985 else
986 localcmd("\ncl_hook_demostart\n");
987
988 calledhooks |= HOOK_START; // mark start hook as fired
989 }
990}
991
992// 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.
993void CSQC_Parse_StuffCmd(string strMessage)
994{
995 if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Parse_StuffCmd(\"%s\")", strMessage);
996 localcmd(strMessage);
997}
998
999// 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.
1000void CSQC_Parse_Print(string strMessage)
1001{
1002 if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Parse_Print(\"%s\")", strMessage);
1003 print(ColorTranslateRGB(strMessage));
1004}
1005
1006// CSQC_Parse_CenterPrint : Provides the centerprint_AddStandard string in the first parameter that the server provided.
1007void CSQC_Parse_CenterPrint(string strMessage)
1008{
1009 if (autocvar_developer_csqcentities) LOG_INFOF("CSQC_Parse_CenterPrint(\"%s\")", strMessage);
1010 centerprint_AddStandard(strMessage);
1011}
1012
1013// CSQC_Parse_TempEntity : Handles all temporary entity network data in the CSQC layer.
1014// You must ALWAYS first acquire the temporary ID, which is sent as a byte.
1015// Return value should be 1 if CSQC handled the temporary entity, otherwise return 0 to have the engine process the event.
1017{
1018 // Acquire TE ID
1019 int nTEID = ReadByte();
1020
1021 FOREACH(TempEntities, it.m_id == nTEID, {
1022 if (autocvar_developer_csqcentities)
1023 LOG_INFOF("CSQC_Parse_TempEntity() nTEID=%s (%d)", it.netname, nTEID);
1024 return it.m_read(NULL, NULL, true);
1025 });
1026
1028 LOG_INFOF("CSQC_Parse_TempEntity() with nTEID=%d", nTEID);
1029
1030 // No special logic for this temporary entity; return 0 so the engine can handle it
1031 return false;
1032}
1033
1038{
1040 {
1042 cvar_set("r_drawfog", "0");
1043 }
1044 else if (forcefog != "")
1045 {
1046 // using cvar_set as it's faster and safer than a command
1047 if (!autocvar_r_drawfog)
1048 cvar_set("r_drawfog", "1");
1050 cvar_set("r_fog_exp2", "0");
1051 localcmd(sprintf("\nfog %s\n", forcefog));
1052 }
1053}
1054
1056NET_HANDLE(ENT_CLIENT_SCORES_INFO, bool isnew)
1057{
1058 make_pure(this);
1059 gametype = ReadRegistered(Gametypes);
1063 FOREACH(Scores, true, {
1065 scores_flags(it) = ReadByte();
1066 });
1067 for (int i = 0; i < MAX_TEAMSCORE; ++i)
1068 {
1071 }
1072 bool welcome_msg_too = ReadByte();
1073 if (welcome_msg_too)
1075 return = true;
1077 Gametype_Init();
1078}
1079
1080NET_HANDLE(ENT_CLIENT_INIT, bool isnew)
1081{
1082 nb_pb_period = ReadByte() / 32; //Accuracy of 1/32th
1083
1092
1094
1095 armorblockpercent = ReadByte() / 255.0;
1096 damagepush_speedfactor = ReadByte() / 255.0;
1097
1099
1100 g_trueaim_minrange = ReadCoord();
1101
1102 return = true;
1103
1104 MUTATOR_CALLHOOK(Ent_Init);
1105
1106 if (!postinit) PostInit();
1107}
1108
1109float GetSpeedUnitFactor(int speed_unit)
1110{
1111 switch(speed_unit)
1112 {
1113 default:
1114 case 1: return 1.0;
1115 case 2: return 0.0254;
1116 case 3: return 0.0254 * 3.6;
1117 case 4: return 0.0254 * 3.6 * 0.6213711922;
1118 case 5: return 0.0254 * 1.943844492; // 1 m/s = 1.943844492 knots, because 1 knot = 1.852 km/h
1119 }
1120}
1121
1122string GetSpeedUnit(int speed_unit)
1123{
1124 switch(speed_unit)
1125 {
1126 // translator-friendly strings without the initial space
1127 default:
1128 case 1: return strcat(" ", _("qu/s"));
1129 case 2: return strcat(" ", _("m/s"));
1130 case 3: return strcat(" ", _("km/h"));
1131 case 4: return strcat(" ", _("mph"));
1132 case 5: return strcat(" ", _("knots"));
1133 }
1134}
1135
1136NET_HANDLE(TE_CSQC_RACE, bool isNew)
1137{
1138 int b = ReadByte();
1139
1140 switch (b)
1141 {
1147 string pbestname = ReadString();
1152 {
1156 }
1157 else
1158 strcpy(race_previousbestname, pbestname);
1159
1161
1162 if(race_checkpoint == 0 || race_checkpoint == 254)
1163 {
1165 race_laptime = time; // valid
1166 }
1167 break;
1168
1170 race_laptime = 0;
1172 break;
1173
1175 race_laptime = ReadCoord();
1176 race_checkpointtime = -99999;
1177 // fall through
1180
1182 if(b != RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING) // not while spectating (matches server)
1184 string newname = ReadString();
1186 if(b != RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING) // not while spectating (matches server)
1189 {
1192 race_mybesttime = 0;
1193 race_mybestspeed = 0;
1195 }
1196 else
1197 strcpy(race_nextbestname, newname);
1198 break;
1199
1207 int who = ReadByte();
1208 if(who)
1210 else
1211 strcpy(race_mycheckpointenemy, ""); // TODO: maybe string_null works fine here?
1212 break;
1213
1221 int what = ReadByte();
1222 if(what)
1224 else
1225 strcpy(race_othercheckpointenemy, ""); // TODO: maybe string_null works fine here?
1226 break;
1227
1231 race_penaltytime = ReadShort();
1232 string reason = ReadString();
1233 if (reason == "missing a checkpoint")
1234 reason = _("missing a checkpoint");
1235 strcpy(race_penaltyreason, reason);
1238 break;
1239
1242 break;
1246 break;
1250 break;
1253 break;
1255 float prevpos, del;
1256 int pos = ReadShort();
1257 prevpos = ReadShort();
1258 del = ReadShort();
1259
1260 // move other rankings out of the way
1261 int i;
1262 if (prevpos) {
1263 int m = min(prevpos, RANKINGS_DISPLAY_CNT);
1264 for (i=m-1; i>pos-1; --i) {
1265 grecordtime[i] = grecordtime[i-1];
1267 }
1268 } else if (del) { // a record has been deleted by the admin
1269 for (i=pos-1; i<= RANKINGS_DISPLAY_CNT-1; ++i) {
1270 if (i == RANKINGS_DISPLAY_CNT-1) { // clear out last record
1271 grecordtime[i] = 0;
1273 }
1274 else {
1275 grecordtime[i] = grecordtime[i+1];
1277 }
1278 }
1279 } else { // player has no ranked record yet
1280 for (i=RANKINGS_DISPLAY_CNT-1;i>pos-1;--i) {
1281 grecordtime[i] = grecordtime[i-1];
1283 }
1284 }
1285
1287 // kick off the player who fell from the last displayed position
1290 }
1291
1292 // store new ranking
1293 strcpy(grecordholder[pos-1], ReadString());
1294 grecordtime[pos-1] = ReadInt24_t();
1295 if(strdecolorize(grecordholder[pos-1]) == strdecolorize(entcs_GetName(player_localnum)))
1296 race_myrank = pos;
1297 break;
1299 race_status = ReadShort();
1301 }
1302 return true;
1303}
1304
1305NET_HANDLE(TE_CSQC_PINGPLREPORT, bool isNew)
1306{
1307 int i = ReadByte();
1308 int pi = ReadShort();
1309 int pl = ReadByte();
1310 int ml = ReadByte();
1311 return = true;
1312 entity e = playerslots[i];
1313 if (!e) return;
1314 e.ping = pi;
1315 e.ping_packetloss = pl / 255.0;
1316 e.ping_movementloss = ml / 255.0;
1317}
1318
1319NET_HANDLE(TE_CSQC_WEAPONCOMPLAIN, bool isNew)
1320{
1321 int weapon_id = ReadByte();
1322 complain_weapon = REGISTRY_GET(Weapons, weapon_id);
1324 return = true;
1325
1327 weapontime = time; // ping the weapon panel
1328
1329 switch(complain_weapon_type)
1330 {
1331 case 0: Local_Notification(MSG_MULTI, ITEM_WEAPON_NOAMMO, weapon_id); break;
1332 case 1: Local_Notification(MSG_MULTI, ITEM_WEAPON_DONTHAVE, weapon_id); break;
1333 default: Local_Notification(MSG_MULTI, ITEM_WEAPON_UNAVAILABLE, weapon_id); break;
1334 }
1335}
1336
1338{
1339 return build_mutator_list(s);
1340}
1341
1343{
1344 if (s == "") return s;
1345 if (s == "All Weapons Arena") return _("All Weapons Arena");
1346 if (s == "All Available Weapons Arena") return _("All Available Weapons Arena");
1347 if (s == "Most Weapons Arena") return _("Most Weapons Arena");
1348 if (s == "Most Available Weapons Arena") return _("Most Available Weapons Arena");
1349 if (s == "Dev All Weapons Arena") return s; // development option, do not translate
1350 if (s == "Dev All Available Weapons Arena") return s; // development option, do not translate
1351 if (s == "No Weapons Arena") return _("No Weapons Arena");
1352
1353 int n = tokenizebyseparator(s, " & ");
1354 string wpn_list = "";
1355 for (int i = 0; i < n; ++i)
1356 {
1357 Weapon wep = Weapon_from_name(argv(i));
1358 if (wep == WEP_Null)
1359 LOG_INFO("^3Warning: ^7server sent an invalid weapon name\n");
1360 wpn_list = cons_mid(wpn_list, " & ", wep.m_name);
1361 }
1362 if (wpn_list != "")
1363 return sprintf(_("%s Arena"), wpn_list);
1364 else
1365 return _("No Weapons Arena");
1366}
1367
1368string GetVersionMessage(string hostversion, bool version_mismatch, bool version_check)
1369{
1370 string xonotic_hostversion = strcat("Xonotic ", hostversion);
1371 if (version_mismatch)
1372 {
1373 if(!version_check)
1374 return strcat(sprintf(_("This is %s"), xonotic_hostversion), "\n^3",
1375 _("Your client version is outdated."), "\n\n\n",
1376 _("### YOU WON'T BE ABLE TO PLAY ON THIS SERVER ###"), "\n\n\n",
1377 _("Please update!"));
1378 else
1379 return strcat(sprintf(_("This is %s"), xonotic_hostversion), "\n^3",
1380 _("This server is using an outdated Xonotic version."), "\n\n\n",
1381 _("### THIS SERVER IS INCOMPATIBLE AND THUS YOU CANNOT JOIN ###"));
1382 }
1383 return sprintf(_("Welcome to %s"), xonotic_hostversion);
1384}
1385
1387{
1388 int flags = ReadByte();
1389
1390 campaign = flags & 1;
1391 if (campaign)
1392 {
1393 int campaign_level = ReadByte();
1394 // Menu can't build the whole campaign message because it lacks getcommandkey and CCR
1395 // so we build part of the message here and let the menu insert the level description
1396 // (that client doesn't know) by replacing the keyword _LEVEL_DESC
1397 string key = getcommandkey(_("jump"), "+jump");
1398 string msg = strcat(
1399 CCR("^F1"), sprintf(_("Level %d:"), campaign_level),
1400 sprintf(CCR(" ^BG%s\n\n"), "_LEVEL_DESC"),
1401 sprintf(CCR(_("^BGPress ^F2%s^BG to enter the game")), key));
1402 msg = MakeConsoleSafe(strreplace("\n", "\\n", msg));
1403 string welcomedialog_args = strcat("CAMPAIGN ", itos(campaign_level), " \"", msg, "\"");
1404
1405 localcmd("\nmenu_cmd directmenu Welcome ", welcomedialog_args, "\n");
1406 return true;
1407 }
1408
1410 string hostversion = ReadString();
1411 bool version_mismatch = flags & 2;
1412 bool version_check = flags & 4;
1414 MapInfo_Map_author = flags & 8 ? ReadString() : "";
1417 string modifications = translate_modifications(ReadString());
1418 string weaponarena_list = translate_weaponarena(ReadString());
1419 string cache_mutatormsg = ReadString();
1420 string motd = ReadString();
1421
1422 string msg = GetVersionMessage(hostversion, version_mismatch, version_check);
1423
1424 msg = strcat(msg, "\n\n", _("Gametype:"), " ^1", MapInfo_Type_ToText(gametype), "\n");
1425
1426 msg = strcat(msg, "\n", _("Map:"), " ", MapInfo_Map_titlestring, "\n");
1427 if (flags & 8)
1428 msg = strcat(msg, "^9", _("by:"), " ", MapInfo_Map_author, "\n");
1429
1431 {
1432 msg = strcat(msg, "\n", _("This match supports"), " ^5");
1434 msg = strcat(msg, sprintf(_("%d players"), srv_maxplayers), "\n");
1435 else if (srv_minplayers && srv_maxplayers)
1436 msg = strcat(msg, sprintf(_("%d to %d players"), srv_minplayers, srv_maxplayers), "\n");
1437 else if (srv_maxplayers)
1438 msg = strcat(msg, sprintf(_("%d players maximum"), srv_maxplayers), "\n");
1439 else
1440 msg = strcat(msg, sprintf(_("%d players minimum"), srv_minplayers), "\n");
1441 }
1442
1443 modifications = cons_mid(modifications, ", ", weaponarena_list);
1444 if(modifications != "")
1445 msg = strcat(msg, "\n", _("Active modifications:"), " ^3", modifications, "\n");
1446
1447 if (cache_mutatormsg != "")
1448 msg = strcat(msg, "\n", _("Special gameplay tips:"), " ^7", cache_mutatormsg, "\n");
1449 string mutator_msg = "";
1450 MUTATOR_CALLHOOK(BuildGameplayTipsString, mutator_msg);
1451 mutator_msg = M_ARGV(0, string);
1452 msg = strcat(msg, mutator_msg); // trust that the mutator will do proper formatting
1453
1454 if (motd != "")
1455 msg = strcat(msg, "\n^9↓ ", _("Server's message"), " ↓\n", motd);
1456
1457 strcpy(welcome_msg, msg);
1458 welcome_msg_menu_check_maxtime = time + 1; // wait for menu to load before showing the welcome dialog
1459 return true;
1460}
1461
1463{
1465 return;
1466
1467 // if want dialog check if menu is initialized but for a short time
1468 if (cvar("_menu_initialized") == 2 || time > welcome_msg_menu_check_maxtime)
1469 {
1470 if (cvar("_menu_welcome_dialog_available"))
1471 {
1472 string welcomedialog_args = strcat("HOSTNAME \"", hostname, "\"");
1473 string msg = MakeConsoleSafe(strreplace("\n", "\\n", welcome_msg));
1474 welcomedialog_args = strcat(welcomedialog_args, " WELCOME \"", msg, "\"");
1475
1477 {
1478 if (cvar("_menu_cmd_closemenu_available"))
1479 {
1480 // initialize the dialog without opening it
1481 localcmd("\nmenu_cmd closemenu Welcome ", welcomedialog_args, "\n");
1482 }
1483 else
1484 {
1485 // legacy code for clients with old menus
1486 // since togglemenu 0 doesn't close the dialog but only hides it,
1487 // playing back a demo the Welcome dialog will pop up on the first ESC press
1488 localcmd("\nmenu_cmd directmenu Welcome ", welcomedialog_args, "\n");
1489 // close it after it's been initialized so it can still be opened manually
1490 localcmd("\ntogglemenu 0\n");
1491 }
1492 }
1493 else
1494 localcmd("\nmenu_cmd directmenu Welcome ", welcomedialog_args, "\n");
1495 }
1496
1499 }
1500}
1501
1502NET_HANDLE(TE_CSQC_SERVERWELCOME, bool isNew)
1503{
1504 return net_handle_ServerWelcome();
1505}
1506
1507string _getcommandkey(string cmd_name, string command, bool forcename)
1508{
1510 return cmd_name;
1511
1512 string key, keys = db_get(binddb, command);
1513 int n, j, found = 0;
1514 float k;
1515
1516 if (keys == "")
1517 {
1518 const bool joy_active = cvar("joy_active");
1519 n = tokenize(findkeysforcommand(command, 0)); // uses '...' strings
1520 for (j = 0; j < n; ++j)
1521 {
1522 k = stof(argv(j));
1523 if (k == -1)
1524 continue;
1525 key = keynumtostring(k);
1526 if (!joy_active && startsWith(key, "JOY"))
1527 continue;
1528
1529 keys = cons_mid(keys, ", ", translate_key(key));
1530
1532 break;
1533 }
1534 if (keys == "")
1535 keys = "NO_KEY";
1536 db_put(binddb, command, keys);
1537 }
1538
1539 if (keys == "NO_KEY")
1540 {
1541 if (autocvar_hud_showbinds > 1)
1542 return sprintf(_("%s (not bound)"), cmd_name);
1543 else
1544 return cmd_name;
1545 }
1546 else if (autocvar_hud_showbinds > 1 || forcename)
1547 return sprintf("%s (%s)", cmd_name, keys);
1548 return keys;
1549}
1550
1552void URI_Get_Callback(int id, int status, string data)
1553{
1554 TC(int, id); TC(int, status);
1555 if(url_URI_Get_Callback(id, status, data))
1556 {
1557 // handled
1558 }
1559 else if (id == URI_GET_DISCARD)
1560 {
1561 // discard
1562 }
1563 else if (id >= URI_GET_CURL && id <= URI_GET_CURL_END)
1564 {
1565 // sv_cmd curl
1566 Curl_URI_Get_Callback(id, status, data);
1567 }
1568 else
1569 {
1570 LOG_INFOF("Received HTTP request data for an invalid id %d.", id);
1571 }
1572}
entity parent
Definition animhost.qc:7
vector arc_shotorigin[4]
Definition arc.qh:104
#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:44
string m_name
M: wepname : human readable name.
Definition weapon.qh:81
#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:1507
void Fog_Force()
Definition main.qc:1037
void CSQC_Parse_CenterPrint(string strMessage)
Definition main.qc:1007
void Ent_Remove(entity this)
Definition main.qc:943
void RemovePlayer(entity player)
Definition main.qc:261
string GetVersionMessage(string hostversion, bool version_mismatch, bool version_check)
Definition main.qc:1368
void AuditLists()
Definition main.qc:225
void Gametype_Init()
Definition main.qc:978
float has_team
Definition main.qc:347
void Welcome_Message_Show_Try()
Definition main.qc:1462
string GetSpeedUnit(int speed_unit)
Definition main.qc:1122
void Release_Common_Keys()
Definition main.qc:477
void PostInit()
Definition main.qc:463
int survival_status
Definition main.qc:569
void Ent_RemovePlayerScore(entity this)
Definition main.qc:570
bool net_handle_ServerWelcome()
Definition main.qc:1386
float RegisterTeam(entity Team)
Definition main.qc:292
void Playerchecker_Think(entity this)
Definition main.qc:421
bool CSQC_Parse_TempEntity()
Definition main.qc:1016
string translate_modifications(string s)
Definition main.qc:1337
void CSQC_Parse_Print(string strMessage)
Definition main.qc:1000
string translate_weaponarena(string s)
Definition main.qc:1342
entity GetTeam(int Team, bool add)
Definition main.qc:332
void MoveToLast(entity e)
Definition main.qc:280
void Shutdown()
Definition main.qc:162
bool autocvar_r_fog_exp2
Definition main.qc:1035
string forcefog
Definition main.qc:1036
bool SetTeam(entity o, int Team)
Definition main.qc:348
void URI_Get_Callback(int id, int status, string data)
engine callback
Definition main.qc:1552
void CSQC_Parse_StuffCmd(string strMessage)
Definition main.qc:993
float RegisterPlayer(entity player)
Definition main.qc:245
bool autocvar_r_drawfog
Definition main.qc:1034
void RemoveTeam(entity Team)
Definition main.qc:311
void ignore_list_apply()
Definition main.qc:672
float GetSpeedUnitFactor(int speed_unit)
Definition main.qc:1109
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:928
#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:768
string translate_key(string key)
Definition util.qc:1512
float cvar_settemp(string tmp_cvar, string tmp_value)
Definition util.qc:811
vector decompressShotOrigin(int f)
Definition util.qc:1275
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:251
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:71
#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:366
#define NET_HANDLE(id, param)
Definition net.qh:15
float servertime
Definition net.qh:348
#define serialize(T, stream,...)
Definition net.qh:243
int ReadInt24_t()
Definition net.qh:355
#define ReadRegistered(r)
Definition net.qh:298
int ReadByte()
const int REPLICATEVARS_DESTROY
Definition replicate.qh:6
#define STAT(...)
Definition stats.qh:82
void WarpZone_Shutdown()
Definition client.qc:290
#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:656
string MapInfo_Type_ToText(Gametype t)
Definition mapinfo.qc:661
float _MapInfo_GetTeamPlayBool(Gametype t)
Definition mapinfo.qc:539
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
const int RACE_NET_CHECKPOINT_HIT_QUALIFYING
Definition net_linked.qh:11
const int RACE_NET_SERVER_RECORD
Definition net_linked.qh:19
const int RACE_NET_CHECKPOINT_HIT_RACE_BY_OPPONENT
Definition net_linked.qh:15
const int RACE_NET_SPEED_AWARD
Definition net_linked.qh:20
const int RACE_NET_CHECKPOINT_HIT_RACE
Definition net_linked.qh:14
const int RACE_NET_PENALTY_RACE
Definition net_linked.qh:17
const int RACE_NET_SERVER_STATUS
Definition net_linked.qh:23
const int RACE_NET_PENALTY_QUALIFYING
Definition net_linked.qh:18
const int RACE_NET_SPEED_AWARD_BEST
Definition net_linked.qh:21
const int RACE_NET_CHECKPOINT_NEXT_QUALIFYING
Definition net_linked.qh:13
const int RACE_NET_RANKINGS_CNT
Definition net_linked.qh:26
const int RACE_NET_CHECKPOINT_NEXT_SPEC_QUALIFYING
Definition net_linked.qh:16
const int RACE_NET_CHECKPOINT_CLEAR
Definition net_linked.qh:12
const int RACE_NET_SERVER_RANKINGS
Definition net_linked.qh:22
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:486
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:136
#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:327
const int WEP_FIRST
Definition all.qh:326
string cache_mutatormsg
Definition world.qh:69