[READY] Bot Refactor (#18930)

* [WIP] Bot Refactor

* No more spawns, sleeps, and working EDs

* Mules

* GC fixing

* h
This commit is contained in:
AffectedArc07
2022-09-17 12:46:25 +01:00
committed by GitHub
parent e4e06f2759
commit 1d008754da
20 changed files with 475 additions and 743 deletions
+112 -145
View File
@@ -23,8 +23,6 @@
bubble_icon = "machine"
faction = list("neutral", "silicon")
var/obj/machinery/bot_core/bot_core = null
var/bot_core_type = /obj/machinery/bot_core
var/list/users = list() //for dialog updates
var/window_id = "bot_control"
var/window_name = "Protobot 1.0" //Popup title
@@ -93,6 +91,9 @@
var/path_image_color = "#FFFFFF"
var/reset_access_timer_id
/// List of access values you can have to access the bot. Consider this as req_one_access
var/list/req_access = list()
hud_possible = list(DIAG_STAT_HUD, DIAG_BOT_HUD, DIAG_HUD, DIAG_PATH_HUD = HUD_LIST_LIST)//Diagnostic HUD views
/obj/item/radio/headset/bot
@@ -159,11 +160,6 @@
add_language("Trinary", 1)
default_language = GLOB.all_languages["Galactic Common"]
bot_core = new bot_core_type(src)
if(SSradio && bot_filter)
SSradio.add_object(bot_core, control_freq, bot_filter)
prepare_huds()
for(var/datum/atom_hud/data/diagnostic/diag_hud in GLOB.huds)
diag_hud.add_to_hud(src)
@@ -194,12 +190,11 @@
GLOB.bots_list -= src
QDEL_NULL(Radio)
QDEL_NULL(access_card)
if(reset_access_timer_id)
deltimer(reset_access_timer_id)
reset_access_timer_id = null
if(SSradio && bot_filter)
SSradio.remove_object(bot_core, control_freq)
QDEL_NULL(bot_core)
return ..()
/mob/living/simple_animal/bot/death(gibbed)
@@ -319,7 +314,7 @@
else
to_chat(user, "<span class='warning'>The maintenance panel is locked.</span>")
else if(istype(W, /obj/item/card/id) || istype(W, /obj/item/pda))
if(bot_core.allowed(user) && !open && !emagged)
if(allowed(user) && !open && !emagged)
locked = !locked
to_chat(user, "Controls are now [locked ? "locked." : "unlocked."]")
else
@@ -405,14 +400,18 @@
if(paicard)
paicard.emp_act(severity)
src.visible_message("[paicard] is flies out of [bot_name]!","<span class='warning'>You are forcefully ejected from [bot_name]!</span>")
ejectpai(0)
visible_message("[paicard] is flies out of [bot_name]!")
ejectpai()
if(on)
turn_off()
spawn(severity*300)
stat &= ~EMPED
if(was_on)
turn_on()
addtimer(CALLBACK(src, .proc/un_emp, was_on), severity * 300)
/mob/living/simple_animal/bot/proc/un_emp(was_on)
stat &= ~EMPED
if(was_on)
turn_on()
/mob/living/simple_animal/bot/rename_character(oldname, newname)
if(!..(oldname, newname))
@@ -478,43 +477,50 @@ Movement proc for stepping a bot through a path generated through A-star.
Pass a positive integer as an argument to override a bot's default speed.
*/
/mob/living/simple_animal/bot/proc/bot_move(dest, move_speed)
if(!dest || !path || path.len == 0) //A-star failed or a path/destination was not set.
set_path(null)
return 0
return FALSE
dest = get_turf(dest) //We must always compare turfs, so get the turf of the dest var if dest was originally something else.
var/turf/last_node = get_turf(path[path.len]) //This is the turf at the end of the path, it should be equal to dest.
if(get_turf(src) == dest) //We have arrived, no need to move again.
return 1
return TRUE
else if(dest != last_node) //The path should lead us to our given destination. If this is not true, we must stop.
set_path(null)
return 0
return FALSE
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 < BOT_STEP_MAX_RETRIES)
for(var/step_number = 0, step_number < step_count,step_number++)
spawn(BOT_STEP_DELAY*step_number)
bot_step(dest)
for(var/step_number in 1 to step_count)
// Hopefully this wont fill the buckets too much
addtimer(CALLBACK(src, .proc/bot_step), BOT_STEP_DELAY * (step_number - 1))
else
return 0
return 1
return FALSE
return TRUE
/mob/living/simple_animal/bot/proc/bot_step(dest) //Step,increase tries if failed
if(!path)
return 0
if(path.len > 1)
/mob/living/simple_animal/bot/proc/bot_step() //Step,increase tries if failed
if(!length(path))
return FALSE
// Only one destination
if(length(path) == 1)
step_to(src, path[1])
set_path(null)
else
// Move us slowly
Move(path[1], get_dir(src, path[1]), BOT_STEP_DELAY)
if(get_turf(src) == path[1]) //Successful move
increment_path()
tries = 0
else
tries++
return 0
else if(path.len == 1)
step_to(src, dest)
set_path(null)
return 1
return FALSE
return TRUE
/mob/living/simple_animal/bot/proc/check_bot_access()
@@ -584,10 +590,11 @@ Pass a positive integer as an argument to override a bot's default speed.
/mob/living/simple_animal/bot/proc/bot_patrol()
patrol_step()
spawn(5)
if(mode == BOT_PATROL)
patrol_step()
return
addtimer(CALLBACK(src, .proc/do_patrol), 5)
/mob/living/simple_animal/bot/proc/do_patrol()
if(mode == BOT_PATROL)
patrol_step()
/mob/living/simple_animal/bot/proc/start_patrol()
@@ -602,18 +609,20 @@ Pass a positive integer as an argument to override a bot's default speed.
mode = BOT_IDLE
return
if(patrol_target) // has patrol target
spawn(0)
calc_path() // Find a route to it
if(path.len == 0)
patrol_target = null
return
mode = BOT_PATROL
else // no patrol target, so need a new one
if(patrol_target) // has patrol target
INVOKE_ASYNC(src, .proc/target_patrol)
else // no patrol target, so need a new one
speak("Engaging patrol mode.")
find_patrol_target()
tries++
return
/mob/living/simple_animal/bot/proc/target_patrol()
calc_path() // Find a route to it
if(!length(path))
patrol_target = null
return
mode = BOT_PATROL
// perform a single patrol step
@@ -637,18 +646,19 @@ Pass a positive integer as an argument to override a bot's default speed.
var/moved = bot_move(patrol_target)//step_towards(src, next) // attempt to move
if(!moved) //Couldn't proceed the next step of the path BOT_STEP_MAX_RETRIES times
spawn(2)
calc_path()
if(path.len == 0)
find_patrol_target()
tries = 0
addtimer(CALLBACK(src, .proc/patrol_step_not_moved), 2)
else // no path, so calculate new one
mode = BOT_START_PATROL
/mob/living/simple_animal/bot/proc/patrol_step_not_moved()
calc_path()
if(!length(path))
find_patrol_target()
tries = 0
// finds the nearest beacon to self
/mob/living/simple_animal/bot/proc/find_patrol_target()
send_status()
nearest_beacon = null
new_destination = null
find_nearest_beacon()
@@ -659,7 +669,6 @@ Pass a positive integer as an argument to override a bot's default speed.
auto_patrol = FALSE
mode = BOT_IDLE
speak("Disengaging patrol mode.")
send_status()
/mob/living/simple_animal/bot/proc/get_next_patrol_target()
// search the beacon list for the next target in the list.
@@ -702,83 +711,41 @@ Pass a positive integer as an argument to override a bot's default speed.
else
to_chat(src, "<span class='warning'>Unidentified control sequence recieved: [command]</span>")
/obj/machinery/bot_core/receive_signal(datum/signal/signal)
owner.receive_signal(signal)
/mob/living/simple_animal/bot/proc/receive_signal(datum/signal/signal)
/mob/living/simple_animal/bot/proc/handle_command(mob/user, command, list/params)
// We aint even on, why bother
if(!on)
return 1 //ACCESS DENIED
var/recv = signal.data["command"]
var/user = signal.data["user"]
// process all-bot input
if(recv == "bot_status" && (!signal.data["active"] || signal.data["active"] == src))
send_status()
return 1
return FALSE
// check to see if we are the commanded bot
if(signal.data["active"] == src)
if(emagged == 2 || remote_disabled) //Emagged bots do not respect anyone's authority! Bots with their remote controls off cannot get commands.
return 1
if(client)
bot_control_message(recv, user, signal.data["target"] ? signal.data["target"] : "Unknown")
// process control input
switch(recv)
if("stop")
bot_reset() //HOLD IT!!
auto_patrol = FALSE
if(emagged == 2 || remote_disabled) //Emagged bots do not respect anyone's authority! Bots with their remote controls off cannot get commands.
return FALSE
if("go")
auto_patrol = TRUE
if(client)
bot_control_message(command, user, params["target"] ? params["target"] : "Unknown")
if("summon")
bot_reset()
var/list/user_access = signal.data["useraccess"]
summon_target = signal.data["target"] //Location of the user
if(user_access.len != 0)
access_card.access = user_access + prev_access //Adds the user's access, if any.
mode = BOT_SUMMON
calc_summon_path()
speak("Responding.", radio_channel)
// process control input
switch(command)
if("stop")
bot_reset() //HOLD IT!!
auto_patrol = FALSE
else
return 0
return 1
if("go")
auto_patrol = TRUE
// send a radio signal with a single data key/value pair
/mob/living/simple_animal/bot/proc/post_signal(freq, key, value)
post_signal_multiple(freq, list("[key]" = value) )
if("summon")
bot_reset()
var/list/user_access = params["useraccess"]
summon_target = params["target"] // Location of the user
// send a radio signal with multiple data key/values
/mob/living/simple_animal/bot/proc/post_signal_multiple(freq, list/keyval)
if(!is_station_level(z)) //Bot control will only work on station.
return
var/datum/radio_frequency/frequency = SSradio.return_frequency(freq)
if(!frequency)
return
if(length(user_access))
access_card.access = user_access + prev_access //Adds the user's access, if any.
var/datum/signal/signal = new()
signal.source = bot_core
signal.transmission_method = 1
signal.data = keyval
spawn()
if(signal.data["type"] == bot_type)
frequency.post_signal(bot_core, signal, filter = bot_filter)
else
frequency.post_signal(bot_core, signal)
mode = BOT_SUMMON
calc_summon_path()
speak("Responding.", radio_channel)
return TRUE
// signals bot status etc. to controller
/mob/living/simple_animal/bot/proc/send_status()
if(remote_disabled || emagged == 2)
return
var/list/kv = list(
"type" = bot_type,
"name" = name,
"loca" = get_area(src), // area
"mode" = mode
)
post_signal_multiple(control_freq, kv)
/mob/living/simple_animal/bot/proc/bot_summon() // summoned to PDA
summon_step()
@@ -790,12 +757,12 @@ Pass a positive integer as an argument to override a bot's default speed.
set_path(get_path_to(src, patrol_target, /turf/proc/Distance_cardinal, 0, 120, id=access_card, exclude=avoid))
/mob/living/simple_animal/bot/proc/calc_summon_path(turf/avoid)
set waitfor = FALSE
check_bot_access()
spawn()
set_path(get_path_to(src, summon_target, /turf/proc/Distance_cardinal, 0, 150, id=access_card, exclude=avoid))
if(!path.len) //Cannot reach target. Give up and announce the issue.
speak("Summon command failed, destination unreachable.",radio_channel)
bot_reset()
set_path(get_path_to(src, summon_target, /turf/proc/Distance_cardinal, 0, 150, id=access_card, exclude=avoid))
if(!path.len) //Cannot reach target. Give up and announce the issue.
speak("Summon command failed, destination unreachable.",radio_channel)
bot_reset()
/mob/living/simple_animal/bot/proc/summon_step()
@@ -814,13 +781,17 @@ Pass a positive integer as an argument to override a bot's default speed.
var/moved = bot_move(summon_target, 3) // Move attempt
if(!moved)
spawn(2)
calc_summon_path()
tries = 0
addtimer(CALLBACK(src, .proc/try_calc_path), 2)
else // no path, so calculate new one
calc_summon_path()
/mob/living/simple_animal/bot/proc/try_calc_path()
calc_summon_path()
tries = 0
/mob/living/simple_animal/bot/proc/openedDoor(obj/machinery/door/D)
frustration = 0
@@ -844,6 +815,14 @@ Pass a positive integer as an argument to override a bot's default speed.
/mob/living/simple_animal/bot/proc/get_controls(mob/M)
return "PROTOBOT - NOT FOR USE"
/mob/living/simple_animal/bot/proc/allowed(mob/M)
var/acc = M.get_access() //see mob.dm
if(acc == IGNORE_ACCESS || M.can_admin_interact())
return TRUE //Mob ignores access
return has_access(list(), req_access, acc)
/mob/living/simple_animal/bot/Topic(href, href_list)
if(href_list["close"])// HUE HUE
if(usr in users)
@@ -855,7 +834,7 @@ Pass a positive integer as an argument to override a bot's default speed.
return 1
add_fingerprint(usr)
if((href_list["power"]) && (bot_core.allowed(usr) || !locked || usr.can_admin_interact()))
if((href_list["power"]) && (allowed(usr) || !locked || usr.can_admin_interact()))
if(on)
turn_off()
else
@@ -902,17 +881,6 @@ Pass a positive integer as an argument to override a bot's default speed.
/mob/living/simple_animal/bot/update_icon_state()
icon_state = "[initial(icon_state)][on]"
// Machinery to simplify topic and access calls
/obj/machinery/bot_core
use_power = NO_POWER_USE
var/mob/living/simple_animal/bot/owner = null
/obj/machinery/bot_core/New(loc)
..()
owner = loc
if(!istype(owner))
qdel(src)
/mob/living/simple_animal/bot/proc/topic_denied(mob/user) //Access check proc for bot topics! Remember to place in a bot's individual Topic if desired.
if(user.can_admin_interact())
return FALSE
@@ -975,7 +943,7 @@ Pass a positive integer as an argument to override a bot's default speed.
faction = initial(faction)
/mob/living/simple_animal/bot/proc/ejectpairemote(mob/user)
if(bot_core.allowed(user) && paicard)
if(allowed(user) && paicard)
speak("Ejecting personality chip.", radio_channel)
ejectpai(user)
@@ -1035,8 +1003,7 @@ Pass a positive integer as an argument to override a bot's default speed.
switch(message_mode)
if("intercom")
for(var/obj/item/radio/intercom/I in view(1, src))
spawn(0)
I.talk_into(src, message, null, verb, speaking)
I.talk_into(src, message, null, verb, speaking)
used_radios += I
if("headset")
Radio.talk_into(src, message, null, verb, speaking)
@@ -13,7 +13,7 @@
bot_type = CLEAN_BOT
model = "Cleanbot"
bot_purpose = "seek out messes and clean them"
bot_core_type = /obj/machinery/bot_core/cleanbot
req_access = list(ACCESS_JANITOR, ACCESS_ROBOTICS)
window_id = "autoclean"
window_name = "Automatic Station Cleaner v1.1"
pass_flags = PASSMOB
@@ -61,7 +61,7 @@
/mob/living/simple_animal/bot/cleanbot/attackby(obj/item/W, mob/user, params)
if(istype(W, /obj/item/card/id)||istype(W, /obj/item/pda))
if(bot_core.allowed(user) && !open && !emagged)
if(allowed(user) && !open && !emagged)
locked = !locked
to_chat(user, "<span class='notice'>You [ locked ? "lock" : "unlock"] \the [src] behaviour controls.</span>")
else
@@ -131,7 +131,7 @@
return
if(target && loc == target.loc)
clean(target)
start_clean(target)
path = list()
target = null
@@ -163,17 +163,19 @@
target_types += /obj/effect/decal/cleanable/dirt
target_types += /obj/effect/decal/cleanable/trail_holder
/mob/living/simple_animal/bot/cleanbot/proc/clean(obj/effect/decal/cleanable/target)
/mob/living/simple_animal/bot/cleanbot/proc/start_clean(obj/effect/decal/cleanable/target)
anchored = TRUE
icon_state = "cleanbot-c"
visible_message("<span class='notice'>[src] begins to clean up [target]</span>")
mode = BOT_CLEANING
spawn(50)
if(mode == BOT_CLEANING)
QDEL_NULL(target)
anchored = FALSE
mode = BOT_IDLE
icon_state = "cleanbot[on]"
addtimer(CALLBACK(src, .proc/do_clean, target), 5 SECONDS)
/mob/living/simple_animal/bot/cleanbot/proc/do_clean(obj/effect/decal/cleanable/target)
if(mode == BOT_CLEANING)
QDEL_NULL(target)
anchored = FALSE
mode = BOT_IDLE
icon_state = "cleanbot[on]"
/mob/living/simple_animal/bot/cleanbot/explode()
on = FALSE
@@ -186,10 +188,6 @@
do_sparks(3, 1, src)
..()
/obj/machinery/bot_core/cleanbot
req_one_access = list(ACCESS_JANITOR, ACCESS_ROBOTICS)
/mob/living/simple_animal/bot/cleanbot/show_controls(mob/M)
ui_interact(M)
@@ -245,6 +243,6 @@
/mob/living/simple_animal/bot/cleanbot/UnarmedAttack(atom/A)
if(istype(A,/obj/effect/decal/cleanable))
clean(A)
start_clean(A)
else
..()
@@ -405,7 +405,7 @@
if(!syndicate_aligned)
var/mob/living/simple_animal/bot/medbot/S = new /mob/living/simple_animal/bot/medbot(T, skin)
S.name = created_name
S.bot_core.req_one_access = req_one_access
S.req_access = req_one_access
S.treatment_oxy = treatment_oxy
S.treatment_brute = treatment_brute
S.treatment_fire = treatment_fire
@@ -19,7 +19,7 @@
bot_filter = RADIO_SECBOT
model = "ED-209"
bot_purpose = "seek out criminals, handcuff them, and report their location to security"
bot_core_type = /obj/machinery/bot_core/secbot
req_access = list(ACCESS_SECURITY)
window_id = "autoed209"
window_name = "Automatic Security Unit v2.6"
path_image_color = "#FF0000"
@@ -62,7 +62,7 @@
check_records = FALSE //Don't actively target people set to arrest
arrest_type = TRUE //Don't even try to cuff
declare_arrests = FALSE // Don't spam sec
bot_core.req_access = list(ACCESS_MAINT_TUNNELS, ACCESS_THEATRE, ACCESS_ROBOTICS)
req_access = list(ACCESS_MAINT_TUNNELS, ACCESS_THEATRE, ACCESS_ROBOTICS)
if(created_name == initial(name) || !created_name)
if(lasercolor == "b")
@@ -296,7 +296,7 @@
if(iscarbon(target) && target.canBeHandcuffed())
if(!arrest_type)
if(!target.handcuffed) //he's not cuffed? Try to cuff him!
cuff(target)
start_cuffing(target)
else
back_to_idle()
return
@@ -340,15 +340,13 @@
target = null
last_found = world.time
frustration = 0
spawn(0)
handle_automated_action() //ensure bot quickly responds
INVOKE_ASYNC(src, .proc/handle_automated_action)
/mob/living/simple_animal/bot/ed209/proc/back_to_hunt()
anchored = FALSE
frustration = 0
mode = BOT_HUNT
spawn(0)
handle_automated_action() //ensure bot quickly responds
INVOKE_ASYNC(src, .proc/handle_automated_action)
// look for a criminal in view of the bot
@@ -376,8 +374,7 @@
playsound(loc, pick('sound/voice/ed209_20sec.ogg', 'sound/voice/edplaceholder.ogg'), 50, 0)
visible_message("<b>[src]</b> points at [C.name]!")
mode = BOT_HUNT
spawn(0)
handle_automated_action() // ensure bot quickly responds to a perp
INVOKE_ASYNC(src, .proc/handle_automated_action)
break
else
continue
@@ -488,8 +485,7 @@
pulse2.name = "emp sparks"
pulse2.anchored = TRUE
pulse2.dir = pick(GLOB.cardinal)
spawn(10)
qdel(pulse2)
QDEL_IN(pulse2, 1 SECONDS)
var/list/mob/living/carbon/targets = new
for(var/mob/living/carbon/C in view(12,src))
if(C.stat==2)
@@ -522,23 +518,29 @@
if((lasercolor == "b"))
if(istype(Proj, /obj/item/projectile/beam/lasertag/redtag))
lasertag_check++
else if((lasercolor == "r"))
if(istype(Proj, /obj/item/projectile/beam/lasertag/bluetag))
lasertag_check++
if(lasertag_check)
icon_state = "[lasercolor]ed2090"
disabled = TRUE
walk_to(src, 0)
target = null
spawn(100)
disabled = FALSE
icon_state = "[lasercolor]ed2091"
return 1
addtimer(CALLBACK(src, .proc/unset_disabled), 10 SECONDS)
return TRUE
else
..(Proj)
else
..(Proj)
/mob/living/simple_animal/bot/ed209/proc/unset_disabled()
disabled = FALSE
icon_state = "[lasercolor]ed2091"
/mob/living/simple_animal/bot/ed209/bluetag
lasercolor = "b"
@@ -553,7 +555,7 @@
if(!C.IsStunned() || arrest_type && !baton_delayed)
stun_attack(A)
else if(C.canBeHandcuffed() && !C.handcuffed)
cuff(A)
start_cuffing(A)
else
..()
@@ -573,8 +575,7 @@
/mob/living/simple_animal/bot/ed209/proc/stun_attack(mob/living/carbon/C)
playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
icon_state = "[lasercolor]ed209-c"
spawn(2)
icon_state = "[lasercolor]ed209[on]"
addtimer(VARSET_CALLBACK(src, icon_state, "[lasercolor]ed209[on]"), 2)
var/threat = C.assess_threat(src)
C.SetStuttering(10 SECONDS)
C.adjustStaminaLoss(60)
@@ -588,18 +589,21 @@
C.visible_message("<span class='danger'>[src] has stunned [C]!</span>",\
"<span class='userdanger'>[src] has stunned you!</span>")
/mob/living/simple_animal/bot/ed209/proc/cuff(mob/living/carbon/C)
/mob/living/simple_animal/bot/ed209/proc/start_cuffing(mob/living/carbon/C)
mode = BOT_ARREST
playsound(loc, 'sound/weapons/cablecuff.ogg', 30, 1, -2)
C.visible_message("<span class='danger'>[src] is trying to put zipties on [C]!</span>",\
"<span class='userdanger'>[src] is trying to put zipties on you!</span>")
spawn(60)
if( !Adjacent(C) || !isturf(C.loc) ) //if he's in a closet or not adjacent, we cancel cuffing.
return
if(!C.handcuffed)
C.handcuffed = new /obj/item/restraints/handcuffs/cable/zipties/used(C)
C.update_handcuffed()
back_to_idle()
addtimer(CALLBACK(src, .proc/cuff_target, C), 6 SECONDS)
/mob/living/simple_animal/bot/ed209/proc/cuff_target(mob/living/carbon/C)
if(!Adjacent(C)|| !isturf(C.loc)) //if he's in a closet or not adjacent, we cancel cuffing.
return
if(!C.handcuffed)
C.handcuffed = new /obj/item/restraints/handcuffs/cable/zipties/used(C)
C.update_handcuffed()
back_to_idle()
#undef BATON_COOLDOWN
@@ -14,7 +14,7 @@
bot_filter = RADIO_FLOORBOT
model = "Floorbot"
bot_purpose = "seek out damaged or missing floor tiles, and repair or replace them as necessary"
bot_core_type = /obj/machinery/bot_core/floorbot
req_access = list(ACCESS_CONSTRUCTION, ACCESS_ROBOTICS)
window_id = "autofloor"
window_name = "Automatic Station Floor Repairer v1.1"
path_image_color = "#FFA500"
@@ -233,9 +233,9 @@
if(loc == target || loc == target.loc)
if(istype(target, /obj/item/stack/tile/plasteel))
eattile(target)
start_eattile(target)
else if(istype(target, /obj/item/stack/sheet/metal))
maketile(target)
start_maketile(target)
else if(istype(target, /turf/) && emagged < 2)
repair(target)
else if(emagged == 2 && istype(target,/turf/simulated/floor))
@@ -247,20 +247,23 @@
else
F.ReplaceWithLattice()
audible_message("<span class='danger'>[src] makes an excited booping sound.</span>")
spawn(50)
amount ++
anchored = FALSE
mode = BOT_IDLE
target = null
addtimer(CALLBACK(src, .proc/inc_amount_callback), 5 SECONDS)
path = list()
return
oldloc = loc
/mob/living/simple_animal/bot/floorbot/proc/inc_amount_callback()
amount ++
anchored = FALSE
mode = BOT_IDLE
target = null
/mob/living/simple_animal/bot/floorbot/proc/nag() //Annoy everyone on the channel to refill us!
if(!nagged)
speak("Requesting refill at <b>[get_area(src)]</b>!", radio_channel)
nagged = 1
nagged = TRUE
/mob/living/simple_animal/bot/floorbot/proc/is_hull_breach(turf/t) //Ignore space tiles not considered part of a structure, also ignores shuttle docking areas.
var/area/t_area = get_area(t)
@@ -299,90 +302,106 @@
return result
/mob/living/simple_animal/bot/floorbot/proc/repair(turf/target_turf)
if(istype(target_turf, /turf/space/))
//Must be a hull breach or in bridge mode to continue.
if(!is_hull_breach(target_turf) && !targetdirection)
target = null
return
else if(!istype(target_turf, /turf/simulated/floor))
return
if(amount <= 0)
mode = BOT_IDLE
target = null
return
anchored = TRUE
if(istype(target_turf, /turf/space/)) //If we are fixing an area not part of pure space, it is
visible_message("<span class='notice'>[targetdirection ? "[src] begins installing a bridge plating." : "[src] begins to repair the hole."] </span>")
mode = BOT_REPAIRING
update_icon(UPDATE_ICON_STATE)
spawn(50)
if(mode == BOT_REPAIRING)
if(autotile) //Build the floor and include a tile.
target_turf.ChangeTurf(/turf/simulated/floor/plasteel)
else //Build a hull plating without a floor tile.
target_turf.ChangeTurf(/turf/simulated/floor/plating)
mode = BOT_IDLE
amount -= 1
update_icon(UPDATE_ICON_STATE)
anchored = FALSE
target = null
addtimer(CALLBACK(src, .proc/make_bridge_plating, target_turf), 5 SECONDS)
else
var/turf/simulated/floor/F = target_turf
mode = BOT_REPAIRING
update_icon(UPDATE_ICON_STATE)
visible_message("<span class='notice'>[src] begins repairing the floor.</span>")
spawn(50)
if(mode == BOT_REPAIRING)
F.broken = FALSE
F.burnt = FALSE
F.ChangeTurf(/turf/simulated/floor/plasteel)
mode = BOT_IDLE
amount -= 1
update_icon(UPDATE_ICON_STATE)
anchored = FALSE
target = null
addtimer(CALLBACK(src, .proc/make_bridge_plating, F), 5 SECONDS)
/mob/living/simple_animal/bot/floorbot/proc/eattile(obj/item/stack/tile/plasteel/T)
/mob/living/simple_animal/bot/floorbot/proc/make_floor(turf/simulated/floor/F)
if(mode != BOT_REPAIRING)
return
F.broken = FALSE
F.burnt = FALSE
F.ChangeTurf(/turf/simulated/floor/plasteel)
mode = BOT_IDLE
amount--
update_icon(UPDATE_ICON_STATE)
anchored = FALSE
target = null
/mob/living/simple_animal/bot/floorbot/proc/make_bridge_plating(turf/target_turf)
if(mode != BOT_REPAIRING)
return
if(autotile) //Build the floor and include a tile.
target_turf.ChangeTurf(/turf/simulated/floor/plasteel)
else //Build a hull plating without a floor tile.
target_turf.ChangeTurf(/turf/simulated/floor/plating)
mode = BOT_IDLE
amount--
update_icon(UPDATE_ICON_STATE)
anchored = FALSE
target = null
/mob/living/simple_animal/bot/floorbot/proc/start_eattile(obj/item/stack/tile/plasteel/T)
if(!istype(T, /obj/item/stack/tile/plasteel))
return
visible_message("<span class='notice'>[src] begins to collect tiles.</span>")
mode = BOT_REPAIRING
spawn(20)
if(isnull(T))
target = null
mode = BOT_IDLE
return
if(amount + T.amount > 50)
var/i = 50 - amount
amount += i
T.amount -= i
else
amount += T.amount
qdel(T)
addtimer(CALLBACK(src, .proc/do_eattile, T), 2 SECONDS)
/mob/living/simple_animal/bot/floorbot/proc/do_eattile(obj/item/stack/tile/plasteel/T)
if(isnull(T))
target = null
mode = BOT_IDLE
update_icon(UPDATE_ICON_STATE)
return
if(amount + T.amount > 50)
var/i = 50 - amount
amount += i
T.amount -= i
else
amount += T.amount
qdel(T)
target = null
mode = BOT_IDLE
update_icon(UPDATE_ICON_STATE)
/mob/living/simple_animal/bot/floorbot/proc/maketile(obj/item/stack/sheet/metal/M)
/mob/living/simple_animal/bot/floorbot/proc/start_maketile(obj/item/stack/sheet/metal/M)
if(!istype(M, /obj/item/stack/sheet/metal))
return
visible_message("<span class='notice'>[src] begins to create tiles.</span>")
mode = BOT_REPAIRING
spawn(20)
if(isnull(M))
target = null
mode = BOT_IDLE
return
var/obj/item/stack/tile/plasteel/T = new /obj/item/stack/tile/plasteel
T.amount = 4
T.forceMove(M.loc)
if(M.amount > 1)
M.amount--
else
qdel(M)
addtimer(CALLBACK(src, .proc/do_maketile, M), 2 SECONDS)
/mob/living/simple_animal/bot/floorbot/proc/do_maketile(obj/item/stack/sheet/metal/M)
if(isnull(M))
target = null
mode = BOT_IDLE
return
var/obj/item/stack/tile/plasteel/T = new /obj/item/stack/tile/plasteel
T.amount = 4
T.forceMove(M.loc)
if(M.amount > 1)
M.amount--
else
qdel(M)
target = null
mode = BOT_IDLE
/mob/living/simple_animal/bot/floorbot/update_icon_state()
if(mode == BOT_REPAIRING)
@@ -416,15 +435,12 @@
do_sparks(3, 1, src)
..()
/obj/machinery/bot_core/floorbot
req_one_access = list(ACCESS_CONSTRUCTION, ACCESS_ROBOTICS)
/mob/living/simple_animal/bot/floorbot/UnarmedAttack(atom/A)
if(isturf(A))
repair(A)
else if(istype(A,/obj/item/stack/tile/plasteel))
eattile(A)
start_eattile(A)
else if(istype(A,/obj/item/stack/sheet/metal))
maketile(A)
start_maketile(A)
else
..()
@@ -29,14 +29,11 @@
block_chance_melee = 1
block_chance_ranged = 1
stun_chance = 0
bot_core_type = /obj/machinery/bot_core/toy
req_access = list(ACCESS_MAINT_TUNNELS, ACCESS_THEATRE, ACCESS_ROBOTICS)
weapon = /obj/item/toy/sword
frustration_number = 5
locked = FALSE
/obj/machinery/bot_core/toy
req_access = list(ACCESS_MAINT_TUNNELS, ACCESS_THEATRE, ACCESS_ROBOTICS)
/mob/living/simple_animal/bot/secbot/griefsky/proc/spam_flag_false() //used for addtimer to not spam comms
spam_flag = 0
@@ -82,9 +79,11 @@
..()
/mob/living/simple_animal/bot/secbot/griefsky/proc/sword_attack(mob/living/carbon/C) // esword attack
src.do_attack_animation(C)
do_attack_animation(C)
playsound(loc, 'sound/weapons/blade1.ogg', 50, 1, -1)
spawn(2)
addtimer(CALLBACK(src, .proc/do_sword_attack, C), 2)
/mob/living/simple_animal/bot/secbot/griefsky/proc/do_sword_attack(mob/living/carbon/C)
icon_state = spin_icon
var/threat = C.assess_threat(src)
if(ishuman(C))
@@ -13,7 +13,7 @@
bot_type = HONK_BOT
bot_filter = RADIO_HONKBOT
model = "Honkbot"
bot_core_type = /obj/machinery/bot_core/honkbot
req_access = list(ACCESS_CLOWN, ACCESS_ROBOTICS, ACCESS_MIME)
window_id = "autohonk"
window_name = "Honkomatic Bike Horn Unit v1.0.7"
data_hud_type = DATA_HUD_SECURITY_BASIC // show jobs
@@ -30,9 +30,6 @@
var/threatlevel = FALSE
var/arrest_type = FALSE
/obj/machinery/bot_core/honkbot
req_one_access = list(ACCESS_CLOWN, ACCESS_ROBOTICS, ACCESS_MIME)
/mob/living/simple_animal/bot/honkbot/Initialize(mapload)
. = ..()
update_icon()
@@ -16,7 +16,7 @@
bot_filter = RADIO_MEDBOT
model = "Medibot"
bot_purpose = "seek out hurt crewmembers and ensure that they are healed"
bot_core_type = /obj/machinery/bot_core/medbot
req_access = list(ACCESS_MEDICAL, ACCESS_ROBOTICS)
window_id = "automed"
window_name = "Automatic Medical Unit v1.1"
path_image_color = "#DDDDFF"
@@ -87,7 +87,7 @@
treatment_fire = "kelotane"
treatment_tox = "charcoal"
syndicate_aligned = TRUE
bot_core_type = /obj/machinery/bot_core/medbot/syndicate
req_access = list(ACCESS_SYNDICATE)
control_freq = BOT_FREQ + 1000 // make it not show up on lists
radio_channel = "Syndicate"
radio_config = list("Common" = 1, "Medical" = 1, "Syndicate" = 1)
@@ -508,31 +508,31 @@
bot_reset()
return
else
if(!emagged && check_overdose(patient,reagent_id,injection_amount))
if(!emagged && check_overdose(patient, reagent_id, injection_amount))
soft_reset()
return
C.visible_message("<span class='danger'>[src] is trying to inject [patient]!</span>", \
"<span class='userdanger'>[src] is trying to inject you!</span>")
spawn(30)//replace with do mob
if((get_dist(src, patient) <= 1) && on && assess_patient(patient))
if(inject_beaker)
if(use_beaker && reagent_glass && reagent_glass.reagents.total_volume)
var/fraction = min(injection_amount/reagent_glass.reagents.total_volume, 1)
reagent_glass.reagents.reaction(patient, REAGENT_INGEST, fraction)
reagent_glass.reagents.trans_to(patient, injection_amount) //Inject from beaker instead.
else
patient.reagents.add_reagent(reagent_id,injection_amount)
C.visible_message("<span class='danger'>[src] injects [patient] with its syringe!</span>", \
"<span class='userdanger'>[src] injects you with its syringe!</span>")
else
visible_message("[src] retracts its syringe.")
update_icon()
soft_reset()
return
addtimer(CALLBACK(src, .proc/do_inject, C, inject_beaker, reagent_id), 3 SECONDS)
return
reagent_id = null
return
/mob/living/simple_animal/bot/medbot/proc/do_inject(mob/living/carbon/C, inject_beaker, reagent_id)
if((get_dist(src, patient) <= 1) && on && assess_patient(patient))
if(inject_beaker)
if(use_beaker && reagent_glass && reagent_glass.reagents.total_volume)
var/fraction = min(injection_amount/reagent_glass.reagents.total_volume, 1)
reagent_glass.reagents.reaction(patient, REAGENT_INGEST, fraction)
reagent_glass.reagents.trans_to(patient, injection_amount) //Inject from beaker instead.
else
patient.reagents.add_reagent(reagent_id, injection_amount)
C.visible_message("<span class='danger'>[src] injects [patient] with its syringe!</span>", "<span class='userdanger'>[src] injects you with its syringe!</span>")
else
visible_message("[src] retracts its syringe.")
update_icon()
soft_reset()
/mob/living/simple_animal/bot/medbot/proc/check_overdose(mob/living/carbon/patient,reagent_id,injection_amount)
var/datum/reagent/R = GLOB.chemical_reagents_list[reagent_id]
@@ -598,8 +598,3 @@
spawn(200) //Twenty seconds
declare_cooldown = 0
/obj/machinery/bot_core/medbot
req_one_access = list(ACCESS_MEDICAL, ACCESS_ROBOTICS)
/obj/machinery/bot_core/medbot/syndicate
req_one_access = list(ACCESS_SYNDICATE)
@@ -25,12 +25,17 @@
bot_filter = RADIO_MULEBOT
model = "MULE"
bot_purpose = "deliver crates and other packages between departments, as requested"
bot_core_type = /obj/machinery/bot_core/mulebot
req_access = list(ACCESS_CARGO)
path_image_color = "#7F5200"
suffix = ""
/// Delay in deciseconds between each step
var/step_delay = 0
/// world.time of next move
var/next_move_time = 0
var/global/mulebot_count = 0
var/atom/movable/load = null
var/mob/living/passenger = null
@@ -50,6 +55,8 @@
var/currentBloodColor = "#A10808"
var/currentDNA = null
var/num_steps
/mob/living/simple_animal/bot/mulebot/get_cell()
return cell
@@ -250,7 +257,7 @@
update_controls()
/mob/living/simple_animal/bot/mulebot/proc/toggle_lock(mob/user)
if(bot_core.allowed(user))
if(allowed(user))
locked = !locked
update_controls()
return 1
@@ -442,7 +449,7 @@
// with items dropping as mobs are loaded
for(var/atom/movable/AM in src)
if(AM == cell || AM == access_card || AM == Radio || AM == bot_core || AM == paicard)
if(AM == cell || AM == access_card || AM == Radio || AM == paicard)
continue
AM.forceMove(loc)
@@ -466,109 +473,100 @@
if(!has_power())
on = FALSE
return
if(on)
var/speed = (!wires.is_cut(WIRE_MOTOR1) ? 1 : 0) + (!wires.is_cut(WIRE_MOTOR2) ? 2 : 0)
var/num_steps = 0
switch(speed)
if(0)
// do nothing
if(1)
num_steps = 10
if(2)
num_steps = 5
if(3)
num_steps = 3
if(num_steps)
process_bot()
num_steps--
if(mode != BOT_IDLE)
spawn(0)
for(var/i=num_steps,i>0,i--)
sleep(2)
process_bot()
/mob/living/simple_animal/bot/mulebot/proc/process_bot()
if(!on)
return
update_icon()
var/new_speed = (!wires.is_cut(WIRE_MOTOR1) ? 1 : 0) + (!wires.is_cut(WIRE_MOTOR2) ? 2 : 0)
if(!new_speed)//Devide by zero man bad
return
num_steps = round(10 / new_speed) //10, 5, or 3 steps, depending on how many wires we have cut
step_delay = num_steps // step_delay shouldnt change, num_steps should
START_PROCESSING(SSfastprocess, src)
/mob/living/simple_animal/bot/mulebot/process()
if(!on)
return PROCESS_KILL
num_steps--
switch(mode)
if(BOT_IDLE) // idle
return
if(BOT_DELIVER, BOT_GO_HOME, BOT_BLOCKED) // navigating to deliver,home, or blocked
if(world.time < next_move_time)
return
next_move_time = world.time + step_delay
if(loc == target) // reached target
at_target()
return
else if(path.len > 0 && target) // valid path
else if(length(path) && target) // valid path
var/turf/next = path[1]
reached_target = 0
reached_target = FALSE
if(next == loc)
increment_path()
path -= next
return
if(istype(next, /turf/simulated))
// to_chat(world, "at ([x],[y]) moving to ([next.x],[next.y])")
if(isturf(next))
var/oldloc = loc
var/moved = step_towards(src, next) // attempt to move
if(cell) cell.use(1)
if(moved && oldloc!=loc) // successful move
// to_chat(world, "Successful move.")
var/moved = step_towards(src, next) // attempt to move
if(moved && oldloc!=loc) // successful move
blockcount = 0
increment_path()
path -= loc
if(destination == home_destination)
mode = BOT_GO_HOME
else
mode = BOT_DELIVER
else // failed to move
else // failed to move
// to_chat(world, "Unable to move.")
blockcount++
mode = BOT_BLOCKED
if(blockcount == 3)
buzz(ANNOYED)
if(blockcount > 10) // attempt 10 times before recomputing
if(blockcount > 10) // attempt 10 times before recomputing
// find new path excluding blocked turf
buzz(SIGH)
mode = BOT_WAIT_FOR_NAV
blockcount = 0
spawn(20)
calc_path(avoid=next)
if(path.len > 0)
buzz(DELIGHT)
mode = BOT_BLOCKED
addtimer(CALLBACK(src, .proc/process_blocked, next), 2 SECONDS)
return
return
else
buzz(ANNOYED)
// to_chat(world, "Bad turf.")
mode = BOT_NAV
return
else
// to_chat(world, "No path.")
mode = BOT_NAV
return
if(BOT_NAV) // calculate new path
// to_chat(world, "Calc new path.")
if(BOT_NAV) // calculate new path
mode = BOT_WAIT_FOR_NAV
spawn(0)
calc_path()
INVOKE_ASYNC(src, .proc/process_nav)
if(path.len > 0)
blockcount = 0
mode = BOT_BLOCKED
buzz(DELIGHT)
/mob/living/simple_animal/bot/mulebot/proc/process_blocked(turf/next)
calc_path(avoid=next)
if(length(path))
buzz(DELIGHT)
mode = BOT_BLOCKED
else
buzz(SIGH)
/mob/living/simple_animal/bot/mulebot/proc/process_nav()
calc_path()
mode = BOT_NO_ROUTE
if(length(path))
blockcount = 0
mode = BOT_BLOCKED
buzz(DELIGHT)
else
buzz(SIGH)
mode = BOT_NO_ROUTE
// calculates a path to the current destination
// given an optional turf to avoid
@@ -599,9 +597,11 @@
/mob/living/simple_animal/bot/mulebot/proc/start_home()
if(!on)
return
spawn(0)
set_destination(home_destination)
mode = BOT_BLOCKED
INVOKE_ASYNC(src, .proc/do_start_home)
/mob/living/simple_animal/bot/mulebot/proc/do_start_home()
set_destination(home_destination)
mode = BOT_BLOCKED
update_icon()
// called when bot reaches current target
@@ -732,72 +732,52 @@
to_chat(src, "<span class='warning big'>DELIVER [load] TO [destination]</span>")
else
to_chat(src, "<span class='warning big'>PICK UP DELIVERY AT [destination]</span>")
if("unload")
if("unload", "load")
if(load)
to_chat(src, "<span class='warning big'>UNLOAD</span>")
else
to_chat(src, "<span class='warning big'>LOAD</span>")
if("autoret", "autopick", "target")
else
..()
/mob/living/simple_animal/bot/mulebot/receive_signal(datum/signal/signal)
if(wires.is_cut(WIRE_REMOTE_RX) || ..())
return TRUE
var/recv = signal.data["command"]
/mob/living/simple_animal/bot/mulebot/handle_command(mob/user, command, list/params)
if(wires.is_cut(WIRE_REMOTE_RX) || !..())
return FALSE
if(client)
bot_control_message(command, user, null)
return
. = TRUE
// process control input
switch(recv)
switch(command)
if("start")
start()
if("target")
set_destination(signal.data["destination"])
if("stop")
bot_reset()
if("home")
start_home()
if("unload")
if(client)
return 1
if(loc == target)
unload(loaddir)
else
unload(0)
if("home")
start_home()
if("target")
var/dest = input("Select Bot Destination", "Mulebot [suffix] Interlink", destination) as null|anything in GLOB.deliverybeacontags
if(dest)
set_destination(dest)
if("autoret")
auto_return = text2num(signal.data["value"])
if("set_auto_return")
auto_return = text2num(params["autoret"])
if("autopick")
auto_pickup = text2num(signal.data["value"])
else
return 0
return 1
// send a radio signal with multiple data key/values
/mob/living/simple_animal/bot/mulebot/post_signal_multiple(freq, list/keyval)
if(wires.is_cut(WIRE_REMOTE_TX))
return
..()
// signals bot status etc. to controller
/mob/living/simple_animal/bot/mulebot/send_status()
var/list/kv = list(
"type" = MULE_BOT,
"name" = suffix,
"loca" = get_area(src),
"mode" = mode,
"powr" = (cell ? cell.percent() : 0),
"dest" = destination,
"home" = home_destination,
"load" = load,
"retn" = auto_return,
"pick" = auto_pickup,
)
post_signal_multiple(control_freq, kv)
if("set_pickup_type")
auto_pickup = text2num(params["autopick"])
// player on mulebot attempted to move
/mob/living/simple_animal/bot/mulebot/relaymove(mob/user)
@@ -874,5 +854,3 @@
#undef ANNOYED
#undef DELIGHT
/obj/machinery/bot_core/mulebot
req_access = list(ACCESS_CARGO)
@@ -17,7 +17,7 @@
bot_filter = RADIO_SECBOT
model = "Securitron"
bot_purpose = "seek out criminals, handcuff them, and report their location to security"
bot_core_type = /obj/machinery/bot_core/secbot
req_access = list(ACCESS_SECURITY)
window_id = "autosec"
window_name = "Automatic Security Unit v1.6"
path_image_color = "#FF0000"
@@ -264,8 +264,7 @@
playsound(loc, 'sound/weapons/genhit1.ogg', 50, 1, -1)
do_attack_animation(C)
icon_state = "[base_icon]-c"
spawn(2)
icon_state = "[base_icon][on]"
addtimer(VARSET_CALLBACK(src, icon_state, "[base_icon][on]"), 2)
var/threat = C.assess_threat(src)
if(ishuman(C) && harmbaton) // Bots with harmbaton enabled become shitcurity. - Dave
C.apply_damage(10, BRUTE)
@@ -395,15 +394,13 @@
target = null
last_found = world.time
frustration = 0
spawn(0)
handle_automated_action() //ensure bot quickly responds
INVOKE_ASYNC(src, .proc/handle_automated_action)
/mob/living/simple_animal/bot/secbot/proc/back_to_hunt()
anchored = FALSE
frustration = 0
mode = BOT_HUNT
spawn(0)
handle_automated_action() //ensure bot quickly responds
INVOKE_ASYNC(src, .proc/handle_automated_action)
// look for a criminal in view of the bot
/mob/living/simple_animal/bot/secbot/proc/look_for_perp()
@@ -427,8 +424,7 @@
playsound(loc, pick('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg'), 50, 0)
visible_message("<b>[src]</b> points at [C.name]!")
mode = BOT_HUNT
spawn(0)
handle_automated_action() // ensure bot quickly responds to a perp
INVOKE_ASYNC(src, .proc/handle_automated_action)
break
else
continue
@@ -476,7 +472,4 @@
return
..()
/obj/machinery/bot_core/secbot
req_access = list(ACCESS_SECURITY)
#undef BATON_COOLDOWN
@@ -173,7 +173,7 @@
return
shootAt(A)
/mob/living/simple_animal/bot/ed209/syndicate/cuff(mob/living/carbon/C)
/mob/living/simple_animal/bot/ed209/syndicate/start_cuffing(mob/living/carbon/C)
shootAt(C)
/mob/living/simple_animal/bot/ed209/syndicate/stun_attack(mob/living/carbon/C)
+1 -3
View File
@@ -250,7 +250,7 @@ GLOBAL_LIST_EMPTY(PDAs)
playsound(src, 'sound/machines/pda_button1.ogg', 50, TRUE)
return
/obj/item/pda/attackby(obj/item/C as obj, mob/user as mob, params)
/obj/item/pda/attackby(obj/item/C, mob/user, params)
..()
if(istype(C, /obj/item/cartridge) && !cartridge)
cartridge = C
@@ -260,8 +260,6 @@ GLOBAL_LIST_EMPTY(PDAs)
update_shortcuts()
to_chat(user, "<span class='notice'>You insert [cartridge] into [src].</span>")
SStgui.update_uis(src)
if(cartridge.radio)
cartridge.radio.hostpda = src
playsound(src, 'sound/machines/pda_button1.ogg', 50, TRUE)
else if(istype(C, /obj/item/card/id))
-24
View File
@@ -9,8 +9,6 @@
/// Integrated signaler for captain, science & generic signaler cartridge
var/obj/item/assembly/signaler/integ_signaler
var/obj/item/integrated_radio/radio = null
var/charges = 0
var/list/stored_data = list()
@@ -18,7 +16,6 @@
var/list/messenger_plugins = list()
/obj/item/cartridge/Destroy()
QDEL_NULL(radio)
QDEL_LIST(programs)
QDEL_LIST(messenger_plugins)
return ..()
@@ -70,10 +67,6 @@
new /datum/data/pda/app/secbot_control
)
/obj/item/cartridge/security/Initialize(mapload)
. = ..()
radio = new /obj/item/integrated_radio/beepsky(src)
/obj/item/cartridge/detective
name = "D.E.T.E.C.T. Cartridge"
icon_state = "cart-s"
@@ -148,10 +141,6 @@
new /datum/data/pda/app/mule_control
)
/obj/item/cartridge/quartermaster/Initialize(mapload)
. = ..()
radio = new /obj/item/integrated_radio/mule(src)
/obj/item/cartridge/head
name = "Easy-Record DELUXE"
icon_state = "cart-h"
@@ -170,10 +159,6 @@
new /datum/data/pda/app/status_display
)
/obj/item/cartridge/hop/Initialize(mapload)
. = ..()
radio = new /obj/item/integrated_radio/mule(src)
/obj/item/cartridge/hos
name = "R.O.B.U.S.T. DELUXE"
icon_state = "cart-hos"
@@ -183,10 +168,6 @@
new /datum/data/pda/app/status_display
)
/obj/item/cartridge/hos/Initialize(mapload)
. = ..()
radio = new /obj/item/integrated_radio/beepsky(src)
/obj/item/cartridge/ce
name = "Power-On DELUXE"
icon_state = "cart-ce"
@@ -242,7 +223,6 @@
/obj/item/cartridge/captain/Initialize(mapload)
. = ..()
radio = new /obj/item/integrated_radio/beepsky(src)
integ_signaler = new /obj/item/assembly/signaler(src)
/obj/item/cartridge/supervisor
@@ -271,10 +251,6 @@
new /datum/data/pda/app/status_display
)
/obj/item/cartridge/centcom/Initialize(mapload)
. = ..()
radio = new /obj/item/integrated_radio/beepsky(src)
/obj/item/cartridge/syndicate
name = "Detomatix Cartridge"
icon_state = "cart"
+88 -109
View File
@@ -201,40 +201,41 @@
template = "pda_secbot"
category = "Security"
var/active_uid = null
/datum/data/pda/app/secbot_control/update_ui(mob/user as mob, list/data)
var/list/botsData = list()
var/list/beepskyData = list()
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/integrated_radio/beepsky))
var/obj/item/integrated_radio/beepsky/SC = pda.cartridge.radio
beepskyData["active"] = SC.active ? sanitize(SC.active.name) : null
has_back = SC.active ? 1 : 0
if(SC.active && !isnull(SC.botstatus))
var/area/loca = SC.botstatus["loca"]
var/loca_name = sanitize(loca.name)
beepskyData["botstatus"] = list("loca" = loca_name, "mode" = SC.botstatus["mode"])
else
beepskyData["botstatus"] = list("loca" = null, "mode" = -1)
var/botsCount=0
if(SC.botlist && SC.botlist.len)
for(var/mob/living/simple_animal/bot/B in SC.botlist)
botsCount++
if(B.loc)
botsData[++botsData.len] = list("Name" = sanitize(B.name), "Location" = sanitize(B.loc.loc.name), "uid" = "[B.UID()]")
if(!botsData.len)
var/mob/living/simple_animal/bot/secbot/active_bot = locateUID(active_uid)
if(active_bot && !QDELETED(active_bot))
beepskyData["active"] = active_bot ? sanitize(active_bot.name) : null
has_back = !!active_bot
if(active_bot && !isnull(active_bot.mode))
var/area/loca = get_area(active_bot)
var/loca_name = sanitize(loca.name)
beepskyData["botstatus"] = list("loca" = loca_name, "mode" = active_bot.mode)
else
var/botsCount = 0
var/list/mob/living/simple_animal/bot/bots = list()
for(var/mob/living/simple_animal/bot/secbot/SB in GLOB.bots_list)
bots += SB
for(var/mob/living/simple_animal/bot/ed209/ED in GLOB.bots_list)
bots += ED
for(var/mob/living/simple_animal/bot/B in bots)
botsCount++
if(B.loc)
botsData[++botsData.len] = list("Name" = sanitize(B.name), "Location" = sanitize(get_area(B).name), "uid" = "[B.UID()]")
if(!length(botsData))
botsData[++botsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "uid"= null)
beepskyData["bots"] = botsData
beepskyData["count"] = botsCount
else
beepskyData["active"] = 0
botsData[++botsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "uid"= null)
beepskyData["botstatus"] = list("loca" = null, "mode" = null)
beepskyData["bots"] = botsData
beepskyData["count"] = 0
has_back = 0
data["beepsky"] = beepskyData
/datum/data/pda/app/secbot_control/ui_act(action, list/params)
@@ -246,36 +247,26 @@
. = TRUE
// Aight listen up. Its time for a comment rant again.
// The old way of doing this was to proxy things directly from the NanoUI into the PDA's cartridge's radio Topic() function directly
// It was AWFUL and took me 30 minutes to even understand
// This is in no way a good solution, but it works atleast
// Why do we rely on this whole "magical radio system" anyways
// Hell, I would rather take GLOBs with direct interactions over this
// WHYYYYYYYYYYYYYYY -aa07
switch(action)
if("Back")
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/integrated_radio/beepsky))
pda.cartridge.radio.Topic(null, list(op = "botlist"))
if("Rescan")
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/integrated_radio/beepsky))
pda.cartridge.radio.Topic(null, list(op = "scanbots"))
if("AccessBot")
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/integrated_radio/beepsky))
pda.cartridge.radio.Topic(null, list(op = "control", bot = params["uid"]))
if("Stop")
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/integrated_radio/beepsky))
pda.cartridge.radio.Topic(null, list(op = "stop"))
if("Go")
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/integrated_radio/beepsky))
pda.cartridge.radio.Topic(null, list(op = "go"))
if("Home")
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/integrated_radio/beepsky))
pda.cartridge.radio.Topic(null, list(op = "home"))
if("Summon")
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/integrated_radio/beepsky))
pda.cartridge.radio.Topic(null, list(op = "summon"))
if("control")
active_uid = params["bot"]
if("botlist", "Back") // "Back" is part of the PDA TGUI itself.
active_uid = null
if("stop", "go", "home")
var/mob/living/simple_animal/bot/active_bot = locateUID(active_uid)
if(active_bot && !QDELETED(active_bot))
active_bot.handle_command(usr, action)
else
active_uid = null
if("summon")
var/mob/living/simple_animal/bot/active_bot = locateUID(active_uid)
if(active_bot && !QDELETED(active_bot))
active_bot.handle_command(usr, "summon", list("target" = get_turf(usr), "useraccess" = usr.get_access()))
else
active_uid = null
/datum/data/pda/app/mule_control
name = "Delivery Bot Control"
@@ -283,27 +274,37 @@
template = "pda_mule"
category = "Quartermaster"
var/active_uid = null
/datum/data/pda/app/mule_control/update_ui(mob/user as mob, list/data)
var/list/muleData = list()
var/list/mulebotsData = list()
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/integrated_radio/mule))
var/obj/item/integrated_radio/mule/QC = pda.cartridge.radio
muleData["active"] = QC.active ? sanitize(QC.active.name) : null
has_back = QC.active ? 1 : 0
if(QC.active && !isnull(QC.botstatus))
var/area/loca = QC.botstatus["loca"]
var/mob/living/simple_animal/bot/mulebot/active_bot = locateUID(active_uid)
if(active_bot && !QDELETED(active_bot))
muleData["active"] = active_bot ? sanitize(active_bot.name) : null
has_back = !!active_bot
if(active_bot && !isnull(active_bot.mode))
var/area/loca = get_area(active_bot)
var/loca_name = sanitize(loca.name)
muleData["botstatus"] = list("loca" = loca_name, "mode" = QC.botstatus["mode"],"home"=QC.botstatus["home"],"powr" = QC.botstatus["powr"],"retn" =QC.botstatus["retn"], "pick"=QC.botstatus["pick"], "load" = QC.botstatus["load"], "dest" = sanitize(QC.botstatus["dest"]))
muleData["botstatus"] = list(
"loca" = loca_name,
"mode" = active_bot.mode,
"home" = active_bot.home_destination,
"powr" = (active_bot.cell ? active_bot.cell.percent() : 0),
"retn" = active_bot.auto_return,
"pick" = active_bot.auto_pickup,
"load" = active_bot.load,
"dest" = sanitize(active_bot.destination)
)
else
muleData["botstatus"] = list("loca" = null, "mode" = -1,"home"=null,"powr" = null,"retn" =null, "pick"=null, "load" = null, "dest" = null)
var/mulebotsCount=0
for(var/mob/living/simple_animal/bot/B in QC.botlist)
else
var/mulebotsCount = 0
for(var/mob/living/simple_animal/bot/mulebot/B in GLOB.bots_list)
mulebotsCount++
if(B.loc)
mulebotsData[++mulebotsData.len] = list("Name" = sanitize(B.name), "Location" = sanitize(B.loc.loc.name), "uid" = "[B.UID()]")
mulebotsData[++mulebotsData.len] = list("Name" = sanitize(B.name), "Location" = get_area(B).name, "uid" = "[B.UID()]")
if(!mulebotsData.len)
mulebotsData[++mulebotsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "uid"= null)
@@ -311,14 +312,6 @@
muleData["bots"] = mulebotsData
muleData["count"] = mulebotsCount
else
muleData["botstatus"] = list("loca" = null, "mode" = -1,"home"=null,"powr" = null,"retn" =null, "pick"=null, "load" = null, "dest" = null)
muleData["active"] = 0
mulebotsData[++mulebotsData.len] = list("Name" = "No bots found", "Location" = "Invalid", "uid"= null)
muleData["bots"] = mulebotsData
muleData["count"] = 0
has_back = 0
data["mulebot"] = muleData
/datum/data/pda/app/mule_control/ui_act(action, list/params)
@@ -330,40 +323,26 @@
. = TRUE
// Heres the exact same shit as before, but worse
// See L257 to L263 for explanation
switch(action)
if("Back")
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/integrated_radio/mule))
pda.cartridge.radio.Topic(null, list(op = "botlist"))
if("Rescan")
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/integrated_radio/mule))
pda.cartridge.radio.Topic(null, list(op = "scanbots"))
if("AccessBot")
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/integrated_radio/mule))
pda.cartridge.radio.Topic(null, list(op = "control", bot = params["uid"]))
if("Unload")
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/integrated_radio/mule))
pda.cartridge.radio.Topic(null, list(op = "unload"))
if("SetDest")
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/integrated_radio/mule))
pda.cartridge.radio.Topic(null, list(op = "setdest"))
if("SetAutoReturn")
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/integrated_radio/mule))
pda.cartridge.radio.Topic(null, list(op = params["autoReturnType"])) // "retoff" or "reton"
if("SetAutoPickup")
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/integrated_radio/mule))
pda.cartridge.radio.Topic(null, list(op = params["autoPickupType"])) // "pickoff" or "pickon"
if("Stop")
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/integrated_radio/mule))
pda.cartridge.radio.Topic(null, list(op = "stop"))
if("Start")
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/integrated_radio/mule))
pda.cartridge.radio.Topic(null, list(op = "start"))
if("ReturnHome")
if(pda.cartridge && istype(pda.cartridge.radio, /obj/item/integrated_radio/mule))
pda.cartridge.radio.Topic(null, list(op = "home"))
if("control")
active_uid = params["bot"]
if("botlist", "Back") // "Back" is part of the PDA TGUI itself.
active_uid = null
if("stop", "start", "home", "unload", "target")
var/mob/living/simple_animal/bot/active_bot = locateUID(active_uid)
if(active_bot && !QDELETED(active_bot))
active_bot.handle_command(usr, action)
else
active_uid = null
if("set_auto_return", "set_pickup_type")
var/mob/living/simple_animal/bot/active_bot = locateUID(active_uid)
if(active_bot && !QDELETED(active_bot))
active_bot.handle_command(usr, action, params)
else
active_uid = null
/datum/data/pda/app/supply
name = "Supply Records"
-2
View File
@@ -86,8 +86,6 @@
scanmode = null
if(current_app in C.programs)
start_program(find_program(/datum/data/pda/app/main_menu))
if(C.radio)
C.radio.hostpda = null
for(var/datum/data/pda/P in notifying_programs)
if(P in C.programs)
P.unnotify()
-145
View File
@@ -1,145 +0,0 @@
//TODO convert this crap over to proper radios or find a way to utilize regualr radios for this object, this thing needs to go.
/obj/item/integrated_radio
name = "\improper PDA radio module"
desc = "An electronic radio system of Nanotrasen origin."
icon = 'icons/obj/module.dmi'
icon_state = "power_mod"
var/obj/item/pda/hostpda = null
var/list/botlist = null // list of bots
var/mob/living/simple_animal/bot/active // the active bot; if null, show bot list
var/list/botstatus // the status signal sent by the bot
var/bot_type //The type of bot it is.
var/bot_filter //Determines which radio filter to use.
var/control_freq = 1447
var/on = FALSE //Are we currently active??
var/menu_message = ""
/obj/item/integrated_radio/Initialize(mapload)
. = ..()
if(istype(loc.loc, /obj/item/pda))
hostpda = loc.loc
if(bot_filter)
add_to_radio(bot_filter)
/obj/item/integrated_radio/Destroy()
if(SSradio)
SSradio.remove_object(src, control_freq)
hostpda = null
return ..()
/obj/item/integrated_radio/proc/post_signal(freq, key, value, key2, value2, key3, value3, key4, value4, s_filter)
// to_chat(world, "Post: [freq]: [key]=[value], [key2]=[value2]")
var/datum/radio_frequency/frequency = SSradio.return_frequency(freq)
if(!frequency)
return
var/datum/signal/signal = new()
signal.source = src
signal.transmission_method = 1
signal.data[key] = value
if(key2)
signal.data[key2] = value2
if(key3)
signal.data[key3] = value3
if(key4)
signal.data[key4] = value4
frequency.post_signal(src, signal, filter = s_filter)
/obj/item/integrated_radio/receive_signal(datum/signal/signal)
if(bot_type && istype(signal.source, /obj/machinery/bot_core) && signal.data["type"] == bot_type)
if(!botlist)
botlist = new()
var/obj/machinery/bot_core/core = signal.source
if(istype(core) && !(core.owner in botlist))
botlist += core.owner
if(active == core.owner)
var/list/b = signal.data
botstatus = b.Copy()
/obj/item/integrated_radio/Topic(href, href_list)
..()
switch(href_list["op"])
if("control")
active = locateUID(href_list["bot"])
post_signal(control_freq, "command", "bot_status", "active", active, s_filter = bot_filter)
if("scanbots") // find all bots
botlist = null
post_signal(control_freq, "command", "bot_status", s_filter = bot_filter)
if("botlist")
active = null
if("stop", "go", "home")
post_signal(control_freq, "command", href_list["op"], "active", active, s_filter = bot_filter)
post_signal(control_freq, "command", "bot_status", "active", active, s_filter = bot_filter)
if("summon")
post_signal(control_freq, "command", "summon", "active", active, "target", get_turf(hostpda), "useraccess", hostpda.GetAccess(), "user", usr, s_filter = bot_filter)
post_signal(control_freq, "command", "bot_status", "active", active, s_filter = bot_filter)
/obj/item/integrated_radio/proc/add_to_radio(bot_filter) //Master filter control for bots. Must be placed in the bot's local New() to support map spawned bots.
if(SSradio)
SSradio.add_object(src, control_freq, filter = bot_filter)
/obj/item/integrated_radio/honkbot
bot_filter = RADIO_HONKBOT
bot_type = HONK_BOT
/obj/item/integrated_radio/beepsky
bot_filter = RADIO_SECBOT
bot_type = SEC_BOT
/obj/item/integrated_radio/medbot
bot_filter = RADIO_MEDBOT
bot_type = MED_BOT
/obj/item/integrated_radio/floorbot
bot_filter = RADIO_FLOORBOT
bot_type = FLOOR_BOT
/obj/item/integrated_radio/cleanbot
bot_filter = RADIO_CLEANBOT
bot_type = CLEAN_BOT
/obj/item/integrated_radio/mule
bot_filter = RADIO_MULEBOT
bot_type = MULE_BOT
/obj/item/integrated_radio/mule/Topic(href, href_list)
..()
switch(href_list["op"])
if("start")
post_signal(control_freq, "command", "start", "active", active, s_filter = RADIO_MULEBOT)
if("unload")
post_signal(control_freq, "command", "unload", "active", active, s_filter = RADIO_MULEBOT)
if("setdest")
if(GLOB.deliverybeacons)
var/dest = input("Select Bot Destination", "Mulebot [active.suffix] Interlink", active.destination) as null|anything in GLOB.deliverybeacontags
if(dest)
post_signal(control_freq, "command", "target", "active", active, "destination", dest, s_filter = RADIO_MULEBOT)
if("retoff")
post_signal(control_freq, "command", "autoret", "active", active, "value", 0, s_filter = RADIO_MULEBOT)
if("reton")
post_signal(control_freq, "command", "autoret", "active", active, "value", 1, s_filter = RADIO_MULEBOT)
if("pickoff")
post_signal(control_freq, "command", "autopick", "active", active, "value", 0, s_filter = RADIO_MULEBOT)
if("pickon")
post_signal(control_freq, "command", "autopick", "active", active, "value", 1, s_filter = RADIO_MULEBOT)
post_signal(control_freq, "command", "bot_status", "active", active, s_filter = RADIO_MULEBOT)