Files
RoxyandGitHub 62c08cd213 Fix broken default_deconstruction_screwdriver calls (#5673)
## About The Pull Request

The proc no longer takes icon state arguments so these calls are all
broken now

## Why It's Good For The Game

Makes a bunch of stuff not runtime when you try to open the panel on it

## Proof Of Testing

I spawned in every object changed and tested screwdrivering the panel
open and closed

## Changelog
🆑
fix: fixed screwdrivering certain machines not working
/🆑
2026-05-28 13:46:58 -04:00

386 lines
14 KiB
Plaintext

/obj/item/circuitboard/machine/export_gate
name = "Export Gate"
greyscale_colors = CIRCUIT_COLOR_SUPPLY
build_path = /obj/machinery/export_gate
req_components = list(
/datum/stock_part/scanning_module = 3,
/datum/stock_part/card_reader = 1,
)
/datum/supply_pack/service/export_gate
name = "Bounty Cube Export Gate"
desc = "Automatically registers bounty cube exports, for the logistics automation nerd in you."
cost = CARGO_CRATE_VALUE * 2
contains = list(/obj/item/flatpack/export_gate)
crate_name = "export gate crate"
/obj/machinery/export_gate
name = "export gate"
desc = "Automatically registers bounty cube exports, for the logistics automation nerd in you. Pays out to active cargo techs."
icon = 'icons/obj/machines/scangate.dmi'
icon_state = "scangate_black"
circuit = /obj/item/circuitboard/machine/export_gate
/// Used to secure changing of payment mode
req_one_access = list(ACCESS_QM, ACCESS_ALL_PERSONAL_LOCKERS)
/// Cooldown on the scanner's beep
COOLDOWN_DECLARE(scanner_beep)
/// Cooldown on payout calculation
COOLDOWN_DECLARE(export_payout)
/// Internal timer for scanlines
var/scanline_timer
/// Current scanline icon state
var/scanline_state
/// Bool to check if the scanner's controls are locked by an ID.
var/locked = FALSE
/// The holding bank account used for the export gate
var/datum/bank_account/holding_account
/// Which crew members receive a share of the scanned bounties
var/payment_mode = EX_CARGO_TECHNICIAN | EX_CUSTOMS_AGENT
/// List of crew accounts associated with the current payment mode
var/list/payment_accounts
///Our internal radio
var/obj/item/radio/radio
///The key our internal radio uses
var/radio_key = /obj/item/encryptionkey/headset_cargo
/// The amount of cubes scanned
var/cubes_registered = 0
/// The share paid to each cargo tech last cycle
var/income_share = 0
/// Total payments sent out last cycle
var/income_previous = 0
/// Total payments sent lifetime
var/income_total = 0
/obj/machinery/export_gate/Initialize(mapload)
. = ..()
id_tag = assign_random_name()
if(name == initial(name))
name = "[initial(name)] [id_tag]"
var/static/list/loc_connections = list(
COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
)
register_context()
AddElement(/datum/element/connect_loc, loc_connections)
holding_account = new(name, player_account = FALSE)
holding_account.replaceable = FALSE
radio = new(src)
radio.keyslot = new radio_key
radio.set_listening(FALSE)
radio.recalculateChannels()
align_to_belt()
return INITIALIZE_HINT_LATELOAD
/obj/machinery/export_gate/post_machine_initialize()
. = ..()
set_scanline("passive")
/obj/machinery/export_gate/proc/align_to_belt()
if(isturf(loc))
var/turf/location = loc
var/obj/machinery/conveyor/my_conveyor = locate(/obj/machinery/conveyor) in location
if(my_conveyor)
dir = my_conveyor.dir
set_scanline("passive")
else
clear_scanline()
/obj/machinery/export_gate/Destroy()
disperse_earnings()
QDEL_NULL(radio)
return ..()
/obj/machinery/export_gate/add_context(atom/source, list/context, obj/item/held_item, mob/user)
. = ..()
if(held_item?.tool_behaviour == TOOL_WRENCH)
context[SCREENTIP_CONTEXT_RMB] = "[anchored ? "un" : ""]anchor gate"
return CONTEXTUAL_SCREENTIP_SET
if(held_item?.tool_behaviour == TOOL_SCREWDRIVER)
context[SCREENTIP_CONTEXT_LMB] = "[panel_open ? "close" : "open"] maintenance panel"
return CONTEXTUAL_SCREENTIP_SET
if(held_item?.tool_behaviour == TOOL_SCREWDRIVER && panel_open)
context[SCREENTIP_CONTEXT_LMB] = "deconstruct gate"
return CONTEXTUAL_SCREENTIP_SET
/obj/machinery/export_gate/proc/on_entered(datum/source, atom/movable/package)
SIGNAL_HANDLER
INVOKE_ASYNC(src, PROC_REF(auto_scan), package)
/obj/machinery/export_gate/examine()
. = ..()
. += span_notice("The status display reads:")
. += span_info("Income last cycle: <b>[income_previous] cr.</b>")
. += span_info("Share per account last cycle: <b>[income_share] cr.</b>")
. += span_info("Payment mode: <b>[display_payment_mode()].</b>")
. += span_info("Registered crew accounts last cycle: <b>[LAZYLEN(payment_accounts)]</b>")
. += span_info("Total cubes registered: <b>[cubes_registered]</b>")
. += span_info("Total income: <b>[income_total] cr.</b>")
. += span_notice("The payment mode can be changed by swiping an authorized command ID card.")
/obj/machinery/export_gate/wrench_act(mob/living/user, obj/item/tool)
default_unfasten_wrench(user, tool)
density = !anchored
if(anchored)
align_to_belt()
else
clear_scanline()
return ITEM_INTERACT_SUCCESS
/obj/machinery/export_gate/crowbar_act(mob/living/user, obj/item/tool)
default_deconstruction_crowbar(tool)
return TRUE
/obj/machinery/export_gate/screwdriver_act(mob/living/user, obj/item/tool)
return default_deconstruction_screwdriver(user, tool)
/obj/machinery/export_gate/update_icon_state()
. = ..()
if(panel_open)
icon_state = "[initial(icon_state)]_open"
return
icon_state = initial(icon_state)
/obj/machinery/export_gate/update_overlays()
. = ..()
if(scanline_state && !panel_open)
. += scanline_state
/obj/machinery/export_gate/proc/clear_scanline()
scanline_state = null
deltimer(scanline_timer)
update_appearance()
/obj/machinery/export_gate/proc/set_scanline(type, duration)
scanline_state = type
deltimer(scanline_timer)
update_appearance()
if(duration)
scanline_timer = addtimer(CALLBACK(src, PROC_REF(set_scanline), "passive"), duration, TIMER_STOPPABLE)
if(COOLDOWN_FINISHED(src, scanner_beep) && type != "passive")
COOLDOWN_START(src, scanner_beep, 0.5 SECONDS)
playsound(src, type == "alarm" ? 'sound/machines/buzz/buzz-sigh.ogg' : 'sound/machines/chime.ogg', 45, TRUE)
/obj/machinery/export_gate/proc/auto_scan(atom/movable/package)
if(is_operational && istype(package, /obj/item/bounty_cube) && (!panel_open) && anchored)
perform_scan(package)
/obj/machinery/export_gate/proc/perform_scan(obj/item/package)
var/obj/item/bounty_cube/cube = package
if(cube.bounty_handler_account)
set_scanline("alarm", 1 SECONDS)
say("Scan rejected. Error 403: Bank account for handling tip already registered!")
else if(cube.bounty_value)
set_scanline("scanning", 1 SECONDS)
process_cube(cube)
else if(cube.bounty_value == 0)
set_scanline("alarm", 1 SECONDS)
say("Scan rejected. Error 404: Bounty value not found!")
else
set_scanline("alarm", 1 SECONDS)
say("Scan rejected. Error 500: Check cube for errors and try again.")
use_energy(active_power_usage)
/obj/machinery/export_gate/proc/process_cube(obj/item/incoming_cube)
var/obj/item/bounty_cube/cube = incoming_cube
var/datum/export_report/cube_contents = export_item_and_contents(cube, dry_run = TRUE)
var/cube_value = 0
for(var/exported_datum in cube_contents.total_amount)
cube_value += cube_contents.total_value[exported_datum]
cube.AddComponent(/datum/component/pricetag, holding_account, cube.handler_tip, FALSE)
cube.bounty_handler_account = holding_account
cubes_registered += 1
var/message = "Cube value of [cube_value ? "[floor(cube_value * cube.handler_tip)] credits " : ""]successfully registered."
say(message)
for(var/datum/bank_account/tech_account as anything in payment_accounts)
tech_account.bank_card_talk(message)
#define MODE_CARGO_TECH "Cargo Technician"
#define MODE_CUSTOMS_AGENT "Cargo Technician / Customs Agent"
#define MODE_QUARTERMASTER "Cargo Technician / Customs Agent / Quartermaster"
/obj/machinery/export_gate/proc/set_payment_mode(mob/user, obj/item/card/id/id_card)
var/list/payment_modes = list(MODE_CARGO_TECH, MODE_CUSTOMS_AGENT, MODE_QUARTERMASTER)
var/selected_mode = tgui_input_list(user, "Set bounty payment mode:", src.name, payment_modes)
if(!selected_mode)
return
switch(selected_mode)
if(MODE_CARGO_TECH)
payment_mode = EX_CARGO_TECHNICIAN
if(MODE_CUSTOMS_AGENT)
payment_mode = EX_CARGO_TECHNICIAN | EX_CUSTOMS_AGENT
if(MODE_QUARTERMASTER)
payment_mode = EX_CARGO_TECHNICIAN | EX_CUSTOMS_AGENT | EX_QUARTERMASTER
log_econ("[src.name] payment mode changed by [user] ([id_card.registered_name]) to [display_payment_mode()].")
radio.talk_into(src, "Payment mode set to [display_payment_mode()] by authorized ID [id_card.registered_name].", RADIO_CHANNEL_SUPPLY)
/obj/machinery/export_gate/proc/display_payment_mode()
if(payment_mode & EX_QUARTERMASTER)
return MODE_QUARTERMASTER
if(payment_mode & EX_CUSTOMS_AGENT)
return MODE_CUSTOMS_AGENT
else
return MODE_CARGO_TECH
#undef MODE_CARGO_TECH
#undef MODE_CUSTOMS_AGENT
#undef MODE_QUARTERMASTER
/obj/machinery/export_gate/proc/refresh_payment_accounts(retry = FALSE)
LAZYINITLIST(payment_accounts)
var/list/manifest_accounts = list()
var/list/CT_accounts = SSeconomy.bank_accounts_by_job[/datum/job/cargo_technician]
var/list/CA_accounts = SSeconomy.bank_accounts_by_job[/datum/job/customs_agent]
var/list/QM_accounts = SSeconomy.bank_accounts_by_job[/datum/job/quartermaster]
if(isnull(CT_accounts) && isnull(CA_accounts) && isnull(QM_accounts))
return
if(payment_mode & EX_CARGO_TECHNICIAN)
for(var/datum/bank_account/CT_account as anything in CT_accounts)
if(CT_account.off_duty_check())
continue
manifest_accounts += CT_account
if(payment_mode & EX_CUSTOMS_AGENT)
for(var/datum/bank_account/CA_account as anything in CA_accounts)
if(CA_account.off_duty_check())
continue
manifest_accounts += CA_account
if(payment_mode & EX_QUARTERMASTER)
for(var/datum/bank_account/QM_account as anything in QM_accounts)
if(QM_account.off_duty_check())
continue
manifest_accounts += QM_account
// If there's nobody to pay, fallback to paying everyone
if(LAZYLEN(manifest_accounts) == 0 && !retry)
payment_mode = EX_CARGO_TECHNICIAN | EX_CUSTOMS_AGENT | EX_QUARTERMASTER
log_econ("[src.name] payment mode falling back to [display_payment_mode()] due to lack of crew")
radio.talk_into(src, "Payment mode falling back to [display_payment_mode()] due to lack of crew.", RADIO_CHANNEL_SUPPLY)
refresh_payment_accounts(retry = TRUE)
return
payment_accounts = manifest_accounts
/obj/machinery/export_gate/proc/disperse_earnings()
if(!COOLDOWN_FINISHED(src, export_payout))
return
COOLDOWN_START(src, export_payout, 3 MINUTES)
refresh_payment_accounts()
var/total_accounts = LAZYLEN(payment_accounts)
if(!total_accounts)
return
if(holding_account.account_balance < 50)
radio.talk_into(src, "No export scan income processed this cycle.", RADIO_CHANNEL_SUPPLY)
return
income_previous = 0
income_share = floor(holding_account.account_balance / total_accounts)
log_econ("[src.name] is dispersing [income_share * total_accounts] credits to associated accounts.")
radio.talk_into(src, "Dispersing bounty cube export scan income of [income_share * total_accounts] credits to associated accounts.", RADIO_CHANNEL_SUPPLY)
for(var/datum/bank_account/payout_account as anything in payment_accounts)
if(payout_account.transfer_money(from = holding_account, amount = income_share, transfer_reason = "Export gate: bounty cube earnings"))
income_previous += income_share
income_total += income_share
payout_account.bank_card_talk("Export gate payment of [income_share] cr. processed, account now holds [payout_account.account_balance] cr.")
else
stack_trace("[src.name] attempted to perform a bounty cube export payment to [payout_account.account_holder], but it failed!")
/obj/machinery/export_gate/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
update_last_used(user)
var/obj/item/card/id/id_card = tool.GetID()
if(istype(id_card))
if(check_access(id_card))
set_payment_mode(user, id_card)
return ITEM_INTERACT_SUCCESS
else
user.balloon_alert(user, "insufficient access!")
return ITEM_INTERACT_BLOCKING
/datum/controller/subsystem/economy/issue_paydays()
for(var/obj/machinery/export_gate/payout_gate as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/export_gate))
payout_gate.disperse_earnings()
return ..()
/obj/machinery/conveyor
speed = 0.55 // the items move at the same speed as the belt animation. ~aesthetics~
/obj/machinery/conveyor_switch
conveyor_speed = 0.55 // the items move at the same speed as the belt animation. ~aesthetics~
/datum/bank_account/proc/off_duty_check()
for(var/obj/item/card/id/registered_card in bank_cards)
var/datum/component/off_duty_timer/id_component = registered_card.GetComponent(/datum/component/off_duty_timer)
if(!isnull(id_component))
return TRUE
return FALSE
/// Small explanation for engineering on how to set-up the radioactive nebula shielding
/obj/item/paper/fluff/export_gate
name = "bounty cube export gate"
default_raw_text = {"Export Gate Setup:<br>
Set up the export gate on a conveyor belt, and anchor it to start scanning bounty cubes.<br>
The gate will automatically register bounty cube exports and pay out to active cargo techs, split equally.<br>
Never manually scan a bounty cube ever again! Get those belts and disposal pipes running.
"}
/datum/area_spawn/export_gate
target_areas = list(/area/station/cargo/storage)
desired_atom = /obj/item/flatpack/export_gate
/datum/area_spawn/export_gate/try_spawn()
// Turfs that are available
var/list/available_turfs
for(var/area_type in target_areas)
var/area/found_area = GLOB.areas_by_type[area_type]
if(!found_area)
continue
available_turfs = SSarea_spawn.get_turf_candidates(found_area, mode)
if(LAZYLEN(available_turfs))
break
if(!LAZYLEN(available_turfs))
return
for(var/i in 1 to amount_to_spawn)
var/turf/candidate_turf = SSarea_spawn.pick_turf_candidate(available_turfs)
var/final_desired_atom = desired_atom
new final_desired_atom(candidate_turf)
/datum/area_spawn/export_gate/materials
desired_atom = /obj/item/flatpack/materials_market
/datum/design/board/export_gate
name = "Export Gate Board"
desc = "The circuit board for an export gate."
id = "export_gate"
build_path = /obj/item/circuitboard/machine/export_gate
category = list(
RND_CATEGORY_MACHINE + RND_SUBCATEGORY_MACHINE_CARGO
)
departmental_flags = DEPARTMENT_BITFLAG_ENGINEERING | DEPARTMENT_BITFLAG_CARGO
/datum/techweb_node/office_equip/New()
. = ..()
design_ids += list(
"export_gate",
)