")
+ playsound(loc, 'sound/effects/splat.ogg', 50, 1)
+
+ var/damage = rand(5,15)
+ H.apply_damage(2*damage, BRUTE, "head", run_armor_check("head", "melee"))
+ H.apply_damage(2*damage, BRUTE, "chest", run_armor_check("chest", "melee"))
+ H.apply_damage(0.5*damage, BRUTE, "l_leg", run_armor_check("l_leg", "melee"))
+ H.apply_damage(0.5*damage, BRUTE, "r_leg", run_armor_check("r_leg", "melee"))
+ H.apply_damage(0.5*damage, BRUTE, "l_arm", run_armor_check("l_arm", "melee"))
+ H.apply_damage(0.5*damage, BRUTE, "r_arm", run_armor_check("r_arm", "melee"))
+
+ var/obj/effect/decal/cleanable/blood/B = new(loc)
+ B.blood_DNA = list()
+ B.blood_DNA[H.dna.unique_enzymes] = H.dna.b_type
+ currentDNA = B.blood_DNA
+
+ bloodiness += 4
+
+ currentBloodColor = "#A10808"
+ if(istype(H))
+ var/datum/reagent/blood/bld = H.get_blood(H.vessel)
+ if(bld.data["blood_colour"])
+ currentBloodColor = bld.data["blood_colour"]
+ return
+ B.basecolor = currentBloodColor
+ B.update_icon()
+
+/mob/living/simple_animal/bot/mulebot/bot_control_message(command, mob/user, user_turf)
+ switch(command)
+ if("start")
+ if(load)
+ src << "DELIVER [load] TO [destination]"
+ else
+ src << "PICK UP DELIVERY AT [destination]"
+ if("unload")
+ if(load)
+ src << "UNLOAD"
+ else
+ src << "LOAD"
+ if("autoret", "autopick", "target")
+ else
+ ..()
+
+/mob/living/simple_animal/bot/mulebot/receive_signal(datum/signal/signal)
+ if(!wires.RemoteRX() || ..())
+ return 1
+
+ var/recv = signal.data["command"]
+
+ // process control input
+ switch(recv)
+ if("start")
+ start()
+
+ if("target")
+ set_destination(signal.data["destination"])
+
+ if("unload")
+ if(client)
+ return 1
+ if(loc == target)
+ unload(loaddir)
+ else
+ unload(0)
+
+ if("home")
+ start_home()
+
+ if("autoret")
+ auto_return = text2num(signal.data["value"])
+
+ 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(var/freq, var/list/keyval)
+ if(!wires.RemoteTX())
+ 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)
+
+// player on mulebot attempted to move
+/mob/living/simple_animal/bot/mulebot/relaymove(mob/user)
+ if(user.incapacitated())
+ return
+ if(load == user)
+ unload(0)
+
+
+//Update navigation data. Called when commanded to deliver, return home, or a route update is needed...
+/mob/living/simple_animal/bot/mulebot/proc/get_nav()
+ if(!on || !wires.BeaconRX())
+ return
+
+ for(var/obj/machinery/navbeacon/NB in deliverybeacons)
+ if(NB.location == new_destination) // if the beacon location matches the set destination
+ destination = new_destination // the we will navigate there
+ target = NB.loc
+ var/direction = NB.dir // this will be the load/unload dir
+ loaddir = direction
+ update_icon()
+ calc_path()
+ return
+
+/mob/living/simple_animal/bot/mulebot/emp_act(severity)
+ if(cell)
+ cell.emp_act(severity)
+ if(load)
+ load.emp_act(severity)
+ ..()
+
+
+/mob/living/simple_animal/bot/mulebot/explode()
+ visible_message("[src] blows apart!")
+ var/turf/Tsec = get_turf(src)
+
+ new /obj/item/device/assembly/prox_sensor(Tsec)
+ new /obj/item/stack/rods(Tsec)
+ new /obj/item/stack/rods(Tsec)
+ new /obj/item/stack/cable_coil/cut(Tsec)
+ if(cell)
+ cell.forceMove(Tsec)
+ cell.update_icon()
+ cell = null
+
+ var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread
+ s.set_up(3, 1, src)
+ s.start()
+
+ new /obj/effect/decal/cleanable/blood/oil(loc)
+ ..()
+
+/mob/living/simple_animal/bot/mulebot/remove_air(amount) //To prevent riders suffocating
+ if(loc)
+ return loc.remove_air(amount)
+ else
+ return null
+
+/mob/living/simple_animal/bot/mulebot/resist()
+ ..()
+ if(load)
+ unload()
+
+/mob/living/simple_animal/bot/mulebot/UnarmedAttack(atom/A)
+ if(isturf(A) && isturf(loc) && loc.Adjacent(A) && load)
+ unload(get_dir(loc, A))
+ else
+ ..()
+
+#undef SIGH
+#undef ANNOYED
+#undef DELIGHT
+
+/obj/machinery/bot_core/mulebot
+ req_access = list(access_cargo)
diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm
new file mode 100644
index 00000000000..f60ad0ebb48
--- /dev/null
+++ b/code/modules/mob/living/simple_animal/bot/secbot.dm
@@ -0,0 +1,465 @@
+/mob/living/simple_animal/bot/secbot
+ name = "\improper Securitron"
+ desc = "A little security robot. He looks less than thrilled."
+ icon = 'icons/obj/aibots.dmi'
+ icon_state = "secbot0"
+ density = 0
+ anchored = 0
+ health = 25
+ maxHealth = 25
+ damage_coeff = list(BRUTE = 0.5, BURN = 0.7, TOX = 0, CLONE = 0, STAMINA = 0, OXY = 0)
+ pass_flags = PASSMOB
+
+ radio_channel = "Security" //Security channel
+ bot_type = SEC_BOT
+ 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
+ window_id = "autosec"
+ window_name = "Automatic Security Unit v1.6"
+
+ var/base_icon = "secbot"
+ var/mob/living/carbon/target
+ var/oldtarget_name
+ var/threatlevel = 0
+ var/target_lastloc //Loc of target when arrested.
+ var/last_found //There's a delay
+ var/declare_arrests = 1 //When making an arrest, should it notify everyone on the security channel?
+ var/idcheck = 0 //If true, arrest people with no IDs
+ var/weaponscheck = 0 //If true, arrest people for weapons if they lack access
+ var/check_records = 1 //Does it check security records?
+ var/arrest_type = 0 //If true, don't handcuff
+ var/harmbaton = 0 //If true, beat instead of stun
+ var/flashing_lights = 0 //If true, flash lights
+ var/prev_flashing_lights = 0
+
+/mob/living/simple_animal/bot/secbot/beepsky
+ name = "Officer Beepsky"
+ desc = "It's Officer Beepsky! Powered by a potato and a shot of whiskey."
+ idcheck = 0
+ weaponscheck = 0
+ auto_patrol = 1
+ allow_pai = 0
+
+/mob/living/simple_animal/bot/secbot/beepsky/explode()
+ var/turf/Tsec = get_turf(src)
+ new /obj/item/weapon/stock_parts/cell/potato(Tsec)
+ var/obj/item/weapon/reagent_containers/food/drinks/drinkingglass/S = new(Tsec)
+ S.reagents.add_reagent("whiskey", 15)
+ S.on_reagent_change()
+ ..()
+
+/mob/living/simple_animal/bot/secbot/pingsky
+ name = "Officer Pingsky"
+ desc = "It's Officer Pingsky! Delegated to satellite guard duty for harbouring anti-human sentiment."
+ radio_channel = "AI Private"
+ allow_pai = 0
+
+/mob/living/simple_animal/bot/secbot/ofitser
+ name = "Prison Ofitser"
+ desc = "It's Prison Ofitser! Powered by the tears and sweat of prisoners."
+ idcheck = 0
+ weaponscheck = 1
+ auto_patrol = 1
+ allow_pai = 0
+
+/mob/living/simple_animal/bot/secbot/buzzsky
+ name = "Officer Buzzsky"
+ desc = "It's Officer Buzzsky! Rusted and falling apart, he seems less than thrilled with the crew for leaving him in his current state."
+ base_icon = "rustbot"
+ icon_state = "rustbot0"
+ declare_arrests = 0
+ arrest_type = 1
+ harmbaton = 1
+ emagged = 2
+
+/mob/living/simple_animal/bot/secbot/New()
+ ..()
+ icon_state = "[base_icon][on]"
+ spawn(3)
+ var/datum/job/detective/J = new/datum/job/detective
+ access_card.access += J.get_access()
+ prev_access = access_card.access
+
+ //SECHUD
+ var/datum/atom_hud/secsensor = huds[DATA_HUD_SECURITY_ADVANCED]
+ secsensor.add_hud_to(src)
+ permanent_huds |= secsensor
+
+/mob/living/simple_animal/bot/secbot/turn_on()
+ ..()
+ icon_state = "[base_icon][on]"
+
+/mob/living/simple_animal/bot/secbot/turn_off()
+ ..()
+ icon_state = "[base_icon][on]"
+
+/mob/living/simple_animal/bot/secbot/bot_reset()
+ ..()
+ target = null
+ oldtarget_name = null
+ anchored = 0
+ walk_to(src,0)
+ last_found = world.time
+
+/mob/living/simple_animal/bot/secbot/set_custom_texts()
+
+ text_hack = "You overload [name]'s target identification system."
+ text_dehack = "You reboot [name] and restore the target identification."
+ text_dehack_fail = "[name] refuses to accept your authority!"
+
+/mob/living/simple_animal/bot/secbot/get_controls(mob/user)
+ var/dat
+ dat += hack(user)
+ dat += showpai(user)
+ dat += text({"
+Securitron v1.6 controls
+Status: []
+Behaviour controls are [locked ? "locked" : "unlocked"]
+Maintenance panel panel is [open ? "opened" : "closed"]"},
+
+"[on ? "On" : "Off"]" )
+
+ if(!locked || issilicon(user) || check_rights(R_ADMIN, 0, user))
+ dat += text({"
+Arrest Unidentifiable Persons: []
+Arrest for Unauthorized Weapons: []
+Arrest for Warrant: []
+Operating Mode: []
+Report Arrests[]
+Auto Patrol: []"},
+
+"[idcheck ? "Yes" : "No"]",
+"[weaponscheck ? "Yes" : "No"]",
+"[check_records ? "Yes" : "No"]",
+"[arrest_type ? "Detain" : "Arrest"]",
+"[declare_arrests ? "Yes" : "No"]",
+"[auto_patrol ? "On" : "Off"]" )
+
+ return dat
+
+/mob/living/simple_animal/bot/secbot/Topic(href, href_list)
+ if(..())
+ return 1
+
+ switch(href_list["operation"])
+ if("idcheck")
+ idcheck = !idcheck
+ update_controls()
+ if("weaponscheck")
+ weaponscheck = !weaponscheck
+ update_controls()
+ if("ignorerec")
+ check_records = !check_records
+ update_controls()
+ if("switchmode")
+ arrest_type = !arrest_type
+ update_controls()
+ if("declarearrests")
+ declare_arrests = !declare_arrests
+ update_controls()
+
+/mob/living/simple_animal/bot/secbot/proc/retaliate(mob/living/carbon/human/H)
+ threatlevel = H.assess_threat(src)
+ threatlevel += 6
+ if(threatlevel >= 4)
+ target = H
+ mode = BOT_HUNT
+
+/mob/living/simple_animal/bot/secbot/attack_hand(mob/living/carbon/human/H)
+ if(H.a_intent == "harm")
+ retaliate(H)
+ return ..()
+
+/mob/living/simple_animal/bot/secbot/attackby(obj/item/weapon/W, mob/user, params)
+ ..()
+ if(istype(W, /obj/item/weapon/weldingtool) && user.a_intent != "harm") // Any intent but harm will heal, so we shouldn't get angry.
+ return
+ if(!istype(W, /obj/item/weapon/screwdriver) && (W.force) && (!target) && (W.damtype != STAMINA) ) // Added check for welding tool to fix #2432. Welding tool behavior is handled in superclass.
+ retaliate(user)
+
+/mob/living/simple_animal/bot/secbot/emag_act(mob/user)
+ ..()
+ if(emagged == 2)
+ if(user)
+ user << "You short out [src]'s target assessment circuits."
+ oldtarget_name = user.name
+ audible_message("[src] buzzes oddly!")
+ declare_arrests = 0
+ icon_state = "[base_icon][on]"
+
+/mob/living/simple_animal/bot/secbot/bullet_act(obj/item/projectile/Proj)
+ if(istype(Proj ,/obj/item/projectile/beam)||istype(Proj,/obj/item/projectile/bullet))
+ if((Proj.damage_type == BURN) || (Proj.damage_type == BRUTE))
+ if(!Proj.nodamage && Proj.damage < src.health)
+ retaliate(Proj.firer)
+ ..()
+
+
+/mob/living/simple_animal/bot/secbot/UnarmedAttack(atom/A)
+ if(!on)
+ return
+ if(iscarbon(A))
+ var/mob/living/carbon/C = A
+ if(!C.stunned || arrest_type)
+ stun_attack(A)
+ else if(C.canBeHandcuffed() && !C.handcuffed)
+ cuff(A)
+ else
+ ..()
+
+
+/mob/living/simple_animal/bot/secbot/hitby(atom/movable/AM, skipcatch = 0, hitpush = 1, blocked = 0)
+ if(istype(AM, /obj/item))
+ var/obj/item/I = AM
+ if(I.throwforce < src.health && I.thrower && (istype(I.thrower, /mob/living/carbon/human)))
+ var/mob/living/carbon/human/H = I.thrower
+ retaliate(H)
+ ..()
+
+
+/mob/living/simple_animal/bot/secbot/proc/cuff(mob/living/carbon/C)
+ mode = BOT_ARREST
+ playsound(loc, 'sound/weapons/cablecuff.ogg', 30, 1, -2)
+ C.visible_message("[src] is trying to put zipties on [C]!",\
+ "[src] is trying to put zipties on you!")
+ 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/weapon/restraints/handcuffs/cable/zipties/used(C)
+ C.update_inv_handcuffed(1)
+ playsound(loc, pick('sound/voice/bgod.ogg', 'sound/voice/biamthelaw.ogg', 'sound/voice/bsecureday.ogg', 'sound/voice/bradio.ogg', 'sound/voice/binsult.ogg', 'sound/voice/bcreep.ogg'), 50, 0)
+ back_to_idle()
+
+/mob/living/simple_animal/bot/secbot/proc/stun_attack(mob/living/carbon/C)
+ playsound(loc, 'sound/weapons/Egloves.ogg', 50, 1, -1)
+ if(harmbaton)
+ playsound(loc, 'sound/weapons/genhit1.ogg', 50, 1, -1)
+ icon_state = "[base_icon]-c"
+ spawn(2)
+ icon_state = "[base_icon][on]"
+ var/threat = 5
+ if(istype(C, /mob/living/carbon/human))
+ C.stuttering = 5
+ if(harmbaton) // Bots with harmbaton enabled become shitcurity. - Dave
+ C.apply_damage(10, BRUTE)
+ C.Stun(5)
+ C.Weaken(5)
+ var/mob/living/carbon/human/H = C
+ threat = H.assess_threat(src)
+ else
+ C.Weaken(5)
+ C.stuttering = 5
+ C.Stun(5)
+ add_logs(src,C,"stunned")
+ if(declare_arrests)
+ var/area/location = get_area(src)
+ speak("[arrest_type ? "Detaining" : "Arresting"] level [threat] scumbag [C] in [location].", radio_channel)
+ C.visible_message("[src] has [harmbaton ? "beaten" : "stunned"] [C]!",\
+ "[src] has [harmbaton ? "beaten" : "stunned"] you!")
+
+/mob/living/simple_animal/bot/secbot/Life()
+ . = ..()
+ if(flashing_lights)
+ switch(light_color)
+ if(LIGHT_COLOR_PURE_RED)
+ light_color = LIGHT_COLOR_PURE_BLUE
+ if(LIGHT_COLOR_PURE_BLUE)
+ light_color = LIGHT_COLOR_PURE_RED
+ update_light()
+ else if(prev_flashing_lights)
+ light_color = LIGHT_COLOR_PURE_RED
+ update_light()
+
+ prev_flashing_lights = flashing_lights
+
+/mob/living/simple_animal/bot/secbot/verb/toggle_flashing_lights()
+ set name = "Toggle Flashing Lights"
+ set category = "Object"
+ set src = usr
+
+ flashing_lights = !flashing_lights
+
+/mob/living/simple_animal/bot/secbot/handle_automated_action()
+ if(!..())
+ return
+
+ flashing_lights = mode == BOT_HUNT
+
+ switch(mode)
+ if(BOT_IDLE) // idle
+ walk_to(src,0)
+ look_for_perp() // see if any criminals are in range
+ if(!mode && auto_patrol) // still idle, and set to patrol
+ mode = BOT_START_PATROL // switch to patrol mode
+
+ if(BOT_HUNT) // hunting for perp
+ // if can't reach perp for long enough, go idle
+ if(frustration >= 8)
+ walk_to(src,0)
+ back_to_idle()
+ return
+
+ if(target) // make sure target exists
+ if(Adjacent(target) && isturf(target.loc)) // if right next to perp
+ stun_attack(target)
+
+ mode = BOT_PREP_ARREST
+ anchored = 1
+ target_lastloc = target.loc
+ return
+
+ else // not next to perp
+ var/turf/olddist = get_dist(src, target)
+ walk_to(src, target,1,4)
+ if((get_dist(src, target)) >= (olddist))
+ frustration++
+ else
+ frustration = 0
+ else
+ back_to_idle()
+
+ if(BOT_PREP_ARREST) // preparing to arrest target
+ // see if he got away. If he's no no longer adjacent or inside a closet or about to get up, we hunt again.
+ if( !Adjacent(target) || !isturf(target.loc) || target.weakened < 2 )
+ back_to_hunt()
+ return
+
+ if(iscarbon(target) && target.canBeHandcuffed())
+ if(!arrest_type)
+ if(!target.handcuffed) //he's not cuffed? Try to cuff him!
+ cuff(target)
+ else
+ back_to_idle()
+ return
+ else
+ back_to_idle()
+ return
+
+ if(BOT_ARREST)
+ if(!target)
+ anchored = 0
+ mode = BOT_IDLE
+ last_found = world.time
+ frustration = 0
+ return
+
+ if(target.handcuffed) //no target or target cuffed? back to idle.
+ back_to_idle()
+ return
+
+ if(!Adjacent(target) || !isturf(target.loc) || (target.loc != target_lastloc && target.weakened < 2)) //if he's changed loc and about to get up or not adjacent or got into a closet, we prep arrest again.
+ back_to_hunt()
+ return
+ else //Try arresting again if the target escapes.
+ mode = BOT_PREP_ARREST
+ anchored = 0
+
+ if(BOT_START_PATROL)
+ look_for_perp()
+ start_patrol()
+
+ if(BOT_PATROL)
+ look_for_perp()
+ bot_patrol()
+
+
+ return
+
+/mob/living/simple_animal/bot/secbot/proc/back_to_idle()
+ anchored = 0
+ mode = BOT_IDLE
+ target = null
+ last_found = world.time
+ frustration = 0
+ spawn(0)
+ handle_automated_action() //ensure bot quickly responds
+
+/mob/living/simple_animal/bot/secbot/proc/back_to_hunt()
+ anchored = 0
+ frustration = 0
+ mode = BOT_HUNT
+ spawn(0)
+ handle_automated_action() //ensure bot quickly responds
+// look for a criminal in view of the bot
+
+/mob/living/simple_animal/bot/secbot/proc/look_for_perp()
+ anchored = 0
+ for (var/mob/living/carbon/C in view(7,src)) //Let's find us a criminal
+ if((C.stat) || (C.handcuffed))
+ continue
+
+ if((C.name == oldtarget_name) && (world.time < last_found + 100))
+ continue
+
+ threatlevel = C.assess_threat(src)
+
+ if(!threatlevel)
+ continue
+
+ else if(threatlevel >= 4)
+ target = C
+ oldtarget_name = C.name
+ speak("Level [threatlevel] infraction alert!")
+ playsound(loc, pick('sound/voice/bcriminal.ogg', 'sound/voice/bjustice.ogg', 'sound/voice/bfreeze.ogg'), 50, 0)
+ visible_message("[src] points at [C.name]!")
+ mode = BOT_HUNT
+ spawn(0)
+ handle_automated_action() // ensure bot quickly responds to a perp
+ break
+ else
+ continue
+/mob/living/simple_animal/bot/secbot/proc/check_for_weapons(var/obj/item/slot_item)
+ if(slot_item && slot_item.needs_permit)
+ return 1
+ return 0
+
+/mob/living/simple_animal/bot/secbot/explode()
+
+ walk_to(src,0)
+ visible_message("[src] blows apart!")
+ var/turf/Tsec = get_turf(src)
+
+ var/obj/item/weapon/secbot_assembly/Sa = new /obj/item/weapon/secbot_assembly(Tsec)
+ Sa.build_step = 1
+ Sa.overlays += "hs_hole"
+ Sa.created_name = name
+ new /obj/item/device/assembly/prox_sensor(Tsec)
+ new /obj/item/weapon/melee/baton(Tsec)
+
+ if(prob(50))
+ new /obj/item/robot_parts/l_arm(Tsec)
+
+ var/datum/effect/system/spark_spread/s = new /datum/effect/system/spark_spread
+ s.set_up(3, 1, src)
+ s.start()
+
+ new /obj/effect/decal/cleanable/blood/oil(loc)
+ ..()
+
+/mob/living/simple_animal/bot/secbot/attack_alien(var/mob/living/carbon/alien/user as mob)
+ ..()
+ if(!isalien(target))
+ target = user
+ mode = BOT_HUNT
+
+/mob/living/simple_animal/bot/secbot/Crossed(atom/movable/AM)
+ if(ismob(AM) && target)
+ var/mob/living/carbon/C = AM
+ if(!istype(C) || !C || in_range(src, target))
+ return
+ C.visible_message("[pick( \
+ "[C] dives out of [src]'s way!", \
+ "[C] stumbles over [src]!", \
+ "[C] jumps out of [src]'s path!", \
+ "[C] trips over [src] and falls!", \
+ "[C] topples over [src]!", \
+ "[C] leaps out of [src]'s way!")]")
+ C.Weaken(2)
+ return
+ ..()
+
+/obj/machinery/bot_core/secbot
+ req_access = list(access_security)
diff --git a/code/modules/mob/living/simple_animal/constructs.dm b/code/modules/mob/living/simple_animal/constructs.dm
index da3283355f3..989bbf09508 100644
--- a/code/modules/mob/living/simple_animal/constructs.dm
+++ b/code/modules/mob/living/simple_animal/constructs.dm
@@ -14,14 +14,7 @@
stop_automated_movement = 1
status_flags = CANPUSH
attack_sound = 'sound/weapons/punch1.ogg'
- min_oxy = 0
- max_oxy = 0
- min_tox = 0
- max_tox = 0
- min_co2 = 0
- max_co2 = 0
- min_n2 = 0
- max_n2 = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
faction = list("cult")
flying = 1
@@ -110,7 +103,7 @@
/mob/living/simple_animal/construct/armoured/Life()
weakened = 0
- ..()
+ return ..()
/mob/living/simple_animal/construct/armoured/bullet_act(var/obj/item/projectile/P)
if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam))
diff --git a/code/modules/mob/living/simple_animal/friendly/corgi.dm b/code/modules/mob/living/simple_animal/friendly/corgi.dm
index 6d09809fe2c..f51e3e81f65 100644
--- a/code/modules/mob/living/simple_animal/friendly/corgi.dm
+++ b/code/modules/mob/living/simple_animal/friendly/corgi.dm
@@ -398,11 +398,11 @@
response_disarm = "bops"
response_harm = "kicks"
-/mob/living/simple_animal/pet/corgi/Ian/Life()
+/mob/living/simple_animal/pet/corgi/Ian/process_ai()
..()
//Feeding, chasing food, FOOOOODDDD
- if(!stat && !resting && !buckled && (ckey == null))
+ if(!resting && !buckled)
turns_since_scan++
if(turns_since_scan > 5)
turns_since_scan = 0
@@ -449,10 +449,9 @@
if(prob(1))
custom_emote(1, pick("dances around.","chases its tail!"))
spawn(0)
- if (ckey == null)
- for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2))
- dir = i
- sleep(1)
+ for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2))
+ dir = i
+ sleep(1)
/obj/item/weapon/reagent_containers/food/snacks/meat/corgi
name = "Corgi meat"
@@ -562,20 +561,18 @@
return
..()
-/mob/living/simple_animal/pet/corgi/Lisa/Life()
+/mob/living/simple_animal/pet/corgi/Lisa/process_ai()
..()
make_babies()
- if(!stat && !resting && !buckled)
+ if(!resting && !buckled)
if(prob(1))
- if (ckey == null)
- custom_emote(1, pick("dances around.","chases her tail."))
- spawn(0)
- for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2))
- dir = i
- sleep(1)
-
+ custom_emote(1, pick("dances around.","chases her tail."))
+ spawn(0)
+ for(var/i in list(1,2,4,8,4,2,1,2,4,8,4,2,1,2,4,8,4,2))
+ dir = i
+ sleep(1)
/mob/living/simple_animal/pet/corgi/attack_hand(mob/living/carbon/human/M)
. = ..()
diff --git a/code/modules/mob/living/simple_animal/friendly/mouse.dm b/code/modules/mob/living/simple_animal/friendly/mouse.dm
index b5065fb3f19..c24da570653 100644
--- a/code/modules/mob/living/simple_animal/friendly/mouse.dm
+++ b/code/modules/mob/living/simple_animal/friendly/mouse.dm
@@ -24,7 +24,7 @@
pass_flags = PASSTABLE | PASSGRILLE | PASSMOB
var/mouse_color //brown, gray and white, leave blank for random
layer = MOB_LAYER
- min_oxy = 16 //Require atleast 16kPA oxygen
+ atmos_requirements = list("min_oxy" = 16, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 223 //Below -50 Degrees Celcius
maxbodytemp = 323 //Above 50 Degrees Celcius
universal_speak = 0
@@ -40,14 +40,7 @@
/mob/living/simple_animal/mouse/Life()
. = ..()
-
- if(!ckey && stat == CONSCIOUS && prob(0.5))
- stat = UNCONSCIOUS
- icon_state = "mouse_[mouse_color]_sleep"
- wander = 0
- speak_chance = 0
- //snuffles
- else if(stat == UNCONSCIOUS)
+ if(stat == UNCONSCIOUS)
if(ckey || prob(1))
stat = CONSCIOUS
icon_state = "mouse_[mouse_color]"
@@ -55,6 +48,15 @@
else if(prob(5))
emote("snuffles")
+/mob/living/simple_animal/mouse/process_ai()
+ ..()
+
+ if(prob(0.5))
+ stat = UNCONSCIOUS
+ icon_state = "mouse_[mouse_color]_sleep"
+ wander = 0
+ speak_chance = 0
+
/mob/living/simple_animal/mouse/New()
..()
if(!mouse_color)
diff --git a/code/modules/mob/living/simple_animal/friendly/pug.dm b/code/modules/mob/living/simple_animal/friendly/pug.dm
index 03dd45d5036..b4b6486b859 100644
--- a/code/modules/mob/living/simple_animal/friendly/pug.dm
+++ b/code/modules/mob/living/simple_animal/friendly/pug.dm
@@ -18,10 +18,10 @@
response_harm = "kicks"
see_in_dark = 5
-/mob/living/simple_animal/pet/pug/Life()
+/mob/living/simple_animal/pet/pug/process_ai()
..()
- if(!stat && !resting && !buckled)
+ if(!resting && !buckled)
if(prob(1))
custom_emote(1, pick("chases its tail."))
spawn(0)
diff --git a/code/modules/mob/living/simple_animal/friendly/spiderbot.dm b/code/modules/mob/living/simple_animal/friendly/spiderbot.dm
index 35f06c2b1c2..491f56f74a7 100644
--- a/code/modules/mob/living/simple_animal/friendly/spiderbot.dm
+++ b/code/modules/mob/living/simple_animal/friendly/spiderbot.dm
@@ -1,8 +1,6 @@
/mob/living/simple_animal/spiderbot
- min_oxy = 0
- max_tox = 0
- max_co2 = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
maxbodytemp = 500
diff --git a/code/modules/mob/living/simple_animal/hostile/alien.dm b/code/modules/mob/living/simple_animal/hostile/alien.dm
index b60027f3624..47cfdd23984 100644
--- a/code/modules/mob/living/simple_animal/hostile/alien.dm
+++ b/code/modules/mob/living/simple_animal/hostile/alien.dm
@@ -20,14 +20,7 @@
speak_emote = list("hisses")
a_intent = I_HARM
attack_sound = 'sound/weapons/bladeslice.ogg'
- min_oxy = 0
- max_oxy = 0
- min_tox = 0
- max_tox = 0
- min_co2 = 0
- max_co2 = 0
- min_n2 = 0
- max_n2 = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
var/dead = 0
unsuitable_atmos_damage = 15
faction = list("alien")
@@ -49,14 +42,16 @@
var/plant_cooldown = 30
var/plants_off = 0
-/mob/living/simple_animal/hostile/alien/drone/Life()
- ..()
- if(!stat)
- plant_cooldown--
- if(stance==HOSTILE_STANCE_IDLE)
- if(!plants_off && prob(10) && plant_cooldown<=0)
- plant_cooldown = initial(plant_cooldown)
- SpreadPlants()
+/mob/living/simple_animal/hostile/alien/drone/process_ai()
+ . = ..()
+ if(!.)
+ return
+
+ plant_cooldown--
+ if(stance==HOSTILE_STANCE_IDLE)
+ if(!plants_off && prob(10) && plant_cooldown<=0)
+ plant_cooldown = initial(plant_cooldown)
+ SpreadPlants()
/mob/living/simple_animal/hostile/alien/sentinel
name = "alien sentinel"
@@ -94,18 +89,18 @@
var/egg_cooldown = 30
var/plant_cooldown = 30
-/mob/living/simple_animal/hostile/alien/queen/Life()
+/mob/living/simple_animal/hostile/alien/queen/process_ai()
..()
- if(!stat)
- egg_cooldown--
- plant_cooldown--
- if(stance==HOSTILE_STANCE_IDLE)
- if(!plants_off && prob(10) && plant_cooldown<=0)
- plant_cooldown = initial(plant_cooldown)
- SpreadPlants()
- if(!sterile && prob(10) && egg_cooldown<=0)
- egg_cooldown = initial(egg_cooldown)
- LayEggs()
+
+ egg_cooldown--
+ plant_cooldown--
+ if(stance==HOSTILE_STANCE_IDLE)
+ if(!plants_off && prob(10) && plant_cooldown<=0)
+ plant_cooldown = initial(plant_cooldown)
+ SpreadPlants()
+ if(!sterile && prob(10) && egg_cooldown<=0)
+ egg_cooldown = initial(egg_cooldown)
+ LayEggs()
/mob/living/simple_animal/hostile/alien/proc/SpreadPlants()
if(!isturf(loc) || istype(loc, /turf/space))
diff --git a/code/modules/mob/living/simple_animal/hostile/bat.dm b/code/modules/mob/living/simple_animal/hostile/bat.dm
index 0d0a46e3053..70c117860af 100644
--- a/code/modules/mob/living/simple_animal/hostile/bat.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bat.dm
@@ -22,15 +22,7 @@
attacktext = "bites"
attack_sound = 'sound/weapons/bite.ogg'
- //Space carp aren't affected by atmos.
- min_oxy = 0
- max_oxy = 0
- min_tox = 0
- max_tox = 0
- min_co2 = 0
- max_co2 = 0
- min_n2 = 0
- max_n2 = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
// break_stuff_probability = 2
diff --git a/code/modules/mob/living/simple_animal/hostile/bear.dm b/code/modules/mob/living/simple_animal/hostile/bear.dm
index dc764c317da..0171e960ed0 100644
--- a/code/modules/mob/living/simple_animal/hostile/bear.dm
+++ b/code/modules/mob/living/simple_animal/hostile/bear.dm
@@ -26,14 +26,7 @@
attack_sound = 'sound/weapons/genhit3.ogg'
//Space bears aren't affected by atmos.
- min_oxy = 0
- max_oxy = 0
- min_tox = 0
- max_tox = 0
- min_co2 = 0
- max_co2 = 0
- min_n2 = 0
- max_n2 = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
var/stance_step = 0
@@ -55,12 +48,11 @@
else
icon_state = "bearfloor"
-/mob/living/simple_animal/hostile/bear/Life()
+/mob/living/simple_animal/hostile/bear/process_ai()
. = ..()
if(!.)
return
-
switch(stance)
if(HOSTILE_STANCE_TIRED)
diff --git a/code/modules/mob/living/simple_animal/hostile/carp.dm b/code/modules/mob/living/simple_animal/hostile/carp.dm
index 9c3020e4839..2b13fadec8d 100644
--- a/code/modules/mob/living/simple_animal/hostile/carp.dm
+++ b/code/modules/mob/living/simple_animal/hostile/carp.dm
@@ -25,14 +25,7 @@
speak_emote = list("gnashes")
//Space carp aren't affected by atmos.
- min_oxy = 0
- max_oxy = 0
- min_tox = 0
- max_tox = 0
- min_co2 = 0
- max_co2 = 0
- min_n2 = 0
- max_n2 = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
maxbodytemp = 1500
diff --git a/code/modules/mob/living/simple_animal/hostile/faithless.dm b/code/modules/mob/living/simple_animal/hostile/faithless.dm
index bbcacd234fe..380b332a7e4 100644
--- a/code/modules/mob/living/simple_animal/hostile/faithless.dm
+++ b/code/modules/mob/living/simple_animal/hostile/faithless.dm
@@ -20,14 +20,7 @@
attack_sound = 'sound/hallucinations/growl1.ogg'
speak_emote = list("growls")
- min_oxy = 0
- max_oxy = 0
- min_tox = 0
- max_tox = 0
- min_co2 = 0
- max_co2 = 0
- min_n2 = 0
- max_n2 = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
speed = 4
diff --git a/code/modules/mob/living/simple_animal/hostile/hivebot.dm b/code/modules/mob/living/simple_animal/hostile/hivebot.dm
index 68aeeb72616..44f5caa1609 100644
--- a/code/modules/mob/living/simple_animal/hostile/hivebot.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hivebot.dm
@@ -18,14 +18,7 @@
projectilesound = 'sound/weapons/Gunshot.ogg'
projectiletype = /obj/item/projectile/hivebotbullet
faction = list("hivebot")
- min_oxy = 0
- max_oxy = 0
- min_tox = 0
- max_tox = 0
- min_co2 = 0
- max_co2 = 0
- min_n2 = 0
- max_n2 = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
speak_emote = list("states")
@@ -79,37 +72,36 @@
warpbots()
- New()
- ..()
- var/datum/effect/system/harmless_smoke_spread/smoke = new /datum/effect/system/harmless_smoke_spread()
- smoke.set_up(5, 0, src.loc)
- smoke.start()
- visible_message("\red The [src] warps in!")
- playsound(src.loc, 'sound/effects/EMPulse.ogg', 25, 1)
+/mob/living/simple_animal/hostile/hivebot/tele/New()
+ ..()
+ var/datum/effect/system/harmless_smoke_spread/smoke = new /datum/effect/system/harmless_smoke_spread()
+ smoke.set_up(5, 0, src.loc)
+ smoke.start()
+ visible_message("\red The [src] warps in!")
+ playsound(src.loc, 'sound/effects/EMPulse.ogg', 25, 1)
- warpbots()
- icon_state = "def_radar"
- visible_message("\red The [src] turns on!")
- while(bot_amt > 0)
- bot_amt--
- switch(bot_type)
- if("norm")
- var/mob/living/simple_animal/hostile/hivebot/H = new /mob/living/simple_animal/hostile/hivebot(get_turf(src))
- H.faction = faction
- if("range")
- var/mob/living/simple_animal/hostile/hivebot/range/R = new /mob/living/simple_animal/hostile/hivebot/range(get_turf(src))
- R.faction = faction
- if("rapid")
- var/mob/living/simple_animal/hostile/hivebot/rapid/F = new /mob/living/simple_animal/hostile/hivebot/rapid(get_turf(src))
- F.faction = faction
- spawn(100)
- qdel(src)
+/mob/living/simple_animal/hostile/hivebot/tele/warpbots()
+ icon_state = "def_radar"
+ visible_message("\red The [src] turns on!")
+ while(bot_amt > 0)
+ bot_amt--
+ switch(bot_type)
+ if("norm")
+ var/mob/living/simple_animal/hostile/hivebot/H = new /mob/living/simple_animal/hostile/hivebot(get_turf(src))
+ H.faction = faction
+ if("range")
+ var/mob/living/simple_animal/hostile/hivebot/range/R = new /mob/living/simple_animal/hostile/hivebot/range(get_turf(src))
+ R.faction = faction
+ if("rapid")
+ var/mob/living/simple_animal/hostile/hivebot/rapid/F = new /mob/living/simple_animal/hostile/hivebot/rapid(get_turf(src))
+ F.faction = faction
+ spawn(100)
+ qdel(src)
+ return
+
+/mob/living/simple_animal/hostile/hivebot/tele/process_ai()
+ . = ..()
+ if(!.)
return
-
-
- Life()
- ..()
- if(stat == 0)
- if(prob(2))//Might be a bit low, will mess with it likely
- warpbots()
-
+ if(prob(2))//Might be a bit low, will mess with it likely
+ warpbots()
\ No newline at end of file
diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm
index c5561a2f928..00ca1d65e82 100644
--- a/code/modules/mob/living/simple_animal/hostile/hostile.dm
+++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm
@@ -32,33 +32,34 @@
var/AIStatus = AI_ON //The Status of our AI, can be set to AI_ON (On, usual processing), AI_SLEEP (Will not process, but will return to AI_ON if an enemy comes near), AI_OFF (Off, Not processing ever)
/mob/living/simple_animal/hostile/Life()
-
. = ..()
if(!.)
walk(src, 0)
return 0
if(ranged)
ranged_cooldown--
- if(client)
- return 0
+
+/mob/living/simple_animal/hostile/process_ai()
+ ..()
if(!AICanContinue())
return 0
- if(!stat)
- switch(stance)
- if(HOSTILE_STANCE_IDLE)
- var/new_target = FindTarget()
- GiveTarget(new_target)
+ switch(stance)
+ if(HOSTILE_STANCE_IDLE)
+ var/new_target = FindTarget()
+ GiveTarget(new_target)
- if(HOSTILE_STANCE_ATTACK)
- MoveToTarget()
- DestroySurroundings()
+ if(HOSTILE_STANCE_ATTACK)
+ MoveToTarget()
+ DestroySurroundings()
- if(HOSTILE_STANCE_ATTACKING)
- AttackTarget()
- DestroySurroundings()
+ if(HOSTILE_STANCE_ATTACKING)
+ AttackTarget()
+ DestroySurroundings()
- if(AIShouldSleep())
- AIStatus = AI_SLEEP
+ if(AIShouldSleep())
+ AIStatus = AI_SLEEP
+
+ return 1
//////////////HOSTILE MOB TARGETTING AND AGGRESSION////////////
diff --git a/code/modules/mob/living/simple_animal/hostile/mimic.dm b/code/modules/mob/living/simple_animal/hostile/mimic.dm
index 9d70385cf87..2f077249527 100644
--- a/code/modules/mob/living/simple_animal/hostile/mimic.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mimic.dm
@@ -23,14 +23,7 @@
attack_sound = 'sound/weapons/bite.ogg'
speak_emote = list("creaks")
- min_oxy = 0
- max_oxy = 0
- min_tox = 0
- max_tox = 0
- min_co2 = 0
- max_co2 = 0
- min_n2 = 0
- max_n2 = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
faction = list("mimic")
diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
index ab26322d958..bb5fcb8b23e 100644
--- a/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
+++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs.dm
@@ -1,13 +1,6 @@
/mob/living/simple_animal/hostile/asteroid/
vision_range = 2
- min_oxy = 0
- max_oxy = 0
- min_tox = 0
- max_tox = 0
- min_co2 = 0
- max_co2 = 0
- min_n2 = 0
- max_n2 = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
unsuitable_atmos_damage = 15
faction = list("mining")
environment_smash = 2
@@ -387,7 +380,7 @@
anchored = 1 //Stays anchored until death as to be unpullable
var/pre_attack = 0
-/mob/living/simple_animal/hostile/asteroid/goliath/Life()
+/mob/living/simple_animal/hostile/asteroid/goliath/process_ai()
..()
handle_preattack()
diff --git a/code/modules/mob/living/simple_animal/hostile/pirate.dm b/code/modules/mob/living/simple_animal/hostile/pirate.dm
index 4f3cd78c093..fbbc0d0a5e3 100644
--- a/code/modules/mob/living/simple_animal/hostile/pirate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/pirate.dm
@@ -19,14 +19,7 @@
attacktext = "slashes"
attack_sound = 'sound/weapons/bladeslice.ogg'
- min_oxy = 5
- max_oxy = 0
- min_tox = 0
- max_tox = 1
- min_co2 = 0
- max_co2 = 5
- min_n2 = 0
- max_n2 = 0
+ atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
unsuitable_atmos_damage = 15
speak_emote = list("yarrs")
var/corpse = /obj/effect/landmark/mobcorpse/pirate
diff --git a/code/modules/mob/living/simple_animal/hostile/poison_bees.dm b/code/modules/mob/living/simple_animal/hostile/poison_bees.dm
index dd5a7f35822..b05ba13ccab 100644
--- a/code/modules/mob/living/simple_animal/hostile/poison_bees.dm
+++ b/code/modules/mob/living/simple_animal/hostile/poison_bees.dm
@@ -22,14 +22,7 @@
flying = 1
//Spaceborn beings don't get hurt by space
- min_oxy = 0
- max_oxy = 0
- min_tox = 0
- max_tox = 0
- min_co2 = 0
- max_co2 = 0
- min_n2 = 0
- max_n2 = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
/mob/living/simple_animal/hostile/poison/bees/Process_Spacemove(var/check_drift = 0)
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
index f4f0db898bb..cce4b32235c 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
@@ -23,15 +23,6 @@
attacktext = "attacks"
attack_sound = 'sound/items/bikehorn.ogg'
environment_smash = 0
-
- min_oxy = 5
- max_oxy = 0
- min_tox = 0
- max_tox = 1
- min_co2 = 0
- max_co2 = 5
- min_n2 = 0
- max_n2 = 0
minbodytemp = 270
maxbodytemp = 370
heat_damage_per_tick = 15 //amount of damage applied if animal's body temperature is higher than maxbodytemp
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm
index 6c4986541a6..5ee52bec825 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/drone.dm
@@ -35,14 +35,7 @@
var/exploding = 0
//Drones aren't affected by atmos.
- min_oxy = 0
- max_oxy = 0
- min_tox = 0
- max_tox = 0
- min_co2 = 0
- max_co2 = 0
- min_n2 = 0
- max_n2 = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
var/has_loot = 1
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/pet.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/pet.dm
index 17d764b9c1d..5a0798874e4 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/pet.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/pet.dm
@@ -17,7 +17,4 @@
melee_damage_lower = 15
melee_damage_upper = 20
- min_oxy = 5
- max_tox = 2
- max_co2 = 5
-
+ atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 2, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0)
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm
index abfcad0e403..44de372550f 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/undead.dm
@@ -41,14 +41,7 @@
attacktext = "grips"
attack_sound = 'sound/hallucinations/growl1.ogg'
- min_oxy = 0
- max_oxy = 0
- min_tox = 0
- max_tox = 0
- min_co2 = 0
- max_co2 = 0
- min_n2 = 0
- max_n2 = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
faction = list("undead") // did I mention ghost
@@ -93,14 +86,7 @@
attacktext = "claws"
attack_sound = 'sound/hallucinations/growl1.ogg'
- min_oxy = 0
- max_oxy = 0
- min_tox = 0
- max_tox = 0
- min_co2 = 0
- max_co2 = 0
- min_n2 = 0
- max_n2 = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
faction = list("undead")
@@ -131,14 +117,7 @@
attacktext = "claws"
attack_sound = 'sound/hallucinations/growl1.ogg'
- min_oxy = 0
- max_oxy = 0
- min_tox = 0
- max_tox = 0
- min_co2 = 0
- max_co2 = 0
- min_n2 = 0
- max_n2 = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
faction = list("undead")
diff --git a/code/modules/mob/living/simple_animal/hostile/russian.dm b/code/modules/mob/living/simple_animal/hostile/russian.dm
index 1c32975d5e8..35cdbb14dfb 100644
--- a/code/modules/mob/living/simple_animal/hostile/russian.dm
+++ b/code/modules/mob/living/simple_animal/hostile/russian.dm
@@ -21,14 +21,6 @@
a_intent = I_HARM
var/corpse = /obj/effect/landmark/mobcorpse/russian
var/weapon1 = /obj/item/weapon/kitchen/knife
- min_oxy = 5
- max_oxy = 0
- min_tox = 0
- max_tox = 1
- min_co2 = 0
- max_co2 = 5
- min_n2 = 0
- max_n2 = 0
unsuitable_atmos_damage = 15
faction = list("russian")
status_flags = CANPUSH
diff --git a/code/modules/mob/living/simple_animal/hostile/spaceworms.dm b/code/modules/mob/living/simple_animal/hostile/spaceworms.dm
index 2f477b45482..a186bbe3d09 100644
--- a/code/modules/mob/living/simple_animal/hostile/spaceworms.dm
+++ b/code/modules/mob/living/simple_animal/hostile/spaceworms.dm
@@ -26,9 +26,7 @@
minbodytemp = 0
maxbodytemp = 350
- min_oxy = 0
- max_co2 = 0
- max_tox = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
a_intent = I_HARM //so they don't get pushed around
diff --git a/code/modules/mob/living/simple_animal/hostile/statue.dm b/code/modules/mob/living/simple_animal/hostile/statue.dm
index a466d62306b..8ca393bb2d1 100644
--- a/code/modules/mob/living/simple_animal/hostile/statue.dm
+++ b/code/modules/mob/living/simple_animal/hostile/statue.dm
@@ -23,14 +23,7 @@
attacktext = "claws"
attack_sound = 'sound/hallucinations/growl1.ogg'
- min_oxy = 0
- max_oxy = 0
- min_tox = 0
- max_tox = 0
- min_co2 = 0
- max_co2 = 0
- min_n2 = 0
- max_n2 = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
faction = list("statue")
@@ -76,12 +69,12 @@
icon_state = "angel"
return ..()
-/mob/living/simple_animal/hostile/statue/Life()
- if(..())
- if(!ckey)
- spawn() //for saftey
- checkTargets()
- . = 1
+/mob/living/simple_animal/hostile/statue/process_ai()
+ . = ..()
+ if(!.)
+ return
+ spawn() //for saftey
+ checkTargets()
/mob/living/simple_animal/hostile/statue/proc/checkTargets()
if(target)
@@ -195,6 +188,9 @@
. = ..()
return . - creator
+/mob/living/simple_animal/hostile/statue/sentience_act()
+ faction -= "neutral"
+
// Statue powers
// Flicker lights
diff --git a/code/modules/mob/living/simple_animal/hostile/syndicate.dm b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
index b81a9161686..434d1739b9e 100644
--- a/code/modules/mob/living/simple_animal/hostile/syndicate.dm
+++ b/code/modules/mob/living/simple_animal/hostile/syndicate.dm
@@ -22,14 +22,6 @@
var/corpse = /obj/effect/landmark/mobcorpse/syndicatesoldier
var/weapon1
var/weapon2
- min_oxy = 5
- max_oxy = 0
- min_tox = 0
- max_tox = 1
- min_co2 = 0
- max_co2 = 5
- min_n2 = 0
- max_n2 = 0
unsuitable_atmos_damage = 15
faction = list("syndicate")
status_flags = CANPUSH
@@ -85,14 +77,7 @@
/mob/living/simple_animal/hostile/syndicate/melee/space
- min_oxy = 0
- max_oxy = 0
- min_tox = 0
- max_tox = 0
- min_co2 = 0
- max_co2 = 0
- min_n2 = 0
- max_n2 = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
icon_state = "syndicatemeleespace"
icon_living = "syndicatemeleespace"
@@ -120,14 +105,7 @@
icon_state = "syndicaterangedpsace"
icon_living = "syndicaterangedpsace"
name = "Syndicate Commando"
- min_oxy = 0
- max_oxy = 0
- min_tox = 0
- max_tox = 0
- min_co2 = 0
- max_co2 = 0
- min_n2 = 0
- max_n2 = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
corpse = /obj/effect/landmark/mobcorpse/syndicatecommando
speed = 1
@@ -151,14 +129,7 @@
attacktext = "cuts"
attack_sound = 'sound/weapons/bladeslice.ogg'
faction = list("syndicate")
- min_oxy = 0
- max_oxy = 0
- min_tox = 0
- max_tox = 0
- min_co2 = 0
- max_co2 = 0
- min_n2 = 0
- max_n2 = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
flying = 1
diff --git a/code/modules/mob/living/simple_animal/hostile/tree.dm b/code/modules/mob/living/simple_animal/hostile/tree.dm
index 181ddaa144e..555386debcb 100644
--- a/code/modules/mob/living/simple_animal/hostile/tree.dm
+++ b/code/modules/mob/living/simple_animal/hostile/tree.dm
@@ -24,15 +24,7 @@
attack_sound = 'sound/weapons/bite.ogg'
speak_emote = list("pines")
- //Space carp aren't affected by atmos.
- min_oxy = 0
- max_oxy = 0
- min_tox = 0
- max_tox = 0
- min_co2 = 0
- max_co2 = 0
- min_n2 = 0
- max_n2 = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
faction = list("hostile", "winter")
diff --git a/code/modules/mob/living/simple_animal/hostile/winter_mobs.dm b/code/modules/mob/living/simple_animal/hostile/winter_mobs.dm
index 4606a5157ee..930eb144af8 100644
--- a/code/modules/mob/living/simple_animal/hostile/winter_mobs.dm
+++ b/code/modules/mob/living/simple_animal/hostile/winter_mobs.dm
@@ -14,14 +14,7 @@
icon_living = "placeholder"
icon_dead = "placeholder"
- min_oxy = 0
- max_oxy = 0
- min_tox = 0
- max_tox = 0
- min_co2 = 0
- max_co2 = 0
- min_n2 = 0
- max_n2 = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
melee_damage_lower = 3
diff --git a/code/modules/mob/living/simple_animal/parrot.dm b/code/modules/mob/living/simple_animal/parrot.dm
index 90cd9e45830..9a53f6bfa35 100644
--- a/code/modules/mob/living/simple_animal/parrot.dm
+++ b/code/modules/mob/living/simple_animal/parrot.dm
@@ -52,12 +52,12 @@
universal_speak = 1
var/parrot_state = PARROT_WANDER //Hunt for a perch when created
- var/parrot_sleep_max = 25 //The time the parrot sits while perched before looking around. Mosly a way to avoid the parrot's AI in life() being run every single tick.
+ var/parrot_sleep_max = 25 //The time the parrot sits while perched before looking around. Mosly a way to avoid the parrot's AI in process_ai() being run every single tick.
var/parrot_sleep_dur = 25 //Same as above, this is the var that physically counts down
var/parrot_dam_zone = list("chest", "head", "l_arm", "l_leg", "r_arm", "r_leg") //For humans, select a bodypart to attack
var/parrot_speed = 5 //"Delay in world ticks between movement." according to byond. Yeah, that's BS but it does directly affect movement. Higher number = slower.
- var/parrot_been_shot = 0 //Parrots get a speed bonus after being shot. This will deincrement every Life() and at 0 the parrot will return to regular speed.
+ var/parrot_been_shot = 0 //Parrots get a speed bonus after being shot. This will deincrement every process_ai() and at 0 the parrot will return to regular speed.
var/list/speech_buffer = list()
var/list/available_channels = list()
@@ -272,14 +272,13 @@
//Sprite and AI update for when a parrot gets pulled
if(pulledby && stat == CONSCIOUS)
- icon_state = "parrot_fly"
- if(!client)
- parrot_state = PARROT_WANDER
+ icon_state = "parrot_fly"
+
+/mob/living/simple_animal/parrot/process_ai()
+ if(pulledby)
+ parrot_state = PARROT_WANDER
return
-
- if(client || stat)
- return //Lets not force players or dead/incap parrots to move
-
+
if(!isturf(src.loc) || !canmove || buckled)
return //If it can't move, dont let it move. (The buckled check probably isn't necessary thanks to canmove)
diff --git a/code/modules/mob/living/simple_animal/pony.dm b/code/modules/mob/living/simple_animal/pony.dm
index 85d8031f8a6..db3d06bc3f3 100644
--- a/code/modules/mob/living/simple_animal/pony.dm
+++ b/code/modules/mob/living/simple_animal/pony.dm
@@ -15,9 +15,7 @@
attacktext = "sends rainbows of power to"
minbodytemp = 0
maxbodytemp = 4000
- min_oxy = 0
- max_co2 = 0
- max_tox = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
speed = 0
stop_automated_movement = 0
status_flags = 0
diff --git a/code/modules/mob/living/simple_animal/shade.dm b/code/modules/mob/living/simple_animal/shade.dm
index a006c94b11f..124cacc0a8f 100644
--- a/code/modules/mob/living/simple_animal/shade.dm
+++ b/code/modules/mob/living/simple_animal/shade.dm
@@ -18,9 +18,7 @@
attacktext = "drains the life from"
minbodytemp = 0
maxbodytemp = 4000
- min_oxy = 0
- max_co2 = 0
- max_tox = 0
+ atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
speed = -1
stop_automated_movement = 1
status_flags = 0
diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm
index c3fb44fd509..362ec626f2b 100644
--- a/code/modules/mob/living/simple_animal/simple_animal.dm
+++ b/code/modules/mob/living/simple_animal/simple_animal.dm
@@ -14,6 +14,7 @@
var/oxygen_alert = 0
var/toxins_alert = 0
var/fire_alert = 0
+ var/healable = 1
var/list/speak = list()
var/speak_chance = 0
@@ -41,14 +42,7 @@
var/cold_damage_per_tick = 2 //same as heat_damage_per_tick, only if the bodytemperature it's lower than minbodytemp
//Atmos effect - Yes, you can make creatures that require plasma or co2 to survive. N2O is a trace gas and handled separately, hence why it isn't here. It'd be hard to add it. Hard and me don't mix (Yes, yes make all the dick jokes you want with that.) - Errorage
- var/min_oxy = 5
- var/max_oxy = 0 //Leaving something at 0 means it's off - has no maximum
- var/min_tox = 0
- var/max_tox = 1
- var/min_co2 = 0
- var/max_co2 = 5
- var/min_n2 = 0
- var/max_n2 = 0
+ var/list/atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0) //Leaving something at 0 means it's off - has no maximum
var/unsuitable_atmos_damage = 2 //This damage is taken when atmos doesn't fit all the requirements above
@@ -56,7 +50,7 @@
var/melee_damage_lower = 0
var/melee_damage_upper = 0
var/melee_damage_type = BRUTE //Damage type of a simple mob's melee attack, should it do damage.
- var/list/ignored_damage_types = list(BRUTE = 0, BURN = 0, TOX = 0, CLONE = 0, STAMINA = 1, OXY = 0) //Set 0 to receive that damage type, 1 to ignore
+ var/list/damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) // 1 for full damage , 0 for none , -1 for 1:1 heal from that source
var/attacktext = "attacks"
var/attack_sound = null
var/friendly = "nuzzles" //If the mob does no damage with it's attack
@@ -74,10 +68,12 @@
var/simplespecies //Sorry, no spider+corgi buttbabies.
var/master_commander = null //holding var for determining who own/controls a sentient simple animal (for sentience potions).
+ var/sentience_type = SENTIENCE_ORGANIC // Sentience type, for slime potions
/mob/living/simple_animal/New()
..()
+ simple_animal_list += src
verbs -= /mob/verb/observe
if(!can_hide)
verbs -= /mob/living/simple_animal/verb/hide
@@ -90,6 +86,7 @@
if(collar)
collar.forceMove(loc)
collar = null
+ simple_animal_list -= src
return ..()
/mob/living/simple_animal/Login()
@@ -128,16 +125,14 @@
if(0) healths.icon_state = "health7"
/mob/living/simple_animal/Life()
-
- if(..())
- if(!ckey)
- handle_automated_movement()
- handle_automated_action()
- handle_automated_speech()
- . = 1
-
+ . = ..()
handle_state_icons()
+/mob/living/simple_animal/proc/process_ai()
+ handle_automated_movement()
+ handle_automated_action()
+ handle_automated_speech()
+
/mob/living/simple_animal/proc/handle_state_icons()
if(resting && icon_resting && stat != DEAD)
icon_state = icon_resting
@@ -216,32 +211,32 @@
var/n2 = environment.nitrogen
var/co2 = environment.carbon_dioxide
- if(min_oxy && oxy < min_oxy)
+ if(atmos_requirements["min_oxy"] && oxy < atmos_requirements["min_oxy"])
atmos_suitable = 0
oxygen_alert = 1
- else if(max_oxy && oxy > max_oxy)
+ else if(atmos_requirements["max_oxy"] && oxy > atmos_requirements["max_oxy"])
atmos_suitable = 0
oxygen_alert = 1
else
oxygen_alert = 0
- if(min_tox && tox < min_tox)
+ if(atmos_requirements["min_tox"] && tox < atmos_requirements["min_tox"])
atmos_suitable = 0
toxins_alert = 1
- else if(max_tox && tox > max_tox)
+ else if(atmos_requirements["max_tox"] && tox > atmos_requirements["max_tox"])
atmos_suitable = 0
toxins_alert = 1
else
toxins_alert = 0
- if(min_n2 && n2 < min_n2)
+ if(atmos_requirements["min_n2"] && n2 < atmos_requirements["min_n2"])
atmos_suitable = 0
- else if(max_n2 && n2 > max_n2)
+ else if(atmos_requirements["max_n2"] && n2 > atmos_requirements["max_n2"])
atmos_suitable = 0
- if(min_co2 && co2 < min_co2)
+ if(atmos_requirements["min_co2"] && co2 < atmos_requirements["min_co2"])
atmos_suitable = 0
- else if(max_co2 && co2 > max_co2)
+ else if(atmos_requirements["max_co2"] && co2 > atmos_requirements["max_co2"])
atmos_suitable = 0
if(!atmos_suitable)
@@ -413,7 +408,7 @@
return
/mob/living/simple_animal/attackby(var/obj/item/O as obj, var/mob/living/user as mob) //Marker -Agouri
- if(istype(O, /obj/item/stack/medical))
+ if(istype(O, /obj/item/stack/medical) && healable)
if(stat != DEAD)
var/obj/item/stack/medical/MED = O
if(health < maxHealth)
@@ -507,21 +502,29 @@
if(3.0)
adjustBruteLoss(30)
-/mob/living/simple_animal/adjustBruteLoss(damage)
- if(!ignored_damage_types[BRUTE])
- ..()
+/mob/living/simple_animal/adjustBruteLoss(amount)
+ if(damage_coeff[BRUTE])
+ return ..(amount * damage_coeff[BRUTE])
-/mob/living/simple_animal/adjustFireLoss(damage)
- if(!ignored_damage_types[BURN])
- ..(damage)
+/mob/living/simple_animal/adjustFireLoss(amount)
+ if(damage_coeff[BURN])
+ return ..(amount * damage_coeff[BURN])
-/mob/living/simple_animal/adjustToxLoss(damage)
- if(!ignored_damage_types[TOX])
- ..(damage)
+/mob/living/simple_animal/adjustOxyLoss(amount)
+ if(damage_coeff[OXY])
+ return ..(amount * damage_coeff[OXY])
-/mob/living/simple_animal/adjustCloneLoss(damage)
- if(!ignored_damage_types[CLONE])
- ..(damage)
+/mob/living/simple_animal/adjustToxLoss(amount)
+ if(damage_coeff[TOX])
+ return ..(amount * damage_coeff[TOX])
+
+/mob/living/simple_animal/adjustCloneLoss(amount)
+ if(damage_coeff[CLONE])
+ return ..(amount * damage_coeff[CLONE])
+
+/mob/living/simple_animal/adjustStaminaLoss(amount)
+ if(damage_coeff[STAMINA])
+ return ..(amount*damage_coeff[STAMINA])
/mob/living/simple_animal/proc/CanAttack(var/atom/the_target)
if(see_invisible < the_target.invisibility)
@@ -541,11 +544,10 @@
return 1
/mob/living/simple_animal/proc/attack_threshold_check(damage, damagetype = BRUTE)
- if(damage <= force_threshold || ignored_damage_types[damagetype])
+ if(damage <= force_threshold || !damage_coeff[damagetype])
visible_message("[src] looks unharmed from the damage.")
else
- adjustBruteLoss(damage)
- updatehealth()
+ apply_damage(damage, damagetype)
/mob/living/simple_animal/update_fire()
@@ -690,4 +692,7 @@
/mob/living/simple_animal/get_access()
. = ..()
if(collar)
- . |= collar.GetAccess()
\ No newline at end of file
+ . |= collar.GetAccess()
+
+/mob/living/simple_animal/proc/sentience_act() //Called when a simple animal gains sentience via gold slime potion
+ return
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index f4ca8d58fba..2fcd5406946 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -755,16 +755,6 @@ var/list/slot_equipment_priority = list( \
namecounts[name] = 1
creatures[name] = O
- if(istype(O, /obj/machinery/bot))
- var/name = "BOT: [O.name]"
- if (names.Find(name))
- namecounts[name]++
- name = "[name] ([namecounts[name]])"
- else
- names.Add(name)
- namecounts[name] = 1
- creatures[name] = O
-
for(var/mob/M in sortAtom(mob_list))
var/name = M.name
@@ -867,9 +857,9 @@ var/list/slot_equipment_priority = list( \
..()
if(M != usr) return
if(M.small) return // Stops pAI drones and small mobs (borers, parrots, crabs) from stripping people. --DZD
+ if(!M.can_strip) return
if(usr == src) return
if(!Adjacent(usr)) return
- if(istype(M,/mob/living/silicon/ai)) return
show_inv(usr)
//this and stop_pulling really ought to be /mob/living procs
diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm
index 88b48eb19f5..e23a621d038 100644
--- a/code/modules/mob/mob_defines.dm
+++ b/code/modules/mob/mob_defines.dm
@@ -87,6 +87,7 @@
var/lastpuke = 0
var/unacidable = 0
var/small = 0
+ var/can_strip = 1
var/list/pinned = list() //List of things pinning this creature to walls (see living_defense.dm)
var/list/embedded = list() //Embedded items, since simple mobs don't have organs.
var/list/languages = list() // For speaking/listening.
diff --git a/code/modules/mob/mob_helpers.dm b/code/modules/mob/mob_helpers.dm
index cd574507d6f..834592eb9c5 100644
--- a/code/modules/mob/mob_helpers.dm
+++ b/code/modules/mob/mob_helpers.dm
@@ -94,6 +94,11 @@ proc/isembryo(A)
return 1
return 0
+/proc/isbot(A)
+ if(istype(A, /mob/living/simple_animal/bot))
+ return 1
+ return 0
+
/proc/isclown(A)
if(istype(A, /mob/living/simple_animal/hostile/retaliate/clown))
return 1
diff --git a/code/modules/nano/interaction/default.dm b/code/modules/nano/interaction/default.dm
index e0e7c3a98f6..ad70ec7f484 100644
--- a/code/modules/nano/interaction/default.dm
+++ b/code/modules/nano/interaction/default.dm
@@ -96,4 +96,10 @@
if(. != STATUS_CLOSE)
. = min(., shared_living_nano_distance(src_object))
if(!IsAdvancedToolUser())
+ . = STATUS_CLOSE
+
+/mob/living/simple_animal/bot/default_can_use_topic(var/src_object)
+ . = shared_nano_interaction(src_object)
+ if(. != STATUS_CLOSE)
+ if(!(src_object in contents))
. = STATUS_CLOSE
\ No newline at end of file
diff --git a/code/modules/nano/nanoui.dm b/code/modules/nano/nanoui.dm
index cddb25bd118..6b78745c97f 100644
--- a/code/modules/nano/nanoui.dm
+++ b/code/modules/nano/nanoui.dm
@@ -187,7 +187,7 @@ nanoui is used to open and update nano browser uis
"showMap" = show_map,
"mapZLevel" = map_z_level,
"user" = list(
- "name" = user.name,
+ "name" = sanitize(user.name),
"fancy" = user.client.prefs.nanoui_fancy
),
"window" = list(
diff --git a/code/modules/pda/cart_apps.dm b/code/modules/pda/cart_apps.dm
index 58db368a489..9afb3e52764 100644
--- a/code/modules/pda/cart_apps.dm
+++ b/code/modules/pda/cart_apps.dm
@@ -96,7 +96,7 @@
/datum/data/pda/app/power/update_ui(mob/user as mob, list/data)
update = PDA_APP_UPDATE_SLOW
-
+
if (powmonitor && !isnull(powmonitor.powernet))
data["records"] = list(
"powerconnected" = 1,
@@ -226,7 +226,7 @@
beepskyData["botstatus"] = list("loca" = null, "mode" = -1)
var/botsCount=0
if(SC.botlist && SC.botlist.len)
- for(var/obj/machinery/bot/B in SC.botlist)
+ 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), "ref" = "\ref[B]")
@@ -276,7 +276,7 @@
var/mulebotsCount=0
- for(var/obj/machinery/bot/B in QC.botlist)
+ for(var/mob/living/simple_animal/bot/B in QC.botlist)
mulebotsCount++
if(B.loc)
mulebotsData[++mulebotsData.len] = list("Name" = sanitize(B.name), "Location" = sanitize(B.loc.loc.name), "ref" = "\ref[B]")
@@ -392,7 +392,7 @@
BucketData[++BucketData.len] = list("x" = 0, "y" = 0, dir=null, status = null)
var/CbotData[0]
- for(var/obj/machinery/bot/cleanbot/B in aibots)
+ for(var/mob/living/simple_animal/bot/cleanbot/B in simple_animal_list)
var/turf/bl = get_turf(B)
if(bl)
if(bl.z != cl.z)
diff --git a/code/modules/pda/radio.dm b/code/modules/pda/radio.dm
index 02a5dc996e2..b343d6b2ce3 100644
--- a/code/modules/pda/radio.dm
+++ b/code/modules/pda/radio.dm
@@ -5,7 +5,7 @@
icon_state = "power_mod"
var/obj/item/device/pda/hostpda = null
var/list/botlist = null // list of bots
- var/obj/machinery/bot/active // the active bot; if null, show bot list
+ 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.
@@ -17,9 +17,9 @@
/obj/item/radio/integrated/New()
..()
- if (istype(loc.loc, /obj/item/device/pda))
+ if(istype(loc.loc, /obj/item/device/pda))
hostpda = loc.loc
- if (bot_filter)
+ if(bot_filter)
spawn(5)
add_to_radio(bot_filter)
@@ -51,31 +51,22 @@
frequency.post_signal(src, signal, filter = s_filter)
/obj/item/radio/integrated/receive_signal(datum/signal/signal)
- /*var/obj/item/device/pda/P = src.loc
-
-
- world << "recvd:[P] : [signal.source]"
- for(var/d in signal.data)
- world << "- [d] = [signal.data[d]]"
- */
-
if (signal.data["type"] == bot_type)
if(!botlist)
botlist = new()
- if(!(signal.source in botlist))
- botlist += signal.source
+ var/obj/machinery/bot_core/core = signal.source
- if(active == 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/radio/integrated/Topic(href, href_list)
..()
- var/obj/item/device/pda/PDA = src.hostpda
-
switch(href_list["op"])
-
if("control")
active = locate(href_list["bot"])
spawn(0)
@@ -89,14 +80,14 @@
if("botlist")
active = null
- if("stop", "go")
+ if("stop", "go", "home")
spawn(0)
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")
spawn(0)
- post_signal(control_freq, "command", "summon", "active", active, "target", get_turf(PDA) , "useraccess", PDA.GetAccess(), s_filter = bot_filter)
+ 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/radio/integrated/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.
@@ -121,101 +112,45 @@
bot_type = CLEAN_BOT
/obj/item/radio/integrated/mule
- //var/list/botlist = null // list of bots
- //var/obj/machinery/bot/mulebot/active // the active bot; if null, show bot list
- //var/list/botstatus // the status signal sent by the bot
- var/list/beacons
-
- var/beacon_freq = 1400
- control_freq = 1447
-
-// create a new QM cartridge, and register to receive bot control & beacon message
-/obj/item/radio/integrated/mule/New()
- ..()
- spawn(5)
- if(radio_controller)
- radio_controller.add_object(src, control_freq, filter = RADIO_MULEBOT)
- radio_controller.add_object(src, beacon_freq, filter = RADIO_NAVBEACONS)
- spawn(10)
- post_signal(beacon_freq, "findbeacon", "delivery", s_filter = RADIO_NAVBEACONS)
-
-/obj/item/radio/integrated/mule/Destroy()
- if(radio_controller)
- radio_controller.remove_object(src,beacon_freq)
- return ..()
-
-// receive radio signals
-// can detect bot status signals
-// and beacon locations
-// create/populate lists as they are recvd
-
-/obj/item/radio/integrated/mule/receive_signal(datum/signal/signal)
- if(signal.data["type"] == MULE_BOT)
- if(!botlist)
- botlist = new()
-
- if(!(signal.source in botlist))
- botlist += signal.source
-
- if(active == signal.source)
- var/list/b = signal.data
- botstatus = b.Copy()
-
- else if(signal.data["beacon"])
- if(!beacons)
- beacons = new()
-
- beacons[signal.data["beacon"] ] = signal.source
+ bot_filter = RADIO_MULEBOT
+ bot_type = MULE_BOT
/obj/item/radio/integrated/mule/Topic(href, href_list)
- //..()
- //var/obj/item/device/pda/PDA = src.hostpda
- var/cmd = "command"
- if(active)
- cmd = "command [active.suffix]"
-
+ ..()
switch(href_list["op"])
- if("control")
- active = locate(href_list["bot"])
-
- if("scanbots") // find all bots
- botlist = null
-
- if("botlist")
- active = null
+ if("start")
+ spawn(0)
+ post_signal(control_freq, "command", "start", "active", active, s_filter = RADIO_MULEBOT)
if("unload")
spawn(0)
- post_signal(control_freq, cmd, "unload", s_filter = RADIO_MULEBOT)
+ post_signal(control_freq, "command", "unload", "active", active, s_filter = RADIO_MULEBOT)
+
if("setdest")
- if(beacons)
- var/dest = input("Select Bot Destination", "Mulebot [active.suffix] Interlink", active.destination) as null|anything in beacons
+ if(deliverybeacons)
+ var/dest = input("Select Bot Destination", "Mulebot [active.suffix] Interlink", active.destination) as null|anything in deliverybeacontags
if(dest)
spawn(0)
- post_signal(control_freq, cmd, "target", "destination", dest, s_filter = RADIO_MULEBOT)
+ post_signal(control_freq, "command", "target", "active", active, "destination", dest, s_filter = RADIO_MULEBOT)
if("retoff")
spawn(0)
- post_signal(control_freq, cmd, "autoret", "value", 0, s_filter = RADIO_MULEBOT)
-
+ post_signal(control_freq, "command", "autoret", "active", active, "value", 0, s_filter = RADIO_MULEBOT)
+
if("reton")
spawn(0)
- post_signal(control_freq, cmd, "autoret", "value", 1, s_filter = RADIO_MULEBOT)
+ post_signal(control_freq, "command", "autoret", "active", active, "value", 1, s_filter = RADIO_MULEBOT)
if("pickoff")
spawn(0)
- post_signal(control_freq, cmd, "autopick", "value", 0, s_filter = RADIO_MULEBOT)
+ post_signal(control_freq, "command", "autopick", "active", active, "value", 0, s_filter = RADIO_MULEBOT)
if("pickon")
spawn(0)
- post_signal(control_freq, cmd, "autopick", "value", 1, s_filter = RADIO_MULEBOT)
-
- if("stop", "go", "home")
- spawn(0)
- post_signal(control_freq, cmd, href_list["op"], s_filter = RADIO_MULEBOT)
+ post_signal(control_freq, "command", "autopick", "active", active, "value", 1, s_filter = RADIO_MULEBOT)
spawn(10)
- post_signal(control_freq, cmd, "bot_status", s_filter = RADIO_MULEBOT)
+ post_signal(control_freq, "command", "bot_status", "active", active, s_filter = RADIO_MULEBOT)
diff --git a/code/modules/reagents/reagent_containers/glass_containers.dm b/code/modules/reagents/reagent_containers/glass_containers.dm
index b5071cda21f..e7a13b4783c 100644
--- a/code/modules/reagents/reagent_containers/glass_containers.dm
+++ b/code/modules/reagents/reagent_containers/glass_containers.dm
@@ -28,7 +28,7 @@
/obj/machinery/atmospherics/unary/cryo_cell,
/obj/machinery/dna_scannernew,
/obj/item/weapon/grenade/chem_grenade,
- /obj/machinery/bot/medbot,
+ /mob/living/simple_animal/bot/medbot,
/obj/item/weapon/storage/secure/safe,
/obj/machinery/iv_drip,
/obj/machinery/computer/pandemic,
diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm
index ce990a7226b..aed517d98ce 100644
--- a/code/modules/shuttle/supply.dm
+++ b/code/modules/shuttle/supply.dm
@@ -780,7 +780,8 @@
var/list/mobs_can_pass = list(
/mob/living/carbon/slime,
/mob/living/simple_animal/mouse,
- /mob/living/silicon/robot/drone
+ /mob/living/silicon/robot/drone,
+ /mob/living/simple_animal/bot/mulebot
)
/obj/structure/plasticflaps/CanPass(atom/A, turf/T)
@@ -814,6 +815,18 @@
return ..()
+
+/obj/structure/plasticflaps/CanAStarPass(ID, to_dir, caller)
+ if(istype(caller, /mob/living))
+ for(var/mob_type in mobs_can_pass)
+ if(istype(caller, mob_type))
+ return 1
+
+ var/mob/living/M = caller
+ if(!M.ventcrawler && !M.small)
+ return 0
+ return 1
+
/obj/structure/plasticflaps/ex_act(severity)
switch(severity)
if (1)
diff --git a/icons/effects/fluidtracks.dmi b/icons/effects/fluidtracks.dmi
index 0675d93d7f9..810ecc7f265 100644
Binary files a/icons/effects/fluidtracks.dmi and b/icons/effects/fluidtracks.dmi differ
diff --git a/icons/mob/hud.dmi b/icons/mob/hud.dmi
index 9b2a74768d1..4f7829c3aac 100644
Binary files a/icons/mob/hud.dmi and b/icons/mob/hud.dmi differ
diff --git a/icons/mob/screen1_bot.dmi b/icons/mob/screen1_bot.dmi
new file mode 100644
index 00000000000..7522623f327
Binary files /dev/null and b/icons/mob/screen1_bot.dmi differ
diff --git a/icons/mob/screen1_robot.dmi b/icons/mob/screen1_robot.dmi
index 9188e33ff5f..0128584d284 100644
Binary files a/icons/mob/screen1_robot.dmi and b/icons/mob/screen1_robot.dmi differ
diff --git a/nano/templates/pda_mule.tmpl b/nano/templates/pda_mule.tmpl
index cf3c5eff6f6..369d0830aa5 100644
--- a/nano/templates/pda_mule.tmpl
+++ b/nano/templates/pda_mule.tmpl
@@ -110,7 +110,7 @@
{{:helper.link('Stop', 'gear', {'radiomenu' : "1", 'op' : "stop"}, null, 'pdalink fixedLeft')}}
- {{:helper.link('Proceed', 'gear', {'radiomenu' : "1", 'op' : "go"}, null, 'pdalink fixedLeft')}}
+ {{:helper.link('Proceed', 'gear', {'radiomenu' : "1", 'op' : "start"}, null, 'pdalink fixedLeft')}}
{{:helper.link('Return Home', 'gear', {'radiomenu' : "1", 'op' : "home"}, null, 'pdalink fixedLeft')}}
diff --git a/paradise.dme b/paradise.dme
index 5828f4e1f83..e7fde85fc36 100644
--- a/paradise.dme
+++ b/paradise.dme
@@ -17,6 +17,7 @@
#include "code\__DEFINES\_readme.dm"
#include "code\__DEFINES\admin.dm"
#include "code\__DEFINES\atmospherics.dm"
+#include "code\__DEFINES\bots.dm"
#include "code\__DEFINES\btime.dm"
#include "code\__DEFINES\clothing.dm"
#include "code\__DEFINES\combat.dm"
@@ -99,6 +100,7 @@
#include "code\_onclick\hud\ai.dm"
#include "code\_onclick\hud\alien.dm"
#include "code\_onclick\hud\alien_larva.dm"
+#include "code\_onclick\hud\bot.dm"
#include "code\_onclick\hud\hud.dm"
#include "code\_onclick\hud\human.dm"
#include "code\_onclick\hud\monkey.dm"
@@ -156,7 +158,7 @@
#include "code\controllers\voting.dm"
#include "code\controllers\Processes\air.dm"
#include "code\controllers\Processes\alarm.dm"
-#include "code\controllers\Processes\bot.dm"
+#include "code\controllers\Processes\animal.dm"
#include "code\controllers\Processes\diseases.dm"
#include "code\controllers\Processes\event.dm"
#include "code\controllers\Processes\garbage.dm"
@@ -533,13 +535,6 @@
#include "code\game\machinery\atmoalter\pump.dm"
#include "code\game\machinery\atmoalter\scrubber.dm"
#include "code\game\machinery\atmoalter\zvent.dm"
-#include "code\game\machinery\bots\bots.dm"
-#include "code\game\machinery\bots\cleanbot.dm"
-#include "code\game\machinery\bots\ed209bot.dm"
-#include "code\game\machinery\bots\floorbot.dm"
-#include "code\game\machinery\bots\medbot.dm"
-#include "code\game\machinery\bots\mulebot.dm"
-#include "code\game\machinery\bots\secbot.dm"
#include "code\game\machinery\camera\camera.dm"
#include "code\game\machinery\camera\camera_assembly.dm"
#include "code\game\machinery\camera\motion.dm"
@@ -1529,6 +1524,15 @@
#include "code\modules\mob\living\simple_animal\simple_animal.dm"
#include "code\modules\mob\living\simple_animal\tribbles.dm"
#include "code\modules\mob\living\simple_animal\vox.dm"
+#include "code\modules\mob\living\simple_animal\bot\bot.dm"
+#include "code\modules\mob\living\simple_animal\bot\cleanbot.dm"
+#include "code\modules\mob\living\simple_animal\bot\construction.dm"
+#include "code\modules\mob\living\simple_animal\bot\ed209bot.dm"
+#include "code\modules\mob\living\simple_animal\bot\emote.dm"
+#include "code\modules\mob\living\simple_animal\bot\floorbot.dm"
+#include "code\modules\mob\living\simple_animal\bot\medbot.dm"
+#include "code\modules\mob\living\simple_animal\bot\mulebot.dm"
+#include "code\modules\mob\living\simple_animal\bot\secbot.dm"
#include "code\modules\mob\living\simple_animal\friendly\butterfly.dm"
#include "code\modules\mob\living\simple_animal\friendly\cat.dm"
#include "code\modules\mob\living\simple_animal\friendly\corgi.dm"