Reworks bileworms into artillery-like enemies (#96159)

## About The Pull Request

Bileworms now attack by firing a barrage of arcing projectiles at their
target, one guaranteed to hit their turf and the rest spread around
them. Bileworms fire 5 shots and vileworms fire 7 at a faster rate.
The projectiles themselves deal 20/25 burn damage and scale with MELEE
armor (as ACID is mostly for atom armor and not mob) on mobs and ACID on
objects.

Bileworms now have a short jump animation before they burrow, during
which they can be stunned by getting shot or hit (only damaging
projectiles count, so you need to melee with your crusher if you want to
stop a burrow). Doing so prevents them from attacking for 2.4 seconds,
after which they burrow back underground without an animation (as to
avoid chainstunning)
They will not burrow immediatelly after firing, now only repositioning
if their target is 3 or less tiles away from them or if they have been
hit by an attack. Their health has been increased to 110/175 to
compensate for them now being able to be stunned, as those are above
important breakpoints for damage, making them require 1 more swing after
backstab/1 more shot to kill respectively.

When attacking NODE drones bileworms will have 30% less spread, making
them a priority target to take out during vent defense, but not as
dangerous as brimdemons or legions.


https://github.com/user-attachments/assets/9d11959f-c90b-4fd5-b93f-bc514237e9bf

Full video of 7 bileworm/5 vileworm fights with better visuals and no
compression can be seen here: https://streamable.com/6thbmm
(Both underground firing and dead sprite issues have been fixed after
the recording)
Worm jumping sprite/animation by ArcaneMusic, edited by me

## Why It's Good For The Game

Bileworms are not fun to fight for both PKA and PKC users, there is no
counterplay to their burrowing, and they are not engaging during vent
defense. This should address all of these issues, and make them more fun
to fight.

## Changelog
🆑 SmArtKar, ArcaneMusic
balance: Bileworms now fire arcing shots instead of cross patterns, and
can be stunned by hitting them during the burrow animation. Their health
has been slightly buffed to compensate.
/🆑
This commit is contained in:
SmArtKar
2026-05-23 14:43:48 +01:00
committed by GitHub
parent baa2776d35
commit 5fb3112981
17 changed files with 266 additions and 95 deletions
@@ -6,8 +6,8 @@
icon_living = "bileworm"
icon_dead = "bileworm_dead"
mob_biotypes = MOB_ORGANIC|MOB_BUG|MOB_MINING
maxHealth = 100
health = 100
maxHealth = 110
health = 110
verb_say = "spittles"
verb_ask = "spittles questioningly"
verb_exclaim = "splutters and gurgles"
@@ -30,10 +30,16 @@
ai_controller = /datum/ai_controller/basic_controller/bileworm
///which action this mob will be given, subtypes have different attacks
var/attack_action_path = /datum/action/cooldown/mob_cooldown/projectile_attack/dir_shots/bileworm
///which, if at all, mob this evolves into at the 30 min mark
/// Which action this mob will be given, subtypes have different attacks
var/attack_action_path = /datum/action/cooldown/mob_cooldown/bileworm_spew
/// Which, if at all, mob this evolves into at the 30 min mark
var/evolve_path = /mob/living/basic/mining/bileworm/vileworm
/// Emissive icon_state
var/emissive_state = "bileworm_e"
/// Icon file used for the jumping animation
var/icon_jump = 'icons/mob/simple/lavaland/bileworm_jump.dmi'
/// Are we currently in the middle of a jump?
var/jumping = FALSE
/mob/living/basic/mining/bileworm/Initialize(mapload)
. = ..()
@@ -42,11 +48,7 @@
if(ispath(evolve_path))
AddComponent(/datum/component/evolutionary_leap, 30 MINUTES, evolve_path)
AddElement(/datum/element/content_barfer)
//setup mob abilities
//well, one of them has to start on infinite cooldown
var/datum/action/cooldown/mob_cooldown/projectile_attack/dir_shots/bileworm/spew_bile = new(src)
var/datum/action/cooldown/mob_cooldown/spew_bile = new attack_action_path(src)
spew_bile.Grant(src)
spew_bile.StartCooldownSelf(INFINITY)
ai_controller?.set_blackboard_key(BB_BILEWORM_SPEW_BILE, spew_bile)
@@ -61,5 +63,10 @@
/mob/living/basic/mining/bileworm/update_overlays()
. = ..()
if (stat != DEAD)
. += emissive_appearance(icon, "[icon_living]_e", src)
if (stat != DEAD && !jumping)
. += emissive_appearance(icon, emissive_state, src)
/mob/living/basic/mining/bileworm/on_attacked(datum/source, atom/attacker, attack_flags)
. = ..()
if (!(attack_flags & (ATTACKER_STAMINA_ATTACK | ATTACKER_SHOVING)))
ai_controller?.set_blackboard_key(BB_BILEWORM_SCARED, TRUE)
@@ -2,21 +2,70 @@
name = "Resurface"
desc = "Burrow underground, and then move to a new location near your target. Must spew bile to refresh."
shared_cooldown = MOB_SHARED_COOLDOWN_1 | MOB_SHARED_COOLDOWN_2
/// Damage tracker var for bileworms
var/jump_damaged = FALSE
/// How long does the jump take to perform?
var/jump_length = 1 SECONDS
/// How long do we get stunned for if we fail a jump?
var/jump_stun = 2.4 SECONDS
/datum/action/cooldown/mob_cooldown/resurface/Grant(mob/granted_to)
. = ..()
owner?.AddElement(/datum/element/relay_attackers)
/datum/action/cooldown/mob_cooldown/resurface/Activate(atom/target_atom)
StartCooldownSelf(INFINITY)
StartCooldownOthers(INFINITY)
burrow(owner, target_atom)
//spew now off cooldown shortly
StartCooldownOthers(1.5 SECONDS)
/datum/action/cooldown/mob_cooldown/resurface/proc/burrow(mob/living/burrower, atom/target)
/// Amount of frames in the jump animation
#define BILEWORM_JUMP_FRAMES 14
/datum/action/cooldown/mob_cooldown/resurface/proc/burrow(mob/living/burrower, atom/target, force = FALSE)
var/turf/unburrow_turf = get_unburrow_turf(burrower, target)
if(!unburrow_turf) // means all the turfs nearby are station turfs or something, not lavaland
if (!unburrow_turf) // means all the turfs nearby are station turfs or something, not lavaland
to_chat(burrower, span_warning("Couldn't burrow anywhere near the target!"))
if(burrower.ai_controller?.ai_status == AI_STATUS_ON)
//this is a valid reason to give up on a target
burrower.ai_controller.clear_blackboard_key(BB_BASIC_MOB_CURRENT_TARGET)
return
if (istype(burrower, /mob/living/basic/mining/bileworm) && !force)
var/mob/living/basic/mining/bileworm/worm = burrower
new /obj/effect/temp_visual/mook_dust(get_turf(worm))
var/old_icon_state = worm.icon_state
worm.icon_state = null
// Get rid of the base emissive
worm.jumping = TRUE
worm.update_appearance(UPDATE_OVERLAYS)
var/atom/movable/visual = worm.flick_overlay_view(mutable_appearance(worm.icon_jump, "[worm.icon_living]_jump_1"), jump_length)
visual.vis_flags |= VIS_INHERIT_ID // So you can attack it
var/atom/movable/emissive_visual = worm.flick_overlay_view(emissive_appearance(worm.icon_jump, "[worm.emissive_state]_jump_1", worm), jump_length)
// We have to manually animate these to get around BYOND icon_state animations happening in world time and not per-object
for (var/i in 2 to BILEWORM_JUMP_FRAMES)
animate(visual, time = jump_length / BILEWORM_JUMP_FRAMES, icon_state = "[worm.icon_living]_jump_[i]", flags = ANIMATION_CONTINUE)
animate(emissive_visual, time = jump_length / BILEWORM_JUMP_FRAMES, icon_state = "[worm.emissive_state]_jump_[i]", flags = ANIMATION_CONTINUE)
jump_damaged = FALSE
RegisterSignal(worm, COMSIG_ATOM_WAS_ATTACKED, PROC_REF(on_attacked))
// Not in an if check direclty to reduce duplicate code
var/jump_result = do_after(worm, jump_length, worm, hidden = TRUE, extra_checks = CALLBACK(src, PROC_REF(damage_check)))
UnregisterSignal(worm, COMSIG_ATOM_WAS_ATTACKED)
if (worm.icon_state == null)
worm.icon_state = old_icon_state
worm.jumping = FALSE
worm.update_appearance(UPDATE_OVERLAYS)
if (!jump_result && jump_stun)
if (!QDELETED(visual))
QDEL_NULL(visual)
QDEL_NULL(emissive_visual)
worm.flick_overlay_view(mutable_appearance('icons/effects/effects.dmi', "dazed"), jump_stun)
worm.Stun(jump_stun)
addtimer(CALLBACK(src, PROC_REF(burrow_again), burrower, target), jump_stun)
return
burrower.ai_controller?.set_blackboard_key(BB_BILEWORM_SCARED, FALSE)
playsound(burrower, 'sound/effects/break_stone.ogg', 50, TRUE)
new /obj/effect/temp_visual/mook_dust(get_turf(burrower))
ADD_TRAIT(burrower, TRAIT_GODMODE, REF(src))
@@ -29,59 +78,189 @@
REMOVE_TRAIT(burrower, TRAIT_GODMODE, REF(src))
burrower.RemoveInvisibility(type)
#undef BILEWORM_JUMP_FRAMES
/datum/action/cooldown/mob_cooldown/resurface/proc/burrow_again(mob/living/burrower, atom/target)
if (!QDELETED(burrower) && !burrower.stat)
// Burrow immediatelly after being stunned out of the first jump to avoid chainstuns
burrow(burrower, target, force = TRUE)
/datum/action/cooldown/mob_cooldown/resurface/proc/on_attacked(datum/source, atom/attacker, attack_flags)
SIGNAL_HANDLER
if (!(attack_flags & (ATTACKER_STAMINA_ATTACK | ATTACKER_SHOVING)) && jump_stun)
jump_damaged = TRUE
/datum/action/cooldown/mob_cooldown/resurface/proc/damage_check()
return !jump_damaged
/datum/action/cooldown/mob_cooldown/resurface/proc/get_unburrow_turf(mob/living/burrower, atom/target)
//we want the worm to try guaranteeing a hit on a living target if it thinks it can
var/cardinal_only = FALSE
if(isliving(target))
var/mob/living/living_target = target
if(living_target.stat >= UNCONSCIOUS)
cardinal_only = TRUE
var/list/potential_turfs = shuffle(oview(5, target))//get in view, shuffle
var/list/fallback_turfs = list()
for(var/turf/open/misc/chosen_one in potential_turfs)//first turf that counts as ground
if(cardinal_only && !(get_dir(chosen_one, target) in GLOB.cardinals))
fallback_turfs.Add(chosen_one)
continue
var/list/potential_turfs = shuffle(oview(5, target)) // get in view, shuffle
for(var/turf/open/misc/chosen_one in potential_turfs) // first turf that counts as ground
return chosen_one
//even if a worm can't execute someone in crit, it should not fail if it has SOMETHING to move to.
if(fallback_turfs.len)
return pick(fallback_turfs)
/datum/action/cooldown/mob_cooldown/projectile_attack/dir_shots/bileworm
/datum/action/cooldown/mob_cooldown/bileworm_spew
name = "Spew Bile"
desc = "Spews bile everywhere. Must resurface after use to refresh."
projectile_type = /obj/projectile/bileworm_acid
projectile_sound = 'sound/mobs/non-humanoids/bileworm/bileworm_spit.ogg'
desc = "Spew a barrage of bile globs."
shared_cooldown = MOB_SHARED_COOLDOWN_1 | MOB_SHARED_COOLDOWN_2
cooldown_time = 3 SECONDS
/// Sound played when firing a projectile
var/projectile_sound = 'sound/mobs/non-humanoids/bileworm/bileworm_spit.ogg'
/// How many additional projectiles to shoot around the target?
var/additional_shots = 4
/// Delay between each shot
var/shot_delay = 0.15 SECONDS
/// Effect to spawn
var/obj/effect/bileworm_acid/acid_type = /obj/effect/bileworm_acid
/datum/action/cooldown/mob_cooldown/projectile_attack/dir_shots/bileworm/Activate(atom/target_atom)
/datum/action/cooldown/mob_cooldown/bileworm_spew/Activate(atom/target_atom)
StartCooldownSelf(INFINITY)
attack_sequence(owner, target_atom)
//resurface now off cooldown shortly
StartCooldownOthers(2.5 SECONDS)
StartCooldownSelf()
// Resurface now off cooldown shortly
StartCooldownOthers(2 SECONDS) // Enough time for a mark + detonation combo, or 3 shots with a PKA
/datum/action/cooldown/mob_cooldown/projectile_attack/dir_shots/bileworm/attack_sequence(mob/living/firer, atom/target)
fire_in_directions(firer, target, GLOB.cardinals)
SLEEP_CHECK_DEATH(0.5 SECONDS, firer)
fire_in_directions(firer, target, GLOB.diagonals)
/datum/action/cooldown/mob_cooldown/bileworm_spew/proc/attack_sequence(mob/living/firer, atom/target)
new acid_type(firer, target)
playsound(firer, projectile_sound, 70)
var/list/all_dirs = GLOB.alldirs.Copy()
var/turf/hit_turf = get_turf(target)
// One guaranteed to hit target's turf, the rest hit randomly around them
for (var/i in 1 to additional_shots)
if (!length(all_dirs))
return
/obj/projectile/bileworm_acid
SLEEP_CHECK_DEATH(shot_delay, firer)
if (hit_turf != target.loc)
all_dirs = list(NONE) + GLOB.alldirs // Refresh potential target turfs if they've moved
var/turf/target_turf = null
// NODE drones get a much more focused barrage sent at them
if (istype(target, /mob/living/basic/node_drone) && prob(30))
target_turf = get_turf(target)
else
var/target_dir = pick_n_take(all_dirs)
target_turf = target_dir ? get_step(target, target_dir) : get_turf(target)
if (target_turf == firer.loc) // Don't hit ourselves
var/target_dir = pick_n_take(all_dirs)
target_turf = target_dir ? get_step(target, target_dir) : get_turf(target)
new acid_type(firer, target_turf)
if (i % 2 == 0)
playsound(firer, projectile_sound, 70)
/obj/effect/bileworm_acid
name = "acidic bile"
icon_state = "neurotoxin"
hitsound = 'sound/items/weapons/sear.ogg'
damage = 20
speed = 0.5
range = 20
jitter = 3 SECONDS
stutter = 3 SECONDS
damage_type = BURN
pass_flags = PASSTABLE
icon = 'icons/obj/weapons/guns/projectiles.dmi'
icon_state = "bile_glob"
layer = ABOVE_ALL_MOB_LAYER
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
/// Damage dealt to all mobs in the impact turf
var/damage = 20
/// Tiles travelled per second at maximum range
var/speed = 5
/// Maximum range for our speed calculations
var/max_range = 10
/// Warning sign on the turf we're about to hit
var/obj/effect/bileworm_target/target_sign = null
/obj/projectile/bileworm_acid/Initialize(mapload)
/obj/effect/bileworm_acid/Initialize(mapload, atom/new_target)
. = ..()
AddComponent(/datum/component/parriable_projectile)
update_appearance(UPDATE_OVERLAYS)
if (new_target)
fire_at(get_turf(new_target))
/obj/effect/bileworm_acid/Destroy(force)
QDEL_NULL(target_sign)
return ..()
/obj/effect/bileworm_acid/update_overlays()
. = ..()
. += emissive_appearance(icon, icon_state, src, alpha = 20, effect_type = EMISSIVE_BLOOM)
/obj/effect/bileworm_acid/proc/fire_at(turf/target)
if (!istype(target))
target = get_turf(target)
var/turf/start = get_turf(src)
forceMove(target) // Immediately move to the target turf so we can guarantee they can see us
pixel_x = (start.x - target.x) * ICON_SIZE_X
pixel_y = (start.y - target.y) * ICON_SIZE_Y
// Because BYOND's get_dist is taxicab distance
var/travel_dist = sqrt((start.x - target.x) ** 2 + (start.y - target.y) ** 2)
// Slightly scale the speed with distance for fairer gameplay
if (travel_dist < max_range)
speed *= 0.5 + travel_dist / max_range * 0.5
var/travel_time = travel_dist / speed * 1 SECONDS
animate(src, pixel_x = 0, time = travel_time, flags = ANIMATION_PARALLEL, easing = SINE_EASING | EASE_OUT) // Not a perfect arc but looks better
animate(src, pixel_y = 160, time = travel_time / 2, flags = ANIMATION_PARALLEL, easing = QUAD_EASING | EASE_OUT)
animate(pixel_y = 0, time = travel_time / 2, easing = QUAD_EASING | EASE_IN)
animate(src, transform = matrix().Turn(start.x > target.x ? -91 : 91), time = travel_time / 2, flags = ANIMATION_PARALLEL, easing = SINE_EASING | EASE_IN)
animate(transform = matrix().Turn(start.x > target.x ? -180 : 180), time = travel_time / 2, easing = SINE_EASING | EASE_OUT)
target_sign = new(target)
addtimer(CALLBACK(src, PROC_REF(impact), target), travel_time)
/obj/effect/bileworm_acid/proc/impact(turf/target)
var/obj/effect/abstract/particle_holder/impact_particles = new(target, /particles/bile)
QDEL_IN(impact_particles, /particles/bile::lifespan)
var/hit_something = FALSE
for (var/mob/living/victim in target)
if(HAS_TRAIT(target, TRAIT_UNHITTABLE_BY_PROJECTILES))
if(!HAS_TRAIT(target, TRAIT_BLOCKING_PROJECTILES) && isliving(target))
var/mob/living/living_target = target
living_target.block_projectile_effects()
continue
// Doesn't make much sense to use melee for mobs, but its a mining mob so eeeeeh
// Can't use acid either as its mostly for atom armor only
var/blocked = victim.run_armor_check(null, MELEE, armour_penetration = 40, silent = TRUE)
if (blocked >= 100)
continue
hit_something = TRUE
victim.apply_damage(damage, BURN, null, blocked, wound_bonus = CANT_WOUND)
to_chat(victim, span_userdanger("You're hit by [src]!"))
for (var/obj/thing in target)
if (!thing.uses_integrity || !thing.density)
continue
hit_something = TRUE
thing.take_damage(damage, BURN, ACID, sound_effect = FALSE)
if (hit_something)
playsound(target, 'sound/items/weapons/sear.ogg', 50, -1)
qdel(src)
/obj/effect/bileworm_target
icon = 'icons/mob/telegraphing/telegraph.dmi'
icon_state = "projectile_circle"
layer = BELOW_MOB_LAYER
plane = GAME_PLANE
/obj/effect/bileworm_target/Initialize(mapload)
. = ..()
update_appearance(UPDATE_OVERLAYS)
/obj/effect/bileworm_target/update_overlays()
. = ..()
. += emissive_appearance(icon, icon_state, src, alpha = 90, effect_type = EMISSIVE_BLOOM)
/particles/bile
icon = 'icons/effects/particles/goop.dmi'
icon_state = list("goop_1" = 6, "goop_2" = 2, "goop_3" = 1)
width = 100
height = 100
count = 10
spawning = 10
color = "#00ea2b80" //to get 96 alpha
lifespan = 1.5 SECONDS
fade = 1 SECONDS
grow = -0.025
gravity = list(0, 0.15)
position = generator(GEN_SPHERE, 0, 8, NORMAL_RAND)
spin = generator(GEN_NUM, -15, 15, NORMAL_RAND)
velocity = generator(GEN_BOX, list(-2, 2), list(2, 4), NORMAL_RAND)
/datum/action/cooldown/mob_cooldown/devour
name = "Devour"
@@ -2,6 +2,7 @@
blackboard = list(
BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/bileworm,
BB_TARGET_PRIORITY_STRATEGY = /datum/target_priority_strategy/mining,
BB_BILEWORM_FLEE_DISTANCE = 3,
)
planning_subtrees = list(
@@ -22,16 +23,12 @@
return
var/datum/action/cooldown/mob_cooldown/resurface = controller.blackboard[BB_BILEWORM_RESURFACE]
var/datum/action/cooldown/mob_cooldown/bile = controller.blackboard[BB_BILEWORM_SPEW_BILE]
//because one ability is always INFINITY cooldown, this actually works to check which ability should be used
//sometimes it will try to spew bile on infinity cooldown, but that's okay because as soon as resurface is ready it will attempt that
if(resurface?.IsAvailable())
if(resurface?.IsAvailable() && (controller.blackboard[BB_BILEWORM_SCARED] || get_dist(controller.pawn, controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET]) <= controller.blackboard[BB_BILEWORM_FLEE_DISTANCE]))
controller.queue_behavior(/datum/ai_behavior/targeted_mob_ability/and_plan_execute, BB_BILEWORM_RESURFACE, BB_BASIC_MOB_CURRENT_TARGET)
return SUBTREE_RETURN_FINISH_PLANNING
var/datum/action/cooldown/mob_cooldown/bile = controller.blackboard[BB_BILEWORM_SPEW_BILE]
if(bile?.IsAvailable())
controller.queue_behavior(/datum/ai_behavior/targeted_mob_ability/and_plan_execute, BB_BILEWORM_SPEW_BILE, BB_BASIC_MOB_CURRENT_TARGET)
return SUBTREE_RETURN_FINISH_PLANNING //focus on the fight
@@ -2,7 +2,7 @@
name = "bilehorn"
desc = "Bits of bileworm anatomy rearranged to produce wonderful music, not bile. Keeps the name though, because for an instrument, it is quite vile."
force = 5
icon = 'icons/mob/simple/lavaland/bileworm.dmi'
icon = 'icons/obj/mining_zones/artefacts.dmi'
icon_state = "bilehorn"
allowed_instrument_ids = "bilehorn"
inhand_icon_state = null
@@ -5,7 +5,7 @@
name = "bileworm skin"
desc = "The slushy, squishy and slightly shiny skin of a postmortem bileworm."
singular_name = "bileworm skin piece"
icon = 'icons/mob/simple/lavaland/bileworm.dmi'
icon = 'icons/obj/stack_objects.dmi'
icon_state = "sheet-bileworm"
inhand_icon_state = null
merge_type = /obj/item/stack/sheet/animalhide/bileworm
@@ -4,34 +4,20 @@
icon_state = "vileworm"
icon_living = "vileworm"
icon_dead = "vileworm_dead"
maxHealth = 150
health = 150
maxHealth = 175
health = 175
attack_action_path = /datum/action/cooldown/mob_cooldown/projectile_attack/dir_shots/bileworm/vileworm
attack_action_path = /datum/action/cooldown/mob_cooldown/bileworm_spew/corrupt
evolve_path = null
/datum/action/cooldown/mob_cooldown/projectile_attack/dir_shots/bileworm/vileworm
/datum/action/cooldown/mob_cooldown/bileworm_spew/corrupt
name = "Spew Corrupted Bile"
desc = "Spews corrupted bile everywhere. Must resurface after use to refresh."
projectile_type = /obj/projectile/bileworm_acid/vile
desc = "Spew a barrage of corrupted bile globs."
cooldown_time = 2.5 SECONDS
acid_type = /obj/effect/bileworm_acid/corrupt
additional_shots = 6
shot_delay = 0.1 SECONDS
/datum/action/cooldown/mob_cooldown/projectile_attack/dir_shots/bileworm/vileworm/Activate(atom/target_atom)
StartCooldownSelf(INFINITY)
attack_sequence(owner, target_atom)
//faster than unevolved
StartCooldownOthers(1.5 SECONDS)
/datum/action/cooldown/mob_cooldown/projectile_attack/dir_shots/bileworm/vileworm/attack_sequence(mob/living/firer, atom/target)
fire_in_directions(firer, target, GLOB.cardinals)
SLEEP_CHECK_DEATH(0.25 SECONDS, firer)
fire_in_directions(firer, target, GLOB.diagonals)
SLEEP_CHECK_DEATH(0.25 SECONDS, firer)
fire_in_directions(firer, target, GLOB.cardinals)
// surprise!
if(prob(25))
SLEEP_CHECK_DEATH(0.25 SECONDS, firer)
fire_in_directions(firer, target, GLOB.diagonals)
/obj/projectile/bileworm_acid/vile
name = "corrupted bile"
icon_state = "vileworm"
/obj/effect/bileworm_acid/corrupt
icon_state = "corrupt_bile_glob"
damage = 27
@@ -40,7 +40,7 @@
drop_mod = crusher_drop_chance,\
drop_immediately = basic_mob_flags & DEL_ON_DEATH,\
)
RegisterSignal(src, COMSIG_ATOM_WAS_ATTACKED, PROC_REF(check_ashwalker_peace_violation))
RegisterSignal(src, COMSIG_ATOM_WAS_ATTACKED, PROC_REF(on_attacked))
// We add this to ensure that mobs will actually receive the above signal, as some will lack AI
// handling for retaliation and attack special cases
AddElement(/datum/element/relay_attackers)
@@ -55,9 +55,9 @@
throw_blocked_message = throw_blocked_message,\
)
/mob/living/basic/mining/proc/check_ashwalker_peace_violation(datum/source, mob/living/carbon/human/possible_ashwalker)
/mob/living/basic/mining/proc/on_attacked(datum/source, atom/attacker, attack_flags)
SIGNAL_HANDLER
if(!isashwalker(possible_ashwalker) || !has_faction(FACTION_ASHWALKER))
if(!isashwalker(attacker) || !has_faction(FACTION_ASHWALKER))
return
remove_faction(FACTION_ASHWALKER)