From a24f6da1e35ef9bf308b476e486ba4eb6d7d169b Mon Sep 17 00:00:00 2001 From: ArcaneMusic <41715314+ArcaneMusic@users.noreply.github.com> Date: Tue, 31 Mar 2020 01:55:06 -0400 Subject: [PATCH] Items without Export Datums calculate their value based on material datums. (#49991) * The exportlarity. * Some clean up on cargo logs. May need tweaks still * Whoops. * Several Review comments and some cleanup on pricetags * Review comments round 2 * Almost forgot * further updates. * Forgot one. * Yeah that isn't doing anything. --- code/__DEFINES/dcs/signals.dm | 3 ++ code/datums/components/pricetag.dm | 7 ++- code/datums/materials/basemats.dm | 2 +- code/modules/cargo/exports.dm | 73 +++++++++++++++++++++++++++--- 4 files changed, 73 insertions(+), 12 deletions(-) diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 4633d180150..716e980af14 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -288,10 +288,13 @@ // /obj/item signals for economy #define COMSIG_ITEM_SOLD "item_sold" //called when an item is sold by the exports subsystem +#define COMSIG_ITEM_SOLD_MATERIAL "item_sold_material" //called when an item is sold by the exports subsystem using material datums. #define COMSIG_STRUCTURE_UNWRAPPED "structure_unwrapped" //called when a wrapped up structure is opened by hand #define COMSIG_ITEM_UNWRAPPED "item_unwrapped" //called when a wrapped up item is opened by hand #define COMSIG_ITEM_SPLIT_VALUE 1 #define COMSIG_ITEM_SPLIT_PROFIT "item_split_profits" //Called when getting the item's exact ratio for cargo's profit. +#define COMSIG_ITEM_SPLIT_PROFIT_DRY "item_split_profits_dry" //Called when getting the item's exact ratio for cargo's profit, without selling the item. +#define COMSIG_ITEM_SPLIT_PROFIT_MATERIAL "item_split_material_profits" //Called when getting an item's profit ratio, but when calculating wealth from material datums. // /obj/item/clothing signals diff --git a/code/datums/components/pricetag.dm b/code/datums/components/pricetag.dm index 3220dc425a5..99fe6512103 100644 --- a/code/datums/components/pricetag.dm +++ b/code/datums/components/pricetag.dm @@ -8,10 +8,9 @@ owner = _owner if(_profit_ratio) profit_ratio = _profit_ratio - RegisterSignal(parent, COMSIG_ITEM_SOLD, .proc/split_profit) - RegisterSignal(parent, COMSIG_STRUCTURE_UNWRAPPED, .proc/Unwrapped) - RegisterSignal(parent, COMSIG_ITEM_UNWRAPPED, .proc/Unwrapped) - RegisterSignal(parent, COMSIG_ITEM_SPLIT_PROFIT, .proc/return_ratio) + RegisterSignal(parent, list(COMSIG_ITEM_SOLD, COMSIG_ITEM_SOLD_MATERIAL), .proc/split_profit) + RegisterSignal(parent, list(COMSIG_STRUCTURE_UNWRAPPED, COMSIG_ITEM_UNWRAPPED), .proc/Unwrapped) + RegisterSignal(parent, list(COMSIG_ITEM_SPLIT_PROFIT, COMSIG_ITEM_SPLIT_PROFIT_DRY, COMSIG_ITEM_SPLIT_PROFIT_MATERIAL), .proc/return_ratio) /datum/component/pricetag/proc/Unwrapped() qdel(src) //Once it leaves it's wrapped container, the object in question should lose it's pricetag component. diff --git a/code/datums/materials/basemats.dm b/code/datums/materials/basemats.dm index 51873225a44..b4aefc70960 100644 --- a/code/datums/materials/basemats.dm +++ b/code/datums/materials/basemats.dm @@ -198,7 +198,7 @@ Unless you know what you're doing, only use the first three numbers. They're in strength_modifier = 0.5 sheet_type = /obj/item/stack/sheet/mineral/wood categories = list(MAT_CATEGORY_RIGID = TRUE) - value_per_unit = 0.06 + value_per_unit = 0.01 beauty_modifier = 0.1 armor_modifiers = list("melee" = 1.1, "bullet" = 1.1, "laser" = 0.4, "energy" = 0.4, "bomb" = 1, "bio" = 0.2, "rad" = 0, "fire" = 0, "acid" = 0.3) diff --git a/code/modules/cargo/exports.dm b/code/modules/cargo/exports.dm index e9bde3d46e4..044e8425767 100644 --- a/code/modules/cargo/exports.dm +++ b/code/modules/cargo/exports.dm @@ -56,6 +56,11 @@ Credit dupes that require a lot of manual work shouldn't be removed, unless they if(!QDELETED(thing)) report.exported_atoms_ref += thing break + if(!sold && thing.custom_materials) + var/datum/export/S = new /datum/export + if(S.get_material_cost(thing) && (!S.get_cost(thing, allowed_categories , apply_elastic))) + S.sell_material_item(thing, report, dry_run, apply_elastic, profit_ratio) + sold = TRUE if(!dry_run && (sold || delete_unsold)) if(ismob(thing)) thing.investigate_log("deleted through cargo export",INVESTIGATE_CARGO) @@ -66,7 +71,7 @@ Credit dupes that require a lot of manual work shouldn't be removed, unless they /datum/export var/unit_name = "" // Unit name. Only used in "Received [total_amount] [name]s [message]." message var/message = "" - var/cost = 100 // Cost of item, in cargo credits. Must not alow for infinite price dupes, see above. + var/cost = 1 // Cost of item, in cargo credits. Must not alow for infinite price dupes, see above. var/k_elasticity = 1/30 //coefficient used in marginal price calculation that roughly corresponds to the inverse of price elasticity, or "quantity elasticity" var/list/export_types = list() // Type of the exported object. If none, the export datum is considered base type. var/include_subtypes = TRUE // Set to FALSE to make the datum apply only to a strict type. @@ -125,22 +130,31 @@ Credit dupes that require a lot of manual work shouldn't be removed, unless they return FALSE return TRUE -// Called only once, when the object is actually sold by the datum. -// Adds item's cost and amount to the current export cycle. -// get_cost, get_amount and applies_to do not neccesary mean a successful sale. +/** + * Calculates the exact export value of the object, while factoring in all the relivant variables. + * + * Called only once, when the object is actually sold by the datum. + * Adds item's cost and amount to the current export cycle. + * get_cost, get_amount and applies_to do not neccesary mean a successful sale. + * + */ /datum/export/proc/sell_object(obj/O, datum/export_report/report, dry_run = TRUE, allowed_categories = EXPORT_CARGO , apply_elastic = TRUE) + ///This is the value of the object, as derived from export datums. var/the_cost = get_cost(O, allowed_categories , apply_elastic) + ///Quantity of the object in question. var/amount = get_amount(O) + ///Utilized in the pricetag component. Splits the object's profit when it has a pricetag by the specified amount. var/profit_ratio = 0 + if(amount <=0 || the_cost <=0) return FALSE if(dry_run == FALSE) if(SEND_SIGNAL(O, COMSIG_ITEM_SOLD, item_value = get_cost(O, allowed_categories , apply_elastic)) & COMSIG_ITEM_SPLIT_VALUE) - profit_ratio = SEND_SIGNAL(O, COMSIG_ITEM_SPLIT_PROFIT) - the_cost = the_cost*((100-profit_ratio)/100) + profit_ratio = SEND_SIGNAL(O, COMSIG_ITEM_SPLIT_PROFIT_DRY) + the_cost = the_cost * ((100 - profit_ratio) * 0.01) else profit_ratio = SEND_SIGNAL(O, COMSIG_ITEM_SPLIT_PROFIT) - the_cost = the_cost*((100-profit_ratio)/100) + the_cost = the_cost * ((100 - profit_ratio) * 0.01) report.total_value[src] += the_cost if(istype(O, /datum/export/material)) @@ -183,6 +197,51 @@ Credit dupes that require a lot of manual work shouldn't be removed, unless they GLOBAL_LIST_EMPTY(exports_list) +/** + * Calculates the exact export value of the object based on the object's datum materials. + * + * loops through the atom's material datums and then multiplies that amount by it's relative worth, and sums the total. + */ +/datum/export/proc/get_material_cost(atom/movable/A) + for(var/i in A.custom_materials) + var/datum/material/M = i + . += M.value_per_unit * A.custom_materials[M] + . = round(.) //floor of the value + +/** + * Sells an object using it's material cost. + * + * Works similarly to the sell object proc, but utilizes the get_material_cost proc in order to obtain it's raw value in terms of materials. + * Similarly checks for pricetags to split export profit the same way. + */ +/datum/export/proc/sell_material_item(obj/sold_object, datum/export_report/report, dry_run = TRUE, apply_elastic = TRUE) + ///This is the value of the object, as derived from material datums. + var/material_cost = get_material_cost(sold_object) + ///Quantity of the object in question. + var/amount = get_amount(sold_object) + ///Utilized in the pricetag component. Splits the object's profit when it has a pricetag by the specified amount. + var/profit_ratio = 0 + + if(amount <= 0 || material_cost <= 0) + return FALSE + unit_name = "[sold_object.name]" + profit_ratio = SEND_SIGNAL(sold_object, COMSIG_ITEM_SPLIT_PROFIT_MATERIAL) + material_cost = material_cost * ((100 - profit_ratio) * 0.01) + if(dry_run == FALSE) + SEND_SIGNAL(sold_object, COMSIG_ITEM_SOLD_MATERIAL, item_value = material_cost) + report.total_value[src] += material_cost + + if(istype(sold_object, /datum/export/material)) + report.total_amount[src] += amount*MINERAL_MATERIAL_AMOUNT + else + report.total_amount[src] += amount + + if(!dry_run) + if(apply_elastic) + cost *= NUM_E**(-1*k_elasticity*amount) //marginal cost modifier + SSblackbox.record_feedback("nested tally", "export_sold_cost", 1, list("[sold_object.type]", "[material_cost]")) + return TRUE + /proc/setupExports() for(var/subtype in subtypesof(/datum/export)) var/datum/export/E = new subtype