Merge remote-tracking branch 'upstream/master' into kk-rings
@@ -99,37 +99,53 @@ var/SMALLSIZEBLOCK = 0
|
||||
#define DNA_UI_BEARD_STYLE 15
|
||||
#define DNA_UI_HAIR_STYLE 16
|
||||
#define DNA_UI_EAR_STYLE 17 // VOREStation snippet.
|
||||
#define DNA_UI_TAIL_STYLE 18
|
||||
#define DNA_UI_PLAYERSCALE 19
|
||||
#define DNA_UI_TAIL_R 20
|
||||
#define DNA_UI_TAIL_G 21
|
||||
#define DNA_UI_TAIL_B 22
|
||||
#define DNA_UI_TAIL2_R 23
|
||||
#define DNA_UI_TAIL2_G 24
|
||||
#define DNA_UI_TAIL2_B 25
|
||||
#define DNA_UI_TAIL3_R 26
|
||||
#define DNA_UI_TAIL3_G 27
|
||||
#define DNA_UI_TAIL3_B 28
|
||||
#define DNA_UI_EARS_R 29
|
||||
#define DNA_UI_EARS_G 30
|
||||
#define DNA_UI_EARS_B 31
|
||||
#define DNA_UI_EARS2_R 32
|
||||
#define DNA_UI_EARS2_G 33
|
||||
#define DNA_UI_EARS2_B 34
|
||||
#define DNA_UI_EARS3_R 35
|
||||
#define DNA_UI_EARS3_G 36
|
||||
#define DNA_UI_EARS3_B 37
|
||||
#define DNA_UI_WING_STYLE 38
|
||||
#define DNA_UI_WING_R 39
|
||||
#define DNA_UI_WING_G 40
|
||||
#define DNA_UI_WING_B 41
|
||||
#define DNA_UI_WING2_R 42
|
||||
#define DNA_UI_WING2_G 43
|
||||
#define DNA_UI_WING2_B 44
|
||||
#define DNA_UI_WING3_R 45
|
||||
#define DNA_UI_WING3_G 46
|
||||
#define DNA_UI_WING3_B 47 // VOREStation snippet end.
|
||||
#define DNA_UI_LENGTH 47 // VOREStation Edit - Needs to match the highest number above.
|
||||
#define DNA_UI_EAR_SECONDARY_STYLE 18 // VOREStation snippet.
|
||||
#define DNA_UI_TAIL_STYLE 19
|
||||
#define DNA_UI_PLAYERSCALE 20
|
||||
#define DNA_UI_TAIL_R 21
|
||||
#define DNA_UI_TAIL_G 22
|
||||
#define DNA_UI_TAIL_B 23
|
||||
#define DNA_UI_TAIL2_R 24
|
||||
#define DNA_UI_TAIL2_G 25
|
||||
#define DNA_UI_TAIL2_B 26
|
||||
#define DNA_UI_TAIL3_R 27
|
||||
#define DNA_UI_TAIL3_G 28
|
||||
#define DNA_UI_TAIL3_B 29
|
||||
|
||||
#define DNA_UI_EARS_R 30
|
||||
#define DNA_UI_EARS_G 31
|
||||
#define DNA_UI_EARS_B 32
|
||||
#define DNA_UI_EARS2_R 33
|
||||
#define DNA_UI_EARS2_G 34
|
||||
#define DNA_UI_EARS2_B 35
|
||||
#define DNA_UI_EARS3_R 36
|
||||
#define DNA_UI_EARS3_G 37
|
||||
#define DNA_UI_EARS3_B 38
|
||||
|
||||
#define DNA_UI_EARS_SECONDARY_START 39
|
||||
#define DNA_UI_EARS_SECONDARY_COLOR_CHANNEL_COUNT 3
|
||||
|
||||
#define DNA_UI_EARS_SECONDARY_R 39
|
||||
#define DNA_UI_EARS_SECONDARY_G 40
|
||||
#define DNA_UI_EARS_SECONDARY_B 41
|
||||
#define DNA_UI_EARS_SECONDARY2_R 42
|
||||
#define DNA_UI_EARS_SECONDARY2_G 43
|
||||
#define DNA_UI_EARS_SECONDARY2_B 44
|
||||
#define DNA_UI_EARS_SECONDARY3_R 45
|
||||
#define DNA_UI_EARS_SECONDARY3_G 46
|
||||
#define DNA_UI_EARS_SECONDARY3_B 47
|
||||
|
||||
#define DNA_UI_WING_STYLE 48
|
||||
#define DNA_UI_WING_R 49
|
||||
#define DNA_UI_WING_G 50
|
||||
#define DNA_UI_WING_B 51
|
||||
#define DNA_UI_WING2_R 52
|
||||
#define DNA_UI_WING2_G 53
|
||||
#define DNA_UI_WING2_B 54
|
||||
#define DNA_UI_WING3_R 55
|
||||
#define DNA_UI_WING3_G 56
|
||||
#define DNA_UI_WING3_B 57 // VOREStation snippet end.
|
||||
#define DNA_UI_LENGTH 57 // VOREStation Edit - Needs to match the highest number above.
|
||||
|
||||
#define DNA_SE_LENGTH 49 // VOREStation Edit (original was UI+11)
|
||||
|
||||
|
||||
@@ -139,6 +139,10 @@ var/global/list/datum/dna/gene/dna_genes[0]
|
||||
if(character.ear_style)
|
||||
ear_style = ear_styles_list.Find(character.ear_style.type)
|
||||
|
||||
var/ear_secondary_style = 0
|
||||
if(character.ear_secondary_style)
|
||||
ear_secondary_style = ear_styles_list.Find(character.ear_secondary_style.type)
|
||||
|
||||
// Demi Tails
|
||||
var/tail_style = 0
|
||||
if(character.tail_style)
|
||||
@@ -170,10 +174,11 @@ var/global/list/datum/dna/gene/dna_genes[0]
|
||||
src.digitigrade = character.digitigrade
|
||||
|
||||
// +1 to account for the none-of-the-above possibility
|
||||
SetUIValueRange(DNA_UI_EAR_STYLE, ear_style + 1, ear_styles_list.len + 1, 1)
|
||||
SetUIValueRange(DNA_UI_TAIL_STYLE, tail_style + 1, tail_styles_list.len + 1, 1)
|
||||
SetUIValueRange(DNA_UI_PLAYERSCALE, size_multiplier, player_sizes_list.len, 1)
|
||||
SetUIValueRange(DNA_UI_WING_STYLE, wing_style + 1, wing_styles_list.len + 1, 1)
|
||||
SetUIValueRange(DNA_UI_EAR_STYLE, ear_style + 1, ear_styles_list.len + 1, 1)
|
||||
SetUIValueRange(DNA_UI_EAR_SECONDARY_STYLE, ear_secondary_style + 1, ear_styles_list.len + 1, 1)
|
||||
SetUIValueRange(DNA_UI_TAIL_STYLE, tail_style + 1, tail_styles_list.len + 1, 1)
|
||||
SetUIValueRange(DNA_UI_PLAYERSCALE, size_multiplier, player_sizes_list.len, 1)
|
||||
SetUIValueRange(DNA_UI_WING_STYLE, wing_style + 1, wing_styles_list.len + 1, 1)
|
||||
|
||||
SetUIValueRange(DNA_UI_TAIL_R, character.r_tail, 255, 1)
|
||||
SetUIValueRange(DNA_UI_TAIL_G, character.g_tail, 255, 1)
|
||||
@@ -211,6 +216,15 @@ var/global/list/datum/dna/gene/dna_genes[0]
|
||||
SetUIValueRange(DNA_UI_EARS3_G, character.g_ears3, 255, 1)
|
||||
SetUIValueRange(DNA_UI_EARS3_B, character.b_ears3, 255, 1)
|
||||
|
||||
for(var/channel in 1 to DNA_UI_EARS_SECONDARY_COLOR_CHANNEL_COUNT)
|
||||
var/offset = DNA_UI_EARS_SECONDARY_START + (channel - 1) * 3
|
||||
var/list/read_rgb = ReadRGB(LAZYACCESS(character.ear_secondary_colors, channel) || "#ffffff")
|
||||
var/red = read_rgb[1]
|
||||
var/green = read_rgb[2]
|
||||
var/blue = read_rgb[3]
|
||||
SetUIValueRange(offset, red, 255, 1)
|
||||
SetUIValueRange(offset + 1, green, 255, 1)
|
||||
SetUIValueRange(offset + 2, blue, 255, 1)
|
||||
// VORE Station Edit End
|
||||
|
||||
SetUIValueRange(DNA_UI_HAIR_R, character.r_hair, 255, 1)
|
||||
|
||||
@@ -183,6 +183,11 @@
|
||||
H.ear_style = null
|
||||
else if((0 < ears) && (ears <= ear_styles_list.len))
|
||||
H.ear_style = ear_styles_list[ear_styles_list[ears]]
|
||||
var/ears_secondary = dna.GetUIValueRange(DNA_UI_EAR_SECONDARY_STYLE, ear_styles_list.len + 1) - 1
|
||||
if(ears_secondary < 1)
|
||||
H.ear_secondary_style = null
|
||||
else if((0 < ears_secondary) && (ears_secondary <= ear_styles_list.len))
|
||||
H.ear_secondary_style = ear_styles_list[ear_styles_list[ears_secondary]]
|
||||
|
||||
// Ear Color
|
||||
H.r_ears = dna.GetUIValueRange(DNA_UI_EARS_R, 255)
|
||||
@@ -195,6 +200,15 @@
|
||||
H.g_ears3 = dna.GetUIValueRange(DNA_UI_EARS3_G, 255)
|
||||
H.b_ears3 = dna.GetUIValueRange(DNA_UI_EARS3_B, 255)
|
||||
|
||||
LAZYINITLIST(H.ear_secondary_colors)
|
||||
H.ear_secondary_colors.len = max(length(H.ear_secondary_colors), DNA_UI_EARS_SECONDARY_COLOR_CHANNEL_COUNT)
|
||||
for(var/channel in 1 to DNA_UI_EARS_SECONDARY_COLOR_CHANNEL_COUNT)
|
||||
var/offset = DNA_UI_EARS_SECONDARY_START + (channel - 1) * 3
|
||||
H.ear_secondary_colors[channel] = rgb(
|
||||
dna.GetUIValueRange(offset, 255),
|
||||
dna.GetUIValueRange(offset + 1, 255),
|
||||
dna.GetUIValueRange(offset + 2, 255),
|
||||
)
|
||||
|
||||
//Tail
|
||||
var/tail = dna.GetUIValueRange(DNA_UI_TAIL_STYLE, tail_styles_list.len + 1) - 1
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
/obj/machinery/embedded_controller/Topic()
|
||||
. = ..()
|
||||
stack_trace("WARNING: Embedded controller [src] ([type]) had Topic() called unexpectedly. Please report this.")
|
||||
// stack_trace("WARNING: Embedded controller [src] ([type]) had Topic() called unexpectedly. Please report this.") // statpanel means that topic can always be called for clicking
|
||||
|
||||
/obj/machinery/embedded_controller/tgui_act(action, params)
|
||||
if(..())
|
||||
@@ -106,4 +106,4 @@
|
||||
/obj/machinery/embedded_controller/radio/proc/set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = radio_controller.add_object(src, frequency, radio_filter)
|
||||
radio_connection = radio_controller.add_object(src, frequency, radio_filter)
|
||||
|
||||
@@ -17,6 +17,15 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
var/r_ears3 = 30 // Ear tertiary color.
|
||||
var/g_ears3 = 30 // Ear tertiary color
|
||||
var/b_ears3 = 30 // Ear tertiary color
|
||||
|
||||
/// The typepath of the character's selected secondary ears.
|
||||
var/ear_secondary_style
|
||||
/// The color channels for the character's selected secondary ears
|
||||
///
|
||||
/// * This is a lazy list. Its length, when populated, should but cannot be assumed
|
||||
/// to be the number of color channels supported by the secondary ear style.
|
||||
var/list/ear_secondary_colors = list()
|
||||
|
||||
var/tail_style // Type of selected tail style
|
||||
var/r_tail = 30 // Tail/Taur color
|
||||
var/g_tail = 30 // Tail/Taur color
|
||||
@@ -27,6 +36,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
var/r_tail3 = 30 // For tertiary overlay.
|
||||
var/g_tail3 = 30 // For tertiary overlay.
|
||||
var/b_tail3 = 30 // For tertiary overlay.
|
||||
|
||||
var/wing_style // Type of selected wing style
|
||||
var/r_wing = 30 // Wing color
|
||||
var/g_wing = 30 // Wing color
|
||||
@@ -37,6 +47,7 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
var/r_wing3 = 30 // Wing tertiary color
|
||||
var/g_wing3 = 30 // Wing tertiary color
|
||||
var/b_wing3 = 30 // Wing tertiary color
|
||||
|
||||
var/datum/browser/markings_subwindow = null
|
||||
|
||||
// Sanitize ear/wing/tail styles
|
||||
@@ -59,6 +70,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
// Sanitize for non-existent keys.
|
||||
if(ear_style && !(ear_style in get_available_styles(global.ear_styles_list)))
|
||||
ear_style = null
|
||||
if(ear_secondary_style && !(ear_secondary_style in get_available_styles(global.ear_styles_list)))
|
||||
ear_secondary_style = null
|
||||
if(wing_style && !(wing_style in get_available_styles(global.wing_styles_list)))
|
||||
wing_style = null
|
||||
if(tail_style && !(tail_style in get_available_styles(global.tail_styles_list)))
|
||||
@@ -137,6 +150,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
pref.r_ears3 = save_data["r_ears3"]
|
||||
pref.g_ears3 = save_data["g_ears3"]
|
||||
pref.b_ears3 = save_data["b_ears3"]
|
||||
pref.ear_secondary_style = save_data["ear_secondary_style"]
|
||||
pref.ear_secondary_colors = save_data["ear_secondary_colors"]
|
||||
pref.tail_style = save_data["tail_style"]
|
||||
pref.r_tail = save_data["r_tail"]
|
||||
pref.g_tail = save_data["g_tail"]
|
||||
@@ -207,6 +222,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
save_data["r_ears3"] = pref.r_ears3
|
||||
save_data["g_ears3"] = pref.g_ears3
|
||||
save_data["b_ears3"] = pref.b_ears3
|
||||
save_data["ear_secondary_style"] = pref.ear_secondary_style
|
||||
save_data["ear_secondary_colors"] = pref.ear_secondary_colors
|
||||
save_data["tail_style"] = pref.tail_style
|
||||
save_data["r_tail"] = pref.r_tail
|
||||
save_data["g_tail"] = pref.g_tail
|
||||
@@ -274,6 +291,14 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
pref.r_ears3 = sanitize_integer(pref.r_ears3, 0, 255, initial(pref.r_ears3))
|
||||
pref.g_ears3 = sanitize_integer(pref.g_ears3, 0, 255, initial(pref.g_ears3))
|
||||
pref.b_ears3 = sanitize_integer(pref.b_ears3, 0, 255, initial(pref.b_ears3))
|
||||
|
||||
// sanitize secondary ears
|
||||
pref.ear_secondary_colors = SANITIZE_LIST(pref.ear_secondary_colors)
|
||||
if(length(pref.ear_secondary_colors) > length(GLOB.fancy_sprite_accessory_color_channel_names))
|
||||
pref.ear_secondary_colors.len = length(GLOB.fancy_sprite_accessory_color_channel_names)
|
||||
for(var/i in 1 to length(pref.ear_secondary_colors))
|
||||
pref.ear_secondary_colors[i] = sanitize_hexcolor(pref.ear_secondary_colors[i], "#ffffff")
|
||||
|
||||
pref.r_tail = sanitize_integer(pref.r_tail, 0, 255, initial(pref.r_tail))
|
||||
pref.g_tail = sanitize_integer(pref.g_tail, 0, 255, initial(pref.g_tail))
|
||||
pref.b_tail = sanitize_integer(pref.b_tail, 0, 255, initial(pref.b_tail))
|
||||
@@ -348,6 +373,10 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
character.b_ears3 = pref.b_ears3
|
||||
character.g_ears3 = pref.g_ears3
|
||||
|
||||
// apply secondary ears; sanitize again to prevent runtimes in rendering
|
||||
character.ear_secondary_style = ear_styles[pref.ear_secondary_style]
|
||||
character.ear_secondary_colors = SANITIZE_LIST(pref.ear_secondary_colors)
|
||||
|
||||
var/list/tail_styles = pref.get_available_styles(global.tail_styles_list)
|
||||
character.tail_style = tail_styles[pref.tail_style]
|
||||
character.r_tail = pref.r_tail
|
||||
@@ -623,6 +652,15 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
else
|
||||
. += " Style: <a href='?src=\ref[src];ear_style=1'>Select</a><br>"
|
||||
|
||||
var/datum/sprite_accessory/ears/ears_secondary = ear_styles[pref.ear_secondary_style]
|
||||
. += span_bold("Horns") + "<br>"
|
||||
if(istype(ears_secondary))
|
||||
. += " Style: <a href='?src=\ref[src];ear_secondary_style=1'>[ears_secondary.name]</a><br>"
|
||||
for(var/channel in 1 to min(ears_secondary.get_color_channel_count(), length(GLOB.fancy_sprite_accessory_color_channel_names)))
|
||||
. += "<a href='?src=\ref[src];ear_secondary_color=[channel]'>Change [GLOB.fancy_sprite_accessory_color_channel_names[channel]] Color</a> [color_square(hex = LAZYACCESS(pref.ear_secondary_colors, channel) || "#ffffff")]<br>"
|
||||
else
|
||||
. += " Style: <a href='?src=\ref[src];ear_secondary_style=1'>Select</a><br>"
|
||||
|
||||
var/list/tail_styles = pref.get_available_styles(global.tail_styles_list)
|
||||
var/datum/sprite_accessory/tail/tail = tail_styles[pref.tail_style]
|
||||
. += span_bold("Tail") + "<br>"
|
||||
@@ -1264,6 +1302,32 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O
|
||||
pref.b_ears3 = hex2num(copytext(new_earc3, 6, 8))
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
|
||||
else if(href_list["ear_secondary_style"])
|
||||
var/new_style = tgui_input_list(user, "Select an ear style for this character:", "Character Preference", pref.get_available_styles(global.ear_styles_list), pref.ear_secondary_style)
|
||||
if(!new_style)
|
||||
return TOPIC_NOACTION
|
||||
pref.ear_secondary_style = new_style
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
else if(href_list["ear_secondary_color"])
|
||||
var/channel = text2num(href_list["ear_secondary_color"])
|
||||
// very important sanity check; this makes sure someone can't crash the server by setting channel to some insanely high value
|
||||
if(channel > GLOB.fancy_sprite_accessory_color_channel_names.len)
|
||||
return TOPIC_NOACTION
|
||||
// this would say 'secondary ears' but you'd get 'choose your character's primary secondary ear colour' which sounds silly
|
||||
var/new_color = input(
|
||||
user,
|
||||
"Choose your character's [lowertext(GLOB.fancy_sprite_accessory_color_channel_names[channel])] ear colour:",
|
||||
"Secondary Ear Coloration",
|
||||
LAZYACCESS(pref.ear_secondary_colors, channel) || "#ffffff",
|
||||
) as color | null
|
||||
if(!new_color)
|
||||
return TOPIC_NOACTION
|
||||
// ensures color channel list is at least that long
|
||||
// the upper bound is to have a secondary safety check because list index set is a dangerous call
|
||||
pref.ear_secondary_colors.len = clamp(length(pref.ear_secondary_colors), channel, length(GLOB.fancy_sprite_accessory_color_channel_names))
|
||||
pref.ear_secondary_colors[channel] = new_color
|
||||
return TOPIC_REFRESH_UPDATE_PREVIEW
|
||||
|
||||
else if(href_list["tail_style"])
|
||||
var/new_tail_style = tgui_input_list(user, "Select a tail style for this character:", "Character Preference", pref.get_available_styles(global.tail_styles_list), pref.tail_style)
|
||||
if(new_tail_style)
|
||||
|
||||
@@ -568,4 +568,12 @@ Talon pin
|
||||
"Studded Belt" = /obj/item/clothing/accessory/belt/studded
|
||||
)
|
||||
gear_tweaks += new/datum/gear_tweak/path(wristband_lists)
|
||||
gear_tweaks += gear_tweak_free_color_choice
|
||||
gear_tweaks += gear_tweak_free_color_choice
|
||||
|
||||
/datum/gear/accessory/bunny_tail
|
||||
display_name = "bunny tail, colorable"
|
||||
path = /obj/item/clothing/accessory/bunny_tail
|
||||
|
||||
/datum/gear/accessory/bunny_tail/New()
|
||||
..()
|
||||
gear_tweaks += gear_tweak_free_color_choice
|
||||
|
||||
@@ -239,6 +239,10 @@
|
||||
display_name = "rabbit ears"
|
||||
path = /obj/item/clothing/head/rabbitears
|
||||
|
||||
/datum/gear/head/rabbit/New()
|
||||
..()
|
||||
gear_tweaks += gear_tweak_free_color_choice
|
||||
|
||||
/datum/gear/head/beanie
|
||||
display_name = "beanie"
|
||||
path = /obj/item/clothing/head/beanie
|
||||
|
||||
@@ -635,3 +635,22 @@
|
||||
"black tabard-dress"=/obj/item/clothing/under/dress/tabard/black
|
||||
)
|
||||
gear_tweaks += list(new/datum/gear_tweak/path(tabarddress))
|
||||
|
||||
//bunny suits
|
||||
|
||||
/datum/gear/uniform/bunnysuit
|
||||
display_name = "bunny suit selection, colorable"
|
||||
path = /obj/item/clothing/under/bunnysuit
|
||||
|
||||
/datum/gear/uniform/bunnysuit/New()
|
||||
..()
|
||||
var/list/bunnysuit = list(
|
||||
"bunnysuit"=/obj/item/clothing/under/bunnysuit,
|
||||
"maid bunnysuit"=/obj/item/clothing/under/bunnysuit_maid,
|
||||
"reverse bunnysuit"=/obj/item/clothing/under/reverse_bunnysuit,
|
||||
"maid reverse bunnysuit"=/obj/item/clothing/under/reverse_bunnysuit_maid,
|
||||
"reverse bunnysuit, no legs"=/obj/item/clothing/under/reverse_bunnytop,
|
||||
"maid reverse bunnysuit, no legs"=/obj/item/clothing/under/reverse_bunnytop_maid
|
||||
)
|
||||
gear_tweaks += list(new/datum/gear_tweak/path(bunnysuit))
|
||||
gear_tweaks += gear_tweak_free_color_choice
|
||||
|
||||
@@ -1033,3 +1033,13 @@
|
||||
desc = "A studded belt for holding your pants up and looking cool."
|
||||
icon_state = "belt_studded"
|
||||
item_state = "belt_studded"
|
||||
|
||||
/obj/item/clothing/accessory/bunny_tail
|
||||
name = "Bunny Tail"
|
||||
desc = "A little fluffy bunny tail to spice up your outfit."
|
||||
icon = 'icons/inventory/accessory/item.dmi'
|
||||
icon_override = 'icons/inventory/accessory/mob.dmi'
|
||||
icon_state = "bunny_tail"
|
||||
item_state = "bunny_tail"
|
||||
slot_flags = SLOT_TIE | SLOT_BELT
|
||||
slot = ACCESSORY_SLOT_DECOR
|
||||
|
||||
@@ -465,6 +465,7 @@
|
||||
|
||||
var/light_overlay = "helmet_light"
|
||||
var/image/helmet_light
|
||||
var/overhead = 0 //Used by spacesuit helmets
|
||||
|
||||
sprite_sheets = list(
|
||||
SPECIES_TESHARI = 'icons/inventory/head/mob_teshari.dmi',
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
ear_protection = 1
|
||||
drop_sound = 'sound/items/drop/helm.ogg'
|
||||
pickup_sound = 'sound/items/pickup/helm.ogg'
|
||||
overhead = TRUE
|
||||
|
||||
/obj/item/clothing/head/helmet/solgov
|
||||
name = "\improper Solar Confederate Government helmet"
|
||||
|
||||
@@ -31,6 +31,44 @@
|
||||
light_overlay = "helmet_light"
|
||||
light_range = 4
|
||||
|
||||
overhead = TRUE // prevents stacking helmets indefinitely
|
||||
var/obj/item/clothing/head/stored_under_head = null // under head
|
||||
var/mob/living/carbon/human/wearer = null // Used to restore our under when we're dropped
|
||||
|
||||
/obj/item/clothing/head/helmet/space/mob_can_equip(mob/user, slot, disable_warning = FALSE)
|
||||
var/mob/living/carbon/human/H = user
|
||||
if(H.head)
|
||||
stored_under_head = H.head
|
||||
if(!istype(stored_under_head))
|
||||
to_chat(user, "You are unable to wear \the [src] as \the [H.head] is in the way.")
|
||||
stored_under_head = null
|
||||
return 0
|
||||
if(stored_under_head.overhead)
|
||||
to_chat(user, "You are unable to wear \the [src] as \the [H.head] is in the way.")
|
||||
stored_under_head = null
|
||||
return 0
|
||||
H.drop_from_inventory(stored_under_head)
|
||||
stored_under_head.forceMove(src)
|
||||
|
||||
if(!..())
|
||||
if(stored_under_head)
|
||||
if(H.equip_to_slot_if_possible(stored_under_head, slot_head))
|
||||
stored_under_head = null
|
||||
return 0
|
||||
if(stored_under_head)
|
||||
to_chat(user, "You slip \the [src] on over \the [stored_under_head].")
|
||||
wearer = H
|
||||
return 1
|
||||
|
||||
/obj/item/clothing/head/helmet/space/dropped()
|
||||
..()
|
||||
var/mob/living/carbon/human/H = wearer
|
||||
if(stored_under_head)
|
||||
if(!H.equip_to_slot_if_possible(stored_under_head, slot_head))
|
||||
stored_under_head.forceMove(get_turf(src))
|
||||
src.stored_under_head = null
|
||||
wearer = null
|
||||
|
||||
/obj/item/clothing/head/helmet/space/Initialize()
|
||||
. = ..()
|
||||
if(camera_networks)
|
||||
|
||||
@@ -91,11 +91,11 @@
|
||||
boots.canremove = FALSE
|
||||
|
||||
if(helmet)
|
||||
if(H.head)
|
||||
to_chat(M, "You are unable to deploy your suit's helmet as \the [H.head] is in the way.")
|
||||
else if (H.equip_to_slot_if_possible(helmet, slot_head))
|
||||
if(H.equip_to_slot_if_possible(helmet, slot_head))
|
||||
to_chat(M, "Your suit's helmet deploys with a hiss.")
|
||||
helmet.canremove = FALSE
|
||||
else
|
||||
to_chat(M, "You are unable to deploy your suit's helmet[H.head ? " because [H.head] is in the way." : ""].")
|
||||
|
||||
if(tank)
|
||||
if(H.s_store) //In case someone finds a way.
|
||||
@@ -190,13 +190,12 @@
|
||||
helmet.forceMove(src)
|
||||
playsound(src.loc, 'sound/machines/click2.ogg', 75, 1)
|
||||
else
|
||||
if(H.head)
|
||||
to_chat(H, span_danger("You cannot deploy your helmet while wearing \the [H.head]."))
|
||||
return
|
||||
if(H.equip_to_slot_if_possible(helmet, slot_head))
|
||||
helmet.canremove = FALSE
|
||||
to_chat(H, span_info("You deploy your suit helmet, sealing you off from the world."))
|
||||
playsound(src.loc, 'sound/machines/click2.ogg', 75, 1)
|
||||
else
|
||||
to_chat(H, span_danger("You cannot deploy your helmet[H.head ? " while wearing \the [H.head]." : ""]"))
|
||||
|
||||
/obj/item/clothing/suit/space/void/AltClick(mob/living/user)
|
||||
eject_tank()
|
||||
|
||||
@@ -1723,3 +1723,36 @@
|
||||
name = "fiendish dress"
|
||||
desc = "A red and black dress befitting someone from the dark pits themselves… Or someone way too edgy."
|
||||
icon_state = "fienddress"
|
||||
|
||||
//bunny suits
|
||||
|
||||
/obj/item/clothing/under/bunnysuit_maid
|
||||
name = "bunny suit"
|
||||
desc = "A black and white bunny suit, extremely skimpy. Tails and ears sold seperately."
|
||||
icon_state = "bunnysuit_maid"
|
||||
|
||||
/obj/item/clothing/under/bunnysuit
|
||||
name = "bunny suit"
|
||||
desc = "A bunny suit, extremely skimpy. Tails and ears sold seperately."
|
||||
icon_state = "bunnysuit_colour"
|
||||
|
||||
|
||||
/obj/item/clothing/under/reverse_bunnysuit
|
||||
name = "reverse bunny suit"
|
||||
desc = "A reverse bunny suit, literally just covers everything except the bits you're supposed to. Tails and ears sold seperately."
|
||||
icon_state = "reverse_bunnysuit_colour"
|
||||
|
||||
/obj/item/clothing/under/reverse_bunnysuit_maid
|
||||
name = "reverse bunny suit"
|
||||
desc = "A maid themed reverse bunny suit, literally just covers everything except the bits you're supposed to. Tails and ears sold seperately."
|
||||
icon_state = "reverse_bunnysuit_maid"
|
||||
|
||||
/obj/item/clothing/under/reverse_bunnytop
|
||||
name = "reverse bunny suit"
|
||||
desc = "A reverse bunny suit, literally just covers everything except the bits you're supposed to. Tails and ears sold seperately."
|
||||
icon_state = "reverse_bunnytop_colour"
|
||||
|
||||
/obj/item/clothing/under/reverse_bunnytop_maid
|
||||
name = "reverse bunny suit"
|
||||
desc = "A maid themed reverse bunny suit, literally just covers everything except the bits you're supposed to. Tails and ears sold seperately."
|
||||
icon_state = "reverse_bunnytop_maid"
|
||||
|
||||
@@ -1540,6 +1540,14 @@
|
||||
/obj/item/clothing/accessory/maid_arms = 3,
|
||||
/obj/item/clothing/head/headband/maid/modern = 3,
|
||||
/obj/item/clothing/accessory/maidcorset = 3,
|
||||
/obj/item/clothing/under/bunnysuit = 3,
|
||||
/obj/item/clothing/under/bunnysuit_maid = 3,
|
||||
/obj/item/clothing/under/reverse_bunnysuit = 3,
|
||||
/obj/item/clothing/under/reverse_bunnysuit_maid = 3,
|
||||
/obj/item/clothing/under/reverse_bunnytop = 3,
|
||||
/obj/item/clothing/under/reverse_bunnytop_maid = 3,
|
||||
/obj/item/clothing/head/rabbitears = 3,
|
||||
/obj/item/clothing/accessory/bunny_tail = 3,
|
||||
/obj/item/clothing/suit/shrine_maiden = 3)
|
||||
prices = list(/obj/item/clothing/suit/storage/hooded/costume/carp = 200,
|
||||
/obj/item/clothing/suit/storage/hooded/costume/carp = 200,
|
||||
@@ -1617,6 +1625,14 @@
|
||||
/obj/item/clothing/accessory/maid_arms = 25,
|
||||
/obj/item/clothing/head/headband/maid/modern = 25,
|
||||
/obj/item/clothing/accessory/maidcorset = 25,
|
||||
/obj/item/clothing/under/bunnysuit = 50,
|
||||
/obj/item/clothing/under/bunnysuit_maid = 50,
|
||||
/obj/item/clothing/under/reverse_bunnysuit = 50,
|
||||
/obj/item/clothing/under/reverse_bunnysuit_maid = 50,
|
||||
/obj/item/clothing/under/reverse_bunnytop = 50,
|
||||
/obj/item/clothing/under/reverse_bunnytop_maid = 50,
|
||||
/obj/item/clothing/head/rabbitears = 25,
|
||||
/obj/item/clothing/accessory/bunny_tail = 25,
|
||||
/obj/item/clothing/suit/shrine_maiden = 200)
|
||||
premium = list(/obj/item/clothing/suit/imperium_monk = 3,
|
||||
/obj/item/clothing/suit/barding/agatha = 2,
|
||||
|
||||
@@ -31,6 +31,9 @@
|
||||
var/list/random_species_list = list(SPECIES_HUMAN,SPECIES_TAJ,SPECIES_UNATHI,SPECIES_SKRELL)
|
||||
var/list/tail_type = null
|
||||
var/list/ear_type = null
|
||||
/// list(name of ear, color of ear, color of ear, ...).
|
||||
/// Color is optional, each position after the name is a color channel from 1 to n.
|
||||
var/list/ear_secondary_type
|
||||
var/list/wing_type = null
|
||||
var/corpsesynthtype = 0 // 0 for organic, 1 for drone, 2 for posibrain
|
||||
var/corpsesynthbrand = "Unbranded"
|
||||
@@ -85,6 +88,12 @@
|
||||
M.g_ears3 = color_rgb_list[2]
|
||||
M.b_ears3 = color_rgb_list[3]
|
||||
M.update_hair()
|
||||
// handle secondary ears
|
||||
if(length(ear_secondary_type) && (ear_secondary_type[1] in global.ear_styles_list))
|
||||
M.ear_secondary_style = global.ear_styles_list[ear_secondary_type[1]]
|
||||
if(length(ear_secondary_type) > 1)
|
||||
M.ear_secondary_colors = ear_secondary_type.Copy(2, min(length(GLOB.fancy_sprite_accessory_color_channel_names), length(ear_secondary_type)) + 1)
|
||||
|
||||
if(wing_type && wing_type.len)
|
||||
if(wing_type[1] in wing_styles_list)
|
||||
M.wing_style = wing_styles_list[wing_type[1]]
|
||||
|
||||
@@ -135,6 +135,12 @@
|
||||
var/r_ears3 = 30 //Trust me, we could always use more colour. No japes.
|
||||
var/g_ears3 = 30
|
||||
var/b_ears3 = 30
|
||||
|
||||
/// secondary ears sprite accessory reference
|
||||
var/datum/sprite_accessory/ears/ear_secondary_style
|
||||
/// secondary ears color channels; can be null, or a list of #aabbcc hexcolors
|
||||
var/list/ear_secondary_colors
|
||||
|
||||
var/datum/sprite_accessory/tail/tail_style = null
|
||||
var/r_tail = 30
|
||||
var/g_tail = 30
|
||||
@@ -164,4 +170,4 @@
|
||||
|
||||
var/block_hud
|
||||
|
||||
var/phobias //For holding a list of phobias
|
||||
var/phobias //For holding a list of phobias
|
||||
|
||||
@@ -87,6 +87,7 @@
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_wings,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_tail,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_ears,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_secondary_ears,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_eye_colour,
|
||||
/mob/living/proc/set_size,
|
||||
// /mob/living/carbon/human/proc/lleill_contact,
|
||||
|
||||
@@ -82,6 +82,7 @@
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_wings,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_tail,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_ears,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_secondary_ears,
|
||||
/mob/living/proc/set_size,
|
||||
// /mob/living/carbon/human/proc/lleill_invisibility,
|
||||
// /mob/living/carbon/human/proc/lleill_transmute,
|
||||
|
||||
@@ -56,6 +56,37 @@
|
||||
|
||||
update_hair() //Includes Virgo ears
|
||||
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_secondary_ears()
|
||||
set name = "Select Secondary Ears"
|
||||
set category = "Abilities"
|
||||
|
||||
if(stat || world.time < last_special)
|
||||
return
|
||||
last_special = world.time + 1 SECONDS
|
||||
|
||||
// Construct the list of names allowed for this user.
|
||||
var/list/pretty_ear_styles = list("Normal" = null)
|
||||
for(var/path in ear_styles_list)
|
||||
var/datum/sprite_accessory/ears/instance = ear_styles_list[path]
|
||||
if((!instance.ckeys_allowed) || (ckey in instance.ckeys_allowed))
|
||||
pretty_ear_styles[instance.name] = path
|
||||
|
||||
// Handle style pick
|
||||
var/new_ear_style = tgui_input_list(src, "Pick some ears!", "Character Preference", pretty_ear_styles)
|
||||
if(!new_ear_style)
|
||||
return
|
||||
ear_secondary_style = ear_styles_list[pretty_ear_styles[new_ear_style]]
|
||||
|
||||
// Handle color picks
|
||||
var/list/new_colors = list()
|
||||
for(var/channel in 1 to ear_secondary_style.get_color_channel_count())
|
||||
var/channel_name = GLOB.fancy_sprite_accessory_color_channel_names[channel]
|
||||
var/default = LAZYACCESS(ear_secondary_colors, channel) || "#ffffff"
|
||||
var/new_color = input(usr, "Pick [channel_name]", "Ear Color ([channel_name])", default) as color | null
|
||||
new_colors += new_color || default
|
||||
|
||||
update_hair()
|
||||
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_tail()
|
||||
set name = "Select Tail"
|
||||
set category = "Abilities"
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_wings,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_tail,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_ears,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_secondary_ears,
|
||||
/mob/living/carbon/human/proc/prommie_blobform,
|
||||
/mob/living/proc/set_size,
|
||||
/mob/living/carbon/human/proc/promethean_select_opaqueness,
|
||||
|
||||
@@ -103,7 +103,8 @@
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_gender,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_wings,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_tail,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_ears
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_ears,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_secondary_ears,
|
||||
)
|
||||
|
||||
var/global/list/abilities = list()
|
||||
|
||||
@@ -45,6 +45,7 @@
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_wings,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_tail,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_ears,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_secondary_ears,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_eye_colour,
|
||||
/mob/living/proc/set_size
|
||||
)
|
||||
|
||||
@@ -37,6 +37,7 @@
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_wings,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_tail,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_ears,
|
||||
/mob/living/carbon/human/proc/shapeshifter_select_secondary_ears,
|
||||
/mob/living/proc/set_size,
|
||||
/mob/living/carbon/human/proc/regenerate,
|
||||
/mob/living/carbon/human/proc/promethean_select_opaqueness,
|
||||
|
||||
@@ -555,7 +555,8 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
|
||||
if(ears_s.Height() > face_standing.Height()) // Tol ears
|
||||
face_standing.Crop(1, 1, face_standing.Width(), ears_s.Height())
|
||||
face_standing.Blend(ears_s, ICON_OVERLAY)
|
||||
if(ear_style?.em_block)
|
||||
// todo: these should be considered separately, but it'd take a slight refactor to how sprite acc's are rendered (or atleast ears)
|
||||
if(ear_style?.em_block || ear_secondary_style?.em_block)
|
||||
em_block_ears = em_block_image_generic(image(ears_s))
|
||||
|
||||
var/image/semifinal = image(face_standing, layer = BODY_LAYER+HAIR_LAYER, "pixel_y" = head_organ.head_offset)
|
||||
@@ -1315,11 +1316,13 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
|
||||
/mob/living/carbon/human/proc/get_ears_overlay()
|
||||
//If you are FBP with ear style and didn't set a custom one
|
||||
var/datum/robolimb/model = isSynthetic()
|
||||
if(istype(model) && model.includes_ears && !ear_style)
|
||||
if(istype(model) && model.includes_ears && !ear_style && !ear_secondary_style)
|
||||
var/icon/ears_s = new/icon("icon" = synthetic.icon, "icon_state" = "ears")
|
||||
ears_s.Blend(rgb(src.r_ears, src.g_ears, src.b_ears), species.color_mult ? ICON_MULTIPLY : ICON_ADD)
|
||||
return ears_s
|
||||
|
||||
var/icon/rendered
|
||||
|
||||
if(ear_style && !(head && (head.flags_inv & BLOCKHEADHAIR)))
|
||||
var/icon/ears_s = new/icon("icon" = ear_style.icon, "icon_state" = ear_style.icon_state)
|
||||
if(ear_style.do_colouration)
|
||||
@@ -1334,9 +1337,29 @@ var/global/list/damage_icon_parts = list() //see UpdateDamageIcon()
|
||||
overlay.Blend(rgb(src.r_ears3, src.g_ears3, src.b_ears3), ear_style.color_blend_mode)
|
||||
ears_s.Blend(overlay, ICON_OVERLAY)
|
||||
qdel(overlay)
|
||||
return ears_s
|
||||
return null
|
||||
rendered = ears_s
|
||||
|
||||
// todo: this is utterly horrible but i don't think i should be violently refactoring sprite acc rendering in a feature PR ~silicons
|
||||
if(ear_secondary_style && !(head && (head.flags_inv & BLOCKHEADHAIR)))
|
||||
var/icon/ears_s = new/icon("icon" = ear_secondary_style.icon, "icon_state" = ear_secondary_style.icon_state)
|
||||
if(ear_secondary_style.do_colouration)
|
||||
ears_s.Blend(LAZYACCESS(ear_secondary_colors, 1), ear_secondary_style.color_blend_mode)
|
||||
if(ear_secondary_style.extra_overlay)
|
||||
var/icon/overlay = new/icon("icon" = ear_secondary_style.icon, "icon_state" = ear_secondary_style.extra_overlay)
|
||||
overlay.Blend(LAZYACCESS(ear_secondary_colors, 2), ear_secondary_style.color_blend_mode)
|
||||
ears_s.Blend(overlay, ICON_OVERLAY)
|
||||
qdel(overlay)
|
||||
if(ear_secondary_style.extra_overlay2) //MORE COLOURS IS BETTERER
|
||||
var/icon/overlay = new/icon("icon" = ear_secondary_style.icon, "icon_state" = ear_secondary_style.extra_overlay2)
|
||||
overlay.Blend(LAZYACCESS(ear_secondary_colors, 3), ear_secondary_style.color_blend_mode)
|
||||
ears_s.Blend(overlay, ICON_OVERLAY)
|
||||
qdel(overlay)
|
||||
if(!rendered)
|
||||
rendered = ears_s
|
||||
else
|
||||
rendered.Blend(ears_s, ICON_OVERLAY)
|
||||
|
||||
return rendered
|
||||
|
||||
/mob/living/carbon/human/proc/get_tail_image()
|
||||
//If you are FBP with tail style and didn't set a custom one
|
||||
|
||||
@@ -375,7 +375,7 @@
|
||||
|
||||
/mob/living/silicon/robot/handle_light()
|
||||
if(lights_on)
|
||||
set_light(integrated_light_power, 1, "#FFFFFF")
|
||||
set_light(integrated_light_power, 1, robot_light_col)
|
||||
return TRUE
|
||||
else
|
||||
. = ..()
|
||||
|
||||
@@ -15,6 +15,7 @@
|
||||
blocks_emissive = EMISSIVE_BLOCK_UNIQUE
|
||||
|
||||
var/lights_on = 0 // Is our integrated light on?
|
||||
var/robot_light_col = "#FFFFFF"
|
||||
var/used_power_this_tick = 0
|
||||
var/sight_mode = 0
|
||||
var/custom_name = ""
|
||||
|
||||
@@ -62,6 +62,7 @@
|
||||
data["max_charge"] = R.cell?.maxcharge
|
||||
data["health"] = R.health
|
||||
data["max_health"] = R.getMaxHealth()
|
||||
data["light_color"] = R.robot_light_col
|
||||
|
||||
data["weapon_lock"] = R.weapon_lock
|
||||
|
||||
@@ -111,6 +112,11 @@
|
||||
var/mob/living/silicon/robot/R = host
|
||||
|
||||
switch(action)
|
||||
if("set_light_col")
|
||||
var/new_color = params["value"]
|
||||
if(findtext(new_color, GLOB.is_color))
|
||||
R.robot_light_col = new_color
|
||||
. = TRUE
|
||||
if("select_module")
|
||||
R.pick_module()
|
||||
. = TRUE
|
||||
|
||||
@@ -534,8 +534,7 @@
|
||||
onclose(usr, "[name]")
|
||||
if(href_list["flavor_change"])
|
||||
update_flavor_text()
|
||||
// ..()
|
||||
return
|
||||
return ..()
|
||||
|
||||
|
||||
/mob/proc/pull_damage()
|
||||
|
||||
@@ -17,6 +17,14 @@
|
||||
conversion in savefile.dm
|
||||
*/
|
||||
|
||||
/**
|
||||
* Color channel names; this is used in things like character setup, editors, etc.
|
||||
*
|
||||
* * The length of this is also used to sanitize color channel list lengths. This should never be longer than the
|
||||
* maximum number of color channels possible across all sprite accessories.
|
||||
*/
|
||||
GLOBAL_LIST_INIT(fancy_sprite_accessory_color_channel_names, list("Primary", "Secondary", "Tertiary", "Quaternary"))
|
||||
|
||||
/datum/sprite_accessory
|
||||
|
||||
var/icon // the icon file the accessory is located in
|
||||
@@ -44,6 +52,12 @@
|
||||
|
||||
var/list/hide_body_parts = list() //Uses organ tag defines. Bodyparts in this list do not have their icons rendered, allowing for more spriter freedom when doing taur/digitigrade stuff.
|
||||
|
||||
/**
|
||||
* Gets the number of color channels we have.
|
||||
*/
|
||||
/datum/sprite_accessory/proc/get_color_channel_count()
|
||||
return do_colouration ? 1 : 0
|
||||
|
||||
/*
|
||||
////////////////////////////
|
||||
/ =--------------------= /
|
||||
|
||||
@@ -18,6 +18,18 @@
|
||||
|
||||
//species_allowed = list(SPECIES_EVENT1, SPECIES_EVENT2, SPECIES_EVENT3) //Removing Polaris whitelits, ones we need are defined in our files
|
||||
|
||||
/**
|
||||
* Gets the number of color channels we have.
|
||||
*/
|
||||
/datum/sprite_accessory/ears/get_color_channel_count()
|
||||
if(!do_colouration)
|
||||
return 0
|
||||
. = 1
|
||||
if(extra_overlay)
|
||||
. += 1
|
||||
if(extra_overlay2)
|
||||
. += 1
|
||||
|
||||
/datum/sprite_accessory/ears/shadekin
|
||||
name = "Shadekin Ears, colorable"
|
||||
desc = ""
|
||||
@@ -527,4 +539,4 @@
|
||||
do_colouration = 1
|
||||
color_blend_mode = ICON_MULTIPLY
|
||||
extra_overlay = "zorgoia_inner"
|
||||
extra_overlay2 = "zorgoia_tips"
|
||||
extra_overlay2 = "zorgoia_tips"
|
||||
|
||||
@@ -203,7 +203,7 @@
|
||||
var/drug_strength = 20
|
||||
M.druggy = max(M.druggy, drug_strength)
|
||||
|
||||
/datum/reagent/drugs/bliss/overdose(var/mob/living/M as mob)
|
||||
/datum/reagent/drugs/rainbow_toxin/overdose(var/mob/living/M as mob)
|
||||
if(prob_proc == TRUE && prob(20))
|
||||
M.hallucination = max(M.hallucination, 5)
|
||||
prob_proc = FALSE
|
||||
|
||||
@@ -148,6 +148,17 @@
|
||||
temp["colorHref2"] = "ear_color2"
|
||||
styles["Ears"] = temp
|
||||
|
||||
temp = list("styleHref" = "ear_style", "style" = "Normal")
|
||||
if(mannequin.ear_secondary_style)
|
||||
temp["style"] = mannequin.ear_secondary_style.name
|
||||
if(length(mannequin.ear_secondary_colors) >= 1)
|
||||
temp["color"] = mannequin.ear_secondary_colors[1]
|
||||
temp["colorHref"] = list("act" = "ear_secondary_color", "channel" = 1)
|
||||
if(length(mannequin.ear_secondary_colors) >= 2)
|
||||
temp["color"] = mannequin.ear_secondary_colors[2]
|
||||
temp["colorHref"] = list("act" = "ear_secondary_color", "channel" = 2)
|
||||
styles["Horns"] = temp
|
||||
|
||||
temp = list("styleHref" = "tail_style", "style" = "Normal")
|
||||
if(mannequin.tail_style)
|
||||
temp["style"] = mannequin.tail_style.name
|
||||
@@ -419,7 +430,15 @@
|
||||
|
||||
var/href_list = list()
|
||||
href_list["src"] = "\ref[src]"
|
||||
href_list["[params["target_href"]]"] = params["target_value"]
|
||||
var/list/target_href_maybe = params["target_href"]
|
||||
// convert list-form inputs as needed
|
||||
if(islist(target_href_maybe))
|
||||
href_list[target_href_maybe["act"]] = TRUE
|
||||
for(var/key in target_href_maybe["params"])
|
||||
var/val = target_href_maybe["params"][key]
|
||||
href_list[key] = "[val]"
|
||||
else
|
||||
href_list[target_href_maybe] = params["target_value"]
|
||||
var/datum/category_item/player_setup_item/to_use = (params["target_href"] in use_different_category) ? use_different_category[params["target_href"]] : B
|
||||
|
||||
var/action = 0
|
||||
|
||||
@@ -191,6 +191,22 @@
|
||||
update_dna()
|
||||
changed_hook(APPEARANCECHANGER_CHANGED_HAIRSTYLE)
|
||||
return TRUE
|
||||
if("ear_secondary")
|
||||
if(can_change(APPEARANCE_ALL_HAIR))
|
||||
var/datum/sprite_accessory/ears/instance = locate(params["ref"])
|
||||
if(params["clear"])
|
||||
instance = null
|
||||
if(!istype(instance) && !params["clear"])
|
||||
return FALSE
|
||||
target.ear_secondary_style = instance
|
||||
if(!islist(target.ear_secondary_colors))
|
||||
target.ear_secondary_colors = list()
|
||||
if(length(target.ear_secondary_colors) < instance.get_color_channel_count())
|
||||
target.ear_secondary_colors.len = instance.get_color_channel_count()
|
||||
target.update_hair()
|
||||
update_dna()
|
||||
changed_hook(APPEARANCECHANGER_CHANGED_HAIRSTYLE)
|
||||
return TRUE
|
||||
if("ears_color")
|
||||
if(can_change(APPEARANCE_HAIR_COLOR))
|
||||
var/new_hair = input(usr, "Please select ear color.", "Ear Color", rgb(target.r_ears, target.g_ears, target.b_ears)) as color|null
|
||||
@@ -213,6 +229,19 @@
|
||||
target.update_hair()
|
||||
changed_hook(APPEARANCECHANGER_CHANGED_HAIRCOLOR)
|
||||
return 1
|
||||
if("ears_secondary_color")
|
||||
if(can_change(APPEARANCE_HAIR_COLOR))
|
||||
var/channel = params["channel"]
|
||||
if(channel > length(target.ear_secondary_colors))
|
||||
return TRUE
|
||||
var/existing = LAZYACCESS(target.ear_secondary_colors, channel) || "#ffffff"
|
||||
var/new_color = input(usr, "Please select ear color.", "2nd Ear Color", existing) as color|null
|
||||
if(new_color && can_still_topic(usr, state))
|
||||
target.ear_secondary_colors[channel] = new_color
|
||||
update_dna()
|
||||
target.update_hair()
|
||||
changed_hook(APPEARANCECHANGER_CHANGED_HAIRCOLOR)
|
||||
return TRUE
|
||||
if("tail")
|
||||
if(can_change(APPEARANCE_ALL_HAIR))
|
||||
var/datum/sprite_accessory/tail/instance = locate(params["ref"])
|
||||
@@ -406,6 +435,7 @@
|
||||
|
||||
// VOREStation Add - Ears/Tails/Wings
|
||||
data["ear_style"] = target.ear_style
|
||||
data["ear_secondary_style"] = target.ear_secondary_style?.name
|
||||
data["tail_style"] = target.tail_style
|
||||
data["wing_style"] = target.wing_style
|
||||
var/list/markings_data[0]
|
||||
@@ -434,6 +464,12 @@
|
||||
// VOREStation Add - Ears/Tails/Wings
|
||||
data["ears_color"] = rgb(target.r_ears, target.g_ears, target.b_ears)
|
||||
data["ears2_color"] = rgb(target.r_ears2, target.g_ears2, target.b_ears2)
|
||||
|
||||
// secondary ear colors
|
||||
var/list/ear_secondary_color_channels = target.ear_secondary_colors || list()
|
||||
ear_secondary_color_channels.len = target.ear_secondary_style?.get_color_channel_count() || 0
|
||||
data["ear_secondary_colors"] = ear_secondary_color_channels
|
||||
|
||||
data["tail_color"] = rgb(target.r_tail, target.g_tail, target.b_tail)
|
||||
data["tail2_color"] = rgb(target.r_tail2, target.g_tail2, target.b_tail2)
|
||||
data["wing_color"] = rgb(target.r_wing, target.g_wing, target.b_wing)
|
||||
|
||||
@@ -415,7 +415,9 @@ var/global/list/belly_colorable_only_fullscreens = list("a_synth_flesh_mono",
|
||||
host.vore_selected = NB
|
||||
unsaved_changes = TRUE
|
||||
return TRUE
|
||||
|
||||
if("importpanel")
|
||||
import_belly(host)
|
||||
return TRUE
|
||||
if("bellypick")
|
||||
host.vore_selected = locate(params["bellypick"])
|
||||
return TRUE
|
||||
|
||||
@@ -668,7 +668,9 @@
|
||||
|
||||
/obj/item/clothing/head/fluff/avida/mob_can_equip(var/mob/living/carbon/human/H, slot, disable_warning = 0)
|
||||
if(..())
|
||||
if(H.ear_style && (H.ear_style.name == "Bnnuy Ears" || H.ear_style.name == "Bnnuy Ears 2")) //check if wearer's ear sprite is compatible with trimmed icon
|
||||
var/static/list/allowed_ear_names = list("Bnnuy Ears", "Bnnuy Ears 2")
|
||||
//check if wearer's ear sprite is compatible with trimmed icon
|
||||
if((H.ear_style?.name in allowed_ear_names) || (H.ear_secondary_style?.name in allowed_ear_names))
|
||||
item_state = initial(src.item_state)
|
||||
else //if not, just use a generic icon
|
||||
item_state = "avidahatnoears"
|
||||
|
||||
@@ -146,6 +146,11 @@
|
||||
prefs.r_ears3 = character.r_ears3
|
||||
prefs.g_ears3 = character.g_ears3
|
||||
prefs.b_ears3 = character.b_ears3
|
||||
|
||||
// secondary ears
|
||||
prefs.ear_secondary_style = character.ear_secondary_style?.name
|
||||
prefs.ear_secondary_colors = character.ear_secondary_colors
|
||||
|
||||
prefs.r_tail = character.r_tail
|
||||
prefs.b_tail = character.b_tail
|
||||
prefs.g_tail = character.g_tail
|
||||
|
||||
@@ -1,150 +1,147 @@
|
||||
body {
|
||||
font-family: Verdana, Geneva, Tahoma, sans-serif;
|
||||
font-size: 12px !important;
|
||||
font-size: 12px;
|
||||
margin: 0 !important;
|
||||
padding: 0 !important;
|
||||
overflow-x: hidden;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
body.dark {
|
||||
background-color: #131313;
|
||||
color: #b2c4dd;
|
||||
scrollbar-base-color: #1c1c1c;
|
||||
scrollbar-face-color: #3b3b3b;
|
||||
scrollbar-3dlight-color: #252525;
|
||||
scrollbar-highlight-color: #252525;
|
||||
scrollbar-track-color: #1c1c1c;
|
||||
scrollbar-arrow-color: #929292;
|
||||
scrollbar-shadow-color: #3b3b3b;
|
||||
}
|
||||
|
||||
#menu {
|
||||
background-color: #F0F0F0;
|
||||
position: fixed;
|
||||
width: 100%;
|
||||
z-index: 100;
|
||||
}
|
||||
|
||||
.dark #menu {
|
||||
background-color: #202020;
|
||||
}
|
||||
|
||||
#statcontent {
|
||||
padding: 7px 7px 7px 7px;
|
||||
overflow: hidden;
|
||||
}
|
||||
|
||||
a {
|
||||
color: black;
|
||||
text-decoration: none
|
||||
}
|
||||
|
||||
.dark a {
|
||||
color: #b2c4dd;
|
||||
}
|
||||
|
||||
a:hover,
|
||||
.dark a:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
ul {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding: 0;
|
||||
background-color: #333;
|
||||
}
|
||||
|
||||
li {
|
||||
float: left;
|
||||
}
|
||||
|
||||
li a {
|
||||
display: block;
|
||||
color: white;
|
||||
text-align: center;
|
||||
padding: 14px 16px;
|
||||
color: #003399;
|
||||
text-decoration: none;
|
||||
}
|
||||
|
||||
li a:hover:not(.active) {
|
||||
background-color: #111;
|
||||
a:hover {
|
||||
color: #007fff;
|
||||
}
|
||||
|
||||
.button-container {
|
||||
display: inline-flex;
|
||||
h3 {
|
||||
margin: 0 -0.5em 0.5em;
|
||||
padding: 1em 0.66em 0.5em;
|
||||
border-bottom: 0.1667em solid;
|
||||
}
|
||||
|
||||
|
||||
img {
|
||||
-ms-interpolation-mode: nearest-neighbor;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
.stat-container {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
height: 100vh;
|
||||
}
|
||||
|
||||
#menu {
|
||||
display: flex;
|
||||
overflow-x: auto;
|
||||
overflow-y: hidden;
|
||||
padding: 0.25em 0.25em 0;
|
||||
background-color: #ffffff;
|
||||
}
|
||||
|
||||
.menu-wrap {
|
||||
flex-wrap: wrap-reverse;
|
||||
flex-direction: row;
|
||||
align-items: flex-start;
|
||||
overflow-x: hidden;
|
||||
white-space: pre-wrap;
|
||||
padding: 0 4px;
|
||||
}
|
||||
|
||||
#menu.tabs-classic {
|
||||
padding: 0.15em;
|
||||
}
|
||||
|
||||
#menu.tabs-classic .button {
|
||||
min-width: 2em;
|
||||
margin: 0.1em;
|
||||
padding: 0.25em 0.4em;
|
||||
border: 0;
|
||||
border-radius: 0.25em;
|
||||
}
|
||||
|
||||
#menu.tabs-classic .button.active {
|
||||
background-color: #0668b8;
|
||||
color: white;
|
||||
}
|
||||
|
||||
.button {
|
||||
background-color: #dfdfdf;
|
||||
border: 1px solid #cecece;
|
||||
border-bottom-width: 2px;
|
||||
color: rgba(0, 0, 0, 0.7);
|
||||
padding: 6px 4px 4px;
|
||||
text-align: center;
|
||||
text-decoration: none;
|
||||
font-size: 12px;
|
||||
margin: 0;
|
||||
display: inline-table;
|
||||
cursor: pointer;
|
||||
transition-duration: 100ms;
|
||||
order: 3;
|
||||
min-width: 40px;
|
||||
}
|
||||
|
||||
.dark button {
|
||||
background-color: #222222;
|
||||
border-color: #343434;
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
user-select: none;
|
||||
-ms-user-select: none; /* Remove after Byond 516 */
|
||||
text-align: center;
|
||||
font-size: 1em;
|
||||
min-width: 2.9em;
|
||||
padding: 0.5em 0.5em 0.4em;
|
||||
background-color: transparent;
|
||||
color: rgba(0, 0, 0, 0.5);
|
||||
border: 0;
|
||||
border-bottom: 0.1667em solid transparent;
|
||||
border-radius: 0.25em 0.25em 0 0;
|
||||
}
|
||||
|
||||
.button:hover {
|
||||
background-color: #ececec;
|
||||
transition-duration: 0;
|
||||
}
|
||||
|
||||
.dark button:hover {
|
||||
background-color: #2e2e2e;
|
||||
}
|
||||
|
||||
.button:active,
|
||||
.button.active {
|
||||
background-color: #ffffff;
|
||||
cursor: default;
|
||||
background-color: #dfdfdf;
|
||||
color: black;
|
||||
border-top-color: #cecece;
|
||||
border-left-color: #cecece;
|
||||
border-right-color: #cecece;
|
||||
border-bottom-color: #ffffff;
|
||||
border-bottom-color: #000000;
|
||||
}
|
||||
|
||||
.dark .button:active,
|
||||
.dark .button.active {
|
||||
background-color: #444444;
|
||||
color: white;
|
||||
border-top-color: #343434;
|
||||
border-left-color: #343434;
|
||||
border-right-color: #343434;
|
||||
border-bottom-color: #ffffff;
|
||||
#under-menu {
|
||||
height: 0.5em;
|
||||
background-color: #eeeeee;
|
||||
}
|
||||
|
||||
#statcontent {
|
||||
flex: 1;
|
||||
padding: 0.75em 0.5em;
|
||||
overflow-y: scroll;
|
||||
overflow-x: hidden;
|
||||
}
|
||||
|
||||
.grid-container {
|
||||
margin: -2px;
|
||||
margin-right: -15px;
|
||||
margin: -0.25em;
|
||||
}
|
||||
|
||||
.grid-item {
|
||||
display: inline-flex;
|
||||
position: relative;
|
||||
display: inline-block;
|
||||
user-select: none;
|
||||
-ms-user-select: none; /* Remove after Byond 516 */
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
overflow: visible;
|
||||
padding: 3px 2px;
|
||||
max-height: 1.85em;
|
||||
text-decoration: none;
|
||||
background-color: transparent;
|
||||
color: black;
|
||||
}
|
||||
|
||||
.grid-item:hover,
|
||||
.grid-item:active {
|
||||
color: #003399;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.grid-item-text {
|
||||
display: inline-block;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
white-space: nowrap;
|
||||
pointer-events: none;
|
||||
width: 100%;
|
||||
padding: 0.33em 0.5em;
|
||||
border-radius: 0.25em;
|
||||
}
|
||||
|
||||
.grid-item:hover .grid-item-text {
|
||||
overflow: visible;
|
||||
white-space: normal;
|
||||
background-color: #ececec;
|
||||
}
|
||||
|
||||
.grid-item:active .grid-item-text {
|
||||
background-color: #dfdfdf;
|
||||
}
|
||||
|
||||
@media only screen and (min-width: 300px) {
|
||||
@@ -171,31 +168,77 @@ li a:hover:not(.active) {
|
||||
}
|
||||
}
|
||||
|
||||
.grid-item:hover {
|
||||
z-index: 1;
|
||||
.status-info {
|
||||
margin: 0 0.33em 0.25em;
|
||||
}
|
||||
|
||||
.grid-item:hover .grid-item-text {
|
||||
width: auto;
|
||||
text-decoration: underline;
|
||||
.interview_panel_stats,
|
||||
.interview_panel_controls {
|
||||
margin-bottom: 1em;
|
||||
}
|
||||
|
||||
.grid-item-text {
|
||||
display: inline-block;
|
||||
width: 100%;
|
||||
background-color: #ffffff;
|
||||
margin: 0 -6px;
|
||||
padding: 0 6px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
text-overflow: ellipsis;
|
||||
pointer-events: none;
|
||||
/* Dark theme colors */
|
||||
body.dark {
|
||||
background-color: #131313;
|
||||
color: #b2c4dd;
|
||||
scrollbar-base-color: #1c1c1c;
|
||||
scrollbar-face-color: #3b3b3b;
|
||||
scrollbar-3dlight-color: #252525;
|
||||
scrollbar-highlight-color: #252525;
|
||||
scrollbar-track-color: #1c1c1c;
|
||||
scrollbar-arrow-color: #929292;
|
||||
scrollbar-shadow-color: #3b3b3b;
|
||||
}
|
||||
|
||||
.dark .grid-item-text {
|
||||
.dark a {
|
||||
color: #6699ff;
|
||||
}
|
||||
|
||||
.dark a:hover,
|
||||
.dark .grid-item:hover,
|
||||
.dark .grid-item:active {
|
||||
color: #80bfff;
|
||||
}
|
||||
|
||||
.dark #menu {
|
||||
background-color: #131313;
|
||||
}
|
||||
|
||||
.dark #menu.tabs-classic .button.active {
|
||||
background-color: #20b142;
|
||||
}
|
||||
|
||||
.dark .button {
|
||||
color: rgba(255, 255, 255, 0.5);
|
||||
}
|
||||
|
||||
.dark .button:hover {
|
||||
background-color: #252525;
|
||||
}
|
||||
|
||||
.dark .button.active {
|
||||
background-color: #313131;
|
||||
color: #d4dfec;
|
||||
border-bottom-color: #d4dfec;
|
||||
}
|
||||
|
||||
.dark #under-menu {
|
||||
background-color: #202020;
|
||||
}
|
||||
|
||||
.dark .grid-item{
|
||||
color: #b2c4dd;
|
||||
}
|
||||
|
||||
.dark .grid-item:hover .grid-item-text {
|
||||
background-color: #252525;
|
||||
}
|
||||
|
||||
.dark .grid-item:active .grid-item-text {
|
||||
background-color: #313131;
|
||||
}
|
||||
|
||||
/* required for alt click menu */
|
||||
.link {
|
||||
display: inline;
|
||||
background: none;
|
||||
@@ -220,20 +263,6 @@ li a:hover:not(.active) {
|
||||
margin: 2px 2px;
|
||||
}
|
||||
|
||||
.elemcontainer {
|
||||
border-collapse: separate;
|
||||
border-spacing: 0 5px;
|
||||
display: flex;
|
||||
}
|
||||
|
||||
.elem {
|
||||
background: none;
|
||||
border: none;
|
||||
padding: 0px 14px;
|
||||
font-size: 13px;
|
||||
margin: 2px 2px;
|
||||
}
|
||||
|
||||
.dark .link {
|
||||
color: #abc6ec;
|
||||
}
|
||||
@@ -249,13 +278,3 @@ li a:hover:not(.active) {
|
||||
.linkelem:hover {
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
img {
|
||||
-ms-interpolation-mode: nearest-neighbor;
|
||||
image-rendering: pixelated;
|
||||
}
|
||||
|
||||
.interview_panel_controls,
|
||||
.interview_panel_stats {
|
||||
margin-bottom: 10px;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
<ul id="menu" class="button-container"></ul>
|
||||
<div id="under_menu"></div>
|
||||
<div id="statcontent"></div>
|
||||
<div class="stat-container">
|
||||
<div id="menu" class="button-container"></div>
|
||||
<div id="under-menu"></div>
|
||||
<div id="statcontent"></div>
|
||||
</div>
|
||||
|
||||
@@ -33,7 +33,6 @@ var turfname = "";
|
||||
var imageRetryDelay = 500;
|
||||
var imageRetryLimit = 50;
|
||||
var menu = document.getElementById('menu');
|
||||
var under_menu = document.getElementById('under_menu');
|
||||
var statcontentdiv = document.getElementById('statcontent');
|
||||
var storedimages = [];
|
||||
var split_admin_tabs = false;
|
||||
@@ -59,26 +58,26 @@ function createStatusTab(name) {
|
||||
if (!verb_tabs.includes(name) && !permanent_tabs.includes(name)) {
|
||||
return;
|
||||
}
|
||||
var B = document.createElement("BUTTON");
|
||||
B.onclick = function () {
|
||||
var button = document.createElement("DIV");
|
||||
button.onclick = function () {
|
||||
tab_change(name);
|
||||
this.blur();
|
||||
statcontentdiv.focus();
|
||||
};
|
||||
B.id = name;
|
||||
B.textContent = name;
|
||||
B.className = "button";
|
||||
button.id = name;
|
||||
button.textContent = name;
|
||||
button.className = "button";
|
||||
//ORDERING ALPHABETICALLY
|
||||
B.style.order = name.charCodeAt(0);
|
||||
button.style.order = name.charCodeAt(0);
|
||||
if (name == "Status" || name == "MC") {
|
||||
B.style.order = name == "Status" ? 1 : 2;
|
||||
button.style.order = name == "Status" ? 1 : 2;
|
||||
}
|
||||
if (name == "Tickets") {
|
||||
B.style.order = 3;
|
||||
button.style.order = 3;
|
||||
}
|
||||
//END ORDERING
|
||||
menu.appendChild(B);
|
||||
menu.appendChild(button);
|
||||
SendTabToByond(name);
|
||||
under_menu.style.height = menu.clientHeight + 'px';
|
||||
}
|
||||
|
||||
function removeStatusTab(name) {
|
||||
@@ -92,7 +91,6 @@ function removeStatusTab(name) {
|
||||
}
|
||||
menu.removeChild(document.getElementById(name));
|
||||
TakeTabFromByond(name);
|
||||
under_menu.style.height = menu.clientHeight + 'px';
|
||||
}
|
||||
|
||||
function sortVerbs() {
|
||||
@@ -108,10 +106,6 @@ function sortVerbs() {
|
||||
})
|
||||
}
|
||||
|
||||
window.onresize = function () {
|
||||
under_menu.style.height = menu.clientHeight + 'px';
|
||||
}
|
||||
|
||||
function addPermanentTab(name) {
|
||||
if (!permanent_tabs.includes(name)) {
|
||||
permanent_tabs.push(name);
|
||||
@@ -383,6 +377,7 @@ function draw_status() {
|
||||
} else {
|
||||
var div = document.createElement("div");
|
||||
div.textContent = status_tab_parts[i];
|
||||
div.className = "status-info";
|
||||
document.getElementById("statcontent").appendChild(div);
|
||||
}
|
||||
}
|
||||
@@ -506,7 +501,7 @@ function draw_listedturf() {
|
||||
table.appendChild(b);
|
||||
table.appendChild(document.createElement("br"));
|
||||
}
|
||||
document.getElementById("statcontent").appendChild(table);
|
||||
statcontentdiv.appendChild(table);
|
||||
}
|
||||
|
||||
function remove_listedturf() {
|
||||
@@ -777,6 +772,23 @@ function set_theme(which) {
|
||||
}
|
||||
}
|
||||
|
||||
function set_font_size(size) {
|
||||
document.body.style.setProperty('font-size', size);
|
||||
}
|
||||
|
||||
function set_tabs_style(style) {
|
||||
if (style == "default") {
|
||||
menu.classList.add('menu-wrap');
|
||||
menu.classList.remove('tabs-classic');
|
||||
} else if (style == "classic") {
|
||||
menu.classList.add('menu-wrap');
|
||||
menu.classList.add('tabs-classic');
|
||||
} else if (style == "scrollable") {
|
||||
menu.classList.remove('menu-wrap');
|
||||
menu.classList.remove('tabs-classic');
|
||||
}
|
||||
}
|
||||
|
||||
function set_style_sheet(sheet) {
|
||||
if (document.getElementById("goonStyle")) {
|
||||
var currentSheet = document.getElementById("goonStyle");
|
||||
|
||||
|
Before Width: | Height: | Size: 102 KiB After Width: | Height: | Size: 102 KiB |
|
Before Width: | Height: | Size: 166 KiB After Width: | Height: | Size: 166 KiB |
|
Before Width: | Height: | Size: 194 KiB After Width: | Height: | Size: 196 KiB |
|
Before Width: | Height: | Size: 656 KiB After Width: | Height: | Size: 654 KiB |
@@ -5,8 +5,8 @@
|
||||
/* FOR LIVE SERVER */
|
||||
/*********************/
|
||||
|
||||
//#define USE_MAP_TETHER
|
||||
#define USE_MAP_STELLARDELIGHT
|
||||
#define USE_MAP_TETHER
|
||||
//#define USE_MAP_STELLARDELIGHT
|
||||
//#define USE_MAP_GROUNDBASE
|
||||
|
||||
// Debug
|
||||
|
||||
@@ -11,6 +11,7 @@ import { ChatPageSettings } from '../chat';
|
||||
import { changeSettingsTab } from './actions';
|
||||
import { SETTINGS_TABS } from './constants';
|
||||
import { selectActiveTab } from './selectors';
|
||||
import { SettingsStatPanel } from './SettingsStatPanel';
|
||||
import { AdminSettings } from './SettingTabs/AdminSettings';
|
||||
import { ExportTab } from './SettingTabs/ExportTab';
|
||||
import { MessageLimits } from './SettingTabs/MessageLimits';
|
||||
@@ -49,6 +50,7 @@ export const SettingsPanel = (props) => {
|
||||
{activeTab === 'export' && <ExportTab />}
|
||||
{activeTab === 'chatPage' && <ChatPageSettings />}
|
||||
{activeTab === 'textHighlight' && <TextHighlightSettings />}
|
||||
{activeTab === 'statPanel' && <SettingsStatPanel />}
|
||||
{activeTab === 'adminSettings' && <AdminSettings />}
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
|
||||
@@ -0,0 +1,84 @@
|
||||
import { toFixed } from 'common/math';
|
||||
import { capitalize } from 'common/string';
|
||||
import { useDispatch, useSelector } from 'tgui/backend';
|
||||
import {
|
||||
Button,
|
||||
LabeledList,
|
||||
NoticeBox,
|
||||
Section,
|
||||
Slider,
|
||||
Stack,
|
||||
} from 'tgui/components';
|
||||
|
||||
import { updateSettings } from './actions';
|
||||
import { selectSettings } from './selectors';
|
||||
|
||||
const TabsViews = ['default', 'classic', 'scrollable'];
|
||||
const LinkedToChat = () => (
|
||||
<NoticeBox color="red">Unlink Stat Panel from chat!</NoticeBox>
|
||||
);
|
||||
|
||||
export function SettingsStatPanel(props) {
|
||||
const { statLinked, statFontSize, statTabsStyle } =
|
||||
useSelector(selectSettings);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
<Section fill>
|
||||
<Stack fill vertical>
|
||||
<Stack.Item>
|
||||
<LabeledList>
|
||||
<LabeledList.Item label="Tabs" verticalAlign="middle">
|
||||
{TabsViews.map((view) => (
|
||||
<Button
|
||||
key={view}
|
||||
color="transparent"
|
||||
selected={statTabsStyle === view}
|
||||
onClick={() =>
|
||||
dispatch(updateSettings({ statTabsStyle: view }))
|
||||
}
|
||||
>
|
||||
{capitalize(view)}
|
||||
</Button>
|
||||
))}
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Font size">
|
||||
<Stack.Item grow>
|
||||
{statLinked ? (
|
||||
<LinkedToChat />
|
||||
) : (
|
||||
<Slider
|
||||
width="100%"
|
||||
step={1}
|
||||
stepPixelSize={20}
|
||||
minValue={8}
|
||||
maxValue={32}
|
||||
value={statFontSize}
|
||||
unit="px"
|
||||
format={(value) => toFixed(value)}
|
||||
onChange={(e, value) =>
|
||||
dispatch(updateSettings({ statFontSize: value }))
|
||||
}
|
||||
/>
|
||||
)}
|
||||
</Stack.Item>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Stack.Item>
|
||||
<Stack.Divider mt={2.5} />
|
||||
<Stack.Item textAlign="center">
|
||||
<Button
|
||||
fluid
|
||||
icon={statLinked ? 'unlink' : 'link'}
|
||||
color={statLinked ? 'bad' : 'good'}
|
||||
onClick={() =>
|
||||
dispatch(updateSettings({ statLinked: !statLinked }))
|
||||
}
|
||||
>
|
||||
{statLinked ? 'Unlink from chat' : 'Link to chat'}
|
||||
</Button>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
</Section>
|
||||
);
|
||||
}
|
||||
@@ -29,6 +29,10 @@ export const SETTINGS_TABS = [
|
||||
id: 'chatPage',
|
||||
name: 'Chat Tabs',
|
||||
},
|
||||
{
|
||||
id: 'statPanel',
|
||||
name: 'Stat Panel',
|
||||
},
|
||||
];
|
||||
|
||||
export const FONTS_DISABLED = 'Default';
|
||||
|
||||
@@ -13,11 +13,12 @@ import {
|
||||
removeHighlightSetting,
|
||||
updateHighlightSetting,
|
||||
updateSettings,
|
||||
updateToggle,
|
||||
} from './actions';
|
||||
import { FONTS_DISABLED } from './constants';
|
||||
import { selectSettings } from './selectors';
|
||||
|
||||
let statFontTimer: NodeJS.Timeout;
|
||||
let statTabsTimer: NodeJS.Timeout;
|
||||
let overrideRule: HTMLStyleElement;
|
||||
let overrideFontFamily: string | undefined;
|
||||
let overrideFontSize: string;
|
||||
@@ -45,14 +46,37 @@ function updateGlobalOverrideRule() {
|
||||
document.body.style.setProperty('font-size', overrideFontSize);
|
||||
}
|
||||
|
||||
function setGlobalFontSize(fontSize: string) {
|
||||
function setGlobalFontSize(
|
||||
fontSize: string,
|
||||
statFontSize: string,
|
||||
statLinked: boolean,
|
||||
) {
|
||||
overrideFontSize = `${fontSize}px`;
|
||||
|
||||
// Used solution from theme.ts
|
||||
clearInterval(statFontTimer);
|
||||
Byond.command(
|
||||
`.output statbrowser:set_font_size ${statLinked ? fontSize : statFontSize}px`,
|
||||
);
|
||||
statFontTimer = setTimeout(() => {
|
||||
Byond.command(
|
||||
`.output statbrowser:set_font_size ${statLinked ? fontSize : statFontSize}px`,
|
||||
);
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
function setGlobalFontFamily(fontFamily: string) {
|
||||
overrideFontFamily = fontFamily === FONTS_DISABLED ? undefined : fontFamily;
|
||||
}
|
||||
|
||||
function setStatTabsStyle(style: string) {
|
||||
clearInterval(statTabsTimer);
|
||||
Byond.command(`.output statbrowser:set_tabs_style ${style}`);
|
||||
statTabsTimer = setTimeout(() => {
|
||||
Byond.command(`.output statbrowser:set_tabs_style ${style}`);
|
||||
}, 1500);
|
||||
}
|
||||
|
||||
export function settingsMiddleware(store) {
|
||||
let initialized = false;
|
||||
|
||||
@@ -66,7 +90,6 @@ export function settingsMiddleware(store) {
|
||||
});
|
||||
}
|
||||
if (
|
||||
type !== updateToggle.type &&
|
||||
type !== updateSettings.type &&
|
||||
type !== loadSettings.type &&
|
||||
type !== addHighlightSetting.type &&
|
||||
@@ -87,8 +110,15 @@ export function settingsMiddleware(store) {
|
||||
|
||||
const settings = selectSettings(store.getState());
|
||||
|
||||
// Update stat panel settings
|
||||
setStatTabsStyle(settings.statTabsStyle);
|
||||
|
||||
// Update global UI font size
|
||||
setGlobalFontSize(settings.fontSize);
|
||||
setGlobalFontSize(
|
||||
settings.fontSize,
|
||||
settings.statFontSize,
|
||||
settings.statLinked,
|
||||
);
|
||||
setGlobalFontFamily(settings.fontFamily);
|
||||
updateGlobalOverrideRule();
|
||||
|
||||
|
||||
@@ -62,6 +62,9 @@ const initialState = {
|
||||
hideImportantInAdminTab: false,
|
||||
interleave: false,
|
||||
interleaveColor: '#909090',
|
||||
statLinked: true,
|
||||
statFontSize: 12,
|
||||
statTabsStyle: 'default',
|
||||
} as const;
|
||||
|
||||
export function settingsReducer(
|
||||
|
||||
@@ -24,7 +24,7 @@ export function ColorBox(props: Props) {
|
||||
className={classes(['ColorBox', className, computeBoxClassName(rest)])}
|
||||
{...computeBoxProps(rest)}
|
||||
>
|
||||
{content || '.'}
|
||||
{content}
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import { sortBy } from 'common/collections';
|
||||
|
||||
import { useBackend } from '../../backend';
|
||||
import { Button, LabeledList, Section } from '../../components';
|
||||
import { Button, LabeledList, Section, Stack } from '../../components';
|
||||
import { Data, species, styles } from './types';
|
||||
|
||||
export const AppearanceChangerSpecies = (props) => {
|
||||
@@ -66,23 +66,50 @@ export const AppearanceChangerEars = (props) => {
|
||||
const { ear_style, ear_styles } = data;
|
||||
|
||||
return (
|
||||
<Section title="Ears" fill scrollable>
|
||||
<Button
|
||||
onClick={() => act('ear', { clear: true })}
|
||||
selected={ear_style === null}
|
||||
>
|
||||
-- Not Set --
|
||||
</Button>
|
||||
{sortBy(ear_styles, (e: styles) => e.name.toLowerCase()).map((ear) => (
|
||||
<Button
|
||||
key={ear.instance}
|
||||
onClick={() => act('ear', { ref: ear.instance })}
|
||||
selected={ear.name === ear_style}
|
||||
>
|
||||
{ear.name}
|
||||
</Button>
|
||||
))}
|
||||
</Section>
|
||||
<Stack vertical>
|
||||
<Stack.Item grow={1}>
|
||||
<Section title="Ears" fill scrollable>
|
||||
<Button
|
||||
onClick={() => act('ear', { clear: true })}
|
||||
selected={ear_style === null}
|
||||
>
|
||||
-- Not Set --
|
||||
</Button>
|
||||
{sortBy(ear_styles, (e: styles) => e.name.toLowerCase()).map(
|
||||
(ear) => (
|
||||
<Button
|
||||
key={ear.instance}
|
||||
onClick={() => act('ear', { ref: ear.instance })}
|
||||
selected={ear.name === ear_style}
|
||||
>
|
||||
{ear.name}
|
||||
</Button>
|
||||
),
|
||||
)}
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
<Stack.Item grow={1}>
|
||||
<Section title="Ears - Secondary" fill scrollable>
|
||||
<Button
|
||||
onClick={() => act('ear_secondary', { clear: true })}
|
||||
selected={data.ear_secondary_style === null}
|
||||
>
|
||||
-- Not Set --
|
||||
</Button>
|
||||
{sortBy(ear_styles, (e: styles) => e.name.toLowerCase()).map(
|
||||
(ear) => (
|
||||
<Button
|
||||
key={ear.instance}
|
||||
onClick={() => act('ear_secondary', { ref: ear.instance })}
|
||||
selected={ear.name === ear_style}
|
||||
>
|
||||
{ear.name}
|
||||
</Button>
|
||||
),
|
||||
)}
|
||||
</Section>
|
||||
</Stack.Item>
|
||||
</Stack>
|
||||
);
|
||||
};
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useBackend } from '../../backend';
|
||||
import { Box, Button, ColorBox, LabeledList, Section } from '../../components';
|
||||
import { Data } from './types';
|
||||
import { Data, SPRITE_ACCESSORY_COLOR_CHANNEL_NAMES } from './types';
|
||||
|
||||
export const AppearanceChangerColors = (props) => {
|
||||
const { act, data } = useBackend<Data>();
|
||||
@@ -56,14 +56,25 @@ export const AppearanceChangerColors = (props) => {
|
||||
</Box>
|
||||
<Box>
|
||||
<ColorBox color={ears_color} mr={1} />
|
||||
<Button onClick={() => act('ears_color')}>Change Ears Color</Button>
|
||||
<Button onClick={() => act('ears_color')}>
|
||||
Change Ears Color (Primary)
|
||||
</Button>
|
||||
</Box>
|
||||
<Box>
|
||||
<ColorBox color={ears2_color} mr={1} />
|
||||
<Button onClick={() => act('ears2_color')}>
|
||||
Change Secondary Ears Color
|
||||
Change Ears Color (Secondary)
|
||||
</Button>
|
||||
</Box>
|
||||
{data.ear_secondary_colors.map((color, index) => (
|
||||
<Button
|
||||
key={`${index}`}
|
||||
onClick={() => act('ears_secondary_color', { channel: index })}
|
||||
>
|
||||
Change Secondary Ears Color (
|
||||
{SPRITE_ACCESSORY_COLOR_CHANNEL_NAMES.at(index)})
|
||||
</Button>
|
||||
))}
|
||||
<Box>
|
||||
<ColorBox color={tail_color} mr={1} />
|
||||
<Button onClick={() => act('tail_color')}>Change Tail Color</Button>
|
||||
|
||||
@@ -1,5 +1,12 @@
|
||||
import { BooleanLike } from 'common/react';
|
||||
|
||||
export const SPRITE_ACCESSORY_COLOR_CHANNEL_NAMES = [
|
||||
'Primary',
|
||||
'Secondary',
|
||||
'Tertiary',
|
||||
'Quaternary',
|
||||
];
|
||||
|
||||
export type Data = {
|
||||
name: string;
|
||||
specimen: string;
|
||||
@@ -39,6 +46,8 @@ export type Data = {
|
||||
wing2_color: string;
|
||||
facial_hair_styles: { facialhairstyle: string }[];
|
||||
hair_styles: { hairstyle: string }[];
|
||||
ear_secondary_style: string;
|
||||
ear_secondary_colors: string[];
|
||||
};
|
||||
|
||||
type genders = { gender_name: string; gender_key: string }[];
|
||||
|
||||
@@ -10,9 +10,9 @@ export type Data = {
|
||||
styleHref: string;
|
||||
style: string;
|
||||
color: string | undefined;
|
||||
colorHref: string | undefined;
|
||||
colorHref: string | undefined | { act: string; params: Object };
|
||||
color2?: string | undefined;
|
||||
colorHref2?: string | undefined;
|
||||
colorHref2?: string | undefined | { act: string; params: Object };
|
||||
};
|
||||
disk: BooleanLike;
|
||||
diskStored: BooleanLike;
|
||||
@@ -31,6 +31,7 @@ export type activeBodyRecord = {
|
||||
digitigrade: BooleanLike;
|
||||
styles: {
|
||||
Ears: colourableStyle;
|
||||
Horns: colourableStyle;
|
||||
Tail: colourableStyle;
|
||||
Wing: colourableStyle;
|
||||
Hair: simpleStyle;
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
import { useBackend } from 'tgui/backend';
|
||||
import {
|
||||
Box,
|
||||
ColorBox,
|
||||
ImageButton,
|
||||
Input,
|
||||
LabeledList,
|
||||
NoticeBox,
|
||||
ProgressBar,
|
||||
@@ -164,9 +166,9 @@ const Configuration = (props) => {
|
||||
};
|
||||
|
||||
const Status = (props) => {
|
||||
const { data } = useBackend<Data>();
|
||||
const { act, data } = useBackend<Data>();
|
||||
|
||||
const { charge, max_charge, health, max_health } = data;
|
||||
const { charge, max_charge, health, max_health, light_color } = data;
|
||||
|
||||
return (
|
||||
<Section title="Status" fill>
|
||||
@@ -199,6 +201,17 @@ const Status = (props) => {
|
||||
}}
|
||||
/>
|
||||
</LabeledList.Item>
|
||||
<LabeledList.Item label="Light color">
|
||||
<Box inline>
|
||||
<ColorBox mr={1} color={light_color} />
|
||||
<Input
|
||||
width="5em"
|
||||
monospace
|
||||
value={light_color}
|
||||
onChange={(e, value: string) => act('set_light_col', { value })}
|
||||
/>
|
||||
</Box>
|
||||
</LabeledList.Item>
|
||||
</LabeledList>
|
||||
</Section>
|
||||
);
|
||||
|
||||
@@ -30,6 +30,8 @@ export type Data = {
|
||||
health: number;
|
||||
max_health: number;
|
||||
|
||||
light_color: string;
|
||||
|
||||
// Modules
|
||||
modules_static: Module[];
|
||||
emag_modules_static: Module[];
|
||||
|
||||
@@ -29,6 +29,10 @@ export const VoreBellySelectionAndCustomization = (props: {
|
||||
Export
|
||||
<Icon name="file-export" ml={0.5} />
|
||||
</Tabs.Tab>
|
||||
<Tabs.Tab onClick={() => act('importpanel')}>
|
||||
Import
|
||||
<Icon name="file-import" ml={0.5} />
|
||||
</Tabs.Tab>
|
||||
<Divider />
|
||||
{our_bellies.map((belly) => (
|
||||
<Tabs.Tab
|
||||
|
||||
@@ -8,6 +8,10 @@ export const downloadPrefs = (extension: string) => {
|
||||
|
||||
const { db_version, db_repo, mob_name, bellies } = data;
|
||||
|
||||
if (!bellies) {
|
||||
return;
|
||||
}
|
||||
|
||||
let datesegment = getCurrentTimestamp();
|
||||
|
||||
let filename = mob_name + datesegment + extension;
|
||||
|
||||
@@ -4,7 +4,7 @@ export type Data = {
|
||||
db_version: string;
|
||||
db_repo: string;
|
||||
mob_name: string;
|
||||
bellies: Belly[];
|
||||
bellies?: Belly[];
|
||||
};
|
||||
|
||||
export type Belly = {
|
||||
|
||||
@@ -4221,6 +4221,7 @@
|
||||
#include "code\modules\vore\appearance\preferences_vr.dm"
|
||||
#include "code\modules\vore\appearance\update_icons_vr.dm"
|
||||
#include "code\modules\vore\eating\belly_dat_vr.dm"
|
||||
#include "code\modules\vore\eating\belly_import.dm"
|
||||
#include "code\modules\vore\eating\belly_messages.dm"
|
||||
#include "code\modules\vore\eating\belly_obj_vr.dm"
|
||||
#include "code\modules\vore\eating\bellymodes_datum_vr.dm"
|
||||
|
||||