diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index da6c87a202d8..29854ba4e84e 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -126,11 +126,6 @@ #define SPECIES_ZOMBIE "zombie" #define SPECIES_ZOMBIE_INFECTIOUS "memezombie" #define SPECIES_ZOMBIE_KROKODIL "krokodil_zombie" -#define SPECIES_OOZELING "oozeling" -#define SPECIES_IPC "ipc" -#define SPECIES_SIMIAN "simian" //Monkestation Addition -#define SPECIES_GOBLIN "goblin" //Monkestation Addition -#define SPECIES_FLORAN "floran" //Monkestation Addition // Like species IDs, but not specifically attached a species. #define BODYPART_ID_ALIEN "alien" #define BODYPART_ID_ROBOTIC "robotic" diff --git a/code/__DEFINES/research/anomalies.dm b/code/__DEFINES/research/anomalies.dm index c5b626cf9249..9623afb94c5f 100644 --- a/code/__DEFINES/research/anomalies.dm +++ b/code/__DEFINES/research/anomalies.dm @@ -28,12 +28,14 @@ GLOBAL_LIST_INIT(bioscrambler_parts_blacklist, typecacheof(list( ))) /// Blacklist of limb IDs which should not appear when bioscrambled, mostly because they looks awful and buggy. +/* - Moved to Monkeystation Defines file. Because apparently it was never considered we may modularise species code. GLOBAL_LIST_INIT(bioscrambler_limb_id_blacklist, list( BODYPART_ID_PSYKER, SPECIES_SIMIAN, SPECIES_MONKEY, SPECIES_GOBLIN )) +*/ /// Blacklist of organs which should not appear when bioscrambled. /// Either will look terrible outside of intended host, give you magical powers, are irreversible, or kill you diff --git a/code/__DEFINES/~monkestation/mobs.dm b/code/__DEFINES/~monkestation/mobs.dm index 9f531dc4da76..c15eb02c5cee 100644 --- a/code/__DEFINES/~monkestation/mobs.dm +++ b/code/__DEFINES/~monkestation/mobs.dm @@ -1,5 +1,13 @@ +//Monkeystation Species Defines. Please update this here instead of /tg/stations mobs.dm \\ + #define SPECIES_ARACHNIDS "arachnid" #define SPECIES_DRACONIC_SKELETON "draconic_skeleton" +#define SPECIES_OOZELING "oozeling" +#define SPECIES_IPC "ipc" +#define SPECIES_SIMIAN "simian" +#define SPECIES_GOBLIN "goblin" +#define SPECIES_FLORAN "floran" +#define SPECIES_NABBER "nabber" GLOBAL_REAL_VAR(list/voice_type2sound = list( "1" = list( diff --git a/code/__byond_version_compat.dm b/code/__byond_version_compat.dm index 88d78e3ad36d..089d555fb4ff 100644 --- a/code/__byond_version_compat.dm +++ b/code/__byond_version_compat.dm @@ -9,7 +9,6 @@ #error You need version 515.1627 or higher #endif - // Keep savefile compatibilty at minimum supported level /savefile/byond_version = MIN_COMPILER_VERSION diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index 08a3c9d70a23..c0835b2d999b 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -221,6 +221,7 @@ GLOBAL_LIST_INIT(available_ui_styles, list( action_intent = null zone_select = null pull_icon = null + rest_icon = null //MONKEYSTATION FIX: FIXES HARDDEL QDEL_LIST(toggleable_inventory) QDEL_LIST(hotkeybuttons) diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 87fee0d97f30..2d7c6a7d93b8 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -310,6 +310,10 @@ flashy.color = "#C62727" . += flashy +/atom/movable/screen/combattoggle/flashy/Destroy() + . = ..() + QDEL_NULL(flashy) //Monkeystation Edit - Absolutely make sure these things avoid harddels + /atom/movable/screen/combattoggle/robot icon = 'icons/hud/screen_cyborg.dmi' screen_loc = ui_borg_intents diff --git a/code/datums/components/bloodysoles.dm b/code/datums/components/bloodysoles.dm index 9fab9bf8d4b5..a01bc060a1e1 100644 --- a/code/datums/components/bloodysoles.dm +++ b/code/datums/components/bloodysoles.dm @@ -23,6 +23,9 @@ var/footprint_sprite = FOOTPRINT_SPRITE_SHOES + //Monkeystation edit. Holds colors. + var/blood_color + /datum/component/bloodysoles/Initialize() if(!isclothing(parent)) return COMPONENT_INCOMPATIBLE @@ -92,7 +95,7 @@ set_bloody_shoes(pool.blood_state, new_our_bloodiness) pool.bloodiness = total_bloodiness - new_our_bloodiness // Give the pool the remaining blood incase we were limited - + blood_color = pool.color //Monkeystation Edit. if(HAS_TRAIT(parent_atom, TRAIT_LIGHT_STEP)) //the character is agile enough to don't mess their clothing and hands just from one blood splatter at floor return TRUE @@ -184,6 +187,7 @@ oldLocFP.bloodiness = half_our_blood oldLocFP.add_blood_DNA(GET_ATOM_BLOOD_DNA(parent_atom)) oldLocFP.update_appearance() + oldLocFP.color = blood_color //Monkeystation Edit. Blood color for footprints. half_our_blood = bloody_shoes[last_blood_state] / 2 @@ -197,6 +201,7 @@ update_icon() var/obj/effect/decal/cleanable/blood/footprints/FP = new(get_turf(parent_atom), footprint_sprite) + FP.color = blood_color //Monkeystation edit. if(!QDELETED(FP)) ///prints merged FP.blood_state = last_blood_state FP.entered_dirs |= wielder.dir diff --git a/code/datums/interactions/combat_mode.dm b/code/datums/interactions/combat_mode.dm index 2438e1865bed..ad4d174daabe 100644 --- a/code/datums/interactions/combat_mode.dm +++ b/code/datums/interactions/combat_mode.dm @@ -1,6 +1,7 @@ /datum/interaction_mode/combat_mode shift_to_open_context_menu = TRUE var/combat_mode = FALSE + var/held_hud //Monkeystation Edit. Ensures the HUD is tracked to prevent harddels /datum/interaction_mode/combat_mode/update_istate(mob/M, modifiers) M.istate = NONE @@ -19,6 +20,7 @@ if (!M.hud_used.has_interaction_ui) return var/atom/movable/screen/combattoggle/flashy/CT = new + held_hud = CT //Monkeystation Edit. Keep track of this HUD for future destruction. CT.hud = H CT.icon = H.ui_style CT.combat_mode = src diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index 83d905882447..c9781542df4c 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -49,7 +49,7 @@ name = dryname desc = drydesc bloodiness = 0 - color = COLOR_GRAY //not all blood splatters have their own sprites... It still looks pretty nice + color = "#6b0000" //Monkeystation edit. Fallback for blood drying. STOP_PROCESSING(SSobj, src) return TRUE @@ -365,6 +365,8 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) var/splatter_strength = 3 /// Insurance so that we don't keep moving once we hit a stoppoint var/hit_endpoint = FALSE + /// Monkeystation Edit: Ensures these retain proper colour variables, and that even in the worst case, the blood is still red. + var/held_color = "#b60a0a" /obj/effect/decal/cleanable/blood/hitsplatter/Initialize(mapload, splatter_strength) . = ..() @@ -376,7 +378,8 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) if(isturf(loc) && !skip) playsound(src, 'sound/effects/wounds/splatter.ogg', 60, TRUE, -1) if(blood_dna_info) - loc.add_blood_DNA(blood_dna_info) + var/turf/land = loc + land.add_blood_DNA_special(blood_dna_info, colour = held_color) //Monkeystation edit. Preserves blood colour. return ..() /// Set the splatter up to fly through the air until it rounds out of steam or hits something @@ -439,6 +442,7 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) land_on_window(bumped_atom) else var/obj/effect/decal/cleanable/blood/splatter/over_window/final_splatter = new(prev_loc) + final_splatter.color = held_color //Monkeystation Edit: Keeps blood color consistent! final_splatter.pixel_x = (dir == EAST ? 32 : (dir == WEST ? -32 : 0)) final_splatter.pixel_y = (dir == NORTH ? 32 : (dir == SOUTH ? -32 : 0)) else // This will only happen if prev_loc is not even a turf, which is highly unlikely. @@ -451,6 +455,7 @@ GLOBAL_LIST_EMPTY(bloody_footprints_cache) return var/obj/effect/decal/cleanable/blood/splatter/over_window/final_splatter = new final_splatter.forceMove(the_window) + final_splatter.color = src.color //Monkeystation Edit: Keeps blood color consistent! the_window.vis_contents += final_splatter the_window.bloodied = TRUE qdel(src) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index 6a0475ab053b..91f2ecb86523 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -373,6 +373,7 @@ GLOBAL_LIST_EMPTY(preferences_datums) /atom/movable/screen/map_view/char_preview/Destroy() QDEL_NULL(body) + body = null //Monkeystation edit. Absolutely ensure this qdels. preferences?.character_preview_view = null preferences = null return ..() diff --git a/code/modules/mob/living/blood.dm b/code/modules/mob/living/blood.dm index 373398934a8b..f018e216cf26 100644 --- a/code/modules/mob/living/blood.dm +++ b/code/modules/mob/living/blood.dm @@ -335,7 +335,6 @@ var/datum/reagent/blood_type = get_blood_id() var/list/temp_blood_DNA if(small_drip) - if(T.liquids) var/list/blood_drop = list(get_blood_id() = 0.1) T.add_liquid_list(blood_drop, FALSE, 300) @@ -347,7 +346,7 @@ T.pollute_turf(/datum/pollutant/metallic_scent, 5) drop.drips++ drop.add_overlay(pick(drop.random_icon_states)) - drop.transfer_mob_blood_dna(src) + drop.transfer_mob_blood_dna(src, TRUE) //MONKEY EDIT: , TRUE append to allow for custom blood colours. Also makes blood splatters now transfer DNA! Forensics buff! return else temp_blood_DNA = GET_ATOM_BLOOD_DNA(drop) //we transfer the dna from the drip to the splatter @@ -355,7 +354,7 @@ else T.pollute_turf(/datum/pollutant/metallic_scent, 5) drop = new(T, get_static_viruses()) - drop.transfer_mob_blood_dna(src) + drop.transfer_mob_blood_dna(src, TRUE) //MONKEY EDIT: , TRUE append to allow for custom blood colours. Also makes blood splatters now transfer DNA! Forensics buff! return // Create a bit of metallic pollution, as that's how blood smells @@ -365,10 +364,11 @@ var/obj/effect/decal/cleanable/blood/B = locate() in T if(!B) B = new /obj/effect/decal/cleanable/blood/splatter(T, get_static_viruses()) + B.transfer_mob_blood_dna(src, TRUE) //MONKEY EDIT: , TRUE append to allow for custom blood colours. Also makes blood splatters now transfer DNA! Forensics buff! if(QDELETED(B)) //Give it up return B.bloodiness = min((B.bloodiness + BLOOD_AMOUNT_PER_DECAL), BLOOD_POOL_MAX) - B.transfer_mob_blood_dna(src) //give blood info to the blood decal. + B.transfer_mob_blood_dna(src, TRUE) //MONKEY EDIT: , TRUE append to allow for custom blood colours if(temp_blood_DNA) B.add_blood_DNA(temp_blood_DNA) @@ -376,8 +376,8 @@ if(blood_type) B.color = initial(blood_type.color) B.count ++ - B.transfer_mob_blood_dna(src) - B.transfer_mob_blood_dna(src) //give blood info to the blood decal. + B.transfer_mob_blood_dna(src, TRUE) //MONKEY EDIT: , TRUE append to allow for custom blood colours. Also makes blood splatters now transfer DNA! Forensics buff! + B.transfer_mob_blood_dna(src, TRUE) //MONKEY EDIT: , TRUE append to allow for custom blood colours if(temp_blood_DNA) B.add_blood_DNA(temp_blood_DNA) diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index ad10167adec1..3d0c3766586d 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -1353,8 +1353,12 @@ var/obj/effect/decal/cleanable/blood/hitsplatter/our_splatter = new(loc) our_splatter.add_blood_DNA(GET_ATOM_BLOOD_DNA(src)) our_splatter.blood_dna_info = get_blood_dna_list() + our_splatter.transfer_mob_blood_dna(src, TRUE) //Monkeystation Edit: Makes it so blood sprays also inherit blood colour changes var/turf/targ = get_ranged_target_turf(src, splatter_direction, splatter_strength) our_splatter.fly_towards(targ, splatter_strength) + if(ishuman(src)) //Monkeystation Edit: Ensures that no matter what, splatters will hold the color of blood in question. + var/mob/living/carbon/human/blood_donor = src + our_splatter.held_color = blood_donor.dna.species.blood_colours /mob/living/carbon/ominous_nosebleed() var/obj/item/bodypart/head = get_bodypart(BODY_ZONE_HEAD) diff --git a/code/modules/mob/living/carbon/human/human_update_icons.dm b/code/modules/mob/living/carbon/human/human_update_icons.dm index ab2f15c4ee70..c0f94e312bab 100644 --- a/code/modules/mob/living/carbon/human/human_update_icons.dm +++ b/code/modules/mob/living/carbon/human/human_update_icons.dm @@ -1000,4 +1000,22 @@ generate/load female uniform sprites matching all previously decided variables return appearance +//MONKEYSTATION EDIT - ENSURES FILTERS ARE CUT UPON BEING DESTROYED \\ + +/mob/living/carbon/human/proc/get_filter_and_destroy(filtername) //Using this is way neater code-wise. + var/filter = src.get_filter(filtername) + if(filter) + remove_filter(filter) + +/mob/living/carbon/human/Destroy() //Ensure all filters are cut on destroy. Hopefully prevents harddels due to height. + . = ..() + src.get_filter_and_destroy("Gnome_Cut_Torso") + src.get_filter_and_destroy("Gnome_Cut_Legs") + src.get_filter_and_destroy("Cut_Torso") + src.get_filter_and_destroy("Cut_Legs") + src.get_filter_and_destroy("Lenghten_Legs") + src.get_filter_and_destroy("Lenghten_Torso") + +//MONKEYSTATION EDIT END\\ + #undef RESOLVE_ICON_STATE diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 9a6eef2625e3..3f72f7dd0d74 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1050,7 +1050,7 @@ if((!(newdir in TH.existing_dirs) || trail_type == "trails_1" || trail_type == "trails_2") && TH.existing_dirs.len <= 16) //maximum amount of overlays is 16 (all light & heavy directions filled) TH.existing_dirs += newdir TH.add_overlay(image('icons/effects/blood.dmi', trail_type, dir = newdir)) - TH.transfer_mob_blood_dna(src) + TH.transfer_mob_blood_dna(src, TRUE) //Monkeystation Edit: Ensures blood color and DNA is successfully transferred to new blood. /mob/living/carbon/human/makeTrail(turf/T) if(HAS_TRAIT(src, TRAIT_NOBLOOD) || !is_bleeding() || HAS_TRAIT(src, TRAIT_NOBLOOD)) diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index a0625e127bc3..2b0045a3d988 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -108,6 +108,7 @@ var/obj/effect/decal/cleanable/blood/bloodsplatter = locate() in exposed_turf //find some blood here if(!bloodsplatter) bloodsplatter = new(exposed_turf, data["viruses"]) + bloodsplatter.color = "#b60a0a" //Monkeystation Edit: Ensures splattered blood will always be red. else if(LAZYLEN(data["viruses"])) var/list/viri_to_add = list() for(var/datum/disease/virus in data["viruses"]) diff --git a/code/modules/research/techweb/all_nodes.dm b/code/modules/research/techweb/all_nodes.dm index d7387c6a04c4..82f0e2525a76 100644 --- a/code/modules/research/techweb/all_nodes.dm +++ b/code/modules/research/techweb/all_nodes.dm @@ -1542,8 +1542,7 @@ "pepperspray", "seclite", "zipties", - "inspector", - "rubber_c35", //monkestation edit: taco sec + "inspector" ) research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 1000) diff --git a/code/modules/unit_tests/screenshots/screenshot_antag_icons_bloodbrother.png b/code/modules/unit_tests/screenshots/screenshot_antag_icons_bloodbrother.png index a8a72e429e72..940b72c6753f 100644 Binary files a/code/modules/unit_tests/screenshots/screenshot_antag_icons_bloodbrother.png and b/code/modules/unit_tests/screenshots/screenshot_antag_icons_bloodbrother.png differ diff --git a/code/modules/unit_tests/screenshots/screenshot_antag_icons_bloodsucker.png b/code/modules/unit_tests/screenshots/screenshot_antag_icons_bloodsucker.png index 27a91f8f14c2..98a80a2b8882 100644 Binary files a/code/modules/unit_tests/screenshots/screenshot_antag_icons_bloodsucker.png and b/code/modules/unit_tests/screenshots/screenshot_antag_icons_bloodsucker.png differ diff --git a/code/modules/unit_tests/screenshots/screenshot_antag_icons_bloodsuckerbreakout.png b/code/modules/unit_tests/screenshots/screenshot_antag_icons_bloodsuckerbreakout.png index 27a91f8f14c2..98a80a2b8882 100644 Binary files a/code/modules/unit_tests/screenshots/screenshot_antag_icons_bloodsuckerbreakout.png and b/code/modules/unit_tests/screenshots/screenshot_antag_icons_bloodsuckerbreakout.png differ diff --git a/code/modules/unit_tests/screenshots/screenshot_antag_icons_obsessed.png b/code/modules/unit_tests/screenshots/screenshot_antag_icons_obsessed.png index 1d5f88bd8407..08b82e53afee 100644 Binary files a/code/modules/unit_tests/screenshots/screenshot_antag_icons_obsessed.png and b/code/modules/unit_tests/screenshots/screenshot_antag_icons_obsessed.png differ diff --git a/code/modules/unit_tests/screenshots/screenshot_antag_icons_vampiricaccident.png b/code/modules/unit_tests/screenshots/screenshot_antag_icons_vampiricaccident.png index 27a91f8f14c2..98a80a2b8882 100644 Binary files a/code/modules/unit_tests/screenshots/screenshot_antag_icons_vampiricaccident.png and b/code/modules/unit_tests/screenshots/screenshot_antag_icons_vampiricaccident.png differ diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_nabber.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_nabber.png new file mode 100644 index 000000000000..f10aa031b1e0 Binary files /dev/null and b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_nabber.png differ diff --git a/icons/effects/blood.dmi b/icons/effects/blood.dmi index 36f30f74f1ff..4e38d84fce41 100644 Binary files a/icons/effects/blood.dmi and b/icons/effects/blood.dmi differ diff --git a/monkestation/code/__DEFINES/bodytypes.dm b/monkestation/code/__DEFINES/bodytypes.dm new file mode 100644 index 000000000000..b29150dbbc03 --- /dev/null +++ b/monkestation/code/__DEFINES/bodytypes.dm @@ -0,0 +1,2 @@ +//Can likely be moved elsewhere. This will handle limbs that absolutely SHOULD NOT go on other species under any circumstances. +#define BODYSHAPE_CUSTOM (1<<9) diff --git a/monkestation/code/__DEFINES/nabber.dm b/monkestation/code/__DEFINES/nabber.dm new file mode 100644 index 000000000000..63d7defc8e80 --- /dev/null +++ b/monkestation/code/__DEFINES/nabber.dm @@ -0,0 +1,14 @@ +//Handles nabber-related code +#define OFFSET_HELD "held" //handles the fact they have weird grab positions. Can be used for other species. + +#define NABBER_ACCESSORIES_ICON 'monkestation/code/modules/nabbers/icons/mob/clothing/accessories.dmi' +#define NABBER_BACK_ICON 'monkestation/code/modules/nabbers/icons/mob/clothing/back.dmi' +#define NABBER_BELT_ICON 'monkestation/code/modules/nabbers/icons/mob/clothing/belt.dmi' +#define NABBER_EYES_ICON 'monkestation/code/modules/nabbers/icons/mob/clothing/eyes.dmi' +#define NABBER_HANDS_ICON 'monkestation/code/modules/nabbers/icons/mob/clothing/hands.dmi' +#define NABBER_HEAD_ICON 'monkestation/code/modules/nabbers/icons/mob/clothing/head.dmi' +#define NABBER_MASK_ICON 'monkestation/code/modules/nabbers/icons/mob/clothing/mask.dmi' +#define NABBER_NECK_ICON 'monkestation/code/modules/nabbers/icons/mob/clothing/neck.dmi' +#define NABBER_SUIT_ICON 'monkestation/code/modules/nabbers/icons/mob/clothing/suit.dmi' +#define NABBER_UNIFORM_ICON 'monkestation/code/modules/nabbers/icons/mob/clothing/uniform.dmi' +#define NABBER_EARS_ICON 'monkestation/code/modules/nabbers/icons/mob/clothing/ears.dmi' diff --git a/monkestation/code/__DEFINES/research/anomalies.dm b/monkestation/code/__DEFINES/research/anomalies.dm new file mode 100644 index 000000000000..53c39ae94a59 --- /dev/null +++ b/monkestation/code/__DEFINES/research/anomalies.dm @@ -0,0 +1,7 @@ +/// Blacklist of limb IDs which should not appear when bioscrambled, mostly because they looks awful and buggy. +GLOBAL_LIST_INIT(bioscrambler_limb_id_blacklist, list( + BODYPART_ID_PSYKER, + SPECIES_SIMIAN, + SPECIES_MONKEY, + SPECIES_GOBLIN +)) diff --git a/monkestation/code/modules/_assorted_species_upgrades/code/_mob.dm b/monkestation/code/modules/_assorted_species_upgrades/code/_mob.dm new file mode 100644 index 000000000000..5466dd6a0d40 --- /dev/null +++ b/monkestation/code/modules/_assorted_species_upgrades/code/_mob.dm @@ -0,0 +1,246 @@ +//defines +#define NABBER_OVERLAY_LAYER 21.1 //float layer lmao +//handles species upgrades +/datum/species + var/uses_offsets = FALSE //This will determine if the offset system is active or not. + var/blood_colours = "#b60a0a" //This is the default blood colour used by the backup blood system. Until changed on subtypes, this is what is used to handle bleeding. + var/held_accessory //neccessary for nabbers having cool shit + var/held_accessory_path // should not exist unless you're using things like custom arm overlays + +/datum/species/lizard + blood_colours = "#476d0a" + +/datum/species/arachnid + blood_colours = "#4b23b8" + +/datum/species/Destroy(force, ...) //absolutely should never happen. Handle it anyway. + . = ..() + uses_offsets = null + blood_colours = null + held_accessory = null + held_accessory_path = null + +/// Updates features and clothing attached to a specific limb with limb-specific offsets + +/mob/living/carbon/proc/update_features(feature_key) //absolutely vital this loads first + switch(feature_key) + if(OFFSET_UNIFORM) + update_worn_undersuit() + if(OFFSET_ID) + update_worn_id() + if(OFFSET_GLOVES) + update_worn_gloves() + if(OFFSET_GLASSES) + update_worn_glasses() + if(OFFSET_EARS) + update_inv_ears() //why is this inv_ears + if(OFFSET_SHOES) + update_worn_shoes() + if(OFFSET_S_STORE) + update_suit_storage() + if(OFFSET_FACEMASK) + update_worn_mask() + if(OFFSET_HEAD) + update_worn_head() + if(OFFSET_FACE) + dna?.species?.handle_body(src) // updates eye icon + update_worn_mask() + if(OFFSET_BELT) + update_worn_belt() + if(OFFSET_BACK) + update_worn_back() + if(OFFSET_SUIT) + update_worn_oversuit() + if(OFFSET_NECK) + update_worn_neck() + if(OFFSET_HELD) + update_held_items() +//Manages a ton of modular update_icons +//Why god why + +/* --------------------------------------- */ +// VVVV THIS CODE IS FUCKING ASS BUT MODULAR. VVVV +// REMEMBER THIS IS THE LESSER OF TWO EVILS. IT WAS THIS OR DOING A NOVA SECTOR AND REPLACING THE BASE PROCS +//vvvvvv UPDATE_INV PROCS vvvvvv + +/mob/living/carbon/human/proc/modify_accessory_overlay(var/accessory) //Repurposing this to be for all accessories/mods that need a spare layer. + var/mob/living/carbon/human/human_wearer = src + var/wanted_accessory = accessory + var/image/held_overlay + remove_overlay(NABBER_OVERLAY_LAYER) //begone + // handle custom overlay via grabbing the icon + if(human_wearer.dna.species.held_accessory_path) + var/icon/custom_accessory_icon_path = human_wearer.dna.species.held_accessory_path + held_overlay = image(icon=custom_accessory_icon_path,icon_state=wanted_accessory) //Grab the image in question + overlays_standing[NABBER_OVERLAY_LAYER] = held_overlay + apply_overlay(NABBER_OVERLAY_LAYER) + +/mob/living/carbon/human/update_worn_back(update_obscured = TRUE) //We're going to the fucking asylum with this one boys. This is how you should handle all future update_ if you wish to add more than custom backpack positions. + . = ..() + if(src.dna.species.uses_offsets == FALSE) + return + remove_overlay(BACK_LAYER) + + if(client && hud_used && hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_BACK) + 1]) + var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_BACK) + 1] + inv.update_icon() + + if(back) + var/obj/item/worn_item = back + var/mutable_appearance/back_overlay + update_hud_back(worn_item) + var/icon_file = 'icons/mob/clothing/back.dmi' + + var/mutant_override = FALSE + if(dna.species.bodytype & BODYTYPE_CUSTOM) + var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_MISC, back) + if(species_icon_file) + icon_file = species_icon_file + mutant_override = TRUE + + back_overlay = back.build_worn_icon(default_layer = BACK_LAYER, default_icon_file = icon_file , override_file = mutant_override ? icon_file : null) + var/obj/item/bodypart/chest/my_chest = get_bodypart(BODY_ZONE_CHEST) + my_chest?.worn_back_offset?.apply_offset(back_overlay) // BILLIONS MUST ..() + if(!back_overlay) + return + if(!mutant_override &&(OFFSET_BACK in dna.species.offset_features)) + back_overlay.pixel_x += dna.species.offset_features[OFFSET_BACK][1] + back_overlay.pixel_y += dna.species.offset_features[OFFSET_BACK][2] + overlays_standing[BACK_LAYER] = back_overlay + apply_overlay(BACK_LAYER) + + +/mob/living/carbon/human/update_worn_head(update_obscured = TRUE) + . = ..() + if(src.dna.species.uses_offsets == FALSE) + return + remove_overlay(HEAD_LAYER) + if(client && hud_used && hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_BACK) + 1]) + var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_HEAD) + 1] + inv.update_icon() + + if(head) + var/obj/item/worn_item = head + update_hud_head(worn_item) + + if(check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_HEAD) + return + + var/icon_file = 'icons/mob/clothing/head/default.dmi' // billions must ignore checks + + var/mutable_appearance/head_overlay = head.build_worn_icon(default_layer = HEAD_LAYER, default_icon_file = icon_file) + var/obj/item/bodypart/head/my_head = get_bodypart(BODY_ZONE_HEAD) + my_head?.worn_head_offset?.apply_offset(head_overlay) + if((OFFSET_HEAD in dna.species.offset_features)) + head_overlay.pixel_x += dna.species.offset_features[OFFSET_HEAD][1] + head_overlay.pixel_y += dna.species.offset_features[OFFSET_HEAD][2] + overlays_standing[HEAD_LAYER] = head_overlay + + update_mutant_bodyparts() + apply_overlay(HEAD_LAYER) // you should overwrite, NOW + + +/mob/living/carbon/human/update_worn_belt(update_obscured = TRUE) + . = ..() //This technically doubles processing needed for nabbers but honestly I do not know how to do this any better. + if(src.dna.species.uses_offsets == FALSE) //make sure there's no chance of a runtime on species this shouldn't be running on. + return + remove_overlay(BELT_LAYER) + + if(client && hud_used) + var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_BELT) + 1] + inv.update_icon() + + if(belt) + var/obj/item/worn_item = belt + update_hud_belt(worn_item) + + if(check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_BELT) + return + + var/icon_file = 'icons/mob/clothing/belt.dmi' + + var/mutant_override = FALSE + if(dna.species.bodytype & BODYTYPE_CUSTOM) + var/species_icon_file = dna.species.generate_custom_worn_icon(LOADOUT_ITEM_BELT, belt) + if(species_icon_file) + icon_file = species_icon_file + mutant_override = TRUE + + var/mutable_appearance/belt_overlay = belt.build_worn_icon(default_layer = BELT_LAYER, default_icon_file = icon_file, override_file = mutant_override ? icon_file : null) + var/obj/item/bodypart/chest/my_chest = get_bodypart(BODY_ZONE_CHEST) + my_chest?.worn_belt_offset?.apply_offset(belt_overlay) + if(!mutant_override &&(OFFSET_BELT in dna.species.offset_features)) + belt_overlay.pixel_x += dna.species.offset_features[OFFSET_BELT][1] + belt_overlay.pixel_y += dna.species.offset_features[OFFSET_BELT][2] + overlays_standing[BELT_LAYER] = belt_overlay + + apply_overlay(BELT_LAYER) + +/mob/living/carbon/human/update_worn_mask() + . = ..() //This technically doubles processing needed for nabbers but honestly I do not know how to do this any better. + if(src.dna.species.uses_offsets == FALSE) //make sure there's no chance of a runtime on species this shouldn't be running on. + return + remove_overlay(FACEMASK_LAYER) + + if(!get_bodypart(BODY_ZONE_HEAD)) //Decapitated + return + + if(client && hud_used && hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_MASK) + 1]) + var/atom/movable/screen/inventory/inv = hud_used.inv_slots[TOBITSHIFT(ITEM_SLOT_MASK) + 1] + inv.update_icon() + + if(wear_mask) + var/obj/item/worn_item = wear_mask + update_hud_wear_mask(worn_item) + + if(check_obscured_slots(transparent_protection = TRUE) & ITEM_SLOT_MASK) + return + + var/icon_file = 'icons/mob/clothing/mask.dmi' + + var/mutable_appearance/mask_overlay = wear_mask.build_worn_icon(default_layer = FACEMASK_LAYER, default_icon_file = icon_file) + var/obj/item/bodypart/head/my_head = get_bodypart(BODY_ZONE_HEAD) + my_head?.worn_mask_offset?.apply_offset(mask_overlay) + if((OFFSET_FACEMASK in dna.species.offset_features)) + mask_overlay.pixel_x += dna.species.offset_features[OFFSET_FACEMASK][1] + mask_overlay.pixel_y += dna.species.offset_features[OFFSET_FACEMASK][2] + overlays_standing[FACEMASK_LAYER] = mask_overlay + + apply_overlay(FACEMASK_LAYER) + update_mutant_bodyparts() //e.g. upgate needed because mask now hides lizard snout + + +/* +/mob/living/carbon/human/update_worn_id(update_obscured = TRUE) + . = ..() + if(src.dna.species.uses_offsets == FALSE) + return + var/mutable_appearance/id_overlay = overlays_standing[ID_LAYER] + var/obj/item/bodypart/chest/my_chest = get_bodypart(BODY_ZONE_CHEST) + my_chest?.worn_id_offset?.apply_offset(id_overlay) + +/mob/living/carbon/human/update_worn_glasses(update_obscured = TRUE) + . = ..() + if(src.dna.species.uses_offsets == FALSE) + return + var/mutable_appearance/glasses_overlay = glasses.build_worn_icon(default_layer = GLASSES_LAYER) + var/obj/item/bodypart/head/my_head = get_bodypart(BODY_ZONE_HEAD) + my_head.worn_glasses_offset?.apply_offset(glasses_overlay) + +/mob/living/carbon/human/update_inv_ears(update_obscured = TRUE) + . = ..() + if(src.dna.species.uses_offsets == FALSE) + return + var/mutable_appearance/ears_overlay = ears.build_worn_icon(default_layer = EARS_LAYER) + var/obj/item/bodypart/head/my_head = get_bodypart(BODY_ZONE_HEAD) + my_head.worn_ears_offset?.apply_offset(ears_overlay) + +/mob/living/carbon/human/update_worn_neck(update_obscured = TRUE) + . = ..() + if(src.dna.species.uses_offsets == FALSE) + return + var/mutable_appearance/neck_overlay = wear_neck.build_worn_icon(default_layer = NECK_LAYER) + var/obj/item/bodypart/chest/my_chest = get_bodypart(BODY_ZONE_CHEST) + my_chest?.worn_belt_offset?.apply_offset(neck_overlay) + +*/ diff --git a/monkestation/code/modules/_assorted_species_upgrades/code/assorted_fixes.dm b/monkestation/code/modules/_assorted_species_upgrades/code/assorted_fixes.dm new file mode 100644 index 000000000000..d18d891fab85 --- /dev/null +++ b/monkestation/code/modules/_assorted_species_upgrades/code/assorted_fixes.dm @@ -0,0 +1,11 @@ +// Handles general fixes for all forms of mobs and species \\ +// For modularity purposes, this will load first before all other monkeystation modules \\ + +/mob/living/carbon/human/dummy/extra_tall/Destroy() //Ensure that dummies are correctly removing extra_bodyparts. + QDEL_NULL(extra_bodyparts) + return ..() + +/datum/interaction_mode/combat_mode/Destroy(force, ...) + combat_mode = null + QDEL_NULL(held_hud) // Monkeystation Edit. Ensure this always qdels the hud in question. + return ..() diff --git a/monkestation/code/modules/_assorted_species_upgrades/code/blood_colours.dm b/monkestation/code/modules/_assorted_species_upgrades/code/blood_colours.dm new file mode 100644 index 000000000000..f63e4dd61281 --- /dev/null +++ b/monkestation/code/modules/_assorted_species_upgrades/code/blood_colours.dm @@ -0,0 +1,34 @@ +/obj/effect/decal/cleanable/blood + color = "#b60a0a" //Backup of a backup. Should handle when all blood instances are created and not recoloured. + +/atom/transfer_mob_blood_dna(mob/living/injected_mob, should_colour) + ..() + if(ishuman(injected_mob)) + var/mob/living/carbon/human/mob = injected_mob + var/colour = mob.dna.species.blood_colours + if(!(colour == null) && should_colour == TRUE) //fast fast fast + src.color = colour //Switch the blood-colour last moment! + else + src.color = "#b60a0a" //default blood color. Careful on editing this, as it has to apply to all species without blood_colours. Differs from backup for runtime/debug testing + +/turf/proc/add_blood_DNA_special(list/blood_dna, list/datum/disease/diseases, var/colour) //Whenever we have a VERY SPECIFIC need + var/obj/effect/decal/cleanable/blood/splatter/blood_splatter = locate() in src + if(!blood_splatter) + blood_splatter = new /obj/effect/decal/cleanable/blood/splatter(src, diseases) + if(colour != null) + blood_splatter.color = colour + else + blood_splatter.color = "#b60a0a" + if(!QDELETED(blood_splatter)) + blood_splatter.add_blood_DNA(blood_dna) //give blood info to the blood decal. + if(colour != null) + blood_splatter.color = colour + else + blood_splatter.color = "#b60a0a" + return TRUE //we bloodied the floor + return FALSE + +/obj/effect/decal/cleanable/blood/dry() + ..() + if(src.color == null) //uncoloured + src.color = "#ac0e0e" //Fallback to ensure mapped blood will ALWAYS be red, without potentially causing problems for species-based blood diff --git a/monkestation/code/modules/_assorted_species_upgrades/code/bodyparts.dm b/monkestation/code/modules/_assorted_species_upgrades/code/bodyparts.dm new file mode 100644 index 000000000000..39dd8a7cbefb --- /dev/null +++ b/monkestation/code/modules/_assorted_species_upgrades/code/bodyparts.dm @@ -0,0 +1,55 @@ +//May the lord forgive me. +//For I sure as shit won't. +//This handles management of specific offsets, and ensures we can change things around for weird and wacky species things. Like Lizards getting tailbags instead of backpacks (frills hurt when compressed!!!) +//Generally this is very useful to not have to resprite the same item over and over, as you can now instead off-set it on a species/bodypart by bodypart basis. +//A majority of these will be unused until said species are added, and may never be used, but are still good to define for adminbus. + +/obj/item/bodypart/chest + /// Offset to apply to equipment worn as a uniform + var/datum/worn_feature_offset/worn_uniform_offset + /// Offset to apply to equipment worn on the id slot + var/datum/worn_feature_offset/worn_id_offset + /// Offset to apply to equipment worn in the suit slot + var/datum/worn_feature_offset/worn_suit_storage_offset + /// Offset to apply to equipment worn on the hips + var/datum/worn_feature_offset/worn_belt_offset + /// Offset to apply to overlays placed on the back + var/datum/worn_feature_offset/worn_back_offset + /// Offset to apply to equipment worn as a suit + var/datum/worn_feature_offset/worn_suit_offset + /// Offset to apply to equipment worn on the neck + var/datum/worn_feature_offset/worn_neck_offset + /// The offset datum for our accessory overlay. + var/datum/worn_feature_offset/worn_accessory_offset + +/obj/item/bodypart/chest/Destroy() // CURSE OF QDEL UPON YOU + QDEL_NULL(worn_uniform_offset) + QDEL_NULL(worn_id_offset) + QDEL_NULL(worn_suit_storage_offset) + QDEL_NULL(worn_belt_offset) + QDEL_NULL(worn_back_offset) + QDEL_NULL(worn_suit_offset) + QDEL_NULL(worn_neck_offset) + QDEL_NULL(worn_accessory_offset) + return ..() //Just incase + +/obj/item/bodypart/head + /// Offset to apply to equipment worn on the ears + var/datum/worn_feature_offset/worn_ears_offset + /// Offset to apply to equipment worn on the eyes + var/datum/worn_feature_offset/worn_glasses_offset + /// Offset to apply to equipment worn on the mouth + var/datum/worn_feature_offset/worn_mask_offset + /// Offset to apply to equipment worn on the head + var/datum/worn_feature_offset/worn_head_offset + /// Offset to apply to overlays placed on the face + var/datum/worn_feature_offset/worn_face_offset + +/obj/item/bodypart/head/Destroy() // CURSE OF QDEL + QDEL_NULL(worn_ears_offset) + QDEL_NULL(worn_glasses_offset) + QDEL_NULL(worn_mask_offset) + QDEL_NULL(worn_head_offset) + QDEL_NULL(worn_face_offset) + return ..() // Just incase + diff --git a/monkestation/code/modules/_assorted_species_upgrades/code/feature_offset.dm b/monkestation/code/modules/_assorted_species_upgrades/code/feature_offset.dm new file mode 100644 index 000000000000..1720d398fa31 --- /dev/null +++ b/monkestation/code/modules/_assorted_species_upgrades/code/feature_offset.dm @@ -0,0 +1,81 @@ +/// A datum for controlling how to position items on an unusually offset body part +/// For instance if you have an asymmetrical head, hats might need to be offset to one side +/datum/worn_feature_offset + /// Owner of mob we are attached to, could be null on a severed limb + var/mob/living/carbon/owner + /// What are we attached to + var/obj/item/bodypart/attached_part + /// Key used to identify what this offset applies to + var/feature_key + /// Offsets to apply on the x axis for each direction + var/list/offset_x + /// Offsets to apply on the y axis for each direction + var/list/offset_y + +/datum/worn_feature_offset/New( + obj/item/bodypart/attached_part, + feature_key, + list/offset_x = list("south" = 0), + list/offset_y = list("south" = 0), +) + attached_part.feature_offsets[feature_key] = src + owner = attached_part.owner + src.attached_part = attached_part + src.feature_key = feature_key + src.offset_x = offset_x + src.offset_y = offset_y + + if (length(offset_x) <= 1 && length(offset_y) <= 1) + return // We don't need to do any extra signal handling + + if (!isnull(owner)) + changed_owner(owner) + RegisterSignal(attached_part, COMSIG_BODYPART_CHANGED_OWNER, PROC_REF(changed_owner)) + +/// Returns the current offset which should be used for this feature +/datum/worn_feature_offset/proc/get_offset() + var/current_dir = owner ? owner.dir : SOUTH + current_dir = dir2text(current_dir) + var/x = length(offset_x) ? ((current_dir in offset_x) ? offset_x[current_dir] : offset_x["south"]) : 0 + var/y = length(offset_y) ? ((current_dir in offset_y) ? offset_y[current_dir] : offset_y["south"]) : 0 + return list("x" = x, "y" = y) + +/// Applies the current offset to a provided overlay image +/datum/worn_feature_offset/proc/apply_offset(image/overlay) + var/list/offset = get_offset() + overlay.pixel_x += offset["x"] + overlay.pixel_y += offset["y"] + +/// When the owner of the bodypart changes, update our signal registrations +/datum/worn_feature_offset/proc/changed_owner(obj/item/bodypart/part, mob/living/new_owner, mob/living/old_owner) + SIGNAL_HANDLER + owner = new_owner + if (!isnull(old_owner)) + UnregisterSignal(old_owner, COMSIG_ATOM_DIR_CHANGE) + if (!isnull(new_owner)) + RegisterSignal(new_owner, COMSIG_ATOM_DIR_CHANGE, PROC_REF(on_dir_change)) + RegisterSignal(new_owner, COMSIG_QDELETING, PROC_REF(on_owner_deleted)) + +/// If the owner is deleted, stop updating +/datum/worn_feature_offset/proc/on_owner_deleted(mob/living/host) + SIGNAL_HANDLER + owner = null + attached_part = null + feature_key = null + offset_x = null + offset_y = null + +/datum/worn_feature_offset/Destroy(force, ...) //absolutely ensure that on destroy it clears these variables + . = ..() + SIGNAL_HANDLER + owner = null + attached_part = null + feature_key = null + offset_x = null + offset_y = null + + +/// When we change direction, re-apply the offset +/datum/worn_feature_offset/proc/on_dir_change(mob/living/carbon/owner, olddir, newdir) + SIGNAL_HANDLER + owner.update_features(feature_key) diff --git a/monkestation/code/modules/_assorted_species_upgrades/code/items.dm b/monkestation/code/modules/_assorted_species_upgrades/code/items.dm new file mode 100644 index 000000000000..9166eb0a24e5 --- /dev/null +++ b/monkestation/code/modules/_assorted_species_upgrades/code/items.dm @@ -0,0 +1,4 @@ +//TODO: Add a ton of stuff here to manage new items for species.\\ +//For now, will do nothing. +/obj/item/clothing/suit/costume/poncho + species_exception = list(/datum/species/golem, /datum/species/nabber) //ensure nabbers can wear ponchos. diff --git a/monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/belt.json b/monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/belt.json new file mode 100644 index 000000000000..a417197c74ee --- /dev/null +++ b/monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/belt.json @@ -0,0 +1,10 @@ +{ + "": [ + { + "type": "icon_state", + "icon_state": "belt", + "blend_mode": "overlay", + "color_ids": [ 1 ] + } + ] +} diff --git a/monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/glasses.json b/monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/glasses.json new file mode 100644 index 000000000000..32b589115cc8 --- /dev/null +++ b/monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/glasses.json @@ -0,0 +1,10 @@ +{ + "": [ + { + "type": "icon_state", + "icon_state": "glasses", + "blend_mode": "overlay", + "color_ids": [ 1 ] + } + ] +} diff --git a/monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/gloves.json b/monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/gloves.json new file mode 100644 index 000000000000..b122076b2c83 --- /dev/null +++ b/monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/gloves.json @@ -0,0 +1,10 @@ +{ + "": [ + { + "type": "icon_state", + "icon_state": "gloves", + "blend_mode": "overlay", + "color_ids": [ 1 ] + } + ] +} diff --git a/monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/mask.json b/monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/mask.json new file mode 100644 index 000000000000..e8c2254aea1b --- /dev/null +++ b/monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/mask.json @@ -0,0 +1,10 @@ +{ + "": [ + { + "type": "icon_state", + "icon_state": "mask", + "blend_mode": "overlay", + "color_ids": [ 1 ] + } + ] +} diff --git a/monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/neck.json b/monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/neck.json new file mode 100644 index 000000000000..d52da8a1265e --- /dev/null +++ b/monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/neck.json @@ -0,0 +1,10 @@ +{ + "": [ + { + "type": "icon_state", + "icon_state": "poncho", + "blend_mode": "overlay", + "color_ids": [ 1 ] + } + ] +} diff --git a/monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/uniform.json b/monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/uniform.json new file mode 100644 index 000000000000..1d4ac28564a3 --- /dev/null +++ b/monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/uniform.json @@ -0,0 +1,10 @@ +{ + "": [ + { + "type": "icon_state", + "icon_state": "uniform", + "blend_mode": "overlay", + "color_ids": [ 1 ] + } + ] +} diff --git a/monkestation/code/modules/nabbers/code/GAGS/nabber_gags.dm b/monkestation/code/modules/nabbers/code/GAGS/nabber_gags.dm new file mode 100644 index 000000000000..a51cb6b15383 --- /dev/null +++ b/monkestation/code/modules/nabbers/code/GAGS/nabber_gags.dm @@ -0,0 +1,100 @@ +#define BASE_CLOTH_X_1 1 +#define BASE_CLOTH_Y_1 1 + +/obj/item + var/datum/greyscale_config/greyscale_config_worn_nabber_fallback + var/icon/worn_icon_nabber + +/datum/species/nabber/get_custom_worn_icon(item_slot, obj/item/item) + return item.worn_icon_nabber + +/datum/species/nabber/set_custom_worn_icon(item_slot, obj/item/item, icon/icon) + item.worn_icon_nabber = icon + +/datum/species/nabber/get_custom_worn_config_fallback(item_slot, obj/item/item) + return item.greyscale_config_worn_nabber_fallback + +/datum/species/nabber/generate_custom_worn_icon(item_slot, obj/item/item, mob/living/carbon/human/human_owner) + . = ..() + if(.) + return + + . = generate_custom_worn_icon_fallback(item_slot, item, human_owner) + if(.) + return + +/obj/item/clothing/under + species_clothing_color_coords = list(list(BASE_CLOTH_X_1, BASE_CLOTH_Y_1)) + greyscale_config_worn_nabber_fallback = /datum/greyscale_config/nabber + +/obj/item/clothing/neck + species_clothing_color_coords = list(list(BASE_CLOTH_X_1, BASE_CLOTH_Y_1)) + greyscale_config_worn_nabber_fallback = /datum/greyscale_config/nabber/scarf + +/obj/item/clothing/neck/cloak + species_clothing_color_coords = list(list(BASE_CLOTH_X_1, BASE_CLOTH_Y_1)) + greyscale_config_worn_nabber_fallback = /datum/greyscale_config/nabber/cloak + +/obj/item/clothing/neck/tie + species_clothing_color_coords = list(list(BASE_CLOTH_X_1, BASE_CLOTH_Y_1)) + greyscale_config_worn_nabber_fallback = /datum/greyscale_config/nabber/tie + +/obj/item/clothing/gloves + species_clothing_color_coords = list(list(BASE_CLOTH_X_1, BASE_CLOTH_Y_1)) + greyscale_config_worn_nabber_fallback = /datum/greyscale_config/nabber/gloves + +/obj/item/clothing/belt + species_clothing_color_coords = list(list(BASE_CLOTH_X_1, BASE_CLOTH_Y_1)) + greyscale_config_worn_nabber_fallback = /datum/greyscale_config/nabber/belt + +/obj/item/clothing/mask // I can only forsee this going well + species_clothing_color_coords = list(list(BASE_CLOTH_X_1, BASE_CLOTH_Y_1)) + greyscale_config_worn_nabber_fallback = /datum/greyscale_config/nabber/mask + +/obj/item/clothing/mask/gas //because we have to subtype... every single time. + species_clothing_color_coords = list(list(BASE_CLOTH_X_1, BASE_CLOTH_Y_1)) + greyscale_config_worn_nabber_fallback = /datum/greyscale_config/nabber/mask + +/obj/item/clothing/glasses + greyscale_config_worn_nabber_fallback = /datum/greyscale_config/nabber/glasses + worn_icon_nabber = 'monkestation/code/modules/nabbers/icons/mob/clothing/glasses.dmi' + +/** + * Nabber fallbacks. + * In case what we have another species with specials Json config file. We use this for our case. + * Check teshari fasllbacks .json config files for more datails. + */ + +/datum/greyscale_config/nabber + name = "Nabber clothing" + icon_file = 'monkestation/code/modules/nabbers/icons/nabber_fallbacks.dmi' + json_config = 'monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/uniform.json' + +/datum/greyscale_config/nabber/cloak + name = "Nabber Poncho" + json_config = 'monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/neck.json' + +/datum/greyscale_config/nabber/tie + name = "Nabber Tie" + json_config = 'monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/neck.json' + +/datum/greyscale_config/nabber/scarf + name = "Nabber Scarf" + json_config = 'monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/neck.json' + +/datum/greyscale_config/nabber/gloves + name = "Nabber Gloves" + json_config = 'monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/gloves.json' + +/datum/greyscale_config/nabber/belt + name = "Nabber Belt" + json_config = 'monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/belt.json' + +/datum/greyscale_config/nabber/mask //yippie + name = "Nabber Mask" + json_config = 'monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/mask.json' + +/datum/greyscale_config/nabber/glasses //yippie + name = "Nabber Glasses" + icon_file = 'monkestation/code/modules/nabbers/icons/mob/clothing/glasses.dmi' + json_config = 'monkestation/code/modules/nabbers/code/GAGS/greyscale/json_configs/nabber_fallbacks/glasses.json' diff --git a/monkestation/code/modules/nabbers/code/_nabbers.dm b/monkestation/code/modules/nabbers/code/_nabbers.dm new file mode 100644 index 000000000000..decd3533b1d9 --- /dev/null +++ b/monkestation/code/modules/nabbers/code/_nabbers.dm @@ -0,0 +1,209 @@ +#define NABBER_DAMAGE_ONBURNING 5 //Yeah it needed a nerf. +#ifdef TRAIT_HARD_SOLES //Checks to see if this trait exists. +/datum/species/nabber //If Hard_soles is detected, apply it to their inherent_traits. Cross-Testmerge compatability! + inherent_traits = list( + TRAIT_ADVANCEDTOOLUSER, + TRAIT_PUSHIMMUNE, //You aint pushing it, chief. + TRAIT_LIGHT_STEP, //Can't wear shoes + TRAIT_RESISTLOWPRESSURE, + TRAIT_HARD_SOLES, + TRAIT_RADIMMUNE //Flavor + ) +#else +/datum/species/nabber //If hard soles does not exist (Satyrs not merged/Testmerged) + inherent_traits = list( + TRAIT_ADVANCEDTOOLUSER, + TRAIT_PUSHIMMUNE, //You aint pushing it, chief. + TRAIT_LIGHT_STEP, //Can't wear shoes + TRAIT_RESISTLOWPRESSURE, + TRAIT_RADIMMUNE //Flavor + ) +#endif +//Handles species + +//Nabbers armor datum. Change this to change their resistances. Is now affected by armor piercing/etc +//By default, this is a way easier method of balancing a species rather than directly affecting burn/brute_mod, as this takes into account AP. +//Currently Nabbers also recieve a 5% brute damage reduction atop of this, and a 1.8x burn modifier, atop of their pre-existing heat modifiers. +//Whenever you adjust these variables, make sure to adjust their damage reduction, heat modifiers, and burn vulnerability to prevent scaling issues. +//All values are currently temporary and will require further balancing as eye protection, and nabber nukie modsuits are added. + +/datum/armor/nabbers + melee = 45 //Massively reduce incoming melee damage + bullet = 25 //Reduce incoming bullet damage, too + wound = 25 //Bare wound chance reduction + acid = 15 // Acid reduction + bomb = 10 //Forgot to add this earlier. Should stop them from instantly getting eviscerated from things like exploding vines/etc + +/datum/species/nabber + name = "Giant Armored Serpentid" + id = SPECIES_NABBER + eyes_icon = 'monkestation/code/modules/nabbers/icons/organs/nabber_eyes_new.dmi' + held_accessory = null + held_accessory_path = 'monkestation/code/modules/nabbers/icons/bodyparts/bodypart_overlays.dmi' + species_traits = list( + MUTCOLORS, + EYECOLOR, + NO_UNDERWEAR, + NOZOMBIE, //Breaks things majorly if they get zombified + NO_DNA_COPY //Cannot be cloned, body too big. + ) + digitigrade_customization = DIGITIGRADE_NEVER + blood_colours = "#30498f" //Haemolyph is typically a deep blue. + no_equip_flags = ITEM_SLOT_FEET | ITEM_SLOT_OCLOTHING | ITEM_SLOT_SUITSTORE + inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID + uses_offsets = TRUE + mutanttongue = /obj/item/organ/internal/tongue/nabber + hair_alpha = 0 + coldmod = 0.3 //Very very resistant to cold + heatmod = 2.5 // IT BURNS + changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_MAGIC | MIRROR_PRIDE | ERT_SPAWN | RACE_SWAP | SLIME_EXTRACT + bodytemp_heat_damage_limit = (BODYTEMP_HEAT_DAMAGE_LIMIT - 5) //-10 was a bit too high, as it already does damage to their lungs + bodytype = BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + mutantbrain = /obj/item/organ/internal/brain/nabber + mutanteyes = /obj/item/organ/internal/eyes/robotic/nabber + mutantlungs = /obj/item/organ/internal/lungs/nabber + mutantheart = /obj/item/organ/internal/heart/nabber + mutantliver = /obj/item/organ/internal/liver/nabber + mutantears = /obj/item/organ/internal/ears/nabber + mutantappendix = null + bodypart_overrides = list( + BODY_ZONE_HEAD = /obj/item/bodypart/head/mutant/nabber, + BODY_ZONE_CHEST = /obj/item/bodypart/chest/mutant/nabber, + BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/mutant/nabber, + BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/mutant/nabber, + BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/mutant/nabber, + BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/mutant/nabber, + ) + custom_worn_icons = list( + LOADOUT_ITEM_HEAD = NABBER_HEAD_ICON, + LOADOUT_ITEM_MASK = NABBER_MASK_ICON, + LOADOUT_ITEM_UNIFORM = NABBER_UNIFORM_ICON, + LOADOUT_ITEM_HANDS = NABBER_HANDS_ICON, + LOADOUT_ITEM_BELT = NABBER_BELT_ICON, + LOADOUT_ITEM_MISC = NABBER_BACK_ICON, + LOADOUT_ITEM_EARS = NABBER_EARS_ICON + ) + var/datum/action/cooldown/toggle_arms/arms + var/datum/action/cooldown/optical_camouflage/camouflage + //var/datum/action/cooldown/nabber_threat/threat_mod -Disabled pending balance and re-spriting. + +/datum/species/nabber/on_species_gain(mob/living/carbon/human/C, datum/species/old_species, pref_load) + . = ..() + arms = new(C) + arms.Grant(C) + camouflage = new(C) + camouflage.Grant(C) + + C.set_armor(C.get_armor().add_other_armor(/datum/armor/nabbers)) //Assign the armor + +/datum/species/nabber/get_species_description() + return "Large, bulky - impressively armoured and chitinous, these ambush predators are a recent acquisition by NanoTrasen. Loyal workers, not the brightest bulb in the pack - and physically impressive, they're perfect for all forms of menial, unimportant labor. Known to be extremely flammable." + +/mob/living/carbon/human/proc/destroy_anime() //HATE. LET ME TELL YOU HOW MUCH I HAVE COME TO HATE. + var/obj/item/organ/external/anime_head/removing1 = src.get_organ_slot(ORGAN_SLOT_EXTERNAL_ANIME_HEAD) + var/obj/item/organ/external/anime_middle/removing2 = src.get_organ_slot(ORGAN_SLOT_EXTERNAL_ANIME_CHEST) + var/obj/item/organ/external/anime_bottom/removing3 = src.get_organ_slot(ORGAN_SLOT_EXTERNAL_ANIME_BOTTOM) + if(removing1) //Fugly-ass code but it works for ensuring we don't get sprite/code issues. + qdel(removing1) + if(removing2) + qdel(removing2) + if(removing3) + qdel(removing3) + + +/datum/species/nabber/after_equip_job(datum/job/J, mob/living/carbon/human/C, visualsOnly = FALSE, client/preference_source = null) //Handle things such as post_spawn timers here. In this case, prepare to evaporate anime. + ..() + addtimer(CALLBACK(C, TYPE_PROC_REF(/mob/living/carbon/human, destroy_anime), TRUE), 2.5 SECONDS) //Enough time to ensure that we don't get any runtimes. + +/datum/species/nabber/on_species_loss(mob/living/carbon/human/C, datum/species/new_species, pref_load) + . = ..() + qdel(arms) + qdel(camouflage) + C.set_armor(C.get_armor().subtract_other_armor(/datum/armor/nabbers)) //Make sure to remove it, to stop people abusing lings/etc to gain infinite melee armor + //threat_mod.Destroy() + +/datum/species/nabber/spec_life(mob/living/carbon/human/H, seconds_per_tick, times_fired) + . = ..() + if(H.stat == DEAD) //Should never allow for them to keep burning forever + return + //Handles bonus burn damage + if(H.on_fire) //Make sure this isn't being applied if they're fire immune. + H.apply_damage(NABBER_DAMAGE_ONBURNING, OXY) + if(H.fire_stacks <= 5 && !H.on_fire) //Never give more than 15 firestacks... Normally. Or if they have enough fire armor. + H.adjust_fire_stacks(10) + +/datum/species/nabber/prepare_human_for_preview(mob/living/carbon/human/nabber) + var/nabber_color = "#00ac1d" + nabber.dna.features["mcolor"] = nabber_color + nabber.dna.features["mcolor2"] = nabber_color + nabber.dna.features["mcolor3"] = nabber_color + regenerate_organs(nabber, src, visual_only = TRUE) + nabber.update_body(TRUE) + +/datum/species/nabber/create_pref_unique_perks() + var/list/perk_descriptions = list() + + perk_descriptions += list(list( + SPECIES_PERK_TYPE = SPECIES_NEGATIVE_PERK, + SPECIES_PERK_ICON = "dna", + SPECIES_PERK_NAME = "Inhuman Proportions", + SPECIES_PERK_DESC = "Giant Armoured Serpentids are, unfortunately, too different to wear a majority of traditional armor, MODsuits and goggles!." + )) + + perk_descriptions += list(list( + SPECIES_PERK_TYPE = SPECIES_POSITIVE_PERK, + SPECIES_PERK_ICON = "dna", + SPECIES_PERK_NAME = "Robust Chitin", + SPECIES_PERK_DESC = "Giant Armoured Serpentids have a robust external chitin layer that protects them from a majority of brute damage sources." + )) + + perk_descriptions += list(list( + SPECIES_PERK_TYPE = SPECIES_NEGATIVE_PERK, + SPECIES_PERK_ICON = "star-of-life", + SPECIES_PERK_NAME = "Chitin-Breather", + SPECIES_PERK_DESC = "Due to the fact Giant Armoured Serpentids (Nabbers) rely on spiracles beneath their chitin to breathe, when set on fire - they are unable to intake oxygen!" + )) + + perk_descriptions += list(list( + SPECIES_PERK_TYPE = SPECIES_NEGATIVE_PERK, + SPECIES_PERK_ICON = "star-of-life", + SPECIES_PERK_NAME = "Flammable Chitin", + SPECIES_PERK_DESC = "Due to the photoreflectivity and nature of their chitin, Giant Armoured Serpentids are known to be EXTREMELY burn weak, taking almost double damage from all sources, and combusting on exposure to open flame or hot enough atmospherics." + )) + + perk_descriptions += list(list( + SPECIES_PERK_TYPE = SPECIES_POSITIVE_PERK, + SPECIES_PERK_ICON = "user-plus", + SPECIES_PERK_NAME = "Nictating Membrane", + SPECIES_PERK_DESC = "Giant Armoured Serpentids have a secondary membrane in their eyes that allows them to shield their sensitive vision from bright lights." + )) + + perk_descriptions += list(list( + SPECIES_PERK_TYPE = SPECIES_POSITIVE_PERK, + SPECIES_PERK_ICON = "user-plus", + SPECIES_PERK_NAME = "Mantid Bladearms", + SPECIES_PERK_DESC = "Giant Armoured Serpentids have two sets of arms - with the upper Bladearms requiring a majority of their haemolyph to remain active and mobile. These are dangerous weapons, and are treated by Security as such!" + )) + + perk_descriptions += list(list( + SPECIES_PERK_TYPE = SPECIES_POSITIVE_PERK, + SPECIES_PERK_ICON = "user-plus", + SPECIES_PERK_NAME = "Natural Electrochromic Chitin", + SPECIES_PERK_DESC = "Giant Armoured Serpentids have naturally-electrochromic chitin. Easily disrupted by grounding to any object they touch, they can remain mostly invisible, so long as they are not disturbed nor interact with their surroundings." + )) + + return perk_descriptions + +/datum/species/nabber/random_name(gender, unique, lastname) + if(unique) + return random_unique_name(gender) + + var/random_name + random_name += (pick("Alpha","Delta","Dzetta","Phi","Epsilon","Gamma","Tau","Omega") + " [rand(1, 199)]") //Stolen from elsewhere. + return random_name + +/datum/species/nabber/randomize_features(mob/living/carbon/human_mob) //NEVER randomise features. This causes runtimes. + return FALSE + +/mob/living/carbon/human/species/nabber + race = /datum/species/nabber diff --git a/monkestation/code/modules/nabbers/code/abilites/camouflage.dm b/monkestation/code/modules/nabbers/code/abilites/camouflage.dm new file mode 100644 index 000000000000..7a7ca712e479 --- /dev/null +++ b/monkestation/code/modules/nabbers/code/abilites/camouflage.dm @@ -0,0 +1,68 @@ +#define ICON_STATE_CAMOUFLAGE_ON "camuflage_off" +#define ICON_STATE_CAMOUFLAGE_OFF "camuflage_on" + +/datum/action/cooldown/optical_camouflage + name = "Toggle camouflage" + desc = "Blend it with your surroundings and become transparent." + cooldown_time = 10 SECONDS + + button_icon = 'monkestation/code/modules/nabbers/icons/actions.dmi' + var/active = FALSE + var/camouflage_alpha = 60 //ORIGINALLY: 35 + +/datum/action/cooldown/optical_camouflage/Activate(atom/target) + . = ..() + if(!owner) + return FALSE + + if(isdead(owner) || owner.incapacitated()) + owner.balloon_alert(owner, "Incapacitated!") + return FALSE + + if(active) + remove_camouflage() + return TRUE + +/* - Disabled until the effect is re-enabled - * + if(owner.has_status_effect(/datum/status_effect/nabber_combat)) + owner.balloon_alert(owner, "Can't now!") + return FALSE +*/ + + RegisterSignals(owner, list(COMSIG_MOB_ITEM_ATTACK, COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_HITBY, COMSIG_ATOM_HULK_ATTACK, COMSIG_ATOM_ATTACK_PAW, COMSIG_CARBON_CUFF_ATTEMPTED, COMSIG_ATOM_BULLET_ACT, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, COMSIG_LIVING_MOB_BUMP, COMSIG_HUMAN_BURNING), PROC_REF(remove_camouflage)) + enter_camouflage() + return TRUE + +/datum/action/cooldown/optical_camouflage/Grant(mob/granted_to) + . = ..() + button_icon_state = ICON_STATE_CAMOUFLAGE_OFF + +/datum/action/cooldown/optical_camouflage/Destroy() + . = ..() + if(!owner) + return + remove_camouflage() + +/datum/action/cooldown/optical_camouflage/proc/enter_camouflage() + owner.visible_message(span_notice("[owner] starts hypnotically shifting colours, before eventually blending in with their surroundings"), span_notice("You blend in with your surroundings."), span_hear("You hear a low hiss as [owner] begins to shimmer.")) + + animate(owner, alpha = camouflage_alpha, time = cooldown_time) + + button_icon_state = ICON_STATE_CAMOUFLAGE_ON + owner.update_action_buttons() + + active = TRUE + +/datum/action/cooldown/optical_camouflage/proc/remove_camouflage() + owner.visible_message(span_notice("[owner] stops blending in with their surroundings."), span_notice("You become visible again."), span_hear("You hear a low hiss as [owner] shimmers into visibility.")) + animate(owner, alpha = 255, time = 1.5 SECONDS) + + UnregisterSignal(owner, list(COMSIG_HUMAN_EARLY_UNARMED_ATTACK, COMSIG_MOB_ITEM_ATTACK, COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_ATTACK_HAND, COMSIG_ATOM_BULLET_ACT, COMSIG_ATOM_HITBY, COMSIG_ATOM_HULK_ATTACK, COMSIG_ATOM_ATTACK_PAW, COMSIG_CARBON_CUFF_ATTEMPTED, COMSIG_LIVING_MOB_BUMP, COMSIG_HUMAN_BURNING)) + + button_icon_state = ICON_STATE_CAMOUFLAGE_OFF + owner.update_action_buttons() + + active = FALSE + +#undef ICON_STATE_CAMOUFLAGE_ON +#undef ICON_STATE_CAMOUFLAGE_OFF diff --git a/monkestation/code/modules/nabbers/code/abilites/nabber_combat_effect.dm b/monkestation/code/modules/nabbers/code/abilites/nabber_combat_effect.dm new file mode 100644 index 000000000000..7c81ab7c4093 --- /dev/null +++ b/monkestation/code/modules/nabbers/code/abilites/nabber_combat_effect.dm @@ -0,0 +1,70 @@ +/* Nabber Threat Display. Disabled until balancing pass & fixes. + +#define NABBER_THREAT_ICON 'monkestation/code/modules/nabbers/icons/effects.dmi' +#define NABBER_THREAT_ICON_STATE "nabber_threat" + +/datum/status_effect/nabber_combat + id = "Nabber combat" + alert_type = null + status_type = STATUS_EFFECT_UNIQUE + tick_interval = -1 + var/image/nabber_image + +/datum/status_effect/nabber_combat/on_apply() + var/mob/living/carbon/human/color_source = owner + + nabber_image = image(NABBER_THREAT_ICON, owner, NABBER_THREAT_ICON_STATE, dir = owner.dir) + nabber_image.override = TRUE + nabber_image.alpha = 0 + nabber_image.color = color_source.dna.features["mcolor"] + animate(nabber_image, alpha = 255, 0.2 SECONDS) + owner.add_movespeed_modifier(/datum/movespeed_modifier/nabber_combat) + owner.add_alt_appearance(/datum/atom_hud/alternate_appearance/basic/everyone, id, nabber_image) + + if(owner.body_position == LYING_DOWN) + nabber_image.transform = turn(nabber_image.transform, 90) + + RegisterSignal(owner, COMSIG_ATOM_DIR_CHANGE, PROC_REF(on_dir_change)) + RegisterSignal(owner, COMSIG_LIVING_SET_BODY_POSITION, PROC_REF(on_body_position_change)) + return TRUE + +/datum/status_effect/nabber_combat/on_remove() + owner.remove_alt_appearance(id) + owner.remove_movespeed_modifier(/datum/movespeed_modifier/nabber_combat) + QDEL_NULL(nabber_image) + + UnregisterSignal(owner, list( + COMSIG_ATOM_DIR_CHANGE, + COMSIG_LIVING_SET_BODY_POSITION + )) + +/datum/status_effect/nabber_combat/proc/on_dir_change(datum/source, old_dir, new_dir) + SIGNAL_HANDLER + + nabber_image.dir = new_dir + +/datum/status_effect/nabber_combat/proc/on_body_position_change(datum/source, new_value, old_value) + SIGNAL_HANDLER + + if(new_value == LYING_DOWN) + nabber_image.transform = turn(nabber_image.transform, 90) + else + nabber_image.transform = turn(nabber_image.transform, -90) + +/datum/status_effect/nabber_combat/Destroy() //absolutely ensure we're harddelling here + . = ..() + QDEL_NULL(nabber_image) + + UnregisterSignal(owner, list( + COMSIG_ATOM_DIR_CHANGE, + COMSIG_LIVING_SET_BODY_POSITION + )) + + +/datum/movespeed_modifier/nabber_combat + blacklisted_movetypes = FLYING + multiplicative_slowdown = -0.25 + +#undef NABBER_THREAT_ICON +#undef NABBER_THREAT_ICON_STATE +*/ diff --git a/monkestation/code/modules/nabbers/code/abilites/nabber_threat.dm b/monkestation/code/modules/nabbers/code/abilites/nabber_threat.dm new file mode 100644 index 000000000000..45a13c511898 --- /dev/null +++ b/monkestation/code/modules/nabbers/code/abilites/nabber_threat.dm @@ -0,0 +1,91 @@ +/* Disabled until balance pass +/datum/action/cooldown/nabber_threat + name = "Toggle threat" + desc = "Strengthen your chitin by coloring it with a battle color. Gaining extra speed!" + cooldown_time = 10 SECONDS + + button_icon = 'monkestation/code/modules/nabbers/icons/actions.dmi' + var/active = FALSE + +/datum/action/cooldown/nabber_threat/New(Target, original) + . = ..() + button_icon_state = "nabber_threat_off" + +/datum/action/cooldown/nabber_threat/Destroy() + . = ..() + if(active) + remove_effect() + +/datum/action/cooldown/nabber_threat/Activate(atom/target) + . = ..() + var/mob/living/carbon/human/nabber = owner + + if(!nabber) + return FALSE + + if(isdead(nabber) || nabber.incapacitated()) + nabber.balloon_alert(nabber, "Incapacitated!") + return FALSE + + if(nabber.on_fire) + nabber.balloon_alert(nabber, "On fire!") + return FALSE + + if(nabber.alpha < 255) + nabber.balloon_alert(nabber, "Can't now!") + return FALSE + + if(active) + remove_effect() + return TRUE + + RegisterSignal(owner, COMSIG_HUMAN_BURNING, PROC_REF(on_fire)) + RegisterSignal(owner, COMSIG_LIVING_STATUS_INCAPACITATE, PROC_REF(on_incapacitated)) + RegisterSignal(owner, COMSIG_LIVING_DEATH, PROC_REF(on_death)) + + apply_effect() + return TRUE + +/datum/action/cooldown/nabber_threat/proc/apply_effect() + var/mob/living/carbon/human/nabber = owner + + nabber.visible_message(span_warning("[nabber] makes its chitin shimmer colorfully. Emitting threat."), span_notice("You made your chitin, hostile shimmer!"), span_hear("You hear a low hiss.")) + nabber.balloon_alert(nabber, "Threat on!") + nabber.apply_status_effect(/datum/status_effect/nabber_combat) + button_icon_state = "nabber_threat_on" + nabber.update_action_buttons() + active = TRUE + return TRUE + +/datum/action/cooldown/nabber_threat/proc/remove_effect(force = FALSE) + var/mob/living/carbon/human/nabber = owner + + nabber.visible_message(span_notice("[nabber] becoming normal. Shimmering chitin, back to normal."), span_notice("You've got your chitin back to normal."), span_hear("You hear a low hiss.")) + if(force == TRUE) + nabber.Stun(2 SECONDS) + + nabber.balloon_alert(nabber, "Threat off!") + nabber.remove_status_effect(/datum/status_effect/nabber_combat) + button_icon_state = "nabber_threat_off" + nabber.update_action_buttons() + active = FALSE + UnregisterSignal(owner, list(COMSIG_HUMAN_BURNING, COMSIG_LIVING_STATUS_INCAPACITATE, COMSIG_LIVING_DEATH)) + return TRUE + +/datum/action/cooldown/nabber_threat/proc/on_fire() + SIGNAL_HANDLER + + owner.balloon_alert(owner, "On fire!") + return remove_effect(force = TRUE) + +/datum/action/cooldown/nabber_threat/proc/on_incapacitated() + SIGNAL_HANDLER + + owner.balloon_alert(owner, "Incapacitated!") + return remove_effect(force = TRUE) + +/datum/action/cooldown/nabber_threat/proc/on_death() + SIGNAL_HANDLER + + return remove_effect(force = TRUE) +*/ diff --git a/monkestation/code/modules/nabbers/code/abilites/nabber_welding_eyes.dm b/monkestation/code/modules/nabbers/code/abilites/nabber_welding_eyes.dm new file mode 100644 index 000000000000..b536098e568a --- /dev/null +++ b/monkestation/code/modules/nabbers/code/abilites/nabber_welding_eyes.dm @@ -0,0 +1,22 @@ +/datum/action/cooldown/toggle_welding + name = "Toggle welding shield" + desc = "Toggle your eyes welding shield" + + var/obj/item/organ/internal/eyes/robotic/nabber/eyes + cooldown_time = 2 SECONDS + +/datum/action/cooldown/toggle_welding/Activate() + . = ..() + var/owner = eyes.owner + var/mob/living/carbon/human/nabber = owner + if(!do_after(nabber, 2 SECONDS, nabber)) //Makes it so its difficult to abuse these in combat to avoid flashes + StartCooldown() + nabber.balloon_alert(nabber, "Stand still!") + return FALSE + eyes.toggle_shielding() + StartCooldown() + +/datum/action/cooldown/toggle_welding/Destroy() + . = ..() + eyes = null + cooldown_time = null diff --git a/monkestation/code/modules/nabbers/code/abilites/toggle_arms.dm b/monkestation/code/modules/nabbers/code/abilites/toggle_arms.dm new file mode 100644 index 000000000000..d7feb6ec8338 --- /dev/null +++ b/monkestation/code/modules/nabbers/code/abilites/toggle_arms.dm @@ -0,0 +1,161 @@ +/datum/action/cooldown/toggle_arms + name = "Toggle mantis arms" + desc = "Pump your Haemolyph from the rest of your body into your hunting arms, allowing you to stab at foes. This will take time to do, and can be interrupted." + cooldown_time = 3 SECONDS + + button_icon = 'monkestation/code/modules/nabbers/icons/actions.dmi' + var/blade_type = NABBER_ARM_TYPE_REGULAR //Need to hold this here. + var/held_desc // Manages any custom blade messages on examine + +/datum/action/cooldown/toggle_arms/Destroy() + blade_type = null + held_desc = null + return ..() + +/datum/action/cooldown/toggle_arms/New(Target, original) + . = ..() + button_icon_state = "arms_off" + +/datum/action/cooldown/toggle_arms/Activate(atom/target) + var/mob/living/carbon/human/nabber = owner + if(!nabber) + return FALSE + + if(isdead(nabber) || nabber.incapacitated()) + nabber.balloon_alert(nabber, "Incapacitated!") + return FALSE + + if(nabber.num_hands < 2) + nabber.balloon_alert(nabber, "Need both hands!") + return FALSE + + var/obj/item/held = nabber.get_active_held_item() + var/obj/item/inactive = nabber.get_inactive_held_item() + + if(((held || inactive) && !nabber.drop_all_held_items()) && !(istype((inactive || held), /obj/item/melee/nabber_blade))) + nabber.balloon_alert(nabber, "Hands occupied!") + return FALSE + + else if(istype((inactive || held), /obj/item/melee/nabber_blade)) + StartCooldown() + down_arms() + return TRUE + + rise_arms() + StartCooldown() + return TRUE + +/datum/action/cooldown/toggle_arms/proc/rise_arms() + var/mob/living/carbon/human/nabber = owner + nabber.balloon_alert(nabber, "Begin pumping blood in!") + nabber.visible_message(span_danger("[nabber] starts to pump blood into their hunting arms!"), span_warning("You let out a aggressive screech, raising your blade-arms!"), span_hear("You hear a sharp screech of an agitated creature!")) + playsound(nabber, 'monkestation/code/modules/nabbers/sounds/nabberscream.ogg', 70) + + if(!do_after(nabber, 1.5 SECONDS, nabber)) + StartCooldown() + nabber.balloon_alert(nabber, "Stand still!") + return FALSE + RegisterSignal(nabber, COMSIG_ATOM_PRE_BULLET_ACT, PROC_REF(hit_by_projectile), override = TRUE) + nabber.balloon_alert(nabber, "Arms raised!") + nabber.visible_message(span_warning("[nabber] raised their mantid-like hunting arms in a frenzy, ready for a fight!"), span_warning("You raise your mantis arms, ready for combat."), span_hear("You hear a terrible hunting screech!")) + playsound(nabber, 'monkestation/code/modules/nabbers/sounds/nabberscream.ogg', 70) + + var/c = nabber.dna.features["mcolor"] + var/active_path = text2path("/obj/item/melee/nabber_blade[blade_type]") + var/inactive_path = text2path("/obj/item/melee/nabber_blade[blade_type]/alt") + var/obj/item/melee/nabber_blade/active_hand = new active_path + var/obj/item/melee/nabber_blade/inactive_hand = new inactive_path + + active_hand.color = c + inactive_hand.color = c + + nabber.put_in_active_hand(active_hand) + nabber.put_in_inactive_hand(inactive_hand) + if(blade_type) //Rather than just having these be items that can cause huge problems, ensure we delete them and just recreate with the force neccessary. + RegisterSignal(nabber, COMSIG_ATOM_EXAMINE, PROC_REF(examined)) + if(active_hand.icon_type_on) + nabber.modify_accessory_overlay(active_hand.icon_type_on) + RegisterSignal(owner, COMSIG_CARBON_REMOVE_LIMB, PROC_REF(on_lose_hand)) + button_icon_state = "arms_on" + nabber.update_action_buttons() + +/datum/action/cooldown/toggle_arms/proc/down_arms(force = FALSE) + var/mob/living/carbon/human/nabber = owner + nabber.visible_message(span_notice("[nabber] starts to relax, pumping blood away from their hunting-arms!"), span_notice("You start pumping blood out your mantis arms. Stay still!"), span_hear("You hear [src] let out a quiet hissing sigh.")) + + if(force) + nabber.Stun(5 SECONDS) + for(var/obj/item/held in nabber.held_items) + var/obj/item/melee/nabber_blade/held_temp = held + if(held_temp.icon_type_off) + nabber.modify_accessory_overlay(held_temp.icon_type_off) + qdel(held) + button_icon_state = "arms_on" + nabber.update_action_buttons() + UnregisterSignal(nabber, list(COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_PRE_BULLET_ACT)) + return FALSE + + nabber.balloon_alert(nabber, "Removing blood from hunting-arms!") + + if(!do_after(nabber, 0.5 SECONDS, nabber)) + nabber.balloon_alert(nabber, "Stand still!") + return FALSE + + UnregisterSignal(nabber, list(COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_PRE_BULLET_ACT)) + playsound(nabber, 'monkestation/code/modules/nabbers/sounds/nabberscream.ogg', 70) + if(blade_type) + UnregisterSignal(nabber, COMSIG_ATOM_EXAMINE, PROC_REF(examined)) + for(var/obj/item/held in nabber.held_items) + var/obj/item/melee/nabber_blade/held_temp = held + if(held_temp.icon_type_off) + nabber.modify_accessory_overlay(held_temp.icon_type_off) + qdel(held) + + UnregisterSignal(owner, COMSIG_CARBON_REMOVE_LIMB) + nabber.balloon_alert(nabber, "Arms down!") + button_icon_state = "arms_off" + nabber.update_action_buttons() + +/datum/action/cooldown/toggle_arms/proc/on_lose_hand() + SIGNAL_HANDLER + var/mob/living/carbon/human/nabber = owner + UnregisterSignal(nabber, list(COMSIG_ATOM_ATTACKBY, COMSIG_ATOM_PRE_BULLET_ACT)) + if(!(nabber.num_hands < 2)) + return FALSE + + nabber.visible_message(span_notice("[nabber] has their arm violently removed, spurting high-pressure haemolyph, the other going limp!"), span_notice("HOLY SHIT MY ARM!"), span_hear("You hear [nabber] let out a sharp hiss as they lose a limb!")) + playsound(nabber, 'monkestation/code/modules/nabbers/sounds/nabberscream.ogg', 70) + nabber.balloon_alert(nabber, "Lost hands!") + nabber.Stun(5 SECONDS) + if(blade_type) + UnregisterSignal(nabber, COMSIG_ATOM_EXAMINE, PROC_REF(examined)) + for(var/obj/item/held in nabber.held_items) + var/obj/item/melee/nabber_blade/held_temp = held + if(held_temp.icon_type_off) + nabber.modify_accessory_overlay(held_temp.icon_type_off) + qdel(held) + + button_icon_state = "arms_off" + nabber.update_action_buttons() + +/datum/action/cooldown/toggle_arms/proc/examined(mob/living/carbon/examined, mob/user, list/examine_list) + SIGNAL_HANDLER + if(held_desc) + var/examine_text = span_bolditalic("[examined] [held_desc]") + examine_list += examine_text + +/datum/action/cooldown/toggle_arms/proc/hit_by_projectile(mob/living/nabber, obj/projectile/hitting_projectile, def_zone) //stolen from sleeping carp my beloved + SIGNAL_HANDLER + if(blade_type == (NABBER_ARM_TYPE_SYNDICATE || NABBER_ARM_TYPE_NUCLEAR)) + if(hitting_projectile.reflectable == REFLECT_NORMAL) //Should only work on very few projectiles. + nabber.visible_message( + span_bolddanger("[nabber] deflects [hitting_projectile] aside with a shower of sparks! [nabber.p_They()] can deflect energy projectiles with [nabber.p_their()] glowing armblades!"), + span_userdanger("You deflect [hitting_projectile]!"), + ) + playsound(nabber, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), vol = 75, vary = TRUE) + hitting_projectile.firer = nabber + hitting_projectile.set_angle(rand(0, 360))//SHING + return COMPONENT_BULLET_PIERCED + return NONE + + diff --git a/monkestation/code/modules/nabbers/code/items.dm b/monkestation/code/modules/nabbers/code/items.dm new file mode 100644 index 000000000000..28d7db1a9d87 --- /dev/null +++ b/monkestation/code/modules/nabbers/code/items.dm @@ -0,0 +1,171 @@ +//HANDLES ALL NABBER-UNIQUE ITEMS, INCLUDING TRAITOR ITEMS\\ +//Defines. Handles what type of arm to give. Always use blank or /type to prevent issues with regular arms. +#define NABBER_ARM_TYPE_REGULAR "" +#define NABBER_ARM_TYPE_SHARPENED "/sharp" +#define NABBER_ARM_TYPE_SYNDICATE "/syndicate" +#define NABBER_ARM_TYPE_NUCLEAR 3 //Unimplemented for now. +#define NABBER_ARM_TYPE_PACIFIED 4 //Unimplemented for now. + +//Moves all nabber items to its own folder. Note: Do not add to toggle_arms unless you want this to be an unreadable mess. + +/obj/item/melee/nabber_blade + name = "Hunting arm" + desc = "A sharpened, grotesque limb of chitin and hydraulic muscles, designed to pierce into a target and bleed them out like a stuck pig." + icon = 'monkestation/code/modules/nabbers/icons/items.dmi' + icon_state = "mantis_arm_r" + item_flags = ABSTRACT | DROPDEL + w_class = WEIGHT_CLASS_HUGE + force = 14 //Temporary nerf. Original value; 17. Should no longer be able to damage reinforced windows. + armour_penetration = 7 //Hydraulic muscle-driven arms. + throwforce = 0 //Buggy. + throw_range = 0 + throw_speed = 0 + hitsound = 'sound/weapons/bladeslice.ogg' + attack_verb_continuous = list("attacks", "slashes", "stabs", "slices", "tears", "lacerates", "rips", "dices", "cuts") + attack_verb_simple = list("attack", "slash", "stab", "slice", "tear", "lacerate", "rip", "dice", "cut") + sharpness = SHARP_EDGED + wound_bonus = 5 // 1/3rd of cleaver + bare_wound_bonus = 10 // Way less due to the fact that on a random greytider this would give them almost 30 wound_threshold bonus pre-damage calc. + var/icon_type_on //will manage if a blade should have custom icons. + var/icon_type_off + +/obj/item/melee/nabber_blade/Initialize(mapload,silent,synthetic) + . = ..() //Always run last. Chain last together repeatedly to modify butcher statistics. + ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT) //They're designed for this + AddComponent(/datum/component/butchering, \ + speed = 3 SECONDS, \ + effectiveness = 85, \ + ) + +/obj/item/melee/nabber_blade/Destroy() + icon_type_on = null + icon_type_off = null + return ..() + +/obj/item/melee/nabber_blade/alt + icon_state = "mantis_arm_l" + +/obj/item/melee/nabber_blade/sharp + force = 18 //+4 damage to simulate whetstone usage. + wound_bonus = 15 // Same as cleaver + bare_wound_bonus = 10 // Less than the default, due to higher flat wound_bonus + name = "lethally sharpened hunting-arm" + +/obj/item/melee/nabber_blade/sharp/alt + icon_state = "mantis_arm_l" //todo: replace sprites + +/obj/item/melee/nabber_blade/sharp/Initialize(mapload,silent,synthetic) + . = ..() + ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT) //They're designed for this + var/datum/component/butchering/held_component = src.GetComponent(/datum/component/butchering) + held_component.effectiveness = 95 + held_component.speed = 1.5 SECONDS + +/obj/item/melee/nabber_blade/syndicate + name = "energy-enhanced bladearm" + force = 29 //Only 5 less than a DEsword, but way more utility for nabbers. + armour_penetration = 45 //Almost half AP however + wound_bonus = 15 //Same as cleaver + bare_wound_bonus = 20 //Insane, but this is a 18tc item. On-par with double-bladed esword/esword + hitsound = 'sound/weapons/blade1.ogg' + hit_reaction_chance = 45 //45% chance to block leaps/melee/unarmed. + armor_type = /datum/armor/item_shield + icon_type_on = "blades_on" + icon_type_off = "blades_off" + light_system = OVERLAY_LIGHT + light_outer_range = 5 + light_power = 0.65 //Bright, but not awfully so. + light_on = TRUE + light_color = LIGHT_COLOR_INTENSE_RED //Cant forget this + +/obj/item/melee/nabber_blade/syndicate/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK) + if(attack_type == UNARMED_ATTACK || attack_type == MELEE_ATTACK || attack_type == LEAP_ATTACK) + if(prob(hit_reaction_chance)) + owner.visible_message(span_danger("[owner] reflexively blocks [attack_text] with [src]!")) + return TRUE + return FALSE + +/* Adds balance concerns & a lack of coolness I don't like. +/obj/item/melee/nabber_blade/syndicate/IsReflect() // IF EVERYTHING, ABSOLUTELY EVERYTHING FAILS, ABSOLUTELY MAKE SURE YOU REFLECT AND DO NOT BLOCK. + return TRUE +*/ + +/obj/item/melee/nabber_blade/syndicate/Initialize(mapload,silent,synthetic) + . = ..() + ADD_TRAIT(src, TRAIT_NODROP, ABSTRACT_ITEM_TRAIT) //They're designed for this + var/datum/component/butchering/held_component = src.GetComponent(/datum/component/butchering) + held_component.effectiveness = 65 + held_component.speed = 4 SECONDS //Faster, but they're worse at it. + +/obj/item/melee/nabber_blade/syndicate/alt + icon_state = "mantis_arm_l" //todo: custom sprites. + +/obj/item/melee/nabber_blade/pre_attack(atom/Whetstone, mob/living/user, params) //Handles whetstoning your limbs. TODO: Maybe add nabber-specific traitor item for this? + if (istype(Whetstone, /obj/item/sharpener)) + var/obj/item/sharpener/poorstone = Whetstone + for(var/datum/action/cooldown/toggle_arms/arms in user.actions) + if(arms.blade_type != NABBER_ARM_TYPE_REGULAR) + user.visible_message(span_notice("[user] tries to sharpen their blade-arms... But fails, like a doofus."), + span_notice("You can't sharpen these!")) + return FALSE + if(poorstone.uses >= 1) + user.visible_message(span_notice("[user] begins to sharpen their massive blade-arms."), + span_notice("You begin to sharpen your natural weaponry.")) + if(do_after(user, 7 SECONDS, target = src)) + user.visible_message(span_notice("[user] sharpens the large, sharp underside of their bladearms..."), + span_notice("You sharpen the large underside of your bladearm, ready to kill...")) + playsound(src, 'sound/items/unsheath.ogg', 100, TRUE) + poorstone.uses-- //Make sure you cant sharpen both for a single whetstone! + poorstone.name = "thoroughly ruined whetstone" + poorstone.desc = "A whetstone, ruined seemingly by sharpening both sides of a massive, bladed limb - ground utterly smooth." //Give a forensic hint as to what ruined it. + for(var/datum/action/cooldown/toggle_arms/arms in user.actions) //Should only ever be one instance. Make sure to handle it, though + arms.blade_type = NABBER_ARM_TYPE_SHARPENED + arms.held_desc = span_notice("has sharpened their blade-arms with what appears to be crude whetstoning, the honed edge gleaming with a dangerous tint...") + return + else + user.visible_message(span_notice("[user] attempts to sharpen their arms, only to find the whetstone too smooth to do so!"), + span_notice("You fail to even grind the burr away from your chitinous limbs. Use a better stone.")) + + + if (istype(Whetstone, /obj/item/nabber_energyblades)) //Ideally turn this into a component in the future. + user.visible_message(span_notice("[user] begins to carefully run their blade-arms through the suspicious case, an ominous red glow present..."), + span_notice("You lower your arms into the case, utilising the inbuilt autosurgeon to attach several energy-projectors to the undersides.")) + if(do_after(user, 7 SECONDS, target = src)) + user.visible_message(span_notice("[user] raises their blade-arms, a new black-and-red set of projectors providing an ominous nimbus..."), + span_notice("With your new energy-blades, you're more than ready to kill.")) + playsound(src, 'sound/weapons/saberon.ogg', 100, TRUE) + qdel(Whetstone) //Destroy the evidence! + for(var/datum/action/cooldown/toggle_arms/arms in user.actions) //Should only ever be one instance. Make sure to handle it, though + arms.blade_type = NABBER_ARM_TYPE_SYNDICATE + arms.held_desc = span_bolddanger("has clearly been modified - several large energy projectors attached to their blade-arms, glowing with the classic red nimbus of syndicate technology...") + return + return ..() + +/obj/item/melee/nabber_blade/afterattack(atom/target, mob/user, proximity) + . = ..() + if(!proximity) + return + else if(istype(target, /obj/structure/chair)) + var/obj/structure/chair/C = target + C.deconstruct() + else if(istype(target, /obj/machinery/computer)) + var/obj/machinery/computer/C = target + C.attack_alien(user) + + //TRAITOR ITEMS\\ + +/datum/uplink_item/device_tools/nabber_energyblades + name = "Energy Projector Attachment Case (EPAC)" + desc = "Techy, flashy. The ultimate upgrade for a premier predator - this case of energy-projectors allows Nabbers to turn themselves from scary, to downright terrifying. \ + Once attached to their blade-arms, these project a sharp energy-field on-par with a double-bladed energy sword, capable of blocking a majority of incoming fire; while rendering them far more lethal than normal." + item = /obj/item/nabber_energyblades + cost = 18 // These give people 28 damage, 45 AP weapons with huge total block and basically no way to remove them past getting their arms cut off. + restricted_species = list(SPECIES_NABBER) //Whoops. + +/obj/item/nabber_energyblades + name = "sinister case" + desc = "A sinster black-and-red box, advertised as containing a large supply of nabber-related energy emitters. Printed on the side is instructions on how to attach them to ones bladearms: Open case, slot bladearms inside, wait until process complete." + w_class = WEIGHT_CLASS_TINY + icon = 'icons/obj/device.dmi' + icon_state = "contacts" //stealing these for now. + diff --git a/monkestation/code/modules/nabbers/code/nabber_bodyparts.dm b/monkestation/code/modules/nabbers/code/nabber_bodyparts.dm new file mode 100644 index 000000000000..4a8e6820aa7f --- /dev/null +++ b/monkestation/code/modules/nabbers/code/nabber_bodyparts.dm @@ -0,0 +1,109 @@ +#define NABBER_PUNCH_LOW 3 // Base punch damage. +#define NABBER_PUNCH_HIGH 5 +#define BODYPART_ICON_NABBER 'monkestation/code/modules/nabbers/icons/bodyparts/nabber_parts_greyscale.dmi' +#define NABBER_BRUTE_MODIFIER 0.90 //10% total incoming brute damage reduction atop of armor. Reduces toolboxes from 12 damage to ~10 (9.8) but does not significantly affect AP using weapons +#define NABBER_BURN_MODIFIER 1.3 // 0.65x incoming brute, 1.3x burn. 1.8x was way too high and allowed you to be crit in 3 hits from a regular welder. + +//Nabbers limbs. +/obj/item/bodypart/head/mutant/nabber + icon_greyscale = BODYPART_ICON_NABBER + limb_id = SPECIES_NABBER + brute_modifier = NABBER_BRUTE_MODIFIER + burn_modifier = NABBER_BURN_MODIFIER + bodytype = BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + +/obj/item/bodypart/head/mutant/nabber/Initialize(mapload) + worn_ears_offset = new( + attached_part = src, + feature_key = OFFSET_EARS, + offset_y = list("north" = 9, "south" = 9, "east" = 9, "west" = 9), + ) + worn_head_offset = new( + attached_part = src, + feature_key = OFFSET_HEAD, + offset_y = list("north" = 8, "south" = 9, "east" = 8, "west" = 8), + offset_x = list("north" = 8, "south" = -0.15, "east" = 8, "west" = 8), + ) + worn_mask_offset = new( + attached_part = src, + feature_key = OFFSET_FACEMASK, + offset_y = list("north" = 7, "south" = 7, "east" = 7, "west" = 7), + ) + return ..() + +/obj/item/bodypart/head/mutant/nabber/Destroy() + . = ..() + QDEL_NULL(worn_ears_offset) //ABSOLUTELY ensure we are qdelling here, if not, rely on backups. + QDEL_NULL(worn_head_offset) + QDEL_NULL(worn_mask_offset) + +/obj/item/bodypart/chest/mutant/nabber + icon_greyscale = BODYPART_ICON_NABBER + biological_state = BIO_STANDARD_UNJOINTED + limb_id = SPECIES_NABBER + brute_modifier = NABBER_BRUTE_MODIFIER + burn_modifier = NABBER_BURN_MODIFIER + bodytype = BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + acceptable_bodytype = BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + +/obj/item/bodypart/chest/mutant/nabber/Initialize(mapload) + worn_back_offset = new( + attached_part = src, + feature_key = OFFSET_BACK, + offset_y = list("north" = 5, "south" = 5, "east" = 5, "west" = 5), + ) + worn_accessory_offset = new( + attached_part = src, + feature_key = OFFSET_ACCESSORY, + offset_y = list("north" = 10, "south" = 10, "east" = 10, "west" = 10), + ) + return ..() + +/obj/item/bodypart/chest/mutant/nabber/Destroy() + . = ..() + QDEL_NULL(worn_back_offset) // ditto + QDEL_NULL(worn_accessory_offset) + +/obj/item/bodypart/arm/left/mutant/nabber + icon_greyscale = BODYPART_ICON_NABBER + limb_id = SPECIES_NABBER + unarmed_damage_low = NABBER_PUNCH_LOW + unarmed_damage_high = NABBER_PUNCH_HIGH + brute_modifier = NABBER_BRUTE_MODIFIER + burn_modifier = NABBER_BURN_MODIFIER + bodytype = BODYTYPE_ORGANIC | BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + biological_state = BIO_STANDARD_UNJOINTED + bodypart_traits = list(TRAIT_CHUNKYFINGERS) + +/obj/item/bodypart/arm/right/mutant/nabber + icon_greyscale = BODYPART_ICON_NABBER + limb_id = SPECIES_NABBER + unarmed_damage_low = NABBER_PUNCH_LOW + unarmed_damage_high = NABBER_PUNCH_HIGH + brute_modifier = NABBER_BRUTE_MODIFIER + burn_modifier = NABBER_BURN_MODIFIER + bodytype = BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + biological_state = BIO_STANDARD_UNJOINTED + bodypart_traits = list(TRAIT_CHUNKYFINGERS) + +/obj/item/bodypart/leg/left/mutant/nabber + icon_greyscale = BODYPART_ICON_NABBER + limb_id = SPECIES_NABBER + brute_modifier = NABBER_BRUTE_MODIFIER + burn_modifier = NABBER_BURN_MODIFIER + biological_state = BIO_STANDARD_UNJOINTED + bodytype = BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + +/obj/item/bodypart/leg/right/mutant/nabber + icon_greyscale = BODYPART_ICON_NABBER + limb_id = SPECIES_NABBER + brute_modifier = NABBER_BRUTE_MODIFIER + burn_modifier = NABBER_BURN_MODIFIER + bodytype = BODYTYPE_ORGANIC | BODYTYPE_CUSTOM + biological_state = BIO_STANDARD_UNJOINTED + +#undef NABBER_PUNCH_LOW +#undef NABBER_PUNCH_HIGH +#undef BODYPART_ICON_NABBER +#undef NABBER_BURN_MODIFIER +#undef NABBER_BRUTE_MODIFIER diff --git a/monkestation/code/modules/nabbers/code/nabber_emotes.dm b/monkestation/code/modules/nabbers/code/nabber_emotes.dm new file mode 100644 index 000000000000..4f794b207682 --- /dev/null +++ b/monkestation/code/modules/nabbers/code/nabber_emotes.dm @@ -0,0 +1,5 @@ +/datum/species/nabber/get_scream_sound(mob/living/carbon/human/human) + return 'monkestation/code/modules/nabbers/sounds/nabberscream.ogg' + +/datum/species/nabber/get_laugh_sound(mob/living/carbon/human/human) + return 'monkestation/code/modules/nabbers/sounds/nabberlaugh.ogg' diff --git a/monkestation/code/modules/nabbers/code/nabber_organs.dm b/monkestation/code/modules/nabbers/code/nabber_organs.dm new file mode 100644 index 000000000000..d9440dbf28c9 --- /dev/null +++ b/monkestation/code/modules/nabbers/code/nabber_organs.dm @@ -0,0 +1,113 @@ +#define NABBER_COLD_THRESHOLD_1 180 +#define NABBER_COLD_THRESHOLD_2 140 +#define NABBER_COLD_THRESHOLD_3 100 + +#define NABBER_HEAT_THRESHOLD_1 300 +#define NABBER_HEAT_THRESHOLD_2 440 +#define NABBER_HEAT_THRESHOLD_3 600 + +#define ORGAN_ICON_NABBER 'monkestation/code/modules/nabbers/icons/organs/nabber_organs.dmi' + +/obj/item/organ/internal/tongue/nabber + name = "nabber tongue" + + //DO NOT ENABLE UNTIL THE SPECIES -> TONGUE TASTE REFACTOR IS IN. + //liked_foodtypes = RAW | GORE | GRAIN + //disliked_foodtypes = CLOTH | FRIED | TOXIC + //toxic_foodtypes = DAIRY + +/obj/item/organ/internal/ears/nabber + name = "nabber ears" + icon = ORGAN_ICON_NABBER + icon_state = "ears" + +/obj/item/organ/internal/heart/nabber + name = "haemolyph pump" + icon = ORGAN_ICON_NABBER + icon_state = "heart" + +/obj/item/organ/internal/brain/nabber + name = "nabber brain" + icon = ORGAN_ICON_NABBER + icon_state = "brain" + +/obj/item/organ/internal/eyes/nabber + name = "nictating eyes" + desc = "Small orange orbs." + icon = ORGAN_ICON_NABBER + icon_state = "eyes" + flash_protect = FLASH_PROTECTION_SENSITIVE + +/obj/item/organ/internal/eyes/robotic/nabber + name = "nictating eyes" + desc = "Small orange orbs. With pair welding shield linses." + icon = ORGAN_ICON_NABBER + icon_state = "eyes" + flash_protect = FLASH_PROTECTION_SENSITIVE + var/datum/action/cooldown/toggle_welding/shield + var/active = FALSE + +/obj/item/organ/internal/eyes/robotic/nabber/on_insert(mob/living/carbon/eye_recipient) + . = ..() + shield = new(eye_recipient) + shield.button_icon = ORGAN_ICON_NABBER + shield.button_icon_state = "eyes" + shield.Grant(eye_recipient) + shield.eyes = src + +/obj/item/organ/internal/eyes/robotic/nabber/proc/toggle_shielding() + if(!owner) + return + + active = !active + playsound(owner, 'sound/machines/click.ogg', 50, TRUE) + + if(active) + flash_protect = FLASH_PROTECTION_WELDER + tint = 2 + owner.update_tint() + owner.balloon_alert(owner, "Welder eyelids shut!") + return + + flash_protect = FLASH_PROTECTION_SENSITIVE + tint = 0 + owner.update_tint() + owner.balloon_alert(owner, "Welder eyelids open!") + +/obj/item/organ/internal/eyes/robotic/nabber/Remove(mob/living/carbon/eye_owner, special) + . = ..() + qdel(shield) + active = FALSE + toggle_shielding() + +/obj/item/organ/internal/lungs/nabber + name = "spiracle lungs" //Insects breathe differently + icon = ORGAN_ICON_NABBER + icon_state = "lungs" + + cold_message = "frigid cold" + cold_level_1_threshold = NABBER_COLD_THRESHOLD_1 + cold_level_2_threshold = NABBER_COLD_THRESHOLD_2 + cold_level_3_threshold = NABBER_COLD_THRESHOLD_3 + cold_level_1_damage = COLD_GAS_DAMAGE_LEVEL_1 //Keep in mind with gas damage levels, you can set these to be negative, if you want someone to heal, instead. + cold_level_2_damage = COLD_GAS_DAMAGE_LEVEL_1 + cold_level_3_damage = COLD_GAS_DAMAGE_LEVEL_2 + cold_damage_type = BRUTE + + + hot_message = "scorching heat" + heat_level_1_threshold = NABBER_HEAT_THRESHOLD_1 + heat_level_2_threshold = NABBER_HEAT_THRESHOLD_2 + heat_level_3_threshold = NABBER_HEAT_THRESHOLD_3 + heat_level_1_damage = HEAT_GAS_DAMAGE_LEVEL_2 + heat_level_2_damage = HEAT_GAS_DAMAGE_LEVEL_3 + heat_level_3_damage = HEAT_GAS_DAMAGE_LEVEL_3 + heat_damage_type = BURN + +/obj/item/organ/internal/liver/nabber + name = "catalytic processor" //Nabbers convert oxygen -> plasma lorewise in their blood + icon_state = "liver" + icon = ORGAN_ICON_NABBER + liver_resistance = 0.8 //Weaker livers + +#undef ORGAN_ICON_NABBER diff --git a/monkestation/code/modules/nabbers/icons/actions.dmi b/monkestation/code/modules/nabbers/icons/actions.dmi new file mode 100644 index 000000000000..86e2754fdeb7 Binary files /dev/null and b/monkestation/code/modules/nabbers/icons/actions.dmi differ diff --git a/monkestation/code/modules/nabbers/icons/bodyparts/bodypart_overlays.dmi b/monkestation/code/modules/nabbers/icons/bodyparts/bodypart_overlays.dmi new file mode 100644 index 000000000000..b1a812c93327 Binary files /dev/null and b/monkestation/code/modules/nabbers/icons/bodyparts/bodypart_overlays.dmi differ diff --git a/monkestation/code/modules/nabbers/icons/bodyparts/nabber_parts_greyscale.dmi b/monkestation/code/modules/nabbers/icons/bodyparts/nabber_parts_greyscale.dmi new file mode 100644 index 000000000000..7913ff4c40c1 Binary files /dev/null and b/monkestation/code/modules/nabbers/icons/bodyparts/nabber_parts_greyscale.dmi differ diff --git a/monkestation/code/modules/nabbers/icons/bodyparts/nabber_parts_greyscale_legacy.dmi b/monkestation/code/modules/nabbers/icons/bodyparts/nabber_parts_greyscale_legacy.dmi new file mode 100644 index 000000000000..873dcfe9191e Binary files /dev/null and b/monkestation/code/modules/nabbers/icons/bodyparts/nabber_parts_greyscale_legacy.dmi differ diff --git a/monkestation/code/modules/nabbers/icons/effects.dmi b/monkestation/code/modules/nabbers/icons/effects.dmi new file mode 100644 index 000000000000..55f1cb4d662e Binary files /dev/null and b/monkestation/code/modules/nabbers/icons/effects.dmi differ diff --git a/monkestation/code/modules/nabbers/icons/items.dmi b/monkestation/code/modules/nabbers/icons/items.dmi new file mode 100644 index 000000000000..4c453a9c0bf6 Binary files /dev/null and b/monkestation/code/modules/nabbers/icons/items.dmi differ diff --git a/monkestation/code/modules/nabbers/icons/mob/clothing/accessories.dmi b/monkestation/code/modules/nabbers/icons/mob/clothing/accessories.dmi new file mode 100644 index 000000000000..d21127651db2 Binary files /dev/null and b/monkestation/code/modules/nabbers/icons/mob/clothing/accessories.dmi differ diff --git a/monkestation/code/modules/nabbers/icons/mob/clothing/back.dmi b/monkestation/code/modules/nabbers/icons/mob/clothing/back.dmi new file mode 100644 index 000000000000..d21127651db2 Binary files /dev/null and b/monkestation/code/modules/nabbers/icons/mob/clothing/back.dmi differ diff --git a/monkestation/code/modules/nabbers/icons/mob/clothing/belt.dmi b/monkestation/code/modules/nabbers/icons/mob/clothing/belt.dmi new file mode 100644 index 000000000000..d53d5cb77b98 Binary files /dev/null and b/monkestation/code/modules/nabbers/icons/mob/clothing/belt.dmi differ diff --git a/monkestation/code/modules/nabbers/icons/mob/clothing/ears.dmi b/monkestation/code/modules/nabbers/icons/mob/clothing/ears.dmi new file mode 100644 index 000000000000..d21127651db2 Binary files /dev/null and b/monkestation/code/modules/nabbers/icons/mob/clothing/ears.dmi differ diff --git a/monkestation/code/modules/nabbers/icons/mob/clothing/eyes.dmi b/monkestation/code/modules/nabbers/icons/mob/clothing/eyes.dmi new file mode 100644 index 000000000000..d21127651db2 Binary files /dev/null and b/monkestation/code/modules/nabbers/icons/mob/clothing/eyes.dmi differ diff --git a/monkestation/code/modules/nabbers/icons/mob/clothing/glasses.dmi b/monkestation/code/modules/nabbers/icons/mob/clothing/glasses.dmi new file mode 100644 index 000000000000..88eb9652497e Binary files /dev/null and b/monkestation/code/modules/nabbers/icons/mob/clothing/glasses.dmi differ diff --git a/monkestation/code/modules/nabbers/icons/mob/clothing/hands.dmi b/monkestation/code/modules/nabbers/icons/mob/clothing/hands.dmi new file mode 100644 index 000000000000..9c8703caeb43 Binary files /dev/null and b/monkestation/code/modules/nabbers/icons/mob/clothing/hands.dmi differ diff --git a/monkestation/code/modules/nabbers/icons/mob/clothing/head.dmi b/monkestation/code/modules/nabbers/icons/mob/clothing/head.dmi new file mode 100644 index 000000000000..d21127651db2 Binary files /dev/null and b/monkestation/code/modules/nabbers/icons/mob/clothing/head.dmi differ diff --git a/monkestation/code/modules/nabbers/icons/mob/clothing/mask.dmi b/monkestation/code/modules/nabbers/icons/mob/clothing/mask.dmi new file mode 100644 index 000000000000..d21127651db2 Binary files /dev/null and b/monkestation/code/modules/nabbers/icons/mob/clothing/mask.dmi differ diff --git a/monkestation/code/modules/nabbers/icons/mob/clothing/neck.dmi b/monkestation/code/modules/nabbers/icons/mob/clothing/neck.dmi new file mode 100644 index 000000000000..d21127651db2 Binary files /dev/null and b/monkestation/code/modules/nabbers/icons/mob/clothing/neck.dmi differ diff --git a/monkestation/code/modules/nabbers/icons/mob/clothing/suit.dmi b/monkestation/code/modules/nabbers/icons/mob/clothing/suit.dmi new file mode 100644 index 000000000000..d21127651db2 Binary files /dev/null and b/monkestation/code/modules/nabbers/icons/mob/clothing/suit.dmi differ diff --git a/monkestation/code/modules/nabbers/icons/mob/clothing/uniform.dmi b/monkestation/code/modules/nabbers/icons/mob/clothing/uniform.dmi new file mode 100644 index 000000000000..468b83ab889c Binary files /dev/null and b/monkestation/code/modules/nabbers/icons/mob/clothing/uniform.dmi differ diff --git a/monkestation/code/modules/nabbers/icons/nabber_fallbacks.dmi b/monkestation/code/modules/nabbers/icons/nabber_fallbacks.dmi new file mode 100644 index 000000000000..25c0b6800633 Binary files /dev/null and b/monkestation/code/modules/nabbers/icons/nabber_fallbacks.dmi differ diff --git a/monkestation/code/modules/nabbers/icons/organs/nabber_eyes_new.dmi b/monkestation/code/modules/nabbers/icons/organs/nabber_eyes_new.dmi new file mode 100644 index 000000000000..4b0894992a38 Binary files /dev/null and b/monkestation/code/modules/nabbers/icons/organs/nabber_eyes_new.dmi differ diff --git a/monkestation/code/modules/nabbers/icons/organs/nabber_organs.dmi b/monkestation/code/modules/nabbers/icons/organs/nabber_organs.dmi new file mode 100644 index 000000000000..e44606f57893 Binary files /dev/null and b/monkestation/code/modules/nabbers/icons/organs/nabber_organs.dmi differ diff --git a/monkestation/code/modules/nabbers/sounds/nabbercough.ogg b/monkestation/code/modules/nabbers/sounds/nabbercough.ogg new file mode 100644 index 000000000000..36779fcf692f Binary files /dev/null and b/monkestation/code/modules/nabbers/sounds/nabbercough.ogg differ diff --git a/monkestation/code/modules/nabbers/sounds/nabberlaugh.ogg b/monkestation/code/modules/nabbers/sounds/nabberlaugh.ogg new file mode 100644 index 000000000000..3f8df21a71b9 Binary files /dev/null and b/monkestation/code/modules/nabbers/sounds/nabberlaugh.ogg differ diff --git a/monkestation/code/modules/nabbers/sounds/nabberscream.ogg b/monkestation/code/modules/nabbers/sounds/nabberscream.ogg new file mode 100644 index 000000000000..335f3f01b32a Binary files /dev/null and b/monkestation/code/modules/nabbers/sounds/nabberscream.ogg differ diff --git a/monkestation/code/modules/nabbers/sounds/nabbersneeze.ogg b/monkestation/code/modules/nabbers/sounds/nabbersneeze.ogg new file mode 100644 index 000000000000..80b91057bab5 Binary files /dev/null and b/monkestation/code/modules/nabbers/sounds/nabbersneeze.ogg differ diff --git a/monkestation/code/modules/stungloves/code/stungloves_normal.dm b/monkestation/code/modules/stungloves/code/stungloves_normal.dm new file mode 100644 index 000000000000..ffe45e14d2b4 --- /dev/null +++ b/monkestation/code/modules/stungloves/code/stungloves_normal.dm @@ -0,0 +1,71 @@ +//Add any and all powergloves/stungloves to this file!\\ + +/obj/item/melee/baton/security/stungloves //Compatible with species with chunky fingers. + name = "PSG-MK3" + desc = "The Mark-Three Powered Stun Gloves. For re-educating the Clown with your fists, now in legally-correct flavors! Wearable - turns your punches into stunbaton hits!." + force = 1 // These are gloves meant to stun targets. They're not meant to be used to beat the clown to death. Hopefully. + icon = 'monkestation/code/modules/stungloves/icons/stunglove_item.dmi' + worn_icon = 'monkestation/code/modules/stungloves/icons/stunglove_item.dmi' + worn_icon_nabber = 'monkestation/code/modules/nabbers/icons/mob/clothing/hands.dmi' + icon_state = "stunglove" + inhand_icon_state = "baton" + worn_icon_state = "stunglove_onmob" + body_parts_covered = HANDS + slot_flags = ITEM_SLOT_GLOVES + chunky_finger_usable = TRUE + + cooldown = 1.5 SECONDS //Reduced down to accomodate the way less stam damage. + stamina_damage = 70 //Lower. + knockdown_time = 2.5 SECONDS //Half + clumsy_knockdown_time = 6 SECONDS //Lower power batong + var/datum/action/cooldown/toggle_stunners/assistant_killer + var/traits_to_give = list(TRAIT_CHUNKYFINGERS_IGNORE_BATON) + +/obj/item/melee/baton/security/stungloves/Destroy() + qdel(assistant_killer) // This should never be neccessary except if admins are manually deleting players. + return ..() + +/obj/item/melee/baton/security/stungloves/equipped(mob/user, slot) + . = ..() + if(slot & ITEM_SLOT_GLOVES) + RegisterSignal(user, COMSIG_HUMAN_EARLY_UNARMED_ATTACK, PROC_REF(punch_to_stun)) + assistant_killer = new(user) + assistant_killer.Grant(user) + user.add_traits(traits_to_give, TRAIT_GENERIC) + +/obj/item/melee/baton/security/stungloves/dropped(mob/user) + . = ..() + if(user.get_item_by_slot(ITEM_SLOT_GLOVES) == src) + UnregisterSignal(user, COMSIG_HUMAN_EARLY_UNARMED_ATTACK) + assistant_killer.Remove(user) + qdel(assistant_killer) //Ensure this evaporates itself. Likely WILL NOT happen if an admin deletes someone wearing them, so handle it on destroy too. + user.remove_traits(traits_to_give, TRAIT_GENERIC) + +/obj/item/melee/baton/security/stungloves/proc/punch_to_stun(mob/living/carbon/human/source, atom/target, proximity, modifiers) + SIGNAL_HANDLER + if(!proximity) + return NONE + if(ishuman(target)) + if((source.istate & ISTATE_HARM) || (source.istate & ISTATE_SECONDARY)) + return src.attack(target, source, BATON_ATTACKING) //Make sure we stun them, or at worst case, just prod them if no cell + if(ismob(target)) + if((source.istate & ISTATE_HARM) || (source.istate & ISTATE_SECONDARY)) + return src.attack(target, source) //Make sure we beat they ass + return NONE + +/obj/item/melee/baton/security/stungloves/preloaded + preload_cell_type = /obj/item/stock_parts/cell/high + +/datum/action/cooldown/toggle_stunners + name = "Toggle Stungloves" + desc = "Toggle your stungloves on or off." + button_icon = 'icons/mob/actions/actions_items.dmi' + check_flags = AB_CHECK_HANDS_BLOCKED|AB_CHECK_IMMOBILE|AB_CHECK_CONSCIOUS + button_icon_state = "nanite_power" //Placeholder + cooldown_time = 0.25 SECONDS //Stops spam. + +/datum/action/cooldown/toggle_stunners/Activate() + . = ..() + var/mob/living/carbon/human/shitsec = owner // we do a little trolling + var/obj/item/melee/baton/security/stungloves/assistantkiller = shitsec.get_item_by_slot(ITEM_SLOT_GLOVES) + assistantkiller.attack_self(shitsec) //handles turning this on and off pretty well diff --git a/monkestation/code/modules/stungloves/code/stungloves_research.dm b/monkestation/code/modules/stungloves/code/stungloves_research.dm new file mode 100644 index 000000000000..b5f65f2ffb54 --- /dev/null +++ b/monkestation/code/modules/stungloves/code/stungloves_research.dm @@ -0,0 +1,24 @@ +/datum/techweb_node/monkeysec + id = "sec_adv" + display_name = "Advanced Security Equipment" + description = "Advanced equipment used by security." + prereq_ids = list("sec_basic") + design_ids = list( + "rubber_c35", //Moves nonmodular sec edits to here. Might aswell. + "stungloves_empty" + ) + research_costs = list(TECHWEB_POINT_TYPE_GENERIC = 3000) + + +/datum/design/stunglove_empty //tacking this onto basic sectech + name = "Mark-Three Stungloves" + desc = "A specialized set of tools. Wraps around an Officer's hand, and projects an energy field while enabled - allowing punches to successfully stun a target." + id = "stungloves_empty" + build_type = PROTOLATHE | AWAY_LATHE + materials = list(/datum/material/iron =HALF_SHEET_MATERIAL_AMOUNT*9, /datum/material/plasma = HALF_SHEET_MATERIAL_AMOUNT*6, /datum/material/titanium =SMALL_MATERIAL_AMOUNT*8) //Low titanium cost. + build_path = /obj/item/melee/baton/security/stungloves + category = list( + RND_CATEGORY_EQUIPMENT + RND_SUBCATEGORY_EQUIPMENT_SECURITY + ) + departmental_flags = DEPARTMENT_BITFLAG_SECURITY + autolathe_exportable = FALSE diff --git a/monkestation/code/modules/stungloves/icons/stunglove_item.dmi b/monkestation/code/modules/stungloves/icons/stunglove_item.dmi new file mode 100644 index 000000000000..4243b28fcd29 Binary files /dev/null and b/monkestation/code/modules/stungloves/icons/stunglove_item.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 5af7a8d6ef11..bc16f6af1568 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -5678,7 +5678,10 @@ #include "interface\fonts\spess_font.dm" #include "interface\fonts\tiny_unicode.dm" #include "interface\fonts\vcr_osd_mono.dm" +#include "monkestation\code\__DEFINES\bodytypes.dm" +#include "monkestation\code\__DEFINES\nabber.dm" #include "monkestation\code\__DEFINES\projectile.dm" +#include "monkestation\code\__DEFINES\research\anomalies.dm" #include "monkestation\code\__HELPERS\_lists.dm" #include "monkestation\code\__HELPERS\anime.dm" #include "monkestation\code\__HELPERS\reagents.dm" @@ -5791,6 +5794,12 @@ #include "monkestation\code\game\objects\items\storage\uplink_kits.dm" #include "monkestation\code\game\turfs\open\water.dm" #include "monkestation\code\game\turfs\open\floor\misc_floor.dm" +#include "monkestation\code\modules\_assorted_species_upgrades\code\_mob.dm" +#include "monkestation\code\modules\_assorted_species_upgrades\code\assorted_fixes.dm" +#include "monkestation\code\modules\_assorted_species_upgrades\code\blood_colours.dm" +#include "monkestation\code\modules\_assorted_species_upgrades\code\bodyparts.dm" +#include "monkestation\code\modules\_assorted_species_upgrades\code\feature_offset.dm" +#include "monkestation\code\modules\_assorted_species_upgrades\code\items.dm" #include "monkestation\code\modules\_paperwork\paper_premade.dm" #include "monkestation\code\modules\admin\antag_tokens.dm" #include "monkestation\code\modules\admin\camera_view.dm" @@ -6657,6 +6666,17 @@ #include "monkestation\code\modules\modular_guns\components\gun_stat_modifiers.dm" #include "monkestation\code\modules\modular_guns\crafting\part_recipes.dm" #include "monkestation\code\modules\modular_guns\makeshift_effects\__base_effect.dm" +#include "monkestation\code\modules\nabbers\code\_nabbers.dm" +#include "monkestation\code\modules\nabbers\code\items.dm" +#include "monkestation\code\modules\nabbers\code\nabber_bodyparts.dm" +#include "monkestation\code\modules\nabbers\code\nabber_emotes.dm" +#include "monkestation\code\modules\nabbers\code\nabber_organs.dm" +#include "monkestation\code\modules\nabbers\code\abilites\camouflage.dm" +#include "monkestation\code\modules\nabbers\code\abilites\nabber_combat_effect.dm" +#include "monkestation\code\modules\nabbers\code\abilites\nabber_threat.dm" +#include "monkestation\code\modules\nabbers\code\abilites\nabber_welding_eyes.dm" +#include "monkestation\code\modules\nabbers\code\abilites\toggle_arms.dm" +#include "monkestation\code\modules\nabbers\code\GAGS\nabber_gags.dm" #include "monkestation\code\modules\ocean_content\department_consoles\engineering.dm" #include "monkestation\code\modules\ocean_content\fluff\barrier.dm" #include "monkestation\code\modules\ocean_content\fluff\base_turf_editor.dm" @@ -7054,6 +7074,8 @@ #include "monkestation\code\modules\storytellers\storytellers\sleeper.dm" #include "monkestation\code\modules\storytellers\storytellers\vote.dm" #include "monkestation\code\modules\storytellers\storytellers\warrior.dm" +#include "monkestation\code\modules\stungloves\code\stungloves_normal.dm" +#include "monkestation\code\modules\stungloves\code\stungloves_research.dm" #include "monkestation\code\modules\surgery\blood_filter.dm" #include "monkestation\code\modules\surgery\bodyparts\arachnid_bodyparts.dm" #include "monkestation\code\modules\surgery\bodyparts\clockwork_bodyparts.dm"