#define DRILL_LIGHT_IDLE 0
#define DRILL_LIGHT_WARNING 1
#define DRILL_LIGHT_ACTIVE 2
/obj/machinery/mining
icon = 'icons/obj/mining_drill.dmi'
anchored = FALSE
use_power = 0 //The drill takes power directly from a cell.
density = TRUE
layer = MOB_LAYER + 0.1 //So it draws over mobs in the tile north of it.
/obj/machinery/mining/drill
name = "mining drill head"
desc = "A large industrial drill. Its bore does not penetrate deep enough to access the sublevels."
desc_info = "You can upgrade this machine with better matter bins, capacitors, micro lasers, and power cells. You can also attach a mining satchel that has a warp pack and a linked ore box to it, to bluespace teleport any mined ore directly into the linked ore box."
icon_state = "mining_drill"
var/braces_needed = 2
var/list/supports = list()
var/supported = FALSE
var/active = FALSE
var/current_error
var/list/resource_field = list()
var/ore_types = list(
MATERIAL_IRON = /obj/item/ore/iron,
MATERIAL_URANIUM = /obj/item/ore/uranium,
MATERIAL_GOLD = /obj/item/ore/gold,
MATERIAL_SILVER = /obj/item/ore/silver,
MATERIAL_DIAMOND = /obj/item/ore/diamond,
MATERIAL_PHORON = /obj/item/ore/phoron,
MATERIAL_OSMIUM = /obj/item/ore/osmium,
"hydrogen" = /obj/item/ore/hydrogen,
"silicates" = /obj/item/ore/glass,
"carbonaceous rock" = /obj/item/ore/coal
)
//Upgrades
var/harvest_speed
var/capacity
var/charge_use
var/obj/item/cell/cell
var/obj/item/storage/bag/ore/attached_satchel
//Flags
var/need_update_field = FALSE
var/need_player_check = FALSE
var/datum/effect_system/sparks/spark_system
component_types = list(
/obj/item/circuitboard/miningdrill,
/obj/item/stock_parts/matter_bin,
/obj/item/stock_parts/capacitor,
/obj/item/stock_parts/micro_laser,
/obj/item/cell/high
)
/obj/machinery/mining/drill/Initialize()
. = ..()
spark_system = bind_spark(src, 3)
/obj/machinery/mining/drill/Destroy()
QDEL_NULL(attached_satchel)
QDEL_NULL(spark_system)
return ..()
/obj/machinery/mining/drill/machinery_process()
if(need_player_check)
return
check_supports()
if(!active)
return
if(!anchored || !use_cell_power())
system_error("System configuration or charge error.")
return
if(need_update_field)
get_resource_field()
if(world.time % 10 == 0)
update_icon()
if(!active)
return
//Drill through the flooring, if any.
if(istype(get_turf(src), /turf/unsimulated/floor/asteroid))
var/turf/unsimulated/floor/asteroid/T = get_turf(src)
if(!T.dug)
T.gets_dug()
for(var/obj/item/ore/ore in range(1, src)) // gets_dug causes ore to spawn, this picks that ore up as well
ore.forceMove(src)
if(attached_satchel?.linked_box)
attached_satchel.insert_into_storage(ore)
else if(istype(get_turf(src), /turf/simulated/floor))
var/turf/simulated/floor/T = get_turf(src)
T.ex_act(2.0)
//Dig out the tasty ores.
if(length(resource_field))
var/turf/harvesting = pick(resource_field)
while(length(resource_field) && !harvesting.resources)
harvesting.has_resources = FALSE
harvesting.resources = null
resource_field -= harvesting
harvesting = pick(resource_field)
if(!harvesting)
return
var/total_harvest = harvest_speed //Ore harvest-per-tick.
var/found_resource = FALSE //If this doesn't get set, the area is depleted and the drill errors out.
for(var/ore in ore_types)
if(length(contents) >= capacity)
system_error("Insufficient storage space.")
active = FALSE
need_player_check = TRUE
update_icon()
return
if(length(contents) + total_harvest >= capacity)
total_harvest = capacity - length(contents)
if(total_harvest <= 0)
break
if(harvesting.resources[ore])
found_resource = TRUE
var/create_ore = 0
if(harvesting.resources[ore] >= total_harvest)
harvesting.resources[ore] -= total_harvest
create_ore = total_harvest
total_harvest = 0
else
total_harvest -= harvesting.resources[ore]
create_ore = harvesting.resources[ore]
harvesting.resources[ore] = 0
for(var/i = 1, i <= create_ore, i++)
var/oretype = ore_types[ore]
var/obj/stored_ore = new oretype(src)
if(attached_satchel?.linked_box)
attached_satchel.insert_into_storage(stored_ore)
if(!found_resource)
harvesting.has_resources = FALSE
harvesting.resources = null
resource_field -= harvesting
else
active = FALSE
need_player_check = TRUE
system_error("Resource field depleted.")
update_icon()
/obj/machinery/mining/drill/examine(mob/user)
..(user)
if(need_player_check)
to_chat(user, SPAN_WARNING("The drill error light is flashing. The cell panel is [panel_open ? "open" : "closed"]."))
else
to_chat(user, "The drill is [active ? "active" : "inactive"] and the cell panel is [panel_open ? "open" : "closed"].")
if(panel_open)
to_chat(user, "The power cell is [cell ? "installed" : "missing"].")
to_chat(user, "The cell charge meter reads [cell ? round(cell.percent(),1) : 0]%.")
if(user.Adjacent(src))
if(attached_satchel)
to_chat(user, FONT_SMALL(SPAN_NOTICE("It has a [attached_satchel] attached to it.")))
if(current_error)
to_chat(user, FONT_SMALL(SPAN_WARNING("The error display reads \"[current_error]\".")))
return
/obj/machinery/mining/drill/proc/activate_light(var/lights = DRILL_LIGHT_IDLE)
switch(lights)
if(DRILL_LIGHT_IDLE)
set_light(2, 0.75, LIGHT_COLOR_TUNGSTEN)
if(DRILL_LIGHT_WARNING)
set_light(3, 1, LIGHT_COLOR_EMERGENCY)
if(DRILL_LIGHT_ACTIVE)
set_light(4, 1, LIGHT_COLOR_LAVA)
/obj/machinery/mining/drill/attack_ai(mob/user)
return src.attack_hand(user)
/obj/machinery/mining/drill/attackby(obj/item/O, mob/user)
if(!active)
if(default_deconstruction_screwdriver(user, O))
return
if (!panel_open)
if(default_deconstruction_crowbar(user, O))
return
if(default_part_replacement(user, O))
return
if(active)
return ..()
if(istype(O, /obj/item/storage/bag/ore))
var/obj/item/storage/bag/ore/S = O
if(attached_satchel)
to_chat(user, SPAN_WARNING("\The [src] already has a satchel attached to it!"))
return
if(!S.linked_beacon)
to_chat(user, SPAN_WARNING("\The [S] doesn't have an extraction pack in it!"))
return
if(!S.linked_box)
to_chat(user, SPAN_WARNING("\The [S] doesn't have a linked ore box!"))
return
user.drop_from_inventory(S, src)
attached_satchel = S
to_chat(user, SPAN_NOTICE("You attach \the [S] to \the [src]."))
for(var/obj/item/ore/ore in src) // takes ore currently in the drill and beams it away
attached_satchel.insert_into_storage(ore)
return
if(O.iswrench())
if(!attached_satchel)
to_chat(user, SPAN_WARNING("\The [src] doesn't have a satchel attached to it!"))
return
user.visible_message(SPAN_NOTICE("\The [user] starts detaching \the [attached_satchel]."), SPAN_NOTICE("You start detaching \the [attached_satchel]."))
if(do_after(user, 30, TRUE, src))
if(!attached_satchel)
return
attached_satchel.forceMove(get_turf(user))
user.put_in_hands(attached_satchel)
user.visible_message(SPAN_NOTICE("\The [user] detaches \the [attached_satchel]."), SPAN_NOTICE("You detach \the [attached_satchel]."))
attached_satchel = null
return
if(O.iscrowbar())
if (panel_open)
if(cell)
to_chat(user, SPAN_NOTICE("You wrench out \the [cell]."))
cell.forceMove(get_turf(user))
component_parts -= cell
cell = null
return
else
to_chat(user, SPAN_WARNING("There's no cell to remove!"))
return
if(istype(O, /obj/item/cell))
if(panel_open)
if(cell)
to_chat(user, SPAN_WARNING("There is already a power cell inside."))
return
else
// insert cell
user.drop_from_inventory(O, src)
cell = O
component_parts += O
O.add_fingerprint(user)
visible_message(span("notice", "\The [user] inserts a power cell into \the [src]."),
span("notice", "You insert the power cell into \the [src]."))
power_change()
else
to_chat(user, span("notice", "The hatch must be open to insert a power cell."))
return
else
..()
return
/obj/machinery/mining/drill/attack_hand(mob/user)
check_supports()
if(need_player_check)
to_chat(user, SPAN_NOTICE("You hit the manual override and reset the drill's error checking."))
current_error = null
need_player_check = FALSE
if(anchored)
get_resource_field()
update_icon()
return
else if(supported && !panel_open)
if(use_cell_power())
active = !active
if(active)
visible_message(SPAN_NOTICE("\The [src] lurches downwards, grinding noisily."))
need_update_field = TRUE
else
visible_message(SPAN_NOTICE("\The [src] shudders to a grinding halt."))
else
to_chat(user, SPAN_NOTICE("\The [src] is unpowered."))
else
if(use_cell_power())
if(!supported && !panel_open)
system_error("Unbraced drill error.")
sleep(30)
if(!supported) //if you can resolve it manually in three seconds then power to you good-sir.
visible_message(SPAN_NOTICE("\icon[src] [src.name] beeps, \"Unbraced drill error automatically corrected. Please brace your drill.\""))
else
visible_message(SPAN_NOTICE("\icon[src] [src.name] beeps, \"Unbraced drill error manually resolved. Operations may resume normally.\""))
if(supported && panel_open)
if(cell)
system_error("Unsealed cell fitting error. Volatile cell discharge may occur if not immediately corrected.")
spark_system.queue()
sleep(20)
spark_system.queue()
sleep(10)
spark_system.queue()
sleep(10)
if(panel_open)
if(prob(70))
visible_message(SPAN_DANGER("\The [src]'s cell shorts out!"))
cell.use(cell.charge)
else
visible_message(SPAN_DANGER("\The [src]'s cell detonates!"))
explosion(get_turf(src), -1, -1, 2, 1)
qdel(cell)
component_parts -= cell
cell = null
else
visible_message(SPAN_NOTICE("\icon[src] [src.name] beeps, \"Unsealed cell fitting error manually resolved. Operations may resume normally.\""))
else
to_chat(user, SPAN_NOTICE("\The [src] is unpowered."))
update_icon()
/obj/machinery/mining/drill/update_icon()
if(need_player_check)
icon_state = "mining_drill_error"
activate_light(DRILL_LIGHT_WARNING)
else if(active)
icon_state = "mining_drill_active"
activate_light(DRILL_LIGHT_ACTIVE)
else if(supported)
icon_state = "mining_drill_braced"
activate_light(DRILL_LIGHT_IDLE)
else
icon_state = "mining_drill"
activate_light(DRILL_LIGHT_IDLE)
return
/obj/machinery/mining/drill/RefreshParts()
..()
harvest_speed = 0
capacity = 0
charge_use = 25
for(var/obj/item/stock_parts/P in component_parts)
if(ismicrolaser(P))
harvest_speed = P.rating
else if(ismatterbin(P))
capacity = 200 * P.rating
else if(iscapacitor(P))
charge_use -= 5 * P.rating
cell = locate(/obj/item/cell) in component_parts
/obj/machinery/mining/drill/proc/check_supports()
supported = FALSE
if((!supports || !supports.len) && initial(anchored) == 0)
icon_state = "mining_drill"
anchored = FALSE
active = FALSE
else
anchored = TRUE
if(supports && length(supports) >= braces_needed)
supported = TRUE
update_icon()
/obj/machinery/mining/drill/proc/system_error(var/error)
if(error)
visible_message(SPAN_WARNING("\icon[src] [capitalize_first_letters(src.name)] flashes a system warning: \"[error]\"."))
current_error = error
playsound(get_turf(src), 'sound/machines/warning-buzzer.ogg', 100, 1)
need_player_check = TRUE
active = FALSE
update_icon()
/obj/machinery/mining/drill/proc/get_resource_field()
resource_field = list()
need_update_field = FALSE
var/turf/T = get_turf(src)
if(!istype(T))
return
for(var/turf/mine_turf in block(locate(src.x + 2, src.y + 2, src.z), locate(src.x - 2, src.y - 2, src.z)))
if(mine_turf?.has_resources)
resource_field += mine_turf
if(!length(resource_field))
system_error("Resources depleted.")
/obj/machinery/mining/drill/proc/use_cell_power()
if(!cell)
return FALSE
if(cell.charge >= charge_use)
cell.use(charge_use)
return TRUE
return FALSE
/obj/machinery/mining/drill/verb/unload()
set name = "Unload Drill"
set category = "Object"
set src in oview(1)
if(use_check_and_message(usr))
return
var/obj/structure/ore_box/B = locate() in orange(1)
if(B)
for(var/obj/item/ore/O in contents)
O.forceMove(B)
to_chat(usr, SPAN_NOTICE("You unload \the [src]'s storage cache into the ore box."))
else
for(var/obj/item/ore/O in contents)
O.forceMove(get_turf(src))
to_chat(usr, SPAN_NOTICE("You spill the contents of \the [src]'s storage box all over the ground."))
/obj/machinery/mining/brace
name = "mining drill brace"
desc = "A machinery brace for an industrial drill. It looks easily two feet thick."
icon_state = "mining_brace"
obj_flags = OBJ_FLAG_ROTATABLE
var/obj/machinery/mining/drill/connected
component_types = list(
/obj/item/circuitboard/miningdrillbrace
)
/obj/machinery/mining/brace/attackby(obj/item/W, mob/user)
if(connected?.active)
to_chat(user, SPAN_WARNING("You know you ought not work with the brace of a running drill, but you do anyways."))
sleep(5)
if(istype(user, /mob/living/carbon/human))
//Save the users active hand
var/mob/living/carbon/human/H = user
var/obj/item/organ/external/LA = H.get_organ(BP_L_HAND)
var/obj/item/organ/external/RA = H.get_organ(BP_R_HAND)
var/active_hand = H.hand
if(prob(20))
if(active_hand)
LA.droplimb(0, DROPLIMB_BLUNT)
else
RA.droplimb(0, DROPLIMB_BLUNT)
connected.system_error("Unexpected user interface error.")
return
else
H.apply_damage(25, BRUTE, damage_flags = DAM_SHARP|DAM_EDGE)
connected.system_error("Unexpected user interface error.")
return
else
var/mob/living/M = user
M.apply_damage(25, BRUTE, damage_flags = DAM_SHARP|DAM_EDGE)
if(default_deconstruction_screwdriver(user, W))
return
if(default_deconstruction_crowbar(user, W))
return
if(W.iswrench())
if(istype(get_turf(src), /turf/space))
to_chat(user, SPAN_NOTICE("You send \the [src] careening into space. Idiot."))
var/inertia = rand(10, 30)
for(var/i in 1 to inertia)
step_away(src, user, 15, 8)
if(!(istype(get_turf(src), /turf/space)))
break
sleep(1)
return
if(connected?.active)
if(prob(50))
sleep(10)
connected.system_error("Unbraced drill error.")
sleep(30)
if(connected?.active) //if you can resolve it manually in three seconds then power to you good-sir.
visible_message(SPAN_NOTICE("\icon[src] [src.name] beeps, \"Unbraced drill error automatically corrected. Please brace your drill.\""))
else
connected.system_error("Unexpected user interface error.")
return
playsound(get_turf(src), W.usesound, 100, 1)
to_chat(user, SPAN_NOTICE("You [anchored ? "un" : ""]anchor the brace."))
for(var/angle in cardinal) // make it face any drill in cardinal direction from it
if(locate(/obj/machinery/mining/drill) in get_step(src, angle))
src.dir = angle
break
anchored = !anchored
if(anchored)
connect()
else
disconnect()
/obj/machinery/mining/brace/proc/connect()
var/turf/T = get_step(get_turf(src), src.dir)
for(var/thing in T.contents)
if(istype(thing, /obj/machinery/mining/drill))
connected = thing
break
if(!connected)
return
if(!connected.supports)
connected.supports = list()
icon_state = "mining_brace_active"
connected.supports += src
connected.check_supports()
/obj/machinery/mining/brace/proc/disconnect()
if(!connected)
return
if(!connected.supports)
connected.supports = list()
icon_state = "mining_brace"
connected.supports -= src
connected.check_supports()
connected = null