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_ammo_fuel = start_ammo_fuel;
939 warmup_start_health = start_health;
940 warmup_start_armorvalue = start_armorvalue;
941 warmup_start_weapons = start_weapons;
943 if (!g_weaponarena && !g_nixnex && !g_minstagib)
945 if (cvar("g_use_ammunition"))
947 warmup_start_ammo_shells = cvar("g_warmup_start_ammo_shells");
948 warmup_start_ammo_cells = cvar("g_warmup_start_ammo_cells");
949 warmup_start_ammo_nails = cvar("g_warmup_start_ammo_nails");
950 warmup_start_ammo_rockets = cvar("g_warmup_start_ammo_rockets");
951 warmup_start_ammo_fuel = cvar("g_warmup_start_ammo_fuel");
953 warmup_start_health = cvar("g_warmup_start_health");
954 warmup_start_armorvalue = cvar("g_warmup_start_armor");
955 if (cvar("g_warmup_allguns"))
957 for (i = WEP_FIRST; i <= WEP_LAST; ++i)
959 e = get_weaponinfo(i);
962 if (e.spawnflags & WEPSPAWNFLAG_NORMAL)
964 warmup_start_weapons |= e.weapons;
965 weapon_action(e.weapon, WR_PRECACHE);
972 if (g_jetpack || (g_grappling_hook && (start_weapons & WEPBIT_HOOK)))
974 g_grappling_hook = 0; // these two can't coexist, as they use the same button
975 start_items |= IT_FUEL_REGEN;
976 start_ammo_fuel = max(start_ammo_fuel, cvar("g_balance_fuel_rotstable"));
977 warmup_start_ammo_fuel = max(warmup_start_ammo_fuel, cvar("g_balance_fuel_rotstable"));
981 start_items |= IT_JETPACK;
983 if (g_weapon_stay == 2)
985 if (!start_ammo_shells) start_ammo_shells = g_pickup_shells;
986 if (!start_ammo_nails) start_ammo_nails = g_pickup_nails;
987 if (!start_ammo_cells) start_ammo_cells = g_pickup_cells;
988 if (!start_ammo_rockets) start_ammo_rockets = g_pickup_rockets;
989 if (!start_ammo_fuel) start_ammo_fuel = g_pickup_fuel;
990 if (!warmup_start_ammo_shells) warmup_start_ammo_shells = g_pickup_shells;
991 if (!warmup_start_ammo_nails) warmup_start_ammo_nails = g_pickup_nails;
992 if (!warmup_start_ammo_cells) warmup_start_ammo_cells = g_pickup_cells;
993 if (!warmup_start_ammo_rockets) warmup_start_ammo_rockets = g_pickup_rockets;
994 if (!warmup_start_ammo_fuel) warmup_start_ammo_fuel = g_pickup_fuel;
997 start_ammo_shells = max(0, start_ammo_shells);
998 start_ammo_nails = max(0, start_ammo_nails);
999 start_ammo_cells = max(0, start_ammo_cells);
1000 start_ammo_rockets = max(0, start_ammo_rockets);
1001 start_ammo_fuel = max(0, start_ammo_fuel);
1003 warmup_start_ammo_shells = max(0, warmup_start_ammo_shells);
1004 warmup_start_ammo_nails = max(0, warmup_start_ammo_nails);
1005 warmup_start_ammo_cells = max(0, warmup_start_ammo_cells);
1006 warmup_start_ammo_rockets = max(0, warmup_start_ammo_rockets);
1007 warmup_start_ammo_fuel = max(0, warmup_start_ammo_fuel);
1011 float g_bugrigs_planar_movement;
1012 float g_bugrigs_planar_movement_car_jumping;
1013 float g_bugrigs_reverse_spinning;
1014 float g_bugrigs_reverse_speeding;
1015 float g_bugrigs_reverse_stopping;
1016 float g_bugrigs_air_steering;
1017 float g_bugrigs_angle_smoothing;
1018 float g_bugrigs_friction_floor;
1019 float g_bugrigs_friction_brake;
1020 float g_bugrigs_friction_air;
1021 float g_bugrigs_accel;
1022 float g_bugrigs_speed_ref;
1023 float g_bugrigs_speed_pow;
1024 float g_bugrigs_steer;
1026 float g_touchexplode;
1027 float g_touchexplode_radius;
1028 float g_touchexplode_damage;
1029 float g_touchexplode_edgedamage;
1030 float g_touchexplode_force;
1035 void readlevelcvars(void)
1037 g_bugrigs = cvar("g_bugrigs");
1038 g_bugrigs_planar_movement = cvar("g_bugrigs_planar_movement");
1039 g_bugrigs_planar_movement_car_jumping = cvar("g_bugrigs_planar_movement_car_jumping");
1040 g_bugrigs_reverse_spinning = cvar("g_bugrigs_reverse_spinning");
1041 g_bugrigs_reverse_speeding = cvar("g_bugrigs_reverse_speeding");
1042 g_bugrigs_reverse_stopping = cvar("g_bugrigs_reverse_stopping");
1043 g_bugrigs_air_steering = cvar("g_bugrigs_air_steering");
1044 g_bugrigs_angle_smoothing = cvar("g_bugrigs_angle_smoothing");
1045 g_bugrigs_friction_floor = cvar("g_bugrigs_friction_floor");
1046 g_bugrigs_friction_brake = cvar("g_bugrigs_friction_brake");
1047 g_bugrigs_friction_air = cvar("g_bugrigs_friction_air");
1048 g_bugrigs_accel = cvar("g_bugrigs_accel");
1049 g_bugrigs_speed_ref = cvar("g_bugrigs_speed_ref");
1050 g_bugrigs_speed_pow = cvar("g_bugrigs_speed_pow");
1051 g_bugrigs_steer = cvar("g_bugrigs_steer");
1053 g_touchexplode = cvar("g_touchexplode");
1054 g_touchexplode_radius = cvar("g_touchexplode_radius");
1055 g_touchexplode_damage = cvar("g_touchexplode_damage");
1056 g_touchexplode_edgedamage = cvar("g_touchexplode_edgedamage");
1057 g_touchexplode_force = cvar("g_touchexplode_force");
1059 #ifdef ALLOW_FORCEMODELS
1060 sv_clforceplayermodels = cvar("sv_clforceplayermodels");
1062 sv_loddistance1 = cvar("sv_loddistance1");
1063 sv_loddistance2 = cvar("sv_loddistance2");
1064 if(sv_loddistance2 <= sv_loddistance1)
1065 sv_loddistance2 = 1073741824; // enough to turn off LOD 2 reliably
1066 sv_clones = cvar("sv_clones");
1067 sv_cheats = cvar("sv_cheats");
1068 sv_gentle = cvar("sv_gentle");
1069 sv_foginterval = cvar("sv_foginterval");
1070 g_cloaked = cvar("g_cloaked");
1071 g_jump_grunt = cvar("g_jump_grunt");
1072 g_footsteps = cvar("g_footsteps");
1073 g_grappling_hook = cvar("g_grappling_hook");
1074 g_jetpack = cvar("g_jetpack");
1075 g_laserguided_missile = cvar("g_laserguided_missile");
1076 g_midair = cvar("g_midair");
1077 g_minstagib = cvar("g_minstagib");
1078 g_nixnex = cvar("g_nixnex");
1079 g_nixnex_with_laser = cvar("g_nixnex_with_laser");
1080 g_norecoil = cvar("g_norecoil");
1081 g_vampire = cvar("g_vampire");
1082 g_bloodloss = cvar("g_bloodloss");
1083 sv_maxidle = cvar("sv_maxidle");
1084 sv_maxidle_spectatorsareidle = cvar("sv_maxidle_spectatorsareidle");
1085 sv_pogostick = cvar("sv_pogostick");
1086 sv_doublejump = cvar("sv_doublejump");
1087 g_ctf_reverse = cvar("g_ctf_reverse");
1088 sv_autotaunt = cvar("sv_autotaunt");
1089 sv_taunt = cvar("sv_taunt");
1091 inWarmupStage = cvar("g_warmup");
1092 g_warmup_limit = cvar("g_warmup_limit");
1093 g_warmup_allguns = cvar("g_warmup_allguns");
1094 g_warmup_allow_timeout = cvar("g_warmup_allow_timeout");
1096 if ((g_race && g_race_qualifying == 2) || g_runematch || g_arena || g_assault || cvar("g_campaign"))
1097 inWarmupStage = 0; // these modes cannot work together, sorry
1099 g_pickup_respawntime_weapon = cvar("g_pickup_respawntime_weapon");
1100 g_pickup_respawntime_ammo = cvar("g_pickup_respawntime_ammo");
1101 g_pickup_respawntime_short = cvar("g_pickup_respawntime_short");
1102 g_pickup_respawntime_medium = cvar("g_pickup_respawntime_medium");
1103 g_pickup_respawntime_long = cvar("g_pickup_respawntime_long");
1104 g_pickup_respawntime_powerup = cvar("g_pickup_respawntime_powerup");
1105 g_pickup_respawntimejitter_weapon = cvar("g_pickup_respawntimejitter_weapon");
1106 g_pickup_respawntimejitter_ammo = cvar("g_pickup_respawntimejitter_ammo");
1107 g_pickup_respawntimejitter_short = cvar("g_pickup_respawntimejitter_short");
1108 g_pickup_respawntimejitter_medium = cvar("g_pickup_respawntimejitter_medium");
1109 g_pickup_respawntimejitter_long = cvar("g_pickup_respawntimejitter_long");
1110 g_pickup_respawntimejitter_powerup = cvar("g_pickup_respawntimejitter_powerup");
1112 if (g_minstagib) g_nixnex = g_weaponarena = 0;
1113 if (g_nixnex) g_weaponarena = 0;
1116 g_weaponspeedfactor = cvar("g_weaponspeedfactor");
1117 g_weaponratefactor = cvar("g_weaponratefactor");
1118 g_weapondamagefactor = cvar("g_weapondamagefactor");
1119 g_weaponforcefactor = cvar("g_weaponforcefactor");
1121 g_pickup_shells = cvar("g_pickup_shells");
1122 g_pickup_shells_max = cvar("g_pickup_shells_max");
1123 g_pickup_nails = cvar("g_pickup_nails");
1124 g_pickup_nails_max = cvar("g_pickup_nails_max");
1125 g_pickup_rockets = cvar("g_pickup_rockets");
1126 g_pickup_rockets_max = cvar("g_pickup_rockets_max");
1127 g_pickup_cells = cvar("g_pickup_cells");
1128 g_pickup_cells_max = cvar("g_pickup_cells_max");
1129 g_pickup_fuel = cvar("g_pickup_fuel");
1130 g_pickup_fuel_jetpack = cvar("g_pickup_fuel_jetpack");
1131 g_pickup_fuel_max = cvar("g_pickup_fuel_max");
1132 g_pickup_armorsmall = cvar("g_pickup_armorsmall");
1133 g_pickup_armorsmall_max = cvar("g_pickup_armorsmall_max");
1134 g_pickup_armormedium = cvar("g_pickup_armormedium");
1135 g_pickup_armormedium_max = cvar("g_pickup_armormedium_max");
1136 g_pickup_armorbig = cvar("g_pickup_armorbig");
1137 g_pickup_armorbig_max = cvar("g_pickup_armorbig_max");
1138 g_pickup_armorlarge = cvar("g_pickup_armorlarge");
1139 g_pickup_armorlarge_max = cvar("g_pickup_armorlarge_max");
1140 g_pickup_healthsmall = cvar("g_pickup_healthsmall");
1141 g_pickup_healthsmall_max = cvar("g_pickup_healthsmall_max");
1142 g_pickup_healthmedium = cvar("g_pickup_healthmedium");
1143 g_pickup_healthmedium_max = cvar("g_pickup_healthmedium_max");
1144 g_pickup_healthlarge = cvar("g_pickup_healthlarge");
1145 g_pickup_healthlarge_max = cvar("g_pickup_healthlarge_max");
1146 g_pickup_healthmega = cvar("g_pickup_healthmega");
1147 g_pickup_healthmega_max = cvar("g_pickup_healthmega_max");
1149 g_pinata = cvar("g_pinata");
1151 g_weapon_stay = cvar("g_weapon_stay");
1152 if (!g_weapon_stay && (cvar("deathmatch") == 2))
1155 if not(inWarmupStage)
1156 game_starttime = cvar("g_start_delay");
1158 readplayerstartcvars();
1162 // TODO sound pack system
1165 string precache_sound_builtin (string s) = #19;
1166 void(entity e, float chan, string samp, float vol, float atten) sound_builtin = #8;
1167 string precache_sound(string s)
1169 return precache_sound_builtin(strcat(soundpack, s));
1171 void play2(entity e, string filename)
1173 stuffcmd(e, strcat("play2 ", soundpack, filename, "\n"));
1175 void sound(entity e, float chan, string samp, float vol, float atten)
1177 sound_builtin(e, chan, strcat(soundpack, samp), vol, atten);
1182 string precache_sound (string s) = #19;
1183 void(entity e, float chan, string samp, float vol, float atten) sound_builtin = #8;
1184 float precache_sound_index (string s) = #19;
1186 #define SND_VOLUME 1
1187 #define SND_ATTENUATION 2
1188 #define SND_LARGEENTITY 8
1189 #define SND_LARGESOUND 16
1191 float sound_allowed(float dest, entity e)
1193 // sounds from world may always pass
1196 if (e.classname == "body")
1198 if (e.owner && e.owner != e)
1203 // sounds to self may always pass
1204 if (dest == MSG_ONE)
1205 if (e == msg_entity)
1207 // sounds by players can be removed
1208 if (cvar("bot_sound_monopoly"))
1209 if (clienttype(e) == CLIENTTYPE_REAL)
1211 // anything else may pass
1215 void sound(entity e, float chan, string samp, float vol, float atten)
1217 if (!sound_allowed(MSG_BROADCAST, e))
1219 sound_builtin(e, chan, samp, vol, atten);
1221 void soundtoat(float dest, entity e, vector o, float chan, string samp, float vol, float atten)
1225 if (!sound_allowed(dest, e))
1228 entno = num_for_edict(e);
1229 idx = precache_sound_index(samp);
1234 atten = floor(atten * 64);
1235 vol = floor(vol * 255);
1238 sflags |= SND_VOLUME;
1240 sflags |= SND_ATTENUATION;
1242 sflags |= SND_LARGEENTITY;
1244 sflags |= SND_LARGESOUND;
1246 WriteByte(dest, SVC_SOUND);
1247 WriteByte(dest, sflags);
1248 if (sflags & SND_VOLUME)
1249 WriteByte(dest, vol);
1250 if (sflags & SND_ATTENUATION)
1251 WriteByte(dest, atten);
1252 if (sflags & SND_LARGEENTITY)
1254 WriteShort(dest, entno);
1255 WriteByte(dest, chan);
1259 WriteShort(dest, entno * 8 + chan);
1261 if (sflags & SND_LARGESOUND)
1262 WriteShort(dest, idx);
1264 WriteByte(dest, idx);
1266 WriteCoord(dest, o_x);
1267 WriteCoord(dest, o_y);
1268 WriteCoord(dest, o_z);
1270 void soundto(float dest, entity e, float chan, string samp, float vol, float atten)
1274 if (!sound_allowed(dest, e))
1277 o = e.origin + 0.5 * (e.mins + e.maxs);
1278 soundtoat(dest, e, o, chan, samp, vol, atten);
1280 void soundat(entity e, vector o, float chan, string samp, float vol, float atten)
1282 soundtoat(MSG_BROADCAST, e, o, chan, samp, vol, atten);
1284 void stopsoundto(float dest, entity e, float chan)
1288 if (!sound_allowed(dest, e))
1291 entno = num_for_edict(e);
1296 idx = precache_sound_index("misc/null.wav");
1297 sflags = SND_LARGEENTITY;
1299 sflags |= SND_LARGESOUND;
1300 WriteByte(dest, SVC_SOUND);
1301 WriteByte(dest, sflags);
1302 WriteShort(dest, entno);
1303 WriteByte(dest, chan);
1304 if (sflags & SND_LARGESOUND)
1305 WriteShort(dest, idx);
1307 WriteByte(dest, idx);
1308 WriteCoord(dest, e.origin_x);
1309 WriteCoord(dest, e.origin_y);
1310 WriteCoord(dest, e.origin_z);
1314 WriteByte(dest, SVC_STOPSOUND);
1315 WriteShort(dest, entno * 8 + chan);
1318 void stopsound(entity e, float chan)
1320 if (!sound_allowed(MSG_BROADCAST, e))
1323 stopsoundto(MSG_BROADCAST, e, chan); // unreliable, gets there fast
1324 stopsoundto(MSG_ALL, e, chan); // in case of packet loss
1327 void play2(entity e, string filename)
1329 //stuffcmd(e, strcat("play2 ", filename, "\n"));
1331 soundtoat(MSG_ONE, world, '0 0 0', CHAN_AUTO, filename, VOL_BASE, ATTN_NONE);
1334 .float announcetime;
1335 float announce(entity player, string msg)
1337 if (time > player.announcetime)
1338 if (clienttype(player) == CLIENTTYPE_REAL)
1340 player.announcetime = time + 0.8;
1346 // use this one if you might be causing spam (e.g. from touch functions that might get called more than once per frame)
1347 float spamsound(entity e, float chan, string samp, float vol, float atten)
1349 if (!sound_allowed(MSG_BROADCAST, e))
1352 if (time > e.announcetime)
1354 e.announcetime = time;
1355 sound(e, chan, samp, vol, atten);
1361 void play2team(float t, string filename)
1365 if (cvar("bot_sound_monopoly"))
1368 FOR_EACH_REALPLAYER(head)
1371 play2(head, filename);
1375 void play2all(string samp)
1377 if (cvar("bot_sound_monopoly"))
1380 sound(world, CHAN_AUTO, samp, VOL_BASE, ATTN_NONE);
1383 void PrecachePlayerSounds(string f);
1384 void precache_all_models(string pattern)
1386 float globhandle, i, n;
1389 globhandle = search_begin(pattern, TRUE, FALSE);
1392 n = search_getsize(globhandle);
1393 for (i = 0; i < n; ++i)
1395 //print(search_getfilename(globhandle, i), "\n");
1396 f = search_getfilename(globhandle, i);
1399 if(substring(f, -9,5) == "_lod1")
1401 if(substring(f, -9,5) == "_lod2")
1403 if(!sv_loddistance1)
1405 PrecachePlayerSounds(strcat(f, ".sounds"));
1407 search_end(globhandle);
1412 // gamemode related things
1413 precache_model ("models/misc/chatbubble.spr");
1414 precache_model ("models/misc/teambubble.spr");
1417 precache_model ("models/runematch/curse.mdl");
1418 precache_model ("models/runematch/rune.mdl");
1421 #ifdef TTURRETS_ENABLED
1422 if (cvar("g_turrets"))
1426 // Precache all player models if desired
1427 if (cvar("sv_precacheplayermodels"))
1429 PrecachePlayerSounds("sound/player/default.sounds");
1430 precache_all_models("models/player/*.zym");
1431 precache_all_models("models/player/*.dpm");
1432 precache_all_models("models/player/*.md3");
1433 precache_all_models("models/player/*.psk");
1434 //precache_model("models/player/carni.zym");
1435 //precache_model("models/player/crash.zym");
1436 //precache_model("models/player/grunt.zym");
1437 //precache_model("models/player/headhunter.zym");
1438 //precache_model("models/player/insurrectionist.zym");
1439 //precache_model("models/player/jeandarc.zym");
1440 //precache_model("models/player/lurk.zym");
1441 //precache_model("models/player/lycanthrope.zym");
1442 //precache_model("models/player/marine.zym");
1443 //precache_model("models/player/nexus.zym");
1444 //precache_model("models/player/pyria.zym");
1445 //precache_model("models/player/shock.zym");
1446 //precache_model("models/player/skadi.zym");
1447 //precache_model("models/player/specop.zym");
1448 //precache_model("models/player/visitant.zym");
1451 if (cvar("sv_defaultcharacter"))
1454 s = cvar_string("sv_defaultplayermodel_red");
1458 PrecachePlayerSounds(strcat(s, ".sounds"));
1460 s = cvar_string("sv_defaultplayermodel_blue");
1464 PrecachePlayerSounds(strcat(s, ".sounds"));
1466 s = cvar_string("sv_defaultplayermodel_yellow");
1470 PrecachePlayerSounds(strcat(s, ".sounds"));
1472 s = cvar_string("sv_defaultplayermodel_pink");
1476 PrecachePlayerSounds(strcat(s, ".sounds"));
1478 s = cvar_string("sv_defaultplayermodel");
1482 PrecachePlayerSounds(strcat(s, ".sounds"));
1488 PrecacheGlobalSound((globalsound_step = "misc/footstep0 6"));
1489 PrecacheGlobalSound((globalsound_metalstep = "misc/metalfootstep0 6"));
1492 // gore and miscellaneous sounds
1493 //precache_sound ("misc/h2ohit.wav");
1494 precache_model ("models/hook.md3");
1495 precache_sound ("misc/armorimpact.wav");
1496 precache_sound ("misc/bodyimpact1.wav");
1497 precache_sound ("misc/bodyimpact2.wav");
1498 precache_sound ("misc/gib.wav");
1499 precache_sound ("misc/gib_splat01.wav");
1500 precache_sound ("misc/gib_splat02.wav");
1501 precache_sound ("misc/gib_splat03.wav");
1502 precache_sound ("misc/gib_splat04.wav");
1503 precache_sound ("misc/hit.wav");
1504 PrecacheGlobalSound((globalsound_fall = "misc/hitground 4"));
1505 PrecacheGlobalSound((globalsound_metalfall = "misc/metalhitground 4"));
1506 precache_sound ("misc/null.wav");
1507 precache_sound ("misc/spawn.wav");
1508 precache_sound ("misc/talk.wav");
1509 precache_sound ("misc/teleport.wav");
1510 precache_sound ("misc/poweroff.wav");
1511 precache_sound ("player/lava.wav");
1512 precache_sound ("player/slime.wav");
1515 precache_sound ("misc/jetpack_fly.wav");
1517 // announcer sounds - male
1518 precache_sound ("announcer/male/electrobitch.wav");
1519 precache_sound ("announcer/male/airshot.wav");
1520 precache_sound ("announcer/male/03kills.wav");
1521 precache_sound ("announcer/male/05kills.wav");
1522 precache_sound ("announcer/male/10kills.wav");
1523 precache_sound ("announcer/male/15kills.wav");
1524 precache_sound ("announcer/male/20kills.wav");
1525 precache_sound ("announcer/male/25kills.wav");
1526 precache_sound ("announcer/male/30kills.wav");
1527 precache_sound ("announcer/male/botlike.wav");
1528 precache_sound ("announcer/male/yoda.wav");
1529 precache_sound ("announcer/male/amazing.wav");
1530 precache_sound ("announcer/male/awesome.wav");
1531 precache_sound ("announcer/male/headshot.wav");
1532 precache_sound ("announcer/male/impressive.wav");
1534 // announcer sounds - robotic
1535 precache_sound ("announcer/robotic/prepareforbattle.wav");
1536 precache_sound ("announcer/robotic/begin.wav");
1537 precache_sound ("announcer/robotic/timeoutcalled.wav");
1538 precache_sound ("announcer/robotic/1fragleft.wav");
1539 precache_sound ("announcer/robotic/2fragsleft.wav");
1540 precache_sound ("announcer/robotic/3fragsleft.wav");
1541 precache_sound ("announcer/robotic/terminated.wav");
1544 precache_sound ("announcer/robotic/lastsecond.wav");
1545 precache_sound ("announcer/robotic/narrowly.wav");
1548 precache_model ("models/sprites/0.spr32");
1549 precache_model ("models/sprites/1.spr32");
1550 precache_model ("models/sprites/2.spr32");
1551 precache_model ("models/sprites/3.spr32");
1552 precache_model ("models/sprites/4.spr32");
1553 precache_model ("models/sprites/5.spr32");
1554 precache_model ("models/sprites/6.spr32");
1555 precache_model ("models/sprites/7.spr32");
1556 precache_model ("models/sprites/8.spr32");
1557 precache_model ("models/sprites/9.spr32");
1558 precache_model ("models/sprites/10.spr32");
1559 precache_sound ("announcer/robotic/1.wav");
1560 precache_sound ("announcer/robotic/2.wav");
1561 precache_sound ("announcer/robotic/3.wav");
1562 precache_sound ("announcer/robotic/4.wav");
1563 precache_sound ("announcer/robotic/5.wav");
1564 precache_sound ("announcer/robotic/6.wav");
1565 precache_sound ("announcer/robotic/7.wav");
1566 precache_sound ("announcer/robotic/8.wav");
1567 precache_sound ("announcer/robotic/9.wav");
1568 precache_sound ("announcer/robotic/10.wav");
1570 // common weapon precaches
1571 precache_sound ("weapons/weapon_switch.wav");
1572 precache_sound ("weapons/weaponpickup.wav");
1573 precache_sound ("weapons/unavailable.wav");
1574 if (g_grappling_hook)
1576 precache_sound ("weapons/hook_fire.wav"); // hook
1577 precache_sound ("weapons/hook_impact.wav"); // hook
1580 if (cvar("sv_precacheweapons") || g_nixnex)
1582 //precache weapon models/sounds
1585 while (wep <= WEP_LAST)
1587 weapon_action(wep, WR_PRECACHE);
1592 precache_model("models/elaser.mdl");
1593 precache_model("models/laser.mdl");
1594 precache_model("models/ebomb.mdl");
1597 // Disabled this code because it simply does not work (e.g. ignores bgmvolume, overlaps with "cd loop" controlled tracks).
1599 if (!self.noise && self.music) // quake 3 uses the music field
1600 self.noise = self.music;
1602 // plays music for the level if there is any
1605 precache_sound (self.noise);
1606 ambientsound ('0 0 0', self.noise, VOL_BASE, ATTN_NONE);
1611 // sorry, but using \ in macros breaks line numbers
1612 #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
1613 #define WRITESPECTATABLE_MSG_ONE(statement) WRITESPECTATABLE_MSG_ONE_VARNAME(oldmsg_entity, statement)
1614 #define WRITESPECTATABLE(msg,statement) if(msg == MSG_ONE) { WRITESPECTATABLE_MSG_ONE(statement); } else statement float WRITESPECTATABLE_workaround = 0
1616 vector ExactTriggerHit_mins;
1617 vector ExactTriggerHit_maxs;
1618 float ExactTriggerHit_Recurse()
1624 tracebox('0 0 0', ExactTriggerHit_mins, ExactTriggerHit_maxs, '0 0 0', MOVE_NORMAL, other);
1627 if (trace_ent == self)
1632 se.solid = SOLID_NOT;
1633 f = ExactTriggerHit_Recurse();
1639 float ExactTriggerHit()
1643 if not(self.modelindex)
1647 self.solid = SOLID_BSP;
1648 ExactTriggerHit_mins = other.absmin;
1649 ExactTriggerHit_maxs = other.absmax;
1650 f = ExactTriggerHit_Recurse();
1656 // WARNING: this kills the trace globals
1657 #define EXACTTRIGGER_TOUCH if not(ExactTriggerHit()) return
1658 #define EXACTTRIGGER_INIT InitSolidBSPTrigger(); self.solid = SOLID_TRIGGER
1660 #define INITPRIO_FIRST 0
1661 #define INITPRIO_GAMETYPE 0
1662 #define INITPRIO_GAMETYPE_FALLBACK 1
1663 #define INITPRIO_CVARS 5
1664 #define INITPRIO_FINDTARGET 10
1665 #define INITPRIO_DROPTOFLOOR 20
1666 #define INITPRIO_SETLOCATION 90
1667 #define INITPRIO_LINKDOORS 91
1668 #define INITPRIO_LAST 99
1670 .void(void) initialize_entity;
1671 .float initialize_entity_order;
1672 .entity initialize_entity_next;
1673 entity initialize_entity_first;
1675 void make_safe_for_remove(entity e)
1677 if (e.initialize_entity)
1680 for (ent = initialize_entity_first; ent; )
1682 if ((ent == e) || ((ent.classname == "initialize_entity") && (ent.enemy == e)))
1684 //print("make_safe_for_remove: getting rid of initializer ", etos(ent), "\n");
1685 // skip it in linked list
1688 prev.initialize_entity_next = ent.initialize_entity_next;
1689 ent = prev.initialize_entity_next;
1693 initialize_entity_first = ent.initialize_entity_next;
1694 ent = initialize_entity_first;
1700 ent = ent.initialize_entity_next;
1706 void objerror(string s)
1708 make_safe_for_remove(self);
1709 objerror_builtin(s);
1712 void remove_unsafely(entity e)
1717 void remove_safely(entity e)
1719 make_safe_for_remove(e);
1723 void InitializeEntity(entity e, void(void) func, float order)
1727 if (!e || e.initialize_entity)
1729 // make a proxy initializer entity
1733 e.classname = "initialize_entity";
1737 e.initialize_entity = func;
1738 e.initialize_entity_order = order;
1740 cur = initialize_entity_first;
1743 if (!cur || cur.initialize_entity_order > order)
1745 // insert between prev and cur
1747 prev.initialize_entity_next = e;
1749 initialize_entity_first = e;
1750 e.initialize_entity_next = cur;
1754 cur = cur.initialize_entity_next;
1757 void InitializeEntitiesRun()
1760 startoflist = initialize_entity_first;
1761 initialize_entity_first = world;
1762 for (self = startoflist; self; )
1765 var void(void) func;
1766 e = self.initialize_entity_next;
1767 func = self.initialize_entity;
1768 self.initialize_entity_order = 0;
1769 self.initialize_entity = func_null;
1770 self.initialize_entity_next = world;
1771 if (self.classname == "initialize_entity")
1775 remove_builtin(self);
1778 //dprint("Delayed initialization: ", self.classname, "\n");
1784 .float uncustomizeentityforclient_set;
1785 .void(void) uncustomizeentityforclient;
1786 void(void) SUB_Nullpointer = #0;
1787 void UncustomizeEntitiesRun()
1791 for (self = world; (self = findfloat(self, uncustomizeentityforclient_set, 1)); )
1792 self.uncustomizeentityforclient();
1795 void SetCustomizer(entity e, float(void) customizer, void(void) uncustomizer)
1797 e.customizeentityforclient = customizer;
1798 e.uncustomizeentityforclient = uncustomizer;
1799 e.uncustomizeentityforclient_set = (uncustomizer != SUB_Nullpointer);
1803 #define IFTARGETED if(!self.nottargeted && self.targetname != "")
1806 void Net_LinkEntity(entity e, float docull, float dt, float(entity, float) sendfunc)
1810 if (e.classname == "")
1811 e.classname = "net_linked";
1813 if (e.model == "" || self.modelindex == 0)
1817 setmodel(e, "null");
1821 e.SendEntity = sendfunc;
1822 e.SendFlags = 0xFFFFFF;
1825 e.effects |= EF_NODEPTHTEST;
1829 e.nextthink = time + dt;
1830 e.think = SUB_Remove;
1834 void adaptor_think2touch()
1843 void adaptor_think2use()
1855 // deferred dropping
1856 void DropToFloor_Handler()
1858 droptofloor_builtin();
1859 self.dropped_origin = self.origin;
1864 InitializeEntity(self, DropToFloor_Handler, INITPRIO_DROPTOFLOOR);
1869 float trace_hits_box_a0, trace_hits_box_a1;
1871 float trace_hits_box_1d(float end, float thmi, float thma)
1875 // just check if x is in range
1883 // do the trace with respect to x
1884 // 0 -> end has to stay in thmi -> thma
1885 trace_hits_box_a0 = max(trace_hits_box_a0, min(thmi / end, thma / end));
1886 trace_hits_box_a1 = min(trace_hits_box_a1, max(thmi / end, thma / end));
1887 if (trace_hits_box_a0 > trace_hits_box_a1)
1893 float trace_hits_box(vector start, vector end, vector thmi, vector thma)
1898 // now it is a trace from 0 to end
1900 trace_hits_box_a0 = 0;
1901 trace_hits_box_a1 = 1;
1903 if (!trace_hits_box_1d(end_x, thmi_x, thma_x))
1905 if (!trace_hits_box_1d(end_y, thmi_y, thma_y))
1907 if (!trace_hits_box_1d(end_z, thmi_z, thma_z))
1913 float tracebox_hits_box(vector start, vector mi, vector ma, vector end, vector thmi, vector thma)
1915 return trace_hits_box(start, end, thmi - ma, thma - mi);
1918 float SUB_NoImpactCheck()
1920 // zero hitcontents = this is not the real impact, but either the
1921 // mirror-impact of something hitting the projectile instead of the
1922 // projectile hitting the something, or a touchareagrid one. Neither of
1923 // these stop the projectile from moving, so...
1924 if(trace_dphitcontents == 0)
1926 dprint("A hit happened with zero hit contents... DEBUG THIS, this should never happen for projectiles! Projectile will self-destruct.\n");
1929 if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
1931 if (other == world && self.size != '0 0 0')
1934 tic = self.velocity * sys_ticrate;
1935 tic = tic + normalize(tic) * vlen(self.maxs - self.mins);
1936 traceline(self.origin - tic, self.origin + tic, MOVE_NORMAL, self);
1937 if (trace_fraction >= 1)
1939 dprint("Odd... did not hit...?\n");
1941 else if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_NOIMPACT)
1943 dprint("Detected and prevented the sky-grapple bug.\n");
1951 #define SUB_OwnerCheck() (other && (other == self.owner))
1953 #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)
1955 float MAX_IPBAN_URIS = 16;
1957 float URI_GET_DISCARD = 0;
1958 float URI_GET_IPBAN = 1;
1959 float URI_GET_IPBAN_END = 16;
1961 void URI_Get_Callback(float id, float status, string data)
1963 dprint("Received HTTP request data for id ", ftos(id), "; status is ", ftos(status), "\nData is:\n");
1965 dprint("\nEnd of data.\n");
1967 if (id == URI_GET_DISCARD)
1971 else if (id >= URI_GET_IPBAN && id <= URI_GET_IPBAN_END)
1974 OnlineBanList_URI_Get_Callback(id, status, data);
1978 print("Received HTTP request data for an invalid id ", ftos(id), ".\n");
1982 void print_to(entity e, string s)
1985 sprint(e, strcat(s, "\n"));
2004 for (i = 0; i < MapInfo_count; ++i)
2006 if (MapInfo_Get_ByID(i))
2008 r = stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, "/captimerecord/time")));
2011 h = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, "/captimerecord/netname"));
2012 s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-6, ftos_decimals(r, 2)), " ", h, "\n");
2020 for (i = 0; i < MapInfo_count; ++i)
2022 if (MapInfo_Get_ByID(i))
2024 r = stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, RACE_RECORD, "time")));
2027 h = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, RACE_RECORD, "netname"));
2028 s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-8, TIME_ENCODED_TOSTRING(r)), " ", h, "\n");
2036 for (i = 0; i < MapInfo_count; ++i)
2038 if (MapInfo_Get_ByID(i))
2040 r = stof(db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, CTS_RECORD, "time")));
2043 h = db_get(ServerProgsDB, strcat(MapInfo_Map_bspname, CTS_RECORD, "netname"));
2044 s = strcat(s, strpad(32, MapInfo_Map_bspname), " ", strpad(-8, TIME_ENCODED_TOSTRING(r)), " ", h, "\n");
2050 MapInfo_ClearTemps();
2053 return "No records are available on this server.\n";
2055 return strcat("Records on this server:\n", s);
2058 float MoveToRandomMapLocation(entity e, float goodcontents, float badcontents, float badsurfaceflags, float attempts, float maxaboveground, float minviewdistance)
2061 vector start, org, delta, end, enddown, mstart;
2063 m = e.dphitcontentsmask;
2064 e.dphitcontentsmask = goodcontents | badcontents;
2067 delta = world.maxs - world.mins;
2069 for (i = 0; i < attempts; ++i)
2071 start_x = org_x + random() * delta_x;
2072 start_y = org_y + random() * delta_y;
2073 start_z = org_z + random() * delta_z;
2075 // rule 1: start inside world bounds, and outside
2076 // solid, and don't start from somewhere where you can
2077 // fall down to evil
2078 tracebox(start, e.mins, e.maxs, start - '0 0 1' * delta_z, MOVE_NORMAL, e);
2079 if (trace_fraction >= 1)
2081 if (trace_startsolid)
2083 if (trace_dphitcontents & badcontents)
2085 if (trace_dphitq3surfaceflags & badsurfaceflags)
2088 // rule 2: if we are too high, lower the point
2089 if (trace_fraction * delta_z > maxaboveground)
2090 start = trace_endpos + '0 0 1' * maxaboveground;
2091 enddown = trace_endpos;
2093 // rule 3: make sure we aren't outside the map. This only works
2094 // for somewhat well formed maps. A good rule of thumb is that
2095 // the map should have a convex outside hull.
2096 // these can be traceLINES as we already verified the starting box
2097 mstart = start + 0.5 * (e.mins + e.maxs);
2098 traceline(mstart, mstart + '1 0 0' * delta_x, MOVE_NORMAL, e);
2099 if (trace_fraction >= 1)
2101 traceline(mstart, mstart - '1 0 0' * delta_x, 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 1 0' * delta_y, MOVE_NORMAL, e);
2108 if (trace_fraction >= 1)
2110 traceline(mstart, mstart + '0 0 1' * delta_z, MOVE_NORMAL, e);
2111 if (trace_fraction >= 1)
2114 // find a random vector to "look at"
2115 end_x = org_x + random() * delta_x;
2116 end_y = org_y + random() * delta_y;
2117 end_z = org_z + random() * delta_z;
2118 end = start + normalize(end - start) * vlen(delta);
2120 // rule 4: start TO end must not be too short
2121 tracebox(start, e.mins, e.maxs, end, MOVE_NORMAL, e);
2122 if (trace_startsolid)
2124 if (trace_fraction < minviewdistance / vlen(delta))
2127 // rule 5: don't want to look at sky
2128 if (trace_dphitq3surfaceflags & Q3SURFACEFLAG_SKY)
2131 // rule 6: we must not end up in trigger_hurt
2132 if (tracebox_hits_trigger_hurt(start, e.mins, e.maxs, enddown))
2134 dprint("trigger_hurt! ouch! and nothing else could find it!\n");
2141 e.dphitcontentsmask = m;
2145 setorigin(e, start);
2146 e.angles = vectoangles(end - start);
2147 dprint("Needed ", ftos(i + 1), " attempts\n");
2154 void zcurveparticles(float effectno, vector start, vector end, float end_dz, float spd)
2156 WriteByte(MSG_BROADCAST, SVC_TEMPENTITY);
2157 WriteByte(MSG_BROADCAST, TE_CSQC_ZCURVEPARTICLES);
2158 WriteShort(MSG_BROADCAST, effectno);
2159 WriteCoord(MSG_BROADCAST, start_x);
2160 WriteCoord(MSG_BROADCAST, start_y);
2161 WriteCoord(MSG_BROADCAST, start_z);
2162 WriteCoord(MSG_BROADCAST, end_x);
2163 WriteCoord(MSG_BROADCAST, end_y);
2164 WriteCoord(MSG_BROADCAST, end_z);
2165 WriteCoord(MSG_BROADCAST, end_dz);
2166 WriteShort(MSG_BROADCAST, spd / 16);
2169 void zcurveparticles_from_tracetoss(float effectno, vector start, vector end, vector vel)
2172 vector vecxy, velxy;
2174 vecxy = end - start;
2179 if (vlen(velxy) < 0.000001 * fabs(vel_z))
2181 trailparticles(world, effectno, start, end);
2185 end_dz = vlen(vecxy) / vlen(velxy) * vel_z - (end_z - start_z);
2186 zcurveparticles(effectno, start, end, end_dz, vlen(vel));
2189 string GetGametype(); // g_world.qc
2190 void write_recordmarker(entity pl, float tstart, float dt)
2192 GameLogEcho(strcat(":recordset:", ftos(pl.playerid), ":", ftos(dt)));
2194 // also write a marker into demo files for demotc-race-record-extractor to find
2197 strcat("//", strconv(2, 0, 0, GetGametype()), " RECORD SET ", TIME_ENCODED_TOSTRING(TIME_ENCODE(dt))),
2198 " ", ftos(tstart), " ", ftos(dt), "\n"));
2201 vector shotorg_adjustfromclient(vector vecs, float y_is_right, float allowcenter)
2203 switch(self.owner.cvar_cl_gunalign)
2214 if(allowcenter) // 2: allow center handedness
2227 if(allowcenter) // 2: allow center handedness
2243 vector shotorg_adjust(vector vecs, float y_is_right, float visual)
2248 if (cvar("g_shootfromeye"))
2252 vecs = shotorg_adjustfromclient(vecs, y_is_right, TRUE);
2260 else if (cvar("g_shootfromcenter"))
2264 vecs = shotorg_adjustfromclient(vecs, y_is_right, TRUE);
2272 else if (cvar("g_shootfromclient"))
2274 vecs = shotorg_adjustfromclient(vecs, y_is_right, (cvar("g_shootfromclient") >= 2));
2276 else if ((s = cvar_string("g_shootfromfixedorigin")) != "")
2291 void attach_sameorigin(entity e, entity to, string tag)
2293 vector org, t_forward, t_left, t_up, e_forward, e_up;
2300 org = e.origin - gettaginfo(to, gettagindex(to, tag));
2301 tagscale = pow(vlen(v_forward), -2); // undo a scale on the tag
2302 t_forward = v_forward * tagscale;
2303 t_left = v_right * -tagscale;
2304 t_up = v_up * tagscale;
2306 e.origin_x = org * t_forward;
2307 e.origin_y = org * t_left;
2308 e.origin_z = org * t_up;
2310 // current forward and up directions
2311 if (substring(e.model, 0, 1) == "*") // bmodels have their own rules
2312 e.angles_x = -e.angles_x;
2313 fixedmakevectors(e.angles);
2315 // untransform forward, up!
2316 e_forward_x = v_forward * t_forward;
2317 e_forward_y = v_forward * t_left;
2318 e_forward_z = v_forward * t_up;
2319 e_up_x = v_up * t_forward;
2320 e_up_y = v_up * t_left;
2321 e_up_z = v_up * t_up;
2323 e.angles = fixedvectoangles2(e_forward, e_up);
2324 if (substring(e.model, 0, 1) == "*") // bmodels have their own rules
2325 e.angles_x = -e.angles_x;
2327 setattachment(e, to, tag);
2328 setorigin(e, e.origin);
2331 void detach_sameorigin(entity e)
2334 org = gettaginfo(e, 0);
2335 e.angles = fixedvectoangles2(v_forward, v_up);
2336 if (substring(e.model, 0, 1) == "*") // bmodels have their own rules
2337 e.angles_x = -e.angles_x;
2339 setattachment(e, world, "");
2340 setorigin(e, e.origin);
2343 void follow_sameorigin(entity e, entity to)
2345 e.movetype = MOVETYPE_FOLLOW; // make the hole follow
2346 e.aiment = to; // make the hole follow bmodel
2347 e.punchangle = to.angles; // the original angles of bmodel
2348 e.view_ofs = e.origin - to.origin; // relative origin
2349 e.v_angle = e.angles - to.angles; // relative angles
2352 void unfollow_sameorigin(entity e)
2354 e.movetype = MOVETYPE_NONE;
2357 entity gettaginfo_relative_ent;
2358 vector gettaginfo_relative(entity e, float tag)
2360 if (!gettaginfo_relative_ent)
2362 gettaginfo_relative_ent = spawn();
2363 gettaginfo_relative_ent.effects = EF_NODRAW;
2365 gettaginfo_relative_ent.model = e.model;
2366 gettaginfo_relative_ent.modelindex = e.modelindex;
2367 gettaginfo_relative_ent.frame = e.frame;
2368 return gettaginfo(gettaginfo_relative_ent, tag);
2371 void SoundEntity_StartSound(entity pl, float chan, string samp, float vol, float attn)
2375 if (pl.soundentity.cnt & p)
2377 soundtoat(MSG_ALL, pl.soundentity, gettaginfo(pl.soundentity, 0), chan, samp, vol, attn);
2378 pl.soundentity.cnt |= p;
2381 void SoundEntity_StopSound(entity pl, float chan)
2385 if (pl.soundentity.cnt & p)
2387 stopsoundto(MSG_ALL, pl.soundentity, chan);
2388 pl.soundentity.cnt &~= p;
2392 void SoundEntity_Attach(entity pl)
2394 pl.soundentity = spawn();
2395 pl.soundentity.classname = "soundentity";
2396 pl.soundentity.owner = pl;
2397 setattachment(pl.soundentity, pl, "");
2398 setmodel(pl.soundentity, "null");
2401 void SoundEntity_Detach(entity pl)
2404 for (i = 0; i <= 7; ++i)
2405 SoundEntity_StopSound(pl, i);
2409 float ParseCommandPlayerSlotTarget_firsttoken;
2410 entity GetCommandPlayerSlotTargetFromTokenizedCommand(float tokens, float idx) // idx = start index
2418 ParseCommandPlayerSlotTarget_firsttoken = -1;
2422 if (substring(argv(idx), 0, 1) == "#")
2424 s = substring(argv(idx), 1, -1);
2432 ParseCommandPlayerSlotTarget_firsttoken = idx;
2433 if (s == ftos(stof(s)))
2435 e = edict_num(stof(s));
2436 if (e.flags & FL_CLIENT)
2442 // it must be a nick name
2445 ParseCommandPlayerSlotTarget_firsttoken = idx;
2448 FOR_EACH_CLIENT(head)
2449 if (head.netname == s)
2457 s = strdecolorize(s);
2459 FOR_EACH_CLIENT(head)
2460 if (strdecolorize(head.netname) == s)
2475 float modeleffect_SendEntity(entity to, float sf)
2478 WriteByte(MSG_ENTITY, ENT_CLIENT_MODELEFFECT);
2481 if(self.velocity != '0 0 0')
2483 if(self.angles != '0 0 0')
2485 if(self.avelocity != '0 0 0')
2488 WriteByte(MSG_ENTITY, f);
2489 WriteShort(MSG_ENTITY, self.modelindex);
2490 WriteByte(MSG_ENTITY, self.skin);
2491 WriteByte(MSG_ENTITY, self.frame);
2492 WriteCoord(MSG_ENTITY, self.origin_x);
2493 WriteCoord(MSG_ENTITY, self.origin_y);
2494 WriteCoord(MSG_ENTITY, self.origin_z);
2497 WriteCoord(MSG_ENTITY, self.velocity_x);
2498 WriteCoord(MSG_ENTITY, self.velocity_y);
2499 WriteCoord(MSG_ENTITY, self.velocity_z);
2503 WriteCoord(MSG_ENTITY, self.angles_x);
2504 WriteCoord(MSG_ENTITY, self.angles_y);
2505 WriteCoord(MSG_ENTITY, self.angles_z);
2509 WriteCoord(MSG_ENTITY, self.avelocity_x);
2510 WriteCoord(MSG_ENTITY, self.avelocity_y);
2511 WriteCoord(MSG_ENTITY, self.avelocity_z);
2513 WriteShort(MSG_ENTITY, self.scale * 256.0);
2514 WriteShort(MSG_ENTITY, self.scale2 * 256.0);
2515 WriteByte(MSG_ENTITY, self.teleport_time * 100.0);
2516 WriteByte(MSG_ENTITY, self.fade_time * 100.0);
2517 WriteByte(MSG_ENTITY, self.alpha * 255.0);
2522 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)
2527 e.classname = "modeleffect";
2535 e.teleport_time = t1;
2539 e.scale = s0 / max6(-e.mins_x, -e.mins_y, -e.mins_z, e.maxs_x, e.maxs_y, e.maxs_z);
2543 e.scale2 = s2 / max6(-e.mins_x, -e.mins_y, -e.mins_z, e.maxs_x, e.maxs_y, e.maxs_z);
2546 sz = max(e.scale, e.scale2);
2547 setsize(e, e.mins * sz, e.maxs * sz);
2548 Net_LinkEntity(e, FALSE, 0.1, modeleffect_SendEntity);
2551 void shockwave_spawn(string m, vector org, float sz, float t1, float t2)
2553 return modeleffect_spawn(m, 0, 0, org, '0 0 0', '0 0 0', '0 0 0', 0, sz, 1, t1, t2);