3 ======================================
4 FrikBot X (Version 0.10.1)
5 ======================================
7 This program is in the Public Domain. My crack legal
8 team would like to add:
10 RYAN "FRIKAC" SMITH IS PROVIDING THIS SOFTWARE "AS IS"
11 AND MAKES NO WARRANTY, EXPRESS OR IMPLIED, AS TO THE
12 ACCURACY, CAPABILITY, EFFICIENCY, MERCHANTABILITY, OR
13 FUNCTIONING OF THIS SOFTWARE AND/OR DOCUMENTATION. IN
14 NO EVENT WILL RYAN "FRIKAC" SMITH BE LIABLE FOR ANY
15 GENERAL, CONSEQUENTIAL, INDIRECT, INCIDENTAL,
16 EXEMPLARY, OR SPECIAL DAMAGES, EVEN IF RYAN "FRIKAC"
17 SMITH HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH
18 DAMAGES, IRRESPECTIVE OF THE CAUSE OF SUCH DAMAGES.
20 You accept this software on the condition that you
21 indemnify and hold harmless Ryan "FrikaC" Smith from
22 any and all liability or damages to third parties,
23 including attorney fees, court costs, and other
24 related costs and expenses, arising out of your use
25 of this software irrespective of the cause of said
28 The export from the United States or the subsequent
29 reexport of this software is subject to compliance
30 with United States export control and munitions
31 control restrictions. You agree that in the event you
32 seek to export this software, you assume full
33 responsibility for obtaining all necessary export
34 licenses and approvals and for assuring compliance
35 with applicable reexport restrictions.
37 Any reproduction of this software must contain
38 this notice in its entirety.
40 ======================================
41 These installation instructions only apply to Normal Quake (as does this
42 entire file). For QuakeWorld, please refer to bot_qw.qc
44 --------------------------------------
45 To install on a new mod, do all this:
46 --------------------------------------
47 Place all included bot*.qc files in the subdirectory "frikbot"
48 in your source folder, then...
50 * Add the following lines to progs.src right after the defs.qc line
60 --------------------------------------
61 * Comment out the following functions in defs.qc
62 sound, stuffcmd, sprint, aim, centerprint, setspawnparms
63 WriteByte, WriteChar, WriteShort, WriteLong, WriteCoord
64 WriteAngle, WriteString, WriteEntity
65 --------------------------------------
66 * Add this to worldspawn() in world.qc, right at the very top, before InitBodyQue();
68 --------------------------------------
69 * add this line to StartFrame() in world.qc, at the very top
70 BotFrame(); // FrikBot
71 --------------------------------------
72 * Add these two lines to PlayerPreThink in client.qc at the very top
73 if (BotPreFrame()) // FrikBot
75 --------------------------------------
76 * Add this line to PlayerPostThink in client.qc at the very top
77 if (BotPostFrame()) // FrikBot
79 --------------------------------------
80 * Add the following line to the very top of Client Connect in client.qc
81 ClientInRankings(); // FrikBot
82 --------------------------------------
83 * Add these lines to the very top of ClientDisconnect in client.qc
84 ClientDisconnected(); // FrikBot
85 --------------------------------------
90 // place your qc loaded waypoints here
91 if (mapname == "mattrye1_nex")
96 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
100 bot.qc has become pretty much a header file
101 for all variable in the bot...
103 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
106 // ----- entity fields ---
107 .float wallhug, keys, oldkeys, ishuman;
108 .float b_frags, b_clientno, b_shirt, b_pants;
109 .float priority, ai_time, b_sound, missile_speed;
110 .float portal_time, b_skill, switch_wallhug;
111 .float b_aiflags, b_num, b_chattime;
112 .float b_menu, b_menu_time, b_menu_value;
113 .float route_failed, dyn_flags, dyn_time;
115 .entity temp_way, last_way, phys_obj;
116 .entity target1, target2, target3, target4;
117 .entity _next, _last;
119 .vector b_angle, b_dest, mouse_emu, obs_dir;
120 .vector movevect, b_dir;
124 .vector dest1, dest2;
126 // --------defines-----
127 //float SVC_UPDATENAME = 13;
128 //float SVC_UPDATEFRAGS = 14;
129 //float SVC_UPDATECOLORS = 17;
131 // used for the physics & movement AI
132 float KEY_MOVEUP = 1;
133 float KEY_MOVEDOWN = 2;
134 float KEY_MOVELEFT = 4;
135 float KEY_MOVERIGHT = 8;
136 float KEY_MOVEFORWARD = 16;
137 float KEY_MOVEBACK = 32;
138 float KEY_LOOKUP = 64;
139 float KEY_LOOKDOWN = 128;
140 float KEY_LOOKLEFT = 256;
141 float KEY_LOOKRIGHT = 512;
143 // these are aiflags for waypoints
144 // some overlap to the bot
145 float AI_TELELINK_1 = 1; // link type
146 float AI_TELELINK_2 = 2; // link type
147 float AI_TELELINK_3 = 4; // link type
148 float AI_TELELINK_4 = 8; // link type
149 float AI_DOORFLAG = 16; // read ahead
150 float AI_PRECISION = 32; // read ahead + point
151 float AI_SURFACE = 64; // point
152 float AI_BLIND = 128; // read ahead + point
153 float AI_JUMP = 256; // point + ignore
154 float AI_DIRECTIONAL = 512; // read ahead + ignore
155 float AI_PLAT_BOTTOM = 1024; // read ahead
156 float AI_RIDE_TRAIN = 2048; // read ahead
157 float AI_SUPER_JUMP = 4096; // point + ignore + route test
158 float AI_SNIPER = 8192; // point type
159 float AI_AMBUSH = 16384; // point type
160 float AI_DOOR_NO_OPEN = 32768; // read ahead
161 float AI_DIFFICULT = 65536; // route test
162 float AI_TRACE_TEST = 131072; // route test
164 // these are flags for bots/players (dynamic/editor flags)
165 float AI_OBSTRUCTED = 1;
166 float AI_HOLD_SELECT = 2;
167 float AI_ROUTE_FAILED = 2;
173 float AI_POINT_TYPES = 29152;
174 float AI_READAHEAD_TYPES = 36528;
175 float AI_IGNORE_TYPES = 4864;
178 float WM_DYNAMIC = 1;
179 float WM_LOADING = 2;
182 float WM_EDITOR_DYNAMIC = 5;
183 float WM_EDITOR_DYNLINK = 6;
186 float OPT_SAVEBOTS = 1;
187 float OPT_NOCHAT = 2;
189 // -------globals-----
190 float active_clients;
191 float max_clients, real_frametime;
192 float bot_count, b_options;
193 float waypoint_mode, dump_mode;
194 float waypoints, direct_route;
195 float sv_friction, sv_gravity;
196 float sv_accelerate, sv_maxspeed, sv_stopspeed;
199 entity b_temp1, b_temp2, b_temp3;
200 entity player_head, phys_head, way_head;
201 float busy_waypoints;
202 float saved_bots, saved_skills1, saved_skills2, current_bots;
204 // -------ProtoTypes------
206 void() ClientConnect;
207 void() ClientDisconnect;
211 float(float clientno) ClientBitFlag;
212 float() ClientNextAvailable;
213 void(float whichteam, float whatbot, float whatskill) BotConnect;
214 void(entity bot) BotDisconnect;
215 void(float clientno) BotInvalidClientNo;
216 void(entity who) UpdateClient;
219 void() DynamicWaypoint;
220 entity(vector org) make_waypoint;
224 void(entity this, float direct) bot_get_path;
225 void() WaypointThink;
226 entity(entity start) FindWayPoint;
228 // physics & movement
229 float(entity e) bot_can_rj;
231 void() frik_bot_roam;
232 float(vector weird) frik_walkmove;
233 void() frik_movetogoal;
234 void() frik_obstacles;
235 float(float flag) frik_recognize_plat;
236 float(vector sdir) frik_KeysForDir;
237 void(vector whichway, float danger) frik_obstructed;
238 void() SV_Physics_Client;
239 void() SV_ClientThink;
243 string() PickARandomName;
244 float(entity targ) fov;
245 float(float y1, float y2) angcomp;
246 float(entity targ1, entity targ2) wisible;
247 float(entity targ) sisible;
248 float(entity targ) fisible;
249 vector(entity ent) realorigin;
250 void(entity ent) target_drop;
251 void(entity ent) target_add;
254 void(entity targ, float success) bot_lost;
255 string(float r) BotName;
256 float(float v) frik_anglemod;
258 void(float tpic) bot_start_topic;
264 void() bot_menu_display;
267 // ----------Commands---------
268 void(entity e, float chan, string samp, float vol, float atten) frik_sound = #8;
269 void(entity client, string s) frik_stuffcmd = #21;
270 void(entity client, string s) frik_sprint = #24;
271 vector(entity e, float sped) frik_aim = #44;
272 void(entity client, string s) frik_centerprint = #73;
273 void(entity e) frik_setspawnparms = #78;
274 void(float to, float f) frik_WriteByte = #52;
275 void(float to, float f) frik_WriteChar = #53;
276 void(float to, float f) frik_WriteShort = #54;
277 void(float to, float f) frik_WriteLong = #55;
278 void(float to, float f) frik_WriteCoord = #56;
279 void(float to, float f) frik_WriteAngle = #57;
280 void(float to, string s) frik_WriteString = #58;
281 void(float to, entity s) frik_WriteEntity = #59;
283 void(entity client, string s1, string s2, string s3, string s4, string s5, string s6, string s7)
284 frik_big_centerprint = #73;
286 //----------------------------------------------------------------------------
289 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
291 Function redclarations. These allow function
292 designed to work for clients (sprint, so forth)
293 to mainly not complain when working with a bot
295 Although these shouldn't be needed anymore,
296 as the bots truly are clients now, if you don't
297 stop the SZ_ buffer from filling up by disabling
298 direct messages to the bots, it crashes quake :-(
300 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
302 void(entity client, string s) stuffcmd =
304 if (client.ishuman == 1)
305 frik_stuffcmd(client, s);
306 b_temp1 = player_head;
310 if (b_temp1.classname == "botcam")
312 if ((b_temp1.enemy == client) && b_temp1.ishuman)
313 frik_stuffcmd(b_temp1, s);
315 b_temp1 = b_temp1._next;
319 void(entity e) setspawnparms =
322 frik_setspawnparms(e);
325 b_temp1 = player_head;
330 frik_setspawnparms(b_temp1);
333 b_temp1 = b_temp1._next;
338 void(entity client, string s) sprint =
340 if (client.ishuman == 1)
341 frik_sprint(client, s);
342 b_temp1 = player_head;
346 if (b_temp1.classname == "botcam")
348 if ((b_temp1.enemy == client) && b_temp1.ishuman)
349 frik_sprint(b_temp1, s);
351 b_temp1 = b_temp1._next;
355 void(entity client, string s) centerprint =
357 if (client.ishuman == 1)
358 frik_centerprint(client, s);
359 b_temp1 = player_head;
363 if (b_temp1.classname == "botcam")
365 if ((b_temp1.enemy == client) && b_temp1.ishuman)
366 frik_centerprint(b_temp1, s);
368 b_temp1 = b_temp1._next;
372 vector(entity e, float sped) aim =
374 e.missile_speed = sped;
375 return frik_aim(e, sped);
378 void(entity e, float chan, string samp, float vol, float atten) sound =
381 frik_sound(e, chan, samp, vol, atten);
382 if (samp == "items/inv3.wav")
384 else if (e.classname == "player")
385 e.b_sound = time + 1;
386 else if (other.classname == "player")
387 other.b_sound = time + 1;
390 void(float to, float f) WriteByte =
392 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
394 frik_WriteByte(to, f);
396 void(float to, float f) WriteChar =
398 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
400 frik_WriteChar(to, f);
402 void(float to, float f) WriteShort =
404 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
406 frik_WriteShort(to, f);
408 void(float to, float f) WriteLong =
410 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
412 frik_WriteLong(to, f);
414 void(float to, float f) WriteCoord =
416 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
418 frik_WriteCoord(to, f);
420 void(float to, float f) WriteAngle =
422 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
424 frik_WriteAngle(to, f);
426 void(float to, string s) WriteString =
428 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
430 frik_WriteString(to, s);
432 void(float to, entity s) WriteEntity =
434 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
436 frik_WriteEntity(to, s);
439 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
441 Bot Cam, see what the bot sees (or any other player)
443 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
448 if (self.classname != "botcam")
450 setorigin(self, self.enemy.origin);
451 self.items = self.enemy.items;
452 self.weapon = self.enemy.weapon;
453 self.weaponmodel = self.enemy.weaponmodel;
454 self.currentammo = self.enemy.currentammo;
455 self.weaponframe = self.enemy.weaponframe;
456 self.ammo_shells = self.enemy.ammo_shells;
457 self.ammo_nails = self.enemy.ammo_nails;
458 self.ammo_rockets= self.enemy.ammo_rockets;
459 self.ammo_cells = self.enemy.ammo_cells;
460 self.view_ofs = self.enemy.view_ofs;
461 self.health = self.enemy.health;
462 self.armorvalue = self.enemy.armorvalue;
463 self.dmg_take = self.enemy.dmg_take;
464 self.dmg_save = self.enemy.dmg_save;
465 self.dmg_inflictor = self.enemy.dmg_inflictor;
466 self.punchangle = self.enemy.punchangle;
467 self.deadflag = self.enemy.deadflag;
469 WriteByte (MSG_ONE,5);
470 WriteEntity (MSG_ONE, self.enemy);
471 WriteByte (MSG_ONE, 10);
472 WriteAngle (MSG_ONE,self.enemy.v_angle_x);
473 WriteAngle (MSG_ONE,self.enemy.v_angle_y);
474 WriteAngle (MSG_ONE,self.enemy.v_angle_z);
485 // sloppy cycling code
486 if (self.classname != "botcam")
488 self.enemy = player_head;
493 self.enemy = self.enemy._next;
494 while (self.enemy.classname == "botcam");
496 if (self.enemy == self)
499 self.enemy = self.enemy._next;
500 while (self.enemy.classname == "botcam");
503 self.classname = "botcam";
504 self.solid = SOLID_NOT;
505 self.movetype = MOVETYPE_NONE;
506 self.takedamage = DAMAGE_NO;
511 sprint(self, "No one left to track!\n");
513 WriteByte (MSG_ONE,5);
514 WriteEntity (MSG_ONE, self);
518 if (!self.enemy.ishuman)
520 self.enemy.dmg_take = 0;
521 self.enemy.dmg_save = 0;
523 sprint(self, "Now tracking ");
524 sprint(self, self.enemy.netname);
531 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
533 Stuff mentioned up top
534 it just links the bot into the mod
536 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
539 void() ClientFixRankings =
542 if (self.switch_wallhug > time)
544 self.switch_wallhug = 0;
546 b_temp2 = nextent(world);
549 while (cno < max_clients)
551 if ((!b_temp2.ishuman) && (active_clients & ClientBitFlag(cno)))
552 UpdateClient(b_temp2);
554 b_temp2 = nextent(b_temp2);
558 void() ClientInRankings =
562 player_head._last = self;
564 self._next = player_head;
571 while (b_temp2 != world && b_temp2.owner != self)
572 b_temp2 = b_temp2._next;
573 self.phys_obj = b_temp2;
576 if (self.ishuman == 2)
578 self.ishuman = FALSE;
581 cno = self.colormap - 1;
582 BotInvalidClientNo (cno);
583 active_clients = active_clients | ClientBitFlag(cno);
585 self.b_clientno = cno;
587 self.switch_wallhug = time + 1;
591 void() ClientDisconnected =
593 if (player_head == self)
594 player_head = self._next;
596 self._next._last = self._last;
598 self._last._next = self._next;
600 active_clients = active_clients - active_clients & ClientBitFlag(self.b_clientno);
603 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
605 BotPreFrame & BotPostFrame, used to make the
606 bot easier to install
608 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
610 float () BotPreFrame =
612 if (self.b_clientno == -1)
616 if (self.switch_wallhug)
618 if (self.classname == "botcam")
621 if (self.b_frags != self.frags)
624 if (self.b_frags > self.frags)
626 if (pointcontents(self.origin) == CONTENT_LAVA)
633 self.b_frags = self.frags;
638 float () BotPostFrame =
640 if (self.b_clientno == -1)
645 if (waypoint_mode > WM_LOADED)
657 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
661 The rest of this code is in bot_misc.qc
663 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
665 void(string h) BotSay = // simulate talking by composing a 'chat' message
667 WriteByte(MSG_ALL, 8);
668 WriteByte(MSG_ALL, 1);
669 WriteString(MSG_ALL, self.netname);
670 WriteByte(MSG_ALL, 8);
671 WriteByte(MSG_ALL, 2);
672 WriteString(MSG_ALL, h);
676 WriteByte(MSG_ALL, 8);
677 WriteByte(MSG_ALL, 1);
678 WriteString(MSG_ALL, self.netname);
680 void(string h) BotSay2 =
682 WriteByte(MSG_ALL, 8);
683 WriteByte(MSG_ALL, 2);
684 WriteString(MSG_ALL, h);
686 void(string h) BotSayTeam =
694 if (t.team == self.team)
697 WriteByte(MSG_ONE, 8);
698 WriteByte(MSG_ONE, 1);
699 WriteByte(MSG_ONE, 40);
700 WriteString(MSG_ONE, self.netname);
701 WriteByte(MSG_ONE, 8);
702 WriteByte(MSG_ONE, 2);
703 WriteByte(MSG_ONE, 41);
704 WriteString(MSG_ONE, h);
710 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
714 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
720 local entity ent, fisent;
723 // spawn entities for the physics
724 ent = nextent(world);
729 max_clients = max_clients + 1;
732 if (max_clients > 16)
735 ent = nextent(world);
737 while (numents < max_clients)
742 fisent._next = phys_head;
743 phys_head._last = fisent;
745 ent.phys_obj = phys_head;
746 phys_head.classname = "phys_obj";
747 phys_head.owner = ent;
748 numents = numents + 1;
751 precache_model("progs/s_light.spr");
752 precache_model("progs/s_bubble.spr");
754 b_options = cvar("saved1");
755 if (coop || (b_options & OPT_SAVEBOTS))
757 saved_bots = cvar("scratch1");
758 saved_skills1 = cvar("scratch2");
759 saved_skills2 = cvar("scratch3");
761 cvar_set ("saved4", "0");
764 localcmd("exec maps/");
767 waypoint_mode = WM_DYNAMIC;
771 waypoint_mode = WM_LOADED;
776 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
778 Rankings 'utilities'. Written by Alan Kivlin,
779 this code just fools clients by sending precisely
780 the same network messages as when a real player
781 signs on to the server.
783 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
787 void(entity who) UpdateClient =
789 WriteByte (MSG_ALL, SVC_UPDATENAME);
790 WriteByte (MSG_ALL, who.b_clientno);
791 WriteString (MSG_ALL, who.netname);
792 WriteByte (MSG_ALL, SVC_UPDATECOLORS);
793 WriteByte (MSG_ALL, who.b_clientno);
794 WriteByte (MSG_ALL, who.b_shirt * 16 + who.b_pants);
795 WriteByte (MSG_ALL, SVC_UPDATEFRAGS);
796 WriteByte (MSG_ALL, who.b_clientno);
797 WriteShort (MSG_ALL, who.frags);
800 float(float clientno) ClientBitFlag =
802 // bigger, but faster
805 else if (clientno == 1)
807 else if (clientno == 2)
809 else if (clientno == 3)
811 else if (clientno == 4)
813 else if (clientno == 5)
815 else if (clientno == 6)
817 else if (clientno == 7)
819 else if (clientno == 8)
821 else if (clientno == 9)
823 else if (clientno == 10)
825 else if (clientno == 11)
827 else if (clientno == 12)
829 else if (clientno == 13)
831 else if (clientno == 14)
833 else if (clientno == 15)
838 float() ClientNextAvailable =
840 local float clientno;
842 clientno = max_clients;
845 clientno = clientno - 1;
847 if(!(active_clients & ClientBitFlag(clientno)))
855 void(entity e1, entity e2, float flag) DeveloperLightning =
857 // used to show waypoint links for debugging
858 WriteByte (MSG_BROADCAST, 23);
860 WriteByte (MSG_BROADCAST, 6);
862 WriteByte (MSG_BROADCAST, 13);
863 WriteEntity (MSG_BROADCAST, e2);
864 WriteCoord (MSG_BROADCAST, e1.origin_x);
865 WriteCoord (MSG_BROADCAST, e1.origin_y);
866 WriteCoord (MSG_BROADCAST, e1.origin_z);
867 WriteCoord (MSG_BROADCAST, e2.origin_x);
868 WriteCoord (MSG_BROADCAST, e2.origin_y);
869 WriteCoord (MSG_BROADCAST, e2.origin_z);
873 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
879 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
882 float(float tcolor) FindAnotherColor =
884 local float bestbet, scolor, pcount, bestp;
889 if (scolor != tcolor)
891 b_temp2 = player_head;
893 while(b_temp2 != world)
895 if (b_temp2.team == scolor + 1)
897 b_temp2 = b_temp2._next;
899 if ((pcount < bestp) && pcount)
910 while (bestbet == tcolor)
912 bestbet = floor(random() * 13);
919 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
921 BotConnect and related functions.
923 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
925 entity(float num) GetClientEntity =
933 upsy = nextent(upsy);
938 void(float whichteam, float whatbot, float whatskill) BotConnect =
944 f = ClientNextAvailable();
948 bprint("Unable to connect a bot, server is full.\n");
954 active_clients = active_clients | ClientBitFlag(f);
955 bot_count = bot_count + 1;
956 self = GetClientEntity(f);
960 self.colormap = f + 1;
962 self.netname = BotName(whatbot);
964 self.netname = PickARandomName();
967 // players can set skill all weird, so leave these checks in
968 whatskill = rint(whatskill);
971 else if (whatskill < 0)
973 self.b_skill = whatskill;
975 if (teamplay && !coop)
978 self.b_pants = FindAnotherColor(uself.team - 1);
980 self.b_pants = uself.team - 1;
981 self.b_shirt = self.b_pants;
984 self.team = self.b_pants + 1;
991 // this is risky... could corrupt .way files if done wrong
992 // If you're not the gambling type, comment this out
994 f = ClientBitFlag(self.b_num - 1);
995 current_bots = current_bots | f;
998 saved_skills1 = (saved_skills1 & (65536 - (3 * f)) | (self.b_skill * f));
1001 f = ClientBitFlag(self.b_num - 9);
1002 saved_skills2 = (saved_skills2 & (65536 - (3 * f)) | (self.b_skill * f));
1005 h = ftos(current_bots);
1006 cvar_set("scratch1", h);
1007 h = ftos(saved_skills1);
1008 cvar_set("scratch2", h);
1009 h = ftos(saved_skills2);
1010 cvar_set("scratch3", h);
1015 void(entity bot) BotDisconnect =
1022 bot_count = bot_count - 1;
1023 current_bots = current_bots - (current_bots & ClientBitFlag(self.b_num - 1));
1024 h = ftos(current_bots);
1025 cvar_set("scratch1", h);
1030 if (self.b_clientno != -1)
1032 // the bot's client number is not in use by a real player so we
1033 // must remove it's entry in the rankings
1034 // Quake engine sets all fields to 0, can only do the most important here
1035 self.b_frags = self.frags = 0;
1037 self.classname = "";
1040 self.armorvalue = 0;
1041 self.weaponmodel = "";
1044 self.ammo_shells = self.ammo_nails = self.ammo_rockets = self.ammo_cells = 0;
1046 active_clients = active_clients - (active_clients & ClientBitFlag(self.b_clientno));
1047 self.b_clientno = -1;
1052 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1055 kicks a bot if a player connects and takes the bot's space
1057 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1060 void(float clientno) BotInvalidClientNo =
1064 bot = GetClientEntity(clientno);
1065 if(bot.b_clientno > 0)
1069 bot.b_clientno = -1;
1071 active_clients = active_clients | ClientBitFlag(self.b_clientno);
1072 BotConnect(0, bot.b_num, bot.b_skill);
1079 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1081 Waypoint Loading from file
1083 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1085 void() LoadWaypoint =
1090 org_x = cvar("saved1");
1091 org_y = cvar("saved2");
1092 org_z = cvar("saved3");
1094 tep = make_waypoint(org);
1098 tep.b_aiflags = floor(r / 4);
1099 tep.b_pants = cvar("scratch1");
1100 tep.b_skill = cvar("scratch2");
1101 tep.b_shirt = cvar("scratch3");
1102 tep.b_frags = cvar("scratch4");
1109 if ((waypoint_mode == WM_DYNAMIC) || (waypoint_mode == WM_LOADED))
1113 if (saved_bots & 1) BotConnect(0, 1, saved_skills1 & 3);
1114 if (saved_bots & 2) BotConnect(0, 2, (saved_skills1 & 12) / 4);
1115 if (saved_bots & 4) BotConnect(0, 3, (saved_skills1 & 48) / 16);
1116 if (saved_bots & 8) BotConnect(0, 4, (saved_skills1 & 192) / 64);
1117 if (saved_bots & 16) BotConnect(0, 5, (saved_skills1 & 768) / 256);
1118 if (saved_bots & 32) BotConnect(0, 6, (saved_skills1 & 3072) / 1024);
1119 if (saved_bots & 64) BotConnect(0, 7, (saved_skills1 & 12288) / 4096);
1120 if (saved_bots & 128) BotConnect(0, 8, (saved_skills1 & 49152) / 16384);
1121 if (saved_bots & 256) BotConnect(0, 9, saved_skills2 & 3);
1122 if (saved_bots & 512) BotConnect(0, 10, (saved_skills2 & 12) / 4);
1123 if (saved_bots & 1024) BotConnect(0, 11, (saved_skills2& 48) / 16);
1124 if (saved_bots & 2048) BotConnect(0, 12, (saved_skills2 & 192) / 64);
1125 if (saved_bots & 4096) BotConnect(0, 13, (saved_skills2 & 768) / 256);
1126 if (saved_bots & 8192) BotConnect(0, 14, (saved_skills2 & 3072) / 1024);
1127 if (saved_bots & 16384) BotConnect(0, 15, (saved_skills2 & 12288) / 4096);
1128 if (saved_bots & 32768) BotConnect(0, 16, (saved_skills2 & 49152) / 16384);
1135 void() WaypointWatch =
1137 // Waypoint Baywatch
1138 local float bigboobs;
1141 if (max_clients < 2)
1143 if (waypoint_mode != WM_UNINIT)
1145 bigboobs = cvar("saved4");
1148 if ((bigboobs & 3) == 1)
1150 else if ((bigboobs & 3) == 3)
1153 h = ftos(b_options);
1154 cvar_set("saved1", h);
1155 cvar_set("saved4", "0");
1156 cvar_set("scratch1", "0");
1157 waypoint_mode = WM_LOADED;
1161 waypoint_mode = WM_LOADING;
1162 cvar_set("saved4", "0");
1170 // for the sake of speed
1171 sv_maxspeed = cvar("sv_maxspeed");
1172 sv_gravity = cvar("sv_gravity");
1173 sv_friction = cvar("sv_friction");
1174 sv_accelerate = cvar("sv_accelerate");
1175 sv_stopspeed = cvar("sv_stopspeed");
1176 real_frametime = frametime; // in NQ this is alright
1178 self = nextent(world);
1180 while (num < max_clients)
1182 if (self.ishuman == FALSE)
1184 if (active_clients & ClientBitFlag(num))
1189 SV_Physics_Client();
1192 self = nextent(self);
1202 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1204 Bot Impulses. Allows the player to perform bot
1207 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1210 void() BotImpulses =
1214 if (self.impulse == 100)
1217 BotConnect(0, 0, f);
1219 else if (self.impulse == 101)
1222 BotConnect(1, 0, f);
1224 else if (self.impulse == 102)
1226 else if (self.impulse == 103)
1228 else if (self.impulse == 104)