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 cvar_set("developer", "1");
589 dprint("--- CUT HERE ---\nWARNING: ");
592 remove(world); // isn't there any better way to cause a backtrace?
593 dprint("\n--- CUT UNTIL HERE ---\n");
594 cvar_set("developer", ftos(dev));
597 string Team_ColorCode(float teamid)
599 if (teamid == COLOR_TEAM1)
601 else if (teamid == COLOR_TEAM2)
603 else if (teamid == COLOR_TEAM3)
605 else if (teamid == COLOR_TEAM4)
610 string Team_ColorName(float t)
612 // fixme: Search for team entities and get their .netname's!
613 if (t == COLOR_TEAM1)
615 if (t == COLOR_TEAM2)
617 if (t == COLOR_TEAM3)
619 if (t == COLOR_TEAM4)
623 string Team_ColorNameLowerCase(float t)
625 // fixme: Search for team entities and get their .netname's!
626 if (t == COLOR_TEAM1)
628 if (t == COLOR_TEAM2)
630 if (t == COLOR_TEAM3)
632 if (t == COLOR_TEAM4)
637 #define CENTERPRIO_POINT 1
638 #define CENTERPRIO_SPAM 2
639 #define CENTERPRIO_VOTE 4
640 #define CENTERPRIO_NORMAL 5
641 #define CENTERPRIO_SHIELDING 7
642 #define CENTERPRIO_MAPVOTE 9
643 #define CENTERPRIO_IDLEKICK 50
644 #define CENTERPRIO_ADMIN 99
645 .float centerprint_priority;
646 .float centerprint_expires;
647 void centerprint_atprio(entity e, float prio, string s)
649 if (intermission_running)
650 if (prio < CENTERPRIO_MAPVOTE)
652 if (time > e.centerprint_expires)
653 e.centerprint_priority = 0;
654 if (prio >= e.centerprint_priority)
656 e.centerprint_priority = prio;
657 if (timeoutStatus == 2)
658 e.centerprint_expires = time + (e.cvar_scr_centertime * TIMEOUT_SLOWMO_VALUE);
660 e.centerprint_expires = time + e.cvar_scr_centertime;
661 centerprint_builtin(e, s);
664 void centerprint_expire(entity e, float prio)
666 if (prio == e.centerprint_priority)
668 e.centerprint_priority = 0;
669 centerprint_builtin(e, "");
672 void centerprint(entity e, string s)
674 centerprint_atprio(e, CENTERPRIO_NORMAL, s);
677 // decolorizes and team colors the player name when needed
678 string playername(entity p)
681 if (teams_matter && !intermission_running && p.classname == "player")
683 t = Team_ColorCode(p.team);
684 return strcat(t, strdecolorize(p.netname));
690 vector randompos(vector m1, vector m2)
694 v_x = m2_x * random() + m1_x;
695 v_y = m2_y * random() + m1_y;
696 v_z = m2_z * random() + m1_z;
700 float g_pickup_shells;
701 float g_pickup_shells_max;
702 float g_pickup_nails;
703 float g_pickup_nails_max;
704 float g_pickup_rockets;
705 float g_pickup_rockets_max;
706 float g_pickup_cells;
707 float g_pickup_cells_max;
709 float g_pickup_fuel_jetpack;
710 float g_pickup_fuel_max;
711 float g_pickup_armorsmall;
712 float g_pickup_armorsmall_max;
713 float g_pickup_armormedium;
714 float g_pickup_armormedium_max;
715 float g_pickup_armorbig;
716 float g_pickup_armorbig_max;
717 float g_pickup_armorlarge;
718 float g_pickup_armorlarge_max;
719 float g_pickup_healthsmall;
720 float g_pickup_healthsmall_max;
721 float g_pickup_healthmedium;
722 float g_pickup_healthmedium_max;
723 float g_pickup_healthlarge;
724 float g_pickup_healthlarge_max;
725 float g_pickup_healthmega;
726 float g_pickup_healthmega_max;
728 float g_weaponarena_random;
729 string g_weaponarena_list;
730 float g_weaponspeedfactor;
731 float g_weaponratefactor;
732 float g_weapondamagefactor;
733 float g_weaponforcefactor;
737 float start_ammo_shells;
738 float start_ammo_nails;
739 float start_ammo_rockets;
740 float start_ammo_cells;
741 float start_ammo_fuel;
743 float start_armorvalue;
744 float warmup_start_weapons;
745 float warmup_start_ammo_shells;
746 float warmup_start_ammo_nails;
747 float warmup_start_ammo_rockets;
748 float warmup_start_ammo_cells;
749 float warmup_start_ammo_fuel;
750 float warmup_start_health;
751 float warmup_start_armorvalue;
755 entity get_weaponinfo(float w);
757 float NixNex_CanChooseWeapon(float wpn);
758 void readplayerstartcvars()
764 // initialize starting values for players
767 start_ammo_shells = 0;
768 start_ammo_nails = 0;
769 start_ammo_rockets = 0;
770 start_ammo_cells = 0;
771 start_health = cvar("g_balance_health_start");
772 start_armorvalue = cvar("g_balance_armor_start");
775 s = cvar_string("g_weaponarena");
781 g_weaponarena_list = "All Weapons";
782 for (j = WEP_FIRST; j <= WEP_LAST; ++j)
784 e = get_weaponinfo(j);
785 g_weaponarena |= e.weapons;
786 weapon_action(e.weapon, WR_PRECACHE);
789 else if (s == "most")
791 g_weaponarena_list = "Most Weapons";
792 for (j = WEP_FIRST; j <= WEP_LAST; ++j)
794 e = get_weaponinfo(j);
795 if (e.spawnflags & WEPSPAWNFLAG_NORMAL)
797 g_weaponarena |= e.weapons;
798 weapon_action(e.weapon, WR_PRECACHE);
802 else if (s == "none")
804 g_weaponarena_list = "No Weapons";
805 g_weaponarena = WEPBIT_ALL + 1; // this supports no single weapon bit!
809 t = tokenize_console(s);
810 g_weaponarena_list = "";
811 for (i = 0; i < t; ++i)
814 for (j = WEP_FIRST; j <= WEP_LAST; ++j)
816 e = get_weaponinfo(j);
819 g_weaponarena |= e.weapons;
820 weapon_action(e.weapon, WR_PRECACHE);
821 g_weaponarena_list = strcat(g_weaponarena_list, e.message, " & ");
827 print("The weapon mutator list contains an unknown weapon ", s, ". Skipped.\n");
830 g_weaponarena_list = strzone(substring(g_weaponarena_list, 0, strlen(g_weaponarena_list) - 3));
834 g_weaponarena_random = cvar("g_weaponarena_random");
836 g_weaponarena_random = 0;
841 // will be done later
842 for (i = WEP_FIRST; i <= WEP_LAST; ++i)
843 if (NixNex_CanChooseWeapon(i))
844 weapon_action(i, WR_PRECACHE);
845 if(!cvar("g_use_ammunition"))
846 start_items |= IT_UNLIMITED_AMMO;
848 else if (g_weaponarena)
850 start_weapons = g_weaponarena;
851 if (g_weaponarena & (WEPBIT_GRENADE_LAUNCHER | WEPBIT_HAGAR | WEPBIT_ROCKET_LAUNCHER))
852 start_ammo_rockets = 999;
853 if (g_weaponarena & WEPBIT_SHOTGUN)
854 start_ammo_shells = 999;
855 if (g_weaponarena & (WEPBIT_ELECTRO | WEPBIT_CRYLINK | WEPBIT_NEX | WEPBIT_MINSTANEX | WEPBIT_HLAC | WEPBIT_HOOK))
856 start_ammo_cells = 999;
857 if (g_weaponarena & (WEPBIT_UZI | WEPBIT_CAMPINGRIFLE))
858 start_ammo_nails = 999;
859 if (g_weaponarena & WEPBIT_HOOK)
860 start_ammo_fuel = 999;
861 start_items |= IT_UNLIMITED_AMMO;
863 else if (g_minstagib)
866 start_armorvalue = 0;
867 start_weapons = WEPBIT_MINSTANEX;
868 weapon_action(WEP_MINSTANEX, WR_PRECACHE);
869 start_ammo_cells = cvar("g_minstagib_ammo_start");
870 g_minstagib_invis_alpha = cvar("g_minstagib_invis_alpha");
871 start_ammo_fuel = cvar("g_start_ammo_fuel");
873 if (g_minstagib_invis_alpha <= 0)
874 g_minstagib_invis_alpha = -1;
880 start_ammo_shells = cvar("g_lms_start_ammo_shells");
881 start_ammo_nails = cvar("g_lms_start_ammo_nails");
882 start_ammo_rockets = cvar("g_lms_start_ammo_rockets");
883 start_ammo_cells = cvar("g_lms_start_ammo_cells");
884 start_ammo_fuel = cvar("g_lms_start_ammo_fuel");
885 start_health = cvar("g_lms_start_health");
886 start_armorvalue = cvar("g_lms_start_armor");
888 else if (cvar("g_use_ammunition"))
890 start_ammo_shells = cvar("g_start_ammo_shells");
891 start_ammo_nails = cvar("g_start_ammo_nails");
892 start_ammo_rockets = cvar("g_start_ammo_rockets");
893 start_ammo_cells = cvar("g_start_ammo_cells");
894 start_ammo_fuel = cvar("g_start_ammo_fuel");
898 start_ammo_shells = cvar("g_pickup_shells_max");
899 start_ammo_nails = cvar("g_pickup_nails_max");
900 start_ammo_rockets = cvar("g_pickup_rockets_max");
901 start_ammo_cells = cvar("g_pickup_cells_max");
902 start_ammo_fuel = cvar("g_pickup_fuel_max");
903 start_items |= IT_UNLIMITED_AMMO;
906 for (i = WEP_FIRST; i <= WEP_LAST; ++i)
908 e = get_weaponinfo(i);
912 t = cvar(strcat("g_start_weapon_", e.netname));
914 if (t < 0) // "default" weapon selection
917 t = (e.spawnflags & WEPSPAWNFLAG_NORMAL);
918 else if (g_race || g_cts)
919 t = (i == WEP_LASER);
921 t = 0; // weapon is set a few lines later
923 t = (i == WEP_LASER || i == WEP_SHOTGUN);
924 if (g_grappling_hook) // if possible, redirect off-hand hook to on-hand hook
925 t += (i == WEP_HOOK);
928 if (g_nexball && i == WEP_PORTO)
933 start_weapons |= e.weapons;
934 weapon_action(e.weapon, WR_PRECACHE);
941 warmup_start_ammo_shells = start_ammo_shells;
942 warmup_start_ammo_nails = start_ammo_nails;
943 warmup_start_ammo_rockets = start_ammo_rockets;
944 warmup_start_ammo_cells = start_ammo_cells;
945 warmup_start_ammo_fuel = start_ammo_fuel;
946 warmup_start_health = start_health;
947 warmup_start_armorvalue = start_armorvalue;
948 warmup_start_weapons = start_weapons;
950 if (!g_weaponarena && !g_nixnex && !g_minstagib)
952 if (cvar("g_use_ammunition"))
954 warmup_start_ammo_shells = cvar("g_warmup_start_ammo_shells");
955 warmup_start_ammo_cells = cvar("g_warmup_start_ammo_cells");
956 warmup_start_ammo_nails = cvar("g_warmup_start_ammo_nails");
957 warmup_start_ammo_rockets = cvar("g_warmup_start_ammo_rockets");
958 warmup_start_ammo_fuel = cvar("g_warmup_start_ammo_fuel");
960 warmup_start_health = cvar("g_warmup_start_health");
961 warmup_start_armorvalue = cvar("g_warmup_start_armor");
962 if (cvar("g_warmup_allguns"))
964 for (i = WEP_FIRST; i <= WEP_LAST; ++i)
966 e = get_weaponinfo(i);
969 if (e.spawnflags & WEPSPAWNFLAG_NORMAL)
971 warmup_start_weapons |= e.weapons;
972 weapon_action(e.weapon, WR_PRECACHE);
979 if (g_jetpack || (g_grappling_hook && (start_weapons & WEPBIT_HOOK)))
981 g_grappling_hook = 0; // these two can't coexist, as they use the same button
982 start_items |= IT_FUEL_REGEN;
983 start_ammo_fuel = max(start_ammo_fuel, cvar("g_balance_fuel_rotstable"));
984 warmup_start_ammo_fuel = max(warmup_start_ammo_fuel, cvar("g_balance_fuel_rotstable"));
988 start_items |= IT_JETPACK;
990 if (g_weapon_stay == 2)
992 if (!start_ammo_shells) start_ammo_shells = g_pickup_shells;
993 if (!start_ammo_nails) start_ammo_nails = g_pickup_nails;
994 if (!start_ammo_cells) start_ammo_cells = g_pickup_cells;
995 if (!start_ammo_rockets) start_ammo_rockets = g_pickup_rockets;
996 if (!start_ammo_fuel) start_ammo_fuel = g_pickup_fuel;
997 if (!warmup_start_ammo_shells) warmup_start_ammo_shells = g_pickup_shells;
998 if (!warmup_start_ammo_nails) warmup_start_ammo_nails = g_pickup_nails;
999 if (!warmup_start_ammo_cells) warmup_start_ammo_cells = g_pickup_cells;
1000 if (!warmup_start_ammo_rockets) warmup_start_ammo_rockets = g_pickup_rockets;
1001 if (!warmup_start_ammo_fuel) warmup_start_ammo_fuel = g_pickup_fuel;
1004 start_ammo_shells = max(0, start_ammo_shells);
1005 start_ammo_nails = max(0, start_ammo_nails);
1006 start_ammo_cells = max(0, start_ammo_cells);
1007 start_ammo_rockets = max(0, start_ammo_rockets);
1008 start_ammo_fuel = max(0, start_ammo_fuel);
1010 warmup_start_ammo_shells = max(0, warmup_start_ammo_shells);
1011 warmup_start_ammo_nails = max(0, warmup_start_ammo_nails);
1012 warmup_start_ammo_cells = max(0, warmup_start_ammo_cells);
1013 warmup_start_ammo_rockets = max(0, warmup_start_ammo_rockets);
1014 warmup_start_ammo_fuel = max(0, warmup_start_ammo_fuel);
1018 float g_bugrigs_planar_movement;
1019 float g_bugrigs_planar_movement_car_jumping;
1020 float g_bugrigs_reverse_spinning;
1021 float g_bugrigs_reverse_speeding;
1022 float g_bugrigs_reverse_stopping;
1023 float g_bugrigs_air_steering;
1024 float g_bugrigs_angle_smoothing;
1025 float g_bugrigs_friction_floor;
1026 float g_bugrigs_friction_brake;
1027 float g_bugrigs_friction_air;
1028 float g_bugrigs_accel;
1029 float g_bugrigs_speed_ref;
1030 float g_bugrigs_speed_pow;
1031 float g_bugrigs_steer;
1033 float g_touchexplode;
1034 float g_touchexplode_radius;
1035 float g_touchexplode_damage;
1036 float g_touchexplode_edgedamage;
1037 float g_touchexplode_force;
1042 void readlevelcvars(void)
1044 g_bugrigs = cvar("g_bugrigs");
1045 g_bugrigs_planar_movement = cvar("g_bugrigs_planar_movement");
1046 g_bugrigs_planar_movement_car_jumping = cvar("g_bugrigs_planar_movement_car_jumping");
1047 g_bugrigs_reverse_spinning = cvar("g_bugrigs_reverse_spinning");
1048 g_bugrigs_reverse_speeding = cvar("g_bugrigs_reverse_speeding");
1049 g_bugrigs_reverse_stopping = cvar("g_bugrigs_reverse_stopping");
1050 g_bugrigs_air_steering = cvar("g_bugrigs_air_steering");
1051 g_bugrigs_angle_smoothing = cvar("g_bugrigs_angle_smoothing");
1052 g_bugrigs_friction_floor = cvar("g_bugrigs_friction_floor");
1053 g_bugrigs_friction_brake = cvar("g_bugrigs_friction_brake");
1054 g_bugrigs_friction_air = cvar("g_bugrigs_friction_air");
1055 g_bugrigs_accel = cvar("g_bugrigs_accel");
1056 g_bugrigs_speed_ref = cvar("g_bugrigs_speed_ref");
1057 g_bugrigs_speed_pow = cvar("g_bugrigs_speed_pow");
1058 g_bugrigs_steer = cvar("g_bugrigs_steer");
1060 g_touchexplode = cvar("g_touchexplode");
1061 g_touchexplode_radius = cvar("g_touchexplode_radius");
1062 g_touchexplode_damage = cvar("g_touchexplode_damage");
1063 g_touchexplode_edgedamage = cvar("g_touchexplode_edgedamage");
1064 g_touchexplode_force = cvar("g_touchexplode_force");
1066 #ifdef ALLOW_FORCEMODELS
1067 sv_clforceplayermodels = cvar("sv_clforceplayermodels");
1069 sv_loddistance1 = cvar("sv_loddistance1");
1070 sv_loddistance2 = cvar("sv_loddistance2");
1071 if(sv_loddistance2 <= sv_loddistance1)
1072 sv_loddistance2 = 1073741824; // enough to turn off LOD 2 reliably
1073 sv_clones = cvar("sv_clones");
1074 sv_cheats = cvar("sv_cheats");
1075 sv_gentle = cvar("sv_gentle");
1076 sv_foginterval = cvar("sv_foginterval");
1077 g_cloaked = cvar("g_cloaked");
1078 g_jump_grunt = cvar("g_jump_grunt");
1079 g_footsteps = cvar("g_footsteps");
1080 g_grappling_hook = cvar("g_grappling_hook");
1081 g_jetpack = cvar("g_jetpack");
1082 g_laserguided_missile = cvar("g_laserguided_missile");
1083 g_midair = cvar("g_midair");
1084 g_minstagib = cvar("g_minstagib");
1085 g_nixnex = cvar("g_nixnex");
1086 g_nixnex_with_laser = cvar("g_nixnex_with_laser");
1087 g_norecoil = cvar("g_norecoil");
1088 g_vampire = cvar("g_vampire");
1089 g_bloodloss = cvar("g_bloodloss");
1090 sv_maxidle = cvar("sv_maxidle");
1091 sv_maxidle_spectatorsareidle = cvar("sv_maxidle_spectatorsareidle");
1092 sv_pogostick = cvar("sv_pogostick");
1093 sv_doublejump = cvar("sv_doublejump");
1094 g_ctf_reverse = cvar("g_ctf_reverse");
1095 sv_autotaunt = cvar("sv_autotaunt");
1096 sv_taunt = cvar("sv_taunt");
1098 inWarmupStage = cvar("g_warmup");
1099 g_warmup_limit = cvar("g_warmup_limit");
1100 g_warmup_allguns = cvar("g_warmup_allguns");
1101 g_warmup_allow_timeout = cvar("g_warmup_allow_timeout");
1103 if ((g_race && g_race_qualifying == 2) || g_runematch || g_arena || g_assault || cvar("g_campaign"))
1104 inWarmupStage = 0; // these modes cannot work together, sorry
1106 g_pickup_respawntime_weapon = cvar("g_pickup_respawntime_weapon");
1107 g_pickup_respawntime_ammo = cvar("g_pickup_respawntime_ammo");
1108 g_pickup_respawntime_short = cvar("g_pickup_respawntime_short");
1109 g_pickup_respawntime_medium = cvar("g_pickup_respawntime_medium");
1110 g_pickup_respawntime_long = cvar("g_pickup_respawntime_long");
1111 g_pickup_respawntime_powerup = cvar("g_pickup_respawntime_powerup");
1112 g_pickup_respawntimejitter_weapon = cvar("g_pickup_respawntimejitter_weapon");
1113 g_pickup_respawntimejitter_ammo = cvar("g_pickup_respawntimejitter_ammo");
1114 g_pickup_respawntimejitter_short = cvar("g_pickup_respawntimejitter_short");
1115 g_pickup_respawntimejitter_medium = cvar("g_pickup_respawntimejitter_medium");
1116 g_pickup_respawntimejitter_long = cvar("g_pickup_respawntimejitter_long");
1117 g_pickup_respawntimejitter_powerup = cvar("g_pickup_respawntimejitter_powerup");
1119 if (g_minstagib) g_nixnex = g_weaponarena = 0;
1120 if (g_nixnex) g_weaponarena = 0;
1123 g_weaponspeedfactor = cvar("g_weaponspeedfactor");
1124 g_weaponratefactor = cvar("g_weaponratefactor");
1125 g_weapondamagefactor = cvar("g_weapondamagefactor");
1126 g_weaponforcefactor = cvar("g_weaponforcefactor");
1128 g_pickup_shells = cvar("g_pickup_shells");
1129 g_pickup_shells_max = cvar("g_pickup_shells_max");
1130 g_pickup_nails = cvar("g_pickup_nails");
1131 g_pickup_nails_max = cvar("g_pickup_nails_max");
1132 g_pickup_rockets = cvar("g_pickup_rockets");
1133 g_pickup_rockets_max = cvar("g_pickup_rockets_max");
1134 g_pickup_cells = cvar("g_pickup_cells");
1135 g_pickup_cells_max = cvar("g_pickup_cells_max");
1136 g_pickup_fuel = cvar("g_pickup_fuel");
1137 g_pickup_fuel_jetpack = cvar("g_pickup_fuel_jetpack");
1138 g_pickup_fuel_max = cvar("g_pickup_fuel_max");
1139 g_pickup_armorsmall = cvar("g_pickup_armorsmall");
1140 g_pickup_armorsmall_max = cvar("g_pickup_armorsmall_max");
1141 g_pickup_armormedium = cvar("g_pickup_armormedium");
1142 g_pickup_armormedium_max = cvar("g_pickup_armormedium_max");
1143 g_pickup_armorbig = cvar("g_pickup_armorbig");
1144 g_pickup_armorbig_max = cvar("g_pickup_armorbig_max");
1145 g_pickup_armorlarge = cvar("g_pickup_armorlarge");
1146 g_pickup_armorlarge_max = cvar("g_pickup_armorlarge_max");
1147 g_pickup_healthsmall = cvar("g_pickup_healthsmall");
1148 g_pickup_healthsmall_max = cvar("g_pickup_healthsmall_max");
1149 g_pickup_healthmedium = cvar("g_pickup_healthmedium");
1150 g_pickup_healthmedium_max = cvar("g_pickup_healthmedium_max");
1151 g_pickup_healthlarge = cvar("g_pickup_healthlarge");
1152 g_pickup_healthlarge_max = cvar("g_pickup_healthlarge_max");
1153 g_pickup_healthmega = cvar("g_pickup_healthmega");
1154 g_pickup_healthmega_max = cvar("g_pickup_healthmega_max");
1156 g_pinata = cvar("g_pinata");
1158 g_weapon_stay = cvar("g_weapon_stay");
1159 if (!g_weapon_stay && (cvar("deathmatch") == 2))
1161 g_ghost_items = cvar("g_ghost_items");
1162 if(g_ghost_items >= 1)
1163 g_ghost_items = 0.13; // default alpha value
1165 if not(inWarmupStage)
1166 game_starttime = cvar("g_start_delay");
1168 readplayerstartcvars();
1172 // TODO sound pack system
1175 string precache_sound_builtin (string s) = #19;
1176 void(entity e, float chan, string samp, float vol, float atten) sound_builtin = #8;
1177 string precache_sound(string s)
1179 return precache_sound_builtin(strcat(soundpack, s));
1181 void play2(entity e, string filename)
1183 stuffcmd(e, strcat("play2 ", soundpack, filename, "\n"));
1185 void sound(entity e, float chan, string samp, float vol, float atten)
1187 sound_builtin(e, chan, strcat(soundpack, samp), vol, atten);
1192 string precache_sound (string s) = #19;
1193 void(entity e, float chan, string samp, float vol, float atten) sound_builtin = #8;
1194 float precache_sound_index (string s) = #19;
1196 #define SND_VOLUME 1
1197 #define SND_ATTENUATION 2
1198 #define SND_LARGEENTITY 8
1199 #define SND_LARGESOUND 16
1201 float sound_allowed(float dest, entity e)
1203 // sounds from world may always pass
1206 if (e.classname == "body")
1208 if (e.owner && e.owner != e)
1213 // sounds to self may always pass
1214 if (dest == MSG_ONE)
1215 if (e == msg_entity)
1217 // sounds by players can be removed
1218 if (cvar("bot_sound_monopoly"))
1219 if (clienttype(e) == CLIENTTYPE_REAL)
1221 // anything else may pass
1225 void sound(entity e, float chan, string samp, float vol, float atten)
1227 if (!sound_allowed(MSG_BROADCAST, e))
1229 sound_builtin(e, chan, samp, vol, atten);
1231 void soundtoat(float dest, entity e, vector o, float chan, string samp, float vol, float atten)
1235 if (!sound_allowed(dest, e))
1238 entno = num_for_edict(e);
1239 idx = precache_sound_index(samp);
1244 atten = floor(atten * 64);
1245 vol = floor(vol * 255);
1248 sflags |= SND_VOLUME;
1250 sflags |= SND_ATTENUATION;
1252 sflags |= SND_LARGEENTITY;
1254 sflags |= SND_LARGESOUND;
1256 WriteByte(dest, SVC_SOUND);
1257 WriteByte(dest, sflags);
1258 if (sflags & SND_VOLUME)
1259 WriteByte(dest, vol);
1260 if (sflags & SND_ATTENUATION)
1261 WriteByte(dest, atten);
1262 if (sflags & SND_LARGEENTITY)
1264 WriteShort(dest, entno);
1265 WriteByte(dest, chan);
1269 WriteShort(dest, entno * 8 + chan);
1271 if (sflags & SND_LARGESOUND)
1272 WriteShort(dest, idx);
1274 WriteByte(dest, idx);
1276 WriteCoord(dest, o_x);
1277 WriteCoord(dest, o_y);
1278 WriteCoord(dest, o_z);
1280 void soundto(float dest, entity e, float chan, string samp, float vol, float atten)
1284 if (!sound_allowed(dest, e))
1287 o = e.origin + 0.5 * (e.mins + e.maxs);
1288 soundtoat(dest, e, o, chan, samp, vol, atten);
1290 void soundat(entity e, vector o, float chan, string samp, float vol, float atten)
1292 soundtoat(MSG_BROADCAST, e, o, chan, samp, vol, atten);
1294 void stopsoundto(float dest, entity e, float chan)
1298 if (!sound_allowed(dest, e))
1301 entno = num_for_edict(e);
1306 idx = precache_sound_index("misc/null.wav");
1307 sflags = SND_LARGEENTITY;
1309 sflags |= SND_LARGESOUND;
1310 WriteByte(dest, SVC_SOUND);
1311 WriteByte(dest, sflags);
1312 WriteShort(dest, entno);
1313 WriteByte(dest, chan);
1314 if (sflags & SND_LARGESOUND)
1315 WriteShort(dest, idx);
1317 WriteByte(dest, idx);
1318 WriteCoord(dest, e.origin_x);
1319 WriteCoord(dest, e.origin_y);
1320 WriteCoord(dest, e.origin_z);
1324 WriteByte(dest, SVC_STOPSOUND);
1325 WriteShort(dest, entno * 8 + chan);
1328 void stopsound(entity e, float chan)
1330 if (!sound_allowed(MSG_BROADCAST, e))
1333 stopsoundto(MSG_BROADCAST, e, chan); // unreliable, gets there fast
1334 stopsoundto(MSG_ALL, e, chan); // in case of packet loss
1337 void play2(entity e, string filename)
1339 //stuffcmd(e, strcat("play2 ", filename, "\n"));
1341 soundtoat(MSG_ONE, world, '0 0 0', CHAN_AUTO, filename, VOL_BASE, ATTN_NONE);
1344 .float announcetime;
1345 float announce(entity player, string msg)
1347 if (time > player.announcetime)
1348 if (clienttype(player) == CLIENTTYPE_REAL)
1350 player.announcetime = time + 0.8;
1356 // use this one if you might be causing spam (e.g. from touch functions that might get called more than once per frame)
1357 float spamsound(entity e, float chan, string samp, float vol, float atten)
1359 if (!sound_allowed(MSG_BROADCAST, e))
1362 if (time > e.announcetime)
1364 e.announcetime = time;
1365 sound(e, chan, samp, vol, atten);
1371 void play2team(float t, string filename)
1375 if (cvar("bot_sound_monopoly"))
1378 FOR_EACH_REALPLAYER(head)
1381 play2(head, filename);
1385 void play2all(string samp)
1387 if (cvar("bot_sound_monopoly"))
1390 sound(world, CHAN_AUTO, samp, VOL_BASE, ATTN_NONE);
1393 void PrecachePlayerSounds(string f);
1394 void precache_all_models(string pattern)
1396 float globhandle, i, n;
1399 globhandle = search_begin(pattern, TRUE, FALSE);
1402 n = search_getsize(globhandle);
1403 for (i = 0; i < n; ++i)
1405 //print(search_getfilename(globhandle, i), "\n");
1406 f = search_getfilename(globhandle, i);
1409 if(substring(f, -9,5) == "_lod1")
1411 if(substring(f, -9,5) == "_lod2")
1413 if(!sv_loddistance1)
1415 PrecachePlayerSounds(strcat(f, ".sounds"));
1417 search_end(globhandle);
1422 // gamemode related things
1423 precache_model ("models/misc/chatbubble.spr");
1424 precache_model ("models/misc/teambubble.spr");
1427 precache_model ("models/runematch/curse.mdl");
1428 precache_model ("models/runematch/rune.mdl");
1431 #ifdef TTURRETS_ENABLED
1432 if (cvar("g_turrets"))
1436 // Precache all player models if desired
1437 if (cvar("sv_precacheplayermodels"))
1439 PrecachePlayerSounds("sound/player/default.sounds");
1440 precache_all_models("models/player/*.zym");
1441 precache_all_models("models/player/*.dpm");
1442 precache_all_models("models/player/*.md3");
1443 precache_all_models("models/player/*.psk");
1444 //precache_model("models/player/carni.zym");
1445 //precache_model("models/player/crash.zym");
1446 //precache_model("models/player/grunt.zym");
1447 //precache_model("models/player/headhunter.zym");
1448 //precache_model("models/player/insurrectionist.zym");
1449 //precache_model("models/player/jeandarc.zym");
1450 //precache_model("models/player/lurk.zym");
1451 //precache_model("models/player/lycanthrope.zym");
1452 //precache_model("models/player/marine.zym");
1453 //precache_model("models/player/nexus.zym");
1454 //precache_model("models/player/pyria.zym");
1455 //precache_model("models/player/shock.zym");
1456 //precache_model("models/player/skadi.zym");
1457 //precache_model("models/player/specop.zym");
1458 //precache_model("models/player/visitant.zym");
1461 if (cvar("sv_defaultcharacter"))
1464 s = cvar_string("sv_defaultplayermodel_red");
1468 PrecachePlayerSounds(strcat(s, ".sounds"));
1470 s = cvar_string("sv_defaultplayermodel_blue");
1474 PrecachePlayerSounds(strcat(s, ".sounds"));
1476 s = cvar_string("sv_defaultplayermodel_yellow");
1480 PrecachePlayerSounds(strcat(s, ".sounds"));
1482 s = cvar_string("sv_defaultplayermodel_pink");
1486 PrecachePlayerSounds(strcat(s, ".sounds"));
1488 s = cvar_string("sv_defaultplayermodel");
1492 PrecachePlayerSounds(strcat(s, ".sounds"));
1498 PrecacheGlobalSound((globalsound_step = "misc/footstep0 6"));
1499 PrecacheGlobalSound((globalsound_metalstep = "misc/metalfootstep0 6"));
1502 // gore and miscellaneous sounds
1503 //precache_sound ("misc/h2ohit.wav");
1504 precache_model ("models/hook.md3");
1505 precache_sound ("misc/armorimpact.wav");
1506 precache_sound ("misc/bodyimpact1.wav");
1507 precache_sound ("misc/bodyimpact2.wav");
1508 precache_sound ("misc/gib.wav");
1509 precache_sound ("misc/gib_splat01.wav");
1510 precache_sound ("misc/gib_splat02.wav");
1511 precache_sound ("misc/gib_splat03.wav");
1512 precache_sound ("misc/gib_splat04.wav");
1513 precache_sound ("misc/hit.wav");
1514 PrecacheGlobalSound((globalsound_fall = "misc/hitground 4"));
1515 PrecacheGlobalSound((globalsound_metalfall = "misc/metalhitground 4"));
1516 precache_sound ("misc/null.wav");
1517 precache_sound ("misc/spawn.wav");
1518 precache_sound ("misc/talk.wav");
1519 precache_sound ("misc/teleport.wav");
1520 precache_sound ("misc/poweroff.wav");
1521 precache_sound ("player/lava.wav");
1522 precache_sound ("player/slime.wav");
1525 precache_sound ("misc/jetpack_fly.wav");
1527 // announcer sounds - male
1528 precache_sound ("announcer/male/electrobitch.wav");
1529 precache_sound ("announcer/male/airshot.wav");
1530 precache_sound ("announcer/male/03kills.wav");
1531 precache_sound ("announcer/male/05kills.wav");
1532 precache_sound ("announcer/male/10kills.wav");
1533 precache_sound ("announcer/male/15kills.wav");
1534 precache_sound ("announcer/male/20kills.wav");
1535 precache_sound ("announcer/male/25kills.wav");
1536 precache_sound ("announcer/male/30kills.wav");
1537 precache_sound ("announcer/male/botlike.wav");
1538 precache_sound ("announcer/male/yoda.wav");
1539 precache_sound ("announcer/male/amazing.wav");
1540 precache_sound ("announcer/male/awesome.wav");
1541 precache_sound ("announcer/male/headshot.wav");
1542 precache_sound ("announcer/male/impressive.wav");
1544 // announcer sounds - robotic
1545 precache_sound ("announcer/robotic/prepareforbattle.wav");
1546 precache_sound ("announcer/robotic/begin.wav");
1547 precache_sound ("announcer/robotic/timeoutcalled.wav");
1548 precache_sound ("announcer/robotic/1fragleft.wav");
1549 precache_sound ("announcer/robotic/2fragsleft.wav");
1550 precache_sound ("announcer/robotic/3fragsleft.wav");
1551 precache_sound ("announcer/robotic/terminated.wav");
1554 precache_sound ("announcer/robotic/lastsecond.wav");
1555 precache_sound ("announcer/robotic/narrowly.wav");
1558 precache_model ("models/sprites/0.spr32");
1559 precache_model ("models/sprites/1.spr32");
1560 precache_model ("models/sprites/2.spr32");
1561 precache_model ("models/sprites/3.spr32");
1562 precache_model ("models/sprites/4.spr32");
1563 precache_model ("models/sprites/5.spr32");
1564 precache_model ("models/sprites/6.spr32");
1565 precache_model ("models/sprites/7.spr32");
1566 precache_model ("models/sprites/8.spr32");
1567 precache_model ("models/sprites/9.spr32");
1568 precache_model ("models/sprites/10.spr32");
1569 precache_sound ("announcer/robotic/1.wav");
1570 precache_sound ("announcer/robotic/2.wav");
1571 precache_sound ("announcer/robotic/3.wav");
1572 precache_sound ("announcer/robotic/4.wav");
1573 precache_sound ("announcer/robotic/5.wav");
1574 precache_sound ("announcer/robotic/6.wav");
1575 precache_sound ("announcer/robotic/7.wav");
1576 precache_sound ("announcer/robotic/8.wav");
1577 precache_sound ("announcer/robotic/9.wav");
1578 precache_sound ("announcer/robotic/10.wav");
1580 // common weapon precaches
1581 precache_sound ("weapons/weapon_switch.wav");
1582 precache_sound ("weapons/weaponpickup.wav");
1583 precache_sound ("weapons/unavailable.wav");
1584 if (g_grappling_hook)
1586 precache_sound ("weapons/hook_fire.wav"); // hook
1587 precache_sound ("weapons/hook_impact.wav"); // hook
1590 if (cvar("sv_precacheweapons") || g_nixnex)
1592 //precache weapon models/sounds
1595 while (wep <= WEP_LAST)
1597 weapon_action(wep, WR_PRECACHE);
1602 precache_model("models/elaser.mdl");
1603 precache_model("models/laser.mdl");
1604 precache_model("models/ebomb.mdl");
1607 // Disabled this code because it simply does not work (e.g. ignores bgmvolume, overlaps with "cd loop" controlled tracks).
1609 if (!self.noise && self.music) // quake 3 uses the music field
1610 self.noise = self.music;
1612 // plays music for the level if there is any
1615 precache_sound (self.noise);
1616 ambientsound ('0 0 0', self.noise, VOL_BASE, ATTN_NONE);
1621 // sorry, but using \ in macros breaks line numbers
1622 #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
1623 #define WRITESPECTATABLE_MSG_ONE(statement) WRITESPECTATABLE_MSG_ONE_VARNAME(oldmsg_entity, statement)
1624 #define WRITESPECTATABLE(msg,statement) if(msg == MSG_ONE) { WRITESPECTATABLE_MSG_ONE(statement); } else statement float WRITESPECTATABLE_workaround = 0
1626 vector ExactTriggerHit_mins;
1627 vector ExactTriggerHit_maxs;
1628 float ExactTriggerHit_Recurse()
1634 tracebox('0 0 0', ExactTriggerHit_mins, ExactTriggerHit_maxs, '0 0 0', MOVE_NORMAL, other);
1637 if (trace_ent == self)
1642 se.solid = SOLID_NOT;
1643 f = ExactTriggerHit_Recurse();
1649 float ExactTriggerHit()
1653 if not(self.modelindex)
1657 self.solid = SOLID_BSP;
1658 ExactTriggerHit_mins = other.absmin;
1659 ExactTriggerHit_maxs = other.absmax;
1660 f = ExactTriggerHit_Recurse();
1666 // WARNING: this kills the trace globals
1667 #define EXACTTRIGGER_TOUCH if not(ExactTriggerHit()) return
1668 #define EXACTTRIGGER_INIT InitSolidBSPTrigger(); self.solid = SOLID_TRIGGER
1670 #define INITPRIO_FIRST 0
1671 #define INITPRIO_GAMETYPE 0
1672 #define INITPRIO_GAMETYPE_FALLBACK 1
1673 #define INITPRIO_CVARS 5
1674 #define INITPRIO_FINDTARGET 10
1675 #define INITPRIO_DROPTOFLOOR 20
1676 #define INITPRIO_SETLOCATION 90
1677 #define INITPRIO_LINKDOORS 91
1678 #define INITPRIO_LAST 99
1680 .void(void) initialize_entity;
1681 .float initialize_entity_order;
1682 .entity initialize_entity_next;
1683 entity initialize_entity_first;
1685 void make_safe_for_remove(entity e)
1687 if (e.initialize_entity)
1690 for (ent = initialize_entity_first; ent; )
1692 if ((ent == e) || ((ent.classname == "initialize_entity") && (ent.enemy == e)))
1694 //print("make_safe_for_remove: getting rid of initializer ", etos(ent), "\n");
1695 // skip it in linked list
1698 prev.initialize_entity_next = ent.initialize_entity_next;
1699 ent = prev.initialize_entity_next;
1703 initialize_entity_first = ent.initialize_entity_next;
1704 ent = initialize_entity_first;
1710 ent = ent.initialize_entity_next;
1716 void objerror(string s)
1718 make_safe_for_remove(self);
1719 objerror_builtin(s);
1722 void remove_unsafely(entity e)
1727 void remove_safely(entity e)
1729 make_safe_for_remove(e);
1733 void InitializeEntity(entity e, void(void) func, float order)
1737 if (!e || e.initialize_entity)
1739 // make a proxy initializer entity
1743 e.classname = "initialize_entity";
1747 e.initialize_entity = func;
1748 e.initialize_entity_order = order;
1750 cur = initialize_entity_first;
1753 if (!cur || cur.initialize_entity_order > order)
1755 // insert between prev and cur
1757 prev.initialize_entity_next = e;
1759 initialize_entity_first = e;
1760 e.initialize_entity_next = cur;
1764 cur = cur.initialize_entity_next;
1767 void InitializeEntitiesRun()
1770 startoflist = initialize_entity_first;
1771 initialize_entity_first = world;
1772 for (self = startoflist; self; )
1775 var void(void) func;
1776 e = self.initialize_entity_next;
1777 func = self.initialize_entity;
1778 self.initialize_entity_order = 0;
1779 self.initialize_entity = func_null;
1780 self.initialize_entity_next = world;
1781 if (self.classname == "initialize_entity")
1785 remove_builtin(self);
1788 //dprint("Delayed initialization: ", self.classname, "\n");
1794 .float uncustomizeentityforclient_set;
1795 .void(void) uncustomizeentityforclient;
1796 void(void) SUB_Nullpointer = #0;
1797 void UncustomizeEntitiesRun()
1801 for (self = world; (self = findfloat(self, uncustomizeentityforclient_set, 1)); )
1802 self.uncustomizeentityforclient();
1805 void SetCustomizer(entity e, float(void) customizer, void(void) uncustomizer)
1807 e.customizeentityforclient = customizer;
1808 e.uncustomizeentityforclient = uncustomizer;
1809 e.uncustomizeentityforclient_set = (uncustomizer != SUB_Nullpointer);
1813 #define IFTARGETED if(!self.nottargeted && self.targetname != "")
1816 void Net_LinkEntity(entity e, float docull, float dt, float(entity, float) sendfunc)
1820 if (e.classname == "")
1821 e.classname = "net_linked";
1823 if (e.model == "" || self.modelindex == 0)
1827 setmodel(e, "null");
1831 e.SendEntity = sendfunc;
1832 e.SendFlags = 0xFFFFFF;
1835 e.effects |= EF_NODEPTHTEST;
1839 e.nextthink = time + dt;
1840 e.think = SUB_Remove;
1844 void adaptor_think2touch()
1853 void adaptor_think2use()
1865 // deferred dropping
1866 void DropToFloor_Handler()
1868 droptofloor_builtin();
1869 self.dropped_origin = self.origin;
1874 InitializeEntity(self, DropToFloor_Handler, INITPRIO_DROPTOFLOOR);
1879 float trace_hits_box_a0, trace_hits_box_a1;
1881 float trace_hits_box_1d(float end, float thmi, float thma)
1885 // just check if x is in range
1893 // do the trace with respect to x
1894 // 0 -> end has to stay in thmi -> thma
1895 trace_hits_box_a0 = max(trace_hits_box_a0, min(thmi / end, thma / end));
1896 trace_hits_box_a1 = min(trace_hits_box_a1, max(thmi / end, thma / end));
1897 if (trace_hits_box_a0 > trace_hits_box_a1)
1903 float trace_hits_box(vector start, vector end, vector thmi, vector thma)
1908 // now it is a trace from 0 to end
1910 trace_hits_box_a0 = 0;
1911 trace_hits_box_a1 = 1;
1913 if (!trace_hits_box_1d(end_x, thmi_x, thma_x))
1915 if (!trace_hits_box_1d(end_y, thmi_y, thma_y))
1917 if (!trace_hits_box_1d(end_z, thmi_z, thma_z))
1923 float tracebox_hits_box(vector start, vector mi, vector ma, vector end, vector thmi, vector thma)
1925 return trace_hits_box(start, end, thmi - ma, thma - mi);
1928 float SUB_NoImpactCheck()
1930 // zero hitcontents = this is not the real impact, but either the
1931 // mirror-impact of something hitting the projectile instead of the
1932 // projectile hitting the something, or a touchareagrid one. Neither of
1933 // these stop the projectile from moving, so...
1934 if(trace_dphitcontents == 0)
1936 dprint("A hit happened with zero hit contents... DEBUG THIS, this should never happen for projectiles! Projectile will self-destruct.\n");
1939 if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
1941 if (other == world && self.size != '0 0 0')
1944 tic = self.velocity * sys_ticrate;
1945 tic = tic + normalize(tic) * vlen(self.maxs - self.mins);
1946 traceline(self.origin - tic, self.origin + tic, MOVE_NORMAL, self);
1947 if (trace_fraction >= 1)
1949 dprint("Odd... did not hit...?\n");
1951 else if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
1953 dprint("Detected and prevented the sky-grapple bug.\n");
1961 #define SUB_OwnerCheck() (other && (other == self.owner))
1963 #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)
1965 float MAX_IPBAN_URIS = 16;
1967 float URI_GET_DISCARD = 0;
1968 float URI_GET_IPBAN = 1;
1969 float URI_GET_IPBAN_END = 16;
1971 void URI_Get_Callback(float id, float status, string data)
1973 dprint("Received HTTP request data for id ", ftos(id), "; status is ", ftos(status), "\nData is:\n");
1975 dprint("\nEnd of data.\n");
1977 if (id == URI_GET_DISCARD)
1981 else if (id >= URI_GET_IPBAN && id <= URI_GET_IPBAN_END)
1984 OnlineBanList_URI_Get_Callback(id, status, data);
1988 print("Received HTTP request data for an invalid id ", ftos(id), ".\n");
1992 void print_to(entity e, string s)
1995 sprint(e, strcat(s, "\n"));
2014 for (i = 0; i < MapInfo_count; ++i)
2016 if (MapInfo_Get_ByID(i))
2018 r = stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, "/captimerecord/time")));
2021 h = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, "/captimerecord/netname"));
2022 s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-6, ftos_decimals(r, 2)), " ", h, "\n");
2030 for (i = 0; i < MapInfo_count; ++i)
2032 if (MapInfo_Get_ByID(i))
2034 r = stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, RACE_RECORD, "time")));
2037 h = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, RACE_RECORD, "netname"));
2038 s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-8, TIME_ENCODED_TOSTRING(r)), " ", h, "\n");
2046 for (i = 0; i < MapInfo_count; ++i)
2048 if (MapInfo_Get_ByID(i))
2050 r = stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, CTS_RECORD, "time")));
2053 h = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, CTS_RECORD, "netname"));
2054 s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-8, TIME_ENCODED_TOSTRING(r)), " ", h, "\n");
2060 MapInfo_ClearTemps();
2063 return "No records are available on this server.\n";
2065 return strcat("Records on this server:\n", s);
2068 float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
2071 vector start, org, delta, end, enddown, mstart;
2073 m = e.dphitcontentsmask;
2074 e.dphitcontentsmask = goodcontents | badcontents;
2077 delta = world.maxs - world.mins;
2079 for (i = 0; i < attempts; ++i)
2081 start_x = org_x + random() * delta_x;
2082 start_y = org_y + random() * delta_y;
2083 start_z = org_z + random() * delta_z;
2085 // rule 1: start inside world bounds, and outside
2086 // solid, and don't start from somewhere where you can
2087 // fall down to evil
2088 tracebox(start, e.mins, e.maxs, start - '0 0 1' * delta_z, MOVE_NORMAL, e);
2089 if (trace_fraction >= 1)
2091 if (trace_startsolid)
2093 if (trace_dphitcontents & badcontents)
2095 if (trace_dphitq3surfaceflags & badsurfaceflags)
2098 // rule 2: if we are too high, lower the point
2099 if (trace_fraction * delta_z > maxaboveground)
2100 start = trace_endpos + '0 0 1' * maxaboveground;
2101 enddown = trace_endpos;
2103 // rule 3: make sure we aren't outside the map. This only works
2104 // for somewhat well formed maps. A good rule of thumb is that
2105 // the map should have a convex outside hull.
2106 // these can be traceLINES as we already verified the starting box
2107 mstart = start + 0.5 * (e.mins + e.maxs);
2108 traceline(mstart, mstart + '1 0 0' * delta_x, MOVE_NORMAL, e);
2109 if (trace_fraction >= 1)
2111 traceline(mstart, mstart - '1 0 0' * delta_x, MOVE_NORMAL, e);
2112 if (trace_fraction >= 1)
2114 traceline(mstart, mstart + '0 1 0' * delta_y, 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 0 1' * delta_z, MOVE_NORMAL, e);
2121 if (trace_fraction >= 1)
2124 // find a random vector to "look at"
2125 end_x = org_x + random() * delta_x;
2126 end_y = org_y + random() * delta_y;
2127 end_z = org_z + random() * delta_z;
2128 end = start + normalize(end - start) * vlen(delta);
2130 // rule 4: start TO end must not be too short
2131 tracebox(start, e.mins, e.maxs, end, MOVE_NORMAL, e);
2132 if (trace_startsolid)
2134 if (trace_fraction < minviewdistance / vlen(delta))
2137 // rule 5: don't want to look at sky
2138 if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
2141 // rule 6: we must not end up in trigger_hurt
2142 if (tracebox_hits_trigger_hurt(start, e.mins, e.maxs, enddown))
2144 dprint("trigger_hurt! ouch! and nothing else could find it!\n");
2151 e.dphitcontentsmask = m;
2155 setorigin(e, start);
2156 e.angles = vectoangles(end - start);
2157 dprint("Needed ", ftos(i + 1), " attempts\n");
2164 float zcurveparticles_effectno;
2165 vector zcurveparticles_start;
2166 float zcurveparticles_spd;
2168 void endzcurveparticles()
2170 if(zcurveparticles_effectno)
2173 WriteShort(MSG_BROADCAST, zcurveparticles_spd | 0x8000);
2175 zcurveparticles_effectno = 0;
2178 void zcurveparticles(float effectno, vector start, vector end, float end_dz, float spd)
2180 spd = bound(0, floor(spd / 16), 32767);
2181 if(effectno != zcurveparticles_effectno || start != zcurveparticles_start)
2183 endzcurveparticles();
2184 WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
2185 WriteByte(MSG_BROADCAST, TE_CSQC_ZCURVEPARTICLES);
2186 WriteShort(MSG_BROADCAST, effectno);
2187 WriteCoord(MSG_BROADCAST, start_x);
2188 WriteCoord(MSG_BROADCAST, start_y);
2189 WriteCoord(MSG_BROADCAST, start_z);
2190 zcurveparticles_effectno = effectno;
2191 zcurveparticles_start = start;
2194 WriteShort(MSG_BROADCAST, zcurveparticles_spd);
2195 WriteCoord(MSG_BROADCAST, end_x);
2196 WriteCoord(MSG_BROADCAST, end_y);
2197 WriteCoord(MSG_BROADCAST, end_z);
2198 WriteCoord(MSG_BROADCAST, end_dz);
2199 zcurveparticles_spd = spd;
2202 void zcurveparticles_from_tracetoss(float effectno, vector start, vector end, vector vel)
2205 vector vecxy, velxy;
2207 vecxy = end - start;
2212 if (vlen(velxy) < 0.000001 * fabs(vel_z))
2214 endzcurveparticles();
2215 trailparticles(world, effectno, start, end);
2219 end_dz = vlen(vecxy) / vlen(velxy) * vel_z - (end_z - start_z);
2220 zcurveparticles(effectno, start, end, end_dz, vlen(vel));
2223 string GetGametype(); // g_world.qc
2224 void write_recordmarker(entity pl, float tstart, float dt)
2226 GameLogEcho(strcat(":recordset:", ftos(pl.playerid), ":", ftos(dt)));
2228 // also write a marker into demo files for demotc-race-record-extractor to find
2231 strcat("//", strconv(2, 0, 0, GetGametype()), " RECORD SET ", TIME_ENCODED_TOSTRING(TIME_ENCODE(dt))),
2232 " ", ftos(tstart), " ", ftos(dt), "\n"));
2235 vector shotorg_adjustfromclient(vector vecs, float y_is_right, float allowcenter)
2237 switch(self.owner.cvar_cl_gunalign)
2248 if(allowcenter) // 2: allow center handedness
2261 if(allowcenter) // 2: allow center handedness
2277 vector shotorg_adjust(vector vecs, float y_is_right, float visual)
2282 if (cvar("g_shootfromeye"))
2286 vecs = shotorg_adjustfromclient(vecs, y_is_right, TRUE);
2294 else if (cvar("g_shootfromcenter"))
2298 vecs = shotorg_adjustfromclient(vecs, y_is_right, TRUE);
2306 else if (cvar("g_shootfromclient"))
2308 vecs = shotorg_adjustfromclient(vecs, y_is_right, (cvar("g_shootfromclient") >= 2));
2310 else if ((s = cvar_string("g_shootfromfixedorigin")) != "")
2325 void attach_sameorigin(entity e, entity to, string tag)
2327 vector org, t_forward, t_left, t_up, e_forward, e_up;
2334 org = e.origin - gettaginfo(to, gettagindex(to, tag));
2335 tagscale = pow(vlen(v_forward), -2); // undo a scale on the tag
2336 t_forward = v_forward * tagscale;
2337 t_left = v_right * -tagscale;
2338 t_up = v_up * tagscale;
2340 e.origin_x = org * t_forward;
2341 e.origin_y = org * t_left;
2342 e.origin_z = org * t_up;
2344 // current forward and up directions
2345 if (substring(e.model, 0, 1) == "*") // bmodels have their own rules
2346 e.angles_x = -e.angles_x;
2347 fixedmakevectors(e.angles);
2349 // untransform forward, up!
2350 e_forward_x = v_forward * t_forward;
2351 e_forward_y = v_forward * t_left;
2352 e_forward_z = v_forward * t_up;
2353 e_up_x = v_up * t_forward;
2354 e_up_y = v_up * t_left;
2355 e_up_z = v_up * t_up;
2357 e.angles = fixedvectoangles2(e_forward, e_up);
2358 if (substring(e.model, 0, 1) == "*") // bmodels have their own rules
2359 e.angles_x = -e.angles_x;
2361 setattachment(e, to, tag);
2362 setorigin(e, e.origin);
2365 void detach_sameorigin(entity e)
2368 org = gettaginfo(e, 0);
2369 e.angles = fixedvectoangles2(v_forward, v_up);
2370 if (substring(e.model, 0, 1) == "*") // bmodels have their own rules
2371 e.angles_x = -e.angles_x;
2373 setattachment(e, world, "");
2374 setorigin(e, e.origin);
2377 void follow_sameorigin(entity e, entity to)
2379 e.movetype = MOVETYPE_FOLLOW; // make the hole follow
2380 e.aiment = to; // make the hole follow bmodel
2381 e.punchangle = to.angles; // the original angles of bmodel
2382 e.view_ofs = e.origin - to.origin; // relative origin
2383 e.v_angle = e.angles - to.angles; // relative angles
2386 void unfollow_sameorigin(entity e)
2388 e.movetype = MOVETYPE_NONE;
2391 entity gettaginfo_relative_ent;
2392 vector gettaginfo_relative(entity e, float tag)
2394 if (!gettaginfo_relative_ent)
2396 gettaginfo_relative_ent = spawn();
2397 gettaginfo_relative_ent.effects = EF_NODRAW;
2399 gettaginfo_relative_ent.model = e.model;
2400 gettaginfo_relative_ent.modelindex = e.modelindex;
2401 gettaginfo_relative_ent.frame = e.frame;
2402 return gettaginfo(gettaginfo_relative_ent, tag);
2405 void SoundEntity_StartSound(entity pl, float chan, string samp, float vol, float attn)
2409 if (pl.soundentity.cnt & p)
2411 soundtoat(MSG_ALL, pl.soundentity, gettaginfo(pl.soundentity, 0), chan, samp, vol, attn);
2412 pl.soundentity.cnt |= p;
2415 void SoundEntity_StopSound(entity pl, float chan)
2419 if (pl.soundentity.cnt & p)
2421 stopsoundto(MSG_ALL, pl.soundentity, chan);
2422 pl.soundentity.cnt &~= p;
2426 void SoundEntity_Attach(entity pl)
2428 pl.soundentity = spawn();
2429 pl.soundentity.classname = "soundentity";
2430 pl.soundentity.owner = pl;
2431 setattachment(pl.soundentity, pl, "");
2432 setmodel(pl.soundentity, "null");
2435 void SoundEntity_Detach(entity pl)
2438 for (i = 0; i <= 7; ++i)
2439 SoundEntity_StopSound(pl, i);
2443 float ParseCommandPlayerSlotTarget_firsttoken;
2444 entity GetCommandPlayerSlotTargetFromTokenizedCommand(float tokens, float idx) // idx = start index
2452 ParseCommandPlayerSlotTarget_firsttoken = -1;
2456 if (substring(argv(idx), 0, 1) == "#")
2458 s = substring(argv(idx), 1, -1);
2466 ParseCommandPlayerSlotTarget_firsttoken = idx;
2467 if (s == ftos(stof(s)))
2469 e = edict_num(stof(s));
2470 if (e.flags & FL_CLIENT)
2476 // it must be a nick name
2479 ParseCommandPlayerSlotTarget_firsttoken = idx;
2482 FOR_EACH_CLIENT(head)
2483 if (head.netname == s)
2491 s = strdecolorize(s);
2493 FOR_EACH_CLIENT(head)
2494 if (strdecolorize(head.netname) == s)
2509 float modeleffect_SendEntity(entity to, float sf)
2512 WriteByte(MSG_ENTITY, ENT_CLIENT_MODELEFFECT);
2515 if(self.velocity != '0 0 0')
2517 if(self.angles != '0 0 0')
2519 if(self.avelocity != '0 0 0')
2522 WriteByte(MSG_ENTITY, f);
2523 WriteShort(MSG_ENTITY, self.modelindex);
2524 WriteByte(MSG_ENTITY, self.skin);
2525 WriteByte(MSG_ENTITY, self.frame);
2526 WriteCoord(MSG_ENTITY, self.origin_x);
2527 WriteCoord(MSG_ENTITY, self.origin_y);
2528 WriteCoord(MSG_ENTITY, self.origin_z);
2531 WriteCoord(MSG_ENTITY, self.velocity_x);
2532 WriteCoord(MSG_ENTITY, self.velocity_y);
2533 WriteCoord(MSG_ENTITY, self.velocity_z);
2537 WriteCoord(MSG_ENTITY, self.angles_x);
2538 WriteCoord(MSG_ENTITY, self.angles_y);
2539 WriteCoord(MSG_ENTITY, self.angles_z);
2543 WriteCoord(MSG_ENTITY, self.avelocity_x);
2544 WriteCoord(MSG_ENTITY, self.avelocity_y);
2545 WriteCoord(MSG_ENTITY, self.avelocity_z);
2547 WriteShort(MSG_ENTITY, self.scale * 256.0);
2548 WriteShort(MSG_ENTITY, self.scale2 * 256.0);
2549 WriteByte(MSG_ENTITY, self.teleport_time * 100.0);
2550 WriteByte(MSG_ENTITY, self.fade_time * 100.0);
2551 WriteByte(MSG_ENTITY, self.alpha * 255.0);
2556 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)
2561 e.classname = "modeleffect";
2569 e.teleport_time = t1;
2573 e.scale = s0 / max6(-e.mins_x, -e.mins_y, -e.mins_z, e.maxs_x, e.maxs_y, e.maxs_z);
2577 e.scale2 = s2 / max6(-e.mins_x, -e.mins_y, -e.mins_z, e.maxs_x, e.maxs_y, e.maxs_z);
2580 sz = max(e.scale, e.scale2);
2581 setsize(e, e.mins * sz, e.maxs * sz);
2582 Net_LinkEntity(e, FALSE, 0.1, modeleffect_SendEntity);
2585 void shockwave_spawn(string m, vector org, float sz, float t1, float t2)
2587 return modeleffect_spawn(m, 0, 0, org, '0 0 0', '0 0 0', '0 0 0', 0, sz, 1, t1, t2);
2590 float randombit(float bits)
2592 if not(bits & (bits-1)) // this ONLY holds for powers of two!
2601 for(f = 1; f <= bits; f *= 2)
2610 r = (r - 1) / (n - 1);
2617 float randombits(float bits, float k, float error_return)
2621 while(k > 0 && bits != r)
2623 r += randombit(bits - r);
2632 void randombit_test(float bits, float iter)
2636 print(ftos(randombit(bits)), "\n");
2641 float ExponentialFalloff(float mindist, float maxdist, float halflifedist, float d)
2643 if(halflifedist > 0)
2644 return pow(0.5, (bound(mindist, d, maxdist) - mindist) / halflifedist);
2645 else if(halflifedist < 0)
2646 return pow(0.5, (bound(mindist, d, maxdist) - maxdist) / halflifedist);