From 843559859b7423046bf6a36801c6bd5e9962507a Mon Sep 17 00:00:00 2001 From: Nadyr Date: Mon, 21 Oct 2024 22:18:56 -0400 Subject: [PATCH 01/26] Ports in-round record updates --- code/game/machinery/computer/medical.dm | 10 ++ code/game/machinery/computer/security.dm | 10 ++ code/game/machinery/computer/skills.dm | 10 ++ code/modules/client/record_updator.dm | 129 ++++++++++++++++++ .../GeneralRecords/GeneralRecordsOptions.tsx | 8 ++ .../GeneralRecordsViewGeneral.tsx | 1 + .../MedicalRecords/MedicalRecordsOptions.tsx | 8 ++ .../MedicalRecordsViewMedical.tsx | 15 +- .../SecurityRecordsOptions.tsx | 8 ++ .../SecurityRecordsViewSecurity.tsx | 21 ++- vorestation.dme | 1 + 11 files changed, 214 insertions(+), 7 deletions(-) create mode 100644 code/modules/client/record_updator.dm diff --git a/code/game/machinery/computer/medical.dm b/code/game/machinery/computer/medical.dm index 1fb0455476..22e3fb90c9 100644 --- a/code/game/machinery/computer/medical.dm +++ b/code/game/machinery/computer/medical.dm @@ -296,6 +296,16 @@ active1 = general_record active2 = medical_record screen = MED_DATA_RECORD + if("sync_r") + if(active2) + set_temp(client_update_record(src,usr)) + if("edit_notes") + // The modal input in tgui is busted for this sadly... + var/new_notes = strip_html_simple(tgui_input_text(usr,"Enter new information here.","Character Preference", html_decode(active2.fields["notes"]), MAX_RECORD_LENGTH, TRUE, prevent_enter = TRUE), MAX_RECORD_LENGTH) + if(usr.Adjacent(src)) + if(new_notes != "" || tgui_alert(usr, "Are you sure you want to delete the current record's notes?", "Confirm Delete", list("Delete", "No")) == "Delete") + if(usr.Adjacent(src)) + active2.fields["notes"] = new_notes if("new") if(istype(active1, /datum/data/record) && !istype(active2, /datum/data/record)) var/datum/data/record/R = new /datum/data/record() diff --git a/code/game/machinery/computer/security.dm b/code/game/machinery/computer/security.dm index 1be57d146e..9ed9242767 100644 --- a/code/game/machinery/computer/security.dm +++ b/code/game/machinery/computer/security.dm @@ -270,6 +270,16 @@ qdel(active1) if(active2) qdel(active2) + if("sync_r") + if(active2) + set_temp(client_update_record(src,usr)) + if("edit_notes") + // The modal input in tgui is busted for this sadly... + var/new_notes = strip_html_simple(tgui_input_text(usr,"Enter new information here.","Character Preference", html_decode(active2.fields["notes"]), MAX_RECORD_LENGTH, TRUE, prevent_enter = TRUE), MAX_RECORD_LENGTH) + if(usr.Adjacent(src)) + if(new_notes != "" || tgui_alert(usr, "Are you sure you want to delete the current record's notes?", "Confirm Delete", list("Delete", "No")) == "Delete") + if(usr.Adjacent(src)) + active2.fields["notes"] = new_notes if("d_rec") var/datum/data/record/general_record = locate(params["d_rec"] || "") if(!data_core.general.Find(general_record)) diff --git a/code/game/machinery/computer/skills.dm b/code/game/machinery/computer/skills.dm index 57524d95fd..9be405d36d 100644 --- a/code/game/machinery/computer/skills.dm +++ b/code/game/machinery/computer/skills.dm @@ -214,6 +214,16 @@ for(var/datum/data/record/R in data_core.general) qdel(R) set_temp("All employment records deleted.") + if("sync_r") + if(active1) + set_temp(client_update_record(src,active1,usr)) + if("edit_notes") + // The modal input in tgui is busted for this sadly... + var/new_notes = strip_html_simple(tgui_input_text(usr,"Enter new information here.","Character Preference", html_decode(active1.fields["notes"]), MAX_RECORD_LENGTH, TRUE, prevent_enter = TRUE), MAX_RECORD_LENGTH) + if(usr.Adjacent(src)) + if(new_notes != "" || tgui_alert(usr, "Are you sure you want to delete the current record's notes?", "Confirm Delete", list("Delete", "No")) == "Delete") + if(usr.Adjacent(src)) + active1.fields["notes"] = new_notes if("del_r") if(PDA_Manifest) PDA_Manifest.Cut() diff --git a/code/modules/client/record_updator.dm b/code/modules/client/record_updator.dm new file mode 100644 index 0000000000..de802eedcf --- /dev/null +++ b/code/modules/client/record_updator.dm @@ -0,0 +1,129 @@ +var/global/client_record_update_lock = FALSE + +// Manually updating records from medical console to a player's save. +/proc/get_current_mob_from_record(var/datum/data/record/active) + var/datum/transcore_db/db = SStranscore.db_by_mind_name(active.fields["name"]) + if(db) + var/datum/transhuman/mind_record/record = db.backed_up[active.fields["name"]] + if(record.mind_ref) + var/datum/mind/D = record.mind_ref + if(D.current) + var/client/C = D.current.client + if(C && C.ckey != record.ckey) + return null + return D.current + return null + + +/proc/client_update_record(var/obj/machinery/computer/COM, var/user) + if(!COM || QDELETED(COM)) + return "Invalid console" + + if(jobban_isbanned(user, "Records") ) + COM.visible_message(span_notice("\The [COM] buzzes!")) + playsound(COM, 'sound/machines/deniedbeep.ogg', 50, 0) + return "Update syncronization denied (OOC: You are banned from editing records)" + + var/record_string = "" + var/datum/data/record/active + var/console_path = null + if(istype(COM,/obj/machinery/computer/med_data)) + var/obj/machinery/computer/med_data/MCOM = COM + active = MCOM.active2 + record_string = "medical" + console_path = /obj/machinery/computer/med_data + if(istype(COM,/obj/machinery/computer/skills)) + var/obj/machinery/computer/skills/ECOM = COM + active = ECOM.active1 + record_string = "employment" + console_path = /obj/machinery/computer/skills + if(istype(COM,/obj/machinery/computer/secure_data)) + var/obj/machinery/computer/secure_data/SCOM = COM + active = SCOM.active2 + record_string = "security" + console_path = /obj/machinery/computer/secure_data + + if(client_record_update_lock) + to_chat(user,"Update already in progress! Please wait a moment...") + if(COM && !QDELETED(COM)) + COM.visible_message(span_notice("\The [COM] buzzes!")) + playsound(COM, 'sound/machines/deniedbeep.ogg', 50, 0) + return "Update already in progress! Please wait a moment..." + client_record_update_lock = TRUE + spawn(60 SECONDS) + client_record_update_lock = FALSE + + if(!active || !console_path) + if(COM && !QDELETED(COM)) + COM.visible_message(span_notice("\The [COM] buzzes!")) + playsound(COM, 'sound/machines/deniedbeep.ogg', 50, 0) + return "Update syncronization failed (OOC: Record or console destroyed)" + + to_chat(user,"Update sent! Please wait for a response...") + message_admins("[user] pushed [record_string] record update to [active.fields["name"]].") + + var/mob/M = get_current_mob_from_record(active) + if(!M) + if(COM && !QDELETED(COM)) + COM.visible_message(span_notice("\The [COM] buzzes!")) + playsound(COM, 'sound/machines/deniedbeep.ogg', 50, 0) + return "Update syncronization failed (OOC: Client mob does not exist, has no mind record, or is possesssed)" + + var/client/C = M.client + if(!C) + if(COM && !QDELETED(COM)) + COM.visible_message(span_notice("\The [COM] buzzes!")) + playsound(COM, 'sound/machines/deniedbeep.ogg', 50, 0) + return "Update syncronization failed (OOC: Record's owner is offline)" + + var/choice = tgui_alert(M, "Your [record_string] record has been updated from the a records console by [user]. Please review the changes made to your [record_string] record. Accepting these changes will SAVE your CURRENT character slot! If your new [record_string] record has errors, it is recomended to have it corrected IC instead of editing it yourself.", "Record Updated", list("Review Changes","Refuse Update")) + if(choice == "Refuse Update") + message_admins("[active.fields["name"]] refused [record_string] record update from [user] without review.") + if(COM && !QDELETED(COM)) + COM.visible_message(span_notice("\The [COM] buzzes!")) + playsound(COM, 'sound/machines/deniedbeep.ogg', 50, 0) + return "Update syncronization failed (OOC: Client refused without review)" + + var/datum/preferences/P = C.prefs + var/new_data = strip_html_simple(tgui_input_text(M,"Please review [user]'s changes to your [record_string] record before confirming. Confirming will SAVE your CURRENT character slot! If your new [record_string] record major errors, it is recomended to have it corrected IC instead of editing it yourself.","Character Preference", html_decode(active.fields["notes"]), MAX_RECORD_LENGTH, TRUE, prevent_enter = TRUE), MAX_RECORD_LENGTH) + if(!new_data) + message_admins("[active.fields["name"]] refused [record_string] record update from [user] with review.") + if(COM && !QDELETED(COM)) + COM.visible_message(span_notice("\The [COM] buzzes!")) + playsound(COM, 'sound/machines/deniedbeep.ogg', 50, 0) + return "Update syncronization failed (OOC: Client refused with review)" + if(!M || !M.client || !P) + message_admins("[active.fields["name"]]'s [record_string] record could not be updated, client disconnected.") + if(COM && !QDELETED(COM)) + COM.visible_message(span_notice("\The [COM] buzzes!")) + playsound(COM, 'sound/machines/deniedbeep.ogg', 50, 0) + return "Update syncronization failed (OOC: Client does not exist)" + + // Update records in the consoles, remember this can happen a while after a record is closed on the console... Use cached data. + switch(console_path) + if(/obj/machinery/computer/med_data) + P.med_record = new_data + if(active) + active.fields["notes"] = new_data + if(/obj/machinery/computer/skills) + P.gen_record = new_data + if(active) + active.fields["notes"] = new_data + if(/obj/machinery/computer/secure_data) + P.sec_record = new_data + if(active) + active.fields["notes"] = new_data + + // Update player record + P.save_preferences() + P.save_character() + if(M) + to_chat(M,span_notice("Your [record_string] record for [active.fields["name"]] has been updated.")) + message_admins("[active.fields["name"]] accepted the [record_string] record update from [user].") + + // ding! + if(COM && !QDELETED(COM)) + COM.visible_message(span_notice("\The [COM] dings!")) + playsound(COM, 'sound/machines/ding.ogg', 50, 1) + + return "Record syncronized." diff --git a/tgui/packages/tgui/interfaces/GeneralRecords/GeneralRecordsOptions.tsx b/tgui/packages/tgui/interfaces/GeneralRecords/GeneralRecordsOptions.tsx index 5db9a5c321..457294e6a0 100644 --- a/tgui/packages/tgui/interfaces/GeneralRecords/GeneralRecordsOptions.tsx +++ b/tgui/packages/tgui/interfaces/GeneralRecords/GeneralRecordsOptions.tsx @@ -21,6 +21,14 @@ export const GeneralRecordsView = (props) => {
+ {
{general.skills || 'No data found.'} + {
{general.comments && general.comments.length === 0 ? ( diff --git a/tgui/packages/tgui/interfaces/MedicalRecords/MedicalRecordsOptions.tsx b/tgui/packages/tgui/interfaces/MedicalRecords/MedicalRecordsOptions.tsx index 757e79b7cd..a711cdf931 100644 --- a/tgui/packages/tgui/interfaces/MedicalRecords/MedicalRecordsOptions.tsx +++ b/tgui/packages/tgui/interfaces/MedicalRecords/MedicalRecordsOptions.tsx @@ -36,6 +36,14 @@ export const MedicalRecordsView = (props) => {
+ { {field.value} -
+ { {field.value} - + + + + + + + + + + + + + + + + + + + + +
+ + +
+ + + ); +}; From bbe8f45c6b7e955d01bf1aeb9da1c61178b35873 Mon Sep 17 00:00:00 2001 From: Kashargul <144968721+Kashargul@users.noreply.github.com> Date: Tue, 12 Nov 2024 20:12:15 +0100 Subject: [PATCH 08/26] . --- code/__defines/update_icons.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/__defines/update_icons.dm b/code/__defines/update_icons.dm index 0028080cde..7120edd168 100644 --- a/code/__defines/update_icons.dm +++ b/code/__defines/update_icons.dm @@ -23,7 +23,7 @@ #define SUIT_STORE_LAYER 20 //Suit storage-slot item #define BACK_LAYER 21 //Back-slot item #define HAIR_LAYER 22 //The human's hair -#define HAIR_ACCESSORY_LAYER 23 //VOREStation edit. Simply move this up a number if things are added. +#define HAIR_ACCESSORY_LAYER 23 //Simply move this up a number if things are added. #define EARS_LAYER 24 //Both ear-slot items (combined image) #define EYES_LAYER 25 //Mob's eyes (used for glowing eyes) #define FACEMASK_LAYER 26 //Mask-slot item From c063be65bc7d57743d4475739177df90482b3c95 Mon Sep 17 00:00:00 2001 From: Kashargul <144968721+Kashargul@users.noreply.github.com> Date: Wed, 13 Nov 2024 12:23:39 +0100 Subject: [PATCH 09/26] missing ooc escspe section --- code/modules/vore/eating/living_vr.dm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/modules/vore/eating/living_vr.dm b/code/modules/vore/eating/living_vr.dm index ae486f1e3f..b568f1b319 100644 --- a/code/modules/vore/eating/living_vr.dm +++ b/code/modules/vore/eating/living_vr.dm @@ -609,6 +609,12 @@ forceMove(get_turf(src)) log_and_message_admins("[key_name(src)] used the OOC escape button to get out of a microwave.") + else if(istype(loc, /obj/structure/gargoyle) && loc:was_rayed) + var/obj/structure/gargoyle/G = loc + G.can_revert = TRUE + qdel(G) + log_and_message_admins("[key_name(src)] used the OOC escape button to revert back from being petrified.") + //You are in food and for some reason can't resist out else if(istype(loc, /obj/item/reagent_containers/food)) var/obj/item/reagent_containers/food/F = src.loc From 1f7926eeefa45e4bebfcb768599619611d4de3ca Mon Sep 17 00:00:00 2001 From: Kashargul <144968721+Kashargul@users.noreply.github.com> Date: Wed, 13 Nov 2024 12:30:07 +0100 Subject: [PATCH 10/26] missing string section --- code/modules/client/preference_setup/vore/07_traits.dm | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/code/modules/client/preference_setup/vore/07_traits.dm b/code/modules/client/preference_setup/vore/07_traits.dm index 2614b6a8f4..6fca677568 100644 --- a/code/modules/client/preference_setup/vore/07_traits.dm +++ b/code/modules/client/preference_setup/vore/07_traits.dm @@ -63,6 +63,9 @@ var/global/list/valid_bloodreagents = list("default","iron","copper","phoron","s . += link + (trait_prefs[identifier] ? "Enabled" : "Disabled") if (2) //TRAIT_PREF_TYPE_COLOR . += " " + color_square(hex = trait_prefs[identifier]) + link + "Change" + if (3) //TRAIT_PREF_TYPE_STRING + var/string = trait_prefs[identifier] + . += link + (length(string) > 0 ? string : "\[Empty\]") . += "" . += "" if (altered) @@ -101,6 +104,9 @@ var/global/list/valid_bloodreagents = list("default","iron","copper","phoron","s var/new_color = input(user, "Choose the color for this trait preference:", "Trait Preference", trait_prefs[preference]) as color|null if (new_color) trait_prefs[preference] = new_color + if (3) //TRAIT_PREF_TYPE_STRING + var/new_string = instance.apply_sanitization_to_string(preference, tgui_input_text(user, "What should the new value be?", instance.has_preferences[preference][2], trait_prefs[preference], MAX_NAME_LEN)) + trait_prefs[preference] = new_string // Definition of the stuff for Ears /datum/category_item/player_setup_item/vore/traits From 4c9f046e6d9b83184203c7beb6e1cdfb74801458 Mon Sep 17 00:00:00 2001 From: ShadowLarkens Date: Mon, 18 Nov 2024 05:48:57 -0800 Subject: [PATCH 11/26] Update the radial menu system to tg latest --- code/__defines/_planes+layers.dm | 4 + code/_onclick/hud/radial.dm | 175 +++++++++++++++++++++++------- code/game/objects/effects/info.dm | 28 +++++ icons/effects/effects.dmi | Bin 435437 -> 435722 bytes icons/mob/radial.dmi | Bin 17929 -> 17988 bytes vorestation.dme | 1 + 6 files changed, 170 insertions(+), 38 deletions(-) create mode 100644 code/game/objects/effects/info.dm diff --git a/code/__defines/_planes+layers.dm b/code/__defines/_planes+layers.dm index a06ef90f7a..f8ee1c976e 100644 --- a/code/__defines/_planes+layers.dm +++ b/code/__defines/_planes+layers.dm @@ -187,6 +187,10 @@ What is the naming convention for planes or layers? #define PLANE_PLAYER_HUD_ITEMS 96 //Separate layer with which to apply colorblindness #define PLANE_PLAYER_HUD_ABOVE 97 //Things above the player hud +#define RADIAL_BACKGROUND_LAYER 0 +///1000 is an unimportant number, it's just to normalize copied layers +#define RADIAL_CONTENT_LAYER 1000 + #define PLANE_ADMIN3 99 //Purely for shenanigans (above HUD) diff --git a/code/_onclick/hud/radial.dm b/code/_onclick/hud/radial.dm index 32725ec5ae..b803227325 100644 --- a/code/_onclick/hud/radial.dm +++ b/code/_onclick/hud/radial.dm @@ -3,33 +3,52 @@ GLOBAL_LIST_EMPTY(radial_menus) -// Ported from TG - /obj/screen/radial icon = 'icons/mob/radial.dmi' - layer = LAYER_HUD_ABOVE plane = PLANE_PLAYER_HUD_ABOVE + vis_flags = VIS_INHERIT_PLANE + var/click_on_hover = FALSE var/datum/radial_menu/parent +/obj/screen/radial/proc/set_parent(new_value) + if(parent) + UnregisterSignal(parent, COMSIG_PARENT_QDELETING) + parent = new_value + if(parent) + RegisterSignal(parent, COMSIG_PARENT_QDELETING, PROC_REF(handle_parent_del)) + +/obj/screen/radial/proc/handle_parent_del() + SIGNAL_HANDLER + set_parent(null) + /obj/screen/radial/slice icon_state = "radial_slice" var/choice var/next_page = FALSE var/tooltips = FALSE -/obj/screen/radial/Destroy() - parent = null - return ..() +/obj/screen/radial/slice/set_parent(new_value) + . = ..() + if(parent) + icon_state = parent.radial_slice_icon /obj/screen/radial/slice/MouseEntered(location, control, params) . = ..() - icon_state = "radial_slice_focus" + if(next_page || !parent) + icon_state = "radial_slice_focus" + else + icon_state = "[parent.radial_slice_icon]_focus" if(tooltips) openToolTip(usr, src, params, title = name) + if (click_on_hover && !isnull(usr) && !isnull(parent)) + Click(location, control, params) /obj/screen/radial/slice/MouseExited(location, control, params) . = ..() - icon_state = "radial_slice" + if(next_page || !parent) + icon_state = "radial_slice" + else + icon_state = parent.radial_slice_icon if(tooltips) closeToolTip(usr) @@ -38,7 +57,7 @@ GLOBAL_LIST_EMPTY(radial_menus) if(next_page) parent.next_page() else - parent.element_chosen(choice,usr) + parent.element_chosen(choice, usr, params) /obj/screen/radial/center name = "Close Menu" @@ -57,9 +76,18 @@ GLOBAL_LIST_EMPTY(radial_menus) parent.finished = TRUE /datum/radial_menu - var/list/choices = list() //List of choice id's - var/list/choices_icons = list() //choice_id -> icon - var/list/choices_values = list() //choice_id -> choice + /// List of choice IDs + var/list/choices = list() + + /// choice_id -> icon + var/list/choices_icons = list() + + /// choice_id -> choice + var/list/choices_values = list() + + /// choice_id -> /datum/radial_menu_choice + var/list/choice_datums = list() + var/list/page_data = list() //list of choices per page @@ -87,6 +115,9 @@ GLOBAL_LIST_EMPTY(radial_menus) var/py_shift = 0 var/entry_animation = TRUE + ///A replacement icon state for the generic radial slice bg icon. Doesn't affect the next page nor the center buttons + var/radial_slice_icon + //If we swap to vis_contens inventory these will need a redo /datum/radial_menu/proc/check_screen_border(mob/user) var/atom/movable/AM = anchor @@ -98,6 +129,8 @@ GLOBAL_LIST_EMPTY(radial_menus) else py_shift = 32 restrict_to_dir(NORTH) //I was going to parse screen loc here but that's more effort than it's worth. + else if(hudfix_method && AM.loc) + anchor = get_atom_on_turf(anchor) //Sets defaults //These assume 45 deg min_angle @@ -116,7 +149,7 @@ GLOBAL_LIST_EMPTY(radial_menus) starting_angle = 180 ending_angle = 45 -/datum/radial_menu/proc/setup_menu(use_tooltips) +/datum/radial_menu/proc/setup_menu(use_tooltips, set_page = 1, click_on_hover = FALSE) if(ending_angle > starting_angle) zone = ending_angle - starting_angle else @@ -129,7 +162,7 @@ GLOBAL_LIST_EMPTY(radial_menus) for(var/i in 1 to elements_to_add) //Create all elements var/obj/screen/radial/slice/new_element = new /obj/screen/radial/slice new_element.tooltips = use_tooltips - new_element.parent = src + new_element.set_parent(src) elements += new_element var/page = 1 @@ -152,22 +185,31 @@ GLOBAL_LIST_EMPTY(radial_menus) page_data[page] = current pages = page - current_page = 1 - update_screen_objects(anim = entry_animation) + current_page = clamp(set_page, 1, pages) + update_screen_objects(entry_animation, click_on_hover) -/datum/radial_menu/proc/update_screen_objects(anim = FALSE) +/datum/radial_menu/proc/update_screen_objects(anim = FALSE, click_on_hover = FALSE) var/list/page_choices = page_data[current_page] var/angle_per_element = round(zone / page_choices.len) for(var/i in 1 to elements.len) - var/obj/screen/radial/E = elements[i] + var/obj/screen/radial/element = elements[i] var/angle = WRAP(starting_angle + (i - 1) * angle_per_element,0,360) if(i > page_choices.len) - HideElement(E) + HideElement(element) + element.click_on_hover = FALSE else - SetElement(E,page_choices[i],angle,anim = anim,anim_order = i) + SetElement(element,page_choices[i],angle,anim = anim,anim_order = i) + // Only activate click on hover after the animation plays + if (!click_on_hover) + continue + if (anim) + addtimer(VARSET_CALLBACK(element, click_on_hover, TRUE), i * 0.5) + else + element.click_on_hover = TRUE /datum/radial_menu/proc/HideElement(obj/screen/radial/slice/E) E.cut_overlays() + E.vis_contents.Cut() E.alpha = 0 E.name = "None" E.maptext = null @@ -194,13 +236,22 @@ GLOBAL_LIST_EMPTY(radial_menus) E.alpha = 255 E.mouse_opacity = MOUSE_OPACITY_ICON E.cut_overlays() + E.vis_contents.Cut() if(choice_id == NEXT_PAGE_ID) E.name = "Next Page" E.next_page = TRUE + E.icon_state = "radial_slice" // Resets the bg icon state to the default for next page buttons. E.add_overlay("radial_next") else - if(istext(choices_values[choice_id])) + //This isn't granted to exist, so use the ?. operator for conditionals that use it. + var/datum/radial_menu_choice/choice_datum = choice_datums[choice_id] + if(choice_datum?.name) + E.name = choice_datum.name + else if(istext(choices_values[choice_id])) E.name = choices_values[choice_id] + else if(ispath(choices_values[choice_id],/atom)) + var/atom/A = choices_values[choice_id] + E.name = initial(A.name) else var/atom/movable/AM = choices_values[choice_id] //Movables only E.name = AM.name @@ -209,15 +260,21 @@ GLOBAL_LIST_EMPTY(radial_menus) E.next_page = FALSE if(choices_icons[choice_id]) E.add_overlay(choices_icons[choice_id]) + if (choice_datum?.info) + var/obj/effect/abstract/info/info_button = new(E, choice_datum.info) + info_button.plane = PLANE_PLAYER_HUD_ABOVE + info_button.layer = RADIAL_CONTENT_LAYER + E.vis_contents += info_button /datum/radial_menu/New() close_button = new - close_button.parent = src + close_button.set_parent(src) /datum/radial_menu/proc/Reset() choices.Cut() choices_icons.Cut() choices_values.Cut() + choice_datums.Cut() current_page = 1 /datum/radial_menu/proc/element_chosen(choice_id,mob/user) @@ -226,7 +283,7 @@ GLOBAL_LIST_EMPTY(radial_menus) /datum/radial_menu/proc/get_next_id() return "c_[choices.len]" -/datum/radial_menu/proc/set_choices(list/new_choices, use_tooltips) +/datum/radial_menu/proc/set_choices(list/new_choices, use_tooltips, click_on_hover = FALSE, set_page = 1) if(choices.len) Reset() for(var/E in new_choices) @@ -237,13 +294,20 @@ GLOBAL_LIST_EMPTY(radial_menus) var/I = extract_image(new_choices[E]) if(I) choices_icons[id] = I - setup_menu(use_tooltips) + if (istype(new_choices[E], /datum/radial_menu_choice)) + choice_datums[id] = new_choices[E] + setup_menu(use_tooltips, set_page, click_on_hover) -/datum/radial_menu/proc/extract_image(E) - var/mutable_appearance/MA = new /mutable_appearance(E) +/datum/radial_menu/proc/extract_image(to_extract_from) + if (istype(to_extract_from, /datum/radial_menu_choice)) + var/datum/radial_menu_choice/choice = to_extract_from + to_extract_from = choice.image + + var/mutable_appearance/MA = new /mutable_appearance(to_extract_from) if(MA) - MA.layer = LAYER_HUD_ABOVE + MA.plane = PLANE_PLAYER_HUD_ABOVE + MA.layer = RADIAL_CONTENT_LAYER MA.appearance_flags |= RESET_TRANSFORM return MA @@ -253,15 +317,16 @@ GLOBAL_LIST_EMPTY(radial_menus) current_page = WRAP(current_page + 1,1,pages+1) update_screen_objects() -/datum/radial_menu/proc/show_to(mob/M) +/datum/radial_menu/proc/show_to(mob/M, offset_x = 0, offset_y = 0) if(current_user) hide() if(!M.client || !anchor) return current_user = M.client //Blank - menu_holder = image(icon='icons/effects/effects.dmi',loc=anchor,icon_state="nothing",layer = LAYER_HUD_ABOVE) - menu_holder.appearance_flags |= KEEP_APART + menu_holder = image(icon='icons/effects/effects.dmi',loc=anchor,icon_state="nothing", layer = RADIAL_BACKGROUND_LAYER, pixel_x = offset_x, pixel_y = offset_y) + menu_holder.plane = PLANE_PLAYER_HUD_ABOVE + menu_holder.appearance_flags |= KEEP_APART|RESET_ALPHA|RESET_COLOR|RESET_TRANSFORM menu_holder.vis_contents += elements + close_button current_user.images += menu_holder @@ -283,9 +348,7 @@ GLOBAL_LIST_EMPTY(radial_menus) /datum/radial_menu/Destroy() Reset() hide() - QDEL_LIST_NULL(elements) - QDEL_NULL(close_button) - QDEL_NULL(custom_check_callback) + custom_check_callback = null . = ..() /* @@ -293,30 +356,66 @@ GLOBAL_LIST_EMPTY(radial_menus) Choices should be a list where list keys are movables or text used for element names and return value and list values are movables/icons/images used for element icons */ -/proc/show_radial_menu(mob/user, atom/anchor, list/choices, uniqueid, radius, datum/callback/custom_check, require_near = FALSE, tooltips = FALSE) +/proc/show_radial_menu(mob/user, atom/anchor, list/choices, uniqueid, radius, datum/callback/custom_check, require_near = FALSE, tooltips = FALSE, no_repeat_close = FALSE, radial_slice_icon = "radial_slice", autopick_single_option = TRUE, entry_animation = TRUE, click_on_hover = FALSE, user_space = FALSE) if(!user || !anchor || !length(choices)) return + + if(length(choices)==1 && autopick_single_option) + return choices[1] + if(!uniqueid) uniqueid = "defmenu_[REF(user)]_[REF(anchor)]" if(GLOB.radial_menus[uniqueid]) + if(!no_repeat_close) + var/datum/radial_menu/menu = GLOB.radial_menus[uniqueid] + menu.finished = TRUE return var/datum/radial_menu/menu = new + menu.entry_animation = entry_animation GLOB.radial_menus[uniqueid] = menu if(radius) menu.radius = radius if(istype(custom_check)) menu.custom_check_callback = custom_check - menu.anchor = anchor + menu.anchor = user_space ? user : anchor + menu.radial_slice_icon = radial_slice_icon menu.check_screen_border(user) //Do what's needed to make it look good near borders or on hud - menu.set_choices(choices, tooltips) - menu.show_to(user) + menu.set_choices(choices, tooltips, click_on_hover) + var/offset_x = 0 + var/offset_y = 0 + if (user_space) + var/turf/user_turf = get_turf(user) + var/turf/anchor_turf = get_turf(anchor) + offset_x = (anchor_turf.x - user_turf.x) * ICON_SIZE_X + anchor.pixel_x - user.pixel_x + offset_y = (anchor_turf.y - user_turf.y) * ICON_SIZE_Y + anchor.pixel_y - user.pixel_y + menu.show_to(user, offset_x, offset_y) menu.wait(user, anchor, require_near) var/answer = menu.selected_choice - QDEL_NULL(menu) + qdel(menu) GLOB.radial_menus -= uniqueid + if(require_near && !in_range(anchor, user)) + return + if(istype(custom_check)) + if(!custom_check.Invoke()) + return return answer +/// Can be provided to choices in radial menus if you want to provide more information +/datum/radial_menu_choice + /// Required -- what to display for this button + var/image + + /// If provided, this will be the name the radial slice hud button. This has priority over everything else. + var/name + + /// If provided, will display an info button that will put this text in your chat + var/info + +/datum/radial_menu_choice/Destroy(force) + . = ..() + QDEL_NULL(image) + #undef NEXT_PAGE_ID #undef DEFAULT_CHECK_DELAY diff --git a/code/game/objects/effects/info.dm b/code/game/objects/effects/info.dm new file mode 100644 index 0000000000..e98cf020a1 --- /dev/null +++ b/code/game/objects/effects/info.dm @@ -0,0 +1,28 @@ +/// An info button that, when clicked, puts some text in the user's chat +/obj/effect/abstract/info + name = "info" + icon = 'icons/effects/effects.dmi' + icon_state = "info" + + mouse_opacity = MOUSE_OPACITY_OPAQUE + + /// What should the info button display when clicked? + var/info_text + +/obj/effect/abstract/info/Initialize(mapload, info_text) + . = ..() + + if (!isnull(info_text)) + src.info_text = info_text + +/obj/effect/abstract/info/Click() + . = ..() + to_chat(usr, info_text) + +/obj/effect/abstract/info/MouseEntered(location, control, params) + . = ..() + icon_state = "info_hovered" + +/obj/effect/abstract/info/MouseExited() + . = ..() + icon_state = initial(icon_state) diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index 4df86b72fff444a1f1a4006b4f3a815bd1fb2a14..97643ad7a8c1877664b5d7efc182cbebbaec4040 100644 GIT binary patch delta 12185 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 PkB%0Jo@S-Gb>#m6dBpzk delta 11897 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 X*=f6X!INibsGqXDs$7YTN$~#wG~i1W diff --git a/icons/mob/radial.dmi b/icons/mob/radial.dmi index bf14a197341d47883eed4c4d5bffc7f609a6d6d5..156eb8a72293fc5ba031ed670c92db198dbe9601 100644 GIT binary patch delta 17613 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 Z{_|(6^XstGafmShfv2mV%Q~loCIBpSA~XO1 delta 17554 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 E0KW@55dZ)H diff --git a/vorestation.dme b/vorestation.dme index dbe63b1438..05420f0cec 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -1219,6 +1219,7 @@ #include "code\game\objects\effects\explosion_particles.dm" #include "code\game\objects\effects\gibs.dm" #include "code\game\objects\effects\glowshroom.dm" +#include "code\game\objects\effects\info.dm" #include "code\game\objects\effects\item_pickup_ghost.dm" #include "code\game\objects\effects\job_start_landmarks.dm" #include "code\game\objects\effects\landmarks.dm" From 1ee1e409938aab6eab45a7a1e0974bd249316742 Mon Sep 17 00:00:00 2001 From: ShadowLarkens Date: Mon, 18 Nov 2024 05:49:25 -0800 Subject: [PATCH 12/26] Make the grinder always show a radial menu, no autopick --- code/modules/reagents/machinery/grinder.dm | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/code/modules/reagents/machinery/grinder.dm b/code/modules/reagents/machinery/grinder.dm index a20920fc7e..80a85443b8 100644 --- a/code/modules/reagents/machinery/grinder.dm +++ b/code/modules/reagents/machinery/grinder.dm @@ -209,14 +209,7 @@ var/global/list/ore_reagents = list( //have a number of reageents divisible by R if(length(holdingitems)) options["grind"] = radial_grind - var/choice - if(length(options) < 1) - return - if(length(options) == 1) - for(var/key in options) - choice = key - else - choice = show_radial_menu(user, src, options, require_near = !issilicon(user)) + var/choice = show_radial_menu(user, src, options, require_near = !issilicon(user), autopick_single_option = FALSE) // post choice verification if(inuse || (isAI(user) && stat & NOPOWER) || user.incapacitated()) From 9f0a297579646bf8924f15e955c35e4b06a288e3 Mon Sep 17 00:00:00 2001 From: ShadowLarkens Date: Mon, 18 Nov 2024 06:18:32 -0800 Subject: [PATCH 13/26] Add power and safety to CookingAppliance UI --- .../food/kitchen/cooking_machines/_cooker.dm | 8 ++++++ .../tgui/interfaces/CookingAppliance.tsx | 27 ++++++++++++++++++- 2 files changed, 34 insertions(+), 1 deletion(-) diff --git a/code/modules/food/kitchen/cooking_machines/_cooker.dm b/code/modules/food/kitchen/cooking_machines/_cooker.dm index a8c1c25080..17707d0f4e 100644 --- a/code/modules/food/kitchen/cooking_machines/_cooker.dm +++ b/code/modules/food/kitchen/cooking_machines/_cooker.dm @@ -26,6 +26,8 @@ /obj/machinery/appliance/cooker/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) var/list/data = ..() + data["on"] = !(stat & POWEROFF) + data["safety"] = food_safety data["temperature"] = round(temperature - T0C, 0.1) data["optimalTemp"] = round(optimal_temp - T0C, 0.1) data["temperatureEnough"] = temperature >= min_temp @@ -56,6 +58,12 @@ return TRUE switch(action) + if("toggle_power") + attempt_toggle_power(usr) + return TRUE + if("toggle_safety") + toggle_safety() + return TRUE if("slot") var/slot = params["slot"] var/obj/item/I = usr.get_active_hand() diff --git a/tgui/packages/tgui/interfaces/CookingAppliance.tsx b/tgui/packages/tgui/interfaces/CookingAppliance.tsx index 7b951cd5db..55dc806189 100644 --- a/tgui/packages/tgui/interfaces/CookingAppliance.tsx +++ b/tgui/packages/tgui/interfaces/CookingAppliance.tsx @@ -12,6 +12,8 @@ import { import { Window } from '../layouts'; type Data = { + on: BooleanLike; + safety: BooleanLike; temperature: number; optimalTemp: number; temperatureEnough: BooleanLike; @@ -29,6 +31,8 @@ export const CookingAppliance = (props) => { const { act, data } = useBackend(); const { + on, + safety, temperature, optimalTemp, temperatureEnough, @@ -40,8 +44,29 @@ export const CookingAppliance = (props) => { return ( -
+
act('toggle_power')} + > + {on ? 'On' : 'Off'} + + } + > + + + Date: Mon, 18 Nov 2024 06:30:51 -0800 Subject: [PATCH 14/26] Add selectable output to CookingAppliance UI --- .../food/kitchen/cooking_machines/_cooker.dm | 5 +++++ .../tgui/interfaces/CookingAppliance.tsx | 16 ++++++++++++++++ 2 files changed, 21 insertions(+) diff --git a/code/modules/food/kitchen/cooking_machines/_cooker.dm b/code/modules/food/kitchen/cooking_machines/_cooker.dm index 17707d0f4e..b557af04a8 100644 --- a/code/modules/food/kitchen/cooking_machines/_cooker.dm +++ b/code/modules/food/kitchen/cooking_machines/_cooker.dm @@ -33,6 +33,8 @@ data["temperatureEnough"] = temperature >= min_temp data["efficiency"] = round(get_efficiency(), 0.1) data["containersRemovable"] = can_remove_items(user, show_warning = FALSE) + data["selected_option"] = selected_option + data["show_selected_option"] = LAZYLEN(output_options) var/list/our_contents = list() for(var/i in 1 to max_contents) @@ -64,6 +66,9 @@ if("toggle_safety") toggle_safety() return TRUE + if("change_output") + choose_output() + return TRUE if("slot") var/slot = params["slot"] var/obj/item/I = usr.get_active_hand() diff --git a/tgui/packages/tgui/interfaces/CookingAppliance.tsx b/tgui/packages/tgui/interfaces/CookingAppliance.tsx index 55dc806189..2c721da681 100644 --- a/tgui/packages/tgui/interfaces/CookingAppliance.tsx +++ b/tgui/packages/tgui/interfaces/CookingAppliance.tsx @@ -14,6 +14,8 @@ import { Window } from '../layouts'; type Data = { on: BooleanLike; safety: BooleanLike; + selected_option: string | null; + show_selected_option: BooleanLike; temperature: number; optimalTemp: number; temperatureEnough: BooleanLike; @@ -33,6 +35,8 @@ export const CookingAppliance = (props) => { const { on, safety, + selected_option, + show_selected_option, temperature, optimalTemp, temperatureEnough, @@ -67,6 +71,18 @@ export const CookingAppliance = (props) => { {safety ? 'On' : 'Off'} + {!!show_selected_option && ( + + + + )} Date: Mon, 18 Nov 2024 07:07:09 -0800 Subject: [PATCH 15/26] Add a radial menu to generic appliances (just mixers, I think?) --- .../kitchen/cooking_machines/_appliance.dm | 32 ++++++++++++++++-- icons/mob/radial.dmi | Bin 17988 -> 18477 bytes 2 files changed, 30 insertions(+), 2 deletions(-) diff --git a/code/modules/food/kitchen/cooking_machines/_appliance.dm b/code/modules/food/kitchen/cooking_machines/_appliance.dm index 5a37e9fb7b..6d95e881cd 100644 --- a/code/modules/food/kitchen/cooking_machines/_appliance.dm +++ b/code/modules/food/kitchen/cooking_machines/_appliance.dm @@ -43,6 +43,11 @@ var/combine_first = FALSE // If TRUE, this appliance will do combination cooking before checking recipes var/food_safety = FALSE //RS ADD - If true, the appliance automatically ejects food instead of burning it + var/static/radial_eject = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_eject") + var/static/radial_power = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_power") + var/static/radial_safety = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_safety") + var/static/radial_output = image(icon = 'icons/mob/radial.dmi', icon_state = "radial_change_output") + /obj/machinery/appliance/Initialize() . = ..() @@ -611,8 +616,31 @@ if(..()) return - if(cooking_objs.len) - removal_menu(user) + interact(user) + +/obj/machinery/appliance/interact(mob/user) + var/list/options = list( + "power" = radial_power, + "safety" = radial_safety, + ) + + if(LAZYLEN(cooking_objs)) + options["remove"] = radial_eject + + if(LAZYLEN(output_options)) + options["select_output"] = radial_output + + var/choice = show_radial_menu(user, src, options, require_near = !issilicon(user)) + + switch(choice) + if("power") + toggle_power() + if("safety") + toggle_safety() + if("remove") + removal_menu(user) + if("select_output") + choose_output() /obj/machinery/appliance/proc/removal_menu(var/mob/user) if (can_remove_items(user)) diff --git a/icons/mob/radial.dmi b/icons/mob/radial.dmi index 156eb8a72293fc5ba031ed670c92db198dbe9601..d38f1e63be5306bc343a559d61b477fb6902d327 100644 GIT binary patch literal 18477 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 OAO=rYKbLh*2~7Zx41-4i literal 17988 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�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 Date: Wed, 20 Nov 2024 21:19:33 +0100 Subject: [PATCH 16/26] . --- code/game/objects/structures/watercloset.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index c6bab80041..085faf154e 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -573,6 +573,7 @@ H.l_hand.clean_blood() H.bloody_hands = 0 H.germ_level = 0 + H.update_bloodied() else user.clean_blood() for(var/mob/V in viewers(src, null)) From c0321536be6b7cd67d2b61c83c3b552e36c30bb9 Mon Sep 17 00:00:00 2001 From: Kashargul <144968721+Kashargul@users.noreply.github.com> Date: Wed, 20 Nov 2024 21:24:46 +0100 Subject: [PATCH 17/26] . --- code/game/objects/structures/watercloset.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 085faf154e..94b31a10c2 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -573,7 +573,7 @@ H.l_hand.clean_blood() H.bloody_hands = 0 H.germ_level = 0 - H.update_bloodied() + H.update_bloodied() else user.clean_blood() for(var/mob/V in viewers(src, null)) From 635cabdd6956b898faf367a712b7c7a479a2eb09 Mon Sep 17 00:00:00 2001 From: Kashargul <144968721+Kashargul@users.noreply.github.com> Date: Wed, 20 Nov 2024 22:06:02 +0100 Subject: [PATCH 18/26] . --- code/game/objects/structures/watercloset.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index 94b31a10c2..926ac2cb52 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -573,6 +573,8 @@ H.l_hand.clean_blood() H.bloody_hands = 0 H.germ_level = 0 + H.hand_blood_color = null + LAZYCLEARLIST(H.blood_DNA) H.update_bloodied() else user.clean_blood() From 38192e56161b9ac12291fb682ca862e307d85535 Mon Sep 17 00:00:00 2001 From: Nadyr <41974248+Darlantanis@users.noreply.github.com> Date: Wed, 20 Nov 2024 18:22:03 -0500 Subject: [PATCH 19/26] Rename record_updator.dm to record_updater.dm --- code/modules/client/{record_updator.dm => record_updater.dm} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename code/modules/client/{record_updator.dm => record_updater.dm} (100%) diff --git a/code/modules/client/record_updator.dm b/code/modules/client/record_updater.dm similarity index 100% rename from code/modules/client/record_updator.dm rename to code/modules/client/record_updater.dm From ae97b1e41ade36b8513e4647e43f177df95f7da4 Mon Sep 17 00:00:00 2001 From: Nadyr <41974248+Darlantanis@users.noreply.github.com> Date: Wed, 20 Nov 2024 18:22:38 -0500 Subject: [PATCH 20/26] new file name --- vorestation.dme | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/vorestation.dme b/vorestation.dme index c68a927734..fae6179beb 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -1976,7 +1976,7 @@ #include "code\modules\client\preferences_tgui.dm" #include "code\modules\client\preferences_toggle_procs.dm" #include "code\modules\client\preferences_vr.dm" -#include "code\modules\client\record_updator.dm" +#include "code\modules\client\record_updater.dm" #include "code\modules\client\spam_prevention.dm" #include "code\modules\client\stored_item.dm" #include "code\modules\client\ui_style.dm" From 51653714f60abcc52624fa4b8c837b4c534dc50c Mon Sep 17 00:00:00 2001 From: ShadowLarkens Date: Sun, 24 Nov 2024 11:22:09 -0800 Subject: [PATCH 21/26] Allow pAIs to attack_ai the machine they're inside, this literally just means rn microwaves can be triggered by them --- code/modules/food/kitchen/microwave.dm | 5 +++++ code/modules/mob/living/silicon/pai/pai_vr.dm | 10 ++++++++++ 2 files changed, 15 insertions(+) diff --git a/code/modules/food/kitchen/microwave.dm b/code/modules/food/kitchen/microwave.dm index 41a01ee608..982b53a837 100644 --- a/code/modules/food/kitchen/microwave.dm +++ b/code/modules/food/kitchen/microwave.dm @@ -219,6 +219,11 @@ ..() SStgui.update_uis(src) +/obj/machinery/microwave/tgui_status(mob/user) + if(user == paicard?.pai) + return STATUS_INTERACTIVE + . = ..() + /obj/machinery/microwave/tgui_state(mob/user) return GLOB.tgui_physical_state diff --git a/code/modules/mob/living/silicon/pai/pai_vr.dm b/code/modules/mob/living/silicon/pai/pai_vr.dm index eda552040e..1fa7a3b6e6 100644 --- a/code/modules/mob/living/silicon/pai/pai_vr.dm +++ b/code/modules/mob/living/silicon/pai/pai_vr.dm @@ -291,6 +291,16 @@ if(I_GRAB) pai_nom(A) +// Allow card inhabited machines to be interacted with +// This has to override ClickOn because of storage depth nonsense with how pAIs are in cards in machines +/mob/living/silicon/pai/ClickOn(var/atom/A, var/params) + if(istype(A, /obj/machinery)) + var/obj/machinery/M = A + if(M.paicard == card) + M.attack_ai(src) + return + return ..() + /mob/living/silicon/pai/proc/hug(var/mob/living/silicon/pai/H, var/mob/living/target) var/t_him = "them" From 49d0d773e55b53c7d625cdd5b52eb8b0eb0d3008 Mon Sep 17 00:00:00 2001 From: ShadowLarkens Date: Tue, 26 Nov 2024 11:12:56 -0800 Subject: [PATCH 22/26] Make the microwave preview what it'll (probably) create --- .../effects/decals/Cleanable/humans.dm | 2 +- .../asset_cache/assets/kitchen_recipes.dm | 26 ++ code/modules/food/kitchen/microwave.dm | 118 +++------ tgui/packages/tgui/interfaces/Microwave.tsx | 246 ++++++++++++++---- .../tgui/interfaces/common/AnimatedArrows.tsx | 37 +++ vorestation.dme | 1 + 6 files changed, 296 insertions(+), 134 deletions(-) create mode 100644 code/modules/asset_cache/assets/kitchen_recipes.dm create mode 100644 tgui/packages/tgui/interfaces/common/AnimatedArrows.tsx diff --git a/code/game/objects/effects/decals/Cleanable/humans.dm b/code/game/objects/effects/decals/Cleanable/humans.dm index 184bee8bed..5574861298 100644 --- a/code/game/objects/effects/decals/Cleanable/humans.dm +++ b/code/game/objects/effects/decals/Cleanable/humans.dm @@ -192,7 +192,7 @@ var/global/list/image/splatter_cache=list() density = FALSE anchored = TRUE icon = 'icons/effects/blood.dmi' - icon_state = "gibbl5" + icon_state = "gib1" random_icon_states = list("gib1", "gib2", "gib3", "gib5", "gib6") var/fleshcolor = "#FFFFFF" diff --git a/code/modules/asset_cache/assets/kitchen_recipes.dm b/code/modules/asset_cache/assets/kitchen_recipes.dm new file mode 100644 index 0000000000..2cca2ed670 --- /dev/null +++ b/code/modules/asset_cache/assets/kitchen_recipes.dm @@ -0,0 +1,26 @@ +/datum/asset/spritesheet/kitchen_recipes + name = "kitchen_recipes" + +/datum/asset/spritesheet/kitchen_recipes/create_spritesheets() + for(var/datum/recipe/R as anything in subtypesof(/datum/recipe)) + add_atom_icon(R.result, sanitize_css_class_name("[R.type]")) + +/datum/asset/spritesheet/kitchen_recipes/proc/add_atom_icon(typepath, id) + var/icon_file + var/icon_state + var/obj/preview_item = typepath + + // if(ispath(ingredient_typepath, /datum/reagent)) + // var/datum/reagent/reagent = ingredient_typepath + // preview_item = initial(reagent.default_container) + // var/datum/glass_style/style = GLOB.glass_style_singletons[preview_item]?[reagent] + // if(istype(style)) + // icon_file = style.icon + // icon_state = style.icon_state + + // icon_file ||= initial(preview_item.icon_preview) || initial(preview_item.icon) + // icon_state ||= initial(preview_item.icon_state_preview) || initial(preview_item.icon_state) + icon_file = initial(preview_item.icon) + icon_state = initial(preview_item.icon_state) + + Insert("[id]", icon_file, icon_state) diff --git a/code/modules/food/kitchen/microwave.dm b/code/modules/food/kitchen/microwave.dm index 41a01ee608..5bb105cb26 100644 --- a/code/modules/food/kitchen/microwave.dm +++ b/code/modules/food/kitchen/microwave.dm @@ -138,6 +138,7 @@ user.visible_message( \ span_notice("\The [user] has added one of [O] to \the [src]."), \ span_notice("You add one of [O] to \the [src].")) + update_static_data_for_all_viewers() return else // user.remove_from_mob(O) //This just causes problems so far as I can tell. -Pete - Man whoever you are, it's been years. o7 @@ -145,7 +146,7 @@ user.visible_message( \ span_notice("\The [user] has added \the [O] to \the [src]."), \ span_notice("You add \the [O] to \the [src].")) - SStgui.update_uis(src) + update_static_data_for_all_viewers() return else if (istype(O,/obj/item/storage/bag/plants)) // There might be a better way about making plant bags dump their contents into a microwave, but it works. var/obj/item/storage/bag/plants/bag = O @@ -173,6 +174,7 @@ to_chat(user, "You fill \the [src] from \the [O].") SStgui.update_uis(src) + update_static_data_for_all_viewers() return 0 else if(istype(O,/obj/item/reagent_containers/glass) || \ @@ -185,6 +187,8 @@ if (!(R.id in acceptable_reagents)) to_chat(user, span_warning("Your [O] contains components unsuitable for cookery.")) return 1 + // gotta let afterattack resolve + addtimer(CALLBACK(src, TYPE_PROC_REF(/datum, update_static_data_for_all_viewers)), 1 SECOND) return else if(istype(O,/obj/item/grab)) var/obj/item/grab/G = O @@ -242,6 +246,20 @@ ui = new(user, src, "Microwave", name) ui.open() +/obj/machinery/microwave/ui_assets(mob/user) + return list( + get_asset_datum(/datum/asset/spritesheet/kitchen_recipes) + ) + +/obj/machinery/microwave/tgui_static_data(mob/user) + var/list/data = ..() + + var/datum/recipe/recipe = select_recipe(available_recipes,src) + data["recipe"] = recipe ? sanitize_css_class_name("[recipe.type]") : null + data["recipe_name"] = recipe ? initial(recipe.result:name) : null + + return data + /obj/machinery/microwave/tgui_data(mob/user, datum/tgui/ui, datum/tgui_state/state) var/list/data = ..() @@ -250,6 +268,21 @@ data["dirty"] = dirty == 100 data["items"] = get_items_list() + var/list/reagents_data = list() + for(var/datum/reagent/R in reagents.reagent_list) + var/display_name = R.name + if(R.id == "capsaicin") + display_name = "Hotsauce" + if(R.id == "frostoil") + display_name = "Coldsauce" + UNTYPED_LIST_ADD(reagents_data, list( + "name" = display_name, + "amt" = R.volume, + "extra" = "unit[R.volume > 1 ? "s" : ""]", + "color" = R.color, + )) + data["reagents"] = reagents_data + return data /obj/machinery/microwave/proc/get_items_list() @@ -258,7 +291,8 @@ var/list/items_counts = list() var/list/items_measures = list() var/list/items_measures_p = list() - //for(var/obj/O in ((contents - component_parts) - circuit)) + var/list/icons = list() + for(var/obj/O in cookingContents()) var/display_name = O.name if(istype(O,/obj/item/reagent_containers/food/snacks/egg)) @@ -278,33 +312,26 @@ items_measures[display_name] = "fillet of meat" items_measures_p[display_name] = "fillets of meat" items_counts[display_name]++ + icons[display_name] = list("icon" = O.icon, "icon_state" = O.icon_state) + for(var/O in items_counts) var/N = items_counts[O] + var/icon = icons[O] if(!(O in items_measures)) data.Add(list(list( "name" = capitalize(O), "amt" = N, "extra" = "[lowertext(O)][N > 1 ? "s" : ""]", + "icon" = icon, ))) else data.Add(list(list( "name" = capitalize(O), "amt" = N, "extra" = N == 1 ? items_measures[O] : items_measures_p[O], + "icon" = icon, ))) - for(var/datum/reagent/R in reagents.reagent_list) - var/display_name = R.name - if(R.id == "capsaicin") - display_name = "Hotsauce" - if(R.id == "frostoil") - display_name = "Coldsauce" - data.Add(list(list( - "name" = display_name, - "amt" = R.volume, - "extra" = "unit[R.volume > 1 ? "s" : ""]" - ))) - return data /obj/machinery/microwave/tgui_act(action, list/params, datum/tgui/ui, datum/tgui_state/state) @@ -322,69 +349,6 @@ if("dispose") dispose() return TRUE -/* -/obj/machinery/microwave/interact(mob/user as mob) // The microwave Menu - var/dat = "" - if(src.broken > 0) - dat = {"Bzzzzttttt"} - else if(src.operating) - dat = {"Microwaving in progress!
Please wait...!
"} - else if(src.dirty==100) - dat = {"This microwave is dirty!
Please clean it before use!
"} - else - var/list/items_counts = new - var/list/items_measures = new - var/list/items_measures_p = new - for (var/obj/O in ((contents - component_parts) - circuit)) - var/display_name = O.name - if (istype(O,/obj/item/reagent_containers/food/snacks/egg)) - items_measures[display_name] = "egg" - items_measures_p[display_name] = "eggs" - if (istype(O,/obj/item/reagent_containers/food/snacks/tofu)) - items_measures[display_name] = "tofu chunk" - items_measures_p[display_name] = "tofu chunks" - if (istype(O,/obj/item/reagent_containers/food/snacks/meat)) //any meat - items_measures[display_name] = "slab of meat" - items_measures_p[display_name] = "slabs of meat" - if (istype(O,/obj/item/reagent_containers/food/snacks/donkpocket)) - display_name = "Turnovers" - items_measures[display_name] = "turnover" - items_measures_p[display_name] = "turnovers" - if (istype(O,/obj/item/reagent_containers/food/snacks/carpmeat)) - items_measures[display_name] = "fillet of meat" - items_measures_p[display_name] = "fillets of meat" - items_counts[display_name]++ - for (var/O in items_counts) - var/N = items_counts[O] - if (!(O in items_measures)) - dat += span_bold("[capitalize(O)]:") + " [N] [lowertext(O)]\s
" - else - if (N==1) - dat += span_bold("[capitalize(O)]:") + " [N] [items_measures[O]]
" - else - dat += span_bold("[capitalize(O)]:") + " [N] [items_measures_p[O]]
" - - for (var/datum/reagent/R in reagents.reagent_list) - var/display_name = R.name - if (R.id == "capsaicin") - display_name = "Hotsauce" - if (R.id == "frostoil") - display_name = "Coldsauce" - dat += span_bold("[display_name]:") + " [R.volume] unit\s
" - - if (items_counts.len==0 && reagents.reagent_list.len==0) - dat = span_bold("The microwave is empty") + "
" - else - dat = span_bold("Ingredients:") + "
[dat]" - dat += {"

\ -
Turn on!
\ -
Eject ingredients!
\ -"} - - user << browse("Microwave Controls[dat]", "window=microwave") - onclose(user, "microwave") - return -*/ /*********************************** * Microwave Menu Handling/Cooking diff --git a/tgui/packages/tgui/interfaces/Microwave.tsx b/tgui/packages/tgui/interfaces/Microwave.tsx index e087adc9e9..363a880264 100644 --- a/tgui/packages/tgui/interfaces/Microwave.tsx +++ b/tgui/packages/tgui/interfaces/Microwave.tsx @@ -1,75 +1,209 @@ import { BooleanLike } from 'common/react'; +import { DmIcon, Stack, Tooltip } from 'tgui-core/components'; +import { classes } from 'tgui-core/react'; import { useBackend } from '../backend'; -import { Box, Button, LabeledList, Section } from '../components'; +import { Box, Button, Section } from '../components'; import { Window } from '../layouts'; +import { AnimatedArrows } from './common/AnimatedArrows'; + +type Item = { + name: string; + amt: number; + extra: string; + icon: { icon: string; icon_state: string }; +}; + +type Reagent = { + name: string; + amt: number; + extra: string; + color: string; +}; type Data = { broken: BooleanLike; operating: BooleanLike; dirty: BooleanLike; - items: { name: string; amt: number; extra: string }[]; + items: Item[]; + reagents: Reagent[]; + recipe: string | null; + recipe_name: string | null; }; export const Microwave = (props) => { - const { act, config, data } = useBackend(); + const { config, data } = useBackend(); const { broken, operating, dirty, items } = data; + let inner; + + if (broken) { + inner = ( +
+ Bzzzzttttt!! +
+ ); + } else if (operating) { + inner = ( +
+ + Microwaving in progress! +
+ Please wait...! +
+
+ ); + } else if (dirty) { + inner = ( +
+ + This microwave is dirty! +
+ Please clean it before use! +
+
+ ); + } else if (items.length) { + inner = ; + } else { + inner = ( +
+ {config.title} is empty. +
+ ); + } + return ( - - - {(broken && ( -
- Bzzzzttttt!! -
- )) || - (operating && ( -
- - Microwaving in progress! -
- Please wait...! -
-
- )) || - (dirty && ( -
- - This microwave is dirty! -
- Please clean it before use! -
-
- )) || - (items.length && ( -
- - - - } - > - - {items.map((item) => ( - - {item.amt} {item.extra} - - ))} - -
- )) || ( -
- {config.title} is empty. -
- )} -
+ + {inner} ); }; + +const MicrowaveContents = (props) => { + const { act, data } = useBackend(); + + const { items, reagents, recipe, recipe_name } = data; + + return ( +
+ + + + } + > + + + + {items.map((item) => ( + + + + x{item.amt} + + + + + ))} + {reagents.map((r) => ( + + + + {r.amt} + + {/* To be clear: This is fucking cursed + We're directly loading the rectangular glass and + manually colorizing a div that's set to be the right shape */} + + + + + ))} + + + + + + + + + {recipe ? ( + + ) : ( + + )} + + + + +
+ ); +}; diff --git a/tgui/packages/tgui/interfaces/common/AnimatedArrows.tsx b/tgui/packages/tgui/interfaces/common/AnimatedArrows.tsx new file mode 100644 index 0000000000..6fc6efc1ee --- /dev/null +++ b/tgui/packages/tgui/interfaces/common/AnimatedArrows.tsx @@ -0,0 +1,37 @@ +import { useEffect, useState } from 'react'; +import { Box } from 'tgui/components'; +import { BoxProps } from 'tgui/components/Box'; +import { Icon } from 'tgui-core/components'; + +export const AnimatedArrows = (props: { on: boolean } & BoxProps) => { + const { on, ...rest } = props; + + const [activeArrow, setActiveArrow] = useState(0); + + // Lower to make it animate faster + const SPEED = 200; + + useEffect(() => { + const id = setInterval(() => { + setActiveArrow((arrow) => (arrow + 1) % 3); + }, SPEED); + return () => clearInterval(id); + }, []); + + return ( + + + + + + ); +}; diff --git a/vorestation.dme b/vorestation.dme index 4bf4bb73c1..2b80870d9b 100644 --- a/vorestation.dme +++ b/vorestation.dme @@ -1961,6 +1961,7 @@ #include "code\modules\asset_cache\assets\fontawesome.dm" #include "code\modules\asset_cache\assets\icon_ref_map.dm" #include "code\modules\asset_cache\assets\jquery.dm" +#include "code\modules\asset_cache\assets\kitchen_recipes.dm" #include "code\modules\asset_cache\assets\preferences.dm" #include "code\modules\asset_cache\assets\tgfont.dm" #include "code\modules\asset_cache\assets\tgui.dm" From 5c81b06c749d4c6705d55d82403acff74b6a8d2a Mon Sep 17 00:00:00 2001 From: Killian Date: Thu, 28 Nov 2024 23:33:43 +0000 Subject: [PATCH 23/26] space ghost and mining spawn tweaks --- .../subtypes/animal/alien animals/spookyghost.dm | 6 ++++-- maps/submaps/space_rocks/space_rocks_stuff.dm | 10 ++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/spookyghost.dm b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/spookyghost.dm index 5d2084d0f0..6991ecb70e 100644 --- a/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/spookyghost.dm +++ b/code/modules/mob/living/simple_mob/subtypes/animal/alien animals/spookyghost.dm @@ -97,7 +97,8 @@ /mob/living/simple_mob/vore/alienanimals/space_ghost/apply_melee_effects(var/atom/A) var/mob/living/L = A - L.hallucination += 50 + if(L.hallucination <= 100) + L.hallucination += rand(1,10) /mob/living/simple_mob/vore/alienanimals/space_ghost/shoot(atom/A) //We're shooting ghosts at people and need them to have the same faction as their parent, okay? if(!projectiletype) @@ -209,7 +210,8 @@ /mob/living/simple_mob/vore/alienanimals/spooky_ghost/apply_melee_effects(var/atom/A) var/mob/living/L = A if(L && istype(L)) - L.hallucination += rand(1,50) + if(L.hallucination <= 100) + L.hallucination += rand(1,10) /mob/living/simple_mob/vore/alienanimals/spooky_ghost/Life() . = ..() diff --git a/maps/submaps/space_rocks/space_rocks_stuff.dm b/maps/submaps/space_rocks/space_rocks_stuff.dm index ff0d03b854..dfa64b90ce 100644 --- a/maps/submaps/space_rocks/space_rocks_stuff.dm +++ b/maps/submaps/space_rocks/space_rocks_stuff.dm @@ -19,11 +19,13 @@ prob_fall = 40 //guard = 20 mobs_to_pick_from = list( - /mob/living/simple_mob/animal/space/bats = 10, - /mob/living/simple_mob/vore/alienanimals/space_jellyfish = 15, - /mob/living/simple_mob/vore/alienanimals/startreader = 15, - /mob/living/simple_mob/vore/alienanimals/space_ghost = 6, + /mob/living/simple_mob/vore/alienanimals/space_jellyfish = 1, + /mob/living/simple_mob/vore/alienanimals/startreader = 3, + /mob/living/simple_mob/vore/alienanimals/space_ghost = 2, /mob/living/simple_mob/vore/oregrub = 1, + /mob/living/simple_mob/animal/space/ray = 10, + /mob/living/simple_mob/animal/space/bats = 10, + /mob/living/simple_mob/animal/space/gnat = 15, /mob/living/simple_mob/animal/space/carp = 3, /mob/living/simple_mob/animal/space/carp/large = 1, /mob/living/simple_mob/animal/space/carp/large/huge = 1 From 6a8f1bfc408edc40b8e49219d28d4410d0a184c8 Mon Sep 17 00:00:00 2001 From: Killian Date: Fri, 29 Nov 2024 06:41:02 +0000 Subject: [PATCH 24/26] samples from strange rocks --- code/modules/xenoarcheaology/finds/finds.dm | 25 ++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/code/modules/xenoarcheaology/finds/finds.dm b/code/modules/xenoarcheaology/finds/finds.dm index 2dd956bc27..8f30b0cb15 100644 --- a/code/modules/xenoarcheaology/finds/finds.dm +++ b/code/modules/xenoarcheaology/finds/finds.dm @@ -26,9 +26,32 @@ /obj/item/strangerock/New(loc, var/inside_item_type = 0) pixel_x = rand(0,16)-8 pixel_y = rand(0,8)-8 + var/d100 = rand(1,100) if(inside_item_type) - new /obj/item/archaeological_find(src, new_item_type = inside_item_type) + switch(d100) + if(51 to 100) //standard spawn logic 50% of the time + new /obj/item/archaeological_find(src, new_item_type = inside_item_type) + if(21 to 50) // 30% chance + new /obj/item/research_sample/common(src) + if(6 to 20) // 15% chance + new /obj/item/research_sample/uncommon(src) + if(1 to 5) // 5% chance + new /obj/item/research_sample/rare(src) + else //if something went wrong, somehow, generate the usual find + new /obj/item/archaeological_find(src, new_item_type = inside_item_type) + else //if this strange rock isn't set to generate a find for whatever reason, create a sample 75% of the time (this shouldn't happen unless the rock is mapped in or adminspawned) + switch(d100) + if(76 to 100) + return + if(21 to 75) + new /obj/item/research_sample/common(src) + if(6 to 20) + new /obj/item/research_sample/uncommon(src) + if(1 to 5) + new /obj/item/research_sample/rare(src) + else //if we somehow glitched + return //do nothing /obj/item/strangerock/attackby(var/obj/item/I, var/mob/user) if(istype(I, /obj/item/pickaxe/brush)) From 633cc9514c42b6efa10631cbcffef2c1f1db80a7 Mon Sep 17 00:00:00 2001 From: Killian Date: Fri, 29 Nov 2024 06:41:02 +0000 Subject: [PATCH 25/26] samples from strange rocks --- code/modules/xenoarcheaology/finds/finds.dm | 25 ++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/code/modules/xenoarcheaology/finds/finds.dm b/code/modules/xenoarcheaology/finds/finds.dm index 2dd956bc27..8f30b0cb15 100644 --- a/code/modules/xenoarcheaology/finds/finds.dm +++ b/code/modules/xenoarcheaology/finds/finds.dm @@ -26,9 +26,32 @@ /obj/item/strangerock/New(loc, var/inside_item_type = 0) pixel_x = rand(0,16)-8 pixel_y = rand(0,8)-8 + var/d100 = rand(1,100) if(inside_item_type) - new /obj/item/archaeological_find(src, new_item_type = inside_item_type) + switch(d100) + if(51 to 100) //standard spawn logic 50% of the time + new /obj/item/archaeological_find(src, new_item_type = inside_item_type) + if(21 to 50) // 30% chance + new /obj/item/research_sample/common(src) + if(6 to 20) // 15% chance + new /obj/item/research_sample/uncommon(src) + if(1 to 5) // 5% chance + new /obj/item/research_sample/rare(src) + else //if something went wrong, somehow, generate the usual find + new /obj/item/archaeological_find(src, new_item_type = inside_item_type) + else //if this strange rock isn't set to generate a find for whatever reason, create a sample 75% of the time (this shouldn't happen unless the rock is mapped in or adminspawned) + switch(d100) + if(76 to 100) + return + if(21 to 75) + new /obj/item/research_sample/common(src) + if(6 to 20) + new /obj/item/research_sample/uncommon(src) + if(1 to 5) + new /obj/item/research_sample/rare(src) + else //if we somehow glitched + return //do nothing /obj/item/strangerock/attackby(var/obj/item/I, var/mob/user) if(istype(I, /obj/item/pickaxe/brush)) From c02a954816329c6280e4bad9779cd813c8eee54c Mon Sep 17 00:00:00 2001 From: Casey Date: Sun, 1 Dec 2024 17:16:07 -0500 Subject: [PATCH 26/26] Map Swap --- maps/~map_system/_map_selection.dm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/maps/~map_system/_map_selection.dm b/maps/~map_system/_map_selection.dm index 879f058f54..47ff0d984d 100644 --- a/maps/~map_system/_map_selection.dm +++ b/maps/~map_system/_map_selection.dm @@ -5,8 +5,8 @@ /* FOR LIVE SERVER */ /*********************/ -#define USE_MAP_TETHER -//#define USE_MAP_STELLARDELIGHT +//#define USE_MAP_TETHER +#define USE_MAP_STELLARDELIGHT //#define USE_MAP_GROUNDBASE // Debug