From c40a37db229e081f25c90302131bb9705f115501 Mon Sep 17 00:00:00 2001 From: Geeves Date: Mon, 10 Jun 2024 13:54:20 +0200 Subject: [PATCH] Some Preview Stuff (#19308) * Added more backgrounds to choose from in the character preview screen. * You can now selectively hide your job uniform, suit, or hat. --------- Signed-off-by: Geeves Co-authored-by: Fluffy <65877598+FluffyGhoster@users.noreply.github.com> --- code/__DEFINES/prefs.dm | 22 ++++++++-- code/__HELPERS/lists.dm | 16 ++++++++ code/game/jobs/job/job.dm | 26 +++++++++++- .../preference_setup/general/03_body.dm | 18 +++++++-- code/modules/client/preferences.dm | 38 +++++++++++------- .../abstract/new_player/preferences_setup.dm | 2 +- html/changelogs/geeves-preview_stuff.yml | 7 ++++ icons/turf/flooring/character_preview.dmi | Bin 0 -> 12199 bytes 8 files changed, 105 insertions(+), 24 deletions(-) create mode 100644 html/changelogs/geeves-preview_stuff.yml create mode 100644 icons/turf/flooring/character_preview.dmi diff --git a/code/__DEFINES/prefs.dm b/code/__DEFINES/prefs.dm index 4d058b8ac1e..6725d511af1 100644 --- a/code/__DEFINES/prefs.dm +++ b/code/__DEFINES/prefs.dm @@ -1,6 +1,22 @@ -#define EQUIP_PREVIEW_LOADOUT 1 -#define EQUIP_PREVIEW_JOB 2 -#define EQUIP_PREVIEW_ALL (EQUIP_PREVIEW_LOADOUT|EQUIP_PREVIEW_JOB) +// Character Preview Bitflags + +/// Will show loadout items +#define EQUIP_PREVIEW_LOADOUT BITFLAG(0) + +/// Will show job items, specific item bitflags will determine if those ones are shown or not +#define EQUIP_PREVIEW_JOB BITFLAG(1) + +/// Will show job hat if true, will hide if this is false or EQUIP_PREVIEW_JOB is false +#define EQUIP_PREVIEW_JOB_HAT BITFLAG(2) + +/// Will show job uniform if true, will hide if this is false or EQUIP_PREVIEW_JOB is false +#define EQUIP_PREVIEW_JOB_UNIFORM BITFLAG(3) + +/// Will show job suit if true, will hide if this is false or EQUIP_PREVIEW_JOB is false +#define EQUIP_PREVIEW_JOB_SUIT BITFLAG(4) + +/// The default EQUIP_PREVIEW bitflag, with this, all character creation items are shown +#define EQUIP_PREVIEW_ALL (EQUIP_PREVIEW_LOADOUT|EQUIP_PREVIEW_JOB|EQUIP_PREVIEW_JOB_HAT|EQUIP_PREVIEW_JOB_UNIFORM|EQUIP_PREVIEW_JOB_SUIT) /// External organ. Is a prosthesis with a robo-limb manufacturer. #define ORGAN_PREF_CYBORG "cyborg" diff --git a/code/__HELPERS/lists.dm b/code/__HELPERS/lists.dm index 3ec1cf83641..767f0d5189e 100644 --- a/code/__HELPERS/lists.dm +++ b/code/__HELPERS/lists.dm @@ -295,6 +295,22 @@ return L[i+1] return L[1] +/// Returns the value after the current value in a key-value pair associated list. If this is the last element, or the element isn't present in the list, it'll return the first value in the list +/proc/next_in_assoc_list(element, list/our_list) + // this is the index we'll use to get the key at the end of the function, which is used to get the value + var/index = 1 + + // loop through to the list to find where exactly our value element is in the list + for(var/i in 1 to length(our_list)) + if(our_list[our_list[i]] == element) + // we've found our value, now we need to check if it's at the end of the list + // if not, we can select our index + 1 + // First element in the list if we're at the end of it, next one otherwise + index = ((i == length(our_list)) ? 1 : i + 1) + break + + return our_list[our_list[index]] + /* * Sorting */ diff --git a/code/game/jobs/job/job.dm b/code/game/jobs/job/job.dm index 529557a77e8..752b8bed198 100644 --- a/code/game/jobs/job/job.dm +++ b/code/game/jobs/job/job.dm @@ -111,7 +111,7 @@ to_chat(H, SPAN_BOLD(SPAN_NOTICE("Your account number is: [account.account_number], your account pin is: [account.remote_access_pin]"))) // overrideable separately so AIs/borgs can have cardborg hats without unneccessary new()/del() -/datum/job/proc/equip_preview(mob/living/carbon/human/H, var/alt_title, var/faction_override) +/datum/job/proc/equip_preview(mob/living/carbon/human/H, datum/preferences/prefs, var/alt_title, var/faction_override) if(faction_override) var/faction = SSjobs.name_factions[faction_override] if(faction) @@ -123,9 +123,33 @@ O.pre_equip(H, TRUE) O.equip(H, TRUE) return + + var/pre_hat_ref = H.head ? REF(H.head) : null + var/pre_uniform_ref = H.w_uniform ? REF(H.w_uniform) : null + var/pre_suit_ref = H.wear_suit ? REF(H.wear_suit) : null + pre_equip(H, TRUE) . = equip(H, TRUE, FALSE, alt_title=alt_title) + // slightly hacky, but effectively what we're doing here is checking whether we want this preview mob to actually have the uniform we're putting onto it + // if not, we drop it from the inventory into nullspace, and then deleting it + // i don't THINK this'll make performance that much worse, considering how much we already do to equip the mob in the first place + // the reasoning for the ref checks is that we don't want to delete loadout uniforms, just the job ones, so we need to confirm the before and after + + var/equip_preview_mob = prefs.equip_preview_mob + + if(!(equip_preview_mob & EQUIP_PREVIEW_JOB_HAT) && H.head && REF(H.head) != pre_hat_ref) + H.drop_from_inventory(H.head) + qdel(H.head) + + if(!(equip_preview_mob & EQUIP_PREVIEW_JOB_UNIFORM) && H.w_uniform && REF(H.w_uniform) != pre_uniform_ref) + H.drop_from_inventory(H.w_uniform) + qdel(H.w_uniform) + + if(!(equip_preview_mob & EQUIP_PREVIEW_JOB_UNIFORM) && H.wear_suit && REF(H.wear_suit) != pre_suit_ref) + H.drop_from_inventory(H.wear_suit) + qdel(H.wear_suit) + /datum/job/proc/get_access(selected_title) SHOULD_NOT_SLEEP(TRUE) diff --git a/code/modules/client/preference_setup/general/03_body.dm b/code/modules/client/preference_setup/general/03_body.dm index 31a7e5d562c..13a358d4a41 100644 --- a/code/modules/client/preference_setup/general/03_body.dm +++ b/code/modules/client/preference_setup/general/03_body.dm @@ -214,8 +214,8 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O if (!pref.disabilities || !islist(pref.disabilities)) pref.disabilities = list() - if(!pref.bgstate || !(pref.bgstate in pref.bgstate_options)) - pref.bgstate = "000000" + if(!pref.bgstate || !(pref.bgstate in list_values(pref.bgstate_options))) + pref.bgstate = "plain_black" /datum/category_item/player_setup_item/general/body/content(var/mob/user) var/list/out = list() @@ -283,10 +283,14 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O out += "

" out += "Preview" - out += "
Cycle background" + out += "
Cycle Background" + out += "
Select Background" out += "
Set Preview Scale - [pref.scale_x] - [pref.scale_y]" out += "
[pref.equip_preview_mob & EQUIP_PREVIEW_LOADOUT ? "Hide loadout" : "Show loadout"]" out += "
[pref.equip_preview_mob & EQUIP_PREVIEW_JOB ? "Hide job gear" : "Show job gear"]" + out += "
[pref.equip_preview_mob & EQUIP_PREVIEW_JOB_HAT ? "Hide job hat" : "Show job hat"]" + out += "
[pref.equip_preview_mob & EQUIP_PREVIEW_JOB_UNIFORM ? "Hide job uniform" : "Show job uniform"]" + out += "
[pref.equip_preview_mob & EQUIP_PREVIEW_JOB_SUIT ? "Hide job suit" : "Show job suit"]" out += "" var/tail_spacing = FALSE @@ -894,7 +898,13 @@ var/global/list/valid_bloodtypes = list("A+", "A-", "B+", "B-", "AB+", "AB-", "O return TOPIC_REFRESH_UPDATE_PREVIEW else if(href_list["cycle_bg"]) - pref.bgstate = next_in_list(pref.bgstate, pref.bgstate_options) + pref.bgstate = next_in_assoc_list(pref.bgstate, pref.bgstate_options) + return TOPIC_REFRESH_UPDATE_PREVIEW + + else if(href_list["select_bg"]) + var/choice = tgui_input_list(user, "Which background would you like for your preview?", "Select Preview Background", pref.bgstate_options) + if(choice) + pref.bgstate = pref.bgstate_options[choice] return TOPIC_REFRESH_UPDATE_PREVIEW else if(href_list["set_preview_scale"]) diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm index c586cf0af9f..e80eb50371c 100644 --- a/code/modules/client/preferences.dm +++ b/code/modules/client/preferences.dm @@ -180,21 +180,29 @@ var/list/preferences_datums = list() var/savefile/loaded_character var/datum/category_collection/player_setup_collection/player_setup - var/bgstate = "000000" + var/bgstate = "plain_black" var/list/bgstate_options = list( - "FFFFFF", - "000000", - "tiled_preview", - "monotile_preview", - "dark_preview", - "wood", - "grass", - "reinforced", - "white_preview", - "freezer", - "carpet", - "reinforced" - ) + "Plain Black" = "plain_black", + "Plain White" = "plain_white", + "Monotile" = "monotile", + "Tiles" = "tile", + "Dark Tiles" = "dark_tile", + "Freezer Tiles" = "freezer_tile", + "Reinforced Tiles" = "reinforced", + "Wood Floor" = "wood", + "Grass" = "grass", + "Red Carpet" = "carpet_red", + "Cyan Carpet" = "carpet_cyan", + "Green Carpet" = "carpet_green", + "Purple Carpet" = "carpet_purple", + "Magenta Carpet" = "carpet_magenta", + "Rubber Carpet" = "carpet_rubber", + "Blue Circuits" = "circuit_blue", + "Green Circuits" = "circuit_green", + "Asteroid Turf" = "asteroid", + "Desert Turf" = "desert", + "Space" = "space" + ) var/fov_cone_alpha = 255 @@ -283,7 +291,7 @@ var/list/preferences_datums = list() BG = new BG.appearance_flags = TILE_BOUND|PIXEL_SCALE|NO_CLIENT_COLOR BG.layer = TURF_LAYER - BG.icon = 'icons/turf/flooring/tiles.dmi' + BG.icon = 'icons/turf/flooring/character_preview.dmi' LAZYSET(char_render_holders, "BG", BG) client.screen |= BG BG.icon_state = bgstate diff --git a/code/modules/mob/abstract/new_player/preferences_setup.dm b/code/modules/mob/abstract/new_player/preferences_setup.dm index d02b822f28b..eb42c9cfc21 100644 --- a/code/modules/mob/abstract/new_player/preferences_setup.dm +++ b/code/modules/mob/abstract/new_player/preferences_setup.dm @@ -221,7 +221,7 @@ SSjobs.EquipCustom(mannequin, previewJob, src, leftovers, null, used_slots) if((equip_preview_mob & EQUIP_PREVIEW_JOB) && previewJob) - previewJob.equip_preview(mannequin, player_alt_titles[previewJob.title], faction) + previewJob.equip_preview(mannequin, src, player_alt_titles[previewJob.title], faction) if((equip_preview_mob & EQUIP_PREVIEW_LOADOUT) && leftovers.len) SSjobs.EquipCustomDeferred(mannequin, src, leftovers, used_slots) diff --git a/html/changelogs/geeves-preview_stuff.yml b/html/changelogs/geeves-preview_stuff.yml new file mode 100644 index 00000000000..cecbf4dc5cb --- /dev/null +++ b/html/changelogs/geeves-preview_stuff.yml @@ -0,0 +1,7 @@ +author: Geeves + +delete-after: True + +changes: + - rscadd: "Added more backgrounds to choose from in the character preview screen." + - rscadd: "You can now selectively hide your job uniform, suit, or hat." diff --git a/icons/turf/flooring/character_preview.dmi b/icons/turf/flooring/character_preview.dmi new file mode 100644 index 0000000000000000000000000000000000000000..eeb361a968646ac5d4e1a5ae99c6cf15e83bbeca GIT binary patch literal 12199 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