From 4b7b8a0e948514222f8379b47c68e91a00c63446 Mon Sep 17 00:00:00 2001 From: GunHog Date: Wed, 2 Dec 2015 16:16:33 -0600 Subject: [PATCH] Adds Bots to Diagnostic HUDs - Adds bots to the Diagnostic HUD. - Fixes mode tracking issues with AI's botcall interface - Added Sentience tracking to bots in PDA and AI displays - New HUD sprites by WJohnston - Moved bot defines to its own file so it can be used properly. --- code/__DEFINES/bots.dm | 25 ++++++++ code/__DEFINES/hud.dm | 1 + code/game/data_huds.dm | 40 ++++++++++++- code/modules/mob/living/silicon/ai/ai.dm | 7 ++- .../mob/living/simple_animal/bot/bot.dm | 54 +++++++++--------- icons/mob/hud.dmi | Bin 9465 -> 9768 bytes tgstation.dme | 1 + 7 files changed, 96 insertions(+), 32 deletions(-) create mode 100644 code/__DEFINES/bots.dm diff --git a/code/__DEFINES/bots.dm b/code/__DEFINES/bots.dm new file mode 100644 index 00000000000..d6da76b02e4 --- /dev/null +++ b/code/__DEFINES/bots.dm @@ -0,0 +1,25 @@ +//Bot defines, placed here so they can be read by other things! + +#define BOT_STEP_DELAY 4 //Delay between movemements + +#define DEFAULT_SCAN_RANGE 7 //default view range for finding targets. + +//Mode defines +#define BOT_IDLE 0 // idle +#define BOT_HUNT 1 // found target, hunting +#define BOT_PREP_ARREST 2 // at target, preparing to arrest +#define BOT_ARREST 3 // arresting target +#define BOT_START_PATROL 4 // start patrol +#define BOT_PATROL 5 // patrolling +#define BOT_SUMMON 6 // summoned by PDA +#define BOT_CLEANING 7 // cleaning (cleanbots) +#define BOT_REPAIRING 8 // repairing hull breaches (floorbots) +#define BOT_MOVING 9 // for clean/floor/med bots, when moving. +#define BOT_HEALING 10 // healing people (medbots) +#define BOT_RESPONDING 11 // responding to a call from the AI +#define BOT_DELIVER 12 // moving to deliver +#define BOT_GO_HOME 13 // returning to home +#define BOT_BLOCKED 14 // blocked +#define BOT_NAV 15 // computing navigation +#define BOT_WAIT_FOR_NAV 16 // waiting for nav computation +#define BOT_NO_ROUTE 17 // no destination beacon found (or no route) \ No newline at end of file diff --git a/code/__DEFINES/hud.dm b/code/__DEFINES/hud.dm index c10e56598de..0ac66f3092d 100644 --- a/code/__DEFINES/hud.dm +++ b/code/__DEFINES/hud.dm @@ -13,6 +13,7 @@ #define DIAG_HUD "9" // Silicon health bar #define DIAG_BATT_HUD "10"// Borg/Mech power meter #define DIAG_MECH_HUD "11"// Mech health bar +#define DIAG_BOT_HUD "12"// Bot HUDs //for antag huds. these are used at the /mob level #define ANTAG_HUD "12" diff --git a/code/game/data_huds.dm b/code/game/data_huds.dm index 7e25943ea11..3ae2e05f76d 100644 --- a/code/game/data_huds.dm +++ b/code/game/data_huds.dm @@ -45,7 +45,7 @@ hud_icons = list(ID_HUD, IMPTRACK_HUD, IMPLOYAL_HUD, IMPCHEM_HUD, WANTED_HUD) /datum/atom_hud/data/diagnostic - hud_icons = list (DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD) + hud_icons = list (DIAG_HUD, DIAG_STAT_HUD, DIAG_BATT_HUD, DIAG_MECH_HUD, DIAG_BOT_HUD) /* MED/SEC/DIAG HUD HOOKS */ @@ -248,4 +248,40 @@ var/image/holder = hud_list[DIAG_STAT_HUD] holder.icon_state = null if(internal_damage) - holder.icon_state = "hudwarn" \ No newline at end of file + holder.icon_state = "hudwarn" + +/*~~~~~~~~~ + Bots! +~~~~~~~~~~*/ +/mob/living/simple_animal/bot/proc/diag_hud_set_bothealth() + var/image/holder = hud_list[DIAG_HUD] + holder.icon_state = "huddiag[RoundDiagBar(health/maxHealth)]" + +/mob/living/simple_animal/bot/proc/diag_hud_set_botstat() //On (With wireless on or off), Off, EMP'ed + var/image/holder = hud_list[DIAG_STAT_HUD] + if(on) + holder.icon_state = "hudstat" + else if(stat) //Generally EMP causes this + holder.icon_state = "hudoffline" + else //Bot is off + holder.icon_state = "huddead2" + +/mob/living/simple_animal/bot/proc/diag_hud_set_botmode() //Shows a bot's current operation + var/image/holder = hud_list[DIAG_BOT_HUD] + if(client) //If the bot is player controlled, it will not be following mode logic! + holder.icon_state = "hudsentient" + return + + switch(mode) + if(BOT_SUMMON, BOT_RESPONDING) //Responding to PDA or AI summons + holder.icon_state = "hudcalled" + if(BOT_CLEANING, BOT_REPAIRING, BOT_HEALING) //Cleanbot cleaning, Floorbot fixing, or Medibot Healing + holder.icon_state = "hudworking" + if(BOT_PATROL, BOT_START_PATROL) //Patrol mode + holder.icon_state = "hudpatrol" + if(BOT_PREP_ARREST, BOT_ARREST, BOT_HUNT) //STOP RIGHT THERE, CRIMINAL SCUM! + holder.icon_state = "hudalert" + if(BOT_MOVING, BOT_DELIVER, BOT_GO_HOME, BOT_NAV) //Moving to target for normal bots, moving to deliver or go home for MULES. + holder.icon_state = "hudmove" + else + holder.icon_state = "" \ No newline at end of file diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm index 1115cb8aeb8..642634e0032 100644 --- a/code/modules/mob/living/silicon/ai/ai.dm +++ b/code/modules/mob/living/silicon/ai/ai.dm @@ -517,15 +517,16 @@ var/list/ai_list = list() var/ai_Zlevel = ai_current_turf.z var/d var/area/bot_area - d += "Query network status
" + d += "Query network status
" d += "" for (Bot in living_mob_list) if(Bot.z == ai_Zlevel && !Bot.remote_disabled) //Only non-emagged bots on the same Z-level are detected! bot_area = get_area(Bot) - d += "" + var/bot_mode = Bot.get_mode() + d += "" //If the bot is on, it will display the bot's current mode status. If the bot is not mode, it will just report "Idle". "Inactive if it is not on at all. - d += "" + d += "" d += "" d += "" d += "" diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index 9d9d8428860..e47418d058f 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -1,26 +1,4 @@ -#define BOT_STEP_DELAY 4 //Delay between movemements - -#define DEFAULT_SCAN_RANGE 7 //default view range for finding targets. - -//Mode defines -#define BOT_IDLE 0 // idle -#define BOT_HUNT 1 // found target, hunting -#define BOT_PREP_ARREST 2 // at target, preparing to arrest -#define BOT_ARREST 3 // arresting target -#define BOT_START_PATROL 4 // start patrol -#define BOT_PATROL 5 // patrolling -#define BOT_SUMMON 6 // summoned by PDA -#define BOT_CLEANING 7 // cleaning (cleanbots) -#define BOT_REPAIRING 8 // repairing hull breaches (floorbots) -#define BOT_MOVING 9 // for clean/floor/med bots, when moving. -#define BOT_HEALING 10 // healing people (medbots) -#define BOT_RESPONDING 11 // responding to a call from the AI -#define BOT_DELIVER 12 // moving to deliver -#define BOT_GO_HOME 13 // returning to home -#define BOT_BLOCKED 14 // blocked -#define BOT_NAV 15 // computing navigation -#define BOT_WAIT_FOR_NAV 16 // waiting for nav computation -#define BOT_NO_ROUTE 17 // no destination beacon found (or no route) +//Defines for bots are now found in code\__DEFINES\bots.dm // AI (i.e. game AI, not the AI player) controlled bots /mob/living/simple_animal/bot @@ -92,17 +70,24 @@ "Waiting for clear path", "Calculating navigation path", "Pinging beacon network", "Unable to reach destination") //This holds text for what the bot is mode doing, reported on the remote bot control interface. + hud_possible = list(DIAG_STAT_HUD, DIAG_BOT_HUD, DIAG_HUD) //Diagnostic HUD views + /mob/living/simple_animal/bot/proc/get_mode() - if(!mode) - return "Idle" + if(client) //Player bots do not have modes, thus the override. Also an easy way for PDA users/AI to know when a bot is a player. + return "Sentient" + else if(!on) + return "Inactive" + else if(!mode) + return "Idle" else - return mode_name[mode] + return "[mode_name[mode]]" /mob/living/simple_animal/bot/proc/turn_on() if(stat) return 0 on = 1 SetLuminosity(initial(luminosity)) update_icon() + diag_hud_set_botstat() return 1 /mob/living/simple_animal/bot/proc/turn_off() @@ -125,6 +110,13 @@ bot_core = new bot_core_type(src) + prepare_huds() + var/datum/atom_hud/data/diagnostic/diag_hud = huds[DATA_HUD_DIAGNOSTIC] + diag_hud.add_to_hud(src) + diag_hud_set_bothealth() + diag_hud_set_botstat() + diag_hud_set_botmode() + /mob/living/simple_animal/bot/update_canmove() . = ..() if(!on) @@ -181,8 +173,13 @@ new /obj/effect/decal/cleanable/oil(loc) return ..(amount) +/mob/living/simple_animal/bot/updatehealth() + ..() + diag_hud_set_bothealth() + /mob/living/simple_animal/bot/handle_automated_action() //Master process which handles code common across most bots. set background = BACKGROUND_ENABLED + diag_hud_set_botmode() if(!on || client) return @@ -376,7 +373,7 @@ Pass a positive integer as an argument to override a bot's default speed. path = list() return 0 var/step_count = move_speed ? move_speed : base_speed //If a value is passed into move_speed, use that instead of the default speed var. - + if(step_count >= 1 && tries < 4) for(var/step_number = 0, step_number < step_count,step_number++) spawn(BOT_STEP_DELAY*step_number) @@ -453,6 +450,8 @@ Pass a positive integer as an argument to override a bot's default speed. access_card.access = prev_access tries = 0 mode = BOT_IDLE + diag_hud_set_botstat() + diag_hud_set_botmode() @@ -780,6 +779,7 @@ Pass a positive integer as an argument to override a bot's default speed. /mob/living/simple_animal/bot/Login() . = ..() access_card.access += player_access + diag_hud_set_botmode() /mob/living/simple_animal/bot/Logout() . = ..() diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi index 90afe2db20029c6401d98e16d4a004f4e3976c2d..81d7d489e48c900bb498a819925e97aa580411ad 100644 GIT binary patch literal 9768 zcmcI~cT|&4w{DP*0#XzU5=9UY0Y#7|L=?f$o6?(tfEYk}XhFaRA{qol2u+IgDlL#u zMF>@T4G4rzfB+$+op{c==a2LK*1dn6@2-`}ns?Uw?kRiEp8f1+-WeO}aC4pG0ssKq z;0Ic!005KY-@?JhXnE!IO&8Iu5`^3lH+t1z0695QGLwqst61Z{lb$?fx zWy_EI?s|O5w#Iyg?VU!Jy^~c35o1;FT?JapmIp*NFD-J{Y6bs%f+o!GXy9iX!vg6Q zNU}G2wnA}m5`s*YyR|-IpS|okHDg<5ks|H_I~+<&LqdqxtRJ5S?t}t)Prf&7koiK2 zJnaUJQKz0IO<)v=o`NXh-UNrn8QbaG?!6;tV~U6GoF3;`bd{H3eG+%vtZiIU#(2X3FY zNcL_h3%Yg8-dDzKSbdTuRbW`sPdL{6JL!I25cdZa;|}dCg+V1jgF;6q<8HWoBWv}n zuh8tBQv57~Ezo?4{F7WD!} zZcHfJ@wm+E&4FnGtXo|flE!vlW#cZdV3i}c;x7LQdl&L!fw(>t+iy@&c0AhtV_ebk zCzo%Yy0tM=)R~W7o|%ddoSAt;-sko8T~t0t*~0?>7Xe@`P4l3%&6zMi^Zh3LPCpM{ zlknP7jbpu_)YZr@*(>djwkoc-XMVRhc|TTn{hmqr=;Jud`MpdxbJO@i>rjAJe9h=@ z>-&&(0bbAHD&rKBXlB0luiERH_oT;s>aPAm!SoND`+yk;5pK`_eo-qkxv!N`0kd=4fxSzDzw8D0jKv~%5_*-pmx$T#8xx2$bPys z;uZg?rOuu@T*9NN*Sza#l-2xGD7pl;vSg-T?di4<5UBpwmn%ASzKk^5zxb6rSkNxZkfY>-u<;q?}G!kswc^f}eA*Z?V?AV78&g{IrE0%TMS!~?rKFiE(ALW1( z9y>(7HEf3awPym?DG7Z8r+l?NiasbfL;_A`$lheqOX(Wh-#Z^;*m!!VY}gb9h`CoV zT#1_s=2qT(u9Mz4HC6`{x3LR!8pzaye`dVzQ^|JCB_?qHr`nI;1w`9x4Pb9g?0P~(B&J>M5xUxyFe-DC|l6DBpddpo4uOsDd* zDrm_r}ct$LM2hfXjl{0cWxzn3_3QPXM$f z9Rb(x{%>A+uv)5-86tmnV+%w}!G|Ep^;yXW7wL6|zsd>ch>#!MMLJ3lnb2F=95 z_+E7#_%Lj;4W84l5o!~!4?Mdr)KZW<#!7~{!mYyh4%@=YyK6PVV=03KZMJ(Kq=YNN zT~3B@zUc&pO}DMfexM)a#%ZF%sbXMW12ucN0(8q1{F{tN14B5gSe%M=tXxuSAvQ>{ z0}7Q#RofJ!1lv23z!$$)2L)3Gz3z7P?$}`Iqoh~E^kKV4v;`nlwOTbiIiQ~9##5#I zU;P2g30!rB0(s-=JM98S?O)N5P5!XM@t!ouywE&TKKg=db&h^l_~E$ze#U`!AIrh) zv~Sv?mkm;DhF3XfBw#(Xfa2seRgQr2PNwENl_{gQjE?y$43^t;yA}G<14$< z3grH-Lf@6Snq51?W~bF?Y-s5RZ1AxkeaX{?jiiQd7Ro^Nf+Ayf2I)uzq~Lt3tb}7b zCiobcp`5kw=1Z(&bFEA7l$VSm1|^s+1l)q?%OJk`ZahdPAp^~}Aqsl7vT3*=_DXyz z_*l~P1(+o&t2|n|l=^UELa@Aoq3{yaPAfQb`J)M3`{!4zeb>_~b3ue}SZ5OJ7ZT1d zIfJfT*Vn%+>QE^)YkVl+NZXs*6)>iBI=HRHo%Tr!fSzXg6WHA`#zxAY+mkGMPdzm^ z@K=wd{LIb3fg63hCGqHSLW$A6Dh--!*tv6niz1C2?EePK{(tNbsl=SbWVDE2!_Jos z;8OiK=Q?FQ`PS*4zs9<#_AyA+>N+S4?jT6&m-%9UogOU}sN4m+VRd+jUPr3X9`_Mx z{)d|_zwkWCVqs(9ISVJ25p2qf^KABzxkYz8SN_y{U&+lIKN1JAU#5PWOfh6eV%64N$pw>8H|Ir+uVT z`1fU!SItIL6lM9eJ}=5Q2pE@Ip^V(@ns_1xE-UtkX^M8xzY`M=t9+`ZmYs zU3rsv|723u?!}>w(p|j;N~hY@YqSBzfc7^X#P(ZFiqbaQRtCR`yXdZ<_SN<&gnl)Q zY{1}ejMSYrs<+HFJMcNBColTQrS~xd{-wDTiI=Xz)9iNH5pD0(1Pz;IsooF3eJn?9 zmpY67OggAwGHwUD7jX_JURR=rC3j*+_HNS+ASD3~cb!NdQY$RWLScucpsa+&Qr*%YDX&i99}P?_TR&RPTokJ?F3a8d@UJ zZ*19U=LEE+vV6SBgp@@YR|kE=@RcTAywY!1IQUJ+H5Sj92VznC{!P1NnBQ*gFYHmX zlZr=kE|siDojK+BuWH2eB3dPno)lQJmk)nw`;YZ;rHEFdGwLx*qRC)*>to`9XQHh~dgt8ep;N*rHF774Yt; zJ5v3a`o=-RW4U=1UmVNQ(h{qeUan~ch+~klwzjr$Fga z+2rJ88X3h1HUuOL{k~@OckB=!9B_P4**)W)m~&m~qk^q9>1X%2o^mMV8#V-v#G{dA z=!?pMJ(pO$YzWKoe$$H$mIP!Ezm~the-V3&e>emJIp}=`%ubf|{gyHs|4MPJQzQvp z0D~+vFb_&-bZt^!v|n=QwFfFasrcDznHC1ypMu4!qqVyA(XV9f-X%E%b@HB-Z(r4j zCOcVa49eY2CV!;oJlPTZOlO%hrR{mNG)BWpdKS+sI0W{r?Rb?re_Ikx<_GISQ>4`B zzjNJoxX;RK30%?lM)8hji#uAemGdQ)lN2^Av&#G}9O#4aFrR}n>M9}n2Vp`2-tHTm zNT=3l&ifX3K6{O+coN*rWjqE9i{T25B$hq7%-YcCe}Agc?z&mxQnz4xD5i&bG* z7Q@1RNub{nVyOz%f7kLCh;{SrJ=8h!*^{QeOw54kb@}`(raKk?z9`{e4eoC^l4A}} zx4Et^>9@dXwzX}$(VnK_%Y}0Ym~b)NHEL=sb)*5q?U%%0l*1iXLPpS^ciDCHgf8cn zP%II#*x7q@Xs8A?y$C+_L~g9oH9UQWc4&6|Nx#vRgqE-M4pKo=glPnYbv`W3)p-I1kiM0zGpT)%cHEa^Z>Qx&w?+LKhz7iL% z{W~}galiIgL|ynJ=`5)9@83|eYFC+6gZbscLIreRvY4H1;&4oZs-2Iwk_3tOM6fx0 zFJ6eZ+w-`_c#i+QH#LIWb!TIJHC7oXPTGd8IZbdw7oSk}8<+2SLweSKee_i0wbKxT zxscdi1B11x{P;&fDap3l3SMRztsrPX%{Kw;0Is*Bw*Knew>7zuysW_05%Nue?Z1`p zM|wYAkmL}H^fkC%bza{X{zJchb0Oge<1xo|xidY?0nbnM2jkv79jWPISegi33fxfX z9=63Ioa7mP76}J2Ay1#K@F3~&&bw5+lfAcLkb4_4sX)~jFW?)52=x0U(XEflR8=qS zZ&BmYAbronjhfcv5^td;z$#;QSh%j;DoV)spkR1!L81DL z70|&#g&Q*P9r(aBU~_EA-7V^as*Fu!fw}H^2iWwgyW4!qNqD8}okJ8Jiozqu*#UP% z!UcH#zhRL7_AaJtqKngd;R1q_wDpj_1KULgWESknQ1N}bLF#gr=lJ|F->>h$I~7kh zJjfad5Sm!5&7eO*o3t2|3DFuoKEQdxV9;W65RLs?Bptc!%IZbNC(zrD6#W zOGKElW$ObK`_F09B^M}%a;=0gbQQf^7=Vq0y|UsMs>s5~b+a4B!@4 zHsV^>37~(u&v7y=i3Tr^`BP165ulN~!6CaB)4qm5JJCI~(sN%bo6R zOuXa|4jt#28E-PDn+DX0t^VA~wN}`8fT+nc$2`F@|6qhQ4bB7c{{27IF62n(2Nmya z&DbO+CQeqm#F`d-9@;1mZKJrRcZFVf^ytwVBtOJ-`gYmvkh4kUiV_~pF8iHVWf+@V z?spNElsp2kq=-pi(S5lU^UXnAWwzBfK)z)~$ zld7fT=bcD3`{6b?dO|?49D2<2i@FKJ zryE{@-{Dj*y`Zv=ihX?{rKz`rzn$3#^c4}*hVkaE8-IU6?G}<{4(ge#L`W8$dvr3V zVR$!c(e2n4L-_uq3=QjfDB~AgWCYw-U+9<376&u4^9(n?WUdm}X8ixP)ZC#RIi_g6 zlkn;+XCOp!LI<8EtCyjWHZzUQaEB6YPJM56Bie>$FEqOd=W#v z#sNN>OwDI2xiY82JBsBYM-2@Pufx_4D{1)b?rnfLBB1F;eJ)0x4J0%b|g}oQQiaE-o*{O6-tH?5FMw z`c|?DX9qE5vZ7=D9m$LTb{zkj0=aNhwWpr&@TC}JfBmp(w^>#{1Y&*>>>F?Ixl4VF z00tLli@M#vsmy2J6bJ8vAYnrTQ>kUsxh_Mb*)t&hH=)1w|-A2`0Pab?Ks3%Z~s;0V$|@WD=g;ZhrE zigzyKX;LT3*mU=bU#O)r0L_Ta_j>}@JC6IM`R`aQ2XbDJvd|Im4gs;2voKw>hqCUy za4$HBS0gYck5inZxV+uqZ@=%V`z*#^iAxr=G5)E^kcs*2!|LelC4r(}ENL>fONkXx zoXQQ;#vIE`%-%T0bdq!L4SVDFD{zebk^C7S{rR{1(#-0h z{Z~z@z#D|dQ4Du_vQ(zB!+Q_ev6a2^KK`fMJ7*fetVtKMdyZSek8XiZri$k0?{Obf z$}f8G7q}KdjQT_t#BAVC<7S3~r*4KJmTE%^4fz(o5fG^7DN0RE4q6bU z`tb*-Fulo6D93Or3nH{q?z}woe|Kzl5xRDsWny*g8CQ+ujAZQZxXSd1myd_Uxh%Ww z=>B#nLB>&rY-RcIxC%pm-}y=?p(`?W zRN8l^ypO%u@7*!Bh{x@6j{*ONMB<-CBmRftMb^}gC{=XdgoB#$x~nTIy!u<`hmD#} z*^p}olqFvK!L5v35&v08#a5e5mvebuj#gX1mU$MYj{Xet@L_*IJi64=qnM;Vb*Lwu zRq}!MN4GMLx{Veib?ujcu)sf0vEuH-N2An=(6>n1id81MCcqTdK@+-B2!Hs}l+{x* z(5yATUq!uce(U_c7k*X(+%VS+T#JG=7CYFIqtojS-;M7kgM#jF$7#@WG@1@%fZz=xGTO-BZprTiSLwES2Sxd#mTGxpvL2$&zehp5yF5rojFDAWS8_?Ncc`? zo%jodP+YK`&n$a`%QIf?rWK75tW8-F4l*Rb8*Voh;u#+XWFYJ5wKCawhQ;sGQP)SO z6~)C>^-^}JbqYkMSy(5}YGIMW^W{EE;w5Z$!p&S8v`Itoz04lr`95UqxtpZ@ebxCj z0YqN^vxSDD4Rh6!U7X3SL_=6sn50q2CJL`**;e(sZF0xMAtF&EH20dL?a=X0#*ZeTno+_{~AL;x*@F0q^x)e`$269r?-P@*!yJ z8AR;$hSevcYgkLz^^Azzq+Nsdo9_Z1oJc4~;+uDIxo>=2-&s*HM;^F3kLt3Vl!a0g zhFo~gCK)L+w<51K&6VikclPcxbdH*tCF)V@uFTVrT^8f?gU`Aw6H3bh-hR6?7+vMj zW2J=k#_}M6UNbMz5!3b;Xb$4IOFR_c7iz%?1|s%84Tq+Dtll|@+fCTA?@E+UD2rXS zxN2JpOisdG)2aI!!Jd{>UyPMR1m!0Dnx-(NjBFnr1tWs8$*V+65AaXOYV~3-vC^y5 zJ|f|3f4~=zVwLqNlu9s@VRz%e={Q3@-4HXi&1)Qi9?fihM-x^pU`6(;GVWSduw3yt z)eXm7am2xp<~bPoaPD2~A2ory-Jd;a?c~wp#E!F41uoo-Bk1==`*|);qyapYGib0Y z-Oopl6BJS;2JK6_G;25fUHix9?W%r_qGd5x%t;hJBq=}3UmJxn>*IO>?Y6pvcv$nQ z-MaZ4eRbtMKZ?QfIb*1KczPGK0DFK*qDY6&Y0#688}{Moj@@Q`1Yn{1jZ{$mk<~J( z-%jaDDy(%s7O{+0C=gABO}D!A5s(rI6O{f?EHvD}z~B~)k>ks|H`4Y{hS;IvzlA>@ z8%hv=8>Qnn#vtfYm(XTtJN&Sh62{@jQ{)9v~5u*Q(B-;O>-1r$;v$rFQR#Q=Tr+{C7 z#9Qc-@S`6-iCwU4Qclgd$po@Z?AcmT@kb>fVy_-hlCL~;CdAv+^+3ak&X^q-4hf=t z{rdGettaJX7xuV*`VaM>{(ixDSx=2dQp&yc3|rw4PQ$;gUf#Kp$JL=k*WI>ts?xO^ z{ry(V;Y;5W9kx_+N4oY@Xl1}3qh7B^rUk>&1?Fp~+9+CA6Lrtvq!V?m zIy%??+|iXJ1XN6w?K~$bE{71=xn%u_l%!tWYFl1827P$4%#Ea73$gqoreTd5giuex zXviN=thqp!pjWx0Iu(%QkslTxaey;zA}0juocbMhT^2;mC&p_e1EQjP!~ExmCklI|x(>;uwkxwrM*{q}jjwH0h9F5cqp zo$O4#?eQWH(yEAc#<*L0?k2OaKa%S!CA}WATW0@ZUlhvdsn{0bH8ny=hW$}OV|~u+ zo%|mR=L18gvZERA5=JQsV~WUbW%(!2kfV3%x~mf-$8J{`!Ib&MxY_DphjC}-SkK?P z0RKZG2di+4)fs?o_CNBcK`6Wpo*5vRYbta}&Y+Nk3j*?-moNLWTLuly7hBC6(p6Oi z)oV9P zUXU{inZWdQNi*mqhNSH;bM4MpYYzp})B(*1l_nor&vb@JOX!`P z*yYaX7H7pItzHqDH`OC)@A_}Z7kE(y$8Mvla<>IIR|mD8hFaC=k2N-$VL+>m#RLsf zlE}2&&5|H@S5Vf|{7TAt>7vlxt9;7pw8tmIB5Q-*6CW9Joq?B@er%Ev zE&d=!=X{-UT{XUnQ`x$;57^+%dGXr3x50P|zm_NJv(%qH4Drojx)SzgNaAe?Iu^2< zu-a3!H)uL;vy1HBc{S0}@v=(DGWKNxAp+U$?l?+%fq2apYITZib&?{=2DsT_-%PnG j|LC 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 ltn+^X(f^O$UZgVo`P5x

Name

Status

Location

Control

[Bot.hacked ? "(!)" : ""] [Bot.name] ([Bot.model])
[Bot.hacked ? "(!)" : ""] [Bot.name] ([Bot.model])[Bot.on ? "[Bot.mode ? "[ Bot.get_mode() ]": "Idle"]" : "Inactive"][bot_mode][bot_area.name]InterfaceCall