Secondary goals (#24599)

* Extract requests console message sending code.

* Add secondary goals

* Converted supply shuttle to a signal-based system.

* Lint.

* Review suggestions.

* Secondary goals can now check the supply shuttle for their requirements.

* Remove redundant completion variable, undef what we define.

* Made the request console refuse to issue a secondary goal until you finish the current one.

* Made the shuttle blacklist error more specific, added locked/manifest-attached crates to blacklist.

* Added round end secondary goal report.

* Lint

* Add tags to reagents for secondary goals to use.

* Extracted the reagent logic from the bar goal, used reagent tags.

* Added the Variety of Drinks Bar goal.

* Added variety drinks goal for the Bar.

* CC no longer complains about sending stuff in containers, but the shuttle will refuse lockboxes without goal items.

* Allow unlocked lockboxes on the shuttle.

* Added kitchen goals.

* Lint

* More lint

* Add goals for scichem and medchem, pending reagent labelling.

* Added Kudzu goal for botany.

* I forgot to rename them, oops.

* Lint

* Made mechs sellable, configurable goal rewards.

* Balancing changes.

* Added random Ripley goal.

* Add Clear Task Backlog station goal.

* Lint

* Oops.

* did i even do this right

* Lint

* Excluded drinks available from upgraded booze dispenser.

* Such bugs. Much fix. Wow.

* Goal notice formatting.

* Apply suggestions from code review

Co-authored-by: Henri215 <77684085+Henri215@users.noreply.github.com>

* Made storage nesting better, improved consistency between storage types.

* Out, er, space.

* Added a proc for sending a requests console message.

* Added error messages to Virology Goals.

Backported a few small things from Secondary Goals to make this easier.

* Extracted out the three-way reward code into a proc.

* Update code/__DEFINES/dcs/signals.dm

Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com>

* Removed redundant SIGNAL_HANDLER labels.

* Yes, that should be a proc.

* Enforce important parent calls.

* Thank you, DreamChecker

* Undid accidental merge of #24699

* Removed a testing proc that wasn't intended for this PR.

* Removed parts of #24750 that also crept in.

* Made the variety of [x] goals more explicit that they want 50u of each.

* Reduced Kudzu trait requirement to 1.

* Request consoles now output the list of valid departments if you're at an unsupported one.

* Added personal crates.

* Added a supply pack of personal crates.

* Added special cargo handling for personal crates.

* Added automatic personal crate when requesting a goal.

* Required personal crates for most secondary goals.

* Add goal labels to the hand labeler, require them for mech goals.

* Made secondary goals one-per-person, not one-per-department.

* Added support for multi-line system messages to the request consoles.

* Made the RC message for goals nicer.

* Send goal crates even if no normal crates are ready, name and access-lock them properly.

* Don't double-label.

* Let's not use registered_account, names are fine.

* Add a ton of blackbox data to cargo and secondary goals.

* Fix a few bugs.

* More bugfixing, couple more stats.

* Even more stats.

* Text fix.

* Made cargo fines more consistent with other cargo feedback.

* Fixed a bug that prevented non-top-level items from being checked for CARGO_REQUIRE_PRIORITY.

* Blocked large crates from being sent back unopened.

* Enum values should probably be different from each other.

* Correct a bitflag mishap.

* Removed redundant supply shuttle docking and buy/sell attempts.

* Tweak message about personal crates to inlclude that they need to lock it.

* Add /Crates to the Personal Lockers description.

* Less pretty alignment, less complaining linters.

* Corrected a bad name in stats tracking.

* Reduced SciChem variety goal to 5 types.

* Toned down Task Backlog a bit.

* Fixed a bug that made unsellable items nested in containers be stolen by CC (qdeleted).

* Don't require bluespace 8, that's silly.

* Made secondary goals modifiable in the Modify Station Goals UI.

* Whoops, that was supposed to be 600u.

* i ded pls nerf

---------

Co-authored-by: synthtee <127706731+SynthTwo@users.noreply.github.com>
Co-authored-by: Henri215 <77684085+Henri215@users.noreply.github.com>
Co-authored-by: DGamerL <108773801+DGamerL@users.noreply.github.com>
This commit is contained in:
Charlie Nolan
2024-04-01 07:50:07 +00:00
committed by GitHub
co-authored by Henri215 DGamerL synthtee
parent 663e007d4d
commit 5c5f7842df
64 changed files with 2892 additions and 490 deletions
+2 -2
View File
@@ -284,7 +284,7 @@
//this is a hook for custom behaviour. Maybe at some point we could add checks to see if engines are intact
/obj/docking_port/mobile/proc/canMove()
return 0 //0 means we can move
return TRUE // TRUE means we can move. Why would it ever be otherwise?
//this is to check if this shuttle can physically dock at dock S
/obj/docking_port/mobile/proc/canDock(obj/docking_port/stationary/S)
@@ -450,7 +450,7 @@
if(!check_dock(S1))
return -1
if(canMove())
if(!canMove())
return -1
var/obj/docking_port/stationary/S0 = get_docked()
+721 -177
View File
@@ -1,5 +1,12 @@
#define MAX_CRATE_DELIVERY 40
#define CARGO_OK 0
#define CARGO_PREVENT_SHUTTLE 1
#define CARGO_SKIP_ATOM 2
#define CARGO_REQUIRE_PRIORITY 3
#define CARGO_HAS_PRIORITY 4
/obj/docking_port/mobile/supply
name = "supply shuttle"
id = "supply"
@@ -10,45 +17,57 @@
dwidth = 5
height = 7
// The list of things that can't be sent to CC.
var/list/blacklist = list(
"living creatures" = list(
/mob/living,
/obj/structure/blob,
/obj/structure/spider/spiderling,
/obj/machinery/clonepod,
/obj/item/paicard),
"classified nuclear weaponry" = list(
/obj/item/disk/nuclear,
/obj/machinery/nuclearbomb),
"homing beacons" = list(
/obj/item/radio/beacon,
/obj/machinery/quantumpad,
/obj/machinery/teleport/station,
/obj/machinery/teleport/hub,
/obj/machinery/telepad,
/obj/machinery/telepad_cargo,
/obj/structure/extraction_point),
"high-energy objects" = list(
/obj/singularity,
/obj/machinery/the_singularitygen,
/obj/effect/hierophant,
/obj/item/warp_cube),
"undelivered mail" = list(/obj/item/envelope))
// The current manifest of what's on the shuttle.
var/datum/economy/cargo_shuttle_manifest/manifest = new
// The auto-registered simple_seller instances.
var/list/simple_sellers = list()
// The item preventing this shuttle from going to CC.
var/blocking_item = "ERR_UNKNOWN"
/obj/docking_port/mobile/supply/Initialize()
..()
for(var/T in subtypesof(/datum/economy/simple_seller))
var/datum/economy/simple_seller/seller = new T
simple_sellers += seller
seller.register(src)
/obj/docking_port/mobile/supply/register()
if(!..())
return FALSE
SSshuttle.supply = src
return TRUE
/obj/docking_port/mobile/supply/proc/forbidden_atoms_check(atom/A)
var/list/blacklist = list(
/mob/living,
/obj/structure/blob,
/obj/structure/spider/spiderling,
/obj/item/disk/nuclear,
/obj/machinery/nuclearbomb,
/obj/item/radio/beacon,
/obj/machinery/the_singularitygen,
/obj/singularity,
/obj/machinery/teleport/station,
/obj/machinery/teleport/hub,
/obj/machinery/telepad,
/obj/machinery/telepad_cargo,
/obj/machinery/clonepod,
/obj/effect/hierophant,
/obj/item/warp_cube,
/obj/machinery/quantumpad,
/obj/structure/extraction_point,
/obj/item/envelope,
/obj/item/paicard)
if(A)
if(is_type_in_list(A, blacklist))
return TRUE
for(var/thing in A)
if(.(thing))
return TRUE
return FALSE
/obj/docking_port/mobile/supply/canMove()
if(is_station_level(z))
return forbidden_atoms_check(areaInstance)
return scan_cargo()
return ..()
/obj/docking_port/mobile/supply/request(obj/docking_port/stationary/S)
@@ -56,27 +75,30 @@
return 2
return ..()
/obj/docking_port/mobile/supply/dock()
/obj/docking_port/mobile/supply/dock(port)
. = ..()
if(.)
return
buy()
sell()
if(istype(port, /obj/docking_port/stationary/transit))
// Ignore transit ports.
return
if(is_station_level(z))
// Buy when arriving at the station.
buy()
if(z == level_name_to_num(CENTCOMM))
// Sell when arriving at CentComm.
sell()
/obj/docking_port/mobile/supply/proc/buy()
if(!is_station_level(z)) //we only buy when we are -at- the station
return 1
for(var/datum/supply_order/order as anything in SSeconomy.shopping_list)
if(length(SSeconomy.delivery_list) >= MAX_CRATE_DELIVERY)
break
SSeconomy.delivery_list += order
SSeconomy.shopping_list -= order
if(!length(SSeconomy.delivery_list))
return 2
var/list/emptyTurfs = list()
for(var/turf/simulated/T in areaInstance)
if(T.density)
@@ -108,151 +130,673 @@
SSeconomy.delivery_list.Cut()
/obj/docking_port/mobile/supply/proc/sell()
if(z != level_name_to_num(CENTCOMM)) //we only sell when we are -at- centcomm
return 1
for(var/datum/station_goal/secondary/SG in SSticker.mode.secondary_goals)
if(!SG.should_send_crate)
continue
var/plasma_count = 0
var/intel_count = 0
var/crate_count = 0
var/total_crate_value = 0
var/turf/T = pick_n_take(emptyTurfs) //turf we will place it in
if(!T)
break
var/obj/structure/closet/crate/secure/personal/PC = new(T)
if(SG.requester_name)
PC.name = "goal crate ([SG.requester_name] in [SG.department])"
PC.desc = "This personal crate has been configured by CC for [SG.requester_name]'s use in completing the secondary goal [SG.name]."
PC.registered_name = SG.requester_name
else
PC.name = "goal crate (Unknown in [SG.department])"
PC.locked = FALSE
PC.update_icon()
SG.should_send_crate = FALSE
/obj/docking_port/mobile/supply/proc/scan_cargo()
manifest = new
SEND_SIGNAL(src, COMSIG_CARGO_BEGIN_SCAN)
for(var/atom/movable/AM in areaInstance)
if(deep_scan(AM, TRUE) == CARGO_PREVENT_SHUTTLE)
return FALSE
return TRUE
/obj/docking_port/mobile/supply/proc/deep_scan(atom/movable/AM, top_level = FALSE)
var/handling = prefilter_atom(AM)
if(handling == CARGO_PREVENT_SHUTTLE)
return CARGO_PREVENT_SHUTTLE
var/found_priority = FALSE
for(var/atom/movable/child in AM)
var/child_handling = deep_scan(child)
if(child_handling == CARGO_PREVENT_SHUTTLE)
return CARGO_PREVENT_SHUTTLE
if(child_handling == CARGO_HAS_PRIORITY)
found_priority = TRUE
if(handling != CARGO_SKIP_ATOM)
if(handling == CARGO_REQUIRE_PRIORITY && !found_priority)
blocking_item = "locked containers that don't contain goal items ([AM])"
return CARGO_PREVENT_SHUTTLE
var/sellable = SEND_SIGNAL(src, COMSIG_CARGO_CHECK_SELL, AM)
manifest.items_to_sell[AM] = sellable
if(top_level && !(sellable & COMSIG_CARGO_IS_SECURED))
manifest.loose_cargo = TRUE
if(sellable & COMSIG_CARGO_SELL_PRIORITY)
if(top_level)
return CARGO_OK
return CARGO_HAS_PRIORITY
return CARGO_OK
/obj/docking_port/mobile/supply/proc/prefilter_atom(atom/movable/AM)
for(var/reason in blacklist)
if(is_type_in_list(AM, blacklist[reason]))
blocking_item = "[reason] ([AM])"
return CARGO_PREVENT_SHUTTLE
if(istype(AM, /obj/structure/largecrate))
blocking_item = "unopened large crates ([AM])"
return CARGO_PREVENT_SHUTTLE
if(istype(AM, /obj/structure/closet/crate))
var/obj/structure/closet/crate/C = AM
if(C.manifest)
blocking_item = "crates with their manifest still attached ([AM])"
return CARGO_PREVENT_SHUTTLE
if(istype(AM, /obj/structure/closet/crate/secure))
var/obj/structure/closet/crate/secure/SC = AM
if(SC.locked)
return CARGO_REQUIRE_PRIORITY
else if(istype(SC, /obj/structure/closet/crate/secure/personal))
blocking_item = "unlocked personal crates ([AM])"
return CARGO_PREVENT_SHUTTLE
if(istype(AM, /obj/item/storage/lockbox))
var/obj/item/storage/lockbox/LB = AM
if(LB.locked)
return CARGO_REQUIRE_PRIORITY
if(istype(AM, /obj/effect))
var/obj/effect/E = AM
if(E.is_cleanable())
return CARGO_OK
if(AM.anchored && !istype(AM, /obj/mecha/working))
return CARGO_SKIP_ATOM
return CARGO_OK
/obj/docking_port/mobile/supply/proc/sell()
SEND_SIGNAL(src, COMSIG_CARGO_BEGIN_SELL)
SSeconomy.sold_atoms = list()
var/list/qdel_atoms = list()
var/list/rescue_atoms = list()
for(var/atom/movable/AM in manifest.items_to_sell)
var/sellable = manifest.items_to_sell[AM]
if(sellable & COMSIG_CARGO_SELL_PRIORITY)
SEND_SIGNAL(src, COMSIG_CARGO_DO_PRIORITY_SELL, AM, manifest)
SSeconomy.sold_atoms += "[AM.name](priority)"
qdel_atoms += AM
continue
else if(sellable & COMSIG_CARGO_SELL_NORMAL)
SEND_SIGNAL(src, COMSIG_CARGO_DO_SELL, AM, manifest)
SSeconomy.sold_atoms += "[AM.name](normal)"
qdel_atoms += AM
continue
else if(sellable & COMSIG_CARGO_SELL_WRONG)
SEND_SIGNAL(src, COMSIG_CARGO_SEND_ERROR, AM, manifest)
SSeconomy.sold_atoms += "[AM.name](error)"
qdel_atoms += AM
continue
else if(sellable & COMSIG_CARGO_MESS)
manifest.messy_shuttle = TRUE
SSeconomy.sold_atoms += "[AM.name](mess)"
qdel_atoms += AM
continue
else if(!(sellable & COMSIG_CARGO_SELL_SKIP))
manifest.sent_trash = TRUE
rescue_atoms += AM
for(var/atom/movable/AM in rescue_atoms)
if(AM.loc in qdel_atoms)
AM.forceMove(get_turf(AM))
for(var/AM in qdel_atoms)
qdel(AM)
SEND_SIGNAL(src, COMSIG_CARGO_END_SELL, manifest)
SSblackbox.record_feedback("amount", "cargo shipments", 1)
if(manifest.loose_cargo)
var/datum/economy/line_item/item = new
item.account = SSeconomy.cargo_account
item.credits = SSeconomy.fine_for_loose_cargo
item.reason = "Please remember to secure all items in crates."
manifest.line_items += item
SSblackbox.record_feedback("nested tally", "cargo fines", 1, list("loose cargo", "amount"))
SSblackbox.record_feedback("nested tally", "cargo fines", SSeconomy.fine_for_loose_cargo, list("loose cargo", "credits"))
if(manifest.messy_shuttle)
var/datum/economy/line_item/item = new
item.account = SSeconomy.cargo_account
item.credits = SSeconomy.fine_for_messy_shuttle
item.reason = "Shuttle cleaning fee."
manifest.line_items += item
SSblackbox.record_feedback("nested tally", "cargo fines", 1, list("messy shuttle", "amount"))
SSblackbox.record_feedback("nested tally", "cargo fines", SSeconomy.fine_for_messy_shuttle, list("messy shuttle", "credits"))
if(manifest.sent_trash)
var/datum/economy/line_item/item = new
item.account = SSeconomy.cargo_account
item.credits = SSeconomy.fine_for_selling_trash
item.reason = "Don't send us random junk."
manifest.line_items += item
SSblackbox.record_feedback("nested tally", "cargo fines", 1, list("sent trash", "amount"))
SSblackbox.record_feedback("nested tally", "cargo fines", SSeconomy.fine_for_selling_trash, list("sent trash", "credits"))
var/msg = "<center>---[station_time_timestamp()]---</center><br>"
var/credits_to_deposit = 0
var/research_credits = 0
var/service_credits = 0
var/medical_credits = 0
for(var/atom/movable/MA in areaInstance)
if(MA.anchored)
continue
if(istype(MA, /mob/dead))
continue
if(istype(MA, /obj/structure/closet/crate/mail))
continue
SSeconomy.sold_atoms += " [MA.name]"
var/list/credit_changes = list()
for(var/datum/economy/line_item/item in manifest.line_items)
if(!credit_changes[item.account])
credit_changes[item.account] = 0
credit_changes[item.account] += item.credits
// Must be in a crate (or a critter crate)!
if(istype(MA, /obj/structure/closet/crate) || istype(MA, /obj/structure/closet/critter))
SSeconomy.sold_atoms += ":"
if(!length(MA.contents))
SSeconomy.sold_atoms += " (empty)"
if(istype(MA, /obj/structure/closet/crate))
var/obj/structure/closet/crate/exported_crate = MA
total_crate_value += exported_crate.crate_value
else
total_crate_value += DEFAULT_CRATE_VALUE
crate_count++
if(item.credits > 0)
msg += "<span class='good'>[item.account.account_name] +[item.credits]</span>: [item.reason]<br>"
else if(item.credits == 0)
msg += "<span class='[item.zero_is_good ? "good" : "bad"]'>[item.account.account_name] Notice</span>: [item.reason]<br>"
else
msg += "<span class='bad'>[item.account.account_name] [item.credits]</span>: [item.reason]<br>"
var/find_slip = TRUE
for(var/thing in MA)
// Sell manifests
SSeconomy.sold_atoms += " [thing:name]"
if(find_slip && istype(thing,/obj/item/paper/manifest))
var/obj/item/paper/manifest/slip = thing
credits_to_deposit += SSeconomy.credits_per_manifest
msg += "<span class='good'>+[SSeconomy.credits_per_manifest]</span>: Package [slip.ordernumber] accorded.<br>"
for(var/datum/money_account/account in credit_changes)
if(account.account_type == ACCOUNT_TYPE_DEPARTMENT)
SSblackbox.record_feedback("tally", "cargo profits", credit_changes[account], "[account.account_name]")
else
SSblackbox.record_feedback("tally", "cargo profits", credit_changes[account], "All personal accounts")
// Sell plasma
if(istype(thing, /obj/item/stack/sheet/mineral/plasma))
var/obj/item/stack/sheet/mineral/plasma/P = thing
plasma_count += P.amount
// Sell syndicate intel
if(istype(thing, /obj/item/documents/syndicate))
++intel_count
// Sell tech levels
if(istype(thing, /obj/item/disk/tech_disk))
var/obj/item/disk/tech_disk/disk = thing
if(!disk.stored)
continue
var/datum/tech/tech = disk.stored
var/cost = tech.getCost(SSeconomy.tech_levels[tech.id])
if(cost)
SSeconomy.tech_levels[tech.id] = tech.level
research_credits += cost / 2
credits_to_deposit += cost / 2
msg += "<span class='good'>+[cost]</span>: [tech.name] - new data.<br>"
// Sell designs
if(istype(thing, /obj/item/disk/design_disk))
var/obj/item/disk/design_disk/disk = thing
if(!disk.blueprint)
continue
var/datum/design/design = disk.blueprint
if(design.id in SSeconomy.research_designs)
continue
credits_to_deposit += SSeconomy.credits_per_design
SSeconomy.research_designs += design.id
msg += "<span class='good'>+[SSeconomy.credits_per_design]</span>: [design.name] design.<br>"
// Sell viral sample virology goals, those in vial lockboxes included
if(istype(thing, /obj/item/reagent_containers) || istype(thing, /obj/item/storage/lockbox/vials))
var/list/sold_containers = list()
if(istype(thing, /obj/item/reagent_containers))
sold_containers += thing
if(istype(thing, /obj/item/storage/lockbox/vials))
for(var/obj/item/reagent_containers/C in thing)
sold_containers += C
for(var/obj/item/reagent_containers/C in sold_containers)
if(C.reagents?.reagent_list)
for(var/datum/virology_goal/G in GLOB.virology_goals)
if(G.completed)
continue
if(G.check_completion(C.reagents.reagent_list))
medical_credits += SSeconomy.credits_per_virology_goal
msg += "<span class='good'>+[SSeconomy.credits_per_virology_goal]</span>: [G.name] completion.<br>"
// Sell exotic plants
if(istype(thing, /obj/item/seeds))
var/obj/item/seeds/S = thing
if(S.rarity == 0) // Mundane species
msg += "<span class='bad'>+0</span>: We don't need samples of mundane species \"[capitalize(S.species)]\".<br>"
else if(SSeconomy.discovered_plants[S.type]) // This species has already been sent to CentComm
var/potDiff = S.potency - SSeconomy.discovered_plants[S.type] // Compare it to the previous best
if(potDiff > 0) // This sample is better
SSeconomy.discovered_plants[S.type] = S.potency
msg += "<span class='good'>+[potDiff]</span>: New sample of \"[capitalize(S.species)]\" is superior. Good work.<br>"
service_credits += potDiff / 2
credits_to_deposit += potDiff / 2
else // This sample is worthless
msg += "<span class='bad'>+0</span>: New sample of \"[capitalize(S.species)]\" is not more potent than existing sample ([SSeconomy.discovered_plants[S.type]] potency).<br>"
else // This is a new discovery!
SSeconomy.discovered_plants[S.type] = S.potency
msg += "<span class='good'>[S.rarity]</span>: New species discovered: \"[capitalize(S.species)]\". Excellent work.<br>"
service_credits += S.rarity / 2 // That's right, no bonus for potency. Send a crappy sample first to "show improvement" later
credits_to_deposit += S.rarity / 2
if(istype(thing, /obj/item/organ/internal/alien))
var/obj/item/organ/internal/alien/organ = thing
credits_to_deposit += organ.cargo_profit
qdel(MA)
SSeconomy.sold_atoms += "."
if(plasma_count > 0)
var/credits_from_plasma = plasma_count * SSeconomy.credits_per_plasma
msg += "<span class='good'>+[credits_from_plasma]</span>: Received [plasma_count] unit(s) of exotic material.<br>"
credits_to_deposit += credits_from_plasma
if(intel_count > 0)
var/credits_from_intel = intel_count * SSeconomy.credits_per_intel
msg += "<span class='good'>+[credits_from_intel]</span>: Received [intel_count] article(s) of enemy intelligence.<br>"
credits_to_deposit += credits_from_intel
if(crate_count > 0)
msg += "<span class='good'>+[total_crate_value]</span>: Received [crate_count] crate(s).<br>"
credits_to_deposit += total_crate_value
if(credit_changes[account] > 0)
GLOB.station_money_database.credit_account(account, credit_changes[account], "Supply Shuttle Exports Payment", "Central Command Supply Master", supress_log = FALSE)
else
GLOB.station_money_database.charge_account(account, -credit_changes[account], "Supply Shuttle Fine", "Central Command Supply Master", allow_overdraft = TRUE, supress_log = FALSE)
SSeconomy.centcom_message += "[msg]<hr>"
if(credits_to_deposit > 0)
GLOB.station_money_database.credit_account(SSeconomy.cargo_account, credits_to_deposit, "Supply Shuttle Exports Payment", "Central Command Supply Master", supress_log = FALSE)
if(research_credits)
GLOB.station_money_database.credit_account(GLOB.station_money_database.get_account_by_department(DEPARTMENT_SCIENCE), research_credits, "Supply Shuttle Exports Payment", "Central Command Supply Master", supress_log = FALSE)
if(service_credits)
GLOB.station_money_database.credit_account(GLOB.station_money_database.get_account_by_department(DEPARTMENT_SERVICE), service_credits, "Supply Shuttle Exports Payment", "Central Command Supply Master", supress_log = FALSE)
if(medical_credits)
GLOB.station_money_database.credit_account(GLOB.station_money_database.get_account_by_department(DEPARTMENT_MEDICAL), medical_credits, "Supply Shuttle Exports Payment", "Central Command Supply Master", supress_log = FALSE)
manifest = new
// Convenience object that registers itself with the supply shuttle and provides
// methods for you to override.
/datum/economy/simple_seller
/datum/economy/simple_seller/proc/register(obj/docking_port/mobile/supply/S)
RegisterSignal(S, COMSIG_CARGO_BEGIN_SCAN, PROC_REF(begin_scan))
RegisterSignal(S, COMSIG_CARGO_CHECK_SELL, PROC_REF(check_sell))
RegisterSignal(S, COMSIG_CARGO_BEGIN_SELL, PROC_REF(begin_sell))
RegisterSignal(S, COMSIG_CARGO_DO_PRIORITY_SELL, PROC_REF(sell_priority))
RegisterSignal(S, COMSIG_CARGO_DO_SELL, PROC_REF(sell_normal))
RegisterSignal(S, COMSIG_CARGO_SEND_ERROR, PROC_REF(sell_wrong))
RegisterSignal(S, COMSIG_CARGO_END_SELL, PROC_REF(end_sell))
/datum/economy/simple_seller/proc/begin_scan(obj/docking_port/mobile/supply/S)
SIGNAL_HANDLER // COMSIG_CARGO_BEGIN_SCAN
return
/datum/economy/simple_seller/proc/check_sell(obj/docking_port/mobile/supply/S, atom/movable/AM)
SIGNAL_HANDLER // COMSIG_CARGO_CHECK_SELL
return NONE
/datum/economy/simple_seller/proc/begin_sell(obj/docking_port/mobile/supply/S)
SIGNAL_HANDLER // COMSIG_CARGO_BEGIN_SELL
return
/datum/economy/simple_seller/proc/sell_priority(obj/docking_port/mobile/supply/S, atom/movable/AM, datum/economy/cargo_shuttle_manifest/manifest)
SIGNAL_HANDLER // COMSIG_CARGO_DO_PRIORITY_SELL
return check_sell(S, AM) & COMSIG_CARGO_SELL_PRIORITY
/datum/economy/simple_seller/proc/sell_normal(obj/docking_port/mobile/supply/S, atom/movable/AM, datum/economy/cargo_shuttle_manifest/manifest)
SIGNAL_HANDLER // COMSIG_CARGO_DO_SELL
return check_sell(S, AM) & COMSIG_CARGO_SELL_NORMAL
/datum/economy/simple_seller/proc/sell_wrong(obj/docking_port/mobile/supply/S, atom/movable/AM, datum/economy/cargo_shuttle_manifest/manifest)
SIGNAL_HANDLER // COMSIG_CARGO_SEND_ERROR
return check_sell(S, AM) & COMSIG_CARGO_SELL_WRONG
/datum/economy/simple_seller/proc/end_sell(obj/docking_port/mobile/supply/S, datum/economy/cargo_shuttle_manifest/manifest)
SIGNAL_HANDLER // COMSIG_CARGO_END_SELL
return
/datum/economy/simple_seller/crates
var/crates = 0
var/credits = 0
/datum/economy/simple_seller/crates/begin_sell(obj/docking_port/mobile/supply/S)
crates = 0
credits = 0
/datum/economy/simple_seller/crates/check_sell(obj/docking_port/mobile/supply/S, AM)
if(istype(AM, /obj/structure/closet/crate) || istype(AM, /obj/structure/closet/critter) || istype(AM, /obj/structure/closet/crate/mail))
return COMSIG_CARGO_SELL_NORMAL | COMSIG_CARGO_IS_SECURED
/datum/economy/simple_seller/crates/sell_normal(obj/docking_port/mobile/supply/S, atom/movable/AM, datum/economy/cargo_shuttle_manifest/manifest)
if(!..())
return
crates += 1
if(istype(AM, /obj/structure/closet/crate))
var/obj/structure/closet/crate/exported_crate = AM
credits += exported_crate.crate_value
else
credits += DEFAULT_CRATE_VALUE
/datum/economy/simple_seller/crates/end_sell(obj/docking_port/mobile/supply/S, datum/economy/cargo_shuttle_manifest/manifest)
if(!credits)
return
var/datum/economy/line_item/item = new
item.account = SSeconomy.cargo_account
item.credits = credits
item.reason = "Returned [crates] crate(s)."
manifest.line_items += item
SSblackbox.record_feedback("tally", "cargo crates sold", crates, "amount")
SSblackbox.record_feedback("tally", "cargo crates sold", item.credits, "credits")
/datum/economy/simple_seller/plasma
var/plasma = 0
/datum/economy/simple_seller/plasma/begin_sell(obj/docking_port/mobile/supply/S)
plasma = 0
/datum/economy/simple_seller/plasma/check_sell(obj/docking_port/mobile/supply/S, atom/movable/AM)
if(istype(AM, /obj/item/stack/sheet/mineral/plasma))
return COMSIG_CARGO_SELL_NORMAL
/datum/economy/simple_seller/plasma/sell_normal(obj/docking_port/mobile/supply/S, atom/movable/AM, datum/economy/cargo_shuttle_manifest/manifest)
if(!..())
return
var/obj/item/stack/sheet/mineral/plasma/P = AM
plasma += P.amount
/datum/economy/simple_seller/plasma/end_sell(obj/docking_port/mobile/supply/S, datum/economy/cargo_shuttle_manifest/manifest)
if(!plasma)
return
var/datum/economy/line_item/item = new
item.account = SSeconomy.cargo_account
item.credits = plasma * SSeconomy.credits_per_plasma
item.reason = "Received [plasma] unit(s) of exotic material."
manifest.line_items += item
SSblackbox.record_feedback("tally", "cargo plasma sold", plasma, "amount")
SSblackbox.record_feedback("tally", "cargo plasma sold", item.credits, "credits")
/datum/economy/simple_seller/intel
var/intel = 0
/datum/economy/simple_seller/intel/begin_sell(obj/docking_port/mobile/supply/S)
intel = 0
/datum/economy/simple_seller/intel/check_sell(obj/docking_port/mobile/supply/S, atom/movable/AM)
if(istype(AM, /obj/item/documents/syndicate))
return COMSIG_CARGO_SELL_NORMAL
/datum/economy/simple_seller/intel/sell_normal(obj/docking_port/mobile/supply/S, atom/movable/AM, datum/economy/cargo_shuttle_manifest/manifest)
if(!..())
return
intel++
/datum/economy/simple_seller/intel/end_sell(obj/docking_port/mobile/supply/S, datum/economy/cargo_shuttle_manifest/manifest)
if(!intel)
return
var/datum/economy/line_item/item = new
item.account = SSeconomy.cargo_account
item.credits = intel * SSeconomy.credits_per_intel
item.reason = "Received [intel] article(s) of enemy intelligence."
manifest.line_items += item
SSblackbox.record_feedback("tally", "cargo intel sold", intel, "amount")
SSblackbox.record_feedback("tally", "cargo intel sold", item.credits, "credits")
/datum/economy/simple_seller/alien_organs
/datum/economy/simple_seller/alien_organs/check_sell(obj/docking_port/mobile/supply/S, atom/movable/AM)
if(istype(AM, /obj/item/organ/internal/alien))
return COMSIG_CARGO_SELL_NORMAL
/datum/economy/simple_seller/alien_organs/sell_normal(obj/docking_port/mobile/supply/S, atom/movable/AM, datum/economy/cargo_shuttle_manifest/manifest)
if(!..())
return
var/obj/item/organ/internal/alien/organ = AM
var/datum/economy/line_item/item = new
item.account = SSeconomy.cargo_account
item.credits = organ.cargo_profit
item.reason = "Received a sample of exotic biological tissue."
manifest.line_items += item
SSblackbox.record_feedback("tally", "cargo alien organs sold", 1, "amount")
SSblackbox.record_feedback("tally", "cargo alien organs sold", item.credits, "credits")
/datum/economy/simple_seller/shipping_manifests
/datum/economy/simple_seller/shipping_manifests/check_sell(obj/docking_port/mobile/supply/S, atom/movable/AM)
if(istype(AM,/obj/item/paper/manifest))
return COMSIG_CARGO_SELL_NORMAL
/datum/economy/simple_seller/shipping_manifests/sell_normal(obj/docking_port/mobile/supply/S, atom/movable/AM, datum/economy/cargo_shuttle_manifest/manifest)
if(!..())
return
var/obj/item/paper/manifest/slip = AM
var/datum/economy/line_item/item = new
item.account = SSeconomy.cargo_account
item.credits = SSeconomy.credits_per_manifest
item.reason = "Package [slip.ordernumber] accorded."
manifest.line_items += item
SSblackbox.record_feedback("tally", "cargo manifests sold", 1, "amount")
SSblackbox.record_feedback("tally", "cargo manifests sold", item.credits, "credits")
/datum/economy/simple_seller/tech_levels
var/list/temp_tech_levels
/datum/economy/simple_seller/tech_levels/begin_scan(obj/docking_port/mobile/supply/S)
temp_tech_levels = SSeconomy.tech_levels.Copy()
/datum/economy/simple_seller/tech_levels/begin_sell(obj/docking_port/mobile/supply/S)
temp_tech_levels = SSeconomy.tech_levels.Copy()
/datum/economy/simple_seller/tech_levels/check_sell(obj/docking_port/mobile/supply/S, atom/movable/AM)
if(istype(AM, /obj/item/disk/tech_disk))
var/obj/item/disk/tech_disk/disk = AM
if(!disk.stored)
return COMSIG_CARGO_SELL_WRONG
var/datum/tech/tech = disk.stored
var/cost = tech.getCost(temp_tech_levels[tech.id])
if(cost)
temp_tech_levels[tech.id] = tech.level
return COMSIG_CARGO_SELL_NORMAL
return COMSIG_CARGO_SELL_WRONG
/datum/economy/simple_seller/tech_levels/sell_normal(obj/docking_port/mobile/supply/S, atom/movable/AM, datum/economy/cargo_shuttle_manifest/manifest)
if(!..())
return
var/obj/item/disk/tech_disk/disk = AM
if(!disk.stored)
return
var/datum/tech/tech = disk.stored
var/cost = tech.getCost(SSeconomy.tech_levels[tech.id])
if(!cost)
return
SSeconomy.tech_levels[tech.id] = tech.level
SSblackbox.record_feedback("tally", "cargo tech disks sold", 1, "amount")
SSblackbox.record_feedback("tally", "cargo tech disks sold", cost, "credits")
var/datum/economy/line_item/cargo_item = new
cargo_item.account = SSeconomy.cargo_account
cargo_item.credits = cost / 2
cargo_item.reason = "[tech.name] - new data."
manifest.line_items += cargo_item
var/datum/economy/line_item/science_item = new
science_item.account = GLOB.station_money_database.get_account_by_department(DEPARTMENT_SCIENCE)
science_item.credits = cost / 2
science_item.reason = "[tech.name] - new data."
manifest.line_items += science_item
/datum/economy/simple_seller/tech_levels/sell_wrong(obj/docking_port/mobile/supply/S, atom/movable/AM, datum/economy/cargo_shuttle_manifest/manifest)
if(!..())
return
var/datum/economy/line_item/item = new
item.account = GLOB.station_money_database.get_account_by_department(DEPARTMENT_SCIENCE)
item.credits = 0
var/obj/item/disk/tech_disk/disk = AM
if(!disk.stored)
item.reason = "Blank tech disk."
manifest.line_items += item
SSblackbox.record_feedback("tally", "cargo tech disks sold", 1, "blank")
return
var/datum/tech/tech = disk.stored
var/cost = tech.getCost(SSeconomy.tech_levels[tech.id])
if(!cost)
item.reason = "[tech.name] - no new data."
manifest.line_items += item
SSblackbox.record_feedback("tally", "cargo tech disks sold", 1, "repeat")
/datum/economy/simple_seller/designs
var/list/temp_designs
/datum/economy/simple_seller/designs/begin_scan(obj/docking_port/mobile/supply/S)
temp_designs = SSeconomy.research_designs.Copy()
/datum/economy/simple_seller/designs/begin_sell(obj/docking_port/mobile/supply/S)
temp_designs = SSeconomy.research_designs.Copy()
/datum/economy/simple_seller/designs/check_sell(obj/docking_port/mobile/supply/S, atom/movable/AM)
if(istype(AM, /obj/item/disk/design_disk))
var/obj/item/disk/design_disk/disk = AM
if(!disk.blueprint)
return COMSIG_CARGO_SELL_WRONG
var/datum/design/design = disk.blueprint
if(design.id in temp_designs)
return COMSIG_CARGO_SELL_WRONG
temp_designs += design.id
return COMSIG_CARGO_SELL_NORMAL
/datum/economy/simple_seller/designs/sell_normal(obj/docking_port/mobile/supply/S, atom/movable/AM, datum/economy/cargo_shuttle_manifest/manifest)
if(!..())
return
var/obj/item/disk/design_disk/disk = AM
if(!disk.blueprint)
return
var/datum/design/design = disk.blueprint
if(design.id in SSeconomy.research_designs)
return
SSeconomy.research_designs += design.id
SSblackbox.record_feedback("tally", "cargo design disks sold", 1, "amount")
SSblackbox.record_feedback("tally", "cargo design disks sold", SSeconomy.credits_per_design, "credits")
var/datum/economy/line_item/cargo_item = new
cargo_item.account = SSeconomy.cargo_account
cargo_item.credits = SSeconomy.credits_per_design / 2
cargo_item.reason = "[design.name] design."
manifest.line_items += cargo_item
var/datum/economy/line_item/science_item = new
science_item.account = GLOB.station_money_database.get_account_by_department(DEPARTMENT_SCIENCE)
science_item.credits = SSeconomy.credits_per_design / 2
science_item.reason = "[design.name] design."
manifest.line_items += science_item
/datum/economy/simple_seller/designs/sell_wrong(obj/docking_port/mobile/supply/S, atom/movable/AM, datum/economy/cargo_shuttle_manifest/manifest)
if(!..())
return
var/datum/economy/line_item/item = new
item.account = GLOB.station_money_database.get_account_by_department(DEPARTMENT_SCIENCE)
item.credits = 0
var/obj/item/disk/design_disk/disk = AM
if(!disk.blueprint)
item.reason = "Blank design disk."
manifest.line_items += item
SSblackbox.record_feedback("tally", "cargo design disks sold", 1, "blank")
return
var/datum/design/design = disk.blueprint
if(design.id in SSeconomy.research_designs)
item.reason = "Duplicate design for [design.name]."
manifest.line_items += item
SSblackbox.record_feedback("tally", "cargo design disks sold", 1, "repeat")
return
/datum/economy/simple_seller/seeds
var/list/temp_discovered
/datum/economy/simple_seller/seeds/begin_scan(obj/docking_port/mobile/supply/S)
temp_discovered = SSeconomy.discovered_plants.Copy()
/datum/economy/simple_seller/seeds/begin_sell(obj/docking_port/mobile/supply/S)
temp_discovered = SSeconomy.discovered_plants.Copy()
/datum/economy/simple_seller/seeds/check_sell(obj/docking_port/mobile/supply/S, atom/movable/AM)
if(istype(AM, /obj/item/seeds))
var/obj/item/seeds/seed = AM
if(seed.rarity == 0) // Mundane species
return COMSIG_CARGO_SELL_WRONG
if(!temp_discovered[seed.type] || temp_discovered[seed.type] < seed.potency)
temp_discovered[seed.type] = seed.potency
return COMSIG_CARGO_SELL_NORMAL
return COMSIG_CARGO_SELL_WRONG
/datum/economy/simple_seller/seeds/sell_normal(obj/docking_port/mobile/supply/S, atom/movable/AM, datum/economy/cargo_shuttle_manifest/manifest)
if(!..())
return
var/msg = ""
var/credits = 0
var/obj/item/seeds/seed = AM
if(seed.rarity == 0) // Mundane species
return
else if(SSeconomy.discovered_plants[seed.type])
// This species has already been sent to CentComm
// Compare it to the previous best
var/potDiff = seed.potency - SSeconomy.discovered_plants[seed.type]
if(potDiff > 0)
SSeconomy.discovered_plants[seed.type] = seed.potency
credits = potDiff
msg = "New sample of \"[capitalize(seed.species)]\" is superior. Good work."
SSblackbox.record_feedback("tally", "cargo seeds sold", 1, "improved")
else
// This is a new discovery!
SSeconomy.discovered_plants[seed.type] = seed.potency
credits = seed.rarity + seed.potency
msg = "New species discovered: \"[capitalize(seed.species)]\". Excellent work."
SSblackbox.record_feedback("tally", "cargo seeds sold", 1, "new")
if(credits == 0)
return
SSblackbox.record_feedback("tally", "cargo seeds sold", 1, "amount")
SSblackbox.record_feedback("tally", "cargo seeds sold", credits, "credits")
var/datum/economy/line_item/cargo_item = new
cargo_item.account = SSeconomy.cargo_account
cargo_item.credits = credits / 2
cargo_item.reason = msg
manifest.line_items += cargo_item
var/datum/economy/line_item/service_item = new
service_item.account = GLOB.station_money_database.get_account_by_department(DEPARTMENT_SERVICE)
service_item.credits = credits / 2
service_item.reason = msg
manifest.line_items += service_item
/datum/economy/simple_seller/seeds/sell_wrong(obj/docking_port/mobile/supply/S, atom/movable/AM, datum/economy/cargo_shuttle_manifest/manifest)
if(!..())
return
var/datum/economy/line_item/item = new
item.account = GLOB.station_money_database.get_account_by_department(DEPARTMENT_SERVICE)
item.credits = 0
var/obj/item/seeds/seed = AM
if(seed.rarity == 0)
item.reason = "We don't need samples of mundane species \"[capitalize(seed.species)]\"."
manifest.line_items += item
SSblackbox.record_feedback("tally", "cargo seeds sold", 1, "boring")
else if(SSeconomy.discovered_plants[seed.type] && SSeconomy.discovered_plants[seed.type] < seed.potency)
item.reason = "New sample of \"[capitalize(seed.species)]\" is not more potent than existing sample ([SSeconomy.discovered_plants[seed.type]] potency)."
manifest.line_items += item
SSblackbox.record_feedback("tally", "cargo seeds sold", 1, "repeat")
// If neither succeeds, this seed was declared wrong by a different
// seller, so we should be quiet.
/datum/economy/simple_seller/messes
/datum/economy/simple_seller/messes/check_sell(obj/docking_port/mobile/supply/S, atom/movable/AM)
if(istype(AM, /obj/effect))
var/obj/effect/E = AM
if(E.is_cleanable())
return COMSIG_CARGO_MESS | COMSIG_CARGO_IS_SECURED
/datum/economy/simple_seller/containers
/datum/economy/simple_seller/containers/check_sell(obj/docking_port/mobile/supply/S, atom/movable/AM)
if(istype(AM, /obj/item/storage))
return COMSIG_CARGO_SELL_NORMAL
/datum/economy/simple_seller/containers/sell_normal(obj/docking_port/mobile/supply/S, atom/movable/AM, datum/economy/cargo_shuttle_manifest/manifest)
if(!..())
return
SSblackbox.record_feedback("amount", "cargo containers sold", 1)
/datum/economy/simple_seller/mechs
/datum/economy/simple_seller/mechs/sell_normal(obj/docking_port/mobile/supply/S, atom/movable/AM, datum/economy/cargo_shuttle_manifest/manifest)
if(!..())
return
SSblackbox.record_feedback("tally", "cargo basic mechs sold", 1, "amount")
SSblackbox.record_feedback("tally", "cargo basic mechs sold", SSeconomy.credits_per_mech, "credits")
var/datum/economy/line_item/cargo_item = new
cargo_item.account = SSeconomy.cargo_account
cargo_item.credits = SSeconomy.credits_per_mech / 2
cargo_item.reason = "Received a working [AM.name], great job!"
manifest.line_items += cargo_item
var/datum/economy/line_item/science_item = new
science_item.account = GLOB.station_money_database.get_account_by_department(DEPARTMENT_SCIENCE)
science_item.credits = SSeconomy.credits_per_mech / 2
science_item.reason = "Received a working [AM.name], great job!"
manifest.line_items += science_item
/datum/economy/simple_seller/mechs/check_sell(obj/docking_port/mobile/supply/S, atom/movable/AM)
if(istype(AM, /obj/mecha/working))
return COMSIG_CARGO_SELL_NORMAL | COMSIG_CARGO_IS_SECURED
// Skip mech parts to avoid complaining about them.
/datum/economy/simple_seller/mech_parts
/datum/economy/simple_seller/mech_parts/check_sell(obj/docking_port/mobile/supply/S, atom/movable/AM)
if(istype(AM.loc, /obj/mecha/working))
return COMSIG_CARGO_SELL_SKIP
/datum/economy/cargo_shuttle_manifest
var/list/items_to_sell = list()
var/list/line_items = list()
var/loose_cargo = FALSE
var/messy_shuttle = FALSE
var/sent_trash = FALSE
/datum/economy/line_item
var/datum/money_account/account
var/credits
var/reason
var/zero_is_good = FALSE
#undef MAX_CRATE_DELIVERY
#undef CARGO_OK
#undef CARGO_PREVENT_SHUTTLE
#undef CARGO_SKIP_ATOM
#undef CARGO_REQUIRE_PRIORITY
#undef CARGO_HAS_PRIORITY