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