Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[MIRROR] Removes final remnants of 'targetted' #563

Merged
merged 1 commit into from
Nov 12, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions code/__DEFINES/ai/ai_blackboard.dm
Original file line number Diff line number Diff line change
Expand Up @@ -65,8 +65,8 @@
#define BB_BASIC_MOB_FLEE_DISTANCE "BB_basic_flee_distance"
#define DEFAULT_BASIC_FLEE_DISTANCE 9

/// Generic key for a non-specific targetted action
#define BB_TARGETTED_ACTION "BB_targetted_action"
/// Generic key for a non-specific targeted action
#define BB_TARGETED_ACTION "BB_TARGETED_action"
/// Generic key for a non-specific action
#define BB_GENERIC_ACTION "BB_generic_action"

Expand Down
2 changes: 1 addition & 1 deletion code/__DEFINES/traits.dm
Original file line number Diff line number Diff line change
Expand Up @@ -663,7 +663,7 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
#define TRAIT_TENTACLE_IMMUNE "tentacle_immune"
/// Currently under the effect of overwatch
#define TRAIT_OVERWATCHED "watcher_overwatched"
/// Cannot be targetted by watcher overwatch
/// Cannot be targeted by watcher overwatch
#define TRAIT_OVERWATCH_IMMUNE "overwatch_immune"

