[MIRROR] more TG prefs (#11241)

Co-authored-by: Cameron Lennox <killer65311@gmail.com>
This commit is contained in:
CHOMPStation2StaffMirrorBot
2025-07-25 17:05:02 -07:00
committed by GitHub
parent dd34a22879
commit f51b2c3f7d
13 changed files with 167 additions and 51 deletions

View File

@@ -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

View File

@@ -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()

View File

@@ -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)

View File

@@ -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

View File

@@ -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

View File

@@ -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()

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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

View File

@@ -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)

View File

@@ -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 (
<Window width={300} height={isSubtle ? 220 : 190} theme="abductor">
<Window width={300} height={windowHeight} theme="abductor">
<Window.Content>
<Stack fill vertical g={0}>
{isSubtle && (
@@ -44,7 +52,7 @@ export const ShadekinConfig = (props) => {
</Stack.Item>
)}
<Stack.Item>
<Section fill title="Shadekin Settings">
<Section fill title="Light Settings">
<LabeledList>
<LabeledList.Item label="Flicker Count">
<Stack>
@@ -125,6 +133,26 @@ export const ShadekinConfig = (props) => {
</LabeledList>
</Section>
</Stack.Item>
{!!extended_kin && (
<Stack.Item>
<Section fill title="Misc Settings">
<LabeledList.Item label="Retreat on Death">
<Button.Checkbox
tooltip="Toggle if you wish to return to the Dark Retreat upon death!"
checked={!no_retreat}
onClick={() => act('toggle_retreat')}
/>
</LabeledList.Item>
<LabeledList.Item label="Nutrition Conversion">
<Button.Checkbox
tooltip="Toggle to have dark energy and nutrition being converted into each other when full!"
checked={nutrition_energy_conversion}
onClick={() => act('toggle_nutrition')}
/>
</LabeledList.Item>
</Section>
</Stack.Item>
)}
</Stack>
</Window.Content>
</Window>