Basic Faithless Mob (#72479)

## About The Pull Request
Turns the faithless mob into a basic mob with unique behaviors, it will
now break lights and drag around victims bodies. Can also punch open
airlocks if they can be opened.
## Why It's Good For The Game
Now the faithless mob has its own unique behavior and it is cool to see
more AI variety.
## Changelog
🆑
add: Faithless will now also break lights and drag victims around
refactor: Faithless into basic mob
/🆑
This commit is contained in:
Comxy
2023-01-09 18:08:29 +00:00
committed by GitHub
parent 430a0ba224
commit 40a3363525
11 changed files with 177 additions and 51 deletions
+1 -1
View File
@@ -68,7 +68,7 @@ GLOBAL_LIST_INIT(phobia_mobs, list(
/mob/living/simple_animal/bot/mulebot/paranormal,
/mob/living/simple_animal/hostile/construct,
/mob/living/simple_animal/hostile/dark_wizard,
/mob/living/simple_animal/hostile/faithless,
/mob/living/basic/faithless,
/mob/living/simple_animal/hostile/heretic_summon,
/mob/living/simple_animal/hostile/imp,
/mob/living/simple_animal/hostile/retaliate/bat,
@@ -25,6 +25,8 @@
action_cooldown = 1 SECONDS
/// If we should attack walls, be prepared for complaints about breaches
var/can_attack_turfs = FALSE
/// Tries to bump open airlocks with an attack
var/bump_open_airlock = FALSE
/datum/ai_behavior/attack_obstructions/perform(delta_time, datum/ai_controller/controller, target_key)
. = ..()
@@ -76,3 +78,6 @@
if (basic_mob.see_invisible < object.invisibility)
return FALSE
return TRUE // It's in our way, let's get it out of our way
/datum/ai_planning_subtree/attack_obstacle_in_path/low_priority_target
target_key = BB_LOW_PRIORITY_HUNTING_TARGET
@@ -106,3 +106,7 @@
dog_pawn.update_dog_speech(src)
return ..()
/datum/ai_planning_subtree/random_speech/faithless
speech_chance = 1
emote_see = list("wails.")
@@ -75,6 +75,8 @@
behavior_flags = AI_BEHAVIOR_REQUIRE_MOVEMENT
/// How long do we have to wait after a successful hunt?
var/hunt_cooldown = 5 SECONDS
/// Do we reset the target after attacking something, so we can check for status changes.
var/always_reset_target = FALSE
/datum/ai_behavior/hunt_target/setup(datum/ai_controller/controller, hunting_target_key, hunting_cooldown_key)
. = ..()
@@ -118,6 +120,8 @@
controller.blackboard[hunting_cooldown_key] = world.time + hunt_cooldown
else if(hunting_target_key)
controller.blackboard[hunting_target_key] = null
if(always_reset_target && hunting_target_key)
controller.blackboard[hunting_target_key] = null
/datum/ai_behavior/hunt_target/unarmed_attack_target
@@ -0,0 +1,23 @@
/datum/ai_planning_subtree/find_and_hunt_target/look_for_light_fixtures
target_key = BB_LOW_PRIORITY_HUNTING_TARGET
finding_behavior = /datum/ai_behavior/find_hunt_target/light_fixtures
hunting_behavior = /datum/ai_behavior/hunt_target/light_fixtures
hunt_targets = list(/obj/machinery/light)
hunt_range = 7
/datum/ai_behavior/hunt_target/light_fixtures
hunt_cooldown = 10 SECONDS
always_reset_target = TRUE
/datum/ai_behavior/hunt_target/light_fixtures/target_caught(mob/living/hunter, obj/machinery/light/hunted)
hunter.UnarmedAttack(hunted, TRUE)
/datum/ai_behavior/find_hunt_target/light_fixtures
/datum/ai_behavior/find_hunt_target/light_fixtures/valid_dinner(mob/living/source, obj/machinery/light/dinner, radius)
if(istype(dinner, /obj/machinery/light))
var/obj/machinery/light/light_target = dinner
if(light_target.status == LIGHT_BROKEN) //light is already broken
return FALSE
return can_see(source, dinner, radius)
+52
View File
@@ -0,0 +1,52 @@
/**
* Attached to a basic mob.
* Causes attacks on doors to attempt to open them.
*/
/datum/component/pry_open_door
/// Odds the attack opens the door
var/open_chance
/// Time it takes to open a door with force
var/force_wait
/datum/component/pry_open_door/Initialize(open_chance = 100, force_wait = 10 SECONDS)
. = ..()
if(!isbasicmob(parent))
return COMPONENT_INCOMPATIBLE
src.open_chance = open_chance
src.force_wait = force_wait
/datum/component/pry_open_door/RegisterWithParent()
RegisterSignal(parent, COMSIG_HOSTILE_POST_ATTACKINGTARGET, PROC_REF(hostile_attackingtarget))
/datum/component/pry_open_door/UnregisterFromParent()
UnregisterSignal(parent, COMSIG_HOSTILE_POST_ATTACKINGTARGET)
/datum/component/pry_open_door/proc/hostile_attackingtarget(mob/living/basic/attacker, atom/target, success)
SIGNAL_HANDLER
if(!success)
return
if(istype(target, /obj/machinery/door/airlock) && prob(open_chance))
var/obj/machinery/door/airlock/airlock_target = target
INVOKE_ASYNC(src, PROC_REF(open_door), attacker, airlock_target)
/datum/component/pry_open_door/proc/open_door(mob/living/basic/attacker, obj/machinery/door/airlock/airlock_target)
if(airlock_target.locked)
to_chat(attacker, span_warning("The airlock's bolts prevent it from being forced!"))
return
else if(!airlock_target.allowed(attacker) && airlock_target.hasPower())
attacker.visible_message(span_warning("We start forcing the [airlock_target] open."), \
span_hear("You hear a metal screeching sound."))
playsound(airlock_target, 'sound/machines/airlock_alien_prying.ogg', 100, TRUE)
if(!do_after(attacker, force_wait, airlock_target))
return
if(airlock_target.locked)
return
attacker.visible_message(span_warning("We force the [airlock_target] to open."))
airlock_target.open(2)
else if(!airlock_target.hasPower())
attacker.visible_message(span_warning("We force the [airlock_target] to open."))
airlock_target.open(1)
else
airlock_target.open(0)
@@ -0,0 +1,84 @@
/mob/living/basic/faithless
name = "The Faithless"
desc = "The Wish Granter's faith in humanity, incarnate."
icon_state = "faithless"
icon_living = "faithless"
icon_dead = "faithless_dead"
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
gender = MALE
response_help_continuous = "passes through"
response_help_simple = "pass through"
speed = 0.5
maxHealth = 80
health = 80
obj_damage = 50
melee_damage_lower = 15
melee_damage_upper = 15
attack_verb_continuous = "grips"
attack_verb_simple = "grip"
attack_sound = 'sound/hallucinations/growl1.ogg'
speak_emote = list("growls")
unsuitable_atmos_damage = 0
unsuitable_cold_damage = 0
unsuitable_heat_damage = 0
faction = list("faithless")
gold_core_spawnable = HOSTILE_SPAWN
ai_controller = /datum/ai_controller/basic_controller/faithless
/mob/living/basic/faithless/Initialize(mapload)
. = ..()
ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT)
AddElement(/datum/element/footstep, FOOTSTEP_MOB_SHOE)
AddComponent(/datum/component/pry_open_door)
/datum/ai_controller/basic_controller/faithless
blackboard = list(
BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/faithless(),
BB_LOW_PRIORITY_HUNTING_TARGET = null, // lights
)
ai_movement = /datum/ai_movement/basic_avoidance
idle_behavior = /datum/idle_behavior/idle_random_walk
planning_subtrees = list(
/datum/ai_planning_subtree/simple_find_target,
/datum/ai_planning_subtree/attack_obstacle_in_path,
/datum/ai_planning_subtree/attack_obstacle_in_path/low_priority_target,
/datum/ai_planning_subtree/basic_melee_attack_subtree/faithless,
/datum/ai_planning_subtree/find_and_hunt_target/look_for_light_fixtures,
/datum/ai_planning_subtree/random_speech/faithless,
)
/datum/targetting_datum/basic/faithless
stat_attack = UNCONSCIOUS
/datum/ai_planning_subtree/basic_melee_attack_subtree/faithless
melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/faithless
/datum/ai_behavior/basic_melee_attack/faithless
action_cooldown = 1 SECONDS
/// What are the odds we paralyze a target
var/paralyze_chance = 12
/// How long do we paralyze a target for if we attack them
var/paralyze_duration = 2 SECONDS
/datum/ai_behavior/basic_melee_attack/faithless/perform(delta_time, datum/ai_controller/controller, target_key, targetting_datum_key, hiding_location_key)
. = ..()
var/datum/weakref/weak_target = controller.blackboard[target_key]
var/atom/target = weak_target?.resolve()
var/mob/living/living_pawn = controller.pawn
if(!isliving(target))
return
var/mob/living/living_target = target
if(living_target.pulledby != living_pawn && !HAS_AI_CONTROLLER_TYPE(living_target.pulledby, /datum/ai_controller/basic_controller/faithless)) //Dont steal from my fellow faithless.
if(living_pawn.Adjacent(living_target) && isturf(living_target.loc) && living_target.stat == SOFT_CRIT)
living_target.grabbedby(living_pawn) //Drag their bodies around as a menace.
if(prob(paralyze_chance) && iscarbon(target))
var/mob/living/carbon/carbon_target = target
carbon_target.Paralyze(paralyze_duration)
carbon_target.visible_message(span_danger("\The [living_pawn] knocks down \the [carbon_target]!"), \
span_userdanger("\The [living_pawn] knocks you down!"))
@@ -1,48 +0,0 @@
/mob/living/simple_animal/hostile/faithless
name = "The Faithless"
desc = "The Wish Granter's faith in humanity, incarnate."
icon_state = "faithless"
icon_living = "faithless"
icon_dead = "faithless_dead"
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
gender = MALE
speak_chance = 0
turns_per_move = 5
response_help_continuous = "passes through"
response_help_simple = "pass through"
emote_taunt = list("wails")
taunt_chance = 25
speed = 0
maxHealth = 80
health = 80
stat_attack = HARD_CRIT
robust_searching = 1
harm_intent_damage = 10
obj_damage = 50
melee_damage_lower = 15
melee_damage_upper = 15
attack_verb_continuous = "grips"
attack_verb_simple = "grip"
attack_sound = 'sound/hallucinations/growl1.ogg'
speak_emote = list("growls")
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
faction = list("faithless")
gold_core_spawnable = HOSTILE_SPAWN
footstep_type = FOOTSTEP_MOB_SHOE
/mob/living/simple_animal/hostile/faithless/Initialize(mapload)
. = ..()
ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT)
/mob/living/simple_animal/hostile/faithless/AttackingTarget()
. = ..()
if(. && prob(12) && iscarbon(target))
var/mob/living/carbon/C = target
C.Paralyze(60)
C.visible_message(span_danger("\The [src] knocks down \the [C]!"), \
span_userdanger("\The [src] knocks you down!"))
@@ -149,7 +149,6 @@
/mob/living/simple_animal/hostile/construct/wraith/noncult,
/mob/living/simple_animal/hostile/dark_wizard,
/mob/living/simple_animal/hostile/eyeball,
/mob/living/simple_animal/hostile/faithless,
/mob/living/simple_animal/hostile/giant_spider,
/mob/living/simple_animal/hostile/giant_spider/hunter,
/mob/living/simple_animal/hostile/giant_spider/hunter/flesh,
+3 -1
View File
@@ -765,6 +765,7 @@
#include "code\datums\ai\hauntium\hauntium_subtrees.dm"
#include "code\datums\ai\hunting_behavior\hunting_behaviors.dm"
#include "code\datums\ai\hunting_behavior\hunting_cockroach.dm"
#include "code\datums\ai\hunting_behavior\hunting_lights.dm"
#include "code\datums\ai\hunting_behavior\hunting_mouse.dm"
#include "code\datums\ai\idle_behaviors\_idle_behavior.dm"
#include "code\datums\ai\idle_behaviors\idle_dog.dm"
@@ -911,6 +912,7 @@
#include "code\datums\components\pellet_cloud.dm"
#include "code\datums\components\phylactery.dm"
#include "code\datums\components\pricetag.dm"
#include "code\datums\components\pry_open_door.dm"
#include "code\datums\components\punchcooldown.dm"
#include "code\datums\components\puzzgrid.dm"
#include "code\datums\components\radiation_countdown.dm"
@@ -3688,6 +3690,7 @@
#include "code\modules\mob\living\basic\space_fauna\carp\carp_controllers.dm"
#include "code\modules\mob\living\basic\space_fauna\carp\magicarp.dm"
#include "code\modules\mob\living\basic\space_fauna\carp\megacarp.dm"
#include "code\modules\mob\living\basic\space_fauna\faithless\faithless.dm"
#include "code\modules\mob\living\basic\syndicate\syndicate.dm"
#include "code\modules\mob\living\basic\syndicate\syndicate_ai.dm"
#include "code\modules\mob\living\basic\vermin\axolotl.dm"
@@ -3900,7 +3903,6 @@
#include "code\modules\mob\living\simple_animal\hostile\cat_butcher.dm"
#include "code\modules\mob\living\simple_animal\hostile\dark_wizard.dm"
#include "code\modules\mob\living\simple_animal\hostile\eyeballs.dm"
#include "code\modules\mob\living\simple_animal\hostile\faithless.dm"
#include "code\modules\mob\living\simple_animal\hostile\giant_spider.dm"
#include "code\modules\mob\living\simple_animal\hostile\goose.dm"
#include "code\modules\mob\living\simple_animal\hostile\headcrab.dm"
@@ -0,0 +1 @@
/mob/living/simple_animal/hostile/faithless : /mob/living/basic/faithless{@OLD}