diff --git a/code/datums/ai/_ai_controller.dm b/code/datums/ai/_ai_controller.dm index 5c9481a28d8..5c33236f089 100644 --- a/code/datums/ai/_ai_controller.dm +++ b/code/datums/ai/_ai_controller.dm @@ -108,18 +108,23 @@ multiple modular subtrees with behaviors SEND_SIGNAL(src, COMSIG_AI_CONTROLLER_POSSESSED_PAWN) - if (!ismob(new_pawn)) - set_ai_status(AI_STATUS_ON) - else - set_ai_status(get_setup_mob_ai_status(new_pawn)) - RegisterSignal(pawn, COMSIG_MOB_STATCHANGE, PROC_REF(on_stat_changed)) - + reset_ai_status() + RegisterSignal(pawn, COMSIG_MOB_STATCHANGE, PROC_REF(on_stat_changed)) RegisterSignal(pawn, COMSIG_MOB_LOGIN, PROC_REF(on_sentience_gained)) -/// Mobs have more complicated factors about whether their AI should be on or not -/datum/ai_controller/proc/get_setup_mob_ai_status(mob/mob_pawn) +/// Sets the AI on or off based on current conditions, call to reset after you've manually disabled it somewhere +/datum/ai_controller/proc/reset_ai_status() + set_ai_status(get_expected_ai_status()) + +/// Returns what the AI status should be based on current conditions. +/datum/ai_controller/proc/get_expected_ai_status() var/final_status = AI_STATUS_ON + if (!ismob(pawn)) + return final_status + + var/mob/living/mob_pawn = pawn + if(!continue_processing_when_client && mob_pawn.client) final_status = AI_STATUS_OFF @@ -302,8 +307,7 @@ multiple modular subtrees with behaviors /// Turn the controller on or off based on if you're alive, we only register to this if the flag is present so don't need to check again /datum/ai_controller/proc/on_stat_changed(mob/living/source, new_stat) SIGNAL_HANDLER - var/new_ai_status = get_setup_mob_ai_status(source) - set_ai_status(new_ai_status) + reset_ai_status() /datum/ai_controller/proc/on_sentience_gained() SIGNAL_HANDLER diff --git a/code/datums/components/aura_healing.dm b/code/datums/components/aura_healing.dm index e162f1ecfc5..38cadccdc44 100644 --- a/code/datums/components/aura_healing.dm +++ b/code/datums/components/aura_healing.dm @@ -116,7 +116,7 @@ if (should_show_effect && candidate.health < candidate.maxHealth) new /obj/effect/temp_visual/heal(get_turf(candidate), healing_color) - if (iscarbon(candidate) || issilicon(candidate)) + if (iscarbon(candidate) || issilicon(candidate) || isbasicmob(candidate)) candidate.adjustBruteLoss(-brute_heal * delta_time, updating_health = FALSE) candidate.adjustFireLoss(-burn_heal * delta_time, updating_health = FALSE) @@ -131,8 +131,11 @@ for (var/organ in organ_healing) candidate.adjustOrganLoss(organ, -organ_healing[organ] * delta_time) else if (isanimal(candidate)) - var/mob/living/simple_animal/simple_candidate = candidate - simple_candidate.adjustHealth(-simple_heal * delta_time, updating_health = FALSE) + var/mob/living/simple_animal/animal_candidate = candidate + animal_candidate.adjustHealth(-simple_heal * delta_time, updating_health = FALSE) + else if (isbasicmob(candidate)) + var/mob/living/basic/basic_candidate = candidate + basic_candidate.adjust_health(-simple_heal * delta_time, updating_health = FALSE) if (candidate.blood_volume < BLOOD_VOLUME_NORMAL) candidate.blood_volume += blood_heal * delta_time diff --git a/code/datums/components/dejavu.dm b/code/datums/components/dejavu.dm index 462a1f2c590..8a5016f589d 100644 --- a/code/datums/components/dejavu.dm +++ b/code/datums/components/dejavu.dm @@ -58,9 +58,9 @@ saved_bodyparts = C.save_bodyparts() rewind_type = PROC_REF(rewind_carbon) - else if(isanimal(parent)) - var/mob/living/simple_animal/M = parent - brute_loss = M.bruteloss + else if(isanimal_or_basicmob(parent)) + var/mob/living/animal = parent + brute_loss = animal.bruteloss rewind_type = PROC_REF(rewind_animal) else if(isobj(parent)) @@ -110,7 +110,7 @@ rewind_living() /datum/component/dejavu/proc/rewind_animal() - var/mob/living/simple_animal/master = parent + var/mob/living/master = parent master.bruteloss = brute_loss master.updatehealth() rewind_living() diff --git a/code/datums/components/riding/riding_mob.dm b/code/datums/components/riding/riding_mob.dm index ddc7e469487..4f969692189 100644 --- a/code/datums/components/riding/riding_mob.dm +++ b/code/datums/components/riding/riding_mob.dm @@ -111,7 +111,7 @@ var/atom/movable/movable_parent = parent movable_parent.unbuckle_mob(rider) - if(!isanimal(movable_parent) && !iscyborg(movable_parent)) + if(!iscyborg(movable_parent) && !isanimal_or_basicmob(movable_parent)) return var/turf/target = get_edge_target_turf(movable_parent, movable_parent.dir) @@ -130,7 +130,7 @@ /// If we're a cyborg or animal and we spin, we yeet whoever's on us off us /datum/component/riding/creature/proc/check_emote(mob/living/user, datum/emote/emote) SIGNAL_HANDLER - if((!iscyborg(user) && !isanimal(user)) || !istype(emote, /datum/emote/spin)) + if((!iscyborg(user) && !isanimal_or_basicmob(user)) || !istype(emote, /datum/emote/spin)) return for(var/mob/yeet_mob in user.buckled_mobs) diff --git a/code/datums/components/soulstoned.dm b/code/datums/components/soulstoned.dm index d15bdec0386..dbe47748be7 100644 --- a/code/datums/components/soulstoned.dm +++ b/code/datums/components/soulstoned.dm @@ -3,29 +3,29 @@ var/atom/movable/container /datum/component/soulstoned/Initialize(atom/movable/container) - if(!isanimal(parent)) + if(!isliving(parent)) return COMPONENT_INCOMPATIBLE - var/mob/living/simple_animal/S = parent + var/mob/living/stoned = parent src.container = container - S.forceMove(container) - S.fully_heal() - ADD_TRAIT(S, TRAIT_IMMOBILIZED, SOULSTONE_TRAIT) - ADD_TRAIT(S, TRAIT_HANDS_BLOCKED, SOULSTONE_TRAIT) - S.status_flags |= GODMODE + stoned.forceMove(container) + stoned.fully_heal() + ADD_TRAIT(stoned, TRAIT_IMMOBILIZED, SOULSTONE_TRAIT) + ADD_TRAIT(stoned, TRAIT_HANDS_BLOCKED, SOULSTONE_TRAIT) + stoned.status_flags |= GODMODE - RegisterSignal(S, COMSIG_MOVABLE_MOVED, PROC_REF(free_prisoner)) + RegisterSignal(stoned, COMSIG_MOVABLE_MOVED, PROC_REF(free_prisoner)) /datum/component/soulstoned/proc/free_prisoner() SIGNAL_HANDLER - var/mob/living/simple_animal/S = parent - if(S.loc != container) + var/mob/living/stoned = parent + if(stoned.loc != container) qdel(src) /datum/component/soulstoned/UnregisterFromParent() - var/mob/living/simple_animal/S = parent - S.status_flags &= ~GODMODE - REMOVE_TRAIT(S, TRAIT_IMMOBILIZED, SOULSTONE_TRAIT) - REMOVE_TRAIT(S, TRAIT_HANDS_BLOCKED, SOULSTONE_TRAIT) + var/mob/living/stoned = parent + stoned.status_flags &= ~GODMODE + REMOVE_TRAIT(stoned, TRAIT_IMMOBILIZED, SOULSTONE_TRAIT) + REMOVE_TRAIT(stoned, TRAIT_HANDS_BLOCKED, SOULSTONE_TRAIT) diff --git a/code/datums/proximity_monitor/fields/timestop.dm b/code/datums/proximity_monitor/fields/timestop.dm index a7a1fd3db26..687c6c23601 100644 --- a/code/datums/proximity_monitor/fields/timestop.dm +++ b/code/datums/proximity_monitor/fields/timestop.dm @@ -200,27 +200,33 @@ /datum/proximity_monitor/advanced/timestop/proc/unfreeze_projectile(obj/projectile/P) P.paused = FALSE -/datum/proximity_monitor/advanced/timestop/proc/freeze_mob(mob/living/L) - frozen_mobs += L - L.Stun(20, ignore_canstun = TRUE) - ADD_TRAIT(L, TRAIT_MUTE, TIMESTOP_TRAIT) - ADD_TRAIT(L, TRAIT_EMOTEMUTE, TIMESTOP_TRAIT) - SSmove_manager.stop_looping(L) //stops them mid pathing even if they're stunimmune //This is really dumb - if(isanimal(L)) - var/mob/living/simple_animal/S = L - S.toggle_ai(AI_OFF) - if(ishostile(L)) - var/mob/living/simple_animal/hostile/H = L - H.LoseTarget() +/datum/proximity_monitor/advanced/timestop/proc/freeze_mob(mob/living/victim) + frozen_mobs += victim + victim.Stun(20, ignore_canstun = TRUE) + ADD_TRAIT(victim, TRAIT_MUTE, TIMESTOP_TRAIT) + ADD_TRAIT(victim, TRAIT_EMOTEMUTE, TIMESTOP_TRAIT) + SSmove_manager.stop_looping(victim) //stops them mid pathing even if they're stunimmune //This is really dumb + if(isanimal(victim)) + var/mob/living/simple_animal/animal_victim = victim + animal_victim.toggle_ai(AI_OFF) + if(ishostile(victim)) + var/mob/living/simple_animal/hostile/hostile_victim = victim + hostile_victim.LoseTarget() + else if(isbasicmob(victim)) + var/mob/living/basic/basic_victim = victim + basic_victim.ai_controller?.set_ai_status(AI_STATUS_OFF) -/datum/proximity_monitor/advanced/timestop/proc/unfreeze_mob(mob/living/L) - L.AdjustStun(-20, ignore_canstun = TRUE) - REMOVE_TRAIT(L, TRAIT_MUTE, TIMESTOP_TRAIT) - REMOVE_TRAIT(L, TRAIT_EMOTEMUTE, TIMESTOP_TRAIT) - frozen_mobs -= L - if(isanimal(L)) - var/mob/living/simple_animal/S = L - S.toggle_ai(initial(S.AIStatus)) +/datum/proximity_monitor/advanced/timestop/proc/unfreeze_mob(mob/living/victim) + victim.AdjustStun(-20, ignore_canstun = TRUE) + REMOVE_TRAIT(victim, TRAIT_MUTE, TIMESTOP_TRAIT) + REMOVE_TRAIT(victim, TRAIT_EMOTEMUTE, TIMESTOP_TRAIT) + frozen_mobs -= victim + if(isanimal(victim)) + var/mob/living/simple_animal/animal_victim = victim + animal_victim.toggle_ai(initial(animal_victim.AIStatus)) + else if(isbasicmob(victim)) + var/mob/living/basic/basic_victim = victim + basic_victim.ai_controller?.reset_ai_status() //you don't look quite right, is something the matter? /datum/proximity_monitor/advanced/timestop/proc/into_the_negative_zone(atom/A) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 4b04d1b2a4a..78b382e9e13 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -871,7 +871,9 @@ var/list/nested_locs = get_nested_locs(src) + src for(var/channel in gone.important_recursive_contents) for(var/atom/movable/location as anything in nested_locs) + LAZYINITLIST(location.important_recursive_contents) var/list/recursive_contents = location.important_recursive_contents // blue hedgehog velocity + LAZYINITLIST(recursive_contents[channel]) recursive_contents[channel] -= gone.important_recursive_contents[channel] switch(channel) if(RECURSIVE_CONTENTS_CLIENT_MOBS, RECURSIVE_CONTENTS_HEARING_SENSITIVE) @@ -979,7 +981,9 @@ SSspatial_grid.remove_grid_membership(src, our_turf, SPATIAL_GRID_CONTENTS_TYPE_CLIENTS) for(var/atom/movable/movable_loc as anything in get_nested_locs(src) + src) + LAZYINITLIST(movable_loc.important_recursive_contents) var/list/recursive_contents = movable_loc.important_recursive_contents // blue hedgehog velocity + LAZYINITLIST(recursive_contents[RECURSIVE_CONTENTS_CLIENT_MOBS]) recursive_contents[RECURSIVE_CONTENTS_CLIENT_MOBS] -= src if(!length(recursive_contents[RECURSIVE_CONTENTS_CLIENT_MOBS])) SSspatial_grid.remove_grid_awareness(movable_loc, SPATIAL_GRID_CONTENTS_TYPE_CLIENTS) diff --git a/code/game/objects/items/food/packaged.dm b/code/game/objects/items/food/packaged.dm index abb3a66a54d..ce8a6f6a825 100644 --- a/code/game/objects/items/food/packaged.dm +++ b/code/game/objects/items/food/packaged.dm @@ -108,26 +108,31 @@ return ..() apply_buff(user) +/obj/item/food/canned/envirochow/attack_basic_mob(mob/living/basic/user, list/modifiers) + if(!check_buffability(user)) + return ..() + apply_buff(user) + /obj/item/food/canned/envirochow/afterattack(atom/target, mob/user, proximity_flag) . = ..() if(!proximity_flag) return - if(!isanimal(target)) - return if(!check_buffability(target)) return apply_buff(target, user) ///This proc checks if the mob is able to recieve the buff. -/obj/item/food/canned/envirochow/proc/check_buffability(mob/living/simple_animal/hungry_pet) - if(!is_drainable()) //can is not open +/obj/item/food/canned/envirochow/proc/check_buffability(mob/living/hungry_pet) + if(!isanimal_or_basicmob(hungry_pet)) // Not a pet return FALSE - if(hungry_pet.stat) //parrot deceased + if(!is_drainable()) // Can is not open + return FALSE + if(hungry_pet.stat) // Parrot deceased return FALSE if(hungry_pet.mob_biotypes & (MOB_BEAST|MOB_REPTILE|MOB_BUG)) return TRUE else - return FALSE //humans, robots & spooky ghosts not allowed + return FALSE // Humans, robots & spooky ghosts not allowed ///This makes the animal eat the food, and applies the buff status effect to them. /obj/item/food/canned/envirochow/proc/apply_buff(mob/living/simple_animal/hungry_pet, mob/living/dog_mom) diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm index d5fa88b1a69..3d121f854f8 100644 --- a/code/game/objects/items/handcuffs.dm +++ b/code/game/objects/items/handcuffs.dm @@ -419,42 +419,38 @@ update_appearance() playsound(src, 'sound/effects/snap.ogg', 50, TRUE) -/obj/item/restraints/legcuffs/beartrap/proc/spring_trap(datum/source, atom/movable/AM, thrown_at = FALSE) +/obj/item/restraints/legcuffs/beartrap/proc/spring_trap(datum/source, atom/movable/target, thrown_at = FALSE) SIGNAL_HANDLER - if(!armed || !isturf(loc) || !isliving(AM)) + if(!armed || !isturf(loc) || !isliving(target)) return - var/mob/living/L = AM - var/snap = TRUE - if(istype(L.buckled, /obj/vehicle)) - var/obj/vehicle/ridden_vehicle = L.buckled + var/mob/living/victim = target + if(istype(victim.buckled, /obj/vehicle)) + var/obj/vehicle/ridden_vehicle = victim.buckled if(!ridden_vehicle.are_legs_exposed) //close the trap without injuring/trapping the rider if their legs are inside the vehicle at all times. close_trap() ridden_vehicle.visible_message(span_danger("[ridden_vehicle] triggers \the [src].")) + return - if(!thrown_at && L.movement_type & (FLYING|FLOATING)) //don't close the trap if they're flying/floating over it. - snap = FALSE + //don't close the trap if they're as small as a mouse, or not touching the ground + if(victim.mob_size <= MOB_SIZE_TINY || (!thrown_at && victim.movement_type & (FLYING|FLOATING))) + return + close_trap() + if(thrown_at) + victim.visible_message(span_danger("\The [src] ensnares [victim]!"), \ + span_userdanger("\The [src] ensnares you!")) + else + victim.visible_message(span_danger("[victim] triggers \the [src]."), \ + span_userdanger("You trigger \the [src]!")) var/def_zone = BODY_ZONE_CHEST - if(snap && iscarbon(L)) - var/mob/living/carbon/C = L - if(C.body_position == STANDING_UP) - def_zone = pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) - if(!C.legcuffed && C.num_legs >= 2) //beartrap can't cuff your leg if there's already a beartrap or legcuffs, or you don't have two legs. - INVOKE_ASYNC(C, TYPE_PROC_REF(/mob/living/carbon, equip_to_slot), src, ITEM_SLOT_LEGCUFFED) - SSblackbox.record_feedback("tally", "handcuffs", 1, type) - else if(snap && isanimal(L)) - var/mob/living/simple_animal/SA = L - if(SA.mob_size <= MOB_SIZE_TINY) //don't close the trap if they're as small as a mouse. - snap = FALSE - if(snap) - close_trap() - if(!thrown_at) - L.visible_message(span_danger("[L] triggers \the [src]."), \ - span_userdanger("You trigger \the [src]!")) - else - L.visible_message(span_danger("\The [src] ensnares [L]!"), \ - span_userdanger("\The [src] ensnares you!")) - L.apply_damage(trap_damage, BRUTE, def_zone) + if(iscarbon(victim) && victim.body_position == STANDING_UP) + var/mob/living/carbon/carbon_victim = victim + def_zone = pick(BODY_ZONE_L_LEG, BODY_ZONE_R_LEG) + if(!carbon_victim.legcuffed && carbon_victim.num_legs >= 2) //beartrap can't cuff your leg if there's already a beartrap or legcuffs, or you don't have two legs. + INVOKE_ASYNC(carbon_victim, TYPE_PROC_REF(/mob/living/carbon, equip_to_slot), src, ITEM_SLOT_LEGCUFFED) + SSblackbox.record_feedback("tally", "handcuffs", 1, type) + + victim.apply_damage(trap_damage, BRUTE, def_zone) /** * # Energy snare diff --git a/code/game/objects/items/implants/implant.dm b/code/game/objects/items/implants/implant.dm index 667632f009a..aac636cf3ba 100644 --- a/code/game/objects/items/implants/implant.dm +++ b/code/game/objects/items/implants/implant.dm @@ -37,10 +37,8 @@ if(isslime(target)) return TRUE - if(isanimal(target)) - var/mob/living/simple_animal/animal = target - // Robots and most non-organics aren't healable. - return animal.healable + if((target.mob_biotypes & (MOB_ROBOTIC|MOB_MINERAL|MOB_SPIRIT))) + return FALSE return TRUE diff --git a/code/game/objects/items/robot/items/generic.dm b/code/game/objects/items/robot/items/generic.dm index a1644958b18..05d72166c5b 100644 --- a/code/game/objects/items/robot/items/generic.dm +++ b/code/game/objects/items/robot/items/generic.dm @@ -83,7 +83,7 @@ return switch(mode) if(HUG_MODE_NICE) - if(isanimal(attacked_mob)) + if(isanimal_or_basicmob(attacked_mob)) var/list/modifiers = params2list(params) if (!user.combat_mode && !LAZYACCESS(modifiers, RIGHT_CLICK)) attacked_mob.attack_hand(user, modifiers) //This enables borgs to get the floating heart icon and mob emote from simple_animal's that have petbonus == true. diff --git a/code/modules/admin/player_panel.dm b/code/modules/admin/player_panel.dm index 609d4c0b26e..45aeabd765a 100644 --- a/code/modules/admin/player_panel.dm +++ b/code/modules/admin/player_panel.dm @@ -253,7 +253,7 @@ else M_job = "Silicon-based" - else if(isanimal(M)) //simple animals + else if(isanimal_or_basicmob(M)) //simple animals if(iscorgi(M)) M_job = "Corgi" else if(isslime(M)) diff --git a/code/modules/events/ghost_role/sentience.dm b/code/modules/events/ghost_role/sentience.dm index 873e38ceeab..6c1035d29af 100644 --- a/code/modules/events/ghost_role/sentience.dm +++ b/code/modules/events/ghost_role/sentience.dm @@ -1,20 +1,24 @@ GLOBAL_LIST_INIT(high_priority_sentience, typecacheof(list( - /mob/living/basic/pet, /mob/living/simple_animal/pet, /mob/living/simple_animal/parrot, /mob/living/simple_animal/hostile/lizard, /mob/living/simple_animal/sloth, - /mob/living/basic/mouse/brown/tom, /mob/living/simple_animal/hostile/retaliate/goat, /mob/living/simple_animal/chicken, - /mob/living/basic/cow, /mob/living/simple_animal/hostile/retaliate/bat, - /mob/living/basic/carp/pet/cayenne, /mob/living/simple_animal/butterfly, /mob/living/simple_animal/hostile/retaliate/snake, /mob/living/simple_animal/hostile/retaliate/goose/vomit, /mob/living/simple_animal/bot/mulebot, /mob/living/simple_animal/bot/secbot/beepsky, + /mob/living/basic/carp/pet/cayenne, + /mob/living/basic/cow, + /mob/living/basic/pet, + /mob/living/basic/pig, + /mob/living/basic/rabbit, + /mob/living/basic/giant_spider/sgt_araneus, + /mob/living/basic/sheep, + /mob/living/basic/mouse/brown/tom, ))) /datum/round_event_control/sentience @@ -59,16 +63,10 @@ GLOBAL_LIST_INIT(high_priority_sentience, typecacheof(list( var/list/hi_pri = list() var/list/low_pri = list() - for(var/mob/living/simple_animal/L in GLOB.alive_mob_list) - var/turf/T = get_turf(L) - if(!T || !is_station_level(T.z)) - continue - if((L in GLOB.player_list) || L.mind || (L.flags_1 & HOLOGRAM_1)) - continue - if(is_type_in_typecache(L, GLOB.high_priority_sentience)) - hi_pri += L - else - low_pri += L + for(var/mob/living/simple_animal/check_mob in GLOB.alive_mob_list) + set_mob_priority(check_mob, hi_pri, low_pri) + for(var/mob/living/basic/check_mob in GLOB.alive_mob_list) + set_mob_priority(check_mob, hi_pri, low_pri) shuffle_inplace(hi_pri) shuffle_inplace(low_pri) @@ -82,30 +80,46 @@ GLOBAL_LIST_INIT(high_priority_sentience, typecacheof(list( var/spawned_animals = 0 while(spawned_animals < animals && candidates.len && potential.len) - var/mob/living/simple_animal/SA = popleft(potential) - var/mob/dead/observer/SG = pick_n_take(candidates) + var/mob/living/selected = popleft(potential) + var/mob/dead/observer/picked_candidate = pick_n_take(candidates) spawned_animals++ - SA.key = SG.key + selected.key = picked_candidate.key - SA.grant_all_languages(TRUE, FALSE, FALSE) + selected.grant_all_languages(TRUE, FALSE, FALSE) - SA.sentience_act() + if (isanimal(selected)) + var/mob/living/simple_animal/animal_selected = selected + animal_selected.sentience_act() + animal_selected.del_on_death = FALSE + else if (isbasicmob(selected)) + var/mob/living/basic/animal_selected = selected + animal_selected.basic_mob_flags &= ~DEL_ON_DEATH - SA.maxHealth = max(SA.maxHealth, 200) - SA.health = SA.maxHealth - SA.del_on_death = FALSE + selected.maxHealth = max(selected.maxHealth, 200) + selected.health = selected.maxHealth + spawned_mobs += selected - spawned_mobs += SA - - to_chat(SA, span_userdanger("Hello world!")) - to_chat(SA, "Due to freak radiation and/or chemicals \ + to_chat(selected, span_userdanger("Hello world!")) + to_chat(selected, "Due to freak radiation and/or chemicals \ and/or lucky chance, you have gained human level intelligence \ and the ability to speak and understand human language!") return SUCCESSFUL_SPAWN +/// Adds a mob to either the high or low priority event list +/datum/round_event/ghost_role/sentience/proc/set_mob_priority(mob/living/checked_mob, list/high, list/low) + var/turf/mob_turf = get_turf(checked_mob) + if(!mob_turf || !is_station_level(mob_turf.z)) + return + if((checked_mob in GLOB.player_list) || checked_mob.mind || (checked_mob.flags_1 & HOLOGRAM_1)) + return + if(is_type_in_typecache(checked_mob, GLOB.high_priority_sentience)) + high += checked_mob + else + low += checked_mob + /datum/round_event_control/sentience/all name = "Station-wide Human-level Intelligence" typepath = /datum/round_event/ghost_role/sentience/all diff --git a/code/modules/events/wizard/petsplosion.dm b/code/modules/events/wizard/petsplosion.dm index 548752e1e5f..89a74adaea7 100644 --- a/code/modules/events/wizard/petsplosion.dm +++ b/code/modules/events/wizard/petsplosion.dm @@ -1,22 +1,52 @@ +/// Candidates for the petsplosion wizard event +GLOBAL_LIST_INIT(petsplosion_candidates, typecacheof(list( + /mob/living/simple_animal/pet, + /mob/living/simple_animal/parrot, + /mob/living/simple_animal/hostile/lizard, + /mob/living/simple_animal/sloth, + /mob/living/simple_animal/hostile/retaliate/goat, + /mob/living/simple_animal/chicken, + /mob/living/simple_animal/hostile/retaliate/bat, + /mob/living/simple_animal/butterfly, + /mob/living/simple_animal/hostile/retaliate/snake, + /mob/living/simple_animal/hostile/retaliate/goose/vomit, + /mob/living/basic/carp/pet/cayenne, + /mob/living/basic/cow, + /mob/living/basic/mothroach, + /mob/living/basic/pet, + /mob/living/basic/pig, + /mob/living/basic/rabbit, + /mob/living/basic/giant_spider/sgt_araneus, + /mob/living/basic/sheep, + /mob/living/basic/mouse/brown/tom, +))) + /datum/round_event_control/wizard/petsplosion //the horror name = "Petsplosion" weight = 2 typepath = /datum/round_event/wizard/petsplosion max_occurrences = 1 //Exponential growth is nothing to sneeze at! earliest_start = 0 MINUTES - var/mobs_to_dupe = 0 description = "Rapidly multiplies the animals on the station." min_wizard_trigger_potency = 0 max_wizard_trigger_potency = 4 + /// Number of mobs we're going to duplicate + var/mobs_to_dupe = 0 /datum/round_event_control/wizard/petsplosion/preRunEvent() - for(var/mob/living/simple_animal/F in GLOB.alive_mob_list) - if(!ishostile(F) && is_station_level(F.z)) - mobs_to_dupe++ + for(var/mob/living/basic/dupe_animal in GLOB.alive_mob_list) + count_mob(dupe_animal) + for(var/mob/living/simple_animal/dupe_animal in GLOB.alive_mob_list) + count_mob(dupe_animal) if(mobs_to_dupe > 100 || !mobs_to_dupe) return EVENT_CANT_RUN - ..() + return ..() + +/// Counts whether we found some kind of valid living mob +/datum/round_event_control/wizard/petsplosion/proc/count_mob(mob/living/dupe_animal) + if(is_type_in_typecache(dupe_animal, GLOB.petsplosion_candidates) && is_station_level(dupe_animal.z)) + mobs_to_dupe++ /datum/round_event/wizard/petsplosion end_when = 61 //1 minute (+1 tick for endWhen not to interfere with tick) @@ -24,12 +54,21 @@ var/mobs_duped = 0 /datum/round_event/wizard/petsplosion/tick() - if(activeFor >= 30 * countdown) // 0 seconds : 2 animals | 30 seconds : 4 animals | 1 minute : 8 animals - countdown += 1 - for(var/mob/living/simple_animal/F in GLOB.alive_mob_list) //If you cull the heard before the next replication, things will be easier for you - if(!ishostile(F) && is_station_level(F.z)) - new F.type(F.loc) - mobs_duped++ - if(mobs_duped > 400) - kill() + if(activeFor < 30 * countdown) // 0 seconds : 2 animals | 30 seconds : 4 animals | 1 minute : 8 animals + return + countdown += 1 + //If you cull the herd before the next replication, things will be easier for you + for(var/mob/living/basic/dupe_animal in GLOB.alive_mob_list) + duplicate_mob(dupe_animal) + for(var/mob/living/simple_animal/dupe_animal in GLOB.alive_mob_list) + duplicate_mob(dupe_animal) + +/// Makes a duplicate of a valid mob and increments our "too many mobs" counter +/datum/round_event/wizard/petsplosion/proc/duplicate_mob(mob/living/dupe_animal) + if(!is_type_in_typecache(dupe_animal, GLOB.petsplosion_candidates) || !is_station_level(dupe_animal.z)) + return + new dupe_animal.type(dupe_animal.loc) + mobs_duped++ + if(mobs_duped > 400) + kill() diff --git a/code/modules/events/wizard/rpgtitles.dm b/code/modules/events/wizard/rpgtitles.dm index 98a543916f3..b2890150c93 100644 --- a/code/modules/events/wizard/rpgtitles.dm +++ b/code/modules/events/wizard/rpgtitles.dm @@ -65,7 +65,7 @@ GLOBAL_DATUM(rpgtitle_controller, /datum/rpgtitle_controller) var/maptext_title = "" - if(!(isanimal(new_crewmember) || isbasicmob(new_crewmember))) + if(!isanimal_or_basicmob(new_crewmember)) maptext_title = job.rpg_title || job.title else //this following code can only be described as bitflag black magic. ye be warned. i tried to comment excessively to explain what the fuck is happening diff --git a/code/modules/mining/lavaland/megafauna_loot.dm b/code/modules/mining/lavaland/megafauna_loot.dm index 03feac3acf2..b938dd49894 100644 --- a/code/modules/mining/lavaland/megafauna_loot.dm +++ b/code/modules/mining/lavaland/megafauna_loot.dm @@ -1061,7 +1061,7 @@ new /obj/effect/temp_visual/electricity(turf) for(var/mob/living/hit_mob in turf) to_chat(hit_mob, span_userdanger("You've been struck by lightning!")) - hit_mob.electrocute_act(15 * (isanimal(hit_mob) ? 3 : 1) * (turf == target ? 2 : 1) * (boosted ? 2 : 1), src, flags = SHOCK_TESLA|SHOCK_NOSTUN) + hit_mob.electrocute_act(15 * (isanimal_or_basicmob(hit_mob) ? 3 : 1) * (turf == target ? 2 : 1) * (boosted ? 2 : 1), src, flags = SHOCK_TESLA|SHOCK_NOSTUN) for(var/obj/hit_thing in turf) hit_thing.take_damage(20, BURN, ENERGY, FALSE) diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm index 44dede98790..09676a499e9 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -301,9 +301,9 @@ emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE mob_type_blacklist_typecache = list(/mob/living/carbon/human) //Humans get specialized scream. -/datum/emote/living/scream/select_message_type(mob/user, intentional) +/datum/emote/living/scream/select_message_type(mob/user, message, intentional) . = ..() - if(!intentional && isanimal(user)) + if(!intentional && isanimal_or_basicmob(user)) return "makes a loud and pained whimper." /datum/emote/living/scowl diff --git a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm index aa789a40989..3135c2e6318 100644 --- a/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm +++ b/code/modules/mob/living/simple_animal/hostile/jungle/leaper.dm @@ -42,13 +42,18 @@ /obj/projectile/leaper/on_hit(atom/target, blocked = FALSE) ..() + if (!isliving(target)) + return + var/mob/living/bubbled = target if(iscarbon(target)) - var/mob/living/carbon/C = target - C.reagents.add_reagent(/datum/reagent/toxin/leaper_venom, 5) + bubbled.reagents.add_reagent(/datum/reagent/toxin/leaper_venom, 5) return if(isanimal(target)) - var/mob/living/simple_animal/L = target - L.adjustHealth(25) + var/mob/living/simple_animal/bubbled_animal = bubbled + bubbled_animal.adjustHealth(25) + return + if (isbasicmob(target)) + bubbled.adjustBruteLoss(25) /obj/projectile/leaper/on_range() var/turf/T = get_turf(src) @@ -101,20 +106,22 @@ playsound(src,'sound/effects/snap.ogg',50, TRUE, -1) return ..() -/obj/structure/leaper_bubble/proc/on_entered(datum/source, atom/movable/AM) +/obj/structure/leaper_bubble/proc/on_entered(datum/source, atom/movable/bubbled) SIGNAL_HANDLER - if(isliving(AM)) - var/mob/living/L = AM - if(!istype(L, /mob/living/simple_animal/hostile/jungle/leaper)) - playsound(src,'sound/effects/snap.ogg',50, TRUE, -1) - L.Paralyze(50) - if(iscarbon(L)) - var/mob/living/carbon/C = L - C.reagents.add_reagent(/datum/reagent/toxin/leaper_venom, 5) - if(isanimal(L)) - var/mob/living/simple_animal/A = L - A.adjustHealth(25) - qdel(src) + if(!isliving(bubbled) || istype(bubbled, /mob/living/simple_animal/hostile/jungle/leaper)) + return + var/mob/living/bubbled_mob = bubbled + + playsound(src,'sound/effects/snap.ogg',50, TRUE, -1) + bubbled_mob.Paralyze(50) + if(iscarbon(bubbled_mob)) + bubbled_mob.reagents.add_reagent(/datum/reagent/toxin/leaper_venom, 5) + else if(isanimal(bubbled_mob)) + var/mob/living/simple_animal/bubbled_animal = bubbled_mob + bubbled_animal.adjustHealth(25) + else if(isbasicmob(bubbled_mob)) + bubbled_mob.adjustBruteLoss(25) + qdel(src) /datum/reagent/toxin/leaper_venom name = "Leaper venom" diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index a0881633de9..55d539536d1 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -544,18 +544,33 @@ use_time = 1 SECONDS /obj/machinery/anomalous_crystal/possessor/ActivationReaction(mob/user, method) - if(..()) - if(ishuman(user)) - var/mobcheck = FALSE - for(var/mob/living/simple_animal/A in range(1, src)) - if(A.melee_damage_upper > 5 || A.mob_size >= MOB_SIZE_LARGE || A.ckey || A.stat) - break - var/obj/structure/closet/stasis/S = new /obj/structure/closet/stasis(A) - user.forceMove(S) - mobcheck = TRUE - break - if(!mobcheck) - new /mob/living/basic/cockroach(get_step(src,dir)) //Just in case there aren't any animals on the station, this will leave you with a terrible option to possess if you feel like it //i found it funny that in the file for a giant angel beast theres a cockroach + . = ..() + if (!. || !ishuman(user)) + return FALSE + + var/list/valid_mobs = list() + var/list/nearby_things = range(1, src) + for(var/mob/living/basic/possible_mob in nearby_things) + if (!is_valid_animal(possible_mob)) + continue + valid_mobs += possible_mob + for(var/mob/living/simple_animal/possible_mob in nearby_things) + if (!is_valid_animal(possible_mob)) + continue + valid_mobs += possible_mob + + if (!length(valid_mobs)) //Just in case there aren't any animals on the station, this will leave you with a terrible option to possess if you feel like it //i found it funny that in the file for a giant angel beast theres a cockroach + new /mob/living/basic/cockroach(get_step(src,dir)) + return + + var/mob/living/picked_mob = pick(valid_mobs) + var/obj/structure/closet/stasis/possessor_container = new /obj/structure/closet/stasis(picked_mob) + user.forceMove(possessor_container) + +/// Returns true if this is a mob you're allowed to possess +/obj/machinery/anomalous_crystal/possessor/proc/is_valid_animal(mob/living/check_mob) + return check_mob.stat != DEAD && !check_mob.ckey && check_mob.mob_size < MOB_SIZE_LARGE && check_mob.melee_damage_upper <= 5 + /obj/structure/closet/stasis name = "quantum entanglement stasis warp field" @@ -577,7 +592,7 @@ /obj/structure/closet/stasis/Initialize(mapload) . = ..() - if(isanimal(loc)) + if(isanimal_or_basicmob(loc)) holder_animal = loc START_PROCESSING(SSobj, src) @@ -594,17 +609,20 @@ /obj/structure/closet/stasis/dump_contents(kill = TRUE) STOP_PROCESSING(SSobj, src) - for(var/mob/living/L in src) - REMOVE_TRAIT(L, TRAIT_MUTE, STASIS_MUTE) - L.status_flags &= ~GODMODE - L.notransform = 0 + for(var/mob/living/possessor in src) + REMOVE_TRAIT(possessor, TRAIT_MUTE, STASIS_MUTE) + possessor.status_flags &= ~GODMODE + possessor.notransform = FALSE + if(kill || !isanimal_or_basicmob(loc)) + possessor.investigate_log("has died from [src].", INVESTIGATE_DEATHS) + possessor.death(FALSE) if(holder_animal) - holder_animal.mind.transfer_to(L) + possessor.forceMove(get_turf(holder_animal)) + holder_animal.mind.transfer_to(possessor) + possessor.mind.grab_ghost(force = TRUE) holder_animal.gib() - if(kill || !isanimal(loc)) - L.investigate_log("has died from [src].", INVESTIGATE_DEATHS) - L.death(FALSE) - ..() + return ..() + return ..() /obj/structure/closet/stasis/emp_act() return diff --git a/code/modules/mob/living/simple_animal/slime/life.dm b/code/modules/mob/living/simple_animal/slime/life.dm index 9f30a634901..f4e7376dc30 100644 --- a/code/modules/mob/living/simple_animal/slime/life.dm +++ b/code/modules/mob/living/simple_animal/slime/life.dm @@ -168,35 +168,34 @@ updatehealth() /mob/living/simple_animal/slime/proc/handle_feeding(delta_time, times_fired) - var/mob/M = buckled + var/mob/living/prey = buckled if(stat) Feedstop(silent = TRUE) - if(M.stat == DEAD) // our victim died + if(prey.stat == DEAD) // our victim died if(!client) if(!rabid && !attacked) - var/mob/last_to_hurt = M.LAssailant?.resolve() - if(last_to_hurt && last_to_hurt != M) + var/mob/last_to_hurt = prey.LAssailant?.resolve() + if(last_to_hurt && last_to_hurt != prey) if(DT_PROB(30, delta_time)) add_friendship(last_to_hurt, 1) else to_chat(src, "This subject does not have a strong enough life energy anymore...") - if(M.client && ishuman(M)) + if(prey.client && ishuman(prey)) if(DT_PROB(61, delta_time)) rabid = 1 //we go rabid after finishing to feed on a human with a client. Feedstop() return - if(iscarbon(M)) - var/mob/living/carbon/C = M - C.adjustCloneLoss(rand(2, 4) * 0.5 * delta_time) - C.adjustToxLoss(rand(1, 2) * 0.5 * delta_time) + if(iscarbon(prey)) + prey.adjustCloneLoss(rand(2, 4) * 0.5 * delta_time) + prey.adjustToxLoss(rand(1, 2) * 0.5 * delta_time) - if(DT_PROB(5, delta_time) && C.client) - to_chat(C, "[pick("You can feel your body becoming weak!", \ + if(DT_PROB(5, delta_time) && prey.client) + to_chat(prey, "[pick("You can feel your body becoming weak!", \ "You feel like you're about to die!", \ "You feel every part of your body screaming in agony!", \ "A low, rolling pain passes through your body!", \ @@ -204,12 +203,12 @@ "You feel extremely weak!", \ "A sharp, deep pain bathes every inch of your body!")]") - else if(isanimal(M)) - var/mob/living/simple_animal/SA = M + else if(isanimal_or_basicmob(prey)) + var/mob/living/animal_victim = prey var/totaldamage = 0 //total damage done to this unfortunate animal - totaldamage += SA.adjustCloneLoss(rand(2, 4) * 0.5 * delta_time) - totaldamage += SA.adjustToxLoss(rand(1, 2) * 0.5 * delta_time) + totaldamage += animal_victim.adjustCloneLoss(rand(2, 4) * 0.5 * delta_time) + totaldamage += animal_victim.adjustToxLoss(rand(1, 2) * 0.5 * delta_time) if(totaldamage <= 0) //if we did no(or negative!) damage to it, stop Feedstop(0, 0) diff --git a/code/modules/mob/living/simple_animal/slime/powers.dm b/code/modules/mob/living/simple_animal/slime/powers.dm index 572201d336b..255a2deac1b 100644 --- a/code/modules/mob/living/simple_animal/slime/powers.dm +++ b/code/modules/mob/living/simple_animal/slime/powers.dm @@ -53,29 +53,39 @@ var/mob/living/simple_animal/slime/S = owner S.Feed() -/mob/living/simple_animal/slime/proc/CanFeedon(mob/living/M, silent = FALSE) - if(!Adjacent(M)) +/mob/living/simple_animal/slime/proc/CanFeedon(mob/living/meal, silent = FALSE) + if(!Adjacent(meal)) return FALSE if(buckled) Feedstop() return FALSE - if(issilicon(M) || M.mob_biotypes & MOB_ROBOTIC) + if(issilicon(meal) || meal.mob_biotypes & MOB_ROBOTIC) return FALSE - if(isanimal(M)) - var/mob/living/simple_animal/S = M - if(S.damage_coeff[TOX] <= 0 && S.damage_coeff[CLONE] <= 0) //The creature wouldn't take any damage, it must be too weird even for us. + if(isanimal(meal)) + var/mob/living/simple_animal/simple_meal = meal + if(simple_meal.damage_coeff[TOX] <= 0 && simple_meal.damage_coeff[CLONE] <= 0) //The creature wouldn't take any damage, it must be too weird even for us. if(silent) return FALSE to_chat(src, "[pick("This subject is incompatible", \ - "This subject does not have life energy", "This subject is empty", \ - "I am not satisified", "I can not feed from this subject", \ - "I do not feel nourished", "This subject is not food")]!") + "This subject does not have life energy", "This subject is empty", \ + "I am not satisified", "I can not feed from this subject", \ + "I do not feel nourished", "This subject is not food")]!") + return FALSE + else if(isbasicmob(meal)) + var/mob/living/basic/basic_meal = meal + if(basic_meal.damage_coeff[TOX] <= 0 && basic_meal.damage_coeff[CLONE] <= 0) + if (silent) + return FALSE + to_chat(src, "[pick("This subject is incompatible", \ + "This subject does not have life energy", "This subject is empty", \ + "I am not satisified", "I can not feed from this subject", \ + "I do not feel nourished", "This subject is not food")]!") return FALSE - if(isslime(M)) + if(isslime(meal)) if(silent) return FALSE to_chat(src, span_warning("I can't latch onto another slime...")) @@ -93,13 +103,13 @@ to_chat(src, span_warning("I must be conscious to do this...")) return FALSE - if(M.stat == DEAD) + if(meal.stat == DEAD) if(silent) return FALSE to_chat(src, span_warning("This subject does not have a strong enough life energy...")) return FALSE - if(locate(/mob/living/simple_animal/slime) in M.buckled_mobs) + if(locate(/mob/living/simple_animal/slime) in meal.buckled_mobs) if(silent) return FALSE to_chat(src, span_warning("Another slime is already feeding on this subject...")) diff --git a/code/modules/research/xenobiology/crossbreeding/_misc.dm b/code/modules/research/xenobiology/crossbreeding/_misc.dm index 547bd9345c9..ed9b9983ae3 100644 --- a/code/modules/research/xenobiology/crossbreeding/_misc.dm +++ b/code/modules/research/xenobiology/crossbreeding/_misc.dm @@ -176,32 +176,31 @@ Slimecrossing Items icon = 'icons/obj/xenobiology/slimecrossing.dmi' icon_state = "capturedevice" -/obj/item/capturedevice/attack(mob/living/M, mob/user) +/obj/item/capturedevice/attack(mob/living/pokemon, mob/user) if(length(contents)) to_chat(user, span_warning("The device already has something inside.")) return - if(!isanimal(M)) + if(!isanimal_or_basicmob(pokemon)) to_chat(user, span_warning("The capture device only works on simple creatures.")) return - if(M.mind) - to_chat(user, span_notice("You offer the device to [M].")) - if(tgui_alert(M, "Would you like to enter [user]'s capture device?", "Gold Capture Device", list("Yes", "No")) == "Yes") - if(user.can_perform_action(src) && user.can_perform_action(M)) - to_chat(user, span_notice("You store [M] in the capture device.")) - to_chat(M, span_notice("The world warps around you, and you're suddenly in an endless void, with a window to the outside floating in front of you.")) - store(M, user) + if(pokemon.mind) + to_chat(user, span_notice("You offer the device to [pokemon].")) + if(tgui_alert(pokemon, "Would you like to enter [user]'s capture device?", "Gold Capture Device", list("Yes", "No")) == "Yes") + if(user.can_perform_action(src) && user.can_perform_action(pokemon)) + to_chat(user, span_notice("You store [pokemon] in the capture device.")) + to_chat(pokemon, span_notice("The world warps around you, and you're suddenly in an endless void, with a window to the outside floating in front of you.")) + store(pokemon, user) else - to_chat(user, span_warning("You were too far away from [M].")) - to_chat(M, span_warning("You were too far away from [user].")) + to_chat(user, span_warning("You were too far away from [pokemon].")) + to_chat(pokemon, span_warning("You were too far away from [user].")) else - to_chat(user, span_warning("[M] refused to enter the device.")) + to_chat(user, span_warning("[pokemon] refused to enter the device.")) return - else - if(ishostile(M) && !(FACTION_NEUTRAL in M.faction)) - to_chat(user, span_warning("This creature is too aggressive to capture.")) - return - to_chat(user, span_notice("You store [M] in the capture device.")) - store(M) + else if(!(FACTION_NEUTRAL in pokemon.faction)) + to_chat(user, span_warning("This creature is too aggressive to capture.")) + return + to_chat(user, span_notice("You store [pokemon] in the capture device.")) + store(pokemon) /obj/item/capturedevice/attack_self(mob/user) if(contents.len) diff --git a/code/modules/research/xenobiology/crossbreeding/_potions.dm b/code/modules/research/xenobiology/crossbreeding/_potions.dm index 6dba8b7c491..0b5368f5372 100644 --- a/code/modules/research/xenobiology/crossbreeding/_potions.dm +++ b/code/modules/research/xenobiology/crossbreeding/_potions.dm @@ -60,7 +60,7 @@ Slimecrossing Potions to_chat(user, span_notice("You feed [peace_target] [src]!")) else to_chat(user, span_warning("You drink [src]!")) - if(isanimal(peace_target)) + if(isanimal_or_basicmob(peace_target)) ADD_TRAIT(peace_target, TRAIT_PACIFISM, MAGIC_TRAIT) else if(iscarbon(peace_target)) var/mob/living/carbon/peaceful_carbon = peace_target diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index caa4ef03144..6d8344d5244 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -996,20 +996,18 @@ icon = 'icons/obj/medical/chemical.dmi' icon_state = "potgrey" -/obj/item/slimepotion/slime/slimeradio/attack(mob/living/M, mob/user) - if(!ismob(M)) +/obj/item/slimepotion/slime/slimeradio/attack(mob/living/radio_head, mob/user) + if(!isanimal_or_basicmob(radio_head)) + to_chat(user, span_warning("[radio_head] is too complex for the potion!")) return - if(!isanimal(M)) - to_chat(user, span_warning("[M] is too complex for the potion!")) - return - if(M.stat) - to_chat(user, span_warning("[M] is dead!")) + if(radio_head.stat) + to_chat(user, span_warning("[radio_head] is dead!")) return - to_chat(user, span_notice("You feed the potion to [M].")) - to_chat(M, span_notice("Your mind tingles as you are fed the potion. You can hear radio waves now!")) + to_chat(user, span_notice("You feed the potion to [radio_head].")) + to_chat(radio_head, span_notice("Your mind tingles as you are fed the potion. You can hear radio waves now!")) var/obj/item/implant/radio/slime/imp = new(src) - imp.implant(M, user) + imp.implant(radio_head, user) qdel(src) ///Definitions for slime products that don't have anywhere else to go (Floor tiles, blueprints). diff --git a/code/modules/shuttle/emergency.dm b/code/modules/shuttle/emergency.dm index 3f4838fc438..407ba8e1df3 100644 --- a/code/modules/shuttle/emergency.dm +++ b/code/modules/shuttle/emergency.dm @@ -391,7 +391,7 @@ if(player.stat != DEAD) if(issilicon(player) && filter_by_human) //Borgs are technically dead anyways continue - if(isanimal(player) && filter_by_human) //animals don't count + if(isanimal_or_basicmob(player) && filter_by_human) //animals don't count continue if(isbrain(player)) //also technically dead continue