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
95 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
99 bot.qc has become pretty much a header file
100 for all variable in the bot...
102 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
105 // ----- entity fields ---
106 .float wallhug, keys, oldkeys, ishuman;
107 .float b_frags, b_clientno, b_shirt, b_pants;
108 .float priority, ai_time, b_sound, missile_speed;
109 .float portal_time, b_skill, switch_wallhug;
110 .float b_aiflags, b_num, b_chattime;
111 .float b_menu, b_menu_time, b_menu_value;
112 .float route_failed, dyn_flags, dyn_time;
114 .entity temp_way, last_way, phys_obj;
115 .entity target1, target2, target3, target4;
116 .entity _next, _last;
118 .vector b_angle, b_dest, mouse_emu, obs_dir;
119 .vector movevect, b_dir;
123 .vector dest1, dest2;
125 // --------defines-----
126 //float SVC_UPDATENAME = 13;
127 //float SVC_UPDATEFRAGS = 14;
128 //float SVC_UPDATECOLORS = 17;
130 // used for the physics & movement AI
131 float KEY_MOVEUP = 1;
132 float KEY_MOVEDOWN = 2;
133 float KEY_MOVELEFT = 4;
134 float KEY_MOVERIGHT = 8;
135 float KEY_MOVEFORWARD = 16;
136 float KEY_MOVEBACK = 32;
137 float KEY_LOOKUP = 64;
138 float KEY_LOOKDOWN = 128;
139 float KEY_LOOKLEFT = 256;
140 float KEY_LOOKRIGHT = 512;
142 // these are aiflags for waypoints
143 // some overlap to the bot
144 float AI_TELELINK_1 = 1; // link type
145 float AI_TELELINK_2 = 2; // link type
146 float AI_TELELINK_3 = 4; // link type
147 float AI_TELELINK_4 = 8; // link type
148 float AI_DOORFLAG = 16; // read ahead
149 float AI_PRECISION = 32; // read ahead + point
150 float AI_SURFACE = 64; // point
151 float AI_BLIND = 128; // read ahead + point
152 float AI_JUMP = 256; // point + ignore
153 float AI_DIRECTIONAL = 512; // read ahead + ignore
154 float AI_PLAT_BOTTOM = 1024; // read ahead
155 float AI_RIDE_TRAIN = 2048; // read ahead
156 float AI_SUPER_JUMP = 4096; // point + ignore + route test
157 float AI_SNIPER = 8192; // point type
158 float AI_AMBUSH = 16384; // point type
159 float AI_DOOR_NO_OPEN = 32768; // read ahead
160 float AI_DIFFICULT = 65536; // route test
161 float AI_TRACE_TEST = 131072; // route test
163 // these are flags for bots/players (dynamic/editor flags)
164 float AI_OBSTRUCTED = 1;
165 float AI_HOLD_SELECT = 2;
166 float AI_ROUTE_FAILED = 2;
172 float AI_POINT_TYPES = 29152;
173 float AI_READAHEAD_TYPES = 36528;
174 float AI_IGNORE_TYPES = 4864;
177 float WM_DYNAMIC = 1;
178 float WM_LOADING = 2;
181 float WM_EDITOR_DYNAMIC = 5;
182 float WM_EDITOR_DYNLINK = 6;
185 float OPT_SAVEBOTS = 1;
186 float OPT_NOCHAT = 2;
188 // -------globals-----
189 float active_clients;
190 float max_clients, real_frametime;
191 float bot_count, b_options;
192 float waypoint_mode, dump_mode;
193 float waypoints, direct_route;
194 float sv_friction, sv_gravity;
195 float sv_accelerate, sv_maxspeed, sv_stopspeed;
198 entity b_temp1, b_temp2, b_temp3;
199 entity player_head, phys_head, way_head;
200 float busy_waypoints;
201 float saved_bots, saved_skills1, saved_skills2, current_bots;
203 // -------ProtoTypes------
205 void() ClientConnect;
206 void() ClientDisconnect;
210 float(float clientno) ClientBitFlag;
211 float() ClientNextAvailable;
212 void(float whichteam, float whatbot, float whatskill) BotConnect;
213 void(entity bot) BotDisconnect;
214 void(float clientno) BotInvalidClientNo;
215 void(entity who) UpdateClient;
218 void() DynamicWaypoint;
219 entity(vector org) make_waypoint;
223 void(entity this, float direct) bot_get_path;
224 void() WaypointThink;
225 entity(entity start) FindWayPoint;
227 // physics & movement
228 float(entity e) bot_can_rj;
230 void() frik_bot_roam;
231 float(vector weird) frik_walkmove;
232 void() frik_movetogoal;
233 void() frik_obstacles;
234 float(float flag) frik_recognize_plat;
235 float(vector sdir) frik_KeysForDir;
236 void(vector whichway, float danger) frik_obstructed;
237 void() SV_Physics_Client;
238 void() SV_ClientThink;
242 string() PickARandomName;
243 float(entity targ) fov;
244 float(float y1, float y2) angcomp;
245 float(entity targ1, entity targ2) wisible;
246 float(entity targ) sisible;
247 float(entity targ) fisible;
248 vector(entity ent) realorigin;
249 void(entity ent) target_drop;
250 void(entity ent) target_add;
253 void(entity targ, float success) bot_lost;
254 string(float r) BotName;
255 float(float v) frik_anglemod;
257 void(float tpic) bot_start_topic;
263 void() bot_menu_display;
266 // ----------Commands---------
267 void(entity e, float chan, string samp, float vol, float atten) frik_sound = #8;
268 void(entity client, string s) frik_stuffcmd = #21;
269 void(entity client, string s) frik_sprint = #24;
270 vector(entity e, float sped) frik_aim = #44;
271 void(entity client, string s) frik_centerprint = #73;
272 void(entity e) frik_setspawnparms = #78;
273 void(float to, float f) frik_WriteByte = #52;
274 void(float to, float f) frik_WriteChar = #53;
275 void(float to, float f) frik_WriteShort = #54;
276 void(float to, float f) frik_WriteLong = #55;
277 void(float to, float f) frik_WriteCoord = #56;
278 void(float to, float f) frik_WriteAngle = #57;
279 void(float to, string s) frik_WriteString = #58;
280 void(float to, entity s) frik_WriteEntity = #59;
282 void(entity client, string s1, string s2, string s3, string s4, string s5, string s6, string s7)
283 frik_big_centerprint = #73;
285 //----------------------------------------------------------------------------
288 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
290 Function redclarations. These allow function
291 designed to work for clients (sprint, so forth)
292 to mainly not complain when working with a bot
294 Although these shouldn't be needed anymore,
295 as the bots truly are clients now, if you don't
296 stop the SZ_ buffer from filling up by disabling
297 direct messages to the bots, it crashes quake :-(
299 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
301 void(entity client, string s) stuffcmd =
303 if (client.ishuman == 1)
304 frik_stuffcmd(client, s);
305 b_temp1 = player_head;
309 if (b_temp1.classname == "botcam")
311 if ((b_temp1.enemy == client) && b_temp1.ishuman)
312 frik_stuffcmd(b_temp1, s);
314 b_temp1 = b_temp1._next;
318 void(entity e) setspawnparms =
321 frik_setspawnparms(e);
324 b_temp1 = player_head;
329 frik_setspawnparms(b_temp1);
332 b_temp1 = b_temp1._next;
337 void(entity client, string s) sprint =
339 if (client.ishuman == 1)
340 frik_sprint(client, s);
341 b_temp1 = player_head;
345 if (b_temp1.classname == "botcam")
347 if ((b_temp1.enemy == client) && b_temp1.ishuman)
348 frik_sprint(b_temp1, s);
350 b_temp1 = b_temp1._next;
354 void(entity client, string s) centerprint =
356 if (client.ishuman == 1)
357 frik_centerprint(client, s);
358 b_temp1 = player_head;
362 if (b_temp1.classname == "botcam")
364 if ((b_temp1.enemy == client) && b_temp1.ishuman)
365 frik_centerprint(b_temp1, s);
367 b_temp1 = b_temp1._next;
371 vector(entity e, float sped) aim =
373 e.missile_speed = sped;
374 return frik_aim(e, sped);
377 void(entity e, float chan, string samp, float vol, float atten) sound =
380 frik_sound(e, chan, samp, vol, atten);
381 if (samp == "items/inv3.wav")
383 else if (e.classname == "player")
384 e.b_sound = time + 1;
385 else if (other.classname == "player")
386 other.b_sound = time + 1;
389 void(float to, float f) WriteByte =
391 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
393 frik_WriteByte(to, f);
395 void(float to, float f) WriteChar =
397 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
399 frik_WriteChar(to, f);
401 void(float to, float f) WriteShort =
403 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
405 frik_WriteShort(to, f);
407 void(float to, float f) WriteLong =
409 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
411 frik_WriteLong(to, f);
413 void(float to, float f) WriteCoord =
415 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
417 frik_WriteCoord(to, f);
419 void(float to, float f) WriteAngle =
421 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
423 frik_WriteAngle(to, f);
425 void(float to, string s) WriteString =
427 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
429 frik_WriteString(to, s);
431 void(float to, entity s) WriteEntity =
433 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
435 frik_WriteEntity(to, s);
438 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
440 Bot Cam, see what the bot sees (or any other player)
442 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
447 if (self.classname != "botcam")
449 setorigin(self, self.enemy.origin);
450 self.items = self.enemy.items;
451 self.weapon = self.enemy.weapon;
452 self.weaponmodel = self.enemy.weaponmodel;
453 self.currentammo = self.enemy.currentammo;
454 self.weaponframe = self.enemy.weaponframe;
455 self.ammo_shells = self.enemy.ammo_shells;
456 self.ammo_nails = self.enemy.ammo_nails;
457 self.ammo_rockets= self.enemy.ammo_rockets;
458 self.ammo_cells = self.enemy.ammo_cells;
459 self.view_ofs = self.enemy.view_ofs;
460 self.health = self.enemy.health;
461 self.armorvalue = self.enemy.armorvalue;
462 self.dmg_take = self.enemy.dmg_take;
463 self.dmg_save = self.enemy.dmg_save;
464 self.dmg_inflictor = self.enemy.dmg_inflictor;
465 self.punchangle = self.enemy.punchangle;
466 self.deadflag = self.enemy.deadflag;
468 WriteByte (MSG_ONE,5);
469 WriteEntity (MSG_ONE, self.enemy);
470 WriteByte (MSG_ONE, 10);
471 WriteAngle (MSG_ONE,self.enemy.v_angle_x);
472 WriteAngle (MSG_ONE,self.enemy.v_angle_y);
473 WriteAngle (MSG_ONE,self.enemy.v_angle_z);
484 // sloppy cycling code
485 if (self.classname != "botcam")
487 self.enemy = player_head;
492 self.enemy = self.enemy._next;
493 while (self.enemy.classname == "botcam");
495 if (self.enemy == self)
498 self.enemy = self.enemy._next;
499 while (self.enemy.classname == "botcam");
502 self.classname = "botcam";
503 self.solid = SOLID_NOT;
504 self.movetype = MOVETYPE_NONE;
505 self.takedamage = DAMAGE_NO;
510 sprint(self, "No one left to track!\n");
512 WriteByte (MSG_ONE,5);
513 WriteEntity (MSG_ONE, self);
517 if (!self.enemy.ishuman)
519 self.enemy.dmg_take = 0;
520 self.enemy.dmg_save = 0;
522 sprint(self, "Now tracking ");
523 sprint(self, self.enemy.netname);
530 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
532 Stuff mentioned up top
533 it just links the bot into the mod
535 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
538 void() ClientFixRankings =
541 if (self.switch_wallhug > time)
543 self.switch_wallhug = 0;
545 b_temp2 = nextent(world);
548 while (cno < max_clients)
550 if ((!b_temp2.ishuman) && (active_clients & ClientBitFlag(cno)))
551 UpdateClient(b_temp2);
553 b_temp2 = nextent(b_temp2);
557 void() ClientInRankings =
561 player_head._last = self;
563 self._next = player_head;
570 while (b_temp2 != world && b_temp2.owner != self)
571 b_temp2 = b_temp2._next;
572 self.phys_obj = b_temp2;
575 if (self.ishuman == 2)
577 self.ishuman = FALSE;
580 cno = self.colormap - 1;
581 BotInvalidClientNo (cno);
582 active_clients = active_clients | ClientBitFlag(cno);
584 self.b_clientno = cno;
586 self.switch_wallhug = time + 1;
590 void() ClientDisconnected =
592 if (player_head == self)
593 player_head = self._next;
595 self._next._last = self._last;
597 self._last._next = self._next;
599 active_clients = active_clients - active_clients & ClientBitFlag(self.b_clientno);
602 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
604 BotPreFrame & BotPostFrame, used to make the
605 bot easier to install
607 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
609 float () BotPreFrame =
611 if (self.b_clientno == -1)
615 if (self.switch_wallhug)
617 if (self.classname == "botcam")
620 if (self.b_frags != self.frags)
623 if (self.b_frags > self.frags)
625 if (pointcontents(self.origin) == CONTENT_LAVA)
632 self.b_frags = self.frags;
637 float () BotPostFrame =
639 if (self.b_clientno == -1)
644 if (waypoint_mode > WM_LOADED)
656 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
660 The rest of this code is in bot_misc.qc
662 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
664 void(string h) BotSay = // simulate talking by composing a 'chat' message
666 WriteByte(MSG_ALL, 8);
667 WriteByte(MSG_ALL, 1);
668 WriteString(MSG_ALL, self.netname);
669 WriteByte(MSG_ALL, 8);
670 WriteByte(MSG_ALL, 2);
671 WriteString(MSG_ALL, h);
675 WriteByte(MSG_ALL, 8);
676 WriteByte(MSG_ALL, 1);
677 WriteString(MSG_ALL, self.netname);
679 void(string h) BotSay2 =
681 WriteByte(MSG_ALL, 8);
682 WriteByte(MSG_ALL, 2);
683 WriteString(MSG_ALL, h);
685 void(string h) BotSayTeam =
693 if (t.team == self.team)
696 WriteByte(MSG_ONE, 8);
697 WriteByte(MSG_ONE, 1);
698 WriteByte(MSG_ONE, 40);
699 WriteString(MSG_ONE, self.netname);
700 WriteByte(MSG_ONE, 8);
701 WriteByte(MSG_ONE, 2);
702 WriteByte(MSG_ONE, 41);
703 WriteString(MSG_ONE, h);
709 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
713 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
719 local entity ent, fisent;
722 // spawn entities for the physics
723 ent = nextent(world);
728 max_clients = max_clients + 1;
731 if (max_clients > 16)
734 ent = nextent(world);
736 while (numents < max_clients)
741 fisent._next = phys_head;
742 phys_head._last = fisent;
744 ent.phys_obj = phys_head;
745 phys_head.classname = "phys_obj";
746 phys_head.owner = ent;
747 numents = numents + 1;
750 precache_model("progs/s_light.spr");
751 precache_model("progs/s_bubble.spr");
753 b_options = cvar("saved1");
754 if (coop || (b_options & OPT_SAVEBOTS))
756 saved_bots = cvar("scratch1");
757 saved_skills1 = cvar("scratch2");
758 saved_skills2 = cvar("scratch3");
760 cvar_set ("saved4", "0");
763 localcmd("exec maps/");
766 waypoint_mode = WM_DYNAMIC;
770 waypoint_mode = WM_LOADED;
775 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
777 Rankings 'utilities'. Written by Alan Kivlin,
778 this code just fools clients by sending precisely
779 the same network messages as when a real player
780 signs on to the server.
782 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
786 void(entity who) UpdateClient =
788 WriteByte (MSG_ALL, SVC_UPDATENAME);
789 WriteByte (MSG_ALL, who.b_clientno);
790 WriteString (MSG_ALL, who.netname);
791 WriteByte (MSG_ALL, SVC_UPDATECOLORS);
792 WriteByte (MSG_ALL, who.b_clientno);
793 WriteByte (MSG_ALL, who.b_shirt * 16 + who.b_pants);
794 WriteByte (MSG_ALL, SVC_UPDATEFRAGS);
795 WriteByte (MSG_ALL, who.b_clientno);
796 WriteShort (MSG_ALL, who.frags);
799 float(float clientno) ClientBitFlag =
801 // bigger, but faster
804 else if (clientno == 1)
806 else if (clientno == 2)
808 else if (clientno == 3)
810 else if (clientno == 4)
812 else if (clientno == 5)
814 else if (clientno == 6)
816 else if (clientno == 7)
818 else if (clientno == 8)
820 else if (clientno == 9)
822 else if (clientno == 10)
824 else if (clientno == 11)
826 else if (clientno == 12)
828 else if (clientno == 13)
830 else if (clientno == 14)
832 else if (clientno == 15)
837 float() ClientNextAvailable =
839 local float clientno;
841 clientno = max_clients;
844 clientno = clientno - 1;
846 if(!(active_clients & ClientBitFlag(clientno)))
854 void(entity e1, entity e2, float flag) DeveloperLightning =
856 // used to show waypoint links for debugging
857 WriteByte (MSG_BROADCAST, 23);
859 WriteByte (MSG_BROADCAST, 6);
861 WriteByte (MSG_BROADCAST, 13);
862 WriteEntity (MSG_BROADCAST, e2);
863 WriteCoord (MSG_BROADCAST, e1.origin_x);
864 WriteCoord (MSG_BROADCAST, e1.origin_y);
865 WriteCoord (MSG_BROADCAST, e1.origin_z);
866 WriteCoord (MSG_BROADCAST, e2.origin_x);
867 WriteCoord (MSG_BROADCAST, e2.origin_y);
868 WriteCoord (MSG_BROADCAST, e2.origin_z);
872 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
878 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
881 float(float tcolor) FindAnotherColor =
883 local float bestbet, scolor, pcount, bestp;
888 if (scolor != tcolor)
890 b_temp2 = player_head;
892 while(b_temp2 != world)
894 if (b_temp2.team == scolor + 1)
896 b_temp2 = b_temp2._next;
898 if ((pcount < bestp) && pcount)
909 while (bestbet == tcolor)
911 bestbet = floor(random() * 13);
918 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
920 BotConnect and related functions.
922 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
924 entity(float num) GetClientEntity =
932 upsy = nextent(upsy);
937 void(float whichteam, float whatbot, float whatskill) BotConnect =
943 f = ClientNextAvailable();
947 bprint("Unable to connect a bot, server is full.\n");
953 active_clients = active_clients | ClientBitFlag(f);
954 bot_count = bot_count + 1;
955 self = GetClientEntity(f);
959 self.colormap = f + 1;
961 self.netname = BotName(whatbot);
963 self.netname = PickARandomName();
966 // players can set skill all weird, so leave these checks in
967 whatskill = rint(whatskill);
970 else if (whatskill < 0)
972 self.b_skill = whatskill;
974 if (teamplay && !coop)
977 self.b_pants = FindAnotherColor(uself.team - 1);
979 self.b_pants = uself.team - 1;
980 self.b_shirt = self.b_pants;
983 self.team = self.b_pants + 1;
990 // this is risky... could corrupt .way files if done wrong
991 // If you're not the gambling type, comment this out
993 f = ClientBitFlag(self.b_num - 1);
994 current_bots = current_bots | f;
997 saved_skills1 = (saved_skills1 & (65536 - (3 * f)) | (self.b_skill * f));
1000 f = ClientBitFlag(self.b_num - 9);
1001 saved_skills2 = (saved_skills2 & (65536 - (3 * f)) | (self.b_skill * f));
1004 h = ftos(current_bots);
1005 cvar_set("scratch1", h);
1006 h = ftos(saved_skills1);
1007 cvar_set("scratch2", h);
1008 h = ftos(saved_skills2);
1009 cvar_set("scratch3", h);
1014 void(entity bot) BotDisconnect =
1021 bot_count = bot_count - 1;
1022 current_bots = current_bots - (current_bots & ClientBitFlag(self.b_num - 1));
1023 h = ftos(current_bots);
1024 cvar_set("scratch1", h);
1029 if (self.b_clientno != -1)
1031 // the bot's client number is not in use by a real player so we
1032 // must remove it's entry in the rankings
1033 // Quake engine sets all fields to 0, can only do the most important here
1034 self.b_frags = self.frags = 0;
1036 self.classname = "";
1039 self.armorvalue = 0;
1040 self.weaponmodel = "";
1043 self.ammo_shells = self.ammo_nails = self.ammo_rockets = self.ammo_cells = 0;
1045 active_clients = active_clients - (active_clients & ClientBitFlag(self.b_clientno));
1046 self.b_clientno = -1;
1051 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1054 kicks a bot if a player connects and takes the bot's space
1056 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1059 void(float clientno) BotInvalidClientNo =
1063 bot = GetClientEntity(clientno);
1064 if(bot.b_clientno > 0)
1068 bot.b_clientno = -1;
1070 active_clients = active_clients | ClientBitFlag(self.b_clientno);
1071 BotConnect(0, bot.b_num, bot.b_skill);
1078 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1080 Waypoint Loading from file
1082 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1084 void() LoadWaypoint =
1089 org_x = cvar("saved1");
1090 org_y = cvar("saved2");
1091 org_z = cvar("saved3");
1093 tep = make_waypoint(org);
1097 tep.b_aiflags = floor(r / 4);
1098 tep.b_pants = cvar("scratch1");
1099 tep.b_skill = cvar("scratch2");
1100 tep.b_shirt = cvar("scratch3");
1101 tep.b_frags = cvar("scratch4");
1108 if ((waypoint_mode == WM_DYNAMIC) || (waypoint_mode == WM_LOADED))
1112 if (saved_bots & 1) BotConnect(0, 1, saved_skills1 & 3);
1113 if (saved_bots & 2) BotConnect(0, 2, (saved_skills1 & 12) / 4);
1114 if (saved_bots & 4) BotConnect(0, 3, (saved_skills1 & 48) / 16);
1115 if (saved_bots & 8) BotConnect(0, 4, (saved_skills1 & 192) / 64);
1116 if (saved_bots & 16) BotConnect(0, 5, (saved_skills1 & 768) / 256);
1117 if (saved_bots & 32) BotConnect(0, 6, (saved_skills1 & 3072) / 1024);
1118 if (saved_bots & 64) BotConnect(0, 7, (saved_skills1 & 12288) / 4096);
1119 if (saved_bots & 128) BotConnect(0, 8, (saved_skills1 & 49152) / 16384);
1120 if (saved_bots & 256) BotConnect(0, 9, saved_skills2 & 3);
1121 if (saved_bots & 512) BotConnect(0, 10, (saved_skills2 & 12) / 4);
1122 if (saved_bots & 1024) BotConnect(0, 11, (saved_skills2& 48) / 16);
1123 if (saved_bots & 2048) BotConnect(0, 12, (saved_skills2 & 192) / 64);
1124 if (saved_bots & 4096) BotConnect(0, 13, (saved_skills2 & 768) / 256);
1125 if (saved_bots & 8192) BotConnect(0, 14, (saved_skills2 & 3072) / 1024);
1126 if (saved_bots & 16384) BotConnect(0, 15, (saved_skills2 & 12288) / 4096);
1127 if (saved_bots & 32768) BotConnect(0, 16, (saved_skills2 & 49152) / 16384);
1134 void() WaypointWatch =
1136 // Waypoint Baywatch
1137 local float bigboobs;
1140 if (max_clients < 2)
1142 if (waypoint_mode != WM_UNINIT)
1144 bigboobs = cvar("saved4");
1147 if ((bigboobs & 3) == 1)
1149 else if ((bigboobs & 3) == 3)
1152 h = ftos(b_options);
1153 cvar_set("saved1", h);
1154 cvar_set("saved4", "0");
1155 cvar_set("scratch1", "0");
1156 waypoint_mode = WM_LOADED;
1160 waypoint_mode = WM_LOADING;
1161 cvar_set("saved4", "0");
1169 // for the sake of speed
1170 sv_maxspeed = cvar("sv_maxspeed");
1171 sv_gravity = cvar("sv_gravity");
1172 sv_friction = cvar("sv_friction");
1173 sv_accelerate = cvar("sv_accelerate");
1174 sv_stopspeed = cvar("sv_stopspeed");
1175 real_frametime = frametime; // in NQ this is alright
1177 self = nextent(world);
1179 while (num < max_clients)
1181 if (self.ishuman == FALSE)
1183 if (active_clients & ClientBitFlag(num))
1188 SV_Physics_Client();
1191 self = nextent(self);
1201 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1203 Bot Impulses. Allows the player to perform bot
1206 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1209 void() BotImpulses =
1213 if (self.impulse == 100)
1216 BotConnect(0, 0, f);
1218 else if (self.impulse == 101)
1221 BotConnect(1, 0, f);
1223 else if (self.impulse == 102)
1225 else if (self.impulse == 103)
1227 else if (self.impulse == 104)