diff --git a/code/datums/elements/voucher_redeemer.dm b/code/datums/elements/voucher_redeemer.dm new file mode 100644 index 00000000000..da53fce3e1e --- /dev/null +++ b/code/datums/elements/voucher_redeemer.dm @@ -0,0 +1,77 @@ +/** + * Accepts a [voucher_type] and a [set_type] and allows the user to redeem the voucher for items from a set. + */ +/datum/element/voucher_redeemer + element_flags = ELEMENT_BESPOKE + argument_hash_start_idx = 2 + /// Typepath to what voucher sets are available to us + var/set_type + /// Typepath to what item must be redeemed + var/voucher_type + /// Cached set of radial options for redeeming a voucher + var/list/cached_options + /// Cached set of voucher sets + var/list/set_instances + +/datum/element/voucher_redeemer/Attach(datum/target, voucher_type = /obj/item/coin, set_type = /datum/voucher_set) + . = ..() + if(!ismovable(target)) + return ELEMENT_INCOMPATIBLE + if(!ispath(voucher_type, /obj/item)) + stack_trace("Invalid voucher type for voucher_redeemer [voucher_type || "null"]") + return ELEMENT_INCOMPATIBLE + if(!ispath(set_type, /datum/voucher_set)) + stack_trace("Invalid set type for voucher_redeemer [set_type || "null"]") + return ELEMENT_INCOMPATIBLE + + src.voucher_type = voucher_type + src.set_type = set_type + RegisterSignal(target, COMSIG_ATOM_ITEM_INTERACTION, PROC_REF(redeem_voucher)) + +/datum/element/voucher_redeemer/Detach(datum/target) + . = ..() + UnregisterSignal(target, COMSIG_ATOM_ITEM_INTERACTION) + +/datum/element/voucher_redeemer/proc/redeem_voucher(atom/source, mob/living/redeemer, obj/item/voucher, list/modifiers) + SIGNAL_HANDLER + + INVOKE_ASYNC(src, PROC_REF(redeem_voucher_async), source, redeemer, voucher) + return ITEM_INTERACT_SUCCESS + +/datum/element/voucher_redeemer/proc/redeem_voucher_async(atom/source, mob/living/redeemer, obj/item/voucher) + if(!set_instances) + set_instances = list() + for(var/datum/voucher_set/static_set as anything in subtypesof(set_type)) + set_instances[initial(static_set.name)] = new static_set() + + if(!cached_options) + cached_options = list() + for(var/set_name in set_instances) + var/datum/voucher_set/current_set = set_instances[set_name] + var/datum/radial_menu_choice/option = new() + option.image = image(icon = current_set.icon, icon_state = current_set.icon_state) + if(current_set.description) + option.info = span_boldnotice(current_set.description) + cached_options[set_name] = option + + var/selection = show_radial_menu(redeemer, source, cached_options, custom_check = CALLBACK(src, PROC_REF(check_menu), voucher, redeemer), radius = 38, require_near = TRUE, tooltips = TRUE) + if(!selection) + return + + var/datum/voucher_set/chosen_set = set_instances[selection] + chosen_set.spawn_set(source.drop_location()) + if(chosen_set.blackbox_key) + SSblackbox.record_feedback("tally", chosen_set.blackbox_key, 1, selection) + source.balloon_alert(redeemer, "redeemed [LOWER_TEXT(selection)]") + qdel(voucher) + +/datum/element/voucher_redeemer/proc/check_menu(obj/item/voucher, mob/living/redeemer) + if(!istype(redeemer)) + return FALSE + if(redeemer.incapacitated) + return FALSE + if(QDELETED(voucher)) + return FALSE + if(!redeemer.is_holding(voucher)) + return FALSE + return TRUE diff --git a/code/game/machinery/computer/orders/order_computer/mining_order.dm b/code/game/machinery/computer/orders/order_computer/mining_order.dm index 7bce69ffc02..e2e1477792e 100644 --- a/code/game/machinery/computer/orders/order_computer/mining_order.dm +++ b/code/game/machinery/computer/orders/order_computer/mining_order.dm @@ -26,6 +26,10 @@ blackbox_key = "mining" announcement_line = "A shaft miner has ordered equipment which will arrive on the cargo shuttle! Please make sure it gets to them as soon as possible!" +/obj/machinery/computer/order_console/mining/Initialize(mapload) + . = ..() + AddElement(/datum/element/voucher_redeemer, /obj/item/mining_voucher, /datum/voucher_set/mining) + /obj/machinery/computer/order_console/mining/subtract_points(final_cost, obj/item/card/id/card) if(final_cost <= card.registered_account.mining_points) card.registered_account.mining_points -= final_cost @@ -68,73 +72,10 @@ if(!.) flick("mining-deny", src) -/obj/machinery/computer/order_console/mining/attackby(obj/item/weapon, mob/user, params) - if(istype(weapon, /obj/item/mining_voucher)) - redeem_voucher(weapon, user) - return - //SKYRAT EDIT ADDITON BEGIN - SEVA - if(istype(weapon, /obj/item/suit_voucher)) - redeem_suit_voucher(weapon, user) - return - //SKYRAT EDIT ADDITON END - return ..() - /obj/machinery/computer/order_console/mining/update_icon_state() icon_state = "[initial(icon_state)][powered() ? null : "-off"]" return ..() - -/** - * Allows user to redeem a mining voucher for one set of a mining equipment - * - * * Arguments: - * * voucher The mining voucher that is being used to redeem the mining equipment - * * redeemer The mob that is redeeming the mining equipment - */ -/obj/machinery/computer/order_console/mining/proc/redeem_voucher(obj/item/mining_voucher/voucher, mob/redeemer) - var/static/list/set_types - if(!set_types) - set_types = list() - for(var/datum/voucher_set/static_set as anything in subtypesof(/datum/voucher_set)) - set_types[initial(static_set.name)] = new static_set - - var/list/items = list() - for(var/set_name in set_types) - var/datum/voucher_set/current_set = set_types[set_name] - var/datum/radial_menu_choice/option = new - option.image = image(icon = current_set.icon, icon_state = current_set.icon_state) - option.info = span_boldnotice(current_set.description) - items[set_name] = option - - var/selection = show_radial_menu(redeemer, src, items, custom_check = CALLBACK(src, PROC_REF(check_menu), voucher, redeemer), radius = 38, require_near = TRUE, tooltips = TRUE) - if(!selection) - return - - var/datum/voucher_set/chosen_set = set_types[selection] - for(var/item in chosen_set.set_items) - new item(drop_location()) - - SSblackbox.record_feedback("tally", "mining_voucher_redeemed", 1, selection) - qdel(voucher) - -/** - * Checks if we are allowed to interact with a radial menu - * - * * Arguments: - * * voucher The mining voucher that is being used to redeem a mining equipment - * * redeemer The living mob interacting with the menu - */ -/obj/machinery/computer/order_console/mining/proc/check_menu(obj/item/mining_voucher/voucher, mob/living/redeemer) - if(!istype(redeemer)) - return FALSE - if(redeemer.incapacitated) - return FALSE - if(QDELETED(voucher)) - return FALSE - if(!redeemer.is_holding(voucher)) - return FALSE - return TRUE - /**********************Mining Equipment Voucher**********************/ /obj/item/mining_voucher diff --git a/code/modules/mining/voucher_sets.dm b/code/modules/mining/voucher_sets.dm index 1c61f707ea5..b5190b2686d 100644 --- a/code/modules/mining/voucher_sets.dm +++ b/code/modules/mining/voucher_sets.dm @@ -1,32 +1,54 @@ /** * # Voucher Set * - * A set consisting of a various equipment that can be then used as a reward for redeeming a mining voucher. + * A set consisting of a various equipment that can be then used as a reward for redeeming a voucher. * + * See [Voucher Redeemer](/datum/element/voucher_redeemer) for where these sets are handled. */ /datum/voucher_set - /// Name of the set + /// Required, Name of the set. var/name - /// Description of the set + /// Optional, description of the set var/description - /// Icon of the set + /// Optional, Icon of the set. Defaults to first item if not set. var/icon - /// Icon state of the set + /// Optional, Icon state of the set. Defaults to first item if not set. var/icon_state - /// List of items contained in the set - var/list/set_items = list() + /// Required, List of items contained in the set + var/list/atom/set_items + /// Optional, what key to use for blackbox feedback. No data will be recorded if not set. + var/blackbox_key -/datum/voucher_set/crusher_kit +/datum/voucher_set/New() + . = ..() + if(!length(set_items)) + stack_trace("Voucher set [type] has no items set.") + return + if(isnull(icon)) + icon = initial(set_items[1].icon) + if(isnull(icon_state)) + icon_state = initial(set_items[1].icon_state) + if(isnull(name)) + stack_trace("Voucher set [type] has no name set.") + +/datum/voucher_set/proc/spawn_set(atom/spawn_loc) + for(var/item in set_items) + new item(spawn_loc) + +/datum/voucher_set/mining + blackbox_key = "mining_voucher_redeemed" + +/datum/voucher_set/mining/crusher_kit name = "Crusher Kit" description = "Contains a kinetic crusher and a pocket fire extinguisher. Kinetic crusher is a versatile melee mining tool capable both of mining and fighting local fauna, however it is difficult to use effectively for anyone but most skilled and/or suicidal miners." icon = 'icons/obj/mining.dmi' icon_state = "crusher" set_items = list( - /obj/item/extinguisher/mini, /obj/item/kinetic_crusher, - ) + /obj/item/extinguisher/mini, + ) -/datum/voucher_set/extraction_kit +/datum/voucher_set/mining/extraction_kit name = "Extraction and Rescue Kit" description = "Contains a fulton extraction pack and a beacon signaller, which allows you to send back home minerals, items and dead bodies without having to use the mining shuttle. And as a bonus, you get 30 marker beacons to help you better mark your path." icon = 'icons/obj/fulton.dmi' @@ -35,28 +57,28 @@ /obj/item/extraction_pack, /obj/item/fulton_core, /obj/item/stack/marker_beacon/thirty, - ) + ) -/datum/voucher_set/resonator_kit +/datum/voucher_set/mining/resonator_kit name = "Resonator Kit" description = "Contains a resonator and a pocket fire extinguisher. Resonator is a handheld device that creates small fields of energy that resonate until they detonate, crushing rock. It does increased damage in low pressure." icon = 'icons/obj/mining.dmi' icon_state = "resonator" set_items = list( - /obj/item/extinguisher/mini, /obj/item/resonator, - ) + /obj/item/extinguisher/mini, + ) -/datum/voucher_set/survival_capsule +/datum/voucher_set/mining/survival_capsule name = "Survival Capsule and Explorer's Webbing" description = "Contains an explorer's webbing, which allows you to carry even more mining equipment and already has a spare shelter capsule in it." icon = 'icons/obj/clothing/belts.dmi' icon_state = "explorer1" set_items = list( /obj/item/storage/belt/mining/vendor, - ) + ) -/datum/voucher_set/minebot_kit +/datum/voucher_set/mining/minebot_kit name = "Minebot Kit" description = "Contains a little minebot companion that helps you in storing ore and hunting wildlife. Also comes with an upgraded industrial welding tool (80u), a welding mask and a KA modkit that allows shots to pass through the minebot." icon = 'icons/mob/silicon/aibots.dmi' @@ -66,9 +88,9 @@ /obj/item/weldingtool/hugetank, /obj/item/clothing/head/utility/welding, /obj/item/borg/upgrade/modkit/minebot_passthrough, - ) + ) -/datum/voucher_set/conscription_kit +/datum/voucher_set/mining/conscription_kit name = "Mining Conscription Kit" description = "Contains a whole new mining starter kit for one crewmember, consisting of a proto-kinetic accelerator, a survival knife, a seclite, an explorer's suit, mesons, an automatic mining scanner, a mining satchel, a gas mask, a mining radio key and a special ID card with a basic mining access." icon = 'icons/obj/storage/backpack.dmi' diff --git a/tgstation.dme b/tgstation.dme index 700460be321..b7e770bac1d 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -1762,6 +1762,7 @@ #include "code\datums\elements\uplink_reimburse.dm" #include "code\datums\elements\venomous.dm" #include "code\datums\elements\volatile_gas_storage.dm" +#include "code\datums\elements\voucher_redeemer.dm" #include "code\datums\elements\waddling.dm" #include "code\datums\elements\wall_engraver.dm" #include "code\datums\elements\wall_smasher.dm"