mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2025-12-14 11:42:27 +00:00
## About The Pull Request Change `/obj/item/construction/examine` so that if there's any upgrades installed it will list their names in the examine text. Also add a `/datum/bitfield` entry for RCD upgrades for a little debug QOL. ## Why It's Good For The Game It sucks to accidentally print an upgrade you already have for the RCD. ## Changelog 🆑 qol: The RCD examine text now lists any upgrades it has installed. /🆑
492 lines
17 KiB
Plaintext
492 lines
17 KiB
Plaintext
//attack with an item - open/close cover, insert cell, or (un)lock interface
|
|
|
|
/obj/machinery/power/apc/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
|
|
. = NONE
|
|
if(HAS_TRAIT(tool, TRAIT_APC_SHOCKING))
|
|
. = fork_outlet_act(user, tool)
|
|
if(.)
|
|
return .
|
|
|
|
if(tool.GetID())
|
|
togglelock(user)
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
if(istype(tool, /obj/item/stock_parts/power_store))
|
|
. = cell_act(user, tool)
|
|
else if(istype(tool, /obj/item/stack/cable_coil))
|
|
. = cable_act(user, tool, LAZYACCESS(modifiers, RIGHT_CLICK))
|
|
else if(istype(tool, /obj/item/electronics/apc))
|
|
. = electronics_act(user, tool)
|
|
else if(istype(tool, /obj/item/electroadaptive_pseudocircuit))
|
|
. = pseudocircuit_act(user, tool)
|
|
else if(istype(tool, /obj/item/wallframe/apc))
|
|
. = wallframe_act(user, tool)
|
|
if(.)
|
|
return .
|
|
|
|
if(panel_open && !opened && is_wire_tool(tool))
|
|
wires.interact(user)
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
return .
|
|
|
|
/// Called when we interact with the APC with an item with which we can get shocked when we stuff it into an APC
|
|
/obj/machinery/power/apc/proc/fork_outlet_act(mob/living/user, obj/item/tool)
|
|
var/metal = 0
|
|
var/shock_source = null
|
|
metal += LAZYACCESS(tool.custom_materials, GET_MATERIAL_REF(/datum/material/iron))//This prevents wooden rolling pins from shocking the user
|
|
|
|
if(cell || terminal) //The mob gets shocked by whichever powersource has the most electricity
|
|
if(cell && terminal)
|
|
shock_source = cell.charge > terminal.powernet.avail ? cell : terminal.powernet
|
|
else
|
|
shock_source = terminal?.powernet || cell
|
|
|
|
if(shock_source && metal && (panel_open || opened)) //Now you're cooking with electricity
|
|
if(!electrocute_mob(user, shock_source, src, siemens_coeff = 1, dist_check = TRUE))//People with insulated gloves just attack the APC normally. They're just short of magical anyway
|
|
return NONE
|
|
do_sparks(5, TRUE, src)
|
|
user.visible_message(span_notice("[user.name] shoves [tool] into the internal components of [src], erupting into a cascade of sparks!"))
|
|
if(shock_source == cell)//If the shock is coming from the cell just fully discharge it, because it's funny
|
|
cell.use(cell.charge)
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
/// Called when we interact with the APC with a cell, attempts to insert it
|
|
/obj/machinery/power/apc/proc/cell_act(mob/living/user, obj/item/stock_parts/power_store/new_cell)
|
|
if(!opened)
|
|
return NONE
|
|
|
|
if(cell)
|
|
balloon_alert(user, "cell already installed!")
|
|
return ITEM_INTERACT_BLOCKING
|
|
if(machine_stat & MAINT)
|
|
balloon_alert(user, "no connector for a cell!")
|
|
return ITEM_INTERACT_BLOCKING
|
|
if(!user.transferItemToLoc(new_cell, src))
|
|
return ITEM_INTERACT_BLOCKING
|
|
cell = new_cell
|
|
user.visible_message(span_notice("[user.name] inserts the power cell to [src.name]!"))
|
|
balloon_alert(user, "cell inserted")
|
|
update_appearance()
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
/// Checks if we can place a terminal on the APC
|
|
/obj/machinery/power/apc/proc/can_place_terminal(mob/living/user, obj/item/stack/cable_coil/installing_cable, silent = TRUE)
|
|
if(!opened)
|
|
return FALSE
|
|
var/turf/host_turf = get_turf(src)
|
|
if(host_turf.underfloor_accessibility < UNDERFLOOR_INTERACTABLE)
|
|
if(!silent && user)
|
|
balloon_alert(user, "remove the floor plating!")
|
|
return FALSE
|
|
if(!isnull(terminal))
|
|
if(!silent && user)
|
|
balloon_alert(user, "already wired!")
|
|
return FALSE
|
|
if(!has_electronics)
|
|
if(!silent && user)
|
|
balloon_alert(user, "no board to wire!")
|
|
return FALSE
|
|
if(panel_open)
|
|
if(!silent && user)
|
|
balloon_alert(user, "wires prevent placing a terminal!")
|
|
return FALSE
|
|
if(installing_cable.get_amount() < 10)
|
|
if(!silent && user)
|
|
balloon_alert(user, "need ten lengths of cable!")
|
|
return FALSE
|
|
return TRUE
|
|
|
|
/// Called when we interact with the APC with a cable, attempts to wire the APC and create a terminal
|
|
/obj/machinery/power/apc/proc/cable_act(mob/living/user, obj/item/stack/cable_coil/installing_cable, is_right_clicking)
|
|
if(!opened)
|
|
return NONE
|
|
if(!can_place_terminal(user, installing_cable, silent = FALSE))
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
var/terminal_cable_layer = cable_layer // Default to machine's cable layer
|
|
if(is_right_clicking)
|
|
var/choice = tgui_input_list(user, "Select Power Input Cable Layer", "Select Cable Layer", GLOB.cable_name_to_layer)
|
|
if(isnull(choice) \
|
|
|| !user.is_holding(installing_cable) \
|
|
|| !user.Adjacent(src) \
|
|
|| user.incapacitated \
|
|
|| !can_place_terminal(user, installing_cable, silent = TRUE) \
|
|
)
|
|
return ITEM_INTERACT_BLOCKING
|
|
terminal_cable_layer = GLOB.cable_name_to_layer[choice]
|
|
|
|
user.visible_message(span_notice("[user.name] starts addding cables to the APC frame."))
|
|
balloon_alert(user, "adding cables...")
|
|
playsound(src, 'sound/items/deconstruct.ogg', 50, TRUE)
|
|
|
|
if(!do_after(user, 2 SECONDS, target = src))
|
|
return ITEM_INTERACT_BLOCKING
|
|
if(!can_place_terminal(user, installing_cable, silent = TRUE))
|
|
return ITEM_INTERACT_BLOCKING
|
|
var/turf/our_turf = get_turf(src)
|
|
var/obj/structure/cable/cable_node = our_turf.get_cable_node(terminal_cable_layer)
|
|
if(prob(50) && electrocute_mob(usr, cable_node, cable_node, 1, TRUE))
|
|
do_sparks(5, TRUE, src)
|
|
return ITEM_INTERACT_BLOCKING
|
|
installing_cable.use(10)
|
|
user.visible_message(span_notice("[user.name] adds cables to the APC frame."))
|
|
balloon_alert(user, "cables added")
|
|
make_terminal(terminal_cable_layer)
|
|
terminal.connect_to_network()
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
/// Called when we interact with the APC with APC electronics, attempts to install the board
|
|
/obj/machinery/power/apc/proc/electronics_act(mob/living/user, obj/item/electronics/apc/installing_board)
|
|
if(!opened)
|
|
return NONE
|
|
|
|
if(has_electronics)
|
|
balloon_alert(user, "there is already a board!")
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
if(machine_stat & BROKEN)
|
|
balloon_alert(user, "the frame is damaged!")
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
user.visible_message(span_notice("[user.name] inserts the power control board into [src]."))
|
|
balloon_alert(user, "inserting the board...")
|
|
playsound(loc, 'sound/items/deconstruct.ogg', 50, TRUE)
|
|
|
|
if(!do_after(user, 1 SECONDS, target = src) || has_electronics)
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
has_electronics = APC_ELECTRONICS_INSTALLED
|
|
locked = FALSE
|
|
balloon_alert(user, "board installed")
|
|
qdel(installing_board)
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
/// Called when we interact with the APC with an electroadaptive pseudocircuit, used by cyborgs to install a board or weak cell
|
|
/obj/machinery/power/apc/proc/pseudocircuit_act(mob/living/user, obj/item/electroadaptive_pseudocircuit/pseudocircuit)
|
|
if(!has_electronics)
|
|
if(machine_stat & BROKEN)
|
|
balloon_alert(user, "frame is too damaged!")
|
|
return ITEM_INTERACT_BLOCKING
|
|
if(!pseudocircuit.adapt_circuit(user, circuit_cost = 0.05 * STANDARD_CELL_CHARGE))
|
|
return ITEM_INTERACT_BLOCKING
|
|
user.visible_message(
|
|
span_notice("[user] fabricates a circuit and places it into [src]."),
|
|
span_notice("You adapt a power control board and click it into place in [src]'s guts."),
|
|
)
|
|
has_electronics = APC_ELECTRONICS_INSTALLED
|
|
locked = FALSE
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
if(!cell)
|
|
if(machine_stat & MAINT)
|
|
balloon_alert(user, "no board for a cell!")
|
|
return ITEM_INTERACT_BLOCKING
|
|
if(!pseudocircuit.adapt_circuit(user, circuit_cost = 0.5 * STANDARD_CELL_CHARGE))
|
|
return ITEM_INTERACT_BLOCKING
|
|
var/obj/item/stock_parts/power_store/battery/crap/empty/bad_cell = new(src)
|
|
bad_cell.forceMove(src)
|
|
cell = bad_cell
|
|
user.visible_message(
|
|
span_notice("[user] fabricates a weak power cell and places it into [src]."),
|
|
span_warning("Your [pseudocircuit.name] whirrs with strain as you create a weak power cell and place it into [src]!"),
|
|
)
|
|
update_appearance()
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
balloon_alert(user, "has both board and cell!")
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
/// Called when we interact with the APC with and APC frame, used for replacing a damaged cover/frame
|
|
/obj/machinery/power/apc/proc/wallframe_act(mob/living/user, obj/item/wallframe/apc/wallframe)
|
|
if(!opened)
|
|
return NONE
|
|
|
|
if(!(machine_stat & BROKEN || opened == APC_COVER_REMOVED || atom_integrity < max_integrity)) // There is nothing to repair
|
|
balloon_alert(user, "no reason for repairs!")
|
|
return ITEM_INTERACT_BLOCKING
|
|
if((machine_stat & BROKEN) && opened == APC_COVER_REMOVED && has_electronics && terminal) // Cover is the only thing broken, we do not need to remove elctronicks to replace cover
|
|
user.visible_message(span_notice("[user.name] replaces missing APC's cover."))
|
|
balloon_alert(user, "replacing APC's cover...")
|
|
if(!do_after(user, 2 SECONDS, target = src)) // replacing cover is quicker than replacing whole frame
|
|
return ITEM_INTERACT_BLOCKING
|
|
balloon_alert(user, "cover replaced")
|
|
qdel(wallframe)
|
|
update_integrity(30) //needs to be welded to fully repair but can work without
|
|
set_machine_stat(machine_stat & ~(BROKEN|MAINT))
|
|
opened = APC_COVER_OPENED
|
|
update_appearance()
|
|
return ITEM_INTERACT_SUCCESS
|
|
if(has_electronics)
|
|
balloon_alert(user, "remove the board inside!")
|
|
return ITEM_INTERACT_BLOCKING
|
|
user.visible_message(span_notice("[user.name] replaces the damaged APC frame with a new one."))
|
|
balloon_alert(user, "replacing damaged frame...")
|
|
if(!do_after(user, 5 SECONDS, target = src))
|
|
return ITEM_INTERACT_BLOCKING
|
|
balloon_alert(user, "replaced frame")
|
|
qdel(wallframe)
|
|
set_machine_stat(machine_stat & ~BROKEN)
|
|
atom_integrity = max_integrity
|
|
if(opened == APC_COVER_REMOVED)
|
|
opened = APC_COVER_OPENED
|
|
update_appearance()
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
/obj/machinery/power/apc/crowbar_act(mob/user, obj/item/crowbar)
|
|
. = TRUE
|
|
|
|
//Prying off broken cover
|
|
if((opened == APC_COVER_CLOSED || opened == APC_COVER_OPENED) && (machine_stat & BROKEN))
|
|
crowbar.play_tool_sound(src)
|
|
balloon_alert(user, "prying...")
|
|
if(!crowbar.use_tool(src, user, 5 SECONDS))
|
|
return
|
|
opened = APC_COVER_REMOVED
|
|
balloon_alert(user, "cover removed")
|
|
update_appearance()
|
|
return
|
|
|
|
//Opening and closing cover
|
|
if((!opened && opened != APC_COVER_REMOVED) && !(machine_stat & BROKEN))
|
|
if(coverlocked && !(machine_stat & MAINT)) // locked...
|
|
balloon_alert(user, "cover is locked!")
|
|
return
|
|
else if(panel_open)
|
|
balloon_alert(user, "wires prevents opening it!")
|
|
return
|
|
else
|
|
opened = APC_COVER_OPENED
|
|
update_appearance()
|
|
return
|
|
|
|
if((opened && has_electronics == APC_ELECTRONICS_SECURED) && !(machine_stat & BROKEN))
|
|
opened = APC_COVER_CLOSED
|
|
coverlocked = TRUE //closing cover relocks it
|
|
balloon_alert(user, "locking the cover")
|
|
update_appearance()
|
|
return
|
|
|
|
//Taking out the electronics
|
|
if(!opened || has_electronics != APC_ELECTRONICS_INSTALLED)
|
|
return
|
|
if(terminal)
|
|
balloon_alert(user, "disconnect wires first!")
|
|
return
|
|
crowbar.play_tool_sound(src)
|
|
if(!crowbar.use_tool(src, user, 50))
|
|
return
|
|
if(has_electronics != APC_ELECTRONICS_INSTALLED)
|
|
return
|
|
has_electronics = APC_ELECTRONICS_MISSING
|
|
if(machine_stat & BROKEN)
|
|
user.visible_message(span_notice("[user.name] breaks the power control board inside [name]!"), \
|
|
span_hear("You hear a crack."))
|
|
balloon_alert(user, "charred board breaks")
|
|
return
|
|
else if(obj_flags & EMAGGED)
|
|
obj_flags &= ~EMAGGED
|
|
user.visible_message(span_notice("[user.name] discards an emagged power control board from [name]!"))
|
|
balloon_alert(user, "emagged board discarded")
|
|
return
|
|
else if(malfhack)
|
|
user.visible_message(span_notice("[user.name] discards a strangely programmed power control board from [name]!"))
|
|
balloon_alert(user, "reprogrammed board discarded")
|
|
malfai = null
|
|
malfhack = 0
|
|
return
|
|
user.visible_message(span_notice("[user.name] removes the power control board from [name]!"))
|
|
balloon_alert(user, "removed the board")
|
|
new /obj/item/electronics/apc(loc)
|
|
return
|
|
|
|
/obj/machinery/power/apc/screwdriver_act(mob/living/user, obj/item/W)
|
|
if(..())
|
|
return TRUE
|
|
. = TRUE
|
|
|
|
if(!opened)
|
|
if(obj_flags & EMAGGED)
|
|
balloon_alert(user, "interface is broken!")
|
|
return
|
|
toggle_panel_open()
|
|
balloon_alert(user, "wires [panel_open ? "exposed" : "unexposed"]")
|
|
W.play_tool_sound(src)
|
|
update_appearance()
|
|
return
|
|
|
|
if(cell)
|
|
user.visible_message(span_notice("[user] removes \the [cell] from [src]!"))
|
|
balloon_alert(user, "cell removed")
|
|
var/turf/user_turf = get_turf(user)
|
|
cell.forceMove(user_turf)
|
|
cell = null
|
|
charging = APC_NOT_CHARGING
|
|
update_appearance()
|
|
return
|
|
|
|
switch (has_electronics)
|
|
if(APC_ELECTRONICS_INSTALLED)
|
|
has_electronics = APC_ELECTRONICS_SECURED
|
|
set_machine_stat(machine_stat & ~MAINT)
|
|
W.play_tool_sound(src)
|
|
balloon_alert(user, "board fastened")
|
|
if(APC_ELECTRONICS_SECURED)
|
|
has_electronics = APC_ELECTRONICS_INSTALLED
|
|
set_machine_stat(machine_stat | MAINT)
|
|
W.play_tool_sound(src)
|
|
balloon_alert(user, "board unfastened")
|
|
else
|
|
balloon_alert(user, "no board to fasten!")
|
|
return
|
|
update_appearance()
|
|
|
|
/obj/machinery/power/apc/wirecutter_act(mob/living/user, obj/item/W)
|
|
. = ..()
|
|
if(terminal && opened)
|
|
terminal.dismantle(user, W)
|
|
return TRUE
|
|
|
|
/obj/machinery/power/apc/welder_act(mob/living/user, obj/item/welder)
|
|
. = ..()
|
|
|
|
//repairing the cover
|
|
if((atom_integrity < max_integrity) && has_electronics)
|
|
if(opened == APC_COVER_REMOVED)
|
|
balloon_alert(user, "no cover to repair!")
|
|
return
|
|
if (machine_stat & BROKEN)
|
|
balloon_alert(user, "too damaged to repair!")
|
|
return
|
|
if(!welder.tool_start_check(user, amount=1))
|
|
return
|
|
balloon_alert(user, "repairing...")
|
|
if(welder.use_tool(src, user, 4 SECONDS, volume = 50))
|
|
update_integrity(min(atom_integrity += 50,max_integrity))
|
|
balloon_alert(user, "repaired")
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
//disassembling the frame
|
|
if(!opened || has_electronics || terminal)
|
|
return
|
|
if(!welder.tool_start_check(user, amount=1))
|
|
return
|
|
user.visible_message(span_notice("[user.name] welds [src]."), \
|
|
span_hear("You hear welding."))
|
|
balloon_alert(user, "welding the APC frame")
|
|
if(!welder.use_tool(src, user, 50, volume=50))
|
|
return
|
|
if((machine_stat & BROKEN) || opened == APC_COVER_REMOVED)
|
|
new /obj/item/stack/sheet/iron(loc)
|
|
user.visible_message(span_notice("[user.name] cuts [src] apart with [welder]."))
|
|
user.balloon_alert(user, "disassembled the broken frame")
|
|
else
|
|
new /obj/item/wallframe/apc(loc)
|
|
user.visible_message(span_notice("[user.name] cuts [src] from the wall with [welder]."))
|
|
user.balloon_alert(user, "cut the frame from the wall")
|
|
qdel(src)
|
|
return TRUE
|
|
|
|
/obj/machinery/power/apc/rcd_vals(mob/user, obj/item/construction/rcd/the_rcd)
|
|
if(!(the_rcd.construction_upgrades & RCD_UPGRADE_SIMPLE_CIRCUITS))
|
|
return FALSE
|
|
|
|
if(!has_electronics)
|
|
if(machine_stat & BROKEN)
|
|
balloon_alert(user, "frame is too damaged!")
|
|
return FALSE
|
|
return list("delay" = 2 SECONDS, "cost" = 1)
|
|
|
|
if(!cell)
|
|
if(machine_stat & MAINT)
|
|
balloon_alert(user, "no board for a cell!")
|
|
return FALSE
|
|
return list("delay" = 5 SECONDS, "cost" = 10)
|
|
|
|
balloon_alert(user, "has both board and cell!")
|
|
return FALSE
|
|
|
|
/obj/machinery/power/apc/rcd_act(mob/user, obj/item/construction/rcd/the_rcd, list/rcd_data)
|
|
if(!(the_rcd.construction_upgrades & RCD_UPGRADE_SIMPLE_CIRCUITS) || rcd_data["[RCD_DESIGN_MODE]"] != RCD_WALLFRAME)
|
|
return FALSE
|
|
|
|
if(!has_electronics)
|
|
if(machine_stat & BROKEN)
|
|
balloon_alert(user, "frame is too damaged!")
|
|
return
|
|
balloon_alert(user, "control board placed")
|
|
has_electronics = TRUE
|
|
locked = TRUE
|
|
return TRUE
|
|
|
|
if(!cell)
|
|
if(machine_stat & MAINT)
|
|
balloon_alert(user, "no board for a cell!")
|
|
return FALSE
|
|
var/obj/item/stock_parts/power_store/battery/crap/empty/C = new(src)
|
|
C.forceMove(src)
|
|
cell = C
|
|
balloon_alert(user, "power cell installed")
|
|
update_appearance()
|
|
return TRUE
|
|
|
|
balloon_alert(user, "has both board and cell!")
|
|
return FALSE
|
|
|
|
/obj/machinery/power/apc/emag_act(mob/user, obj/item/card/emag/emag_card)
|
|
if((obj_flags & EMAGGED) || malfhack)
|
|
return FALSE
|
|
|
|
if(opened)
|
|
balloon_alert(user, "close the cover first!")
|
|
return FALSE
|
|
else if(panel_open)
|
|
balloon_alert(user, "close the panel first!")
|
|
return FALSE
|
|
else if(machine_stat & (BROKEN|MAINT))
|
|
balloon_alert(user, "nothing happens!")
|
|
return FALSE
|
|
else
|
|
flick("apc-spark", src)
|
|
playsound(src, SFX_SPARKS, 75, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
|
|
obj_flags |= EMAGGED
|
|
locked = FALSE
|
|
balloon_alert(user, "interface damaged")
|
|
update_appearance()
|
|
flicker_hacked_icon()
|
|
return TRUE
|
|
|
|
// damage and destruction acts
|
|
/obj/machinery/power/apc/emp_act(severity)
|
|
. = ..()
|
|
if(!(. & EMP_PROTECT_CONTENTS))
|
|
if(cell)
|
|
cell.emp_act(severity)
|
|
if(occupier)
|
|
occupier.emp_act(severity)
|
|
if(. & EMP_PROTECT_SELF)
|
|
return
|
|
lighting = APC_CHANNEL_OFF
|
|
equipment = APC_CHANNEL_OFF
|
|
environ = APC_CHANNEL_OFF
|
|
update_appearance()
|
|
update()
|
|
addtimer(CALLBACK(src, PROC_REF(reset), APC_RESET_EMP), 60 SECONDS)
|
|
|
|
/obj/machinery/power/apc/proc/togglelock(mob/living/user)
|
|
if(obj_flags & EMAGGED)
|
|
balloon_alert(user, "interface is broken!")
|
|
else if(opened)
|
|
balloon_alert(user, "close the cover first!")
|
|
else if(panel_open)
|
|
balloon_alert(user, "close the panel first!")
|
|
else if(machine_stat & (BROKEN|MAINT))
|
|
balloon_alert(user, "nothing happens!")
|
|
else
|
|
if(allowed(usr) && !wires.is_cut(WIRE_IDSCAN) && ((!malfhack && !remote_control_user) || (malfhack && (malfai == user || (user in malfai.connected_robots)))))
|
|
locked = !locked
|
|
balloon_alert(user, locked ? "locked" : "unlocked")
|
|
update_appearance()
|
|
else
|
|
balloon_alert(user, "access denied!")
|