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 movement, 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
163 float AI_CARELESS = 262144; // Electro - jumppads, bot doesn't have to touch this entity, only get close
165 // these are flags for bots/players (dynamic/editor flags)
166 float AI_OBSTRUCTED = 1;
167 float AI_HOLD_SELECT = 2;
168 float AI_ROUTE_FAILED = 2;
174 float AI_POINT_TYPES = 29152;
175 float AI_READAHEAD_TYPES = 36528;
176 float AI_IGNORE_TYPES = 4864;
179 float WM_DYNAMIC = 1;
180 float WM_LOADING = 2;
183 float WM_EDITOR_DYNAMIC = 5;
184 float WM_EDITOR_DYNLINK = 6;
187 float OPT_SAVEBOTS = 1;
188 float OPT_NOCHAT = 2;
190 // -------globals-----
191 float active_clients;
192 float max_clients, real_frametime;
193 float bot_count, b_options;
194 float waypoint_mode, dump_mode;
195 float waypoints, direct_route;
196 float sv_friction, sv_gravity;
197 float sv_accelerate, sv_maxspeed, sv_stopspeed;
200 entity b_temp1, b_temp2, b_temp3;
201 entity player_head, phys_head, way_head;
202 float busy_waypoints;
203 float saved_bots, saved_skills1, saved_skills2, current_bots;
205 // -------ProtoTypes------
207 void() ClientConnect;
208 void() ClientDisconnect;
212 float(float clientno) ClientBitFlag;
213 float() ClientNextAvailable;
214 void(float whichteam, float whatbot, float whatskill) BotConnect;
215 void(entity bot) BotDisconnect;
216 void(float clientno) BotInvalidClientNo;
217 void(entity who) UpdateClient;
220 void() DynamicWaypoint;
221 entity(vector org) make_waypoint;
225 void(entity this, float direct) bot_get_path;
226 void() WaypointThink;
227 entity(entity start) FindWayPoint;
229 // physics & movement
230 float(entity e) bot_can_rj;
232 void() frik_bot_roam;
233 float(vector weird) frik_walkmove;
234 void() frik_movetogoal;
235 void() frik_obstacles;
236 float(float flag) frik_recognize_plat;
237 float(vector sdir) frik_KeysForDir;
238 void(vector whichway, float danger) frik_obstructed;
239 void() SV_Physics_Client;
240 void() SV_ClientThink;
244 string() PickARandomName;
245 float(entity targ) fov;
246 float(float y1, float y2) angcomp;
247 float(entity targ1, entity targ2) wisible;
248 float(entity targ) sisible;
249 float(entity targ) fisible;
250 vector(entity ent) realorigin;
251 void(entity ent) target_drop;
252 void(entity ent) target_add;
255 void(entity targ, float success) bot_lost;
256 string(float r) BotName;
257 float(float v) frik_anglemod;
259 void(float tpic) bot_start_topic;
265 void() bot_menu_display;
268 // ----------Commands---------
269 void(entity e, float chan, string samp, float vol, float atten) frik_sound = #8;
270 void(entity client, string s) frik_stuffcmd = #21;
271 void(entity client, string s) frik_sprint = #24;
272 vector(entity e, float sped) frik_aim = #44;
273 void(entity client, string s) frik_centerprint = #73;
274 void(entity e) frik_setspawnparms = #78;
275 void(float to, float f) frik_WriteByte = #52;
276 void(float to, float f) frik_WriteChar = #53;
277 void(float to, float f) frik_WriteShort = #54;
278 void(float to, float f) frik_WriteLong = #55;
279 void(float to, float f) frik_WriteCoord = #56;
280 void(float to, float f) frik_WriteAngle = #57;
281 void(float to, string s) frik_WriteString = #58;
282 void(float to, entity s) frik_WriteEntity = #59;
284 void(entity client, string s1, string s2, string s3, string s4, string s5, string s6, string s7)
285 frik_big_centerprint = #73;
287 //----------------------------------------------------------------------------
290 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
292 Function redclarations. These allow function
293 designed to work for clients (sprint, so forth)
294 to mainly not complain when working with a bot
296 Although these shouldn't be needed anymore,
297 as the bots truly are clients now, if you don't
298 stop the SZ_ buffer from filling up by disabling
299 direct messages to the bots, it crashes quake :-(
301 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
303 void(entity client, string s) stuffcmd =
305 if (client.ishuman == 1)
306 frik_stuffcmd(client, s);
307 b_temp1 = player_head;
311 if (b_temp1.classname == "botcam")
313 if ((b_temp1.enemy == client) && b_temp1.ishuman)
314 frik_stuffcmd(b_temp1, s);
316 b_temp1 = b_temp1._next;
320 void(entity e) setspawnparms =
323 frik_setspawnparms(e);
326 b_temp1 = player_head;
331 frik_setspawnparms(b_temp1);
334 b_temp1 = b_temp1._next;
339 void(entity client, string s) sprint =
341 if (client.ishuman == 1)
342 frik_sprint(client, s);
343 b_temp1 = player_head;
347 if (b_temp1.classname == "botcam")
349 if ((b_temp1.enemy == client) && b_temp1.ishuman)
350 frik_sprint(b_temp1, s);
352 b_temp1 = b_temp1._next;
356 void(entity client, string s) centerprint =
358 if (client.ishuman == 1)
359 frik_centerprint(client, s);
360 b_temp1 = player_head;
364 if (b_temp1.classname == "botcam")
366 if ((b_temp1.enemy == client) && b_temp1.ishuman)
367 frik_centerprint(b_temp1, s);
369 b_temp1 = b_temp1._next;
373 vector(entity e, float sped) aim =
375 e.missile_speed = sped;
376 return frik_aim(e, sped);
379 void(entity e, float chan, string samp, float vol, float atten) sound =
382 frik_sound(e, chan, samp, vol, atten);
383 if (samp == "items/inv3.wav")
385 else if (e.classname == "player")
386 e.b_sound = time + 1;
387 else if (other.classname == "player")
388 other.b_sound = time + 1;
391 void(float to, float f) WriteByte =
393 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
395 frik_WriteByte(to, f);
397 void(float to, float f) WriteChar =
399 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
401 frik_WriteChar(to, f);
403 void(float to, float f) WriteShort =
405 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
407 frik_WriteShort(to, f);
409 void(float to, float f) WriteLong =
411 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
413 frik_WriteLong(to, f);
415 void(float to, float f) WriteCoord =
417 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
419 frik_WriteCoord(to, f);
421 void(float to, float f) WriteAngle =
423 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
425 frik_WriteAngle(to, f);
427 void(float to, string s) WriteString =
429 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
431 frik_WriteString(to, s);
433 void(float to, entity s) WriteEntity =
435 if ((to == MSG_ONE) && (msg_entity.ishuman != TRUE))
437 frik_WriteEntity(to, s);
440 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
442 Bot Cam, see what the bot sees (or any other player)
444 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
449 if (self.classname != "botcam")
451 setorigin(self, self.enemy.origin);
452 self.items = self.enemy.items;
453 self.weapon = self.enemy.weapon;
454 self.weaponmodel = self.enemy.weaponmodel;
455 self.currentammo = self.enemy.currentammo;
456 self.weaponframe = self.enemy.weaponframe;
457 self.ammo_shells = self.enemy.ammo_shells;
458 self.ammo_nails = self.enemy.ammo_nails;
459 self.ammo_rockets= self.enemy.ammo_rockets;
460 self.ammo_cells = self.enemy.ammo_cells;
461 self.view_ofs = self.enemy.view_ofs;
462 self.health = self.enemy.health;
463 self.armorvalue = self.enemy.armorvalue;
464 self.dmg_take = self.enemy.dmg_take;
465 self.dmg_save = self.enemy.dmg_save;
466 self.dmg_inflictor = self.enemy.dmg_inflictor;
467 self.punchangle = self.enemy.punchangle;
468 self.deadflag = self.enemy.deadflag;
470 WriteByte (MSG_ONE,5);
471 WriteEntity (MSG_ONE, self.enemy);
472 WriteByte (MSG_ONE, 10);
473 WriteAngle (MSG_ONE,self.enemy.v_angle_x);
474 WriteAngle (MSG_ONE,self.enemy.v_angle_y);
475 WriteAngle (MSG_ONE,self.enemy.v_angle_z);
486 // sloppy cycling code
487 if (self.classname != "botcam")
489 self.enemy = player_head;
494 self.enemy = self.enemy._next;
495 while (self.enemy.classname == "botcam");
497 if (self.enemy == self)
500 self.enemy = self.enemy._next;
501 while (self.enemy.classname == "botcam");
504 self.classname = "botcam";
505 self.solid = SOLID_NOT;
506 self.movetype = MOVETYPE_NONE;
507 self.takedamage = DAMAGE_NO;
512 sprint(self, "No one left to track!\n");
514 WriteByte (MSG_ONE,5);
515 WriteEntity (MSG_ONE, self);
519 if (!self.enemy.ishuman)
521 self.enemy.dmg_take = 0;
522 self.enemy.dmg_save = 0;
524 sprint(self, "Now tracking ");
525 sprint(self, self.enemy.netname);
532 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
534 Stuff mentioned up top
535 it just links the bot into the mod
537 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
540 void() ClientFixRankings =
543 if (self.switch_wallhug > time)
545 self.switch_wallhug = 0;
547 b_temp2 = nextent(world);
550 while (cno < max_clients)
552 if ((!b_temp2.ishuman) && (active_clients & ClientBitFlag(cno)))
553 UpdateClient(b_temp2);
555 b_temp2 = nextent(b_temp2);
559 void() ClientInRankings =
563 player_head._last = self;
565 self._next = player_head;
572 while (b_temp2 != world && b_temp2.owner != self)
573 b_temp2 = b_temp2._next;
574 self.phys_obj = b_temp2;
577 if (self.ishuman == 2)
579 self.ishuman = FALSE;
582 cno = self.colormap - 1;
583 BotInvalidClientNo (cno);
584 active_clients = active_clients | ClientBitFlag(cno);
586 self.b_clientno = cno;
588 self.switch_wallhug = time + 1;
592 void() ClientDisconnected =
594 if (player_head == self)
595 player_head = self._next;
597 self._next._last = self._last;
599 self._last._next = self._next;
601 active_clients = active_clients - active_clients & ClientBitFlag(self.b_clientno);
604 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
606 BotPreFrame & BotPostFrame, used to make the
607 bot easier to install
609 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
611 float () BotPreFrame =
613 if (self.b_clientno == -1)
617 if (self.switch_wallhug)
619 if (self.classname == "botcam")
622 if (self.b_frags != self.frags)
625 if (self.b_frags > self.frags)
627 if (pointcontents(self.origin) == CONTENT_LAVA)
634 self.b_frags = self.frags;
639 float () BotPostFrame =
641 if (self.b_clientno == -1)
646 if (waypoint_mode > WM_LOADED)
658 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
662 The rest of this code is in bot_misc.qc
664 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
666 void(string h) BotSay = // simulate talking by composing a 'chat' message
668 WriteByte(MSG_ALL, 8);
669 WriteByte(MSG_ALL, 1);
670 WriteString(MSG_ALL, self.netname);
671 WriteByte(MSG_ALL, 8);
672 WriteByte(MSG_ALL, 2);
673 WriteString(MSG_ALL, h);
677 WriteByte(MSG_ALL, 8);
678 WriteByte(MSG_ALL, 1);
679 WriteString(MSG_ALL, self.netname);
681 void(string h) BotSay2 =
683 WriteByte(MSG_ALL, 8);
684 WriteByte(MSG_ALL, 2);
685 WriteString(MSG_ALL, h);
687 void(string h) BotSayTeam =
695 if (t.team == self.team)
698 WriteByte(MSG_ONE, 8);
699 WriteByte(MSG_ONE, 1);
700 WriteByte(MSG_ONE, 40);
701 WriteString(MSG_ONE, self.netname);
702 WriteByte(MSG_ONE, 8);
703 WriteByte(MSG_ONE, 2);
704 WriteByte(MSG_ONE, 41);
705 WriteString(MSG_ONE, h);
711 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
715 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
721 local entity ent, fisent;
724 // spawn entities for the physics
725 ent = nextent(world);
730 max_clients = max_clients + 1;
733 if (max_clients > 16)
736 ent = nextent(world);
738 while (numents < max_clients)
743 fisent._next = phys_head;
744 phys_head._last = fisent;
746 ent.phys_obj = phys_head;
747 phys_head.classname = "phys_obj";
748 phys_head.owner = ent;
749 numents = numents + 1;
752 precache_model("progs/s_light.spr");
753 precache_model("progs/s_bubble.spr");
755 b_options = cvar("saved1");
756 if (coop || (b_options & OPT_SAVEBOTS))
758 saved_bots = cvar("scratch1");
759 saved_skills1 = cvar("scratch2");
760 saved_skills2 = cvar("scratch3");
762 cvar_set ("saved4", "0");
765 localcmd("exec maps/");
768 waypoint_mode = WM_DYNAMIC;
772 waypoint_mode = WM_LOADED;
777 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
779 Rankings 'utilities'. Written by Alan Kivlin,
780 this code just fools clients by sending precisely
781 the same network messages as when a real player
782 signs on to the server.
784 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
788 void(entity who) UpdateClient =
790 WriteByte (MSG_ALL, SVC_UPDATENAME);
791 WriteByte (MSG_ALL, who.b_clientno);
792 WriteString (MSG_ALL, who.netname);
793 WriteByte (MSG_ALL, SVC_UPDATECOLORS);
794 WriteByte (MSG_ALL, who.b_clientno);
795 WriteByte (MSG_ALL, who.b_shirt * 16 + who.b_pants);
796 WriteByte (MSG_ALL, SVC_UPDATEFRAGS);
797 WriteByte (MSG_ALL, who.b_clientno);
798 WriteShort (MSG_ALL, who.frags);
801 float(float clientno) ClientBitFlag =
803 // bigger, but faster
806 else if (clientno == 1)
808 else if (clientno == 2)
810 else if (clientno == 3)
812 else if (clientno == 4)
814 else if (clientno == 5)
816 else if (clientno == 6)
818 else if (clientno == 7)
820 else if (clientno == 8)
822 else if (clientno == 9)
824 else if (clientno == 10)
826 else if (clientno == 11)
828 else if (clientno == 12)
830 else if (clientno == 13)
832 else if (clientno == 14)
834 else if (clientno == 15)
839 float() ClientNextAvailable =
841 local float clientno;
843 clientno = max_clients;
846 clientno = clientno - 1;
848 if(!(active_clients & ClientBitFlag(clientno)))
856 void(entity e1, entity e2, float flag) DeveloperLightning =
858 // used to show waypoint links for debugging
859 WriteByte (MSG_BROADCAST, 23);
861 WriteByte (MSG_BROADCAST, 6);
863 WriteByte (MSG_BROADCAST, 13);
864 WriteEntity (MSG_BROADCAST, e2);
865 WriteCoord (MSG_BROADCAST, e1.origin_x);
866 WriteCoord (MSG_BROADCAST, e1.origin_y);
867 WriteCoord (MSG_BROADCAST, e1.origin_z);
868 WriteCoord (MSG_BROADCAST, e2.origin_x);
869 WriteCoord (MSG_BROADCAST, e2.origin_y);
870 WriteCoord (MSG_BROADCAST, e2.origin_z);
874 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
880 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
883 float(float tcolor) FindAnotherColor =
885 local float bestbet, scolor, pcount, bestp;
890 if (scolor != tcolor)
892 b_temp2 = player_head;
894 while(b_temp2 != world)
896 if (b_temp2.team == scolor + 1)
898 b_temp2 = b_temp2._next;
900 if ((pcount < bestp) && pcount)
911 while (bestbet == tcolor)
913 bestbet = floor(random() * 13);
920 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
922 BotConnect and related functions.
924 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
926 entity(float num) GetClientEntity =
934 upsy = nextent(upsy);
939 void(float whichteam, float whatbot, float whatskill) BotConnect =
945 f = ClientNextAvailable();
949 bprint("Unable to connect a bot, server is full.\n");
955 active_clients = active_clients | ClientBitFlag(f);
956 bot_count = bot_count + 1;
957 self = GetClientEntity(f);
961 self.colormap = f + 1;
963 self.netname = BotName(whatbot);
965 self.netname = PickARandomName();
968 // players can set skill all weird, so leave these checks in
969 whatskill = rint(whatskill);
972 else if (whatskill < 0)
974 self.b_skill = whatskill;
976 if (teamplay && !coop)
979 self.b_pants = FindAnotherColor(uself.team - 1);
981 self.b_pants = uself.team - 1;
982 self.b_shirt = self.b_pants;
985 self.team = self.b_pants + 1;
990 self.classname = "player";
993 // this is risky... could corrupt .way files if done wrong
994 // If you're not the gambling type, comment this out
996 f = ClientBitFlag(self.b_num - 1);
997 current_bots = current_bots | f;
1000 saved_skills1 = (saved_skills1 & (65536 - (3 * f)) | (self.b_skill * f));
1003 f = ClientBitFlag(self.b_num - 9);
1004 saved_skills2 = (saved_skills2 & (65536 - (3 * f)) | (self.b_skill * f));
1007 h = ftos(current_bots);
1008 cvar_set("scratch1", h);
1009 h = ftos(saved_skills1);
1010 cvar_set("scratch2", h);
1011 h = ftos(saved_skills2);
1012 cvar_set("scratch3", h);
1017 void(entity bot) BotDisconnect =
1024 bot_count = bot_count - 1;
1025 current_bots = current_bots - (current_bots & ClientBitFlag(self.b_num - 1));
1026 h = ftos(current_bots);
1027 cvar_set("scratch1", h);
1032 if (self.b_clientno != -1)
1034 // the bot's client number is not in use by a real player so we
1035 // must remove it's entry in the rankings
1036 // Quake engine sets all fields to 0, can only do the most important here
1037 self.b_frags = self.frags = 0;
1039 self.classname = "";
1042 self.armorvalue = 0;
1043 self.weaponmodel = "";
1046 self.ammo_shells = self.ammo_nails = self.ammo_rockets = self.ammo_cells = 0;
1048 active_clients = active_clients - (active_clients & ClientBitFlag(self.b_clientno));
1049 self.b_clientno = -1;
1054 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1057 kicks a bot if a player connects and takes the bot's space
1059 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1062 void(float clientno) BotInvalidClientNo =
1066 bot = GetClientEntity(clientno);
1067 if(bot.b_clientno > 0)
1071 bot.b_clientno = -1;
1073 active_clients = active_clients | ClientBitFlag(self.b_clientno);
1074 BotConnect(0, bot.b_num, bot.b_skill);
1081 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1083 Waypoint Loading from file
1085 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1087 void() LoadWaypoint =
1092 org_x = cvar("saved1");
1093 org_y = cvar("saved2");
1094 org_z = cvar("saved3");
1096 tep = make_waypoint(org);
1100 tep.b_aiflags = floor(r / 4);
1101 tep.b_pants = cvar("scratch1");
1102 tep.b_skill = cvar("scratch2");
1103 tep.b_shirt = cvar("scratch3");
1104 tep.b_frags = cvar("scratch4");
1111 if ((waypoint_mode == WM_DYNAMIC) || (waypoint_mode == WM_LOADED))
1115 if (saved_bots & 1) BotConnect(0, 1, saved_skills1 & 3);
1116 if (saved_bots & 2) BotConnect(0, 2, (saved_skills1 & 12) / 4);
1117 if (saved_bots & 4) BotConnect(0, 3, (saved_skills1 & 48) / 16);
1118 if (saved_bots & 8) BotConnect(0, 4, (saved_skills1 & 192) / 64);
1119 if (saved_bots & 16) BotConnect(0, 5, (saved_skills1 & 768) / 256);
1120 if (saved_bots & 32) BotConnect(0, 6, (saved_skills1 & 3072) / 1024);
1121 if (saved_bots & 64) BotConnect(0, 7, (saved_skills1 & 12288) / 4096);
1122 if (saved_bots & 128) BotConnect(0, 8, (saved_skills1 & 49152) / 16384);
1123 if (saved_bots & 256) BotConnect(0, 9, saved_skills2 & 3);
1124 if (saved_bots & 512) BotConnect(0, 10, (saved_skills2 & 12) / 4);
1125 if (saved_bots & 1024) BotConnect(0, 11, (saved_skills2& 48) / 16);
1126 if (saved_bots & 2048) BotConnect(0, 12, (saved_skills2 & 192) / 64);
1127 if (saved_bots & 4096) BotConnect(0, 13, (saved_skills2 & 768) / 256);
1128 if (saved_bots & 8192) BotConnect(0, 14, (saved_skills2 & 3072) / 1024);
1129 if (saved_bots & 16384) BotConnect(0, 15, (saved_skills2 & 12288) / 4096);
1130 if (saved_bots & 32768) BotConnect(0, 16, (saved_skills2 & 49152) / 16384);
1137 void() WaypointWatch =
1139 // Waypoint Baywatch
1140 local float bigboobs;
1143 if (max_clients < 2)
1145 if (waypoint_mode != WM_UNINIT)
1147 bigboobs = cvar("saved4");
1150 if ((bigboobs & 3) == 1)
1152 else if ((bigboobs & 3) == 3)
1155 h = ftos(b_options);
1156 cvar_set("saved1", h);
1157 cvar_set("saved4", "0");
1158 cvar_set("scratch1", "0");
1159 waypoint_mode = WM_LOADED;
1163 waypoint_mode = WM_LOADING;
1164 cvar_set("saved4", "0");
1172 // for the sake of speed
1173 sv_maxspeed = cvar("sv_maxspeed");
1174 sv_gravity = cvar("sv_gravity");
1175 sv_friction = cvar("sv_friction");
1176 sv_accelerate = cvar("sv_accelerate");
1177 sv_stopspeed = cvar("sv_stopspeed");
1178 real_frametime = frametime; // in NQ this is alright
1180 self = nextent(world);
1182 while (num < max_clients)
1184 if (self.ishuman == FALSE)
1186 if (active_clients & ClientBitFlag(num))
1191 SV_Physics_Client();
1194 self = nextent(self);
1204 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1206 Bot Impulses. Allows the player to perform bot
1209 -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
1212 void() BotImpulses =
1215 if (self.impulse == 100)
1218 BotConnect(0, 0, f);
1220 if (self.impulse == 101)
1223 BotConnect(1, 0, f);
1225 else if (self.impulse == 102)
1227 else if (self.impulse == 103)
1229 else if (self.impulse == 104)