From a1da8c5e00a7c048944040444eb27c2953e93c74 Mon Sep 17 00:00:00 2001 From: Kashargul <144968721+Kashargul@users.noreply.github.com> Date: Sat, 16 Dec 2023 21:14:48 +0100 Subject: [PATCH] self recolour for simple mob / robot (#7415) --- code/__defines/misc_ch.dm | 7 +- .../code/datums/colormate/colormate.dm | 219 ++++++++++++++++++ .../code/game/machinery/colormate.dm | 6 +- .../modules/mob/living/silicon/robot/robot.dm | 16 ++ .../mob/living/simple_mob/simple_mob.dm | 12 + vorestation.dme | 1 + 6 files changed, 255 insertions(+), 6 deletions(-) create mode 100644 modular_chomp/code/datums/colormate/colormate.dm diff --git a/code/__defines/misc_ch.dm b/code/__defines/misc_ch.dm index 58f0f9ac4d..c3ca475a8d 100644 --- a/code/__defines/misc_ch.dm +++ b/code/__defines/misc_ch.dm @@ -31,4 +31,9 @@ #define VANTAG_VORE_D "vantag_vore_d" #define VANTAG_VORE_DE "vantag_vore_de" #define VANTAG_VORE_DD "vantag_vore_dd" -#define VANTAG_VORE_DA "vantag_vore_da" \ No newline at end of file +#define VANTAG_VORE_DA "vantag_vore_da" + +// ColorMate states +#define COLORMATE_TINT 1 +#define COLORMATE_HSV 2 +#define COLORMATE_MATRIX 3 diff --git a/modular_chomp/code/datums/colormate/colormate.dm b/modular_chomp/code/datums/colormate/colormate.dm new file mode 100644 index 0000000000..5f23d25260 --- /dev/null +++ b/modular_chomp/code/datums/colormate/colormate.dm @@ -0,0 +1,219 @@ +/datum/ColorMate + var/name = "colouring" + var/atom/movable/inserted + var/activecolor = "#FFFFFF" + var/list/color_matrix_last + var/active_mode = COLORMATE_HSV + + var/build_hue = 0 + var/build_sat = 1 + var/build_val = 1 + + /// Minimum lightness for normal mode + var/minimum_normal_lightness = 50 + /// Minimum lightness for matrix mode, tested using 4 test colors of full red, green, blue, white. + var/minimum_matrix_lightness = 75 + /// Minimum matrix tests that must pass for something to be considered a valid color (see above) + var/minimum_matrix_tests = 2 + /// Temporary messages + var/temp + +/datum/ColorMate/New(mob/user) + color_matrix_last = list( + 1, 0, 0, + 0, 1, 0, + 0, 0, 1, + 0, 0, 0, + ) + if(istype(user)) + inserted = user + . = ..() + +/datum/ColorMate/Destroy() + inserted = null + . = ..() + +/datum/ColorMate/tgui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ColorMate", name) + ui.open() + +/datum/ColorMate/ui_interact(mob/user, datum/tgui/ui) + ui = SStgui.try_update_ui(user, src, ui) + if(!ui) + ui = new(user, src, "ColorMate", src.name) + ui.set_autoupdate(FALSE) //This might be a bit intensive, better to not update it every few ticks + ui.open() + +/datum/ColorMate/tgui_state(mob/user) + return GLOB.tgui_conscious_state + +/datum/ColorMate/tgui_data() + . = list() + .["activemode"] = active_mode + .["matrixcolors"] = list( + "rr" = color_matrix_last[1], + "rg" = color_matrix_last[2], + "rb" = color_matrix_last[3], + "gr" = color_matrix_last[4], + "gg" = color_matrix_last[5], + "gb" = color_matrix_last[6], + "br" = color_matrix_last[7], + "bg" = color_matrix_last[8], + "bb" = color_matrix_last[9], + "cr" = color_matrix_last[10], + "cg" = color_matrix_last[11], + "cb" = color_matrix_last[12], + ) + .["buildhue"] = build_hue + .["buildsat"] = build_sat + .["buildval"] = build_val + if(temp) + .["temp"] = temp + if(inserted) + .["item"] = list() + .["item"]["name"] = inserted.name + .["item"]["sprite"] = icon2base64(get_flat_icon(inserted,dir=SOUTH,no_anim=TRUE)) + .["item"]["preview"] = icon2base64(build_preview()) + else + .["item"] = null + +/datum/ColorMate/tgui_act(action, params) + . = ..() + if(.) + return + if(inserted) + switch(action) + if("switch_modes") + active_mode = text2num(params["mode"]) + return TRUE + if("choose_color") + var/chosen_color = input(inserted, "Choose a color: ", "ColorMate colour picking", activecolor) as color|null + if(chosen_color) + activecolor = chosen_color + return TRUE + if("paint") + do_paint(inserted) + temp = "Painted Successfully!" + if(istype(inserted, /mob/living/simple_mob)) + var/mob/living/simple_mob/M = inserted + M.has_recoloured = TRUE + if(istype(inserted, /mob/living/silicon/robot)) + var/mob/living/silicon/robot/R = inserted + R.has_recoloured = TRUE + Destroy() + if("drop") + temp = "" + Destroy() + if("clear") + inserted.remove_atom_colour(FIXED_COLOUR_PRIORITY) + playsound(src, 'sound/effects/spray3.ogg', 50, 1) + temp = "Cleared Successfully!" + return TRUE + if("set_matrix_color") + color_matrix_last[params["color"]] = params["value"] + return TRUE + if("set_hue") + build_hue = clamp(text2num(params["buildhue"]), 0, 360) + return TRUE + if("set_sat") + build_sat = clamp(text2num(params["buildsat"]), -10, 10) + return TRUE + if("set_val") + build_val = clamp(text2num(params["buildval"]), -10, 10) + return TRUE + +/datum/ColorMate/proc/do_paint(mob/user) + var/color_to_use + switch(active_mode) + if(COLORMATE_TINT) + color_to_use = activecolor + if(COLORMATE_MATRIX) + color_to_use = rgb_construct_color_matrix( + text2num(color_matrix_last[1]), + text2num(color_matrix_last[2]), + text2num(color_matrix_last[3]), + text2num(color_matrix_last[4]), + text2num(color_matrix_last[5]), + text2num(color_matrix_last[6]), + text2num(color_matrix_last[7]), + text2num(color_matrix_last[8]), + text2num(color_matrix_last[9]), + text2num(color_matrix_last[10]), + text2num(color_matrix_last[11]), + text2num(color_matrix_last[12]), + ) + if(COLORMATE_HSV) + color_to_use = color_matrix_hsv(build_hue, build_sat, build_val) + color_matrix_last = color_to_use + if(!color_to_use || !check_valid_color(color_to_use, user)) + to_chat(user, SPAN_NOTICE("Invalid color.")) + return FALSE + inserted.add_atom_colour(color_to_use, FIXED_COLOUR_PRIORITY) + playsound(src, 'sound/effects/spray3.ogg', 50, 1) + return TRUE + +/// Produces the preview image of the item, used in the UI, the way the color is not stacking is a sin. +/datum/ColorMate/proc/build_preview() + if(inserted) //sanity + var/list/cm + switch(active_mode) + if(COLORMATE_MATRIX) + cm = rgb_construct_color_matrix( + text2num(color_matrix_last[1]), + text2num(color_matrix_last[2]), + text2num(color_matrix_last[3]), + text2num(color_matrix_last[4]), + text2num(color_matrix_last[5]), + text2num(color_matrix_last[6]), + text2num(color_matrix_last[7]), + text2num(color_matrix_last[8]), + text2num(color_matrix_last[9]), + text2num(color_matrix_last[10]), + text2num(color_matrix_last[11]), + text2num(color_matrix_last[12]), + ) + if(!check_valid_color(cm, usr)) + return get_flat_icon(inserted, dir=SOUTH, no_anim=TRUE) + + if(COLORMATE_TINT) + if(!check_valid_color(activecolor, usr)) + return get_flat_icon(inserted, dir=SOUTH, no_anim=TRUE) + + if(COLORMATE_HSV) + cm = color_matrix_hsv(build_hue, build_sat, build_val) + color_matrix_last = cm + if(!check_valid_color(cm, usr)) + return get_flat_icon(inserted, dir=SOUTH, no_anim=TRUE) + + var/cur_color = inserted.color + inserted.color = null + inserted.color = (active_mode == COLORMATE_TINT ? activecolor : cm) + var/icon/preview = get_flat_icon(inserted, dir=SOUTH, no_anim=TRUE) + inserted.color = cur_color + temp = "" + + . = preview + +/datum/ColorMate/proc/check_valid_color(list/cm, mob/user) + if(!islist(cm)) // normal + var/list/HSV = ReadHSV(RGBtoHSV(cm)) + if(HSV[3] < minimum_normal_lightness) + temp = "[cm] is too dark (Minimum lightness: [minimum_normal_lightness])" + return FALSE + return TRUE + else // matrix + // We test using full red, green, blue, and white + // A predefined number of them must pass to be considered valid + var/passed = 0 +#define COLORTEST(thestring, thematrix) passed += (ReadHSV(RGBtoHSV(RGBMatrixTransform(thestring, thematrix)))[3] >= minimum_matrix_lightness) + COLORTEST("FF0000", cm) + COLORTEST("00FF00", cm) + COLORTEST("0000FF", cm) + COLORTEST("FFFFFF", cm) +#undef COLORTEST + if(passed < minimum_matrix_tests) + temp = "Matrix is too dark. (passed [passed] out of [minimum_matrix_tests] required tests. Minimum lightness: [minimum_matrix_lightness])." + return FALSE + return TRUE diff --git a/modular_chomp/code/game/machinery/colormate.dm b/modular_chomp/code/game/machinery/colormate.dm index e3a3537352..71104d9930 100644 --- a/modular_chomp/code/game/machinery/colormate.dm +++ b/modular_chomp/code/game/machinery/colormate.dm @@ -1,7 +1,3 @@ -#define COLORMATE_TINT 1 -#define COLORMATE_HSV 2 -#define COLORMATE_MATRIX 3 - /obj/machinery/gear_painter name = "Color Mate" desc = "A machine to give your apparel a fresh new color!" @@ -297,4 +293,4 @@ if(passed < minimum_matrix_tests) temp = "Matrix is too dark. (passed [passed] out of [minimum_matrix_tests] required tests. Minimum lightness: [minimum_matrix_lightness])." return FALSE - return TRUE \ No newline at end of file + return TRUE diff --git a/modular_chomp/code/modules/mob/living/silicon/robot/robot.dm b/modular_chomp/code/modules/mob/living/silicon/robot/robot.dm index d9f3588b4d..20e7757f1e 100644 --- a/modular_chomp/code/modules/mob/living/silicon/robot/robot.dm +++ b/modular_chomp/code/modules/mob/living/silicon/robot/robot.dm @@ -1,6 +1,7 @@ /mob/living/silicon/robot var/sleeper_resting = FALSE //Enable resting belly sprites for dogborgs that have the sprites var/datum/matter_synth/water_res = null //Enable water for lick clean + var/has_recoloured = FALSE /mob/living/silicon/robot/verb/purge_nutrition() set name = "Purge Nutrition" @@ -28,3 +29,18 @@ to_chat(src, "You refill the extinguisher using your water reserves.") else to_chat(src, "Insufficient water reserves.") + +/mob/living/silicon/robot/module_reset() + ..() + has_recoloured = FALSE + +/mob/living/silicon/robot/verb/ColorMate() + set name = "Recolour Module" + set category = "Robot Commands" + set desc = "Allows to recolour once." + + if(!has_recoloured) + var/datum/ColorMate/recolour = new /datum/ColorMate(usr) + recolour.tgui_interact(usr) + return + to_chat(usr, "You've already recoloured yourself once. Ask for a module reset for another.") diff --git a/modular_chomp/code/modules/mob/living/simple_mob/simple_mob.dm b/modular_chomp/code/modules/mob/living/simple_mob/simple_mob.dm index b8ed4037ba..8bbf3cb06a 100644 --- a/modular_chomp/code/modules/mob/living/simple_mob/simple_mob.dm +++ b/modular_chomp/code/modules/mob/living/simple_mob/simple_mob.dm @@ -3,6 +3,7 @@ var/list/speech_sounds = list() var/speech_chance = 75 //mobs can be a bit more emotive than carbon/humans var/speech_sound_enabled = TRUE + var/has_recoloured = FALSE //vars for vore_icons toggle control var/vore_icons_cache = null // null by default. Going from ON to OFF should store vore_icons val here, OFF to ON reset as null @@ -132,3 +133,14 @@ /mob/living/simple_mob/proc/character_directory_species() return "simplemob" + +/mob/living/simple_mob/verb/ColorMate() + set name = "Recolour" + set category = "Abilities" + set desc = "Allows to recolour once." + + if(!has_recoloured) + var/datum/ColorMate/recolour = new /datum/ColorMate(usr) + recolour.tgui_interact(usr) + return + to_chat(usr, "You've already recoloured yourself once. You are only allowed to recolour yourself once during a around.") diff --git a/vorestation.dme b/vorestation.dme index 02c40a0f97..cc36199df7 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -4607,6 +4607,7 @@ #include "modular_chomp\code\datums\autolathe\general_ch.dm" #include "modular_chomp\code\datums\browser\color_matrix_picker.dm" #include "modular_chomp\code\datums\changelog\changelog.dm" +#include "modular_chomp\code\datums\colormate\colormate.dm" #include "modular_chomp\code\datums\components\gargoyle.dm" #include "modular_chomp\code\datums\components\squeak.dm" #include "modular_chomp\code\datums\components\xenoqueen.dm"