From cc175499529e8c41de8609a8f5212ea14927c6ff Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Fri, 13 May 2022 08:49:15 -0600 Subject: [PATCH 01/47] add trade_beacon.dm --- .../modules/overmap_trade/tradebeacon.dm | 62 +++++++++++++++++++ 1 file changed, 62 insertions(+) create mode 100644 mods/persistence/modules/overmap_trade/tradebeacon.dm diff --git a/mods/persistence/modules/overmap_trade/tradebeacon.dm b/mods/persistence/modules/overmap_trade/tradebeacon.dm new file mode 100644 index 00000000000..31e4033f118 --- /dev/null +++ b/mods/persistence/modules/overmap_trade/tradebeacon.dm @@ -0,0 +1,62 @@ +/obj/machinery/trade_beacon + name = "trade beacon" + desc = "An large broadcasting array meant to control trade between the Outreach system and the wider galaxy. ." + icon = 'icons/obj/jukebox_new.dmi' + icon_state = "jukebox3-nopower" + var/state_base = "jukebox3" + anchored = 1 + density = 1 + power_channel = EQUIP + idle_power_usage = 10 + active_power_usage = 100 + clicksound = 'sound/machines/buttonbeep.ogg' + pixel_x = -8 + + uncreated_component_parts = null + stat_immune = 0 + construct_state = /decl/machine_construction/default/panel_closed + var/state = 1 +/obj/machinery/trade_beacon/interface_interact() + ui_interact(user) + return TRUE + + +/obj/machinery/trade_beacon/powered() + return 1 + +/obj/machinery/trade_beacon/power_change() + return + +/obj/machinery/trade_beacon/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) + user.set_machine(src) + var/list/data = list() + data["state"] = state + var/name + var/cost + var/type_name + var/path + if (state == BG_READY) + data["points"] = points + var/list/listed_types = list() + for(var/c_type =1 to products.len) + type_name = products[c_type] + var/list/current_content = products[type_name] + var/list/listed_products = list() + for(var/c_product =1 to current_content.len) + path = current_content[c_product] + var/atom/A = path + name = initial(A.name) + cost = current_content[path] + listed_products.Add(list(list( + "product_index" = c_product, + "name" = name, + "cost" = cost))) + listed_types.Add(list(list( + "type_name" = type_name, + "products" = listed_products))) + data["types"] = listed_types + ui = SSnano.try_update_ui(user, src, ui_key, ui, data, force_open) + if (!ui) + ui = new(user, src, ui_key, "trade_beacon.tmpl", "Trade Beacon", 440, 600) + ui.set_initial_data(data) + ui.open() From 392de096e49e1addc987fabe62382e501e7bd97c Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Fri, 13 May 2022 08:49:32 -0600 Subject: [PATCH 02/47] Create trade_beacon.tmpl --- nano/templates/trade_beacon.tmpl | 47 ++++++++++++++++++++++++++++++++ 1 file changed, 47 insertions(+) create mode 100644 nano/templates/trade_beacon.tmpl diff --git a/nano/templates/trade_beacon.tmpl b/nano/templates/trade_beacon.tmpl new file mode 100644 index 00000000000..a861bb5f267 --- /dev/null +++ b/nano/templates/trade_beacon.tmpl @@ -0,0 +1,47 @@ + + +

{{:data.title}}

+ +
+
+ Linked Network: +
+
+ {{:data.network}} +
+
+
+
+ Tax Rate: +
+
+ {{:data.tax}}% +
+
+


+{{if data.authed}} +
+
+ Tax Rate: +
+
+ {{:data.tax}}% +
+
+ + +{{else}} +
+
+ Tax Rate: +
+
+ {{:data.tax}}% +
+
+{{/if}} +

+{{:helper.link('Disconnect from Network', '', {'disconnect' : '1'}, null)}} From 658b1b193fedc79f6d1931fcfa621422c2eef381 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Fri, 13 May 2022 14:56:25 -0600 Subject: [PATCH 03/47] Update tradebeacon.dm --- .../modules/overmap_trade/tradebeacon.dm | 26 ++++++++++++++----- 1 file changed, 19 insertions(+), 7 deletions(-) diff --git a/mods/persistence/modules/overmap_trade/tradebeacon.dm b/mods/persistence/modules/overmap_trade/tradebeacon.dm index 31e4033f118..1c0d380c35a 100644 --- a/mods/persistence/modules/overmap_trade/tradebeacon.dm +++ b/mods/persistence/modules/overmap_trade/tradebeacon.dm @@ -1,21 +1,33 @@ +/datum/beacon_import + var/name = "Beacon Import" + var/price_per_purchase = 1 + var/unit_per_purchase = 1 + var/container_type + var/unit_type + +/datum/beacon_export + var/name = "Beacon Export" + var/price_per_purchase = 1 + var/unit_per_purchase = 1 + var/unit_type + /obj/machinery/trade_beacon name = "trade beacon" - desc = "An large broadcasting array meant to control trade between the Outreach system and the wider galaxy. ." + desc = "An large broadcasting array meant to control trade between the Outreach system and the wider galaxy." icon = 'icons/obj/jukebox_new.dmi' icon_state = "jukebox3-nopower" - var/state_base = "jukebox3" anchored = 1 density = 1 power_channel = EQUIP - idle_power_usage = 10 - active_power_usage = 100 + idle_power_usage = 0 + active_power_usage = 0 clicksound = 'sound/machines/buttonbeep.ogg' - pixel_x = -8 - uncreated_component_parts = null stat_immune = 0 construct_state = /decl/machine_construction/default/panel_closed - var/state = 1 + var/list/imports = list() + var/list/exports = list() + /obj/machinery/trade_beacon/interface_interact() ui_interact(user) return TRUE From 72510d840acbf5c246a7d3925f3294c613cabd0a Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Fri, 13 May 2022 14:56:32 -0600 Subject: [PATCH 04/47] Update trade_beacon.tmpl --- nano/templates/trade_beacon.tmpl | 47 ++++++++------------------------ 1 file changed, 12 insertions(+), 35 deletions(-) diff --git a/nano/templates/trade_beacon.tmpl b/nano/templates/trade_beacon.tmpl index a861bb5f267..cbc7668ae5f 100644 --- a/nano/templates/trade_beacon.tmpl +++ b/nano/templates/trade_beacon.tmpl @@ -6,42 +6,19 @@ Used In File(s): mods\persistence\modules\overmap_trade\trade_beacon.dm

{{:data.title}}

-
- Linked Network: -
-
- {{:data.network}} -
+
+ Linked Network: +
+
+ {{:data.network}} +
-
- Tax Rate: -
-
- {{:data.tax}}% -
-
-


-{{if data.authed}} -
-
- Tax Rate: -
-
- {{:data.tax}}% -
+
+ Tax Rate:
- - -{{else}} -
-
- Tax Rate: -
-
- {{:data.tax}}% -
+
+ {{:helper.link( data.tax, '', {'action' : 'change_tax'}, data.authed ? null : 'disabled', null)}}%
-{{/if}} -

-{{:helper.link('Disconnect from Network', '', {'disconnect' : '1'}, null)}} +
+


From a4f7f9affea85f8cfa61ea53fae42e14c1de9124 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Mon, 16 May 2022 17:27:06 -0700 Subject: [PATCH 05/47] Fix SQL file remove comma --- sql/V100__Persistence.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sql/V100__Persistence.sql b/sql/V100__Persistence.sql index 894407e3f4a..0ee3dac3ccf 100644 --- a/sql/V100__Persistence.sql +++ b/sql/V100__Persistence.sql @@ -66,7 +66,7 @@ CREATE TABLE IF NOT EXISTS `limbo` ( `p_ids` longtext NOT NULL, `metadata` varchar(64) DEFAULT NULL, `limbo_assoc` varchar(12) NOT NULL, - `metadata2` varchar(64) DEFAULT NULL, + `metadata2` varchar(64) DEFAULT NULL ) ENGINE=InnoDB DEFAULT CHARSET=UTF8MB4; DROP TABLE IF EXISTS `limbo_list_element`; From 9f9d035e76de9be88aef99b713131320b907e693 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Wed, 18 May 2022 06:09:58 -0700 Subject: [PATCH 06/47] update trade beacon --- .../modules/overmap_trade/tradebeacon.dm | 50 ++++++++++++++++--- 1 file changed, 42 insertions(+), 8 deletions(-) diff --git a/mods/persistence/modules/overmap_trade/tradebeacon.dm b/mods/persistence/modules/overmap_trade/tradebeacon.dm index 1c0d380c35a..21de16d3e90 100644 --- a/mods/persistence/modules/overmap_trade/tradebeacon.dm +++ b/mods/persistence/modules/overmap_trade/tradebeacon.dm @@ -1,11 +1,4 @@ -/datum/beacon_import - var/name = "Beacon Import" - var/price_per_purchase = 1 - var/unit_per_purchase = 1 - var/container_type - var/unit_type - -/datum/beacon_export + /datum/beacon_export var/name = "Beacon Export" var/price_per_purchase = 1 var/unit_per_purchase = 1 @@ -27,6 +20,8 @@ construct_state = /decl/machine_construction/default/panel_closed var/list/imports = list() var/list/exports = list() + var/list/category_names = list() + var/list/category_contents = list() /obj/machinery/trade_beacon/interface_interact() ui_interact(user) @@ -72,3 +67,42 @@ ui = new(user, src, ui_key, "trade_beacon.tmpl", "Trade Beacon", 440, 600) ui.set_initial_data(data) ui.open() + +/obj/machinery/trade_beacon/proc/get_category_contents() + if(!category_contents || !category_contents.len) + generate_categories() + return catogry_contents + +/obj/machinery/trade_beacon/proc/get_category_contents() + if(!category_names || !category_names.len) + generate_categories() + return catogry_names + +/obj/machinery/trade_beacon/proc/generate_categories() + category_names.Cut() + category_contents.Cut() + var/decl/hierarchy/supply_pack/root = GET_DECL(/decl/hierarchy/supply_pack) + var/decl/currency/cur = GET_DECL(global.using_map.default_currency) + for(var/decl/hierarchy/supply_pack/sp in root.children) + var/found = 0 + if(!sp.is_category()) + continue // No children + var/list/category[0] + for(var/decl/hierarchy/supply_pack/spc in sp.get_descendents()) + if((spc.hidden || spc.contraband || !spc.sec_available()) && !emagged || !(spc.type in imports)) + continue + category.Add(list(list( + "name" = spc.name, + "cost" = cur.format_value(spc.cost), + "ref" = "\ref[spc]" + ))) + found = 1 + if(found) + category_names.Add(sp.name) + category_contents[sp.name] = category + +/obj/machinery/trade_beacon/Outreach + imports = list( + /decl/hierarchy/supply_pack/materials/steel50, + /decl/hierarchy/supply_pack/materials/alum50 + ) \ No newline at end of file From b4e1ba896359e05950781f7de41a71bf7a034861 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Wed, 18 May 2022 14:29:02 -0600 Subject: [PATCH 07/47] Update trade_beacon.tmpl --- nano/templates/trade_beacon.tmpl | 32 ++++++++++++++++++++++++++++++-- 1 file changed, 30 insertions(+), 2 deletions(-) diff --git a/nano/templates/trade_beacon.tmpl b/nano/templates/trade_beacon.tmpl index cbc7668ae5f..87504c17a59 100644 --- a/nano/templates/trade_beacon.tmpl +++ b/nano/templates/trade_beacon.tmpl @@ -10,7 +10,7 @@ Used In File(s): mods\persistence\modules\overmap_trade\trade_beacon.dm Linked Network:
- {{:data.network}} + {{:data.network}}
{{:helper.link('Disconnect from Network', '', {'disconnect' : 1}, null, null)}}
@@ -18,7 +18,35 @@ Used In File(s): mods\persistence\modules\overmap_trade\trade_beacon.dm Tax Rate:
- {{:helper.link( data.tax, '', {'action' : 'change_tax'}, data.authed ? null : 'disabled', null)}}% + {{:helper.link( data.tax, '', {'change_tax' : 1}, data.authed ? null : 'disabled', null)}}%



+

Products available at this beacon

+{{for data.categories}} + {{:helper.link(value, null, {'select_category' : value}, data.category == value ? 'selected' : null)}} +{{/for}} +{{if data.category}} + + {{#def.common_supply_header}} + {{for data.possible_purchases}} + + + {{#def.common_supply_header}} + {{else}} + {{:helper.link('Contents', null, {'show_contents' : value.ref})}} + {{/if}} + {{/for}} +
{{:value.name}} + {{:value.cost}} {{:data.currency}} + + {{:helper.link('Order', null, {'order' : value.ref})}} + {{if data.showing_contents_of && data.showing_contents_of == value.ref}} + {{:helper.link('Close', null, {'hide_contents' : 1})}} +
Contents + {{for data.contents_of_order :content :content_index}} +
{{:content.name}} × {{:content.amount}} + {{/for}} +
+
+{{/if}} From c9a97bf7d10326a9a455ef6b5465f222ba2e1c01 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Wed, 18 May 2022 14:29:06 -0600 Subject: [PATCH 08/47] Update tradebeacon.dm --- .../modules/overmap_trade/tradebeacon.dm | 210 +++++++++++++++--- 1 file changed, 184 insertions(+), 26 deletions(-) diff --git a/mods/persistence/modules/overmap_trade/tradebeacon.dm b/mods/persistence/modules/overmap_trade/tradebeacon.dm index 21de16d3e90..7d9e04e9093 100644 --- a/mods/persistence/modules/overmap_trade/tradebeacon.dm +++ b/mods/persistence/modules/overmap_trade/tradebeacon.dm @@ -1,4 +1,4 @@ - /datum/beacon_export +/datum/beacon_export var/name = "Beacon Export" var/price_per_purchase = 1 var/unit_per_purchase = 1 @@ -22,6 +22,11 @@ var/list/exports = list() var/list/category_names = list() var/list/category_contents = list() + var/owner_name = "Owner Name" + var/lore = "A generic trade beacon not associated to any particular owner." + var/showing_contents_of_ref + var/list/contents_of_order = list() + /obj/machinery/trade_beacon/interface_interact() ui_interact(user) @@ -39,35 +44,105 @@ var/list/data = list() data["state"] = state var/name - var/cost - var/type_name - var/path - if (state == BG_READY) - data["points"] = points - var/list/listed_types = list() - for(var/c_type =1 to products.len) - type_name = products[c_type] - var/list/current_content = products[type_name] - var/list/listed_products = list() - for(var/c_product =1 to current_content.len) - path = current_content[c_product] - var/atom/A = path - name = initial(A.name) - cost = current_content[path] - listed_products.Add(list(list( - "product_index" = c_product, - "name" = name, - "cost" = cost))) - listed_types.Add(list(list( - "type_name" = type_name, - "products" = listed_products))) - data["types"] = listed_types + data["categories"] = category_names + if(selected_category) + data["category"] = selected_category + data["possible_purchases"] = category_contents[selected_category] + if(showing_contents_of_ref) + data["showing_contents_of"] = showing_contents_of_ref + data["contents_of_order"] = contents_of_order + + ui = SSnano.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) ui = new(user, src, ui_key, "trade_beacon.tmpl", "Trade Beacon", 440, 600) ui.set_initial_data(data) ui.open() +/obj/machinery/trade_beacon/Topic(href, href_list) +var/mob/user = usr + if(..()) + return 1 + + if(href_list["select_category"]) + clear_order_contents() + selected_category = href_list["select_category"] + return 1 + + if(href_list["show_contents"]) + generate_order_contents(href_list["show_contents"]) + + if(href_list["hide_contents"]) + clear_order_contents() + + if(href_list["change_tax"]) + // tax handling here + + if(href_list["hide_contents"]) + clear_order_contents() + + // Items requiring cargo access go below this entry. Other items go above. + if(!check_access(access_cargo)) + return 1 + + + + +/datum/nano_module/supply/proc/generate_categories() + category_names.Cut() + category_contents.Cut() + var/decl/hierarchy/supply_pack/root = GET_DECL(/decl/hierarchy/supply_pack) + var/decl/currency/cur = GET_DECL(global.using_map.default_currency) + for(var/decl/hierarchy/supply_pack/sp in root.children) + if(!sp.is_category()) + continue // No children + category_names.Add(sp.name) + var/list/category[0] + for(var/decl/hierarchy/supply_pack/spc in sp.get_descendents()) + if((spc.hidden || spc.contraband || !spc.sec_available()) && !emagged) + continue + category.Add(list(list( + "name" = spc.name, + "cost" = cur.format_value(spc.cost), + "ref" = "\ref[spc]" + ))) + category_contents[sp.name] = category + + + + + + + + +/obj/machinery/trade_beacon/proc/generate_order_contents(var/order_ref) + var/decl/hierarchy/supply_pack/sp = locate(order_ref) in SSsupply.master_supply_list + if(!istype(sp)) + return FALSE + contents_of_order.Cut() + showing_contents_of_ref = order_ref + for(var/item_path in sp.contains) // Thanks to Lohikar for helping me with type paths - CarlenWhite + var/obj/item/stack/OB = item_path // Not always a stack, but will always have a name we can fetch. + var/name = initial(OB.name) + var/amount = sp.contains[item_path] || 1 // If it's just one item (has no number associated), fallback to 1. + if(ispath(item_path, /obj/item/stack)) // And if it is a stack, consider the amount + amount *= initial(OB.amount) + + + contents_of_order.Add(list(list( + "name" = name, + "amount" = amount + ))) + + if(sp.contains.len == 0) // Handles the case where sp.contains is empty, e.g. for livecargo + contents_of_order.Add(list(list( + "name" = sp.containername, + "amount" = 1 + ))) + + return TRUE + + /obj/machinery/trade_beacon/proc/get_category_contents() if(!category_contents || !category_contents.len) generate_categories() @@ -102,7 +177,90 @@ category_contents[sp.name] = category /obj/machinery/trade_beacon/Outreach + owner_name = "Nanotrasen" + lore = "Nanotrasen go brrrrrrrrrrrr" imports = list( + /decl/hierarchy/supply_pack/materials/steel50, - /decl/hierarchy/supply_pack/materials/alum50 - ) \ No newline at end of file + /decl/hierarchy/supply_pack/materials/alum50, + /decl/hierarchy/supply_pack/materials/glass50, + /decl/hierarchy/supply_pack/materials/fiberglass50, + /decl/hierarchy/supply_pack/materials/plastic50, + /decl/hierarchy/supply_pack/materials/marble50, + /decl/hierarchy/supply_pack/materials/plasteel50, + /decl/hierarchy/supply_pack/materials/copper50, + /decl/hierarchy/supply_pack/materials/titanium50, + /decl/hierarchy/supply_pack/materials/ocp50, + /decl/hierarchy/supply_pack/materials/graphite50, + /decl/hierarchy/supply_pack/materials/gold10, + /decl/hierarchy/supply_pack/materials/silver10, + /decl/hierarchy/supply_pack/materials/uranium10, + /decl/hierarchy/supply_pack/materials/diamond10, + /decl/hierarchy/supply_pack/materials/wood50, + /decl/hierarchy/supply_pack/materials/mahogany25, + /decl/hierarchy/supply_pack/materials/maple50, + /decl/hierarchy/supply_pack/materials/walnut25, + /decl/hierarchy/supply_pack/materials/ebony25, + /decl/hierarchy/supply_pack/materials/yew25, + + /decl/hierarchy/supply_pack/supply/toner, + /decl/hierarchy/supply_pack/supply/cardboard_sheets, + /decl/hierarchy/supply_pack/supply/stickies, + /decl/hierarchy/supply_pack/supply/wpaper, + /decl/hierarchy/supply_pack/supply/tapes, + /decl/hierarchy/supply_pack/supply/taperolls, + /decl/hierarchy/supply_pack/supply/bogrolls, + + /decl/hierarchy/supply_pack/engineering/electrical, + /decl/hierarchy/supply_pack/engineering/mechanical, + /decl/hierarchy/supply_pack/engineering/pacman_parts, + /decl/hierarchy/supply_pack/engineering/voidsuit_engineering, + + /decl/hierarchy/supply_pack/flooring/carpetbrown, + /decl/hierarchy/supply_pack/flooring/white_tiles, + /decl/hierarchy/supply_pack/flooring/dark_tiles + + /decl/hierarchy/supply_pack/medical/medical, + /decl/hierarchy/supply_pack/medical/atk, + /decl/hierarchy/supply_pack/medical/abk, + /decl/hierarchy/supply_pack/medical/trauma, + /decl/hierarchy/supply_pack/medical/bodybag, + /decl/hierarchy/supply_pack/medical/stretcher, + /decl/hierarchy/supply_pack/medical/wheelchair, + /decl/hierarchy/supply_pack/medical/rescuebag, + /decl/hierarchy/supply_pack/medical/doctorgear, + /decl/hierarchy/supply_pack/medical/autopsy, + /decl/hierarchy/supply_pack/medical/surgery, + /decl/hierarchy/supply_pack/medical/sterile, + /decl/hierarchy/supply_pack/medical/scanner_module, + /decl/hierarchy/supply_pack/medical/defib, + /decl/hierarchy/supply_pack/medical/autocomp, + + /decl/hierarchy/supply_pack/galley/food, + /decl/hierarchy/supply_pack/galley/beef, + /decl/hierarchy/supply_pack/galley/eggs, + /decl/hierarchy/supply_pack/galley/milk, + /decl/hierarchy/supply_pack/galley/pizza, + /decl/hierarchy/supply_pack/galley/barsupplies, + /decl/hierarchy/supply_pack/galley/party, + /decl/hierarchy/supply_pack/galley/beer_dispenser, + /decl/hierarchy/supply_pack/galley/soda_dispenser, + + /decl/hierarchy/supply_pack/operations/orebox, + /decl/hierarchy/supply_pack/operations/bureaucracy, + /decl/hierarchy/supply_pack/operations/voidsuit_engineering, + + /decl/hierarchy/supply_pack/nonessent/painters, + /decl/hierarchy/supply_pack/nonessent/artscrafts, + /decl/hierarchy/supply_pack/nonessent/card_packs, + /decl/hierarchy/supply_pack/nonessent/instruments, + /decl/hierarchy/supply_pack/nonessent/llamps, + /decl/hierarchy/supply_pack/nonessent/chaplaingear, + + /decl/hierarchy/supply_pack/custodial/janitor, + /decl/hierarchy/supply_pack/custodial/cleaning, + /decl/hierarchy/supply_pack/custodial/mousetrap, + /decl/hierarchy/supply_pack/custodial/janitorbiosuits + + + ) From 409aaad68308e5014ea1c841bc46c1b30c29358a Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Fri, 20 May 2022 06:30:15 -0700 Subject: [PATCH 09/47] updates --- mods/persistence/_persistence.dme | 1 + .../modules/overmap_trade/tradebeacon.dm | 106 ++++++------------ nano/templates/trade_beacon.tmpl | 3 +- 3 files changed, 38 insertions(+), 72 deletions(-) diff --git a/mods/persistence/_persistence.dme b/mods/persistence/_persistence.dme index 0466b416983..f1734730fe5 100644 --- a/mods/persistence/_persistence.dme +++ b/mods/persistence/_persistence.dme @@ -160,6 +160,7 @@ #include "modules\overmap\exoplanets\_exoplanet.dm" #include "modules\overmap\exoplanets\turfs.dm" #include "modules\overmap\ships\landable.dm" +#include "modules\overmap_trade\tradebeacon.dm" #include "modules\power\apc.dm" #include "modules\power\port_gen.dm" #include "modules\power\smes.dm" diff --git a/mods/persistence/modules/overmap_trade/tradebeacon.dm b/mods/persistence/modules/overmap_trade/tradebeacon.dm index 7d9e04e9093..67adf74e6ea 100644 --- a/mods/persistence/modules/overmap_trade/tradebeacon.dm +++ b/mods/persistence/modules/overmap_trade/tradebeacon.dm @@ -3,7 +3,7 @@ var/price_per_purchase = 1 var/unit_per_purchase = 1 var/unit_type - + /obj/machinery/trade_beacon name = "trade beacon" desc = "An large broadcasting array meant to control trade between the Outreach system and the wider galaxy." @@ -26,12 +26,8 @@ var/lore = "A generic trade beacon not associated to any particular owner." var/showing_contents_of_ref var/list/contents_of_order = list() - - -/obj/machinery/trade_beacon/interface_interact() - ui_interact(user) - return TRUE - + var/screen = 1 + var/selected_category /obj/machinery/trade_beacon/powered() return 1 @@ -42,17 +38,17 @@ /obj/machinery/trade_beacon/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) user.set_machine(src) var/list/data = list() - data["state"] = state - var/name - data["categories"] = category_names - if(selected_category) - data["category"] = selected_category - data["possible_purchases"] = category_contents[selected_category] - if(showing_contents_of_ref) - data["showing_contents_of"] = showing_contents_of_ref - data["contents_of_order"] = contents_of_order - - + if(screen == 1) + data["categories"] = category_names + if(selected_category) + data["category"] = selected_category + data["possible_purchases"] = category_contents[selected_category] + if(showing_contents_of_ref) + data["showing_contents_of"] = showing_contents_of_ref + data["contents_of_order"] = contents_of_order + if(screen == 2) + + ui = SSnano.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) ui = new(user, src, ui_key, "trade_beacon.tmpl", "Trade Beacon", 440, 600) @@ -60,7 +56,6 @@ ui.open() /obj/machinery/trade_beacon/Topic(href, href_list) -var/mob/user = usr if(..()) return 1 @@ -74,45 +69,21 @@ var/mob/user = usr if(href_list["hide_contents"]) clear_order_contents() - + if(href_list["change_tax"]) // tax handling here - - if(href_list["hide_contents"]) - clear_order_contents() + if(href_list["set_screen"]) + clear_order_contents() + screen = text2num(href_list["set_screen"]) + return 1 // Items requiring cargo access go below this entry. Other items go above. if(!check_access(access_cargo)) return 1 - - - -/datum/nano_module/supply/proc/generate_categories() - category_names.Cut() - category_contents.Cut() - var/decl/hierarchy/supply_pack/root = GET_DECL(/decl/hierarchy/supply_pack) - var/decl/currency/cur = GET_DECL(global.using_map.default_currency) - for(var/decl/hierarchy/supply_pack/sp in root.children) - if(!sp.is_category()) - continue // No children - category_names.Add(sp.name) - var/list/category[0] - for(var/decl/hierarchy/supply_pack/spc in sp.get_descendents()) - if((spc.hidden || spc.contraband || !spc.sec_available()) && !emagged) - continue - category.Add(list(list( - "name" = spc.name, - "cost" = cur.format_value(spc.cost), - "ref" = "\ref[spc]" - ))) - category_contents[sp.name] = category - - - - - - +/obj/machinery/trade_beacon/proc/clear_order_contents() + contents_of_order.Cut() + showing_contents_of_ref = null /obj/machinery/trade_beacon/proc/generate_order_contents(var/order_ref) @@ -146,12 +117,8 @@ var/mob/user = usr /obj/machinery/trade_beacon/proc/get_category_contents() if(!category_contents || !category_contents.len) generate_categories() - return catogry_contents + return category_contents -/obj/machinery/trade_beacon/proc/get_category_contents() - if(!category_names || !category_names.len) - generate_categories() - return catogry_names /obj/machinery/trade_beacon/proc/generate_categories() category_names.Cut() @@ -164,7 +131,7 @@ var/mob/user = usr continue // No children var/list/category[0] for(var/decl/hierarchy/supply_pack/spc in sp.get_descendents()) - if((spc.hidden || spc.contraband || !spc.sec_available()) && !emagged || !(spc.type in imports)) + if((spc.hidden || !(spc.type in imports))) continue category.Add(list(list( "name" = spc.name, @@ -177,10 +144,9 @@ var/mob/user = usr category_contents[sp.name] = category /obj/machinery/trade_beacon/Outreach - owner_name = "Nanotrasen" + owner_name = "Nanotrasen" lore = "Nanotrasen go brrrrrrrrrrrr" imports = list( - /decl/hierarchy/supply_pack/materials/steel50, /decl/hierarchy/supply_pack/materials/alum50, /decl/hierarchy/supply_pack/materials/glass50, @@ -202,7 +168,7 @@ var/mob/user = usr /decl/hierarchy/supply_pack/materials/walnut25, /decl/hierarchy/supply_pack/materials/ebony25, /decl/hierarchy/supply_pack/materials/yew25, - + /decl/hierarchy/supply_pack/supply/toner, /decl/hierarchy/supply_pack/supply/cardboard_sheets, /decl/hierarchy/supply_pack/supply/stickies, @@ -210,17 +176,17 @@ var/mob/user = usr /decl/hierarchy/supply_pack/supply/tapes, /decl/hierarchy/supply_pack/supply/taperolls, /decl/hierarchy/supply_pack/supply/bogrolls, - + /decl/hierarchy/supply_pack/engineering/electrical, /decl/hierarchy/supply_pack/engineering/mechanical, /decl/hierarchy/supply_pack/engineering/pacman_parts, /decl/hierarchy/supply_pack/engineering/voidsuit_engineering, - + /decl/hierarchy/supply_pack/flooring/carpetbrown, /decl/hierarchy/supply_pack/flooring/white_tiles, - /decl/hierarchy/supply_pack/flooring/dark_tiles - - /decl/hierarchy/supply_pack/medical/medical, + /decl/hierarchy/supply_pack/flooring/dark_tiles, + + /decl/hierarchy/supply_pack/medical/medical, /decl/hierarchy/supply_pack/medical/atk, /decl/hierarchy/supply_pack/medical/abk, /decl/hierarchy/supply_pack/medical/trauma, @@ -235,7 +201,7 @@ var/mob/user = usr /decl/hierarchy/supply_pack/medical/scanner_module, /decl/hierarchy/supply_pack/medical/defib, /decl/hierarchy/supply_pack/medical/autocomp, - + /decl/hierarchy/supply_pack/galley/food, /decl/hierarchy/supply_pack/galley/beef, /decl/hierarchy/supply_pack/galley/eggs, @@ -245,22 +211,20 @@ var/mob/user = usr /decl/hierarchy/supply_pack/galley/party, /decl/hierarchy/supply_pack/galley/beer_dispenser, /decl/hierarchy/supply_pack/galley/soda_dispenser, - + /decl/hierarchy/supply_pack/operations/orebox, /decl/hierarchy/supply_pack/operations/bureaucracy, /decl/hierarchy/supply_pack/operations/voidsuit_engineering, - + /decl/hierarchy/supply_pack/nonessent/painters, /decl/hierarchy/supply_pack/nonessent/artscrafts, /decl/hierarchy/supply_pack/nonessent/card_packs, /decl/hierarchy/supply_pack/nonessent/instruments, /decl/hierarchy/supply_pack/nonessent/llamps, /decl/hierarchy/supply_pack/nonessent/chaplaingear, - + /decl/hierarchy/supply_pack/custodial/janitor, /decl/hierarchy/supply_pack/custodial/cleaning, /decl/hierarchy/supply_pack/custodial/mousetrap, /decl/hierarchy/supply_pack/custodial/janitorbiosuits - - ) diff --git a/nano/templates/trade_beacon.tmpl b/nano/templates/trade_beacon.tmpl index 87504c17a59..b29a07666bf 100644 --- a/nano/templates/trade_beacon.tmpl +++ b/nano/templates/trade_beacon.tmpl @@ -22,7 +22,8 @@ Used In File(s): mods\persistence\modules\overmap_trade\trade_beacon.dm


-

Products available at this beacon

+{{:helper.link('View Imports', 'cart', {'set_screen' : 1}, data.screen == 1 ? 'selected' : null)}} +{{:helper.link('View Exports', 'calculator', {'set_screen' : 2}, data.screen == 2 ? 'selected' : null)}} {{for data.categories}} {{:helper.link(value, null, {'select_category' : value}, data.category == value ? 'selected' : null)}} {{/for}} From 44936b6db0f9b16d36947dddc35f7379438ad5fe Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Wed, 25 May 2022 07:18:56 -0700 Subject: [PATCH 10/47] update files --- .../modules/overmap_trade/tradebeacon.dm | 32 ++++++++++-- nano/templates/trade_beacon.tmpl | 51 ++++++++++++------- 2 files changed, 62 insertions(+), 21 deletions(-) diff --git a/mods/persistence/modules/overmap_trade/tradebeacon.dm b/mods/persistence/modules/overmap_trade/tradebeacon.dm index 67adf74e6ea..1f26f31938d 100644 --- a/mods/persistence/modules/overmap_trade/tradebeacon.dm +++ b/mods/persistence/modules/overmap_trade/tradebeacon.dm @@ -1,12 +1,12 @@ /datum/beacon_export var/name = "Beacon Export" - var/price_per_purchase = 1 + var/price_per_unit = 0 var/unit_per_purchase = 1 var/unit_type /obj/machinery/trade_beacon name = "trade beacon" - desc = "An large broadcasting array meant to control trade between the Outreach system and the wider galaxy." + desc = "A large broadcasting array meant to control trade between the Outreach system and the wider galaxy." icon = 'icons/obj/jukebox_new.dmi' icon_state = "jukebox3-nopower" anchored = 1 @@ -28,6 +28,8 @@ var/list/contents_of_order = list() var/screen = 1 var/selected_category + var/list/exports_nano = list() + var/network_key /obj/machinery/trade_beacon/powered() return 1 @@ -38,7 +40,12 @@ /obj/machinery/trade_beacon/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) user.set_machine(src) var/list/data = list() + data["title"] = name + var/decl/currency/cur = GET_DECL(global.using_map.default_currency) + data["currency"] = cur.name + if(screen == 1) + get_category_contents() data["categories"] = category_names if(selected_category) data["category"] = selected_category @@ -47,7 +54,8 @@ data["showing_contents_of"] = showing_contents_of_ref data["contents_of_order"] = contents_of_order if(screen == 2) - + get_exports_nano() + data["exports"] = exports_nano ui = SSnano.try_update_ui(user, src, ui_key, ui, data, force_open) if (!ui) @@ -77,6 +85,7 @@ clear_order_contents() screen = text2num(href_list["set_screen"]) return 1 + // Items requiring cargo access go below this entry. Other items go above. if(!check_access(access_cargo)) return 1 @@ -120,6 +129,12 @@ return category_contents +/obj/machinery/trade_beacon/proc/get_exports_nano() + if(!exports_nano || !exports_nano.len) + generate_exports_list() + return exports_nano + + /obj/machinery/trade_beacon/proc/generate_categories() category_names.Cut() category_contents.Cut() @@ -143,6 +158,17 @@ category_names.Add(sp.name) category_contents[sp.name] = category + +/obj/machinery/trade_beacon/proc/generate_exports_list() + exports_nano.Cut() + var/decl/currency/cur = GET_DECL(global.using_map.default_currency) + for(var/datum/beacon_export/export in exports) + category.Add(list(list( + "name" = export.name, + "cost" = cur.format_value(spc.price_per_unit), + ))) + + /obj/machinery/trade_beacon/Outreach owner_name = "Nanotrasen" lore = "Nanotrasen go brrrrrrrrrrrr" diff --git a/nano/templates/trade_beacon.tmpl b/nano/templates/trade_beacon.tmpl index b29a07666bf..c3a6cb42692 100644 --- a/nano/templates/trade_beacon.tmpl +++ b/nano/templates/trade_beacon.tmpl @@ -24,30 +24,45 @@ Used In File(s): mods\persistence\modules\overmap_trade\trade_beacon.dm


