diff --git a/code/__DEFINES/colors.dm b/code/__DEFINES/colors.dm index 9e1fe18270a..78e6e78d5cb 100644 --- a/code/__DEFINES/colors.dm +++ b/code/__DEFINES/colors.dm @@ -291,6 +291,23 @@ #define COLOR_CARP_SILVER "#fdfbf3" #define COLOR_CARP_DARK_BLUE "#3a384d" +#define COLOR_GNOME_RED_ONE "#f10b0b" +#define COLOR_GNOME_RED_TWO "#bc5347" +#define COLOR_GNOME_RED_THREE "#b40f1a" +#define COLOR_GNOME_BLUE_ONE "#2e8ff7" +#define COLOR_GNOME_BLUE_TWO "#312bd6" +#define COLOR_GNOME_BLUE_THREE "#4e409a" +#define COLOR_GNOME_GREEN_ONE "#28da1c" +#define COLOR_GNOME_GREEN_TWO "#50a954" +#define COLOR_GNOME_YELLOW "#f6da3c" +#define COLOR_GNOME_ORANGE "#d56f2f" +#define COLOR_GNOME_BROWN_ONE "#874e2a" +#define COLOR_GNOME_BROWN_TWO "#543d2e" +#define COLOR_GNOME_PURPLE "#ac1dd7" +#define COLOR_GNOME_WHITE "#e8e8e8" +#define COLOR_GNOME_GREY "#a9a9a9" +#define COLOR_GNOME_BLACK "#303030" + #define SOFA_BROWN "#a75400" #define SOFA_MAROON "#830000" 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 221b2259600..bfabe1cb8b7 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/speech_subtree.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/speech_subtree.dm @@ -110,3 +110,9 @@ /datum/ai_planning_subtree/random_speech/faithless speech_chance = 1 emote_see = list("wails.") + +/datum/ai_planning_subtree/random_speech/garden_gnome + speech_chance = 5 + speak = list("Gnot a gnelf!", "Gnot a gnoblin!", "Howdy chum!") + emote_hear = list("snores.", "burps.") + emote_see = list("blinks.") diff --git a/code/datums/ai/idle_behaviors/idle_random_walk.dm b/code/datums/ai/idle_behaviors/idle_random_walk.dm index 1187d8786c1..69a236ba831 100644 --- a/code/datums/ai/idle_behaviors/idle_random_walk.dm +++ b/code/datums/ai/idle_behaviors/idle_random_walk.dm @@ -10,3 +10,5 @@ var/move_dir = pick(GLOB.alldirs) living_pawn.Move(get_step(living_pawn, move_dir), move_dir) +/datum/idle_behavior/idle_random_walk/less_walking + walk_chance = 10 diff --git a/code/datums/components/ai_retaliate_advanced.dm b/code/datums/components/ai_retaliate_advanced.dm new file mode 100644 index 00000000000..8be84dc5cef --- /dev/null +++ b/code/datums/components/ai_retaliate_advanced.dm @@ -0,0 +1,33 @@ +/** + * Attached to a mob with an AI controller, passes things which have damaged it to a blackboard. + * The AI controller is responsible for doing anything with that information. + */ +/datum/component/ai_retaliate_advanced + /// Callback to a mob for custom behaviour + var/datum/callback/post_retaliate_callback + +/datum/component/ai_retaliate_advanced/Initialize(datum/callback/post_retaliate_callback) + if(!ismob(parent)) + return ELEMENT_INCOMPATIBLE + + src.post_retaliate_callback = post_retaliate_callback + parent.AddElement(/datum/element/relay_attackers) + +/datum/component/ai_retaliate_advanced/RegisterWithParent() + RegisterSignal(parent, COMSIG_ATOM_WAS_ATTACKED, PROC_REF(on_attacked)) + +/datum/component/ai_retaliate_advanced/UnregisterFromParent() + UnregisterSignal(parent, COMSIG_ATOM_WAS_ATTACKED) + +/// Add an attacking atom to a blackboard list of things which attacked us +/datum/component/ai_retaliate_advanced/proc/on_attacked(mob/victim, atom/attacker) + SIGNAL_HANDLER + + if (!victim.ai_controller) + return + var/list/enemy_refs = victim.ai_controller.blackboard[BB_BASIC_MOB_RETALIATE_LIST] + if (!enemy_refs) + enemy_refs = list() + enemy_refs |= WEAKREF(attacker) + victim.ai_controller.blackboard[BB_BASIC_MOB_RETALIATE_LIST] = enemy_refs + post_retaliate_callback?.InvokeAsync(attacker) diff --git a/code/datums/components/caltrop.dm b/code/datums/components/caltrop.dm index a9b3ebf7812..726c705ee8d 100644 --- a/code/datums/components/caltrop.dm +++ b/code/datums/components/caltrop.dm @@ -13,6 +13,9 @@ ///Probability of actually "firing", stunning and doing damage var/probability + ///Amount of time the spike will paralyze + var/paralyze_duration + ///Miscelanous caltrop flags; shoe bypassing, walking interaction, silence var/flags @@ -27,7 +30,7 @@ ///So we can update ant damage dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS -/datum/component/caltrop/Initialize(min_damage = 0, max_damage = 0, probability = 100, flags = NONE, soundfile = null) +/datum/component/caltrop/Initialize(min_damage = 0, max_damage = 0, probability = 100, paralyze_duration = 6 SECONDS, flags = NONE, soundfile = null) . = ..() if(!isatom(parent)) return COMPONENT_INCOMPATIBLE @@ -35,6 +38,7 @@ src.min_damage = min_damage src.max_damage = max(min_damage, max_damage) src.probability = probability + src.paralyze_duration = paralyze_duration src.flags = flags src.soundfile = soundfile @@ -115,7 +119,7 @@ H.apply_damage(damage, BRUTE, picked_def_zone, wound_bonus = CANT_WOUND) if(!(flags & CALTROP_NOSTUN)) // Won't set off the paralysis. - H.Paralyze(60) + H.Paralyze(paralyze_duration) if(!soundfile) return diff --git a/code/datums/components/ground_sinking.dm b/code/datums/components/ground_sinking.dm new file mode 100644 index 00000000000..3123172b222 --- /dev/null +++ b/code/datums/components/ground_sinking.dm @@ -0,0 +1,142 @@ +#define REGENERATION_FILTER "healing_glow" + +/** + * # Ground sinking component (basicly only for garden gnomes ever at this point) + * + * A basic mob with this component will sink into the ground, once sinked into the ground it will regenerate and + * might gain damage resistence. Can be combined with caltrop. + */ +/datum/component/ground_sinking + /// The icon state of the parent + var/target_icon_state + /// You will only sink if you haven't been walking for this many seconds + var/ground_sinking_delay + /// The speed at which the mob will sink + var/sink_speed + /// If we will heal once we are sinked + var/heal_when_sinked + /// Health to regenerate per second + var/health_per_second + /// Outline colour of the regeneration + var/outline_colour + /// Our damage_coeffs when we are sinked + var/damage_res_sinked + /// If we sinked into the ground right now + var/sinked = FALSE + /// If we sinking into the ground right now + var/is_sinking = FALSE + /// How far we have sinked + var/sink_count = 0 + /// When this timer completes we start sinking + var/ground_sinking_start_timer + +/datum/component/ground_sinking/Initialize(target_icon_state, + ground_sinking_delay = 8 SECONDS, + sink_speed = 1 SECONDS, + heal_when_sinked = TRUE, + health_per_second = 1, + outline_colour = COLOR_PALE_GREEN, + damage_res_sinked = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1)) + + if (!isbasicmob(parent)) + return COMPONENT_INCOMPATIBLE + + src.target_icon_state = target_icon_state + src.ground_sinking_delay = ground_sinking_delay + src.sink_speed = sink_speed + src.heal_when_sinked = heal_when_sinked + src.health_per_second = health_per_second + src.outline_colour = outline_colour + src.damage_res_sinked = damage_res_sinked + +/datum/component/ground_sinking/RegisterWithParent() + RegisterSignal(parent, COMSIG_MOVABLE_MOVED, PROC_REF(on_moved)) + +/datum/component/ground_sinking/UnregisterFromParent() + if(sinked || is_sinking) + unsink() + if(ground_sinking_start_timer) + deltimer(ground_sinking_start_timer) + UnregisterSignal(parent, COMSIG_MOVABLE_MOVED) + +/datum/component/ground_sinking/Destroy(force, silent) + if(sinked || is_sinking) + unsink() + . = ..() + if(ground_sinking_start_timer) + deltimer(ground_sinking_start_timer) + +/// When you take damage, reset the cooldown and start processing +/datum/component/ground_sinking/proc/on_moved(mob/living/basic/living_target, atom/OldLoc, Dir, Forced) + SIGNAL_HANDLER + if(sinked || is_sinking) + unsink() + if(ground_sinking_start_timer) + deltimer(ground_sinking_start_timer) + ground_sinking_start_timer = addtimer(CALLBACK(src, PROC_REF(start_sinking), living_target), ground_sinking_delay, TIMER_STOPPABLE) + +/// Start processing health regeneration, and show animation if provided +/datum/component/ground_sinking/proc/start_sinking(mob/living/basic/living_target) + if(!sinked || is_sinking) + is_sinking = TRUE + INVOKE_ASYNC(src, PROC_REF(sink_once), living_target) + +/datum/component/ground_sinking/proc/sink_once(mob/living/basic/living_target) + living_target.visible_message(span_notice("[living_target] starts sinking into the ground!")) + for(var/i in 1 to 3) + if(do_after(living_target, sink_speed, living_target)) + sink_count += 1 + living_target.icon_state = "[target_icon_state]_burried_[sink_count]" + sink_count = 0 + is_sinked(living_target) + +/datum/component/ground_sinking/proc/is_sinked(mob/living/basic/living_target) + sinked = TRUE + is_sinking = FALSE + living_target.density = FALSE + living_target.damage_coeff = damage_res_sinked + if(heal_when_sinked) + start_regenerating() + +/datum/component/ground_sinking/proc/unsink() + var/mob/living/basic/living_target = parent + if(sinked && heal_when_sinked) + stop_regenerating() + living_target.icon_state = target_icon_state + living_target.damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) + living_target.density = TRUE + sinked = FALSE + +/datum/component/ground_sinking/proc/start_regenerating() + var/mob/living/basic/living_parent = parent + if (living_parent.stat == DEAD) + return + if (living_parent.health == living_parent.maxHealth) + return + living_parent.visible_message(span_notice("[living_parent]'s wounds begin to knit closed!")) + START_PROCESSING(SSobj, src) + if (!outline_colour) + return + living_parent.add_filter(REGENERATION_FILTER, 2, list("type" = "outline", "color" = outline_colour, "alpha" = 0, "size" = 1)) + var/filter = living_parent.get_filter(REGENERATION_FILTER) + animate(filter, alpha = 200, time = 0.5 SECONDS, loop = -1) + animate(alpha = 0, time = 0.5 SECONDS) + +/datum/component/ground_sinking/proc/stop_regenerating() + STOP_PROCESSING(SSobj, src) + var/mob/living/basic/living_parent = parent + var/filter = living_parent.get_filter(REGENERATION_FILTER) + animate(filter) + living_parent.remove_filter(REGENERATION_FILTER) + +/datum/component/ground_sinking/process(delta_time = SSMOBS_DT) + var/mob/living/basic/living_parent = parent + if (living_parent.stat == DEAD) + stop_regenerating() + return + if (living_parent.health == living_parent.maxHealth) + stop_regenerating() + return + living_parent.heal_overall_damage(health_per_second * delta_time) + +#undef REGENERATION_FILTER diff --git a/code/datums/greyscale/config_types/greyscale_configs.dm b/code/datums/greyscale/config_types/greyscale_configs.dm index 9ad57fdd575..0d1ab52cbe8 100644 --- a/code/datums/greyscale/config_types/greyscale_configs.dm +++ b/code/datums/greyscale/config_types/greyscale_configs.dm @@ -52,6 +52,11 @@ name = "Space Carp, Disk in Mouth" json_config = 'code/datums/greyscale/json_configs/carp_disk_mouth.json' +/datum/greyscale_config/garden_gnome + name = "Garden Gnome" + icon_file = 'icons/mob/simple/garden_gnome.dmi' + json_config = 'code/datums/greyscale/json_configs/garden_gnome.json' + /datum/greyscale_config/wirecutters name = "Wirecutters" icon_file = 'icons/obj/tools.dmi' diff --git a/code/datums/greyscale/json_configs/garden_gnome.json b/code/datums/greyscale/json_configs/garden_gnome.json new file mode 100644 index 00000000000..c443e6f04a6 --- /dev/null +++ b/code/datums/greyscale/json_configs/garden_gnome.json @@ -0,0 +1,126 @@ +{ + "gnome": [ + { + "type": "icon_state", + "icon_state": "gnome", + "blend_mode": "overlay" + }, + { + "type": "icon_state", + "icon_state": "gnome_hat", + "blend_mode": "overlay", + "color_ids": [ 1 ] + }, + { + "type": "icon_state", + "icon_state": "gnome_body", + "blend_mode": "overlay", + "color_ids": [ 2 ] + }, + { + "type": "icon_state", + "icon_state": "gnome_pants", + "blend_mode": "overlay", + "color_ids": [ 3 ] + }, + { + "type": "icon_state", + "icon_state": "gnome_beard", + "blend_mode": "overlay", + "color_ids": [ 4 ] + } + ], + "gnome_burried_1": [ + { + "type": "icon_state", + "icon_state": "gnome_burried_1", + "blend_mode": "overlay" + }, + { + "type": "icon_state", + "icon_state": "gnome_hat_burried_1", + "blend_mode": "overlay", + "color_ids": [ 1 ] + }, + { + "type": "icon_state", + "icon_state": "gnome_body_burried_1", + "blend_mode": "overlay", + "color_ids": [ 2 ] + }, + { + "type": "icon_state", + "icon_state": "gnome_pants_burried_1", + "blend_mode": "overlay", + "color_ids": [ 3 ] + }, + { + "type": "icon_state", + "icon_state": "gnome_beard_burried_1", + "blend_mode": "overlay", + "color_ids": [ 4 ] + } + ], + "gnome_burried_2": [ + { + "type": "icon_state", + "icon_state": "gnome_burried_2", + "blend_mode": "overlay" + }, + { + "type": "icon_state", + "icon_state": "gnome_hat_burried_2", + "blend_mode": "overlay", + "color_ids": [ 1 ] + }, + { + "type": "icon_state", + "icon_state": "gnome_body_burried_2", + "blend_mode": "overlay", + "color_ids": [ 2 ] + }, + { + "type": "icon_state", + "icon_state": "gnome_pants_burried_2", + "blend_mode": "overlay", + "color_ids": [ 3 ] + }, + { + "type": "icon_state", + "icon_state": "gnome_beard_burried_2", + "blend_mode": "overlay", + "color_ids": [ 4 ] + } + ], + "gnome_burried_3": [ + { + "type": "icon_state", + "icon_state": "gnome_burried_3", + "blend_mode": "overlay" + }, + { + "type": "icon_state", + "icon_state": "gnome_hat_burried_3", + "blend_mode": "overlay", + "color_ids": [ 1 ] + }, + { + "type": "icon_state", + "icon_state": "gnome_body_burried_3", + "blend_mode": "overlay", + "color_ids": [ 2 ] + }, + { + "type": "icon_state", + "icon_state": "gnome_pants_burried_3", + "blend_mode": "overlay", + "color_ids": [ 3 ] + }, + { + "type": "icon_state", + "icon_state": "gnome_beard_burried_3", + "blend_mode": "overlay", + "color_ids": [ 4 ] + } + ] +} diff --git a/code/modules/cargo/packs/livestock.dm b/code/modules/cargo/packs/livestock.dm index a1f6b33930b..a2a1f641945 100644 --- a/code/modules/cargo/packs/livestock.dm +++ b/code/modules/cargo/packs/livestock.dm @@ -197,3 +197,16 @@ access_view = ACCESS_JANITOR contains = list(/mob/living/simple_animal/hostile/lizard) crate_name = "lizard crate" + +/datum/supply_pack/critter/garden_gnome + name = "Garden Gnome Crate" + desc = "Collect them all for your garden. Comes with three!" + hidden = TRUE + cost = CARGO_CRATE_VALUE * 20 + contains = list(/mob/living/basic/garden_gnome) + crate_name = "garden gnome crate" + +/datum/supply_pack/critter/garden_gnome/generate() + . = ..() + for(var/i in 1 to 2) + new /mob/living/basic/garden_gnome(.) diff --git a/code/modules/mob/living/basic/retaliate/garden_gnome.dm b/code/modules/mob/living/basic/retaliate/garden_gnome.dm new file mode 100644 index 00000000000..36c2b64a961 --- /dev/null +++ b/code/modules/mob/living/basic/retaliate/garden_gnome.dm @@ -0,0 +1,149 @@ +/mob/living/basic/garden_gnome + name = "Garden Gnome" + desc = "You have been gnomed." + icon = 'icons/mob/simple/garden_gnome.dmi' + icon_state = "gnome" + icon_living = "gnome" + pass_flags = PASSMOB + mob_biotypes = MOB_ORGANIC|MOB_HUMANOID + speed = 1 + maxHealth = 40 + health = 40 + basic_mob_flags = DEL_ON_DEATH + + obj_damage = 20 + melee_damage_lower = 5 + melee_damage_upper = 10 + attack_verb_continuous = "punches" + attack_verb_simple = "punch" + attack_sound = 'sound/weapons/punch1.ogg' + damage_coeff = list(BRUTE = 1, BURN = 1, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) + speak_emote = list("announces") + + unsuitable_atmos_damage = 0 + minimum_survivable_temperature = 0 + maximum_survivable_temperature = 500 + + faction = list("gnomes") + mob_size = MOB_SIZE_SMALL + gold_core_spawnable = HOSTILE_SPAWN + greyscale_config = /datum/greyscale_config/garden_gnome + ai_controller = /datum/ai_controller/basic_controller/garden_gnome + /// The damage resistence when sinked into the ground + var/resistance_when_sinked = list(BRUTE = 0.5, BURN = 0.5, TOX = 1, CLONE = 1, STAMINA = 0, OXY = 1) + /// Realistically weighted list of usual gnome hat colours + var/static/list/gnome_hat_colours = list( + COLOR_GNOME_RED_ONE = 9, + COLOR_GNOME_RED_TWO = 9, + COLOR_GNOME_RED_THREE = 9, + COLOR_GNOME_BLUE_ONE = 3, + COLOR_GNOME_BLUE_TWO = 3, + COLOR_GNOME_BLUE_THREE = 3, + COLOR_GNOME_GREEN_ONE = 3, + COLOR_GNOME_GREEN_TWO = 3, + COLOR_GNOME_ORANGE = 3, + COLOR_GNOME_BROWN_ONE = 3, + COLOR_GNOME_YELLOW = 2, + COLOR_GNOME_GREY = 2, + COLOR_GNOME_PURPLE = 1, + COLOR_GNOME_WHITE = 1, + COLOR_GNOME_BLACK = 1, + ) + /// The chosen hat colour + var/chosen_hat_colour + /// Realistically weighted list of usual gnome body colours + var/static/list/gnome_body_colours = list( + COLOR_GNOME_YELLOW = 6, + COLOR_GNOME_RED_ONE = 3, + COLOR_GNOME_RED_TWO = 3, + COLOR_GNOME_RED_THREE = 3, + COLOR_GNOME_BLUE_ONE = 3, + COLOR_GNOME_BLUE_TWO = 3, + COLOR_GNOME_BLUE_THREE = 3, + COLOR_GNOME_GREEN_ONE = 3, + COLOR_GNOME_GREEN_TWO = 3, + COLOR_GNOME_BROWN_ONE = 3, + COLOR_GNOME_ORANGE = 2, + COLOR_GNOME_WHITE = 1, + COLOR_GNOME_GREY = 1, + COLOR_GNOME_PURPLE = 1, + COLOR_GNOME_BLACK = 1, + ) + /// Realistically weighted list of usual gnome pants colours + var/static/list/gnome_pants_colours = list( + COLOR_GNOME_BLUE_ONE = 6, + COLOR_GNOME_BLUE_TWO = 6, + COLOR_GNOME_BLUE_THREE = 6, + COLOR_GNOME_GREEN_ONE = 6, + COLOR_GNOME_GREEN_TWO = 6, + COLOR_GNOME_BROWN_ONE = 3, + COLOR_GNOME_BROWN_TWO = 3, + COLOR_GNOME_RED_ONE = 1, + COLOR_GNOME_ORANGE = 1, + COLOR_GNOME_WHITE = 1, + COLOR_GNOME_GREY = 1, + COLOR_GNOME_PURPLE = 1, + COLOR_GNOME_BLACK = 1, + ) + /// Realistically weighted list of usual gnome beard colours + var/static/list/gnome_beard_colours = list( + COLOR_GNOME_WHITE = 9, + COLOR_GNOME_GREY = 9, + COLOR_GNOME_BROWN_ONE = 6, + COLOR_GNOME_BROWN_TWO = 6, + COLOR_GNOME_BLACK = 6, + COLOR_GNOME_ORANGE = 3, + COLOR_GNOME_GREEN_TWO = 1, + COLOR_GNOME_RED_ONE = 1, + COLOR_GNOME_PURPLE = 1, + ) + +/mob/living/basic/garden_gnome/Initialize(mapload) + . = ..() + var/datum/callback/retaliate_callback = CALLBACK(src, PROC_REF(ai_retaliate_behaviour)) + chosen_hat_colour = pick_weight(gnome_hat_colours) + apply_colour() + AddElement(/datum/element/death_drops, list(/obj/effect/gibspawner/generic)) + AddElement(/datum/element/footstep, FOOTSTEP_MOB_SHOE) + AddComponent(/datum/component/ai_retaliate_advanced, retaliate_callback) + AddComponent(/datum/component/swarming) + AddComponent(/datum/component/ground_sinking, target_icon_state = icon_state, outline_colour = chosen_hat_colour, damage_res_sinked = resistance_when_sinked) + AddComponent(/datum/component/caltrop, min_damage = 5, max_damage = 10, paralyze_duration = 1 SECONDS, flags = CALTROP_BYPASS_SHOES) + ADD_TRAIT(src, TRAIT_SPACEWALK, INNATE_TRAIT) + ADD_TRAIT(src, TRAIT_VENTCRAWLER_ALWAYS, INNATE_TRAIT) + +/mob/living/basic/garden_gnome/proc/apply_colour() + if(!greyscale_config) + return + set_greyscale(colors = list(chosen_hat_colour, pick_weight(gnome_body_colours), pick_weight(gnome_pants_colours), pick_weight(gnome_beard_colours))) + +/mob/living/basic/garden_gnome/proc/ai_retaliate_behaviour(mob/living/attacker) + if (!istype(attacker)) + return + var/list/enemy_refs + for (var/mob/living/basic/garden_gnome/potential_gnome in oview(src, 7)) + enemy_refs = potential_gnome.ai_controller.blackboard[BB_BASIC_MOB_RETALIATE_LIST] + if (!enemy_refs) + enemy_refs = list() + enemy_refs |= WEAKREF(attacker) + potential_gnome.ai_controller.blackboard[BB_BASIC_MOB_RETALIATE_LIST] = enemy_refs + +/datum/ai_controller/basic_controller/garden_gnome + blackboard = list( + BB_TARGETTING_DATUM = new /datum/targetting_datum/basic(), + ) + + ai_movement = /datum/ai_movement/basic_avoidance + idle_behavior = /datum/idle_behavior/idle_random_walk/less_walking + planning_subtrees = list( + /datum/ai_planning_subtree/target_retaliate, + /datum/ai_planning_subtree/attack_obstacle_in_path, + /datum/ai_planning_subtree/basic_melee_attack_subtree/garden_gnome, + /datum/ai_planning_subtree/random_speech/garden_gnome, + ) + +/datum/ai_planning_subtree/basic_melee_attack_subtree/garden_gnome + melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/garden_gnome + +/datum/ai_behavior/basic_melee_attack/garden_gnome + action_cooldown = 1.2 SECONDS diff --git a/icons/mob/simple/garden_gnome.dmi b/icons/mob/simple/garden_gnome.dmi new file mode 100644 index 00000000000..f4158c7069e Binary files /dev/null and b/icons/mob/simple/garden_gnome.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 48f829cb819..d78d895b0e7 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -894,6 +894,7 @@ #include "code\datums\components\acid.dm" #include "code\datums\components\action_item_overlay.dm" #include "code\datums\components\admin_popup.dm" +#include "code\datums\components\ai_retaliate_advanced.dm" #include "code\datums\components\anti_magic.dm" #include "code\datums\components\aquarium.dm" #include "code\datums\components\area_sound_manager.dm" @@ -953,6 +954,7 @@ #include "code\datums\components\genetic_damage.dm" #include "code\datums\components\gps.dm" #include "code\datums\components\grillable.dm" +#include "code\datums\components\ground_sinking.dm" #include "code\datums\components\gunpoint.dm" #include "code\datums\components\hazard_area.dm" #include "code\datums\components\heirloom.dm" @@ -3760,6 +3762,7 @@ #include "code\modules\mob\living\basic\lavaland\bileworm\bileworm_vileworm.dm" #include "code\modules\mob\living\basic\pets\dog.dm" #include "code\modules\mob\living\basic\pets\pet.dm" +#include "code\modules\mob\living\basic\retaliate\garden_gnome.dm" #include "code\modules\mob\living\basic\retaliate\ghost.dm" #include "code\modules\mob\living\basic\ruin_defender\stickman.dm" #include "code\modules\mob\living\basic\space_fauna\carp\carp.dm"