mirror of
https://github.com/KabKebab/GS13.git
synced 2026-07-14 17:37:04 +01:00
Add the nutribot
This adds a nutribot. This is pretty epic if you ask me. It's supposed to feed you and stuff.. current bug where it thinks you need feeding in assess, but then fails to feed you in medicate. Always thinks you need feeding, too
This commit is contained in:
@@ -0,0 +1,735 @@
|
||||
//nutribot
|
||||
//nutribot PATHFINDING
|
||||
//nutribot ASSEMBLY
|
||||
#define NUTRIBOT_PANIC_NONE 0
|
||||
#define NUTRIBOT_PANIC_LOW 15
|
||||
#define NUTRIBOT_PANIC_MED 35
|
||||
#define NUTRIBOT_PANIC_HIGH 55
|
||||
#define NUTRIBOT_PANIC_FUCK 70
|
||||
#define NUTRIBOT_PANIC_ENDING 90
|
||||
#define NUTRIBOT_PANIC_END 100
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot
|
||||
name = "\improper Nutribot"
|
||||
desc = "A little nutritional robot. He looks somewhat underwhelmed."
|
||||
icon = 'icons/mob/aibots.dmi'
|
||||
icon_state = "nutribot0"
|
||||
density = FALSE
|
||||
anchored = FALSE
|
||||
health = 20
|
||||
maxHealth = 20
|
||||
pass_flags = PASSMOB
|
||||
|
||||
status_flags = (CANPUSH | CANSTUN)
|
||||
|
||||
radio_key = /obj/item/encryptionkey/headset_med
|
||||
radio_channel = RADIO_CHANNEL_MEDICAL
|
||||
|
||||
bot_type = MED_BOT
|
||||
model = "Nutribot"
|
||||
bot_core_type = /obj/machinery/bot_core/nutribot
|
||||
window_id = "automed"
|
||||
window_name = "Automatic Nutritional Unit v1.1"
|
||||
data_hud_type = DATA_HUD_MEDICAL_ADVANCED
|
||||
path_image_color = "#DDDDFF"
|
||||
|
||||
var/obj/item/reagent_containers/glass/reagent_glass = null //Can be set to draw from this for reagents.
|
||||
var/healthanalyzer = /obj/item/healthanalyzer
|
||||
var/firstaid = /obj/item/storage/firstaid
|
||||
var/skin = null //Set to "tox", "ointment" or "o2" for the other two firstaid kits.
|
||||
var/mob/living/carbon/patient = null
|
||||
var/mob/living/carbon/oldpatient = null
|
||||
var/oldloc = null
|
||||
var/last_found = 0
|
||||
var/last_newpatient_speak = 0 //Don't spam the "HEY I'M COMING" messages
|
||||
var/injection_amount = 15 //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/feed_threshold = 200 // The weight that people should be fed to!
|
||||
var/use_beaker = 0 //Use reagents in beaker instead of default treatment agents.
|
||||
var/declare_crit = 1 //If active, the bot will transmit a critical patient alert to MedHUD users.
|
||||
var/declare_cooldown = 0 //Prevents spam of critical patient alerts.
|
||||
var/stationary_mode = 0 //If enabled, the Nutribot will not move automatically.
|
||||
//Setting which reagents to use to treat what by default. By id.
|
||||
var/treatment_thin = /datum/reagent/consumable/nutriment
|
||||
var/treatment_thirsty = /datum/reagent/water
|
||||
var/hunger_check = NUTRITION_LEVEL_FED
|
||||
/*var/treatment_brute_avoid = /datum/reagent/medicine/tricordrazine
|
||||
var/treatment_brute = /datum/reagent/medicine/bicaridine
|
||||
var/treatment_oxy_avoid = null
|
||||
var/treatment_oxy = /datum/reagent/medicine/dexalin
|
||||
var/treatment_fire_avoid = /datum/reagent/medicine/tricordrazine
|
||||
var/treatment_fire = /datum/reagent/medicine/kelotane
|
||||
var/treatment_tox_avoid = /datum/reagent/medicine/tricordrazine
|
||||
var/treatment_tox = /datum/reagent/medicine/charcoal
|
||||
var/treatment_tox_toxlover = /datum/reagent/toxin
|
||||
var/treatment_virus_avoid = null
|
||||
var/treatment_virus = /datum/reagent/medicine/spaceacillin
|
||||
var/treat_virus = 1 //If on, the bot will attempt to treat viral infections, curing them if possible.
|
||||
*/
|
||||
var/shut_up = 0 //self explanatory :)
|
||||
|
||||
//How panicked we are about being tipped over (why would you do this?)
|
||||
var/tipped_status = NUTRIBOT_PANIC_NONE
|
||||
//The name we got when we were tipped
|
||||
var/tipper_name
|
||||
//The last time we were tipped/righted and said a voice line, to avoid spam
|
||||
var/last_tipping_action_voice = 0
|
||||
|
||||
/*
|
||||
/mob/living/simple_animal/bot/nutribot/mysterious
|
||||
name = "\improper Mysterious Nutribot"
|
||||
desc = "International Nutribot of mystery."
|
||||
skin = "bezerk"
|
||||
treatment_brute = /datum/reagent/medicine/tricordrazine
|
||||
treatment_fire = /datum/reagent/medicine/tricordrazine
|
||||
treatment_tox = /datum/reagent/medicine/tricordrazine
|
||||
*/
|
||||
|
||||
/*
|
||||
/mob/living/simple_animal/bot/nutribot/derelict
|
||||
name = "\improper Old Nutribot"
|
||||
desc = "Looks like it hasn't been modified since the late 2080s."
|
||||
skin = "bezerk"
|
||||
heal_threshold = 0
|
||||
declare_crit = 0
|
||||
treatment_oxy = /datum/reagent/toxin/pancuronium
|
||||
treatment_brute_avoid = null
|
||||
treatment_brute = /datum/reagent/toxin/pancuronium
|
||||
treatment_fire_avoid = null
|
||||
treatment_fire = /datum/reagent/toxin/sodium_thiopental
|
||||
treatment_tox_avoid = null
|
||||
treatment_tox = /datum/reagent/toxin/sodium_thiopental
|
||||
*/
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/update_icon()
|
||||
cut_overlays()
|
||||
if(!on)
|
||||
icon_state = "off"
|
||||
return
|
||||
if(IsStun())
|
||||
icon_state = "medibota"
|
||||
return
|
||||
if(mode == BOT_HEALING)
|
||||
icon_state = "medibots[stationary_mode]"
|
||||
return
|
||||
else if(stationary_mode) //Bot has yellow light to indicate stationary mode.
|
||||
icon_state = "medibot2"
|
||||
else
|
||||
icon_state = "medibot1"
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/Initialize(mapload, new_skin)
|
||||
. = ..()
|
||||
var/datum/job/doctor/J = new /datum/job/doctor
|
||||
access_card.access += J.get_access()
|
||||
prev_access = access_card.access
|
||||
qdel(J)
|
||||
skin = new_skin
|
||||
update_icon()
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/update_canmove()
|
||||
. = ..()
|
||||
update_icon()
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/bot_reset()
|
||||
..()
|
||||
patient = null
|
||||
oldpatient = null
|
||||
oldloc = null
|
||||
last_found = world.time
|
||||
declare_cooldown = 0
|
||||
update_icon()
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/proc/soft_reset() //Allows the Nutribot to still actively perform its medical duties without being completely halted as a hard reset does.
|
||||
path = list()
|
||||
patient = null
|
||||
mode = BOT_IDLE
|
||||
last_found = world.time
|
||||
update_icon()
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/set_custom_texts()
|
||||
|
||||
text_hack = "You corrupt [name]'s reagent processor circuits."
|
||||
text_dehack = "You reset [name]'s reagent processor circuits."
|
||||
text_dehack_fail = "[name] seems damaged and does not respond to reprogramming!"
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/attack_paw(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/get_controls(mob/user)
|
||||
var/dat
|
||||
dat += hack(user)
|
||||
dat += showpai(user)
|
||||
dat += "<TT><B>Medical Unit Controls v1.1</B></TT><BR><BR>"
|
||||
dat += "Status: <A href='?src=[REF(src)];power=1'>[on ? "On" : "Off"]</A><BR>"
|
||||
dat += "Maintenance panel panel is [open ? "opened" : "closed"]<BR>"
|
||||
dat += "Beaker: "
|
||||
if(reagent_glass)
|
||||
dat += "<A href='?src=[REF(src)];eject=1'>Loaded \[[reagent_glass.reagents.total_volume]/[reagent_glass.reagents.maximum_volume]\]</a>"
|
||||
else
|
||||
dat += "None Loaded"
|
||||
dat += "<br>Behaviour controls are [locked ? "locked" : "unlocked"]<hr>"
|
||||
if(!locked || issilicon(user) || IsAdminGhost(user))
|
||||
/*dat += "<TT>Healing Threshold: "
|
||||
dat += "<a href='?src=[REF(src)];adj_threshold=-10'>--</a> "
|
||||
dat += "<a href='?src=[REF(src)];adj_threshold=-5'>-</a> "
|
||||
dat += "[heal_threshold] "
|
||||
dat += "<a href='?src=[REF(src)];adj_threshold=5'>+</a> "
|
||||
dat += "<a href='?src=[REF(src)];adj_threshold=10'>++</a>"
|
||||
dat += "</TT><br>"*/
|
||||
|
||||
dat += "<TT>Injection Level: "
|
||||
dat += "<a href='?src=[REF(src)];adj_inject=-5'>-</a> "
|
||||
dat += "[injection_amount] "
|
||||
dat += "<a href='?src=[REF(src)];adj_inject=5'>+</a> "
|
||||
dat += "</TT><br>"
|
||||
|
||||
dat += "Reagent Source: "
|
||||
dat += "<a href='?src=[REF(src)];use_beaker=1'>[use_beaker ? "Loaded Beaker (When available)" : "Internal Synthesizer"]</a><br>"
|
||||
|
||||
dat += "Hunger Check: "
|
||||
dat += "<a href='?src=[REF(src)];hunger_check=1'>[(hunger_check==NUTRITION_LEVEL_HUNGRY) ? "Yes" : "No"]</a><br>"
|
||||
|
||||
dat += "<TT>Maximum Weight: "
|
||||
dat += "[feed_threshold ? 140+(feed_threshold*FATNESS_TO_WEIGHT_RATIO) : "???"] "
|
||||
dat += "Disable Maximum Weight: <a href='?src=[REF(src)];feed_threshold=1'>["Disable"]</a><br> "
|
||||
dat += "<a href='?src=[REF(src)];feed_threshold=-100'>-</a> "
|
||||
dat += "<a href='?src=[REF(src)];feed_threshold=100'>+</a> "
|
||||
dat += "</TT><br>"
|
||||
|
||||
//dat += "Treat Viral Infections: <a href='?src=[REF(src)];virus=1'>[treat_virus ? "Yes" : "No"]</a><br>"
|
||||
dat += "The speaker switch is [shut_up ? "off" : "on"]. <a href='?src=[REF(src)];togglevoice=[1]'>Toggle</a><br>"
|
||||
//dat += "Critical Patient Alerts: <a href='?src=[REF(src)];critalerts=1'>[declare_crit ? "Yes" : "No"]</a><br>"
|
||||
dat += "Patrol Station: <a href='?src=[REF(src)];operation=patrol'>[auto_patrol ? "Yes" : "No"]</a><br>"
|
||||
dat += "Stationary Mode: <a href='?src=[REF(src)];stationary=1'>[stationary_mode ? "Yes" : "No"]</a><br>"
|
||||
|
||||
return dat
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/Topic(href, href_list)
|
||||
if(..())
|
||||
return 1
|
||||
|
||||
/*if(href_list["adj_threshold"])
|
||||
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"])
|
||||
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"])
|
||||
use_beaker = !use_beaker
|
||||
|
||||
else if(href_list["eject"] && (!isnull(reagent_glass)))
|
||||
reagent_glass.forceMove(drop_location())
|
||||
reagent_glass = null
|
||||
|
||||
else if(href_list["togglevoice"])
|
||||
shut_up = !shut_up
|
||||
|
||||
/*else if(href_list["critalerts"])
|
||||
declare_crit = !declare_crit*/
|
||||
|
||||
else if(href_list["stationary"])
|
||||
stationary_mode = !stationary_mode
|
||||
path = list()
|
||||
update_icon()
|
||||
|
||||
//else if(href_list["virus"])
|
||||
//treat_virus = !treat_virus
|
||||
|
||||
else if(href_list["hunger_check"])
|
||||
hunger_check = ((hunger_check==NUTRITION_LEVEL_HUNGRY) ? NUTRITION_LEVEL_FULL : NUTRITION_LEVEL_HUNGRY)
|
||||
|
||||
else if(href_list["feed_threshold"])
|
||||
var/adjust_num = text2num(href_list["feed_threshold"])
|
||||
feed_threshold += adjust_num
|
||||
if(adjust_num == 1)
|
||||
feed_threshold = 0
|
||||
if(feed_threshold < 0)
|
||||
feed_threshold = 0
|
||||
|
||||
update_controls()
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/attackby(obj/item/W as obj, mob/user as mob, params)
|
||||
if(istype(W, /obj/item/reagent_containers/glass))
|
||||
. = 1 //no afterattack
|
||||
if(locked)
|
||||
to_chat(user, "<span class='warning'>You cannot insert a beaker because the panel is locked!</span>")
|
||||
return
|
||||
if(!isnull(reagent_glass))
|
||||
to_chat(user, "<span class='warning'>There is already a beaker loaded!</span>")
|
||||
return
|
||||
if(!user.transferItemToLoc(W, src))
|
||||
return
|
||||
|
||||
reagent_glass = W
|
||||
to_chat(user, "<span class='notice'>You insert [W].</span>")
|
||||
show_controls(user)
|
||||
|
||||
else
|
||||
var/current_health = health
|
||||
..()
|
||||
if(health < current_health) //if nutribot took some damage
|
||||
step_to(src, (get_step_away(src,user)))
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/emag_act(mob/user)
|
||||
..()
|
||||
if(emagged == 2)
|
||||
//declare_crit = 0
|
||||
if(user)
|
||||
to_chat(user, "<span class='notice'>You short out [src]'s reagent synthesis circuits.</span>")
|
||||
audible_message("<span class='danger'>[src] buzzes oddly!</span>")
|
||||
flick("nutribot_spark", src)
|
||||
playsound(src, "sparks", 75, 1)
|
||||
if(user)
|
||||
oldpatient = user
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/process_scan(mob/living/carbon/human/H)
|
||||
if(H.stat == DEAD)
|
||||
return
|
||||
|
||||
if((H == oldpatient) && (world.time < last_found + 200))
|
||||
return
|
||||
|
||||
if(assess_patient(H))
|
||||
last_found = world.time
|
||||
if((last_newpatient_speak + 300) < world.time) //Don't spam these messages!
|
||||
var/list/messagevoice = list("Hey, [H.name]! Hold on, I'm coming." = 'sound/voice/medbot/coming.ogg',"Wait [H.name]! I want to help!" = 'sound/voice/medbot/help.ogg',"[H.name], you appear to be injured!" = 'sound/voice/medbot/injured.ogg')
|
||||
var/message = pick(messagevoice)
|
||||
if(prob(2) && ISINRANGE_EX(H.getFireLoss(), 0, 20))
|
||||
message = "Notices your minor burns*OwO what's this?"
|
||||
messagevoice[message] = 'sound/voice/medbot/owo.ogg'
|
||||
speak(message)
|
||||
playsound(loc, messagevoice[message], 50, 0)
|
||||
last_newpatient_speak = world.time
|
||||
return H
|
||||
else
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/proc/tip_over(mob/user)
|
||||
canmove = 0
|
||||
//mobility_flags &= ~MOBILITY_MOVE
|
||||
playsound(src, 'sound/machines/warning-buzzer.ogg', 50)
|
||||
user.visible_message("<span class='danger'>[user] tips over [src]!</span>", "<span class='danger'>You tip [src] over!</span>")
|
||||
mode = BOT_TIPPED
|
||||
var/matrix/mat = transform
|
||||
transform = mat.Turn(180)
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/proc/set_right(mob/user)
|
||||
canmove = 1
|
||||
//mobility_flags &= MOBILITY_MOVE
|
||||
var/list/messagevoice
|
||||
if(user)
|
||||
user.visible_message("<span class='notice'>[user] sets [src] right-side up!</span>", "<span class='green'>You set [src] right-side up!</span>")
|
||||
if(user.name == tipper_name)
|
||||
messagevoice = list("I forgive you." = 'sound/voice/medbot/forgive.ogg')
|
||||
else
|
||||
messagevoice = list("Thank you!" = 'sound/voice/medbot/thank_you.ogg', "You are a good person." = 'sound/voice/medbot/youre_good.ogg')
|
||||
else
|
||||
visible_message("<span class='notice'>[src] manages to writhe wiggle enough to right itself.</span>")
|
||||
messagevoice = list("Fuck you." = 'sound/voice/medbot/fuck_you.ogg', "Your behavior has been reported, have a nice day." = 'sound/voice/medbot/reported.ogg')
|
||||
|
||||
tipper_name = null
|
||||
if(world.time > last_tipping_action_voice + 15 SECONDS)
|
||||
last_tipping_action_voice = world.time
|
||||
var/message = pick(messagevoice)
|
||||
speak(message)
|
||||
playsound(src, messagevoice[message], 70)
|
||||
tipped_status = NUTRIBOT_PANIC_NONE
|
||||
mode = BOT_IDLE
|
||||
transform = matrix()
|
||||
|
||||
// if someone tipped us over, check whether we should ask for help or just right ourselves eventually
|
||||
/mob/living/simple_animal/bot/nutribot/proc/handle_panic()
|
||||
tipped_status++
|
||||
var/list/messagevoice
|
||||
switch(tipped_status)
|
||||
if(NUTRIBOT_PANIC_LOW)
|
||||
messagevoice = list("I require assistance." = 'sound/voice/medbot/i_require_asst.ogg')
|
||||
if(NUTRIBOT_PANIC_MED)
|
||||
messagevoice = list("Please put me back." = 'sound/voice/medbot/please_put_me_back.ogg')
|
||||
if(NUTRIBOT_PANIC_HIGH)
|
||||
messagevoice = list("Please, I am scared!" = 'sound/voice/medbot/please_im_scared.ogg')
|
||||
if(NUTRIBOT_PANIC_FUCK)
|
||||
messagevoice = list("I don't like this, I need help!" = 'sound/voice/medbot/dont_like.ogg', "This hurts, my pain is real!" = 'sound/voice/medbot/pain_is_real.ogg')
|
||||
if(NUTRIBOT_PANIC_ENDING)
|
||||
messagevoice = list("Is this the end?" = 'sound/voice/medbot/is_this_the_end.ogg', "Nooo!" = 'sound/voice/medbot/nooo.ogg')
|
||||
if(NUTRIBOT_PANIC_END)
|
||||
speak("PSYCH ALERT: Crewmember [tipper_name] recorded displaying antisocial tendencies torturing bots in [get_area(src)]. Please schedule psych evaluation.", radio_channel)
|
||||
set_right() // strong independent nutribot
|
||||
|
||||
if(prob(tipped_status))
|
||||
do_jitter_animation(tipped_status * 0.1)
|
||||
|
||||
if(messagevoice)
|
||||
var/message = pick(messagevoice)
|
||||
speak(message)
|
||||
playsound(src, messagevoice[message], 70)
|
||||
else if(prob(tipped_status * 0.2))
|
||||
playsound(src, 'sound/machines/warning-buzzer.ogg', 30, extrarange=-2)
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/examine(mob/user)
|
||||
. = ..()
|
||||
if(tipped_status == NUTRIBOT_PANIC_NONE)
|
||||
return
|
||||
|
||||
switch(tipped_status)
|
||||
if(NUTRIBOT_PANIC_NONE to NUTRIBOT_PANIC_LOW)
|
||||
. += "It appears to be tipped over, and is quietly waiting for someone to set it right."
|
||||
if(NUTRIBOT_PANIC_LOW to NUTRIBOT_PANIC_MED)
|
||||
. += "It is tipped over and requesting help."
|
||||
if(NUTRIBOT_PANIC_MED to NUTRIBOT_PANIC_HIGH)
|
||||
. += "They are tipped over and appear visibly distressed." // now we humanize the nutribot as a they, not an it
|
||||
if(NUTRIBOT_PANIC_HIGH to NUTRIBOT_PANIC_FUCK)
|
||||
. += "<span class='warning'>They are tipped over and visibly panicking!</span>"
|
||||
if(NUTRIBOT_PANIC_FUCK to INFINITY)
|
||||
. += "<span class='warning'><b>They are freaking out from being tipped over!</b></span>"
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/handle_automated_action()
|
||||
if(!..())
|
||||
return
|
||||
|
||||
if(mode == BOT_TIPPED)
|
||||
handle_panic()
|
||||
return
|
||||
|
||||
if(mode == BOT_HEALING)
|
||||
return
|
||||
|
||||
if(IsStun())
|
||||
oldpatient = patient
|
||||
patient = null
|
||||
mode = BOT_IDLE
|
||||
return
|
||||
|
||||
if(frustration > 8)
|
||||
oldpatient = patient
|
||||
soft_reset()
|
||||
|
||||
if(QDELETED(patient))
|
||||
if(!shut_up && prob(1))
|
||||
if(emagged && prob(30))
|
||||
var/list/i_need_scissors = list('sound/voice/medbot/fuck_you.ogg', 'sound/voice/medbot/turn_off.ogg', 'sound/voice/medbot/im_different.ogg', 'sound/voice/medbot/close.ogg', 'sound/voice/medbot/shindemashou.ogg')
|
||||
playsound(src, pick(i_need_scissors), 70)
|
||||
else
|
||||
var/list/messagevoice = list("Radar, put a mask on!" = 'sound/voice/medbot/radar.ogg',"There's always a catch, and I'm the best there is." = 'sound/voice/medbot/catch.ogg',"I knew it, I should've been a plastic surgeon." = 'sound/voice/medbot/surgeon.ogg',"What kind of medbay is this? Everyone's dropping like flies." = 'sound/voice/medbot/flies.ogg',"Delicious!" = 'sound/voice/medbot/delicious.ogg', "Why are we still here? Just to suffer?" = 'sound/voice/medbot/why.ogg')
|
||||
var/message = pick(messagevoice)
|
||||
speak(message)
|
||||
playsound(src, messagevoice[message], 50)
|
||||
var/scan_range = (stationary_mode ? 1 : DEFAULT_SCAN_RANGE) //If in stationary mode, scan range is limited to adjacent patients.
|
||||
patient = scan(/mob/living/carbon/human, oldpatient, scan_range)
|
||||
oldpatient = patient
|
||||
|
||||
if(patient && (get_dist(src,patient) <= 1)) //Patient is next to us, begin treatment!
|
||||
if(mode != BOT_HEALING)
|
||||
mode = BOT_HEALING
|
||||
update_icon()
|
||||
frustration = 0
|
||||
medicate_patient(patient)
|
||||
return
|
||||
|
||||
//Patient has moved away from us!
|
||||
else if(patient && path.len && (get_dist(patient,path[path.len]) > 2))
|
||||
path = list()
|
||||
mode = BOT_IDLE
|
||||
last_found = world.time
|
||||
|
||||
else if(stationary_mode && patient) //Since we cannot move in this mode, ignore the patient and wait for another.
|
||||
soft_reset()
|
||||
return
|
||||
|
||||
if(patient && path.len == 0 && (get_dist(src,patient) > 1))
|
||||
path = get_path_to(src, get_turf(patient), /turf/proc/Distance_cardinal, 0, 30,id=access_card)
|
||||
mode = BOT_MOVING
|
||||
if(!path.len) //try to get closer if you can't reach the patient directly
|
||||
path = get_path_to(src, get_turf(patient), /turf/proc/Distance_cardinal, 0, 30,1,id=access_card)
|
||||
if(!path.len) //Do not chase a patient we cannot reach.
|
||||
soft_reset()
|
||||
|
||||
if(path.len > 0 && patient)
|
||||
if(!bot_move(path[path.len]))
|
||||
oldpatient = patient
|
||||
soft_reset()
|
||||
return
|
||||
|
||||
if(path.len > 8 && patient)
|
||||
frustration++
|
||||
|
||||
if(auto_patrol && !stationary_mode && !patient)
|
||||
if(mode == BOT_IDLE || mode == BOT_START_PATROL)
|
||||
start_patrol()
|
||||
|
||||
if(mode == BOT_PATROL)
|
||||
bot_patrol()
|
||||
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/proc/assess_patient(mob/living/carbon/C)
|
||||
//Time to see if they need medical help!
|
||||
if(C.stat == DEAD || (HAS_TRAIT(C, TRAIT_FAKEDEATH)))
|
||||
return FALSE //welp too late for them!
|
||||
|
||||
if(!(loc == C.loc) && !(isturf(C.loc) && isturf(loc)))
|
||||
return FALSE
|
||||
|
||||
if(C.suiciding)
|
||||
return FALSE //Kevorkian school of robotic medical assistants.
|
||||
|
||||
if(emagged == 2) //Everyone needs our medicine. (Our medicine is corn oil)
|
||||
return TRUE
|
||||
|
||||
if(ishuman(C))
|
||||
var/mob/living/carbon/human/H = C
|
||||
if (H.wear_suit && H.head && istype(H.wear_suit, /obj/item/clothing) && istype(H.head, /obj/item/clothing))
|
||||
var/obj/item/clothing/CS = H.wear_suit
|
||||
var/obj/item/clothing/CH = H.head
|
||||
if (CS.clothing_flags & CH.clothing_flags & THICKMATERIAL)
|
||||
return FALSE // Skip over them if they have no exposed flesh.
|
||||
|
||||
//if(declare_crit && C.health <= 0) //Critical condition! Call for help!
|
||||
//declare(C)
|
||||
|
||||
//If they're injured, we're using a beaker, and don't have one of our WONDERCHEMS.
|
||||
if((reagent_glass) && (use_beaker) && (C.fatness <= feed_threshold))
|
||||
for(var/A in reagent_glass.reagents.reagent_list)
|
||||
var/datum/reagent/R = A
|
||||
if(!C.reagents.has_reagent(R.type))
|
||||
return TRUE
|
||||
|
||||
//They're injured enough for it!
|
||||
if((C.nutrition <= hunger_check) && (C.fatness <= feed_threshold) && (!C.reagents.has_reagent(treatment_thin)))
|
||||
return TRUE //If they're already medicated don't bother!
|
||||
|
||||
if((C.thirst <= THIRST_LEVEL_QUENCHED) && (!C.reagents.has_reagent(treatment_thirsty)))
|
||||
return TRUE //If they're already medicated don't bother!
|
||||
|
||||
/*var/treatment_toxavoid = get_avoidchem_toxin(C)
|
||||
if(((isnull(treatment_toxavoid) || !C.reagents.has_reagent(treatment_toxavoid))) && (C.getToxLoss() >= heal_threshold) && (!C.reagents.has_reagent(get_healchem_toxin(C))))
|
||||
return TRUE
|
||||
|
||||
if(treat_virus && !C.reagents.has_reagent(treatment_virus_avoid) && !C.reagents.has_reagent(treatment_virus))
|
||||
for(var/thing in C.diseases)
|
||||
var/datum/disease/D = thing
|
||||
//the Nutribot can't detect viruses that are undetectable to Health Analyzers or Pandemic machines.
|
||||
if(!(D.visibility_flags & HIDDEN_SCANNER || D.visibility_flags & HIDDEN_PANDEMIC) \
|
||||
&& D.severity != DISEASE_SEVERITY_POSITIVE \
|
||||
&& (D.stage > 1 || (D.spread_flags & DISEASE_SPREAD_AIRBORNE))) // Nutribot can't detect a virus in its initial stage unless it spreads airborne.
|
||||
return TRUE //STOP DISEASE FOREVER
|
||||
*/
|
||||
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/attack_hand(mob/living/carbon/human/H)
|
||||
if(H.a_intent == INTENT_DISARM && mode != BOT_TIPPED)
|
||||
H.visible_message("<span class='danger'>[H] begins tipping over [src].</span>", "<span class='warning'>You begin tipping over [src]...</span>")
|
||||
|
||||
if(world.time > last_tipping_action_voice + 15 SECONDS)
|
||||
last_tipping_action_voice = world.time // message for tipping happens when we start interacting, message for righting comes after finishing
|
||||
var/list/messagevoice = list("Hey, wait..." = 'sound/voice/medbot/hey_wait.ogg',"Please don't..." = 'sound/voice/medbot/please_dont.ogg',"I trusted you..." = 'sound/voice/medbot/i_trusted_you.ogg', "Nooo..." = 'sound/voice/medbot/nooo.ogg', "Oh fuck-" = 'sound/voice/medbot/oh_fuck.ogg')
|
||||
var/message = pick(messagevoice)
|
||||
speak(message)
|
||||
playsound(src, messagevoice[message], 70, FALSE)
|
||||
|
||||
if(do_after(H, 3 SECONDS, target=src))
|
||||
tip_over(H)
|
||||
|
||||
else if(H.a_intent == INTENT_HELP && mode == BOT_TIPPED)
|
||||
H.visible_message("<span class='notice'>[H] begins righting [src].</span>", "<span class='notice'>You begin righting [src]...</span>")
|
||||
if(do_after(H, 3 SECONDS, target=src))
|
||||
set_right(H)
|
||||
else
|
||||
..()
|
||||
|
||||
/*
|
||||
/mob/living/simple_animal/bot/nutribot/proc/get_avoidchem_toxin(mob/M)
|
||||
return HAS_TRAIT(M, TRAIT_TOXINLOVER)? null : treatment_tox_avoid
|
||||
*/
|
||||
|
||||
/*
|
||||
/mob/living/simple_animal/bot/nutribot/proc/get_healchem_toxin(mob/M)
|
||||
return HAS_TRAIT(M, TRAIT_TOXINLOVER)? treatment_tox_toxlover : treatment_tox
|
||||
*/
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/UnarmedAttack(atom/A)
|
||||
if(iscarbon(A))
|
||||
var/mob/living/carbon/C = A
|
||||
patient = C
|
||||
mode = BOT_HEALING
|
||||
update_icon()
|
||||
medicate_patient(C)
|
||||
update_icon()
|
||||
else
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/examinate(atom/A as mob|obj|turf in view())
|
||||
..()
|
||||
if(!is_blind(src))
|
||||
chemscan(src, A)
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/proc/medicate_patient(mob/living/carbon/C)
|
||||
if(!on)
|
||||
return
|
||||
|
||||
if(!istype(C))
|
||||
oldpatient = patient
|
||||
soft_reset()
|
||||
return
|
||||
|
||||
if(C.stat == DEAD || (HAS_TRAIT(C, TRAIT_FAKEDEATH)))
|
||||
var/list/messagevoice = list("No! Stay with me!" = 'sound/voice/medbot/no.ogg',"Live, damnit! LIVE!" = 'sound/voice/medbot/live.ogg',"I...I've never lost a patient before. Not today, I mean." = 'sound/voice/medbot/lost.ogg')
|
||||
var/message = pick(messagevoice)
|
||||
speak(message)
|
||||
playsound(loc, messagevoice[message], 50, 0)
|
||||
oldpatient = patient
|
||||
soft_reset()
|
||||
return
|
||||
|
||||
var/reagent_id = null
|
||||
|
||||
if(emagged == 2) //Emagged! Time to poison everybody.
|
||||
reagent_id = "emagged" //evil fucking check for a string as a reagent this shit is evil. its supposed to inject corn oil AND filzulphite but ill handle that later
|
||||
|
||||
else
|
||||
/*if(treat_virus)
|
||||
var/virus = 0
|
||||
for(var/thing in C.diseases)
|
||||
var/datum/disease/D = thing
|
||||
//detectable virus
|
||||
if((!(D.visibility_flags & HIDDEN_SCANNER)) || (!(D.visibility_flags & HIDDEN_PANDEMIC)))
|
||||
if(D.severity != DISEASE_SEVERITY_POSITIVE) //virus is harmful
|
||||
if((D.stage > 1) || (D.spread_flags & DISEASE_SPREAD_AIRBORNE))
|
||||
virus = 1
|
||||
|
||||
if(!reagent_id && (virus))
|
||||
if(!C.reagents.has_reagent(treatment_virus) && !C.reagents.has_reagent(treatment_virus_avoid))
|
||||
reagent_id = treatment_virus*/
|
||||
|
||||
if(!reagent_id && ((feed_threshold == 0) || (C.fatness <= feed_threshold)) && (C.nutrition <= hunger_check))
|
||||
if(!C.reagents.has_reagent(treatment_thin))
|
||||
reagent_id = treatment_thin
|
||||
|
||||
if(!reagent_id && (C.thirst <= THIRST_LEVEL_THIRSTY))
|
||||
if(!C.reagents.has_reagent(treatment_thirsty))
|
||||
reagent_id = treatment_thirsty
|
||||
|
||||
/*if(!reagent_id && (C.getOxyLoss() >= (15 + heal_threshold)))
|
||||
if(!C.reagents.has_reagent(treatment_oxy) && !C.reagents.has_reagent(treatment_oxy_avoid))
|
||||
reagent_id = treatment_oxy
|
||||
|
||||
if(!reagent_id && (C.getFireLoss() >= heal_threshold))
|
||||
if(!C.reagents.has_reagent(treatment_fire) && !C.reagents.has_reagent(treatment_fire_avoid))
|
||||
reagent_id = treatment_fire
|
||||
|
||||
if(!reagent_id && (C.getToxLoss() >= heal_threshold))
|
||||
var/toxin_heal_avoid = get_avoidchem_toxin(C)
|
||||
var/toxin_healchem = get_healchem_toxin(C)
|
||||
if(!C.reagents.has_reagent(toxin_healchem) && (isnull(toxin_heal_avoid) || !C.reagents.has_reagent(toxin_heal_avoid)))
|
||||
reagent_id = toxin_healchem*/
|
||||
|
||||
//If the patient is injured but doesn't have our special reagent in them then we should give it to them first
|
||||
if(reagent_id && use_beaker && reagent_glass && reagent_glass.reagents.total_volume)
|
||||
for(var/A in reagent_glass.reagents.reagent_list)
|
||||
var/datum/reagent/R = A
|
||||
if(!C.reagents.has_reagent(R.type))
|
||||
reagent_id = "internal_beaker"
|
||||
break
|
||||
|
||||
if(!reagent_id) //If they don't need any of that they're probably cured!
|
||||
if(C.maxHealth - C.health < heal_threshold)
|
||||
to_chat(src, "<span class='notice'>[C] is healthy! Your programming prevents you from injecting anyone without at least [heal_threshold] damage of any one type ([heal_threshold + 15] for oxygen damage.)</span>")
|
||||
var/list/messagevoice = list("All patched up!" = 'sound/voice/medbot/patchedup.ogg',"An apple a day keeps me away." = 'sound/voice/medbot/apple.ogg',"Feel better soon!" = 'sound/voice/medbot/feelbetter.ogg')
|
||||
var/message = pick(messagevoice)
|
||||
speak(message)
|
||||
playsound(loc, messagevoice[message], 50, 0)
|
||||
bot_reset()
|
||||
return
|
||||
else
|
||||
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>")
|
||||
|
||||
var/failed = FALSE
|
||||
if(do_mob(src, patient, 30)) //Is C == patient? This is so confusing
|
||||
if((get_dist(src, patient) <= 1) && (on) && assess_patient(patient))
|
||||
if(reagent_id == "internal_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, INJECT, 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
|
||||
failed = TRUE
|
||||
else
|
||||
failed = TRUE
|
||||
|
||||
if(failed)
|
||||
visible_message("[src] retracts its syringe.")
|
||||
update_icon()
|
||||
soft_reset()
|
||||
return
|
||||
|
||||
reagent_id = null
|
||||
return
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/proc/check_overdose(mob/living/carbon/patient,reagent_id,injection_amount)
|
||||
var/datum/reagent/R = GLOB.chemical_reagents_list[reagent_id]
|
||||
if(!R.overdose_threshold) //Some chems do not have an OD threshold
|
||||
return FALSE
|
||||
var/current_volume = patient.reagents.get_reagent_amount(reagent_id)
|
||||
if(current_volume + injection_amount > R.overdose_threshold)
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/explode()
|
||||
on = FALSE
|
||||
visible_message("<span class='boldannounce'>[src] blows apart!</span>")
|
||||
var/atom/Tsec = drop_location()
|
||||
|
||||
drop_part(firstaid, Tsec)
|
||||
new /obj/item/assembly/prox_sensor(Tsec)
|
||||
drop_part(healthanalyzer, Tsec)
|
||||
|
||||
if(reagent_glass)
|
||||
drop_part(reagent_glass, Tsec)
|
||||
|
||||
if(prob(50))
|
||||
drop_part(robot_arm, Tsec)
|
||||
|
||||
if(emagged && prob(25))
|
||||
playsound(loc, 'sound/voice/medbot/insult.ogg', 50, 0)
|
||||
|
||||
do_sparks(3, TRUE, src)
|
||||
..()
|
||||
|
||||
/mob/living/simple_animal/bot/nutribot/proc/declare(crit_patient)
|
||||
if(declare_cooldown > world.time)
|
||||
return
|
||||
var/area/location = get_area(src)
|
||||
speak("Medical emergency! [crit_patient ? "<b>[crit_patient]</b>" : "A patient"] is in critical condition at [location]!",radio_channel)
|
||||
declare_cooldown = world.time + 200
|
||||
|
||||
/obj/machinery/bot_core/nutribot
|
||||
req_one_access = list(ACCESS_MEDICAL, ACCESS_ROBOTICS)
|
||||
|
||||
#undef NUTRIBOT_PANIC_NONE
|
||||
#undef NUTRIBOT_PANIC_LOW
|
||||
#undef NUTRIBOT_PANIC_MED
|
||||
#undef NUTRIBOT_PANIC_HIGH
|
||||
#undef NUTRIBOT_PANIC_FUCK
|
||||
#undef NUTRIBOT_PANIC_ENDING
|
||||
#undef NUTRIBOT_PANIC_END
|
||||
Reference in New Issue
Block a user