{{:helper.link('View Imports', 'cart', {'set_screen' : 1}, data.screen == 1 ? 'selected' : null)}} {{:helper.link('View Exports', 'calculator', {'set_screen' : 2}, data.screen == 2 ? 'selected' : null)}} -{{for data.categories}} - {{:helper.link(value, null, {'select_category' : value}, data.category == value ? 'selected' : null)}} -{{/for}} -{{if data.category}} +{{if data.screen == 1}} +

Items Available to Import

+ {{for data.categories}} + {{:helper.link(value, null, {'select_category' : value}, data.category == value ? 'selected' : null)}} + {{/for}} + {{if data.category}} + + {{#def.common_supply_header}} + {{for data.possible_purchases}} + + + {{#def.common_supply_header}} + {{else}} + {{:helper.link('Contents', null, {'show_contents' : value.ref})}} + {{/if}} + {{/for}} +
{{:value.name}} + {{:value.cost}} {{:data.currency}} + + {{if data.showing_contents_of && data.showing_contents_of == value.ref}} + {{:helper.link('Close', null, {'hide_contents' : 1})}} +
Contents + {{for data.contents_of_order :content :content_index}} +
{{:content.name}} × {{:content.amount}} + {{/for}} +
+
+ {{/if}} + +{{else data.screen == 2}} +

Items Available to Export

{{#def.common_supply_header}} - {{for data.possible_purchases}} + {{for data.exports}} - {{#def.common_supply_header}} - {{else}} - {{:helper.link('Contents', null, {'show_contents' : value.ref})}} - {{/if}} {{/for}}
{{:value.name}} {{:value.cost}} {{:data.currency}} - {{:helper.link('Order', null, {'order' : value.ref})}} - {{if data.showing_contents_of && data.showing_contents_of == value.ref}} - {{:helper.link('Close', null, {'hide_contents' : 1})}} -
Contents - {{for data.contents_of_order :content :content_index}} -
{{:content.name}} × {{:content.amount}} - {{/for}} -
-
+ {{/if}} From 034bd0606286ce741ac5d103a37fd87cd2f54a33 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 13:38:40 -0600 Subject: [PATCH 11/47] TRADE BEACON UPDATE Adds trade beacons to persistence, devices scattered across the overmap that give access to unique import/export opportunities. This includes a new network device that lets networks take control of trade beacons. The entire system is in place and functional, but we still need to add imports/exports and a variety of trade beacons. I will save that for future updates. --- .../circuitboards/machinery/network.dm | 21 +- .../modular_computers/networking/_network.dm | 9 + icons/obj/machines/telepad.dmi | Bin 0 -> 1197 bytes mods/persistence/_persistence.dme | 8 + .../controllers/subsystems/trade_beacons.dm | 21 + .../programs/trade_beacon_program.dm | 560 ++++++++++++ .../hardware/trade_controller.dm | 89 ++ .../networking/trade_controller.dm | 104 +++ .../modules/quadrants/quadrants.dm | 13 + mods/persistence/modules/quadrants/trade.dm | 827 ++++++++++++++++++ .../modules/trade_beacons/cargo_telepads.dm | 28 + .../modules/trade_beacons/exports.dm | 80 ++ .../modules/trade_beacons/imports.dm | 53 ++ .../modules/trade_beacons/trade_beacons.dm | 103 +++ nano/templates/trade_controller.tmpl | 49 ++ nano/templates/trade_management.tmpl | 179 ++++ 16 files changed, 2143 insertions(+), 1 deletion(-) create mode 100644 icons/obj/machines/telepad.dmi create mode 100644 mods/persistence/controllers/subsystems/trade_beacons.dm create mode 100644 mods/persistence/modules/modular_computers/file_system/programs/trade_beacon_program.dm create mode 100644 mods/persistence/modules/modular_computers/hardware/trade_controller.dm create mode 100644 mods/persistence/modules/modular_computers/networking/trade_controller.dm create mode 100644 mods/persistence/modules/quadrants/quadrants.dm create mode 100644 mods/persistence/modules/quadrants/trade.dm create mode 100644 mods/persistence/modules/trade_beacons/cargo_telepads.dm create mode 100644 mods/persistence/modules/trade_beacons/exports.dm create mode 100644 mods/persistence/modules/trade_beacons/imports.dm create mode 100644 mods/persistence/modules/trade_beacons/trade_beacons.dm create mode 100644 nano/templates/trade_controller.tmpl create mode 100644 nano/templates/trade_management.tmpl diff --git a/code/game/objects/items/weapons/circuitboards/machinery/network.dm b/code/game/objects/items/weapons/circuitboards/machinery/network.dm index 614673fdabe..66a3a63e3e1 100644 --- a/code/game/objects/items/weapons/circuitboards/machinery/network.dm +++ b/code/game/objects/items/weapons/circuitboards/machinery/network.dm @@ -106,4 +106,23 @@ additional_spawn_components = list( /obj/item/stock_parts/power/apc/buildable = 1 - ) \ No newline at end of file + ) + + +/obj/item/stock_parts/circuitboard/trade_controller + name = "circuitboard (trade control device)" + build_path = /obj/machinery/network/trade_controller + origin_tech = "{'programming':4,'magnets':3}" + req_components = list( + /obj/item/stock_parts/capacitor = 1, + /obj/item/stock_parts/scanning_module = 2 + ) + + additional_spawn_components = list( + /obj/item/stock_parts/power/apc/buildable = 1 + ) + +/obj/item/stock_parts/circuitboard/telepad + name = "circuitboard (cargo telepad)" + build_path = /obj/machinery/telepad_cargo + diff --git a/code/modules/modular_computers/networking/_network.dm b/code/modules/modular_computers/networking/_network.dm index ec7eb0b4723..cd4150fa4ef 100644 --- a/code/modules/modular_computers/networking/_network.dm +++ b/code/modules/modular_computers/networking/_network.dm @@ -24,6 +24,8 @@ var/datum/money_account/parent/network/parent_account var/list/datum/extension/network_device/money_cube/money_cubes = list() + var/datum/extension/network_device/trade_controller/trade_controller + var/network_features_enabled = NET_ALL_FEATURES var/intrusion_detection_enabled var/intrusion_detection_alarm @@ -108,6 +110,7 @@ banking_mainframe = D add_log("New banking mainframe set", newtag) + else if(istype(D, /datum/extension/network_device/money_cube)) if(!parent_account) return FALSE @@ -117,6 +120,12 @@ parent_account.adjust_money(cube.stored_money) cube.stored_money = 0 + else if(istype(D, /datum/extension/network_device/trade_controller)) + if(trade_controller) + return FALSE + trade_controller = D + add_log("New Trade Control set", newtag) + D.network_tag = newtag devices |= D devices_by_tag[D.network_tag] = D diff --git a/icons/obj/machines/telepad.dmi b/icons/obj/machines/telepad.dmi new file mode 100644 index 0000000000000000000000000000000000000000..14667b036aa75ff61be7a4f03549af1718503508 GIT binary patch literal 1197 zcmV;e1XBBnP)RZe*yo40L6V3%w+)NbpYgi0Dw^vFfcGwQBZ4W zW<5nt|AhemlK`-NHkfNEVPUc`&nhGvXty+yDRo0d!JMQvg8b*k%9# z0Ec>1Sad{Xb7OL8aCB*JZU6vyoKseCa&`CgQ*iP1*dE&70AK@ghUlEo~p340MVaFe*IloV9FKMn9|RbMz@gVS#$&0Ci8Eh51MQxl zfbYJZiWA=hxiK7}g5@w>%`d*?sudhkx*hUr9W!_@1Gy8 zA5z@>Z?a<+U0|?&P(dQxFF#nP(SpzTRv!iU-|!|@&DNI{|LqFhbRYsPa6M! zY5YI2{C}!`h;rBeAEEsjsSkAh@GHSP^Bw>HlBf?-^@ESM{{Hv*`6c21Q}u(7JO2KX z@c*g$!OLxbPZIt=RX_OoS|6z$lHjTN!~K8%1%-Y+m6~t- zec(M-%>SGDEX;LQDii)6c=$b0aDMCWWiBKB|C-=1pDBKIx$*a};!Pan0a|_y`hV%I z515Cuetqy}`TMKw|E1>dt^a>j{$IA78UBZf;$8DAYk1@DWfNWh4|gV)cBpHcSEYfK z06yd1A55+fWWxWC;+DUMok#tDk~1&2{Jl*0|8ab+4+itKKJf9s(gTS;kaa;S00000 LNkvXXu0mjf= (last_cycle + 2 HOURS)) + last_cycle = REALTIMEOFDAY + for(var/obj/effect/overmap/trade_beacon/x in all_trade_beacons) + x.regenerate_imports() + x.regenerate_exports() diff --git a/mods/persistence/modules/modular_computers/file_system/programs/trade_beacon_program.dm b/mods/persistence/modules/modular_computers/file_system/programs/trade_beacon_program.dm new file mode 100644 index 00000000000..ac643350de1 --- /dev/null +++ b/mods/persistence/modules/modular_computers/file_system/programs/trade_beacon_program.dm @@ -0,0 +1,560 @@ +/datum/computer_file/program/trade_management + filename = "trademnrger" + filedesc = "Import/Export Management" + extended_desc = "This program allows you to process imports or exports from nearby trade beacons." + + program_icon_state = "generic" + program_key_state = "generic_key" + program_menu_icon = "cart" + + available_on_network = 1 + + size = 12 + nanomodule_path = /datum/nano_module/program/trade_management + category = PROG_SUPPLY + + var/obj/effect/overmap/trade_beacon/selected_beacon + + var/import_menu = 1 + var/export_menu = 0 + var/log_menu = 0 + var/datum/beacon_import/selected_import + var/datum/beacon_export/selected_export + var/payment_type = 1 // 1 == personal account 2 == chargestick 3 == network parent account + + var/list/detected_telepads = list() + var/obj/selected_telepad + +/datum/computer_file/program/trade_management/proc/detect_telepads() + detected_telepads = list() + for(var/obj/machinery/telepad_cargo/c in orange(3, get_turf(computer))) + if(c.anchored) + detected_telepads |= c + return + +/datum/computer_file/program/trade_management/on_startup(mob/living/user, datum/extension/interactive/os/new_host) + . = ..() + detect_telepads() + + +/datum/nano_module/program/trade_management + name = "Import/Export Management" + + +/datum/computer_file/program/trade_management/proc/spawnImport() + var/turf/T = get_turf(selected_telepad) + flick("pad-beam", selected_telepad) + . = selected_import.spawnImport(T) + if(selected_import.remaining_stock < 1) + selected_beacon.active_imports.Remove(selected_import) + selected_import = null +/datum/computer_file/program/trade_management/proc/checkImport() + var/turf/T = get_turf(selected_telepad) + flick("pad-beam", selected_telepad) + return selected_import.checkImport(T) + +/datum/computer_file/program/trade_management/proc/takeExport() + flick("pad-beam", selected_telepad) + . = selected_export.takeExport() + if(selected_export.remaining_stock < 1) + selected_beacon.active_exports.Remove(selected_export) + selected_export = null +/datum/computer_file/program/trade_management/proc/checkExport() + var/turf/T = get_turf(selected_telepad) + return selected_export.checkExport(T) + +/datum/computer_file/program/trade_management/proc/resetExport() + return selected_export.resetExport() + + +/datum/nano_module/program/trade_management/ui_interact(mob/user, ui_key, datum/nanoui/ui, force_open, datum/nanoui/master_ui, datum/topic_state/state) + var/list/data = host.initial_data() + var/datum/computer_file/program/trade_management/PRG = program + var/datum/extension/interactive/os/computer = PRG.computer + var/list/telepads[0] + var/update_time = time2text((SStrade_beacons.last_cycle+2 HOURS),"hh:mm") + for(var/obj/machinery/telepad_cargo/x in PRG.detected_telepads) + var/selected = 0 + if(x == PRG.selected_telepad) selected = 1 + telepads.Add(list(list( + "telepad_name" = "[x.name] ([x.telepad_id])", + "selected" = selected, + "telepad_ref" = any2ref(x), + ))) + if(!telepads.len) + telepads.Add(list(list( + "telepad_name" = "No telepads detected!", + "selected" = 1, + ))) + data["telepads"] = telepads + data["update_time"] = update_time + var/obj/effect/overmap/trade_beacon/selected_beacon = PRG.selected_beacon + if(selected_beacon) + data["selected_beacon"] = TRUE + data["beacon_name"] = selected_beacon.name + var/access = 1 + if(selected_beacon && selected_beacon.linked_controller && selected_beacon.linked_controller.get_network()) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + data["controlling_network"] = network.network_id + if(selected_beacon.linked_controller.beacon_restrict) + if(selected_beacon.linked_controller.get_network() == PRG.computer.get_network()) + var/list/accesses = computer.get_access(user) + if(selected_beacon.linked_controller.access && !(selected_beacon.linked_controller.access in accesses)) + access = 0 + else + access = 0 + + if(access) + data["beacon_access"] = 1 + if(PRG.import_menu) + data["import"] = 1 + var/import_tax = 0 + if(selected_beacon && selected_beacon.linked_controller) + import_tax = selected_beacon.linked_controller.import_tax + + data["import_tax"] = import_tax + var/list/imports[0] + for(var/datum/beacon_import/x in selected_beacon.active_imports) + imports.Add(list(list( + "import_name" = x.name, + "import_cost" = x.get_cost(import_tax), + "import_remaining" = x.remaining_stock, + "import_ref" = any2ref(x), + ))) + data["imports"] = imports + + else if(PRG.export_menu) + data["export"] = 1 + var/export_tax = 0 + if(selected_beacon && selected_beacon.linked_controller) + export_tax = selected_beacon.linked_controller.export_tax + data["export_tax"] = export_tax + var/list/exports[0] + for(var/datum/beacon_export/x in selected_beacon.active_exports) + exports.Add(list(list( + "export_name" = x.name, + "export_cost" = x.get_cost(export_tax), + "export_remaining" = x.remaining_stock, + "export_ref" = any2ref(x), + ))) + data["exports"] = exports + else if(PRG.log_menu) + data["log"] = 1 + else if(PRG.selected_import) + switch(PRG.payment_type) + if(1) + data["personal_account_sel"] = 1 + if(2) + data["charge_stick_sel"] = 1 + if(3) + data["network_account_sel"] = 1 + + var/import_tax = 0 + if(selected_beacon && selected_beacon.linked_controller) + import_tax = selected_beacon.linked_controller.import_tax + + data["selected_import"] = PRG.selected_import.name + data["import_cost"] = PRG.selected_import.get_cost(import_tax) + data["import_desc"] = PRG.selected_import.desc + + var/datum/computer_file/data/account/A = PRG.computer.get_account() + if(A) + var/datum/money_account/child/network/money_account = A.money_account + if(money_account) + data["personal_account"] = money_account.account_name + data["personal_account_balance"] = money_account.money + else + data["personal_account_error"] = "This account has no valid bank account associated with it on this network. Check your login details or contact a system administrator." + + else + data["personal_account_error"] = "This account has no valid bank account associated with it on this network. Check your login details or contact a system administrator." + + var/obj/item/stock_parts/computer/charge_stick_slot/charge_slot = computer.get_component(PART_MSTICK) + if(!charge_slot || !charge_slot.is_functional()) + data["charge_stick_error"] = "No functional charge stick slot found!" + else if(!charge_slot.stored_stick) + data["charge_stick_error"] = "No charge stick inserted!" + else + data["charge_stick"] = "Charge Stick" + data["charge_stick_balance"] = charge_slot.stored_stick.loaded_worth + var/datum/computer_network/net = PRG.computer.get_network() + var/list/accesses = computer.get_access(user) + if(net && net.banking_mainframe) + if(!net.banking_mainframe.has_access(accesses)) + data["network_account_error"] = "You do not have access to the parent account on your current network." + else + var/datum/money_account/parent/network/bank_account = net.banking_mainframe.get_parent_account() + if(!bank_account) + data["network_account_error"] = "The network does not have a parent account created." + else + data["network_account"] = bank_account.account_name + data["network_account_balance"] = bank_account.money + else + data["network_account_error"] = "The network does not have a banking mainframe." + + + else if(PRG.selected_export) + switch(PRG.payment_type) + if(1) + data["personal_account_sel"] = 1 + if(2) + data["charge_stick_sel"] = 1 + if(3) + data["network_account_sel"] = 1 + + var/export_tax = 0 + if(selected_beacon && selected_beacon.linked_controller) + export_tax = selected_beacon.linked_controller.export_tax + + data["selected_export"] = PRG.selected_export.name + data["export_cost"] = PRG.selected_export.get_cost(export_tax) + data["export_desc"] = PRG.selected_export.desc + + var/datum/computer_file/data/account/A = PRG.computer.get_account() + if(A) + var/datum/money_account/child/network/money_account = A.money_account + if(money_account) + data["personal_account"] = money_account.account_name + data["personal_account_balance"] = money_account.money + else + data["personal_account_error"] = "No bank account." + + else + data["personal_account_error"] = "Not logged in." + + var/obj/item/stock_parts/computer/charge_stick_slot/charge_slot = computer.get_component(PART_MSTICK) + if(!charge_slot || !charge_slot.is_functional()) + data["personal_account_error"] = "Noslot found!" + else if(!charge_slot.stored_stick) + data["personal_account_error"] = "No charge stick!" + else + data["charge_stick"] = "Charge Stick" + data["charge_stick_balance"] = charge_slot.stored_stick.loaded_worth + var/datum/computer_network/net = PRG.computer.get_network() + var/list/accesses = computer.get_access(user) + if(net && net.banking_mainframe) + if(!net.banking_mainframe.has_access(accesses)) + data["network_account_error"] = "No access." + else + var/datum/money_account/parent/network/bank_account = net.banking_mainframe.get_parent_account() + if(!bank_account) + data["network_account_error"] = "No Network Account" + else + data["network_account"] = bank_account.account_name + data["network_account_balance"] = bank_account.money + else + data["network_account_error"] = "No Network Bank." + + + else + data["beacon_name"] = "*DISCONNECTED*" + + + ui = SSnano.try_update_ui(user, src, ui_key, ui, data, force_open) + if (!ui) + ui = new(user, src, ui_key, "trade_management.tmpl", name, 600, 750, state = state) + ui.auto_update_layout = 1 + ui.set_initial_data(data) + ui.set_auto_update(1) + ui.open() + +/datum/computer_file/program/trade_management/Topic(href, href_list, state) + . = ..() + if(.) + return + + if(href_list["select_beacon"]) + var/obj/hold = computer.get_physical_host() + var/list/possible_trade_beacons = hold.get_adjacent_trade_beacons() + possible_trade_beacons += "*DISCONNECT*" + var/beacon = input(usr, "Select a nearby trade beacon.", "Pick a beacon") as null|anything in possible_trade_beacons + if(!CanInteract(usr, global.default_topic_state)) + return TOPIC_REFRESH + if(beacon == "*DISCONNECT*") + selected_beacon = null + else if(beacon) + selected_beacon = beacon + + return TOPIC_REFRESH + if(href_list["import"]) + import_menu = 1 + export_menu = 0 + log_menu = 0 + selected_import = null + selected_export = null + return TOPIC_REFRESH + if(href_list["export"]) + import_menu = 0 + export_menu = 1 + log_menu = 0 + selected_import = null + selected_export = null + return TOPIC_REFRESH + if(href_list["log"]) + import_menu = 0 + export_menu = 0 + log_menu = 1 + selected_import = null + selected_export = null + return TOPIC_REFRESH + if(href_list["select_import"]) + import_menu = 0 + export_menu = 0 + log_menu = 0 + selected_import = locate(href_list["select_import"]) + selected_export = null + return TOPIC_REFRESH + if(href_list["select_export"]) + import_menu = 0 + export_menu = 0 + log_menu = 0 + selected_import = null + selected_export = locate(href_list["select_export"]) + return TOPIC_REFRESH + if(href_list["select_personal_account"]) + payment_type = 1 + return TOPIC_REFRESH + if(href_list["select_charge_stick"]) + payment_type = 2 + return TOPIC_REFRESH + if(href_list["select_network_account"]) + payment_type = 3 + return TOPIC_REFRESH + if(href_list["select_telepad"]) + detect_telepads() + var/obj/T = locate(href_list["select_telepad"]) + if(T && T in detected_telepads) + selected_telepad = T + return TOPIC_REFRESH + if(href_list["refresh_telepad"]) + detect_telepads() + return TOPIC_REFRESH + if(href_list["buy_import"]) + var/import_tax = 0 + if(!selected_import || !selected_beacon) + return + if(!(selected_import in selected_beacon.active_imports)) + selected_import = null + return + if(!selected_telepad) + to_chat(usr, SPAN_WARNING("You must select a telepad to send the import to.")) + return TOPIC_REFRESH + if(selected_beacon && selected_beacon.linked_controller) + import_tax = selected_beacon.linked_controller.import_tax + var/cost = selected_import.get_cost(import_tax) + var/tax_portion = selected_import.get_tax(import_tax) + switch(payment_type) + if(1) + var/datum/computer_file/data/account/A = computer.get_account() + if(A) + + var/oerr = checkImport() + if(oerr) + to_chat(usr, SPAN_WARNING("Import purchase failed: [oerr]")) + return TOPIC_HANDLED + var/datum/money_account/child/network/money_account = A.money_account + if(money_account) + var/terr = money_account.can_afford(cost, selected_beacon.beacon_account) + if(terr) + to_chat(usr, SPAN_WARNING("Import purchase failed: [terr]")) + return TOPIC_HANDLED + var/final_cost = cost-tax_portion + var/err = money_account.transfer(selected_beacon.beacon_account, final_cost, "Import Purchase ([selected_import.name] from [selected_beacon.name])") + if(err) + to_chat(usr, SPAN_WARNING("Import purchase failed: [err].")) + return TOPIC_HANDLED + else + if(tax_portion) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + err = money_account.transfer(network.banking_mainframe.get_parent_account(), tax_portion, "Import Purchase Tax ([selected_import.name] from [selected_beacon.name])") + if(err) + selected_beacon.beacon_account.transfer(money_account, final_cost, "Refunded Import Purchase ([selected_import.name] from [selected_beacon.name])") + else + spawnImport() + else + spawnImport() + else + to_chat(usr, SPAN_WARNING("No banking account associated with this network. Contact your system administrator..")) + else + to_chat(usr, SPAN_WARNING("You must login to a valid account on your network to pay digitally.")) + if(2) + var/obj/item/stock_parts/computer/charge_stick_slot/charge_slot = computer.get_component(PART_MSTICK) + if(!charge_slot || !charge_slot.stored_stick) + to_chat(usr, SPAN_WARNING("No charge stick is inserted into the computer.")) + return TOPIC_REFRESH + var/obj/item/charge_stick/stick = charge_slot.stored_stick + if(cost > stick.loaded_worth) + to_chat(usr, SPAN_WARNING("The loaded charge stick does not have enough credits stored!")) + return TOPIC_HANDLED + var/oerr = checkImport() + if(oerr) + to_chat(usr, SPAN_WARNING("Import purchase failed: [oerr]")) + return TOPIC_HANDLED + stick.adjust_worth(-(cost)) + if(tax_portion) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + var/datum/money_account/child/network/money_account = network.banking_mainframe.get_parent_account() + money_account.deposit(tax_portion, "Import Purchase Tax ([selected_import.name] from [selected_beacon.name])") + spawnImport() + if(3) + var/datum/computer_network/net = computer.get_network() + var/list/accesses = computer.get_access(usr) + if(net && net.banking_mainframe) + if(!net.banking_mainframe.has_access(accesses)) + to_chat(usr, SPAN_WARNING("You do not have access to the parent account on your current network.")) + return TOPIC_REFRESH + else + var/datum/money_account/parent/network/money_account = net.banking_mainframe.get_parent_account() + if(money_account) + var/terr = money_account.can_afford(cost, selected_beacon.beacon_account) + if(terr) + to_chat(usr, SPAN_WARNING("Import purchase failed: [terr]")) + return TOPIC_HANDLED + var/oerr = checkImport() + if(oerr) + to_chat(usr, SPAN_WARNING("Import purchase failed: [oerr]")) + return TOPIC_HANDLED + if(tax_portion) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + if(network.banking_mainframe.get_parent_account() == money_account) // dont pay tax from the account into the same account + tax_portion = 0 + cost = selected_import.get_cost(0) + else // remove tax if we cant find a parent account to pay it to. + tax_portion = 0 + cost = selected_import.get_cost(0) + if(money_account.money < cost) + to_chat(usr, SPAN_WARNING("Import purchase failed: Insufficent funds.")) + return TOPIC_HANDLED + var/final_cost = cost-tax_portion + var/err = money_account.transfer(selected_beacon.beacon_account, final_cost, "Import Purchase ([selected_import.name] from [selected_beacon.name])") + if(err) + to_chat(usr, SPAN_WARNING("Import purchase failed: [err].")) + return TOPIC_HANDLED + else + if(tax_portion) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + err = money_account.transfer(network.banking_mainframe.get_parent_account(), tax_portion, "Import Purchase Tax ([selected_import.name] from [selected_beacon.name])") + if(err) + selected_beacon.beacon_account.transfer(money_account, final_cost, "Refunded Import Purchase ([selected_import.name] from [selected_beacon.name])") + else + spawnImport() + else + spawnImport() + else + to_chat(usr, SPAN_WARNING("The network does not have a central account.")) + return TOPIC_REFRESH + return TOPIC_REFRESH + if(href_list["buy_export"]) + var/export_tax = 0 + if(!selected_export || !selected_beacon) + return TOPIC_REFRESH + if(!(selected_export in selected_beacon.active_exports)) + selected_export = null + return + if(!selected_telepad) + to_chat(usr, SPAN_WARNING("You must select a telepad to send the export to.")) + return TOPIC_REFRESH + if(selected_beacon && selected_beacon.linked_controller) + export_tax = selected_beacon.linked_controller.export_tax + var/cost = selected_export.get_cost(export_tax) + var/tax_portion = selected_export.get_tax(export_tax) + switch(payment_type) + if(1) + var/datum/computer_file/data/account/A = computer.get_account() + if(A) + var/datum/money_account/child/network/money_account = A.money_account + if(money_account) + var/e_err = checkExport() + if(e_err) + to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) + resetExport() + return TOPIC_HANDLED + var/err = money_account.deposit(cost, "Export ([selected_export.name] from [selected_beacon.name])") + if(err) + to_chat(usr, SPAN_WARNING("Export failed: [err].")) + resetExport() + return TOPIC_HANDLED + else + + if(tax_portion) // SUCCESS + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + var/datum/money_account/acc = network.banking_mainframe.get_parent_account() + err = acc.deposit(tax_portion, "Export Tax ([selected_export.name] from [selected_beacon.name])") + var/result = takeExport() + if(result) + to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) + else + to_chat(usr, SPAN_WARNING("No banking account associated with this network. Contact your system administrator.")) + return TOPIC_REFRESH + else + to_chat(usr, SPAN_WARNING("You must login to a valid account on your network to pay digitally.")) + return TOPIC_REFRESH + if(2) + var/obj/item/stock_parts/computer/charge_stick_slot/charge_slot = computer.get_component(PART_MSTICK) + if(!charge_slot || !charge_slot.stored_stick) + to_chat(usr, SPAN_WARNING("No charge stick is inserted into the computer.")) + return TOPIC_REFRESH + var/obj/item/charge_stick/stick = charge_slot.stored_stick + var/e_err = checkExport() + if(e_err) + to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) + resetExport() + return TOPIC_HANDLED + stick.adjust_worth(cost) + if(tax_portion) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + var/datum/money_account/acc = network.banking_mainframe.get_parent_account() + acc.deposit(tax_portion, "Export Tax ([selected_export.name] from [selected_beacon.name])") + var/result = takeExport() + if(result) + to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) + if(3) + var/datum/computer_network/net = computer.get_network() + var/list/accesses = computer.get_access(usr) + if(net && net.banking_mainframe) + if(!net.banking_mainframe.has_access(accesses)) + to_chat(usr, SPAN_WARNING("You do not have access to the parent account on your current network.")) + return TOPIC_REFRESH + else + var/datum/money_account/parent/network/money_account = net.banking_mainframe.get_parent_account() + if(money_account) + if(tax_portion) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + if(network.banking_mainframe.get_parent_account() == money_account) // dont pay tax from the account into the same account + tax_portion = 0 + cost = selected_export.get_cost(0) + else // remove tax if we cant find a parent account to pay it to. + tax_portion = 0 + cost = selected_export.get_cost(0) + var/e_err = checkExport() + if(e_err) + to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) + resetExport() + return TOPIC_HANDLED + var/err = money_account.deposit(cost, "Export ([selected_export.name] to [selected_beacon.name])") + if(err) + to_chat(usr, SPAN_WARNING("Export failed: [err].")) + resetExport() + return TOPIC_HANDLED + + else // SUCCESS + if(tax_portion) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + var/datum/money_account/acc = network.banking_mainframe.get_parent_account() + err = acc.deposit(tax_portion, "Export Tax ([selected_export.name] from [selected_beacon.name])") + var/result = takeExport() + if(result) + to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) + + else + to_chat(usr, SPAN_WARNING("The network does not have a central account.")) + return TOPIC_REFRESH + return TOPIC_REFRESH diff --git a/mods/persistence/modules/modular_computers/hardware/trade_controller.dm b/mods/persistence/modules/modular_computers/hardware/trade_controller.dm new file mode 100644 index 00000000000..01263743057 --- /dev/null +++ b/mods/persistence/modules/modular_computers/hardware/trade_controller.dm @@ -0,0 +1,89 @@ +/datum/extension/network_device/trade_controller + var/obj/effect/overmap/trade_beacon/linked_beacon + var/import_tax = 0 + var/export_tax = 0 + var/beacon_restrict = 0 // Restriction to ALL beacon functions, import/export/log. 0 = no restricton, 1 = restricted to the network + var/log_restrict = 0 // Restriction of the transaction log. 0 = no restricton, 1 = restricted to the network + var/access = 0 // Which access will allow for general beacon functions + var/log_access = 0 // which access will allow for viewing the transaction log + +/datum/extension/network_device/trade_controller/proc/Unlink() + if(linked_beacon) + linked_beacon.linked_controller = null + linked_beacon = null +/datum/extension/network_device/trade_controller/Destroy() + Unlink() + . = ..() + +/datum/extension/network_device/trade_controller/disconnect(net_down) + Unlink() + . = ..() + +/datum/extension/network_device/trade_controller/proc/toggle_beacon_restrict() + if(!linked_beacon) + beacon_restrict = 0 + return + beacon_restrict = !beacon_restrict + var/datum/computer_network/network = get_network() + if(network.trade_controller == src) + network.add_log("Trade Control Device toggled beacon restriction for [linked_beacon.name].", network_tag) + return 1 + + +/datum/extension/network_device/trade_controller/proc/select_beacon_access(var/mob/M, var/obj/machinery/network/trade_controller/machine) + var/list/access_choices = list() + var/datum/computer_network/network = get_network() + var/datum/extension/network_device/acl/D + if(network) + D = network.access_controller + if(!linked_beacon) + access = 0 + return + if(!D) + to_chat(M, SPAN_WARNING("Cannot restrict access! No access controller detected on network!")) + return + for(var/parent_group in D.group_dict) + access_choices |= parent_group + for(var/child_group in D.group_dict[parent_group]) + access_choices |= child_group + access_choices |= "*NONE*" + var/chosen = input(M, "Select an Access for the Trade Beacon.", "Beacon Access Selection") as null|anything in access_choices + if(chosen && (!machine || machine.CanUseTopic(M))) + if(chosen == "*NONE*") + access = 0 + network.add_log("Trade Control Device unset beacon access for [linked_beacon.name].", network_tag) + else + access = chosen + network.add_log("Trade Control Device set beacon access to [chosen] for [linked_beacon.name].", network_tag) + return 1 +/datum/extension/network_device/trade_controller/proc/select_import_tax(var/mob/M, var/obj/machinery/network/trade_controller/machine) + var/datum/computer_network/network = get_network() + if(!linked_beacon) + import_tax = 0 + return + var/chosen_tax = input(M, "Enter the import tax% to charge for this beacon. (30% MAX)", "Import Tax") as num|null + if(!machine || machine.CanUseTopic(M)) + import_tax = clamp(chosen_tax, 0, 30) + network.add_log("Trade Control Device changed the import tax rate to [import_tax] for [linked_beacon.name].", network_tag) + return 1 + +/datum/extension/network_device/trade_controller/proc/select_export_tax(var/mob/M, var/obj/machinery/network/trade_controller/machine) + var/datum/computer_network/network = get_network() + if(!linked_beacon) + export_tax = 0 + return + var/chosen_tax = input(M, "Enter the export tax% to charge for this beacon. (30% MAX)", "Export Tax") as num|null + if(!machine || machine.CanUseTopic(M)) + export_tax = clamp(chosen_tax, 0, 30) + network.add_log("Trade Control Device changed the export tax rate to [export_tax] for [linked_beacon.name].", network_tag) + return 1 + +/datum/extension/network_device/trade_controller/proc/toggle_log_restrict() + if(!linked_beacon) + log_restrict = 0 + return + log_restrict = !log_restrict + var/datum/computer_network/network = get_network() + if(network.trade_controller == src) + network.add_log("Trade Control Device toggled transaction log restriction for [linked_beacon.name].", network_tag) + return 1 \ No newline at end of file diff --git a/mods/persistence/modules/modular_computers/networking/trade_controller.dm b/mods/persistence/modules/modular_computers/networking/trade_controller.dm new file mode 100644 index 00000000000..b8dae3a196b --- /dev/null +++ b/mods/persistence/modules/modular_computers/networking/trade_controller.dm @@ -0,0 +1,104 @@ +/obj/machinery/network/trade_controller + name = "trade control device" + desc = "A device used for controlling trade beacons and adding import/export tax. It must remain in a gravity well near the trade beacon" + icon = 'icons/obj/machines/tcomms/hub.dmi' + icon_state = "hub" + network_device_type = /datum/extension/network_device/trade_controller + main_template = "trade_controller.tmpl" + construct_state = /decl/machine_construction/default/panel_closed + uncreated_component_parts = null + base_type = /obj/machinery/network/trade_controller + + +/obj/machinery/network/trade_controller/OnTopic(mob/user, href_list, datum/topic_state/state) + . = ..() + if(.) + return + var/datum/extension/network_device/trade_controller/D = get_extension(src, /datum/extension/network_device) + var/datum/computer_network/network = D.get_network() + if(!network || network.trade_controller != D) + error = "NETWORK ERROR: Connection lost. Another trade controller may be active on the network." + return TOPIC_REFRESH + + if(href_list["connect_beacon"]) + var/list/possible_trade_beacons = get_adjacent_trade_beacons() + possible_trade_beacons += "*DISCONNECT*" + var/selected_beacon = input(usr, "Select a nearby trade beacon.", "Pick a beacon") as null|anything in possible_trade_beacons + if(!CanInteract(user, global.default_topic_state) || !selected_beacon) + return TOPIC_REFRESH + if(selected_beacon == "*DISCONNECT*") + D.Unlink() + else + var/obj/effect/overmap/trade_beacon/a = selected_beacon + if(a.linked_controller) + to_chat(user, SPAN_NOTICE("This beacon is already connected to a trade control device. The existing trade control device must be removed first.")) + return TOPIC_REFRESH + else + a.linked_controller = D + D.linked_beacon = a + return TOPIC_REFRESH + + if(href_list["toggle_beacon_restrict"]) + D.toggle_beacon_restrict() + return TOPIC_REFRESH + if(href_list["select_beacon_access"]) + D.select_beacon_access(usr, src) + return TOPIC_REFRESH + if(href_list["change_import_tax"]) + D.select_import_tax(usr, src) + return TOPIC_REFRESH + if(href_list["change_export_tax"]) + D.select_export_tax(usr, src) + return TOPIC_REFRESH + if(href_list["toggle_log_restrict"]) + D.toggle_log_restrict() + return TOPIC_REFRESH + + if(href_list["info"]) + switch(href_list["info"]) + if("connect_beacon") + to_chat(user, SPAN_NOTICE("The Trade Controller can take control of trade beacons that you are within 1 tile of in space. A beacon can only be controlled by one Trade Controller, and will remaiin controlled until that controller is brought offline.")) + if("restrict_beacon_access") + to_chat(user, SPAN_NOTICE("If Beacon restriction is turned on, only devices connected to this network and with the appropriate access will be able to use the beacon for imports, exports or viewing the transaction log.")) + if("select_beacon_access") + to_chat(user, SPAN_NOTICE("You can set this access to any group in the network, in which case it will be required to access the Import/Export/Log functions for the beacon. If this is unset any device on this network will be able to access the beacon.")) + if("import_tax") + to_chat(user, SPAN_NOTICE("This is a percentage added to the cost of all imports done, except those done by the primary money account on this network. The added percentage will be deposited into the primary money account.")) + if("export_tax") + to_chat(user, SPAN_NOTICE("This is a percentage taken from the revenue of all exports done, except those done by the primary money account on this network. The added percentage will be deposited into the primary money account.")) + if("restrict_log_access") + to_chat(user, SPAN_NOTICE("If Transaction Log restriction is turned on, only devices connected to this network and with the appropriate access will be able to view the transaction log.")) + if("select_log_access") + to_chat(user, SPAN_NOTICE("You can set this access to any group in the network, in which case it will be required to access the Log functions for the beacon. If this is unset any device on this network will be able to access the transaction log.")) + +/obj/machinery/network/trade_controller/ui_data(mob/user, ui_key) + . = ..() + + if(error) + .["error"] = error + return + + var/datum/extension/network_device/trade_controller/D = get_extension(src, /datum/extension/network_device) + if(!D.get_network()) + .["connected"] = FALSE + return + .["connected"] = TRUE + if(D.linked_beacon) + .["connected_beacon"] = D.linked_beacon.name + .["valid_beacon"] = TRUE + .["beacon_restrict"] = D.beacon_restrict + if(D.beacon_restrict) + if(D.access) + .["selected_beacon_access"] = D.access + else + .["selected_beacon_access"] = "*NONE*" + .["import_tax"] = D.import_tax + .["export_tax"] = D.export_tax + .["log_restrict"] = D.log_restrict + if(D.log_restrict) + if(D.log_access) + .["selected_log_access"] = D.log_access + else + .["selected_log_access"] = "*NONE*" + else + .["connected_beacon"] = "*DISCONNECTED*" \ No newline at end of file diff --git a/mods/persistence/modules/quadrants/quadrants.dm b/mods/persistence/modules/quadrants/quadrants.dm new file mode 100644 index 00000000000..43a46546a6f --- /dev/null +++ b/mods/persistence/modules/quadrants/quadrants.dm @@ -0,0 +1,13 @@ +/datum/quadrant + var/name = "Default Quadrant" + var/default_securitylvl = 2 // Security levels + var/list/securitylvl_modifiers = list() + var/uid = "default" // used to link trade beacons/events with the + var/current_securitylvl = 0 + + + +/datum/SLModifier + var/name = "Security Level Modifier" + var/value = 0 // how much to change the security level by + var/expiry = 0 // realtime that the modifier should be deleted diff --git a/mods/persistence/modules/quadrants/trade.dm b/mods/persistence/modules/quadrants/trade.dm new file mode 100644 index 00000000000..e65f18f7355 --- /dev/null +++ b/mods/persistence/modules/quadrants/trade.dm @@ -0,0 +1,827 @@ +var/global/list/all_trade_beacons = list() + +/atom/proc/get_adjacent_trade_beacons() + var/list/adjacent_trade_beacons = list() + var/atom/target = src + if(!istype(src, /turf)) + target = get_turf(src) + var/obj/ob = target.get_owning_overmap_object() + if(ob) + var/turf/T = get_turf(ob) + if(T) + for(var/obj/beacon in all_trade_beacons) + var/turf/beacon_turf = get_turf(beacon) + if(beacon_turf && beacon_turf.Adjacent(T)) + adjacent_trade_beacons |= beacon + return adjacent_trade_beacons + +/obj/effect/overmap/trade_beacon + name = "Trade Beacon" + var/list/possible_imports = list() // structure is list(/datum/beacon_import/example = 100) list(type = percentage chance of appearing). + var/list/possible_exports = list() + var/list/active_imports = list() + var/list/active_exports = list() + icon = 'icons/obj/supplybeacon.dmi' + icon_state = "beacon_active" + var/datum/extension/network_device/trade_controller/linked_controller + var/datum/money_account/beacon_account + var/start_x = 0 + var/start_y = 0 + +/obj/effect/overmap/trade_beacon/proc/move_to_starting_location() + var/datum/overmap/overmap = global.overmaps_by_name[overmap_id] + var/location + + if(start_x && start_y) + location = locate(start_x, start_y, overmap.assigned_z) + else + var/list/candidate_turfs = block( + locate(OVERMAP_EDGE, OVERMAP_EDGE, overmap.assigned_z), + locate(overmap.map_size_x - OVERMAP_EDGE, overmap.map_size_y - OVERMAP_EDGE, overmap.assigned_z) + ) + + candidate_turfs = where(candidate_turfs, /proc/can_not_locate, /obj/effect/overmap) + location = SAFEPICK(candidate_turfs) || locate( + rand(OVERMAP_EDGE, overmap.map_size_x - OVERMAP_EDGE), + rand(OVERMAP_EDGE, overmap.map_size_y - OVERMAP_EDGE), + overmap.assigned_z + ) + + forceMove(location) + +/obj/effect/overmap/trade_beacon/test_beacon + start_x = 28 + start_y = 23 + possible_imports = list( + /datum/beacon_import/example = 100, + /datum/beacon_import/steel = 100 + ) + possible_exports = list( + /datum/beacon_export/example = 100, + /datum/beacon_export/xanaducrystal = 100 + ) + name = "Kleibkhar Debug Trade Beacon" + +/obj/effect/overmap/trade_beacon/test_beacon2 + start_x = 27 + start_y = 22 + possible_imports = list( + /datum/beacon_import/example = 100, + /datum/beacon_import/steel = 100 + ) + possible_exports = list( + /datum/beacon_export/example = 100, + /datum/beacon_export/xanaducrystal = 100 + ) + name = "Kleibkhar Debug Trade Beacon Secondus" + + + +/obj/effect/overmap/trade_beacon/New() + beacon_account = new() + beacon_account.account_name = name + +/obj/effect/overmap/trade_beacon/Initialize() + all_trade_beacons |= src + ..() + move_to_starting_location() + regenerate_imports() + regenerate_exports() + +/obj/effect/overmap/trade_beacon/proc/regenerate_imports() + active_imports.Cut() + for(var/import in possible_imports) + if(!prob(possible_imports[import])) continue + active_imports |= new import() + + + +/obj/effect/overmap/trade_beacon/proc/regenerate_exports() + active_exports.Cut() + for(var/export in possible_exports) + if(!prob(possible_exports[export])) continue + active_exports |= new export() + +/datum/beacon_import + var/name = "Beacon Import" + var/list/provided_items = list() // structure is list(/obj/item/example = 1, /obj/item/multi = 2) list(type = number provided). + var/container_type = /obj/structure/closet/crate + var/cost = 1000 + var/remaining_stock = 5 // how many are left to buy this cycle + var/desc = "Import Desription" + +/datum/beacon_import/proc/get_cost(var/tax) + if(!tax) return cost + return cost+((tax/100)*cost) + +/datum/beacon_import/proc/get_tax(var/tax) + if(!tax) return 0 + return (tax/100)*cost + +/datum/beacon_import/proc/checkImport(var/turf/L) + if(!L) return "Invalid telepad." + for(var/obj/i in L.contents) + if(!istype(i, /obj/machinery)) // machines are ok + return "Telepad obstructed" +/datum/beacon_import/proc/spawnImport(var/turf/L) + if(!L) return + var/obj/structure/container = new container_type(L) + for(var/item_type in provided_items) + var/ind = provided_items[item_type] + if(!ind) ind = 1 + var/obj/item/stack/stacking = 0 + for(var/i=1;i<=ind;i++) + if(stacking) + stacking.add(1) + else + var/obj/o = new item_type(container) + if(isstack(o)) + stacking = o + remaining_stock-- + +/datum/beacon_import/steel + provided_items = list(/obj/item/stack/material/sheet/mapped/steel = 50) + name = "Steel (50 Sheets)" + cost = 500 + desc = "A stack of fifty steel sheets. Fifty sheets of grey steel." + + +/datum/beacon_import/example + provided_items = list(/obj/item/stack/cable_coil/single = 10, /obj/item/plunger = 2) + name = "Example Import" + cost = 150 + desc = "This is a debug import that tests stacks and multiple single items. It sends 10 pieces of cable coil, stacked and 2 plungers." + + + +/datum/beacon_export + var/name = "Beacon Export" + var/list/required_items = list() // structure is list(/obj/item/example = 1, /obj/item/multi = 2) list(type = number required). + var/cost = 1000 + var/remaining_stock = 5 + var/desc = "Export Description" + var/obj/checked_closet +/datum/beacon_export/proc/get_cost(var/tax) + if(!tax) return cost + return cost-((tax/100)*cost) + +/datum/beacon_export/proc/get_tax(var/tax) + if(!tax) return 0 + return (tax/100)*cost + +/datum/beacon_export/proc/takeExport() + if(checked_closet) + checked_closet.forceMove(null) + qdel(checked_closet) + checked_closet = null + remaining_stock-- +/datum/beacon_export/proc/resetExport() + checked_closet = null + +/datum/beacon_export/proc/checkExport(var/turf/L) + if(!L) return "No valid location detected" + var/obj/closet_found = 0 + var/valid_items = list() + for(var/obj/structure/closet/C in L.contents) + closet_found = C + for(var/item_type in required_items) + var/ind = required_items[item_type] + if(!ind) ind = 1 + var/found = 0 + for(var/obj/o in C.contents) + if(istype(o, item_type)) + if(isstack(o)) + var/obj/item/stack/s = o + ind -= s.amount + if(ind >= 0) + valid_items |= o + else + ind-- + valid_items |= o + if(ind < 0) + return "Too many items included ([o.name]). Exact orders only." + if(ind == 0) + found = 1 + break + if(!found) + return "Incomplete Export Detected ([item_type])" + break // only check 1, the for loop is just a convient way to search + if(!closet_found) + return "No container detected" + else + var/obj/invalid_item = 0 + for(var/obj/o in closet_found.contents) + if(!(o in valid_items)) + invalid_item = o + break + if(invalid_item) + return "Too many items included ([invalid_item.name]). Exact orders only." + checked_closet = closet_found + return // SUCCESS + +/datum/beacon_export/example + required_items = list(/obj/item/stack/cable_coil = 10, /obj/item/plunger = 2) + name = "Example Export" + desc = "This is a debug export to test sending stacked items and multiple single items. It requires a ten stack of cable coil and two plungers to complete." + cost = 500 + +/datum/beacon_export/xanaducrystal + required_items = list(/obj/item/plunger = 1) + name = "Xanadu Crystal" + desc = "The rare Xanadu Crystal is much prized across the Galaxy." + cost = 5000 +///////////////////////////////////////// + + + +/datum/computer_file/program/trade_management + filename = "trademnrger" + filedesc = "Import/Export Management" + extended_desc = "This program allows you to process imports or exports from nearby trade beacons." + + program_icon_state = "generic" + program_key_state = "generic_key" + program_menu_icon = "cart" + + available_on_network = 1 + + size = 12 + nanomodule_path = /datum/nano_module/program/trade_management + + var/current_map_z + var/obj/effect/overmap/trade_beacon/selected_beacon + + var/import_menu = 1 + var/export_menu = 0 + var/log_menu = 0 + var/datum/beacon_import/selected_import + var/datum/beacon_export/selected_export + var/payment_type = 1 // 1 == personal account 2 == chargestick 3 == network parent account + + var/list/detected_telepads = list() + var/obj/selected_telepad + +/datum/computer_file/program/trade_management/proc/detect_telepads() + detected_telepads = list() + for(var/obj/machinery/telepad_cargo/c in orange(3, get_turf(computer))) + if(c.anchored) + detected_telepads |= c + return + +/datum/computer_file/program/trade_management/on_startup(mob/living/user, datum/extension/interactive/os/new_host) + . = ..() + detect_telepads() + + +/datum/computer_file/program/trade_management/on_shutdown() + . = ..() + current_map_z = null + +/datum/nano_module/program/trade_management + name = "Import/Export Management" + + +/datum/computer_file/program/trade_management/proc/spawnImport() + var/turf/T = get_turf(selected_telepad) + flick("pad-beam", selected_telepad) + . = selected_import.spawnImport(T) + if(selected_import.remaining_stock < 1) + selected_beacon.active_imports.Remove(selected_import) + selected_import = null +/datum/computer_file/program/trade_management/proc/checkImport() + var/turf/T = get_turf(selected_telepad) + flick("pad-beam", selected_telepad) + return selected_import.checkImport(T) + +/datum/computer_file/program/trade_management/proc/takeExport() + flick("pad-beam", selected_telepad) + . = selected_export.takeExport() + if(selected_export.remaining_stock < 1) + selected_beacon.active_exports.Remove(selected_export) + selected_export = null +/datum/computer_file/program/trade_management/proc/checkExport() + var/turf/T = get_turf(selected_telepad) + return selected_export.checkExport(T) + +/datum/computer_file/program/trade_management/proc/resetExport() + return selected_export.resetExport() + + +/datum/nano_module/program/trade_management/ui_interact(mob/user, ui_key, datum/nanoui/ui, force_open, datum/nanoui/master_ui, datum/topic_state/state) + var/list/data = host.initial_data() + var/datum/computer_file/program/trade_management/PRG = program + var/datum/extension/interactive/os/computer = PRG.computer + var/list/telepads[0] + + for(var/obj/machinery/telepad_cargo/x in PRG.detected_telepads) + var/selected = 0 + if(x == PRG.selected_telepad) selected = 1 + telepads.Add(list(list( + "telepad_name" = "[x.name] ([x.telepad_id])", + "selected" = selected, + "telepad_ref" = any2ref(x), + ))) + if(!telepads.len) + telepads.Add(list(list( + "telepad_name" = "No telepads detected!", + "selected" = 1, + ))) + data["telepads"] = telepads + + var/obj/effect/overmap/trade_beacon/selected_beacon = PRG.selected_beacon + if(selected_beacon) + data["selected_beacon"] = TRUE + data["beacon_name"] = selected_beacon.name + var/access = 1 + if(selected_beacon && selected_beacon.linked_controller && selected_beacon.linked_controller.get_network()) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + data["controlling_network"] = network.network_id + if(selected_beacon.linked_controller.beacon_restrict) + if(selected_beacon.linked_controller.get_network() == PRG.computer.get_network()) + var/list/accesses = computer.get_access(user) + if(selected_beacon.linked_controller.access && !(selected_beacon.linked_controller.access in accesses)) + access = 0 + else + access = 0 + + if(access) + data["beacon_access"] = 1 + if(PRG.import_menu) + data["import"] = 1 + var/import_tax = 0 + if(selected_beacon && selected_beacon.linked_controller) + import_tax = selected_beacon.linked_controller.import_tax + + data["import_tax"] = import_tax + var/list/imports[0] + for(var/datum/beacon_import/x in selected_beacon.active_imports) + imports.Add(list(list( + "import_name" = x.name, + "import_cost" = x.get_cost(import_tax), + "import_ref" = any2ref(x), + ))) + data["imports"] = imports + + else if(PRG.export_menu) + data["export"] = 1 + var/export_tax = 0 + if(selected_beacon && selected_beacon.linked_controller) + export_tax = selected_beacon.linked_controller.export_tax + data["export_tax"] = export_tax + var/list/exports[0] + for(var/datum/beacon_export/x in selected_beacon.active_exports) + exports.Add(list(list( + "export_name" = x.name, + "export_cost" = x.get_cost(export_tax), + "export_ref" = any2ref(x), + ))) + data["exports"] = exports + else if(PRG.log_menu) + data["log"] = 1 + else if(PRG.selected_import) + switch(PRG.payment_type) + if(1) + data["personal_account_sel"] = 1 + if(2) + data["charge_stick_sel"] = 1 + if(3) + data["network_account_sel"] = 1 + + var/import_tax = 0 + if(selected_beacon && selected_beacon.linked_controller) + import_tax = selected_beacon.linked_controller.import_tax + + data["selected_import"] = PRG.selected_import.name + data["import_cost"] = PRG.selected_import.get_cost(import_tax) + data["import_desc"] = PRG.selected_import.desc + + var/datum/computer_file/data/account/A = PRG.computer.get_account() + if(A) + var/datum/money_account/child/network/money_account = A.money_account + if(money_account) + data["personal_account"] = money_account.account_name + data["personal_account_balance"] = money_account.money + else + data["personal_account_error"] = "This account has no valid bank account associated with it on this network. Check your login details or contact a system administrator." + + else + data["personal_account_error"] = "This account has no valid bank account associated with it on this network. Check your login details or contact a system administrator." + + var/obj/item/stock_parts/computer/charge_stick_slot/charge_slot = computer.get_component(PART_MSTICK) + if(!charge_slot || !charge_slot.is_functional()) + data["charge_stick_error"] = "No functional charge stick slot found!" + else if(!charge_slot.stored_stick) + data["charge_stick_error"] = "No charge stick inserted!" + else + data["charge_stick"] = "Charge Stick" + data["charge_stick_balance"] = charge_slot.stored_stick.loaded_worth + var/datum/computer_network/net = PRG.computer.get_network() + var/list/accesses = computer.get_access(user) + if(net && net.banking_mainframe) + if(!net.banking_mainframe.has_access(accesses)) + data["network_account_error"] = "You do not have access to the parent account on your current network." + else + var/datum/money_account/parent/network/bank_account = net.banking_mainframe.get_parent_account() + if(!bank_account) + data["network_account_error"] = "The network does not have a parent account created." + else + data["network_account"] = bank_account.account_name + data["network_account_balance"] = bank_account.money + else + data["network_account_error"] = "The network does not have a banking mainframe." + + + else if(PRG.selected_export) + switch(PRG.payment_type) + if(1) + data["personal_account_sel"] = 1 + if(2) + data["charge_stick_sel"] = 1 + if(3) + data["network_account_sel"] = 1 + + var/export_tax = 0 + if(selected_beacon && selected_beacon.linked_controller) + export_tax = selected_beacon.linked_controller.export_tax + + data["selected_export"] = PRG.selected_export.name + data["export_cost"] = PRG.selected_export.get_cost(export_tax) + data["export_desc"] = PRG.selected_export.desc + + var/datum/computer_file/data/account/A = PRG.computer.get_account() + if(A) + var/datum/money_account/child/network/money_account = A.money_account + if(money_account) + data["personal_account"] = money_account.account_name + data["personal_account_balance"] = money_account.money + else + data["personal_account_error"] = "No bank account." + + else + data["personal_account_error"] = "Not logged in." + + var/obj/item/stock_parts/computer/charge_stick_slot/charge_slot = computer.get_component(PART_MSTICK) + if(!charge_slot || !charge_slot.is_functional()) + data["personal_account_error"] = "Noslot found!" + else if(!charge_slot.stored_stick) + data["personal_account_error"] = "No charge stick!" + else + data["charge_stick"] = "Charge Stick" + data["charge_stick_balance"] = charge_slot.stored_stick.loaded_worth + var/datum/computer_network/net = PRG.computer.get_network() + var/list/accesses = computer.get_access(user) + if(net && net.banking_mainframe) + if(!net.banking_mainframe.has_access(accesses)) + data["network_account_error"] = "No access." + else + var/datum/money_account/parent/network/bank_account = net.banking_mainframe.get_parent_account() + if(!bank_account) + data["network_account_error"] = "No Network Account" + else + data["network_account"] = bank_account.account_name + data["network_account_balance"] = bank_account.money + else + data["network_account_error"] = "No Network Bank." + + + else + data["beacon_name"] = "*DISCONNECTED*" + + + ui = SSnano.try_update_ui(user, src, ui_key, ui, data, force_open) + if (!ui) + ui = new(user, src, ui_key, "trade_management.tmpl", name, 600, 750, state = state) + ui.auto_update_layout = 1 + ui.set_initial_data(data) + ui.set_auto_update(1) + ui.open() + +/datum/computer_file/program/trade_management/Topic(href, href_list, state) + . = ..() + if(.) + return + + if(href_list["select_beacon"]) + var/obj/hold = computer.get_physical_host() + var/list/possible_trade_beacons = hold.get_adjacent_trade_beacons() + possible_trade_beacons += "*DISCONNECT*" + var/beacon = input(usr, "Select a nearby trade beacon.", "Pick a beacon") as null|anything in possible_trade_beacons + if(!CanInteract(usr, global.default_topic_state)) + return TOPIC_REFRESH + if(beacon == "*DISCONNECT*") + selected_beacon = null + else if(beacon) + selected_beacon = beacon + + return TOPIC_REFRESH + if(href_list["import"]) + import_menu = 1 + export_menu = 0 + log_menu = 0 + selected_import = null + selected_export = null + return TOPIC_REFRESH + if(href_list["export"]) + import_menu = 0 + export_menu = 1 + log_menu = 0 + selected_import = null + selected_export = null + return TOPIC_REFRESH + if(href_list["log"]) + import_menu = 0 + export_menu = 0 + log_menu = 1 + selected_import = null + selected_export = null + return TOPIC_REFRESH + if(href_list["select_import"]) + import_menu = 0 + export_menu = 0 + log_menu = 0 + selected_import = locate(href_list["select_import"]) + selected_export = null + return TOPIC_REFRESH + if(href_list["select_export"]) + import_menu = 0 + export_menu = 0 + log_menu = 0 + selected_import = null + selected_export = locate(href_list["select_export"]) + return TOPIC_REFRESH + if(href_list["select_personal_account"]) + payment_type = 1 + return TOPIC_REFRESH + if(href_list["select_charge_stick"]) + payment_type = 2 + return TOPIC_REFRESH + if(href_list["select_network_account"]) + payment_type = 3 + return TOPIC_REFRESH + if(href_list["select_telepad"]) + detect_telepads() + var/obj/T = locate(href_list["select_telepad"]) + if(T && T in detected_telepads) + selected_telepad = T + return TOPIC_REFRESH + if(href_list["refresh_telepad"]) + detect_telepads() + return TOPIC_REFRESH + if(href_list["buy_import"]) + var/import_tax = 0 + if(!selected_import || !selected_beacon) + return + if(!(selected_import in selected_beacon.active_imports)) + selected_import = null + return + if(!selected_telepad) + to_chat(usr, SPAN_WARNING("You must select a telepad to send the import to.")) + return TOPIC_REFRESH + if(selected_beacon && selected_beacon.linked_controller) + import_tax = selected_beacon.linked_controller.import_tax + var/cost = selected_import.get_cost(import_tax) + var/tax_portion = selected_import.get_tax(import_tax) + switch(payment_type) + if(1) + var/datum/computer_file/data/account/A = computer.get_account() + if(A) + + var/oerr = checkImport() + if(oerr) + to_chat(usr, SPAN_WARNING("Import purchase failed: [oerr]")) + return TOPIC_HANDLED + var/datum/money_account/child/network/money_account = A.money_account + if(money_account) + var/terr = money_account.can_afford(cost, selected_beacon.beacon_account) + if(terr) + to_chat(usr, SPAN_WARNING("Import purchase failed: [terr]")) + return TOPIC_HANDLED + var/final_cost = cost-tax_portion + var/err = money_account.transfer(selected_beacon.beacon_account, final_cost, "Import Purchase ([selected_import.name] from [selected_beacon.name])") + if(err) + to_chat(usr, SPAN_WARNING("Import purchase failed: [err].")) + return TOPIC_HANDLED + else + if(tax_portion) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + err = money_account.transfer(network.banking_mainframe.get_parent_account(), tax_portion, "Import Purchase Tax ([selected_import.name] from [selected_beacon.name])") + if(err) + selected_beacon.beacon_account.transfer(money_account, final_cost, "Refunded Import Purchase ([selected_import.name] from [selected_beacon.name])") + else + spawnImport() + else + spawnImport() + else + to_chat(usr, SPAN_WARNING("No banking account associated with this network. Contact your system administrator..")) + else + to_chat(usr, SPAN_WARNING("You must login to a valid account on your network to pay digitally.")) + if(2) + var/obj/item/stock_parts/computer/charge_stick_slot/charge_slot = computer.get_component(PART_MSTICK) + if(!charge_slot || !charge_slot.stored_stick) + to_chat(usr, SPAN_WARNING("No charge stick is inserted into the computer.")) + return TOPIC_REFRESH + var/obj/item/charge_stick/stick = charge_slot.stored_stick + if(cost > stick.loaded_worth) + to_chat(usr, SPAN_WARNING("The loaded charge stick does not have enough credits stored!")) + return TOPIC_HANDLED + var/oerr = checkImport() + if(oerr) + to_chat(usr, SPAN_WARNING("Import purchase failed: [oerr]")) + return TOPIC_HANDLED + stick.adjust_worth(-(cost)) + if(tax_portion) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + var/datum/money_account/child/network/money_account = network.banking_mainframe.get_parent_account() + money_account.deposit(tax_portion, "Import Purchase Tax ([selected_import.name] from [selected_beacon.name])") + spawnImport() + if(3) + var/datum/computer_network/net = computer.get_network() + var/list/accesses = computer.get_access(usr) + if(net && net.banking_mainframe) + if(!net.banking_mainframe.has_access(accesses)) + to_chat(usr, SPAN_WARNING("You do not have access to the parent account on your current network.")) + return TOPIC_REFRESH + else + var/datum/money_account/parent/network/money_account = net.banking_mainframe.get_parent_account() + if(money_account) + var/terr = money_account.can_afford(cost, selected_beacon.beacon_account) + if(terr) + to_chat(usr, SPAN_WARNING("Import purchase failed: [terr]")) + return TOPIC_HANDLED + var/oerr = checkImport() + if(oerr) + to_chat(usr, SPAN_WARNING("Import purchase failed: [oerr]")) + return TOPIC_HANDLED + if(tax_portion) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + if(network.banking_mainframe.get_parent_account() == money_account) // dont pay tax from the account into the same account + tax_portion = 0 + cost = selected_import.get_cost(0) + else // remove tax if we cant find a parent account to pay it to. + tax_portion = 0 + cost = selected_import.get_cost(0) + if(money_account.money < cost) + to_chat(usr, SPAN_WARNING("Import purchase failed: Insufficent funds.")) + return TOPIC_HANDLED + var/final_cost = cost-tax_portion + var/err = money_account.transfer(selected_beacon.beacon_account, final_cost, "Import Purchase ([selected_import.name] from [selected_beacon.name])") + if(err) + to_chat(usr, SPAN_WARNING("Import purchase failed: [err].")) + return TOPIC_HANDLED + else + if(tax_portion) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + err = money_account.transfer(network.banking_mainframe.get_parent_account(), tax_portion, "Import Purchase Tax ([selected_import.name] from [selected_beacon.name])") + if(err) + selected_beacon.beacon_account.transfer(money_account, final_cost, "Refunded Import Purchase ([selected_import.name] from [selected_beacon.name])") + else + spawnImport() + else + spawnImport() + else + to_chat(usr, SPAN_WARNING("The network does not have a central account.")) + return TOPIC_REFRESH + return TOPIC_REFRESH + if(href_list["buy_export"]) + var/export_tax = 0 + if(!selected_export || !selected_beacon) + return TOPIC_REFRESH + if(!(selected_export in selected_beacon.active_exports)) + selected_export = null + return + if(!selected_telepad) + to_chat(usr, SPAN_WARNING("You must select a telepad to send the export to.")) + return TOPIC_REFRESH + if(selected_beacon && selected_beacon.linked_controller) + export_tax = selected_beacon.linked_controller.export_tax + var/cost = selected_export.get_cost(export_tax) + var/tax_portion = selected_export.get_tax(export_tax) + switch(payment_type) + if(1) + var/datum/computer_file/data/account/A = computer.get_account() + if(A) + var/datum/money_account/child/network/money_account = A.money_account + if(money_account) + var/e_err = checkExport() + if(e_err) + to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) + resetExport() + return TOPIC_HANDLED + var/err = money_account.deposit(cost, "Export ([selected_export.name] from [selected_beacon.name])") + if(err) + to_chat(usr, SPAN_WARNING("Export failed: [err].")) + resetExport() + return TOPIC_HANDLED + else + + if(tax_portion) // SUCCESS + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + var/datum/money_account/acc = network.banking_mainframe.get_parent_account() + err = acc.deposit(tax_portion, "Export Tax ([selected_export.name] from [selected_beacon.name])") + var/result = takeExport() + if(result) + to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) + else + to_chat(usr, SPAN_WARNING("No banking account associated with this network. Contact your system administrator.")) + return TOPIC_REFRESH + else + to_chat(usr, SPAN_WARNING("You must login to a valid account on your network to pay digitally.")) + return TOPIC_REFRESH + if(2) + var/obj/item/stock_parts/computer/charge_stick_slot/charge_slot = computer.get_component(PART_MSTICK) + if(!charge_slot || !charge_slot.stored_stick) + to_chat(usr, SPAN_WARNING("No charge stick is inserted into the computer.")) + return TOPIC_REFRESH + var/obj/item/charge_stick/stick = charge_slot.stored_stick + var/e_err = checkExport() + if(e_err) + to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) + resetExport() + return TOPIC_HANDLED + stick.adjust_worth(cost) + if(tax_portion) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + var/datum/money_account/acc = network.banking_mainframe.get_parent_account() + acc.deposit(tax_portion, "Export Tax ([selected_export.name] from [selected_beacon.name])") + var/result = takeExport() + if(result) + to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) + if(3) + var/datum/computer_network/net = computer.get_network() + var/list/accesses = computer.get_access(usr) + if(net && net.banking_mainframe) + if(!net.banking_mainframe.has_access(accesses)) + to_chat(usr, SPAN_WARNING("You do not have access to the parent account on your current network.")) + return TOPIC_REFRESH + else + var/datum/money_account/parent/network/money_account = net.banking_mainframe.get_parent_account() + if(money_account) + if(tax_portion) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + if(network.banking_mainframe.get_parent_account() == money_account) // dont pay tax from the account into the same account + tax_portion = 0 + cost = selected_export.get_cost(0) + else // remove tax if we cant find a parent account to pay it to. + tax_portion = 0 + cost = selected_export.get_cost(0) + var/e_err = checkExport() + if(e_err) + to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) + resetExport() + return TOPIC_HANDLED + var/err = money_account.deposit(cost, "Export ([selected_export.name] to [selected_beacon.name])") + if(err) + to_chat(usr, SPAN_WARNING("Export failed: [err].")) + resetExport() + return TOPIC_HANDLED + + else // SUCCESS + if(tax_portion) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + var/datum/money_account/acc = network.banking_mainframe.get_parent_account() + err = acc.deposit(tax_portion, "Export Tax ([selected_export.name] from [selected_beacon.name])") + var/result = takeExport() + if(result) + to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) + + else + to_chat(usr, SPAN_WARNING("The network does not have a central account.")) + return TOPIC_REFRESH + return TOPIC_REFRESH + +/obj/machinery/telepad_cargo + name = "cargo telepad" + desc = "A telepad used to recieve imports and send exports." + icon = 'icons/obj/machines/telepad.dmi' + icon_state = "pad-idle" + anchored = 1 + use_power = 1 + idle_power_usage = 20 + active_power_usage = 500 + var/telepad_id = 0 +/obj/machinery/telepad_cargo/New() + telepad_id = random_id(type,10000,99999) + +/obj/machinery/telepad_cargo/attackby(obj/item/O as obj, mob/user as mob, params) + if(IS_WRENCH(O)) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) + if(anchored) + anchored = 0 + to_chat(user, " The [src] can now be moved.") + else if(!anchored) + anchored = 1 + to_chat(user, " The [src] is now secured.") + if(IS_MULTITOOL(O)) + var/id = input(user, "Enter a new telepad ID", "Telepad ID") as text|null + id = sanitize(id) + if(CanInteract(user, DefaultTopicState()) && id) telepad_id = id + + return component_attackby(O, user) \ No newline at end of file diff --git a/mods/persistence/modules/trade_beacons/cargo_telepads.dm b/mods/persistence/modules/trade_beacons/cargo_telepads.dm new file mode 100644 index 00000000000..82278b104d6 --- /dev/null +++ b/mods/persistence/modules/trade_beacons/cargo_telepads.dm @@ -0,0 +1,28 @@ +/obj/machinery/telepad_cargo + name = "cargo telepad" + desc = "A telepad used to recieve imports and send exports." + icon = 'icons/obj/machines/telepad.dmi' + icon_state = "pad-idle" + anchored = 1 + use_power = 1 + idle_power_usage = 20 + active_power_usage = 500 + var/telepad_id = 0 +/obj/machinery/telepad_cargo/New() + telepad_id = random_id(type,10000,99999) + +/obj/machinery/telepad_cargo/attackby(obj/item/O as obj, mob/user as mob, params) + if(IS_WRENCH(O)) + playsound(src, 'sound/items/Ratchet.ogg', 50, 1) + if(anchored) + anchored = 0 + to_chat(user, " The [src] can now be moved.") + else if(!anchored) + anchored = 1 + to_chat(user, " The [src] is now secured.") + if(IS_MULTITOOL(O)) + var/id = input(user, "Enter a new telepad ID", "Telepad ID") as text|null + id = sanitize(id) + if(CanInteract(user, DefaultTopicState()) && id) telepad_id = id + + return component_attackby(O, user) \ No newline at end of file diff --git a/mods/persistence/modules/trade_beacons/exports.dm b/mods/persistence/modules/trade_beacons/exports.dm new file mode 100644 index 00000000000..4ebbe98cac5 --- /dev/null +++ b/mods/persistence/modules/trade_beacons/exports.dm @@ -0,0 +1,80 @@ + +/datum/beacon_export + var/name = "Beacon Export" + var/list/required_items = list() // structure is list(/obj/item/example = 1, /obj/item/multi = 2) list(type = number required). + var/cost = 1000 + var/remaining_stock = 5 + var/desc = "Export Description" + var/obj/checked_closet +/datum/beacon_export/proc/get_cost(var/tax) + if(!tax) return cost + return cost-((tax/100)*cost) + +/datum/beacon_export/proc/get_tax(var/tax) + if(!tax) return 0 + return (tax/100)*cost + +/datum/beacon_export/proc/takeExport() + if(checked_closet) + checked_closet.forceMove(null) + qdel(checked_closet) + checked_closet = null + remaining_stock-- +/datum/beacon_export/proc/resetExport() + checked_closet = null + +/datum/beacon_export/proc/checkExport(var/turf/L) + if(!L) return "No valid location detected" + var/obj/closet_found = 0 + var/valid_items = list() + for(var/obj/structure/closet/C in L.contents) + closet_found = C + for(var/item_type in required_items) + var/ind = required_items[item_type] + if(!ind) ind = 1 + var/found = 0 + for(var/obj/o in C.contents) + if(istype(o, item_type)) + if(isstack(o)) + var/obj/item/stack/s = o + ind -= s.amount + if(ind >= 0) + valid_items |= o + else + ind-- + valid_items |= o + if(ind < 0) + return "Too many items included ([o.name]). Exact orders only." + if(ind == 0) + found = 1 + break + if(!found) + return "Incomplete Export Detected ([item_type])" + break // only check 1, the for loop is just a convient way to search + if(!closet_found) + return "No container detected" + else + var/obj/invalid_item = 0 + for(var/obj/o in closet_found.contents) + if(!(o in valid_items)) + invalid_item = o + break + if(invalid_item) + return "Too many items included ([invalid_item.name]). Exact orders only." + checked_closet = closet_found + return // SUCCESS + + +///////////////////////////////////////// + +/datum/beacon_export/example + required_items = list(/obj/item/stack/cable_coil = 10, /obj/item/plunger = 2) + name = "Example Export" + desc = "This is a debug export to test sending stacked items and multiple single items. It requires a ten stack of cable coil and two plungers to complete." + cost = 500 + +/datum/beacon_export/xanaducrystal + required_items = list(/obj/item/plunger = 1) + name = "Xanadu Crystal" + desc = "The rare Xanadu Crystal is much prized across the Galaxy." + cost = 5000 \ No newline at end of file diff --git a/mods/persistence/modules/trade_beacons/imports.dm b/mods/persistence/modules/trade_beacons/imports.dm new file mode 100644 index 00000000000..2d7cfcf2eb8 --- /dev/null +++ b/mods/persistence/modules/trade_beacons/imports.dm @@ -0,0 +1,53 @@ +/datum/beacon_import + var/name = "Beacon Import" + var/list/provided_items = list() // structure is list(/obj/item/example = 1, /obj/item/multi = 2) list(type = number provided). + var/container_type = /obj/structure/closet/crate + var/cost = 1000 + var/remaining_stock = 5 // how many are left to buy this cycle + var/desc = "Import Desription" + +/datum/beacon_import/proc/get_cost(var/tax) + if(!tax) return cost + return cost+((tax/100)*cost) + +/datum/beacon_import/proc/get_tax(var/tax) + if(!tax) return 0 + return (tax/100)*cost + +/datum/beacon_import/proc/checkImport(var/turf/L) + if(!L) return "Invalid telepad." + for(var/obj/i in L.contents) + if(!istype(i, /obj/machinery)) // machines are ok + return "Telepad obstructed" +/datum/beacon_import/proc/spawnImport(var/turf/L) + if(!L) return + var/obj/structure/container = new container_type(L) + for(var/item_type in provided_items) + var/ind = provided_items[item_type] + if(!ind) ind = 1 + var/obj/item/stack/stacking = 0 + for(var/i=1;i<=ind;i++) + if(stacking) + stacking.add(1) + else + var/obj/o = new item_type(container) + if(isstack(o)) + stacking = o + remaining_stock-- + + +////////////////////////////////////////////////////////////////// + +/datum/beacon_import/steel + provided_items = list(/obj/item/stack/material/sheet/mapped/steel = 50) + name = "Steel (50 Sheets)" + cost = 500 + desc = "A stack of fifty steel sheets. Fifty sheets of grey steel." + + +/datum/beacon_import/example + provided_items = list(/obj/item/stack/cable_coil/single = 10, /obj/item/plunger = 2) + name = "Example Import" + cost = 150 + desc = "This is a debug import that tests stacks and multiple single items. It sends 10 pieces of cable coil, stacked and 2 plungers." + diff --git a/mods/persistence/modules/trade_beacons/trade_beacons.dm b/mods/persistence/modules/trade_beacons/trade_beacons.dm new file mode 100644 index 00000000000..f12f6adade5 --- /dev/null +++ b/mods/persistence/modules/trade_beacons/trade_beacons.dm @@ -0,0 +1,103 @@ +/atom/proc/get_adjacent_trade_beacons() + var/list/adjacent_trade_beacons = list() + var/atom/target = src + if(!istype(src, /turf)) + target = get_turf(src) + var/obj/ob = target.get_owning_overmap_object() + if(ob) + var/turf/T = get_turf(ob) + if(T) + for(var/obj/beacon in SStrade_beacons.all_trade_beacons) + var/turf/beacon_turf = get_turf(beacon) + if(beacon_turf && beacon_turf.Adjacent(T)) + adjacent_trade_beacons |= beacon + return adjacent_trade_beacons + +/obj/effect/overmap/trade_beacon + name = "Trade Beacon" + var/list/possible_imports = list() // structure is list(/datum/beacon_import/example = 100) list(type = percentage chance of appearing). + var/list/possible_exports = list() + var/list/active_imports = list() + var/list/active_exports = list() + icon = 'icons/obj/supplybeacon.dmi' + icon_state = "beacon_active" + var/datum/extension/network_device/trade_controller/linked_controller + var/datum/money_account/beacon_account + var/start_x = 0 + var/start_y = 0 + +/obj/effect/overmap/trade_beacon/proc/move_to_starting_location() + var/datum/overmap/overmap = global.overmaps_by_name[overmap_id] + var/location + + if(start_x && start_y) + location = locate(start_x, start_y, overmap.assigned_z) + else + var/list/candidate_turfs = block( + locate(OVERMAP_EDGE, OVERMAP_EDGE, overmap.assigned_z), + locate(overmap.map_size_x - OVERMAP_EDGE, overmap.map_size_y - OVERMAP_EDGE, overmap.assigned_z) + ) + + candidate_turfs = where(candidate_turfs, /proc/can_not_locate, /obj/effect/overmap) + location = SAFEPICK(candidate_turfs) || locate( + rand(OVERMAP_EDGE, overmap.map_size_x - OVERMAP_EDGE), + rand(OVERMAP_EDGE, overmap.map_size_y - OVERMAP_EDGE), + overmap.assigned_z + ) + + forceMove(location) + + + +/obj/effect/overmap/trade_beacon/New() + beacon_account = new() + beacon_account.account_name = name + +/obj/effect/overmap/trade_beacon/Initialize() + ..() + move_to_starting_location() + regenerate_imports() + regenerate_exports() + +/obj/effect/overmap/trade_beacon/proc/regenerate_imports() + active_imports.Cut() + for(var/import in possible_imports) + if(!prob(possible_imports[import])) continue + active_imports |= new import() + + + +/obj/effect/overmap/trade_beacon/proc/regenerate_exports() + active_exports.Cut() + for(var/export in possible_exports) + if(!prob(possible_exports[export])) continue + active_exports |= new export() + +//////////////////////////////// BEACONS + + +/obj/effect/overmap/trade_beacon/test_beacon + start_x = 28 + start_y = 23 + possible_imports = list( + /datum/beacon_import/example = 100, + /datum/beacon_import/steel = 100 + ) + possible_exports = list( + /datum/beacon_export/example = 100, + /datum/beacon_export/xanaducrystal = 100 + ) + name = "Kleibkhar Debug Trade Beacon" + +/obj/effect/overmap/trade_beacon/test_beacon2 + start_x = 27 + start_y = 22 + possible_imports = list( + /datum/beacon_import/example = 100, + /datum/beacon_import/steel = 100 + ) + possible_exports = list( + /datum/beacon_export/example = 100, + /datum/beacon_export/xanaducrystal = 100 + ) + name = "Kleibkhar Debug Trade Beacon Secondus" diff --git a/nano/templates/trade_controller.tmpl b/nano/templates/trade_controller.tmpl new file mode 100644 index 00000000000..4e1c56db602 --- /dev/null +++ b/nano/templates/trade_controller.tmpl @@ -0,0 +1,49 @@ +{{if data.error}} +

An error has occured:

+ Additional information: {{:data.error}}
+ Please try again. If the problem persists contact your system administrator for assistance. +
+ {{:helper.link('REFRESH', null, { "refresh" : 1 })}} + {{:helper.link("NETWORK SETTINGS", null, { "settings" : 1 })}} +
+{{else}} + + Welcome to the Trade control device. You may control a nearby trade beacon, adding taxes or restricting access as required.
+
+ {{:helper.link("NETWORK SETTINGS", null, { "settings" : 1 })}} +
+ {{if !data.connected}} +

Disconnected from network.

+ {{else}} + <
SettingToggleInfo +
CONNECTED BEACON: + {{:helper.link(data.connected_beacon, null, { "connect_beacon" : 1 })}} + {{:helper.link('?', null, { "info" : "connect_beacon"})}} + {{if data.valid_beacon}} + +
RESTRICT BEACON + {{:helper.link(data.beacon_restrict ? 'ON' : 'OFF', null, { "toggle_beacon_restrict" : 1 })}} + {{:helper.link('?', null, { "info" : "restrict_beacon_access"})}} + {{if data.beacon_restrict}} +
BEACON ACCESS + {{:helper.link(data.selected_beacon_access, null, { "select_beacon_access" : 1 })}} + {{:helper.link('?', null, { "info" : "select_beacon_access"})}} + {{/if}} +
IMPORT TARIFF % + {{:helper.link(data.import_tax, null, { "change_import_tax" : 1 })}} + {{:helper.link('?', null, { "info" : "import_tax"})}} +
EXPORT TARIFF % + {{:helper.link(data.export_tax, null, { "change_export_tax" : 1 })}} + {{:helper.link('?', null, { "info" : "export_tax"})}} +
RESTRICT TRANSACTION LOG + {{:helper.link(data.log_restrict ? 'ON' : 'OFF', null, { "toggle_log_restrict" : 1 })}} + {{:helper.link('?', null, { "info" : "restrict_log_access"})}} + {{if data.log_restrict}} +
TRANSACTION LOG ACCESS + {{:helper.link(data.selected_log_access, null, { "select_log_access" : 1 })}} + {{:helper.link('?', null, { "info" : "select_log_access"})}} + {{/if}} + {{/if}} +
+ {{/if}} +{{/if}} \ No newline at end of file diff --git a/nano/templates/trade_management.tmpl b/nano/templates/trade_management.tmpl new file mode 100644 index 00000000000..78b6152d5c3 --- /dev/null +++ b/nano/templates/trade_management.tmpl @@ -0,0 +1,179 @@ +
+
+ Connected Trade Beacon: +
+
+ {{:helper.link(data.beacon_name, '', {'select_beacon' : 1 })}} +
+
+ + +
Telepad + {{for data.telepads}} +
{{:helper.link(value.telepad_name, '', {'select_telepad' : value.telepad_ref}, value.selected ? 'selected' : null)}} + {{/for}} +
+{{:helper.link('Rescan for Telepads', '', { 'refresh_telepad' : 1 })}} +
+
+
+ Inventories Reset: +
+
+ {{:data.update_time}} +
+
+

+{{if !data.selected_beacon}} +

No Trade Beacon Connected! You must connect to a trade beacon to use this program.

+{{else}} + {{if data.beacon_access}} + {{:helper.link('Import', null, { 'import' : 1 }, data.import ? 'selected' : null)}} + {{:helper.link('Export', null, { 'export' : 1 }, data.export ? 'selected' : null)}} + {{:helper.link('Transaction Log', null, { 'log' : 1 }, data.log ? 'selected' : null)}} +
+ {{if data.import}} +

Import Selection

+ {{if data.import_tax}} +
+ Current Import Tariff %: +
+
+ {{:data.import_tax}} +
+
+ The beacon is under control the control of the network '{{:data.controlling_network}}' which is taxing all imports from the beacon by {{:data.import_tax}}%. This increase is automatically included in the prices here. +

+ {{/if}} + + +
Import PackCost$Remaining Stock + {{for data.imports}} +
{{:helper.link(value.import_name, '', {'select_import' : value.import_ref})}} + {{:value.import_cost}} + {{:value.import_remaining}} + {{/for}} +
+ {{/if}} + {{if data.export}} +

Export Selection

+
+ {{if data.export_tax}} +
+ Current Export Tariff %: +
+
+ {{:data.export_tax}} +
+
+ The beacon is under control the control of the network '{{:data.controlling_network}}' which is taxing all exports from the beacon by {{:data.export_tax}}% This deduction is already included in the payments listed here. +

+ {{/if}} + + +
Export PackPayment$Remaining Demand + {{for data.exports}} +
{{:helper.link(value.export_name, '', {'select_export' : value.export_ref})}} + {{:value.export_cost}} + {{:value.export_remaining}} + {{/for}} +
+ {{/if}} + + + {{if data.log}} + {{if data.log_access}} +

Transaction Log

+ + +
TransactionPayment + {{for data.transactions}} +
{{:value.transaction}} + {{:value.transaction_cost}} + {{/for}} +
+ {{else}} + The beacon is under control the control of the network '{{:data.controlling_network}}' which has restricted access to the transaction log. + {{/if}} + {{/if}} + + {{if data.selected_import}} +

{{:data.selected_import}} ${{:data.import_cost}}

+
+ {{:data.import_desc}} +
+

+ + + {{if data.personal_account}} + + {{if data.charge_stick}} + + {{if data.network_account}} +
Purchase OptionBalance$ +
{{:helper.link(data.personal_account, '', {'select_personal_account' : 1}, data.personal_account_sel ? 'selected' : null)}} + ${{:data.personal_account_balance}} + {{else}} + {{:data.personal_account_error}} + *N/A* + {{/if}} +
{{:helper.link('Charge Stick', '', {'select_charge_stick' : 1}, data.charge_stick_sel ? 'selected' : null)}} + ${{:data.charge_stick_balance}} + {{else}} + {{:data.charge_stick_error}} + *N/A* + {{/if}} +
{{:helper.link(data.network_account, '', {'select_network_account' : 1}, data.network_account_sel ? 'selected' : null)}} + ${{:data.network_account_balance}} + {{else}} + {{:data.network_account_error}} + *N/A* + {{/if}} +
+

+ {{:helper.link('Purchase Import', 'cart', { 'buy_import' : 1 })}} + {{:helper.link('Back', 'arrowthickstop-1-w', {'import' : 1})}} + {{/if}} + + + {{if data.selected_export}} +

{{:data.selected_export}} ${{:data.export_cost}}

+
+ {{:data.export_desc}} +
+

+ + + {{if data.personal_account}} + + {{if data.charge_stick}} + + {{if data.network_account}} +
Purchase OptionBalance$ +
{{:helper.link(data.personal_account, '', {'select_personal_account' : 1}, data.personal_account_sel ? 'selected' : null)}} + ${{:data.personal_account_balance}} + {{else}} + {{:data.personal_account_error}} + *N/A* + {{/if}} +
{{:helper.link('Charge Stick', '', {'select_charge_stick' : 1}, data.charge_stick_sel ? 'selected' : null)}} + ${{:data.charge_stick_balance}} + {{else}} + {{:data.charge_stick_error}} + *N/A* + {{/if}} +
{{:helper.link(data.network_account, '', {'select_network_account' : 1}, data.network_account_sel ? 'selected' : null)}} + ${{:data.network_account_balance}} + {{else}} + {{:data.network_account_error}} + *N/A* + {{/if}} +
+

+ {{:helper.link('Process Export', 'cart', { 'buy_export' : 1 }, null)}} + {{:helper.link('Back', 'arrowthickstop-1-w', {'export' : 1})}} + {{/if}} + {{else}} + The beacon is under control the control of the network '{{:data.controlling_network}}' which has restricted access. + {{/if}} +{{/if}} \ No newline at end of file From dc44d19fa3a4bd76c886fc748f48593d9c1f3b18 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 13:50:44 -0600 Subject: [PATCH 12/47] removed old files --- .../modules/quadrants/quadrants.dm | 13 - mods/persistence/modules/quadrants/trade.dm | 827 ------------------ 2 files changed, 840 deletions(-) delete mode 100644 mods/persistence/modules/quadrants/quadrants.dm delete mode 100644 mods/persistence/modules/quadrants/trade.dm diff --git a/mods/persistence/modules/quadrants/quadrants.dm b/mods/persistence/modules/quadrants/quadrants.dm deleted file mode 100644 index 43a46546a6f..00000000000 --- a/mods/persistence/modules/quadrants/quadrants.dm +++ /dev/null @@ -1,13 +0,0 @@ -/datum/quadrant - var/name = "Default Quadrant" - var/default_securitylvl = 2 // Security levels - var/list/securitylvl_modifiers = list() - var/uid = "default" // used to link trade beacons/events with the - var/current_securitylvl = 0 - - - -/datum/SLModifier - var/name = "Security Level Modifier" - var/value = 0 // how much to change the security level by - var/expiry = 0 // realtime that the modifier should be deleted diff --git a/mods/persistence/modules/quadrants/trade.dm b/mods/persistence/modules/quadrants/trade.dm deleted file mode 100644 index e65f18f7355..00000000000 --- a/mods/persistence/modules/quadrants/trade.dm +++ /dev/null @@ -1,827 +0,0 @@ -var/global/list/all_trade_beacons = list() - -/atom/proc/get_adjacent_trade_beacons() - var/list/adjacent_trade_beacons = list() - var/atom/target = src - if(!istype(src, /turf)) - target = get_turf(src) - var/obj/ob = target.get_owning_overmap_object() - if(ob) - var/turf/T = get_turf(ob) - if(T) - for(var/obj/beacon in all_trade_beacons) - var/turf/beacon_turf = get_turf(beacon) - if(beacon_turf && beacon_turf.Adjacent(T)) - adjacent_trade_beacons |= beacon - return adjacent_trade_beacons - -/obj/effect/overmap/trade_beacon - name = "Trade Beacon" - var/list/possible_imports = list() // structure is list(/datum/beacon_import/example = 100) list(type = percentage chance of appearing). - var/list/possible_exports = list() - var/list/active_imports = list() - var/list/active_exports = list() - icon = 'icons/obj/supplybeacon.dmi' - icon_state = "beacon_active" - var/datum/extension/network_device/trade_controller/linked_controller - var/datum/money_account/beacon_account - var/start_x = 0 - var/start_y = 0 - -/obj/effect/overmap/trade_beacon/proc/move_to_starting_location() - var/datum/overmap/overmap = global.overmaps_by_name[overmap_id] - var/location - - if(start_x && start_y) - location = locate(start_x, start_y, overmap.assigned_z) - else - var/list/candidate_turfs = block( - locate(OVERMAP_EDGE, OVERMAP_EDGE, overmap.assigned_z), - locate(overmap.map_size_x - OVERMAP_EDGE, overmap.map_size_y - OVERMAP_EDGE, overmap.assigned_z) - ) - - candidate_turfs = where(candidate_turfs, /proc/can_not_locate, /obj/effect/overmap) - location = SAFEPICK(candidate_turfs) || locate( - rand(OVERMAP_EDGE, overmap.map_size_x - OVERMAP_EDGE), - rand(OVERMAP_EDGE, overmap.map_size_y - OVERMAP_EDGE), - overmap.assigned_z - ) - - forceMove(location) - -/obj/effect/overmap/trade_beacon/test_beacon - start_x = 28 - start_y = 23 - possible_imports = list( - /datum/beacon_import/example = 100, - /datum/beacon_import/steel = 100 - ) - possible_exports = list( - /datum/beacon_export/example = 100, - /datum/beacon_export/xanaducrystal = 100 - ) - name = "Kleibkhar Debug Trade Beacon" - -/obj/effect/overmap/trade_beacon/test_beacon2 - start_x = 27 - start_y = 22 - possible_imports = list( - /datum/beacon_import/example = 100, - /datum/beacon_import/steel = 100 - ) - possible_exports = list( - /datum/beacon_export/example = 100, - /datum/beacon_export/xanaducrystal = 100 - ) - name = "Kleibkhar Debug Trade Beacon Secondus" - - - -/obj/effect/overmap/trade_beacon/New() - beacon_account = new() - beacon_account.account_name = name - -/obj/effect/overmap/trade_beacon/Initialize() - all_trade_beacons |= src - ..() - move_to_starting_location() - regenerate_imports() - regenerate_exports() - -/obj/effect/overmap/trade_beacon/proc/regenerate_imports() - active_imports.Cut() - for(var/import in possible_imports) - if(!prob(possible_imports[import])) continue - active_imports |= new import() - - - -/obj/effect/overmap/trade_beacon/proc/regenerate_exports() - active_exports.Cut() - for(var/export in possible_exports) - if(!prob(possible_exports[export])) continue - active_exports |= new export() - -/datum/beacon_import - var/name = "Beacon Import" - var/list/provided_items = list() // structure is list(/obj/item/example = 1, /obj/item/multi = 2) list(type = number provided). - var/container_type = /obj/structure/closet/crate - var/cost = 1000 - var/remaining_stock = 5 // how many are left to buy this cycle - var/desc = "Import Desription" - -/datum/beacon_import/proc/get_cost(var/tax) - if(!tax) return cost - return cost+((tax/100)*cost) - -/datum/beacon_import/proc/get_tax(var/tax) - if(!tax) return 0 - return (tax/100)*cost - -/datum/beacon_import/proc/checkImport(var/turf/L) - if(!L) return "Invalid telepad." - for(var/obj/i in L.contents) - if(!istype(i, /obj/machinery)) // machines are ok - return "Telepad obstructed" -/datum/beacon_import/proc/spawnImport(var/turf/L) - if(!L) return - var/obj/structure/container = new container_type(L) - for(var/item_type in provided_items) - var/ind = provided_items[item_type] - if(!ind) ind = 1 - var/obj/item/stack/stacking = 0 - for(var/i=1;i<=ind;i++) - if(stacking) - stacking.add(1) - else - var/obj/o = new item_type(container) - if(isstack(o)) - stacking = o - remaining_stock-- - -/datum/beacon_import/steel - provided_items = list(/obj/item/stack/material/sheet/mapped/steel = 50) - name = "Steel (50 Sheets)" - cost = 500 - desc = "A stack of fifty steel sheets. Fifty sheets of grey steel." - - -/datum/beacon_import/example - provided_items = list(/obj/item/stack/cable_coil/single = 10, /obj/item/plunger = 2) - name = "Example Import" - cost = 150 - desc = "This is a debug import that tests stacks and multiple single items. It sends 10 pieces of cable coil, stacked and 2 plungers." - - - -/datum/beacon_export - var/name = "Beacon Export" - var/list/required_items = list() // structure is list(/obj/item/example = 1, /obj/item/multi = 2) list(type = number required). - var/cost = 1000 - var/remaining_stock = 5 - var/desc = "Export Description" - var/obj/checked_closet -/datum/beacon_export/proc/get_cost(var/tax) - if(!tax) return cost - return cost-((tax/100)*cost) - -/datum/beacon_export/proc/get_tax(var/tax) - if(!tax) return 0 - return (tax/100)*cost - -/datum/beacon_export/proc/takeExport() - if(checked_closet) - checked_closet.forceMove(null) - qdel(checked_closet) - checked_closet = null - remaining_stock-- -/datum/beacon_export/proc/resetExport() - checked_closet = null - -/datum/beacon_export/proc/checkExport(var/turf/L) - if(!L) return "No valid location detected" - var/obj/closet_found = 0 - var/valid_items = list() - for(var/obj/structure/closet/C in L.contents) - closet_found = C - for(var/item_type in required_items) - var/ind = required_items[item_type] - if(!ind) ind = 1 - var/found = 0 - for(var/obj/o in C.contents) - if(istype(o, item_type)) - if(isstack(o)) - var/obj/item/stack/s = o - ind -= s.amount - if(ind >= 0) - valid_items |= o - else - ind-- - valid_items |= o - if(ind < 0) - return "Too many items included ([o.name]). Exact orders only." - if(ind == 0) - found = 1 - break - if(!found) - return "Incomplete Export Detected ([item_type])" - break // only check 1, the for loop is just a convient way to search - if(!closet_found) - return "No container detected" - else - var/obj/invalid_item = 0 - for(var/obj/o in closet_found.contents) - if(!(o in valid_items)) - invalid_item = o - break - if(invalid_item) - return "Too many items included ([invalid_item.name]). Exact orders only." - checked_closet = closet_found - return // SUCCESS - -/datum/beacon_export/example - required_items = list(/obj/item/stack/cable_coil = 10, /obj/item/plunger = 2) - name = "Example Export" - desc = "This is a debug export to test sending stacked items and multiple single items. It requires a ten stack of cable coil and two plungers to complete." - cost = 500 - -/datum/beacon_export/xanaducrystal - required_items = list(/obj/item/plunger = 1) - name = "Xanadu Crystal" - desc = "The rare Xanadu Crystal is much prized across the Galaxy." - cost = 5000 -///////////////////////////////////////// - - - -/datum/computer_file/program/trade_management - filename = "trademnrger" - filedesc = "Import/Export Management" - extended_desc = "This program allows you to process imports or exports from nearby trade beacons." - - program_icon_state = "generic" - program_key_state = "generic_key" - program_menu_icon = "cart" - - available_on_network = 1 - - size = 12 - nanomodule_path = /datum/nano_module/program/trade_management - - var/current_map_z - var/obj/effect/overmap/trade_beacon/selected_beacon - - var/import_menu = 1 - var/export_menu = 0 - var/log_menu = 0 - var/datum/beacon_import/selected_import - var/datum/beacon_export/selected_export - var/payment_type = 1 // 1 == personal account 2 == chargestick 3 == network parent account - - var/list/detected_telepads = list() - var/obj/selected_telepad - -/datum/computer_file/program/trade_management/proc/detect_telepads() - detected_telepads = list() - for(var/obj/machinery/telepad_cargo/c in orange(3, get_turf(computer))) - if(c.anchored) - detected_telepads |= c - return - -/datum/computer_file/program/trade_management/on_startup(mob/living/user, datum/extension/interactive/os/new_host) - . = ..() - detect_telepads() - - -/datum/computer_file/program/trade_management/on_shutdown() - . = ..() - current_map_z = null - -/datum/nano_module/program/trade_management - name = "Import/Export Management" - - -/datum/computer_file/program/trade_management/proc/spawnImport() - var/turf/T = get_turf(selected_telepad) - flick("pad-beam", selected_telepad) - . = selected_import.spawnImport(T) - if(selected_import.remaining_stock < 1) - selected_beacon.active_imports.Remove(selected_import) - selected_import = null -/datum/computer_file/program/trade_management/proc/checkImport() - var/turf/T = get_turf(selected_telepad) - flick("pad-beam", selected_telepad) - return selected_import.checkImport(T) - -/datum/computer_file/program/trade_management/proc/takeExport() - flick("pad-beam", selected_telepad) - . = selected_export.takeExport() - if(selected_export.remaining_stock < 1) - selected_beacon.active_exports.Remove(selected_export) - selected_export = null -/datum/computer_file/program/trade_management/proc/checkExport() - var/turf/T = get_turf(selected_telepad) - return selected_export.checkExport(T) - -/datum/computer_file/program/trade_management/proc/resetExport() - return selected_export.resetExport() - - -/datum/nano_module/program/trade_management/ui_interact(mob/user, ui_key, datum/nanoui/ui, force_open, datum/nanoui/master_ui, datum/topic_state/state) - var/list/data = host.initial_data() - var/datum/computer_file/program/trade_management/PRG = program - var/datum/extension/interactive/os/computer = PRG.computer - var/list/telepads[0] - - for(var/obj/machinery/telepad_cargo/x in PRG.detected_telepads) - var/selected = 0 - if(x == PRG.selected_telepad) selected = 1 - telepads.Add(list(list( - "telepad_name" = "[x.name] ([x.telepad_id])", - "selected" = selected, - "telepad_ref" = any2ref(x), - ))) - if(!telepads.len) - telepads.Add(list(list( - "telepad_name" = "No telepads detected!", - "selected" = 1, - ))) - data["telepads"] = telepads - - var/obj/effect/overmap/trade_beacon/selected_beacon = PRG.selected_beacon - if(selected_beacon) - data["selected_beacon"] = TRUE - data["beacon_name"] = selected_beacon.name - var/access = 1 - if(selected_beacon && selected_beacon.linked_controller && selected_beacon.linked_controller.get_network()) - var/datum/computer_network/network = selected_beacon.linked_controller.get_network() - data["controlling_network"] = network.network_id - if(selected_beacon.linked_controller.beacon_restrict) - if(selected_beacon.linked_controller.get_network() == PRG.computer.get_network()) - var/list/accesses = computer.get_access(user) - if(selected_beacon.linked_controller.access && !(selected_beacon.linked_controller.access in accesses)) - access = 0 - else - access = 0 - - if(access) - data["beacon_access"] = 1 - if(PRG.import_menu) - data["import"] = 1 - var/import_tax = 0 - if(selected_beacon && selected_beacon.linked_controller) - import_tax = selected_beacon.linked_controller.import_tax - - data["import_tax"] = import_tax - var/list/imports[0] - for(var/datum/beacon_import/x in selected_beacon.active_imports) - imports.Add(list(list( - "import_name" = x.name, - "import_cost" = x.get_cost(import_tax), - "import_ref" = any2ref(x), - ))) - data["imports"] = imports - - else if(PRG.export_menu) - data["export"] = 1 - var/export_tax = 0 - if(selected_beacon && selected_beacon.linked_controller) - export_tax = selected_beacon.linked_controller.export_tax - data["export_tax"] = export_tax - var/list/exports[0] - for(var/datum/beacon_export/x in selected_beacon.active_exports) - exports.Add(list(list( - "export_name" = x.name, - "export_cost" = x.get_cost(export_tax), - "export_ref" = any2ref(x), - ))) - data["exports"] = exports - else if(PRG.log_menu) - data["log"] = 1 - else if(PRG.selected_import) - switch(PRG.payment_type) - if(1) - data["personal_account_sel"] = 1 - if(2) - data["charge_stick_sel"] = 1 - if(3) - data["network_account_sel"] = 1 - - var/import_tax = 0 - if(selected_beacon && selected_beacon.linked_controller) - import_tax = selected_beacon.linked_controller.import_tax - - data["selected_import"] = PRG.selected_import.name - data["import_cost"] = PRG.selected_import.get_cost(import_tax) - data["import_desc"] = PRG.selected_import.desc - - var/datum/computer_file/data/account/A = PRG.computer.get_account() - if(A) - var/datum/money_account/child/network/money_account = A.money_account - if(money_account) - data["personal_account"] = money_account.account_name - data["personal_account_balance"] = money_account.money - else - data["personal_account_error"] = "This account has no valid bank account associated with it on this network. Check your login details or contact a system administrator." - - else - data["personal_account_error"] = "This account has no valid bank account associated with it on this network. Check your login details or contact a system administrator." - - var/obj/item/stock_parts/computer/charge_stick_slot/charge_slot = computer.get_component(PART_MSTICK) - if(!charge_slot || !charge_slot.is_functional()) - data["charge_stick_error"] = "No functional charge stick slot found!" - else if(!charge_slot.stored_stick) - data["charge_stick_error"] = "No charge stick inserted!" - else - data["charge_stick"] = "Charge Stick" - data["charge_stick_balance"] = charge_slot.stored_stick.loaded_worth - var/datum/computer_network/net = PRG.computer.get_network() - var/list/accesses = computer.get_access(user) - if(net && net.banking_mainframe) - if(!net.banking_mainframe.has_access(accesses)) - data["network_account_error"] = "You do not have access to the parent account on your current network." - else - var/datum/money_account/parent/network/bank_account = net.banking_mainframe.get_parent_account() - if(!bank_account) - data["network_account_error"] = "The network does not have a parent account created." - else - data["network_account"] = bank_account.account_name - data["network_account_balance"] = bank_account.money - else - data["network_account_error"] = "The network does not have a banking mainframe." - - - else if(PRG.selected_export) - switch(PRG.payment_type) - if(1) - data["personal_account_sel"] = 1 - if(2) - data["charge_stick_sel"] = 1 - if(3) - data["network_account_sel"] = 1 - - var/export_tax = 0 - if(selected_beacon && selected_beacon.linked_controller) - export_tax = selected_beacon.linked_controller.export_tax - - data["selected_export"] = PRG.selected_export.name - data["export_cost"] = PRG.selected_export.get_cost(export_tax) - data["export_desc"] = PRG.selected_export.desc - - var/datum/computer_file/data/account/A = PRG.computer.get_account() - if(A) - var/datum/money_account/child/network/money_account = A.money_account - if(money_account) - data["personal_account"] = money_account.account_name - data["personal_account_balance"] = money_account.money - else - data["personal_account_error"] = "No bank account." - - else - data["personal_account_error"] = "Not logged in." - - var/obj/item/stock_parts/computer/charge_stick_slot/charge_slot = computer.get_component(PART_MSTICK) - if(!charge_slot || !charge_slot.is_functional()) - data["personal_account_error"] = "Noslot found!" - else if(!charge_slot.stored_stick) - data["personal_account_error"] = "No charge stick!" - else - data["charge_stick"] = "Charge Stick" - data["charge_stick_balance"] = charge_slot.stored_stick.loaded_worth - var/datum/computer_network/net = PRG.computer.get_network() - var/list/accesses = computer.get_access(user) - if(net && net.banking_mainframe) - if(!net.banking_mainframe.has_access(accesses)) - data["network_account_error"] = "No access." - else - var/datum/money_account/parent/network/bank_account = net.banking_mainframe.get_parent_account() - if(!bank_account) - data["network_account_error"] = "No Network Account" - else - data["network_account"] = bank_account.account_name - data["network_account_balance"] = bank_account.money - else - data["network_account_error"] = "No Network Bank." - - - else - data["beacon_name"] = "*DISCONNECTED*" - - - ui = SSnano.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "trade_management.tmpl", name, 600, 750, state = state) - ui.auto_update_layout = 1 - ui.set_initial_data(data) - ui.set_auto_update(1) - ui.open() - -/datum/computer_file/program/trade_management/Topic(href, href_list, state) - . = ..() - if(.) - return - - if(href_list["select_beacon"]) - var/obj/hold = computer.get_physical_host() - var/list/possible_trade_beacons = hold.get_adjacent_trade_beacons() - possible_trade_beacons += "*DISCONNECT*" - var/beacon = input(usr, "Select a nearby trade beacon.", "Pick a beacon") as null|anything in possible_trade_beacons - if(!CanInteract(usr, global.default_topic_state)) - return TOPIC_REFRESH - if(beacon == "*DISCONNECT*") - selected_beacon = null - else if(beacon) - selected_beacon = beacon - - return TOPIC_REFRESH - if(href_list["import"]) - import_menu = 1 - export_menu = 0 - log_menu = 0 - selected_import = null - selected_export = null - return TOPIC_REFRESH - if(href_list["export"]) - import_menu = 0 - export_menu = 1 - log_menu = 0 - selected_import = null - selected_export = null - return TOPIC_REFRESH - if(href_list["log"]) - import_menu = 0 - export_menu = 0 - log_menu = 1 - selected_import = null - selected_export = null - return TOPIC_REFRESH - if(href_list["select_import"]) - import_menu = 0 - export_menu = 0 - log_menu = 0 - selected_import = locate(href_list["select_import"]) - selected_export = null - return TOPIC_REFRESH - if(href_list["select_export"]) - import_menu = 0 - export_menu = 0 - log_menu = 0 - selected_import = null - selected_export = locate(href_list["select_export"]) - return TOPIC_REFRESH - if(href_list["select_personal_account"]) - payment_type = 1 - return TOPIC_REFRESH - if(href_list["select_charge_stick"]) - payment_type = 2 - return TOPIC_REFRESH - if(href_list["select_network_account"]) - payment_type = 3 - return TOPIC_REFRESH - if(href_list["select_telepad"]) - detect_telepads() - var/obj/T = locate(href_list["select_telepad"]) - if(T && T in detected_telepads) - selected_telepad = T - return TOPIC_REFRESH - if(href_list["refresh_telepad"]) - detect_telepads() - return TOPIC_REFRESH - if(href_list["buy_import"]) - var/import_tax = 0 - if(!selected_import || !selected_beacon) - return - if(!(selected_import in selected_beacon.active_imports)) - selected_import = null - return - if(!selected_telepad) - to_chat(usr, SPAN_WARNING("You must select a telepad to send the import to.")) - return TOPIC_REFRESH - if(selected_beacon && selected_beacon.linked_controller) - import_tax = selected_beacon.linked_controller.import_tax - var/cost = selected_import.get_cost(import_tax) - var/tax_portion = selected_import.get_tax(import_tax) - switch(payment_type) - if(1) - var/datum/computer_file/data/account/A = computer.get_account() - if(A) - - var/oerr = checkImport() - if(oerr) - to_chat(usr, SPAN_WARNING("Import purchase failed: [oerr]")) - return TOPIC_HANDLED - var/datum/money_account/child/network/money_account = A.money_account - if(money_account) - var/terr = money_account.can_afford(cost, selected_beacon.beacon_account) - if(terr) - to_chat(usr, SPAN_WARNING("Import purchase failed: [terr]")) - return TOPIC_HANDLED - var/final_cost = cost-tax_portion - var/err = money_account.transfer(selected_beacon.beacon_account, final_cost, "Import Purchase ([selected_import.name] from [selected_beacon.name])") - if(err) - to_chat(usr, SPAN_WARNING("Import purchase failed: [err].")) - return TOPIC_HANDLED - else - if(tax_portion) - var/datum/computer_network/network = selected_beacon.linked_controller.get_network() - if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) - err = money_account.transfer(network.banking_mainframe.get_parent_account(), tax_portion, "Import Purchase Tax ([selected_import.name] from [selected_beacon.name])") - if(err) - selected_beacon.beacon_account.transfer(money_account, final_cost, "Refunded Import Purchase ([selected_import.name] from [selected_beacon.name])") - else - spawnImport() - else - spawnImport() - else - to_chat(usr, SPAN_WARNING("No banking account associated with this network. Contact your system administrator..")) - else - to_chat(usr, SPAN_WARNING("You must login to a valid account on your network to pay digitally.")) - if(2) - var/obj/item/stock_parts/computer/charge_stick_slot/charge_slot = computer.get_component(PART_MSTICK) - if(!charge_slot || !charge_slot.stored_stick) - to_chat(usr, SPAN_WARNING("No charge stick is inserted into the computer.")) - return TOPIC_REFRESH - var/obj/item/charge_stick/stick = charge_slot.stored_stick - if(cost > stick.loaded_worth) - to_chat(usr, SPAN_WARNING("The loaded charge stick does not have enough credits stored!")) - return TOPIC_HANDLED - var/oerr = checkImport() - if(oerr) - to_chat(usr, SPAN_WARNING("Import purchase failed: [oerr]")) - return TOPIC_HANDLED - stick.adjust_worth(-(cost)) - if(tax_portion) - var/datum/computer_network/network = selected_beacon.linked_controller.get_network() - if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) - var/datum/money_account/child/network/money_account = network.banking_mainframe.get_parent_account() - money_account.deposit(tax_portion, "Import Purchase Tax ([selected_import.name] from [selected_beacon.name])") - spawnImport() - if(3) - var/datum/computer_network/net = computer.get_network() - var/list/accesses = computer.get_access(usr) - if(net && net.banking_mainframe) - if(!net.banking_mainframe.has_access(accesses)) - to_chat(usr, SPAN_WARNING("You do not have access to the parent account on your current network.")) - return TOPIC_REFRESH - else - var/datum/money_account/parent/network/money_account = net.banking_mainframe.get_parent_account() - if(money_account) - var/terr = money_account.can_afford(cost, selected_beacon.beacon_account) - if(terr) - to_chat(usr, SPAN_WARNING("Import purchase failed: [terr]")) - return TOPIC_HANDLED - var/oerr = checkImport() - if(oerr) - to_chat(usr, SPAN_WARNING("Import purchase failed: [oerr]")) - return TOPIC_HANDLED - if(tax_portion) - var/datum/computer_network/network = selected_beacon.linked_controller.get_network() - if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) - if(network.banking_mainframe.get_parent_account() == money_account) // dont pay tax from the account into the same account - tax_portion = 0 - cost = selected_import.get_cost(0) - else // remove tax if we cant find a parent account to pay it to. - tax_portion = 0 - cost = selected_import.get_cost(0) - if(money_account.money < cost) - to_chat(usr, SPAN_WARNING("Import purchase failed: Insufficent funds.")) - return TOPIC_HANDLED - var/final_cost = cost-tax_portion - var/err = money_account.transfer(selected_beacon.beacon_account, final_cost, "Import Purchase ([selected_import.name] from [selected_beacon.name])") - if(err) - to_chat(usr, SPAN_WARNING("Import purchase failed: [err].")) - return TOPIC_HANDLED - else - if(tax_portion) - var/datum/computer_network/network = selected_beacon.linked_controller.get_network() - if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) - err = money_account.transfer(network.banking_mainframe.get_parent_account(), tax_portion, "Import Purchase Tax ([selected_import.name] from [selected_beacon.name])") - if(err) - selected_beacon.beacon_account.transfer(money_account, final_cost, "Refunded Import Purchase ([selected_import.name] from [selected_beacon.name])") - else - spawnImport() - else - spawnImport() - else - to_chat(usr, SPAN_WARNING("The network does not have a central account.")) - return TOPIC_REFRESH - return TOPIC_REFRESH - if(href_list["buy_export"]) - var/export_tax = 0 - if(!selected_export || !selected_beacon) - return TOPIC_REFRESH - if(!(selected_export in selected_beacon.active_exports)) - selected_export = null - return - if(!selected_telepad) - to_chat(usr, SPAN_WARNING("You must select a telepad to send the export to.")) - return TOPIC_REFRESH - if(selected_beacon && selected_beacon.linked_controller) - export_tax = selected_beacon.linked_controller.export_tax - var/cost = selected_export.get_cost(export_tax) - var/tax_portion = selected_export.get_tax(export_tax) - switch(payment_type) - if(1) - var/datum/computer_file/data/account/A = computer.get_account() - if(A) - var/datum/money_account/child/network/money_account = A.money_account - if(money_account) - var/e_err = checkExport() - if(e_err) - to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) - resetExport() - return TOPIC_HANDLED - var/err = money_account.deposit(cost, "Export ([selected_export.name] from [selected_beacon.name])") - if(err) - to_chat(usr, SPAN_WARNING("Export failed: [err].")) - resetExport() - return TOPIC_HANDLED - else - - if(tax_portion) // SUCCESS - var/datum/computer_network/network = selected_beacon.linked_controller.get_network() - if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) - var/datum/money_account/acc = network.banking_mainframe.get_parent_account() - err = acc.deposit(tax_portion, "Export Tax ([selected_export.name] from [selected_beacon.name])") - var/result = takeExport() - if(result) - to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) - else - to_chat(usr, SPAN_WARNING("No banking account associated with this network. Contact your system administrator.")) - return TOPIC_REFRESH - else - to_chat(usr, SPAN_WARNING("You must login to a valid account on your network to pay digitally.")) - return TOPIC_REFRESH - if(2) - var/obj/item/stock_parts/computer/charge_stick_slot/charge_slot = computer.get_component(PART_MSTICK) - if(!charge_slot || !charge_slot.stored_stick) - to_chat(usr, SPAN_WARNING("No charge stick is inserted into the computer.")) - return TOPIC_REFRESH - var/obj/item/charge_stick/stick = charge_slot.stored_stick - var/e_err = checkExport() - if(e_err) - to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) - resetExport() - return TOPIC_HANDLED - stick.adjust_worth(cost) - if(tax_portion) - var/datum/computer_network/network = selected_beacon.linked_controller.get_network() - if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) - var/datum/money_account/acc = network.banking_mainframe.get_parent_account() - acc.deposit(tax_portion, "Export Tax ([selected_export.name] from [selected_beacon.name])") - var/result = takeExport() - if(result) - to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) - if(3) - var/datum/computer_network/net = computer.get_network() - var/list/accesses = computer.get_access(usr) - if(net && net.banking_mainframe) - if(!net.banking_mainframe.has_access(accesses)) - to_chat(usr, SPAN_WARNING("You do not have access to the parent account on your current network.")) - return TOPIC_REFRESH - else - var/datum/money_account/parent/network/money_account = net.banking_mainframe.get_parent_account() - if(money_account) - if(tax_portion) - var/datum/computer_network/network = selected_beacon.linked_controller.get_network() - if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) - if(network.banking_mainframe.get_parent_account() == money_account) // dont pay tax from the account into the same account - tax_portion = 0 - cost = selected_export.get_cost(0) - else // remove tax if we cant find a parent account to pay it to. - tax_portion = 0 - cost = selected_export.get_cost(0) - var/e_err = checkExport() - if(e_err) - to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) - resetExport() - return TOPIC_HANDLED - var/err = money_account.deposit(cost, "Export ([selected_export.name] to [selected_beacon.name])") - if(err) - to_chat(usr, SPAN_WARNING("Export failed: [err].")) - resetExport() - return TOPIC_HANDLED - - else // SUCCESS - if(tax_portion) - var/datum/computer_network/network = selected_beacon.linked_controller.get_network() - if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) - var/datum/money_account/acc = network.banking_mainframe.get_parent_account() - err = acc.deposit(tax_portion, "Export Tax ([selected_export.name] from [selected_beacon.name])") - var/result = takeExport() - if(result) - to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) - - else - to_chat(usr, SPAN_WARNING("The network does not have a central account.")) - return TOPIC_REFRESH - return TOPIC_REFRESH - -/obj/machinery/telepad_cargo - name = "cargo telepad" - desc = "A telepad used to recieve imports and send exports." - icon = 'icons/obj/machines/telepad.dmi' - icon_state = "pad-idle" - anchored = 1 - use_power = 1 - idle_power_usage = 20 - active_power_usage = 500 - var/telepad_id = 0 -/obj/machinery/telepad_cargo/New() - telepad_id = random_id(type,10000,99999) - -/obj/machinery/telepad_cargo/attackby(obj/item/O as obj, mob/user as mob, params) - if(IS_WRENCH(O)) - playsound(src, 'sound/items/Ratchet.ogg', 50, 1) - if(anchored) - anchored = 0 - to_chat(user, " The [src] can now be moved.") - else if(!anchored) - anchored = 1 - to_chat(user, " The [src] is now secured.") - if(IS_MULTITOOL(O)) - var/id = input(user, "Enter a new telepad ID", "Telepad ID") as text|null - id = sanitize(id) - if(CanInteract(user, DefaultTopicState()) && id) telepad_id = id - - return component_attackby(O, user) \ No newline at end of file From ac18716351506de160cddfdb4ba355506561af63 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 13:57:42 -0600 Subject: [PATCH 13/47] Delete tradebeacon.dm --- .../modules/overmap_trade/tradebeacon.dm | 256 ------------------ 1 file changed, 256 deletions(-) delete mode 100644 mods/persistence/modules/overmap_trade/tradebeacon.dm diff --git a/mods/persistence/modules/overmap_trade/tradebeacon.dm b/mods/persistence/modules/overmap_trade/tradebeacon.dm deleted file mode 100644 index 1f26f31938d..00000000000 --- a/mods/persistence/modules/overmap_trade/tradebeacon.dm +++ /dev/null @@ -1,256 +0,0 @@ -/datum/beacon_export - var/name = "Beacon Export" - var/price_per_unit = 0 - var/unit_per_purchase = 1 - var/unit_type - -/obj/machinery/trade_beacon - name = "trade beacon" - desc = "A large broadcasting array meant to control trade between the Outreach system and the wider galaxy." - icon = 'icons/obj/jukebox_new.dmi' - icon_state = "jukebox3-nopower" - anchored = 1 - density = 1 - power_channel = EQUIP - idle_power_usage = 0 - active_power_usage = 0 - clicksound = 'sound/machines/buttonbeep.ogg' - uncreated_component_parts = null - stat_immune = 0 - construct_state = /decl/machine_construction/default/panel_closed - var/list/imports = list() - var/list/exports = list() - var/list/category_names = list() - var/list/category_contents = list() - var/owner_name = "Owner Name" - var/lore = "A generic trade beacon not associated to any particular owner." - var/showing_contents_of_ref - var/list/contents_of_order = list() - var/screen = 1 - var/selected_category - var/list/exports_nano = list() - var/network_key - -/obj/machinery/trade_beacon/powered() - return 1 - -/obj/machinery/trade_beacon/power_change() - return - -/obj/machinery/trade_beacon/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1) - user.set_machine(src) - var/list/data = list() - data["title"] = name - var/decl/currency/cur = GET_DECL(global.using_map.default_currency) - data["currency"] = cur.name - - if(screen == 1) - get_category_contents() - data["categories"] = category_names - if(selected_category) - data["category"] = selected_category - data["possible_purchases"] = category_contents[selected_category] - if(showing_contents_of_ref) - data["showing_contents_of"] = showing_contents_of_ref - data["contents_of_order"] = contents_of_order - if(screen == 2) - get_exports_nano() - data["exports"] = exports_nano - - ui = SSnano.try_update_ui(user, src, ui_key, ui, data, force_open) - if (!ui) - ui = new(user, src, ui_key, "trade_beacon.tmpl", "Trade Beacon", 440, 600) - ui.set_initial_data(data) - ui.open() - -/obj/machinery/trade_beacon/Topic(href, href_list) - if(..()) - return 1 - - if(href_list["select_category"]) - clear_order_contents() - selected_category = href_list["select_category"] - return 1 - - if(href_list["show_contents"]) - generate_order_contents(href_list["show_contents"]) - - if(href_list["hide_contents"]) - clear_order_contents() - - if(href_list["change_tax"]) - // tax handling here - - if(href_list["set_screen"]) - clear_order_contents() - screen = text2num(href_list["set_screen"]) - return 1 - - // Items requiring cargo access go below this entry. Other items go above. - if(!check_access(access_cargo)) - return 1 - -/obj/machinery/trade_beacon/proc/clear_order_contents() - contents_of_order.Cut() - showing_contents_of_ref = null - - -/obj/machinery/trade_beacon/proc/generate_order_contents(var/order_ref) - var/decl/hierarchy/supply_pack/sp = locate(order_ref) in SSsupply.master_supply_list - if(!istype(sp)) - return FALSE - contents_of_order.Cut() - showing_contents_of_ref = order_ref - for(var/item_path in sp.contains) // Thanks to Lohikar for helping me with type paths - CarlenWhite - var/obj/item/stack/OB = item_path // Not always a stack, but will always have a name we can fetch. - var/name = initial(OB.name) - var/amount = sp.contains[item_path] || 1 // If it's just one item (has no number associated), fallback to 1. - if(ispath(item_path, /obj/item/stack)) // And if it is a stack, consider the amount - amount *= initial(OB.amount) - - - contents_of_order.Add(list(list( - "name" = name, - "amount" = amount - ))) - - if(sp.contains.len == 0) // Handles the case where sp.contains is empty, e.g. for livecargo - contents_of_order.Add(list(list( - "name" = sp.containername, - "amount" = 1 - ))) - - return TRUE - - -/obj/machinery/trade_beacon/proc/get_category_contents() - if(!category_contents || !category_contents.len) - generate_categories() - return category_contents - - -/obj/machinery/trade_beacon/proc/get_exports_nano() - if(!exports_nano || !exports_nano.len) - generate_exports_list() - return exports_nano - - -/obj/machinery/trade_beacon/proc/generate_categories() - category_names.Cut() - category_contents.Cut() - var/decl/hierarchy/supply_pack/root = GET_DECL(/decl/hierarchy/supply_pack) - var/decl/currency/cur = GET_DECL(global.using_map.default_currency) - for(var/decl/hierarchy/supply_pack/sp in root.children) - var/found = 0 - if(!sp.is_category()) - continue // No children - var/list/category[0] - for(var/decl/hierarchy/supply_pack/spc in sp.get_descendents()) - if((spc.hidden || !(spc.type in imports))) - continue - category.Add(list(list( - "name" = spc.name, - "cost" = cur.format_value(spc.cost), - "ref" = "\ref[spc]" - ))) - found = 1 - if(found) - category_names.Add(sp.name) - category_contents[sp.name] = category - - -/obj/machinery/trade_beacon/proc/generate_exports_list() - exports_nano.Cut() - var/decl/currency/cur = GET_DECL(global.using_map.default_currency) - for(var/datum/beacon_export/export in exports) - category.Add(list(list( - "name" = export.name, - "cost" = cur.format_value(spc.price_per_unit), - ))) - - -/obj/machinery/trade_beacon/Outreach - owner_name = "Nanotrasen" - lore = "Nanotrasen go brrrrrrrrrrrr" - imports = list( - /decl/hierarchy/supply_pack/materials/steel50, - /decl/hierarchy/supply_pack/materials/alum50, - /decl/hierarchy/supply_pack/materials/glass50, - /decl/hierarchy/supply_pack/materials/fiberglass50, - /decl/hierarchy/supply_pack/materials/plastic50, - /decl/hierarchy/supply_pack/materials/marble50, - /decl/hierarchy/supply_pack/materials/plasteel50, - /decl/hierarchy/supply_pack/materials/copper50, - /decl/hierarchy/supply_pack/materials/titanium50, - /decl/hierarchy/supply_pack/materials/ocp50, - /decl/hierarchy/supply_pack/materials/graphite50, - /decl/hierarchy/supply_pack/materials/gold10, - /decl/hierarchy/supply_pack/materials/silver10, - /decl/hierarchy/supply_pack/materials/uranium10, - /decl/hierarchy/supply_pack/materials/diamond10, - /decl/hierarchy/supply_pack/materials/wood50, - /decl/hierarchy/supply_pack/materials/mahogany25, - /decl/hierarchy/supply_pack/materials/maple50, - /decl/hierarchy/supply_pack/materials/walnut25, - /decl/hierarchy/supply_pack/materials/ebony25, - /decl/hierarchy/supply_pack/materials/yew25, - - /decl/hierarchy/supply_pack/supply/toner, - /decl/hierarchy/supply_pack/supply/cardboard_sheets, - /decl/hierarchy/supply_pack/supply/stickies, - /decl/hierarchy/supply_pack/supply/wpaper, - /decl/hierarchy/supply_pack/supply/tapes, - /decl/hierarchy/supply_pack/supply/taperolls, - /decl/hierarchy/supply_pack/supply/bogrolls, - - /decl/hierarchy/supply_pack/engineering/electrical, - /decl/hierarchy/supply_pack/engineering/mechanical, - /decl/hierarchy/supply_pack/engineering/pacman_parts, - /decl/hierarchy/supply_pack/engineering/voidsuit_engineering, - - /decl/hierarchy/supply_pack/flooring/carpetbrown, - /decl/hierarchy/supply_pack/flooring/white_tiles, - /decl/hierarchy/supply_pack/flooring/dark_tiles, - - /decl/hierarchy/supply_pack/medical/medical, - /decl/hierarchy/supply_pack/medical/atk, - /decl/hierarchy/supply_pack/medical/abk, - /decl/hierarchy/supply_pack/medical/trauma, - /decl/hierarchy/supply_pack/medical/bodybag, - /decl/hierarchy/supply_pack/medical/stretcher, - /decl/hierarchy/supply_pack/medical/wheelchair, - /decl/hierarchy/supply_pack/medical/rescuebag, - /decl/hierarchy/supply_pack/medical/doctorgear, - /decl/hierarchy/supply_pack/medical/autopsy, - /decl/hierarchy/supply_pack/medical/surgery, - /decl/hierarchy/supply_pack/medical/sterile, - /decl/hierarchy/supply_pack/medical/scanner_module, - /decl/hierarchy/supply_pack/medical/defib, - /decl/hierarchy/supply_pack/medical/autocomp, - - /decl/hierarchy/supply_pack/galley/food, - /decl/hierarchy/supply_pack/galley/beef, - /decl/hierarchy/supply_pack/galley/eggs, - /decl/hierarchy/supply_pack/galley/milk, - /decl/hierarchy/supply_pack/galley/pizza, - /decl/hierarchy/supply_pack/galley/barsupplies, - /decl/hierarchy/supply_pack/galley/party, - /decl/hierarchy/supply_pack/galley/beer_dispenser, - /decl/hierarchy/supply_pack/galley/soda_dispenser, - - /decl/hierarchy/supply_pack/operations/orebox, - /decl/hierarchy/supply_pack/operations/bureaucracy, - /decl/hierarchy/supply_pack/operations/voidsuit_engineering, - - /decl/hierarchy/supply_pack/nonessent/painters, - /decl/hierarchy/supply_pack/nonessent/artscrafts, - /decl/hierarchy/supply_pack/nonessent/card_packs, - /decl/hierarchy/supply_pack/nonessent/instruments, - /decl/hierarchy/supply_pack/nonessent/llamps, - /decl/hierarchy/supply_pack/nonessent/chaplaingear, - - /decl/hierarchy/supply_pack/custodial/janitor, - /decl/hierarchy/supply_pack/custodial/cleaning, - /decl/hierarchy/supply_pack/custodial/mousetrap, - /decl/hierarchy/supply_pack/custodial/janitorbiosuits - ) From 4e23eaad2e65ba9b065d49363200649dd546d0c6 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 14:00:21 -0600 Subject: [PATCH 14/47] Update _persistence.dme --- mods/persistence/_persistence.dme | 1 - 1 file changed, 1 deletion(-) diff --git a/mods/persistence/_persistence.dme b/mods/persistence/_persistence.dme index bed604cb04a..29e66102c8e 100644 --- a/mods/persistence/_persistence.dme +++ b/mods/persistence/_persistence.dme @@ -212,7 +212,6 @@ #include "modules\overmap\exoplanets\turfs.dm" #include "modules\overmap\internet\internet_uplink.dm" #include "modules\overmap\ships\landable.dm" -#include "modules\overmap_trade\tradebeacon.dm" #include "modules\paperwork\printer.dm" #include "modules\power\apc.dm" #include "modules\power\cable.dm" From 7dc1b2e76898e83feabcc657d20b73806d11dd58 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 14:03:01 -0600 Subject: [PATCH 15/47] Update trade_beacon_program.dm --- .../file_system/programs/trade_beacon_program.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/persistence/modules/modular_computers/file_system/programs/trade_beacon_program.dm b/mods/persistence/modules/modular_computers/file_system/programs/trade_beacon_program.dm index ac643350de1..63bccf26436 100644 --- a/mods/persistence/modules/modular_computers/file_system/programs/trade_beacon_program.dm +++ b/mods/persistence/modules/modular_computers/file_system/programs/trade_beacon_program.dm @@ -323,7 +323,7 @@ if(href_list["select_telepad"]) detect_telepads() var/obj/T = locate(href_list["select_telepad"]) - if(T && T in detected_telepads) + if(T && (T in detected_telepads)) selected_telepad = T return TOPIC_REFRESH if(href_list["refresh_telepad"]) From 7261a26b84dc54e2a88616a529db0dd6f2fbfe57 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 14:19:19 -0600 Subject: [PATCH 16/47] fix map units tests --- .../modules/economy}/cargo_telepads.dm | 0 .../hardware/trade_controller.dm | 89 +++++++++++++++++++ .../networking/machinery}/trade_controller.dm | 0 mods/persistence/_persistence.dme | 3 - nebula.dme | 3 + 5 files changed, 92 insertions(+), 3 deletions(-) rename {mods/persistence/modules/trade_beacons => code/modules/economy}/cargo_telepads.dm (100%) create mode 100644 code/modules/modular_computers/hardware/trade_controller.dm rename {mods/persistence/modules/modular_computers/networking => code/modules/modular_computers/networking/machinery}/trade_controller.dm (100%) diff --git a/mods/persistence/modules/trade_beacons/cargo_telepads.dm b/code/modules/economy/cargo_telepads.dm similarity index 100% rename from mods/persistence/modules/trade_beacons/cargo_telepads.dm rename to code/modules/economy/cargo_telepads.dm diff --git a/code/modules/modular_computers/hardware/trade_controller.dm b/code/modules/modular_computers/hardware/trade_controller.dm new file mode 100644 index 00000000000..01263743057 --- /dev/null +++ b/code/modules/modular_computers/hardware/trade_controller.dm @@ -0,0 +1,89 @@ +/datum/extension/network_device/trade_controller + var/obj/effect/overmap/trade_beacon/linked_beacon + var/import_tax = 0 + var/export_tax = 0 + var/beacon_restrict = 0 // Restriction to ALL beacon functions, import/export/log. 0 = no restricton, 1 = restricted to the network + var/log_restrict = 0 // Restriction of the transaction log. 0 = no restricton, 1 = restricted to the network + var/access = 0 // Which access will allow for general beacon functions + var/log_access = 0 // which access will allow for viewing the transaction log + +/datum/extension/network_device/trade_controller/proc/Unlink() + if(linked_beacon) + linked_beacon.linked_controller = null + linked_beacon = null +/datum/extension/network_device/trade_controller/Destroy() + Unlink() + . = ..() + +/datum/extension/network_device/trade_controller/disconnect(net_down) + Unlink() + . = ..() + +/datum/extension/network_device/trade_controller/proc/toggle_beacon_restrict() + if(!linked_beacon) + beacon_restrict = 0 + return + beacon_restrict = !beacon_restrict + var/datum/computer_network/network = get_network() + if(network.trade_controller == src) + network.add_log("Trade Control Device toggled beacon restriction for [linked_beacon.name].", network_tag) + return 1 + + +/datum/extension/network_device/trade_controller/proc/select_beacon_access(var/mob/M, var/obj/machinery/network/trade_controller/machine) + var/list/access_choices = list() + var/datum/computer_network/network = get_network() + var/datum/extension/network_device/acl/D + if(network) + D = network.access_controller + if(!linked_beacon) + access = 0 + return + if(!D) + to_chat(M, SPAN_WARNING("Cannot restrict access! No access controller detected on network!")) + return + for(var/parent_group in D.group_dict) + access_choices |= parent_group + for(var/child_group in D.group_dict[parent_group]) + access_choices |= child_group + access_choices |= "*NONE*" + var/chosen = input(M, "Select an Access for the Trade Beacon.", "Beacon Access Selection") as null|anything in access_choices + if(chosen && (!machine || machine.CanUseTopic(M))) + if(chosen == "*NONE*") + access = 0 + network.add_log("Trade Control Device unset beacon access for [linked_beacon.name].", network_tag) + else + access = chosen + network.add_log("Trade Control Device set beacon access to [chosen] for [linked_beacon.name].", network_tag) + return 1 +/datum/extension/network_device/trade_controller/proc/select_import_tax(var/mob/M, var/obj/machinery/network/trade_controller/machine) + var/datum/computer_network/network = get_network() + if(!linked_beacon) + import_tax = 0 + return + var/chosen_tax = input(M, "Enter the import tax% to charge for this beacon. (30% MAX)", "Import Tax") as num|null + if(!machine || machine.CanUseTopic(M)) + import_tax = clamp(chosen_tax, 0, 30) + network.add_log("Trade Control Device changed the import tax rate to [import_tax] for [linked_beacon.name].", network_tag) + return 1 + +/datum/extension/network_device/trade_controller/proc/select_export_tax(var/mob/M, var/obj/machinery/network/trade_controller/machine) + var/datum/computer_network/network = get_network() + if(!linked_beacon) + export_tax = 0 + return + var/chosen_tax = input(M, "Enter the export tax% to charge for this beacon. (30% MAX)", "Export Tax") as num|null + if(!machine || machine.CanUseTopic(M)) + export_tax = clamp(chosen_tax, 0, 30) + network.add_log("Trade Control Device changed the export tax rate to [export_tax] for [linked_beacon.name].", network_tag) + return 1 + +/datum/extension/network_device/trade_controller/proc/toggle_log_restrict() + if(!linked_beacon) + log_restrict = 0 + return + log_restrict = !log_restrict + var/datum/computer_network/network = get_network() + if(network.trade_controller == src) + network.add_log("Trade Control Device toggled transaction log restriction for [linked_beacon.name].", network_tag) + return 1 \ No newline at end of file diff --git a/mods/persistence/modules/modular_computers/networking/trade_controller.dm b/code/modules/modular_computers/networking/machinery/trade_controller.dm similarity index 100% rename from mods/persistence/modules/modular_computers/networking/trade_controller.dm rename to code/modules/modular_computers/networking/machinery/trade_controller.dm diff --git a/mods/persistence/_persistence.dme b/mods/persistence/_persistence.dme index 29e66102c8e..4e4d1c923b0 100644 --- a/mods/persistence/_persistence.dme +++ b/mods/persistence/_persistence.dme @@ -178,10 +178,8 @@ #include "modules\modular_computers\file_system\reports\crew_record.dm" #include "modules\modular_computers\file_system\reports\report.dm" #include "modules\modular_computers\hardware\battery_module.dm" -#include "modules\modular_computers\hardware\trade_controller.dm" #include "modules\modular_computers\networking\_network.dm" #include "modules\modular_computers\networking\network_cable.dm" -#include "modules\modular_computers\networking\trade_controller.dm" #include "modules\modular_computers\networking\accounts\account.dm" #include "modules\modular_computers\networking\accounts\email_message.dm" #include "modules\modular_computers\networking\device_types\_network_device.dm" @@ -258,7 +256,6 @@ #include "modules\shuttles\shuttle.dm" #include "modules\surgery\__surgery_setup.dm" #include "modules\surgery\_surgery.dm" -#include "modules\trade_beacons\cargo_telepads.dm" #include "modules\trade_beacons\exports.dm" #include "modules\trade_beacons\imports.dm" #include "modules\trade_beacons\trade_beacons.dm" diff --git a/nebula.dme b/nebula.dme index 44caf023f65..25b6f98f20e 100644 --- a/nebula.dme +++ b/nebula.dme @@ -1860,6 +1860,7 @@ #include "code\modules\detectivework\tools\sample_kits\fingerprinting.dm" #include "code\modules\detectivework\tools\sample_kits\swabs.dm" #include "code\modules\economy\_worth.dm" +#include "code\modules\economy\cargo_telepads.dm" #include "code\modules\economy\worth_ammo.dm" #include "code\modules\economy\worth_cash.dm" #include "code\modules\economy\worth_clothing.dm" @@ -2650,6 +2651,7 @@ #include "code\modules\modular_computers\hardware\portable_hard_drive.dm" #include "code\modules\modular_computers\hardware\processor_unit.dm" #include "code\modules\modular_computers\hardware\tesla_link.dm" +#include "code\modules\modular_computers\hardware\trade_controller.dm" #include "code\modules\modular_computers\hardware\scanners\scanner.dm" #include "code\modules\modular_computers\hardware\scanners\scanner_atmos.dm" #include "code\modules\modular_computers\hardware\scanners\scanner_medical.dm" @@ -2685,6 +2687,7 @@ #include "code\modules\modular_computers\networking\machinery\modem.dm" #include "code\modules\modular_computers\networking\machinery\relay.dm" #include "code\modules\modular_computers\networking\machinery\router.dm" +#include "code\modules\modular_computers\networking\machinery\trade_controller.dm" #include "code\modules\modular_computers\networking\machinery\wall_relay.dm" #include "code\modules\modular_computers\networking\machinery\wall_router.dm" #include "code\modules\modular_computers\networking\NTNRC\conversation.dm" From 0500438759e4e70a9748278e09e18e9eff369f62 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 15:02:31 -0600 Subject: [PATCH 17/47] Fix unit tests, all_trade_beacons list --- code/modules/economy/cargo_telepads.dm | 2 +- mods/persistence/controllers/subsystems/trade_beacons.dm | 2 ++ mods/persistence/modules/trade_beacons/trade_beacons.dm | 7 ++----- 3 files changed, 5 insertions(+), 6 deletions(-) diff --git a/code/modules/economy/cargo_telepads.dm b/code/modules/economy/cargo_telepads.dm index 82278b104d6..95b865bd8a6 100644 --- a/code/modules/economy/cargo_telepads.dm +++ b/code/modules/economy/cargo_telepads.dm @@ -8,7 +8,7 @@ idle_power_usage = 20 active_power_usage = 500 var/telepad_id = 0 -/obj/machinery/telepad_cargo/New() +/obj/machinery/telepad_cargo/Initialize() telepad_id = random_id(type,10000,99999) /obj/machinery/telepad_cargo/attackby(obj/item/O as obj, mob/user as mob, params) diff --git a/mods/persistence/controllers/subsystems/trade_beacons.dm b/mods/persistence/controllers/subsystems/trade_beacons.dm index cfe69deb731..b2e160e7792 100644 --- a/mods/persistence/controllers/subsystems/trade_beacons.dm +++ b/mods/persistence/controllers/subsystems/trade_beacons.dm @@ -7,8 +7,10 @@ SUBSYSTEM_DEF(trade_beacons) var/last_cycle = 0 /datum/controller/subsystem/trade_beacons/Initialize() + all_trade_beacons = list() for(var/x in wanted_trade_beacons) var/obj/effect/overmap/trade_beacon/beacon = new x() + all_trade_beacons |= beacon beacon.Initialize() . = ..() diff --git a/mods/persistence/modules/trade_beacons/trade_beacons.dm b/mods/persistence/modules/trade_beacons/trade_beacons.dm index f12f6adade5..2bdb21a46a3 100644 --- a/mods/persistence/modules/trade_beacons/trade_beacons.dm +++ b/mods/persistence/modules/trade_beacons/trade_beacons.dm @@ -48,13 +48,10 @@ forceMove(location) - -/obj/effect/overmap/trade_beacon/New() - beacon_account = new() - beacon_account.account_name = name - /obj/effect/overmap/trade_beacon/Initialize() ..() + beacon_account = new() + beacon_account.account_name = name move_to_starting_location() regenerate_imports() regenerate_exports() From f500804ca5cc5d91e461995a1ccca9d259dfa6a8 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 15:14:00 -0600 Subject: [PATCH 18/47] fix unit tests --- code/modules/economy/cargo_telepads.dm | 1 + nebula.dme | 3 +++ 2 files changed, 4 insertions(+) diff --git a/code/modules/economy/cargo_telepads.dm b/code/modules/economy/cargo_telepads.dm index 95b865bd8a6..c0e8c3e7542 100644 --- a/code/modules/economy/cargo_telepads.dm +++ b/code/modules/economy/cargo_telepads.dm @@ -10,6 +10,7 @@ var/telepad_id = 0 /obj/machinery/telepad_cargo/Initialize() telepad_id = random_id(type,10000,99999) + ..() /obj/machinery/telepad_cargo/attackby(obj/item/O as obj, mob/user as mob, params) if(IS_WRENCH(O)) diff --git a/nebula.dme b/nebula.dme index 25b6f98f20e..9fe823fb3d0 100644 --- a/nebula.dme +++ b/nebula.dme @@ -3554,5 +3554,8 @@ #include "maps\~mapsystem\maps_unit_testing.dm" #include "maps\~unit_tests\unit_testing.dm" #include "mods\_modpack.dm" +#include "mods\persistence\modules\trade_beacons\exports.dm" +#include "mods\persistence\modules\trade_beacons\imports.dm" +#include "mods\persistence\modules\trade_beacons\trade_beacons.dm" #include "~code\global_init.dm" // END_INCLUDE From b8a8350868cfc88e196d8cfc6bb9cc0fadcf9f8b Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 15:17:28 -0600 Subject: [PATCH 19/47] Update _persistence.dme --- mods/persistence/_persistence.dme | 3 --- 1 file changed, 3 deletions(-) diff --git a/mods/persistence/_persistence.dme b/mods/persistence/_persistence.dme index 4e4d1c923b0..9f8eb37cac3 100644 --- a/mods/persistence/_persistence.dme +++ b/mods/persistence/_persistence.dme @@ -256,9 +256,6 @@ #include "modules\shuttles\shuttle.dm" #include "modules\surgery\__surgery_setup.dm" #include "modules\surgery\_surgery.dm" -#include "modules\trade_beacons\exports.dm" -#include "modules\trade_beacons\imports.dm" -#include "modules\trade_beacons\trade_beacons.dm" #include "modules\world_save\_persistence.dm" #include "modules\world_save\load_cache.dm" #include "modules\world_save\saved_vars.dm" From 6085c60956fa2f2832b3846373847839c148a45b Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 15:21:04 -0600 Subject: [PATCH 20/47] Update network.dm --- .../objects/items/weapons/circuitboards/machinery/network.dm | 5 ----- 1 file changed, 5 deletions(-) diff --git a/code/game/objects/items/weapons/circuitboards/machinery/network.dm b/code/game/objects/items/weapons/circuitboards/machinery/network.dm index 66a3a63e3e1..93a2d0787d4 100644 --- a/code/game/objects/items/weapons/circuitboards/machinery/network.dm +++ b/code/game/objects/items/weapons/circuitboards/machinery/network.dm @@ -108,7 +108,6 @@ /obj/item/stock_parts/power/apc/buildable = 1 ) - /obj/item/stock_parts/circuitboard/trade_controller name = "circuitboard (trade control device)" build_path = /obj/machinery/network/trade_controller @@ -118,10 +117,6 @@ /obj/item/stock_parts/scanning_module = 2 ) - additional_spawn_components = list( - /obj/item/stock_parts/power/apc/buildable = 1 - ) - /obj/item/stock_parts/circuitboard/telepad name = "circuitboard (cargo telepad)" build_path = /obj/machinery/telepad_cargo From 9f21dda975b9748eac7cebaf402df360d5f80f96 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 15:23:59 -0600 Subject: [PATCH 21/47] Update cargo_telepads.dm --- code/modules/economy/cargo_telepads.dm | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) diff --git a/code/modules/economy/cargo_telepads.dm b/code/modules/economy/cargo_telepads.dm index c0e8c3e7542..4f7cb8d931b 100644 --- a/code/modules/economy/cargo_telepads.dm +++ b/code/modules/economy/cargo_telepads.dm @@ -8,19 +8,12 @@ idle_power_usage = 20 active_power_usage = 500 var/telepad_id = 0 + obj_flags = OBJ_FLAG_ANCHORABLE /obj/machinery/telepad_cargo/Initialize() telepad_id = random_id(type,10000,99999) ..() /obj/machinery/telepad_cargo/attackby(obj/item/O as obj, mob/user as mob, params) - if(IS_WRENCH(O)) - playsound(src, 'sound/items/Ratchet.ogg', 50, 1) - if(anchored) - anchored = 0 - to_chat(user, " The [src] can now be moved.") - else if(!anchored) - anchored = 1 - to_chat(user, " The [src] is now secured.") if(IS_MULTITOOL(O)) var/id = input(user, "Enter a new telepad ID", "Telepad ID") as text|null id = sanitize(id) From 3c60d1b010051cb8559b40f51f9bb0b63ccfa396 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 15:28:30 -0600 Subject: [PATCH 22/47] Update cargo_telepads.dm --- code/modules/economy/cargo_telepads.dm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/code/modules/economy/cargo_telepads.dm b/code/modules/economy/cargo_telepads.dm index 4f7cb8d931b..3158b588933 100644 --- a/code/modules/economy/cargo_telepads.dm +++ b/code/modules/economy/cargo_telepads.dm @@ -19,4 +19,8 @@ id = sanitize(id) if(CanInteract(user, DefaultTopicState()) && id) telepad_id = id - return component_attackby(O, user) \ No newline at end of file + ..() + +/obj/machinery/telepad_cargo/examine(mob/user) + . = ..() + to_chat(user, "It has a telepad ID of [telepad_id].") \ No newline at end of file From 9f61421c56386a2e91a44cbb378bf960aff5467f Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 15:40:32 -0600 Subject: [PATCH 23/47] fix unit tests, improve readability --- mods/persistence/_persistence.dme | 1 - .../programs/trade_beacon_program.dm | 460 +++++++++--------- .../modules/trade_beacons/exports.dm | 1 + nebula.dme | 1 + 4 files changed, 235 insertions(+), 228 deletions(-) diff --git a/mods/persistence/_persistence.dme b/mods/persistence/_persistence.dme index 9f8eb37cac3..128a828b7f3 100644 --- a/mods/persistence/_persistence.dme +++ b/mods/persistence/_persistence.dme @@ -27,7 +27,6 @@ #include "controllers\subsystems\mining.dm" #include "controllers\subsystems\persistence.dm" #include "controllers\subsystems\skills.dm" -#include "controllers\subsystems\trade_beacons.dm" #include "controllers\subsystems\initialization\chargen.dm" #include "controllers\subsystems\initialization\fabrication.dm" #include "controllers\subsystems\processing\specifications.dm" diff --git a/mods/persistence/modules/modular_computers/file_system/programs/trade_beacon_program.dm b/mods/persistence/modules/modular_computers/file_system/programs/trade_beacon_program.dm index 63bccf26436..4420339e751 100644 --- a/mods/persistence/modules/modular_computers/file_system/programs/trade_beacon_program.dm +++ b/mods/persistence/modules/modular_computers/file_system/programs/trade_beacon_program.dm @@ -66,6 +66,237 @@ /datum/computer_file/program/trade_management/proc/resetExport() return selected_export.resetExport() +/datum/computer_file/program/trade_management/proc/buyImport() + var/import_tax = 0 + if(!selected_import || !selected_beacon) + return + if(!(selected_import in selected_beacon.active_imports)) + selected_import = null + return + if(!selected_telepad) + to_chat(usr, SPAN_WARNING("You must select a telepad to send the import to.")) + return TOPIC_REFRESH + if(selected_beacon && selected_beacon.linked_controller) + import_tax = selected_beacon.linked_controller.import_tax + var/cost = selected_import.get_cost(import_tax) + var/tax_portion = selected_import.get_tax(import_tax) + switch(payment_type) + if(1) + var/datum/computer_file/data/account/A = computer.get_account() + if(A) + + var/oerr = checkImport() + if(oerr) + to_chat(usr, SPAN_WARNING("Import purchase failed: [oerr]")) + return TOPIC_HANDLED + var/datum/money_account/child/network/money_account = A.money_account + if(money_account) + var/terr = money_account.can_afford(cost, selected_beacon.beacon_account) + if(terr) + to_chat(usr, SPAN_WARNING("Import purchase failed: [terr]")) + return TOPIC_HANDLED + var/final_cost = cost-tax_portion + var/err = money_account.transfer(selected_beacon.beacon_account, final_cost, "Import Purchase ([selected_import.name] from [selected_beacon.name])") + if(err) + to_chat(usr, SPAN_WARNING("Import purchase failed: [err].")) + return TOPIC_HANDLED + else + if(tax_portion) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + err = money_account.transfer(network.banking_mainframe.get_parent_account(), tax_portion, "Import Purchase Tax ([selected_import.name] from [selected_beacon.name])") + if(err) + selected_beacon.beacon_account.transfer(money_account, final_cost, "Refunded Import Purchase ([selected_import.name] from [selected_beacon.name])") + else + spawnImport() + else + spawnImport() + else + to_chat(usr, SPAN_WARNING("No banking account associated with this network. Contact your system administrator..")) + else + to_chat(usr, SPAN_WARNING("You must login to a valid account on your network to pay digitally.")) + if(2) + var/obj/item/stock_parts/computer/charge_stick_slot/charge_slot = computer.get_component(PART_MSTICK) + if(!charge_slot || !charge_slot.stored_stick) + to_chat(usr, SPAN_WARNING("No charge stick is inserted into the computer.")) + return TOPIC_REFRESH + var/obj/item/charge_stick/stick = charge_slot.stored_stick + if(cost > stick.loaded_worth) + to_chat(usr, SPAN_WARNING("The loaded charge stick does not have enough credits stored!")) + return TOPIC_HANDLED + var/oerr = checkImport() + if(oerr) + to_chat(usr, SPAN_WARNING("Import purchase failed: [oerr]")) + return TOPIC_HANDLED + stick.adjust_worth(-(cost)) + if(tax_portion) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + var/datum/money_account/child/network/money_account = network.banking_mainframe.get_parent_account() + money_account.deposit(tax_portion, "Import Purchase Tax ([selected_import.name] from [selected_beacon.name])") + spawnImport() + if(3) + var/datum/computer_network/net = computer.get_network() + var/list/accesses = computer.get_access(usr) + if(net && net.banking_mainframe) + if(!net.banking_mainframe.has_access(accesses)) + to_chat(usr, SPAN_WARNING("You do not have access to the parent account on your current network.")) + return TOPIC_REFRESH + else + var/datum/money_account/parent/network/money_account = net.banking_mainframe.get_parent_account() + if(money_account) + var/terr = money_account.can_afford(cost, selected_beacon.beacon_account) + if(terr) + to_chat(usr, SPAN_WARNING("Import purchase failed: [terr]")) + return TOPIC_HANDLED + var/oerr = checkImport() + if(oerr) + to_chat(usr, SPAN_WARNING("Import purchase failed: [oerr]")) + return TOPIC_HANDLED + if(tax_portion) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + if(network.banking_mainframe.get_parent_account() == money_account) // dont pay tax from the account into the same account + tax_portion = 0 + cost = selected_import.get_cost(0) + else // remove tax if we cant find a parent account to pay it to. + tax_portion = 0 + cost = selected_import.get_cost(0) + if(money_account.money < cost) + to_chat(usr, SPAN_WARNING("Import purchase failed: Insufficent funds.")) + return TOPIC_HANDLED + var/final_cost = cost-tax_portion + var/err = money_account.transfer(selected_beacon.beacon_account, final_cost, "Import Purchase ([selected_import.name] from [selected_beacon.name])") + if(err) + to_chat(usr, SPAN_WARNING("Import purchase failed: [err].")) + return TOPIC_HANDLED + else + if(tax_portion) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + err = money_account.transfer(network.banking_mainframe.get_parent_account(), tax_portion, "Import Purchase Tax ([selected_import.name] from [selected_beacon.name])") + if(err) + selected_beacon.beacon_account.transfer(money_account, final_cost, "Refunded Import Purchase ([selected_import.name] from [selected_beacon.name])") + else + spawnImport() + else + spawnImport() + else + to_chat(usr, SPAN_WARNING("The network does not have a central account.")) + return TOPIC_REFRESH + return TOPIC_REFRESH + +/datum/computer_file/program/trade_management/proc/buyExport() + var/export_tax = 0 + if(!selected_export || !selected_beacon) + return TOPIC_REFRESH + if(!(selected_export in selected_beacon.active_exports)) + selected_export = null + return + if(!selected_telepad) + to_chat(usr, SPAN_WARNING("You must select a telepad to send the export to.")) + return TOPIC_REFRESH + if(selected_beacon && selected_beacon.linked_controller) + export_tax = selected_beacon.linked_controller.export_tax + var/cost = selected_export.get_cost(export_tax) + var/tax_portion = selected_export.get_tax(export_tax) + switch(payment_type) + if(1) + var/datum/computer_file/data/account/A = computer.get_account() + if(A) + var/datum/money_account/child/network/money_account = A.money_account + if(money_account) + var/e_err = checkExport() + if(e_err) + to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) + resetExport() + return TOPIC_HANDLED + var/err = money_account.deposit(cost, "Export ([selected_export.name] from [selected_beacon.name])") + if(err) + to_chat(usr, SPAN_WARNING("Export failed: [err].")) + resetExport() + return TOPIC_HANDLED + else + + if(tax_portion) // SUCCESS + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + var/datum/money_account/acc = network.banking_mainframe.get_parent_account() + err = acc.deposit(tax_portion, "Export Tax ([selected_export.name] from [selected_beacon.name])") + var/result = takeExport() + if(result) + to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) + else + to_chat(usr, SPAN_WARNING("No banking account associated with this network. Contact your system administrator.")) + return TOPIC_REFRESH + else + to_chat(usr, SPAN_WARNING("You must login to a valid account on your network to pay digitally.")) + return TOPIC_REFRESH + if(2) + var/obj/item/stock_parts/computer/charge_stick_slot/charge_slot = computer.get_component(PART_MSTICK) + if(!charge_slot || !charge_slot.stored_stick) + to_chat(usr, SPAN_WARNING("No charge stick is inserted into the computer.")) + return TOPIC_REFRESH + var/obj/item/charge_stick/stick = charge_slot.stored_stick + var/e_err = checkExport() + if(e_err) + to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) + resetExport() + return TOPIC_HANDLED + stick.adjust_worth(cost) + if(tax_portion) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + var/datum/money_account/acc = network.banking_mainframe.get_parent_account() + acc.deposit(tax_portion, "Export Tax ([selected_export.name] from [selected_beacon.name])") + var/result = takeExport() + if(result) + to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) + if(3) + var/datum/computer_network/net = computer.get_network() + var/list/accesses = computer.get_access(usr) + if(net && net.banking_mainframe) + if(!net.banking_mainframe.has_access(accesses)) + to_chat(usr, SPAN_WARNING("You do not have access to the parent account on your current network.")) + return TOPIC_REFRESH + else + var/datum/money_account/parent/network/money_account = net.banking_mainframe.get_parent_account() + if(money_account) + if(tax_portion) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + if(network.banking_mainframe.get_parent_account() == money_account) // dont pay tax from the account into the same account + tax_portion = 0 + cost = selected_export.get_cost(0) + else // remove tax if we cant find a parent account to pay it to. + tax_portion = 0 + cost = selected_export.get_cost(0) + var/e_err = checkExport() + if(e_err) + to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) + resetExport() + return TOPIC_HANDLED + var/err = money_account.deposit(cost, "Export ([selected_export.name] to [selected_beacon.name])") + if(err) + to_chat(usr, SPAN_WARNING("Export failed: [err].")) + resetExport() + return TOPIC_HANDLED + + else // SUCCESS + if(tax_portion) + var/datum/computer_network/network = selected_beacon.linked_controller.get_network() + if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) + var/datum/money_account/acc = network.banking_mainframe.get_parent_account() + err = acc.deposit(tax_portion, "Export Tax ([selected_export.name] from [selected_beacon.name])") + var/result = takeExport() + if(result) + to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) + + else + to_chat(usr, SPAN_WARNING("The network does not have a central account.")) + return TOPIC_REFRESH + return TOPIC_REFRESH + /datum/nano_module/program/trade_management/ui_interact(mob/user, ui_key, datum/nanoui/ui, force_open, datum/nanoui/master_ui, datum/topic_state/state) var/list/data = host.initial_data() @@ -330,231 +561,6 @@ detect_telepads() return TOPIC_REFRESH if(href_list["buy_import"]) - var/import_tax = 0 - if(!selected_import || !selected_beacon) - return - if(!(selected_import in selected_beacon.active_imports)) - selected_import = null - return - if(!selected_telepad) - to_chat(usr, SPAN_WARNING("You must select a telepad to send the import to.")) - return TOPIC_REFRESH - if(selected_beacon && selected_beacon.linked_controller) - import_tax = selected_beacon.linked_controller.import_tax - var/cost = selected_import.get_cost(import_tax) - var/tax_portion = selected_import.get_tax(import_tax) - switch(payment_type) - if(1) - var/datum/computer_file/data/account/A = computer.get_account() - if(A) - - var/oerr = checkImport() - if(oerr) - to_chat(usr, SPAN_WARNING("Import purchase failed: [oerr]")) - return TOPIC_HANDLED - var/datum/money_account/child/network/money_account = A.money_account - if(money_account) - var/terr = money_account.can_afford(cost, selected_beacon.beacon_account) - if(terr) - to_chat(usr, SPAN_WARNING("Import purchase failed: [terr]")) - return TOPIC_HANDLED - var/final_cost = cost-tax_portion - var/err = money_account.transfer(selected_beacon.beacon_account, final_cost, "Import Purchase ([selected_import.name] from [selected_beacon.name])") - if(err) - to_chat(usr, SPAN_WARNING("Import purchase failed: [err].")) - return TOPIC_HANDLED - else - if(tax_portion) - var/datum/computer_network/network = selected_beacon.linked_controller.get_network() - if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) - err = money_account.transfer(network.banking_mainframe.get_parent_account(), tax_portion, "Import Purchase Tax ([selected_import.name] from [selected_beacon.name])") - if(err) - selected_beacon.beacon_account.transfer(money_account, final_cost, "Refunded Import Purchase ([selected_import.name] from [selected_beacon.name])") - else - spawnImport() - else - spawnImport() - else - to_chat(usr, SPAN_WARNING("No banking account associated with this network. Contact your system administrator..")) - else - to_chat(usr, SPAN_WARNING("You must login to a valid account on your network to pay digitally.")) - if(2) - var/obj/item/stock_parts/computer/charge_stick_slot/charge_slot = computer.get_component(PART_MSTICK) - if(!charge_slot || !charge_slot.stored_stick) - to_chat(usr, SPAN_WARNING("No charge stick is inserted into the computer.")) - return TOPIC_REFRESH - var/obj/item/charge_stick/stick = charge_slot.stored_stick - if(cost > stick.loaded_worth) - to_chat(usr, SPAN_WARNING("The loaded charge stick does not have enough credits stored!")) - return TOPIC_HANDLED - var/oerr = checkImport() - if(oerr) - to_chat(usr, SPAN_WARNING("Import purchase failed: [oerr]")) - return TOPIC_HANDLED - stick.adjust_worth(-(cost)) - if(tax_portion) - var/datum/computer_network/network = selected_beacon.linked_controller.get_network() - if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) - var/datum/money_account/child/network/money_account = network.banking_mainframe.get_parent_account() - money_account.deposit(tax_portion, "Import Purchase Tax ([selected_import.name] from [selected_beacon.name])") - spawnImport() - if(3) - var/datum/computer_network/net = computer.get_network() - var/list/accesses = computer.get_access(usr) - if(net && net.banking_mainframe) - if(!net.banking_mainframe.has_access(accesses)) - to_chat(usr, SPAN_WARNING("You do not have access to the parent account on your current network.")) - return TOPIC_REFRESH - else - var/datum/money_account/parent/network/money_account = net.banking_mainframe.get_parent_account() - if(money_account) - var/terr = money_account.can_afford(cost, selected_beacon.beacon_account) - if(terr) - to_chat(usr, SPAN_WARNING("Import purchase failed: [terr]")) - return TOPIC_HANDLED - var/oerr = checkImport() - if(oerr) - to_chat(usr, SPAN_WARNING("Import purchase failed: [oerr]")) - return TOPIC_HANDLED - if(tax_portion) - var/datum/computer_network/network = selected_beacon.linked_controller.get_network() - if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) - if(network.banking_mainframe.get_parent_account() == money_account) // dont pay tax from the account into the same account - tax_portion = 0 - cost = selected_import.get_cost(0) - else // remove tax if we cant find a parent account to pay it to. - tax_portion = 0 - cost = selected_import.get_cost(0) - if(money_account.money < cost) - to_chat(usr, SPAN_WARNING("Import purchase failed: Insufficent funds.")) - return TOPIC_HANDLED - var/final_cost = cost-tax_portion - var/err = money_account.transfer(selected_beacon.beacon_account, final_cost, "Import Purchase ([selected_import.name] from [selected_beacon.name])") - if(err) - to_chat(usr, SPAN_WARNING("Import purchase failed: [err].")) - return TOPIC_HANDLED - else - if(tax_portion) - var/datum/computer_network/network = selected_beacon.linked_controller.get_network() - if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) - err = money_account.transfer(network.banking_mainframe.get_parent_account(), tax_portion, "Import Purchase Tax ([selected_import.name] from [selected_beacon.name])") - if(err) - selected_beacon.beacon_account.transfer(money_account, final_cost, "Refunded Import Purchase ([selected_import.name] from [selected_beacon.name])") - else - spawnImport() - else - spawnImport() - else - to_chat(usr, SPAN_WARNING("The network does not have a central account.")) - return TOPIC_REFRESH - return TOPIC_REFRESH + return buyImport() if(href_list["buy_export"]) - var/export_tax = 0 - if(!selected_export || !selected_beacon) - return TOPIC_REFRESH - if(!(selected_export in selected_beacon.active_exports)) - selected_export = null - return - if(!selected_telepad) - to_chat(usr, SPAN_WARNING("You must select a telepad to send the export to.")) - return TOPIC_REFRESH - if(selected_beacon && selected_beacon.linked_controller) - export_tax = selected_beacon.linked_controller.export_tax - var/cost = selected_export.get_cost(export_tax) - var/tax_portion = selected_export.get_tax(export_tax) - switch(payment_type) - if(1) - var/datum/computer_file/data/account/A = computer.get_account() - if(A) - var/datum/money_account/child/network/money_account = A.money_account - if(money_account) - var/e_err = checkExport() - if(e_err) - to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) - resetExport() - return TOPIC_HANDLED - var/err = money_account.deposit(cost, "Export ([selected_export.name] from [selected_beacon.name])") - if(err) - to_chat(usr, SPAN_WARNING("Export failed: [err].")) - resetExport() - return TOPIC_HANDLED - else - - if(tax_portion) // SUCCESS - var/datum/computer_network/network = selected_beacon.linked_controller.get_network() - if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) - var/datum/money_account/acc = network.banking_mainframe.get_parent_account() - err = acc.deposit(tax_portion, "Export Tax ([selected_export.name] from [selected_beacon.name])") - var/result = takeExport() - if(result) - to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) - else - to_chat(usr, SPAN_WARNING("No banking account associated with this network. Contact your system administrator.")) - return TOPIC_REFRESH - else - to_chat(usr, SPAN_WARNING("You must login to a valid account on your network to pay digitally.")) - return TOPIC_REFRESH - if(2) - var/obj/item/stock_parts/computer/charge_stick_slot/charge_slot = computer.get_component(PART_MSTICK) - if(!charge_slot || !charge_slot.stored_stick) - to_chat(usr, SPAN_WARNING("No charge stick is inserted into the computer.")) - return TOPIC_REFRESH - var/obj/item/charge_stick/stick = charge_slot.stored_stick - var/e_err = checkExport() - if(e_err) - to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) - resetExport() - return TOPIC_HANDLED - stick.adjust_worth(cost) - if(tax_portion) - var/datum/computer_network/network = selected_beacon.linked_controller.get_network() - if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) - var/datum/money_account/acc = network.banking_mainframe.get_parent_account() - acc.deposit(tax_portion, "Export Tax ([selected_export.name] from [selected_beacon.name])") - var/result = takeExport() - if(result) - to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) - if(3) - var/datum/computer_network/net = computer.get_network() - var/list/accesses = computer.get_access(usr) - if(net && net.banking_mainframe) - if(!net.banking_mainframe.has_access(accesses)) - to_chat(usr, SPAN_WARNING("You do not have access to the parent account on your current network.")) - return TOPIC_REFRESH - else - var/datum/money_account/parent/network/money_account = net.banking_mainframe.get_parent_account() - if(money_account) - if(tax_portion) - var/datum/computer_network/network = selected_beacon.linked_controller.get_network() - if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) - if(network.banking_mainframe.get_parent_account() == money_account) // dont pay tax from the account into the same account - tax_portion = 0 - cost = selected_export.get_cost(0) - else // remove tax if we cant find a parent account to pay it to. - tax_portion = 0 - cost = selected_export.get_cost(0) - var/e_err = checkExport() - if(e_err) - to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) - resetExport() - return TOPIC_HANDLED - var/err = money_account.deposit(cost, "Export ([selected_export.name] to [selected_beacon.name])") - if(err) - to_chat(usr, SPAN_WARNING("Export failed: [err].")) - resetExport() - return TOPIC_HANDLED - - else // SUCCESS - if(tax_portion) - var/datum/computer_network/network = selected_beacon.linked_controller.get_network() - if(network && network.banking_mainframe && network.banking_mainframe.get_parent_account()) - var/datum/money_account/acc = network.banking_mainframe.get_parent_account() - err = acc.deposit(tax_portion, "Export Tax ([selected_export.name] from [selected_beacon.name])") - var/result = takeExport() - if(result) - to_chat(usr, SPAN_WARNING("Export failed: [e_err].")) - - else - to_chat(usr, SPAN_WARNING("The network does not have a central account.")) - return TOPIC_REFRESH - return TOPIC_REFRESH + return buyExport() diff --git a/mods/persistence/modules/trade_beacons/exports.dm b/mods/persistence/modules/trade_beacons/exports.dm index 4ebbe98cac5..7757cf2009e 100644 --- a/mods/persistence/modules/trade_beacons/exports.dm +++ b/mods/persistence/modules/trade_beacons/exports.dm @@ -23,6 +23,7 @@ /datum/beacon_export/proc/resetExport() checked_closet = null + /datum/beacon_export/proc/checkExport(var/turf/L) if(!L) return "No valid location detected" var/obj/closet_found = 0 diff --git a/nebula.dme b/nebula.dme index 9fe823fb3d0..99d4de4e068 100644 --- a/nebula.dme +++ b/nebula.dme @@ -3554,6 +3554,7 @@ #include "maps\~mapsystem\maps_unit_testing.dm" #include "maps\~unit_tests\unit_testing.dm" #include "mods\_modpack.dm" +#include "mods\persistence\controllers\subsystems\trade_beacons.dm" #include "mods\persistence\modules\trade_beacons\exports.dm" #include "mods\persistence\modules\trade_beacons\imports.dm" #include "mods\persistence\modules\trade_beacons\trade_beacons.dm" From 69bc0a2248def6d3277b7e5dbf170c5141a0fb40 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 15:44:52 -0600 Subject: [PATCH 24/47] include return on init --- mods/persistence/modules/trade_beacons/trade_beacons.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/persistence/modules/trade_beacons/trade_beacons.dm b/mods/persistence/modules/trade_beacons/trade_beacons.dm index 2bdb21a46a3..ef170a78669 100644 --- a/mods/persistence/modules/trade_beacons/trade_beacons.dm +++ b/mods/persistence/modules/trade_beacons/trade_beacons.dm @@ -49,7 +49,7 @@ /obj/effect/overmap/trade_beacon/Initialize() - ..() + . = ..() beacon_account = new() beacon_account.account_name = name move_to_starting_location() From b276e775b1aee2fbede03117e6e092361b22a99d Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 15:58:21 -0600 Subject: [PATCH 25/47] Update trade_beacons.dm --- mods/persistence/modules/trade_beacons/trade_beacons.dm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/mods/persistence/modules/trade_beacons/trade_beacons.dm b/mods/persistence/modules/trade_beacons/trade_beacons.dm index ef170a78669..efb39ecb518 100644 --- a/mods/persistence/modules/trade_beacons/trade_beacons.dm +++ b/mods/persistence/modules/trade_beacons/trade_beacons.dm @@ -29,7 +29,8 @@ /obj/effect/overmap/trade_beacon/proc/move_to_starting_location() var/datum/overmap/overmap = global.overmaps_by_name[overmap_id] var/location - + if(!overmap) + return if(start_x && start_y) location = locate(start_x, start_y, overmap.assigned_z) else From 66e5a60338644d979b9fe584a088b12c8edd1b4d Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 16:08:52 -0600 Subject: [PATCH 26/47] fix unit tests --- code/modules/economy/cargo_telepads.dm | 3 ++- mods/persistence/modules/trade_beacons/trade_beacons.dm | 4 +++- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/code/modules/economy/cargo_telepads.dm b/code/modules/economy/cargo_telepads.dm index 3158b588933..39607b9a24c 100644 --- a/code/modules/economy/cargo_telepads.dm +++ b/code/modules/economy/cargo_telepads.dm @@ -9,9 +9,10 @@ active_power_usage = 500 var/telepad_id = 0 obj_flags = OBJ_FLAG_ANCHORABLE + /obj/machinery/telepad_cargo/Initialize() telepad_id = random_id(type,10000,99999) - ..() + . = ..() /obj/machinery/telepad_cargo/attackby(obj/item/O as obj, mob/user as mob, params) if(IS_MULTITOOL(O)) diff --git a/mods/persistence/modules/trade_beacons/trade_beacons.dm b/mods/persistence/modules/trade_beacons/trade_beacons.dm index efb39ecb518..8d50f48e456 100644 --- a/mods/persistence/modules/trade_beacons/trade_beacons.dm +++ b/mods/persistence/modules/trade_beacons/trade_beacons.dm @@ -25,7 +25,9 @@ var/datum/money_account/beacon_account var/start_x = 0 var/start_y = 0 - +/obj/effect/overmap/trade_beacon/Destroy() + SStrade_beacons.all_trade_beacons.Remove(src) + . = ..() /obj/effect/overmap/trade_beacon/proc/move_to_starting_location() var/datum/overmap/overmap = global.overmaps_by_name[overmap_id] var/location From a4b2754e9ab691ac3274c4f7d67ee8685bfaf4e0 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 16:19:03 -0600 Subject: [PATCH 27/47] fix unit tests???? --- mods/persistence/modules/trade_beacons/trade_beacons.dm | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/mods/persistence/modules/trade_beacons/trade_beacons.dm b/mods/persistence/modules/trade_beacons/trade_beacons.dm index 8d50f48e456..1a1bc199331 100644 --- a/mods/persistence/modules/trade_beacons/trade_beacons.dm +++ b/mods/persistence/modules/trade_beacons/trade_beacons.dm @@ -25,8 +25,16 @@ var/datum/money_account/beacon_account var/start_x = 0 var/start_y = 0 + + /obj/effect/overmap/trade_beacon/Destroy() SStrade_beacons.all_trade_beacons.Remove(src) + QDEL_NULL(possible_imports) + QDEL_NULL(possible_exports) + QDEL_NULL(active_imports) + QDEL_NULL(active_exports) + linked_controller = null + QDEL_NULL(beacon_account) . = ..() /obj/effect/overmap/trade_beacon/proc/move_to_starting_location() var/datum/overmap/overmap = global.overmaps_by_name[overmap_id] From 8b9a391417cef618d77be0c91439045bf8ebc010 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 17:00:31 -0600 Subject: [PATCH 28/47] Update trade_beacons.dm --- mods/persistence/modules/trade_beacons/trade_beacons.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/persistence/modules/trade_beacons/trade_beacons.dm b/mods/persistence/modules/trade_beacons/trade_beacons.dm index 1a1bc199331..7761d03e53d 100644 --- a/mods/persistence/modules/trade_beacons/trade_beacons.dm +++ b/mods/persistence/modules/trade_beacons/trade_beacons.dm @@ -60,12 +60,12 @@ /obj/effect/overmap/trade_beacon/Initialize() - . = ..() beacon_account = new() beacon_account.account_name = name move_to_starting_location() regenerate_imports() regenerate_exports() + . = ..() /obj/effect/overmap/trade_beacon/proc/regenerate_imports() active_imports.Cut() From 3ea5d8f5eded4bb5f2e3fa46a4537e41da6ae341 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 17:18:29 -0600 Subject: [PATCH 29/47] Update trade_beacons.dm --- .../modules/trade_beacons/trade_beacons.dm | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/mods/persistence/modules/trade_beacons/trade_beacons.dm b/mods/persistence/modules/trade_beacons/trade_beacons.dm index 7761d03e53d..7ca3f96d903 100644 --- a/mods/persistence/modules/trade_beacons/trade_beacons.dm +++ b/mods/persistence/modules/trade_beacons/trade_beacons.dm @@ -29,11 +29,13 @@ /obj/effect/overmap/trade_beacon/Destroy() SStrade_beacons.all_trade_beacons.Remove(src) - QDEL_NULL(possible_imports) - QDEL_NULL(possible_exports) - QDEL_NULL(active_imports) - QDEL_NULL(active_exports) - linked_controller = null + QDEL_NULL_LIST(possible_imports) + QDEL_NULL_LIST(possible_exports) + QDEL_NULL_LIST(active_imports) + QDEL_NULL_LIST(active_exports) + if(linked_controller) + linked_controller.linked_beacon = null + linked_controller = null QDEL_NULL(beacon_account) . = ..() /obj/effect/overmap/trade_beacon/proc/move_to_starting_location() From 0d5da55e652831cc28070e9cb711eddc7aa2c7ef Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 17:37:26 -0600 Subject: [PATCH 30/47] Update trade_beacons.dm --- mods/persistence/modules/trade_beacons/trade_beacons.dm | 2 -- 1 file changed, 2 deletions(-) diff --git a/mods/persistence/modules/trade_beacons/trade_beacons.dm b/mods/persistence/modules/trade_beacons/trade_beacons.dm index 7ca3f96d903..0b7eb11d7ec 100644 --- a/mods/persistence/modules/trade_beacons/trade_beacons.dm +++ b/mods/persistence/modules/trade_beacons/trade_beacons.dm @@ -29,8 +29,6 @@ /obj/effect/overmap/trade_beacon/Destroy() SStrade_beacons.all_trade_beacons.Remove(src) - QDEL_NULL_LIST(possible_imports) - QDEL_NULL_LIST(possible_exports) QDEL_NULL_LIST(active_imports) QDEL_NULL_LIST(active_exports) if(linked_controller) From 1378028674621a5195ba28fc86cf698a3f2f1a92 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 17:49:02 -0600 Subject: [PATCH 31/47] fix unit tests?? --- mods/persistence/controllers/subsystems/trade_beacons.dm | 2 +- mods/persistence/modules/trade_beacons/trade_beacons.dm | 2 ++ 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/mods/persistence/controllers/subsystems/trade_beacons.dm b/mods/persistence/controllers/subsystems/trade_beacons.dm index b2e160e7792..ac15a6d0543 100644 --- a/mods/persistence/controllers/subsystems/trade_beacons.dm +++ b/mods/persistence/controllers/subsystems/trade_beacons.dm @@ -11,7 +11,6 @@ SUBSYSTEM_DEF(trade_beacons) for(var/x in wanted_trade_beacons) var/obj/effect/overmap/trade_beacon/beacon = new x() all_trade_beacons |= beacon - beacon.Initialize() . = ..() /datum/controller/subsystem/trade_beacons/fire(resumed = FALSE) @@ -21,3 +20,4 @@ SUBSYSTEM_DEF(trade_beacons) for(var/obj/effect/overmap/trade_beacon/x in all_trade_beacons) x.regenerate_imports() x.regenerate_exports() + diff --git a/mods/persistence/modules/trade_beacons/trade_beacons.dm b/mods/persistence/modules/trade_beacons/trade_beacons.dm index 0b7eb11d7ec..18356fbeffb 100644 --- a/mods/persistence/modules/trade_beacons/trade_beacons.dm +++ b/mods/persistence/modules/trade_beacons/trade_beacons.dm @@ -68,6 +68,7 @@ . = ..() /obj/effect/overmap/trade_beacon/proc/regenerate_imports() + if(!active_imports) active_imports = list() active_imports.Cut() for(var/import in possible_imports) if(!prob(possible_imports[import])) continue @@ -76,6 +77,7 @@ /obj/effect/overmap/trade_beacon/proc/regenerate_exports() + if(!active_exports) active_exports = list() active_exports.Cut() for(var/export in possible_exports) if(!prob(possible_exports[export])) continue From 4628ef5720eb9898c9e68714b78b70fe36c74c45 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 18:05:27 -0600 Subject: [PATCH 32/47] Update trade_beacons.dm --- mods/persistence/modules/trade_beacons/trade_beacons.dm | 3 +++ 1 file changed, 3 insertions(+) diff --git a/mods/persistence/modules/trade_beacons/trade_beacons.dm b/mods/persistence/modules/trade_beacons/trade_beacons.dm index 18356fbeffb..83803671a13 100644 --- a/mods/persistence/modules/trade_beacons/trade_beacons.dm +++ b/mods/persistence/modules/trade_beacons/trade_beacons.dm @@ -35,6 +35,9 @@ linked_controller.linked_beacon = null linked_controller = null QDEL_NULL(beacon_account) + active_imports = null + active_exports = null + beacon_account = null . = ..() /obj/effect/overmap/trade_beacon/proc/move_to_starting_location() var/datum/overmap/overmap = global.overmaps_by_name[overmap_id] From 6d2347b345d6dca229d6d863aa5901c93f4617a0 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 18:20:38 -0600 Subject: [PATCH 33/47] Update trade_beacons.dm --- mods/persistence/modules/trade_beacons/trade_beacons.dm | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/mods/persistence/modules/trade_beacons/trade_beacons.dm b/mods/persistence/modules/trade_beacons/trade_beacons.dm index 83803671a13..b4317e8a386 100644 --- a/mods/persistence/modules/trade_beacons/trade_beacons.dm +++ b/mods/persistence/modules/trade_beacons/trade_beacons.dm @@ -27,8 +27,9 @@ var/start_y = 0 -/obj/effect/overmap/trade_beacon/Destroy() - SStrade_beacons.all_trade_beacons.Remove(src) +/obj/effect/overmap/trade_beacon/Destroy(force) + if(SStrade_beacons && SStrade_beacons.all_trade_beacons) + SStrade_beacons.all_trade_beacons -= src QDEL_NULL_LIST(active_imports) QDEL_NULL_LIST(active_exports) if(linked_controller) From b57d1c1fabda8a2a0ebba88ccbd584ef6f27cd6a Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 18:30:05 -0600 Subject: [PATCH 34/47] Update trade_beacons.dm --- mods/persistence/controllers/subsystems/trade_beacons.dm | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/mods/persistence/controllers/subsystems/trade_beacons.dm b/mods/persistence/controllers/subsystems/trade_beacons.dm index ac15a6d0543..30f86da591e 100644 --- a/mods/persistence/controllers/subsystems/trade_beacons.dm +++ b/mods/persistence/controllers/subsystems/trade_beacons.dm @@ -6,6 +6,10 @@ SUBSYSTEM_DEF(trade_beacons) var/list/wanted_trade_beacons = list(/obj/effect/overmap/trade_beacon/test_beacon, /obj/effect/overmap/trade_beacon/test_beacon2) // list(//obj/effect/overmap/trade_beacon/example, /obj/effect/overmap/trade_beacon/steel, /obj/effect/overmap/trade_beacon/xandahar) var/last_cycle = 0 +/datum/controller/subsystem/trade_beacons/Destroy() + QDEL_NULL_LIST(all_trade_beacons) + . = ..() + /datum/controller/subsystem/trade_beacons/Initialize() all_trade_beacons = list() for(var/x in wanted_trade_beacons) From 4095407601753ab79ebae028be2cc2814feec772 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 18:49:16 -0600 Subject: [PATCH 35/47] fix unit tests --- mods/persistence/controllers/subsystems/trade_beacons.dm | 1 + mods/persistence/modules/trade_beacons/trade_beacons.dm | 2 ++ 2 files changed, 3 insertions(+) diff --git a/mods/persistence/controllers/subsystems/trade_beacons.dm b/mods/persistence/controllers/subsystems/trade_beacons.dm index 30f86da591e..ff2c1100d1d 100644 --- a/mods/persistence/controllers/subsystems/trade_beacons.dm +++ b/mods/persistence/controllers/subsystems/trade_beacons.dm @@ -25,3 +25,4 @@ SUBSYSTEM_DEF(trade_beacons) x.regenerate_imports() x.regenerate_exports() + ..() \ No newline at end of file diff --git a/mods/persistence/modules/trade_beacons/trade_beacons.dm b/mods/persistence/modules/trade_beacons/trade_beacons.dm index b4317e8a386..c698daa1d80 100644 --- a/mods/persistence/modules/trade_beacons/trade_beacons.dm +++ b/mods/persistence/modules/trade_beacons/trade_beacons.dm @@ -28,6 +28,7 @@ /obj/effect/overmap/trade_beacon/Destroy(force) + loc = null if(SStrade_beacons && SStrade_beacons.all_trade_beacons) SStrade_beacons.all_trade_beacons -= src QDEL_NULL_LIST(active_imports) @@ -40,6 +41,7 @@ active_exports = null beacon_account = null . = ..() + /obj/effect/overmap/trade_beacon/proc/move_to_starting_location() var/datum/overmap/overmap = global.overmaps_by_name[overmap_id] var/location From bc08eb572c390cdf3b0940d1f2624659471bf733 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 18:49:27 -0600 Subject: [PATCH 36/47] Update trade_beacons.dm --- mods/persistence/controllers/subsystems/trade_beacons.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/persistence/controllers/subsystems/trade_beacons.dm b/mods/persistence/controllers/subsystems/trade_beacons.dm index ff2c1100d1d..8578a73d449 100644 --- a/mods/persistence/controllers/subsystems/trade_beacons.dm +++ b/mods/persistence/controllers/subsystems/trade_beacons.dm @@ -25,4 +25,4 @@ SUBSYSTEM_DEF(trade_beacons) x.regenerate_imports() x.regenerate_exports() - ..() \ No newline at end of file + . = ..() \ No newline at end of file From 62536d2437fe6cafe4e8d8d5e1e06f67cfc4fbec Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 19:07:28 -0600 Subject: [PATCH 37/47] fix unit tests --- mods/persistence/modules/trade_beacons/trade_beacons.dm | 2 +- nano/templates/trade_management.tmpl | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/mods/persistence/modules/trade_beacons/trade_beacons.dm b/mods/persistence/modules/trade_beacons/trade_beacons.dm index c698daa1d80..ec1bcc25ed4 100644 --- a/mods/persistence/modules/trade_beacons/trade_beacons.dm +++ b/mods/persistence/modules/trade_beacons/trade_beacons.dm @@ -28,7 +28,7 @@ /obj/effect/overmap/trade_beacon/Destroy(force) - loc = null + forceMove(null) if(SStrade_beacons && SStrade_beacons.all_trade_beacons) SStrade_beacons.all_trade_beacons -= src QDEL_NULL_LIST(active_imports) diff --git a/nano/templates/trade_management.tmpl b/nano/templates/trade_management.tmpl index 78b6152d5c3..36b6057d033 100644 --- a/nano/templates/trade_management.tmpl +++ b/nano/templates/trade_management.tmpl @@ -98,7 +98,7 @@ {{/if}} {{if data.selected_import}} -

{{:data.selected_import}} ${{:data.import_cost}}

+

{{:data.selected_import}} | ${{:data.import_cost} | R:{{:data.import.remaining}}

{{:data.import_desc}}
From eca3ad022a99beed5d6e0889a0c362ddd7a8a26d Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 19:20:21 -0600 Subject: [PATCH 38/47] fix err --- mods/persistence/controllers/subsystems/trade_beacons.dm | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/mods/persistence/controllers/subsystems/trade_beacons.dm b/mods/persistence/controllers/subsystems/trade_beacons.dm index 8578a73d449..d13d505e772 100644 --- a/mods/persistence/controllers/subsystems/trade_beacons.dm +++ b/mods/persistence/controllers/subsystems/trade_beacons.dm @@ -18,11 +18,9 @@ SUBSYSTEM_DEF(trade_beacons) . = ..() /datum/controller/subsystem/trade_beacons/fire(resumed = FALSE) - if(REALTIMEOFDAY >= (last_cycle + 2 HOURS)) last_cycle = REALTIMEOFDAY for(var/obj/effect/overmap/trade_beacon/x in all_trade_beacons) x.regenerate_imports() x.regenerate_exports() - - . = ..() \ No newline at end of file + return \ No newline at end of file From 84d75675328e33d8072e4abc6baacd0e0656b701 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 19:31:40 -0600 Subject: [PATCH 39/47] Update trade_beacons.dm --- mods/persistence/modules/trade_beacons/trade_beacons.dm | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/mods/persistence/modules/trade_beacons/trade_beacons.dm b/mods/persistence/modules/trade_beacons/trade_beacons.dm index ec1bcc25ed4..f88c16f8913 100644 --- a/mods/persistence/modules/trade_beacons/trade_beacons.dm +++ b/mods/persistence/modules/trade_beacons/trade_beacons.dm @@ -27,7 +27,7 @@ var/start_y = 0 -/obj/effect/overmap/trade_beacon/Destroy(force) +/obj/effect/overmap/trade_beacon/Destroy() forceMove(null) if(SStrade_beacons && SStrade_beacons.all_trade_beacons) SStrade_beacons.all_trade_beacons -= src @@ -40,8 +40,13 @@ active_imports = null active_exports = null beacon_account = null + STOP_PROCESSING(SSobj, src) + SSovermap.moving_entities -= src + speed = list(0, 0) + position = list(0, 0) . = ..() + /obj/effect/overmap/trade_beacon/proc/move_to_starting_location() var/datum/overmap/overmap = global.overmaps_by_name[overmap_id] var/location From 7ec419f1d90b8897c61bec064366de692389f604 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 19:55:20 -0600 Subject: [PATCH 40/47] Update trade_beacons.dm --- .../modules/trade_beacons/trade_beacons.dm | 15 ++------------- 1 file changed, 2 insertions(+), 13 deletions(-) diff --git a/mods/persistence/modules/trade_beacons/trade_beacons.dm b/mods/persistence/modules/trade_beacons/trade_beacons.dm index f88c16f8913..d966274aa46 100644 --- a/mods/persistence/modules/trade_beacons/trade_beacons.dm +++ b/mods/persistence/modules/trade_beacons/trade_beacons.dm @@ -31,19 +31,8 @@ forceMove(null) if(SStrade_beacons && SStrade_beacons.all_trade_beacons) SStrade_beacons.all_trade_beacons -= src - QDEL_NULL_LIST(active_imports) - QDEL_NULL_LIST(active_exports) - if(linked_controller) - linked_controller.linked_beacon = null - linked_controller = null - QDEL_NULL(beacon_account) - active_imports = null - active_exports = null - beacon_account = null - STOP_PROCESSING(SSobj, src) - SSovermap.moving_entities -= src - speed = list(0, 0) - position = list(0, 0) + else + return QDEL_HINT_IFFAIL_FINDREFERENCE . = ..() From b6e288c3eba9c606fc677ac92bc7af8bac356a64 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 20:07:09 -0600 Subject: [PATCH 41/47] Update trade_beacons.dm --- mods/persistence/modules/trade_beacons/trade_beacons.dm | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/mods/persistence/modules/trade_beacons/trade_beacons.dm b/mods/persistence/modules/trade_beacons/trade_beacons.dm index d966274aa46..a8400390f00 100644 --- a/mods/persistence/modules/trade_beacons/trade_beacons.dm +++ b/mods/persistence/modules/trade_beacons/trade_beacons.dm @@ -30,9 +30,11 @@ /obj/effect/overmap/trade_beacon/Destroy() forceMove(null) if(SStrade_beacons && SStrade_beacons.all_trade_beacons) - SStrade_beacons.all_trade_beacons -= src - else - return QDEL_HINT_IFFAIL_FINDREFERENCE + SStrade_beacons.all_trade_beacons.Remove(src) + QDEL_NULL(beacon_account) + QDEL_NULL_LIST(active_imports) + QDEL_NULL_LIST(active_exports) + return QDEL_HINT_HARDDEL . = ..() From 70a49761fa6eb9784cce254a6c33af4e2ba7f582 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 20:12:24 -0600 Subject: [PATCH 42/47] z --- mods/persistence/modules/trade_beacons/trade_beacons.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mods/persistence/modules/trade_beacons/trade_beacons.dm b/mods/persistence/modules/trade_beacons/trade_beacons.dm index a8400390f00..4bf58684696 100644 --- a/mods/persistence/modules/trade_beacons/trade_beacons.dm +++ b/mods/persistence/modules/trade_beacons/trade_beacons.dm @@ -34,8 +34,8 @@ QDEL_NULL(beacon_account) QDEL_NULL_LIST(active_imports) QDEL_NULL_LIST(active_exports) + ..() return QDEL_HINT_HARDDEL - . = ..() /obj/effect/overmap/trade_beacon/proc/move_to_starting_location() From 921a612c64b793087633fb7422a150a2dfd9f483 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 20:16:26 -0600 Subject: [PATCH 43/47] Update trade_beacons.dm --- mods/persistence/controllers/subsystems/trade_beacons.dm | 2 ++ 1 file changed, 2 insertions(+) diff --git a/mods/persistence/controllers/subsystems/trade_beacons.dm b/mods/persistence/controllers/subsystems/trade_beacons.dm index d13d505e772..741d368ae95 100644 --- a/mods/persistence/controllers/subsystems/trade_beacons.dm +++ b/mods/persistence/controllers/subsystems/trade_beacons.dm @@ -12,9 +12,11 @@ SUBSYSTEM_DEF(trade_beacons) /datum/controller/subsystem/trade_beacons/Initialize() all_trade_beacons = list() +#ifndef UNIT_TEST for(var/x in wanted_trade_beacons) var/obj/effect/overmap/trade_beacon/beacon = new x() all_trade_beacons |= beacon +#endif . = ..() /datum/controller/subsystem/trade_beacons/fire(resumed = FALSE) From 6d2ad2924b78492f2eae62db410144db8d5656aa Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Tue, 14 Mar 2023 20:16:49 -0600 Subject: [PATCH 44/47] Update trade_beacons.dm --- mods/persistence/modules/trade_beacons/trade_beacons.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/mods/persistence/modules/trade_beacons/trade_beacons.dm b/mods/persistence/modules/trade_beacons/trade_beacons.dm index 4bf58684696..5c7124df865 100644 --- a/mods/persistence/modules/trade_beacons/trade_beacons.dm +++ b/mods/persistence/modules/trade_beacons/trade_beacons.dm @@ -35,7 +35,6 @@ QDEL_NULL_LIST(active_imports) QDEL_NULL_LIST(active_exports) ..() - return QDEL_HINT_HARDDEL /obj/effect/overmap/trade_beacon/proc/move_to_starting_location() From 7db10212ce5aa31635d957c4dd79ca7970871770 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Fri, 17 Mar 2023 14:07:37 -0600 Subject: [PATCH 45/47] Update mods/persistence/modules/trade_beacons/trade_beacons.dm Co-authored-by: PsyCommando --- mods/persistence/modules/trade_beacons/trade_beacons.dm | 1 - 1 file changed, 1 deletion(-) diff --git a/mods/persistence/modules/trade_beacons/trade_beacons.dm b/mods/persistence/modules/trade_beacons/trade_beacons.dm index 5c7124df865..c159e2e0b7a 100644 --- a/mods/persistence/modules/trade_beacons/trade_beacons.dm +++ b/mods/persistence/modules/trade_beacons/trade_beacons.dm @@ -28,7 +28,6 @@ /obj/effect/overmap/trade_beacon/Destroy() - forceMove(null) if(SStrade_beacons && SStrade_beacons.all_trade_beacons) SStrade_beacons.all_trade_beacons.Remove(src) QDEL_NULL(beacon_account) From 4dfa4b2503244c04f9ada3205325d7333fc3aeb0 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Fri, 17 Mar 2023 14:07:45 -0600 Subject: [PATCH 46/47] Update code/modules/economy/cargo_telepads.dm Co-authored-by: PsyCommando --- code/modules/economy/cargo_telepads.dm | 1 + 1 file changed, 1 insertion(+) diff --git a/code/modules/economy/cargo_telepads.dm b/code/modules/economy/cargo_telepads.dm index 39607b9a24c..95ab3e0cd6c 100644 --- a/code/modules/economy/cargo_telepads.dm +++ b/code/modules/economy/cargo_telepads.dm @@ -19,6 +19,7 @@ var/id = input(user, "Enter a new telepad ID", "Telepad ID") as text|null id = sanitize(id) if(CanInteract(user, DefaultTopicState()) && id) telepad_id = id + return TRUE ..() From d8da38958ad8248e2bac717b1a17a98d0e643cb6 Mon Sep 17 00:00:00 2001 From: FaurnsGoldberg Date: Fri, 17 Mar 2023 14:07:51 -0600 Subject: [PATCH 47/47] Update code/modules/economy/cargo_telepads.dm Co-authored-by: PsyCommando --- code/modules/economy/cargo_telepads.dm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/code/modules/economy/cargo_telepads.dm b/code/modules/economy/cargo_telepads.dm index 95ab3e0cd6c..93e3e2f051a 100644 --- a/code/modules/economy/cargo_telepads.dm +++ b/code/modules/economy/cargo_telepads.dm @@ -21,7 +21,7 @@ if(CanInteract(user, DefaultTopicState()) && id) telepad_id = id return TRUE - ..() + . = ..() /obj/machinery/telepad_cargo/examine(mob/user) . = ..()