diff --git a/_maps/RandomRuins/LavaRuins/lavaland_biodome_clown_planet.dmm b/_maps/RandomRuins/LavaRuins/lavaland_biodome_clown_planet.dmm
index 7ab354935c3..ef650913f14 100644
--- a/_maps/RandomRuins/LavaRuins/lavaland_biodome_clown_planet.dmm
+++ b/_maps/RandomRuins/LavaRuins/lavaland_biodome_clown_planet.dmm
@@ -671,7 +671,7 @@
/area/ruin/powered/clownplanet)
"RW" = (
/obj/effect/mapping_helpers/no_lava,
-/mob/living/simple_animal/hostile/retaliate/clown,
+/mob/living/basic/clown,
/turf/open/floor/noslip,
/area/ruin/powered/clownplanet)
"Tj" = (
@@ -714,7 +714,7 @@
"YI" = (
/obj/machinery/light/small/directional/south,
/obj/effect/mapping_helpers/no_lava,
-/mob/living/simple_animal/hostile/retaliate/clown,
+/mob/living/basic/clown,
/turf/open/floor/noslip,
/area/ruin/powered/clownplanet)
"Zg" = (
diff --git a/_maps/RandomRuins/SpaceRuins/clownplanet.dmm b/_maps/RandomRuins/SpaceRuins/clownplanet.dmm
index b0cc8cc29e2..fa0b50cc443 100644
--- a/_maps/RandomRuins/SpaceRuins/clownplanet.dmm
+++ b/_maps/RandomRuins/SpaceRuins/clownplanet.dmm
@@ -26,7 +26,7 @@
/turf/open/floor/engine,
/area/ruin/space/has_grav/powered/clownplanet)
"ah" = (
-/mob/living/simple_animal/hostile/retaliate/clown/clownhulk/destroyer,
+/mob/living/basic/clown/clownhulk/destroyer,
/turf/open/floor/engine,
/area/ruin/space/has_grav/powered/clownplanet)
"ai" = (
diff --git a/code/__DEFINES/ai/ai_blackboard.dm b/code/__DEFINES/ai/ai_blackboard.dm
index c71b1a4acd5..443a51a7eb7 100644
--- a/code/__DEFINES/ai/ai_blackboard.dm
+++ b/code/__DEFINES/ai/ai_blackboard.dm
@@ -88,3 +88,11 @@
///should we skip the faction check for the targetting datum?
#define BB_BASIC_MOB_SKIP_FACTION_CHECK "BB_basic_mob_skip_faction_check"
+
+///currently only used by clowns, a list of what can the mob speak randomly
+#define BB_BASIC_MOB_SPEAK_LINES "BB_speech_lines"
+#define BB_EMOTE_SAY "emote_say"
+#define BB_EMOTE_HEAR "emote_hear"
+#define BB_EMOTE_SEE "emote_see"
+#define BB_EMOTE_SOUND "emote_sound"
+#define BB_EMOTE_CHANCE "emote_chance"
diff --git a/code/__DEFINES/is_helpers.dm b/code/__DEFINES/is_helpers.dm
index 3c4ebd9d124..a52d2d809e6 100644
--- a/code/__DEFINES/is_helpers.dm
+++ b/code/__DEFINES/is_helpers.dm
@@ -176,7 +176,7 @@ GLOBAL_LIST_INIT(turfs_pass_meteor, typecacheof(list(
#define ismegafauna(A) (istype(A, /mob/living/simple_animal/hostile/megafauna))
-#define isclown(A) (istype(A, /mob/living/simple_animal/hostile/retaliate/clown))
+#define isclown(A) (istype(A, /mob/living/basic/clown))
#define isspider(A) (istype(A, /mob/living/basic/spider/giant))
diff --git a/code/datums/ai/basic_mobs/basic_subtrees/speech_subtree.dm b/code/datums/ai/basic_mobs/basic_subtrees/speech_subtree.dm
index a04765b1a88..005a9ee835d 100644
--- a/code/datums/ai/basic_mobs/basic_subtrees/speech_subtree.dm
+++ b/code/datums/ai/basic_mobs/basic_subtrees/speech_subtree.dm
@@ -199,3 +199,19 @@
speech_chance = 5
emote_hear = list("rawrs.","grumbles.","grawls.", "stomps!")
emote_see = list("stares ferociously.")
+
+/datum/ai_planning_subtree/random_speech/blackboard //literal tower of babel, subtree form
+ speech_chance = 1
+
+/datum/ai_planning_subtree/random_speech/blackboard/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick)
+ var/list/speech_lines = controller.blackboard[BB_BASIC_MOB_SPEAK_LINES]
+ if(isnull(speech_lines))
+ return ..()
+
+ speak = speech_lines[BB_EMOTE_SAY] ? speech_lines[BB_EMOTE_SAY] : initial(speak)
+ emote_see = speech_lines[BB_EMOTE_SEE] ? speech_lines[BB_EMOTE_SEE] : initial(emote_see)
+ emote_hear = speech_lines[BB_EMOTE_HEAR] ? speech_lines[BB_EMOTE_HEAR] : initial(emote_hear)
+ sound = speech_lines[BB_EMOTE_SOUND] ? speech_lines[BB_EMOTE_SOUND] : initial(sound)
+ speech_chance = speech_lines[BB_EMOTE_CHANCE] ? speech_lines[BB_EMOTE_CHANCE] : initial(speech_chance)
+
+ return ..()
diff --git a/code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm b/code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm
index 43b974219e2..570088ce4d6 100644
--- a/code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm
+++ b/code/datums/ai/basic_mobs/targetting_datums/basic_targetting_datum.dm
@@ -124,3 +124,9 @@
/datum/targetting_datum/basic/of_size/larger
find_smaller = FALSE
inclusive = FALSE
+
+/datum/targetting_datum/basic/attack_until_dead
+ stat_attack = HARD_CRIT
+
+/datum/targetting_datum/basic/attack_even_if_dead
+ stat_attack = DEAD
diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm
index f784b2670ba..516f5ec8453 100644
--- a/code/game/machinery/syndicatebomb.dm
+++ b/code/game/machinery/syndicatebomb.dm
@@ -416,7 +416,7 @@
/obj/item/bombcore/badmin/summon/clown
name = "bananium payload"
desc = "Clowns delivered fast and cheap!"
- summon_path = /mob/living/simple_animal/hostile/retaliate/clown
+ summon_path = /mob/living/basic/clown
amt_summon = 50
/obj/item/bombcore/badmin/summon/clown/defuse()
diff --git a/code/game/objects/effects/effect_system/fluid_spread/effects_foam.dm b/code/game/objects/effects/effect_system/fluid_spread/effects_foam.dm
index 914b19e6a88..787ce602a3a 100644
--- a/code/game/objects/effects/effect_system/fluid_spread/effects_foam.dm
+++ b/code/game/objects/effects/effect_system/fluid_spread/effects_foam.dm
@@ -459,6 +459,20 @@
allow_duplicate_results = FALSE
result_type = /obj/effect/decal/cleanable/dirt
+/obj/effect/spawner/foam_starter
+ var/datum/effect_system/fluid_spread/foam/foam_type = /datum/effect_system/fluid_spread/foam
+ var/foam_size = 4
+
+/obj/effect/spawner/foam_starter/Initialize(mapload)
+ . = ..()
+
+ var/datum/effect_system/fluid_spread/foam/foam = new foam_type()
+ foam.set_up(foam_size, holder = src, location = loc)
+ foam.start()
+
+/obj/effect/spawner/foam_starter/small
+ foam_size = 2
+
#undef MINIMUM_FOAM_DILUTION_RANGE
#undef MINIMUM_FOAM_DILUTION
#undef FOAM_REAGENT_SCALE
diff --git a/code/game/objects/items/grenades/spawnergrenade.dm b/code/game/objects/items/grenades/spawnergrenade.dm
index 860812021e2..1b9d9ff27d0 100644
--- a/code/game/objects/items/grenades/spawnergrenade.dm
+++ b/code/game/objects/items/grenades/spawnergrenade.dm
@@ -61,7 +61,7 @@
desc = "A sleek device often given to clowns on their 10th birthdays for protection. You can hear faint scratching coming from within."
icon_state = "clown_ball"
inhand_icon_state = null
- spawner_type = list(/mob/living/simple_animal/hostile/retaliate/clown/fleshclown, /mob/living/simple_animal/hostile/retaliate/clown/clownhulk, /mob/living/simple_animal/hostile/retaliate/clown/longface, /mob/living/simple_animal/hostile/retaliate/clown/clownhulk/chlown, /mob/living/simple_animal/hostile/retaliate/clown/clownhulk/honcmunculus, /mob/living/simple_animal/hostile/retaliate/clown/mutant/glutton, /mob/living/simple_animal/hostile/retaliate/clown/banana, /mob/living/simple_animal/hostile/retaliate/clown/honkling, /mob/living/simple_animal/hostile/retaliate/clown/lube)
+ spawner_type = list(/mob/living/basic/clown/fleshclown, /mob/living/basic/clown/clownhulk, /mob/living/basic/clown/longface, /mob/living/basic/clown/clownhulk/chlown, /mob/living/basic/clown/clownhulk/honkmunculus, /mob/living/basic/clown/mutant/glutton, /mob/living/basic/clown/banana, /mob/living/basic/clown/honkling, /mob/living/basic/clown/lube)
deliveryamt = 1
/obj/item/grenade/spawnergrenade/clown_broken
@@ -69,5 +69,5 @@
desc = "A sleek device often given to clowns on their 10th birthdays for protection. While a typical C.L.U.W.N.E only holds one creature, sometimes foolish young clowns try to cram more in, often to disasterous effect."
icon_state = "clown_broken"
inhand_icon_state = null
- spawner_type = /mob/living/simple_animal/hostile/retaliate/clown/mutant
+ spawner_type = /mob/living/basic/clown/mutant
deliveryamt = 5
diff --git a/code/game/objects/structures/icemoon/cave_entrance.dm b/code/game/objects/structures/icemoon/cave_entrance.dm
index ded6851914b..10f7a56c7f9 100644
--- a/code/game/objects/structures/icemoon/cave_entrance.dm
+++ b/code/game/objects/structures/icemoon/cave_entrance.dm
@@ -187,7 +187,7 @@ GLOBAL_LIST_INIT(ore_probability, list(
if(24)
new /obj/structure/elite_tumor(loc)
if(25)
- new /mob/living/simple_animal/hostile/retaliate/clown/clownhulk(loc)
+ new /mob/living/basic/clown/clownhulk(loc)
if(26)
new /obj/item/clothing/shoes/winterboots/ice_boots(loc)
if(27)
diff --git a/code/game/objects/structures/spawner.dm b/code/game/objects/structures/spawner.dm
index 4e51d0900c5..db04c82815f 100644
--- a/code/game/objects/structures/spawner.dm
+++ b/code/game/objects/structures/spawner.dm
@@ -54,16 +54,16 @@
max_mobs = 15
spawn_time = 15 SECONDS
mob_types = list(
- /mob/living/simple_animal/hostile/retaliate/clown,
- /mob/living/simple_animal/hostile/retaliate/clown/banana,
- /mob/living/simple_animal/hostile/retaliate/clown/clownhulk,
- /mob/living/simple_animal/hostile/retaliate/clown/clownhulk/chlown,
- /mob/living/simple_animal/hostile/retaliate/clown/clownhulk/honcmunculus,
- /mob/living/simple_animal/hostile/retaliate/clown/fleshclown,
- /mob/living/simple_animal/hostile/retaliate/clown/mutant/glutton,
- /mob/living/simple_animal/hostile/retaliate/clown/honkling,
- /mob/living/simple_animal/hostile/retaliate/clown/longface,
- /mob/living/simple_animal/hostile/retaliate/clown/lube,
+ /mob/living/basic/clown,
+ /mob/living/basic/clown/banana,
+ /mob/living/basic/clown/clownhulk,
+ /mob/living/basic/clown/clownhulk/chlown,
+ /mob/living/basic/clown/clownhulk/honkmunculus,
+ /mob/living/basic/clown/fleshclown,
+ /mob/living/basic/clown/mutant/glutton,
+ /mob/living/basic/clown/honkling,
+ /mob/living/basic/clown/longface,
+ /mob/living/basic/clown/lube,
)
spawn_text = "climbs out of"
faction = list(FACTION_CLOWN)
diff --git a/code/modules/antagonists/wizard/equipment/artefact.dm b/code/modules/antagonists/wizard/equipment/artefact.dm
index 39d9605c3ef..3e4cf0766f5 100644
--- a/code/modules/antagonists/wizard/equipment/artefact.dm
+++ b/code/modules/antagonists/wizard/equipment/artefact.dm
@@ -86,7 +86,7 @@
/obj/item/veilrender/honkrender
name = "honk render"
desc = "A wicked curved blade of alien origin, recovered from the ruins of a vast circus."
- spawn_type = /mob/living/simple_animal/hostile/retaliate/clown
+ spawn_type = /mob/living/basic/clown
spawn_amt = 10
activate_descriptor = "depression"
rend_desc = "Gently wafting with the sounds of endless laughter."
@@ -97,7 +97,7 @@
/obj/item/veilrender/honkrender/honkhulkrender
name = "superior honk render"
desc = "A wicked curved blade of alien origin, recovered from the ruins of a vast circus. This one gleams with a special light."
- spawn_type = /mob/living/simple_animal/hostile/retaliate/clown/clownhulk
+ spawn_type = /mob/living/basic/clown/clownhulk
spawn_amt = 5
activate_descriptor = "depression"
rend_desc = "Gently wafting with the sounds of mirthful grunting."
diff --git a/code/modules/mob/living/basic/basic.dm b/code/modules/mob/living/basic/basic.dm
index 155321805c6..aebb54770d7 100644
--- a/code/modules/mob/living/basic/basic.dm
+++ b/code/modules/mob/living/basic/basic.dm
@@ -11,7 +11,7 @@
var/basic_mob_flags = NONE
- ///Defines how fast the basic mob can move. This is a multiplier
+ ///Defines how fast the basic mob can move. This is not a multiplier
var/speed = 1
///How much stamina the mob recovers per second
var/stamina_recovery = 5
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm b/code/modules/mob/living/basic/clown/clown.dm
similarity index 62%
rename from code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
rename to code/modules/mob/living/basic/clown/clown.dm
index 529c3025479..78715361356 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
+++ b/code/modules/mob/living/basic/clown/clown.dm
@@ -1,4 +1,4 @@
-/mob/living/simple_animal/hostile/retaliate/clown
+/mob/living/basic/clown
name = "Clown"
desc = "A denizen of clown planet."
icon = 'icons/mob/simple/clown_mobs.dmi'
@@ -8,73 +8,517 @@
icon_gib = "clown_gib"
health_doll_icon = "clown" //if >32x32, it will use this generic. for all the huge clown mobs that subtype from this
mob_biotypes = MOB_ORGANIC|MOB_HUMANOID
- turns_per_move = 5
response_disarm_continuous = "gently pushes aside"
response_disarm_simple = "gently push aside"
response_harm_continuous = "robusts"
response_harm_simple = "robust"
- speak = list("HONK", "Honk!", "Welcome to clown planet!")
- emote_see = list("honks", "squeaks")
- speak_chance = 1
combat_mode = TRUE
maxHealth = 75
health = 75
- speed = 1
- harm_intent_damage = 8
melee_damage_lower = 10
melee_damage_upper = 10
attack_sound = 'sound/items/bikehorn.ogg'
- obj_damage = 0
+ attacked_sound = 'sound/items/bikehorn.ogg'
environment_smash = ENVIRONMENT_SMASH_NONE
- del_on_death = 1
- loot = list(/obj/effect/mob_spawn/corpse/human/clown)
+ basic_mob_flags = DEL_ON_DEATH
initial_language_holder = /datum/language_holder/clown
- atmos_requirements = list("min_oxy" = 5, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0)
- minbodytemp = 270
- maxbodytemp = 370
+ habitable_atmos = list("min_oxy" = 5, "max_oxy" = 0, "min_plas" = 0, "max_plas" = 1, "min_co2" = 0, "max_co2" = 5, "min_n2" = 0, "max_n2" = 0)
+ minimum_survivable_temperature = T0C
+ maximum_survivable_temperature = (T0C + 100)
unsuitable_atmos_damage = 10
unsuitable_heat_damage = 15
- footstep_type = FOOTSTEP_MOB_SHOE
faction = list(FACTION_CLOWN)
- var/attack_reagent
+ ai_controller = /datum/ai_controller/basic_controller/clown
+ speed = 1.4 //roughly close to simpleanimal clowns
+ ///list of stuff we drop on death
+ var/list/loot = list(/obj/effect/mob_spawn/corpse/human/clown)
+ ///blackboard emote list
+ var/list/emotes = list(
+ BB_EMOTE_SAY = list("HONK", "Honk!", "Welcome to clown planet!"),
+ BB_EMOTE_HEAR = list("honks", "squeaks"),
+ BB_EMOTE_SOUND = list('sound/items/bikehorn.ogg'), //WE LOVE TO PARTY
+ BB_EMOTE_CHANCE = 5,
+ )
+ ///do we waddle (honk)
+ var/waddles = TRUE
-/mob/living/simple_animal/hostile/retaliate/clown/Initialize(mapload)
+/mob/living/basic/clown/Initialize(mapload)
. = ..()
- if(attack_reagent)
- var/static/list/injection_range
- if(!injection_range)
- injection_range = string_numbers_list(list(1, 5))
- AddElement(/datum/element/venomous, attack_reagent, injection_range)
+ AddElement(/datum/element/footstep, footstep_type = FOOTSTEP_MOB_SHOE)
+ AddComponent(/datum/component/ai_retaliate_advanced, CALLBACK(src, PROC_REF(retaliate_callback)))
+ ai_controller.set_blackboard_key(BB_BASIC_MOB_SPEAK_LINES, emotes)
+ //im not putting dynamic humans or whatever its called here because this is the base path of nonhuman clownstrosities
+ if(waddles)
+ AddElement(/datum/element/waddling)
+ if(length(loot))
+ loot = string_list(loot)
+ AddElement(/datum/element/death_drops, loot)
-/mob/living/simple_animal/hostile/retaliate/clown/attack_hand(mob/living/carbon/human/user, list/modifiers)
- ..()
- playsound(loc, 'sound/items/bikehorn.ogg', 50, TRUE)
+/mob/living/basic/clown/proc/retaliate_callback(mob/living/attacker)
+ if (!istype(attacker))
+ return
+ for (var/mob/living/basic/clown/harbringer in oview(src, 7))
+ harbringer.ai_controller.insert_blackboard_key_lazylist(BB_BASIC_MOB_RETALIATE_LIST, attacker)
-/mob/living/simple_animal/hostile/retaliate/clown/AttackingTarget(atom/attacked_target)
- if(!istype(attacked_target, /obj/item/food/grown/banana/bunch))
+/mob/living/basic/clown/melee_attack(atom/target, list/modifiers, ignore_cooldown = FALSE)
+ if(!istype(target, /obj/item/food/grown/banana/bunch))
return ..()
- var/obj/item/food/grown/banana/bunch/unripe_bunch = attacked_target
+ var/obj/item/food/grown/banana/bunch/unripe_bunch = target
unripe_bunch.start_ripening()
- log_combat(src, attacked_target, "honksposivley ripened")
+ log_combat(src, target, "explosively ripened")
-/mob/living/simple_animal/hostile/retaliate/clown/lube
+/mob/living/basic/clown/lube
name = "Living Lube"
desc = "A puddle of lube brought to life by the honkmother."
icon_state = "lube"
icon_living = "lube"
- turns_per_move = 1
response_help_continuous = "dips a finger into"
response_help_simple = "dip a finger into"
response_disarm_continuous = "gently scoops and pours aside"
response_disarm_simple = "gently scoop and pour aside"
- emote_see = list("bubbles", "oozes")
- loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/particle_effect/fluid/foam)
+ emotes = list(
+ BB_EMOTE_SAY = list("HONK", "Honk!", "Welcome to clown planet!"),
+ BB_EMOTE_HEAR = list("bubbles", "oozes"),
+ )
+ waddles = FALSE
+ loot = list(
+ /obj/effect/spawner/foam_starter/small,
+ /obj/item/clothing/mask/gas/clown_hat,
+ )
-/mob/living/simple_animal/hostile/retaliate/clown/lube/Initialize(mapload)
+/mob/living/basic/clown/lube/Initialize(mapload)
. = ..()
AddElement(/datum/element/snailcrawl)
-/mob/living/simple_animal/hostile/retaliate/clown/banana
+/mob/living/basic/clown/honkling
+ name = "Honkling"
+ desc = "A divine being sent by the Honkmother to spread joy. It's not dangerous, but it's a bit of a nuisance."
+ icon_state = "honkling"
+ icon_living = "honkling"
+ speed = 1.1
+ melee_damage_lower = 1
+ melee_damage_upper = 1
+ attack_verb_continuous = "cheers up"
+ attack_verb_simple = "cheer up"
+ loot = list(
+ /obj/item/clothing/mask/gas/clown_hat,
+ /obj/effect/gibspawner/human,
+ /obj/item/soap,
+ /obj/item/seeds/banana/bluespace,
+ )
+
+/mob/living/basic/clown/honkling/Initialize(mapload)
+ . = ..()
+ var/static/list/injection_range
+ if(!injection_range)
+ injection_range = string_numbers_list(list(1, 5))
+ AddElement(/datum/element/venomous, /datum/reagent/consumable/laughter, injection_range)
+
+/mob/living/basic/clown/fleshclown
+ name = "Fleshclown"
+ desc = "A being forged out of the pure essence of pranking, cursed into existence by a cruel maker."
+ icon_state = "fleshclown"
+ icon_living = "fleshclown"
+ response_help_continuous = "reluctantly pokes"
+ response_help_simple = "reluctantly poke"
+ response_disarm_continuous = "sinks his hands into the spongy flesh of"
+ response_disarm_simple = "sink your hands into the spongy flesh of"
+ response_harm_continuous = "cleanses the world of"
+ response_harm_simple = "cleanse the world of"
+ maxHealth = 140
+ health = 140
+ speed = 1
+ melee_damage_upper = 15
+ attack_verb_continuous = "limply slaps"
+ attack_verb_simple = "limply slap"
+ obj_damage = 5
+ loot = list(
+ /obj/effect/gibspawner/human,
+ /obj/item/clothing/mask/gas/clown_hat,
+ /obj/item/soap,
+ /obj/item/clothing/suit/hooded/bloated_human,
+ )
+ emotes = list(
+ BB_EMOTE_SAY = list(
+ "HONK",
+ "Honk!",
+ "I didn't ask for this",
+ "I feel constant and horrible pain",
+ "I was born out of mirthful pranking but I live in suffering",
+ "This body is a merciless and unforgiving prison",
+ "YA-HONK!!!",
+ ),
+ BB_EMOTE_HEAR = list("honks", "contemplates its existence"),
+ BB_EMOTE_SEE = list("sweats", "jiggles"),
+ BB_EMOTE_CHANCE = 5,
+ )
+
+/mob/living/basic/clown/fleshclown/Initialize(mapload)
+ . = ..()
+ ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
+
+/mob/living/basic/clown/longface
+ name = "Longface"
+ desc = "Often found walking into the bar."
+ icon_state = "long face"
+ icon_living = "long face"
+ move_resist = INFINITY
+ response_help_continuous = "tries to awkwardly hug"
+ response_help_simple = "try to awkwardly hug"
+ response_disarm_continuous = "pushes the unwieldy frame of"
+ response_disarm_simple = "push the unwieldy frame of"
+ response_harm_continuous = "tries to shut up"
+ response_harm_simple = "try to shut up"
+ maxHealth = 150
+ health = 150
+ pixel_x = -16
+ base_pixel_x = -16
+ speed = 3
+ melee_damage_lower = 5
+ attack_verb_continuous = "YA-HONKs"
+ attack_verb_simple = "YA-HONK"
+ loot = list(
+ /obj/effect/gibspawner/human,
+ /obj/item/soap,
+ /obj/item/clothing/mask/gas/clown_hat,
+ )
+ emotes = list(
+ BB_EMOTE_SAY = list("YA-HONK!!!"),
+ BB_EMOTE_HEAR = list("honks", "squeaks"),
+ BB_EMOTE_CHANCE = 60,
+ )
+
+/mob/living/basic/clown/clownhulk
+ name = "Honk Hulk"
+ desc = "A cruel and fearsome clown. Don't make him angry."
+ icon_state = "honkhulk"
+ icon_living = "honkhulk"
+ move_resist = INFINITY
+ gender = MALE
+ response_help_continuous = "tries desperately to appease"
+ response_help_simple = "try desperately to appease"
+ response_disarm_continuous = "foolishly pushes"
+ response_disarm_simple = "foolishly push"
+ response_harm_continuous = "angers"
+ response_harm_simple = "anger"
+ maxHealth = 400
+ health = 400
+ pixel_x = -16
+ base_pixel_x = -16
+ speed = 2
+ melee_damage_lower = 15
+ melee_damage_upper = 20
+ attack_verb_continuous = "pummels"
+ attack_verb_simple = "pummel"
+ obj_damage = 30
+ environment_smash = ENVIRONMENT_SMASH_WALLS
+ loot = list(
+ /obj/effect/gibspawner/human,
+ /obj/item/soap,
+ /obj/item/clothing/mask/gas/clown_hat,
+ )
+ emotes = list(
+ BB_EMOTE_SAY = list("HONK", "Honk!", "HAUAUANK!!!", "GUUURRRRAAAHHH!!!"),
+ BB_EMOTE_HEAR = list("honks", "grunts"),
+ BB_EMOTE_SEE = list("sweats"),
+ BB_EMOTE_CHANCE = 5,
+ )
+
+/mob/living/basic/clown/clownhulk/chlown
+ name = "Chlown"
+ desc = "A real lunkhead who somehow gets all the girls."
+ icon_state = "chlown"
+ icon_living = "chlown"
+ gender = MALE
+ response_help_continuous = "submits to"
+ response_help_simple = "submit to"
+ response_disarm_continuous = "tries to assert dominance over"
+ response_disarm_simple = "try to assert dominance over"
+ response_harm_continuous = "makes a weak beta attack at"
+ response_harm_simple = "make a weak beta attack at"
+ maxHealth = 500
+ health = 500
+ speed = -2 //ridicilously fast but i dont even know what this is used for
+ armour_penetration = 20
+ attack_verb_continuous = "steals the girlfriend of"
+ attack_verb_simple = "steal the girlfriend of"
+ attack_sound = 'sound/items/airhorn2.ogg'
+ loot = list(
+ /obj/effect/gibspawner/human,
+ /obj/effect/spawner/foam_starter/small,
+ /obj/item/soap,
+ /obj/item/clothing/mask/gas/clown_hat,
+ )
+ emotes = list(
+ BB_EMOTE_SAY = list("HONK", "Honk!", "Bruh", "cheeaaaahhh?"),
+ BB_EMOTE_SEE = list("asserts his dominance", "emasculates everyone implicitly"),
+ BB_EMOTE_CHANCE = 5,
+ )
+
+/mob/living/basic/clown/clownhulk/honkmunculus
+ name = "Honkmunculus"
+ desc = "A slender wiry figure of alchemical origin."
+ icon_state = "honkmunculus"
+ icon_living = "honkmunculus"
+ response_help_continuous = "skeptically pokes"
+ response_help_simple = "skeptically poke"
+ response_disarm_continuous = "pushes the unwieldy frame of"
+ response_disarm_simple = "push the unwieldy frame of"
+ maxHealth = 200
+ health = 200
+ speed = 1
+ melee_damage_lower = 5
+ melee_damage_upper = 10
+ attack_verb_continuous = "ferociously mauls"
+ attack_verb_simple = "ferociously maul"
+ environment_smash = ENVIRONMENT_SMASH_NONE
+ loot = list(
+ /obj/effect/gibspawner/xeno/bodypartless,
+ /obj/effect/spawner/foam_starter/small,
+ /obj/item/soap,
+ /obj/item/clothing/mask/gas/clown_hat,
+ )
+ emotes = list(
+ BB_EMOTE_SAY = list("honk"),
+ BB_EMOTE_SEE = list("squirms", "writhes"),
+ )
+
+/mob/living/basic/clown/clownhulk/honkmunculus/Initialize(mapload)
+ . = ..()
+ var/static/list/injection_range
+ if(!injection_range)
+ injection_range = string_numbers_list(list(1, 5))
+ AddElement(/datum/element/venomous, /datum/reagent/peaceborg/confuse, injection_range)
+
+/mob/living/basic/clown/clownhulk/destroyer
+ name = "The Destroyer"
+ desc = "An ancient being born of arcane honking."
+ icon_state = "destroyer"
+ icon_living = "destroyer"
+ response_disarm_continuous = "bounces off of"
+ response_harm_continuous = "bounces off of"
+ maxHealth = 400
+ health = 400
+ speed = 5
+ melee_damage_lower = 20
+ melee_damage_upper = 40
+ armour_penetration = 30
+ attack_verb_continuous = "acts out divine vengeance on"
+ attack_verb_simple = "act out divine vengeance on"
+ obj_damage = 50
+ environment_smash = ENVIRONMENT_SMASH_RWALLS
+ ai_controller = /datum/ai_controller/basic_controller/clown/murder
+ loot = list(
+ /obj/effect/gibspawner/human,
+ /obj/effect/spawner/foam_starter/small,
+ /obj/item/soap,
+ /obj/item/clothing/mask/gas/clown_hat,
+ )
+ emotes = list(
+ BB_EMOTE_SAY = list("HONK!!!", "The Honkmother is merciful, so I must act out her wrath.", "parce mihi ad beatus honkmother placet mihi ut peccata committere,", "DIE!!!"),
+ BB_EMOTE_HEAR = list("honks", "grunts"),
+ BB_EMOTE_SEE = list("sweats"),
+ BB_EMOTE_CHANCE = 5,
+ )
+
+/mob/living/basic/clown/mutant
+ name = "Unknown"
+ desc = "Kill it for its own sake."
+ icon_state = "mutant"
+ icon_living = "mutant"
+ move_resist = INFINITY
+ response_help_continuous = "reluctantly sinks a finger into"
+ response_help_simple = "reluctantly sink a finger into"
+ response_disarm_continuous = "squishes into"
+ response_disarm_simple = "squish into"
+ response_harm_continuous = "squishes into"
+ response_harm_simple = "squish into"
+ maxHealth = 130
+ health = 130
+ pixel_x = -16
+ base_pixel_x = -16
+ speed = -5
+ melee_damage_lower = 10
+ melee_damage_upper = 20
+ attack_verb_continuous = "awkwardly flails at"
+ attack_verb_simple = "awkwardly flail at"
+ loot = list(
+ /obj/effect/gibspawner/generic,
+ /obj/effect/gibspawner/generic/animal,
+ /obj/effect/gibspawner/human,
+ /obj/effect/gibspawner/human/bodypartless,
+ /obj/effect/gibspawner/xeno/bodypartless,
+ /obj/item/soap,
+ /obj/item/clothing/mask/gas/clown_hat,
+ )
+ emotes = list(
+ BB_EMOTE_SAY = list("aaaaaahhhhuuhhhuhhhaaaaa", "AAAaaauuuaaAAAaauuhhh", "huuuuuh... hhhhuuuooooonnnnkk", "HuaUAAAnKKKK"),
+ BB_EMOTE_SEE = list("squirms", "writhes", "pulsates", "froths", "oozes"),
+ BB_EMOTE_CHANCE = 10,
+ )
+
+/mob/living/basic/clown/mutant/slow
+ speed = 20
+
+/mob/living/basic/clown/mutant/glutton
+ name = "banana glutton"
+ desc = "Something that was once a clown"
+ icon_state = "glutton"
+ icon_living = "glutton"
+ health = 200
+ mob_size = MOB_SIZE_LARGE
+ speed = 1
+ melee_damage_lower = 10
+ melee_damage_upper = 15
+ force_threshold = 10 //lots of fat to cushion blows.
+ damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 2, STAMINA = 0, OXY = 1)
+ attack_verb_continuous = "slams"
+ attack_verb_simple = "slam"
+ loot = list(
+ /obj/effect/gibspawner/generic,
+ /obj/effect/gibspawner/generic/animal,
+ /obj/effect/gibspawner/human/bodypartless,
+ /obj/effect/gibspawner/xeno/bodypartless,
+ )
+ emotes = list(
+ BB_EMOTE_SAY = list("hey, buddy", "HONK!!!", "H-h-h-H-HOOOOONK!!!!", "HONKHONKHONK!!!", "HEY, BUCKO, GET BACK HERE!!!", "HOOOOOOOONK!!!"),
+ BB_EMOTE_SEE = list("jiggles", "wobbles"),
+ )
+ death_sound = 'sound/misc/sadtrombone.ogg'
+ waddles = FALSE
+ ///This is the list of items we are ready to regurgitate,
+ var/list/prank_pouch = list()
+
+/mob/living/basic/clown/mutant/glutton/Initialize(mapload)
+ . = ..()
+ var/datum/action/cooldown/regurgitate/spit = new(src)
+ spit.Grant(src)
+
+ AddElement(/datum/element/swabable, CELL_LINE_TABLE_GLUTTON, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5)
+ AddComponent(/datum/component/tameable, food_types = list(/obj/item/food/cheesiehonkers, /obj/item/food/cornchips), tame_chance = 30, bonus_tame_chance = 0, after_tame = CALLBACK(src, PROC_REF(tamed)))
+
+
+/mob/living/basic/clown/mutant/glutton/attacked_by(obj/item/item, mob/living/user)
+ if(!check_edible(item))
+ return ..()
+ eat_atom(item)
+
+/mob/living/basic/clown/mutant/glutton/melee_attack(atom/target, list/modifiers, ignore_cooldown = FALSE)
+ if(!check_edible(target))
+ return ..()
+ eat_atom(target)
+
+/mob/living/basic/clown/mutant/glutton/UnarmedAttack(atom/victim, proximity_flag, list/modifiers)
+ if(!check_edible(victim))
+ return ..()
+ eat_atom(victim)
+
+///Returns whether or not the supplied movable atom is edible.
+/mob/living/basic/clown/mutant/glutton/proc/check_edible(atom/movable/potential_food)
+ if(isliving(potential_food))
+ var/mob/living/living_morsel = potential_food
+ if(living_morsel.mob_size > MOB_SIZE_SMALL)
+ return FALSE
+ else
+ return TRUE
+
+ if(IS_EDIBLE(potential_food))
+ if(prank_pouch.len >= 8)
+ to_chat(src, span_warning("Your prank pouch is filled to the brim! You don't think you can swallow any more morsels right now."))
+ return FALSE
+ return TRUE
+
+///This proc eats the atom, certain funny items are stored directly in the prank pouch while bananas grant a heal based on their potency and the peels are retained in the pouch.
+/mob/living/basic/clown/mutant/glutton/proc/eat_atom(atom/movable/eaten_atom)
+
+ var/static/funny_items = list(
+ /obj/item/food/pie/cream,
+ /obj/item/food/grown/tomato,
+ /obj/item/food/meatclown,
+ )
+
+ visible_message(span_warning("[src] eats [eaten_atom]!"), span_notice("You eat [eaten_atom]."))
+ if(is_type_in_list(eaten_atom, funny_items))
+ eaten_atom.forceMove(src)
+ prank_pouch += eaten_atom
+
+ else
+ if(istype(eaten_atom, /obj/item/food/grown/banana))
+ var/obj/item/food/grown/banana/banana_morsel = eaten_atom
+ adjustBruteLoss(-banana_morsel.seed.potency * 0.25)
+ prank_pouch += banana_morsel.generate_trash(src)
+
+ qdel(eaten_atom)
+
+ playsound(loc,'sound/items/eatfood.ogg', rand(30,50), TRUE)
+ flick("glutton_mouth", src)
+
+/mob/living/basic/clown/mutant/glutton/proc/tamed(mob/living/tamer)
+ buckle_lying = 0
+ AddElement(/datum/element/ridable, /datum/component/riding/creature/glutton)
+
+/mob/living/basic/clown/mutant/glutton/Exited(atom/movable/gone, direction)
+ . = ..()
+ prank_pouch -= gone
+
+///This ability will let you fire one random item from your pouch,
+/datum/action/cooldown/regurgitate
+ name = "Regurgitate"
+ desc = "Regurgitates a single item from the depths of your pouch."
+ background_icon_state = "bg_changeling"
+ overlay_icon_state = "bg_changeling_border"
+ button_icon = 'icons/mob/actions/actions_animal.dmi'
+ button_icon_state = "regurgitate"
+ check_flags = AB_CHECK_CONSCIOUS|AB_CHECK_INCAPACITATED
+ melee_cooldown_time = 0 SECONDS
+ click_to_activate = TRUE
+
+/datum/action/cooldown/regurgitate/set_click_ability(mob/on_who)
+ . = ..()
+ if(!.)
+ return
+
+ to_chat(on_who, span_notice("Your throat muscles tense up. Left-click to regurgitate a funny morsel!"))
+ on_who.icon_state = "glutton_tongue"
+ on_who.update_appearance(UPDATE_ICON)
+
+/datum/action/cooldown/regurgitate/unset_click_ability(mob/on_who, refund_cooldown = TRUE)
+ . = ..()
+ if(!.)
+ return
+
+ if(refund_cooldown)
+ to_chat(on_who, span_notice("Your throat muscles relax."))
+ on_who.icon_state = initial(on_who.icon_state)
+ on_who.update_appearance(UPDATE_ICON)
+
+/datum/action/cooldown/regurgitate/IsAvailable(feedback = FALSE)
+ . = ..()
+ if(!.)
+ return FALSE
+
+ // Hardcoded to only work with gluttons. Come back next year
+ return istype(owner, /mob/living/basic/clown/mutant/glutton)
+
+/datum/action/cooldown/regurgitate/Activate(atom/spit_at)
+ StartCooldown(cooldown_time / 4)
+
+ var/mob/living/basic/clown/mutant/glutton/pouch_owner = owner
+ if(!length(pouch_owner.prank_pouch))
+ pouch_owner.icon_state = initial(pouch_owner.icon_state)
+ to_chat(pouch_owner, span_notice("Your prank pouch is empty."))
+ return TRUE
+
+ var/obj/item/projected_morsel = pick(pouch_owner.prank_pouch)
+ projected_morsel.forceMove(pouch_owner.loc)
+ projected_morsel.throw_at(spit_at, 8, 2, pouch_owner)
+ flick("glutton_mouth", pouch_owner)
+ playsound(pouch_owner, 'sound/misc/soggy.ogg', 75)
+
+ StartCooldown()
+ return TRUE
+
+/mob/living/basic/clown/banana
name = "Clownana"
desc = "A fusion of clown and banana DNA birthed from a botany experiment gone wrong."
icon_state = "banana tree"
@@ -83,26 +527,33 @@
response_disarm_simple = "peel"
response_harm_continuous = "peels"
response_harm_simple = "peel"
- turns_per_move = 1
- speak = list("HONK", "Honk!", "YA-HONK!!!")
- emote_see = list("honks", "bites into the banana", "plucks a banana off its head", "photosynthesizes")
maxHealth = 120
health = 120
speed = -1
- loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/item/soap, /obj/item/seeds/banana)
+ loot = list(
+ /obj/effect/gibspawner/human,
+ /obj/item/seeds/banana,
+ /obj/item/soap,
+ /obj/item/clothing/mask/gas/clown_hat,
+ )
+ emotes = list(
+ BB_EMOTE_SAY = list("HONK", "Honk!", "YA-HONK!!!"),
+ BB_EMOTE_SEE = list("bites into the banana", "plucks a banana off its head", "photosynthesizes"),
+ BB_EMOTE_SOUND = list('sound/items/bikehorn.ogg'),
+ )
///Our peel dropping ability
var/datum/action/cooldown/rustle/banana_rustle
///Our banana bunch spawning ability
var/datum/action/cooldown/exquisite_bunch/banana_bunch
-/mob/living/simple_animal/hostile/retaliate/clown/banana/Initialize(mapload)
+/mob/living/basic/clown/banana/Initialize(mapload)
. = ..()
banana_rustle = new()
banana_rustle.Grant(src)
banana_bunch = new()
banana_bunch.Grant(src)
-/mob/living/simple_animal/hostile/retaliate/clown/banana/Destroy()
+/mob/living/basic/clown/banana/Destroy()
. = ..()
QDEL_NULL(banana_rustle)
QDEL_NULL(banana_bunch)
@@ -176,358 +627,3 @@
playsound(owner, 'sound/items/bikehorn.ogg', 60)
addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(playsound), owner, 'sound/creatures/clown/hohoho.ogg', 100, 1), 1 SECONDS)
StartCooldown()
-
-/mob/living/simple_animal/hostile/retaliate/clown/honkling
- name = "Honkling"
- desc = "A divine being sent by the Honkmother to spread joy. It's not dangerous, but it's a bit of a nuisance."
- icon_state = "honkling"
- icon_living = "honkling"
- turns_per_move = 1
- speed = -10
- harm_intent_damage = 1
- melee_damage_lower = 1
- melee_damage_upper = 1
- attack_verb_continuous = "cheers up"
- attack_verb_simple = "cheer up"
- loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/item/soap, /obj/item/seeds/banana/bluespace)
- attack_reagent = /datum/reagent/consumable/laughter
-
-/mob/living/simple_animal/hostile/retaliate/clown/fleshclown
- name = "Fleshclown"
- desc = "A being forged out of the pure essence of pranking, cursed into existence by a cruel maker."
- icon_state = "fleshclown"
- icon_living = "fleshclown"
- response_help_continuous = "reluctantly pokes"
- response_help_simple = "reluctantly poke"
- response_disarm_continuous = "sinks his hands into the spongy flesh of"
- response_disarm_simple = "sink your hands into the spongy flesh of"
- response_harm_continuous = "cleanses the world of"
- response_harm_simple = "cleanse the world of"
- speak = list("HONK", "Honk!", "I didn't ask for this", "I feel constant and horrible pain", "YA-HONK!!!", "this body is a merciless and unforgiving prison", "I was born out of mirthful pranking but I live in suffering")
- emote_see = list("honks", "sweats", "jiggles", "contemplates its existence")
- speak_chance = 5
- dextrous = TRUE
- hud_type = /datum/hud/dextrous
- maxHealth = 140
- health = 140
- speed = -5
- melee_damage_upper = 15
- attack_verb_continuous = "limply slaps"
- attack_verb_simple = "limply slap"
- obj_damage = 5
- loot = list(/obj/item/clothing/suit/hooded/bloated_human, /obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/item/soap)
-
-/mob/living/simple_animal/hostile/retaliate/clown/fleshclown/Initialize(mapload)
- . = ..()
- ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT)
-
-/mob/living/simple_animal/hostile/retaliate/clown/longface
- name = "Longface"
- desc = "Often found walking into the bar."
- icon_state = "long face"
- icon_living = "long face"
- move_resist = INFINITY
- turns_per_move = 10
- response_help_continuous = "tries to awkwardly hug"
- response_help_simple = "try to awkwardly hug"
- response_disarm_continuous = "pushes the unwieldy frame of"
- response_disarm_simple = "push the unwieldy frame of"
- response_harm_continuous = "tries to shut up"
- response_harm_simple = "try to shut up"
- speak = list("YA-HONK!!!")
- emote_see = list("honks", "squeaks")
- speak_chance = 60
- maxHealth = 150
- health = 150
- pixel_x = -16
- base_pixel_x = -16
- speed = 10
- harm_intent_damage = 5
- melee_damage_lower = 5
- attack_verb_continuous = "YA-HONKs"
- attack_verb_simple = "YA-HONK"
- loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/item/soap)
-
-/mob/living/simple_animal/hostile/retaliate/clown/clownhulk
- name = "Honk Hulk"
- desc = "A cruel and fearsome clown. Don't make him angry."
- icon_state = "honkhulk"
- icon_living = "honkhulk"
- move_resist = INFINITY
- gender = MALE
- response_help_continuous = "tries desperately to appease"
- response_help_simple = "try desperately to appease"
- response_disarm_continuous = "foolishly pushes"
- response_disarm_simple = "foolishly push"
- response_harm_continuous = "angers"
- response_harm_simple = "anger"
- speak = list("HONK", "Honk!", "HAUAUANK!!!", "GUUURRRRAAAHHH!!!")
- emote_see = list("honks", "sweats", "grunts")
- speak_chance = 5
- maxHealth = 400
- health = 400
- pixel_x = -16
- base_pixel_x = -16
- speed = 2
- harm_intent_damage = 15
- melee_damage_lower = 15
- melee_damage_upper = 20
- attack_verb_continuous = "pummels"
- attack_verb_simple = "pummel"
- obj_damage = 30
- environment_smash = ENVIRONMENT_SMASH_WALLS
- loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/item/soap)
-
-/mob/living/simple_animal/hostile/retaliate/clown/clownhulk/chlown
- name = "Chlown"
- desc = "A real lunkhead who somehow gets all the girls."
- icon_state = "chlown"
- icon_living = "chlown"
- gender = MALE
- response_help_continuous = "submits to"
- response_help_simple = "submit to"
- response_disarm_continuous = "tries to assert dominance over"
- response_disarm_simple = "try to assert dominance over"
- response_harm_continuous = "makes a weak beta attack at"
- response_harm_simple = "make a weak beta attack at"
- speak = list("HONK", "Honk!", "Bruh", "cheeaaaahhh?")
- emote_see = list("asserts his dominance", "emasculates everyone implicitly")
- maxHealth = 500
- health = 500
- speed = -2
- armour_penetration = 20
- attack_verb_continuous = "steals the girlfriend of"
- attack_verb_simple = "steal the girlfriend of"
- attack_sound = 'sound/items/airhorn2.ogg'
- loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/effect/particle_effect/fluid/foam, /obj/item/soap)
-
-/mob/living/simple_animal/hostile/retaliate/clown/clownhulk/honcmunculus
- name = "Honkmunculus"
- desc = "A slender wiry figure of alchemical origin."
- icon_state = "honkmunculus"
- icon_living = "honkmunculus"
- response_help_continuous = "skeptically pokes"
- response_help_simple = "skeptically poke"
- response_disarm_continuous = "pushes the unwieldy frame of"
- response_disarm_simple = "push the unwieldy frame of"
- speak = list("honk")
- emote_see = list("squirms", "writhes")
- speak_chance = 1
- maxHealth = 200
- health = 200
- speed = -5
- harm_intent_damage = 5
- melee_damage_lower = 5
- melee_damage_upper = 10
- attack_verb_continuous = "ferociously mauls"
- attack_verb_simple = "ferociously maul"
- environment_smash = ENVIRONMENT_SMASH_NONE
- loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/xeno/bodypartless, /obj/effect/particle_effect/fluid/foam, /obj/item/soap)
- attack_reagent = /datum/reagent/peaceborg/confuse
-
-/mob/living/simple_animal/hostile/retaliate/clown/clownhulk/destroyer
- name = "The Destroyer"
- desc = "An ancient being born of arcane honking."
- icon_state = "destroyer"
- icon_living = "destroyer"
- response_disarm_continuous = "bounces off of"
- response_harm_continuous = "bounces off of"
- speak = list("HONK!!!", "The Honkmother is merciful, so I must act out her wrath.", "parce mihi ad beatus honkmother placet mihi ut peccata committere,", "DIE!!!")
- maxHealth = 400
- health = 400
- speed = 5
- harm_intent_damage = 30
- melee_damage_lower = 20
- melee_damage_upper = 40
- armour_penetration = 30
- stat_attack = HARD_CRIT
- attack_verb_continuous = "acts out divine vengeance on"
- attack_verb_simple = "act out divine vengeance on"
- obj_damage = 50
- environment_smash = ENVIRONMENT_SMASH_RWALLS
- loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/effect/particle_effect/fluid/foam, /obj/item/soap)
-
-/mob/living/simple_animal/hostile/retaliate/clown/mutant
- name = "Unknown"
- desc = "Kill it for its own sake."
- icon_state = "mutant"
- icon_living = "mutant"
- move_resist = INFINITY
- turns_per_move = 10
- response_help_continuous = "reluctantly sinks a finger into"
- response_help_simple = "reluctantly sink a finger into"
- response_disarm_continuous = "squishes into"
- response_disarm_simple = "squish into"
- response_harm_continuous = "squishes into"
- response_harm_simple = "squish into"
- speak = list("aaaaaahhhhuuhhhuhhhaaaaa", "AAAaaauuuaaAAAaauuhhh", "huuuuuh... hhhhuuuooooonnnnkk", "HuaUAAAnKKKK")
- emote_see = list("squirms", "writhes", "pulsates", "froths", "oozes")
- speak_chance = 10
- maxHealth = 130
- health = 130
- pixel_x = -16
- base_pixel_x = -16
- speed = -5
- harm_intent_damage = 10
- melee_damage_lower = 10
- melee_damage_upper = 20
- attack_verb_continuous = "awkwardly flails at"
- attack_verb_simple = "awkwardly flail at"
- loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/xeno/bodypartless, /obj/item/soap, /obj/effect/gibspawner/generic, /obj/effect/gibspawner/generic/animal, /obj/effect/gibspawner/human/bodypartless, /obj/effect/gibspawner/human)
-
-/mob/living/simple_animal/hostile/retaliate/clown/mutant/slow
- speed = 20
- move_to_delay = 60
-
-/mob/living/simple_animal/hostile/retaliate/clown/mutant/glutton
- name = "banana glutton"
- desc = "Something that was once a clown"
- icon_state = "glutton"
- icon_living = "glutton"
- speak = list("hey, buddy", "HONK!!!", "H-h-h-H-HOOOOONK!!!!", "HONKHONKHONK!!!", "HEY, BUCKO, GET BACK HERE!!!", "HOOOOOOOONK!!!")
- emote_see = list("jiggles", "wobbles")
- health = 200
- mob_size = MOB_SIZE_LARGE
- speed = 1
- melee_damage_lower = 10
- melee_damage_upper = 15
- force_threshold = 10 //lots of fat to cushion blows.
- damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 2, STAMINA = 0, OXY = 1)
- attack_verb_continuous = "slams"
- attack_verb_simple = "slam"
- loot = list(/obj/effect/gibspawner/xeno/bodypartless, /obj/effect/gibspawner/generic, /obj/effect/gibspawner/generic/animal, /obj/effect/gibspawner/human/bodypartless)
- death_sound = 'sound/misc/sadtrombone.ogg'
- ///This is the list of items we are ready to regurgitate,
- var/list/prank_pouch = list()
-
-/mob/living/simple_animal/hostile/retaliate/clown/mutant/glutton/Initialize(mapload)
- . = ..()
- var/datum/action/cooldown/regurgitate/spit = new(src)
- spit.Grant(src)
-
- add_cell_sample()
- AddComponent(/datum/component/tameable, food_types = list(/obj/item/food/cheesiehonkers, /obj/item/food/cornchips), tame_chance = 30, bonus_tame_chance = 0, after_tame = CALLBACK(src, PROC_REF(tamed)))
-
-
-/mob/living/simple_animal/hostile/retaliate/clown/mutant/glutton/attacked_by(obj/item/I, mob/living/user)
- if(!check_edible(I))
- return ..()
- eat_atom(I)
-
-/mob/living/simple_animal/hostile/retaliate/clown/mutant/glutton/AttackingTarget(atom/attacked_target)
- if(!check_edible(attacked_target))
- return ..()
- eat_atom(attacked_target)
-
-/mob/living/simple_animal/hostile/retaliate/clown/mutant/glutton/UnarmedAttack(atom/A, proximity_flag, list/modifiers)
- if(!check_edible(A))
- return ..()
- eat_atom(A)
-
-///Returns whether or not the supplied movable atom is edible.
-/mob/living/simple_animal/hostile/retaliate/clown/mutant/glutton/proc/check_edible(atom/movable/potential_food)
- if(isliving(potential_food))
- var/mob/living/living_morsel = potential_food
- if(living_morsel.mob_size > MOB_SIZE_SMALL)
- return FALSE
- else
- return TRUE
-
- if(IS_EDIBLE(potential_food))
- if(prank_pouch.len >= 8)
- to_chat(src, span_warning("Your prank pouch is filled to the brim! You don't think you can swallow any more morsels right now."))
- return FALSE
- return TRUE
-
-///This proc eats the atom, certain funny items are stored directly in the prank pouch while bananas grant a heal based on their potency and the peels are retained in the pouch.
-/mob/living/simple_animal/hostile/retaliate/clown/mutant/glutton/proc/eat_atom(atom/movable/eaten_atom)
-
- var/static/funny_items = list(
- /obj/item/food/pie/cream,
- /obj/item/food/grown/tomato,
- /obj/item/food/meatclown,
- )
-
- visible_message(span_warning("[src] eats [eaten_atom]!"), span_notice("You eat [eaten_atom]."))
- if(is_type_in_list(eaten_atom, funny_items))
- eaten_atom.forceMove(src)
- prank_pouch += eaten_atom
-
- else
- if(istype(eaten_atom, /obj/item/food/grown/banana))
- var/obj/item/food/grown/banana/banana_morsel = eaten_atom
- adjustBruteLoss(-banana_morsel.seed.potency * 0.25)
- prank_pouch += banana_morsel.generate_trash(src)
-
- qdel(eaten_atom)
-
- playsound(loc,'sound/items/eatfood.ogg', rand(30,50), TRUE)
- flick("glutton_mouth", src)
-
-/mob/living/simple_animal/hostile/retaliate/clown/mutant/glutton/proc/tamed(mob/living/tamer)
- buckle_lying = 0
- AddElement(/datum/element/ridable, /datum/component/riding/creature/glutton)
-
-/mob/living/simple_animal/hostile/retaliate/clown/mutant/glutton/add_cell_sample()
- AddElement(/datum/element/swabable, CELL_LINE_TABLE_GLUTTON, CELL_VIRUS_TABLE_GENERIC_MOB, 1, 5)
-
-/mob/living/simple_animal/hostile/retaliate/clown/mutant/glutton/Exited(atom/movable/gone, direction)
- . = ..()
- prank_pouch -= gone
-
-///This ability will let you fire one random item from your pouch,
-/datum/action/cooldown/regurgitate
- name = "Regurgitate"
- desc = "Regurgitates a single item from the depths of your pouch."
- background_icon_state = "bg_changeling"
- overlay_icon_state = "bg_changeling_border"
- button_icon = 'icons/mob/actions/actions_animal.dmi'
- button_icon_state = "regurgitate"
- check_flags = AB_CHECK_CONSCIOUS|AB_CHECK_INCAPACITATED
- melee_cooldown_time = 0 SECONDS
- click_to_activate = TRUE
-
-/datum/action/cooldown/regurgitate/set_click_ability(mob/on_who)
- . = ..()
- if(!.)
- return
-
- to_chat(on_who, span_notice("Your throat muscles tense up. Left-click to regurgitate a funny morsel!"))
- on_who.icon_state = "glutton_tongue"
- on_who.update_appearance(UPDATE_ICON)
-
-/datum/action/cooldown/regurgitate/unset_click_ability(mob/on_who, refund_cooldown = TRUE)
- . = ..()
- if(!.)
- return
-
- if(refund_cooldown)
- to_chat(on_who, span_notice("Your throat muscles relax."))
- on_who.icon_state = initial(on_who.icon_state)
- on_who.update_appearance(UPDATE_ICON)
-
-/datum/action/cooldown/regurgitate/IsAvailable(feedback = FALSE)
- . = ..()
- if(!.)
- return FALSE
-
- // Hardcoded to only work with gluttons. Come back next year
- return istype(owner, /mob/living/simple_animal/hostile/retaliate/clown/mutant/glutton)
-
-/datum/action/cooldown/regurgitate/Activate(atom/spit_at)
- StartCooldown(cooldown_time / 4)
-
- var/mob/living/simple_animal/hostile/retaliate/clown/mutant/glutton/pouch_owner = owner
- if(!length(pouch_owner.prank_pouch))
- pouch_owner.icon_state = initial(pouch_owner.icon_state)
- to_chat(pouch_owner, span_notice("Your prank pouch is empty."))
- return TRUE
-
- var/obj/item/projected_morsel = pick(pouch_owner.prank_pouch)
- projected_morsel.forceMove(pouch_owner.loc)
- projected_morsel.throw_at(spit_at, 8, 2, pouch_owner)
- flick("glutton_mouth", pouch_owner)
- playsound(pouch_owner, 'sound/misc/soggy.ogg', 75)
-
- StartCooldown()
- return TRUE
diff --git a/code/modules/mob/living/basic/clown/clown_ai.dm b/code/modules/mob/living/basic/clown/clown_ai.dm
new file mode 100644
index 00000000000..b2e6418dde7
--- /dev/null
+++ b/code/modules/mob/living/basic/clown/clown_ai.dm
@@ -0,0 +1,19 @@
+/datum/ai_controller/basic_controller/clown
+ blackboard = list(
+ BB_TARGETTING_DATUM = new /datum/targetting_datum/basic,
+ BB_BASIC_MOB_SPEAK_LINES = null,
+ )
+
+ ai_movement = /datum/ai_movement/basic_avoidance
+ idle_behavior = /datum/idle_behavior/idle_random_walk
+ planning_subtrees = list(
+ /datum/ai_planning_subtree/target_retaliate,
+ /datum/ai_planning_subtree/basic_melee_attack_subtree,
+ /datum/ai_planning_subtree/random_speech/blackboard,
+ )
+
+/datum/ai_controller/basic_controller/clown/murder
+ blackboard = list(
+ BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/attack_until_dead,
+ BB_BASIC_MOB_SPEAK_LINES = null,
+ )
diff --git a/code/modules/mob/living/basic/syndicate/syndicate_ai.dm b/code/modules/mob/living/basic/syndicate/syndicate_ai.dm
index 393ef19287e..be84c1a5685 100644
--- a/code/modules/mob/living/basic/syndicate/syndicate_ai.dm
+++ b/code/modules/mob/living/basic/syndicate/syndicate_ai.dm
@@ -1,6 +1,6 @@
/datum/ai_controller/basic_controller/syndicate
blackboard = list(
- BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/syndicate()
+ BB_TARGETTING_DATUM = new /datum/targetting_datum/basic/attack_until_dead
)
ai_movement = /datum/ai_movement/basic_avoidance
@@ -11,8 +11,11 @@
/datum/ai_planning_subtree/basic_melee_attack_subtree,
)
-/datum/targetting_datum/basic/syndicate
- stat_attack = HARD_CRIT
+/datum/ai_planning_subtree/basic_melee_attack_subtree/syndicate
+ melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/syndicate
+
+/datum/ai_behavior/basic_melee_attack/syndicate
+ action_cooldown = 1.2 SECONDS
/datum/ai_planning_subtree/attack_obstacle_in_path/syndicate
attack_behaviour = /datum/ai_behavior/attack_obstructions/syndicate
diff --git a/code/modules/research/xenobiology/vatgrowing/samples/cell_lines/common.dm b/code/modules/research/xenobiology/vatgrowing/samples/cell_lines/common.dm
index bec3092d8ea..abb764d0689 100644
--- a/code/modules/research/xenobiology/vatgrowing/samples/cell_lines/common.dm
+++ b/code/modules/research/xenobiology/vatgrowing/samples/cell_lines/common.dm
@@ -481,7 +481,7 @@
/datum/micro_organism/cell_line/clown/fuck_up_growing(obj/machinery/plumbing/growing_vat/vat)
vat.visible_message(span_warning("The biological sample in [vat] seems to have created something horrific!"))
- var/mob/selected_mob = pick(list(/mob/living/simple_animal/hostile/retaliate/clown/mutant/slow, /mob/living/simple_animal/hostile/retaliate/clown/fleshclown))
+ var/mob/selected_mob = pick(list(/mob/living/basic/clown/mutant/slow, /mob/living/basic/clown/fleshclown))
new selected_mob(get_turf(vat))
if(SEND_SIGNAL(vat.biological_sample, COMSIG_SAMPLE_GROWTH_COMPLETED) & SPARE_SAMPLE)
@@ -509,7 +509,7 @@
/datum/reagent/consumable/nothing = -2,
/datum/reagent/fuel/oil = -1)
- resulting_atoms = list(/mob/living/simple_animal/hostile/retaliate/clown/banana = 1)
+ resulting_atoms = list(/mob/living/basic/clown/banana = 1)
/datum/micro_organism/cell_line/clown/glutton
desc = "hyperadipogenic clown stem cells"
@@ -535,7 +535,7 @@
/datum/reagent/consumable/nothing = -2,
/datum/reagent/toxin/bad_food = -1)
- resulting_atoms = list(/mob/living/simple_animal/hostile/retaliate/clown/mutant/glutton = 1)
+ resulting_atoms = list(/mob/living/basic/clown/mutant/glutton = 1)
/datum/micro_organism/cell_line/clown/longclown
desc = "long clown bits"
@@ -558,7 +558,7 @@
/datum/reagent/consumable/nothing = -2,
/datum/reagent/sulfur = -1)
- resulting_atoms = list(/mob/living/simple_animal/hostile/retaliate/clown/longface = 1)
+ resulting_atoms = list(/mob/living/basic/clown/longface = 1)
/datum/micro_organism/cell_line/frog
desc = "anura amphibian cells"
diff --git a/code/modules/unit_tests/simple_animal_freeze.dm b/code/modules/unit_tests/simple_animal_freeze.dm
index 7f235ba9582..56910fe08da 100644
--- a/code/modules/unit_tests/simple_animal_freeze.dm
+++ b/code/modules/unit_tests/simple_animal_freeze.dm
@@ -183,19 +183,6 @@
/mob/living/simple_animal/hostile/pirate/ranged,
/mob/living/simple_animal/hostile/pirate/ranged/space,
/mob/living/simple_animal/hostile/retaliate,
- /mob/living/simple_animal/hostile/retaliate/clown,
- /mob/living/simple_animal/hostile/retaliate/clown/banana,
- /mob/living/simple_animal/hostile/retaliate/clown/clownhulk,
- /mob/living/simple_animal/hostile/retaliate/clown/clownhulk/chlown,
- /mob/living/simple_animal/hostile/retaliate/clown/clownhulk/destroyer,
- /mob/living/simple_animal/hostile/retaliate/clown/clownhulk/honcmunculus,
- /mob/living/simple_animal/hostile/retaliate/clown/fleshclown,
- /mob/living/simple_animal/hostile/retaliate/clown/honkling,
- /mob/living/simple_animal/hostile/retaliate/clown/longface,
- /mob/living/simple_animal/hostile/retaliate/clown/lube,
- /mob/living/simple_animal/hostile/retaliate/clown/mutant,
- /mob/living/simple_animal/hostile/retaliate/clown/mutant/glutton,
- /mob/living/simple_animal/hostile/retaliate/clown/mutant/slow,
/mob/living/simple_animal/hostile/retaliate/goat,
/mob/living/simple_animal/hostile/retaliate/goose,
/mob/living/simple_animal/hostile/retaliate/goose/vomit,
diff --git a/tgstation.dme b/tgstation.dme
index 5194435e694..ecc32c9e5de 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -4314,6 +4314,8 @@
#include "code\modules\mob\living\basic\festivus_pole.dm"
#include "code\modules\mob\living\basic\health_adjustment.dm"
#include "code\modules\mob\living\basic\tree.dm"
+#include "code\modules\mob\living\basic\clown\clown.dm"
+#include "code\modules\mob\living\basic\clown\clown_ai.dm"
#include "code\modules\mob\living\basic\farm_animals\deer.dm"
#include "code\modules\mob\living\basic\farm_animals\pig.dm"
#include "code\modules\mob\living\basic\farm_animals\pony.dm"
@@ -4699,7 +4701,6 @@
#include "code\modules\mob\living\simple_animal\hostile\mining_mobs\elites\herald.dm"
#include "code\modules\mob\living\simple_animal\hostile\mining_mobs\elites\legionnaire.dm"
#include "code\modules\mob\living\simple_animal\hostile\mining_mobs\elites\pandora.dm"
-#include "code\modules\mob\living\simple_animal\hostile\retaliate\clown.dm"
#include "code\modules\mob\living\simple_animal\hostile\retaliate\goose.dm"
#include "code\modules\mob\living\simple_animal\hostile\retaliate\retaliate.dm"
#include "code\modules\mob\living\simple_animal\hostile\retaliate\snake.dm"
diff --git a/tools/UpdatePaths/Scripts/78448_basicclowns.txt b/tools/UpdatePaths/Scripts/78448_basicclowns.txt
new file mode 100644
index 00000000000..91d134d157e
--- /dev/null
+++ b/tools/UpdatePaths/Scripts/78448_basicclowns.txt
@@ -0,0 +1,3 @@
+#comment Repaths simpleanimal clowns to basicmob clowns
+
+/mob/living/simple_animal/hostile/retaliate/clown/@SUBTYPES : /mob/living/basic/clown/@SUBTYPES{@OLD}
\ No newline at end of file