diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/targetting.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/targetting.dm index c52a52bb104..e23ba6ce54b 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/targetting.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/targetting.dm @@ -7,14 +7,20 @@ /datum/ai_behavior/find_potential_targets/perform(delta_time, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key) . = ..() - var/list/potential_targets var/mob/living/living_mob = controller.pawn var/datum/targetting_datum/targetting_datum = controller.blackboard[targetting_datum_key] if(!targetting_datum) CRASH("No target datum was supplied in the blackboard for [controller.pawn]") - potential_targets = hearers(vision_range, controller.pawn) - living_mob //Remove self, so we don't suicide + var/datum/weakref/weak_target = controller.blackboard[target_key] + var/atom/current_target = weak_target?.resolve() + if (targetting_datum.can_attack(living_mob, current_target)) + finish_action(controller, succeeded = TRUE) + return + + controller.blackboard[target_key] = null + var/list/potential_targets = hearers(vision_range, controller.pawn) - living_mob //Remove self, so we don't suicide for(var/HM in typecache_filter_list(range(vision_range, living_mob), hostile_machines)) //Can we see any hostile machines? if(can_see(living_mob, HM, vision_range)) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/simple_find_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/simple_find_target.dm index f6ad41d4e01..a4a6aea9b67 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/simple_find_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/simple_find_target.dm @@ -2,8 +2,4 @@ /datum/ai_planning_subtree/simple_find_target/SelectBehaviors(datum/ai_controller/controller, delta_time) . = ..() - var/datum/weakref/weak_target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] - var/atom/target = weak_target?.resolve() - if(!QDELETED(target)) - return controller.queue_behavior(/datum/ai_behavior/find_potential_targets, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) diff --git a/code/modules/mining/equipment/lazarus_injector.dm b/code/modules/mining/equipment/lazarus_injector.dm index d6aa2abd765..2bcdab1032c 100644 --- a/code/modules/mining/equipment/lazarus_injector.dm +++ b/code/modules/mining/equipment/lazarus_injector.dm @@ -29,30 +29,16 @@ . = ..() if(!loaded || !(isliving(target) && proximity_flag) ) return - if(!isanimal(target)) - to_chat(user, span_info("[src] is only effective on lesser beings.")) - return - var/mob/living/simple_animal/target_animal = target - if(target_animal.sentience_type != revive_type) - to_chat(user, span_info("[src] does not work on this sort of creature.")) + var/mob/living/target_animal = target + if(!target_animal.compare_sentience_type(revive_type)) // Will also return false if not a basic or simple mob, which are the only two we want anyway + balloon_alert(user, "invalid creature!") return if(target_animal.stat != DEAD) - to_chat(user, span_info("[src] is only effective on the dead.")) + balloon_alert(user, "it's not dead!") return - target_animal.faction = list(FACTION_NEUTRAL) - target_animal.revive(HEAL_ALL) - if(ishostile(target)) - var/mob/living/simple_animal/hostile/target_hostile = target_animal - if(malfunctioning) - target_hostile.faction |= list("lazarus", "[REF(user)]") - target_hostile.robust_searching = TRUE - target_hostile.friends += user - target_hostile.attack_same = TRUE - user.log_message("has revived hostile mob [key_name(target)] with a malfunctioning lazarus injector.", LOG_GAME) - else - target_hostile.attack_same = FALSE + target_animal.lazarus_revive(user, malfunctioning) loaded = FALSE user.visible_message(span_notice("[user] injects [target_animal] with [src], reviving it.")) SSblackbox.record_feedback("tally", "lazarus_injector", 1, target_animal.type) diff --git a/code/modules/mob/living/basic/basic.dm b/code/modules/mob/living/basic/basic.dm index 9a2b1c210b7..f7a386e9ba9 100644 --- a/code/modules/mob/living/basic/basic.dm +++ b/code/modules/mob/living/basic/basic.dm @@ -202,3 +202,6 @@ . = ..() . += "Health: [round((health / maxHealth) * 100)]%" . += "Combat Mode: [combat_mode ? "On" : "Off"]" + +/mob/living/basic/compare_sentience_type(compare_type) + return sentience_type == compare_type diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 71b091e0bc4..25429252f96 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -2469,6 +2469,21 @@ GLOBAL_LIST_EMPTY(fire_appearances) . = ..() add_mood_event("gaming", /datum/mood_event/gaming) +/** + * Helper proc for basic and simple animals to return true if the passed sentience type matches theirs + * Living doesn't have a sentience type though so it always returns false if not a basic or simple mob + */ +/mob/living/proc/compare_sentience_type(compare_type) + return FALSE + +/// Proc called when targetted by a lazarus injector +/mob/living/proc/lazarus_revive(mob/living/reviver, malfunctioning) + revive(HEAL_ALL) + befriend(reviver) + faction = (malfunctioning) ? list("[REF(reviver)]") : list(FACTION_NEUTRAL) + if (malfunctioning) + reviver.log_message("has revived mob [key_name(src)] with a malfunctioning lazarus injector.", LOG_GAME) + /// Proc for giving a mob a new 'friend', generally used for AI control and targetting. Returns false if already friends. /mob/living/proc/befriend(mob/living/new_friend) SHOULD_CALL_PARENT(TRUE) diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index d19048c5b2d..262d2085752 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -672,3 +672,10 @@ return friends += new_friend faction = new_friend.faction.Copy() + +/mob/living/simple_animal/hostile/lazarus_revive(mob/living/reviver, malfunctioning) + . = ..() + if (malfunctioning) + robust_searching = TRUE // enables friends list check + return + robust_searching = initial(robust_searching) diff --git a/code/modules/mob/living/simple_animal/simple_animal.dm b/code/modules/mob/living/simple_animal/simple_animal.dm index 549ecb4a3e2..5eed9bbbce7 100644 --- a/code/modules/mob/living/simple_animal/simple_animal.dm +++ b/code/modules/mob/living/simple_animal/simple_animal.dm @@ -751,3 +751,6 @@ hunted = null COOLDOWN_START(src, emote_cooldown, 1 MINUTES) return + +/mob/living/simple_animal/compare_sentience_type(compare_type) + return sentience_type == compare_type diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index c12ab614751..33c8bd72027 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -689,46 +689,38 @@ var/sentience_type = SENTIENCE_ORGANIC /obj/item/slimepotion/slime/sentience/attack(mob/living/dumb_mob, mob/user) - if(being_used || !ismob(dumb_mob)) + if(being_used || !isliving(dumb_mob)) return - if((!isanimal(dumb_mob) && !isbasicmob(dumb_mob)) || dumb_mob.ckey) //only works on animals that aren't player controlled - to_chat(user, span_warning("[dumb_mob] is already too intelligent for this to work!")) + if(dumb_mob.ckey) //only works on animals that aren't player controlled + balloon_alert(user, "already sentient!") return if(dumb_mob.stat) - to_chat(user, span_warning("[dumb_mob] is dead!")) + balloon_alert(user, "it's dead!") + return + if(!dumb_mob.compare_sentience_type(sentience_type)) // Will also return false if not a basic or simple mob, which are the only two we want anyway + balloon_alert(user, "invalid creature!") return - if(isanimal(dumb_mob)) - var/mob/living/simple_animal/dumb_animal = dumb_mob - if(dumb_animal.sentience_type != sentience_type) - to_chat(user, span_warning("[src] won't work on [dumb_animal].")) - return - else if(isbasicmob(dumb_mob)) //duplicate shit code until all simple animasls are made into basic mobs. sentience_type is not on living, but it duplicated on basic and animal - var/mob/living/basic/basic_dumb_bitch = dumb_mob - if(basic_dumb_bitch.sentience_type != sentience_type) - to_chat(user, span_warning("[src] won't work on [basic_dumb_bitch].")) - return - to_chat(user, span_notice("You offer [src] to [dumb_mob]...")) + balloon_alert(user, "offering...") being_used = TRUE var/list/candidates = poll_candidates_for_mob("Do you want to play as [dumb_mob.name]?", ROLE_SENTIENCE, ROLE_SENTIENCE, 5 SECONDS, dumb_mob, POLL_IGNORE_SENTIENCE_POTION) // see poll_ignore.dm - if(LAZYLEN(candidates)) - var/mob/dead/observer/C = pick(candidates) - dumb_mob.key = C.key - dumb_mob.mind.enslave_mind_to_creator(user) - SEND_SIGNAL(dumb_mob, COMSIG_SIMPLEMOB_SENTIENCEPOTION, user) - if(isanimal(dumb_mob)) - var/mob/living/simple_animal/smart_animal = dumb_mob - smart_animal.sentience_act() - dumb_mob.mind.add_antag_datum(/datum/antagonist/sentient_creature) - to_chat(user, span_notice("[dumb_mob] accepts [src] and suddenly becomes attentive and aware. It worked!")) - dumb_mob.copy_languages(user, LANGUAGE_MASTER) - after_success(user, dumb_mob) - qdel(src) - else - to_chat(user, span_notice("[dumb_mob] looks interested for a moment, but then looks back down. Maybe you should try again later.")) + if(!LAZYLEN(candidates)) + balloon_alert(user, "try again later!") being_used = FALSE - ..() + return ..() + + var/mob/dead/observer/C = pick(candidates) + dumb_mob.key = C.key + dumb_mob.mind.enslave_mind_to_creator(user) + SEND_SIGNAL(dumb_mob, COMSIG_SIMPLEMOB_SENTIENCEPOTION, user) + if(isanimal(dumb_mob)) + var/mob/living/simple_animal/smart_animal = dumb_mob + smart_animal.sentience_act() + dumb_mob.mind.add_antag_datum(/datum/antagonist/sentient_creature) + balloon_alert(user, "success") + after_success(user, dumb_mob) + qdel(src) /obj/item/slimepotion/slime/sentience/proc/after_success(mob/living/user, mob/living/smart_mob) return @@ -753,31 +745,24 @@ /obj/item/slimepotion/transference/afterattack(mob/living/switchy_mob, mob/living/user, proximity) if(!proximity) return - if(prompted || !ismob(switchy_mob)) + if(prompted || !isliving(switchy_mob)) return - if(!(isanimal(switchy_mob) || isbasicmob(switchy_mob)) || switchy_mob.ckey) //much like sentience, these will not work on something that is already player controlled - to_chat(user, span_warning("[switchy_mob] already has a higher consciousness!")) + if(switchy_mob.ckey) //much like sentience, these will not work on something that is already player controlled + balloon_alert(user, "already sentient!") return ..() if(switchy_mob.stat) - to_chat(user, span_warning("[switchy_mob] is dead!")) + balloon_alert(user, "it's dead!") + return ..() + if(!switchy_mob.compare_sentience_type(animal_type)) + balloon_alert(user, "invalid creature!") return ..() - if(isanimal(switchy_mob)) - var/mob/living/simple_animal/switchy_animal= switchy_mob - if(switchy_animal.sentience_type != animal_type) - to_chat(user, span_warning("You cannot transfer your consciousness to [switchy_animal].") ) - return ..() - else //ugly code duplication, but necccesary as sentience_type is implemented twice. - var/mob/living/basic/basic_mob = switchy_mob - if(basic_mob.sentience_type != animal_type) - to_chat(user, span_warning("You cannot transfer your consciousness to [basic_mob].") ) - return ..() var/job_banned = is_banned_from(user.ckey, ROLE_MIND_TRANSFER) if(QDELETED(src) || QDELETED(switchy_mob) || QDELETED(user)) return if(job_banned) - to_chat(user, span_warning("Your mind goes blank as you attempt to use the potion.")) + balloon_alert(user, "you're banned!") return prompted = 1 diff --git a/code/modules/spells/spell_types/pointed/dominate.dm b/code/modules/spells/spell_types/pointed/dominate.dm index 7d2c587a222..682d1559ff8 100644 --- a/code/modules/spells/spell_types/pointed/dominate.dm +++ b/code/modules/spells/spell_types/pointed/dominate.dm @@ -20,15 +20,15 @@ active_msg = "You prepare to dominate the mind of a target..." /datum/action/cooldown/spell/pointed/dominate/is_valid_target(atom/cast_on) - if(!isanimal(cast_on)) + if(!isliving(cast_on)) return FALSE - var/mob/living/simple_animal/animal = cast_on + var/mob/living/animal = cast_on if(animal.mind) return FALSE if(animal.stat == DEAD) return FALSE - if(animal.sentience_type != SENTIENCE_ORGANIC) + if(!animal.compare_sentience_type(SENTIENCE_ORGANIC)) // Will also return false if not a basic or simple mob, which are the only two we want anyway return FALSE if("cult" in animal.faction) return FALSE