mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-08-23 13:10:02 +01:00
Refactors pricetag component: no getcomponent, no ugly signals, fixes cubes a bit (#63954)
Refactors the pricetag component Removes a getcomponent for the pricetag component in cube export handling (replaced with inherit component behavior) Removes some nasty signals which were effectively just send signal, get 1 Deletes the internal radio within bounty cubes from before exporting Disallows bounty cubes from being barcoded with TRAIT_NO_BARCODES Prevents bounty cube pricetag component from being deleted by unwrapping Closes #63921 technically
This commit is contained in:
@@ -197,13 +197,18 @@
|
||||
#define COMSIG_OBJ_ATTEMPT_CHARGE_CHANGE "obj_attempt_simple_charge_change"
|
||||
|
||||
// /obj/item signals for economy
|
||||
///called before an item is sold by the exports system.
|
||||
#define COMSIG_ITEM_PRE_EXPORT "item_pre_sold"
|
||||
/// Stops the export from calling sell_object() on the item, so you can handle it manually.
|
||||
#define COMPONENT_STOP_EXPORT (1<<0)
|
||||
///called when an item is sold by the exports subsystem
|
||||
#define COMSIG_ITEM_SOLD "item_sold"
|
||||
#define COMSIG_ITEM_EXPORTED "item_sold"
|
||||
/// Stops the export from adding the export information to the report, so you can handle it manually.
|
||||
#define COMPONENT_STOP_EXPORT_REPORT (1<<0)
|
||||
///called when a wrapped up structure is opened by hand
|
||||
#define COMSIG_STRUCTURE_UNWRAPPED "structure_unwrapped"
|
||||
///called when a wrapped up item is opened by hand
|
||||
#define COMSIG_ITEM_UNWRAPPED "item_unwrapped"
|
||||
#define COMSIG_ITEM_SPLIT_VALUE (1<<0)
|
||||
///called when getting the item's exact ratio for cargo's profit.
|
||||
#define COMSIG_ITEM_SPLIT_PROFIT "item_split_profits"
|
||||
///called when getting the item's exact ratio for cargo's profit, without selling the item.
|
||||
|
||||
@@ -500,6 +500,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai
|
||||
#define TRAIT_NO_IMMOBILIZE "no_immobilize"
|
||||
/// Prevents stripping this equipment
|
||||
#define TRAIT_NO_STRIP "no_strip"
|
||||
/// Disallows this item from being pricetagged with a barcode
|
||||
#define TRAIT_NO_BARCODES "no_barcode"
|
||||
|
||||
//quirk traits
|
||||
#define TRAIT_ALCOHOL_TOLERANCE "alcohol_tolerance"
|
||||
|
||||
@@ -1,40 +1,102 @@
|
||||
/*
|
||||
* Pricetag component.
|
||||
*
|
||||
* Used when exporting items via the cargo system.
|
||||
* Gives a cut of the profit to one or multiple bank accounts.
|
||||
*/
|
||||
/datum/component/pricetag
|
||||
///Payee gets 100% of the value if no ratio has been set.
|
||||
var/default_profit_ratio = 1
|
||||
///List of bank accounts this pricetag pays out to. Format is payees[bank_account] = profit_ratio.
|
||||
dupe_mode = COMPONENT_DUPE_UNIQUE_PASSARGS
|
||||
/// Whether we qdel ourself when our parent is unwrapped or not.
|
||||
var/delete_on_unwrap = TRUE
|
||||
/// List of bank accounts this pricetag pays out to. Format is payees[bank_account] = profit_ratio.
|
||||
var/list/payees = list()
|
||||
|
||||
/datum/component/pricetag/Initialize(_owner,_profit_ratio)
|
||||
/datum/component/pricetag/Initialize(pay_to_account, profit_ratio = 1, delete_on_unwrap = TRUE)
|
||||
if(!isobj(parent)) //Has to account for both objects and sellable structures like crates.
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
if(_profit_ratio)
|
||||
payees[_owner] = _profit_ratio
|
||||
else
|
||||
payees[_owner] = default_profit_ratio
|
||||
if(isnull(pay_to_account))
|
||||
stack_trace("[type] component was added to something without a pay_to_account!")
|
||||
return COMPONENT_INCOMPATIBLE
|
||||
|
||||
RegisterSignal(parent, list(COMSIG_ITEM_SOLD), .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), .proc/return_ratio)
|
||||
payees[pay_to_account] = profit_ratio
|
||||
src.delete_on_unwrap = delete_on_unwrap
|
||||
|
||||
/datum/component/pricetag/proc/Unwrapped()
|
||||
/datum/component/pricetag/RegisterWithParent()
|
||||
RegisterSignal(parent, COMSIG_ITEM_EXPORTED, .proc/on_parent_sold)
|
||||
// Register this regardless of delete_on_unwrap because it could change by inherited components.
|
||||
RegisterSignal(parent, list(COMSIG_STRUCTURE_UNWRAPPED, COMSIG_ITEM_UNWRAPPED), .proc/on_parent_unwrap)
|
||||
|
||||
/datum/component/pricetag/UnregisterFromParent()
|
||||
UnregisterSignal(parent, list(
|
||||
COMSIG_ITEM_EXPORTED,
|
||||
COMSIG_STRUCTURE_UNWRAPPED,
|
||||
COMSIG_ITEM_UNWRAPPED,
|
||||
))
|
||||
|
||||
/*
|
||||
* Inheriting an incoming / new version of price tag:
|
||||
*
|
||||
* If the account passed in the incoming version is already in our list,
|
||||
* only override it if the ratio is better for the payee
|
||||
*
|
||||
* If the account passed in the incoming version is not in our list, add it like normal.
|
||||
*
|
||||
* If the incoming version shouldn't delete when unwrapped,
|
||||
* our version shouldn't either.
|
||||
* We don't care about the other way around
|
||||
* (Don't go from non-deleting to deleting)
|
||||
*/
|
||||
/datum/component/pricetag/InheritComponent(datum/component/pricetag/new_comp, i_am_original, pay_to_account, profit_ratio = 1, delete_on_unwrap = TRUE)
|
||||
if(!isnull(payees[pay_to_account]) && payees[pay_to_account] >= profit_ratio) // They're already getting a better ratio, don't scam them
|
||||
return
|
||||
|
||||
payees[pay_to_account] = profit_ratio
|
||||
if(!delete_on_unwrap)
|
||||
src.delete_on_unwrap = delete_on_unwrap
|
||||
|
||||
|
||||
/*
|
||||
* Signal proc for [COMSIG_STRUCTURE_UNWRAPPED] and [COMSIG_ITEM_UNWRAPPED].
|
||||
*
|
||||
* Once it leaves its wrapped container,
|
||||
* the parent should loses its pricetag component
|
||||
* (if delete_on_unwrap is TRUE)
|
||||
*/
|
||||
/datum/component/pricetag/proc/on_parent_unwrap(obj/source)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
qdel(src) //Once it leaves it's wrapped container, the object in question should lose it's pricetag component.
|
||||
if(!delete_on_unwrap)
|
||||
return
|
||||
|
||||
/datum/component/pricetag/proc/split_profit(item_value)
|
||||
qdel(src)
|
||||
|
||||
/*
|
||||
* Signal proc for [COMSIG_ITEM_EXPORTED].
|
||||
*
|
||||
* Pays out money to everyone in the payees list.
|
||||
*/
|
||||
/datum/component/pricetag/proc/on_parent_sold(obj/source, datum/export/export, datum/export_report/report, item_value)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
var/price = item_value
|
||||
if(price)
|
||||
for(var/datum/bank_account/payee in payees)
|
||||
var/profit_ratio = payees[payee]
|
||||
var/adjusted_value = price * profit_ratio
|
||||
var/datum/bank_account/bank_account = payee
|
||||
bank_account.adjust_money(adjusted_value)
|
||||
bank_account.bank_card_talk("Sale of [parent] recorded. [adjusted_value] credits added to account.")
|
||||
return TRUE
|
||||
if(!isnum(item_value))
|
||||
return
|
||||
|
||||
/datum/component/pricetag/proc/return_ratio()
|
||||
SIGNAL_HANDLER
|
||||
return default_profit_ratio
|
||||
// Gotta see how much money we've lost by the end of things.
|
||||
var/overall_item_price = item_value
|
||||
|
||||
for(var/datum/bank_account/payee as anything in payees)
|
||||
// Every payee with a ratio gets a cut based on the item's total value
|
||||
var/payee_cut = round(item_value * payees[payee])
|
||||
// And of course, the cut is removed from what cargo gets. (But not below zero, just in case)
|
||||
overall_item_price = max(0, overall_item_price - payee_cut)
|
||||
|
||||
payee.adjust_money(payee_cut)
|
||||
payee.bank_card_talk("Sale of [source] recorded. [payee_cut] credits added to account.")
|
||||
|
||||
// Update the report with the modified final price
|
||||
report.total_value[export] += overall_item_price
|
||||
report.total_amount[export] += export.get_amount(source) * export.amount_report_multiplier
|
||||
|
||||
// And ensure we don't double-add to the report
|
||||
return COMPONENT_STOP_EXPORT_REPORT
|
||||
|
||||
@@ -275,14 +275,17 @@
|
||||
|
||||
/obj/item/bounty_cube/Initialize(mapload)
|
||||
. = ..()
|
||||
ADD_TRAIT(src, TRAIT_NO_BARCODES, INNATE_TRAIT) // Don't allow anyone to override our pricetag component with a barcode
|
||||
radio = new(src)
|
||||
radio.keyslot = new radio_key
|
||||
radio.set_listening(FALSE)
|
||||
radio.recalculateChannels()
|
||||
RegisterSignal(radio, COMSIG_ITEM_PRE_EXPORT, .proc/on_export)
|
||||
|
||||
/obj/item/bounty_cube/Destroy()
|
||||
UnregisterSignal(radio, COMSIG_ITEM_PRE_EXPORT)
|
||||
QDEL_NULL(radio)
|
||||
. = ..()
|
||||
return ..()
|
||||
|
||||
/obj/item/bounty_cube/examine()
|
||||
. = ..()
|
||||
@@ -291,6 +294,20 @@
|
||||
if(handler_tip && !bounty_handler_account)
|
||||
. += span_notice("Scan this in the cargo shuttle with an export scanner to register your bank account for the <b>[bounty_value * handler_tip]</b> credit handling tip.")
|
||||
|
||||
/*
|
||||
* Signal proc for [COMSIG_ITEM_EXPORTED], registered on the internal radio.
|
||||
*
|
||||
* Deletes the internal radio before being exported,
|
||||
* to stop it from bring counted as an export.
|
||||
*
|
||||
* No 4 free credits for you!
|
||||
*/
|
||||
/obj/item/bounty_cube/proc/on_export(datum/source)
|
||||
SIGNAL_HANDLER
|
||||
|
||||
QDEL_NULL(radio)
|
||||
return COMPONENT_STOP_EXPORT // stops the radio from exporting, not the cube
|
||||
|
||||
/obj/item/bounty_cube/process(delta_time)
|
||||
//if our nag cooldown has finished and we aren't on Centcom or in transit, then nag
|
||||
if(COOLDOWN_FINISHED(src, next_nag_time) && !is_centcom_level(z) && !is_reserved_level(z))
|
||||
@@ -320,7 +337,7 @@
|
||||
bounty_holder_account = holder_id.registered_account
|
||||
name = "\improper [bounty_value] cr [name]"
|
||||
desc += " The sales tag indicates it was <i>[bounty_holder] ([bounty_holder_job])</i>'s reward for completing the <i>[bounty_name]</i> bounty."
|
||||
AddComponent(/datum/component/pricetag, holder_id.registered_account, holder_cut)
|
||||
AddComponent(/datum/component/pricetag, holder_id.registered_account, holder_cut, FALSE)
|
||||
AddComponent(/datum/component/gps, "[src]")
|
||||
START_PROCESSING(SSobj, src)
|
||||
COOLDOWN_START(src, next_nag_time, nag_cooldown)
|
||||
|
||||
@@ -29,6 +29,7 @@
|
||||
var/mob/living/carbon/human/scan_human = user
|
||||
if(istype(O, /obj/item/bounty_cube))
|
||||
var/obj/item/bounty_cube/cube = O
|
||||
var/datum/bank_account/scanner_account = scan_human.get_bank_account()
|
||||
|
||||
if(!istype(get_area(cube), /area/shuttle/supply))
|
||||
to_chat(user, span_warning("Shuttle placement not detected. Handling tip not registered."))
|
||||
@@ -36,12 +37,10 @@
|
||||
else if(cube.bounty_handler_account)
|
||||
to_chat(user, span_warning("Bank account for handling tip already registered!"))
|
||||
|
||||
else if(scan_human.get_bank_account() && cube.GetComponent(/datum/component/pricetag))
|
||||
var/datum/component/pricetag/pricetag = cube.GetComponent(/datum/component/pricetag)
|
||||
|
||||
cube.bounty_handler_account = scan_human.get_bank_account()
|
||||
pricetag.payees[cube.bounty_handler_account] += cube.handler_tip
|
||||
else if(scanner_account)
|
||||
cube.AddComponent(/datum/component/pricetag, scanner_account, cube.handler_tip, FALSE)
|
||||
|
||||
cube.bounty_handler_account = scanner_account
|
||||
cube.bounty_handler_account.bank_card_talk("Bank account for [price ? "<b>[price * cube.handler_tip]</b> credit " : ""]handling tip successfully registered.")
|
||||
|
||||
if(cube.bounty_holder_account != cube.bounty_handler_account) //No need to send a tracking update to the person scanning it
|
||||
|
||||
@@ -26,12 +26,10 @@ Then the player gets the profit from selling his own wasted time.
|
||||
var/list/total_value = list() //export instance => total value of sold objects
|
||||
|
||||
// external_report works as "transaction" object, pass same one in if you're doing more than one export in single go
|
||||
/proc/export_item_and_contents(atom/movable/AM, apply_elastic = TRUE, delete_unsold = TRUE, dry_run=FALSE, datum/export_report/external_report)
|
||||
/proc/export_item_and_contents(atom/movable/AM, apply_elastic = TRUE, delete_unsold = TRUE, dry_run = FALSE, datum/export_report/external_report)
|
||||
if(!GLOB.exports_list.len)
|
||||
setupExports()
|
||||
|
||||
var/profit_ratio = 1 //Percentage that gets sent to the seller, rest goes to cargo.
|
||||
|
||||
var/list/contents = AM.get_all_contents()
|
||||
|
||||
var/datum/export_report/report = external_report
|
||||
@@ -45,12 +43,14 @@ Then the player gets the profit from selling his own wasted time.
|
||||
var/sold = FALSE
|
||||
for(var/datum/export/export as anything in GLOB.exports_list)
|
||||
if(export.applies_to(thing, apply_elastic))
|
||||
sold = export.sell_object(thing, report, dry_run, apply_elastic, profit_ratio)
|
||||
if(!dry_run && (SEND_SIGNAL(thing, COMSIG_ITEM_PRE_EXPORT) & COMPONENT_STOP_EXPORT))
|
||||
break
|
||||
sold = export.sell_object(thing, report, dry_run, apply_elastic)
|
||||
report.exported_atoms += " [thing.name]"
|
||||
break
|
||||
if(!dry_run && (sold || delete_unsold))
|
||||
if(ismob(thing))
|
||||
thing.investigate_log("deleted through cargo export",INVESTIGATE_CARGO)
|
||||
thing.investigate_log("deleted through cargo export", INVESTIGATE_CARGO)
|
||||
to_delete += thing
|
||||
|
||||
for(var/atom/movable/thing as anything in to_delete)
|
||||
@@ -136,31 +136,29 @@ Then the player gets the profit from selling his own wasted time.
|
||||
* 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, apply_elastic = TRUE)
|
||||
/datum/export/proc/sell_object(obj/sold_item, datum/export_report/report, dry_run = TRUE, apply_elastic = TRUE)
|
||||
///This is the value of the object, as derived from export datums.
|
||||
var/the_cost = get_cost(O, apply_elastic)
|
||||
var/export_value = get_cost(sold_item, 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
|
||||
var/export_amount = get_amount(sold_item)
|
||||
|
||||
if(amount <=0 || (the_cost <=0 && !allow_negative_cost))
|
||||
if(export_amount <= 0 || (export_value <= 0 && !allow_negative_cost))
|
||||
return FALSE
|
||||
if(dry_run == FALSE)
|
||||
if(SEND_SIGNAL(O, COMSIG_ITEM_SOLD, item_value = get_cost(O, apply_elastic)) & COMSIG_ITEM_SPLIT_VALUE)
|
||||
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) * 0.01)
|
||||
report.total_value[src] += the_cost
|
||||
|
||||
report.total_amount[src] += amount*amount_report_multiplier
|
||||
// If we're not doing a dry run, send COMSIG_ITEM_EXPORTED to the sold item
|
||||
var/export_result
|
||||
if(!dry_run)
|
||||
export_result = SEND_SIGNAL(sold_item, COMSIG_ITEM_EXPORTED, src, report, export_value)
|
||||
|
||||
// If the signal handled adding it to the report, don't do it now
|
||||
if(!(export_result & COMPONENT_STOP_EXPORT_REPORT))
|
||||
report.total_value[src] += export_value
|
||||
report.total_amount[src] += export_amount * amount_report_multiplier
|
||||
|
||||
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("[O.type]", "[the_cost]"))
|
||||
cost *= NUM_E**(-1 * k_elasticity * export_amount) //marginal cost modifier
|
||||
SSblackbox.record_feedback("nested tally", "export_sold_cost", 1, list("[sold_item.type]", "[export_value]"))
|
||||
return TRUE
|
||||
|
||||
// Total printout for the cargo console.
|
||||
|
||||
@@ -114,9 +114,10 @@
|
||||
sticker.payments_acc = tagger.payments_acc //new tag gets the tagger's current account.
|
||||
sticker.cut_multiplier = tagger.cut_multiplier //same, but for the percentage taken.
|
||||
|
||||
var/list/wrap_contents = src.get_all_contents()
|
||||
for(var/obj/I in wrap_contents)
|
||||
I.AddComponent(/datum/component/pricetag, sticker.payments_acc, tagger.cut_multiplier)
|
||||
for(var/obj/wrapped_item in get_all_contents())
|
||||
if(HAS_TRAIT(wrapped_item, TRAIT_NO_BARCODES))
|
||||
continue
|
||||
wrapped_item.AddComponent(/datum/component/pricetag, sticker.payments_acc, tagger.cut_multiplier)
|
||||
var/overlaystring = "[icon_state]_tag"
|
||||
if(giftwrapped)
|
||||
overlaystring = copytext(overlaystring, 5)
|
||||
@@ -133,9 +134,10 @@
|
||||
to_chat(user, span_warning("For some reason, you can't attach [W]!"))
|
||||
return
|
||||
sticker = stickerA
|
||||
var/list/wrap_contents = src.get_all_contents()
|
||||
for(var/obj/I in wrap_contents)
|
||||
I.AddComponent(/datum/component/pricetag, sticker.payments_acc, sticker.cut_multiplier)
|
||||
for(var/obj/wrapped_item in get_all_contents())
|
||||
if(HAS_TRAIT(wrapped_item, TRAIT_NO_BARCODES))
|
||||
continue
|
||||
wrapped_item.AddComponent(/datum/component/pricetag, sticker.payments_acc, sticker.cut_multiplier)
|
||||
var/overlaystring = "[icon_state]_tag"
|
||||
if(giftwrapped)
|
||||
overlaystring = copytext_char(overlaystring, 5) //5 == length("gift") + 1
|
||||
@@ -307,9 +309,10 @@
|
||||
sticker.payments_acc = tagger.payments_acc //new tag gets the tagger's current account.
|
||||
sticker.cut_multiplier = tagger.cut_multiplier //as above, as before.
|
||||
|
||||
var/list/wrap_contents = src.get_all_contents()
|
||||
for(var/obj/I in wrap_contents)
|
||||
I.AddComponent(/datum/component/pricetag, sticker.payments_acc, tagger.cut_multiplier)
|
||||
for(var/obj/wrapped_item in get_all_contents())
|
||||
if(HAS_TRAIT(wrapped_item, TRAIT_NO_BARCODES))
|
||||
continue
|
||||
wrapped_item.AddComponent(/datum/component/pricetag, sticker.payments_acc, tagger.cut_multiplier)
|
||||
var/overlaystring = "[icon_state]_tag"
|
||||
if(giftwrapped)
|
||||
overlaystring = copytext(overlaystring, 5)
|
||||
@@ -327,9 +330,10 @@
|
||||
to_chat(user, span_warning("For some reason, you can't attach [W]!"))
|
||||
return
|
||||
sticker = stickerA
|
||||
var/list/wrap_contents = src.get_all_contents()
|
||||
for(var/obj/I in wrap_contents)
|
||||
I.AddComponent(/datum/component/pricetag, sticker.payments_acc, sticker.cut_multiplier)
|
||||
for(var/obj/wrapped_item in get_all_contents())
|
||||
if(HAS_TRAIT(wrapped_item, TRAIT_NO_BARCODES))
|
||||
continue
|
||||
wrapped_item.AddComponent(/datum/component/pricetag, sticker.payments_acc, sticker.cut_multiplier)
|
||||
var/overlaystring = "[icon_state]_tag"
|
||||
if(giftwrapped)
|
||||
overlaystring = copytext_char(overlaystring, 5) //5 == length("gift") + 1
|
||||
|
||||
Reference in New Issue
Block a user