Whitespace Standardization [MDB IGNORE] (#15748)

* Update settings

* Whitespace changes

* Comment out merger hooks in gitattributes

Corrupt maps would have to be resolved in repo before hooks could be updated

* Revert "Whitespace changes"

This reverts commit afbdd1d844.

* Whitespace again minus example

* Gitignore example changelog

* Restore changelog merge setting

* Keep older dmi hook attribute until hooks can be updated

* update vscode settings too

* Renormalize remaining

* Revert "Gitignore example changelog"

This reverts commit de22ad375d.

* Attempt to normalize example.yml (and another file I guess)

* Try again
This commit is contained in:
Drathek
2024-02-20 02:28:51 -08:00
committed by GitHub
parent 3b61f677b3
commit 7c8bb85de3
1175 changed files with 818171 additions and 818145 deletions
+104 -104
View File
@@ -1,104 +1,104 @@
// Handles AI while stunned or otherwise disabled.
/datum/ai_holder
var/respect_confusion = TRUE // If false, the mob won't wander around recklessly.
// If our holder is able to do anything.
/datum/ai_holder/proc/can_act()
if(!holder) // Holder missing.
manage_processing(0)
return FALSE
if(holder.stat) // Dead or unconscious.
ai_log("can_act() : Stat was non-zero ([holder.stat]).", AI_LOG_TRACE)
return FALSE
if(holder.incapacitated(INCAPACITATION_DISABLED)) // Stunned in some form.
ai_log("can_act() : Incapacited.", AI_LOG_TRACE)
return FALSE
if(holder.instasis()) // In a stasis field.
ai_log("can_act() : In a stasis field.", AI_LOG_TRACE)
return FALSE
if(!belly_attack)
if(isbelly(holder.loc))
return FALSE
return TRUE
// Test if we should switch to STANCE_DISABLE.
// Currently tests for death, stuns, and confusion.
/datum/ai_holder/proc/is_disabled()
if(!can_act())
return TRUE
if(is_confused())
return TRUE
return FALSE
/datum/ai_holder/proc/is_confused()
return holder.confused > 0 && respect_confusion
// Called by the main loop.
/datum/ai_holder/proc/handle_disabled()
if(!can_act())
return // Just sit there and take it.
else if(is_confused())
dangerous_wander() // Let's bump into allies and hit them.
// Similar to normal wander, but will walk into tiles that are harmful, and attack anything they bump into, including allies.
// Occurs when confused.
/datum/ai_holder/proc/dangerous_wander()
ai_log("dangerous_wander() : Entered.", AI_LOG_DEBUG)
if(isturf(holder.loc) && can_act())
// Test if we should refrain from falling/attacking allies, if we're smart enough to realize that.
if(intelligence_level > AI_NORMAL)
var/unsafe = FALSE
tile_test:
for(var/dir_tested in cardinal)
var/turf/turf_tested = get_step(holder, dir_tested)
// Look for unsafe tiles.
if(!turf_tested.is_safe_to_enter(holder))
unsafe = TRUE
break
// Look for allies.
for(var/mob/living/L in turf_tested)
if(holder.IIsAlly(L))
unsafe = TRUE
break tile_test
if(unsafe)
ai_log("dangerous_wander() : Staying still due to risk of harm to self or allies.", AI_LOG_TRACE)
return // Just stay still.
var/moving_to = 0
moving_to = pick(cardinal)
var/turf/T = get_step(holder, moving_to)
var/mob/living/L = locate() in T
if(L)
// Attack whoever's on the tile. Even if it's an ally.
ai_log("dangerous_wander() : Going to confuse-attack [L].", AI_LOG_TRACE)
melee_attack(L)
else
// Move to the tile. Even if it's unsafe.
ai_log("dangerous_wander() : Going to confuse-walk to [T] ([T.x],[T.y],[T.z]).", AI_LOG_TRACE)
holder.IMove(T, safety = FALSE)
ai_log("dangerous_wander() : Exited.", AI_LOG_DEBUG)
/*
// Wanders randomly in cardinal directions.
/datum/ai_holder/proc/handle_wander_movement()
ai_log("handle_wander_movement() : Entered.", AI_LOG_DEBUG)
if(isturf(holder.loc) && can_act())
wander_delay--
if(wander_delay <= 0)
if(!wander_when_pulled && holder.pulledby)
ai_log("handle_wander_movement() : Being pulled and cannot wander. Exiting.", AI_LOG_DEBUG)
return
var/moving_to = 0 // Apparently this is required or it always picks 4, according to the previous developer for simplemob AI.
moving_to = pick(cardinal)
holder.set_dir(moving_to)
holder.IMove(get_step(holder,moving_to))
wander_delay = base_wander_delay
ai_log("handle_wander_movement() : Exited.", AI_LOG_DEBUG)
*/
// Handles AI while stunned or otherwise disabled.
/datum/ai_holder
var/respect_confusion = TRUE // If false, the mob won't wander around recklessly.
// If our holder is able to do anything.
/datum/ai_holder/proc/can_act()
if(!holder) // Holder missing.
manage_processing(0)
return FALSE
if(holder.stat) // Dead or unconscious.
ai_log("can_act() : Stat was non-zero ([holder.stat]).", AI_LOG_TRACE)
return FALSE
if(holder.incapacitated(INCAPACITATION_DISABLED)) // Stunned in some form.
ai_log("can_act() : Incapacited.", AI_LOG_TRACE)
return FALSE
if(holder.instasis()) // In a stasis field.
ai_log("can_act() : In a stasis field.", AI_LOG_TRACE)
return FALSE
if(!belly_attack)
if(isbelly(holder.loc))
return FALSE
return TRUE
// Test if we should switch to STANCE_DISABLE.
// Currently tests for death, stuns, and confusion.
/datum/ai_holder/proc/is_disabled()
if(!can_act())
return TRUE
if(is_confused())
return TRUE
return FALSE
/datum/ai_holder/proc/is_confused()
return holder.confused > 0 && respect_confusion
// Called by the main loop.
/datum/ai_holder/proc/handle_disabled()
if(!can_act())
return // Just sit there and take it.
else if(is_confused())
dangerous_wander() // Let's bump into allies and hit them.
// Similar to normal wander, but will walk into tiles that are harmful, and attack anything they bump into, including allies.
// Occurs when confused.
/datum/ai_holder/proc/dangerous_wander()
ai_log("dangerous_wander() : Entered.", AI_LOG_DEBUG)
if(isturf(holder.loc) && can_act())
// Test if we should refrain from falling/attacking allies, if we're smart enough to realize that.
if(intelligence_level > AI_NORMAL)
var/unsafe = FALSE
tile_test:
for(var/dir_tested in cardinal)
var/turf/turf_tested = get_step(holder, dir_tested)
// Look for unsafe tiles.
if(!turf_tested.is_safe_to_enter(holder))
unsafe = TRUE
break
// Look for allies.
for(var/mob/living/L in turf_tested)
if(holder.IIsAlly(L))
unsafe = TRUE
break tile_test
if(unsafe)
ai_log("dangerous_wander() : Staying still due to risk of harm to self or allies.", AI_LOG_TRACE)
return // Just stay still.
var/moving_to = 0
moving_to = pick(cardinal)
var/turf/T = get_step(holder, moving_to)
var/mob/living/L = locate() in T
if(L)
// Attack whoever's on the tile. Even if it's an ally.
ai_log("dangerous_wander() : Going to confuse-attack [L].", AI_LOG_TRACE)
melee_attack(L)
else
// Move to the tile. Even if it's unsafe.
ai_log("dangerous_wander() : Going to confuse-walk to [T] ([T.x],[T.y],[T.z]).", AI_LOG_TRACE)
holder.IMove(T, safety = FALSE)
ai_log("dangerous_wander() : Exited.", AI_LOG_DEBUG)
/*
// Wanders randomly in cardinal directions.
/datum/ai_holder/proc/handle_wander_movement()
ai_log("handle_wander_movement() : Entered.", AI_LOG_DEBUG)
if(isturf(holder.loc) && can_act())
wander_delay--
if(wander_delay <= 0)
if(!wander_when_pulled && holder.pulledby)
ai_log("handle_wander_movement() : Being pulled and cannot wander. Exiting.", AI_LOG_DEBUG)
return
var/moving_to = 0 // Apparently this is required or it always picks 4, according to the previous developer for simplemob AI.
moving_to = pick(cardinal)
holder.set_dir(moving_to)
holder.IMove(get_step(holder,moving_to))
wander_delay = base_wander_delay
ai_log("handle_wander_movement() : Exited.", AI_LOG_DEBUG)
*/
@@ -1,316 +1,316 @@
// Specialized AI for slime simplemobs.
// Unlike the parent AI code, this will probably break a lot of things if you put it on something that isn't /mob/living/simple_mob/slime/xenobio
/datum/ai_holder/simple_mob/xenobio_slime
hostile = TRUE
cooperative = TRUE
firing_lanes = TRUE
mauling = TRUE // They need it to get the most out of monkeys.
var/rabid = FALSE // Will attack regardless of discipline.
var/discipline = 0 // Beating slimes makes them less likely to lash out. In theory.
var/resentment = 0 // 'Unjustified' beatings make this go up, and makes it more likely for abused slimes to go rabid.
var/obedience = 0 // Conversely, 'justified' beatings make this go up, and makes discipline decay slower, potentially making it not decay at all.
var/always_stun = FALSE // If true, the slime will elect to attempt to permastun the target.
var/last_discipline_decay = null // Last world.time discipline was reduced from decay.
var/discipline_decay_time = 5 SECONDS // Earliest that one discipline can decay.
var/list/grudges = list() // List of Prometheans who are jerks.
/datum/ai_holder/simple_mob/xenobio_slime/Destroy()
grudges.Cut()
..()
/datum/ai_holder/simple_mob/xenobio_slime/sapphire
always_stun = TRUE // They know that stuns are godly.
intelligence_level = AI_SMART // Also knows not to walk while confused if it risks death.
/datum/ai_holder/simple_mob/xenobio_slime/light_pink
discipline = 10
obedience = 10
/datum/ai_holder/simple_mob/xenobio_slime/passive/New() // For Kendrick.
..()
pacify()
/datum/ai_holder/simple_mob/xenobio_slime/New()
..()
ASSERT(istype(holder, /mob/living/simple_mob/slime/xenobio))
// Checks if disciplining the slime would be 'justified' right now.
/datum/ai_holder/simple_mob/xenobio_slime/proc/is_justified_to_discipline()
ai_log("xenobio_slime/is_justified_to_discipline() : Entered.", AI_LOG_TRACE)
if(!can_act())
ai_log("xenobio_slime/is_justified_to_discipline() : Judged to be unjustified because we cannot act. Exiting.", AI_LOG_DEBUG)
return FALSE // The slime considers it abuse if they get stunned while already stunned.
if(rabid)
ai_log("xenobio_slime/is_justified_to_discipline() : Judged to be justified because we're rabid. Exiting.", AI_LOG_TRACE)
return TRUE
if(target && can_attack(target))
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(istype(H.species, /datum/species/monkey))
ai_log("xenobio_slime/is_justified_to_discipline() : Judged to be unjustified because we're targeting a monkey. Exiting.", AI_LOG_DEBUG)
return FALSE // Attacking monkeys is okay.
ai_log("xenobio_slime/is_justified_to_discipline() : Judged to be justified because we are targeting a non-monkey. Exiting.", AI_LOG_TRACE)
return TRUE // Otherwise attacking other things is bad.
ai_log("xenobio_slime/is_justified_to_discipline() : Judged to be unjustified because we are not targeting anything. Exiting.", AI_LOG_DEBUG)
return FALSE // Not attacking anything.
/datum/ai_holder/simple_mob/xenobio_slime/proc/can_command(mob/living/commander)
if(rabid)
return FALSE
if(!hostile)
return SLIME_COMMAND_OBEY
// if(commander in friends)
// return SLIME_COMMAND_FRIEND
if(holder.IIsAlly(commander))
return SLIME_COMMAND_FACTION
if(discipline > resentment && obedience >= 5)
return SLIME_COMMAND_OBEY
return FALSE
/datum/ai_holder/simple_mob/xenobio_slime/proc/adjust_discipline(amount, silent)
var/mob/living/simple_mob/slime/xenobio/my_slime = holder
if(amount > 0)
if(rabid)
return
if(my_slime.untamable)
holder.say("Grrr...")
holder.add_modifier(/datum/modifier/berserk, 30 SECONDS)
enrage()
var/justified = my_slime.is_justified_to_discipline() // This will also consider the AI-side of that proc.
remove_target() // Stop attacking.
if(justified)
obedience++
if(!silent)
holder.say(pick("Fine...", "Okay...", "Sorry...", "I yield...", "Mercy..."))
else
if(prob(resentment * 20))
enrage()
holder.say(pick("Evil...", "Kill...", "Tyrant..."))
else
if(!silent)
holder.say(pick("Why...?", "I don't understand...?", "Cruel...", "Stop...", "Nooo..."))
resentment++ // Done after check so first time will never enrage.
discipline = between(0, discipline + amount, 10)
my_slime.update_mood()
/datum/ai_holder/simple_mob/xenobio_slime/handle_special_strategical()
discipline_decay()
evolve_and_reproduce()
/datum/ai_holder/simple_mob/xenobio_slime/request_help()
if(target)
if(istype(target, /mob/living/simple_mob/slime/xenobio)) //Don't call reinforcements for internal disputes
return
if(istype(target, /mob/living/carbon/human))
var/mob/living/carbon/human/H = target
if(istype(H.species, /datum/species/monkey)) //Or for food
return
..()
// Handles decay of discipline.
/datum/ai_holder/simple_mob/xenobio_slime/proc/discipline_decay()
if(discipline > 0 && last_discipline_decay + discipline_decay_time < world.time)
if(!prob(75 + (obedience * 5)))
adjust_discipline(-1)
last_discipline_decay = world.time
/datum/ai_holder/simple_mob/xenobio_slime/handle_special_tactic()
evolve_and_reproduce()
/datum/ai_holder/simple_mob/xenobio_slime/handle_stance_tactical()
if(!istype(holder) || QDELETED(holder))
qdel(src)
return
..()
// Hit the correct verbs to keep the slime species going.
/datum/ai_holder/simple_mob/xenobio_slime/proc/evolve_and_reproduce()
var/mob/living/simple_mob/slime/xenobio/my_slime = holder
if(my_slime.amount_grown >= 10)
// Press the correct verb when we can.
if(my_slime.is_adult)
my_slime.reproduce() // Splits into four new baby slimes.
else
my_slime.evolve() // Turns our holder into an adult slime.
// Called when pushed too far (or a red slime core was used).
/datum/ai_holder/simple_mob/xenobio_slime/proc/enrage()
var/mob/living/simple_mob/slime/xenobio/my_slime = holder
if(my_slime.harmless)
return
rabid = TRUE
my_slime.update_mood()
my_slime.visible_message(span("danger", "\The [my_slime] enrages!"))
// Called to relax from being rabid (when blue slime core was used).
/datum/ai_holder/simple_mob/xenobio_slime/proc/relax()
var/mob/living/simple_mob/slime/xenobio/my_slime = holder
if(my_slime.harmless)
return
if(rabid)
rabid = FALSE
my_slime.update_mood()
my_slime.visible_message(span("danger", "\The [my_slime] calms down."))
// Called when using a pacification agent (or it's Kendrick being initalized).
/datum/ai_holder/simple_mob/xenobio_slime/proc/pacify()
remove_target() // So it stops trying to kill them.
rabid = FALSE
hostile = FALSE
retaliate = FALSE
cooperative = FALSE
holder.a_intent = I_HELP
// The holder's attack changes based on intent. This lets the AI choose what effect is desired.
/datum/ai_holder/simple_mob/xenobio_slime/pre_melee_attack(atom/A)
if(istype(A, /mob/living))
var/mob/living/L = A
var/mob/living/simple_mob/slime/xenobio/my_slime = holder
if( (!L.lying && prob(30 + (my_slime.power_charge * 7) ) || (!L.lying && always_stun) ))
my_slime.a_intent = I_DISARM // Stun them first.
else if(my_slime.can_consume(L) && L.lying)
my_slime.a_intent = I_GRAB // Then eat them.
else
my_slime.a_intent = I_HURT // Otherwise robust them.
/datum/ai_holder/simple_mob/xenobio_slime/closest_distance(atom/movable/AM)
if(istype(AM, /mob/living))
var/mob/living/L = AM
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(istype(H.species, /datum/species/monkey))
return 1 // Otherwise ranged slimes will eat a lot less often.
if(L.stat >= UNCONSCIOUS)
return 1 // Melee (eat) the target if dead/dying, don't shoot it.
return ..()
/datum/ai_holder/simple_mob/xenobio_slime/can_attack(atom/movable/AM, var/vision_required = TRUE)
. = ..()
if(.) // Do some additional checks because we have Special Code(tm).
if(ishuman(AM))
var/mob/living/carbon/human/H = AM
if(istype(H.species, /datum/species/monkey)) // istype() is so they'll eat the alien monkeys too.
return TRUE // Monkeys are always food (sorry Pun Pun).
else if(H.species && H.species.name == SPECIES_PROMETHEAN) // Prometheans are always our friends.
if(!(H in grudges)) // Unless they're an ass.
return FALSE
if(discipline && !rabid)
holder.a_intent = I_HELP
return FALSE // We're a good slime.
/datum/ai_holder/simple_mob/xenobio_slime/react_to_attack(atom/movable/attacker, ignore_timers = FALSE)
. = ..(attacker)
if(ishuman(attacker))
var/mob/living/carbon/human/H = attacker
if(H.species && H.species.name == SPECIES_PROMETHEAN) // They're a jerk.
grudges |= H
// Commands, reactions, etc
/datum/ai_holder/simple_mob/xenobio_slime/on_hear_say(mob/living/speaker, message)
ai_log("xenobio_slime/on_hear_say([speaker], [message]) : Entered.", AI_LOG_DEBUG)
var/mob/living/simple_mob/slime/xenobio/my_slime = holder
if((findtext(message, num2text(my_slime.number)) || findtext(message, my_slime.name) || findtext(message, "slimes"))) // Talking to us.
// First, make sure it's actually a player saying something and not an AI, or else we risk infinite loops.
if(!speaker.client)
return
// Are all slimes being referred to?
// var/mass_order = FALSE
// if(findtext(message, "slimes"))
// mass_order = TRUE
// Say hello back.
if(findtext(message, "hello") || findtext(message, "hi") || findtext(message, "greetings"))
delayed_say(pick("Hello...", "Hi..."), speaker)
// Follow request.
if(findtext(message, "follow") || findtext(message, "come with me"))
if(!can_command(speaker))
delayed_say(pick("No...", "I won't follow..."), speaker)
return
delayed_say("Yes... I follow \the [speaker]...", speaker)
set_follow(speaker)
// Squish request.
if(findtext(message , "squish"))
if(!can_command(speaker))
delayed_say("No...", speaker)
return
spawn(rand(1 SECOND, 2 SECONDS))
if(!src || !holder || !can_act()) // We might've died/got deleted/etc in the meantime.
return
my_slime.squish()
// Stop request.
if(findtext(message, "stop") || findtext(message, "halt") || findtext(message, "cease"))
if(my_slime.victim) // We're being asked to stop eatting someone.
if(!can_command(speaker) || !is_justified_to_discipline())
delayed_say("No...", speaker)
return
else
delayed_say("Fine...", speaker)
adjust_discipline(1, TRUE)
my_slime.stop_consumption()
if(target) // We're being asked to stop chasing someone.
if(!can_command(speaker) || !is_justified_to_discipline())
delayed_say("No...", speaker)
return
else
delayed_say("Fine...", speaker)
adjust_discipline(1, TRUE) // This must come before losing the target or it will be unjustified.
remove_target()
if(leader) // We're being asked to stop following someone.
if(can_command(speaker) == SLIME_COMMAND_FRIEND || leader == speaker)
delayed_say("Yes... I'll stop...", speaker)
lose_follow()
else
delayed_say("No... I'll keep following \the [leader]...", speaker)
/* // Commented out since its mostly useless now due to slimes refusing to attack if it would make them naughty.
// Murder request
if(findtext(message, "harm") || findtext(message, "attack") || findtext(message, "kill") || findtext(message, "murder") || findtext(message, "eat") || findtext(message, "consume") || findtext(message, "absorb"))
if(can_command(speaker) < SLIME_COMMAND_FACTION)
delayed_say("No...", speaker)
return
for(var/mob/living/L in view(7, my_slime) - list(my_slime, speaker))
if(L == src)
continue // Don't target ourselves.
var/list/valid_names = splittext(L.name, " ") // Should output list("John", "Doe") as an example.
for(var/line in valid_names) // Check each part of someone's name.
if(findtext(message, lowertext(line))) // If part of someone's name is in the command, the slime targets them if allowed to.
if(!(mass_order && line == "slime")) //don't think random other slimes are target
if(can_attack(L))
delayed_say("Okay... I attack \the [L]...", speaker)
give_target(L)
return
else
delayed_say("No... I won't attack \the [L].", speaker)
return
// If we're here, it couldn't find anyone with that name.
delayed_say("No... I don't know who to attack...", speaker)
*/
ai_log("xenobio_slime/on_hear_say() : Exited.", AI_LOG_DEBUG)
/datum/ai_holder/simple_mob/xenobio_slime/can_violently_breakthrough()
if(discipline && !rabid) // Good slimes don't shatter the windows because their buddy in an adjacent cell decided to piss off Slimesky.
return FALSE
return ..()
// Specialized AI for slime simplemobs.
// Unlike the parent AI code, this will probably break a lot of things if you put it on something that isn't /mob/living/simple_mob/slime/xenobio
/datum/ai_holder/simple_mob/xenobio_slime
hostile = TRUE
cooperative = TRUE
firing_lanes = TRUE
mauling = TRUE // They need it to get the most out of monkeys.
var/rabid = FALSE // Will attack regardless of discipline.
var/discipline = 0 // Beating slimes makes them less likely to lash out. In theory.
var/resentment = 0 // 'Unjustified' beatings make this go up, and makes it more likely for abused slimes to go rabid.
var/obedience = 0 // Conversely, 'justified' beatings make this go up, and makes discipline decay slower, potentially making it not decay at all.
var/always_stun = FALSE // If true, the slime will elect to attempt to permastun the target.
var/last_discipline_decay = null // Last world.time discipline was reduced from decay.
var/discipline_decay_time = 5 SECONDS // Earliest that one discipline can decay.
var/list/grudges = list() // List of Prometheans who are jerks.
/datum/ai_holder/simple_mob/xenobio_slime/Destroy()
grudges.Cut()
..()
/datum/ai_holder/simple_mob/xenobio_slime/sapphire
always_stun = TRUE // They know that stuns are godly.
intelligence_level = AI_SMART // Also knows not to walk while confused if it risks death.
/datum/ai_holder/simple_mob/xenobio_slime/light_pink
discipline = 10
obedience = 10
/datum/ai_holder/simple_mob/xenobio_slime/passive/New() // For Kendrick.
..()
pacify()
/datum/ai_holder/simple_mob/xenobio_slime/New()
..()
ASSERT(istype(holder, /mob/living/simple_mob/slime/xenobio))
// Checks if disciplining the slime would be 'justified' right now.
/datum/ai_holder/simple_mob/xenobio_slime/proc/is_justified_to_discipline()
ai_log("xenobio_slime/is_justified_to_discipline() : Entered.", AI_LOG_TRACE)
if(!can_act())
ai_log("xenobio_slime/is_justified_to_discipline() : Judged to be unjustified because we cannot act. Exiting.", AI_LOG_DEBUG)
return FALSE // The slime considers it abuse if they get stunned while already stunned.
if(rabid)
ai_log("xenobio_slime/is_justified_to_discipline() : Judged to be justified because we're rabid. Exiting.", AI_LOG_TRACE)
return TRUE
if(target && can_attack(target))
if(ishuman(target))
var/mob/living/carbon/human/H = target
if(istype(H.species, /datum/species/monkey))
ai_log("xenobio_slime/is_justified_to_discipline() : Judged to be unjustified because we're targeting a monkey. Exiting.", AI_LOG_DEBUG)
return FALSE // Attacking monkeys is okay.
ai_log("xenobio_slime/is_justified_to_discipline() : Judged to be justified because we are targeting a non-monkey. Exiting.", AI_LOG_TRACE)
return TRUE // Otherwise attacking other things is bad.
ai_log("xenobio_slime/is_justified_to_discipline() : Judged to be unjustified because we are not targeting anything. Exiting.", AI_LOG_DEBUG)
return FALSE // Not attacking anything.
/datum/ai_holder/simple_mob/xenobio_slime/proc/can_command(mob/living/commander)
if(rabid)
return FALSE
if(!hostile)
return SLIME_COMMAND_OBEY
// if(commander in friends)
// return SLIME_COMMAND_FRIEND
if(holder.IIsAlly(commander))
return SLIME_COMMAND_FACTION
if(discipline > resentment && obedience >= 5)
return SLIME_COMMAND_OBEY
return FALSE
/datum/ai_holder/simple_mob/xenobio_slime/proc/adjust_discipline(amount, silent)
var/mob/living/simple_mob/slime/xenobio/my_slime = holder
if(amount > 0)
if(rabid)
return
if(my_slime.untamable)
holder.say("Grrr...")
holder.add_modifier(/datum/modifier/berserk, 30 SECONDS)
enrage()
var/justified = my_slime.is_justified_to_discipline() // This will also consider the AI-side of that proc.
remove_target() // Stop attacking.
if(justified)
obedience++
if(!silent)
holder.say(pick("Fine...", "Okay...", "Sorry...", "I yield...", "Mercy..."))
else
if(prob(resentment * 20))
enrage()
holder.say(pick("Evil...", "Kill...", "Tyrant..."))
else
if(!silent)
holder.say(pick("Why...?", "I don't understand...?", "Cruel...", "Stop...", "Nooo..."))
resentment++ // Done after check so first time will never enrage.
discipline = between(0, discipline + amount, 10)
my_slime.update_mood()
/datum/ai_holder/simple_mob/xenobio_slime/handle_special_strategical()
discipline_decay()
evolve_and_reproduce()
/datum/ai_holder/simple_mob/xenobio_slime/request_help()
if(target)
if(istype(target, /mob/living/simple_mob/slime/xenobio)) //Don't call reinforcements for internal disputes
return
if(istype(target, /mob/living/carbon/human))
var/mob/living/carbon/human/H = target
if(istype(H.species, /datum/species/monkey)) //Or for food
return
..()
// Handles decay of discipline.
/datum/ai_holder/simple_mob/xenobio_slime/proc/discipline_decay()
if(discipline > 0 && last_discipline_decay + discipline_decay_time < world.time)
if(!prob(75 + (obedience * 5)))
adjust_discipline(-1)
last_discipline_decay = world.time
/datum/ai_holder/simple_mob/xenobio_slime/handle_special_tactic()
evolve_and_reproduce()
/datum/ai_holder/simple_mob/xenobio_slime/handle_stance_tactical()
if(!istype(holder) || QDELETED(holder))
qdel(src)
return
..()
// Hit the correct verbs to keep the slime species going.
/datum/ai_holder/simple_mob/xenobio_slime/proc/evolve_and_reproduce()
var/mob/living/simple_mob/slime/xenobio/my_slime = holder
if(my_slime.amount_grown >= 10)
// Press the correct verb when we can.
if(my_slime.is_adult)
my_slime.reproduce() // Splits into four new baby slimes.
else
my_slime.evolve() // Turns our holder into an adult slime.
// Called when pushed too far (or a red slime core was used).
/datum/ai_holder/simple_mob/xenobio_slime/proc/enrage()
var/mob/living/simple_mob/slime/xenobio/my_slime = holder
if(my_slime.harmless)
return
rabid = TRUE
my_slime.update_mood()
my_slime.visible_message(span("danger", "\The [my_slime] enrages!"))
// Called to relax from being rabid (when blue slime core was used).
/datum/ai_holder/simple_mob/xenobio_slime/proc/relax()
var/mob/living/simple_mob/slime/xenobio/my_slime = holder
if(my_slime.harmless)
return
if(rabid)
rabid = FALSE
my_slime.update_mood()
my_slime.visible_message(span("danger", "\The [my_slime] calms down."))
// Called when using a pacification agent (or it's Kendrick being initalized).
/datum/ai_holder/simple_mob/xenobio_slime/proc/pacify()
remove_target() // So it stops trying to kill them.
rabid = FALSE
hostile = FALSE
retaliate = FALSE
cooperative = FALSE
holder.a_intent = I_HELP
// The holder's attack changes based on intent. This lets the AI choose what effect is desired.
/datum/ai_holder/simple_mob/xenobio_slime/pre_melee_attack(atom/A)
if(istype(A, /mob/living))
var/mob/living/L = A
var/mob/living/simple_mob/slime/xenobio/my_slime = holder
if( (!L.lying && prob(30 + (my_slime.power_charge * 7) ) || (!L.lying && always_stun) ))
my_slime.a_intent = I_DISARM // Stun them first.
else if(my_slime.can_consume(L) && L.lying)
my_slime.a_intent = I_GRAB // Then eat them.
else
my_slime.a_intent = I_HURT // Otherwise robust them.
/datum/ai_holder/simple_mob/xenobio_slime/closest_distance(atom/movable/AM)
if(istype(AM, /mob/living))
var/mob/living/L = AM
if(ishuman(L))
var/mob/living/carbon/human/H = L
if(istype(H.species, /datum/species/monkey))
return 1 // Otherwise ranged slimes will eat a lot less often.
if(L.stat >= UNCONSCIOUS)
return 1 // Melee (eat) the target if dead/dying, don't shoot it.
return ..()
/datum/ai_holder/simple_mob/xenobio_slime/can_attack(atom/movable/AM, var/vision_required = TRUE)
. = ..()
if(.) // Do some additional checks because we have Special Code(tm).
if(ishuman(AM))
var/mob/living/carbon/human/H = AM
if(istype(H.species, /datum/species/monkey)) // istype() is so they'll eat the alien monkeys too.
return TRUE // Monkeys are always food (sorry Pun Pun).
else if(H.species && H.species.name == SPECIES_PROMETHEAN) // Prometheans are always our friends.
if(!(H in grudges)) // Unless they're an ass.
return FALSE
if(discipline && !rabid)
holder.a_intent = I_HELP
return FALSE // We're a good slime.
/datum/ai_holder/simple_mob/xenobio_slime/react_to_attack(atom/movable/attacker, ignore_timers = FALSE)
. = ..(attacker)
if(ishuman(attacker))
var/mob/living/carbon/human/H = attacker
if(H.species && H.species.name == SPECIES_PROMETHEAN) // They're a jerk.
grudges |= H
// Commands, reactions, etc
/datum/ai_holder/simple_mob/xenobio_slime/on_hear_say(mob/living/speaker, message)
ai_log("xenobio_slime/on_hear_say([speaker], [message]) : Entered.", AI_LOG_DEBUG)
var/mob/living/simple_mob/slime/xenobio/my_slime = holder
if((findtext(message, num2text(my_slime.number)) || findtext(message, my_slime.name) || findtext(message, "slimes"))) // Talking to us.
// First, make sure it's actually a player saying something and not an AI, or else we risk infinite loops.
if(!speaker.client)
return
// Are all slimes being referred to?
// var/mass_order = FALSE
// if(findtext(message, "slimes"))
// mass_order = TRUE
// Say hello back.
if(findtext(message, "hello") || findtext(message, "hi") || findtext(message, "greetings"))
delayed_say(pick("Hello...", "Hi..."), speaker)
// Follow request.
if(findtext(message, "follow") || findtext(message, "come with me"))
if(!can_command(speaker))
delayed_say(pick("No...", "I won't follow..."), speaker)
return
delayed_say("Yes... I follow \the [speaker]...", speaker)
set_follow(speaker)
// Squish request.
if(findtext(message , "squish"))
if(!can_command(speaker))
delayed_say("No...", speaker)
return
spawn(rand(1 SECOND, 2 SECONDS))
if(!src || !holder || !can_act()) // We might've died/got deleted/etc in the meantime.
return
my_slime.squish()
// Stop request.
if(findtext(message, "stop") || findtext(message, "halt") || findtext(message, "cease"))
if(my_slime.victim) // We're being asked to stop eatting someone.
if(!can_command(speaker) || !is_justified_to_discipline())
delayed_say("No...", speaker)
return
else
delayed_say("Fine...", speaker)
adjust_discipline(1, TRUE)
my_slime.stop_consumption()
if(target) // We're being asked to stop chasing someone.
if(!can_command(speaker) || !is_justified_to_discipline())
delayed_say("No...", speaker)
return
else
delayed_say("Fine...", speaker)
adjust_discipline(1, TRUE) // This must come before losing the target or it will be unjustified.
remove_target()
if(leader) // We're being asked to stop following someone.
if(can_command(speaker) == SLIME_COMMAND_FRIEND || leader == speaker)
delayed_say("Yes... I'll stop...", speaker)
lose_follow()
else
delayed_say("No... I'll keep following \the [leader]...", speaker)
/* // Commented out since its mostly useless now due to slimes refusing to attack if it would make them naughty.
// Murder request
if(findtext(message, "harm") || findtext(message, "attack") || findtext(message, "kill") || findtext(message, "murder") || findtext(message, "eat") || findtext(message, "consume") || findtext(message, "absorb"))
if(can_command(speaker) < SLIME_COMMAND_FACTION)
delayed_say("No...", speaker)
return
for(var/mob/living/L in view(7, my_slime) - list(my_slime, speaker))
if(L == src)
continue // Don't target ourselves.
var/list/valid_names = splittext(L.name, " ") // Should output list("John", "Doe") as an example.
for(var/line in valid_names) // Check each part of someone's name.
if(findtext(message, lowertext(line))) // If part of someone's name is in the command, the slime targets them if allowed to.
if(!(mass_order && line == "slime")) //don't think random other slimes are target
if(can_attack(L))
delayed_say("Okay... I attack \the [L]...", speaker)
give_target(L)
return
else
delayed_say("No... I won't attack \the [L].", speaker)
return
// If we're here, it couldn't find anyone with that name.
delayed_say("No... I don't know who to attack...", speaker)
*/
ai_log("xenobio_slime/on_hear_say() : Exited.", AI_LOG_DEBUG)
/datum/ai_holder/simple_mob/xenobio_slime/can_violently_breakthrough()
if(discipline && !rabid) // Good slimes don't shatter the windows because their buddy in an adjacent cell decided to piss off Slimesky.
return FALSE
return ..()