diff --git a/code/datums/components/species/shadekin/helpers/comp_helpers.dm b/code/datums/components/species/shadekin/helpers/comp_helpers.dm index 59ab4b8d80..f007b99eec 100644 --- a/code/datums/components/species/shadekin/helpers/comp_helpers.dm +++ b/code/datums/components/species/shadekin/helpers/comp_helpers.dm @@ -113,9 +113,7 @@ ///Adds the shadekin abilities to the owner. /datum/component/shadekin/proc/add_shadekin_abilities() - if(!owner.ability_master || !istype(owner.ability_master, /obj/screen/movable/ability_master/shadekin)) - owner.ability_master = null - owner.ability_master = new /obj/screen/movable/ability_master/shadekin(owner) + create_shadekin_abilities() for(var/datum/power/shadekin/P in shadekin_ability_datums) if(!(P.verbpath in owner.verbs)) add_verb(owner, P.verbpath) @@ -127,6 +125,52 @@ arguments = list() ) + +///Builds and adds abilities to our owner. Should be used if you're adding new abilities +/datum/component/shadekin/proc/build_and_add_abilities() + clear_shadekin_abilities() + build_ability_datums() + add_shadekin_abilities() + + +///Clears the ability datums and rebuilds it. +/datum/component/shadekin/proc/build_ability_datums() + //generates powers and then adds them + for(var/datum/power in shadekin_ability_datums) + qdel(power) + shadekin_ability_datums = list() + for(var/power in shadekin_abilities) + var/datum/power/shadekin/SKP = new power(src) + shadekin_ability_datums.Add(SKP) + +///Gets rid of any old ability master if we have one and replaces it with a shadekin ability master. +/datum/component/shadekin/proc/create_shadekin_abilities() + if(!owner.ability_master) + owner.ability_master = new /obj/screen/movable/ability_master/shadekin(owner) + else if(!istype(owner.ability_master, /obj/screen/movable/ability_master/shadekin)) + qdel_null(owner.ability_master) + owner.ability_master = new /obj/screen/movable/ability_master/shadekin(owner) + +//Clears up our verbs. Used when rebuilding our verbs list.. +/datum/component/shadekin/proc/clear_shadekin_abilities() + for(var/datum/power/shadekin/P in shadekin_ability_datums) + if((P.verbpath in owner.verbs)) + remove_verb(owner, P.verbpath) + owner.ability_master.remove_shadekin_ability( + object_given = owner, + verb_given = P.verbpath, + arguments = list() + ) + +//Clears our abilities master and gives us a new, non-shadekin one. Used for destroy. +/datum/component/shadekin/proc/replace_shadekin_master() + if(!owner.ability_master) + owner.ability_master = new /obj/screen/movable/ability_master(owner) + else if(istype(owner.ability_master, /obj/screen/movable/ability_master/shadekin)) + qdel_null(owner.ability_master) + owner.ability_master = new /obj/screen/movable/ability_master(owner) + clear_shadekin_abilities() + //wait, it's all light? ///Allows setting the light and darkness gain. ///@Args: light_gain, dark_gain diff --git a/code/datums/components/species/shadekin/shadekin.dm b/code/datums/components/species/shadekin/shadekin.dm index d768c771e7..1e88e87751 100644 --- a/code/datums/components/species/shadekin/shadekin.dm +++ b/code/datums/components/species/shadekin/shadekin.dm @@ -46,6 +46,8 @@ var/in_dark_respite = FALSE var/manual_respite = FALSE var/respite_activating = FALSE + ///If we return to The Dark upon death or not. + var/no_retreat = FALSE //Dark Tunneling Vars (Unused on Virgo) ///If we have already made a dark tunnel @@ -93,17 +95,13 @@ if(!isliving(parent)) return COMPONENT_INCOMPATIBLE owner = parent - add_shadekin_abilities(owner) if(ishuman(owner)) RegisterSignal(owner, COMSIG_SHADEKIN_COMPONENT, PROC_REF(handle_comp)) //Happens every species tick. else RegisterSignal(owner, COMSIG_LIVING_LIFE, PROC_REF(handle_comp)) //Happens every life tick (mobs) //generates powers and then adds them - for(var/power in shadekin_abilities) - var/datum/power/shadekin/SKP = new power(src) - shadekin_ability_datums.Add(SKP) - add_shadekin_abilities() + build_and_add_abilities() handle_comp() //First hit is free! @@ -112,23 +110,21 @@ set_eye_energy() //Sets the energy values based on our eye color. //Misc stuff we need to do - if(extended_kin) - add_verb(owner, /mob/living/proc/nutrition_conversion_toggle) - add_verb(owner, /mob/living/proc/flicker_adjustment) + add_verb(owner, /mob/living/proc/shadekin_control_panel) /datum/component/shadekin/Destroy(force) if(ishuman(owner)) UnregisterSignal(owner, COMSIG_SHADEKIN_COMPONENT) else UnregisterSignal(owner, COMSIG_LIVING_LIFE) - if(extended_kin) - remove_verb(owner, /mob/living/proc/nutrition_conversion_toggle) - remove_verb(owner, /mob/living/proc/flicker_adjustment) + remove_verb(owner, /mob/living/proc/shadekin_control_panel) for(var/datum/power in shadekin_ability_datums) qdel(power) for(var/obj/effect/abstract/dark_maw/dm as anything in active_dark_maws) //if the component gets destroyed so does your precious maws if(!QDELETED(dm)) qdel(dm) + owner.shadekin_display.invisibility = INVISIBILITY_ABSTRACT //hide it + replace_shadekin_master() active_dark_maws.Cut() shadekin_abilities.Cut() shadekin_ability_datums.Cut() @@ -209,6 +205,9 @@ "flicker_color" = flicker_color, "flicker_break_chance" = flicker_break_chance, "flicker_distance" = flicker_distance, + "no_retreat" = no_retreat, + "nutrition_energy_conversion" = nutrition_energy_conversion, + "extended_kin" = extended_kin, ) return data @@ -250,27 +249,18 @@ flicker_distance = new_distance ui.user.write_preference_directly(/datum/preference/numeric/living/flicker_distance, new_distance) return TRUE + if("toggle_retreat") + var/new_retreat = !no_retreat + no_retreat = !no_retreat + ui.user.write_preference_directly(/datum/preference/toggle/living/dark_retreat_toggle, new_retreat) + if("toggle_nutrition") + var/new_retreat = !nutrition_energy_conversion + nutrition_energy_conversion = !nutrition_energy_conversion + ui.user.write_preference_directly(/datum/preference/toggle/living/shadekin_nutrition_conversion, new_retreat) -/mob/living/proc/nutrition_conversion_toggle() - set name = "Toggle Energy <-> Nutrition conversions" - set desc = "Toggle dark energy and nutrition being converted into each other when full" - set category = "Abilities.Shadekin" - - var/datum/component/shadekin/SK = get_shadekin_component() - if(!SK) - to_chat(src, span_warning("Only a shadekin can use that!")) - return FALSE - - if(SK.nutrition_energy_conversion) - to_chat(src, span_notice("Nutrition and dark energy conversions disabled.")) - SK.nutrition_energy_conversion = 0 - else - to_chat(src, span_notice("Nutrition and dark energy conversions enabled.")) - SK.nutrition_energy_conversion = 1 - -/mob/living/proc/flicker_adjustment() - set name = "Adjust Light Flicker" - set desc = "Allows you to adjust the settings of the light flicker when you phase in!" +/mob/living/proc/shadekin_control_panel() + set name = "Shadekin Control Panel" + set desc = "Allows you to adjust the settings of various shadekin settings!" set category = "Abilities.Shadekin" var/datum/component/shadekin/SK = get_shadekin_component() diff --git a/code/game/objects/structures/gargoyle.dm b/code/game/objects/structures/gargoyle.dm index 2d8310fd54..6713920800 100644 --- a/code/game/objects/structures/gargoyle.dm +++ b/code/game/objects/structures/gargoyle.dm @@ -20,7 +20,7 @@ var/adjective = "hardens" var/list/tail_lower_dirs = list(SOUTH, EAST, WEST) var/image/tail_image - var/tail_alt = TAIL_UPPER_LAYER + var/tail_layering = TAIL_UPPER_LAYER var/can_revert = TRUE var/was_rayed = FALSE @@ -62,7 +62,7 @@ tail_lower_dirs.Cut() else if(H.tail_style) tail_lower_dirs = H.tail_style.lower_layer_dirs.Copy() - tail_alt = H.tail_alt ? TAIL_UPPER_LAYER_HIGH : TAIL_UPPER_LAYER + tail_layering = H.tail_layering ? TAIL_UPPER_LAYER_HIGH : TAIL_UPPER_LAYER max_integrity = H.getMaxHealth() + 100 obj_integrity = H.health + 100 @@ -282,7 +282,7 @@ . = ..() if(. && tail_image) cut_overlay(tail_image) - tail_image.layer = BODY_LAYER + ((dir in tail_lower_dirs) ? TAIL_LOWER_LAYER : tail_alt) + tail_image.layer = BODY_LAYER + ((dir in tail_lower_dirs) ? TAIL_LOWER_LAYER : tail_layering) add_overlay(tail_image) /obj/structure/gargoyle/hitby(atom/movable/AM as mob|obj,var/speed = THROWFORCE_SPEED_DIVISOR) diff --git a/code/modules/client/preferences/types/character/general/03_body.dm b/code/modules/client/preferences/types/character/general/03_body.dm index 3b2a1adde0..21fad7af15 100644 --- a/code/modules/client/preferences/types/character/general/03_body.dm +++ b/code/modules/client/preferences/types/character/general/03_body.dm @@ -211,3 +211,18 @@ /datum/preference/numeric/human/ears_alpha/create_default_value() return 255 //no randomization here. + +///Tail style. +/datum/preference/numeric/human/tail_layering + category = PREFERENCE_CATEGORY_MANUALLY_RENDERED + savefile_identifier = PREFERENCE_CHARACTER + savefile_key = "tail_layering" + can_randomize = FALSE + minimum = TAIL_UPPER_LAYER + maximum = TAIL_UPPER_LAYER_HIGH + +/datum/preference/numeric/human/tail_layering/create_default_value() + return TAIL_UPPER_LAYER + +/datum/preference/numeric/human/tail_layering/apply_to_human(mob/living/carbon/human/target, value) + target.tail_layering = value diff --git a/code/modules/client/preferences/types/character/general/06_special.dm b/code/modules/client/preferences/types/character/general/06_special.dm index 65c7f30329..719bc435f5 100644 --- a/code/modules/client/preferences/types/character/general/06_special.dm +++ b/code/modules/client/preferences/types/character/general/06_special.dm @@ -59,3 +59,25 @@ var/datum/component/shadekin/our_SK = target.get_shadekin_component() if(our_SK) our_SK.flicker_distance = value + +/datum/preference/toggle/living/dark_retreat_toggle + category = PREFERENCE_CATEGORY_GAME_PREFERENCES + savefile_key = "DARK_RETREAT_TOGGLE" + default_value = TRUE + savefile_identifier = PREFERENCE_PLAYER + +/datum/preference/toggle/living/dark_retreat_toggle/apply_to_living(mob/living/target, value) + var/datum/component/shadekin/our_SK = target.get_shadekin_component() + if(our_SK) + our_SK.no_retreat = value + +/datum/preference/toggle/living/shadekin_nutrition_conversion + category = PREFERENCE_CATEGORY_GAME_PREFERENCES + savefile_key = "SHADEKIN_NUTRITION_CONVERSION" + default_value = FALSE + savefile_identifier = PREFERENCE_PLAYER + +/datum/preference/toggle/living/shadekin_nutrition_conversion/apply_to_living(mob/living/target, value) + var/datum/component/shadekin/our_SK = target.get_shadekin_component() + if(our_SK) + our_SK.nutrition_energy_conversion = value diff --git a/code/modules/mob/living/carbon/human/emote_vr.dm b/code/modules/mob/living/carbon/human/emote_vr.dm index f6257d9851..345aa2f4fc 100644 --- a/code/modules/mob/living/carbon/human/emote_vr.dm +++ b/code/modules/mob/living/carbon/human/emote_vr.dm @@ -49,18 +49,21 @@ /mob/living/carbon/human/verb/switch_tail_layer() set name = "Switch tail layer" set category = "IC.Game" - set desc = "Switch tail layer on top." + set desc = "Switch tail layer to show below/above/between clothing or other things such as wings!." var/input = tgui_input_list(src, "Select a tail layer.", "Set Tail Layer", list(SWITCH_TAIL_LAYER_UPPER, SWITCH_TAIL_LAYER_STANDARD, SWITCH_TAIL_LAYER_LOWER)) if(isnull(input)) return switch(input) if(SWITCH_TAIL_LAYER_UPPER) - tail_alt = TAIL_UPPER_LAYER_HIGH + tail_layering = input + write_preference_directly(/datum/preference/numeric/human/tail_layering, TAIL_UPPER_LAYER_HIGH) if(SWITCH_TAIL_LAYER_STANDARD) - tail_alt = TAIL_UPPER_LAYER + tail_layering = input + write_preference_directly(/datum/preference/numeric/human/tail_layering, TAIL_UPPER_LAYER) if(SWITCH_TAIL_LAYER_LOWER) - tail_alt = TAIL_UPPER_LAYER_LOW + tail_layering = input + write_preference_directly(/datum/preference/numeric/human/tail_layering, TAIL_UPPER_LAYER_LOW) update_tail_showing() diff --git a/code/modules/mob/living/carbon/human/human_defines_vr.dm b/code/modules/mob/living/carbon/human/human_defines_vr.dm index 08744e8a35..86a60ce231 100644 --- a/code/modules/mob/living/carbon/human/human_defines_vr.dm +++ b/code/modules/mob/living/carbon/human/human_defines_vr.dm @@ -11,6 +11,6 @@ var/markings_len = 0 //mostly an arbitrary number var/low_sorting_priority = FALSE - tail_alt = TAIL_UPPER_LAYER // not a toggle for humans but a pointer for what layer the tail should be when facing North/East/West + tail_layering = TAIL_UPPER_LAYER // not a toggle for humans but a pointer for what layer the tail should be when facing North/East/West var/list/body_writing // assoc list by BP_ key diff --git a/code/modules/mob/living/carbon/human/species/shadekin/shadekin.dm b/code/modules/mob/living/carbon/human/species/shadekin/shadekin.dm index 514722b2fc..8bca4d62b5 100644 --- a/code/modules/mob/living/carbon/human/species/shadekin/shadekin.dm +++ b/code/modules/mob/living/carbon/human/species/shadekin/shadekin.dm @@ -106,13 +106,13 @@ /datum/species/shadekin/handle_death(var/mob/living/carbon/human/H) var/special_handling = TRUE //varswitch for downstream //CHOMPEdit - Enable. H.clear_dark_maws() //clear dark maws on death or similar - if(!special_handling) + var/datum/component/shadekin/SK = H.get_shadekin_component() + if(!special_handling || (SK && SK.no_retreat)) spawn(1) for(var/obj/item/W in H) H.drop_from_inventory(W) qdel(H) else - var/datum/component/shadekin/SK = H.get_shadekin_component() if(!SK) return if(SK.respite_activating) diff --git a/code/modules/mob/living/carbon/human/species/shadekin/shadekin_hud.dm b/code/modules/mob/living/carbon/human/species/shadekin/shadekin_hud.dm index 9749228db1..e53a8a1c2c 100644 --- a/code/modules/mob/living/carbon/human/species/shadekin/shadekin_hud.dm +++ b/code/modules/mob/living/carbon/human/species/shadekin/shadekin_hud.dm @@ -46,3 +46,17 @@ ability_objects.Add(A) if(my_mob && my_mob.client) //If a shadekin is made (mannequins) prior to initialize being finished, my_mob won't be assigned and this will runtime. Mannequins need massive fixing because they shouldn't be getting all these special huds and overlays when they don't need them. toggle_open(2) //forces the icons to refresh on screen + + +/obj/screen/movable/ability_master/proc/remove_shadekin_ability(var/object_given, var/verb_given, var/arguments) + if(!object_given) + message_admins("ERROR: remove_shadekin_ability() was not given an object in its arguments.") + if(!verb_given) + message_admins("ERROR: remove_shadekin_ability() was not given a verb/proc in its arguments.") + var/obj/screen/ability/verb_based/shadekin/A = get_ability_by_proc_ref(verb_given) + if(!A) + return // We don't have the ability, so ignore it. + ability_objects.Remove(A) + qdel(A) + if(my_mob && my_mob.client) //If a shadekin is made (mannequins) prior to initialize being finished, my_mob won't be assigned and this will runtime. Mannequins need massive fixing because they shouldn't be getting all these special huds and overlays when they don't need them. + toggle_open(2) //forces the icons to refresh on screen diff --git a/code/modules/mob/living/carbon/human/update_icons.dm b/code/modules/mob/living/carbon/human/update_icons.dm index a6ef0283fa..d22c91fd1f 100644 --- a/code/modules/mob/living/carbon/human/update_icons.dm +++ b/code/modules/mob/living/carbon/human/update_icons.dm @@ -870,7 +870,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) //see UpdateDamageIcon() suit_sprite = INV_SUIT_DEF_ICON var/icon/c_mask = null - var/tail_is_rendered = overlays_standing[TAIL_LOWER_LAYER] || overlays_standing[tail_alt] + var/tail_is_rendered = overlays_standing[TAIL_LOWER_LAYER] || overlays_standing[tail_layering] var/valid_clip_mask = tail_style?.clip_mask if(tail_is_rendered && valid_clip_mask && !(istype(suit) && suit.taurized)) //Clip the lower half of the suit off using the tail's clip mask for taurs since taur bodies aren't hidden. @@ -1011,7 +1011,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) //see UpdateDamageIcon() if(src.tail_style && src.tail_style.clip_mask_state) tail_layer = TAIL_UPPER_LAYER // Use default, let clip mask handle everything if(tail_layer == TAIL_UPPER_LAYER) - tail_layer = tail_alt + tail_layer = tail_layering var/obj/item/organ/external/chest = organs_by_name[BP_TORSO] @@ -1058,7 +1058,7 @@ GLOBAL_LIST_EMPTY(damage_icon_parts) //see UpdateDamageIcon() if(src.tail_style && src.tail_style.clip_mask_state) tail_layer = TAIL_UPPER_LAYER // Use default, let clip mask handle everything if(tail_layer == TAIL_UPPER_LAYER) - tail_layer = tail_alt + tail_layer = tail_layering var/image/tail_overlay = overlays_standing[tail_layer] remove_layer(TAIL_UPPER_LAYER) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 0ffc996108..5dcaa13342 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -75,7 +75,7 @@ var/allow_self_surgery = FALSE // Used to determine if the mob can perform surgery on itself. - var/tail_alt = 0 + var/tail_layering = 0 var/flying = 0 // Allows flight var/inventory_panel_type = /datum/inventory_panel var/datum/inventory_panel/inventory_panel diff --git a/code/modules/mob/living/silicon/pai/pai_vr.dm b/code/modules/mob/living/silicon/pai/pai_vr.dm index ef1c35919f..14f15924bc 100644 --- a/code/modules/mob/living/silicon/pai/pai_vr.dm +++ b/code/modules/mob/living/silicon/pai/pai_vr.dm @@ -611,7 +611,7 @@ var/icon/new_holo = getCompoundIcon(dummy) - dummy.tail_alt = TRUE + dummy.tail_layering = TRUE dummy.set_dir(NORTH) var/icon/new_holo_north = getCompoundIcon(dummy) diff --git a/tgui/packages/tgui/interfaces/ShadekinConfig.tsx b/tgui/packages/tgui/interfaces/ShadekinConfig.tsx index a50931a6cf..42ddec609d 100644 --- a/tgui/packages/tgui/interfaces/ShadekinConfig.tsx +++ b/tgui/packages/tgui/interfaces/ShadekinConfig.tsx @@ -18,6 +18,9 @@ type Data = { flicker_color: string | null; flicker_break_chance: number; flicker_distance: number; + no_retreat: number; + extended_kin: number; + nutrition_energy_conversion: number; }; export const ShadekinConfig = (props) => { @@ -29,13 +32,18 @@ export const ShadekinConfig = (props) => { flicker_color, flicker_break_chance, flicker_distance, + no_retreat, + extended_kin, + nutrition_energy_conversion, } = data; const isSubtle = flicker_time < 5 || flicker_break_chance < 5 || flicker_distance < 5; + const windowHeight = (isSubtle ? 220 : 190) + (extended_kin ? 95 : 0); + return ( - + {isSubtle && ( @@ -44,7 +52,7 @@ export const ShadekinConfig = (props) => { )} -
+
@@ -125,6 +133,26 @@ export const ShadekinConfig = (props) => {
+ {!!extended_kin && ( + +
+ + act('toggle_retreat')} + /> + + + act('toggle_nutrition')} + /> + +
+
+ )}