From 0afe97837ff7aef483382e2c9e13a4aadc46d593 Mon Sep 17 00:00:00 2001 From: explosivekitty Date: Sat, 9 May 2026 06:39:23 +0200 Subject: [PATCH] Let's you paint items in loadout and spray can coloring modes (#5508) ## About The Pull Request Adds new options for spray can that let you paint items without actually making them washable with water, you also get an option to remove permanent coloring just like prismatic gray extract does. You also can now paint non-greyscale items from loadout so you don't need to take spray can and use it after you spawn. I ran into an issue where after recoloring your item in loadout caused runtimes so i had to make it such there is no preview for colored items in loadout, but if you wanted to help to fix it i left a comment where (i think) additional checks should be added- It shouldn't be a big deal anyway, you most likely already know what color you want for your items and if not just check it on station and then update your loadout accordingly ## Why It's Good For The Game We all hate it when you get sprayed with water and all of your custom colored clothing turns back to how it was initially. ## Proof Of Testing
Screenshots/Videos loadout1 spraycan yes its actually doesnt wash
## Changelog :cl: add: You can now repaint non-greyscale items in loadout the same way spraycan does add: Spray cans can color items in such a way water cant remove the paint, and also remove permanent paint /:cl: --------- Co-authored-by: Copilot Co-authored-by: Roxy <94389951+SapphoQueer@users.noreply.github.com> Co-authored-by: buffyuwu --- code/__DEFINES/~skyrat_defines/loadout.dm | 3 ++ code/game/objects/items/crayons.dm | 23 ++++++++-- code/modules/loadout/loadout_items.dm | 56 +++++++++++++++++++++++ tgui/packages/tgui/interfaces/Crayon.tsx | 13 ++++++ 4 files changed, 92 insertions(+), 3 deletions(-) diff --git a/code/__DEFINES/~skyrat_defines/loadout.dm b/code/__DEFINES/~skyrat_defines/loadout.dm index 5cb6e38f439..80f648483ac 100644 --- a/code/__DEFINES/~skyrat_defines/loadout.dm +++ b/code/__DEFINES/~skyrat_defines/loadout.dm @@ -10,3 +10,6 @@ // Used for custom item descriptions #define INFO_DESCRIBED "description" + +#define INFO_CUSTOM_COLOR "custom_color" +#define INFO_COLOR_MODE "color_mode" diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index 9737e7ba1f5..bfcbae3979b 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -197,6 +197,8 @@ ) /// Combined lists var/static/list/all_drawables = graffiti + symbols + drawings + oriented + runes + graffiti_large_h + var/washable_coloring_mode = TRUE //bubber addition + var/remove_coloring = FALSE //bubber addition /obj/item/toy/crayon/proc/isValidSurface(surface) return isfloorturf(surface) @@ -385,6 +387,8 @@ .["can_change_colour"] = can_change_colour .["selected_color"] = GLOB.pipe_color_name[paint_color] || paint_color .["paint_colors"] = GLOB.pipe_paint_colors + .["washable_coloring_mode"] = washable_coloring_mode //bubber addition + .["remove_coloring"] = remove_coloring //bubber addition /obj/item/toy/crayon/ui_act(action, list/params, datum/tgui/ui, datum/ui_state/state) . = ..() @@ -427,6 +431,15 @@ . = TRUE paint_mode = PAINT_NORMAL drawtype = "a" + if("change_color_mode") //bubber addition + if(has_cap) + washable_coloring_mode = !washable_coloring_mode + . = TRUE + if("toggle_remove_coloring") //bubber addition + if(has_cap) + remove_coloring = !remove_coloring + . = TRUE + update_appearance() /obj/item/toy/crayon/proc/crayon_text_strip(text) @@ -897,6 +910,10 @@ if(check_empty(user)) return ITEM_INTERACT_BLOCKING + if(remove_coloring && isitem(target)) //bubber addition + target.remove_atom_colour(FIXED_COLOUR_PRIORITY) + return ITEM_INTERACT_SUCCESS + if (isbodypart(target)) if (color_limb(target, user)) return ITEM_INTERACT_SUCCESS @@ -926,7 +943,7 @@ var/fraction = min(1, . / reagents.maximum_volume) reagents.expose(carbon_target, VAPOR, fraction * volume_multiplier) - else if(actually_paints && target.is_atom_colour(paint_color, min_priority_index = WASHABLE_COLOUR_PRIORITY)) + else if(actually_paints && target.is_atom_colour(paint_color, min_priority_index = washable_coloring_mode ? WASHABLE_COLOUR_PRIORITY : FIXED_COLOUR_PRIORITY)) //bubber edit balloon_alert(user, "[target.p_theyre()] already that color!") return ITEM_INTERACT_BLOCKING @@ -980,9 +997,9 @@ target_pipe.paint(paint_color) balloon_alert(user, "painted in [GLOB.pipe_color_name[paint_color]] color") else if (is_type_in_typecache(target, direct_color_types)) - target.add_atom_colour(paint_color, WASHABLE_COLOUR_PRIORITY) + target.add_atom_colour(paint_color, washable_coloring_mode ? WASHABLE_COLOUR_PRIORITY : FIXED_COLOUR_PRIORITY) //bubber edit else - target.add_atom_colour(color_transition_filter(paint_color, saturation_mode), WASHABLE_COLOUR_PRIORITY) + target.add_atom_colour(color_transition_filter(paint_color, saturation_mode), washable_coloring_mode ? WASHABLE_COLOUR_PRIORITY : FIXED_COLOUR_PRIORITY) //bubber edit if(isitem(target) && isliving(target.loc)) var/obj/item/target_item = target diff --git a/code/modules/loadout/loadout_items.dm b/code/modules/loadout/loadout_items.dm index f20e78df7f8..ecab82a1abc 100644 --- a/code/modules/loadout/loadout_items.dm +++ b/code/modules/loadout/loadout_items.dm @@ -153,6 +153,45 @@ GLOBAL_LIST_INIT(all_loadout_categories, init_loadout_categories()) if(reskin_datum) return set_skin(manager, user, params) + if("select_color_simple") + return item_color_painting(manager, user) + + if("set_color_mode") + return item_color_mode(manager, user) + + return TRUE + +/datum/loadout_item/proc/item_color_painting(datum/preference_middleware/loadout/manager, mob/user) + if(manager.menu) + return FALSE + + var/list/loadout = manager.get_current_loadout() + if(!loadout?[item_path]) + return FALSE + + var/chosen_color = tgui_color_picker(user, "Pick new color. Setting color to pitch black will remove the existing color.", "Repaint item", "#000000") + if(isnull(chosen_color)) + return FALSE + + var/hsl = rgb2num(chosen_color, COLORSPACE_HSL) + if(hsl[3] == 0) + loadout[item_path][INFO_CUSTOM_COLOR] = null + else + loadout[item_path][INFO_CUSTOM_COLOR] = chosen_color + + manager.save_current_loadout(loadout) + return TRUE + +/datum/loadout_item/proc/item_color_mode(datum/preference_middleware/loadout/manager, mob/user) + var/list/loadout = manager.get_current_loadout() + if(!loadout?[item_path]) + return FALSE + + if(isnull(loadout[item_path][INFO_COLOR_MODE])) + loadout[item_path][INFO_COLOR_MODE] = FALSE + + loadout[item_path][INFO_COLOR_MODE] = !loadout[item_path][INFO_COLOR_MODE] + manager.save_current_loadout(loadout) return TRUE /// Opens up the GAGS editing menu. @@ -305,6 +344,9 @@ GLOBAL_LIST_INIT(all_loadout_categories, init_loadout_categories()) equipped_item.set_greyscale(item_color) update_flag |= equipped_item.slot_flags + if(item_details?[INFO_CUSTOM_COLOR] && !istype(equipper, /mob/living/carbon/human/dummy)) //the dummy check makes it not color the item in the loadout because that causes runtimes, joining into the game colors the item as intended. If you want to fix it, start here + equipped_item.add_atom_colour(color_transition_filter(item_details[INFO_CUSTOM_COLOR], item_details[INFO_COLOR_MODE] ? SATURATION_OVERRIDE : SATURATION_MULTIPLY), FIXED_COLOUR_PRIORITY) + // BUBBER EDIT CHANGE BEGIN - Descriptions if((loadout_flags & LOADOUT_FLAG_ALLOW_NAMING) && !visuals_only) var/renamed = FALSE @@ -444,6 +486,20 @@ GLOBAL_LIST_INIT(all_loadout_categories, init_loadout_categories()) "button_icon" = FA_ICON_PALETTE, "active_key" = INFO_GREYSCALE, )) + else + UNTYPED_LIST_ADD(button_list, list( + "label" = "Repaint", + "act_key" = "select_color_simple", + "button_icon" = FA_ICON_PALETTE, + "active_key" = INFO_CUSTOM_COLOR, + )) + UNTYPED_LIST_ADD(button_list, list( + "label" = "Repainting mode", + "act_key" = "set_color_mode", + "active_key" = INFO_COLOR_MODE, + "active_text" = "Override Color", + "inactive_text" = "Multiply Color", + )) if(loadout_flags & LOADOUT_FLAG_ALLOW_NAMING) UNTYPED_LIST_ADD(button_list, list( diff --git a/tgui/packages/tgui/interfaces/Crayon.tsx b/tgui/packages/tgui/interfaces/Crayon.tsx index 6ca934cb556..fe2f90c9f22 100644 --- a/tgui/packages/tgui/interfaces/Crayon.tsx +++ b/tgui/packages/tgui/interfaces/Crayon.tsx @@ -30,6 +30,8 @@ export const Crayon = (props) => { selected_stencil, is_literate_user, text_buffer, + washable_coloring_mode, + remove_coloring, } = data; const capOrChanges = has_cap || can_change_colour; @@ -54,6 +56,17 @@ export const Crayon = (props) => { onClick={() => act('custom_color')} /> + +