diff --git a/code/__DEFINES/ai/monsters.dm b/code/__DEFINES/ai/monsters.dm index 9a10d411fdc..1f54a54784d 100644 --- a/code/__DEFINES/ai/monsters.dm +++ b/code/__DEFINES/ai/monsters.dm @@ -3,6 +3,8 @@ #define BB_BILEWORM_SPEW_BILE "BB_bileworm_spew_bile" #define BB_BILEWORM_RESURFACE "BB_bileworm_resurface" #define BB_BILEWORM_DEVOUR "BB_bileworm_devour" +#define BB_BILEWORM_SCARED "BB_bileworm_scared" +#define BB_BILEWORM_FLEE_DISTANCE "BB_bileworm_flee_distance" // Meteor Heart AI keys /// Key where we keep the spike trail ability diff --git a/code/modules/mining/equipment/kinetic_crusher/trophies_fauna.dm b/code/modules/mining/equipment/kinetic_crusher/trophies_fauna.dm index 16290710871..dfa4cf8e502 100644 --- a/code/modules/mining/equipment/kinetic_crusher/trophies_fauna.dm +++ b/code/modules/mining/equipment/kinetic_crusher/trophies_fauna.dm @@ -144,7 +144,7 @@ // Bileworm /obj/item/crusher_trophy/bileworm_spewlet name = "bileworm spewlet" - icon = 'icons/mob/simple/lavaland/bileworm.dmi' + icon = 'icons/obj/mining_zones/artefacts.dmi' icon_state = "bileworm_spewlet" desc = "A baby bileworm. Suitable as a trophy for a kinetic crusher." denied_type = /obj/item/crusher_trophy/bileworm_spewlet diff --git a/code/modules/mob/living/basic/lavaland/bileworm/_bileworm.dm b/code/modules/mob/living/basic/lavaland/bileworm/_bileworm.dm index 0ed4359bf23..19d1fd20c6a 100644 --- a/code/modules/mob/living/basic/lavaland/bileworm/_bileworm.dm +++ b/code/modules/mob/living/basic/lavaland/bileworm/_bileworm.dm @@ -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) diff --git a/code/modules/mob/living/basic/lavaland/bileworm/bileworm_actions.dm b/code/modules/mob/living/basic/lavaland/bileworm/bileworm_actions.dm index bd480cc6972..d3a45a89a76 100644 --- a/code/modules/mob/living/basic/lavaland/bileworm/bileworm_actions.dm +++ b/code/modules/mob/living/basic/lavaland/bileworm/bileworm_actions.dm @@ -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" diff --git a/code/modules/mob/living/basic/lavaland/bileworm/bileworm_ai.dm b/code/modules/mob/living/basic/lavaland/bileworm/bileworm_ai.dm index 01c4a564673..cd2450018cf 100644 --- a/code/modules/mob/living/basic/lavaland/bileworm/bileworm_ai.dm +++ b/code/modules/mob/living/basic/lavaland/bileworm/bileworm_ai.dm @@ -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 diff --git a/code/modules/mob/living/basic/lavaland/bileworm/bileworm_instrument.dm b/code/modules/mob/living/basic/lavaland/bileworm/bileworm_instrument.dm index 508728ffa73..74d20946737 100644 --- a/code/modules/mob/living/basic/lavaland/bileworm/bileworm_instrument.dm +++ b/code/modules/mob/living/basic/lavaland/bileworm/bileworm_instrument.dm @@ -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 diff --git a/code/modules/mob/living/basic/lavaland/bileworm/bileworm_loot.dm b/code/modules/mob/living/basic/lavaland/bileworm/bileworm_loot.dm index 55f960e736a..a8bedef666b 100644 --- a/code/modules/mob/living/basic/lavaland/bileworm/bileworm_loot.dm +++ b/code/modules/mob/living/basic/lavaland/bileworm/bileworm_loot.dm @@ -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 diff --git a/code/modules/mob/living/basic/lavaland/bileworm/bileworm_vileworm.dm b/code/modules/mob/living/basic/lavaland/bileworm/bileworm_vileworm.dm index d03ff00f85a..73918285b41 100644 --- a/code/modules/mob/living/basic/lavaland/bileworm/bileworm_vileworm.dm +++ b/code/modules/mob/living/basic/lavaland/bileworm/bileworm_vileworm.dm @@ -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 diff --git a/code/modules/mob/living/basic/lavaland/mining.dm b/code/modules/mob/living/basic/lavaland/mining.dm index 59247792800..b2ba4139559 100644 --- a/code/modules/mob/living/basic/lavaland/mining.dm +++ b/code/modules/mob/living/basic/lavaland/mining.dm @@ -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) diff --git a/code/modules/mod/modules/modules_supply.dm b/code/modules/mod/modules/modules_supply.dm index 52dfb755f94..9fe1b8a137b 100644 --- a/code/modules/mod/modules/modules_supply.dm +++ b/code/modules/mod/modules/modules_supply.dm @@ -752,9 +752,9 @@ /obj/projectile/bullet/mining_missile/proc/spawn_particles(atom/target) var/obj/effect/abstract/particle_holder/impact_particles = new(get_turf(target), /particles/micromissile_impact) - impact_particles.particles.position = generator(GEN_VECTOR, list(impact_x - 2, impact_x + 2), list(impact_y - 2, impact_y + 2), NORMAL_RAND) - impact_particles.particles.velocity = generator(GEN_VECTOR, list(movement_vector.pixel_x * 0.5 * speed * ICON_SIZE_X - 2, movement_vector.pixel_x * 0.5 * speed * ICON_SIZE_X + 2), list(movement_vector.pixel_y * 0.5 * speed * ICON_SIZE_Y - 2, movement_vector.pixel_y * 0.5 * speed * ICON_SIZE_Y + 2), NORMAL_RAND) - QDEL_IN(impact_particles, 1 SECONDS) + impact_particles.particles.position = generator(GEN_BOX, list(impact_x - 2, impact_y - 2), list(impact_x + 2, impact_y + 2), NORMAL_RAND) + impact_particles.particles.velocity = generator(GEN_BOX, list(movement_vector.pixel_x * 0.5 * speed * ICON_SIZE_X - 2, movement_vector.pixel_y * 0.5 * speed * ICON_SIZE_Y - 2, ), list(movement_vector.pixel_x * 0.5 * speed * ICON_SIZE_X + 2, movement_vector.pixel_y * 0.5 * speed * ICON_SIZE_Y + 2), NORMAL_RAND) + QDEL_IN(impact_particles, /particles/micromissile_impact::lifespan) /particles/micromissile_impact icon = 'icons/effects/particles/generic.dmi' diff --git a/icons/mob/simple/lavaland/bileworm.dmi b/icons/mob/simple/lavaland/bileworm.dmi index e3072364e93..e3206d648d5 100644 Binary files a/icons/mob/simple/lavaland/bileworm.dmi and b/icons/mob/simple/lavaland/bileworm.dmi differ diff --git a/icons/mob/simple/lavaland/bileworm_jump.dmi b/icons/mob/simple/lavaland/bileworm_jump.dmi new file mode 100644 index 00000000000..5f7491f1aa1 Binary files /dev/null and b/icons/mob/simple/lavaland/bileworm_jump.dmi differ diff --git a/icons/mob/simple/lavaland/bileworm_old.dmi b/icons/mob/simple/lavaland/bileworm_old.dmi new file mode 100644 index 00000000000..8337f6cc4f1 Binary files /dev/null and b/icons/mob/simple/lavaland/bileworm_old.dmi differ diff --git a/icons/mob/telegraphing/telegraph.dmi b/icons/mob/telegraphing/telegraph.dmi index fb8b7bc83fd..6afddd04b62 100644 Binary files a/icons/mob/telegraphing/telegraph.dmi and b/icons/mob/telegraphing/telegraph.dmi differ diff --git a/icons/obj/mining_zones/artefacts.dmi b/icons/obj/mining_zones/artefacts.dmi index 4c4dda6aa20..1e9325be8d0 100644 Binary files a/icons/obj/mining_zones/artefacts.dmi and b/icons/obj/mining_zones/artefacts.dmi differ diff --git a/icons/obj/stack_objects.dmi b/icons/obj/stack_objects.dmi index 80845395803..8504bbc4690 100644 Binary files a/icons/obj/stack_objects.dmi and b/icons/obj/stack_objects.dmi differ diff --git a/icons/obj/weapons/guns/projectiles.dmi b/icons/obj/weapons/guns/projectiles.dmi index a78f5fa3e36..24aa777660d 100644 Binary files a/icons/obj/weapons/guns/projectiles.dmi and b/icons/obj/weapons/guns/projectiles.dmi differ