[MIRROR] New Lavaland Monster: Bileworms [MDB IGNORE] (#15423)

* New Lavaland Monster: Bileworms

* Update living.dm

* Update space_dragon.dm

* Update mining_mobs.dm

* Update kinetic_crusher.dm

Co-authored-by: tralezab <40974010+tralezab@users.noreply.github.com>
Co-authored-by: Zonespace <41448081+Zonespace27@users.noreply.github.com>
Co-authored-by: Gandalf <9026500+Gandalf2k15@users.noreply.github.com>
This commit is contained in:
SkyratBot
2022-08-08 01:50:57 +01:00
committed by GitHub
co-authored by tralezab Zonespace Gandalf
parent 6b36cb249d
commit bea43365e7
37 changed files with 790 additions and 70 deletions
@@ -0,0 +1,278 @@
//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE
"a" = (
/turf/closed/mineral/volcanic/lava_land_surface,
/area/lavaland/surface/outdoors)
"b" = (
/turf/open/misc/asteroid/lavaland_atmos,
/area/lavaland/surface/outdoors)
"c" = (
/turf/template_noop,
/area/template_noop)
"d" = (
/mob/living/basic/bileworm,
/turf/open/misc/asteroid/lavaland_atmos,
/area/lavaland/surface/outdoors)
"e" = (
/obj/item/crusher_trophy/bileworm_spewlet,
/turf/open/misc/asteroid/lavaland_atmos,
/area/lavaland/surface/outdoors)
"f" = (
/obj/structure/water_source/puddle,
/turf/open/misc/asteroid/lavaland_atmos,
/area/lavaland/surface/outdoors)
(1,1,1) = {"
c
c
c
c
c
c
c
c
c
c
c
c
c
c
c
"}
(2,1,1) = {"
c
c
c
c
c
c
c
c
c
c
c
c
c
c
c
"}
(3,1,1) = {"
c
c
c
c
a
a
a
a
a
a
a
c
c
c
c
"}
(4,1,1) = {"
c
c
c
a
a
a
a
a
a
a
a
a
c
c
c
"}
(5,1,1) = {"
c
c
a
a
a
a
a
a
a
a
a
a
c
c
c
"}
(6,1,1) = {"
c
c
c
a
a
a
b
b
b
a
a
a
c
c
c
"}
(7,1,1) = {"
c
c
a
a
a
b
e
d
b
a
a
a
c
c
c
"}
(8,1,1) = {"
c
c
a
a
a
d
f
b
b
a
a
a
c
c
c
"}
(9,1,1) = {"
c
c
a
a
a
b
b
b
a
a
a
a
c
c
c
"}
(10,1,1) = {"
c
c
a
a
a
b
b
b
a
a
a
a
c
c
c
"}
(11,1,1) = {"
c
c
a
a
a
a
a
a
a
a
a
a
c
c
c
"}
(12,1,1) = {"
c
c
a
a
a
a
a
a
a
a
a
a
c
c
c
"}
(13,1,1) = {"
c
c
c
a
a
a
a
a
a
a
c
a
c
c
c
"}
(14,1,1) = {"
c
c
c
c
c
c
c
c
c
c
c
c
c
c
c
"}
(15,1,1) = {"
c
c
c
c
c
c
c
c
c
c
c
c
c
c
c
"}
+8
View File
@@ -216,3 +216,11 @@
#define BB_BASIC_MOB_CURRENT_TARGET "BB_basic_current_target"
#define BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION "BB_basic_current_target_hiding_location"
#define BB_TARGETTING_DATUM "targetting_datum"
///some behaviors that check current_target also set this on deep crit mobs
#define BB_BASIC_MOB_EXECUTION_TARGET "BB_basic_execution_target"
///Bileworm AI keys
#define BB_BILEWORM_SPEW_BILE "BB_bileworm_spew_bile"
#define BB_BILEWORM_RESURFACE "BB_bileworm_resurface"
#define BB_BILEWORM_DEVOUR "BB_bileworm_devour"
@@ -94,3 +94,5 @@
///From obj/item/toy/crayon/spraycan
#define COMSIG_LIVING_MOB_PAINTED "living_mob_painted"
///From mob/living/proc/wabbajack_act
#define COMSIG_LIVING_WABBAJACKED "living_wabbajacked"
+12 -7
View File
@@ -94,13 +94,7 @@
// "Shared cooldowns" covers actions which are not the same type,
// but have the same cooldown group and are on the same mob
if(shared_cooldown)
for(var/datum/action/cooldown/shared_ability in owner.actions - src)
if(!(shared_cooldown & shared_ability.shared_cooldown))
continue
if(isnum(override_cooldown_time))
shared_ability.StartCooldownSelf(override_cooldown_time)
else
shared_ability.StartCooldownSelf(cooldown_time)
StartCooldownOthers(override_cooldown_time)
StartCooldownSelf(override_cooldown_time)
@@ -119,6 +113,17 @@
UpdateButtons()
START_PROCESSING(SSfastprocess, src)
/// Starts a cooldown time for other abilities that share a cooldown with this. Has some niche usage with more complicated attack ai!
/// Will use default cooldown time if an override is not specified
/datum/action/cooldown/proc/StartCooldownOthers(override_cooldown_time)
for(var/datum/action/cooldown/shared_ability in owner.actions - src)
if(!(shared_cooldown & shared_ability.shared_cooldown))
continue
if(isnum(override_cooldown_time))
shared_ability.StartCooldownSelf(override_cooldown_time)
else
shared_ability.StartCooldownSelf(cooldown_time)
/datum/action/cooldown/Trigger(trigger_flags, atom/target)
. = ..()
if(!.)
+2 -3
View File
@@ -240,9 +240,8 @@
if(!islist(dirs))
dirs = GLOB.alldirs.Copy()
playsound(firer, projectile_sound, 200, TRUE, 2)
for(var/d in dirs)
var/turf/E = get_step(firer, d)
shoot_projectile(firer, E, null, firer, null, null)
for(var/dir in dirs)
shoot_projectile(firer, target, dir2angle(dir), firer)
/datum/action/cooldown/mob_cooldown/projectile_attack/dir_shots/alternating
name = "Alternating Shots"
@@ -0,0 +1,25 @@
/datum/ai_behavior/try_mob_ability
/datum/ai_behavior/try_mob_ability/perform(delta_time, datum/ai_controller/controller, ability_key, target_key)
var/datum/action/cooldown/mob_cooldown/ability = controller.blackboard[ability_key]
var/mob/living/target = controller.blackboard[target_key]
if(!ability || !target)
finish_action(controller, FALSE, ability_key, target_key)
var/mob/pawn = controller.pawn
var/result = ability.InterceptClickOn(pawn, null, target)
finish_action(controller, result, ability_key, target_key)
/datum/ai_behavior/try_mob_ability/finish_action(datum/ai_controller/controller, succeeded, ability_key, target_key)
. = ..()
var/mob/living/target = controller.blackboard[target_key]
if(!target || QDELETED(target) || target.stat >= UNCONSCIOUS)
controller.blackboard[target_key] = null
///subtype of normal mob ability that moves the target into a special execution targetting.
///doesn't need another subtype to clear BB_BASIC_MOB_EXECUTION_TARGET because it will be the target key for above type
/datum/ai_behavior/try_mob_ability/and_plan_execute
/datum/ai_behavior/try_mob_ability/and_plan_execute/finish_action(datum/ai_controller/controller, succeeded, ability_key, target_key)
controller.blackboard[BB_BASIC_MOB_EXECUTION_TARGET] = controller.blackboard[target_key]
return ..()
@@ -20,6 +20,3 @@
return
controller.queue_behavior(ranged_attack_behavior, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETTING_DATUM, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION)
return SUBTREE_RETURN_FINISH_PLANNING //we are going into battle...no distractions.
+28
View File
@@ -0,0 +1,28 @@
/**
* Content Barfer; which expels the contents of a mob when it dies, or is transformed
*
* Used for morphs and bileworms!
*/
/datum/element/content_barfer
element_flags = ELEMENT_DETACH
id_arg_index = 2
/datum/element/content_barfer/Attach(datum/target, tally_string)
. = ..()
if(!isliving(target))
return ELEMENT_INCOMPATIBLE
RegisterSignal(target, list(COMSIG_LIVING_DEATH, COMSIG_LIVING_WABBAJACKED), .proc/barf_contents)
/datum/element/content_barfer/Detach(datum/target)
UnregisterSignal(target, list(COMSIG_LIVING_DEATH, COMSIG_LIVING_WABBAJACKED))
return ..()
/datum/element/content_barfer/proc/barf_contents(mob/living/target)
SIGNAL_HANDLER
for(var/atom/movable/barfed_out in target)
barfed_out.forceMove(target.loc)
if(prob(90))
step(barfed_out, pick(GLOB.alldirs))
+42
View File
@@ -0,0 +1,42 @@
/**
* Crusher Loot; which makes the attached mob drop a crusher trophy of some type if the majority damage was from a crusher!
*
* Used for all the mobs droppin' crusher trophies
*/
/datum/element/crusher_loot
element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH
id_arg_index = 2
/// Path of the trophy dropped
var/trophy_type
/// chance to drop the trophy, lowered by the mob only taking partial crusher damage instead of full
/// for example, 25% would mean ~4 mobs need to die before you find one.
/// but it would be more if you didn't deal full crusher damage to them.
var/drop_mod
/// If true, will immediately spawn the item instead of putting it in butcher loot.
var/drop_immediately
/datum/element/crusher_loot/Attach(datum/target, trophy_type, drop_mod = 25, drop_immediately = FALSE)
. = ..()
if(!isliving(target))
return ELEMENT_INCOMPATIBLE
RegisterSignal(target, COMSIG_LIVING_DEATH, .proc/on_death)
src.trophy_type = trophy_type
src.drop_mod = drop_mod
src.drop_immediately = drop_immediately
/datum/element/crusher_loot/Detach(datum/target)
UnregisterSignal(target, COMSIG_LIVING_DEATH)
return ..()
/datum/element/crusher_loot/proc/on_death(mob/living/target, gibbed)
SIGNAL_HANDLER
var/datum/status_effect/crusher_damage/damage = target.has_status_effect(/datum/status_effect/crusher_damage)
if(damage && prob((damage.total_damage/target.maxHealth) * drop_mod)) //on average, you'll need to kill 4 creatures before getting the item. by default.
if(drop_immediately)
new trophy_type(get_turf(target))
else
target.butcher_results[trophy_type] = 1
+29
View File
@@ -0,0 +1,29 @@
/**
* Mob Killed Tally; which ticks up a blackbox when the mob dies
*
* Used for all the mining mobs!
*/
/datum/element/mob_killed_tally
element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH
id_arg_index = 2
/// Which tally needs to be ticked up in the blackbox
var/tally_string
/datum/element/mob_killed_tally/Attach(datum/target, tally_string)
. = ..()
if(!isliving(target))
return ELEMENT_INCOMPATIBLE
RegisterSignal(target, COMSIG_LIVING_DEATH, .proc/on_death)
src.tally_string = tally_string
/datum/element/mob_killed_tally/Detach(datum/target)
UnregisterSignal(target, COMSIG_LIVING_DEATH)
return ..()
/datum/element/mob_killed_tally/proc/on_death(mob/living/target, gibbed)
SIGNAL_HANDLER
SSblackbox.record_feedback("tally", tally_string, 1, target.type)
@@ -3,11 +3,18 @@
closed_turf_types = list(/turf/closed/mineral/random/volcanic = 1)
mob_spawn_list = list(/mob/living/simple_animal/hostile/asteroid/goliath/beast/random = 50, /obj/structure/spawner/lavaland/goliath = 3, \
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/random = 40, /obj/structure/spawner/lavaland = 2, \
/mob/living/simple_animal/hostile/asteroid/hivelord/legion/random = 30, /obj/structure/spawner/lavaland/legion = 3, \
SPAWN_MEGAFAUNA = 4, /mob/living/simple_animal/hostile/asteroid/goldgrub = 10,
/mob/living/simple_animal/hostile/asteroid/lobstrosity/lava = 20, /mob/living/simple_animal/hostile/asteroid/brimdemon = 20
mob_spawn_list = list(
/mob/living/simple_animal/hostile/asteroid/goliath/beast/random = 50,
/obj/structure/spawner/lavaland/goliath = 3,
/mob/living/simple_animal/hostile/asteroid/basilisk/watcher/random = 40,
/obj/structure/spawner/lavaland = 2,
/mob/living/simple_animal/hostile/asteroid/hivelord/legion/random = 30,
/obj/structure/spawner/lavaland/legion = 3,
SPAWN_MEGAFAUNA = 4,
/mob/living/simple_animal/hostile/asteroid/goldgrub = 10,
/mob/living/simple_animal/hostile/asteroid/lobstrosity/lava = 20,
/mob/living/simple_animal/hostile/asteroid/brimdemon = 20,
/mob/living/basic/bileworm = 20,
)
flora_spawn_list = list(/obj/structure/flora/ash/leaf_shroom = 2 , /obj/structure/flora/ash/cap_shroom = 2 , /obj/structure/flora/ash/stem_shroom = 2 , /obj/structure/flora/ash/cacti = 1, /obj/structure/flora/ash/tall_shroom = 2, /obj/structure/flora/ash/seraka = 2)
///Note that this spawn list is also in the icemoon generator
+8
View File
@@ -253,3 +253,11 @@
suffix = "lavaland_surface_elephant_graveyard.dmm"
allow_duplicates = FALSE
cost = 10
/datum/map_template/ruin/lavaland/bileworm_nest
name = "Bileworm Nest"
id = "bileworm_nest"
description = "A small sanctuary from the harsh wilderness... if you're a bileworm, that is."
cost = 5
suffix = "lavaland_surface_bileworm_nest.dmm"
allow_duplicates = FALSE
+5
View File
@@ -847,6 +847,11 @@
name = "monkey meat"
foodtypes = RAW | MEAT
/obj/item/food/meat/slab/bugmeat
name = "bug meat"
icon_state = "spidermeat"
foodtypes = RAW | MEAT | BUGS
/obj/item/food/meat/slab/mouse
name = "mouse meat"
desc = "A slab of mouse meat. Best not eat it raw."
+5
View File
@@ -92,6 +92,11 @@
base_icon_state = "asteroid_dug"
icon_state = "asteroid_dug"
/turf/open/misc/asteroid/lavaland_atmos
initial_gas_mix = LAVALAND_DEFAULT_ATMOS
planetary_atmos = TRUE
baseturfs = /turf/open/misc/asteroid/lavaland_atmos
/// Used by ashstorms to replenish basalt tiles that have been dug up without going through all of them.
GLOBAL_LIST_EMPTY(dug_up_basalt)
+1 -11
View File
@@ -47,6 +47,7 @@
. = ..()
ADD_TRAIT(src, TRAIT_ALERT_GHOSTS_ON_DEATH, INNATE_TRAIT)
ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
AddElement(/datum/element/content_barfer)
/mob/living/simple_animal/hostile/morph/examine(mob/user)
if(morphed)
@@ -148,19 +149,8 @@
visible_message(span_warning("[src] twists and dissolves into a pile of green flesh!"), \
span_userdanger("Your skin ruptures! Your flesh breaks apart! No disguise can ward off de--"))
restore()
barf_contents()
..()
/mob/living/simple_animal/hostile/morph/proc/barf_contents()
for(var/atom/movable/AM in src)
AM.forceMove(loc)
if(prob(90))
step(AM, pick(GLOB.alldirs))
/mob/living/simple_animal/hostile/morph/wabbajack_act(mob/living/new_mob)
barf_contents()
. = ..()
/mob/living/simple_animal/hostile/morph/Aggro() // automated only
..()
if(morphed)
@@ -23,3 +23,9 @@
id = "mothscream"
real_samples = list("60"='sound/voice/moth/scream_moth.ogg')
admin_only = TRUE
/datum/instrument/fun/bilehorn
name = "Bilehorn"
id = "bilehorn"
real_samples = list("60"='sound/creatures/bileworm/bileworm_spit.ogg')
admin_only = TRUE
@@ -223,21 +223,20 @@
else
..()
/obj/item/crusher_trophy/proc/add_to(obj/item/kinetic_crusher/H, mob/living/user)
for(var/t in H.trophies)
var/obj/item/crusher_trophy/T = t
if(istype(T, denied_type) || istype(src, T.denied_type))
to_chat(user, span_warning("You can't seem to attach [src] to [H]. Maybe remove a few trophies?"))
/obj/item/crusher_trophy/proc/add_to(obj/item/kinetic_crusher/crusher, mob/living/user)
for(var/obj/item/crusher_trophy/trophy as anything in crusher.trophies)
if(istype(trophy, denied_type) || istype(src, trophy.denied_type))
to_chat(user, span_warning("You can't seem to attach [src] to [crusher]. Maybe remove a few trophies?"))
return FALSE
if(!user.transferItemToLoc(src, H))
if(!user.transferItemToLoc(src, crusher))
return
H.trophies += src
to_chat(user, span_notice("You attach [src] to [H]."))
crusher.trophies += src
to_chat(user, span_notice("You attach [src] to [crusher]."))
return TRUE
/obj/item/crusher_trophy/proc/remove_from(obj/item/kinetic_crusher/H, mob/living/user)
forceMove(get_turf(H))
H.trophies -= src
/obj/item/crusher_trophy/proc/remove_from(obj/item/kinetic_crusher/crusher, mob/living/user)
forceMove(get_turf(crusher))
crusher.trophies -= src
return TRUE
/obj/item/crusher_trophy/proc/on_melee_hit(mob/living/target, mob/living/user) //the target and the user
@@ -0,0 +1,56 @@
/mob/living/basic/bileworm
name = "bileworm"
desc = "Bileworms are dangerous detritivores that attack with the highly acidic bile they produce from consuming detritus."
icon = 'icons/mob/lavaland/bileworm.dmi'
icon_state = "bileworm"
icon_living = "bileworm"
icon_dead = "bileworm_dead"
mob_size = MOB_SIZE_LARGE
mob_biotypes = MOB_BUG
maxHealth = 150
health = 150
verb_say = "spittles"
verb_ask = "spittles questioningly"
verb_exclaim = "splutters and gurgles"
verb_yell = "splutters and gurgles"
butcher_results = list(/obj/item/food/meat/slab/bugmeat = 4)
guaranteed_butcher_results = list(
/obj/effect/gibspawner/generic = 1,
/obj/item/stack/sheet/animalhide/bileworm = 1,
)
//it can't be dragged, just butcher it
move_resist = INFINITY
//doesn't melee, at all.
//or move normally.
combat_mode = TRUE
faction = list("mining")
ai_controller = /datum/ai_controller/basic_controller/bileworm
/mob/living/basic/bileworm/Initialize(mapload)
. = ..()
//traits and elements
ADD_TRAIT(src, TRAIT_IMMOBILIZED, INNATE_TRAIT)
ADD_TRAIT(src, TRAIT_LAVA_IMMUNE, INNATE_TRAIT)
ADD_TRAIT(src, TRAIT_ASHSTORM_IMMUNE, INNATE_TRAIT)
AddElement(/datum/element/basic_body_temp_sensitive, max_body_temp = INFINITY)
AddElement(/datum/element/crusher_loot, /obj/item/crusher_trophy/bileworm_spewlet, 15)
AddElement(/datum/element/mob_killed_tally, "mobs_killed_mining")
AddElement(/datum/element/content_barfer)
//setup mob abilities
var/datum/action/cooldown/mob_cooldown/projectile_attack/dir_shots/bileworm/spew_bile = new(src)
spew_bile.Grant(src)
//well, one of them has to start on infinite cooldown
spew_bile.StartCooldownSelf(INFINITY)
var/datum/action/cooldown/mob_cooldown/resurface/resurface = new(src)
resurface.Grant(src)
var/datum/action/cooldown/mob_cooldown/devour/devour = new(src)
devour.Grant(src)
ai_controller.blackboard[BB_BILEWORM_SPEW_BILE] = spew_bile
ai_controller.blackboard[BB_BILEWORM_RESURFACE] = resurface
ai_controller.blackboard[BB_BILEWORM_DEVOUR] = devour
@@ -0,0 +1,123 @@
/datum/action/cooldown/mob_cooldown/resurface
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
/datum/action/cooldown/mob_cooldown/resurface/Activate(atom/target_atom)
StartCooldownSelf(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)
var/turf/unburrow_turf = get_unburrow_turf(burrower, target)
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!"))
return //just put it on cooldown and let the other ability reactivate, you couldn't burrow and that's okay.
playsound(burrower, 'sound/effects/break_stone.ogg', 50, TRUE)
new /obj/effect/temp_visual/mook_dust(get_turf(burrower))
burrower.status_flags |= GODMODE
burrower.invisibility = INVISIBILITY_MAXIMUM
burrower.forceMove(unburrow_turf)
//not that it's gonna die with godmode but still
SLEEP_CHECK_DEATH(rand(0.75 SECONDS, 1.25 SECONDS), burrower)
playsound(burrower, 'sound/effects/break_stone.ogg', 50, TRUE)
new /obj/effect/temp_visual/mook_dust(unburrow_turf)
burrower.status_flags &= ~GODMODE
burrower.invisibility = 0
/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
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
name = "Spew Bile"
desc = "Spews bile everywhere. Must resurface after use to refresh."
projectile_type = /obj/projectile/bileworm_acid
projectile_sound = 'sound/creatures/bileworm/bileworm_spit.ogg'
shared_cooldown = MOB_SHARED_COOLDOWN_1 | MOB_SHARED_COOLDOWN_2
/datum/action/cooldown/mob_cooldown/projectile_attack/dir_shots/bileworm/Activate(atom/target_atom)
StartCooldownSelf(INFINITY)
attack_sequence(owner, target_atom)
//resurface now off cooldown shortly
StartCooldownOthers(1.5 SECONDS)
/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.25 SECONDS, firer)
fire_in_directions(firer, target, GLOB.diagonals)
SLEEP_CHECK_DEATH(0.25 SECONDS, firer)
fire_in_directions(firer, target, GLOB.cardinals)
/obj/projectile/bileworm_acid
name = "acidic bile"
icon_state = "neurotoxin"
hitsound = 'sound/weapons/sear.ogg'
damage = 20
armour_penetration = 100
speed = 2
jitter = 3 SECONDS
stutter = 3 SECONDS
damage_type = BURN
pass_flags = PASSTABLE
/datum/action/cooldown/mob_cooldown/devour
name = "Devour"
desc = "Burrow underground, and then move to your target to consume them. Short cooldown, but your target must be unconscious."
shared_cooldown = MOB_SHARED_COOLDOWN_2
/datum/action/cooldown/mob_cooldown/devour/Activate(atom/target_atom)
if(target_atom == owner)
to_chat(owner, span_warning("You can't eat yourself!"))
return
if(!isliving(target_atom))
to_chat(owner, span_warning("That's not food!"))
return
var/mob/living/living_target = target_atom
if(living_target.stat < UNCONSCIOUS)
to_chat(owner, span_warning("No way you're eating that while it's still kicking! It should at least be unconscious first."))
return
burrow_and_devour(owner, living_target)
/datum/action/cooldown/mob_cooldown/devour/proc/burrow_and_devour(mob/living/devourer, mob/living/target)
var/turf/devour_turf = get_turf(target)
if(!istype(devour_turf, /turf/open/misc)) // means all the turfs nearby are station turfs or something, not lavaland
to_chat(devourer, span_warning("Your target is on something you can't burrow through!"))
return //this will give up on devouring the target which is fine by me
playsound(devourer, 'sound/effects/break_stone.ogg', 50, TRUE)
new /obj/effect/temp_visual/mook_dust(get_turf(devourer))
devourer.status_flags |= GODMODE
devourer.invisibility = INVISIBILITY_MAXIMUM
devourer.forceMove(devour_turf)
//not that it's gonna die with godmode but still
SLEEP_CHECK_DEATH(rand(0.75 SECONDS, 1.25 SECONDS), devourer)
playsound(devourer, 'sound/effects/break_stone.ogg', 50, TRUE)
new /obj/effect/temp_visual/mook_dust(devour_turf)
devourer.status_flags &= ~GODMODE
devourer.invisibility = 0
if(!(target in devour_turf))
to_chat(devourer, span_warning("Someone stole your dinner!"))
return
to_chat(target, span_userdanger("You are consumed by [devourer]!"))
devourer.visible_message("[devourer] consumes [target]!")
devourer.fully_heal()
playsound(devourer, 'sound/effects/splat.ogg', 50, TRUE)
//to be recieved on death
target.forceMove(devourer)
@@ -0,0 +1,39 @@
/datum/ai_controller/basic_controller/bileworm
blackboard = list(
BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(),
)
planning_subtrees = list(
/datum/ai_planning_subtree/simple_find_target,
/datum/ai_planning_subtree/bileworm_attack,
/datum/ai_planning_subtree/bileworm_execute,
)
/datum/ai_planning_subtree/bileworm_attack
/datum/ai_planning_subtree/bileworm_attack/SelectBehaviors(datum/ai_controller/controller, delta_time)
var/atom/target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET]
if(!target || QDELETED(target))
return
var/datum/action/cooldown/mob_cooldown/resurface = controller.blackboard[BB_BILEWORM_RESURFACE]
//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.next_use_time <= world.time)
controller.queue_behavior(/datum/ai_behavior/try_mob_ability/and_plan_execute, BB_BILEWORM_RESURFACE, BB_BASIC_MOB_CURRENT_TARGET)
else
controller.queue_behavior(/datum/ai_behavior/try_mob_ability/and_plan_execute, BB_BILEWORM_SPEW_BILE, BB_BASIC_MOB_CURRENT_TARGET)
return SUBTREE_RETURN_FINISH_PLANNING //focus on the fight
/datum/ai_planning_subtree/bileworm_execute
/datum/ai_planning_subtree/bileworm_execute/SelectBehaviors(datum/ai_controller/controller, delta_time)
var/mob/living/target = controller.blackboard[BB_BASIC_MOB_EXECUTION_TARGET]
if(!target || QDELETED(target) || target.stat < UNCONSCIOUS)
return
controller.queue_behavior(/datum/ai_behavior/try_mob_ability, BB_BILEWORM_DEVOUR, BB_BASIC_MOB_EXECUTION_TARGET)
return SUBTREE_RETURN_FINISH_PLANNING //focus on devouring this fool
@@ -0,0 +1,18 @@
/obj/item/instrument/bilehorn
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/lavaland/bileworm.dmi'
icon_state = "bilehorn"
allowed_instrument_ids = "bilehorn"
inhand_icon_state = "bilehorn"
/datum/crafting_recipe/bilehorn
name = "Bilehorn"
reqs = list(
/obj/item/stack/sheet/animalhide/bileworm = 4,
/obj/item/stack/sheet/bone = 2,
/obj/item/crusher_trophy/bileworm_spewlet = 1,
)
result = /obj/item/instrument/bilehorn
category = CAT_PRIMAL
@@ -0,0 +1,58 @@
//skin
/obj/item/stack/sheet/animalhide/bileworm
name = "bileworm skin"
desc = "The slushy, squishy and slightly shiny skin of a postmortem bileworm."
singular_name = "bileworm skin piece"
icon = 'icons/mob/lavaland/bileworm.dmi'
icon_state = "sheet-bileworm"
inhand_icon_state = "sheet-bileworm"
merge_type = /obj/item/stack/sheet/animalhide/bileworm
//trophy
/obj/item/crusher_trophy/bileworm_spewlet
name = "bileworm spewlet"
icon = 'icons/mob/lavaland/bileworm.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
///item ability that handles the effect
var/datum/action/cooldown/mob_cooldown/projectile_attack/dir_shots/spewlet/ability
/obj/item/crusher_trophy/bileworm_spewlet/Initialize(mapload)
. = ..()
ability = new()
/obj/item/crusher_trophy/bileworm_spewlet/Destroy(force)
. = ..()
QDEL_NULL(ability)
/obj/item/crusher_trophy/bileworm_spewlet/add_to(obj/item/kinetic_crusher/crusher, mob/living/user)
. = ..()
if(.)
crusher.add_item_action(ability)
/obj/item/crusher_trophy/bileworm_spewlet/remove_from(obj/item/kinetic_crusher/crusher, mob/living/user)
. = ..()
crusher.remove_item_action(ability)
/obj/item/crusher_trophy/bileworm_spewlet/effect_desc()
return "mark detonation launches projectiles in cardinal directions on a 10 second cooldown"
/obj/item/crusher_trophy/bileworm_spewlet/on_mark_detonation(mob/living/target, mob/living/user)
//ability itself handles cooldowns.
ability.InterceptClickOn(user, null, target)
//yes this is a /mob_cooldown subtype being added to an item. I can't recommend you do what I'm doing
/datum/action/cooldown/mob_cooldown/projectile_attack/dir_shots/spewlet
check_flags = NONE
owner_has_control = FALSE
cooldown_time = 10 SECONDS
projectile_type = /obj/projectile/bileworm_acid
projectile_sound = 'sound/creatures/bileworm/bileworm_spit.ogg'
/datum/action/cooldown/mob_cooldown/projectile_attack/dir_shots/spewlet/New(Target)
firing_directions = GLOB.cardinals.Copy()
return ..()
+1
View File
@@ -1419,6 +1419,7 @@
// Generally the mob we are currently in is about to be deleted
/mob/living/proc/wabbajack_act(mob/living/new_mob)
log_message("was wabbajack polymorphed into: [new_mob.name]([new_mob.type]).", LOG_GAME)
SEND_SIGNAL(src, COMSIG_LIVING_WABBAJACKED, new_mob)
new_mob.name = real_name
new_mob.real_name = real_name
@@ -53,9 +53,6 @@
OpenFire()
return TRUE
/mob/living/simple_animal/hostile/asteroid/hivelord/spawn_crusher_loot()
loot += crusher_loot //we don't butcher
/mob/living/simple_animal/hostile/asteroid/hivelord/death(gibbed)
mouse_opacity = MOUSE_OPACITY_ICON
..(gibbed)
@@ -74,9 +74,6 @@
SLEEP_CHECK_DEATH(8, src)
return ..()
/mob/living/simple_animal/hostile/asteroid/ice_demon/spawn_crusher_loot()
loot += crusher_loot
/mob/living/simple_animal/hostile/asteroid/ice_demon/death(gibbed)
move_force = MOVE_FORCE_DEFAULT
move_resist = MOVE_RESIST_DEFAULT
@@ -13,15 +13,24 @@
response_harm_simple = "strike"
status_flags = 0
combat_mode = TRUE
var/crusher_loot
var/throw_message = "bounces off of"
var/fromtendril = FALSE
see_in_dark = 8
lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE
mob_size = MOB_SIZE_LARGE
var/icon_aggro = null
///what trophy this mob drops
var/crusher_loot
///what is the chance the mob drops it if all their health was taken by crusher attacks
var/crusher_drop_mod = 25
/mob/living/simple_animal/hostile/asteroid/Initialize(mapload)
. = ..()
if(crusher_loot)
AddElement(/datum/element/crusher_loot, crusher_loot, crusher_drop_mod, del_on_death)
AddElement(/datum/element/mob_killed_tally, "mobs_killed_mining")
/mob/living/simple_animal/hostile/asteroid/Aggro()
..()
if(vision_range == aggro_vision_range && icon_aggro)
@@ -50,21 +59,3 @@
visible_message(span_notice("The [T.name] [throw_message] [src.name]!"))
return
..()
/mob/living/simple_animal/hostile/asteroid/death(gibbed)
SSblackbox.record_feedback("tally", "mobs_killed_mining", 1, type)
var/datum/status_effect/crusher_damage/C = has_status_effect(/datum/status_effect/crusher_damage)
var/crusher_loot_spawned = FALSE //SKYRAT ADDITION
if(C && crusher_loot && prob((C.total_damage/maxHealth) * crusher_drop_mod)) //on average, you'll need to kill 4 creatures before getting the item
spawn_crusher_loot()
crusher_loot_spawned = TRUE //SKYRAT ADDITION
//SKYRAT ADDITION START - ASHWALKER TROPHIES
var/datum/status_effect/ashwalker_damage/ashie_damage = has_status_effect(/datum/status_effect/ashwalker_damage)
if(!crusher_loot_spawned && ashie_damage && crusher_loot && prob((ashie_damage.total_damage / maxHealth) * crusher_drop_mod))
spawn_crusher_loot()
crusher_loot_spawned = TRUE
//SKYRAT ADDITION END
..(gibbed)
/mob/living/simple_animal/hostile/asteroid/proc/spawn_crusher_loot()
butcher_results[crusher_loot] = 1
@@ -105,6 +105,7 @@
ADD_TRAIT(src, TRAIT_NO_FLOATING_ANIM, INNATE_TRAIT)
ADD_TRAIT(src, TRAIT_HEALS_FROM_CARP_RIFTS, INNATE_TRAIT)
ADD_TRAIT(src, TRAIT_ALERT_GHOSTS_ON_DEATH, INNATE_TRAIT)
AddElement(/datum/element/content_barfer)
small_sprite = new
small_sprite.Grant(src)
RegisterSignal(small_sprite, COMSIG_ACTION_TRIGGER, .proc/add_dragon_overlay)
@@ -141,9 +142,9 @@
return
if(riftTimer >= maxRiftTimer)
to_chat(src, span_boldwarning("You've failed to summon the rift in a timely manner! You're being pulled back from whence you came!"))
destroy_rifts()
death(TRUE)
playsound(src, 'sound/magic/demon_dies.ogg', 100, TRUE)
QDEL_NULL(src)
qdel(src)
/mob/living/simple_animal/hostile/space_dragon/AttackingTarget()
if(using_special)
Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 13 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.2 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 92 KiB

After

Width:  |  Height:  |  Size: 85 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 129 KiB

After

Width:  |  Height:  |  Size: 123 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 89 KiB

After

Width:  |  Height:  |  Size: 84 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 37 KiB

After

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 23 KiB

After

Width:  |  Height:  |  Size: 22 KiB

@@ -15,6 +15,3 @@
humi.coretemperature = humi.get_body_temp_normal()
..()
/mob/living/simple_animal/hostile/asteroid/ice_demon/spawn_crusher_loot()
for(var/item_path in crusher_loot)
new item_path(loc)
Binary file not shown.
+9
View File
@@ -738,6 +738,7 @@
#include "code\datums\ai\basic_mobs\basic_ai_behaviors\basic_attacking.dm"
#include "code\datums\ai\basic_mobs\basic_ai_behaviors\targetting.dm"
#include "code\datums\ai\basic_mobs\basic_ai_behaviors\tipped_reaction.dm"
#include "code\datums\ai\basic_mobs\basic_ai_behaviors\try_mob_ability.dm"
#include "code\datums\ai\basic_mobs\basic_subtrees\simple_attack_target.dm"
#include "code\datums\ai\basic_mobs\basic_subtrees\simple_find_target.dm"
#include "code\datums\ai\basic_mobs\basic_subtrees\speech_subtree.dm"
@@ -1045,7 +1046,9 @@
#include "code\datums\elements\cleaning.dm"
#include "code\datums\elements\climbable.dm"
#include "code\datums\elements\connect_loc.dm"
#include "code\datums\elements\content_barfer.dm"
#include "code\datums\elements\crackable.dm"
#include "code\datums\elements\crusher_loot.dm"
#include "code\datums\elements\cult_eyes.dm"
#include "code\datums\elements\cult_halo.dm"
#include "code\datums\elements\curse_announcement.dm"
@@ -1078,6 +1081,7 @@
#include "code\datums\elements\light_blocking.dm"
#include "code\datums\elements\light_eaten.dm"
#include "code\datums\elements\light_eater.dm"
#include "code\datums\elements\mob_killed_tally.dm"
#include "code\datums\elements\movement_turf_changer.dm"
#include "code\datums\elements\movetype_handler.dm"
#include "code\datums\elements\nerfed_pulling.dm"
@@ -3461,6 +3465,11 @@
#include "code\modules\mob\living\basic\basic_defense.dm"
#include "code\modules\mob\living\basic\health_adjustment.dm"
#include "code\modules\mob\living\basic\farm_animals\cows.dm"
#include "code\modules\mob\living\basic\lavaland\bileworm\_bileworm.dm"
#include "code\modules\mob\living\basic\lavaland\bileworm\bileworm_actions.dm"
#include "code\modules\mob\living\basic\lavaland\bileworm\bileworm_ai.dm"
#include "code\modules\mob\living\basic\lavaland\bileworm\bileworm_instrument.dm"
#include "code\modules\mob\living\basic\lavaland\bileworm\bileworm_loot.dm"
#include "code\modules\mob\living\basic\ruin_defender\stickman.dm"
#include "code\modules\mob\living\basic\vermin\cockroach.dm"
#include "code\modules\mob\living\basic\vermin\mothroach.dm"