diff --git a/code/__HELPERS/honkerblast.dm b/code/__HELPERS/honkerblast.dm
new file mode 100644
index 00000000000..bd05d07417a
--- /dev/null
+++ b/code/__HELPERS/honkerblast.dm
@@ -0,0 +1,47 @@
+///Unleashes a honkerblast similar to the honkmech weapon, but with more granular control.
+/proc/honkerblast(atom/origin, light_range = 1, medium_range = 0, heavy_range = 0)
+ var/origin_turf = get_turf(origin)
+ var/list/lightly_honked = list()
+ var/list/properly_honked = list()
+ var/list/severely_honked = list()
+
+ playsound(origin_turf, 'sound/items/airhorn.ogg', 100, TRUE)
+
+ for(var/mob/living/carbon/victim as anything in hearers(max(light_range, medium_range, heavy_range), origin_turf))
+ if(!victim.can_hear())
+ continue
+ var/distance = get_dist(origin_turf, victim.loc)
+ if(distance <= heavy_range)
+ severely_honked += victim
+ else if(distance <= medium_range)
+ properly_honked += victim
+ else if(distance <= light_range)
+ lightly_honked += victim
+
+ for(var/mob/living/carbon/victim in severely_honked)
+ victim.Unconscious(40)
+ victim.Stun(100)
+ victim.stuttering += 15
+ victim.Jitter(500)
+ var/obj/item/organ/ears/ears = victim.getorganslot(ORGAN_SLOT_EARS)
+ ears?.adjustEarDamage(10, 15)
+ to_chat(victim, "HONK")
+ var/obj/item/clothing/shoes/victim_shoes = victim.get_item_by_slot(ITEM_SLOT_FEET)
+ if(!victim_shoes?.can_be_tied)
+ continue
+ victim_shoes.adjust_laces(SHOES_KNOTTED)
+
+ for(var/mob/living/carbon/victim in properly_honked)
+ victim.Paralyze(20)
+ victim.Stun(50)
+ victim.Jitter(250)
+ var/obj/item/organ/ears/ears = victim.getorganslot(ORGAN_SLOT_EARS)
+ ears?.adjustEarDamage(7, 10)
+ to_chat(victim, "HONK")
+
+ for(var/mob/living/carbon/victim in lightly_honked)
+ victim.Knockdown(20)
+ victim.Jitter(100)
+ var/obj/item/organ/ears/ears = victim.getorganslot(ORGAN_SLOT_EARS)
+ ears?.adjustEarDamage(4, 5)
+ to_chat(victim, "HONK")
diff --git a/code/modules/hydroponics/grown/banana.dm b/code/modules/hydroponics/grown/banana.dm
index bdc8693b5fe..a40d6b9dbfc 100644
--- a/code/modules/hydroponics/grown/banana.dm
+++ b/code/modules/hydroponics/grown/banana.dm
@@ -144,3 +144,34 @@
/obj/item/grown/bananapeel/specialpeel/ComponentInitialize()
. = ..()
AddComponent(/datum/component/slippery, 40)
+
+/obj/item/food/grown/banana/bunch
+ name = "banana bunch"
+ desc = "Am exquisite bunch of bananas. The almost otherwordly plumpness steers the mind any discening entertainer towards the divine."
+ icon_state = "banana_bunch"
+ bite_consumption_mod = 4
+ var/is_ripening = FALSE
+
+/obj/item/food/grown/banana/bunch/Initialize(mapload, obj/item/seeds/new_seed)
+ . = ..()
+ reagents.add_reagent(/datum/reagent/consumable/monkey_energy, 10)
+ reagents.add_reagent(/datum/reagent/consumable/banana, 10)
+
+/obj/item/food/grown/banana/bunch/proc/start_ripening()
+ if(is_ripening)
+ return
+ playsound(src, 'sound/effects/fuse.ogg', 80)
+
+ animate(src, time = 1, pixel_z = 12, easing = ELASTIC_EASING)
+ animate(time = 1, pixel_z = 0, easing = BOUNCE_EASING)
+ addtimer(CALLBACK(src, .proc/explosive_ripening), 3 SECONDS)
+ for(var/i in 1 to 32)
+ animate(color = (i % 2) ? "#ffffff": "#ff6739", time = 1, easing = QUAD_EASING)
+
+/obj/item/food/grown/banana/bunch/proc/explosive_ripening()
+ honkerblast(src, light_range = 3, medium_range = 1)
+ for(var/mob/shook_boi in range(6, loc))
+ shake_camera(shook_boi, 3, 5)
+ var/obj/effect/decal/cleanable/food/plant_smudge/banana_smudge = new(loc)
+ banana_smudge.color = "#ffe02f"
+ qdel(src)
diff --git a/code/modules/language/language_holder.dm b/code/modules/language/language_holder.dm
index cff14f2eb25..006178b6604 100644
--- a/code/modules/language/language_holder.dm
+++ b/code/modules/language/language_holder.dm
@@ -389,6 +389,11 @@ Key procs
spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
/datum/language/shadowtongue = list(LANGUAGE_ATOM))
+/datum/language_holder/clown
+ understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
+ /datum/language/monkey = list(LANGUAGE_ATOM))
+ spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM),
+ /datum/language/monkey = list(LANGUAGE_ATOM))
/datum/language_holder/empty
understood_languages = list()
spoken_languages = list()
diff --git a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
index 46ed13fb4f5..5e849e96d34 100644
--- a/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
+++ b/code/modules/mob/living/simple_animal/hostile/retaliate/clown.dm
@@ -28,15 +28,13 @@
environment_smash = ENVIRONMENT_SMASH_NONE
del_on_death = 1
loot = list(/obj/effect/mob_spawn/corpse/human/clown)
-
+ 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
unsuitable_atmos_damage = 10
unsuitable_heat_damage = 15
footstep_type = FOOTSTEP_MOB_SHOE
- var/banana_time = 0 // If there's no time set it won't spawn.
- var/banana_type = /obj/item/grown/bananapeel
var/attack_reagent
/mob/living/simple_animal/hostile/retaliate/clown/Initialize(mapload)
@@ -48,20 +46,12 @@
..()
playsound(loc, 'sound/items/bikehorn.ogg', 50, TRUE)
-/mob/living/simple_animal/hostile/retaliate/clown/Life(delta_time = SSMOBS_DT, times_fired)
- . = ..()
- if(!banana_time || banana_time >= world.time)
- return
- banana_time = world.time + rand(30,60)
- if(!isturf(loc))
- return
- var/list/reachable_turfs = list()
- for(var/turf/adjacent_turf in RANGE_TURFS(1, loc))
- if(adjacent_turf == loc || !CanReach(adjacent_turf))
- continue
- reachable_turfs += adjacent_turf
- if(length(reachable_turfs))
- new banana_type(pick(reachable_turfs))
+/mob/living/simple_animal/hostile/retaliate/clown/AttackingTarget(atom/attacked_target)
+ if(!istype(attacked_target, /obj/item/food/grown/banana/bunch))
+ return ..()
+ var/obj/item/food/grown/banana/bunch/unripe_bunch = attacked_target
+ unripe_bunch.start_ripening()
+ log_combat(src, attacked_target, "honksposivley ripened")
/mob/living/simple_animal/hostile/retaliate/clown/lube
name = "Living Lube"
@@ -94,9 +84,92 @@
emote_see = list("honks", "bites into the banana", "plucks a banana off its head", "photosynthesizes")
maxHealth = 120
health = 120
- speed = -10
+ speed = -1
loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/item/soap, /obj/item/seeds/banana)
- banana_time = 20
+ ///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)
+ . = ..()
+ banana_rustle = new()
+ banana_rustle.Grant(src)
+ banana_bunch = new()
+ banana_bunch.Grant(src)
+
+/mob/living/simple_animal/hostile/retaliate/clown/banana/Destroy()
+ . = ..()
+ QDEL_NULL(banana_rustle)
+ QDEL_NULL(banana_bunch)
+
+///drops peels around the mob when activated
+/datum/action/cooldown/rustle
+ name = "Rustle"
+ desc = "Shake loose a few banana peels."
+ cooldown_time = 8 SECONDS
+ button_icon_state = "rustle"
+ icon_icon = 'icons/mob/actions/actions_clown.dmi'
+ background_icon_state = "bg_nature"
+ ///which type of peel to spawn
+ var/banana_type = /obj/item/grown/bananapeel
+ ///How many peels to spawn
+ var/peel_amount = 3
+
+/datum/action/cooldown/rustle/Activate(atom/target)
+ . = ..()
+ var/list/reachable_turfs = list()
+ for(var/turf/adjacent_turf in RANGE_TURFS(1, owner.loc))
+ if(adjacent_turf == owner.loc || !owner.CanReach(adjacent_turf) || !isopenturf(adjacent_turf))
+ continue
+ reachable_turfs += adjacent_turf
+
+ var/peels_to_spawn = min(peel_amount, reachable_turfs.len)
+ for(var/i in 1 to peels_to_spawn)
+ new banana_type(pick_n_take(reachable_turfs))
+ playsound(owner, 'sound/creatures/clown/clownana_rustle.ogg', 100)
+ animate(owner, time = 1, pixel_x = 6, easing = CUBIC_EASING | EASE_OUT)
+ animate(time = 2, pixel_x = -8, easing = CUBIC_EASING)
+ animate(time = 1, pixel_x = 0, easing = CUBIC_EASING | EASE_IN)
+ StartCooldown()
+
+///spawns a plumb bunch of bananas imbued with mystical power.
+/datum/action/cooldown/exquisite_bunch
+ name = "Exquisite Bunch"
+ desc = "Pluck your finest bunch of bananas from your head. This bunch is especially nutrious to monkeykind. A gentle tap will trigger an explosive ripening process."
+ icon_icon = 'icons/obj/hydroponics/harvest.dmi'
+ cooldown_time = 60 SECONDS
+ button_icon_state = "banana_bunch"
+ background_icon_state = "bg_nature"
+ ///If we are currently activating our ability.
+ var/activating = FALSE
+
+/datum/action/cooldown/exquisite_bunch/Trigger(trigger_flags, atom/target)
+ if(activating)
+ return
+ var/bunch_turf = get_step(owner.loc, owner.dir)
+ if(!bunch_turf)
+ return
+ if(!owner.CanReach(bunch_turf) || !isopenturf(bunch_turf))
+ owner.balloon_alert("can't do that here!")
+ return
+ activating = TRUE
+ if(!do_after(owner, 1 SECONDS))
+ activating = FALSE
+ return
+ playsound(owner, 'sound/creatures/clown/hehe.ogg', 100)
+ if(!do_after(owner, 1 SECONDS))
+ activating = FALSE
+ return
+ activating = FALSE
+ return ..()
+
+/datum/action/cooldown/exquisite_bunch/Activate(atom/target)
+ . = ..()
+ new /obj/item/food/grown/banana/bunch(get_step(owner.loc, owner.dir))
+ playsound(owner, 'sound/items/bikehorn.ogg', 60)
+ addtimer(CALLBACK(GLOBAL_PROC, .proc/playsound, owner, 'sound/creatures/clown/hohoho.ogg', 100, 1), 1 SECONDS)
+ StartCooldown()
/mob/living/simple_animal/hostile/retaliate/clown/honkling
name = "Honkling"
@@ -111,7 +184,6 @@
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)
- banana_type = /obj/item/grown/bananapeel
attack_reagent = /datum/reagent/consumable/laughter
/mob/living/simple_animal/hostile/retaliate/clown/fleshclown
diff --git a/icons/mob/actions/actions_clown.dmi b/icons/mob/actions/actions_clown.dmi
new file mode 100644
index 00000000000..8b94c24abe4
Binary files /dev/null and b/icons/mob/actions/actions_clown.dmi differ
diff --git a/icons/mob/actions/backgrounds.dmi b/icons/mob/actions/backgrounds.dmi
index 7628c646b9f..6b80090e8a1 100644
Binary files a/icons/mob/actions/backgrounds.dmi and b/icons/mob/actions/backgrounds.dmi differ
diff --git a/icons/obj/hydroponics/harvest.dmi b/icons/obj/hydroponics/harvest.dmi
index 0213f65ae06..684ef81a5db 100644
Binary files a/icons/obj/hydroponics/harvest.dmi and b/icons/obj/hydroponics/harvest.dmi differ
diff --git a/sound/attributions.txt b/sound/attributions.txt
index 926df333912..e177646b780 100644
--- a/sound/attributions.txt
+++ b/sound/attributions.txt
@@ -23,6 +23,7 @@ champagne_pop.ogg is credited to ultradust on freesound https://freesound.org/pe
can_open.ogg adapted from https://freesound.org/people/MaxDemianAGL/sounds/130031/
can_shake.ogg adapted from https://freesound.org/people/mcmast/sounds/456703/
-splatter.ogg adapted from https://freesound.org/people/Rocktopus/sounds/233418/
+splatter.ogg adapted from https://freesound.org/people/Rocktopus/sounds/233418/
+hohoho.ogg and hehe.ogg are cut from a recording by Nanakisan on freesound: https://freesound.org/people/Nanakisan/sounds/253534/
mbox_full.ogg and mbox_end.ogg make use of The Ragtime Drummer by James Lent, in the public domain
diff --git a/sound/creatures/clown/clownana_rustle.ogg b/sound/creatures/clown/clownana_rustle.ogg
new file mode 100644
index 00000000000..611d322a31e
Binary files /dev/null and b/sound/creatures/clown/clownana_rustle.ogg differ
diff --git a/sound/creatures/clown/hehe.ogg b/sound/creatures/clown/hehe.ogg
new file mode 100644
index 00000000000..11c6b59f7fe
Binary files /dev/null and b/sound/creatures/clown/hehe.ogg differ
diff --git a/sound/creatures/clown/hohoho.ogg b/sound/creatures/clown/hohoho.ogg
new file mode 100644
index 00000000000..4efe059a13b
Binary files /dev/null and b/sound/creatures/clown/hohoho.ogg differ
diff --git a/tgstation.dme b/tgstation.dme
index 2fe0ea870c8..74ff5d33712 100644
--- a/tgstation.dme
+++ b/tgstation.dme
@@ -276,6 +276,7 @@
#include "code\__HELPERS\guid.dm"
#include "code\__HELPERS\heap.dm"
#include "code\__HELPERS\hearted.dm"
+#include "code\__HELPERS\honkerblast.dm"
#include "code\__HELPERS\icon_smoothing.dm"
#include "code\__HELPERS\icons.dm"
#include "code\__HELPERS\jatum.dm"