[MIRROR] Embedded Examine Info (#11086)

Co-authored-by: eghughguhhhhhh <Hawoogabooga@gmail.com>
This commit is contained in:
CHOMPStation2StaffMirrorBot
2025-06-18 13:10:58 -07:00
committed by GitHub
parent addaf7b874
commit d1e9a9fbf0
15 changed files with 310 additions and 64 deletions

View File

@@ -1,16 +1,14 @@
// Modes for examine text output
#define EXAMINE_MODE_DEFAULT 0
#define EXAMINE_MODE_INCLUDE_USAGE 1
#define EXAMINE_MODE_SWITCH_TO_PANEL 2
#define EXAMINE_MODE_SLIM "Slim"
#define EXAMINE_MODE_VERBOSE "Verbose"
#define EXAMINE_MODE_SWITCH_TO_PANEL "Switch To Panel"
// Should be one higher than the above
#define EXAMINE_MODE_MAX 3
// Modes for parsing multilingual speech
#define MULTILINGUAL_DEFAULT 0
#define MULTILINGUAL_SPACE 1
#define MULTILINGUAL_DOUBLE_DELIMITER 2
#define MULTILINGUAL_OFF 3
#define MULTILINGUAL_DEFAULT "Default"
#define MULTILINGUAL_SPACE "Space"
#define MULTILINGUAL_DOUBLE_DELIMITER "Double Delimiter"
#define MULTILINGUAL_OFF "Single Language"
#define MULTILINGUAL_MODE_MAX 4

View File

@@ -3,6 +3,9 @@
// Adds a generic box around whatever message you're sending in chat. Really makes things stand out.
#define examine_block(str) ("<div class='examine_block'>" + str + "</div>")
//for the foldout stuff
#define span_details(title, content) ("<details>"+"<summary>" + title + "</summary>" + content + "</details>")
// Filtered both under OOC!
#define span_ooc(str) ("<span class='ooc'>" + str + "</span>")
#define span_aooc(str) ("<span class='aooc'>" + str + "</span>")

View File

@@ -170,7 +170,11 @@ SUBSYSTEM_DEF(statpanels)
if(description_holders["antag"])
examine_update += span_red(span_bold("[description_holders["antag"]]")) + "<br />" //Red, malicious antag-related text
target.stat_panel.send_message("update_examine", list("EX" = examine_update, "UPD" = target.prefs.examine_text_mode == EXAMINE_MODE_SWITCH_TO_PANEL))
var/update_panel = FALSE
if(target.prefs?.read_preference(/datum/preference/choiced/examine_mode) == EXAMINE_MODE_SWITCH_TO_PANEL)
update_panel = TRUE
target.stat_panel.send_message("update_examine", list("EX" = examine_update, "UPD" = update_panel))
/datum/controller/subsystem/statpanels/proc/set_tickets_tab(client/target)
/* CHOMPRemove Start, our tickets are handled differently

View File

@@ -199,9 +199,6 @@
var/examine_text = replacetext(get_examine_desc(), "||", "")
var/list/output = list("[icon2html(src,user.client)] That's [f_name] [suffix]", examine_text)
if(user.client?.prefs.examine_text_mode == EXAMINE_MODE_INCLUDE_USAGE)
output += description_info
SEND_SIGNAL(src, COMSIG_PARENT_EXAMINE, user, output)
return output

View File

@@ -121,9 +121,6 @@ var/list/preferences_datums = list()
var/lastnews // Hash of last seen lobby news content.
var/lastlorenews //ID of last seen lore news article.
var/examine_text_mode = 0 // Just examine text, include usage (description_info), switch to examine panel.
var/multilingual_mode = 0 // Default behaviour, delimiter-key-space, delimiter-key-delimiter, off
// THIS IS NOT SAVED
// WE JUST HAVE NOWHERE ELSE TO STORE IT
var/list/action_button_screen_locs

View File

@@ -61,3 +61,25 @@
savefile_key = "PAIN_FREQUENCY"
default_value = FALSE
savefile_identifier = PREFERENCE_PLAYER
/datum/preference/choiced/examine_mode
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
savefile_key = "EXAMINE_MODE"
savefile_identifier = PREFERENCE_PLAYER
/datum/preference/choiced/examine_mode/init_possible_values()
return list(EXAMINE_MODE_SLIM,EXAMINE_MODE_VERBOSE,EXAMINE_MODE_SWITCH_TO_PANEL)
/datum/preference/choiced/examine_mode/create_default_value()
return EXAMINE_MODE_VERBOSE
/datum/preference/choiced/multilingual_mode
category = PREFERENCE_CATEGORY_GAME_PREFERENCES
savefile_identifier = PREFERENCE_PLAYER
savefile_key = "MULTI_LANGUAGE_YAP_MODE"
/datum/preference/choiced/multilingual_mode/init_possible_values()
return list(MULTILINGUAL_DEFAULT,MULTILINGUAL_SPACE,MULTILINGUAL_DOUBLE_DELIMITER, MULTILINGUAL_OFF)
/datum/preference/choiced/multilingual_mode/create_default_value()
return MULTILINGUAL_DEFAULT

View File

@@ -12,38 +12,3 @@
to_chat(src,"You will [(prefs.be_special & role_flag) ? "now" : "no longer"] be considered for [role] events (where possible).")
feedback_add_details("admin_verb","TBeSpecial") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
// Not attached to a pref datum because those are strict binary toggles
/client/verb/toggle_examine_mode()
set name = "Toggle Examine Mode"
set category = "Preferences.Game"
set desc = "Toggle the additional behaviour of examining things."
prefs.examine_text_mode++
prefs.examine_text_mode %= EXAMINE_MODE_MAX // This cycles through them because if you're already specifically being routed to the examine panel, you probably don't need to have the extra text printed to chat
switch(prefs.examine_text_mode) // ... And I only wanted to add one verb
if(EXAMINE_MODE_DEFAULT)
to_chat(src, span_filter_system("Examining things will only output the base examine text, and you will not be redirected to the examine panel automatically."))
if(EXAMINE_MODE_INCLUDE_USAGE)
to_chat(src, span_filter_system("Examining things will also print any extra usage information normally included in the examine panel to the chat."))
if(EXAMINE_MODE_SWITCH_TO_PANEL)
to_chat(src, span_filter_system("Examining things will direct you to the examine panel, where you can view extended information about the thing."))
/client/verb/toggle_multilingual_mode()
set name = "Toggle Multilingual Mode"
set category = "Preferences.Character"
set desc = "Toggle the behaviour of multilingual speech parsing."
prefs.multilingual_mode++
prefs.multilingual_mode %= MULTILINGUAL_MODE_MAX // Cycles through the various options
switch(prefs.multilingual_mode)
if(MULTILINGUAL_DEFAULT)
to_chat(src, span_filter_system("Multilingual parsing will only check for the delimiter-key combination (,0galcom-2tradeband)."))
if(MULTILINGUAL_SPACE)
to_chat(src, span_filter_system("Multilingual parsing will enforce a space after the delimiter-key combination (,0 galcom -2still galcom). The extra space will be consumed by the pattern-matching."))
if(MULTILINGUAL_DOUBLE_DELIMITER)
to_chat(src, span_filter_system("Multilingual parsing will enforce the a language delimiter after the delimiter-key combination (,0,galcom -2 still galcom). The extra delimiter will be consumed by the pattern-matching."))
if(MULTILINGUAL_OFF)
to_chat(src, span_filter_system("Multilingual parsing is now disabled. Entire messages will be in the language specified at the start of the message."))

View File

@@ -76,16 +76,30 @@
return "an average attack speed"
/obj/item/get_description_info()
var/weapon_stats = description_info + "\
<br>"
var/list/weapon_stats = list()
if(description_info)
weapon_stats += description_info
if(force)
weapon_stats += "\nIf used in melee, it deals [describe_power()] [sharp ? "sharp" : "blunt"] damage, [describe_penetration()], and has [describe_speed()]."
weapon_stats += "If used in melee, it deals [describe_power()] [sharp ? "sharp" : "blunt"] damage, [describe_penetration()], and has [describe_speed()]."
if(throwforce)
weapon_stats += "\nIf thrown, it would deal [describe_throwpower()] [sharp ? "sharp" : "blunt"] damage."
weapon_stats += "If thrown, it would deal [describe_throwpower()] [sharp ? "sharp" : "blunt"] damage."
if(can_cleave)
weapon_stats += "\nIt is capable of hitting multiple targets with a single swing."
weapon_stats += "It is capable of hitting multiple targets with a single swing."
if(reach > 1)
weapon_stats += "\nIt can attack targets up to [reach] tiles away, and can attack over certain objects."
weapon_stats += "It can attack targets up to [reach] tiles away, and can attack over certain objects."
return weapon_stats
if(weapon_stats.len < 1)
return ""
var/assembled_string = ""
for(var/index in 1 to weapon_stats.len)
var/msg = weapon_stats[index]
if(index != weapon_stats.len)
msg += "\n"
assembled_string += msg
if(msg == description_info) //keeping the formatting as identical as I can
assembled_string += "<br>"
return assembled_string

View File

@@ -77,12 +77,46 @@
var/list/results = A.examine(src)
if(!results || !results.len)
results = list("You were unable to examine that. Tell a developer!")
results += embedded_info(A)
var/final_string = span_infoplain("[jointext(results, "<br>")]")
if(ismob(A)) // mob descriptions matter more than others
if(ismob(A) || client?.prefs?.read_preference(/datum/preference/choiced/examine_mode) == EXAMINE_MODE_VERBOSE) // mob descriptions matter more than others, & it looks weird to have dropdowns outside the box.
final_string = examine_block(final_string)
to_chat(src, final_string)
update_examine_panel(A)
/mob/proc/embedded_info(var/atom/A)
. = ""
if(!(client?.prefs?.read_preference(/datum/preference/choiced/examine_mode) == EXAMINE_MODE_VERBOSE))
return
if(!client?.prefs?.read_preference(/datum/preference/toggle/vchat_enable))
return //sorry oldchat
//do pref check here
var/desc_info_temp = A.get_description_info()
if(desc_info_temp)
. += span_details(" | Information",desc_info_temp)
var/fluff_info_temp = A.get_description_fluff()
if(fluff_info_temp && fluff_info_temp != "")
var/title = "🪐 | Flavor Information"
if(isliving(A)) //ehhh
var/mob/living/B = A
if(B.flavor_text)
title = "🔍 | Flavor Text"
. += span_details(title,fluff_info_temp)
var/is_antagish = ((mind && mind.special_role) || isobserver(src)) //ghosts don't have minds
var/antag_info_temp = A.get_description_antag()
if(is_antagish && antag_info_temp)
. += span_details("🏴‍☠️ | Antag Information",antag_info_temp)
var/list/interaction_info = A.get_description_interaction()
if(interaction_info.len > 0)
var/temp = ""
for(var/a in interaction_info)
temp += a + "\n"
. += span_details("🛠️ | Interaction Information",temp)
/mob/proc/update_examine_panel(var/atom/A)
if(client)
var/is_antag = ((mind && mind.special_role) || isobserver(src)) //ghosts don't have minds
@@ -90,6 +124,7 @@
SSstatpanels.set_examine_tab(client)
/mob/verb/mob_examine()
set name = "Mob Examine"
set desc = "Allows one to examine mobs they can see, even from inside of bellies and objects."

View File

@@ -179,6 +179,7 @@
// The first character in the selection will always be the prefix (if this is a valid language invocation)
var/prefix = copytext(selection, 1, 2)
var/language_key = copytext(selection, 2, 3)
var/multilingual_mode = client?.prefs?.read_preference(/datum/preference/choiced/multilingual_mode)
if(is_language_prefix(prefix))
// Okay, we're definitely now trying to invoke a language (probably)
// This "[]" is probably unnecessary but BYOND will runtime if a number is used
@@ -187,14 +188,14 @@
L = language_keys[language_key]
// MULTILINGUAL_SPACE enforces a space after the language key
if(client && (client.prefs.multilingual_mode == MULTILINGUAL_SPACE) && (text2ascii(copytext(selection, 3, 4)) != 32)) // If we're looking for a space and we don't find one
if(client && (multilingual_mode == MULTILINGUAL_SPACE) && (text2ascii(copytext(selection, 3, 4)) != 32)) // If we're looking for a space and we don't find one
continue
// MULTILINGUAL_DOUBLE_DELIMITER enforces a delimiter (valid prefix) after the language key
if(client && (client.prefs.multilingual_mode == MULTILINGUAL_DOUBLE_DELIMITER) && !is_language_prefix(copytext(selection, 3, 4)))
if(client && (multilingual_mode == MULTILINGUAL_DOUBLE_DELIMITER) && !is_language_prefix(copytext(selection, 3, 4)))
continue
if(client && (client.prefs.multilingual_mode in list(MULTILINGUAL_DEFAULT)))
if(client && (multilingual_mode in list(MULTILINGUAL_DEFAULT)))
selection = copytext(selection, 1, 3) // These modes only use two characters, not three
// It's kinda silly that we have to check L != null and this isn't done for us by can_speak (it runtimes instead), but w/e
@@ -211,7 +212,7 @@
prefixes[++prefixes.len] = list(get_default_language(), i, i)
// If multilingualism is disabled, then after the first pass we're guaranteed to have either found a language key at the start, or else there isn't one and we're using the default for the whole message
if(client && (client.prefs.multilingual_mode == MULTILINGUAL_OFF))
if(client && (multilingual_mode == MULTILINGUAL_OFF))
break
return prefixes

View File

@@ -1486,3 +1486,50 @@ $border-width-px: $border-width * 1px;
.nif {
color: hsla(180, 100%, 50%, 0.801);
}
details {
width: 80%;
background: hsl(220, 5%, 11%);
margin-bottom: 0.5rem;
box-shadow: 0 0.1rem 1rem -0.5rem rgba(0, 0, 0, 0.4);
border-radius: 5px;
overflow: hidden;
border-color: #343b3d;
border: 1px solid hsl(214, 38%, 74%);
}
summary {
padding: 1rem;
display: block;
background: hsl(220, 5%, 11%);
padding-left: 2.2rem;
position: relative;
cursor: pointer;
user-select: none;
}
summary:before {
content: '';
border-width: 0.4rem;
border-style: solid;
border-color: transparent transparent transparent hsl(214, 38%, 74%);
position: absolute;
top: 1.3rem;
left: 1rem;
transform: rotate(0);
transform-origin: 0.2rem 50%;
transition: 0.25s transform ease;
}
details[open] > summary:before {
transform: rotate(90deg);
}
details summary::-webkit-details-marker {
display: none;
}
details > ul {
padding-bottom: 1rem;
margin-bottom: 0;
}

View File

@@ -1508,3 +1508,49 @@ $border-width-px: $border-width * 1px;
.nif {
color: hsl(180, 100%, 27%);
}
details {
width: 80%;
background: hsl(202, 44%, 96%);
margin-bottom: 0.5rem;
box-shadow: 0 0.1rem 1rem -0.5rem rgba(0, 0, 0, 0.4);
border-radius: 5px;
overflow: hidden;
border-color: #343b3d;
border: 1px solid hsl(215, 39%, 11%);
}
summary {
padding: 1rem;
display: block;
background: hsl(202, 44%, 96%);
padding-left: 2.2rem;
position: relative;
cursor: pointer;
user-select: none;
}
summary:before {
content: '';
border-width: 0.4rem;
border-style: solid;
border-color: transparent transparent transparent hsl(215, 39%, 11%);
position: absolute;
top: 1.3rem;
left: 1rem;
transform: rotate(0);
transform-origin: 0.2rem 50%;
transition: 0.25s transform ease;
}
details[open] > summary:before {
transform: rotate(90deg);
}
details summary::-webkit-details-marker {
display: none;
}
details > ul {
padding-bottom: 1rem;
margin-bottom: 0;
}

View File

@@ -1483,3 +1483,49 @@ $border-width-px: $border-width * 1px;
background-color: inherit;
color: inherit;
}
details {
width: 80%;
background: hsl(220, 5%, 11%);
margin-bottom: 0.5rem;
box-shadow: 0 0.1rem 1rem -0.5rem rgba(0, 0, 0, 0.4);
border-radius: 5px;
overflow: hidden;
border-color: #343b3d;
border: 1px solid hsl(214, 38%, 74%);
}
summary {
padding: 1rem;
display: block;
background: hsl(220, 5%, 11%);
padding-left: 2.2rem;
position: relative;
cursor: pointer;
user-select: none;
}
summary:before {
content: '';
border-width: 0.4rem;
border-style: solid;
border-color: transparent transparent transparent hsl(214, 38%, 74%);
position: absolute;
top: 1.3rem;
left: 1rem;
transform: rotate(0);
transform-origin: 0.2rem 50%;
transition: 0.25s transform ease;
}
details[open] > summary:before {
transform: rotate(90deg);
}
details summary::-webkit-details-marker {
display: none;
}
details > ul {
padding-bottom: 1rem;
margin-bottom: 0;
}

View File

@@ -1502,3 +1502,49 @@ $border-width-px: $border-width * 1px;
background-color: inherit;
color: inherit;
}
details {
width: 80%;
background: hsl(202, 44%, 96%);
margin-bottom: 0.5rem;
box-shadow: 0 0.1rem 1rem -0.5rem rgba(0, 0, 0, 0.4);
border-radius: 5px;
overflow: hidden;
border-color: #343b3d;
border: 1px solid hsl(215, 39%, 11%);
}
summary {
padding: 1rem;
display: block;
background: hsl(202, 44%, 96%);
padding-left: 2.2rem;
position: relative;
cursor: pointer;
user-select: none;
}
summary:before {
content: '';
border-width: 0.4rem;
border-style: solid;
border-color: transparent transparent transparent hsl(215, 39%, 11%);
position: absolute;
top: 1.3rem;
left: 1rem;
transform: rotate(0);
transform-origin: 0.2rem 50%;
transition: 0.25s transform ease;
}
details[open] > summary:before {
transform: rotate(90deg);
}
details summary::-webkit-details-marker {
display: none;
}
details > ul {
padding-bottom: 1rem;
margin-bottom: 0;
}

View File

@@ -1,4 +1,9 @@
import { CheckboxInput, type FeatureToggle } from '../base';
import {
CheckboxInput,
type FeatureChoiced,
type FeatureToggle,
} from '../base';
import { FeatureDropdownInput } from '../dropdowns';
export const CHAT_SHOWICONS: FeatureToggle = {
name: 'Chat Tags',
@@ -71,3 +76,23 @@ export const PAIN_FREQUENCY: FeatureToggle = {
'When enabled, reduces the amount of pain messages for minor wounds that you see.',
component: CheckboxInput,
};
export const EXAMINE_MODE: FeatureChoiced = {
name: 'Examine Mode',
category: 'CHAT',
description:
'Choose how you want to examine items. "Verbose" will include all information found in the examine panel as foldable groups, "Switch To Panel" will switch you to the examine panel upon examining, and "Slim" will do neither. ',
component: FeatureDropdownInput,
};
export const MULTI_LANGUAGE_YAP_MODE: FeatureChoiced = {
name: 'Multilingual Speech Parsing Mode',
category: 'CHAT',
description: `
Default: Multilingual parsing will only check for the delimiter-key combination (e.g., ,0galcom-2tradeband).\n
Space: Multilingual parsing will enforce a space after the delimiter-key combination (,0 galcom -2still galcom). The extra space will be consumed by the pattern-matching.\n
Double Delimiter: Multilingual parsing will enforce the language delimiter after the delimiter-key combination (,0,galcom -2 still galcom). The extra delimiter will be consumed by the pattern-matching.\n
Off: Multilingual parsing is now disabled. Entire messages will be in the language specified at the start of the message.
`,
component: FeatureDropdownInput,
};