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");
565 // fixup of switchweapon (needed for LMS or when spectating is disabled, as PutClientInServer comes too early)
568 if (s == "cl_weaponpriority")
569 self.switchweapon = w_getbestweapon(self);
573 float fexists(string f)
576 fh = fopen(f, FILE_READ);
583 void backtrace(string msg)
586 dev = cvar("developer");
587 war = cvar("prvm_backtraceforwarnings");
588 cvar_set("developer", "1");
589 cvar_set("prvm_backtraceforwarnings", "1");
591 dprint("--- CUT HERE ---\nWARNING: ");
594 remove(world); // isn't there any better way to cause a backtrace?
595 dprint("\n--- CUT UNTIL HERE ---\n");
596 cvar_set("developer", ftos(dev));
597 cvar_set("prvm_backtraceforwarnings", ftos(war));
600 string Team_ColorCode(float teamid)
602 if (teamid == COLOR_TEAM1)
604 else if (teamid == COLOR_TEAM2)
606 else if (teamid == COLOR_TEAM3)
608 else if (teamid == COLOR_TEAM4)
613 string Team_ColorName(float t)
615 // fixme: Search for team entities and get their .netname's!
616 if (t == COLOR_TEAM1)
618 if (t == COLOR_TEAM2)
620 if (t == COLOR_TEAM3)
622 if (t == COLOR_TEAM4)
626 string Team_ColorNameLowerCase(float t)
628 // fixme: Search for team entities and get their .netname's!
629 if (t == COLOR_TEAM1)
631 if (t == COLOR_TEAM2)
633 if (t == COLOR_TEAM3)
635 if (t == COLOR_TEAM4)
640 #define CENTERPRIO_POINT 1
641 #define CENTERPRIO_SPAM 2
642 #define CENTERPRIO_VOTE 4
643 #define CENTERPRIO_NORMAL 5
644 #define CENTERPRIO_SHIELDING 7
645 #define CENTERPRIO_MAPVOTE 9
646 #define CENTERPRIO_IDLEKICK 50
647 #define CENTERPRIO_ADMIN 99
648 .float centerprint_priority;
649 .float centerprint_expires;
650 void centerprint_atprio(entity e, float prio, string s)
652 if (intermission_running)
653 if (prio < CENTERPRIO_MAPVOTE)
655 if (time > e.centerprint_expires)
656 e.centerprint_priority = 0;
657 if (prio >= e.centerprint_priority)
659 e.centerprint_priority = prio;
660 if (timeoutStatus == 2)
661 e.centerprint_expires = time + (e.cvar_scr_centertime * TIMEOUT_SLOWMO_VALUE);
663 e.centerprint_expires = time + e.cvar_scr_centertime;
664 centerprint_builtin(e, s);
667 void centerprint_expire(entity e, float prio)
669 if (prio == e.centerprint_priority)
671 e.centerprint_priority = 0;
672 centerprint_builtin(e, "");
675 void centerprint(entity e, string s)
677 centerprint_atprio(e, CENTERPRIO_NORMAL, s);
680 // decolorizes and team colors the player name when needed
681 string playername(entity p)
684 if (teams_matter && !intermission_running && p.classname == "player")
686 t = Team_ColorCode(p.team);
687 return strcat(t, strdecolorize(p.netname));
693 vector randompos(vector m1, vector m2)
697 v_x = m2_x * random() + m1_x;
698 v_y = m2_y * random() + m1_y;
699 v_z = m2_z * random() + m1_z;
703 float g_pickup_shells;
704 float g_pickup_shells_max;
705 float g_pickup_nails;
706 float g_pickup_nails_max;
707 float g_pickup_rockets;
708 float g_pickup_rockets_max;
709 float g_pickup_cells;
710 float g_pickup_cells_max;
712 float g_pickup_fuel_jetpack;
713 float g_pickup_fuel_max;
714 float g_pickup_armorsmall;
715 float g_pickup_armorsmall_max;
716 float g_pickup_armormedium;
717 float g_pickup_armormedium_max;
718 float g_pickup_armorbig;
719 float g_pickup_armorbig_max;
720 float g_pickup_armorlarge;
721 float g_pickup_armorlarge_max;
722 float g_pickup_healthsmall;
723 float g_pickup_healthsmall_max;
724 float g_pickup_healthmedium;
725 float g_pickup_healthmedium_max;
726 float g_pickup_healthlarge;
727 float g_pickup_healthlarge_max;
728 float g_pickup_healthmega;
729 float g_pickup_healthmega_max;
731 float g_weaponarena_random;
732 string g_weaponarena_list;
733 float g_weaponspeedfactor;
734 float g_weaponratefactor;
735 float g_weapondamagefactor;
736 float g_weaponforcefactor;
740 float start_ammo_shells;
741 float start_ammo_nails;
742 float start_ammo_rockets;
743 float start_ammo_cells;
744 float start_ammo_fuel;
746 float start_armorvalue;
747 float warmup_start_weapons;
748 float warmup_start_ammo_shells;
749 float warmup_start_ammo_nails;
750 float warmup_start_ammo_rockets;
751 float warmup_start_ammo_cells;
752 float warmup_start_ammo_fuel;
753 float warmup_start_health;
754 float warmup_start_armorvalue;
758 entity get_weaponinfo(float w);
760 float NixNex_CanChooseWeapon(float wpn);
761 void readplayerstartcvars()
767 // initialize starting values for players
770 start_ammo_shells = 0;
771 start_ammo_nails = 0;
772 start_ammo_rockets = 0;
773 start_ammo_cells = 0;
774 start_health = cvar("g_balance_health_start");
775 start_armorvalue = cvar("g_balance_armor_start");
778 s = cvar_string("g_weaponarena");
784 g_weaponarena_list = "All Weapons";
785 for (j = WEP_FIRST; j <= WEP_LAST; ++j)
787 e = get_weaponinfo(j);
788 g_weaponarena |= e.weapons;
789 weapon_action(e.weapon, WR_PRECACHE);
792 else if (s == "most")
794 g_weaponarena_list = "Most Weapons";
795 for (j = WEP_FIRST; j <= WEP_LAST; ++j)
797 e = get_weaponinfo(j);
798 if (e.spawnflags & WEPSPAWNFLAG_NORMAL)
800 g_weaponarena |= e.weapons;
801 weapon_action(e.weapon, WR_PRECACHE);
805 else if (s == "none")
807 g_weaponarena_list = "No Weapons";
808 g_weaponarena = WEPBIT_ALL + 1; // this supports no single weapon bit!
812 t = tokenize_console(s);
813 g_weaponarena_list = "";
814 for (i = 0; i < t; ++i)
817 for (j = WEP_FIRST; j <= WEP_LAST; ++j)
819 e = get_weaponinfo(j);
822 g_weaponarena |= e.weapons;
823 weapon_action(e.weapon, WR_PRECACHE);
824 g_weaponarena_list = strcat(g_weaponarena_list, e.message, " & ");
830 print("The weapon mutator list contains an unknown weapon ", s, ". Skipped.\n");
833 g_weaponarena_list = strzone(substring(g_weaponarena_list, 0, strlen(g_weaponarena_list) - 3));
837 g_weaponarena_random = cvar("g_weaponarena_random");
839 g_weaponarena_random = 0;
844 // will be done later
845 for (i = WEP_FIRST; i <= WEP_LAST; ++i)
846 if (NixNex_CanChooseWeapon(i))
847 weapon_action(i, WR_PRECACHE);
848 if(!cvar("g_use_ammunition"))
849 start_items |= IT_UNLIMITED_AMMO;
851 else if (g_weaponarena)
853 start_weapons = g_weaponarena;
854 if (g_weaponarena & (WEPBIT_GRENADE_LAUNCHER | WEPBIT_HAGAR | WEPBIT_ROCKET_LAUNCHER))
855 start_ammo_rockets = 999;
856 if (g_weaponarena & WEPBIT_SHOTGUN)
857 start_ammo_shells = 999;
858 if (g_weaponarena & (WEPBIT_ELECTRO | WEPBIT_CRYLINK | WEPBIT_NEX | WEPBIT_MINSTANEX | WEPBIT_HLAC | WEPBIT_HOOK))
859 start_ammo_cells = 999;
860 if (g_weaponarena & (WEPBIT_UZI | WEPBIT_CAMPINGRIFLE))
861 start_ammo_nails = 999;
862 if (g_weaponarena & WEPBIT_HOOK)
863 start_ammo_fuel = 999;
864 start_items |= IT_UNLIMITED_AMMO;
866 else if (g_minstagib)
869 start_armorvalue = 0;
870 start_weapons = WEPBIT_MINSTANEX;
871 weapon_action(WEP_MINSTANEX, WR_PRECACHE);
872 start_ammo_cells = cvar("g_minstagib_ammo_start");
873 g_minstagib_invis_alpha = cvar("g_minstagib_invis_alpha");
874 start_ammo_fuel = cvar("g_start_ammo_fuel");
876 if (g_minstagib_invis_alpha <= 0)
877 g_minstagib_invis_alpha = -1;
883 start_ammo_shells = cvar("g_lms_start_ammo_shells");
884 start_ammo_nails = cvar("g_lms_start_ammo_nails");
885 start_ammo_rockets = cvar("g_lms_start_ammo_rockets");
886 start_ammo_cells = cvar("g_lms_start_ammo_cells");
887 start_ammo_fuel = cvar("g_lms_start_ammo_fuel");
888 start_health = cvar("g_lms_start_health");
889 start_armorvalue = cvar("g_lms_start_armor");
891 else if (cvar("g_use_ammunition"))
893 start_ammo_shells = cvar("g_start_ammo_shells");
894 start_ammo_nails = cvar("g_start_ammo_nails");
895 start_ammo_rockets = cvar("g_start_ammo_rockets");
896 start_ammo_cells = cvar("g_start_ammo_cells");
897 start_ammo_fuel = cvar("g_start_ammo_fuel");
901 start_ammo_shells = cvar("g_pickup_shells_max");
902 start_ammo_nails = cvar("g_pickup_nails_max");
903 start_ammo_rockets = cvar("g_pickup_rockets_max");
904 start_ammo_cells = cvar("g_pickup_cells_max");
905 start_ammo_fuel = cvar("g_pickup_fuel_max");
906 start_items |= IT_UNLIMITED_AMMO;
909 for (i = WEP_FIRST; i <= WEP_LAST; ++i)
911 e = get_weaponinfo(i);
915 t = cvar(strcat("g_start_weapon_", e.netname));
917 if (t < 0) // "default" weapon selection
920 t = (e.spawnflags & WEPSPAWNFLAG_NORMAL);
921 else if (g_race || g_cts)
922 t = (i == WEP_LASER);
924 t = 0; // weapon is set a few lines later
926 t = (i == WEP_LASER || i == WEP_SHOTGUN);
927 if (g_grappling_hook) // if possible, redirect off-hand hook to on-hand hook
928 t += (i == WEP_HOOK);
931 if (g_nexball && i == WEP_PORTO)
936 start_weapons |= e.weapons;
937 weapon_action(e.weapon, WR_PRECACHE);
944 warmup_start_ammo_shells = start_ammo_shells;
945 warmup_start_ammo_nails = start_ammo_nails;
946 warmup_start_ammo_rockets = start_ammo_rockets;
947 warmup_start_ammo_cells = start_ammo_cells;
948 warmup_start_ammo_fuel = start_ammo_fuel;
949 warmup_start_health = start_health;
950 warmup_start_armorvalue = start_armorvalue;
951 warmup_start_weapons = start_weapons;
953 if (!g_weaponarena && !g_nixnex && !g_minstagib)
955 if (cvar("g_use_ammunition"))
957 warmup_start_ammo_shells = cvar("g_warmup_start_ammo_shells");
958 warmup_start_ammo_cells = cvar("g_warmup_start_ammo_cells");
959 warmup_start_ammo_nails = cvar("g_warmup_start_ammo_nails");
960 warmup_start_ammo_rockets = cvar("g_warmup_start_ammo_rockets");
961 warmup_start_ammo_fuel = cvar("g_warmup_start_ammo_fuel");
963 warmup_start_health = cvar("g_warmup_start_health");
964 warmup_start_armorvalue = cvar("g_warmup_start_armor");
965 if (cvar("g_warmup_allguns"))
967 for (i = WEP_FIRST; i <= WEP_LAST; ++i)
969 e = get_weaponinfo(i);
972 if (e.spawnflags & WEPSPAWNFLAG_NORMAL)
974 warmup_start_weapons |= e.weapons;
975 weapon_action(e.weapon, WR_PRECACHE);
982 if (g_jetpack || (g_grappling_hook && (start_weapons & WEPBIT_HOOK)))
984 g_grappling_hook = 0; // these two can't coexist, as they use the same button
985 start_items |= IT_FUEL_REGEN;
986 start_ammo_fuel = max(start_ammo_fuel, cvar("g_balance_fuel_rotstable"));
987 warmup_start_ammo_fuel = max(warmup_start_ammo_fuel, cvar("g_balance_fuel_rotstable"));
991 start_items |= IT_JETPACK;
993 if (g_weapon_stay == 2)
995 if (!start_ammo_shells) start_ammo_shells = g_pickup_shells;
996 if (!start_ammo_nails) start_ammo_nails = g_pickup_nails;
997 if (!start_ammo_cells) start_ammo_cells = g_pickup_cells;
998 if (!start_ammo_rockets) start_ammo_rockets = g_pickup_rockets;
999 if (!start_ammo_fuel) start_ammo_fuel = g_pickup_fuel;
1000 if (!warmup_start_ammo_shells) warmup_start_ammo_shells = g_pickup_shells;
1001 if (!warmup_start_ammo_nails) warmup_start_ammo_nails = g_pickup_nails;
1002 if (!warmup_start_ammo_cells) warmup_start_ammo_cells = g_pickup_cells;
1003 if (!warmup_start_ammo_rockets) warmup_start_ammo_rockets = g_pickup_rockets;
1004 if (!warmup_start_ammo_fuel) warmup_start_ammo_fuel = g_pickup_fuel;
1007 start_ammo_shells = max(0, start_ammo_shells);
1008 start_ammo_nails = max(0, start_ammo_nails);
1009 start_ammo_cells = max(0, start_ammo_cells);
1010 start_ammo_rockets = max(0, start_ammo_rockets);
1011 start_ammo_fuel = max(0, start_ammo_fuel);
1013 warmup_start_ammo_shells = max(0, warmup_start_ammo_shells);
1014 warmup_start_ammo_nails = max(0, warmup_start_ammo_nails);
1015 warmup_start_ammo_cells = max(0, warmup_start_ammo_cells);
1016 warmup_start_ammo_rockets = max(0, warmup_start_ammo_rockets);
1017 warmup_start_ammo_fuel = max(0, warmup_start_ammo_fuel);
1021 float g_bugrigs_planar_movement;
1022 float g_bugrigs_planar_movement_car_jumping;
1023 float g_bugrigs_reverse_spinning;
1024 float g_bugrigs_reverse_speeding;
1025 float g_bugrigs_reverse_stopping;
1026 float g_bugrigs_air_steering;
1027 float g_bugrigs_angle_smoothing;
1028 float g_bugrigs_friction_floor;
1029 float g_bugrigs_friction_brake;
1030 float g_bugrigs_friction_air;
1031 float g_bugrigs_accel;
1032 float g_bugrigs_speed_ref;
1033 float g_bugrigs_speed_pow;
1034 float g_bugrigs_steer;
1036 float g_touchexplode;
1037 float g_touchexplode_radius;
1038 float g_touchexplode_damage;
1039 float g_touchexplode_edgedamage;
1040 float g_touchexplode_force;
1045 void readlevelcvars(void)
1047 g_bugrigs = cvar("g_bugrigs");
1048 g_bugrigs_planar_movement = cvar("g_bugrigs_planar_movement");
1049 g_bugrigs_planar_movement_car_jumping = cvar("g_bugrigs_planar_movement_car_jumping");
1050 g_bugrigs_reverse_spinning = cvar("g_bugrigs_reverse_spinning");
1051 g_bugrigs_reverse_speeding = cvar("g_bugrigs_reverse_speeding");
1052 g_bugrigs_reverse_stopping = cvar("g_bugrigs_reverse_stopping");
1053 g_bugrigs_air_steering = cvar("g_bugrigs_air_steering");
1054 g_bugrigs_angle_smoothing = cvar("g_bugrigs_angle_smoothing");
1055 g_bugrigs_friction_floor = cvar("g_bugrigs_friction_floor");
1056 g_bugrigs_friction_brake = cvar("g_bugrigs_friction_brake");
1057 g_bugrigs_friction_air = cvar("g_bugrigs_friction_air");
1058 g_bugrigs_accel = cvar("g_bugrigs_accel");
1059 g_bugrigs_speed_ref = cvar("g_bugrigs_speed_ref");
1060 g_bugrigs_speed_pow = cvar("g_bugrigs_speed_pow");
1061 g_bugrigs_steer = cvar("g_bugrigs_steer");
1063 g_touchexplode = cvar("g_touchexplode");
1064 g_touchexplode_radius = cvar("g_touchexplode_radius");
1065 g_touchexplode_damage = cvar("g_touchexplode_damage");
1066 g_touchexplode_edgedamage = cvar("g_touchexplode_edgedamage");
1067 g_touchexplode_force = cvar("g_touchexplode_force");
1069 #ifdef ALLOW_FORCEMODELS
1070 sv_clforceplayermodels = cvar("sv_clforceplayermodels");
1072 sv_loddistance1 = cvar("sv_loddistance1");
1073 sv_loddistance2 = cvar("sv_loddistance2");
1074 if(sv_loddistance2 <= sv_loddistance1)
1075 sv_loddistance2 = 1073741824; // enough to turn off LOD 2 reliably
1076 sv_clones = cvar("sv_clones");
1077 sv_cheats = cvar("sv_cheats");
1078 sv_gentle = cvar("sv_gentle");
1079 sv_foginterval = cvar("sv_foginterval");
1080 g_cloaked = cvar("g_cloaked");
1081 g_jump_grunt = cvar("g_jump_grunt");
1082 g_footsteps = cvar("g_footsteps");
1083 g_grappling_hook = cvar("g_grappling_hook");
1084 g_jetpack = cvar("g_jetpack");
1085 g_laserguided_missile = cvar("g_laserguided_missile");
1086 g_midair = cvar("g_midair");
1087 g_minstagib = cvar("g_minstagib");
1088 g_nixnex = cvar("g_nixnex");
1089 g_nixnex_with_laser = cvar("g_nixnex_with_laser");
1090 g_norecoil = cvar("g_norecoil");
1091 g_vampire = cvar("g_vampire");
1092 g_bloodloss = cvar("g_bloodloss");
1093 sv_maxidle = cvar("sv_maxidle");
1094 sv_maxidle_spectatorsareidle = cvar("sv_maxidle_spectatorsareidle");
1095 sv_pogostick = cvar("sv_pogostick");
1096 sv_doublejump = cvar("sv_doublejump");
1097 g_ctf_reverse = cvar("g_ctf_reverse");
1098 sv_autotaunt = cvar("sv_autotaunt");
1099 sv_taunt = cvar("sv_taunt");
1101 inWarmupStage = cvar("g_warmup");
1102 g_warmup_limit = cvar("g_warmup_limit");
1103 g_warmup_allguns = cvar("g_warmup_allguns");
1104 g_warmup_allow_timeout = cvar("g_warmup_allow_timeout");
1106 if ((g_race && g_race_qualifying == 2) || g_runematch || g_arena || g_assault || cvar("g_campaign"))
1107 inWarmupStage = 0; // these modes cannot work together, sorry
1109 g_pickup_respawntime_weapon = cvar("g_pickup_respawntime_weapon");
1110 g_pickup_respawntime_ammo = cvar("g_pickup_respawntime_ammo");
1111 g_pickup_respawntime_short = cvar("g_pickup_respawntime_short");
1112 g_pickup_respawntime_medium = cvar("g_pickup_respawntime_medium");
1113 g_pickup_respawntime_long = cvar("g_pickup_respawntime_long");
1114 g_pickup_respawntime_powerup = cvar("g_pickup_respawntime_powerup");
1115 g_pickup_respawntimejitter_weapon = cvar("g_pickup_respawntimejitter_weapon");
1116 g_pickup_respawntimejitter_ammo = cvar("g_pickup_respawntimejitter_ammo");
1117 g_pickup_respawntimejitter_short = cvar("g_pickup_respawntimejitter_short");
1118 g_pickup_respawntimejitter_medium = cvar("g_pickup_respawntimejitter_medium");
1119 g_pickup_respawntimejitter_long = cvar("g_pickup_respawntimejitter_long");
1120 g_pickup_respawntimejitter_powerup = cvar("g_pickup_respawntimejitter_powerup");
1122 if (g_minstagib) g_nixnex = g_weaponarena = 0;
1123 if (g_nixnex) g_weaponarena = 0;
1126 g_weaponspeedfactor = cvar("g_weaponspeedfactor");
1127 g_weaponratefactor = cvar("g_weaponratefactor");
1128 g_weapondamagefactor = cvar("g_weapondamagefactor");
1129 g_weaponforcefactor = cvar("g_weaponforcefactor");
1131 g_pickup_shells = cvar("g_pickup_shells");
1132 g_pickup_shells_max = cvar("g_pickup_shells_max");
1133 g_pickup_nails = cvar("g_pickup_nails");
1134 g_pickup_nails_max = cvar("g_pickup_nails_max");
1135 g_pickup_rockets = cvar("g_pickup_rockets");
1136 g_pickup_rockets_max = cvar("g_pickup_rockets_max");
1137 g_pickup_cells = cvar("g_pickup_cells");
1138 g_pickup_cells_max = cvar("g_pickup_cells_max");
1139 g_pickup_fuel = cvar("g_pickup_fuel");
1140 g_pickup_fuel_jetpack = cvar("g_pickup_fuel_jetpack");
1141 g_pickup_fuel_max = cvar("g_pickup_fuel_max");
1142 g_pickup_armorsmall = cvar("g_pickup_armorsmall");
1143 g_pickup_armorsmall_max = cvar("g_pickup_armorsmall_max");
1144 g_pickup_armormedium = cvar("g_pickup_armormedium");
1145 g_pickup_armormedium_max = cvar("g_pickup_armormedium_max");
1146 g_pickup_armorbig = cvar("g_pickup_armorbig");
1147 g_pickup_armorbig_max = cvar("g_pickup_armorbig_max");
1148 g_pickup_armorlarge = cvar("g_pickup_armorlarge");
1149 g_pickup_armorlarge_max = cvar("g_pickup_armorlarge_max");
1150 g_pickup_healthsmall = cvar("g_pickup_healthsmall");
1151 g_pickup_healthsmall_max = cvar("g_pickup_healthsmall_max");
1152 g_pickup_healthmedium = cvar("g_pickup_healthmedium");
1153 g_pickup_healthmedium_max = cvar("g_pickup_healthmedium_max");
1154 g_pickup_healthlarge = cvar("g_pickup_healthlarge");
1155 g_pickup_healthlarge_max = cvar("g_pickup_healthlarge_max");
1156 g_pickup_healthmega = cvar("g_pickup_healthmega");
1157 g_pickup_healthmega_max = cvar("g_pickup_healthmega_max");
1159 g_pinata = cvar("g_pinata");
1161 g_weapon_stay = cvar("g_weapon_stay");
1162 if (!g_weapon_stay && (cvar("deathmatch") == 2))
1164 g_ghost_items = cvar("g_ghost_items");
1165 if(g_ghost_items >= 1)
1166 g_ghost_items = 0.13; // default alpha value
1168 if not(inWarmupStage)
1169 game_starttime = cvar("g_start_delay");
1171 readplayerstartcvars();
1175 // TODO sound pack system
1178 string precache_sound_builtin (string s) = #19;
1179 void(entity e, float chan, string samp, float vol, float atten) sound_builtin = #8;
1180 string precache_sound(string s)
1182 return precache_sound_builtin(strcat(soundpack, s));
1184 void play2(entity e, string filename)
1186 stuffcmd(e, strcat("play2 ", soundpack, filename, "\n"));
1188 void sound(entity e, float chan, string samp, float vol, float atten)
1190 sound_builtin(e, chan, strcat(soundpack, samp), vol, atten);
1195 string precache_sound (string s) = #19;
1196 void(entity e, float chan, string samp, float vol, float atten) sound_builtin = #8;
1197 float precache_sound_index (string s) = #19;
1199 #define SND_VOLUME 1
1200 #define SND_ATTENUATION 2
1201 #define SND_LARGEENTITY 8
1202 #define SND_LARGESOUND 16
1204 float sound_allowed(float dest, entity e)
1206 // sounds from world may always pass
1209 if (e.classname == "body")
1211 if (e.owner && e.owner != e)
1216 // sounds to self may always pass
1217 if (dest == MSG_ONE)
1218 if (e == msg_entity)
1220 // sounds by players can be removed
1221 if (cvar("bot_sound_monopoly"))
1222 if (clienttype(e) == CLIENTTYPE_REAL)
1224 // anything else may pass
1228 void sound(entity e, float chan, string samp, float vol, float atten)
1230 if (!sound_allowed(MSG_BROADCAST, e))
1232 sound_builtin(e, chan, samp, vol, atten);
1234 void soundtoat(float dest, entity e, vector o, float chan, string samp, float vol, float atten)
1238 if (!sound_allowed(dest, e))
1241 entno = num_for_edict(e);
1242 idx = precache_sound_index(samp);
1247 atten = floor(atten * 64);
1248 vol = floor(vol * 255);
1251 sflags |= SND_VOLUME;
1253 sflags |= SND_ATTENUATION;
1255 sflags |= SND_LARGEENTITY;
1257 sflags |= SND_LARGESOUND;
1259 WriteByte(dest, SVC_SOUND);
1260 WriteByte(dest, sflags);
1261 if (sflags & SND_VOLUME)
1262 WriteByte(dest, vol);
1263 if (sflags & SND_ATTENUATION)
1264 WriteByte(dest, atten);
1265 if (sflags & SND_LARGEENTITY)
1267 WriteShort(dest, entno);
1268 WriteByte(dest, chan);
1272 WriteShort(dest, entno * 8 + chan);
1274 if (sflags & SND_LARGESOUND)
1275 WriteShort(dest, idx);
1277 WriteByte(dest, idx);
1279 WriteCoord(dest, o_x);
1280 WriteCoord(dest, o_y);
1281 WriteCoord(dest, o_z);
1283 void soundto(float dest, entity e, float chan, string samp, float vol, float atten)
1287 if (!sound_allowed(dest, e))
1290 o = e.origin + 0.5 * (e.mins + e.maxs);
1291 soundtoat(dest, e, o, chan, samp, vol, atten);
1293 void soundat(entity e, vector o, float chan, string samp, float vol, float atten)
1295 soundtoat(MSG_BROADCAST, e, o, chan, samp, vol, atten);
1297 void stopsoundto(float dest, entity e, float chan)
1301 if (!sound_allowed(dest, e))
1304 entno = num_for_edict(e);
1309 idx = precache_sound_index("misc/null.wav");
1310 sflags = SND_LARGEENTITY;
1312 sflags |= SND_LARGESOUND;
1313 WriteByte(dest, SVC_SOUND);
1314 WriteByte(dest, sflags);
1315 WriteShort(dest, entno);
1316 WriteByte(dest, chan);
1317 if (sflags & SND_LARGESOUND)
1318 WriteShort(dest, idx);
1320 WriteByte(dest, idx);
1321 WriteCoord(dest, e.origin_x);
1322 WriteCoord(dest, e.origin_y);
1323 WriteCoord(dest, e.origin_z);
1327 WriteByte(dest, SVC_STOPSOUND);
1328 WriteShort(dest, entno * 8 + chan);
1331 void stopsound(entity e, float chan)
1333 if (!sound_allowed(MSG_BROADCAST, e))
1336 stopsoundto(MSG_BROADCAST, e, chan); // unreliable, gets there fast
1337 stopsoundto(MSG_ALL, e, chan); // in case of packet loss
1340 void play2(entity e, string filename)
1342 //stuffcmd(e, strcat("play2 ", filename, "\n"));
1344 soundtoat(MSG_ONE, world, '0 0 0', CHAN_AUTO, filename, VOL_BASE, ATTN_NONE);
1347 .float announcetime;
1348 float announce(entity player, string msg)
1350 if (time > player.announcetime)
1351 if (clienttype(player) == CLIENTTYPE_REAL)
1353 player.announcetime = time + 0.8;
1359 // use this one if you might be causing spam (e.g. from touch functions that might get called more than once per frame)
1360 float spamsound(entity e, float chan, string samp, float vol, float atten)
1362 if (!sound_allowed(MSG_BROADCAST, e))
1365 if (time > e.announcetime)
1367 e.announcetime = time;
1368 sound(e, chan, samp, vol, atten);
1374 void play2team(float t, string filename)
1378 if (cvar("bot_sound_monopoly"))
1381 FOR_EACH_REALPLAYER(head)
1384 play2(head, filename);
1388 void play2all(string samp)
1390 if (cvar("bot_sound_monopoly"))
1393 sound(world, CHAN_AUTO, samp, VOL_BASE, ATTN_NONE);
1396 void PrecachePlayerSounds(string f);
1397 void precache_all_models(string pattern)
1399 float globhandle, i, n;
1402 globhandle = search_begin(pattern, TRUE, FALSE);
1405 n = search_getsize(globhandle);
1406 for (i = 0; i < n; ++i)
1408 //print(search_getfilename(globhandle, i), "\n");
1409 f = search_getfilename(globhandle, i);
1412 if(substring(f, -9,5) == "_lod1")
1414 if(substring(f, -9,5) == "_lod2")
1416 if(!sv_loddistance1)
1418 PrecachePlayerSounds(strcat(f, ".sounds"));
1420 search_end(globhandle);
1425 // gamemode related things
1426 precache_model ("models/misc/chatbubble.spr");
1427 precache_model ("models/misc/teambubble.spr");
1430 precache_model ("models/runematch/curse.mdl");
1431 precache_model ("models/runematch/rune.mdl");
1434 #ifdef TTURRETS_ENABLED
1435 if (cvar("g_turrets"))
1439 // Precache all player models if desired
1440 if (cvar("sv_precacheplayermodels"))
1442 PrecachePlayerSounds("sound/player/default.sounds");
1443 precache_all_models("models/player/*.zym");
1444 precache_all_models("models/player/*.dpm");
1445 precache_all_models("models/player/*.md3");
1446 precache_all_models("models/player/*.psk");
1447 //precache_model("models/player/carni.zym");
1448 //precache_model("models/player/crash.zym");
1449 //precache_model("models/player/grunt.zym");
1450 //precache_model("models/player/headhunter.zym");
1451 //precache_model("models/player/insurrectionist.zym");
1452 //precache_model("models/player/jeandarc.zym");
1453 //precache_model("models/player/lurk.zym");
1454 //precache_model("models/player/lycanthrope.zym");
1455 //precache_model("models/player/marine.zym");
1456 //precache_model("models/player/nexus.zym");
1457 //precache_model("models/player/pyria.zym");
1458 //precache_model("models/player/shock.zym");
1459 //precache_model("models/player/skadi.zym");
1460 //precache_model("models/player/specop.zym");
1461 //precache_model("models/player/visitant.zym");
1464 if (cvar("sv_defaultcharacter"))
1467 s = cvar_string("sv_defaultplayermodel_red");
1471 PrecachePlayerSounds(strcat(s, ".sounds"));
1473 s = cvar_string("sv_defaultplayermodel_blue");
1477 PrecachePlayerSounds(strcat(s, ".sounds"));
1479 s = cvar_string("sv_defaultplayermodel_yellow");
1483 PrecachePlayerSounds(strcat(s, ".sounds"));
1485 s = cvar_string("sv_defaultplayermodel_pink");
1489 PrecachePlayerSounds(strcat(s, ".sounds"));
1491 s = cvar_string("sv_defaultplayermodel");
1495 PrecachePlayerSounds(strcat(s, ".sounds"));
1501 PrecacheGlobalSound((globalsound_step = "misc/footstep0 6"));
1502 PrecacheGlobalSound((globalsound_metalstep = "misc/metalfootstep0 6"));
1505 // gore and miscellaneous sounds
1506 //precache_sound ("misc/h2ohit.wav");
1507 precache_model ("models/hook.md3");
1508 precache_sound ("misc/armorimpact.wav");
1509 precache_sound ("misc/bodyimpact1.wav");
1510 precache_sound ("misc/bodyimpact2.wav");
1511 precache_sound ("misc/gib.wav");
1512 precache_sound ("misc/gib_splat01.wav");
1513 precache_sound ("misc/gib_splat02.wav");
1514 precache_sound ("misc/gib_splat03.wav");
1515 precache_sound ("misc/gib_splat04.wav");
1516 precache_sound ("misc/hit.wav");
1517 PrecacheGlobalSound((globalsound_fall = "misc/hitground 4"));
1518 PrecacheGlobalSound((globalsound_metalfall = "misc/metalhitground 4"));
1519 precache_sound ("misc/null.wav");
1520 precache_sound ("misc/spawn.wav");
1521 precache_sound ("misc/talk.wav");
1522 precache_sound ("misc/teleport.wav");
1523 precache_sound ("misc/poweroff.wav");
1524 precache_sound ("player/lava.wav");
1525 precache_sound ("player/slime.wav");
1528 precache_sound ("misc/jetpack_fly.wav");
1530 // announcer sounds - male
1531 precache_sound ("announcer/male/electrobitch.wav");
1532 precache_sound ("announcer/male/airshot.wav");
1533 precache_sound ("announcer/male/03kills.wav");
1534 precache_sound ("announcer/male/05kills.wav");
1535 precache_sound ("announcer/male/10kills.wav");
1536 precache_sound ("announcer/male/15kills.wav");
1537 precache_sound ("announcer/male/20kills.wav");
1538 precache_sound ("announcer/male/25kills.wav");
1539 precache_sound ("announcer/male/30kills.wav");
1540 precache_sound ("announcer/male/botlike.wav");
1541 precache_sound ("announcer/male/yoda.wav");
1542 precache_sound ("announcer/male/amazing.wav");
1543 precache_sound ("announcer/male/awesome.wav");
1544 precache_sound ("announcer/male/headshot.wav");
1545 precache_sound ("announcer/male/impressive.wav");
1547 // announcer sounds - robotic
1548 precache_sound ("announcer/robotic/prepareforbattle.wav");
1549 precache_sound ("announcer/robotic/begin.wav");
1550 precache_sound ("announcer/robotic/timeoutcalled.wav");
1551 precache_sound ("announcer/robotic/1fragleft.wav");
1552 precache_sound ("announcer/robotic/2fragsleft.wav");
1553 precache_sound ("announcer/robotic/3fragsleft.wav");
1554 precache_sound ("announcer/robotic/terminated.wav");
1557 precache_sound ("announcer/robotic/lastsecond.wav");
1558 precache_sound ("announcer/robotic/narrowly.wav");
1561 precache_model ("models/sprites/0.spr32");
1562 precache_model ("models/sprites/1.spr32");
1563 precache_model ("models/sprites/2.spr32");
1564 precache_model ("models/sprites/3.spr32");
1565 precache_model ("models/sprites/4.spr32");
1566 precache_model ("models/sprites/5.spr32");
1567 precache_model ("models/sprites/6.spr32");
1568 precache_model ("models/sprites/7.spr32");
1569 precache_model ("models/sprites/8.spr32");
1570 precache_model ("models/sprites/9.spr32");
1571 precache_model ("models/sprites/10.spr32");
1572 precache_sound ("announcer/robotic/1.wav");
1573 precache_sound ("announcer/robotic/2.wav");
1574 precache_sound ("announcer/robotic/3.wav");
1575 precache_sound ("announcer/robotic/4.wav");
1576 precache_sound ("announcer/robotic/5.wav");
1577 precache_sound ("announcer/robotic/6.wav");
1578 precache_sound ("announcer/robotic/7.wav");
1579 precache_sound ("announcer/robotic/8.wav");
1580 precache_sound ("announcer/robotic/9.wav");
1581 precache_sound ("announcer/robotic/10.wav");
1583 // common weapon precaches
1584 precache_sound ("weapons/weapon_switch.wav");
1585 precache_sound ("weapons/weaponpickup.wav");
1586 precache_sound ("weapons/unavailable.wav");
1587 if (g_grappling_hook)
1589 precache_sound ("weapons/hook_fire.wav"); // hook
1590 precache_sound ("weapons/hook_impact.wav"); // hook
1593 if (cvar("sv_precacheweapons") || g_nixnex)
1595 //precache weapon models/sounds
1598 while (wep <= WEP_LAST)
1600 weapon_action(wep, WR_PRECACHE);
1605 precache_model("models/elaser.mdl");
1606 precache_model("models/laser.mdl");
1607 precache_model("models/ebomb.mdl");
1610 // Disabled this code because it simply does not work (e.g. ignores bgmvolume, overlaps with "cd loop" controlled tracks).
1612 if (!self.noise && self.music) // quake 3 uses the music field
1613 self.noise = self.music;
1615 // plays music for the level if there is any
1618 precache_sound (self.noise);
1619 ambientsound ('0 0 0', self.noise, VOL_BASE, ATTN_NONE);
1624 // sorry, but using \ in macros breaks line numbers
1625 #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
1626 #define WRITESPECTATABLE_MSG_ONE(statement) WRITESPECTATABLE_MSG_ONE_VARNAME(oldmsg_entity, statement)
1627 #define WRITESPECTATABLE(msg,statement) if(msg == MSG_ONE) { WRITESPECTATABLE_MSG_ONE(statement); } else statement float WRITESPECTATABLE_workaround = 0
1629 vector ExactTriggerHit_mins;
1630 vector ExactTriggerHit_maxs;
1631 float ExactTriggerHit_Recurse()
1637 tracebox('0 0 0', ExactTriggerHit_mins, ExactTriggerHit_maxs, '0 0 0', MOVE_NORMAL, other);
1640 if (trace_ent == self)
1645 se.solid = SOLID_NOT;
1646 f = ExactTriggerHit_Recurse();
1652 float ExactTriggerHit()
1656 if not(self.modelindex)
1660 self.solid = SOLID_BSP;
1661 ExactTriggerHit_mins = other.absmin;
1662 ExactTriggerHit_maxs = other.absmax;
1663 f = ExactTriggerHit_Recurse();
1669 // WARNING: this kills the trace globals
1670 #define EXACTTRIGGER_TOUCH if not(ExactTriggerHit()) return
1671 #define EXACTTRIGGER_INIT InitSolidBSPTrigger(); self.solid = SOLID_TRIGGER
1673 #define INITPRIO_FIRST 0
1674 #define INITPRIO_GAMETYPE 0
1675 #define INITPRIO_GAMETYPE_FALLBACK 1
1676 #define INITPRIO_CVARS 5
1677 #define INITPRIO_FINDTARGET 10
1678 #define INITPRIO_DROPTOFLOOR 20
1679 #define INITPRIO_SETLOCATION 90
1680 #define INITPRIO_LINKDOORS 91
1681 #define INITPRIO_LAST 99
1683 .void(void) initialize_entity;
1684 .float initialize_entity_order;
1685 .entity initialize_entity_next;
1686 entity initialize_entity_first;
1688 void make_safe_for_remove(entity e)
1690 if (e.initialize_entity)
1693 for (ent = initialize_entity_first; ent; )
1695 if ((ent == e) || ((ent.classname == "initialize_entity") && (ent.enemy == e)))
1697 //print("make_safe_for_remove: getting rid of initializer ", etos(ent), "\n");
1698 // skip it in linked list
1701 prev.initialize_entity_next = ent.initialize_entity_next;
1702 ent = prev.initialize_entity_next;
1706 initialize_entity_first = ent.initialize_entity_next;
1707 ent = initialize_entity_first;
1713 ent = ent.initialize_entity_next;
1719 void objerror(string s)
1721 make_safe_for_remove(self);
1722 objerror_builtin(s);
1725 void remove_unsafely(entity e)
1730 void remove_safely(entity e)
1732 make_safe_for_remove(e);
1736 void InitializeEntity(entity e, void(void) func, float order)
1740 if (!e || e.initialize_entity)
1742 // make a proxy initializer entity
1746 e.classname = "initialize_entity";
1750 e.initialize_entity = func;
1751 e.initialize_entity_order = order;
1753 cur = initialize_entity_first;
1756 if (!cur || cur.initialize_entity_order > order)
1758 // insert between prev and cur
1760 prev.initialize_entity_next = e;
1762 initialize_entity_first = e;
1763 e.initialize_entity_next = cur;
1767 cur = cur.initialize_entity_next;
1770 void InitializeEntitiesRun()
1773 startoflist = initialize_entity_first;
1774 initialize_entity_first = world;
1775 for (self = startoflist; self; )
1778 var void(void) func;
1779 e = self.initialize_entity_next;
1780 func = self.initialize_entity;
1781 self.initialize_entity_order = 0;
1782 self.initialize_entity = func_null;
1783 self.initialize_entity_next = world;
1784 if (self.classname == "initialize_entity")
1788 remove_builtin(self);
1791 //dprint("Delayed initialization: ", self.classname, "\n");
1797 .float uncustomizeentityforclient_set;
1798 .void(void) uncustomizeentityforclient;
1799 void(void) SUB_Nullpointer = #0;
1800 void UncustomizeEntitiesRun()
1804 for (self = world; (self = findfloat(self, uncustomizeentityforclient_set, 1)); )
1805 self.uncustomizeentityforclient();
1808 void SetCustomizer(entity e, float(void) customizer, void(void) uncustomizer)
1810 e.customizeentityforclient = customizer;
1811 e.uncustomizeentityforclient = uncustomizer;
1812 e.uncustomizeentityforclient_set = (uncustomizer != SUB_Nullpointer);
1816 #define IFTARGETED if(!self.nottargeted && self.targetname != "")
1819 void Net_LinkEntity(entity e, float docull, float dt, float(entity, float) sendfunc)
1823 if (e.classname == "")
1824 e.classname = "net_linked";
1826 if (e.model == "" || self.modelindex == 0)
1830 setmodel(e, "null");
1834 e.SendEntity = sendfunc;
1835 e.SendFlags = 0xFFFFFF;
1838 e.effects |= EF_NODEPTHTEST;
1842 e.nextthink = time + dt;
1843 e.think = SUB_Remove;
1847 void adaptor_think2touch()
1856 void adaptor_think2use()
1868 // deferred dropping
1869 void DropToFloor_Handler()
1871 droptofloor_builtin();
1872 self.dropped_origin = self.origin;
1877 InitializeEntity(self, DropToFloor_Handler, INITPRIO_DROPTOFLOOR);
1882 float trace_hits_box_a0, trace_hits_box_a1;
1884 float trace_hits_box_1d(float end, float thmi, float thma)
1888 // just check if x is in range
1896 // do the trace with respect to x
1897 // 0 -> end has to stay in thmi -> thma
1898 trace_hits_box_a0 = max(trace_hits_box_a0, min(thmi / end, thma / end));
1899 trace_hits_box_a1 = min(trace_hits_box_a1, max(thmi / end, thma / end));
1900 if (trace_hits_box_a0 > trace_hits_box_a1)
1906 float trace_hits_box(vector start, vector end, vector thmi, vector thma)
1911 // now it is a trace from 0 to end
1913 trace_hits_box_a0 = 0;
1914 trace_hits_box_a1 = 1;
1916 if (!trace_hits_box_1d(end_x, thmi_x, thma_x))
1918 if (!trace_hits_box_1d(end_y, thmi_y, thma_y))
1920 if (!trace_hits_box_1d(end_z, thmi_z, thma_z))
1926 float tracebox_hits_box(vector start, vector mi, vector ma, vector end, vector thmi, vector thma)
1928 return trace_hits_box(start, end, thmi - ma, thma - mi);
1931 float SUB_NoImpactCheck()
1933 // zero hitcontents = this is not the real impact, but either the
1934 // mirror-impact of something hitting the projectile instead of the
1935 // projectile hitting the something, or a touchareagrid one. Neither of
1936 // these stop the projectile from moving, so...
1937 if(trace_dphitcontents == 0)
1939 dprint("A hit happened with zero hit contents... DEBUG THIS, this should never happen for projectiles! Projectile will self-destruct.\n");
1942 if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
1944 if (other == world && self.size != '0 0 0')
1947 tic = self.velocity * sys_ticrate;
1948 tic = tic + normalize(tic) * vlen(self.maxs - self.mins);
1949 traceline(self.origin - tic, self.origin + tic, MOVE_NORMAL, self);
1950 if (trace_fraction >= 1)
1952 dprint("Odd... did not hit...?\n");
1954 else if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
1956 dprint("Detected and prevented the sky-grapple bug.\n");
1964 #define SUB_OwnerCheck() (other && (other == self.owner))
1966 #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)
1968 float MAX_IPBAN_URIS = 16;
1970 float URI_GET_DISCARD = 0;
1971 float URI_GET_IPBAN = 1;
1972 float URI_GET_IPBAN_END = 16;
1974 void URI_Get_Callback(float id, float status, string data)
1976 dprint("Received HTTP request data for id ", ftos(id), "; status is ", ftos(status), "\nData is:\n");
1978 dprint("\nEnd of data.\n");
1980 if (id == URI_GET_DISCARD)
1984 else if (id >= URI_GET_IPBAN && id <= URI_GET_IPBAN_END)
1987 OnlineBanList_URI_Get_Callback(id, status, data);
1991 print("Received HTTP request data for an invalid id ", ftos(id), ".\n");
1995 void print_to(entity e, string s)
1998 sprint(e, strcat(s, "\n"));
2017 for (i = 0; i < MapInfo_count; ++i)
2019 if (MapInfo_Get_ByID(i))
2021 r = stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, "/captimerecord/time")));
2024 h = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, "/captimerecord/netname"));
2025 s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-6, ftos_decimals(r, 2)), " ", h, "\n");
2033 for (i = 0; i < MapInfo_count; ++i)
2035 if (MapInfo_Get_ByID(i))
2037 r = stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, RACE_RECORD, "time")));
2040 h = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, RACE_RECORD, "netname"));
2041 s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-8, TIME_ENCODED_TOSTRING(r)), " ", h, "\n");
2049 for (i = 0; i < MapInfo_count; ++i)
2051 if (MapInfo_Get_ByID(i))
2053 r = stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, CTS_RECORD, "time")));
2056 h = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, CTS_RECORD, "netname"));
2057 s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-8, TIME_ENCODED_TOSTRING(r)), " ", h, "\n");
2063 MapInfo_ClearTemps();
2066 return "No records are available on this server.\n";
2068 return strcat("Records on this server:\n", s);
2071 float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
2074 vector start, org, delta, end, enddown, mstart;
2076 m = e.dphitcontentsmask;
2077 e.dphitcontentsmask = goodcontents | badcontents;
2080 delta = world.maxs - world.mins;
2082 for (i = 0; i < attempts; ++i)
2084 start_x = org_x + random() * delta_x;
2085 start_y = org_y + random() * delta_y;
2086 start_z = org_z + random() * delta_z;
2088 // rule 1: start inside world bounds, and outside
2089 // solid, and don't start from somewhere where you can
2090 // fall down to evil
2091 tracebox(start, e.mins, e.maxs, start - '0 0 1' * delta_z, MOVE_NORMAL, e);
2092 if (trace_fraction >= 1)
2094 if (trace_startsolid)
2096 if (trace_dphitcontents & badcontents)
2098 if (trace_dphitq3surfaceflags & badsurfaceflags)
2101 // rule 2: if we are too high, lower the point
2102 if (trace_fraction * delta_z > maxaboveground)
2103 start = trace_endpos + '0 0 1' * maxaboveground;
2104 enddown = trace_endpos;
2106 // rule 3: make sure we aren't outside the map. This only works
2107 // for somewhat well formed maps. A good rule of thumb is that
2108 // the map should have a convex outside hull.
2109 // these can be traceLINES as we already verified the starting box
2110 mstart = start + 0.5 * (e.mins + e.maxs);
2111 traceline(mstart, mstart + '1 0 0' * delta_x, MOVE_NORMAL, e);
2112 if (trace_fraction >= 1)
2114 traceline(mstart, mstart - '1 0 0' * delta_x, MOVE_NORMAL, e);
2115 if (trace_fraction >= 1)
2117 traceline(mstart, mstart + '0 1 0' * delta_y, MOVE_NORMAL, e);
2118 if (trace_fraction >= 1)
2120 traceline(mstart, mstart - '0 1 0' * delta_y, MOVE_NORMAL, e);
2121 if (trace_fraction >= 1)
2123 traceline(mstart, mstart + '0 0 1' * delta_z, MOVE_NORMAL, e);
2124 if (trace_fraction >= 1)
2127 // find a random vector to "look at"
2128 end_x = org_x + random() * delta_x;
2129 end_y = org_y + random() * delta_y;
2130 end_z = org_z + random() * delta_z;
2131 end = start + normalize(end - start) * vlen(delta);
2133 // rule 4: start TO end must not be too short
2134 tracebox(start, e.mins, e.maxs, end, MOVE_NORMAL, e);
2135 if (trace_startsolid)
2137 if (trace_fraction < minviewdistance / vlen(delta))
2140 // rule 5: don't want to look at sky
2141 if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
2144 // rule 6: we must not end up in trigger_hurt
2145 if (tracebox_hits_trigger_hurt(start, e.mins, e.maxs, enddown))
2147 dprint("trigger_hurt! ouch! and nothing else could find it!\n");
2154 e.dphitcontentsmask = m;
2158 setorigin(e, start);
2159 e.angles = vectoangles(end - start);
2160 dprint("Needed ", ftos(i + 1), " attempts\n");
2167 float zcurveparticles_effectno;
2168 vector zcurveparticles_start;
2169 float zcurveparticles_spd;
2171 void endzcurveparticles()
2173 if(zcurveparticles_effectno)
2176 WriteShort(MSG_BROADCAST, zcurveparticles_spd | 0x8000);
2178 zcurveparticles_effectno = 0;
2181 void zcurveparticles(float effectno, vector start, vector end, float end_dz, float spd)
2183 spd = bound(0, floor(spd / 16), 32767);
2184 if(effectno != zcurveparticles_effectno || start != zcurveparticles_start)
2186 endzcurveparticles();
2187 WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
2188 WriteByte(MSG_BROADCAST, TE_CSQC_ZCURVEPARTICLES);
2189 WriteShort(MSG_BROADCAST, effectno);
2190 WriteCoord(MSG_BROADCAST, start_x);
2191 WriteCoord(MSG_BROADCAST, start_y);
2192 WriteCoord(MSG_BROADCAST, start_z);
2193 zcurveparticles_effectno = effectno;
2194 zcurveparticles_start = start;
2197 WriteShort(MSG_BROADCAST, zcurveparticles_spd);
2198 WriteCoord(MSG_BROADCAST, end_x);
2199 WriteCoord(MSG_BROADCAST, end_y);
2200 WriteCoord(MSG_BROADCAST, end_z);
2201 WriteCoord(MSG_BROADCAST, end_dz);
2202 zcurveparticles_spd = spd;
2205 void zcurveparticles_from_tracetoss(float effectno, vector start, vector end, vector vel)
2208 vector vecxy, velxy;
2210 vecxy = end - start;
2215 if (vlen(velxy) < 0.000001 * fabs(vel_z))
2217 endzcurveparticles();
2218 trailparticles(world, effectno, start, end);
2222 end_dz = vlen(vecxy) / vlen(velxy) * vel_z - (end_z - start_z);
2223 zcurveparticles(effectno, start, end, end_dz, vlen(vel));
2226 string GetGametype(); // g_world.qc
2227 void write_recordmarker(entity pl, float tstart, float dt)
2229 GameLogEcho(strcat(":recordset:", ftos(pl.playerid), ":", ftos(dt)));
2231 // also write a marker into demo files for demotc-race-record-extractor to find
2234 strcat("//", strconv(2, 0, 0, GetGametype()), " RECORD SET ", TIME_ENCODED_TOSTRING(TIME_ENCODE(dt))),
2235 " ", ftos(tstart), " ", ftos(dt), "\n"));
2238 vector shotorg_adjustfromclient(vector vecs, float y_is_right, float allowcenter)
2240 switch(self.owner.cvar_cl_gunalign)
2251 if(allowcenter) // 2: allow center handedness
2264 if(allowcenter) // 2: allow center handedness
2280 vector shotorg_adjust(vector vecs, float y_is_right, float visual)
2285 if (cvar("g_shootfromeye"))
2289 vecs = shotorg_adjustfromclient(vecs, y_is_right, TRUE);
2297 else if (cvar("g_shootfromcenter"))
2301 vecs = shotorg_adjustfromclient(vecs, y_is_right, TRUE);
2309 else if (cvar("g_shootfromclient"))
2311 vecs = shotorg_adjustfromclient(vecs, y_is_right, (cvar("g_shootfromclient") >= 2));
2313 else if ((s = cvar_string("g_shootfromfixedorigin")) != "")
2328 void attach_sameorigin(entity e, entity to, string tag)
2330 vector org, t_forward, t_left, t_up, e_forward, e_up;
2337 org = e.origin - gettaginfo(to, gettagindex(to, tag));
2338 tagscale = pow(vlen(v_forward), -2); // undo a scale on the tag
2339 t_forward = v_forward * tagscale;
2340 t_left = v_right * -tagscale;
2341 t_up = v_up * tagscale;
2343 e.origin_x = org * t_forward;
2344 e.origin_y = org * t_left;
2345 e.origin_z = org * t_up;
2347 // current forward and up directions
2348 if (substring(e.model, 0, 1) == "*") // bmodels have their own rules
2349 e.angles_x = -e.angles_x;
2350 fixedmakevectors(e.angles);
2352 // untransform forward, up!
2353 e_forward_x = v_forward * t_forward;
2354 e_forward_y = v_forward * t_left;
2355 e_forward_z = v_forward * t_up;
2356 e_up_x = v_up * t_forward;
2357 e_up_y = v_up * t_left;
2358 e_up_z = v_up * t_up;
2360 e.angles = fixedvectoangles2(e_forward, e_up);
2361 if (substring(e.model, 0, 1) == "*") // bmodels have their own rules
2362 e.angles_x = -e.angles_x;
2364 setattachment(e, to, tag);
2365 setorigin(e, e.origin);
2368 void detach_sameorigin(entity e)
2371 org = gettaginfo(e, 0);
2372 e.angles = fixedvectoangles2(v_forward, v_up);
2373 if (substring(e.model, 0, 1) == "*") // bmodels have their own rules
2374 e.angles_x = -e.angles_x;
2376 setattachment(e, world, "");
2377 setorigin(e, e.origin);
2380 void follow_sameorigin(entity e, entity to)
2382 e.movetype = MOVETYPE_FOLLOW; // make the hole follow
2383 e.aiment = to; // make the hole follow bmodel
2384 e.punchangle = to.angles; // the original angles of bmodel
2385 e.view_ofs = e.origin - to.origin; // relative origin
2386 e.v_angle = e.angles - to.angles; // relative angles
2389 void unfollow_sameorigin(entity e)
2391 e.movetype = MOVETYPE_NONE;
2394 entity gettaginfo_relative_ent;
2395 vector gettaginfo_relative(entity e, float tag)
2397 if (!gettaginfo_relative_ent)
2399 gettaginfo_relative_ent = spawn();
2400 gettaginfo_relative_ent.effects = EF_NODRAW;
2402 gettaginfo_relative_ent.model = e.model;
2403 gettaginfo_relative_ent.modelindex = e.modelindex;
2404 gettaginfo_relative_ent.frame = e.frame;
2405 return gettaginfo(gettaginfo_relative_ent, tag);
2408 void SoundEntity_StartSound(entity pl, float chan, string samp, float vol, float attn)
2412 if (pl.soundentity.cnt & p)
2414 soundtoat(MSG_ALL, pl.soundentity, gettaginfo(pl.soundentity, 0), chan, samp, vol, attn);
2415 pl.soundentity.cnt |= p;
2418 void SoundEntity_StopSound(entity pl, float chan)
2422 if (pl.soundentity.cnt & p)
2424 stopsoundto(MSG_ALL, pl.soundentity, chan);
2425 pl.soundentity.cnt &~= p;
2429 void SoundEntity_Attach(entity pl)
2431 pl.soundentity = spawn();
2432 pl.soundentity.classname = "soundentity";
2433 pl.soundentity.owner = pl;
2434 setattachment(pl.soundentity, pl, "");
2435 setmodel(pl.soundentity, "null");
2438 void SoundEntity_Detach(entity pl)
2441 for (i = 0; i <= 7; ++i)
2442 SoundEntity_StopSound(pl, i);
2446 float ParseCommandPlayerSlotTarget_firsttoken;
2447 entity GetCommandPlayerSlotTargetFromTokenizedCommand(float tokens, float idx) // idx = start index
2455 ParseCommandPlayerSlotTarget_firsttoken = -1;
2459 if (substring(argv(idx), 0, 1) == "#")
2461 s = substring(argv(idx), 1, -1);
2469 ParseCommandPlayerSlotTarget_firsttoken = idx;
2470 if (s == ftos(stof(s)))
2472 e = edict_num(stof(s));
2473 if (e.flags & FL_CLIENT)
2479 // it must be a nick name
2482 ParseCommandPlayerSlotTarget_firsttoken = idx;
2485 FOR_EACH_CLIENT(head)
2486 if (head.netname == s)
2494 s = strdecolorize(s);
2496 FOR_EACH_CLIENT(head)
2497 if (strdecolorize(head.netname) == s)
2512 float modeleffect_SendEntity(entity to, float sf)
2515 WriteByte(MSG_ENTITY, ENT_CLIENT_MODELEFFECT);
2518 if(self.velocity != '0 0 0')
2520 if(self.angles != '0 0 0')
2522 if(self.avelocity != '0 0 0')
2525 WriteByte(MSG_ENTITY, f);
2526 WriteShort(MSG_ENTITY, self.modelindex);
2527 WriteByte(MSG_ENTITY, self.skin);
2528 WriteByte(MSG_ENTITY, self.frame);
2529 WriteCoord(MSG_ENTITY, self.origin_x);
2530 WriteCoord(MSG_ENTITY, self.origin_y);
2531 WriteCoord(MSG_ENTITY, self.origin_z);
2534 WriteCoord(MSG_ENTITY, self.velocity_x);
2535 WriteCoord(MSG_ENTITY, self.velocity_y);
2536 WriteCoord(MSG_ENTITY, self.velocity_z);
2540 WriteCoord(MSG_ENTITY, self.angles_x);
2541 WriteCoord(MSG_ENTITY, self.angles_y);
2542 WriteCoord(MSG_ENTITY, self.angles_z);
2546 WriteCoord(MSG_ENTITY, self.avelocity_x);
2547 WriteCoord(MSG_ENTITY, self.avelocity_y);
2548 WriteCoord(MSG_ENTITY, self.avelocity_z);
2550 WriteShort(MSG_ENTITY, self.scale * 256.0);
2551 WriteShort(MSG_ENTITY, self.scale2 * 256.0);
2552 WriteByte(MSG_ENTITY, self.teleport_time * 100.0);
2553 WriteByte(MSG_ENTITY, self.fade_time * 100.0);
2554 WriteByte(MSG_ENTITY, self.alpha * 255.0);
2559 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)
2564 e.classname = "modeleffect";
2572 e.teleport_time = t1;
2576 e.scale = s0 / max6(-e.mins_x, -e.mins_y, -e.mins_z, e.maxs_x, e.maxs_y, e.maxs_z);
2580 e.scale2 = s2 / max6(-e.mins_x, -e.mins_y, -e.mins_z, e.maxs_x, e.maxs_y, e.maxs_z);
2583 sz = max(e.scale, e.scale2);
2584 setsize(e, e.mins * sz, e.maxs * sz);
2585 Net_LinkEntity(e, FALSE, 0.1, modeleffect_SendEntity);
2588 void shockwave_spawn(string m, vector org, float sz, float t1, float t2)
2590 return modeleffect_spawn(m, 0, 0, org, '0 0 0', '0 0 0', '0 0 0', 0, sz, 1, t1, t2);
2593 float randombit(float bits)
2595 if not(bits & (bits-1)) // this ONLY holds for powers of two!
2604 for(f = 1; f <= bits; f *= 2)
2613 r = (r - 1) / (n - 1);
2620 float randombits(float bits, float k, float error_return)
2624 while(k > 0 && bits != r)
2626 r += randombit(bits - r);
2635 void randombit_test(float bits, float iter)
2639 print(ftos(randombit(bits)), "\n");
2644 float ExponentialFalloff(float mindist, float maxdist, float halflifedist, float d)
2646 if(halflifedist > 0)
2647 return pow(0.5, (bound(mindist, d, maxdist) - mindist) / halflifedist);
2648 else if(halflifedist < 0)
2649 return pow(0.5, (bound(mindist, d, maxdist) - maxdist) / halflifedist);