From fdcd4d39799552a406765d209cf0dc99f97ae5dc Mon Sep 17 00:00:00 2001 From: John Willard <53777086+JohnFulpWillard@users.noreply.github.com> Date: Sat, 10 Feb 2024 12:57:19 -0500 Subject: [PATCH] Adds a signal to buying items from the uplink (& fixes TC misinfo) (#81372) ## About The Pull Request Adds a signal when someone buys an item from the uplink and removes single-letter vars from the ``spawn_item`` proc, and adds/standardizes add/removing of telecrystals from uplinks (and admin setting how much TC they have) to ensure the UI always has the right amount of telecrystals displayed in it. ## Why It's Good For The Game There are reasons why someone would want to hook up to a traitor's uplink and listen to items they purchase to do any special effect on-purchase, so this adds support to do anything in the future with it. Also tells players how much TC they actually have without forcing them to close/reopen the UI every time they insert some TC in it by hand. ## Changelog :cl: fix: Uplinks now update their UI when you add telecrystals in them, so you don't need to close and reopen it. /:cl: --- code/__DEFINES/dcs/signals/uplink.dm | 2 + code/datums/components/uplink.dm | 11 +---- code/datums/elements/uplink_reimburse.dm | 7 ++-- code/datums/mind/_mind.dm | 11 +++-- code/game/objects/items/stacks/telecrystal.dm | 2 +- .../nukeop/equipment/nuclear_challenge.dm | 2 +- code/modules/antagonists/nukeop/nukeop.dm | 4 +- .../antagonists/traitor/traitor_objective.dm | 4 +- .../antagonists/traitor/uplink_handler.dm | 9 ++++ .../living/basic/drone/extra_drone_types.dm | 2 +- .../computers/item/disks/virus_disk.dm | 2 +- code/modules/uplink/uplink_items.dm | 42 ++++++++++++------- tgstation.dme | 1 + 13 files changed, 60 insertions(+), 39 deletions(-) create mode 100644 code/__DEFINES/dcs/signals/uplink.dm diff --git a/code/__DEFINES/dcs/signals/uplink.dm b/code/__DEFINES/dcs/signals/uplink.dm new file mode 100644 index 00000000000..1daa4f31270 --- /dev/null +++ b/code/__DEFINES/dcs/signals/uplink.dm @@ -0,0 +1,2 @@ +///Signal sent to a mob when they purchase an item from their uplink: (datum/uplink_handler/uplink_handler_source, atom/spawned_item, mob/user) +#define COMSIG_ON_UPLINK_PURCHASE "comsig_on_uplink_purchase" diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm index e418988c058..e4e6e611ebc 100644 --- a/code/datums/components/uplink.dm +++ b/code/datums/components/uplink.dm @@ -113,15 +113,6 @@ new /obj/effect/decal/cleanable/ash(get_turf(uplink_item)) qdel(uplink_item) -/// Adds telecrystals to the uplink. It is bad practice to use this outside of the component itself. -/datum/component/uplink/proc/add_telecrystals(telecrystals_added) - set_telecrystals(uplink_handler.telecrystals + telecrystals_added) - -/// Sets the telecrystals of the uplink. It is bad practice to use this outside of the component itself. -/datum/component/uplink/proc/set_telecrystals(new_telecrystal_amount) - uplink_handler.telecrystals = new_telecrystal_amount - uplink_handler.on_update() - /datum/component/uplink/InheritComponent(datum/component/uplink/uplink) lockable |= uplink.lockable active |= uplink.active @@ -135,7 +126,7 @@ if(!silent) to_chat(user, span_notice("You slot [telecrystals] into [parent] and charge its internal uplink.")) var/amt = telecrystals.amount - uplink_handler.telecrystals += amt + uplink_handler.add_telecrystals(amt) telecrystals.use(amt) log_uplink("[key_name(user)] loaded [amt] telecrystals into [parent]'s uplink") diff --git a/code/datums/elements/uplink_reimburse.dm b/code/datums/elements/uplink_reimburse.dm index 3ff182ec231..73a2032fee1 100644 --- a/code/datums/elements/uplink_reimburse.dm +++ b/code/datums/elements/uplink_reimburse.dm @@ -22,7 +22,7 @@ RegisterSignal(target, COMSIG_ATOM_EXAMINE, PROC_REF(on_examine)) RegisterSignal(target, COMSIG_ITEM_ATTEMPT_TC_REIMBURSE, PROC_REF(reimburse)) RegisterSignal(target,COMSIG_TRAITOR_ITEM_USED(target.type), PROC_REF(used)) - + /datum/element/uplink_reimburse/Detach(datum/target) UnregisterSignal(target, list(COMSIG_ATOM_EXAMINE, COMSIG_TRAITOR_ITEM_USED(target.type), COMSIG_ITEM_ATTEMPT_TC_REIMBURSE)) @@ -47,10 +47,11 @@ to_chat(user, span_notice("You tap [uplink_comp.uplink_handler] with [refund_item], and a moment after [refund_item] disappears in a puff of red smoke!")) do_sparks(2, source = uplink_comp.uplink_handler) - uplink_comp.add_telecrystals(refundable_tc) + uplink_comp.uplink_handler.add_telecrystals(refundable_tc) qdel(refund_item) + /// If the item is used, it needs to no longer be refundable /datum/element/uplink_reimburse/proc/used(datum/target) SIGNAL_HANDLER - + Detach(target) diff --git a/code/datums/mind/_mind.dm b/code/datums/mind/_mind.dm index 84942a9684c..6bfdd6070c7 100644 --- a/code/datums/mind/_mind.dm +++ b/code/datums/mind/_mind.dm @@ -457,9 +457,14 @@ if(check_rights(R_FUN)) var/datum/component/uplink/U = find_syndicate_uplink() if(U) - var/crystals = input("Amount of telecrystals for [key]","Syndicate uplink", U.uplink_handler.telecrystals) as null | num - if(!isnull(crystals)) - U.uplink_handler.telecrystals = crystals + var/crystals = tgui_input_number( + user = usr, + message = "Amount of telecrystals for [key]", + title = "Syndicate uplink", + default = U.uplink_handler.telecrystals, + ) + if(crystals && isnum(crystals)) + U.uplink_handler.set_telecrystals(crystals) message_admins("[key_name_admin(usr)] changed [current]'s telecrystal count to [crystals].") log_admin("[key_name(usr)] changed [current]'s telecrystal count to [crystals].") if("progression") diff --git a/code/game/objects/items/stacks/telecrystal.dm b/code/game/objects/items/stacks/telecrystal.dm index 51d21d6ef6c..a6bbe3bfe19 100644 --- a/code/game/objects/items/stacks/telecrystal.dm +++ b/code/game/objects/items/stacks/telecrystal.dm @@ -21,7 +21,7 @@ var/datum/component/uplink/hidden_uplink = uplink.GetComponent(/datum/component/uplink) if(hidden_uplink) - hidden_uplink.add_telecrystals(amount) + hidden_uplink.uplink_handler.add_telecrystals(amount) use(amount) to_chat(user, span_notice("You press [src] onto yourself and charge your hidden uplink.")) return ITEM_INTERACT_SUCCESS diff --git a/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm b/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm index 734025e9a37..a7611c24448 100644 --- a/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm +++ b/code/modules/antagonists/nukeop/equipment/nuclear_challenge.dm @@ -118,7 +118,7 @@ GLOBAL_LIST_EMPTY(jam_on_wardec) var/tc_per_nukie = round(tc_to_distribute / (length(orphans)+length(uplinks))) for (var/datum/component/uplink/uplink in uplinks) - uplink.add_telecrystals(tc_per_nukie) + uplink.uplink_handler.add_telecrystals(tc_per_nukie) tc_to_distribute -= tc_per_nukie for (var/mob/living/L in orphans) diff --git a/code/modules/antagonists/nukeop/nukeop.dm b/code/modules/antagonists/nukeop/nukeop.dm index cf7d90bccf6..6278d5ddaea 100644 --- a/code/modules/antagonists/nukeop/nukeop.dm +++ b/code/modules/antagonists/nukeop/nukeop.dm @@ -63,7 +63,7 @@ var/extra_tc = CEILING(GLOB.joined_player_list.len/5, 5) var/datum/component/uplink/uplink = owner.find_syndicate_uplink() if (uplink) - uplink.add_telecrystals(extra_tc) + uplink.uplink_handler.add_telecrystals(extra_tc) var/datum/component/uplink/uplink = owner.find_syndicate_uplink() if(uplink) @@ -617,7 +617,7 @@ nukie.mind.add_antag_datum(antag_datum, src) var/datum/component/uplink/uplink = nukie.mind.find_syndicate_uplink() - uplink?.set_telecrystals(tc_to_spawn) + uplink?.uplink_handler.set_telecrystals(tc_to_spawn) // add some pizzazz do_sparks(4, FALSE, spawn_loc) diff --git a/code/modules/antagonists/traitor/traitor_objective.dm b/code/modules/antagonists/traitor/traitor_objective.dm index d60820c3fce..3e133401573 100644 --- a/code/modules/antagonists/traitor/traitor_objective.dm +++ b/code/modules/antagonists/traitor/traitor_objective.dm @@ -191,7 +191,7 @@ handle_cleanup() log_traitor("[key_name(handler.owner)] [objective_state == OBJECTIVE_STATE_INACTIVE? "missed" : "failed"] [to_debug_string()]") if(penalty_cost) - handler.telecrystals -= penalty_cost + handler.add_telecrystals(-penalty_cost) objective_state = OBJECTIVE_STATE_FAILED else objective_state = OBJECTIVE_STATE_INVALID @@ -227,7 +227,7 @@ /// Called when rewards should be given to the user. /datum/traitor_objective/proc/completion_payout() handler.progression_points += progression_reward - handler.telecrystals += telecrystal_reward + handler.add_telecrystals(telecrystal_reward) /// Used for sending data to the uplink UI /datum/traitor_objective/proc/uplink_ui_data(mob/user) diff --git a/code/modules/antagonists/traitor/uplink_handler.dm b/code/modules/antagonists/traitor/uplink_handler.dm index aa26b360a75..f78ddb02478 100644 --- a/code/modules/antagonists/traitor/uplink_handler.dm +++ b/code/modules/antagonists/traitor/uplink_handler.dm @@ -254,3 +254,12 @@ return to_act_on.ui_perform_action(user, action) + +///Helper to add telecrystals to the uplink handler, calling set_telecrystals. +/datum/uplink_handler/proc/add_telecrystals(amount) + set_telecrystals(telecrystals + amount) + +///Sets how many telecrystals the uplink handler has, then updates the UI for any players watching. +/datum/uplink_handler/proc/set_telecrystals(amount) + telecrystals = amount + on_update() diff --git a/code/modules/mob/living/basic/drone/extra_drone_types.dm b/code/modules/mob/living/basic/drone/extra_drone_types.dm index 927d28f0ca2..08c9278b753 100644 --- a/code/modules/mob/living/basic/drone/extra_drone_types.dm +++ b/code/modules/mob/living/basic/drone/extra_drone_types.dm @@ -33,7 +33,7 @@ /mob/living/basic/drone/syndrone/Initialize(mapload) . = ..() var/datum/component/uplink/hidden_uplink = internal_storage.GetComponent(/datum/component/uplink) - hidden_uplink.set_telecrystals(telecrystal_count) + hidden_uplink.uplink_handler.set_telecrystals(telecrystal_count) /obj/effect/mob_spawn/ghost_role/drone/syndrone name = "syndrone shell" diff --git a/code/modules/modular_computers/computers/item/disks/virus_disk.dm b/code/modules/modular_computers/computers/item/disks/virus_disk.dm index e3eac7736f5..3f646b22d8a 100644 --- a/code/modules/modular_computers/computers/item/disks/virus_disk.dm +++ b/code/modules/modular_computers/computers/item/disks/virus_disk.dm @@ -154,7 +154,7 @@ hidden_uplink.uplink_handler.generate_objectives() SStraitor.register_uplink_handler(hidden_uplink.uplink_handler) else - hidden_uplink.add_telecrystals(telecrystals) + hidden_uplink.uplink_handler.add_telecrystals(telecrystals) telecrystals = 0 hidden_uplink.locked = FALSE hidden_uplink.active = TRUE diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index 32783504fe8..65935f077e3 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -1,4 +1,3 @@ - // TODO: Work into reworked uplinks. /// Selects a set number of unique items from the uplink, and deducts a percentage discount from them /proc/create_uplink_sales(num, datum/uplink_category/category, limited_stock, list/sale_items) @@ -8,7 +7,20 @@ var/datum/uplink_item/taken_item = pick_n_take(sale_items_copy) var/datum/uplink_item/uplink_item = new taken_item.type() var/discount = uplink_item.get_discount() - var/list/disclaimer = list("Void where prohibited.", "Not recommended for children.", "Contains small parts.", "Check local laws for legality in region.", "Do not taunt.", "Not responsible for direct, indirect, incidental or consequential damages resulting from any defect, error or failure to perform.", "Keep away from fire or flames.", "Product is provided \"as is\" without any implied or expressed warranties.", "As seen on TV.", "For recreational use only.", "Use only as directed.", "16% sales tax will be charged for orders originating within Space Nebraska.") + var/static/list/disclaimer = list( + "Void where prohibited.", + "Not recommended for children.", + "Contains small parts.", + "Check local laws for legality in region.", + "Do not taunt.", + "Not responsible for direct, indirect, incidental or consequential damages resulting from any defect, error or failure to perform.", + "Keep away from fire or flames.", + "Product is provided \"as is\" without any implied or expressed warranties.", + "As seen on TV.", + "For recreational use only.", + "Use only as directed.", + "16% sales tax will be charged for orders originating within Space Nebraska.", + ) uplink_item.limited_stock = limited_stock if(uplink_item.cost >= 20) //Tough love for nuke ops discount *= 0.5 @@ -111,10 +123,10 @@ /// Spawns an item and logs its purchase /datum/uplink_item/proc/purchase(mob/user, datum/uplink_handler/uplink_handler, atom/movable/source) - var/atom/A = spawn_item(item, user, uplink_handler, source) + var/atom/spawned_item = spawn_item(item, user, uplink_handler, source) log_uplink("[key_name(user)] purchased [src] for [cost] telecrystals from [source]'s uplink") if(purchase_log_vis && uplink_handler.purchase_log) - uplink_handler.purchase_log.LogPurchase(A, src, cost) + uplink_handler.purchase_log.LogPurchase(spawned_item, src, cost) if(lock_other_purchases) uplink_handler.shop_locked = TRUE @@ -122,20 +134,20 @@ /datum/uplink_item/proc/spawn_item(spawn_path, mob/user, datum/uplink_handler/uplink_handler, atom/movable/source) if(!spawn_path) return - var/atom/A + var/atom/spawned_item if(ispath(spawn_path)) - A = new spawn_path(get_turf(user)) + spawned_item = new spawn_path(get_turf(user)) else - A = spawn_path + spawned_item = spawn_path if(refundable) - A.AddElement(/datum/element/uplink_reimburse, (refund_amount ? refund_amount : cost)) - if(ishuman(user) && isitem(A)) - var/mob/living/carbon/human/H = user - if(H.put_in_hands(A)) - to_chat(H, span_boldnotice("[A] materializes into your hands!")) - return A - to_chat(user, span_boldnotice("[A] materializes onto the floor!")) - return A + spawned_item.AddElement(/datum/element/uplink_reimburse, (refund_amount ? refund_amount : cost)) + var/mob/living/carbon/human/human_user = user + if(istype(human_user) && isitem(spawned_item) && human_user.put_in_hands(spawned_item)) + to_chat(human_user, span_boldnotice("[spawned_item] materializes into your hands!")) + else + to_chat(user, span_boldnotice("[spawned_item] materializes onto the floor!")) + SEND_SIGNAL(uplink_handler, COMSIG_ON_UPLINK_PURCHASE, spawned_item, user) + return spawned_item ///For special overrides if an item can be bought or not. /datum/uplink_item/proc/can_be_bought(datum/uplink_handler/source) diff --git a/tgstation.dme b/tgstation.dme index 0c076bc191d..29c504f2168 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -357,6 +357,7 @@ #include "code\__DEFINES\dcs\signals\signals_wash.dm" #include "code\__DEFINES\dcs\signals\signals_wizard.dm" #include "code\__DEFINES\dcs\signals\signals_xeno_control.dm" +#include "code\__DEFINES\dcs\signals\uplink.dm" #include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_attack.dm" #include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_explosion.dm" #include "code\__DEFINES\dcs\signals\signals_atom\signals_atom_lighting.dm"