diff --git a/code/__DEFINES/modular_computer.dm b/code/__DEFINES/modular_computer.dm index 424b7ea3d0f..0d57f2ed98d 100644 --- a/code/__DEFINES/modular_computer.dm +++ b/code/__DEFINES/modular_computer.dm @@ -51,3 +51,8 @@ #define NTNET_GOOD_SIGNAL 2 ///Using a Computer, ethernet-connected. #define NTNET_ETHERNET_SIGNAL 3 + +/// The default ringtone of the Messenger app. +#define MESSENGER_RINGTONE_DEFAULT "beep" +/// The maximum length of the ringtone of the Messenger app. +#define MESSENGER_RINGTONE_MAX_LENGTH 20 diff --git a/code/modules/client/preferences/_preference.dm b/code/modules/client/preferences/_preference.dm index 27d987b9b74..6d77a5f8451 100644 --- a/code/modules/client/preferences/_preference.dm +++ b/code/modules/client/preferences/_preference.dm @@ -527,7 +527,7 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key()) "step" = step, ) -/// A prefernece whose value is always TRUE or FALSE +/// A preference whose value is always TRUE or FALSE /datum/preference/toggle abstract_type = /datum/preference/toggle @@ -542,3 +542,27 @@ GLOBAL_LIST_INIT(preference_entries_by_key, init_preference_entries_by_key()) /datum/preference/toggle/is_valid(value) return value == TRUE || value == FALSE + + +/// A string-based preference accepting arbitrary string values entered by the user, with a maximum length. +/datum/preference/text + abstract_type = /datum/preference/text + + /// What is the maximum length of the value allowed in this field? + var/maximum_value_length = 256 + + /// Should we strip HTML the input or simply restrict it to the maximum_value_length? + var/should_strip_html = TRUE + + +/datum/preference/text/deserialize(input, datum/preferences/preferences) + return should_strip_html ? STRIP_HTML_SIMPLE(input, maximum_value_length) : copytext(input, 1, maximum_value_length) + +/datum/preference/text/create_default_value() + return "" + +/datum/preference/text/is_valid(value) + return istext(value) && length(value) < maximum_value_length + +/datum/preference/text/compile_constant_data() + return list("maximum_length" = maximum_value_length) diff --git a/code/modules/client/preferences/pda_ringtone.dm b/code/modules/client/preferences/pda_ringtone.dm new file mode 100644 index 00000000000..f5ea26c9ef8 --- /dev/null +++ b/code/modules/client/preferences/pda_ringtone.dm @@ -0,0 +1,19 @@ +/** + * This is the preference for the player's SpaceMessenger ringtone. + * Currently only applies to humans spawned in with a job, as it's hooked + * into `/datum/job/proc/after_spawn()`. + */ +/datum/preference/text/pda_ringtone + savefile_key = "pda_ringtone" + category = PREFERENCE_CATEGORY_NON_CONTEXTUAL + savefile_identifier = PREFERENCE_CHARACTER + maximum_value_length = MESSENGER_RINGTONE_MAX_LENGTH + + +/datum/preference/text/pda_ringtone/create_default_value() + return MESSENGER_RINGTONE_DEFAULT + + +// Returning false here because this pref is handled a little differently, due to its dependency on the existence of a PDA. +/datum/preference/text/pda_ringtone/apply_to_human(mob/living/carbon/human/target, value, datum/preferences/preferences) + return FALSE diff --git a/code/modules/jobs/job_types/_job.dm b/code/modules/jobs/job_types/_job.dm index 848722d1062..2f862eeeaf1 100644 --- a/code/modules/jobs/job_types/_job.dm +++ b/code/modules/jobs/job_types/_job.dm @@ -155,6 +155,7 @@ if(!ishuman(spawned)) return + var/mob/living/carbon/human/spawned_human = spawned var/list/roundstart_experience if(!config) //Needed for robots. @@ -166,9 +167,8 @@ roundstart_experience = skills if(roundstart_experience) - var/mob/living/carbon/human/experiencer = spawned for(var/i in roundstart_experience) - experiencer.mind.adjust_experience(i, roundstart_experience[i], TRUE) + spawned_human.mind.adjust_experience(i, roundstart_experience[i], TRUE) /datum/job/proc/announce_job(mob/living/joining_mob) if(head_announce) @@ -321,34 +321,46 @@ if(client?.is_veteran() && client?.prefs.read_preference(/datum/preference/toggle/playtime_reward_cloak)) neck = /obj/item/clothing/neck/cloak/skill_reward/playing -/datum/outfit/job/post_equip(mob/living/carbon/human/H, visualsOnly = FALSE) +/datum/outfit/job/post_equip(mob/living/carbon/human/equipped, visualsOnly = FALSE) if(visualsOnly) return - var/datum/job/J = SSjob.GetJobType(jobtype) - if(!J) - J = SSjob.GetJob(H.job) + var/datum/job/equipped_job = SSjob.GetJobType(jobtype) + + if(!equipped_job) + equipped_job = SSjob.GetJob(equipped.job) + + var/obj/item/card/id/card = equipped.wear_id - var/obj/item/card/id/card = H.wear_id if(istype(card)) ADD_TRAIT(card, TRAIT_JOB_FIRST_ID_CARD, ROUNDSTART_TRAIT) shuffle_inplace(card.access) // Shuffle access list to make NTNet passkeys less predictable - card.registered_name = H.real_name - if(H.age) - card.registered_age = H.age + card.registered_name = equipped.real_name + + if(equipped.age) + card.registered_age = equipped.age + card.update_label() card.update_icon() - var/datum/bank_account/B = SSeconomy.bank_accounts_by_id["[H.account_id]"] - if(B && B.account_id == H.account_id) - card.registered_account = B - B.bank_cards += card - H.sec_hud_set_ID() + var/datum/bank_account/account = SSeconomy.bank_accounts_by_id["[equipped.account_id]"] - var/obj/item/modular_computer/tablet/pda/PDA = H.get_item_by_slot(pda_slot) - if(istype(PDA)) - PDA.saved_identification = H.real_name - PDA.saved_job = J.title - PDA.UpdateDisplay() + if(account && account.account_id == equipped.account_id) + card.registered_account = account + account.bank_cards += card + + equipped.sec_hud_set_ID() + + var/obj/item/modular_computer/tablet/pda/pda = equipped.get_item_by_slot(pda_slot) + + if(istype(pda)) + pda.saved_identification = equipped.real_name + pda.saved_job = equipped_job.title + pda.UpdateDisplay() + + var/client/equipped_client = GLOB.directory[ckey(equipped.mind?.key)] + + if(equipped_client) + pda.update_ringtone(equipped_client) /datum/outfit/job/get_chameleon_disguise_info() diff --git a/code/modules/modular_computers/computers/item/tablet.dm b/code/modules/modular_computers/computers/item/tablet.dm index d57d5138726..34cbd30e6a2 100644 --- a/code/modules/modular_computers/computers/item/tablet.dm +++ b/code/modules/modular_computers/computers/item/tablet.dm @@ -146,6 +146,32 @@ explosion(src, devastation_range = -1, heavy_impact_range = -1, light_impact_range = 2, flash_range = 3) qdel(src) + +/** + * A simple helper proc that applies the client's ringtone prefs to the tablet's messenger app, + * if it has one. + * + * Arguments: + * * ringtone_client - The client whose prefs we'll use to set the ringtone of this PDA. + */ +/obj/item/modular_computer/tablet/proc/update_ringtone(client/ringtone_client) + if(!ringtone_client) + return + + var/new_ringtone = ringtone_client?.prefs?.read_preference(/datum/preference/text/pda_ringtone) + + if(!new_ringtone || new_ringtone == MESSENGER_RINGTONE_DEFAULT) + return + + var/obj/item/computer_hardware/hard_drive/drive = all_components[MC_HDD] + + if(!drive) + return + + for(var/datum/computer_file/program/messenger/messenger_app in drive.stored_files) + messenger_app.ringtone = new_ringtone + + // SUBTYPES /obj/item/modular_computer/tablet/syndicate_contract_uplink diff --git a/code/modules/modular_computers/file_system/programs/ntmessenger.dm b/code/modules/modular_computers/file_system/programs/ntmessenger.dm index e05cfd49a43..ef41c1c718a 100644 --- a/code/modules/modular_computers/file_system/programs/ntmessenger.dm +++ b/code/modules/modular_computers/file_system/programs/ntmessenger.dm @@ -15,7 +15,7 @@ alert_able = TRUE /// The current ringtone (displayed in the chat when a message is received). - var/ringtone = "beep" + var/ringtone = MESSENGER_RINGTONE_DEFAULT /// Whether or not the ringtone is currently on. var/ringer_status = TRUE /// Whether or not we're sending and receiving messages. @@ -114,7 +114,7 @@ switch(action) if("PDA_ringSet") - var/new_ringtone = tgui_input_text(usr, "Enter a new ringtone", "Ringtone", ringtone, 20) + var/new_ringtone = tgui_input_text(usr, "Enter a new ringtone", "Ringtone", ringtone, MESSENGER_RINGTONE_MAX_LENGTH) var/mob/living/usr_mob = usr if(!new_ringtone || !in_range(computer, usr_mob) || computer.loc != usr_mob) return diff --git a/tgstation.dme b/tgstation.dme index 93b41103508..3a9ff02fd38 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -2717,6 +2717,7 @@ #include "code\modules\client\preferences\names.dm" #include "code\modules\client\preferences\ooc.dm" #include "code\modules\client\preferences\parallax.dm" +#include "code\modules\client\preferences\pda_ringtone.dm" #include "code\modules\client\preferences\persistent_scars.dm" #include "code\modules\client\preferences\phobia.dm" #include "code\modules\client\preferences\pixel_size.dm" diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx index c7b53900eaa..cc524404ca3 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/base.tsx @@ -3,7 +3,7 @@ import { BooleanLike, classes } from 'common/react'; import { ComponentType, createComponentVNode, InfernoNode } from 'inferno'; import { VNodeFlags } from 'inferno-vnode-flags'; import { sendAct, useBackend, useLocalState } from '../../../../backend'; -import { Box, Button, Dropdown, NumberInput, Stack } from '../../../../components'; +import { Box, Button, Dropdown, Input, NumberInput, Stack } from '../../../../components'; import { createSetPreference, PreferencesMenuData } from '../../data'; import { ServerPreferencesFetcher } from '../../ServerPreferencesFetcher'; @@ -344,3 +344,24 @@ export const FeatureValueInput = ( /> ); }; + +export type FeatureShortTextData = { + maximum_length: number; +}; + +export const FeatureShortTextInput = ( + props: FeatureValueProps +) => { + if (!props.serverData) { + return Loading...; + } + + return ( + props.handleSetValue(value)} + /> + ); +}; diff --git a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/pda.tsx b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/pda.tsx index 0c4092f3e45..b79f145d12b 100644 --- a/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/pda.tsx +++ b/tgui/packages/tgui/interfaces/PreferencesMenu/preferences/features/character_preferences/pda.tsx @@ -1,4 +1,4 @@ -import { Feature, FeatureColorInput, FeatureDropdownInput } from '../base'; +import { Feature, FeatureColorInput, FeatureDropdownInput, FeatureShortTextInput } from '../base'; export const pda_color: Feature = { name: 'PDA color', @@ -13,3 +13,9 @@ export const pda_style: Feature = { description: 'The style of your equipped PDA. Changes font.', component: FeatureDropdownInput, }; + +export const pda_ringtone: Feature = { + name: 'PDA Ringtone', + description: "The ringtone you'll hear when someone sends you a PDA message.", + component: FeatureShortTextInput, +};