//non-mob traits
Expand Down
2 changes: 1 addition & 1 deletion code/__DEFINES/wounds.dm
Original file line number Diff line number Diff line change
Expand Up @@ -90,7 +90,7 @@ GLOBAL_LIST_INIT(wound_severities_chronological, list(

// "Where" a specific biostate is within a given limb
// Interior is hard shit, the last line, shit like bones
// Exterior is soft shit, targetted by slashes and pierces (usually), protects exterior
// Exterior is soft shit, targeted by slashes and pierces (usually), protects exterior
// A limb needs both mangled interior and exterior to be dismembered, but slash/pierce must mangle exterior to attack the interior
// Not having exterior/interior counts as mangled exterior/interior for the purposes of dismemberment
/// The given biostate is on the "interior" of the limb - hard shit, protected by exterior
Expand Down
2 changes: 1 addition & 1 deletion code/datums/actions/mobs/fire_breath.dm
Original file line number Diff line number Diff line change
Expand Up @@ -37,7 +37,7 @@
var/list/turfs = get_line(owner, target_turf) - get_turf(owner)
INVOKE_ASYNC(src, PROC_REF(progressive_fire_line), turfs)

/// Creates fire with a delay on the list of targetted turfs
/// Creates fire with a delay on the list of targeted turfs
/datum/action/cooldown/mob_cooldown/fire_breath/proc/progressive_fire_line(list/burn_turfs)
if (QDELETED(owner) || owner.stat == DEAD)
return
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@
/datum/ai_behavior/basic_melee_attack/setup(datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key)
. = ..()
if(!controller.blackboard[targeting_strategy_key])
CRASH("No target datum was supplied in the blackboard for [controller.pawn]")
CRASH("No targeting strategy was supplied in the blackboard for [controller.pawn]")

//Hiding location is priority
var/atom/target = controller.blackboard[hiding_location_key] || controller.blackboard[target_key]
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/// Attempts to use a mob ability on a target
/datum/ai_planning_subtree/targeted_mob_ability
/// Blackboard key for the ability
var/ability_key = BB_TARGETTED_ACTION
var/ability_key = BB_TARGETED_ACTION
/// Blackboard key for where the target ref is stored
var/target_key = BB_BASIC_MOB_CURRENT_TARGET
/// Behaviour to perform using ability
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
/**
* Simple behaviours which simply try to use an ability whenever it is available.
* For something which wants a target try `targetted_mob_ability`.
* For something which wants a target try `targeted_mob_ability`.
*/
/datum/ai_planning_subtree/use_mob_ability
/// Blackboard key for the ability
Expand Down
18 changes: 9 additions & 9 deletions code/datums/ai/learn_ai.md
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ First, let's look at the blackboard.
```dm
/datum/ai_controller/basic/cow
blackboard = list(
BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/allow_items(),
BB_TARGETING_STRATEGY = new /datum/targeting_strategy/basic/allow_items(),
BB_BASIC_MOB_TIP_REACTING = FALSE,
BB_BASIC_MOB_TIPPER = null,
)
Expand Down Expand Up @@ -81,7 +81,7 @@ Okay, so we have blackboard variables, which are considered by subtrees to plan

//now we know we have a target but should let a hostile subtree plan attacking humans. let's check if it's actually food
if(target in wanted)
controller.queue_behavior(/datum/ai_behavior/basic_melee_attack, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION)
controller.queue_behavior(/datum/ai_behavior/basic_melee_attack, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETING_STRATEGY, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION)
return SUBTREE_RETURN_FINISH_PLANNING //this prevents further subtrees from planning since we want to focus on eating the food
```

Expand All @@ -94,7 +94,7 @@ And one of those behaviors, `basic_melee_attack`. As I have been doing so far, I
//flag tells the AI it needs to have a movement target to work, and since it doesn't have "AI_BEHAVIOR_MOVE_AND_PERFORM", it won't call perform() every 0.6 seconds until it is in melee range. Smart!
behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT

/datum/ai_behavior/basic_melee_attack/setup(datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key)
/datum/ai_behavior/basic_melee_attack/setup(datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key)
. = ..()
//all this is doing in setup is setting the movement target. setup is called once when the behavior is first planned, and returning FALSE can cancel the behavior if something isn't right.

Expand All @@ -107,20 +107,20 @@ And one of those behaviors, `basic_melee_attack`. As I have been doing so far, I
controller.current_movement_target = target

///perform will run every "action_cooldown" deciseconds as long as the conditions are good for it to do so (we set "AI_BEHAVIOR_REQUIRE_MOVEMENT", so it won't perform until in range).
/datum/ai_behavior/basic_melee_attack/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key)
/datum/ai_behavior/basic_melee_attack/perform(seconds_per_tick, datum/ai_controller/controller, target_key, targeting_strategy_key, hiding_location_key)
. = ..()
var/mob/living/basic/basic_mob = controller.pawn
//targetting datum will kill the action if not real anymore
//targeting strategy will kill the action if not real anymore
var/datum/weakref/weak_target = controller.blackboard[target_key]
var/atom/target = weak_target?.resolve()
var/datum/targetting_datum/targetting_datum = controller.blackboard[targetting_datum_key]
var/datum/targeting_strategy/targeting_strategy = controller.blackboard[targeting_strategy_key]

if(!targetting_datum.can_attack(basic_mob, target))
if(!targeting_strategy.can_attack(basic_mob, target))
///We have a target that is no longer valid to attack. Remember that returning doesn't end the behavior, JUST this single performance. So we call "finish_action" with whether it succeeded in doing what it wanted to do (it didn't, so FALSE) and the blackboard keys passed into this behavior.
finish_action(controller, FALSE, target_key)
return //don't forget to end the performance too

var/hiding_target = targetting_datum.find_hidden_mobs(basic_mob, target) //If this is valid, theyre hidden in something!
var/hiding_target = targeting_strategy.find_hidden_mobs(basic_mob, target) //If this is valid, theyre hidden in something!

controller.blackboard[hiding_location_key] = hiding_target

Expand All @@ -131,7 +131,7 @@ And one of those behaviors, `basic_melee_attack`. As I have been doing so far, I
basic_mob.melee_attack(target)

///and so the action has ended. we can now clean up the AI's blackboard based on the success of the action, and the keys passed in.
/datum/ai_behavior/basic_melee_attack/finish_action(datum/ai_controller/controller, succeeded, target_key, targetting_datum_key, hiding_location_key)
/datum/ai_behavior/basic_melee_attack/finish_action(datum/ai_controller/controller, succeeded, target_key, targeting_strategy_key, hiding_location_key)
. = ..()
///if the behavior failed, the target is no longer valid, so we should lose aggro of them. We remove the target_key (which could be anything, it's whatever key was passed into the behavior by the subtree) from the blackboard. Couldn't do THAT with normal variables!
if(!succeeded)
Expand Down
8 changes: 4 additions & 4 deletions code/datums/components/pet_commands/pet_commands_basic.dm
Original file line number Diff line number Diff line change
Expand Up @@ -102,11 +102,11 @@
* # Pet Command: Use ability
* Use an an ability that does not require any targets
*/
/datum/pet_command/untargetted_ability
///untargetted ability we will use
/datum/pet_command/untargeted_ability
///untargeted ability we will use
var/ability_key

/datum/pet_command/untargetted_ability/execute_action(datum/ai_controller/controller)
/datum/pet_command/untargeted_ability/execute_action(datum/ai_controller/controller)
var/datum/action/cooldown/ability = controller.blackboard[ability_key]
if(!ability?.IsAvailable())
return
Expand Down Expand Up @@ -158,7 +158,7 @@
return SUBTREE_RETURN_FINISH_PLANNING

/**
* # Pet Command: Targetted Ability
* # Pet Command: targeted Ability
* Tells a pet to use some kind of ability on the next thing you point at
*/
/datum/pet_command/point_targeting/use_ability
Expand Down
2 changes: 1 addition & 1 deletion code/datums/elements/cuffsnapping.dm
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* cuffsnapping attacks have a wounding bonus between severe and critical+10 wound thresholds. Without some serious wound protecting
* armour this all but guarantees a wound of some sort. The attack is directed specifically at a limb and the limb takes the damage.
*
* Requires the cutter_user to be aiming for either leg zone, which will be targetted specifically. They will than have a 3-second long
* Requires the cutter_user to be aiming for either leg zone, which will be targeted specifically. They will than have a 3-second long
* do_after before executing the attack.
*
* cuffsnapping requires the target to either be on the floor, immobilised or buckled to something. And also to have an appropriate leg.
Expand Down
2 changes: 1 addition & 1 deletion code/datums/elements/kneecapping.dm
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@
* Kneecapping attacks have a wounding bonus between severe and critical+10 wound thresholds. Without some serious wound protecting
* armour this all but guarantees a wound of some sort. The attack is directed specifically at a limb and the limb takes the damage.
*
* Requires the attacker to be aiming for either leg zone, which will be targetted specifically. They will than have a 3-second long
* Requires the attacker to be aiming for either leg zone, which will be targeted specifically. They will than have a 3-second long
* do_after before executing the attack.
*
* Kneecapping requires the target to either be on the floor, immobilised or buckled to something. And also to have an appropriate leg.
Expand Down
4 changes: 2 additions & 2 deletions code/modules/antagonists/malf_ai/malf_ai_modules.dm
Original file line number Diff line number Diff line change
Expand Up @@ -1025,15 +1025,15 @@ GLOBAL_LIST_INIT(malf_modules, subtypesof(/datum/ai_module))
say_name = params["name"]

/datum/ai_module/utility/emag
name = "Targetted Safeties Override"
name = "Targeted Safeties Override"
description = "Allows you to disable the safeties of any machinery on the station, provided you can access it."
cost = 20
power_type = /datum/action/innate/ai/ranged/emag
unlock_text = span_notice("You download an illicit software package from a syndicate database leak and integrate it into your firmware, fighting off a few kernel intrusions along the way.")
unlock_sound = SFX_SPARKS

/datum/action/innate/ai/ranged/emag
name = "Targetted Safeties Override"
name = "Targeted Safeties Override"
desc = "Allows you to effectively emag anything you click on."
button_icon = 'icons/obj/card.dmi'
button_icon_state = "emag"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@
voice = target.voice
voice_filter = target.voice_filter

/// Make the targetted human look like this
/// Make the targeted human look like this
/datum/human_appearance_profile/proc/apply_to(mob/living/carbon/human/target)
target.real_name = name
target.age = age
Expand Down
6 changes: 3 additions & 3 deletions code/modules/fishing/fish/_fish.dm
Original file line number Diff line number Diff line change
Expand Up @@ -441,13 +441,13 @@
//Fish breeding stops if fish count exceeds this.
#define AQUARIUM_MAX_BREEDING_POPULATION 20

/obj/item/fish/proc/ready_to_reproduce(being_targetted = FALSE)
/obj/item/fish/proc/ready_to_reproduce(being_targeted = FALSE)
var/obj/structure/aquarium/aquarium = loc
if(!istype(aquarium))
return FALSE
if(being_targetted && HAS_TRAIT(src, TRAIT_FISH_NO_MATING))
if(being_targeted && HAS_TRAIT(src, TRAIT_FISH_NO_MATING))
return FALSE
if(!being_targetted && length(aquarium.get_fishes()) >= AQUARIUM_MAX_BREEDING_POPULATION)
if(!being_targeted && length(aquarium.get_fishes()) >= AQUARIUM_MAX_BREEDING_POPULATION)
return FALSE
return aquarium.allow_breeding && health >= initial(health) * 0.8 && stable_population > 1 && world.time >= breeding_wait

Expand Down
4 changes: 2 additions & 2 deletions code/modules/mob/living/basic/heretic/raw_prophet.dm
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,7 @@
/// Returns a list of abilities that we should add.
/mob/living/basic/heretic_summon/raw_prophet/proc/get_innate_abilities()
var/list/returnable_list = innate_abilities.Copy()
returnable_list += list(/datum/action/cooldown/spell/pointed/blind/eldritch = BB_TARGETTED_ACTION)
returnable_list += list(/datum/action/cooldown/spell/pointed/blind/eldritch = BB_TARGETED_ACTION)
return returnable_list

/*
Expand Down Expand Up @@ -79,7 +79,7 @@

/mob/living/basic/heretic_summon/raw_prophet/ruins/get_innate_abilities()
var/list/returnable_list = innate_abilities.Copy()
returnable_list += list(/datum/action/cooldown/mob_cooldown/watcher_gaze = BB_TARGETTED_ACTION)
returnable_list += list(/datum/action/cooldown/mob_cooldown/watcher_gaze = BB_TARGETED_ACTION)
return returnable_list

/// Walk and attack people, blind them when we can
Expand Down
2 changes: 1 addition & 1 deletion code/modules/mob/living/basic/heretic/rust_walker.dm
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@

var/static/list/grantable_spells = list(
/datum/action/cooldown/spell/aoe/rust_conversion/small = BB_GENERIC_ACTION,
/datum/action/cooldown/spell/basic_projectile/rust_wave/short = BB_TARGETTED_ACTION,
/datum/action/cooldown/spell/basic_projectile/rust_wave/short = BB_TARGETED_ACTION,
)
grant_actions_by_list(grantable_spells)

Expand Down
4 changes: 2 additions & 2 deletions code/modules/mob/living/basic/jungle/leaper/leaper.dm
Original file line number Diff line number Diff line change
Expand Up @@ -42,8 +42,8 @@
/datum/pet_command/idle,
/datum/pet_command/free,
/datum/pet_command/follow,
/datum/pet_command/untargetted_ability/blood_rain,
/datum/pet_command/untargetted_ability/summon_toad,
/datum/pet_command/untargeted_ability/blood_rain,
/datum/pet_command/untargeted_ability/summon_toad,
/datum/pet_command/point_targeting/attack,
/datum/pet_command/point_targeting/use_ability/flop,
/datum/pet_command/point_targeting/use_ability/bubble,
Expand Down
4 changes: 2 additions & 2 deletions code/modules/mob/living/basic/jungle/leaper/leaper_ai.dm
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
speech_commands = list("bubble", "shoot")
pet_ability_key = BB_LEAPER_BUBBLE

/datum/pet_command/untargetted_ability/blood_rain
/datum/pet_command/untargeted_ability/blood_rain
command_name = "Blood Rain"
command_desc = "Let it rain poisonous blood!"
radial_icon = 'icons/effects/effects.dmi'
Expand All @@ -64,7 +64,7 @@
ability_key = BB_LEAPER_VOLLEY


/datum/pet_command/untargetted_ability/summon_toad
/datum/pet_command/untargeted_ability/summon_toad
command_name = "Summon Toads"
command_desc = "Summon crazy suicide frogs!"
radial_icon = 'icons/mob/simple/animal.dmi'
Expand Down
4 changes: 2 additions & 2 deletions code/modules/mob/living/basic/jungle/venus_human_trap.dm
Original file line number Diff line number Diff line change
Expand Up @@ -175,14 +175,14 @@
. = ..()
AddElement(/datum/element/lifesteal, 5)
var/static/list/innate_actions = list(
/datum/action/cooldown/vine_tangle = BB_TARGETTED_ACTION,
/datum/action/cooldown/vine_tangle = BB_TARGETED_ACTION,
)
grant_actions_by_list(innate_actions)

/mob/living/basic/venus_human_trap/RangedAttack(atom/victim)
if(!combat_mode)
return
var/datum/action/cooldown/mob_cooldown/tangle_ability = ai_controller.blackboard[BB_TARGETTED_ACTION]
var/datum/action/cooldown/mob_cooldown/tangle_ability = ai_controller.blackboard[BB_TARGETED_ACTION]
if(!istype(tangle_ability))
return
tangle_ability.Trigger(target = victim)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
AddElement(/datum/element/footstep, FOOTSTEP_MOB_CLAW)
beam = new(src)
beam.Grant(src)
ai_controller.set_blackboard_key(BB_TARGETTED_ACTION, beam)
ai_controller.set_blackboard_key(BB_TARGETED_ACTION, beam)

/mob/living/basic/mining/brimdemon/RangedAttack(atom/target, modifiers)
beam.Trigger(target = target)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@
if (!succeeded)
return
var/mob/living/target = controller.blackboard[target_key]
var/datum/action/cooldown/ability = controller.blackboard[BB_TARGETTED_ACTION]
var/datum/action/cooldown/ability = controller.blackboard[BB_TARGETED_ACTION]
if(!ability?.IsAvailable())
return
ability.InterceptClickOn(caller = controller.pawn, target = target)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
/// Place some grappling tentacles underfoot
/datum/action/cooldown/mob_cooldown/goliath_tentacles
name = "Unleash Tentacles"
desc = "Unleash burrowed tentacles at a targetted location, grappling targets after a delay."
desc = "Unleash burrowed tentacles at a targeted location, grappling targets after a delay."
button_icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi'
button_icon_state = "goliath_tentacle_wiggle"
background_icon_state = "bg_demon"
Expand Down Expand Up @@ -59,7 +59,7 @@
/// Summon a line of tentacles towards the target
/datum/action/cooldown/mob_cooldown/tentacle_grasp
name = "Tentacle Grasp"
desc = "Unleash burrowed tentacles in a line towards a targetted location, grappling targets after a delay."
desc = "Unleash burrowed tentacles in a line towards a targeted location, grappling targets after a delay."
button_icon = 'icons/mob/simple/lavaland/lavaland_monsters.dmi'
button_icon_state = "goliath_tentacle_wiggle"
background_icon_state = "bg_demon"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -36,7 +36,7 @@
AddComponent(/datum/component/appearance_on_aggro, aggro_state = "hivelord_alert")
spawn_brood = new(src)
spawn_brood.Grant(src)
ai_controller.set_blackboard_key(BB_TARGETTED_ACTION, spawn_brood)
ai_controller.set_blackboard_key(BB_TARGETED_ACTION, spawn_brood)

/mob/living/basic/mining/hivelord/Destroy()
QDEL_NULL(spawn_brood)
Expand Down
2 changes: 1 addition & 1 deletion code/modules/mob/living/basic/lavaland/legion/legion.dm
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@
var/datum/action/cooldown/mob_cooldown/skull_launcher/skull_launcher = new(src)
skull_launcher.Grant(src)
skull_launcher.spawn_type = brood_type
ai_controller.set_blackboard_key(BB_TARGETTED_ACTION, skull_launcher)
ai_controller.set_blackboard_key(BB_TARGETED_ACTION, skull_launcher)

/// Create what we want to drop on death, in proc form so we can always return a static list
/mob/living/basic/mining/legion/proc/get_loot_list()
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@
return
return ..()

/// Turn the targetted mob into one of us
/// Turn the targeted mob into one of us
/mob/living/basic/legion_brood/proc/infest(mob/living/target)
visible_message(span_warning("[name] burrows into the flesh of [target]!"))
var/spawn_type = get_legion_type(target)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
)
charge = new(src)
charge.Grant(src)
ai_controller.set_blackboard_key(BB_TARGETTED_ACTION, charge)
ai_controller.set_blackboard_key(BB_TARGETED_ACTION, charge)

/mob/living/basic/mining/lobstrosity/Destroy()
QDEL_NULL(charge)
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@
flee_behaviour = /datum/ai_behavior/run_away_from_target/lobster

/datum/ai_planning_subtree/flee_target/lobster/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick)
var/datum/action/cooldown/using_action = controller.blackboard[BB_TARGETTED_ACTION]
var/datum/action/cooldown/using_action = controller.blackboard[BB_TARGETED_ACTION]
if (using_action?.IsAvailable())
return
return ..()
Expand Down
2 changes: 1 addition & 1 deletion code/modules/mob/living/carbon/human/human_defense.dm
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
var/obj/item/bodypart/affecting = get_bodypart(check_zone(def_zone))
if(affecting)
return check_armor(affecting, type)
//If a specific bodypart is targetted, check how that bodypart is protected and return the value.
//If a specific bodypart is targeted, check how that bodypart is protected and return the value.

//If you don't specify a bodypart, it checks ALL your bodyparts for protection, and averages out the values
for(var/X in bodyparts)
Expand Down
2 changes: 1 addition & 1 deletion code/modules/mob/living/living.dm
Original file line number Diff line number Diff line change
Expand Up @@ -2562,7 +2562,7 @@ GLOBAL_LIST_EMPTY(fire_appearances)
/mob/living/proc/compare_sentience_type(compare_type)
return FALSE

/// Proc called when targetted by a lazarus injector
/// Proc called when TARGETED by a lazarus injector
/mob/living/proc/lazarus_revive(mob/living/reviver, malfunctioning)
revive(HEAL_ALL)
befriend(reviver)
Expand Down
Loading
Loading