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 e.origin = 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 string g_weaponarena_list;
729 float g_weaponspeedfactor;
730 float g_weaponratefactor;
731 float g_weapondamagefactor;
732 float g_weaponforcefactor;
736 float start_ammo_shells;
737 float start_ammo_nails;
738 float start_ammo_rockets;
739 float start_ammo_cells;
740 float start_ammo_fuel;
742 float start_armorvalue;
743 float warmup_start_weapons;
744 float warmup_start_ammo_shells;
745 float warmup_start_ammo_nails;
746 float warmup_start_ammo_rockets;
747 float warmup_start_ammo_cells;
748 float warmup_start_ammo_fuel;
749 float warmup_start_health;
750 float warmup_start_armorvalue;
753 entity get_weaponinfo(float w);
755 float NixNex_CanChooseWeapon(float wpn);
756 void readplayerstartcvars()
762 // initialize starting values for players
765 start_ammo_shells = 0;
766 start_ammo_nails = 0;
767 start_ammo_rockets = 0;
768 start_ammo_cells = 0;
769 start_health = cvar("g_balance_health_start");
770 start_armorvalue = cvar("g_balance_armor_start");
773 s = cvar_string("g_weaponarena");
779 g_weaponarena_list = "All Weapons";
780 for (j = WEP_FIRST; j <= WEP_LAST; ++j)
782 e = get_weaponinfo(j);
783 g_weaponarena |= e.weapons;
784 weapon_action(e.weapon, WR_PRECACHE);
787 else if (s == "most")
789 g_weaponarena_list = "Most Weapons";
790 for (j = WEP_FIRST; j <= WEP_LAST; ++j)
792 e = get_weaponinfo(j);
793 if (e.spawnflags & WEPSPAWNFLAG_NORMAL)
795 g_weaponarena |= e.weapons;
796 weapon_action(e.weapon, WR_PRECACHE);
800 else if (s == "none")
802 g_weaponarena_list = "No Weapons";
803 g_weaponarena = WEPBIT_ALL + 1; // this supports no single weapon bit!
807 t = tokenize_console(s);
808 g_weaponarena_list = "";
809 for (i = 0; i < t; ++i)
812 for (j = WEP_FIRST; j <= WEP_LAST; ++j)
814 e = get_weaponinfo(j);
817 g_weaponarena |= e.weapons;
818 weapon_action(e.weapon, WR_PRECACHE);
819 g_weaponarena_list = strcat(g_weaponarena_list, e.message, " & ");
825 print("The weapon mutator list contains an unknown weapon ", s, ". Skipped.\n");
828 g_weaponarena_list = strzone(substring(g_weaponarena_list, 0, strlen(g_weaponarena_list) - 3));
834 // will be done later
835 for (i = WEP_FIRST; i <= WEP_LAST; ++i)
836 if (NixNex_CanChooseWeapon(i))
837 weapon_action(i, WR_PRECACHE);
838 if(!cvar("g_use_ammunition"))
839 start_items |= IT_UNLIMITED_AMMO;
841 else if (g_weaponarena)
843 start_weapons = g_weaponarena;
844 if (g_weaponarena & (WEPBIT_GRENADE_LAUNCHER | WEPBIT_HAGAR | WEPBIT_ROCKET_LAUNCHER))
845 start_ammo_rockets = 999;
846 if (g_weaponarena & WEPBIT_SHOTGUN)
847 start_ammo_shells = 999;
848 if (g_weaponarena & (WEPBIT_ELECTRO | WEPBIT_CRYLINK | WEPBIT_NEX | WEPBIT_MINSTANEX | WEPBIT_HLAC | WEPBIT_HOOK))
849 start_ammo_cells = 999;
850 if (g_weaponarena & (WEPBIT_UZI | WEPBIT_CAMPINGRIFLE))
851 start_ammo_nails = 999;
852 if (g_weaponarena & WEPBIT_HOOK)
853 start_ammo_fuel = 999;
854 start_items |= IT_UNLIMITED_AMMO;
856 else if (g_minstagib)
859 start_armorvalue = 0;
860 start_weapons = WEPBIT_MINSTANEX;
861 weapon_action(WEP_MINSTANEX, WR_PRECACHE);
862 start_ammo_cells = cvar("g_minstagib_ammo_start");
863 g_minstagib_invis_alpha = cvar("g_minstagib_invis_alpha");
864 start_ammo_fuel = cvar("g_start_ammo_fuel");
866 if (g_minstagib_invis_alpha <= 0)
867 g_minstagib_invis_alpha = -1;
873 start_ammo_shells = cvar("g_lms_start_ammo_shells");
874 start_ammo_nails = cvar("g_lms_start_ammo_nails");
875 start_ammo_rockets = cvar("g_lms_start_ammo_rockets");
876 start_ammo_cells = cvar("g_lms_start_ammo_cells");
877 start_ammo_fuel = cvar("g_lms_start_ammo_fuel");
878 start_health = cvar("g_lms_start_health");
879 start_armorvalue = cvar("g_lms_start_armor");
881 else if (cvar("g_use_ammunition"))
883 start_ammo_shells = cvar("g_start_ammo_shells");
884 start_ammo_nails = cvar("g_start_ammo_nails");
885 start_ammo_rockets = cvar("g_start_ammo_rockets");
886 start_ammo_cells = cvar("g_start_ammo_cells");
887 start_ammo_fuel = cvar("g_start_ammo_fuel");
891 start_ammo_shells = cvar("g_pickup_shells_max");
892 start_ammo_nails = cvar("g_pickup_nails_max");
893 start_ammo_rockets = cvar("g_pickup_rockets_max");
894 start_ammo_cells = cvar("g_pickup_cells_max");
895 start_ammo_fuel = cvar("g_pickup_fuel_max");
896 start_items |= IT_UNLIMITED_AMMO;
899 for (i = WEP_FIRST; i <= WEP_LAST; ++i)
901 e = get_weaponinfo(i);
905 t = cvar(strcat("g_start_weapon_", e.netname));
907 if (t < 0) // "default" weapon selection
910 t = (e.spawnflags & WEPSPAWNFLAG_NORMAL);
911 else if (g_race || g_cts)
912 t = (i == WEP_LASER);
914 t = 0; // weapon is set a few lines later
916 t = (i == WEP_LASER || i == WEP_SHOTGUN);
917 if (g_grappling_hook) // if possible, redirect off-hand hook to on-hand hook
918 t += (i == WEP_HOOK);
921 if (g_nexball && i == WEP_PORTO)
926 start_weapons |= e.weapons;
927 weapon_action(e.weapon, WR_PRECACHE);
934 warmup_start_ammo_shells = start_ammo_shells;
935 warmup_start_ammo_nails = start_ammo_nails;
936 warmup_start_ammo_rockets = start_ammo_rockets;
937 warmup_start_ammo_cells = start_ammo_cells;
938 warmup_start_health = start_health;
939 warmup_start_armorvalue = start_armorvalue;
940 warmup_start_weapons = start_weapons;
942 if (!g_weaponarena && !g_nixnex && !g_minstagib)
944 if (cvar("g_use_ammunition"))
946 warmup_start_ammo_shells = cvar("g_warmup_start_ammo_shells");
947 warmup_start_ammo_cells = cvar("g_warmup_start_ammo_cells");
948 warmup_start_ammo_nails = cvar("g_warmup_start_ammo_nails");
949 warmup_start_ammo_rockets = cvar("g_warmup_start_ammo_rockets");
951 warmup_start_health = cvar("g_warmup_start_health");
952 warmup_start_armorvalue = cvar("g_warmup_start_armor");
953 if (cvar("g_warmup_allguns"))
955 for (i = WEP_FIRST; i <= WEP_LAST; ++i)
957 e = get_weaponinfo(i);
960 if (e.spawnflags & WEPSPAWNFLAG_NORMAL)
962 warmup_start_weapons |= e.weapons;
963 weapon_action(e.weapon, WR_PRECACHE);
970 if (g_jetpack || (g_grappling_hook && (start_weapons & WEPBIT_HOOK)))
972 g_grappling_hook = 0; // these two can't coexist, as they use the same button
973 start_items |= IT_FUEL_REGEN;
974 start_ammo_fuel = max(start_ammo_fuel, cvar("g_balance_fuel_rotstable"));
978 start_items |= IT_JETPACK;
980 if (g_weapon_stay == 2)
982 if (!start_ammo_shells) start_ammo_shells = g_pickup_shells;
983 if (!start_ammo_nails) start_ammo_nails = g_pickup_nails;
984 if (!start_ammo_cells) start_ammo_cells = g_pickup_cells;
985 if (!start_ammo_rockets) start_ammo_rockets = g_pickup_rockets;
986 if (!start_ammo_fuel) start_ammo_fuel = g_pickup_fuel;
987 if (!warmup_start_ammo_shells) warmup_start_ammo_shells = g_pickup_shells;
988 if (!warmup_start_ammo_nails) warmup_start_ammo_nails = g_pickup_nails;
989 if (!warmup_start_ammo_cells) warmup_start_ammo_cells = g_pickup_cells;
990 if (!warmup_start_ammo_rockets) warmup_start_ammo_rockets = g_pickup_rockets;
991 if (!warmup_start_ammo_fuel) warmup_start_ammo_fuel = g_pickup_fuel;
994 start_ammo_shells = max(0, start_ammo_shells);
995 start_ammo_nails = max(0, start_ammo_nails);
996 start_ammo_cells = max(0, start_ammo_cells);
997 start_ammo_rockets = max(0, start_ammo_rockets);
998 start_ammo_fuel = max(0, start_ammo_fuel);
1000 warmup_start_ammo_shells = max(0, warmup_start_ammo_shells);
1001 warmup_start_ammo_nails = max(0, warmup_start_ammo_nails);
1002 warmup_start_ammo_cells = max(0, warmup_start_ammo_cells);
1003 warmup_start_ammo_rockets = max(0, warmup_start_ammo_rockets);
1004 warmup_start_ammo_fuel = max(0, warmup_start_ammo_fuel);
1008 float g_bugrigs_planar_movement;
1009 float g_bugrigs_planar_movement_car_jumping;
1010 float g_bugrigs_reverse_spinning;
1011 float g_bugrigs_reverse_speeding;
1012 float g_bugrigs_reverse_stopping;
1013 float g_bugrigs_air_steering;
1014 float g_bugrigs_angle_smoothing;
1015 float g_bugrigs_friction_floor;
1016 float g_bugrigs_friction_brake;
1017 float g_bugrigs_friction_air;
1018 float g_bugrigs_accel;
1019 float g_bugrigs_speed_ref;
1020 float g_bugrigs_speed_pow;
1021 float g_bugrigs_steer;
1023 float g_touchexplode;
1024 float g_touchexplode_radius;
1025 float g_touchexplode_damage;
1026 float g_touchexplode_edgedamage;
1027 float g_touchexplode_force;
1032 void readlevelcvars(void)
1034 g_bugrigs = cvar("g_bugrigs");
1035 g_bugrigs_planar_movement = cvar("g_bugrigs_planar_movement");
1036 g_bugrigs_planar_movement_car_jumping = cvar("g_bugrigs_planar_movement_car_jumping");
1037 g_bugrigs_reverse_spinning = cvar("g_bugrigs_reverse_spinning");
1038 g_bugrigs_reverse_speeding = cvar("g_bugrigs_reverse_speeding");
1039 g_bugrigs_reverse_stopping = cvar("g_bugrigs_reverse_stopping");
1040 g_bugrigs_air_steering = cvar("g_bugrigs_air_steering");
1041 g_bugrigs_angle_smoothing = cvar("g_bugrigs_angle_smoothing");
1042 g_bugrigs_friction_floor = cvar("g_bugrigs_friction_floor");
1043 g_bugrigs_friction_brake = cvar("g_bugrigs_friction_brake");
1044 g_bugrigs_friction_air = cvar("g_bugrigs_friction_air");
1045 g_bugrigs_accel = cvar("g_bugrigs_accel");
1046 g_bugrigs_speed_ref = cvar("g_bugrigs_speed_ref");
1047 g_bugrigs_speed_pow = cvar("g_bugrigs_speed_pow");
1048 g_bugrigs_steer = cvar("g_bugrigs_steer");
1050 g_touchexplode = cvar("g_touchexplode");
1051 g_touchexplode_radius = cvar("g_touchexplode_radius");
1052 g_touchexplode_damage = cvar("g_touchexplode_damage");
1053 g_touchexplode_edgedamage = cvar("g_touchexplode_edgedamage");
1054 g_touchexplode_force = cvar("g_touchexplode_force");
1056 #ifdef ALLOW_FORCEMODELS
1057 sv_clforceplayermodels = cvar("sv_clforceplayermodels");
1059 sv_loddistance1 = cvar("sv_loddistance1");
1060 sv_loddistance2 = cvar("sv_loddistance2");
1061 if(sv_loddistance2 <= sv_loddistance1)
1062 sv_loddistance2 = 1073741824; // enough to turn off LOD 2 reliably
1063 sv_clones = cvar("sv_clones");
1064 sv_cheats = cvar("sv_cheats");
1065 sv_gentle = cvar("sv_gentle");
1066 sv_foginterval = cvar("sv_foginterval");
1067 g_cloaked = cvar("g_cloaked");
1068 g_jump_grunt = cvar("g_jump_grunt");
1069 g_footsteps = cvar("g_footsteps");
1070 g_grappling_hook = cvar("g_grappling_hook");
1071 g_jetpack = cvar("g_jetpack");
1072 g_laserguided_missile = cvar("g_laserguided_missile");
1073 g_midair = cvar("g_midair");
1074 g_minstagib = cvar("g_minstagib");
1075 g_nixnex = cvar("g_nixnex");
1076 g_nixnex_with_laser = cvar("g_nixnex_with_laser");
1077 g_norecoil = cvar("g_norecoil");
1078 g_vampire = cvar("g_vampire");
1079 g_bloodloss = cvar("g_bloodloss");
1080 sv_maxidle = cvar("sv_maxidle");
1081 sv_maxidle_spectatorsareidle = cvar("sv_maxidle_spectatorsareidle");
1082 sv_pogostick = cvar("sv_pogostick");
1083 sv_doublejump = cvar("sv_doublejump");
1084 g_ctf_reverse = cvar("g_ctf_reverse");
1085 sv_autotaunt = cvar("sv_autotaunt");
1086 sv_taunt = cvar("sv_taunt");
1088 inWarmupStage = cvar("g_warmup");
1089 g_warmup_limit = cvar("g_warmup_limit");
1090 g_warmup_allguns = cvar("g_warmup_allguns");
1091 g_warmup_allow_timeout = cvar("g_warmup_allow_timeout");
1093 if ((g_race && g_race_qualifying == 2) || g_runematch || g_arena || g_assault || cvar("g_campaign"))
1094 inWarmupStage = 0; // these modes cannot work together, sorry
1096 g_pickup_respawntime_weapon = cvar("g_pickup_respawntime_weapon");
1097 g_pickup_respawntime_ammo = cvar("g_pickup_respawntime_ammo");
1098 g_pickup_respawntime_short = cvar("g_pickup_respawntime_short");
1099 g_pickup_respawntime_medium = cvar("g_pickup_respawntime_medium");
1100 g_pickup_respawntime_long = cvar("g_pickup_respawntime_long");
1101 g_pickup_respawntime_powerup = cvar("g_pickup_respawntime_powerup");
1102 g_pickup_respawntimejitter_weapon = cvar("g_pickup_respawntimejitter_weapon");
1103 g_pickup_respawntimejitter_ammo = cvar("g_pickup_respawntimejitter_ammo");
1104 g_pickup_respawntimejitter_short = cvar("g_pickup_respawntimejitter_short");
1105 g_pickup_respawntimejitter_medium = cvar("g_pickup_respawntimejitter_medium");
1106 g_pickup_respawntimejitter_long = cvar("g_pickup_respawntimejitter_long");
1107 g_pickup_respawntimejitter_powerup = cvar("g_pickup_respawntimejitter_powerup");
1109 if (g_minstagib) g_nixnex = g_weaponarena = 0;
1110 if (g_nixnex) g_weaponarena = 0;
1113 g_weaponspeedfactor = cvar("g_weaponspeedfactor");
1114 g_weaponratefactor = cvar("g_weaponratefactor");
1115 g_weapondamagefactor = cvar("g_weapondamagefactor");
1116 g_weaponforcefactor = cvar("g_weaponforcefactor");
1118 g_pickup_shells = cvar("g_pickup_shells");
1119 g_pickup_shells_max = cvar("g_pickup_shells_max");
1120 g_pickup_nails = cvar("g_pickup_nails");
1121 g_pickup_nails_max = cvar("g_pickup_nails_max");
1122 g_pickup_rockets = cvar("g_pickup_rockets");
1123 g_pickup_rockets_max = cvar("g_pickup_rockets_max");
1124 g_pickup_cells = cvar("g_pickup_cells");
1125 g_pickup_cells_max = cvar("g_pickup_cells_max");
1126 g_pickup_fuel = cvar("g_pickup_fuel");
1127 g_pickup_fuel_jetpack = cvar("g_pickup_fuel_jetpack");
1128 g_pickup_fuel_max = cvar("g_pickup_fuel_max");
1129 g_pickup_armorsmall = cvar("g_pickup_armorsmall");
1130 g_pickup_armorsmall_max = cvar("g_pickup_armorsmall_max");
1131 g_pickup_armormedium = cvar("g_pickup_armormedium");
1132 g_pickup_armormedium_max = cvar("g_pickup_armormedium_max");
1133 g_pickup_armorbig = cvar("g_pickup_armorbig");
1134 g_pickup_armorbig_max = cvar("g_pickup_armorbig_max");
1135 g_pickup_armorlarge = cvar("g_pickup_armorlarge");
1136 g_pickup_armorlarge_max = cvar("g_pickup_armorlarge_max");
1137 g_pickup_healthsmall = cvar("g_pickup_healthsmall");
1138 g_pickup_healthsmall_max = cvar("g_pickup_healthsmall_max");
1139 g_pickup_healthmedium = cvar("g_pickup_healthmedium");
1140 g_pickup_healthmedium_max = cvar("g_pickup_healthmedium_max");
1141 g_pickup_healthlarge = cvar("g_pickup_healthlarge");
1142 g_pickup_healthlarge_max = cvar("g_pickup_healthlarge_max");
1143 g_pickup_healthmega = cvar("g_pickup_healthmega");
1144 g_pickup_healthmega_max = cvar("g_pickup_healthmega_max");
1146 g_pinata = cvar("g_pinata");
1148 g_weapon_stay = cvar("g_weapon_stay");
1149 if (!g_weapon_stay && (cvar("deathmatch") == 2))
1152 if not(inWarmupStage)
1153 game_starttime = cvar("g_start_delay");
1155 readplayerstartcvars();
1159 // TODO sound pack system
1162 string precache_sound_builtin (string s) = #19;
1163 void(entity e, float chan, string samp, float vol, float atten) sound_builtin = #8;
1164 string precache_sound(string s)
1166 return precache_sound_builtin(strcat(soundpack, s));
1168 void play2(entity e, string filename)
1170 stuffcmd(e, strcat("play2 ", soundpack, filename, "\n"));
1172 void sound(entity e, float chan, string samp, float vol, float atten)
1174 sound_builtin(e, chan, strcat(soundpack, samp), vol, atten);
1179 string precache_sound (string s) = #19;
1180 void(entity e, float chan, string samp, float vol, float atten) sound_builtin = #8;
1181 float precache_sound_index (string s) = #19;
1183 #define SND_VOLUME 1
1184 #define SND_ATTENUATION 2
1185 #define SND_LARGEENTITY 8
1186 #define SND_LARGESOUND 16
1188 float sound_allowed(float dest, entity e)
1190 // sounds from world may always pass
1193 if (e.classname == "body")
1195 if (e.owner && e.owner != e)
1200 // sounds to self may always pass
1201 if (dest == MSG_ONE)
1202 if (e == msg_entity)
1204 // sounds by players can be removed
1205 if (cvar("bot_sound_monopoly"))
1206 if (clienttype(e) == CLIENTTYPE_REAL)
1208 // anything else may pass
1212 void sound(entity e, float chan, string samp, float vol, float atten)
1214 if (!sound_allowed(MSG_BROADCAST, e))
1216 sound_builtin(e, chan, samp, vol, atten);
1218 void soundtoat(float dest, entity e, vector o, float chan, string samp, float vol, float atten)
1222 if (!sound_allowed(dest, e))
1225 entno = num_for_edict(e);
1226 idx = precache_sound_index(samp);
1231 atten = floor(atten * 64);
1232 vol = floor(vol * 255);
1235 sflags |= SND_VOLUME;
1237 sflags |= SND_ATTENUATION;
1239 sflags |= SND_LARGEENTITY;
1241 sflags |= SND_LARGESOUND;
1243 WriteByte(dest, SVC_SOUND);
1244 WriteByte(dest, sflags);
1245 if (sflags & SND_VOLUME)
1246 WriteByte(dest, vol);
1247 if (sflags & SND_ATTENUATION)
1248 WriteByte(dest, atten);
1249 if (sflags & SND_LARGEENTITY)
1251 WriteShort(dest, entno);
1252 WriteByte(dest, chan);
1256 WriteShort(dest, entno * 8 + chan);
1258 if (sflags & SND_LARGESOUND)
1259 WriteShort(dest, idx);
1261 WriteByte(dest, idx);
1263 WriteCoord(dest, o_x);
1264 WriteCoord(dest, o_y);
1265 WriteCoord(dest, o_z);
1267 void soundto(float dest, entity e, float chan, string samp, float vol, float atten)
1271 if (!sound_allowed(dest, e))
1274 o = e.origin + 0.5 * (e.mins + e.maxs);
1275 soundtoat(dest, e, o, chan, samp, vol, atten);
1277 void soundat(entity e, vector o, float chan, string samp, float vol, float atten)
1279 soundtoat(MSG_BROADCAST, e, o, chan, samp, vol, atten);
1281 void stopsoundto(float dest, entity e, float chan)
1285 if (!sound_allowed(dest, e))
1288 entno = num_for_edict(e);
1293 idx = precache_sound_index("misc/null.wav");
1294 sflags = SND_LARGEENTITY;
1296 sflags |= SND_LARGESOUND;
1297 WriteByte(dest, SVC_SOUND);
1298 WriteByte(dest, sflags);
1299 WriteShort(dest, entno);
1300 WriteByte(dest, chan);
1301 if (sflags & SND_LARGESOUND)
1302 WriteShort(dest, idx);
1304 WriteByte(dest, idx);
1305 WriteCoord(dest, e.origin_x);
1306 WriteCoord(dest, e.origin_y);
1307 WriteCoord(dest, e.origin_z);
1311 WriteByte(dest, SVC_STOPSOUND);
1312 WriteShort(dest, entno * 8 + chan);
1315 void stopsound(entity e, float chan)
1317 if (!sound_allowed(MSG_BROADCAST, e))
1320 stopsoundto(MSG_BROADCAST, e, chan); // unreliable, gets there fast
1321 stopsoundto(MSG_ALL, e, chan); // in case of packet loss
1324 void play2(entity e, string filename)
1326 //stuffcmd(e, strcat("play2 ", filename, "\n"));
1328 soundtoat(MSG_ONE, world, '0 0 0', CHAN_AUTO, filename, VOL_BASE, ATTN_NONE);
1331 .float announcetime;
1332 float announce(entity player, string msg)
1334 if (time > player.announcetime)
1335 if (clienttype(player) == CLIENTTYPE_REAL)
1337 player.announcetime = time + 0.8;
1343 // use this one if you might be causing spam (e.g. from touch functions that might get called more than once per frame)
1344 float spamsound(entity e, float chan, string samp, float vol, float atten)
1346 if (!sound_allowed(MSG_BROADCAST, e))
1349 if (time > e.announcetime)
1351 e.announcetime = time;
1352 sound(e, chan, samp, vol, atten);
1358 void play2team(float t, string filename)
1362 if (cvar("bot_sound_monopoly"))
1365 FOR_EACH_REALPLAYER(head)
1368 play2(head, filename);
1372 void play2all(string samp)
1374 if (cvar("bot_sound_monopoly"))
1377 sound(world, CHAN_AUTO, samp, VOL_BASE, ATTN_NONE);
1380 void PrecachePlayerSounds(string f);
1381 void precache_all_models(string pattern)
1383 float globhandle, i, n;
1386 globhandle = search_begin(pattern, TRUE, FALSE);
1389 n = search_getsize(globhandle);
1390 for (i = 0; i < n; ++i)
1392 //print(search_getfilename(globhandle, i), "\n");
1393 f = search_getfilename(globhandle, i);
1396 if(substring(f, -9,5) == "_lod1")
1398 if(substring(f, -9,5) == "_lod2")
1400 if(!sv_loddistance1)
1402 PrecachePlayerSounds(strcat(f, ".sounds"));
1404 search_end(globhandle);
1409 // gamemode related things
1410 precache_model ("models/misc/chatbubble.spr");
1411 precache_model ("models/misc/teambubble.spr");
1414 precache_model ("models/runematch/curse.mdl");
1415 precache_model ("models/runematch/rune.mdl");
1418 #ifdef TTURRETS_ENABLED
1419 if (cvar("g_turrets"))
1423 // Precache all player models if desired
1424 if (cvar("sv_precacheplayermodels"))
1426 PrecachePlayerSounds("sound/player/default.sounds");
1427 precache_all_models("models/player/*.zym");
1428 precache_all_models("models/player/*.dpm");
1429 precache_all_models("models/player/*.md3");
1430 precache_all_models("models/player/*.psk");
1431 //precache_model("models/player/carni.zym");
1432 //precache_model("models/player/crash.zym");
1433 //precache_model("models/player/grunt.zym");
1434 //precache_model("models/player/headhunter.zym");
1435 //precache_model("models/player/insurrectionist.zym");
1436 //precache_model("models/player/jeandarc.zym");
1437 //precache_model("models/player/lurk.zym");
1438 //precache_model("models/player/lycanthrope.zym");
1439 //precache_model("models/player/marine.zym");
1440 //precache_model("models/player/nexus.zym");
1441 //precache_model("models/player/pyria.zym");
1442 //precache_model("models/player/shock.zym");
1443 //precache_model("models/player/skadi.zym");
1444 //precache_model("models/player/specop.zym");
1445 //precache_model("models/player/visitant.zym");
1448 if (cvar("sv_defaultcharacter"))
1451 s = cvar_string("sv_defaultplayermodel_red");
1455 PrecachePlayerSounds(strcat(s, ".sounds"));
1457 s = cvar_string("sv_defaultplayermodel_blue");
1461 PrecachePlayerSounds(strcat(s, ".sounds"));
1463 s = cvar_string("sv_defaultplayermodel_yellow");
1467 PrecachePlayerSounds(strcat(s, ".sounds"));
1469 s = cvar_string("sv_defaultplayermodel_pink");
1473 PrecachePlayerSounds(strcat(s, ".sounds"));
1475 s = cvar_string("sv_defaultplayermodel");
1479 PrecachePlayerSounds(strcat(s, ".sounds"));
1485 PrecacheGlobalSound((globalsound_step = "misc/footstep0 6"));
1486 PrecacheGlobalSound((globalsound_metalstep = "misc/metalfootstep0 6"));
1489 // gore and miscellaneous sounds
1490 //precache_sound ("misc/h2ohit.wav");
1491 precache_model ("models/hook.md3");
1492 precache_sound ("misc/armorimpact.wav");
1493 precache_sound ("misc/bodyimpact1.wav");
1494 precache_sound ("misc/bodyimpact2.wav");
1495 precache_sound ("misc/gib.wav");
1496 precache_sound ("misc/gib_splat01.wav");
1497 precache_sound ("misc/gib_splat02.wav");
1498 precache_sound ("misc/gib_splat03.wav");
1499 precache_sound ("misc/gib_splat04.wav");
1500 precache_sound ("misc/hit.wav");
1501 PrecacheGlobalSound((globalsound_fall = "misc/hitground 4"));
1502 PrecacheGlobalSound((globalsound_metalfall = "misc/metalhitground 4"));
1503 precache_sound ("misc/null.wav");
1504 precache_sound ("misc/spawn.wav");
1505 precache_sound ("misc/talk.wav");
1506 precache_sound ("misc/teleport.wav");
1507 precache_sound ("misc/poweroff.wav");
1508 precache_sound ("player/lava.wav");
1509 precache_sound ("player/slime.wav");
1512 precache_sound ("misc/jetpack_fly.wav");
1514 // announcer sounds - male
1515 precache_sound ("announcer/male/electrobitch.wav");
1516 precache_sound ("announcer/male/airshot.wav");
1517 precache_sound ("announcer/male/03kills.wav");
1518 precache_sound ("announcer/male/05kills.wav");
1519 precache_sound ("announcer/male/10kills.wav");
1520 precache_sound ("announcer/male/15kills.wav");
1521 precache_sound ("announcer/male/20kills.wav");
1522 precache_sound ("announcer/male/25kills.wav");
1523 precache_sound ("announcer/male/30kills.wav");
1524 precache_sound ("announcer/male/botlike.wav");
1525 precache_sound ("announcer/male/yoda.wav");
1526 precache_sound ("announcer/male/amazing.wav");
1527 precache_sound ("announcer/male/awesome.wav");
1528 precache_sound ("announcer/male/headshot.wav");
1529 precache_sound ("announcer/male/impressive.wav");
1531 // announcer sounds - robotic
1532 precache_sound ("announcer/robotic/prepareforbattle.wav");
1533 precache_sound ("announcer/robotic/begin.wav");
1534 precache_sound ("announcer/robotic/timeoutcalled.wav");
1535 precache_sound ("announcer/robotic/1fragleft.wav");
1536 precache_sound ("announcer/robotic/2fragsleft.wav");
1537 precache_sound ("announcer/robotic/3fragsleft.wav");
1538 precache_sound ("announcer/robotic/terminated.wav");
1541 precache_sound ("announcer/robotic/lastsecond.wav");
1542 precache_sound ("announcer/robotic/narrowly.wav");
1545 precache_model ("models/sprites/0.spr32");
1546 precache_model ("models/sprites/1.spr32");
1547 precache_model ("models/sprites/2.spr32");
1548 precache_model ("models/sprites/3.spr32");
1549 precache_model ("models/sprites/4.spr32");
1550 precache_model ("models/sprites/5.spr32");
1551 precache_model ("models/sprites/6.spr32");
1552 precache_model ("models/sprites/7.spr32");
1553 precache_model ("models/sprites/8.spr32");
1554 precache_model ("models/sprites/9.spr32");
1555 precache_model ("models/sprites/10.spr32");
1556 precache_sound ("announcer/robotic/1.wav");
1557 precache_sound ("announcer/robotic/2.wav");
1558 precache_sound ("announcer/robotic/3.wav");
1559 precache_sound ("announcer/robotic/4.wav");
1560 precache_sound ("announcer/robotic/5.wav");
1561 precache_sound ("announcer/robotic/6.wav");
1562 precache_sound ("announcer/robotic/7.wav");
1563 precache_sound ("announcer/robotic/8.wav");
1564 precache_sound ("announcer/robotic/9.wav");
1565 precache_sound ("announcer/robotic/10.wav");
1567 // common weapon precaches
1568 precache_sound ("weapons/weapon_switch.wav");
1569 precache_sound ("weapons/weaponpickup.wav");
1570 precache_sound ("weapons/unavailable.wav");
1571 if (g_grappling_hook)
1573 precache_sound ("weapons/hook_fire.wav"); // hook
1574 precache_sound ("weapons/hook_impact.wav"); // hook
1577 if (cvar("sv_precacheweapons") || g_nixnex)
1579 //precache weapon models/sounds
1582 while (wep <= WEP_LAST)
1584 weapon_action(wep, WR_PRECACHE);
1589 precache_model("models/elaser.mdl");
1590 precache_model("models/laser.mdl");
1591 precache_model("models/ebomb.mdl");
1594 // Disabled this code because it simply does not work (e.g. ignores bgmvolume, overlaps with "cd loop" controlled tracks).
1596 if (!self.noise && self.music) // quake 3 uses the music field
1597 self.noise = self.music;
1599 // plays music for the level if there is any
1602 precache_sound (self.noise);
1603 ambientsound ('0 0 0', self.noise, VOL_BASE, ATTN_NONE);
1608 // sorry, but using \ in macros breaks line numbers
1609 #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
1610 #define WRITESPECTATABLE_MSG_ONE(statement) WRITESPECTATABLE_MSG_ONE_VARNAME(oldmsg_entity, statement)
1611 #define WRITESPECTATABLE(msg,statement) if(msg == MSG_ONE) { WRITESPECTATABLE_MSG_ONE(statement); } else statement float WRITESPECTATABLE_workaround = 0
1613 vector ExactTriggerHit_mins;
1614 vector ExactTriggerHit_maxs;
1615 float ExactTriggerHit_Recurse()
1621 tracebox('0 0 0', ExactTriggerHit_mins, ExactTriggerHit_maxs, '0 0 0', MOVE_NORMAL, other);
1624 if (trace_ent == self)
1629 se.solid = SOLID_NOT;
1630 f = ExactTriggerHit_Recurse();
1636 float ExactTriggerHit()
1640 if not(self.modelindex)
1644 self.solid = SOLID_BSP;
1645 ExactTriggerHit_mins = other.absmin;
1646 ExactTriggerHit_maxs = other.absmax;
1647 f = ExactTriggerHit_Recurse();
1653 // WARNING: this kills the trace globals
1654 #define EXACTTRIGGER_TOUCH if not(ExactTriggerHit()) return
1655 #define EXACTTRIGGER_INIT InitSolidBSPTrigger(); self.solid = SOLID_TRIGGER
1657 #define INITPRIO_FIRST 0
1658 #define INITPRIO_GAMETYPE 0
1659 #define INITPRIO_GAMETYPE_FALLBACK 1
1660 #define INITPRIO_CVARS 5
1661 #define INITPRIO_FINDTARGET 10
1662 #define INITPRIO_DROPTOFLOOR 20
1663 #define INITPRIO_SETLOCATION 90
1664 #define INITPRIO_LINKDOORS 91
1665 #define INITPRIO_LAST 99
1667 .void(void) initialize_entity;
1668 .float initialize_entity_order;
1669 .entity initialize_entity_next;
1670 entity initialize_entity_first;
1672 void make_safe_for_remove(entity e)
1674 if (e.initialize_entity)
1677 for (ent = initialize_entity_first; ent; )
1679 if ((ent == e) || ((ent.classname == "initialize_entity") && (ent.enemy == e)))
1681 //print("make_safe_for_remove: getting rid of initializer ", etos(ent), "\n");
1682 // skip it in linked list
1685 prev.initialize_entity_next = ent.initialize_entity_next;
1686 ent = prev.initialize_entity_next;
1690 initialize_entity_first = ent.initialize_entity_next;
1691 ent = initialize_entity_first;
1697 ent = ent.initialize_entity_next;
1703 void objerror(string s)
1705 make_safe_for_remove(self);
1706 objerror_builtin(s);
1709 void remove_unsafely(entity e)
1714 void remove_safely(entity e)
1716 make_safe_for_remove(e);
1720 void InitializeEntity(entity e, void(void) func, float order)
1724 if (!e || e.initialize_entity)
1726 // make a proxy initializer entity
1730 e.classname = "initialize_entity";
1734 e.initialize_entity = func;
1735 e.initialize_entity_order = order;
1737 cur = initialize_entity_first;
1740 if (!cur || cur.initialize_entity_order > order)
1742 // insert between prev and cur
1744 prev.initialize_entity_next = e;
1746 initialize_entity_first = e;
1747 e.initialize_entity_next = cur;
1751 cur = cur.initialize_entity_next;
1754 void InitializeEntitiesRun()
1757 startoflist = initialize_entity_first;
1758 initialize_entity_first = world;
1759 for (self = startoflist; self; )
1762 var void(void) func;
1763 e = self.initialize_entity_next;
1764 func = self.initialize_entity;
1765 self.initialize_entity_order = 0;
1766 self.initialize_entity = func_null;
1767 self.initialize_entity_next = world;
1768 if (self.classname == "initialize_entity")
1772 remove_builtin(self);
1775 //dprint("Delayed initialization: ", self.classname, "\n");
1781 .float uncustomizeentityforclient_set;
1782 .void(void) uncustomizeentityforclient;
1783 void(void) SUB_Nullpointer = #0;
1784 void UncustomizeEntitiesRun()
1788 for (self = world; (self = findfloat(self, uncustomizeentityforclient_set, 1)); )
1789 self.uncustomizeentityforclient();
1792 void SetCustomizer(entity e, float(void) customizer, void(void) uncustomizer)
1794 e.customizeentityforclient = customizer;
1795 e.uncustomizeentityforclient = uncustomizer;
1796 e.uncustomizeentityforclient_set = (uncustomizer != SUB_Nullpointer);
1800 #define IFTARGETED if(!self.nottargeted && self.targetname != "")
1803 void Net_LinkEntity(entity e, float docull, float dt, float(entity, float) sendfunc)
1807 if (e.classname == "")
1808 e.classname = "net_linked";
1810 if (e.model == "" || self.modelindex == 0)
1814 setmodel(e, "null");
1818 e.SendEntity = sendfunc;
1819 e.SendFlags = 0xFFFFFF;
1822 e.effects |= EF_NODEPTHTEST;
1826 e.nextthink = time + dt;
1827 e.think = SUB_Remove;
1831 void adaptor_think2touch()
1840 void adaptor_think2use()
1852 // deferred dropping
1853 void DropToFloor_Handler()
1855 droptofloor_builtin();
1856 self.dropped_origin = self.origin;
1861 InitializeEntity(self, DropToFloor_Handler, INITPRIO_DROPTOFLOOR);
1866 float trace_hits_box_a0, trace_hits_box_a1;
1868 float trace_hits_box_1d(float end, float thmi, float thma)
1872 // just check if x is in range
1880 // do the trace with respect to x
1881 // 0 -> end has to stay in thmi -> thma
1882 trace_hits_box_a0 = max(trace_hits_box_a0, min(thmi / end, thma / end));
1883 trace_hits_box_a1 = min(trace_hits_box_a1, max(thmi / end, thma / end));
1884 if (trace_hits_box_a0 > trace_hits_box_a1)
1890 float trace_hits_box(vector start, vector end, vector thmi, vector thma)
1895 // now it is a trace from 0 to end
1897 trace_hits_box_a0 = 0;
1898 trace_hits_box_a1 = 1;
1900 if (!trace_hits_box_1d(end_x, thmi_x, thma_x))
1902 if (!trace_hits_box_1d(end_y, thmi_y, thma_y))
1904 if (!trace_hits_box_1d(end_z, thmi_z, thma_z))
1910 float tracebox_hits_box(vector start, vector mi, vector ma, vector end, vector thmi, vector thma)
1912 return trace_hits_box(start, end, thmi - ma, thma - mi);
1915 float SUB_NoImpactCheck()
1917 // zero hitcontents = this is not the real impact, but either the
1918 // mirror-impact of something hitting the projectile instead of the
1919 // projectile hitting the something, or a touchareagrid one. Neither of
1920 // these stop the projectile from moving, so...
1921 if(trace_dphitcontents == 0)
1923 dprint("A hit happened with zero hit contents... DEBUG THIS, this should never happen for projectiles! Projectile will self-destruct.\n");
1926 if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
1928 if (other == world && self.size != '0 0 0')
1931 tic = self.velocity * sys_ticrate;
1932 tic = tic + normalize(tic) * vlen(self.maxs - self.mins);
1933 traceline(self.origin - tic, self.origin + tic, MOVE_NORMAL, self);
1934 if (trace_fraction >= 1)
1936 dprint("Odd... did not hit...?\n");
1938 else if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
1940 dprint("Detected and prevented the sky-grapple bug.\n");
1948 #define SUB_OwnerCheck() (other && (other == self.owner))
1950 #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)
1952 float MAX_IPBAN_URIS = 16;
1954 float URI_GET_DISCARD = 0;
1955 float URI_GET_IPBAN = 1;
1956 float URI_GET_IPBAN_END = 16;
1958 void URI_Get_Callback(float id, float status, string data)
1960 dprint("Received HTTP request data for id ", ftos(id), "; status is ", ftos(status), "\nData is:\n");
1962 dprint("\nEnd of data.\n");
1964 if (id == URI_GET_DISCARD)
1968 else if (id >= URI_GET_IPBAN && id <= URI_GET_IPBAN_END)
1971 OnlineBanList_URI_Get_Callback(id, status, data);
1975 print("Received HTTP request data for an invalid id ", ftos(id), ".\n");
1979 void print_to(entity e, string s)
1982 sprint(e, strcat(s, "\n"));
2001 for (i = 0; i < MapInfo_count; ++i)
2003 if (MapInfo_Get_ByID(i))
2005 r = stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, "/captimerecord/time")));
2008 h = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, "/captimerecord/netname"));
2009 s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-6, ftos_decimals(r, 2)), " ", h, "\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, "/racerecord/time")));
2024 h = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, "/racerecord/netname"));
2025 s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-8, mmsss(r)), " ", 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, "/ctsrecord/time")));
2040 h = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, "/ctsrecord/netname"));
2041 s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-8, mmsss(r)), " ", h, "\n");
2047 MapInfo_ClearTemps();
2050 return "No records are available on this server.\n";
2052 return strcat("Records on this server:\n", s);
2055 float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
2058 vector start, org, delta, end, enddown, mstart;
2060 m = e.dphitcontentsmask;
2061 e.dphitcontentsmask = goodcontents | badcontents;
2064 delta = world.maxs - world.mins;
2066 for (i = 0; i < attempts; ++i)
2068 start_x = org_x + random() * delta_x;
2069 start_y = org_y + random() * delta_y;
2070 start_z = org_z + random() * delta_z;
2072 // rule 1: start inside world bounds, and outside
2073 // solid, and don't start from somewhere where you can
2074 // fall down to evil
2075 tracebox(start, e.mins, e.maxs, start - '0 0 1' * delta_z, MOVE_NORMAL, e);
2076 if (trace_fraction >= 1)
2078 if (trace_startsolid)
2080 if (trace_dphitcontents & badcontents)
2082 if (trace_dphitq3surfaceflags & badsurfaceflags)
2085 // rule 2: if we are too high, lower the point
2086 if (trace_fraction * delta_z > maxaboveground)
2087 start = trace_endpos + '0 0 1' * maxaboveground;
2088 enddown = trace_endpos;
2090 // rule 3: make sure we aren't outside the map. This only works
2091 // for somewhat well formed maps. A good rule of thumb is that
2092 // the map should have a convex outside hull.
2093 // these can be traceLINES as we already verified the starting box
2094 mstart = start + 0.5 * (e.mins + e.maxs);
2095 traceline(mstart, mstart + '1 0 0' * delta_x, MOVE_NORMAL, e);
2096 if (trace_fraction >= 1)
2098 traceline(mstart, mstart - '1 0 0' * delta_x, MOVE_NORMAL, e);
2099 if (trace_fraction >= 1)
2101 traceline(mstart, mstart + '0 1 0' * delta_y, MOVE_NORMAL, e);
2102 if (trace_fraction >= 1)
2104 traceline(mstart, mstart - '0 1 0' * delta_y, MOVE_NORMAL, e);
2105 if (trace_fraction >= 1)
2107 traceline(mstart, mstart + '0 0 1' * delta_z, MOVE_NORMAL, e);
2108 if (trace_fraction >= 1)
2111 // find a random vector to "look at"
2112 end_x = org_x + random() * delta_x;
2113 end_y = org_y + random() * delta_y;
2114 end_z = org_z + random() * delta_z;
2115 end = start + normalize(end - start) * vlen(delta);
2117 // rule 4: start TO end must not be too short
2118 tracebox(start, e.mins, e.maxs, end, MOVE_NORMAL, e);
2119 if (trace_startsolid)
2121 if (trace_fraction < minviewdistance / vlen(delta))
2124 // rule 5: don't want to look at sky
2125 if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
2128 // rule 6: we must not end up in trigger_hurt
2129 if (tracebox_hits_trigger_hurt(start, e.mins, e.maxs, enddown))
2131 dprint("trigger_hurt! ouch! and nothing else could find it!\n");
2138 e.dphitcontentsmask = m;
2142 setorigin(e, start);
2143 e.angles = vectoangles(end - start);
2144 dprint("Needed ", ftos(i + 1), " attempts\n");
2151 void zcurveparticles(float effectno, vector start, vector end, float end_dz, float spd)
2153 WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
2154 WriteByte(MSG_BROADCAST, TE_CSQC_ZCURVEPARTICLES);
2155 WriteShort(MSG_BROADCAST, effectno);
2156 WriteCoord(MSG_BROADCAST, start_x);
2157 WriteCoord(MSG_BROADCAST, start_y);
2158 WriteCoord(MSG_BROADCAST, start_z);
2159 WriteCoord(MSG_BROADCAST, end_x);
2160 WriteCoord(MSG_BROADCAST, end_y);
2161 WriteCoord(MSG_BROADCAST, end_z);
2162 WriteCoord(MSG_BROADCAST, end_dz);
2163 WriteShort(MSG_BROADCAST, spd / 16);
2166 void zcurveparticles_from_tracetoss(float effectno, vector start, vector end, vector vel)
2169 vector vecxy, velxy;
2171 vecxy = end - start;
2176 if (vlen(velxy) < 0.000001 * fabs(vel_z))
2178 trailparticles(world, effectno, start, end);
2182 end_dz = vlen(vecxy) / vlen(velxy) * vel_z - (end_z - start_z);
2183 zcurveparticles(effectno, start, end, end_dz, vlen(vel));
2186 string GetGametype(); // g_world.qc
2187 void write_recordmarker(entity pl, float tstart, float dt)
2189 GameLogEcho(strcat(":recordset:", ftos(pl.playerid), ":", ftos(dt)));
2191 // also write a marker into demo files for demotc-race-record-extractor to find
2194 strcat("//", strconv(2, 0, 0, GetGametype()), " RECORD SET ", mmsss(dt * 10)),
2195 " ", ftos(tstart), " ", ftos(dt), "\n"));
2198 vector shotorg_adjustfromclient(vector vecs, float y_is_right, float allowcenter)
2200 switch(self.owner.cvar_cl_gunalign)
2211 if(allowcenter) // 2: allow center handedness
2224 if(allowcenter) // 2: allow center handedness
2240 vector shotorg_adjust(vector vecs, float y_is_right, float visual)
2245 if (cvar("g_shootfromeye"))
2249 vecs = shotorg_adjustfromclient(vecs, y_is_right, TRUE);
2257 else if (cvar("g_shootfromcenter"))
2261 vecs = shotorg_adjustfromclient(vecs, y_is_right, TRUE);
2269 else if (cvar("g_shootfromclient"))
2271 vecs = shotorg_adjustfromclient(vecs, y_is_right, (cvar("g_shootfromclient") >= 2));
2273 else if ((s = cvar_string("g_shootfromfixedorigin")) != "")
2288 void attach_sameorigin(entity e, entity to, string tag)
2290 vector org, t_forward, t_left, t_up, e_forward, e_up;
2297 org = e.origin - gettaginfo(to, gettagindex(to, tag));
2298 tagscale = pow(vlen(v_forward), -2); // undo a scale on the tag
2299 t_forward = v_forward * tagscale;
2300 t_left = v_right * -tagscale;
2301 t_up = v_up * tagscale;
2303 e.origin_x = org * t_forward;
2304 e.origin_y = org * t_left;
2305 e.origin_z = org * t_up;
2307 // current forward and up directions
2308 if (substring(e.model, 0, 1) == "*") // bmodels have their own rules
2309 e.angles_x = -e.angles_x;
2310 fixedmakevectors(e.angles);
2312 // untransform forward, up!
2313 e_forward_x = v_forward * t_forward;
2314 e_forward_y = v_forward * t_left;
2315 e_forward_z = v_forward * t_up;
2316 e_up_x = v_up * t_forward;
2317 e_up_y = v_up * t_left;
2318 e_up_z = v_up * t_up;
2320 e.angles = fixedvectoangles2(e_forward, e_up);
2321 if (substring(e.model, 0, 1) == "*") // bmodels have their own rules
2322 e.angles_x = -e.angles_x;
2324 setattachment(e, to, tag);
2325 setorigin(e, e.origin);
2328 void detach_sameorigin(entity e)
2331 org = gettaginfo(e, 0);
2332 e.angles = fixedvectoangles2(v_forward, v_up);
2333 if (substring(e.model, 0, 1) == "*") // bmodels have their own rules
2334 e.angles_x = -e.angles_x;
2336 setattachment(e, world, "");
2337 setorigin(e, e.origin);
2340 void follow_sameorigin(entity e, entity to)
2342 e.movetype = MOVETYPE_FOLLOW; // make the hole follow
2343 e.aiment = to; // make the hole follow bmodel
2344 e.punchangle = to.angles; // the original angles of bmodel
2345 e.view_ofs = e.origin - to.origin; // relative origin
2346 e.v_angle = e.angles - to.angles; // relative angles
2349 void unfollow_sameorigin(entity e)
2351 e.movetype = MOVETYPE_NONE;
2354 entity gettaginfo_relative_ent;
2355 vector gettaginfo_relative(entity e, float tag)
2357 if (!gettaginfo_relative_ent)
2359 gettaginfo_relative_ent = spawn();
2360 gettaginfo_relative_ent.effects = EF_NODRAW;
2362 gettaginfo_relative_ent.model = e.model;
2363 gettaginfo_relative_ent.modelindex = e.modelindex;
2364 gettaginfo_relative_ent.frame = e.frame;
2365 return gettaginfo(gettaginfo_relative_ent, tag);
2368 void SoundEntity_StartSound(entity pl, float chan, string samp, float vol, float attn)
2372 if (pl.soundentity.cnt & p)
2374 soundtoat(MSG_ALL, pl.soundentity, gettaginfo(pl.soundentity, 0), chan, samp, vol, attn);
2375 pl.soundentity.cnt |= p;
2378 void SoundEntity_StopSound(entity pl, float chan)
2382 if (pl.soundentity.cnt & p)
2384 stopsoundto(MSG_ALL, pl.soundentity, chan);
2385 pl.soundentity.cnt &~= p;
2389 void SoundEntity_Attach(entity pl)
2391 pl.soundentity = spawn();
2392 pl.soundentity.classname = "soundentity";
2393 pl.soundentity.owner = pl;
2394 setattachment(pl.soundentity, pl, "");
2395 setmodel(pl.soundentity, "null");
2398 void SoundEntity_Detach(entity pl)
2401 for (i = 0; i <= 7; ++i)
2402 SoundEntity_StopSound(pl, i);
2406 float ParseCommandPlayerSlotTarget_firsttoken;
2407 entity GetCommandPlayerSlotTargetFromTokenizedCommand(float tokens, float idx) // idx = start index
2415 ParseCommandPlayerSlotTarget_firsttoken = -1;
2419 if (substring(argv(idx), 0, 1) == "#")
2421 s = substring(argv(idx), 1, -1);
2429 ParseCommandPlayerSlotTarget_firsttoken = idx;
2430 if (s == ftos(stof(s)))
2432 e = edict_num(stof(s));
2433 if (e.flags & FL_CLIENT)
2439 // it must be a nick name
2442 ParseCommandPlayerSlotTarget_firsttoken = idx;
2445 FOR_EACH_CLIENT(head)
2446 if (head.netname == s)
2454 s = strdecolorize(s);
2456 FOR_EACH_CLIENT(head)
2457 if (strdecolorize(head.netname) == s)
2472 float modeleffect_SendEntity(entity to, float sf)
2475 WriteByte(MSG_ENTITY, ENT_CLIENT_MODELEFFECT);
2478 if(self.velocity != '0 0 0')
2480 if(self.angles != '0 0 0')
2482 if(self.avelocity != '0 0 0')
2485 WriteByte(MSG_ENTITY, f);
2486 WriteShort(MSG_ENTITY, self.modelindex);
2487 WriteByte(MSG_ENTITY, self.frame);
2488 WriteCoord(MSG_ENTITY, self.origin_x);
2489 WriteCoord(MSG_ENTITY, self.origin_y);
2490 WriteCoord(MSG_ENTITY, self.origin_z);
2493 WriteCoord(MSG_ENTITY, self.velocity_x);
2494 WriteCoord(MSG_ENTITY, self.velocity_y);
2495 WriteCoord(MSG_ENTITY, self.velocity_z);
2499 WriteCoord(MSG_ENTITY, self.angles_x);
2500 WriteCoord(MSG_ENTITY, self.angles_y);
2501 WriteCoord(MSG_ENTITY, self.angles_z);
2505 WriteCoord(MSG_ENTITY, self.avelocity_x);
2506 WriteCoord(MSG_ENTITY, self.avelocity_y);
2507 WriteCoord(MSG_ENTITY, self.avelocity_z);
2509 WriteShort(MSG_ENTITY, self.scale * 256.0);
2510 WriteShort(MSG_ENTITY, self.scale2 * 256.0);
2511 WriteByte(MSG_ENTITY, self.teleport_time * 100.0);
2512 WriteByte(MSG_ENTITY, self.fade_time * 100.0);
2513 WriteByte(MSG_ENTITY, self.alpha * 255.0);
2518 void modeleffect_spawn(string m, float f, vector o, vector v, vector ang, vector angv, float s0, float s2, float a, float t1, float t2)
2523 e.classname = "modeleffect";
2531 e.teleport_time = t1;
2534 e.scale = s0 / max6(-e.mins_x, -e.mins_y, -e.mins_z, e.maxs_x, e.maxs_y, e.maxs_z);
2538 e.scale2 = s2 / max6(-e.mins_x, -e.mins_y, -e.mins_z, e.maxs_x, e.maxs_y, e.maxs_z);
2541 sz = max(e.scale, e.scale2);
2542 setsize(e, e.mins * sz, e.maxs * sz);
2543 Net_LinkEntity(e, FALSE, 0.1, modeleffect_SendEntity);
2546 void shockwave_spawn(string m, vector org, float sz, float t1, float t2)
2548 return modeleffect_spawn(m, 0, org, '0 0 0', '0 0 0', '0 0 0', 0, sz, 1, t1, t2);