diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index 4756b80f02737..c1e517e8fbbbe 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -60,6 +60,9 @@ #define DNA_MOTH_MARKINGS_BLOCK 13 #define DNA_MUSHROOM_CAPS_BLOCK 14 #define DNA_POD_HAIR_BLOCK 15 +/// DOPPLER SHIFT ADDITION BEGIN +#define DNA_BREASTS_BLOCK 16 +/// DOPPLER SHIFT ADDITION END // Hey! Listen up if you're here because you're adding a species feature! // @@ -68,7 +71,7 @@ // (Which means having a DNA block for a feature tied to a mob without DNA is entirely pointless.) /// Total amount of DNA blocks, must be equal to the highest DNA block number -#define DNA_FEATURE_BLOCKS 15 +#define DNA_FEATURE_BLOCKS 16 /// DOPPLER SHIFT EDIT: 16, up from 15 #define DNA_SEQUENCE_LENGTH 4 #define DNA_MUTATION_BLOCKS 8 diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index dad5afdb96979..a740a2bc887e5 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -681,12 +681,20 @@ GLOBAL_LIST_INIT(human_heights_to_offsets, list( #define MUTATIONS_LAYER 35 /// Mutantrace features (tail when looking south) that must appear behind the body parts #define BODY_BEHIND_LAYER 34 +/// DOPPLER SHIFT ADDITION BEGIN +#define BODY_BEHIND_LAYER_2 33.99 +#define BODY_BEHIND_LAYER_3 33.98 +/// DOPPLER SHIFT ADDITION END /// Layer for bodyparts that should appear behind every other bodypart - Mostly, legs when facing WEST or EAST #define BODYPARTS_LOW_LAYER 33 /// Layer for most bodyparts, appears above BODYPARTS_LOW_LAYER and below BODYPARTS_HIGH_LAYER #define BODYPARTS_LAYER 32 /// Mutantrace features (snout, body markings) that must appear above the body parts #define BODY_ADJ_LAYER 31 +/// DOPPLER SHIFT ADDITION BEGIN +#define BODY_ADJ_LAYER_2 30.99 +#define BODY_ADJ_LAYER_3 30.98 +/// DOPPLER SHIFT ADDITION END /// Underwear, undershirts, socks, eyes, lips(makeup) #define BODY_LAYER 30 /// Mutations that should appear above body, body_adj and bodyparts layer (e.g. laser eyes) @@ -737,6 +745,10 @@ GLOBAL_LIST_INIT(human_heights_to_offsets, list( #define HANDS_LAYER 7 /// Body front layer. Usually used for mutant bodyparts that need to be in front of stuff (e.g. cat ears) #define BODY_FRONT_LAYER 6 +/// DOPPLER SHIFT ADDITION BEGIN +#define BODY_FRONT_LAYER_2 5.99 +#define BODY_FRONT_LAYER_3 5.98 +/// DOPPLER SHIFT ADDITION END /// Special body layer that actually require to be above the hair (e.g. lifted welding goggles) #define ABOVE_BODY_FRONT_GLASSES_LAYER 5 /// Special body layer for the rare cases where something on the head needs to be above everything else (e.g. flowers) @@ -798,10 +810,25 @@ GLOBAL_LIST_INIT(layers_to_offset, list( //Bitflags for the layers a bodypart overlay can draw on (can be drawn on multiple layers) /// Draws overlay on the BODY_FRONT_LAYER #define EXTERNAL_FRONT (1 << 0) -/// Draws overlay on the BODY_ADJ_LAYER +/// DOPPLER SHIFT REMOVAL BEGIN +/*/// Draws overlay on the BODY_ADJ_LAYER #define EXTERNAL_ADJACENT (1 << 1) /// Draws overlay on the BODY_BEHIND_LAYER -#define EXTERNAL_BEHIND (1 << 2) +#define EXTERNAL_BEHIND (1 << 2) */ +/// DOPPLER SHIFT REMOVAL END +/// DOPPLER SHIFT ADDITION BEGIN +//Front extra-color layers. +#define EXTERNAL_FRONT_2 (1 << 1) +#define EXTERNAL_FRONT_3 (1 << 2) +//Updated adjacent & extra-color layers. +#define EXTERNAL_ADJACENT (1 << 3) +#define EXTERNAL_ADJACENT_2 (1 << 4) +#define EXTERNAL_ADJACENT_3 (1 << 5) +//Updated behind & extra-color layers. +#define EXTERNAL_BEHIND (1 << 6) +#define EXTERNAL_BEHIND_2 (1 << 7) +#define EXTERNAL_BEHIND_3 (1 << 8) +/// DOPPLER SHIFT ADDITION END /// Draws organ on all EXTERNAL layers #define ALL_EXTERNAL_OVERLAYS EXTERNAL_FRONT | EXTERNAL_ADJACENT | EXTERNAL_BEHIND diff --git a/code/__DEFINES/~doppler_defines/enterprise_resource_planning.dm b/code/__DEFINES/~doppler_defines/enterprise_resource_planning.dm new file mode 100644 index 0000000000000..9aa689eb3c13b --- /dev/null +++ b/code/__DEFINES/~doppler_defines/enterprise_resource_planning.dm @@ -0,0 +1,2 @@ +// Why we need bespoke organ slots for these isn't entirely within my understanding but I assume there's a good reason +#define ORGAN_SLOT_EXTERNAL_BREASTS "breasts" diff --git a/code/__DEFINES/~doppler_defines/keybindings.dm b/code/__DEFINES/~doppler_defines/keybindings.dm new file mode 100644 index 0000000000000..23bcff0827dc0 --- /dev/null +++ b/code/__DEFINES/~doppler_defines/keybindings.dm @@ -0,0 +1,2 @@ +#define COMSIG_KB_MOB_PIXEL_SHIFT_DOWN "keybinding_mob_pixel_shift_down" +#define COMSIG_KB_MOB_PIXEL_SHIFT_UP "keybinding_mob_pixel_shift_up" diff --git a/code/__DEFINES/~doppler_defines/living.dm b/code/__DEFINES/~doppler_defines/living.dm new file mode 100644 index 0000000000000..c92f403607b5f --- /dev/null +++ b/code/__DEFINES/~doppler_defines/living.dm @@ -0,0 +1,8 @@ +///from base of living/set_pull_offset(): (mob/living/pull_target, grab_state) +#define COMSIG_LIVING_SET_PULL_OFFSET "living_set_pull_offset" +///from base of living/reset_pull_offsets(): (mob/living/pull_target, override) +#define COMSIG_LIVING_RESET_PULL_OFFSETS "living_reset_pull_offsets" +///from base of living/CanAllowThrough(): (atom/movable/mover, border_dir) +#define COMSIG_LIVING_CAN_ALLOW_THROUGH "living_can_allow_through" +///Allow to movable atoms to pass through this living mob +#define COMPONENT_LIVING_PASSABLE (1<<0) diff --git a/code/__DEFINES/~doppler_defines/species.dm b/code/__DEFINES/~doppler_defines/species.dm new file mode 100644 index 0000000000000..77e3b78260ad1 --- /dev/null +++ b/code/__DEFINES/~doppler_defines/species.dm @@ -0,0 +1,2 @@ +// Slugcats, from Talon III. +#define SPECIES_SLUGCAT "slugcat" diff --git a/code/datums/bodypart_overlays/bodypart_overlay.dm b/code/datums/bodypart_overlays/bodypart_overlay.dm index 15b1e01114943..10260c8d01910 100644 --- a/code/datums/bodypart_overlays/bodypart_overlay.dm +++ b/code/datums/bodypart_overlays/bodypart_overlay.dm @@ -4,7 +4,12 @@ ///Sometimes we need multiple layers, for like the back, middle and front of the person (EXTERNAL_FRONT, EXTERNAL_ADJACENT, EXTERNAL_BEHIND) var/layers ///List of all possible layers. Used for looping through in drawing - var/static/list/all_layers = list(EXTERNAL_FRONT, EXTERNAL_ADJACENT, EXTERNAL_BEHIND) + //var/static/list/all_layers = list(EXTERNAL_FRONT, EXTERNAL_ADJACENT, EXTERNAL_BEHIND) /// DOPPLER SHIFT REMOVAL + /// DOPPLER SHIFT ADDITION BEGIN + var/static/list/all_layers = list(EXTERNAL_FRONT,EXTERNAL_FRONT_2,EXTERNAL_FRONT_3, + EXTERNAL_ADJACENT,EXTERNAL_ADJACENT_2,EXTERNAL_ADJACENT_3, + EXTERNAL_BEHIND,EXTERNAL_BEHIND_2,EXTERNAL_BEHIND_3) + /// DOPPLER SHIFT ADDITION END ///Key of the icon states of all the sprite_datums for easy caching var/cache_key = "" @@ -57,6 +62,20 @@ return "ADJ" if(-BODY_FRONT_LAYER) return "FRONT" + /// DOPPLER SHIFT ADDITION BEGIN + if(-BODY_BEHIND_LAYER_2) + return "BEHIND_2" + if(-BODY_BEHIND_LAYER_3) + return "BEHIND_3" + if(-BODY_ADJ_LAYER_2) + return "ADJ_2" + if(-BODY_ADJ_LAYER_3) + return "ADJ_3" + if(-BODY_FRONT_LAYER_2) + return "FRONT_2" + if(-BODY_FRONT_LAYER_3) + return "FRONT_3" + /// DOPPLER SHIFT ADDITION END ///Converts a bitflag to the right layer. I'd love to make this a static index list, but byond made an attempt on my life when i did /datum/bodypart_overlay/proc/bitflag_to_layer(layer) @@ -67,6 +86,20 @@ return -BODY_ADJ_LAYER if(EXTERNAL_FRONT) return -BODY_FRONT_LAYER + /// DOPPLER SHIFT ADDITION BEGIN + if(EXTERNAL_BEHIND_2) + return -BODY_BEHIND_LAYER_2 + if(EXTERNAL_BEHIND_3) + return -BODY_BEHIND_LAYER_3 + if(EXTERNAL_ADJACENT_2) + return -BODY_ADJ_LAYER_2 + if(EXTERNAL_ADJACENT_3) + return -BODY_ADJ_LAYER_3 + if(EXTERNAL_FRONT_2) + return -BODY_FRONT_LAYER_2 + if(EXTERNAL_FRONT_3) + return -BODY_FRONT_LAYER_3 + /// DOPPLER SHIFT ADDITION END ///Check whether we can draw the overlays. You generally don't want lizard snouts to draw over an EVA suit /datum/bodypart_overlay/proc/can_draw_on_bodypart(mob/living/carbon/human/human) diff --git a/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm b/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm index d0250cce686eb..83691ea8a8ace 100644 --- a/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm +++ b/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm @@ -71,7 +71,7 @@ var/gender = (limb?.limb_gender == FEMALE) ? "f" : "m" var/list/icon_state_builder = list() icon_state_builder += sprite_datum.gender_specific ? gender : "m" //Male is default because sprite accessories are so ancient they predate the concept of not hardcoding gender - icon_state_builder += feature_key + icon_state_builder += feature_key_sprite ? feature_key_sprite : feature_key /// DOPPLER SHIFT EDIT: try to use the sprite key first, normal key otherwise icon_state_builder += get_base_icon_state() icon_state_builder += mutant_bodyparts_layertext(image_layer) diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 4fff0104439c1..8d6f3d1ec79ce 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -236,6 +236,10 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) L[DNA_MUSHROOM_CAPS_BLOCK] = construct_block(SSaccessories.caps_list.Find(features["caps"]), length(SSaccessories.caps_list)) if(features["pod_hair"]) L[DNA_POD_HAIR_BLOCK] = construct_block(SSaccessories.pod_hair_list.Find(features["pod_hair"]), length(SSaccessories.pod_hair_list)) + /// DOPPLER SHIFT ADDITION BEGIN + if(features["breasts"]) + L[DNA_BREASTS_BLOCK] = construct_block(SSaccessories.breasts_list.Find(features["breasts"]), length(SSaccessories.breasts_list)) + /// DOPPLER SHIFT ADDITION END for(var/blocknum in 1 to DNA_FEATURE_BLOCKS) . += L[blocknum] || random_string(GET_UI_BLOCK_LEN(blocknum), GLOB.hex_characters) @@ -380,6 +384,10 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) set_uni_feature_block(blocknumber, construct_block(SSaccessories.caps_list.Find(features["caps"]), length(SSaccessories.caps_list))) if(DNA_POD_HAIR_BLOCK) set_uni_feature_block(blocknumber, construct_block(SSaccessories.pod_hair_list.Find(features["pod_hair"]), length(SSaccessories.pod_hair_list))) + /// DOPPLER SHIFT ADDITION BEGIN + if(DNA_BREASTS_BLOCK) + set_uni_feature_block(blocknumber, construct_block(SSaccessories.breasts_list.Find(features["breasts"]), length(SSaccessories.breasts_list))) + /// DOPPLER SHIFT ADDITION END //Please use add_mutation or activate_mutation instead /datum/dna/proc/force_give(datum/mutation/human/human_mutation) @@ -681,6 +689,10 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) dna.features["caps"] = SSaccessories.caps_list[deconstruct_block(get_uni_feature_block(features, DNA_MUSHROOM_CAPS_BLOCK), length(SSaccessories.caps_list))] if(dna.features["pod_hair"]) dna.features["pod_hair"] = SSaccessories.pod_hair_list[deconstruct_block(get_uni_feature_block(features, DNA_POD_HAIR_BLOCK), length(SSaccessories.pod_hair_list))] + /// DOPPLER SHIFT ADDITION BEGIN + if(dna.features["breasts"]) + dna.features["breasts"] = SSaccessories.breasts_list[deconstruct_block(get_uni_feature_block(features, DNA_BREASTS_BLOCK), length(SSaccessories.breasts_list))] + /// DOPPLER SHIFT ADDITION END for(var/obj/item/organ/organ in organs) organ.mutate_feature(features, src) diff --git a/code/datums/sprite_accessories.dm b/code/datums/sprite_accessories.dm index 784e9422541bd..2c01857ee0ace 100644 --- a/code/datums/sprite_accessories.dm +++ b/code/datums/sprite_accessories.dm @@ -1724,9 +1724,11 @@ /datum/sprite_accessory/lizard_markings icon = 'icons/mob/human/species/lizard/lizard_markings.dmi' -/datum/sprite_accessory/lizard_markings/none +/// DOPPLER SHIFT REMOVAL BEGIN +/*/datum/sprite_accessory/lizard_markings/none name = "None" - icon_state = "none" + icon_state = "none"*/ +/// DOPPLER SHIFT REMOVAL END /datum/sprite_accessory/lizard_markings/dtiger name = "Dark Tiger Body" @@ -1752,10 +1754,12 @@ icon = 'icons/mob/human/species/lizard/lizard_tails.dmi' spine_key = SPINE_KEY_LIZARD -/datum/sprite_accessory/tails/lizard/none +/// DOPPLER SHIFT REMOVAL BEGIN +/*/datum/sprite_accessory/tails/lizard/none name = SPRITE_ACCESSORY_NONE icon_state = "none" - natural_spawn = FALSE + natural_spawn = FALSE*/ +/// DOPPLER SHIFT REMOVAL END /datum/sprite_accessory/tails/lizard/smooth name = "Smooth" diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index c078a23e89c24..833142ed34b03 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -267,6 +267,41 @@ GLOBAL_LIST_EMPTY(preferences_datums) return FALSE return TRUE + /// DOPPLER SHIFT ADDITION BEGIN + if ("set_tricolor_preference") + var/requested_preference_key = params["preference"] + var/index_key = params["value"] + + var/datum/preference/requested_preference = GLOB.preference_entries_by_key[requested_preference_key] + if (isnull(requested_preference)) + return FALSE + + if (!istype(requested_preference, /datum/preference/tri_color)) + return FALSE + + var/default_value_list = read_preference(requested_preference.type) + if (!islist(default_value_list)) + return FALSE + var/default_value = default_value_list[index_key] + + // Yielding + var/new_color = input( + usr, + "Select new color", + null, + default_value || COLOR_WHITE, + ) as color | null + + if (!new_color) + return FALSE + + default_value_list[index_key] = new_color + + if (!update_preference(requested_preference, default_value_list)) + return FALSE + + return TRUE + /// DOPPLER SHIFT ADDITION END for (var/datum/preference_middleware/preference_middleware as anything in middleware) var/delegation = preference_middleware.action_delegations[action] diff --git a/code/modules/client/preferences/species_features/lizard.dm b/code/modules/client/preferences/species_features/lizard.dm index 11fefc17b8b9e..7749b31a8b287 100644 --- a/code/modules/client/preferences/species_features/lizard.dm +++ b/code/modules/client/preferences/species_features/lizard.dm @@ -15,11 +15,22 @@ if (!isnull(sprite_accessory)) var/icon/accessory_icon = icon(sprite_accessory.icon, "m_[key]_[sprite_accessory.icon_state]_ADJ", EAST) + /// DOPPLER SHIFT ADDITION BEGIN + accessory_icon.Blend(COLOR_RED, ICON_MULTIPLY) + var/icon/accessory_icon_2 = icon(sprite_accessory.icon, "m_[key]_[sprite_accessory.icon_state]_ADJ_2", EAST) + accessory_icon_2.Blend(COLOR_VIBRANT_LIME, ICON_MULTIPLY) + var/icon/accessory_icon_3 = icon(sprite_accessory.icon, "m_[key]_[sprite_accessory.icon_state]_ADJ_3", EAST) + accessory_icon_3.Blend(COLOR_BLUE, ICON_MULTIPLY) + /// DOPPLER SHIFT ADDITION END final_icon.Blend(accessory_icon, ICON_OVERLAY) + /// DOPPLER SHIFT ADDITION BEGIN + final_icon.Blend(accessory_icon_2, ICON_OVERLAY) + final_icon.Blend(accessory_icon_3, ICON_OVERLAY) + /// DOPPLER SHIFT ADDITION END final_icon.Crop(11, 20, 23, 32) final_icon.Scale(32, 32) - final_icon.Blend(COLOR_VIBRANT_LIME, ICON_MULTIPLY) + //final_icon.Blend(COLOR_VIBRANT_LIME, ICON_MULTIPLY) /// DOPPLER SHIFT REMOVAL return final_icon @@ -40,14 +51,27 @@ var/icon/final_icon = icon('icons/mob/human/species/lizard/bodyparts.dmi', "lizard_chest_m") if (sprite_accessory.icon_state != "none") - var/icon/body_markings_icon = icon( + /// DOPPLER SHIFT REMOVAL BEGIN + /*var/icon/body_markings_icon = icon( 'icons/mob/human/species/lizard/lizard_misc.dmi', "male_[sprite_accessory.icon_state]_chest", ) - final_icon.Blend(body_markings_icon, ICON_OVERLAY) - - final_icon.Blend(COLOR_VIBRANT_LIME, ICON_MULTIPLY) + final_icon.Blend(body_markings_icon, ICON_OVERLAY)*/ + /// DOPPLER SHIFT REMOVAL END + /// DOPPLER SHIFT ADDITION BEGIN + var/icon/markings_icon_1 = icon(sprite_accessory.icon, "male_[sprite_accessory.icon_state]_chest") + markings_icon_1.Blend(COLOR_RED, ICON_MULTIPLY) + var/icon/markings_icon_2 = icon(sprite_accessory.icon, "male_[sprite_accessory.icon_state]_chest_2") + markings_icon_2.Blend(COLOR_VIBRANT_LIME, ICON_MULTIPLY) + var/icon/markings_icon_3 = icon(sprite_accessory.icon, "male_[sprite_accessory.icon_state]_chest_3") + markings_icon_3.Blend(COLOR_BLUE, ICON_MULTIPLY) + final_icon.Blend(markings_icon_1, ICON_OVERLAY) + final_icon.Blend(markings_icon_2, ICON_OVERLAY) + final_icon.Blend(markings_icon_3, ICON_OVERLAY) + /// DOPPLER SHIFT ADDITION END + + //final_icon.Blend(COLOR_VIBRANT_LIME, ICON_MULTIPLY) /// DOPPLER SHIFT REMOVAL final_icon.Crop(10, 8, 22, 23) final_icon.Scale(26, 32) final_icon.Crop(-2, 1, 29, 32) diff --git a/code/modules/surgery/organs/external/tails.dm b/code/modules/surgery/organs/external/tails.dm index cae83153bdc55..ba3e711f15974 100644 --- a/code/modules/surgery/organs/external/tails.dm +++ b/code/modules/surgery/organs/external/tails.dm @@ -40,6 +40,13 @@ receiver.add_mood_event("tail_regained", /datum/mood_event/tail_regained_wrong) /obj/item/organ/external/tail/on_bodypart_insert(obj/item/bodypart/bodypart) + /// DOPPLER SHIFT ADDITION BEGIN + // damnit TG your own code fails CI for reasons unclear - TODO, stack trace this to eventually figure out how it's ending up with null owners + if(bodypart == null) + return ..() + if(bodypart.owner == null) + return ..() + /// DOPPLER SHIFT ADDITION END var/obj/item/organ/external/spines/our_spines = bodypart.owner.get_organ_slot(ORGAN_SLOT_EXTERNAL_SPINES) if(our_spines) try_insert_tail_spines(bodypart) diff --git a/code/modules/surgery/organs/internal/eyes/_eyes.dm b/code/modules/surgery/organs/internal/eyes/_eyes.dm index 4b611852b79b7..0893a3a2ad7f7 100644 --- a/code/modules/surgery/organs/internal/eyes/_eyes.dm +++ b/code/modules/surgery/organs/internal/eyes/_eyes.dm @@ -129,15 +129,20 @@ if(isnull(eye_icon_state)) return list() - var/mutable_appearance/eye_left = mutable_appearance('icons/mob/human/human_face.dmi', "[eye_icon_state]_l", -BODY_LAYER) - var/mutable_appearance/eye_right = mutable_appearance('icons/mob/human/human_face.dmi', "[eye_icon_state]_r", -BODY_LAYER) + /// DOPPLER SHIFT ADDITION BEGIN + var/obj/item/bodypart/head/my_head = parent.get_bodypart(BODY_ZONE_HEAD) + var/eye_icon = my_head?.eyes_icon || 'icons/mob/human/human_face.dmi' + /// DOPPLER SHIFT ADDITION END + + var/mutable_appearance/eye_left = mutable_appearance(eye_icon, "[eye_icon_state]_l", -BODY_LAYER) /// DOPPLER SHIFT EDIT: using eye_icon instead of human_face.dmi + var/mutable_appearance/eye_right = mutable_appearance(eye_icon, "[eye_icon_state]_r", -BODY_LAYER) /// DOPPLER SHIFT EDIT: using eye_icon instead of human_face.dmi var/list/overlays = list(eye_left, eye_right) var/obscured = parent.check_obscured_slots(TRUE) if(overlay_ignore_lighting && !(obscured & ITEM_SLOT_EYES)) overlays += emissive_appearance(eye_left.icon, eye_left.icon_state, parent, -BODY_LAYER, alpha = eye_left.alpha) overlays += emissive_appearance(eye_right.icon, eye_right.icon_state, parent, -BODY_LAYER, alpha = eye_right.alpha) - var/obj/item/bodypart/head/my_head = parent.get_bodypart(BODY_ZONE_HEAD) + //var/obj/item/bodypart/head/my_head = parent.get_bodypart(BODY_ZONE_HEAD) /// DOPPLER SHIFT REMOVAL if(my_head) if(my_head.head_flags & HEAD_EYECOLOR) eye_right.color = eye_color_right 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 61b7c36d94a02..4af34b006d757 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_humanoids__datum_species_android.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_android.png index 20addbcdf8ec1..7b9f46157fb5c 100644 Binary files a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_android.png and b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_android.png differ diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_lizard.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_lizard.png index c0a3c30b8bb38..b7325952e0d2d 100644 Binary files a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_lizard.png and b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_lizard.png differ diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_lizard_ashwalker.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_lizard_ashwalker.png index 70d445b771277..698b80483e14b 100644 Binary files a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_lizard_ashwalker.png and b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_lizard_ashwalker.png differ diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_lizard_silverscale.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_lizard_silverscale.png index f7f6ddf47d578..054d30c4a8094 100644 Binary files a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_lizard_silverscale.png and b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_lizard_silverscale.png differ diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_moth.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_moth.png index 284205a73ec13..f3dff225c1eb3 100644 Binary files a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_moth.png and b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_moth.png differ diff --git a/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_slugcat.png b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_slugcat.png new file mode 100644 index 0000000000000..1d9bf938b78e0 Binary files /dev/null and b/code/modules/unit_tests/screenshots/screenshot_humanoids__datum_species_slugcat.png differ diff --git a/code/modules/unit_tests/screenshots/transformation_sting_appearances.png b/code/modules/unit_tests/screenshots/transformation_sting_appearances.png index e20d19d45b680..5d526a0dedc76 100644 Binary files a/code/modules/unit_tests/screenshots/transformation_sting_appearances.png and b/code/modules/unit_tests/screenshots/transformation_sting_appearances.png differ diff --git a/code/~doppler_earliest_defines.dm b/code/~doppler_earliest_defines.dm new file mode 100644 index 0000000000000..4e8042c51c12d --- /dev/null +++ b/code/~doppler_earliest_defines.dm @@ -0,0 +1,26 @@ +/// Hi! This file is here to work around some order-of-operations issues consistent humans & a couple other things have. +/// If our overrides aren't loaded in early enough default TG stuff will end up in the critical [1] slot and break things. +/datum/sprite_accessory/lizard_markings/none + icon = 'modular_doppler/customization/icons/fallbacks.dmi' + name = "No Markings" + icon_state = "none" + +/datum/sprite_accessory/snouts/none + icon = 'modular_doppler/customization/icons/fallbacks.dmi' + name = "No Snout" + icon_state = "none" + +/datum/sprite_accessory/frills/none + icon = 'modular_doppler/customization/icons/fallbacks.dmi' + name = "No Frills" + icon_state = "none" + +/datum/sprite_accessory/horns/none + icon = 'modular_doppler/customization/icons/fallbacks.dmi' + name = "No Horns" + icon_state = "none" + +/datum/sprite_accessory/tails/lizard/none + icon = 'modular_doppler/customization/icons/fallbacks.dmi' + name = "No Tail" + icon_state = "none" diff --git a/config/game_options.txt b/config/game_options.txt index 14646c6920758..abff35f639264 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -364,6 +364,7 @@ ROUNDSTART_RACES lizard ROUNDSTART_RACES moth ROUNDSTART_RACES plasmaman #ROUNDSTART_RACES shadow +ROUNDSTART_RACES slugcat ## Races that are better than humans in some ways, but worse in others ROUNDSTART_RACES ethereal diff --git a/modular_doppler/customization/code/accessory_overrides.dm b/modular_doppler/customization/code/accessory_overrides.dm new file mode 100644 index 0000000000000..d29dfe667f433 --- /dev/null +++ b/modular_doppler/customization/code/accessory_overrides.dm @@ -0,0 +1,3 @@ +/datum/bodypart_overlay/mutant + /// Annoying annoying annoyed annoyance - this is to avoid a massive headache trying to work around tails + var/feature_key_sprite = null diff --git a/modular_doppler/customization/code/accessory_overrides_lizard.dm b/modular_doppler/customization/code/accessory_overrides_lizard.dm new file mode 100644 index 0000000000000..7ded20b493d71 --- /dev/null +++ b/modular_doppler/customization/code/accessory_overrides_lizard.dm @@ -0,0 +1,418 @@ +/datum/species/get_features() + var/list/features = ..() + + features += /datum/preference/choiced/lizard_snout + features += /datum/preference/choiced/lizard_frills + features += /datum/preference/choiced/lizard_horns + features += /datum/preference/choiced/lizard_tail + features += /datum/preference/choiced/lizard_body_markings + + GLOB.features_by_species[type] = features + + return features + + + + + +/// Snout fixing +/obj/item/organ/external/snout + name = "snout" + +/datum/bodypart_overlay/mutant/snout + layers = EXTERNAL_ADJACENT | EXTERNAL_ADJACENT_2 | EXTERNAL_ADJACENT_3 + +/datum/bodypart_overlay/mutant/snout/color_image(image/overlay, draw_layer, obj/item/bodypart/limb) + if(limb == null) + return ..() + if(limb.owner == null) + return ..() + if(draw_layer == bitflag_to_layer(EXTERNAL_ADJACENT)) + overlay.color = limb.owner.dna.features["snout_color_1"] + return overlay + else if(draw_layer == bitflag_to_layer(EXTERNAL_ADJACENT_2)) + overlay.color = limb.owner.dna.features["snout_color_2"] + return overlay + else if(draw_layer == bitflag_to_layer(EXTERNAL_ADJACENT_3)) + overlay.color = limb.owner.dna.features["snout_color_3"] + return overlay + return ..() + +//core toggle +/datum/preference/toggle/snout + savefile_key = "has_snout" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SECONDARY_FEATURES + priority = PREFERENCE_PRIORITY_DEFAULT + +/datum/preference/toggle/snout/apply_to_human(mob/living/carbon/human/target, value) + if(value == FALSE) + target.dna.features["snout"] = /datum/sprite_accessory/snouts/none::name + +/datum/preference/toggle/snout/create_default_value() + return FALSE + +/datum/species/regenerate_organs(mob/living/carbon/target, datum/species/old_species, replace_current = TRUE, list/excluded_zones, visual_only = FALSE) + . = ..() + if(target.dna.features["snout"]) + if(target.dna.features["snout"] != /datum/sprite_accessory/snouts/none::name && target.dna.features["snout"] != /datum/sprite_accessory/blank::name) + var/obj/item/organ/replacement = SSwardrobe.provide_type(/obj/item/organ/external/snout) + replacement.Insert(target, special = TRUE, movement_flags = DELETE_IF_REPLACED) + return . + var/obj/item/organ/old_part = target.get_organ_slot(ORGAN_SLOT_EXTERNAL_SNOUT) + if(old_part) + old_part.Remove(target, special = TRUE, movement_flags = DELETE_IF_REPLACED) + old_part.moveToNullspace() + +//sprite selection +/datum/preference/choiced/lizard_snout + category = PREFERENCE_CATEGORY_CLOTHING + +/datum/preference/choiced/lizard_snout/is_accessible(datum/preferences/preferences) + . = ..() + var/has_snout = preferences.read_preference(/datum/preference/toggle/snout) + if(has_snout == TRUE) + return TRUE + return FALSE + +/datum/preference/choiced/lizard_snout/create_default_value() + return /datum/sprite_accessory/snouts/none::name + + + + + +/// Horns fixing +/obj/item/organ/external/horns + name = "horns" + +/datum/bodypart_overlay/mutant/horns + layers = EXTERNAL_ADJACENT | EXTERNAL_ADJACENT_2 | EXTERNAL_ADJACENT_3 + +/datum/bodypart_overlay/mutant/horns/color_image(image/overlay, draw_layer, obj/item/bodypart/limb) + if(limb == null) + return ..() + if(limb.owner == null) + return ..() + if(draw_layer == bitflag_to_layer(EXTERNAL_ADJACENT)) + overlay.color = limb.owner.dna.features["horns_color_1"] + return overlay + else if(draw_layer == bitflag_to_layer(EXTERNAL_ADJACENT_2)) + overlay.color = limb.owner.dna.features["horns_color_2"] + return overlay + else if(draw_layer == bitflag_to_layer(EXTERNAL_ADJACENT_3)) + overlay.color = limb.owner.dna.features["horns_color_3"] + return overlay + return ..() + +//core toggle +/datum/preference/toggle/horns + savefile_key = "has_horns" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SECONDARY_FEATURES + priority = PREFERENCE_PRIORITY_DEFAULT + +/datum/preference/toggle/horns/apply_to_human(mob/living/carbon/human/target, value) + if(value == FALSE) + target.dna.features["horns"] = /datum/sprite_accessory/horns/none::name + +/datum/preference/toggle/horns/create_default_value() + return FALSE + +/datum/species/regenerate_organs(mob/living/carbon/target, datum/species/old_species, replace_current = TRUE, list/excluded_zones, visual_only = FALSE) + . = ..() + if(target.dna.features["horns"]) + if(target.dna.features["horns"] != /datum/sprite_accessory/horns/none::name && target.dna.features["horns"] != /datum/sprite_accessory/blank::name) + var/obj/item/organ/replacement = SSwardrobe.provide_type(/obj/item/organ/external/horns) + replacement.Insert(target, special = TRUE, movement_flags = DELETE_IF_REPLACED) + return . + var/obj/item/organ/old_part = target.get_organ_slot(ORGAN_SLOT_EXTERNAL_HORNS) + if(old_part) + old_part.Remove(target, special = TRUE, movement_flags = DELETE_IF_REPLACED) + old_part.moveToNullspace() + +//sprite selection +/datum/preference/choiced/lizard_horns + category = PREFERENCE_CATEGORY_CLOTHING + +/datum/preference/choiced/lizard_horns/is_accessible(datum/preferences/preferences) + . = ..() + var/has_horns = preferences.read_preference(/datum/preference/toggle/horns) + if(has_horns == TRUE) + return TRUE + return FALSE + +/datum/preference/choiced/lizard_horns/create_default_value() + return /datum/sprite_accessory/horns/none::name + + + + + +/// Frills fixing +/obj/item/organ/external/frills + name = "frills" + +/datum/bodypart_overlay/mutant/frills + layers = EXTERNAL_ADJACENT | EXTERNAL_ADJACENT_2 | EXTERNAL_ADJACENT_3 + +/datum/bodypart_overlay/mutant/frills/color_image(image/overlay, draw_layer, obj/item/bodypart/limb) + if(limb == null) + return ..() + if(limb.owner == null) + return ..() + if(draw_layer == bitflag_to_layer(EXTERNAL_ADJACENT)) + overlay.color = limb.owner.dna.features["frills_color_1"] + return overlay + else if(draw_layer == bitflag_to_layer(EXTERNAL_ADJACENT_2)) + overlay.color = limb.owner.dna.features["frills_color_2"] + return overlay + else if(draw_layer == bitflag_to_layer(EXTERNAL_ADJACENT_3)) + overlay.color = limb.owner.dna.features["frills_color_3"] + return overlay + return ..() + +//core toggle +/datum/preference/toggle/frills + savefile_key = "has_frills" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SECONDARY_FEATURES + priority = PREFERENCE_PRIORITY_DEFAULT + +/datum/preference/toggle/frills/apply_to_human(mob/living/carbon/human/target, value) + if(value == FALSE) + target.dna.features["frills"] = /datum/sprite_accessory/frills/none::name + +/datum/preference/toggle/frills/create_default_value() + return FALSE + +/datum/species/regenerate_organs(mob/living/carbon/target, datum/species/old_species, replace_current = TRUE, list/excluded_zones, visual_only = FALSE) + . = ..() + if(target.dna.features["frills"]) + if(target.dna.features["frills"] != /datum/sprite_accessory/frills/none::name && target.dna.features["frills"] != /datum/sprite_accessory/blank::name) + var/obj/item/organ/replacement = SSwardrobe.provide_type(/obj/item/organ/external/frills) + replacement.Insert(target, special = TRUE, movement_flags = DELETE_IF_REPLACED) + return . + var/obj/item/organ/old_part = target.get_organ_slot(ORGAN_SLOT_EXTERNAL_FRILLS) + if(old_part) + old_part.Remove(target, special = TRUE, movement_flags = DELETE_IF_REPLACED) + old_part.moveToNullspace() + +//sprite selection +/datum/preference/choiced/lizard_frills + category = PREFERENCE_CATEGORY_CLOTHING + +/datum/preference/choiced/lizard_frills/is_accessible(datum/preferences/preferences) + . = ..() + var/has_frills = preferences.read_preference(/datum/preference/toggle/frills) + if(has_frills == TRUE) + return TRUE + return FALSE + +/datum/preference/choiced/lizard_frills/create_default_value() + return /datum/sprite_accessory/frills/none::name + + + + + +/// Tails fixing +/obj/item/organ/external/tail/lizard + name = "tail" + +/datum/bodypart_overlay/mutant/tail/lizard + layers = EXTERNAL_FRONT | EXTERNAL_FRONT_2 | EXTERNAL_FRONT_3 | EXTERNAL_BEHIND | EXTERNAL_BEHIND_2 | EXTERNAL_BEHIND_3 + feature_key_sprite = "tail" + +/datum/bodypart_overlay/mutant/tail/lizard/color_image(image/overlay, draw_layer, obj/item/bodypart/limb) + if(limb == null) + return ..() + if(limb.owner == null) + return ..() + if(draw_layer == bitflag_to_layer(EXTERNAL_FRONT)) + overlay.color = limb.owner.dna.features["tail_color_1"] + return overlay + else if(draw_layer == bitflag_to_layer(EXTERNAL_BEHIND)) + overlay.color = limb.owner.dna.features["tail_color_1"] + return overlay + else if(draw_layer == bitflag_to_layer(EXTERNAL_FRONT_2)) + overlay.color = limb.owner.dna.features["tail_color_2"] + return overlay + else if(draw_layer == bitflag_to_layer(EXTERNAL_BEHIND_2)) + overlay.color = limb.owner.dna.features["tail_color_2"] + return overlay + else if(draw_layer == bitflag_to_layer(EXTERNAL_FRONT_3)) + overlay.color = limb.owner.dna.features["tail_color_3"] + return overlay + else if(draw_layer == bitflag_to_layer(EXTERNAL_BEHIND_3)) + overlay.color = limb.owner.dna.features["tail_color_3"] + return overlay + return ..() + +//core toggle +/datum/preference/toggle/tail + savefile_key = "has_tail" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SECONDARY_FEATURES + priority = PREFERENCE_PRIORITY_DEFAULT + +/datum/preference/toggle/tail/apply_to_human(mob/living/carbon/human/target, value) + if(value == FALSE) + target.dna.features["tail_lizard"] = /datum/sprite_accessory/tails/lizard/none::name + +/datum/preference/toggle/tail/create_default_value() + return FALSE + +/datum/species/regenerate_organs(mob/living/carbon/target, datum/species/old_species, replace_current = TRUE, list/excluded_zones, visual_only = FALSE) + . = ..() + if(target == null) + return + if(target.dna.features["tail_lizard"]) + if(target.dna.features["tail_lizard"] != /datum/sprite_accessory/tails/lizard/none::name && target.dna.features["tail_lizard"] != /datum/sprite_accessory/blank::name) + var/obj/item/organ/replacement = SSwardrobe.provide_type(/obj/item/organ/external/tail/lizard) + replacement.Insert(target, special = TRUE, movement_flags = DELETE_IF_REPLACED) + return . + var/obj/item/organ/external/tail/lizard/old_part = target.get_organ_slot(ORGAN_SLOT_EXTERNAL_TAIL) + if(istype(old_part)) + old_part.Remove(target, special = TRUE, movement_flags = DELETE_IF_REPLACED) + old_part.moveToNullspace() + +//sprite selection +/datum/preference/choiced/lizard_tail + category = PREFERENCE_CATEGORY_CLOTHING + relevant_external_organ = null + should_generate_icons = TRUE + main_feature_name = "Tail" + +/datum/preference/choiced/lizard_tail/is_accessible(datum/preferences/preferences) + . = ..() + var/has_tail = preferences.read_preference(/datum/preference/toggle/tail) + if(has_tail == TRUE) + return TRUE + return FALSE + +/datum/preference/choiced/lizard_tail/create_default_value() + return /datum/sprite_accessory/tails/lizard/none::name + +/datum/preference/choiced/lizard_tail/icon_for(value) + var/datum/sprite_accessory/sprite_accessory = SSaccessories.tails_list_lizard[value] + + var/icon/final_icon = icon('icons/mob/human/species/lizard/bodyparts.dmi', "lizard_chest_m", NORTH) + + if (sprite_accessory.icon_state != "none") + var/icon/markings_icon_1 = icon(sprite_accessory.icon, "m_tail_[sprite_accessory.icon_state]_BEHIND", NORTH) + markings_icon_1.Blend(COLOR_RED, ICON_MULTIPLY) + var/icon/markings_icon_2 = icon(sprite_accessory.icon, "m_tail_[sprite_accessory.icon_state]_BEHIND_2", NORTH) + markings_icon_2.Blend(COLOR_VIBRANT_LIME, ICON_MULTIPLY) + var/icon/markings_icon_3 = icon(sprite_accessory.icon, "m_tail_[sprite_accessory.icon_state]_BEHIND_3", NORTH) + markings_icon_3.Blend(COLOR_BLUE, ICON_MULTIPLY) + final_icon.Blend(markings_icon_1, ICON_OVERLAY) + final_icon.Blend(markings_icon_2, ICON_OVERLAY) + final_icon.Blend(markings_icon_3, ICON_OVERLAY) + // front breaker + var/icon/markings_icon_1_f = icon(sprite_accessory.icon, "m_tail_[sprite_accessory.icon_state]_FRONT", NORTH) + markings_icon_1_f.Blend(COLOR_RED, ICON_MULTIPLY) + var/icon/markings_icon_2_f = icon(sprite_accessory.icon, "m_tail_[sprite_accessory.icon_state]_FRONT_2", NORTH) + markings_icon_2_f.Blend(COLOR_VIBRANT_LIME, ICON_MULTIPLY) + var/icon/markings_icon_3_f = icon(sprite_accessory.icon, "m_tail_[sprite_accessory.icon_state]_FRONT_3", NORTH) + markings_icon_3_f.Blend(COLOR_BLUE, ICON_MULTIPLY) + final_icon.Blend(markings_icon_1_f, ICON_OVERLAY) + final_icon.Blend(markings_icon_2_f, ICON_OVERLAY) + final_icon.Blend(markings_icon_3_f, ICON_OVERLAY) + + //final_icon.Crop(4, 12, 28, 32) + //final_icon.Scale(32, 26) + //final_icon.Crop(-2, 1, 29, 32) + + return final_icon + + + + + +/// Standard bodymark fixing +/datum/bodypart_overlay/simple/body_marking/lizard + layers = EXTERNAL_ADJACENT | EXTERNAL_ADJACENT_2 | EXTERNAL_ADJACENT_3 + +/datum/bodypart_overlay/simple/body_marking/lizard/get_image(layer, obj/item/bodypart/limb) + if(limb == null) + return ..() + if(limb.owner == null) + return ..() + var/gender_string = (use_gender && limb.is_dimorphic) ? (limb.gender == MALE ? MALE : FEMALE + "_") : "" //we only got male and female sprites + if(layer == bitflag_to_layer(EXTERNAL_ADJACENT_2)) + return image(icon, gender_string + icon_state + "_" + limb.body_zone + "_2", layer = layer) + if(layer == bitflag_to_layer(EXTERNAL_ADJACENT_3)) + return image(icon, gender_string + icon_state + "_" + limb.body_zone + "_3", layer = layer) + return image(icon, gender_string + icon_state + "_" + limb.body_zone, layer = layer) + +/datum/bodypart_overlay/simple/body_marking/lizard/color_image(image/overlay, draw_layer, obj/item/bodypart/limb) + if(limb == null) + return ..() + if(limb.owner == null) + return ..() + if(draw_layer == bitflag_to_layer(EXTERNAL_ADJACENT)) + overlay.color = limb.owner.dna.features["body_markings_color_1"] + return overlay + else if(draw_layer == bitflag_to_layer(EXTERNAL_ADJACENT_2)) + overlay.color = limb.owner.dna.features["body_markings_color_2"] + return overlay + else if(draw_layer == bitflag_to_layer(EXTERNAL_ADJACENT_3)) + overlay.color = limb.owner.dna.features["body_markings_color_3"] + return overlay + return ..() + +/datum/preference/choiced/lizard_body_markings/create_default_value() + return /datum/sprite_accessory/lizard_markings/none::name + +//toggle prefs +/datum/preference/toggle/markings + savefile_key = "has_markings" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SECONDARY_FEATURES + priority = PREFERENCE_PRIORITY_DEFAULT + +/datum/preference/toggle/markings/apply_to_human(mob/living/carbon/human/target, value) + if(value == FALSE) + target.dna.features["lizard_markings"] = /datum/sprite_accessory/lizard_markings/none::name + +/datum/preference/toggle/markings/create_default_value() + return FALSE + +//toggle pref integration +/datum/preference/choiced/lizard_body_markings + category = PREFERENCE_CATEGORY_CLOTHING + +/datum/preference/choiced/lizard_body_markings/is_accessible(datum/preferences/preferences) + . = ..() + var/has_markings = preferences.read_preference(/datum/preference/toggle/markings) + if(has_markings == TRUE) + return TRUE + return FALSE + +//manually adding them now +/datum/species/add_body_markings(mob/living/carbon/human/hooman) + . = ..() + if(hooman.dna.features["lizard_markings"] && hooman.dna.features["lizard_markings"] != /datum/sprite_accessory/lizard_markings/none::name && hooman.dna.features["snout"] != /datum/sprite_accessory/blank::name) //loop through possible species markings + var/datum/bodypart_overlay/simple/body_marking/markings = new /datum/bodypart_overlay/simple/body_marking/lizard() // made to die... mostly because we cant use initial on lists but its convenient and organized + var/accessory_name = hooman.dna.features[markings.dna_feature_key] //get the accessory name from dna + var/datum/sprite_accessory/moth_markings/accessory = markings.get_accessory(accessory_name) //get the actual datum + + if(isnull(accessory)) + CRASH("Value: [accessory_name] did not have a corresponding sprite accessory!") + + for(var/obj/item/bodypart/part as anything in markings.applies_to) //check through our limbs + var/obj/item/bodypart/people_part = hooman.get_bodypart(initial(part.body_zone)) // and see if we have a compatible marking for that limb + + if(!people_part) + continue + + var/datum/bodypart_overlay/simple/body_marking/overlay = new /datum/bodypart_overlay/simple/body_marking/lizard() + + // Tell the overlay what it should look like + overlay.icon = accessory.icon + overlay.icon_state = accessory.icon_state + overlay.use_gender = accessory.gender_specific + overlay.draw_color = accessory.color_src ? hooman.dna.features["mcolor"] : null + + people_part.add_bodypart_overlay(overlay) diff --git a/modular_doppler/customization/code/accessory_overrides_moth.dm b/modular_doppler/customization/code/accessory_overrides_moth.dm new file mode 100644 index 0000000000000..b71ab3f2e69f4 --- /dev/null +++ b/modular_doppler/customization/code/accessory_overrides_moth.dm @@ -0,0 +1,81 @@ +/// Moth bodymark fixing +/datum/bodypart_overlay/simple/body_marking/moth/color_image(image/overlay, draw_layer, obj/item/bodypart/limb) + if(limb == null) + return ..() + if(limb.owner == null) + return ..() + var/color_intended = COLOR_WHITE + + var/tcol_1 = limb.owner.dna.features["moth_markings_color_1"] + var/tcol_2 = limb.owner.dna.features["moth_markings_color_2"] + var/tcol_3 = limb.owner.dna.features["moth_markings_color_3"] + if(tcol_1 && tcol_2 && tcol_3) + //this is beyond ugly but it works + var/r1 = hex2num(copytext(tcol_1, 2, 4)) / 255.0 + var/g1 = hex2num(copytext(tcol_1, 4, 6)) / 255.0 + var/b1 = hex2num(copytext(tcol_1, 6, 8)) / 255.0 + var/r2 = hex2num(copytext(tcol_2, 2, 4)) / 255.0 + var/g2 = hex2num(copytext(tcol_2, 4, 6)) / 255.0 + var/b2 = hex2num(copytext(tcol_2, 6, 8)) / 255.0 + var/r3 = hex2num(copytext(tcol_3, 2, 4)) / 255.0 + var/g3 = hex2num(copytext(tcol_3, 4, 6)) / 255.0 + var/b3 = hex2num(copytext(tcol_3, 6, 8)) / 255.0 + color_intended = list(r1,g1,b1, r2,g2,b2, r3,g3,b3) + overlay.color = color_intended + return overlay + + + +/// Moth wings recolorening +/datum/bodypart_overlay/mutant/wings/moth/color_image(image/overlay, draw_layer, obj/item/bodypart/limb) + if(limb == null) + return ..() + if(limb.owner == null) + return ..() + var/color_intended = COLOR_WHITE + + var/tcol_1 = limb.owner.dna.features["moth_wings_color_1"] + var/tcol_2 = limb.owner.dna.features["moth_wings_color_2"] + var/tcol_3 = limb.owner.dna.features["moth_wings_color_3"] + if(tcol_1 && tcol_2 && tcol_3) + //this is beyond ugly but it works + var/r1 = hex2num(copytext(tcol_1, 2, 4)) / 255.0 + var/g1 = hex2num(copytext(tcol_1, 4, 6)) / 255.0 + var/b1 = hex2num(copytext(tcol_1, 6, 8)) / 255.0 + var/r2 = hex2num(copytext(tcol_2, 2, 4)) / 255.0 + var/g2 = hex2num(copytext(tcol_2, 4, 6)) / 255.0 + var/b2 = hex2num(copytext(tcol_2, 6, 8)) / 255.0 + var/r3 = hex2num(copytext(tcol_3, 2, 4)) / 255.0 + var/g3 = hex2num(copytext(tcol_3, 4, 6)) / 255.0 + var/b3 = hex2num(copytext(tcol_3, 6, 8)) / 255.0 + color_intended = list(r1,g1,b1, r2,g2,b2, r3,g3,b3) + overlay.color = color_intended + return overlay + + + +/// Moth antennae recolorening +/datum/bodypart_overlay/mutant/antennae/color_image(image/overlay, draw_layer, obj/item/bodypart/limb) + if(limb == null) + return ..() + if(limb.owner == null) + return ..() + var/color_intended = COLOR_WHITE + + var/tcol_1 = limb.owner.dna.features["moth_antennae_color_1"] + var/tcol_2 = limb.owner.dna.features["moth_antennae_color_2"] + var/tcol_3 = limb.owner.dna.features["moth_antennae_color_3"] + if(tcol_1 && tcol_2 && tcol_3) + //this is beyond ugly but it works + var/r1 = hex2num(copytext(tcol_1, 2, 4)) / 255.0 + var/g1 = hex2num(copytext(tcol_1, 4, 6)) / 255.0 + var/b1 = hex2num(copytext(tcol_1, 6, 8)) / 255.0 + var/r2 = hex2num(copytext(tcol_2, 2, 4)) / 255.0 + var/g2 = hex2num(copytext(tcol_2, 4, 6)) / 255.0 + var/b2 = hex2num(copytext(tcol_2, 6, 8)) / 255.0 + var/r3 = hex2num(copytext(tcol_3, 2, 4)) / 255.0 + var/g3 = hex2num(copytext(tcol_3, 4, 6)) / 255.0 + var/b3 = hex2num(copytext(tcol_3, 6, 8)) / 255.0 + color_intended = list(r1,g1,b1, r2,g2,b2, r3,g3,b3) + overlay.color = color_intended + return overlay diff --git a/modular_doppler/customization/code/bodypart_overrides.dm b/modular_doppler/customization/code/bodypart_overrides.dm new file mode 100644 index 0000000000000..1e443cc80df80 --- /dev/null +++ b/modular_doppler/customization/code/bodypart_overrides.dm @@ -0,0 +1,16 @@ +/// If you need to make edits to existing bodyparts, do so in here. +/obj/item/bodypart/head + /// Override of the eyes icon file - used for slugcats as test dummies, followed by teshies, vox, possibly moths & insects, and more! + var/eyes_icon + +/obj/item/bodypart/head/lizard + head_flags = HEAD_ALL_FEATURES + +/obj/item/bodypart/head/moth + head_flags = HEAD_ALL_FEATURES + +/obj/item/bodypart/head/robot + head_flags = HEAD_EYESPRITES | HEAD_FACIAL_HAIR | HEAD_HAIR | HEAD_EYECOLOR + +/obj/item/bodypart/head/snail + head_flags = HEAD_EYESPRITES | HEAD_DEBRAIN | HEAD_FACIAL_HAIR | HEAD_HAIR diff --git a/modular_doppler/customization/code/custom_accessories.dm b/modular_doppler/customization/code/custom_accessories.dm new file mode 100644 index 0000000000000..0fc28fc9c3b36 --- /dev/null +++ b/modular_doppler/customization/code/custom_accessories.dm @@ -0,0 +1 @@ +// This is where our bespoke fluff, IPC antennae, etc accessories should go. diff --git a/modular_doppler/customization/code/dropdowns_to_icons.dm b/modular_doppler/customization/code/dropdowns_to_icons.dm new file mode 100644 index 0000000000000..a553e496c9df0 --- /dev/null +++ b/modular_doppler/customization/code/dropdowns_to_icons.dm @@ -0,0 +1 @@ +//wawa diff --git a/modular_doppler/customization/code/tri_color_prefs.dm b/modular_doppler/customization/code/tri_color_prefs.dm new file mode 100644 index 0000000000000..8e9e5866a3674 --- /dev/null +++ b/modular_doppler/customization/code/tri_color_prefs.dm @@ -0,0 +1,399 @@ +/// Tricolor prefs +/datum/preference/tri_color + abstract_type = /datum/preference/tri_color + +/datum/preference/tri_color/deserialize(input, datum/preferences/preferences) + var/list/input_colors = input + return list(sanitize_hexcolor(input_colors[1]), sanitize_hexcolor(input_colors[2]), sanitize_hexcolor(input_colors[3])) + +/datum/preference/tri_color/create_default_value() + return list("#[random_color()]", "#[random_color()]", "#[random_color()]") + +/datum/preference/tri_color/is_valid(list/value) + return islist(value) && value.len == 3 && (findtext(value[1], GLOB.is_color) && findtext(value[2], GLOB.is_color) && findtext(value[3], GLOB.is_color)) + +/datum/preference/tri_color/is_accessible(datum/preferences/preferences) + return ..() + +// Hey, you! +// Wondering how to get the colors from a tri-col pref? +// Look no further: list(sanitize_hexcolor(value[1]), sanitize_hexcolor(value[2]), sanitize_hexcolor(value[3])) +/datum/preference/tri_color/apply_to_human(mob/living/carbon/human/target, value) + if (type == abstract_type) + return ..() + + + + + +/// Snoot colors! +/datum/preference/tri_color/snout_color + priority = PREFERENCE_PRIORITY_BODY_TYPE + savefile_key = "snout_color" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES + //relevant_external_organ = /obj/item/organ/external/snout + +/datum/preference/tri_color/snout_color/create_default_value() + return list(sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]")) + +/datum/preference/tri_color/snout_color/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["snout_color_1"] = value[1] + target.dna.features["snout_color_2"] = value[2] + target.dna.features["snout_color_3"] = value[3] + +/datum/preference/tri_color/snout_color/is_valid(value) + if (!..(value)) + return FALSE + + return TRUE + +// Gotta add to the selector too +/datum/preference/choiced/lizard_snout/compile_constant_data() + var/list/data = ..() + + data[SUPPLEMENTAL_FEATURE_KEY] = /datum/preference/tri_color/snout_color::savefile_key + + return data + + + +/// Horn colors! +/datum/preference/tri_color/horns_color + priority = PREFERENCE_PRIORITY_BODY_TYPE + savefile_key = "horns_color" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES + //relevant_external_organ = /obj/item/organ/external/horns + +/datum/preference/tri_color/horns_color/create_default_value() + return list(sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]")) + +/datum/preference/tri_color/horns_color/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["horns_color_1"] = value[1] + target.dna.features["horns_color_2"] = value[2] + target.dna.features["horns_color_3"] = value[3] + +/datum/preference/tri_color/horns_color/is_valid(value) + if (!..(value)) + return FALSE + + return TRUE + +// Gotta add to the selector too +/datum/preference/choiced/lizard_horns/compile_constant_data() + var/list/data = ..() + + data[SUPPLEMENTAL_FEATURE_KEY] = /datum/preference/tri_color/horns_color::savefile_key + + return data + + + +/// Frill colors! +/datum/preference/tri_color/frills_color + priority = PREFERENCE_PRIORITY_BODY_TYPE + savefile_key = "frills_color" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES + //relevant_external_organ = /obj/item/organ/external/frills + +/datum/preference/tri_color/frills_color/create_default_value() + return list(sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]")) + +/datum/preference/tri_color/frills_color/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["frills_color_1"] = value[1] + target.dna.features["frills_color_2"] = value[2] + target.dna.features["frills_color_3"] = value[3] + +/datum/preference/tri_color/frills_color/is_valid(value) + if (!..(value)) + return FALSE + + return TRUE + +// Gotta add to the selector too +/datum/preference/choiced/lizard_frills/compile_constant_data() + var/list/data = ..() + + data[SUPPLEMENTAL_FEATURE_KEY] = /datum/preference/tri_color/frills_color::savefile_key + + return data + + + +/// Tail colors! +/datum/preference/tri_color/tail_color + priority = PREFERENCE_PRIORITY_BODY_TYPE + savefile_key = "tail_color" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES + //relevant_external_organ = /obj/item/organ/external/tail + +/datum/preference/tri_color/tail_color/create_default_value() + return list(sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]")) + +/datum/preference/tri_color/tail_color/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["tail_color_1"] = value[1] + target.dna.features["tail_color_2"] = value[2] + target.dna.features["tail_color_3"] = value[3] + +/datum/preference/tri_color/tail_color/is_valid(value) + if (!..(value)) + return FALSE + + return TRUE + +// Gotta add to the selector too +/datum/preference/choiced/lizard_tail/compile_constant_data() + var/list/data = ..() + + data[SUPPLEMENTAL_FEATURE_KEY] = /datum/preference/tri_color/tail_color::savefile_key + + return data + + + +/// Ears colors! +/datum/preference/tri_color/ears_color + priority = PREFERENCE_PRIORITY_BODY_TYPE + savefile_key = "ears_color" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES + //TODO: we might need to change this to a different organ type, it's hard to say + //relevant_external_organ = /obj/item/organ/internal/ears + +/datum/preference/tri_color/ears_color/create_default_value() + return list(sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]")) + +/datum/preference/tri_color/ears_color/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["ears_color_1"] = value[1] + target.dna.features["ears_color_2"] = value[2] + target.dna.features["ears_color_3"] = value[3] + +/datum/preference/tri_color/ears_color/is_valid(value) + if (!..(value)) + return FALSE + + return TRUE + +// Gotta add to the snoot selector too +/datum/preference/choiced/ears/compile_constant_data() + var/list/data = ..() + + data[SUPPLEMENTAL_FEATURE_KEY] = /datum/preference/tri_color/ears_color::savefile_key + + return data + + + +/// Spines colors! +/datum/preference/tri_color/spines_color + priority = PREFERENCE_PRIORITY_BODY_TYPE + savefile_key = "spines_color" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES + //relevant_external_organ = /obj/item/organ/external/spines + +/datum/preference/tri_color/spines_color/create_default_value() + return list(sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]")) + +/datum/preference/tri_color/spines_color/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["spines_color_1"] = value[1] + target.dna.features["spines_color_2"] = value[2] + target.dna.features["spines_color_3"] = value[3] + +/datum/preference/tri_color/spines_color/is_valid(value) + if (!..(value)) + return FALSE + + return TRUE + +// Gotta add to the selector too +/datum/preference/choiced/lizard_spines/compile_constant_data() + var/list/data = ..() + + data[SUPPLEMENTAL_FEATURE_KEY] = /datum/preference/tri_color/spines_color::savefile_key + + return data + + + +/// Caps colors! +/datum/preference/tri_color/caps_color + priority = PREFERENCE_PRIORITY_BODY_TYPE + savefile_key = "caps_color" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES + //relevant_external_organ = /obj/item/organ/external/tail + +/datum/preference/tri_color/caps_color/create_default_value() + return list(sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]")) + +/datum/preference/tri_color/caps_color/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["caps_color_1"] = value[1] + target.dna.features["caps_color_2"] = value[2] + target.dna.features["caps_color_3"] = value[3] + +/datum/preference/tri_color/caps_color/is_valid(value) + if (!..(value)) + return FALSE + + return TRUE + +// Gotta add to the selector too +/datum/preference/choiced/mushroom_cap/compile_constant_data() + var/list/data = ..() + + data[SUPPLEMENTAL_FEATURE_KEY] = /datum/preference/tri_color/caps_color::savefile_key + + return data + + + +/// Moth marking colors! +/datum/preference/tri_color/moth_markings_color + priority = PREFERENCE_PRIORITY_BODY_TYPE + savefile_key = "moth_markings_color" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES + +/datum/preference/tri_color/moth_markings_color/create_default_value() + return list(sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]")) + +/datum/preference/tri_color/moth_markings_color/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["moth_markings_color_1"] = value[1] + target.dna.features["moth_markings_color_2"] = value[2] + target.dna.features["moth_markings_color_3"] = value[3] + +/datum/preference/tri_color/moth_markings_color/is_valid(value) + if (!..(value)) + return FALSE + + return TRUE + +// Gotta add to the selector too +/datum/preference/choiced/moth_markings/compile_constant_data() + var/list/data = ..() + + data[SUPPLEMENTAL_FEATURE_KEY] = /datum/preference/tri_color/moth_markings_color::savefile_key + + return data + + + +/// Standard marking colors! +/datum/preference/tri_color/body_markings_color + priority = PREFERENCE_PRIORITY_BODY_TYPE + savefile_key = "body_markings_color" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES + +/datum/preference/tri_color/body_markings_color/create_default_value() + return list(sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]")) + +/datum/preference/tri_color/body_markings_color/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["body_markings_color_1"] = value[1] + target.dna.features["body_markings_color_2"] = value[2] + target.dna.features["body_markings_color_3"] = value[3] + +/datum/preference/tri_color/body_markings_color/is_valid(value) + if (!..(value)) + return FALSE + + return TRUE + +// Gotta add to the selector too +/datum/preference/choiced/lizard_body_markings/compile_constant_data() + var/list/data = ..() + + data[SUPPLEMENTAL_FEATURE_KEY] = /datum/preference/tri_color/body_markings_color::savefile_key + + return data + + + +/// Wing colors! +/datum/preference/tri_color/wings_color + priority = PREFERENCE_PRIORITY_BODY_TYPE + savefile_key = "wings_color" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES + //relevant_external_organ = /obj/item/organ/external/wings + +/datum/preference/tri_color/wings_color/create_default_value() + return list(sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]")) + +/datum/preference/tri_color/wings_color/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["wings_color_1"] = value[1] + target.dna.features["wings_color_2"] = value[2] + target.dna.features["wings_color_3"] = value[3] + +/datum/preference/tri_color/wings_color/is_valid(value) + if (!..(value)) + return FALSE + + return TRUE + +// Gotta add to the selector too +// TODO: can we migrate off of moth_wings for this? +/*/datum/preference/choiced/wings/compile_constant_data() + var/list/data = ..() + + data[SUPPLEMENTAL_FEATURE_KEY] = /datum/preference/tri_color/wings_color::savefile_key + + return data*/ + + + +/// Moth antennae colors! +/datum/preference/tri_color/moth_antennae_color + priority = PREFERENCE_PRIORITY_BODY_TYPE + savefile_key = "moth_antennae_color" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES + //relevant_external_organ = /obj/item/organ/external/wings + +/datum/preference/tri_color/moth_antennae_color/create_default_value() + return list(sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]")) + +/datum/preference/tri_color/moth_antennae_color/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["moth_antennae_color_1"] = value[1] + target.dna.features["moth_antennae_color_2"] = value[2] + target.dna.features["moth_antennae_color_3"] = value[3] + +/datum/preference/tri_color/moth_antennae_color/is_valid(value) + if (!..(value)) + return FALSE + + return TRUE + +// Gotta add to the selector too +/datum/preference/choiced/moth_antennae/compile_constant_data() + var/list/data = ..() + + data[SUPPLEMENTAL_FEATURE_KEY] = /datum/preference/tri_color/moth_antennae_color::savefile_key + + return data diff --git a/modular_doppler/customization/code/tri_color_prefs_bespoke.dm b/modular_doppler/customization/code/tri_color_prefs_bespoke.dm new file mode 100644 index 0000000000000..436a95a81c969 --- /dev/null +++ b/modular_doppler/customization/code/tri_color_prefs_bespoke.dm @@ -0,0 +1,212 @@ +/// Fluff colors! +/datum/preference/tri_color/fluff_color + priority = PREFERENCE_PRIORITY_BODY_TYPE + savefile_key = "fluff_color" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES + // TODO: we need fluff organs & selection + //relevant_external_organ = /obj/item/organ/external/fluff + +/datum/preference/tri_color/fluff_color/create_default_value() + return list(sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]")) + +/datum/preference/tri_color/fluff_color/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["fluff_color_1"] = value[1] + target.dna.features["fluff_color_2"] = value[2] + target.dna.features["fluff_color_3"] = value[3] + +/datum/preference/tri_color/fluff_color/is_valid(value) + if (!..(value)) + return FALSE + + return TRUE + +// Gotta add to the selector too +// TODO: we need fluff organs & selection +/*/datum/preference/choiced/moth_fluff/compile_constant_data() + var/list/data = ..() + + data[SUPPLEMENTAL_FEATURE_KEY] = /datum/preference/tri_color/fluff_color::savefile_key + + return data*/ + + + +/// Synth antenna colors! +/datum/preference/tri_color/ipc_antenna_color + priority = PREFERENCE_PRIORITY_BODY_TYPE + savefile_key = "ipc_antenna_color" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES + // TODO: we need fluff organs & selection + //relevant_external_organ = /obj/item/organ/external/fluff + +/datum/preference/tri_color/ipc_antenna_color/create_default_value() + return list(sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]")) + +/datum/preference/tri_color/ipc_antenna_color/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["ipc_antenna_color_1"] = value[1] + target.dna.features["ipc_antenna_color_2"] = value[2] + target.dna.features["ipc_antenna_color_3"] = value[3] + +/datum/preference/tri_color/ipc_antenna_color/is_valid(value) + if (!..(value)) + return FALSE + + return TRUE + +// Gotta add to the selector too +// TODO: we need fluff organs & selection +/*/datum/preference/choiced/moth_fluff/compile_constant_data() + var/list/data = ..() + + data[SUPPLEMENTAL_FEATURE_KEY] = /datum/preference/tri_color/ipc_antenna_color::savefile_key + + return data*/ + + + +/// Taur body colors! +/datum/preference/tri_color/taur_color + priority = PREFERENCE_PRIORITY_BODY_TYPE + savefile_key = "taur_color" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES + // TODO: we need fluff organs & selection + //relevant_external_organ = /obj/item/organ/external/fluff + +/datum/preference/tri_color/taur_color/create_default_value() + return list(sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]")) + +/datum/preference/tri_color/taur_color/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["taur_color_1"] = value[1] + target.dna.features["taur_color_2"] = value[2] + target.dna.features["taur_color_3"] = value[3] + +/datum/preference/tri_color/taur_color/is_valid(value) + if (!..(value)) + return FALSE + + return TRUE + +// Gotta add to the selector too +// TODO: we need fluff organs & selection +/*/datum/preference/choiced/moth_fluff/compile_constant_data() + var/list/data = ..() + + data[SUPPLEMENTAL_FEATURE_KEY] = /datum/preference/tri_color/taur_color::savefile_key + + return data*/ + + + +/// Xenomorph dorsal fin colors! +/datum/preference/tri_color/xenodorsal_color + priority = PREFERENCE_PRIORITY_BODY_TYPE + savefile_key = "xenodorsal_color" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES + // TODO: we need fluff organs & selection + //relevant_external_organ = /obj/item/organ/external/fluff + +/datum/preference/tri_color/xenodorsal_color/create_default_value() + return list(sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]")) + +/datum/preference/tri_color/xenodorsal_color/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["xenodorsal_color_1"] = value[1] + target.dna.features["xenodorsal_color_2"] = value[2] + target.dna.features["xenodorsal_color_3"] = value[3] + +/datum/preference/tri_color/xenodorsal_color/is_valid(value) + if (!..(value)) + return FALSE + + return TRUE + +// Gotta add to the selector too +// TODO: we need fluff organs & selection +/*/datum/preference/choiced/moth_fluff/compile_constant_data() + var/list/data = ..() + + data[SUPPLEMENTAL_FEATURE_KEY] = /datum/preference/tri_color/xenodorsal_color::savefile_key + + return data*/ + + + +/// Xenomorph head colors! +/datum/preference/tri_color/xenohead_color + priority = PREFERENCE_PRIORITY_BODY_TYPE + savefile_key = "xenohead_color" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES + // TODO: we need fluff organs & selection + //relevant_external_organ = /obj/item/organ/external/fluff + +/datum/preference/tri_color/xenohead_color/create_default_value() + return list(sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]")) + +/datum/preference/tri_color/xenohead_color/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["xenohead_color_1"] = value[1] + target.dna.features["xenohead_color_2"] = value[2] + target.dna.features["xenohead_color_3"] = value[3] + +/datum/preference/tri_color/xenohead_color/is_valid(value) + if (!..(value)) + return FALSE + + return TRUE + +// Gotta add to the selector too +// TODO: we need fluff organs & selection +/*/datum/preference/choiced/moth_fluff/compile_constant_data() + var/list/data = ..() + + data[SUPPLEMENTAL_FEATURE_KEY] = /datum/preference/tri_color/xenohead_color::savefile_key + + return data*/ + + + +/// Moth wing colors! +/datum/preference/tri_color/moth_wings_color + priority = PREFERENCE_PRIORITY_BODY_TYPE + savefile_key = "moth_wings_color" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES + //relevant_external_organ = /obj/item/organ/external/wings + +/datum/preference/tri_color/moth_wings_color/create_default_value() + return list(sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]")) + +/datum/preference/tri_color/moth_wings_color/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["moth_wings_color_1"] = value[1] + target.dna.features["moth_wings_color_2"] = value[2] + target.dna.features["moth_wings_color_3"] = value[3] + +/datum/preference/tri_color/moth_wings_color/is_valid(value) + if (!..(value)) + return FALSE + + return TRUE + +// Gotta add to the selector too +// TODO: can we migrate off of moth_wings for this? +/datum/preference/choiced/moth_wings/compile_constant_data() + var/list/data = ..() + + data[SUPPLEMENTAL_FEATURE_KEY] = /datum/preference/tri_color/moth_wings_color::savefile_key + + return data diff --git a/modular_doppler/customization/icons/fallbacks.dmi b/modular_doppler/customization/icons/fallbacks.dmi new file mode 100644 index 0000000000000..4f5867e07e724 Binary files /dev/null and b/modular_doppler/customization/icons/fallbacks.dmi differ diff --git a/modular_doppler/customization/species/lizards/code/lizard_accessories.dm b/modular_doppler/customization/species/lizards/code/lizard_accessories.dm new file mode 100644 index 0000000000000..90a0771ffc063 --- /dev/null +++ b/modular_doppler/customization/species/lizards/code/lizard_accessories.dm @@ -0,0 +1,16 @@ +//snouts +/datum/sprite_accessory/lizard_markings + icon = 'modular_doppler/customization/species/lizards/icons/lizard_markings.dmi' + +/datum/sprite_accessory/snouts + icon = 'modular_doppler/customization/species/lizards/icons/lizard_external.dmi' + +/datum/sprite_accessory/frills + icon = 'modular_doppler/customization/species/lizards/icons/lizard_external.dmi' + +/datum/sprite_accessory/horns + icon = 'modular_doppler/customization/species/lizards/icons/lizard_external.dmi' + +/datum/sprite_accessory/tails/lizard + icon = 'modular_doppler/customization/species/lizards/icons/lizard_tails.dmi' + diff --git a/modular_doppler/customization/species/lizards/code/lizard_species.dm b/modular_doppler/customization/species/lizards/code/lizard_species.dm new file mode 100644 index 0000000000000..43c9e98275c6f --- /dev/null +++ b/modular_doppler/customization/species/lizards/code/lizard_species.dm @@ -0,0 +1 @@ +//TODO: we may be able to remove this file diff --git a/modular_doppler/customization/species/lizards/icons/bodyparts.dmi b/modular_doppler/customization/species/lizards/icons/bodyparts.dmi new file mode 100644 index 0000000000000..cf74d73796c8c Binary files /dev/null and b/modular_doppler/customization/species/lizards/icons/bodyparts.dmi differ diff --git a/modular_doppler/customization/species/lizards/icons/lizard_external.dmi b/modular_doppler/customization/species/lizards/icons/lizard_external.dmi new file mode 100644 index 0000000000000..ca7ad196b2293 Binary files /dev/null and b/modular_doppler/customization/species/lizards/icons/lizard_external.dmi differ diff --git a/modular_doppler/customization/species/lizards/icons/lizard_markings.dmi b/modular_doppler/customization/species/lizards/icons/lizard_markings.dmi new file mode 100644 index 0000000000000..b94ad9d570c79 Binary files /dev/null and b/modular_doppler/customization/species/lizards/icons/lizard_markings.dmi differ diff --git a/modular_doppler/customization/species/lizards/icons/lizard_tails.dmi b/modular_doppler/customization/species/lizards/icons/lizard_tails.dmi new file mode 100644 index 0000000000000..93788db366118 Binary files /dev/null and b/modular_doppler/customization/species/lizards/icons/lizard_tails.dmi differ diff --git a/modular_doppler/customization/species/scugs/code/slugcat_accessories.dm b/modular_doppler/customization/species/scugs/code/slugcat_accessories.dm new file mode 100644 index 0000000000000..b95c1d478d172 --- /dev/null +++ b/modular_doppler/customization/species/scugs/code/slugcat_accessories.dm @@ -0,0 +1,78 @@ +//snouts +/datum/sprite_accessory/snouts/slugcat + icon = 'modular_doppler/customization/species/scugs/icons/slugcat_external.dmi' + name = "Slugcat" + icon_state = "scug_standard" + +/datum/sprite_accessory/snouts/slugcat/sharp + name = "Slugcat Sharp" + icon_state = "scug_sharp" + +/datum/sprite_accessory/snouts/slugcat/round + name = "Slugcat Round" + icon_state = "scug_round" + +//frills +/datum/sprite_accessory/frills/slugcat + icon = 'modular_doppler/customization/species/scugs/icons/slugcat_external.dmi' + name = "Slugcat" + icon_state = "scug_aquatic" + +/datum/sprite_accessory/frills/slugcat/sharp + name = "Slugcat Sharp" + icon_state = "scug_sharp" + +/datum/sprite_accessory/frills/slugcat/fluffy + name = "Slugcat Fluffy" + icon_state = "scug_fluffy" + +/datum/sprite_accessory/frills/slugcat/draconic + name = "Slugcat Draconic" + icon_state = "scug_dragon" + +//horns +/datum/sprite_accessory/horns/slugcat + icon = 'modular_doppler/customization/species/scugs/icons/slugcat_external.dmi' + name = "Slugcat" + icon_state = "scug_standard" + +/datum/sprite_accessory/horns/slugcat/tall + name = "Slugcat Tall" + icon_state = "scug_tall" + +/datum/sprite_accessory/horns/slugcat/sharp + name = "Slugcat Sharp" + icon_state = "scug_sharp" + +/datum/sprite_accessory/horns/slugcat/forward + name = "Slugcat Droopy" + icon_state = "scug_forward" + +/datum/sprite_accessory/horns/slugcat/flopped + name = "Slugcat Long Flop" + icon_state = "scug_flopped" + +/datum/sprite_accessory/horns/slugcat/fluffy + name = "Slugcat Fluffy" + icon_state = "scug_fluffy" + +/datum/sprite_accessory/horns/slugcat/short + name = "Slugcat Short" + icon_state = "scug_short" + +//tails +/datum/sprite_accessory/tails/lizard/slugcat + icon = 'modular_doppler/customization/species/scugs/icons/slugcat_tails.dmi' + name = "Slugcat" + icon_state = "scug_std" + +/datum/sprite_accessory/tails/lizard/slugcat/thick + name = "Slugcat Thick" + icon_state = "scug_thick" + +//body markings +/datum/sprite_accessory/lizard_markings/slugcat + icon = 'modular_doppler/customization/species/scugs/icons/slugcat_markings.dmi' + name = "Slugcat Underbelly" + icon_state = "scug_lbelly" + gender_specific = TRUE diff --git a/modular_doppler/customization/species/scugs/code/slugcat_bodyparts.dm b/modular_doppler/customization/species/scugs/code/slugcat_bodyparts.dm new file mode 100644 index 0000000000000..ebcfcf5c86eaf --- /dev/null +++ b/modular_doppler/customization/species/scugs/code/slugcat_bodyparts.dm @@ -0,0 +1,38 @@ +/obj/item/bodypart/head/slugcat + icon_greyscale = 'modular_doppler/customization/species/scugs/icons/bodyparts.dmi' + limb_id = SPECIES_SLUGCAT + is_dimorphic = FALSE + eyes_icon = 'modular_doppler/customization/species/scugs/icons/slugcat_eyes.dmi' + +/obj/item/bodypart/chest/slugcat + icon_greyscale = 'modular_doppler/customization/species/scugs/icons/bodyparts.dmi' + limb_id = SPECIES_SLUGCAT + is_dimorphic = TRUE + +/obj/item/bodypart/arm/left/lizard/slugcat + icon_greyscale = 'modular_doppler/customization/species/scugs/icons/bodyparts.dmi' + limb_id = SPECIES_SLUGCAT + +/obj/item/bodypart/arm/right/lizard/slugcat + icon_greyscale = 'modular_doppler/customization/species/scugs/icons/bodyparts.dmi' + limb_id = SPECIES_SLUGCAT + +/obj/item/bodypart/leg/left/digitigrade/slugcat + icon_greyscale = 'modular_doppler/customization/species/scugs/icons/bodyparts.dmi' + limb_id = BODYPART_ID_DIGITIGRADE + bodyshape = BODYSHAPE_HUMANOID | BODYSHAPE_DIGITIGRADE + +/obj/item/bodypart/leg/left/digitigrade/slugcat/update_limb(dropping_limb = FALSE, is_creating = FALSE) + . = ..() + if(limb_id == SPECIES_LIZARD) + limb_id = SPECIES_SLUGCAT + +/obj/item/bodypart/leg/right/digitigrade/slugcat + icon_greyscale = 'modular_doppler/customization/species/scugs/icons/bodyparts.dmi' + limb_id = BODYPART_ID_DIGITIGRADE + bodyshape = BODYSHAPE_HUMANOID | BODYSHAPE_DIGITIGRADE + +/obj/item/bodypart/leg/right/digitigrade/slugcat/update_limb(dropping_limb = FALSE, is_creating = FALSE) + . = ..() + if(limb_id == SPECIES_LIZARD) + limb_id = SPECIES_SLUGCAT diff --git a/modular_doppler/customization/species/scugs/code/slugcat_species.dm b/modular_doppler/customization/species/scugs/code/slugcat_species.dm new file mode 100644 index 0000000000000..18680d4f4babb --- /dev/null +++ b/modular_doppler/customization/species/scugs/code/slugcat_species.dm @@ -0,0 +1,124 @@ +/// Slugcat language holder - they are adept in understanding machines, though unable to speak the tongue themselves. +/datum/language_holder/slugcat + understood_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/movespeak = list(LANGUAGE_ATOM), + /datum/language/machine = list(LANGUAGE_ATOM), + /datum/language/drone = list(LANGUAGE_ATOM)) + spoken_languages = list(/datum/language/common = list(LANGUAGE_ATOM), + /datum/language/movespeak = list(LANGUAGE_ATOM)) + + + +/datum/species/slugcat + // The Slugcats of Talon III + name = "\improper Slugcat" + plural_form = "Slugcats" + id = SPECIES_SLUGCAT + inherent_traits = list( + TRAIT_MUTANT_COLORS, + TRAIT_TACKLING_TAILED_DEFENDER, + ) + inherent_biotypes = MOB_ORGANIC|MOB_HUMANOID + body_markings = list(/datum/bodypart_overlay/simple/body_marking/lizard = "None") + mutant_organs = list( + /obj/item/organ/external/horns = "Slugcat", + /obj/item/organ/external/frills = "None", + /obj/item/organ/external/snout = "Slugcat", + /obj/item/organ/external/tail/lizard = "Slugcat", + ) + payday_modifier = 1.0 + changesource_flags = MIRROR_BADMIN | WABBAJACK | MIRROR_PRIDE | MIRROR_MAGIC | RACE_SWAP | ERT_SPAWN | SLIME_EXTRACT + inert_mutation = /datum/mutation/human/mute + death_sound = 'modular_doppler/customization/species/scugs/sounds/scugdeath.ogg' + species_language_holder = /datum/language_holder/slugcat + digitigrade_customization = DIGITIGRADE_OPTIONAL + + bodypart_overrides = list( + BODY_ZONE_HEAD = /obj/item/bodypart/head/slugcat, + BODY_ZONE_CHEST = /obj/item/bodypart/chest/slugcat, + BODY_ZONE_L_ARM = /obj/item/bodypart/arm/left/lizard/slugcat, + BODY_ZONE_R_ARM = /obj/item/bodypart/arm/right/lizard/slugcat, + BODY_ZONE_L_LEG = /obj/item/bodypart/leg/left/digitigrade/slugcat, + BODY_ZONE_R_LEG = /obj/item/bodypart/leg/right/digitigrade/slugcat, + ) + +/// SOUNDS BREAKER +/datum/species/slugcat/get_scream_sound(mob/living/carbon/human/scug) + return pick( + 'modular_doppler/customization/species/scugs/sounds/scugscream_1.ogg', + ) + +/datum/species/slugcat/get_cough_sound(mob/living/carbon/human/scug) + if(scug.physique == FEMALE) + return pick( + 'sound/voice/human/female_cough1.ogg', + 'sound/voice/human/female_cough2.ogg', + 'sound/voice/human/female_cough3.ogg', + 'sound/voice/human/female_cough4.ogg', + 'sound/voice/human/female_cough5.ogg', + 'sound/voice/human/female_cough6.ogg', + ) + return pick( + 'sound/voice/human/male_cough1.ogg', + 'sound/voice/human/male_cough2.ogg', + 'sound/voice/human/male_cough3.ogg', + 'sound/voice/human/male_cough4.ogg', + 'sound/voice/human/male_cough5.ogg', + 'sound/voice/human/male_cough6.ogg', + ) + +/datum/species/slugcat/get_cry_sound(mob/living/carbon/human/scug) + if(scug.physique == FEMALE) + return pick( + 'sound/voice/human/female_cry1.ogg', + 'sound/voice/human/female_cry2.ogg', + ) + return pick( + 'sound/voice/human/male_cry1.ogg', + 'sound/voice/human/male_cry2.ogg', + 'sound/voice/human/male_cry3.ogg', + ) + +/datum/species/lizard/get_sneeze_sound(mob/living/carbon/human/scug) + if(scug.physique == FEMALE) + return 'sound/voice/human/female_sneeze1.ogg' + return 'sound/voice/human/male_sneeze1.ogg' + +/datum/species/lizard/get_laugh_sound(mob/living/carbon/human/scug) + return 'modular_doppler/customization/species/scugs/sounds/scuglaugh_1.ogg' + +/datum/species/lizard/get_sigh_sound(mob/living/carbon/human/scug) + if(scug.physique == FEMALE) + return 'sound/voice/human/female_sigh.ogg' + return 'sound/voice/human/male_sigh.ogg' + +/datum/species/lizard/get_sniff_sound(mob/living/carbon/human/scug) + if(scug.physique == FEMALE) + return 'sound/voice/human/female_sniff.ogg' + return 'sound/voice/human/male_sniff.ogg' +/// SOUNDS BREAKER END + +/datum/species/slugcat/get_species_description() + return "Nimble omnivores frequently cursed with chronic mutism and a natural aptitude for talking to machines, the Slugcats are a rare sight in systems far from their homeworld of Talon III. \ + Genetically engineered over untold cycles by the manipulation of their homeworld's Resonance field, Slugcats are crafty and intelligent, with incredible capabilities yet incredible fragility, \ + still carrying the scars of their homeworld's brush with death long, long ago." + +/datum/species/slugcat/get_species_lore() + return list( + "Nimble omnivores, both predator and prey, they served as the eyes and ears of the great mechanical minds, the Iterators, as they worked to uncover the secrets of the progenitor species who once ruled their homeworld. \ + Over time, Iterators began to see Slugcats as more than mere servants, treating them as friends and trusted allies despite their small stature. Gazes At Satellites, the leader \ + of the Primary Group began a research project in tandem with 6 Small Stones to try and further guide the growth & evolution of Slugcats.", + + "After many cycles of study & untold many, many more of natural adaptation, Slugcats have ascended to a more recognizable humanoid form, trading some of their nimbleness for craftiness \ + and intelligence to more than rival their most notable compeititors, the Scavs. When exploration probes from 4CA's Ministry of Contact entered orbit of Tallon III, \ + they were contacted by Gazes At Satellites, and soon Slugcats entered the collective consciousness of the galaxy...and due to their history, the baleful gaze of the AIA.", + + "Slugcats remain uncommonly seen beyond the Talon system, as their numbers remain few despite improvements that have been made to the safety and stability of the so-called \"Rain World's\" eco-system. \ + As such, those who do choose to venture beyond their world must do so with their Iterator's express approval and guidance, and typically seek employ and residence within outposts near the Talon system. \ + Slugcats who venture beyond Talon III typically retain the titles given to them by their tribe & Iterator, such as \"The Hunter\" or \"The Artificer\", although some take on the names given to them by their compatriots beyond the stars.", + + "Most of those who do venture beyond remain independents primarily tied to their homeworld, or within the service of the Fourth Celestial Alignment. The Iterators hold a steadfast neutral stance- \ + Talon III remains officially neutral & unaligned, which is how both they & the Slugcats prefer it. This has drawn intense ire from the AIA, whose attempts to convince Slugcats to join them have thus far failed; \ + the entire AIA playbook is based around collective trauma & hatred of uplifting factions...yet amongst the Slugcats' closest allies and confidantes are the Iterators, themselves such a faction. \ + As such, most Slugcats hold a strong dislike & distrust of the AIA, despite their official stance of neutrality.", + ) diff --git a/modular_doppler/customization/species/scugs/icons/bodyparts.dmi b/modular_doppler/customization/species/scugs/icons/bodyparts.dmi new file mode 100644 index 0000000000000..bd748505773f4 Binary files /dev/null and b/modular_doppler/customization/species/scugs/icons/bodyparts.dmi differ diff --git a/modular_doppler/customization/species/scugs/icons/slugcat_external.dmi b/modular_doppler/customization/species/scugs/icons/slugcat_external.dmi new file mode 100644 index 0000000000000..96fe02b359d76 Binary files /dev/null and b/modular_doppler/customization/species/scugs/icons/slugcat_external.dmi differ diff --git a/modular_doppler/customization/species/scugs/icons/slugcat_eyes.dmi b/modular_doppler/customization/species/scugs/icons/slugcat_eyes.dmi new file mode 100644 index 0000000000000..b99a0bbb550f1 Binary files /dev/null and b/modular_doppler/customization/species/scugs/icons/slugcat_eyes.dmi differ diff --git a/modular_doppler/customization/species/scugs/icons/slugcat_markings.dmi b/modular_doppler/customization/species/scugs/icons/slugcat_markings.dmi new file mode 100644 index 0000000000000..9784d69dd4e7b Binary files /dev/null and b/modular_doppler/customization/species/scugs/icons/slugcat_markings.dmi differ diff --git a/modular_doppler/customization/species/scugs/icons/slugcat_tails.dmi b/modular_doppler/customization/species/scugs/icons/slugcat_tails.dmi new file mode 100644 index 0000000000000..991bea5a1e771 Binary files /dev/null and b/modular_doppler/customization/species/scugs/icons/slugcat_tails.dmi differ diff --git a/modular_doppler/customization/species/scugs/sounds/scugdeath.ogg b/modular_doppler/customization/species/scugs/sounds/scugdeath.ogg new file mode 100644 index 0000000000000..a5b0e93fa8bb2 Binary files /dev/null and b/modular_doppler/customization/species/scugs/sounds/scugdeath.ogg differ diff --git a/modular_doppler/customization/species/scugs/sounds/scuglaugh_1.ogg b/modular_doppler/customization/species/scugs/sounds/scuglaugh_1.ogg new file mode 100644 index 0000000000000..33e49aceca961 Binary files /dev/null and b/modular_doppler/customization/species/scugs/sounds/scuglaugh_1.ogg differ diff --git a/modular_doppler/customization/species/scugs/sounds/scugscream_1.ogg b/modular_doppler/customization/species/scugs/sounds/scugscream_1.ogg new file mode 100644 index 0000000000000..a0f404457334b Binary files /dev/null and b/modular_doppler/customization/species/scugs/sounds/scugscream_1.ogg differ diff --git a/modular_doppler/enterprise_resource_planning/code/breasts.dm b/modular_doppler/enterprise_resource_planning/code/breasts.dm new file mode 100644 index 0000000000000..cf2a8ea4772cc --- /dev/null +++ b/modular_doppler/enterprise_resource_planning/code/breasts.dm @@ -0,0 +1,263 @@ +/datum/species/get_features() + var/list/features = ..() + + features += /datum/preference/choiced/breasts + + GLOB.features_by_species[type] = features + + return features + + + +/// SSAccessories setup +/datum/controller/subsystem/accessories + var/list/breasts_list + +/datum/controller/subsystem/accessories/setup_lists() + . = ..() + breasts_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/breasts)["default_sprites"] // FLAKY DEFINE: this should be using DEFAULT_SPRITE_LIST + //damnit SSAccessories + + + +/// The boobage in question +/obj/item/organ/external/breasts + name = "breasts" + desc = "Super-effective at deterring ice dragons." + icon_state = "snout" + + zone = BODY_ZONE_CHEST + slot = ORGAN_SLOT_EXTERNAL_BREASTS + + preference = "feature_breasts" + //external_bodyshapes = BODYSHAPE_SNOUTED + + dna_block = DNA_BREASTS_BLOCK + restyle_flags = EXTERNAL_RESTYLE_FLESH + + bodypart_overlay = /datum/bodypart_overlay/mutant/breasts + +/datum/bodypart_overlay/mutant/breasts + layers = EXTERNAL_ADJACENT | EXTERNAL_ADJACENT_2 | EXTERNAL_ADJACENT_3 | EXTERNAL_BEHIND | EXTERNAL_BEHIND_2 | EXTERNAL_BEHIND_3 + feature_key = "breasts" + +/datum/bodypart_overlay/mutant/breasts/can_draw_on_bodypart(mob/living/carbon/human/human) + if(human.undershirt != "Nude") + return FALSE + if((human.w_uniform && human.w_uniform.body_parts_covered & CHEST) || (human.wear_suit && human.wear_suit.body_parts_covered & CHEST)) + return FALSE + return TRUE + +/datum/bodypart_overlay/mutant/breasts/get_global_feature_list() + return SSaccessories.breasts_list + +/datum/bodypart_overlay/mutant/breasts/color_image(image/overlay, draw_layer, obj/item/bodypart/limb) + if(limb.owner == null) + return ..() + if(draw_layer == bitflag_to_layer(EXTERNAL_ADJACENT)) + overlay.color = limb.owner.dna.features["breasts_color_1"] + return overlay + else if(draw_layer == bitflag_to_layer(EXTERNAL_BEHIND)) + overlay.color = limb.owner.dna.features["breasts_color_1"] + return overlay + else if(draw_layer == bitflag_to_layer(EXTERNAL_ADJACENT_2)) + overlay.color = limb.owner.dna.features["breasts_color_2"] + return overlay + else if(draw_layer == bitflag_to_layer(EXTERNAL_BEHIND_2)) + overlay.color = limb.owner.dna.features["breasts_color_2"] + return overlay + else if(draw_layer == bitflag_to_layer(EXTERNAL_ADJACENT_3)) + overlay.color = limb.owner.dna.features["breasts_color_3"] + return overlay + else if(draw_layer == bitflag_to_layer(EXTERNAL_BEHIND_3)) + overlay.color = limb.owner.dna.features["breasts_color_3"] + return overlay + return ..() + +/datum/bodypart_overlay/mutant/breasts/mutant_bodyparts_layertext(layer) + switch(layer) + if(-(UNIFORM_LAYER + 0.09)) + return "ADJ" + if(-(UNIFORM_LAYER + 0.08)) + return "ADJ_2" + if(-(UNIFORM_LAYER + 0.07)) + return "ADJ_3" + return ..() + +/datum/bodypart_overlay/mutant/breasts/bitflag_to_layer(layer) + switch(layer) + if(EXTERNAL_ADJACENT) + return -(UNIFORM_LAYER + 0.09) + if(EXTERNAL_ADJACENT_2) + return -(UNIFORM_LAYER + 0.08) + if(EXTERNAL_ADJACENT_3) + return -(UNIFORM_LAYER + 0.07) + return ..() + + +/// Main breast prefs +//core toggle +/datum/preference/toggle/breasts + savefile_key = "has_breasts" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SECONDARY_FEATURES + priority = PREFERENCE_PRIORITY_DEFAULT + +/datum/preference/toggle/breasts/apply_to_human(mob/living/carbon/human/target, value) + if(value == FALSE) + //to_chat(world, "Begone, boobs.") + target.dna.features["breasts"] = "Bare" + +/datum/preference/toggle/breasts/create_default_value() + return FALSE + +/datum/species/regenerate_organs(mob/living/carbon/target, datum/species/old_species, replace_current = TRUE, list/excluded_zones, visual_only = FALSE) + . = ..() + /*to_chat(world, "Regenerating organs for [target], a [src], trying to add boobs") + for(var/feature in target.dna.features) + to_chat(world, "[target] has feature [feature]")*/ + if(target.dna.features["breasts"]) + //to_chat(world, "Boobs are in the features list, adding [target.dna.features["breasts"]]") + if(target.dna.features["breasts"] != "Bare") + //to_chat(world, "Boob type valid, trying to insert [target.dna.features["breasts"]]") + var/obj/item/organ/replacement = SSwardrobe.provide_type(/obj/item/organ/external/breasts) + //to_chat(world, "Inserted boobage exists: [replacement]") + //replacement.build_from_dna(target.dna, "breasts") //TODO: do we need to add this + replacement.Insert(target, special = TRUE, movement_flags = DELETE_IF_REPLACED) + //to_chat(world, "Boobs inserted, new state is [target.dna.features["breasts"]]") + return . + var/obj/item/organ/old_part = target.get_organ_slot(ORGAN_SLOT_EXTERNAL_BREASTS) + if(old_part) + old_part.Remove(target, special = TRUE, movement_flags = DELETE_IF_REPLACED) + old_part.moveToNullspace() + + + +//sprite selection +/datum/preference/choiced/breasts + savefile_key = "feature_breasts" + savefile_identifier = PREFERENCE_CHARACTER + //category = PREFERENCE_CATEGORY_FEATURES + category = PREFERENCE_CATEGORY_CLOTHING + main_feature_name = "Breasts" + should_generate_icons = TRUE + priority = PREFERENCE_PRIORITY_DEFAULT + can_randomize = FALSE + +/datum/preference/choiced/breasts/init_possible_values() + return assoc_to_keys_features(SSaccessories.breasts_list) + +/datum/preference/choiced/breasts/icon_for(value) + return generate_genitals_shot(SSaccessories.breasts_list[value], "breasts") + +/datum/preference/choiced/breasts/apply_to_human(mob/living/carbon/human/target, value) + //to_chat(world, "Applying [value] to [target]'s boobs...") + target.dna.features["breasts"] = value + //to_chat(world, "Applied!") + +/datum/preference/choiced/breasts/create_default_value() + return /datum/sprite_accessory/breasts/bare::name + +/datum/preference/choiced/breasts/is_accessible(datum/preferences/preferences) + . = ..() + var/has_breasts = preferences.read_preference(/datum/preference/toggle/breasts) + if(has_breasts == TRUE) + return TRUE + return FALSE + + + +/// Breast colors! +/datum/preference/tri_color/breasts_color + priority = PREFERENCE_PRIORITY_BODY_TYPE + savefile_key = "breasts_color" + savefile_identifier = PREFERENCE_CHARACTER + category = PREFERENCE_CATEGORY_SUPPLEMENTAL_FEATURES + can_randomize = FALSE + +/datum/preference/tri_color/breasts_color/create_default_value() + return list(sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]"), + sanitize_hexcolor("[pick("7F", "FF")][pick("7F", "FF")][pick("7F", "FF")]")) + +/datum/preference/tri_color/breasts_color/apply_to_human(mob/living/carbon/human/target, value) + target.dna.features["breasts_color_1"] = value[1] + target.dna.features["breasts_color_2"] = value[2] + target.dna.features["breasts_color_3"] = value[3] + +/datum/preference/tri_color/breasts_color/is_valid(value) + if (!..(value)) + return FALSE + + return TRUE + +// Gotta add to the selector too +/datum/preference/choiced/breasts/compile_constant_data() + var/list/data = ..() + + data[SUPPLEMENTAL_FEATURE_KEY] = /datum/preference/tri_color/breasts_color::savefile_key + + return data + + + +/// Breast sprite accessories +/datum/sprite_accessory/breasts + icon = 'modular_doppler/enterprise_resource_planning/icons/mob/breasts.dmi' + em_block = TRUE + +/datum/sprite_accessory/breasts/bare + name = "Bare" + icon_state = "bare" + +/datum/sprite_accessory/breasts/pair + name = "Pair 0" + icon_state = "pair_0" + +/datum/sprite_accessory/breasts/pair/size1 + name = "Pair 1" + icon_state = "pair_1" + +/datum/sprite_accessory/breasts/pair/size2 + name = "Pair 2" + icon_state = "pair_2" + +/datum/sprite_accessory/breasts/pair/size3 + name = "Pair 3" + icon_state = "pair_3" + +/datum/sprite_accessory/breasts/pair/size4 + name = "Pair 4" + icon_state = "pair_4" + +/datum/sprite_accessory/breasts/pair/size5 + name = "Pair 5" + icon_state = "pair_5" + +/datum/sprite_accessory/breasts/pair/size6 + name = "Pair 6" + icon_state = "pair_6" + +/datum/sprite_accessory/breasts/pair/size7 + name = "Pair 7" + icon_state = "pair_7" + +/datum/sprite_accessory/breasts/pair/size8 + name = "Pair 8" + icon_state = "pair_8" + +/datum/sprite_accessory/breasts/pair/size9 + name = "Pair 9" + icon_state = "pair_9" + +/datum/sprite_accessory/breasts/pair/size10 + name = "Pair 10" + icon_state = "pair_10" + +/datum/sprite_accessory/breasts/pair/size11 + name = "Pair 11" + icon_state = "pair_11" + +/datum/sprite_accessory/breasts/pair/size12 + name = "Pair 12" + icon_state = "pair_12" diff --git a/modular_doppler/enterprise_resource_planning/code/erp_prefs.dm b/modular_doppler/enterprise_resource_planning/code/erp_prefs.dm new file mode 100644 index 0000000000000..2643b2fd176bb --- /dev/null +++ b/modular_doppler/enterprise_resource_planning/code/erp_prefs.dm @@ -0,0 +1,18 @@ +/proc/generate_genitals_shot(datum/sprite_accessory/sprite_accessory, key) + var/icon/final_icon = icon('icons/mob/human/bodyparts_greyscale.dmi', "human_chest_f", SOUTH) + + if (!isnull(sprite_accessory)) + var/icon/accessory_icon = icon(sprite_accessory.icon, "m_[key]_[sprite_accessory.icon_state]_ADJ", SOUTH) + var/icon/accessory_icon_2 = icon(sprite_accessory.icon, "m_[key]_[sprite_accessory.icon_state]_ADJ_2", SOUTH) + accessory_icon_2.Blend(COLOR_RED, ICON_MULTIPLY) + var/icon/accessory_icon_3 = icon(sprite_accessory.icon, "m_[key]_[sprite_accessory.icon_state]_ADJ_3", SOUTH) + accessory_icon_3.Blend(COLOR_VIBRANT_LIME, ICON_MULTIPLY) + final_icon.Blend(accessory_icon, ICON_OVERLAY) + final_icon.Blend(accessory_icon_2, ICON_OVERLAY) + final_icon.Blend(accessory_icon_3, ICON_OVERLAY) + + final_icon.Crop(10, 8, 22, 23) + final_icon.Scale(26, 32) + final_icon.Crop(-2, 1, 29, 32) + + return final_icon diff --git a/modular_doppler/enterprise_resource_planning/icons/mob/breasts.dmi b/modular_doppler/enterprise_resource_planning/icons/mob/breasts.dmi new file mode 100644 index 0000000000000..b08334e0dbc98 Binary files /dev/null and b/modular_doppler/enterprise_resource_planning/icons/mob/breasts.dmi differ diff --git a/modular_doppler/enterprise_resource_planning/icons/organs.dmi b/modular_doppler/enterprise_resource_planning/icons/organs.dmi new file mode 100644 index 0000000000000..51dc172e8527c Binary files /dev/null and b/modular_doppler/enterprise_resource_planning/icons/organs.dmi differ diff --git a/modular_doppler/languages/language.dmi b/modular_doppler/languages/language.dmi index 5ece55bc6f3a8..4c42de2360185 100644 Binary files a/modular_doppler/languages/language.dmi and b/modular_doppler/languages/language.dmi differ diff --git a/modular_doppler/languages/language_datums.dm b/modular_doppler/languages/language_datums.dm index 5e3212ccfa52a..b4ca17cd7f092 100644 --- a/modular_doppler/languages/language_datums.dm +++ b/modular_doppler/languages/language_datums.dm @@ -1,3 +1,12 @@ +/obj/item/organ/internal/tongue/get_possible_languages() + var/list/langs = ..() + langs += /datum/language/yangyu + langs += /datum/language/movespeak + return langs + + + +/// ACTUAL LANGUAGES BEGIN HERE /datum/language/yangyu name = "Yangyu" desc = "Also popularly known as \"Konjin\", this language group formally regarded as Orbital Sino-Tibetan is a result of a genetic relationship between Chinese, Tibetan, Burmese, and other Human languages of similar characteristics that was first proposed in the early 19th century and is extremely popular even in the space age. Originating from Asia, this group of tongues is the second most spoken by Human and Human-derived populations since the birth of Sol Common - and was a primary contender to be the Sol Federation's official language. Many loanwords, idioms, and cultural relics of Japanese, Ryukyuan, Korean, and other societies have managed to persist within it, especially in the daily lives of speakers coming from Martian cities." @@ -20,3 +29,16 @@ default_priority = 94 default_name_syllable_min = 1 default_name_syllable_max = 2 + +/datum/language/movespeak + name = "Move-Speak" + desc = "A primarily nonverbal language comprised of body movements, gesticulation, and sign language, with only intermittent warbles & other vocalizations. It's almost completely incomprehensible without its somatic components." + key = "M" + flags = TONGUELESS_SPEECH + space_chance = 30 + syllables = list( + "wa", "wawa", "awa", "a" + ) + icon = 'modular_doppler/languages/language.dmi' + icon_state = "movepeak" + default_priority = 93 diff --git a/modular_doppler/pixel_shift/code/pixel_shift_component.dm b/modular_doppler/pixel_shift/code/pixel_shift_component.dm new file mode 100644 index 0000000000000..9603d3d5a20ea --- /dev/null +++ b/modular_doppler/pixel_shift/code/pixel_shift_component.dm @@ -0,0 +1,100 @@ +/datum/component/pixel_shift + dupe_mode = COMPONENT_DUPE_UNIQUE + /// Whether the mob is pixel shifted or not + var/is_shifted = FALSE + /// If we are in the shifting setting. + var/shifting = TRUE + /// Takes the four cardinal direction defines. Any atoms moving into this atom's tile will be allowed to from the added directions. + var/passthroughable = NONE + /// The maximum amount of pixels allowed to move in the turf. + var/maximum_pixel_shift = 16 + /// The amount of pixel shift required to make the parent passthroughable. + var/passable_shift_threshold = 8 + +/datum/component/pixel_shift/Initialize(...) + . = ..() + if(!isliving(parent)) + return COMPONENT_INCOMPATIBLE + +/datum/component/pixel_shift/RegisterWithParent() + RegisterSignal(parent, COMSIG_KB_MOB_PIXEL_SHIFT_DOWN, PROC_REF(pixel_shift_down)) + RegisterSignal(parent, COMSIG_KB_MOB_PIXEL_SHIFT_UP, PROC_REF(pixel_shift_up)) + RegisterSignals(parent, list(COMSIG_LIVING_RESET_PULL_OFFSETS, COMSIG_LIVING_SET_PULL_OFFSET, COMSIG_MOVABLE_MOVED), PROC_REF(unpixel_shift)) + RegisterSignal(parent, COMSIG_MOB_CLIENT_PRE_LIVING_MOVE, PROC_REF(pre_move_check)) + RegisterSignal(parent, COMSIG_LIVING_CAN_ALLOW_THROUGH, PROC_REF(check_passable)) + +/datum/component/pixel_shift/UnregisterFromParent() + UnregisterSignal(parent, COMSIG_KB_MOB_PIXEL_SHIFT_DOWN) + UnregisterSignal(parent, COMSIG_KB_MOB_PIXEL_SHIFT_UP) + UnregisterSignal(parent, COMSIG_LIVING_RESET_PULL_OFFSETS) + UnregisterSignal(parent, COMSIG_LIVING_SET_PULL_OFFSET) + UnregisterSignal(parent, COMSIG_MOVABLE_MOVED) + UnregisterSignal(parent, COMSIG_MOB_CLIENT_PRE_LIVING_MOVE) + UnregisterSignal(parent, COMSIG_LIVING_CAN_ALLOW_THROUGH) + +/// Overrides Move to Pixel Shift. +/datum/component/pixel_shift/proc/pre_move_check(mob/source, new_loc, direct) + SIGNAL_HANDLER + if(shifting) + pixel_shift(source, direct) + return COMSIG_MOB_CLIENT_BLOCK_PRE_LIVING_MOVE + +/// Checks if the parent is considered passthroughable from a direction. Projectiles will ignore the check and hit. +/datum/component/pixel_shift/proc/check_passable(mob/source, atom/movable/mover, border_dir) + SIGNAL_HANDLER + if(!isprojectile(mover) && !mover.throwing && passthroughable & border_dir) + return COMPONENT_LIVING_PASSABLE + +/// Activates Pixel Shift on Keybind down. Only Pixel Shift movement will be allowed. +/datum/component/pixel_shift/proc/pixel_shift_down() + SIGNAL_HANDLER + shifting = TRUE + return COMSIG_KB_ACTIVATED + +/// Disables Pixel Shift on Keybind up. Allows to Move. +/datum/component/pixel_shift/proc/pixel_shift_up() + SIGNAL_HANDLER + shifting = FALSE + +/// Sets parent pixel offsets to default and deletes the component. +/datum/component/pixel_shift/proc/unpixel_shift() + SIGNAL_HANDLER + passthroughable = NONE + if(is_shifted) + var/mob/living/owner = parent + owner.pixel_x = owner.body_position_pixel_x_offset + owner.base_pixel_x + owner.pixel_y = owner.body_position_pixel_y_offset + owner.base_pixel_y + qdel(src) + +/// In-turf pixel movement which can allow things to pass through if the threshold is met. +/datum/component/pixel_shift/proc/pixel_shift(mob/source, direct) + passthroughable = NONE + var/mob/living/owner = parent + switch(direct) + if(NORTH) + if(owner.pixel_y <= maximum_pixel_shift + owner.base_pixel_y) + owner.pixel_y++ + is_shifted = TRUE + if(EAST) + if(owner.pixel_x <= maximum_pixel_shift + owner.base_pixel_x) + owner.pixel_x++ + is_shifted = TRUE + if(SOUTH) + if(owner.pixel_y >= -maximum_pixel_shift + owner.base_pixel_y) + owner.pixel_y-- + is_shifted = TRUE + if(WEST) + if(owner.pixel_x >= -maximum_pixel_shift + owner.base_pixel_x) + owner.pixel_x-- + is_shifted = TRUE + + // Yes, I know this sets it to true for everything if more than one is matched. + // Movement doesn't check diagonals, and instead just checks EAST or WEST, depending on where you are for those. + if(owner.pixel_y > passable_shift_threshold) + passthroughable |= EAST | SOUTH | WEST + else if(owner.pixel_y < -passable_shift_threshold) + passthroughable |= NORTH | EAST | WEST + if(owner.pixel_x > passable_shift_threshold) + passthroughable |= NORTH | SOUTH | WEST + else if(owner.pixel_x < -passable_shift_threshold) + passthroughable |= NORTH | EAST | SOUTH diff --git a/modular_doppler/pixel_shift/code/pixel_shift_keybind.dm b/modular_doppler/pixel_shift/code/pixel_shift_keybind.dm new file mode 100644 index 0000000000000..2375b350a33c7 --- /dev/null +++ b/modular_doppler/pixel_shift/code/pixel_shift_keybind.dm @@ -0,0 +1,17 @@ +/datum/keybinding/mob/pixel_shift + hotkey_keys = list("B") + name = "pixel_shift" + full_name = "Pixel Shift" + description = "Shift your characters offset." + category = CATEGORY_MOVEMENT + keybind_signal = COMSIG_KB_MOB_PIXEL_SHIFT_DOWN + +/datum/keybinding/mob/pixel_shift/down(client/user) + . = ..() + if(.) + return + user.mob.add_pixel_shift_component() + +/datum/keybinding/mob/pixel_shift/up(client/user) + . = ..() + SEND_SIGNAL(user.mob, COMSIG_KB_MOB_PIXEL_SHIFT_UP) diff --git a/modular_doppler/pixel_shift/code/pixel_shift_mob.dm b/modular_doppler/pixel_shift/code/pixel_shift_mob.dm new file mode 100644 index 0000000000000..dbdd1e8d83f23 --- /dev/null +++ b/modular_doppler/pixel_shift/code/pixel_shift_mob.dm @@ -0,0 +1,6 @@ +/// Adds pixel_shift component on call. Default proc does nothing. +/mob/proc/add_pixel_shift_component() + return + +/mob/living/add_pixel_shift_component() + AddComponent(/datum/component/pixel_shift) diff --git a/modular_doppler/pixel_shift/living.dm b/modular_doppler/pixel_shift/living.dm new file mode 100644 index 0000000000000..04aea1e36421b --- /dev/null +++ b/modular_doppler/pixel_shift/living.dm @@ -0,0 +1,7 @@ +/mob/living/set_pull_offsets(mob/living/pull_target, grab_state) + . = ..() + SEND_SIGNAL(pull_target, COMSIG_LIVING_SET_PULL_OFFSET) + +/mob/living/reset_pull_offsets(mob/living/pull_target, override) + . = ..() + SEND_SIGNAL(pull_target, COMSIG_LIVING_RESET_PULL_OFFSETS) diff --git a/modular_doppler/pixel_shift/living_movement.dm b/modular_doppler/pixel_shift/living_movement.dm new file mode 100644 index 0000000000000..a2efb7be0ec51 --- /dev/null +++ b/modular_doppler/pixel_shift/living_movement.dm @@ -0,0 +1,4 @@ +/mob/living/CanAllowThrough(atom/movable/mover, border_dir) + if(SEND_SIGNAL(src, COMSIG_LIVING_CAN_ALLOW_THROUGH, mover, border_dir) & COMPONENT_LIVING_PASSABLE) + return TRUE + return ..() diff --git a/tgstation.dme b/tgstation.dme index 4d7d55957ae6f..5867da72dee06 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -19,6 +19,7 @@ #include "code\_compile_options.dm" #include "code\_experiments.dm" #include "code\world.dm" +#include "code\~doppler_earliest_defines.dm" #include "code\__DEFINES\__globals.dm" #include "code\__DEFINES\_atoms.dm" #include "code\__DEFINES\_bitfields.dm" @@ -395,6 +396,10 @@ #include "code\__DEFINES\traits\declarations.dm" #include "code\__DEFINES\traits\macros.dm" #include "code\__DEFINES\traits\sources.dm" +#include "code\__DEFINES\~doppler_defines\enterprise_resource_planning.dm" +#include "code\__DEFINES\~doppler_defines\keybindings.dm" +#include "code\__DEFINES\~doppler_defines\living.dm" +#include "code\__DEFINES\~doppler_defines\species.dm" #include "code\__HELPERS\_auxtools_api.dm" #include "code\__HELPERS\_dreamluau.dm" #include "code\__HELPERS\_lists.dm" @@ -6356,10 +6361,25 @@ #include "interface\fonts\spess_font.dm" #include "interface\fonts\tiny_unicode.dm" #include "interface\fonts\vcr_osd_mono.dm" +#include "modular_doppler\customization\code\accessory_overrides.dm" +#include "modular_doppler\customization\code\accessory_overrides_lizard.dm" +#include "modular_doppler\customization\code\accessory_overrides_moth.dm" +#include "modular_doppler\customization\code\bodypart_overrides.dm" +#include "modular_doppler\customization\code\custom_accessories.dm" +#include "modular_doppler\customization\code\dropdowns_to_icons.dm" +#include "modular_doppler\customization\code\tri_color_prefs.dm" +#include "modular_doppler\customization\code\tri_color_prefs_bespoke.dm" +#include "modular_doppler\customization\species\lizards\code\lizard_accessories.dm" +#include "modular_doppler\customization\species\lizards\code\lizard_species.dm" +#include "modular_doppler\customization\species\scugs\code\slugcat_accessories.dm" +#include "modular_doppler\customization\species\scugs\code\slugcat_bodyparts.dm" +#include "modular_doppler\customization\species\scugs\code\slugcat_species.dm" #include "modular_doppler\emotes\code\emotes.dm" #include "modular_doppler\emotes\code\added_emotes\animal_sounds.dm" #include "modular_doppler\emotes\code\added_emotes\human_things.dm" #include "modular_doppler\emotes\code\added_emotes\robot_sounds.dm" +#include "modular_doppler\enterprise_resource_planning\code\breasts.dm" +#include "modular_doppler\enterprise_resource_planning\code\erp_prefs.dm" #include "modular_doppler\face_mouse_preferences\code\face_mouse_pref.dm" #include "modular_doppler\icspawn\cconsultant_items.dm" #include "modular_doppler\icspawn\observer_spawn.dm" @@ -6370,6 +6390,11 @@ #include "modular_doppler\modular_cosmetics\code\suits\jacket.dm" #include "modular_doppler\modular_cosmetics\GAGS\greyscale_configs_neck.dm" #include "modular_doppler\modular_items\invisible_gear.dm" +#include "modular_doppler\pixel_shift\living.dm" +#include "modular_doppler\pixel_shift\living_movement.dm" +#include "modular_doppler\pixel_shift\code\pixel_shift_component.dm" +#include "modular_doppler\pixel_shift\code\pixel_shift_keybind.dm" +#include "modular_doppler\pixel_shift\code\pixel_shift_mob.dm" #include "modular_doppler\sprite_accessories\code\hair.dm" #include "modular_doppler\tableflip\tableflip.dm" #include "modular_doppler\wargaming\code\game_kit.dm" diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx index 452eb677519b1..1cf104c681512 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx @@ -95,6 +95,55 @@ export const FeatureColorInput = (props: FeatureValueProps) => { ); }; +/* DOPPLER SHIFT ADDITION BEGIN: tricolor inputs */ +export const FeatureTriColorInput = (props: FeatureValueProps) => { + const buttonFromValue = (index) => { + return ( + + + + ); + }; + return ( + + {buttonFromValue(0)} + {buttonFromValue(1)} + {buttonFromValue(2)} + + ); +}; +/* DOPPLER SHIFT ADDITION END */ + export type FeatureToggle = Feature; export const CheckboxInput = ( diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/dopplershift_preferences/erp_parts.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/dopplershift_preferences/erp_parts.tsx new file mode 100644 index 0000000000000..7ec2287ea9985 --- /dev/null +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/dopplershift_preferences/erp_parts.tsx @@ -0,0 +1,35 @@ +import { + CheckboxInput, + Feature, + FeatureToggle, + FeatureTriColorInput, +} from '../base'; + +export const penis_color: Feature = { + name: 'Penis Color', + component: FeatureTriColorInput, +}; + +export const testicles_color: Feature = { + name: 'Testicles Color', + component: FeatureTriColorInput, +}; + +export const vagina_color: Feature = { + name: 'Vagina Color', + component: FeatureTriColorInput, +}; + +export const has_breasts: FeatureToggle = { + name: 'Add Genitals: Breasts', + category: 'GAMEPLAY', + description: ` + When toggled, adds breasts to your character. + `, + component: CheckboxInput, +}; + +export const breasts_color: Feature = { + name: 'Breasts Color', + component: FeatureTriColorInput, +}; diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/dopplershift_preferences/mutant_newparts.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/dopplershift_preferences/mutant_newparts.tsx new file mode 100644 index 0000000000000..66aa6197aa49f --- /dev/null +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/dopplershift_preferences/mutant_newparts.tsx @@ -0,0 +1,26 @@ +import { Feature, FeatureTriColorInput } from '../base'; + +export const fluff_color: Feature = { + name: 'Fluff Color', + component: FeatureTriColorInput, +}; + +export const ipc_antenna_color: Feature = { + name: 'Synth Antenna Color', + component: FeatureTriColorInput, +}; + +export const taur_color: Feature = { + name: 'Taur Color', + component: FeatureTriColorInput, +}; + +export const xenodorsal_color: Feature = { + name: 'Xenodorsal Color', + component: FeatureTriColorInput, +}; + +export const xenohead_color: Feature = { + name: 'Xenohead Color', + component: FeatureTriColorInput, +}; diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/dopplershift_preferences/mutant_tricolors.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/dopplershift_preferences/mutant_tricolors.tsx new file mode 100644 index 0000000000000..36adc9e2f725c --- /dev/null +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/dopplershift_preferences/mutant_tricolors.tsx @@ -0,0 +1,188 @@ +import { + CheckboxInput, + Feature, + FeatureToggle, + FeatureTriColorInput, +} from '../base'; + +export const has_snout: FeatureToggle = { + name: 'Add Part: Snout', + category: 'GAMEPLAY', + description: ` + When toggled, adds a snout to your character. + `, + component: CheckboxInput, +}; + +export const snout_color: Feature = { + name: 'Snout Color', + component: FeatureTriColorInput, +}; + +export const has_horns: FeatureToggle = { + name: 'Add Part: Horns', + category: 'GAMEPLAY', + description: ` + When toggled, adds horns to your character. + `, + component: CheckboxInput, +}; + +export const horns_color: Feature = { + name: 'Horns Color', + component: FeatureTriColorInput, +}; + +export const has_frills: FeatureToggle = { + name: 'Add Part: Frills', + category: 'GAMEPLAY', + description: ` + When toggled, adds frills to your character. + `, + component: CheckboxInput, +}; + +export const frills_color: Feature = { + name: 'Frills Color', + component: FeatureTriColorInput, +}; + +export const has_tail: FeatureToggle = { + name: 'Add Part: Tail', + category: 'GAMEPLAY', + description: ` + When toggled, adds a tail to your character. + `, + component: CheckboxInput, +}; + +export const tail_color: Feature = { + name: 'Tail Color', + component: FeatureTriColorInput, +}; + +export const has_ears: FeatureToggle = { + name: 'Add Part: Snout', + category: 'GAMEPLAY', + description: ` + When toggled, adds fancy ears to your character. + `, + component: CheckboxInput, +}; + +export const ears_color: Feature = { + name: 'Ears Color', + component: FeatureTriColorInput, +}; + +export const has_spines: FeatureToggle = { + name: 'Add Part: Spines', + category: 'GAMEPLAY', + description: ` + When toggled, adds spines to your character. + `, + component: CheckboxInput, +}; + +export const spines_color: Feature = { + name: 'Spines Color', + component: FeatureTriColorInput, +}; + +export const has_caps: FeatureToggle = { + name: 'Add Part: Snout', + category: 'GAMEPLAY', + description: ` + When toggled, adds mushperson caps to your character. + `, + component: CheckboxInput, +}; + +export const caps_color: Feature = { + name: 'Caps Color', + component: FeatureTriColorInput, +}; + +export const has_markings: FeatureToggle = { + name: 'Add Part: Basic Markings', + category: 'GAMEPLAY', + description: ` + When toggled, adds basic bodymarkings to your character. + `, + component: CheckboxInput, +}; + +export const body_markings_color: Feature = { + name: 'Body Markings Color', + component: FeatureTriColorInput, +}; + +export const has_moth_markings: FeatureToggle = { + name: 'Add Part: Moth Markings', + category: 'GAMEPLAY', + description: ` + When toggled, adds moth-style bodymarkings to your character. + `, + component: CheckboxInput, +}; + +export const moth_markings_color: Feature = { + name: 'Moth Markings Color', + component: FeatureTriColorInput, +}; + +export const has_wings: FeatureToggle = { + name: 'Add Part: Wings', + category: 'GAMEPLAY', + description: ` + When toggled, adds wings to your character. + `, + component: CheckboxInput, +}; + +export const wings_color: Feature = { + name: 'Wings Color', + component: FeatureTriColorInput, +}; + +export const has_moth_wings: FeatureToggle = { + name: 'Add Part: Moth Wings', + category: 'GAMEPLAY', + description: ` + When toggled, adds matrix-colored moth wings to your character. + `, + component: CheckboxInput, +}; + +export const moth_wings_color: Feature = { + name: 'Moth Wings Color', + component: FeatureTriColorInput, +}; + +export const has_antennae: FeatureToggle = { + name: 'Add Part: Antennae', + category: 'GAMEPLAY', + description: ` + When toggled, adds antennae to your character. + `, + component: CheckboxInput, +}; + +export const antennae_color: Feature = { + name: 'Antennae Color', + component: FeatureTriColorInput, +}; + +export const has_moth_antennae: FeatureToggle = { + name: 'Add Part: Moth Antennae', + category: 'GAMEPLAY', + description: ` + When toggled, adds matrix-colored moth antennae to your character. + `, + component: CheckboxInput, +}; + +export const moth_antennae_color: Feature = { + name: 'Moth Antennae Color', + component: FeatureTriColorInput, +};