diff --git a/code/modules/awaymissions/mission_code/ruins/freegolems.dm b/code/modules/awaymissions/mission_code/ruins/freegolems.dm
index d7d23ad1f7a..d13370f1054 100644
--- a/code/modules/awaymissions/mission_code/ruins/freegolems.dm
+++ b/code/modules/awaymissions/mission_code/ruins/freegolems.dm
@@ -35,7 +35,7 @@
*/
/obj/machinery/mineral/ore_redemption/golem
req_access = list(ACCESS_FREE_GOLEMS)
- req_access_claim = ACCESS_FREE_GOLEMS
+ req_access_claim = list(ACCESS_FREE_GOLEMS)
/obj/machinery/mineral/ore_redemption/golem/Initialize(mapload)
. = ..()
diff --git a/code/modules/mining/machine_redemption.dm b/code/modules/mining/machine_redemption.dm
index c2e66526341..c94a37d3295 100644
--- a/code/modules/mining/machine_redemption.dm
+++ b/code/modules/mining/machine_redemption.dm
@@ -10,13 +10,16 @@
icon_state = "ore_redemption"
density = TRUE
anchored = TRUE
- req_access = list(ACCESS_MINERAL_STOREROOM)
speed_process = TRUE
- // Settings
+ req_access = list(ACCESS_MINERAL_STOREROOM)
/// The access number required to claim points from the machine.
- var/req_access_claim = ACCESS_MINING_STATION
- /// If TRUE, [/obj/machinery/mineral/ore_redemption/var/req_access_claim] is ignored and any ID may be used to claim points.
- var/anyone_claim = FALSE
+ var/list/req_access_claim = list(ACCESS_MINING_STATION, ACCESS_EXPEDITION)
+ /// If FALSE, the ORM will ignore all access requirements.
+ var/scan_id = TRUE
+ /// If TRUE, the ORM will throw stuff at people.
+ var/throw_inventory = FALSE
+ /// % chance per process that the ORM will throw stuff at people when `throw_inventory` is TRUE. Remember that this machine speed processes, so this rolls 5 times per second.
+ var/throw_chance = 1
/// List of supply console department names that can receive a notification about ore dumps.
/// A list may be provided as entry value to only notify when specific ore is dumped.
var/list/supply_consoles = list(
@@ -29,7 +32,7 @@
"Bar" = list(MAT_URANIUM, MAT_PLASMA),
"Virology" = list(MAT_PLASMA, MAT_URANIUM, MAT_GOLD)
)
- // Variables
+ var/datum/wires/ore_redemption/wires
/// The number of unclaimed points.
var/points = 0
/// Sheet multiplier applied when smelting ore. Updated by [/obj/machinery/proc/RefreshParts].
@@ -46,13 +49,14 @@
var/obj/item/disk/design_disk/inserted_disk
var/datum/component/material_container/mat_container
var/invalid_material
-
+ COOLDOWN_DECLARE(temp_shock)
/obj/machinery/mineral/ore_redemption/Initialize(mapload)
. = ..()
mat_container = AddComponent(/datum/component/material_container, list(MAT_METAL, MAT_GLASS, MAT_SILVER, MAT_GOLD, MAT_DIAMOND, MAT_PLASMA, MAT_URANIUM, MAT_BANANIUM, MAT_TRANQUILLITE, MAT_TITANIUM, MAT_BLUESPACE, MAT_PLATINUM, MAT_IRIDIUM, MAT_PALLADIUM), INFINITY, FALSE, /obj/item/stack, null, CALLBACK(src, PROC_REF(on_material_insert)))
ore_buffer = list()
files = new /datum/research/smelter(src)
+ wires = new(src)
initialize_parts()
RefreshParts()
@@ -81,8 +85,9 @@
*/
/obj/machinery/mineral/ore_redemption/labor
name = "labor camp ore redemption machine"
+ desc = "A public-access ORM for convicts to deposit ore in exchange for the mining points they need to earn their freedom."
req_access = list()
- anyone_claim = TRUE
+ req_access_claim = list()
/obj/machinery/mineral/ore_redemption/labor/initialize_parts()
component_parts = list()
@@ -95,6 +100,8 @@
/obj/machinery/mineral/ore_redemption/Destroy()
// Move any stuff inside us out
+ SStgui.close_uis(wires)
+ QDEL_NULL(wires)
var/turf/T = get_turf(src)
inserted_disk?.forceMove(T)
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
@@ -161,8 +168,10 @@
SStgui.update_uis(src)
send_console_message()
message_sent = TRUE
+ if(throw_inventory && prob(throw_chance))
+ throw_item()
-// Interactions
+// MARK: Interactions
/obj/machinery/mineral/ore_redemption/item_interaction(mob/living/user, obj/item/used, list/modifiers)
if(istype(used, /obj/item/storage/part_replacer))
return ..()
@@ -173,17 +182,25 @@
if(istype(used, /obj/item/card/id))
var/obj/item/card/id/ID = used
if(!points)
- to_chat(usr, SPAN_WARNING("There are no points to claim."));
+ to_chat(user, SPAN_WARNING("There are no points to claim!"));
return ITEM_INTERACT_COMPLETE
- if(anyone_claim || (req_access_claim in ID.access))
- ID.mining_points += points
- ID.total_mining_points += points
- to_chat(usr, SPAN_NOTICE("[points] Mining Points claimed. You have earned a total of [ID.total_mining_points] Mining Points this Shift!"))
- points = 0
- SStgui.update_uis(src)
- else
- to_chat(usr, SPAN_WARNING("Required access not found."))
- add_fingerprint(usr)
+
+ if(scan_id)
+ var/accepted
+ for(var/req in req_access_claim)
+ if(req in ID.access)
+ accepted = TRUE
+ break
+ if(!accepted)
+ to_chat(user, SPAN_WARNING("Required access not found!"))
+ return ITEM_INTERACT_COMPLETE
+
+ ID.mining_points += points
+ ID.total_mining_points += points
+ to_chat(user, SPAN_NOTICE("[points] Mining Points claimed. You have earned a total of [ID.total_mining_points] Mining Points this Shift!"))
+ points = 0
+ SStgui.update_uis(src)
+ add_fingerprint(user)
return ITEM_INTERACT_COMPLETE
if(istype(used, /obj/item/disk/design_disk))
@@ -210,12 +227,22 @@
if(default_deconstruction_crowbar(user, I))
return TRUE
+/obj/machinery/mineral/ore_redemption/wirecutter_act(mob/user, obj/item/I)
+ if(!panel_open)
+ return
+ . = TRUE
+ if(!I.tool_start_check(src, user, 0))
+ return
+ wires.Interact(user)
+
/obj/machinery/mineral/ore_redemption/multitool_act(mob/user, obj/item/I)
if(!panel_open)
return
. = TRUE
if(!has_power())
return
+ if(is_electrified() && shock(user, 100))
+ return
if(!I.tool_start_check(src, user, 0))
return
input_dir = turn(input_dir, -90)
@@ -223,11 +250,17 @@
to_chat(user, SPAN_NOTICE("You change [src]'s I/O settings, setting the input to [dir2text(input_dir)] and the output to [dir2text(output_dir)]."))
/obj/machinery/mineral/ore_redemption/screwdriver_act(mob/user, obj/item/I)
+ if(is_electrified() && shock(user, 100))
+ return TRUE
+
if(default_deconstruction_screwdriver(user, "ore_redemption-open", "ore_redemption", I))
SStgui.update_uis(src)
return TRUE
/obj/machinery/mineral/ore_redemption/wrench_act(mob/user, obj/item/I)
+ if(is_electrified() && shock(user, 100))
+ return TRUE
+
if(default_unfasten_wrench(user, I, time = 6 SECONDS))
return TRUE
@@ -237,13 +270,69 @@
/obj/machinery/mineral/ore_redemption/attack_hand(mob/user)
if(..())
return
+
+ if(is_electrified() && shock(user, 100))
+ return
+
ui_interact(user)
/obj/machinery/mineral/ore_redemption/ex_act(severity)
do_sparks(5, TRUE, src)
..()
-// UI
+/obj/machinery/mineral/ore_redemption/emag_act(mob/user)
+ if(emagged)
+ return FALSE
+
+ to_chat(user, SPAN_NOTICE("You short out the ID scanner on [src], allowing anyone to access it."))
+ scan_id = FALSE
+ emagged = TRUE
+
+/obj/machinery/mineral/ore_redemption/proc/throw_item()
+ var/mob/living/target = locate() in view(7, src)
+ if(!target)
+ return FALSE
+
+ var/datum/component/material_container/storage = GetComponent(/datum/component/material_container)
+ for(var/product in storage.materials)
+ var/datum/material/M = storage.materials[product]
+ var/mineral_amount = M.amount / MINERAL_MATERIAL_AMOUNT
+ if(!mineral_amount)
+ continue
+
+ storage.retrieve_sheets(1, M.id, loc)
+ break
+
+ var/obj/throw_item = locate(/obj/item/stack/sheet) in get_turf(src)
+ if(!throw_item)
+ return
+
+ throw_item.throw_at(target, 16, 3)
+ visible_message(SPAN_DANGER("[src] launches [throw_item] at [target]!"))
+
+/obj/machinery/mineral/ore_redemption/proc/is_powered()
+ if(stat & (NOPOWER|BROKEN))
+ return FALSE
+
+ return TRUE
+
+/obj/machinery/mineral/ore_redemption/proc/temp_electrify(undo = FALSE)
+ if(undo)
+ COOLDOWN_RESET(src, temp_shock)
+ return
+
+ COOLDOWN_START(src, temp_shock, 30 SECONDS)
+
+/obj/machinery/mineral/ore_redemption/proc/is_electrified()
+ if(!is_powered())
+ return FALSE
+
+ if(wires.is_cut(WIRE_ELECTRIFY) || !COOLDOWN_FINISHED(src, temp_shock))
+ return TRUE
+
+ return FALSE
+
+// MARK: UI
/obj/machinery/mineral/ore_redemption/ui_data(mob/user)
var/list/data = list()
var/datum/component/material_container/materials = GetComponent(/datum/component/material_container)
@@ -359,6 +448,7 @@
get_asset_datum(/datum/asset/spritesheet/alloys)
)
+// MARK: SMELTING
/**
* Smelts the given stack of ore.
*
@@ -499,3 +589,60 @@
/obj/machinery/mineral/ore_redemption/proc/on_material_insert(inserted_type, last_inserted_id, inserted)
give_points(inserted_type, inserted)
SStgui.update_uis(src)
+
+// MARK: Wires
+/datum/wires/ore_redemption
+ holder_type = /obj/machinery/mineral/ore_redemption
+ wire_count = 3
+ proper_name = "Ore Redemption Machine"
+
+/datum/wires/ore_redemption/New(atom/_holder)
+ wires = list(WIRE_IDSCAN, WIRE_ELECTRIFY, WIRE_THROW_ITEM)
+ return ..()
+
+/datum/wires/ore_redemption/interactable(mob/user)
+ var/obj/machinery/mineral/ore_redemption/orm = holder
+ if(!issilicon(user) && orm.is_electrified() && orm.shock(user, 100))
+ return FALSE
+ if(orm.panel_open)
+ return TRUE
+ return FALSE
+
+/datum/wires/ore_redemption/on_pulse(wire)
+ var/obj/machinery/mineral/ore_redemption/orm = holder
+ switch(wire)
+ if(WIRE_IDSCAN)
+ if(orm.emagged)
+ return
+ orm.scan_id = !orm.scan_id
+
+ if(WIRE_ELECTRIFY)
+ orm.temp_electrify()
+
+ if(WIRE_THROW_ITEM)
+ orm.throw_inventory = !orm.throw_inventory
+
+/datum/wires/ore_redemption/on_cut(wire, mend)
+ var/obj/machinery/mineral/ore_redemption/orm = holder
+ switch(wire)
+ if(WIRE_IDSCAN)
+ if(orm.emagged)
+ return
+ orm.scan_id = !orm.scan_id
+
+ if(WIRE_ELECTRIFY)
+ if(mend)
+ orm.temp_electrify(TRUE)
+
+ if(WIRE_THROW_ITEM)
+ orm.throw_inventory = TRUE
+
+/datum/wires/ore_redemption/get_status()
+ . = ..()
+ var/obj/machinery/mineral/ore_redemption/orm = holder
+ . += "The orange light is [(orm.is_electrified()) ? "off" : "on"]."
+ . += "The red light is [(orm.throw_inventory && orm.is_powered()) ? "off" : "blinking"]."
+ . += "The ID scanner light is [(orm.scan_id && !orm.emagged && orm.is_powered()) ? "off" : "on"]."
+
+/obj/machinery/mineral/ore_redemption/get_internal_wires()
+ return wires