1 var void remove(entity e);
2 void objerror(string s);
4 .vector dropped_origin;
6 void() spawnfunc_info_player_deathmatch; // needed for the other spawnpoints
8 string ColoredTeamName(float t);
10 float DistributeEvenly_amount;
11 float DistributeEvenly_totalweight;
12 void DistributeEvenly_Init(float amount, float totalweight)
14 if (DistributeEvenly_amount)
16 dprint("DistributeEvenly_Init: UNFINISHED DISTRIBUTION (", ftos(DistributeEvenly_amount), " for ");
17 dprint(ftos(DistributeEvenly_totalweight), " left!)\n");
20 DistributeEvenly_amount = 0;
22 DistributeEvenly_amount = amount;
23 DistributeEvenly_totalweight = totalweight;
25 float DistributeEvenly_Get(float weight)
30 f = floor(0.5 + DistributeEvenly_amount * weight / DistributeEvenly_totalweight);
31 DistributeEvenly_totalweight -= weight;
32 DistributeEvenly_amount -= f;
36 void move_out_of_solid_expand(entity e, vector by)
39 tracebox(e.origin, e.mins - '1 1 1' * eps, e.maxs + '1 1 1' * eps, e.origin + by, MOVE_WORLDONLY, e);
42 if (trace_fraction < 1)
45 // adjust origin in the other direction...
46 setorigin(e,e.origin - by * (1 - trace_fraction));
50 float move_out_of_solid(entity e)
55 traceline(o, o, MOVE_WORLDONLY, e);
59 tracebox(o, e.mins, e.maxs, o, MOVE_WORLDONLY, e);
60 if (!trace_startsolid)
67 move_out_of_solid_expand(e, '1 0 0' * m0_x);
69 move_out_of_solid_expand(e, '1 0 0' * m1_x);
71 move_out_of_solid_expand(e, '0 1 0' * m0_y);
73 move_out_of_solid_expand(e, '0 1 0' * m1_y);
75 move_out_of_solid_expand(e, '0 0 1' * m0_z);
77 move_out_of_solid_expand(e, '0 0 1' * m1_z);
79 setorigin(e, e.origin);
81 tracebox(e.origin, e.mins, e.maxs, e.origin, MOVE_WORLDONLY, e);
91 string STR_PLAYER = "player";
92 string STR_SPECTATOR = "spectator";
93 string STR_OBSERVER = "observer";
96 #define FOR_EACH_CLIENT(v) for(v = world; (v = findflags(v, flags, FL_CLIENT)) != world; )
97 #define FOR_EACH_REALCLIENT(v) FOR_EACH_CLIENT(v) if(clienttype(v) == CLIENTTYPE_REAL)
98 #define FOR_EACH_PLAYER(v) for(v = world; (v = find(v, classname, STR_PLAYER)) != world; )
99 #define FOR_EACH_REALPLAYER(v) FOR_EACH_PLAYER(v) if(clienttype(v) == CLIENTTYPE_REAL)
101 #define FOR_EACH_CLIENTSLOT(v) for(v = world; (v = nextent(v)) && (num_for_edict(v) <= maxclients); )
102 #define FOR_EACH_CLIENT(v) FOR_EACH_CLIENTSLOT(v) if(v.flags & FL_CLIENT)
103 #define FOR_EACH_REALCLIENT(v) FOR_EACH_CLIENT(v) if(clienttype(v) == CLIENTTYPE_REAL)
104 #define FOR_EACH_PLAYER(v) FOR_EACH_CLIENT(v) if(v.classname == STR_PLAYER)
105 #define FOR_EACH_REALPLAYER(v) FOR_EACH_REALCLIENT(v) if(v.classname == STR_PLAYER)
108 // copies a string to a tempstring (so one can strunzone it)
109 string strcat1(string s) = #115; // FRIK_FILE
114 void bcenterprint(string s)
116 // TODO replace by MSG_ALL (would show it to spectators too, though)?
118 FOR_EACH_PLAYER(head)
119 if (clienttype(head) == CLIENTTYPE_REAL)
120 centerprint(head, s);
123 void GameLogEcho(string s)
128 if (cvar("sv_eventlog_files"))
133 matches = cvar("sv_eventlog_files_counter") + 1;
134 cvar_set("sv_eventlog_files_counter", ftos(matches));
137 fn = strcat(substring("00000000", 0, 8 - strlen(fn)), fn);
138 fn = strcat(cvar_string("sv_eventlog_files_nameprefix"), fn, cvar_string("sv_eventlog_files_namesuffix"));
139 logfile = fopen(fn, FILE_APPEND);
140 fputs(logfile, ":logversion:3\n");
144 if (cvar("sv_eventlog_files_timestamps"))
145 fputs(logfile, strcat(":time:", strftime(TRUE, "%Y-%m-%d %H:%M:%S", "\n", s, "\n")));
147 fputs(logfile, strcat(s, "\n"));
150 if (cvar("sv_eventlog_console"))
159 // will be opened later
164 if (logfile_open && logfile >= 0)
171 float spawnpoint_nag;
172 void relocate_spawnpoint()
174 // nudge off the floor
175 setorigin(self, self.origin + '0 0 1');
177 tracebox(self.origin, PL_MIN, PL_MAX, self.origin, TRUE, self);
178 if (trace_startsolid)
184 if (!move_out_of_solid(self))
185 objerror("could not get out of solid at all!");
186 print("^1NOTE: this map needs FIXING. Spawnpoint at ", vtos(o - '0 0 1'));
187 print(" needs to be moved out of solid, e.g. by '", ftos(self.origin_x - o_x));
188 print(" ", ftos(self.origin_y - o_y));
189 print(" ", ftos(self.origin_z - o_z), "'\n");
190 if (cvar("g_spawnpoints_auto_move_out_of_solid"))
193 print("\{1}^1NOTE: this map needs FIXING (it contains spawnpoints in solid, see server log)\n");
199 self.mins = self.maxs = '0 0 0';
200 objerror("player spawn point in solid, mapper sucks!\n");
205 if (cvar("g_spawnpoints_autodrop"))
207 setsize(self, PL_MIN, PL_MAX);
211 self.use = spawnpoint_use;
212 self.team_saved = self.team;
216 if (g_ctf || g_assault || g_onslaught || g_domination || g_nexball)
218 have_team_spawns = 1;
220 if (cvar("r_showbboxes"))
222 // show where spawnpoints point at too
223 makevectors(self.angles);
226 e.classname = "info_player_foo";
227 setorigin(e, self.origin + v_forward * 24);
228 setsize(e, '-8 -8 -8', '8 8 8');
229 e.solid = SOLID_TRIGGER;
233 #define strstr strstrofs
235 // NOTE: DO NOT USE THIS FUNCTION TOO OFTEN.
236 // IT WILL MOST PROBABLY DESTROY _ALL_ OTHER TEMP
237 // STRINGS AND TAKE QUITE LONG. haystack and needle MUST
238 // BE CONSTANT OR strzoneD!
239 float strstr(string haystack, string needle, float offset)
243 len = strlen(needle);
244 endpos = strlen(haystack) - len;
245 while(offset <= endpos)
247 found = substring(haystack, offset, len);
256 float NUM_NEAREST_ENTITIES = 4;
257 entity nearest_entity[NUM_NEAREST_ENTITIES];
258 float nearest_length[NUM_NEAREST_ENTITIES];
259 entity findnearest(vector point, .string field, string value, vector axismod)
270 localhead = find(world, field, value);
273 if ((localhead.items == IT_KEY1 || localhead.items == IT_KEY2) && localhead.target == "###item###")
274 dist = localhead.oldorigin;
276 dist = localhead.origin;
278 dist = dist_x * axismod_x * '1 0 0' + dist_y * axismod_y * '0 1 0' + dist_z * axismod_z * '0 0 1';
281 for (i = 0; i < num_nearest; ++i)
283 if (len < nearest_length[i])
287 // now i tells us where to insert at
288 // INSERTION SORT! YOU'VE SEEN IT! RUN!
289 if (i < NUM_NEAREST_ENTITIES)
291 for (j = NUM_NEAREST_ENTITIES - 1; j >= i; --j)
293 nearest_length[j + 1] = nearest_length[j];
294 nearest_entity[j + 1] = nearest_entity[j];
296 nearest_length[i] = len;
297 nearest_entity[i] = localhead;
298 if (num_nearest < NUM_NEAREST_ENTITIES)
299 num_nearest = num_nearest + 1;
302 localhead = find(localhead, field, value);
305 // now use the first one from our list that we can see
306 for (i = 0; i < num_nearest; ++i)
308 traceline(point, nearest_entity[i].origin, TRUE, world);
309 if (trace_fraction == 1)
313 dprint("Nearest point (");
314 dprint(nearest_entity[0].netname);
315 dprint(") is not visible, using a visible one.\n");
317 return nearest_entity[i];
321 if (num_nearest == 0)
324 dprint("Not seeing any location point, using nearest as fallback.\n");
326 dprint("Candidates were: ");
327 for(j = 0; j < num_nearest; ++j)
331 dprint(nearest_entity[j].netname);
336 return nearest_entity[0];
339 void spawnfunc_target_location()
341 self.classname = "target_location";
342 // location name in netname
343 // eventually support: count, teamgame selectors, line of sight?
346 void spawnfunc_info_location()
348 self.classname = "target_location";
349 self.message = self.netname;
352 string NearestLocation(vector p)
357 loc = findnearest(p, classname, "target_location", '1 1 1');
364 loc = findnearest(p, target, "###item###", '1 1 4');
371 string formatmessage(string msg)
382 break; // too many replacements
384 p1 = strstr(msg, "%", p); // NOTE: this destroys msg as it's a tempstring!
385 p2 = strstr(msg, "\\", p); // NOTE: this destroys msg as it's a tempstring!
395 replacement = substring(msg, p, 2);
396 escape = substring(msg, p + 1, 1);
399 else if (escape == "\\")
401 else if (escape == "n")
403 else if (escape == "a")
404 replacement = ftos(floor(self.armorvalue));
405 else if (escape == "h")
406 replacement = ftos(floor(self.health));
407 else if (escape == "l")
408 replacement = NearestLocation(self.origin);
409 else if (escape == "y")
410 replacement = NearestLocation(self.cursor_trace_endpos);
411 else if (escape == "d")
412 replacement = NearestLocation(self.death_origin);
413 else if (escape == "w")
418 wep = self.switchweapon;
421 replacement = W_Name(wep);
423 else if (escape == "W")
425 if (self.items & IT_SHELLS) replacement = "shells";
426 else if (self.items & IT_NAILS) replacement = "bullets";
427 else if (self.items & IT_ROCKETS) replacement = "rockets";
428 else if (self.items & IT_CELLS) replacement = "cells";
429 else replacement = "batteries"; // ;)
431 else if (escape == "x")
433 replacement = self.cursor_trace_ent.netname;
434 if (!replacement || !self.cursor_trace_ent)
435 replacement = "nothing";
437 else if (escape == "p")
439 if (self.last_selected_player)
440 replacement = self.last_selected_player.netname;
442 replacement = "(nobody)";
444 msg = strcat(substring(msg, 0, p), replacement, substring(msg, p+2, strlen(msg) - (p+2)));
445 p = p + strlen(replacement);
456 >0: receives a cvar from name=argv(f) value=argv(f+1)
458 void GetCvars_handleString(string thisname, float f, .string field, string name)
463 strunzone(self.field);
464 self.field = string_null;
468 if (thisname == name)
471 strunzone(self.field);
472 self.field = strzone(argv(f + 1));
476 stuffcmd(self, strcat("sendcvar ", name, "\n"));
478 void GetCvars_handleString_Fixup(string thisname, float f, .string field, string name, string(string) func)
480 GetCvars_handleString(thisname, f, field, name);
481 if (f >= 0) // also initialize to the fitting value for "" when sending cvars out
482 if (thisname == name)
485 s = func(strcat1(self.field));
488 strunzone(self.field);
489 self.field = strzone(s);
493 void GetCvars_handleFloat(string thisname, float f, .float field, string name)
500 if (thisname == name)
501 self.field = stof(argv(f + 1));
504 stuffcmd(self, strcat("sendcvar ", name, "\n"));
506 void GetCvars_handleFloatOnce(string thisname, float f, .float field, string name)
513 if (thisname == name)
517 self.field = stof(argv(f + 1));
526 stuffcmd(self, strcat("sendcvar ", name, "\n"));
529 string W_FixWeaponOrder_ForceComplete(string s);
530 string W_FixWeaponOrder_AllowIncomplete(string s);
531 float w_getbestweapon(entity e);
532 void GetCvars(float f)
536 s = strcat1(argv(f));
537 GetCvars_handleFloat(s, f, autoswitch, "cl_autoswitch");
538 GetCvars_handleFloat(s, f, cvar_cl_playerdetailreduction, "cl_playerdetailreduction");
539 GetCvars_handleFloat(s, f, cvar_scr_centertime, "scr_centertime");
540 GetCvars_handleFloat(s, f, cvar_cl_shownames, "cl_shownames");
541 GetCvars_handleString(s, f, cvar_g_nexuizversion, "g_nexuizversion");
542 GetCvars_handleFloat(s, f, cvar_cl_handicap, "cl_handicap");
543 GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriority, "cl_weaponpriority", W_FixWeaponOrder_ForceComplete);
544 GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriorities[0], "cl_weaponpriority0", W_FixWeaponOrder_AllowIncomplete);
545 GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriorities[1], "cl_weaponpriority1", W_FixWeaponOrder_AllowIncomplete);
546 GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriorities[2], "cl_weaponpriority2", W_FixWeaponOrder_AllowIncomplete);
547 GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriorities[3], "cl_weaponpriority3", W_FixWeaponOrder_AllowIncomplete);
548 GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriorities[4], "cl_weaponpriority4", W_FixWeaponOrder_AllowIncomplete);
549 GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriorities[5], "cl_weaponpriority5", W_FixWeaponOrder_AllowIncomplete);
550 GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriorities[6], "cl_weaponpriority6", W_FixWeaponOrder_AllowIncomplete);
551 GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriorities[7], "cl_weaponpriority7", W_FixWeaponOrder_AllowIncomplete);
552 GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriorities[8], "cl_weaponpriority8", W_FixWeaponOrder_AllowIncomplete);
553 GetCvars_handleString_Fixup(s, f, cvar_cl_weaponpriorities[9], "cl_weaponpriority9", W_FixWeaponOrder_AllowIncomplete);
554 GetCvars_handleFloat(s, f, cvar_cl_autotaunt, "cl_autotaunt");
555 GetCvars_handleFloat(s, f, cvar_cl_voice_directional, "cl_voice_directional");
556 GetCvars_handleFloat(s, f, cvar_cl_voice_directional_taunt_attenuation, "cl_voice_directional_taunt_attenuation");
557 GetCvars_handleFloat(s, f, cvar_cl_hitsound, "cl_hitsound");
558 #ifdef ALLOW_FORCEMODELS
559 GetCvars_handleFloat(s, f, cvar_cl_forceplayermodels, "cl_forceplayermodels");
560 GetCvars_handleFloat(s, f, cvar_cl_forceplayermodelsfromnexuiz, "cl_forceplayermodelsfromnexuiz");
562 GetCvars_handleFloatOnce(s, f, cvar_cl_gunalign, "cl_gunalign");
563 GetCvars_handleFloatOnce(s, f, cvar_cl_noantilag, "cl_noantilag");
566 // fixup of switchweapon (needed for LMS or when spectating is disabled, as PutClientInServer comes too early)
569 if (s == "cl_weaponpriority")
570 self.switchweapon = w_getbestweapon(self);
574 float fexists(string f)
577 fh = fopen(f, FILE_READ);
584 void backtrace(string msg)
587 dev = cvar("developer");
588 war = cvar("prvm_backtraceforwarnings");
589 cvar_set("developer", "1");
590 cvar_set("prvm_backtraceforwarnings", "1");
592 dprint("--- CUT HERE ---\nWARNING: ");
595 remove(world); // isn't there any better way to cause a backtrace?
596 dprint("\n--- CUT UNTIL HERE ---\n");
597 cvar_set("developer", ftos(dev));
598 cvar_set("prvm_backtraceforwarnings", ftos(war));
601 string Team_ColorCode(float teamid)
603 if (teamid == COLOR_TEAM1)
605 else if (teamid == COLOR_TEAM2)
607 else if (teamid == COLOR_TEAM3)
609 else if (teamid == COLOR_TEAM4)
614 string Team_ColorName(float t)
616 // fixme: Search for team entities and get their .netname's!
617 if (t == COLOR_TEAM1)
619 if (t == COLOR_TEAM2)
621 if (t == COLOR_TEAM3)
623 if (t == COLOR_TEAM4)
627 string Team_ColorNameLowerCase(float t)
629 // fixme: Search for team entities and get their .netname's!
630 if (t == COLOR_TEAM1)
632 if (t == COLOR_TEAM2)
634 if (t == COLOR_TEAM3)
636 if (t == COLOR_TEAM4)
641 #define CENTERPRIO_POINT 1
642 #define CENTERPRIO_SPAM 2
643 #define CENTERPRIO_VOTE 4
644 #define CENTERPRIO_NORMAL 5
645 #define CENTERPRIO_SHIELDING 7
646 #define CENTERPRIO_MAPVOTE 9
647 #define CENTERPRIO_IDLEKICK 50
648 #define CENTERPRIO_ADMIN 99
649 .float centerprint_priority;
650 .float centerprint_expires;
651 void centerprint_atprio(entity e, float prio, string s)
653 if (intermission_running)
654 if (prio < CENTERPRIO_MAPVOTE)
656 if (time > e.centerprint_expires)
657 e.centerprint_priority = 0;
658 if (prio >= e.centerprint_priority)
660 e.centerprint_priority = prio;
661 if (timeoutStatus == 2)
662 e.centerprint_expires = time + (e.cvar_scr_centertime * TIMEOUT_SLOWMO_VALUE);
664 e.centerprint_expires = time + e.cvar_scr_centertime;
665 centerprint_builtin(e, s);
668 void centerprint_expire(entity e, float prio)
670 if (prio == e.centerprint_priority)
672 e.centerprint_priority = 0;
673 centerprint_builtin(e, "");
676 void centerprint(entity e, string s)
678 centerprint_atprio(e, CENTERPRIO_NORMAL, s);
681 // decolorizes and team colors the player name when needed
682 string playername(entity p)
685 if (teams_matter && !intermission_running && p.classname == "player")
687 t = Team_ColorCode(p.team);
688 return strcat(t, strdecolorize(p.netname));
694 vector randompos(vector m1, vector m2)
698 v_x = m2_x * random() + m1_x;
699 v_y = m2_y * random() + m1_y;
700 v_z = m2_z * random() + m1_z;
704 float g_pickup_shells;
705 float g_pickup_shells_max;
706 float g_pickup_nails;
707 float g_pickup_nails_max;
708 float g_pickup_rockets;
709 float g_pickup_rockets_max;
710 float g_pickup_cells;
711 float g_pickup_cells_max;
713 float g_pickup_fuel_jetpack;
714 float g_pickup_fuel_max;
715 float g_pickup_armorsmall;
716 float g_pickup_armorsmall_max;
717 float g_pickup_armormedium;
718 float g_pickup_armormedium_max;
719 float g_pickup_armorbig;
720 float g_pickup_armorbig_max;
721 float g_pickup_armorlarge;
722 float g_pickup_armorlarge_max;
723 float g_pickup_healthsmall;
724 float g_pickup_healthsmall_max;
725 float g_pickup_healthmedium;
726 float g_pickup_healthmedium_max;
727 float g_pickup_healthlarge;
728 float g_pickup_healthlarge_max;
729 float g_pickup_healthmega;
730 float g_pickup_healthmega_max;
732 float g_weaponarena_random;
733 string g_weaponarena_list;
734 float g_weaponspeedfactor;
735 float g_weaponratefactor;
736 float g_weapondamagefactor;
737 float g_weaponforcefactor;
741 float start_ammo_shells;
742 float start_ammo_nails;
743 float start_ammo_rockets;
744 float start_ammo_cells;
745 float start_ammo_fuel;
747 float start_armorvalue;
748 float warmup_start_weapons;
749 float warmup_start_ammo_shells;
750 float warmup_start_ammo_nails;
751 float warmup_start_ammo_rockets;
752 float warmup_start_ammo_cells;
753 float warmup_start_ammo_fuel;
754 float warmup_start_health;
755 float warmup_start_armorvalue;
759 entity get_weaponinfo(float w);
761 float NixNex_CanChooseWeapon(float wpn);
762 void readplayerstartcvars()
768 // initialize starting values for players
771 start_ammo_shells = 0;
772 start_ammo_nails = 0;
773 start_ammo_rockets = 0;
774 start_ammo_cells = 0;
775 start_health = cvar("g_balance_health_start");
776 start_armorvalue = cvar("g_balance_armor_start");
779 s = cvar_string("g_weaponarena");
785 g_weaponarena_list = "All Weapons";
786 for (j = WEP_FIRST; j <= WEP_LAST; ++j)
788 e = get_weaponinfo(j);
789 g_weaponarena |= e.weapons;
790 weapon_action(e.weapon, WR_PRECACHE);
793 else if (s == "most")
795 g_weaponarena_list = "Most Weapons";
796 for (j = WEP_FIRST; j <= WEP_LAST; ++j)
798 e = get_weaponinfo(j);
799 if (e.spawnflags & WEPSPAWNFLAG_NORMAL)
801 g_weaponarena |= e.weapons;
802 weapon_action(e.weapon, WR_PRECACHE);
806 else if (s == "none")
808 g_weaponarena_list = "No Weapons";
809 g_weaponarena = WEPBIT_ALL + 1; // this supports no single weapon bit!
813 t = tokenize_console(s);
814 g_weaponarena_list = "";
815 for (i = 0; i < t; ++i)
818 for (j = WEP_FIRST; j <= WEP_LAST; ++j)
820 e = get_weaponinfo(j);
823 g_weaponarena |= e.weapons;
824 weapon_action(e.weapon, WR_PRECACHE);
825 g_weaponarena_list = strcat(g_weaponarena_list, e.message, " & ");
831 print("The weapon mutator list contains an unknown weapon ", s, ". Skipped.\n");
834 g_weaponarena_list = strzone(substring(g_weaponarena_list, 0, strlen(g_weaponarena_list) - 3));
838 g_weaponarena_random = cvar("g_weaponarena_random");
840 g_weaponarena_random = 0;
845 // will be done later
846 for (i = WEP_FIRST; i <= WEP_LAST; ++i)
847 if (NixNex_CanChooseWeapon(i))
848 weapon_action(i, WR_PRECACHE);
849 if(!cvar("g_use_ammunition"))
850 start_items |= IT_UNLIMITED_AMMO;
852 else if (g_weaponarena)
854 start_weapons = g_weaponarena;
855 if (g_weaponarena & (WEPBIT_GRENADE_LAUNCHER | WEPBIT_HAGAR | WEPBIT_ROCKET_LAUNCHER))
856 start_ammo_rockets = 999;
857 if (g_weaponarena & WEPBIT_SHOTGUN)
858 start_ammo_shells = 999;
859 if (g_weaponarena & (WEPBIT_ELECTRO | WEPBIT_CRYLINK | WEPBIT_NEX | WEPBIT_MINSTANEX | WEPBIT_HLAC | WEPBIT_HOOK))
860 start_ammo_cells = 999;
861 if (g_weaponarena & (WEPBIT_UZI | WEPBIT_CAMPINGRIFLE))
862 start_ammo_nails = 999;
863 if (g_weaponarena & WEPBIT_HOOK)
864 start_ammo_fuel = 999;
865 start_items |= IT_UNLIMITED_AMMO;
867 else if (g_minstagib)
870 start_armorvalue = 0;
871 start_weapons = WEPBIT_MINSTANEX;
872 weapon_action(WEP_MINSTANEX, WR_PRECACHE);
873 start_ammo_cells = cvar("g_minstagib_ammo_start");
874 g_minstagib_invis_alpha = cvar("g_minstagib_invis_alpha");
875 start_ammo_fuel = cvar("g_start_ammo_fuel");
877 if (g_minstagib_invis_alpha <= 0)
878 g_minstagib_invis_alpha = -1;
884 start_ammo_shells = cvar("g_lms_start_ammo_shells");
885 start_ammo_nails = cvar("g_lms_start_ammo_nails");
886 start_ammo_rockets = cvar("g_lms_start_ammo_rockets");
887 start_ammo_cells = cvar("g_lms_start_ammo_cells");
888 start_ammo_fuel = cvar("g_lms_start_ammo_fuel");
889 start_health = cvar("g_lms_start_health");
890 start_armorvalue = cvar("g_lms_start_armor");
892 else if (cvar("g_use_ammunition"))
894 start_ammo_shells = cvar("g_start_ammo_shells");
895 start_ammo_nails = cvar("g_start_ammo_nails");
896 start_ammo_rockets = cvar("g_start_ammo_rockets");
897 start_ammo_cells = cvar("g_start_ammo_cells");
898 start_ammo_fuel = cvar("g_start_ammo_fuel");
902 start_ammo_shells = cvar("g_pickup_shells_max");
903 start_ammo_nails = cvar("g_pickup_nails_max");
904 start_ammo_rockets = cvar("g_pickup_rockets_max");
905 start_ammo_cells = cvar("g_pickup_cells_max");
906 start_ammo_fuel = cvar("g_pickup_fuel_max");
907 start_items |= IT_UNLIMITED_AMMO;
910 for (i = WEP_FIRST; i <= WEP_LAST; ++i)
912 e = get_weaponinfo(i);
916 t = cvar(strcat("g_start_weapon_", e.netname));
918 if (t < 0) // "default" weapon selection
921 t = (e.spawnflags & WEPSPAWNFLAG_NORMAL);
922 else if (g_race || g_cts)
923 t = (i == WEP_LASER);
925 t = 0; // weapon is set a few lines later
927 t = (i == WEP_LASER || i == WEP_SHOTGUN);
928 if (g_grappling_hook) // if possible, redirect off-hand hook to on-hand hook
929 t += (i == WEP_HOOK);
932 if (g_nexball && i == WEP_PORTO)
937 start_weapons |= e.weapons;
938 weapon_action(e.weapon, WR_PRECACHE);
945 warmup_start_ammo_shells = start_ammo_shells;
946 warmup_start_ammo_nails = start_ammo_nails;
947 warmup_start_ammo_rockets = start_ammo_rockets;
948 warmup_start_ammo_cells = start_ammo_cells;
949 warmup_start_ammo_fuel = start_ammo_fuel;
950 warmup_start_health = start_health;
951 warmup_start_armorvalue = start_armorvalue;
952 warmup_start_weapons = start_weapons;
954 if (!g_weaponarena && !g_nixnex && !g_minstagib)
956 if (cvar("g_use_ammunition"))
958 warmup_start_ammo_shells = cvar("g_warmup_start_ammo_shells");
959 warmup_start_ammo_cells = cvar("g_warmup_start_ammo_cells");
960 warmup_start_ammo_nails = cvar("g_warmup_start_ammo_nails");
961 warmup_start_ammo_rockets = cvar("g_warmup_start_ammo_rockets");
962 warmup_start_ammo_fuel = cvar("g_warmup_start_ammo_fuel");
964 warmup_start_health = cvar("g_warmup_start_health");
965 warmup_start_armorvalue = cvar("g_warmup_start_armor");
966 if (cvar("g_warmup_allguns"))
968 for (i = WEP_FIRST; i <= WEP_LAST; ++i)
970 e = get_weaponinfo(i);
973 if (e.spawnflags & WEPSPAWNFLAG_NORMAL)
975 warmup_start_weapons |= e.weapons;
976 weapon_action(e.weapon, WR_PRECACHE);
983 if (g_jetpack || (g_grappling_hook && (start_weapons & WEPBIT_HOOK)))
985 g_grappling_hook = 0; // these two can't coexist, as they use the same button
986 start_items |= IT_FUEL_REGEN;
987 start_ammo_fuel = max(start_ammo_fuel, cvar("g_balance_fuel_rotstable"));
988 warmup_start_ammo_fuel = max(warmup_start_ammo_fuel, cvar("g_balance_fuel_rotstable"));
992 start_items |= IT_JETPACK;
994 if (g_weapon_stay == 2)
996 if (!start_ammo_shells) start_ammo_shells = g_pickup_shells;
997 if (!start_ammo_nails) start_ammo_nails = g_pickup_nails;
998 if (!start_ammo_cells) start_ammo_cells = g_pickup_cells;
999 if (!start_ammo_rockets) start_ammo_rockets = g_pickup_rockets;
1000 if (!start_ammo_fuel) start_ammo_fuel = g_pickup_fuel;
1001 if (!warmup_start_ammo_shells) warmup_start_ammo_shells = g_pickup_shells;
1002 if (!warmup_start_ammo_nails) warmup_start_ammo_nails = g_pickup_nails;
1003 if (!warmup_start_ammo_cells) warmup_start_ammo_cells = g_pickup_cells;
1004 if (!warmup_start_ammo_rockets) warmup_start_ammo_rockets = g_pickup_rockets;
1005 if (!warmup_start_ammo_fuel) warmup_start_ammo_fuel = g_pickup_fuel;
1008 start_ammo_shells = max(0, start_ammo_shells);
1009 start_ammo_nails = max(0, start_ammo_nails);
1010 start_ammo_cells = max(0, start_ammo_cells);
1011 start_ammo_rockets = max(0, start_ammo_rockets);
1012 start_ammo_fuel = max(0, start_ammo_fuel);
1014 warmup_start_ammo_shells = max(0, warmup_start_ammo_shells);
1015 warmup_start_ammo_nails = max(0, warmup_start_ammo_nails);
1016 warmup_start_ammo_cells = max(0, warmup_start_ammo_cells);
1017 warmup_start_ammo_rockets = max(0, warmup_start_ammo_rockets);
1018 warmup_start_ammo_fuel = max(0, warmup_start_ammo_fuel);
1022 float g_bugrigs_planar_movement;
1023 float g_bugrigs_planar_movement_car_jumping;
1024 float g_bugrigs_reverse_spinning;
1025 float g_bugrigs_reverse_speeding;
1026 float g_bugrigs_reverse_stopping;
1027 float g_bugrigs_air_steering;
1028 float g_bugrigs_angle_smoothing;
1029 float g_bugrigs_friction_floor;
1030 float g_bugrigs_friction_brake;
1031 float g_bugrigs_friction_air;
1032 float g_bugrigs_accel;
1033 float g_bugrigs_speed_ref;
1034 float g_bugrigs_speed_pow;
1035 float g_bugrigs_steer;
1037 float g_touchexplode;
1038 float g_touchexplode_radius;
1039 float g_touchexplode_damage;
1040 float g_touchexplode_edgedamage;
1041 float g_touchexplode_force;
1046 void readlevelcvars(void)
1048 g_bugrigs = cvar("g_bugrigs");
1049 g_bugrigs_planar_movement = cvar("g_bugrigs_planar_movement");
1050 g_bugrigs_planar_movement_car_jumping = cvar("g_bugrigs_planar_movement_car_jumping");
1051 g_bugrigs_reverse_spinning = cvar("g_bugrigs_reverse_spinning");
1052 g_bugrigs_reverse_speeding = cvar("g_bugrigs_reverse_speeding");
1053 g_bugrigs_reverse_stopping = cvar("g_bugrigs_reverse_stopping");
1054 g_bugrigs_air_steering = cvar("g_bugrigs_air_steering");
1055 g_bugrigs_angle_smoothing = cvar("g_bugrigs_angle_smoothing");
1056 g_bugrigs_friction_floor = cvar("g_bugrigs_friction_floor");
1057 g_bugrigs_friction_brake = cvar("g_bugrigs_friction_brake");
1058 g_bugrigs_friction_air = cvar("g_bugrigs_friction_air");
1059 g_bugrigs_accel = cvar("g_bugrigs_accel");
1060 g_bugrigs_speed_ref = cvar("g_bugrigs_speed_ref");
1061 g_bugrigs_speed_pow = cvar("g_bugrigs_speed_pow");
1062 g_bugrigs_steer = cvar("g_bugrigs_steer");
1064 g_touchexplode = cvar("g_touchexplode");
1065 g_touchexplode_radius = cvar("g_touchexplode_radius");
1066 g_touchexplode_damage = cvar("g_touchexplode_damage");
1067 g_touchexplode_edgedamage = cvar("g_touchexplode_edgedamage");
1068 g_touchexplode_force = cvar("g_touchexplode_force");
1070 #ifdef ALLOW_FORCEMODELS
1071 sv_clforceplayermodels = cvar("sv_clforceplayermodels");
1073 sv_loddistance1 = cvar("sv_loddistance1");
1074 sv_loddistance2 = cvar("sv_loddistance2");
1075 if(sv_loddistance2 <= sv_loddistance1)
1076 sv_loddistance2 = 1073741824; // enough to turn off LOD 2 reliably
1077 sv_clones = cvar("sv_clones");
1078 sv_cheats = cvar("sv_cheats");
1079 sv_gentle = cvar("sv_gentle");
1080 sv_foginterval = cvar("sv_foginterval");
1081 g_cloaked = cvar("g_cloaked");
1082 g_jump_grunt = cvar("g_jump_grunt");
1083 g_footsteps = cvar("g_footsteps");
1084 g_grappling_hook = cvar("g_grappling_hook");
1085 g_jetpack = cvar("g_jetpack");
1086 g_laserguided_missile = cvar("g_laserguided_missile");
1087 g_midair = cvar("g_midair");
1088 g_minstagib = cvar("g_minstagib");
1089 g_nixnex = cvar("g_nixnex");
1090 g_nixnex_with_laser = cvar("g_nixnex_with_laser");
1091 g_norecoil = cvar("g_norecoil");
1092 g_vampire = cvar("g_vampire");
1093 g_bloodloss = cvar("g_bloodloss");
1094 sv_maxidle = cvar("sv_maxidle");
1095 sv_maxidle_spectatorsareidle = cvar("sv_maxidle_spectatorsareidle");
1096 sv_pogostick = cvar("sv_pogostick");
1097 sv_doublejump = cvar("sv_doublejump");
1098 g_ctf_reverse = cvar("g_ctf_reverse");
1099 sv_autotaunt = cvar("sv_autotaunt");
1100 sv_taunt = cvar("sv_taunt");
1102 inWarmupStage = cvar("g_warmup");
1103 g_warmup_limit = cvar("g_warmup_limit");
1104 g_warmup_allguns = cvar("g_warmup_allguns");
1105 g_warmup_allow_timeout = cvar("g_warmup_allow_timeout");
1107 if ((g_race && g_race_qualifying == 2) || g_runematch || g_arena || g_assault || cvar("g_campaign"))
1108 inWarmupStage = 0; // these modes cannot work together, sorry
1110 g_pickup_respawntime_weapon = cvar("g_pickup_respawntime_weapon");
1111 g_pickup_respawntime_ammo = cvar("g_pickup_respawntime_ammo");
1112 g_pickup_respawntime_short = cvar("g_pickup_respawntime_short");
1113 g_pickup_respawntime_medium = cvar("g_pickup_respawntime_medium");
1114 g_pickup_respawntime_long = cvar("g_pickup_respawntime_long");
1115 g_pickup_respawntime_powerup = cvar("g_pickup_respawntime_powerup");
1116 g_pickup_respawntimejitter_weapon = cvar("g_pickup_respawntimejitter_weapon");
1117 g_pickup_respawntimejitter_ammo = cvar("g_pickup_respawntimejitter_ammo");
1118 g_pickup_respawntimejitter_short = cvar("g_pickup_respawntimejitter_short");
1119 g_pickup_respawntimejitter_medium = cvar("g_pickup_respawntimejitter_medium");
1120 g_pickup_respawntimejitter_long = cvar("g_pickup_respawntimejitter_long");
1121 g_pickup_respawntimejitter_powerup = cvar("g_pickup_respawntimejitter_powerup");
1123 if (g_minstagib) g_nixnex = g_weaponarena = 0;
1124 if (g_nixnex) g_weaponarena = 0;
1127 g_weaponspeedfactor = cvar("g_weaponspeedfactor");
1128 g_weaponratefactor = cvar("g_weaponratefactor");
1129 g_weapondamagefactor = cvar("g_weapondamagefactor");
1130 g_weaponforcefactor = cvar("g_weaponforcefactor");
1132 g_pickup_shells = cvar("g_pickup_shells");
1133 g_pickup_shells_max = cvar("g_pickup_shells_max");
1134 g_pickup_nails = cvar("g_pickup_nails");
1135 g_pickup_nails_max = cvar("g_pickup_nails_max");
1136 g_pickup_rockets = cvar("g_pickup_rockets");
1137 g_pickup_rockets_max = cvar("g_pickup_rockets_max");
1138 g_pickup_cells = cvar("g_pickup_cells");
1139 g_pickup_cells_max = cvar("g_pickup_cells_max");
1140 g_pickup_fuel = cvar("g_pickup_fuel");
1141 g_pickup_fuel_jetpack = cvar("g_pickup_fuel_jetpack");
1142 g_pickup_fuel_max = cvar("g_pickup_fuel_max");
1143 g_pickup_armorsmall = cvar("g_pickup_armorsmall");
1144 g_pickup_armorsmall_max = cvar("g_pickup_armorsmall_max");
1145 g_pickup_armormedium = cvar("g_pickup_armormedium");
1146 g_pickup_armormedium_max = cvar("g_pickup_armormedium_max");
1147 g_pickup_armorbig = cvar("g_pickup_armorbig");
1148 g_pickup_armorbig_max = cvar("g_pickup_armorbig_max");
1149 g_pickup_armorlarge = cvar("g_pickup_armorlarge");
1150 g_pickup_armorlarge_max = cvar("g_pickup_armorlarge_max");
1151 g_pickup_healthsmall = cvar("g_pickup_healthsmall");
1152 g_pickup_healthsmall_max = cvar("g_pickup_healthsmall_max");
1153 g_pickup_healthmedium = cvar("g_pickup_healthmedium");
1154 g_pickup_healthmedium_max = cvar("g_pickup_healthmedium_max");
1155 g_pickup_healthlarge = cvar("g_pickup_healthlarge");
1156 g_pickup_healthlarge_max = cvar("g_pickup_healthlarge_max");
1157 g_pickup_healthmega = cvar("g_pickup_healthmega");
1158 g_pickup_healthmega_max = cvar("g_pickup_healthmega_max");
1160 g_pinata = cvar("g_pinata");
1162 g_weapon_stay = cvar("g_weapon_stay");
1163 if (!g_weapon_stay && (cvar("deathmatch") == 2))
1165 g_ghost_items = cvar("g_ghost_items");
1166 if(g_ghost_items >= 1)
1167 g_ghost_items = 0.13; // default alpha value
1169 if not(inWarmupStage)
1170 game_starttime = cvar("g_start_delay");
1172 readplayerstartcvars();
1176 // TODO sound pack system
1179 string precache_sound_builtin (string s) = #19;
1180 void(entity e, float chan, string samp, float vol, float atten) sound_builtin = #8;
1181 string precache_sound(string s)
1183 return precache_sound_builtin(strcat(soundpack, s));
1185 void play2(entity e, string filename)
1187 stuffcmd(e, strcat("play2 ", soundpack, filename, "\n"));
1189 void sound(entity e, float chan, string samp, float vol, float atten)
1191 sound_builtin(e, chan, strcat(soundpack, samp), vol, atten);
1196 string precache_sound (string s) = #19;
1197 void(entity e, float chan, string samp, float vol, float atten) sound_builtin = #8;
1198 float precache_sound_index (string s) = #19;
1200 #define SND_VOLUME 1
1201 #define SND_ATTENUATION 2
1202 #define SND_LARGEENTITY 8
1203 #define SND_LARGESOUND 16
1205 float sound_allowed(float dest, entity e)
1207 // sounds from world may always pass
1210 if (e.classname == "body")
1212 if (e.owner && e.owner != e)
1217 // sounds to self may always pass
1218 if (dest == MSG_ONE)
1219 if (e == msg_entity)
1221 // sounds by players can be removed
1222 if (cvar("bot_sound_monopoly"))
1223 if (clienttype(e) == CLIENTTYPE_REAL)
1225 // anything else may pass
1229 void sound(entity e, float chan, string samp, float vol, float atten)
1231 if (!sound_allowed(MSG_BROADCAST, e))
1233 sound_builtin(e, chan, samp, vol, atten);
1235 void soundtoat(float dest, entity e, vector o, float chan, string samp, float vol, float atten)
1239 if (!sound_allowed(dest, e))
1242 entno = num_for_edict(e);
1243 idx = precache_sound_index(samp);
1248 atten = floor(atten * 64);
1249 vol = floor(vol * 255);
1252 sflags |= SND_VOLUME;
1254 sflags |= SND_ATTENUATION;
1256 sflags |= SND_LARGEENTITY;
1258 sflags |= SND_LARGESOUND;
1260 WriteByte(dest, SVC_SOUND);
1261 WriteByte(dest, sflags);
1262 if (sflags & SND_VOLUME)
1263 WriteByte(dest, vol);
1264 if (sflags & SND_ATTENUATION)
1265 WriteByte(dest, atten);
1266 if (sflags & SND_LARGEENTITY)
1268 WriteShort(dest, entno);
1269 WriteByte(dest, chan);
1273 WriteShort(dest, entno * 8 + chan);
1275 if (sflags & SND_LARGESOUND)
1276 WriteShort(dest, idx);
1278 WriteByte(dest, idx);
1280 WriteCoord(dest, o_x);
1281 WriteCoord(dest, o_y);
1282 WriteCoord(dest, o_z);
1284 void soundto(float dest, entity e, float chan, string samp, float vol, float atten)
1288 if (!sound_allowed(dest, e))
1291 o = e.origin + 0.5 * (e.mins + e.maxs);
1292 soundtoat(dest, e, o, chan, samp, vol, atten);
1294 void soundat(entity e, vector o, float chan, string samp, float vol, float atten)
1296 soundtoat(MSG_BROADCAST, e, o, chan, samp, vol, atten);
1298 void stopsoundto(float dest, entity e, float chan)
1302 if (!sound_allowed(dest, e))
1305 entno = num_for_edict(e);
1310 idx = precache_sound_index("misc/null.wav");
1311 sflags = SND_LARGEENTITY;
1313 sflags |= SND_LARGESOUND;
1314 WriteByte(dest, SVC_SOUND);
1315 WriteByte(dest, sflags);
1316 WriteShort(dest, entno);
1317 WriteByte(dest, chan);
1318 if (sflags & SND_LARGESOUND)
1319 WriteShort(dest, idx);
1321 WriteByte(dest, idx);
1322 WriteCoord(dest, e.origin_x);
1323 WriteCoord(dest, e.origin_y);
1324 WriteCoord(dest, e.origin_z);
1328 WriteByte(dest, SVC_STOPSOUND);
1329 WriteShort(dest, entno * 8 + chan);
1332 void stopsound(entity e, float chan)
1334 if (!sound_allowed(MSG_BROADCAST, e))
1337 stopsoundto(MSG_BROADCAST, e, chan); // unreliable, gets there fast
1338 stopsoundto(MSG_ALL, e, chan); // in case of packet loss
1341 void play2(entity e, string filename)
1343 //stuffcmd(e, strcat("play2 ", filename, "\n"));
1345 soundtoat(MSG_ONE, world, '0 0 0', CHAN_AUTO, filename, VOL_BASE, ATTN_NONE);
1348 .float announcetime;
1349 float announce(entity player, string msg)
1351 if (time > player.announcetime)
1352 if (clienttype(player) == CLIENTTYPE_REAL)
1354 player.announcetime = time + 0.8;
1360 // use this one if you might be causing spam (e.g. from touch functions that might get called more than once per frame)
1361 float spamsound(entity e, float chan, string samp, float vol, float atten)
1363 if (!sound_allowed(MSG_BROADCAST, e))
1366 if (time > e.announcetime)
1368 e.announcetime = time;
1369 sound(e, chan, samp, vol, atten);
1375 void play2team(float t, string filename)
1379 if (cvar("bot_sound_monopoly"))
1382 FOR_EACH_REALPLAYER(head)
1385 play2(head, filename);
1389 void play2all(string samp)
1391 if (cvar("bot_sound_monopoly"))
1394 sound(world, CHAN_AUTO, samp, VOL_BASE, ATTN_NONE);
1397 void PrecachePlayerSounds(string f);
1398 void precache_all_models(string pattern)
1400 float globhandle, i, n;
1403 globhandle = search_begin(pattern, TRUE, FALSE);
1406 n = search_getsize(globhandle);
1407 for (i = 0; i < n; ++i)
1409 //print(search_getfilename(globhandle, i), "\n");
1410 f = search_getfilename(globhandle, i);
1413 if(substring(f, -9,5) == "_lod1")
1415 if(substring(f, -9,5) == "_lod2")
1417 if(!sv_loddistance1)
1419 PrecachePlayerSounds(strcat(f, ".sounds"));
1421 search_end(globhandle);
1426 // gamemode related things
1427 precache_model ("models/misc/chatbubble.spr");
1428 precache_model ("models/misc/teambubble.spr");
1431 precache_model ("models/runematch/curse.mdl");
1432 precache_model ("models/runematch/rune.mdl");
1435 #ifdef TTURRETS_ENABLED
1436 if (cvar("g_turrets"))
1440 // Precache all player models if desired
1441 if (cvar("sv_precacheplayermodels"))
1443 PrecachePlayerSounds("sound/player/default.sounds");
1444 precache_all_models("models/player/*.zym");
1445 precache_all_models("models/player/*.dpm");
1446 precache_all_models("models/player/*.md3");
1447 precache_all_models("models/player/*.psk");
1448 //precache_model("models/player/carni.zym");
1449 //precache_model("models/player/crash.zym");
1450 //precache_model("models/player/grunt.zym");
1451 //precache_model("models/player/headhunter.zym");
1452 //precache_model("models/player/insurrectionist.zym");
1453 //precache_model("models/player/jeandarc.zym");
1454 //precache_model("models/player/lurk.zym");
1455 //precache_model("models/player/lycanthrope.zym");
1456 //precache_model("models/player/marine.zym");
1457 //precache_model("models/player/nexus.zym");
1458 //precache_model("models/player/pyria.zym");
1459 //precache_model("models/player/shock.zym");
1460 //precache_model("models/player/skadi.zym");
1461 //precache_model("models/player/specop.zym");
1462 //precache_model("models/player/visitant.zym");
1465 if (cvar("sv_defaultcharacter"))
1468 s = cvar_string("sv_defaultplayermodel_red");
1472 PrecachePlayerSounds(strcat(s, ".sounds"));
1474 s = cvar_string("sv_defaultplayermodel_blue");
1478 PrecachePlayerSounds(strcat(s, ".sounds"));
1480 s = cvar_string("sv_defaultplayermodel_yellow");
1484 PrecachePlayerSounds(strcat(s, ".sounds"));
1486 s = cvar_string("sv_defaultplayermodel_pink");
1490 PrecachePlayerSounds(strcat(s, ".sounds"));
1492 s = cvar_string("sv_defaultplayermodel");
1496 PrecachePlayerSounds(strcat(s, ".sounds"));
1502 PrecacheGlobalSound((globalsound_step = "misc/footstep0 6"));
1503 PrecacheGlobalSound((globalsound_metalstep = "misc/metalfootstep0 6"));
1506 // gore and miscellaneous sounds
1507 //precache_sound ("misc/h2ohit.wav");
1508 precache_model ("models/hook.md3");
1509 precache_sound ("misc/armorimpact.wav");
1510 precache_sound ("misc/bodyimpact1.wav");
1511 precache_sound ("misc/bodyimpact2.wav");
1512 precache_sound ("misc/gib.wav");
1513 precache_sound ("misc/gib_splat01.wav");
1514 precache_sound ("misc/gib_splat02.wav");
1515 precache_sound ("misc/gib_splat03.wav");
1516 precache_sound ("misc/gib_splat04.wav");
1517 precache_sound ("misc/hit.wav");
1518 PrecacheGlobalSound((globalsound_fall = "misc/hitground 4"));
1519 PrecacheGlobalSound((globalsound_metalfall = "misc/metalhitground 4"));
1520 precache_sound ("misc/null.wav");
1521 precache_sound ("misc/spawn.wav");
1522 precache_sound ("misc/talk.wav");
1523 precache_sound ("misc/teleport.wav");
1524 precache_sound ("misc/poweroff.wav");
1525 precache_sound ("player/lava.wav");
1526 precache_sound ("player/slime.wav");
1529 precache_sound ("misc/jetpack_fly.wav");
1531 // announcer sounds - male
1532 precache_sound ("announcer/male/electrobitch.wav");
1533 precache_sound ("announcer/male/airshot.wav");
1534 precache_sound ("announcer/male/03kills.wav");
1535 precache_sound ("announcer/male/05kills.wav");
1536 precache_sound ("announcer/male/10kills.wav");
1537 precache_sound ("announcer/male/15kills.wav");
1538 precache_sound ("announcer/male/20kills.wav");
1539 precache_sound ("announcer/male/25kills.wav");
1540 precache_sound ("announcer/male/30kills.wav");
1541 precache_sound ("announcer/male/botlike.wav");
1542 precache_sound ("announcer/male/yoda.wav");
1543 precache_sound ("announcer/male/amazing.wav");
1544 precache_sound ("announcer/male/awesome.wav");
1545 precache_sound ("announcer/male/headshot.wav");
1546 precache_sound ("announcer/male/impressive.wav");
1548 // announcer sounds - robotic
1549 precache_sound ("announcer/robotic/prepareforbattle.wav");
1550 precache_sound ("announcer/robotic/begin.wav");
1551 precache_sound ("announcer/robotic/timeoutcalled.wav");
1552 precache_sound ("announcer/robotic/1fragleft.wav");
1553 precache_sound ("announcer/robotic/2fragsleft.wav");
1554 precache_sound ("announcer/robotic/3fragsleft.wav");
1555 precache_sound ("announcer/robotic/terminated.wav");
1558 precache_sound ("announcer/robotic/lastsecond.wav");
1559 precache_sound ("announcer/robotic/narrowly.wav");
1562 precache_model ("models/sprites/0.spr32");
1563 precache_model ("models/sprites/1.spr32");
1564 precache_model ("models/sprites/2.spr32");
1565 precache_model ("models/sprites/3.spr32");
1566 precache_model ("models/sprites/4.spr32");
1567 precache_model ("models/sprites/5.spr32");
1568 precache_model ("models/sprites/6.spr32");
1569 precache_model ("models/sprites/7.spr32");
1570 precache_model ("models/sprites/8.spr32");
1571 precache_model ("models/sprites/9.spr32");
1572 precache_model ("models/sprites/10.spr32");
1573 precache_sound ("announcer/robotic/1.wav");
1574 precache_sound ("announcer/robotic/2.wav");
1575 precache_sound ("announcer/robotic/3.wav");
1576 precache_sound ("announcer/robotic/4.wav");
1577 precache_sound ("announcer/robotic/5.wav");
1578 precache_sound ("announcer/robotic/6.wav");
1579 precache_sound ("announcer/robotic/7.wav");
1580 precache_sound ("announcer/robotic/8.wav");
1581 precache_sound ("announcer/robotic/9.wav");
1582 precache_sound ("announcer/robotic/10.wav");
1584 // common weapon precaches
1585 precache_sound ("weapons/weapon_switch.wav");
1586 precache_sound ("weapons/weaponpickup.wav");
1587 precache_sound ("weapons/unavailable.wav");
1588 if (g_grappling_hook)
1590 precache_sound ("weapons/hook_fire.wav"); // hook
1591 precache_sound ("weapons/hook_impact.wav"); // hook
1594 if (cvar("sv_precacheweapons") || g_nixnex)
1596 //precache weapon models/sounds
1599 while (wep <= WEP_LAST)
1601 weapon_action(wep, WR_PRECACHE);
1606 precache_model("models/elaser.mdl");
1607 precache_model("models/laser.mdl");
1608 precache_model("models/ebomb.mdl");
1611 // Disabled this code because it simply does not work (e.g. ignores bgmvolume, overlaps with "cd loop" controlled tracks).
1613 if (!self.noise && self.music) // quake 3 uses the music field
1614 self.noise = self.music;
1616 // plays music for the level if there is any
1619 precache_sound (self.noise);
1620 ambientsound ('0 0 0', self.noise, VOL_BASE, ATTN_NONE);
1625 // sorry, but using \ in macros breaks line numbers
1626 #define WRITESPECTATABLE_MSG_ONE_VARNAME(varname,statement) entity varname; varname = msg_entity; FOR_EACH_REALCLIENT(msg_entity) if(msg_entity == varname || (msg_entity.classname == STR_SPECTATOR && msg_entity.enemy == varname)) statement msg_entity = varname
1627 #define WRITESPECTATABLE_MSG_ONE(statement) WRITESPECTATABLE_MSG_ONE_VARNAME(oldmsg_entity, statement)
1628 #define WRITESPECTATABLE(msg,statement) if(msg == MSG_ONE) { WRITESPECTATABLE_MSG_ONE(statement); } else statement float WRITESPECTATABLE_workaround = 0
1630 vector ExactTriggerHit_mins;
1631 vector ExactTriggerHit_maxs;
1632 float ExactTriggerHit_Recurse()
1638 tracebox('0 0 0', ExactTriggerHit_mins, ExactTriggerHit_maxs, '0 0 0', MOVE_NORMAL, other);
1641 if (trace_ent == self)
1646 se.solid = SOLID_NOT;
1647 f = ExactTriggerHit_Recurse();
1653 float ExactTriggerHit()
1657 if not(self.modelindex)
1661 self.solid = SOLID_BSP;
1662 ExactTriggerHit_mins = other.absmin;
1663 ExactTriggerHit_maxs = other.absmax;
1664 f = ExactTriggerHit_Recurse();
1670 // WARNING: this kills the trace globals
1671 #define EXACTTRIGGER_TOUCH if not(ExactTriggerHit()) return
1672 #define EXACTTRIGGER_INIT InitSolidBSPTrigger(); self.solid = SOLID_TRIGGER
1674 #define INITPRIO_FIRST 0
1675 #define INITPRIO_GAMETYPE 0
1676 #define INITPRIO_GAMETYPE_FALLBACK 1
1677 #define INITPRIO_CVARS 5
1678 #define INITPRIO_FINDTARGET 10
1679 #define INITPRIO_DROPTOFLOOR 20
1680 #define INITPRIO_SETLOCATION 90
1681 #define INITPRIO_LINKDOORS 91
1682 #define INITPRIO_LAST 99
1684 .void(void) initialize_entity;
1685 .float initialize_entity_order;
1686 .entity initialize_entity_next;
1687 entity initialize_entity_first;
1689 void make_safe_for_remove(entity e)
1691 if (e.initialize_entity)
1694 for (ent = initialize_entity_first; ent; )
1696 if ((ent == e) || ((ent.classname == "initialize_entity") && (ent.enemy == e)))
1698 //print("make_safe_for_remove: getting rid of initializer ", etos(ent), "\n");
1699 // skip it in linked list
1702 prev.initialize_entity_next = ent.initialize_entity_next;
1703 ent = prev.initialize_entity_next;
1707 initialize_entity_first = ent.initialize_entity_next;
1708 ent = initialize_entity_first;
1714 ent = ent.initialize_entity_next;
1720 void objerror(string s)
1722 make_safe_for_remove(self);
1723 objerror_builtin(s);
1726 void remove_unsafely(entity e)
1731 void remove_safely(entity e)
1733 make_safe_for_remove(e);
1737 void InitializeEntity(entity e, void(void) func, float order)
1741 if (!e || e.initialize_entity)
1743 // make a proxy initializer entity
1747 e.classname = "initialize_entity";
1751 e.initialize_entity = func;
1752 e.initialize_entity_order = order;
1754 cur = initialize_entity_first;
1757 if (!cur || cur.initialize_entity_order > order)
1759 // insert between prev and cur
1761 prev.initialize_entity_next = e;
1763 initialize_entity_first = e;
1764 e.initialize_entity_next = cur;
1768 cur = cur.initialize_entity_next;
1771 void InitializeEntitiesRun()
1774 startoflist = initialize_entity_first;
1775 initialize_entity_first = world;
1776 for (self = startoflist; self; )
1779 var void(void) func;
1780 e = self.initialize_entity_next;
1781 func = self.initialize_entity;
1782 self.initialize_entity_order = 0;
1783 self.initialize_entity = func_null;
1784 self.initialize_entity_next = world;
1785 if (self.classname == "initialize_entity")
1789 remove_builtin(self);
1792 //dprint("Delayed initialization: ", self.classname, "\n");
1798 .float uncustomizeentityforclient_set;
1799 .void(void) uncustomizeentityforclient;
1800 void(void) SUB_Nullpointer = #0;
1801 void UncustomizeEntitiesRun()
1805 for (self = world; (self = findfloat(self, uncustomizeentityforclient_set, 1)); )
1806 self.uncustomizeentityforclient();
1809 void SetCustomizer(entity e, float(void) customizer, void(void) uncustomizer)
1811 e.customizeentityforclient = customizer;
1812 e.uncustomizeentityforclient = uncustomizer;
1813 e.uncustomizeentityforclient_set = (uncustomizer != SUB_Nullpointer);
1817 #define IFTARGETED if(!self.nottargeted && self.targetname != "")
1820 void Net_LinkEntity(entity e, float docull, float dt, float(entity, float) sendfunc)
1824 if (e.classname == "")
1825 e.classname = "net_linked";
1827 if (e.model == "" || self.modelindex == 0)
1831 setmodel(e, "null");
1835 e.SendEntity = sendfunc;
1836 e.SendFlags = 0xFFFFFF;
1839 e.effects |= EF_NODEPTHTEST;
1843 e.nextthink = time + dt;
1844 e.think = SUB_Remove;
1848 void adaptor_think2touch()
1857 void adaptor_think2use()
1869 // deferred dropping
1870 void DropToFloor_Handler()
1872 droptofloor_builtin();
1873 self.dropped_origin = self.origin;
1878 InitializeEntity(self, DropToFloor_Handler, INITPRIO_DROPTOFLOOR);
1883 float trace_hits_box_a0, trace_hits_box_a1;
1885 float trace_hits_box_1d(float end, float thmi, float thma)
1889 // just check if x is in range
1897 // do the trace with respect to x
1898 // 0 -> end has to stay in thmi -> thma
1899 trace_hits_box_a0 = max(trace_hits_box_a0, min(thmi / end, thma / end));
1900 trace_hits_box_a1 = min(trace_hits_box_a1, max(thmi / end, thma / end));
1901 if (trace_hits_box_a0 > trace_hits_box_a1)
1907 float trace_hits_box(vector start, vector end, vector thmi, vector thma)
1912 // now it is a trace from 0 to end
1914 trace_hits_box_a0 = 0;
1915 trace_hits_box_a1 = 1;
1917 if (!trace_hits_box_1d(end_x, thmi_x, thma_x))
1919 if (!trace_hits_box_1d(end_y, thmi_y, thma_y))
1921 if (!trace_hits_box_1d(end_z, thmi_z, thma_z))
1927 float tracebox_hits_box(vector start, vector mi, vector ma, vector end, vector thmi, vector thma)
1929 return trace_hits_box(start, end, thmi - ma, thma - mi);
1932 float SUB_NoImpactCheck()
1934 // zero hitcontents = this is not the real impact, but either the
1935 // mirror-impact of something hitting the projectile instead of the
1936 // projectile hitting the something, or a touchareagrid one. Neither of
1937 // these stop the projectile from moving, so...
1938 if(trace_dphitcontents == 0)
1940 dprint("A hit happened with zero hit contents... DEBUG THIS, this should never happen for projectiles! Projectile will self-destruct.\n");
1943 if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
1945 if (other == world && self.size != '0 0 0')
1948 tic = self.velocity * sys_ticrate;
1949 tic = tic + normalize(tic) * vlen(self.maxs - self.mins);
1950 traceline(self.origin - tic, self.origin + tic, MOVE_NORMAL, self);
1951 if (trace_fraction >= 1)
1953 dprint("Odd... did not hit...?\n");
1955 else if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
1957 dprint("Detected and prevented the sky-grapple bug.\n");
1965 #define SUB_OwnerCheck() (other && (other == self.owner))
1967 #define PROJECTILE_TOUCH do { if(SUB_OwnerCheck()) return; if(SUB_NoImpactCheck()) { remove(self); return; } if(trace_ent && trace_ent.solid > SOLID_TRIGGER) UpdateCSQCProjectileNextFrame(self); } while(0)
1969 float MAX_IPBAN_URIS = 16;
1971 float URI_GET_DISCARD = 0;
1972 float URI_GET_IPBAN = 1;
1973 float URI_GET_IPBAN_END = 16;
1975 void URI_Get_Callback(float id, float status, string data)
1977 dprint("Received HTTP request data for id ", ftos(id), "; status is ", ftos(status), "\nData is:\n");
1979 dprint("\nEnd of data.\n");
1981 if (id == URI_GET_DISCARD)
1985 else if (id >= URI_GET_IPBAN && id <= URI_GET_IPBAN_END)
1988 OnlineBanList_URI_Get_Callback(id, status, data);
1992 print("Received HTTP request data for an invalid id ", ftos(id), ".\n");
1996 void print_to(entity e, string s)
1999 sprint(e, strcat(s, "\n"));
2018 for (i = 0; i < MapInfo_count; ++i)
2020 if (MapInfo_Get_ByID(i))
2022 r = stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, "/captimerecord/time")));
2025 h = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, "/captimerecord/netname"));
2026 s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-6, ftos_decimals(r, 2)), " ", h, "\n");
2034 for (i = 0; i < MapInfo_count; ++i)
2036 if (MapInfo_Get_ByID(i))
2038 r = stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, RACE_RECORD, "time")));
2041 h = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, RACE_RECORD, "netname"));
2042 s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-8, TIME_ENCODED_TOSTRING(r)), " ", h, "\n");
2050 for (i = 0; i < MapInfo_count; ++i)
2052 if (MapInfo_Get_ByID(i))
2054 r = stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, CTS_RECORD, "time")));
2057 h = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, CTS_RECORD, "netname"));
2058 s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-8, TIME_ENCODED_TOSTRING(r)), " ", h, "\n");
2064 MapInfo_ClearTemps();
2067 return "No records are available on this server.\n";
2069 return strcat("Records on this server:\n", s);
2072 float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
2075 vector start, org, delta, end, enddown, mstart;
2077 m = e.dphitcontentsmask;
2078 e.dphitcontentsmask = goodcontents | badcontents;
2081 delta = world.maxs - world.mins;
2083 for (i = 0; i < attempts; ++i)
2085 start_x = org_x + random() * delta_x;
2086 start_y = org_y + random() * delta_y;
2087 start_z = org_z + random() * delta_z;
2089 // rule 1: start inside world bounds, and outside
2090 // solid, and don't start from somewhere where you can
2091 // fall down to evil
2092 tracebox(start, e.mins, e.maxs, start - '0 0 1' * delta_z, MOVE_NORMAL, e);
2093 if (trace_fraction >= 1)
2095 if (trace_startsolid)
2097 if (trace_dphitcontents & badcontents)
2099 if (trace_dphitq3surfaceflags & badsurfaceflags)
2102 // rule 2: if we are too high, lower the point
2103 if (trace_fraction * delta_z > maxaboveground)
2104 start = trace_endpos + '0 0 1' * maxaboveground;
2105 enddown = trace_endpos;
2107 // rule 3: make sure we aren't outside the map. This only works
2108 // for somewhat well formed maps. A good rule of thumb is that
2109 // the map should have a convex outside hull.
2110 // these can be traceLINES as we already verified the starting box
2111 mstart = start + 0.5 * (e.mins + e.maxs);
2112 traceline(mstart, mstart + '1 0 0' * delta_x, MOVE_NORMAL, e);
2113 if (trace_fraction >= 1)
2115 traceline(mstart, mstart - '1 0 0' * delta_x, MOVE_NORMAL, e);
2116 if (trace_fraction >= 1)
2118 traceline(mstart, mstart + '0 1 0' * delta_y, MOVE_NORMAL, e);
2119 if (trace_fraction >= 1)
2121 traceline(mstart, mstart - '0 1 0' * delta_y, MOVE_NORMAL, e);
2122 if (trace_fraction >= 1)
2124 traceline(mstart, mstart + '0 0 1' * delta_z, MOVE_NORMAL, e);
2125 if (trace_fraction >= 1)
2128 // find a random vector to "look at"
2129 end_x = org_x + random() * delta_x;
2130 end_y = org_y + random() * delta_y;
2131 end_z = org_z + random() * delta_z;
2132 end = start + normalize(end - start) * vlen(delta);
2134 // rule 4: start TO end must not be too short
2135 tracebox(start, e.mins, e.maxs, end, MOVE_NORMAL, e);
2136 if (trace_startsolid)
2138 if (trace_fraction < minviewdistance / vlen(delta))
2141 // rule 5: don't want to look at sky
2142 if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
2145 // rule 6: we must not end up in trigger_hurt
2146 if (tracebox_hits_trigger_hurt(start, e.mins, e.maxs, enddown))
2148 dprint("trigger_hurt! ouch! and nothing else could find it!\n");
2155 e.dphitcontentsmask = m;
2159 setorigin(e, start);
2160 e.angles = vectoangles(end - start);
2161 dprint("Needed ", ftos(i + 1), " attempts\n");
2168 float zcurveparticles_effectno;
2169 vector zcurveparticles_start;
2170 float zcurveparticles_spd;
2172 void endzcurveparticles()
2174 if(zcurveparticles_effectno)
2177 WriteShort(MSG_BROADCAST, zcurveparticles_spd | 0x8000);
2179 zcurveparticles_effectno = 0;
2182 void zcurveparticles(float effectno, vector start, vector end, float end_dz, float spd)
2184 spd = bound(0, floor(spd / 16), 32767);
2185 if(effectno != zcurveparticles_effectno || start != zcurveparticles_start)
2187 endzcurveparticles();
2188 WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
2189 WriteByte(MSG_BROADCAST, TE_CSQC_ZCURVEPARTICLES);
2190 WriteShort(MSG_BROADCAST, effectno);
2191 WriteCoord(MSG_BROADCAST, start_x);
2192 WriteCoord(MSG_BROADCAST, start_y);
2193 WriteCoord(MSG_BROADCAST, start_z);
2194 zcurveparticles_effectno = effectno;
2195 zcurveparticles_start = start;
2198 WriteShort(MSG_BROADCAST, zcurveparticles_spd);
2199 WriteCoord(MSG_BROADCAST, end_x);
2200 WriteCoord(MSG_BROADCAST, end_y);
2201 WriteCoord(MSG_BROADCAST, end_z);
2202 WriteCoord(MSG_BROADCAST, end_dz);
2203 zcurveparticles_spd = spd;
2206 void zcurveparticles_from_tracetoss(float effectno, vector start, vector end, vector vel)
2209 vector vecxy, velxy;
2211 vecxy = end - start;
2216 if (vlen(velxy) < 0.000001 * fabs(vel_z))
2218 endzcurveparticles();
2219 trailparticles(world, effectno, start, end);
2223 end_dz = vlen(vecxy) / vlen(velxy) * vel_z - (end_z - start_z);
2224 zcurveparticles(effectno, start, end, end_dz, vlen(vel));
2227 string GetGametype(); // g_world.qc
2228 void write_recordmarker(entity pl, float tstart, float dt)
2230 GameLogEcho(strcat(":recordset:", ftos(pl.playerid), ":", ftos(dt)));
2232 // also write a marker into demo files for demotc-race-record-extractor to find
2235 strcat("//", strconv(2, 0, 0, GetGametype()), " RECORD SET ", TIME_ENCODED_TOSTRING(TIME_ENCODE(dt))),
2236 " ", ftos(tstart), " ", ftos(dt), "\n"));
2239 vector shotorg_adjustfromclient(vector vecs, float y_is_right, float allowcenter)
2241 switch(self.owner.cvar_cl_gunalign)
2252 if(allowcenter) // 2: allow center handedness
2265 if(allowcenter) // 2: allow center handedness
2281 vector shotorg_adjust(vector vecs, float y_is_right, float visual)
2286 if (cvar("g_shootfromeye"))
2290 vecs = shotorg_adjustfromclient(vecs, y_is_right, TRUE);
2298 else if (cvar("g_shootfromcenter"))
2302 vecs = shotorg_adjustfromclient(vecs, y_is_right, TRUE);
2310 else if (cvar("g_shootfromclient"))
2312 vecs = shotorg_adjustfromclient(vecs, y_is_right, (cvar("g_shootfromclient") >= 2));
2314 else if ((s = cvar_string("g_shootfromfixedorigin")) != "")
2329 void attach_sameorigin(entity e, entity to, string tag)
2331 vector org, t_forward, t_left, t_up, e_forward, e_up;
2338 org = e.origin - gettaginfo(to, gettagindex(to, tag));
2339 tagscale = pow(vlen(v_forward), -2); // undo a scale on the tag
2340 t_forward = v_forward * tagscale;
2341 t_left = v_right * -tagscale;
2342 t_up = v_up * tagscale;
2344 e.origin_x = org * t_forward;
2345 e.origin_y = org * t_left;
2346 e.origin_z = org * t_up;
2348 // current forward and up directions
2349 if (substring(e.model, 0, 1) == "*") // bmodels have their own rules
2350 e.angles_x = -e.angles_x;
2351 fixedmakevectors(e.angles);
2353 // untransform forward, up!
2354 e_forward_x = v_forward * t_forward;
2355 e_forward_y = v_forward * t_left;
2356 e_forward_z = v_forward * t_up;
2357 e_up_x = v_up * t_forward;
2358 e_up_y = v_up * t_left;
2359 e_up_z = v_up * t_up;
2361 e.angles = fixedvectoangles2(e_forward, e_up);
2362 if (substring(e.model, 0, 1) == "*") // bmodels have their own rules
2363 e.angles_x = -e.angles_x;
2365 setattachment(e, to, tag);
2366 setorigin(e, e.origin);
2369 void detach_sameorigin(entity e)
2372 org = gettaginfo(e, 0);
2373 e.angles = fixedvectoangles2(v_forward, v_up);
2374 if (substring(e.model, 0, 1) == "*") // bmodels have their own rules
2375 e.angles_x = -e.angles_x;
2377 setattachment(e, world, "");
2378 setorigin(e, e.origin);
2381 void follow_sameorigin(entity e, entity to)
2383 e.movetype = MOVETYPE_FOLLOW; // make the hole follow
2384 e.aiment = to; // make the hole follow bmodel
2385 e.punchangle = to.angles; // the original angles of bmodel
2386 e.view_ofs = e.origin - to.origin; // relative origin
2387 e.v_angle = e.angles - to.angles; // relative angles
2390 void unfollow_sameorigin(entity e)
2392 e.movetype = MOVETYPE_NONE;
2395 entity gettaginfo_relative_ent;
2396 vector gettaginfo_relative(entity e, float tag)
2398 if (!gettaginfo_relative_ent)
2400 gettaginfo_relative_ent = spawn();
2401 gettaginfo_relative_ent.effects = EF_NODRAW;
2403 gettaginfo_relative_ent.model = e.model;
2404 gettaginfo_relative_ent.modelindex = e.modelindex;
2405 gettaginfo_relative_ent.frame = e.frame;
2406 return gettaginfo(gettaginfo_relative_ent, tag);
2409 void SoundEntity_StartSound(entity pl, float chan, string samp, float vol, float attn)
2413 if (pl.soundentity.cnt & p)
2415 soundtoat(MSG_ALL, pl.soundentity, gettaginfo(pl.soundentity, 0), chan, samp, vol, attn);
2416 pl.soundentity.cnt |= p;
2419 void SoundEntity_StopSound(entity pl, float chan)
2423 if (pl.soundentity.cnt & p)
2425 stopsoundto(MSG_ALL, pl.soundentity, chan);
2426 pl.soundentity.cnt &~= p;
2430 void SoundEntity_Attach(entity pl)
2432 pl.soundentity = spawn();
2433 pl.soundentity.classname = "soundentity";
2434 pl.soundentity.owner = pl;
2435 setattachment(pl.soundentity, pl, "");
2436 setmodel(pl.soundentity, "null");
2439 void SoundEntity_Detach(entity pl)
2442 for (i = 0; i <= 7; ++i)
2443 SoundEntity_StopSound(pl, i);
2447 float ParseCommandPlayerSlotTarget_firsttoken;
2448 entity GetCommandPlayerSlotTargetFromTokenizedCommand(float tokens, float idx) // idx = start index
2456 ParseCommandPlayerSlotTarget_firsttoken = -1;
2460 if (substring(argv(idx), 0, 1) == "#")
2462 s = substring(argv(idx), 1, -1);
2470 ParseCommandPlayerSlotTarget_firsttoken = idx;
2471 if (s == ftos(stof(s)))
2473 e = edict_num(stof(s));
2474 if (e.flags & FL_CLIENT)
2480 // it must be a nick name
2483 ParseCommandPlayerSlotTarget_firsttoken = idx;
2486 FOR_EACH_CLIENT(head)
2487 if (head.netname == s)
2495 s = strdecolorize(s);
2497 FOR_EACH_CLIENT(head)
2498 if (strdecolorize(head.netname) == s)
2513 float modeleffect_SendEntity(entity to, float sf)
2516 WriteByte(MSG_ENTITY, ENT_CLIENT_MODELEFFECT);
2519 if(self.velocity != '0 0 0')
2521 if(self.angles != '0 0 0')
2523 if(self.avelocity != '0 0 0')
2526 WriteByte(MSG_ENTITY, f);
2527 WriteShort(MSG_ENTITY, self.modelindex);
2528 WriteByte(MSG_ENTITY, self.skin);
2529 WriteByte(MSG_ENTITY, self.frame);
2530 WriteCoord(MSG_ENTITY, self.origin_x);
2531 WriteCoord(MSG_ENTITY, self.origin_y);
2532 WriteCoord(MSG_ENTITY, self.origin_z);
2535 WriteCoord(MSG_ENTITY, self.velocity_x);
2536 WriteCoord(MSG_ENTITY, self.velocity_y);
2537 WriteCoord(MSG_ENTITY, self.velocity_z);
2541 WriteCoord(MSG_ENTITY, self.angles_x);
2542 WriteCoord(MSG_ENTITY, self.angles_y);
2543 WriteCoord(MSG_ENTITY, self.angles_z);
2547 WriteCoord(MSG_ENTITY, self.avelocity_x);
2548 WriteCoord(MSG_ENTITY, self.avelocity_y);
2549 WriteCoord(MSG_ENTITY, self.avelocity_z);
2551 WriteShort(MSG_ENTITY, self.scale * 256.0);
2552 WriteShort(MSG_ENTITY, self.scale2 * 256.0);
2553 WriteByte(MSG_ENTITY, self.teleport_time * 100.0);
2554 WriteByte(MSG_ENTITY, self.fade_time * 100.0);
2555 WriteByte(MSG_ENTITY, self.alpha * 255.0);
2560 void modeleffect_spawn(string m, float s, float f, vector o, vector v, vector ang, vector angv, float s0, float s2, float a, float t1, float t2)
2565 e.classname = "modeleffect";
2573 e.teleport_time = t1;
2577 e.scale = s0 / max6(-e.mins_x, -e.mins_y, -e.mins_z, e.maxs_x, e.maxs_y, e.maxs_z);
2581 e.scale2 = s2 / max6(-e.mins_x, -e.mins_y, -e.mins_z, e.maxs_x, e.maxs_y, e.maxs_z);
2584 sz = max(e.scale, e.scale2);
2585 setsize(e, e.mins * sz, e.maxs * sz);
2586 Net_LinkEntity(e, FALSE, 0.1, modeleffect_SendEntity);
2589 void shockwave_spawn(string m, vector org, float sz, float t1, float t2)
2591 return modeleffect_spawn(m, 0, 0, org, '0 0 0', '0 0 0', '0 0 0', 0, sz, 1, t1, t2);
2594 float randombit(float bits)
2596 if not(bits & (bits-1)) // this ONLY holds for powers of two!
2605 for(f = 1; f <= bits; f *= 2)
2614 r = (r - 1) / (n - 1);
2621 float randombits(float bits, float k, float error_return)
2625 while(k > 0 && bits != r)
2627 r += randombit(bits - r);
2636 void randombit_test(float bits, float iter)
2640 print(ftos(randombit(bits)), "\n");
2645 float ExponentialFalloff(float mindist, float maxdist, float halflifedist, float d)
2647 if(halflifedist > 0)
2648 return pow(0.5, (bound(mindist, d, maxdist) - mindist) / halflifedist);
2649 else if(halflifedist < 0)
2650 return pow(0.5, (bound(mindist, d, maxdist) - maxdist) / halflifedist);