/mob/living/bot/medbot name = "Medibot" desc = "A little medical robot. He looks somewhat underwhelmed." icon_state = "medibot0" req_one_access = list(ACCESS_MEDICAL, ACCESS_ROBOTICS) botcard_access = list(ACCESS_MEDICAL, ACCESS_MORGUE, ACCESS_SURGERY, ACCESS_PHARMACY, ACCESS_VIROLOGY, ACCESS_GENETICS) var/obj/item/storage/firstaid/firstaid_item //AI vars var/frustration = 0 var/list/path = list() var/mob/living/carbon/human/patient = null var/mob/ignored = list() // Used by emag var/last_newpatient_speak = 0 var/message = null var/speech = 0 //Healing vars var/obj/item/reagent_containers/glass/reagent_glass = null //Can be set to draw from this for reagents. var/currently_healing = 0 var/injection_amount = 10 //How much reagent do we inject at a time? var/heal_threshold = 10 //Start healing when they have this much damage in a category var/use_beaker = 0 //Use reagents in beaker instead of default treatment agents. var/treatment_brute = /singleton/reagent/tricordrazine var/treatment_oxy = /singleton/reagent/tricordrazine var/treatment_fire = /singleton/reagent/tricordrazine var/treatment_tox = /singleton/reagent/tricordrazine var/treatment_emag = /singleton/reagent/toxin var/declare_treatment = 0 //When attempting to treat a patient, should it notify everyone wearing medhuds? /mob/living/bot/medbot/Initialize() var/list/firstaid_types = typesof(/obj/item/storage/firstaid) var/firstaid_to_use = pick(firstaid_types) firstaid_item = new firstaid_to_use(src) . = ..() /mob/living/bot/medbot/Destroy() QDEL_NULL(reagent_glass) QDEL_NULL(firstaid_item) return ..() /mob/living/bot/medbot/think() ..() if(!on) return if(speech && prob(1)) say(message) if(patient) if(Adjacent(patient)) if(!currently_healing) INVOKE_ASYNC(src, PROC_REF(UnarmedAttack), patient) else if(path.len && (get_dist(patient, path[path.len]) > 2)) // We have a path, but it's off path = list() if(!path.len && (get_dist(src, patient) > 1)) path = get_path_to(src, patient, 30, 0, botcard.GetAccess()) if(!length(path)) path = list() if(path.len) icon_state = "medibots" step_to(src, path[1]) path -= path[1] ++frustration if(get_dist(src, patient) > 7 || frustration > 8) patient = null icon_state = "medibot[on]" else for(var/mob/living/carbon/human/H in view(7, src)) // Time to find a patient! if(valid_healing_target(H)) patient = H frustration = 0 if(last_newpatient_speak + 300 < world.time) var/message = pick("Hey, [H.name]! Hold on, I'm coming.", "Wait [H.name]! I want to help!", "[H.name], you appear to be injured!") say(message) custom_emote(VISIBLE_MESSAGE, "points at [H.name].") last_newpatient_speak = world.time break /mob/living/bot/medbot/UnarmedAttack(var/mob/living/carbon/human/H, var/proximity) . = ..() if(!.) return if(!on) return if(!istype(H)) return if(H.stat == DEAD) if(pAI) to_chat(pAI.pai, SPAN_WARNING("\The [H] is dead, you cannot help them now.")) return var/death_message = pick("No! NO!", "Live, damnit! LIVE!", "I... I've never lost a patient before. Not today, I mean.") say(death_message) patient = null return var/t = valid_healing_target(H) if(!t) var/message = pick("All patched up!", "An apple a day keeps me away.", "Feel better soon!") say(message) patient = null return visible_message(SPAN_WARNING("[src] is trying to inject [H]!")) if(declare_treatment) var/area/location = get_area(src) broadcast_medical_hud_message("[src] is treating [H] in [location]", src) currently_healing = 1 update_icon() if(do_mob(src, H, 30)) if(t == 1) reagent_glass.reagents.trans_to_mob(H, injection_amount, CHEM_BLOOD) else H.reagents.add_reagent(t, injection_amount) visible_message(SPAN_WARNING("[src] injects [H] with the syringe!")) currently_healing = 0 update_icon() /mob/living/bot/medbot/update_icon() if(!underlays.len) underlays += image(firstaid_item.icon, firstaid_item.icon_state) var/matrix/M = matrix() var/image/ha_image = image('icons/obj/item/scanner.dmi', "healthanalyzer") M.Translate(5, 0) ha_image.transform = M underlays += ha_image if(currently_healing) icon_state = "mediboth" else icon_state = "medibot[on]" /mob/living/bot/medbot/attack_hand(var/mob/user) if (!has_ui_access(user)) to_chat(user, SPAN_WARNING("The unit's interface refuses to unlock!")) return var/dat = "" dat += "Status: [on ? "On" : "Off"]
" dat += "Maintenance panel is [open ? "opened" : "closed"]
" dat += "Beaker: " if (reagent_glass) dat += "Loaded \[[reagent_glass.reagents.total_volume]/[reagent_glass.reagents.maximum_volume]\]" else dat += "None Loaded" dat += "
Behaviour controls are [locked ? "locked" : "unlocked"]
" if(!locked || issilicon(user)) dat += "Healing Threshold: " dat += "-- " dat += "- " dat += "[heal_threshold] " dat += "+ " dat += "++" dat += "
" dat += "Injection Level: " dat += "- " dat += "[injection_amount] " dat += "+ " dat += "
" dat += "Reagent Source: " dat += "[use_beaker ? "Loaded Beaker (When available)" : "Internal Synthesizer"]
" dat += "Treatment report is [declare_treatment ? "on" : "off"]. Toggle
" dat += "The speaker switch is [speech ? "on" : "off"]. Toggle
" dat += "Message is [message ? message : "unset"]. Set
" var/datum/browser/bot_win = new(user, "automed", "Automatic Medibot v1.2 Controls") bot_win.set_content(dat) bot_win.open() /mob/living/bot/medbot/attackby(obj/item/attacking_item, mob/user) if(istype(attacking_item, /obj/item/reagent_containers/glass)) if(locked) to_chat(user, SPAN_NOTICE("You cannot insert a beaker because the panel is locked.")) return if(!isnull(reagent_glass)) to_chat(user, SPAN_NOTICE("There is already a beaker loaded.")) return user.drop_from_inventory(attacking_item, src) reagent_glass = attacking_item to_chat(user, SPAN_NOTICE("You insert [attacking_item].")) return 1 else ..() /mob/living/bot/medbot/Topic(href, href_list) if(..()) return usr.set_machine(src) add_fingerprint(usr) if (!has_ui_access(usr)) to_chat(usr, SPAN_WARNING("Insufficient permissions.")) return if (href_list["power"]) if (on) turn_off() else turn_on() else if(href_list["adj_threshold"] && (!locked || issilicon(usr))) var/adjust_num = text2num(href_list["adj_threshold"]) heal_threshold += adjust_num if(heal_threshold < 5) heal_threshold = 5 if(heal_threshold > 75) heal_threshold = 75 else if(href_list["adj_inject"] && (!locked || issilicon(usr))) var/adjust_num = text2num(href_list["adj_inject"]) injection_amount += adjust_num if(injection_amount < 5) injection_amount = 5 if(injection_amount > 15) injection_amount = 15 else if(href_list["use_beaker"] && (!locked || issilicon(usr))) use_beaker = !use_beaker else if (href_list["eject"] && (!isnull(reagent_glass))) if(!locked) reagent_glass.forceMove(get_turf(src)) reagent_glass = null else to_chat(usr, SPAN_NOTICE("You cannot eject the beaker because the panel is locked.")) else if (href_list["declaretreatment"] && (!locked || issilicon(usr))) declare_treatment = !declare_treatment else if (href_list["msg"] && (!locked || issilicon(usr))) var/I = sanitize(input(usr,"What will this medbot say?", "Set Message") as text|null) if(!I) return message = I speech = 1 else if (href_list["speaker"] && (!locked || issilicon(usr))) speech = !speech attack_hand(usr) return /mob/living/bot/medbot/emag_act(var/remaining_uses, var/mob/user) . = ..() if(!emagged) if(user) to_chat(user, SPAN_WARNING("You short out [src]'s reagent synthesis circuits.")) visible_message(SPAN_WARNING("[src] buzzes oddly!")) flick_overlay("medibot_spark", src) patient = null currently_healing = 0 emagged = 1 on = 1 update_icon() . = 1 ignored |= user /mob/living/bot/medbot/explode() on = FALSE visible_message(SPAN_DANGER("\The [src] blows apart!")) var/turf/Tsec = get_turf(src) if(firstaid_item) firstaid_item.forceMove(Tsec) firstaid_item.contents = null firstaid_item = null new /obj/item/assembly/prox_sensor(Tsec) new /obj/item/healthanalyzer(Tsec) if (prob(50)) new /obj/item/robot_parts/l_arm(Tsec) if(reagent_glass) reagent_glass.forceMove(Tsec) reagent_glass = null spark(src, 3, GLOB.alldirs) qdel(src) return /mob/living/bot/medbot/turn_off() patient = null frustration = 0 currently_healing = 0 ..() /mob/living/bot/medbot/proc/valid_healing_target(var/mob/living/carbon/human/H) if(H.stat == DEAD) // He's dead, Jim return null if(isipc(H)) return null if(H in ignored) return null if(emagged) return treatment_emag // If they're injured, we're using a beaker, and they don't have on of the chems in the beaker if(reagent_glass && use_beaker && ((H.getBruteLoss() >= heal_threshold) || (H.getToxLoss() >= heal_threshold) || (H.getToxLoss() >= heal_threshold) || (H.getOxyLoss() >= (heal_threshold + 15)))) for(var/_R in reagent_glass.reagents.reagent_volumes) var/singleton/reagent/R = GET_SINGLETON(_R) if(!H.reagents.has_reagent(R)) return TRUE continue if((H.getBruteLoss() >= heal_threshold) && (!H.reagents.has_reagent(treatment_brute))) return treatment_brute //If they're already medicated don't bother! if((H.getOxyLoss() >= (15 + heal_threshold)) && (!H.reagents.has_reagent(treatment_oxy))) return treatment_oxy if((H.getFireLoss() >= heal_threshold) && (!H.reagents.has_reagent(treatment_fire))) return treatment_fire if((H.getToxLoss() >= heal_threshold) && (!H.reagents.has_reagent(treatment_tox))) return treatment_tox /* Construction */ /obj/item/storage/firstaid/attackby(obj/item/attacking_item, mob/user) var/obj/item/robot_parts/S = attacking_item if ((!istype(S, /obj/item/robot_parts/l_arm)) && (!istype(S, /obj/item/robot_parts/r_arm))) ..() return if(contents.len >= 1) to_chat(user, SPAN_NOTICE("You need to empty [src] out first.")) return var/obj/item/firstaid_arm_assembly/A = new /obj/item/firstaid_arm_assembly A.underlays += image(icon, icon_state) A.firstaid_item = src qdel(S) user.put_in_hands(A) to_chat(user, SPAN_NOTICE("You add the robot arm to the first aid kit.")) qdel(src) /obj/item/firstaid_arm_assembly name = "first aid/robot arm assembly" desc = "A first aid kit with a robot arm permanently grafted to it." icon = 'icons/mob/npc/aibots.dmi' icon_state = "firstaid_arm" w_class = WEIGHT_CLASS_NORMAL var/build_step = 0 var/created_name = "Medibot" //To preserve the name if it's a unique medbot I guess var/obj/item/storage/firstaid/firstaid_item // store the firstaid type if it blows up /obj/item/firstaid_arm_assembly/attackby(obj/item/attacking_item, mob/user) ..() if(attacking_item.tool_behaviour == TOOL_PEN) var/t = sanitizeSafe( tgui_input_text(user, "Enter new robot name", name, created_name, MAX_NAME_LEN), MAX_NAME_LEN ) if(!t) return if(!in_range(src, user) && loc != user) return created_name = t else switch(build_step) if(0) if(istype(attacking_item, /obj/item/healthanalyzer)) user.drop_from_inventory(attacking_item,get_turf(src)) qdel(attacking_item) build_step++ to_chat(user, SPAN_NOTICE("You add the health sensor to [src].")) name = "first-aid/robot arm/health analyzer assembly" var/matrix/M = matrix() var/image/ha_image = image('icons/obj/item/scanner.dmi', "health") M.Translate(5, 0) ha_image.transform = M underlays += ha_image return 1 if(1) if(isprox(attacking_item)) user.drop_from_inventory(attacking_item, get_turf(src)) qdel(attacking_item) to_chat(user, SPAN_NOTICE("You complete the Medibot! Beep boop.")) var/turf/T = get_turf(src) var/mob/living/bot/medbot/S = new /mob/living/bot/medbot(T) S.name = created_name S.underlays = src.underlays S.update_icon() S.firstaid_item = firstaid_item qdel(src) return 1