diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 747ffabcb85..31c75e5085e 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -1,1215 +1,1217 @@
-#define APC_WIRE_IDSCAN 1
-#define APC_WIRE_MAIN_POWER1 2
-#define APC_WIRE_MAIN_POWER2 3
-#define APC_WIRE_AI_CONTROL 4
-
-// the Area Power Controller (APC), formerly Power Distribution Unit (PDU)
-// one per area, needs wire conection to power network
-
-// controls power to devices in that area
-// may be opened to change power cell
-// three different channels (lighting/equipment/environ) - may each be set to on, off, or auto
-
-
-//NOTE: STUFF STOLEN FROM AIRLOCK.DM thx
-
-
-/obj/machinery/power/apc
- name = "area power controller"
-
- icon_state = "apc0"
- anchored = 1
- req_access = list(access_engine_equip)
- var/area/area
- var/areastring = null
- var/obj/item/weapon/cell/cell
- var/start_charge = 90 // initial cell charge %
- var/cell_type = 2500 // 0=no cell, 1=regular, 2=high-cap (x5) <- old, now it's just 0=no cell, otherwise dictate cellcapacity by changing this value. 1 used to be 1000, 2 was 2500
- var/opened = 0 //0=closed, 1=opened, 2=cover removed
- var/shorted = 0
- var/lighting = 3
- var/equipment = 3
- var/environ = 3
- var/operating = 1
- var/charging = 0
- var/chargemode = 1
- var/chargecount = 0
- var/locked = 1
- var/coverlocked = 1
- var/aidisabled = 0
- var/tdir = null
- var/obj/machinery/power/terminal/terminal = null
- var/lastused_light = 0
- var/lastused_equip = 0
- var/lastused_environ = 0
- var/lastused_total = 0
- var/main_status = 0
- var/light_consumption = 0 //not used
- var/equip_consumption = 0 //not used
- var/environ_consumption = 0 //not used
- var/emagged = 0
- var/wiresexposed = 0
- var/apcwires = 15
- netnum = -1 // set so that APCs aren't found as powernet nodes
- var/malfhack = 0 //New var for my changes to AI malf. --NeoFite
- var/mob/living/silicon/ai/malfai = null //See above --NeoFite
-// luminosity = 1
- var/has_electronics = 0 // 0 - none, 1 - plugged in, 2 - secured by screwdriver
- var/overload = 1 //used for the Blackout malf module
- var/mob/living/silicon/ai/occupant = null
-
-/proc/RandomAPCWires()
- //to make this not randomize the wires, just set index to 1 and increment it in the flag for loop (after doing everything else).
- var/list/apcwires = list(0, 0, 0, 0)
- APCIndexToFlag = list(0, 0, 0, 0)
- APCIndexToWireColor = list(0, 0, 0, 0)
- APCWireColorToIndex = list(0, 0, 0, 0)
- var/flagIndex = 1
- for (var/flag=1, flag<16, flag+=flag)
- var/valid = 0
- while (!valid)
- var/colorIndex = rand(1, 4)
- if (apcwires[colorIndex]==0)
- valid = 1
- apcwires[colorIndex] = flag
- APCIndexToFlag[flagIndex] = flag
- APCIndexToWireColor[flagIndex] = colorIndex
- APCWireColorToIndex[colorIndex] = flagIndex
- flagIndex+=1
- return apcwires
-
-/obj/machinery/power/apc/updateDialog()
- if (stat & (BROKEN|MAINT))
- return
- var/list/nearby = viewers(1, src)
- for(var/mob/M in nearby)
- if (M.client && M.machine == src)
- src.interact(M)
- AutoUpdateAI(src)
-
-/obj/machinery/power/apc/New(turf/loc, var/ndir, var/building=0)
- ..()
-
- // offset 24 pixels in direction of dir
- // this allows the APC to be embedded in a wall, yet still inside an area
- if (building)
- dir = ndir
- src.tdir = dir // to fix Vars bug
- dir = SOUTH
-
- pixel_x = (src.tdir & 3)? 0 : (src.tdir == 4 ? 24 : -24)
- pixel_y = (src.tdir & 3)? (src.tdir ==1 ? 24 : -24) : 0
- if (building==0)
- init()
- else
- area = src.loc.loc:master
- opened = 1
- operating = 0
- name = "[area.name] APC"
- stat |= MAINT
- src.updateicon()
- spawn(5)
- src.update()
-
-
-
-/obj/machinery/power/apc/proc/make_terminal()
- // create a terminal object at the same position as original turf loc
- // wires will attach to this
- terminal = new/obj/machinery/power/terminal(src.loc)
- terminal.dir = tdir
- terminal.master = src
-
-/obj/machinery/power/apc/proc/init()
- has_electronics = 2 //installed and secured
- // is starting with a power cell installed, create it and set its charge level
- if(cell_type)
- src.cell = new/obj/item/weapon/cell(src)
- cell.maxcharge = cell_type // cell_type is maximum charge (old default was 1000 or 2500 (values one and two respectively)
- cell.charge = start_charge * cell.maxcharge / 100.0 // (convert percentage to actual value)
-
- var/area/A = src.loc.loc
-
- //if area isn't specified use current
- if(isarea(A) && src.areastring == null)
- src.area = A
- else
- src.area = get_area_name(areastring)
- updateicon()
-
- make_terminal()
-
- spawn(5)
- src.update()
-
-/obj/machinery/power/apc/examine()
- set src in oview(1)
-
- if(usr /*&& !usr.stat*/)
- usr << "A control terminal for the area electrical systems."
- if(stat & BROKEN)
- usr << "Looks broken."
- return
- if(opened)
- if(has_electronics && terminal)
- usr << "The cover is [opened==2?"removed":"open"] and the power cell is [ cell ? "installed" : "missing"]."
- else if (!has_electronics && terminal)
- usr << "There are some wires but no any electronics."
- else if (has_electronics && !terminal)
- usr << "Electronics installed but not wired."
- else /* if (!has_electronics && !terminal) */
- usr << "There is no electronics nor connected wires."
-
- else
- if (stat & MAINT)
- usr << "The cover is closed. Something wrong with it: it's doesn't work."
- else if (malfhack)
- usr << "The cover is broken. It's may be hard to force it open."
- else
- usr << "The cover is closed."
-
-
-// update the APC icon to show the three base states
-// also add overlays for indicator lights
-/obj/machinery/power/apc/proc/updateicon()
- src.overlays = null
- if(opened)
- var/basestate = "apc[ cell ? "2" : "1" ]" // if opened, show cell if it's inserted
- if (opened==1)
- if (stat & (MAINT|BROKEN))
- icon_state = "apcmaint" //disassembled APC cannot hold cell
- else
- icon_state = basestate
- else if (opened == 2)
- if ((stat & BROKEN) || malfhack )
- icon_state = "[basestate]-b-nocover"
- else /* if (emagged)*/
- icon_state = "[basestate]-nocover"
- else if (stat & BROKEN)
- icon_state = "apc-b"
- else if(emagged || malfai)
- icon_state = "apcemag"
- else if(wiresexposed)
- icon_state = "apcewires"
- else
- icon_state = "apc0"
- // if closed, update overlays for channel status
- if (!(stat & (BROKEN|MAINT)))
- overlays += image('power.dmi', "apcox-[locked]") // 0=blue 1=red
- overlays += image('power.dmi', "apco3-[charging]") // 0=red, 1=yellow/black 2=green
- if(operating)
- overlays += image('power.dmi', "apco0-[equipment]") // 0=red, 1=green, 2=blue
- overlays += image('power.dmi', "apco1-[lighting]")
- overlays += image('power.dmi', "apco2-[environ]")
-
-//attack with an item - open/close cover, insert cell, or (un)lock interface
-
-/obj/machinery/power/apc/attackby(obj/item/W, mob/user)
-
- if (istype(user, /mob/living/silicon) && get_dist(src,user)>1)
- return src.attack_hand(user)
- if (istype(W, /obj/item/weapon/crowbar) && opened)
- if (has_electronics==1)
- if (terminal)
- user << "\red Disconnect wires first."
- return
- playsound(src.loc, 'Crowbar.ogg', 50, 1)
- user << "You trying to remove the power control board..."
- if(do_after(user, 50))
- has_electronics = 0
- if ((stat & BROKEN) || malfhack)
- user.visible_message(\
- "\red [user.name] has broken the power control board inside [src.name]!",\
- "You broke the charred power control board and remove the remains.",
- "You hear a crack!")
- //ticker.mode:apcs-- //XSI said no and I agreed. -rastaf0
- else
- user.visible_message(\
- "\red [user.name] has removed the power control board from [src.name]!",\
- "You remove the power control board.")
- new /obj/item/weapon/module/power_control(loc)
- else if (opened!=2) //cover isn't removed
- opened = 0
- updateicon()
- else if (istype(W, /obj/item/weapon/crowbar) && !((stat & BROKEN) || malfhack) )
- if(coverlocked && !(stat & MAINT))
- user << "\red The cover is locked and cannot be opened."
- return
- else
- opened = 1
- updateicon()
- else if (istype(W, /obj/item/weapon/cell) && opened) // trying to put a cell inside
- if(cell)
- user << "There is a power cell already installed."
- return
- else
- if (stat & MAINT)
- user << "\red There is no any connector for your power cell."
- return
- user.drop_item()
- W.loc = src
- cell = W
- user.visible_message(\
- "\red [user.name] has inserted the power cell to [src.name]!",\
- "You insert the power cell.")
- chargecount = 0
- updateicon()
- else if (istype(W, /obj/item/weapon/screwdriver)) // haxing
- if(opened)
- if (cell)
- user << "\red Close the APC first." //Less hints more mystery!
- return
- else
- if (has_electronics==1 && terminal)
- has_electronics = 2
- stat &= ~MAINT
- playsound(src.loc, 'Screwdriver.ogg', 50, 1)
- user << "You screw the circuit electronics into place."
- else if (has_electronics==2)
- has_electronics = 1
- stat |= MAINT
- playsound(src.loc, 'Screwdriver.ogg', 50, 1)
- user << "You unfasten the electronics."
- else /* has_electronics==0 */
- user << "\red There is nothing to secure."
- return
- updateicon()
- else if(emagged)
- user << "The interface is broken."
- else
- wiresexposed = !wiresexposed
- user << "The wires have been [wiresexposed ? "exposed" : "unexposed"]"
- updateicon()
-
- else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) // trying to unlock the interface with an ID card
- if(emagged)
- user << "The interface is broken."
- else if(opened)
- user << "You must close the cover to swipe an ID card."
- else if(wiresexposed)
- user << "You must close the panel"
- else if(stat & (BROKEN|MAINT))
- user << "Nothing happens."
- else
- if(src.allowed(usr))
- locked = !locked
- user << "You [ locked ? "lock" : "unlock"] the APC interface."
- updateicon()
- else
- user << "\red Access denied."
- else if (istype(W, /obj/item/weapon/card/emag) && !(emagged || malfhack)) // trying to unlock with an emag card
- if(opened)
- user << "You must close the cover to swipe an ID card."
- else if(wiresexposed)
- user << "You must close the panel first"
- else if(stat & (BROKEN|MAINT))
- user << "Nothing happens."
- else
- flick("apc-spark", src)
- if (do_after(user,6))
- if(prob(50))
- emagged = 1
- locked = 0
- user << "You emag the APC interface."
- updateicon()
- else
- user << "You fail to [ locked ? "unlock" : "lock"] the APC interface."
- else if (istype(W, /obj/item/weapon/cable_coil) && !terminal && opened && has_electronics!=2)
- if (src.loc:intact)
- user << "\red You must remove the floor plating in front of the APC first."
- return
- var/obj/item/weapon/cable_coil/C = W
- if(C.amount < 10)
- user << "\red You need more wires."
- return
- user << "You start adding cables to the APC frame..."
- playsound(src.loc, 'Deconstruct.ogg', 50, 1)
- if(do_after(user, 20) && C.amount >= 10)
- var/turf/T = get_turf_loc(src)
- var/obj/structure/cable/N = T.get_cable_node()
- if (prob(50) && electrocute_mob(usr, N, N))
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(5, 1, src)
- s.start()
- return
- C.use(10)
- user.visible_message(\
- "\red [user.name] has added cables to the APC frame!",\
- "You add cables to the APC frame.")
- make_terminal()
- terminal.connect_to_network()
- else if (istype(W, /obj/item/weapon/wirecutters) && terminal && opened && has_electronics!=2)
- if (src.loc:intact)
- user << "\red You must remove the floor plating in front of the APC first."
- return
- user << "You begin to cut cables..."
- playsound(src.loc, 'Deconstruct.ogg', 50, 1)
- if(do_after(user, 50))
- if (prob(50) && electrocute_mob(usr, terminal.powernet, terminal))
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(5, 1, src)
- s.start()
- return
- new /obj/item/weapon/cable_coil(loc,10)
- user.visible_message(\
- "\red [user.name] cut cables and dismantled the power terminal.",\
- "You cut cables and dismantle the power terminal.")
- del(terminal)
- else if (istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics==0 && !((stat & BROKEN) || malfhack))
- user << "You trying to insert the power control board into the frame..."
- playsound(src.loc, 'Deconstruct.ogg', 50, 1)
- if(do_after(user, 10))
- has_electronics = 1
- user << "You place the power control board inside the frame."
- del(W)
- else if (istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics==0 && ((stat & BROKEN) || malfhack))
- user << "\red You cannot put the board inside, the frame is damaged."
- return
- else if (istype(W, /obj/item/weapon/weldingtool) && W:welding && opened && has_electronics==0 && !terminal)
- if (W:get_fuel() < 3)
- user << "\blue You need more welding fuel to complete this task."
- return
- user << "You start welding APC frame..."
- if(W:remove_fuel(0,user))
- W:welding = 2
- playsound(src.loc, 'Welder.ogg', 50, 1)
- if(do_after(user, 50))
-
- if (emagged || malfhack || (stat & BROKEN) || opened==2)
- new /obj/item/stack/sheet/metal(loc)
- user.visible_message(\
- "\red [src] has been cut apart by [user.name] with the weldingtool.",\
- "You disassembled the broken APC frame.",\
- "\red You hear welding.")
- else
- new /obj/item/apc_frame(loc)
- user.visible_message(\
- "\red [src] has been cut from the wall by [user.name] with the weldingtool.",\
- "You cut APC frame from the wall.",\
- "\red You hear welding.")
- W:welding = 1
- del(src)
- return
- else if (istype(W, /obj/item/apc_frame) && opened && emagged)
- emagged = 0
- if (opened==2)
- opened = 1
- user.visible_message(\
- "\red [user.name] has replaced the damaged APC frontal panel with a new one.",\
- "You replace the damaged APC frontal panel with a new one.")
- del(W)
- updateicon()
- else if (istype(W, /obj/item/apc_frame) && opened && ((stat & BROKEN) || malfhack))
- if (has_electronics)
- user << "You cannot repair this APC until you remove the electronics still inside."
- return
- user << "You begin to replace the damaged APC frame..."
- if(do_after(user, 50))
- user.visible_message(\
- "\red [user.name] has replaced the damaged APC frame with new one.",\
- "You replace the damaged APC frame with new one.")
- del(W)
- stat &= ~BROKEN
- malfai = null
- malfhack = 0
- if (opened==2)
- opened = 1
- updateicon()
- else
- if ( ((stat & BROKEN) || malfhack) \
- && !opened \
- && W.force >= 5 \
- && W.w_class >= 3.0 \
- && prob(20) )
- opened = 2
- user.visible_message("\red The APC cover was knocked down with the [W.name] by [user.name]!", \
- "\red You knock down the APC cover with your [W.name]!", \
- "You hear bang")
- updateicon()
- else
- if (istype(user, /mob/living/silicon))
- return src.attack_hand(user)
- if (!opened && wiresexposed && \
- (istype(W, /obj/item/device/multitool) || \
- istype(W, /obj/item/weapon/wirecutters)))
- return src.attack_hand(user)
- user.visible_message("\red The [src.name] has been hit with the [W.name] by [user.name]!", \
- "\red You hit the [src.name] with your [W.name]!", \
- "You hear bang")
-
-// attack with hand - remove cell (if cover open) or interact with the APC
-
-/obj/machinery/power/apc/attack_hand(mob/user)
- if (!can_use(user))
- return
- src.add_fingerprint(user)
- if(opened && (!istype(user, /mob/living/silicon)))
- if(cell)
- usr.put_in_hand(cell)
- cell.add_fingerprint(user)
- cell.updateicon()
-
- src.cell = null
- user.visible_message("\red [user.name] removes the power cell from [src.name]!", "You remove the power cell.")
- //user << "You remove the power cell."
- charging = 0
- src.updateicon()
- return
- if(stat & (BROKEN|MAINT))
- return
-
- if(ishuman(user))
- if(istype(user:gloves, /obj/item/clothing/gloves/space_ninja)&&user:gloves:candrain&&!user:gloves:draining)
- call(/obj/item/clothing/gloves/space_ninja/proc/drain)("APC",src,user:wear_suit)
- return
- // do APC interaction
- user.machine = src
- src.interact(user)
-
-/obj/machinery/power/apc/proc/interact(mob/user)
- if(!user)
- return
-
- if ( (get_dist(src, user) > 1 ))
- if (!istype(user, /mob/living/silicon))
- user.machine = null
- user << browse(null, "window=apc")
- return
- else if (istype(user, /mob/living/silicon) && src.aidisabled && !src.malfhack)
- user << "AI control for this APC interface has been disabled."
- user << browse(null, "window=apc")
- return
- else if (src.malfai)
- if ((src.malfai != user && src.malfai != user:parent) && !islinked(user, malfai))
- user << "AI control for this APC interface has been disabled."
- user << browse(null, "window=apc")
- return
- if(wiresexposed && (!istype(user, /mob/living/silicon)))
- var/t1 = text("
[area.name] APC wiresAccess Panel
\n")
- var/list/apcwires = list(
- "Orange" = 1,
- "Dark red" = 2,
- "White" = 3,
- "Yellow" = 4,
- )
- for(var/wiredesc in apcwires)
- var/is_uncut = src.apcwires & APCWireColorToFlag[apcwires[wiredesc]]
- t1 += "[wiredesc] wire: "
- if(!is_uncut)
- t1 += "Mend"
- else
- t1 += "Cut "
- t1 += "Pulse "
- t1 += "
"
- t1 += text("
\n[(src.locked ? "The APC is locked." : "The APC is unlocked.")]
\n[(src.shorted ? "The APCs power has been shorted." : "The APC is working properly!")]
\n[(src.aidisabled ? "The 'AI control allowed' light is off." : "The 'AI control allowed' light is on.")]")
- t1 += text("Close
")
- user << browse(t1, "window=apcwires")
- onclose(user, "apcwires")
-
- user.machine = src
- var/t = "[area.name] APCArea Power Controller ([area.name])
"
-
- if(locked && (!istype(user, /mob/living/silicon)))
- t += "(Swipe ID card to unlock inteface.)
"
- t += "Main breaker : [operating ? "On" : "Off"]
"
- t += "External power : [ main_status ? (main_status ==2 ? "Good" : "Low") : "None"]
"
- t += "Power cell: [cell ? "[round(cell.percent())]%" : "Not connected."]"
- if(cell)
- t += " ([charging ? ( charging == 1 ? "Charging" : "Fully charged" ) : "Not charging"])"
- t += " ([chargemode ? "Auto" : "Off"])"
-
- t += "
Power channels
"
-
- var/list/L = list ("Off","Off (Auto)", "On", "On (Auto)")
-
- t += "Equipment: [add_lspace(lastused_equip, 6)] W : [L[equipment+1]]
"
- t += "Lighting: [add_lspace(lastused_light, 6)] W : [L[lighting+1]]
"
- t += "Environmental:[add_lspace(lastused_environ, 6)] W : [L[environ+1]]
"
-
- t += "
Total load: [lastused_light + lastused_equip + lastused_environ] W"
- t += "
Cover lock: [coverlocked ? "Engaged" : "Disengaged"]"
-
- else
- if (!istype(user, /mob/living/silicon))
- t += "(Swipe ID card to lock interface.)
"
- t += "Main breaker: [operating ? "On Off" : "On Off" ]
"
- t += "External power : [ main_status ? (main_status ==2 ? "Good" : "Low") : "None"]
"
- if(cell)
- t += "Power cell: [round(cell.percent())]%"
- t += " ([charging ? ( charging == 1 ? "Charging" : "Fully charged" ) : "Not charging"])"
- t += " ([chargemode ? "Off Auto" : "Off Auto"])"
-
- else
- t += "Power cell: Not connected."
-
- t += "
Power channels
"
-
-
- t += "Equipment: [add_lspace(lastused_equip, 6)] W : "
- switch(equipment)
- if(0)
- t += "Off On Auto"
- if(1)
- t += "Off On Auto (Off)"
- if(2)
- t += "Off On Auto"
- if(3)
- t += "Off On Auto (On)"
- t +="
"
-
- t += "Lighting: [add_lspace(lastused_light, 6)] W : "
-
- switch(lighting)
- if(0)
- t += "Off On Auto"
- if(1)
- t += "Off On Auto (Off)"
- if(2)
- t += "Off On Auto"
- if(3)
- t += "Off On Auto (On)"
- t +="
"
-
-
- t += "Environmental:[add_lspace(lastused_environ, 6)] W : "
- switch(environ)
- if(0)
- t += "Off On Auto"
- if(1)
- t += "Off On Auto (Off)"
- if(2)
- t += "Off On Auto"
- if(3)
- t += "Off On Auto (On)"
-
-
-
- t += "
Total load: [lastused_light + lastused_equip + lastused_environ] W
"
- t += "
Cover lock: [coverlocked ? "Engaged" : "Disengaged"]"
-
-
- if (istype(user, /mob/living/silicon))
- t += "
Overload lighting circuit
"
- if (ticker && ticker.mode)
-// world << "there's a ticker"
- if(user.mind in ticker.mode.malf_ai)
-// world << "ticker says its malf"
- if (!src.malfai)
- t += "
Override Programming
"
- else
- t += "
APC Hacked
"
- if(!src.occupant)
- t += "Shunt Core Processes
"
- else
- t += "Core Processes Uploaded
"
-
- t += "
Close"
-
- t += ""
- user << browse(t, "window=apc")
- onclose(user, "apc")
- return
-
-/obj/machinery/power/apc/proc/report()
- return "[area.name] : [equipment]/[lighting]/[environ] ([lastused_equip+lastused_light+lastused_environ]) : [cell? cell.percent() : "N/C"] ([charging])"
-
-/obj/machinery/power/apc/proc/update()
- if(operating && !shorted)
- area.power_light = (lighting > 1)
- area.power_equip = (equipment > 1)
- area.power_environ = (environ > 1)
-// if (area.name == "AI Chamber")
-// spawn(10)
-// world << " [area.name] [area.power_equip]"
- else
- area.power_light = 0
- area.power_equip = 0
- area.power_environ = 0
-// if (area.name == "AI Chamber")
-// world << "[area.power_equip]"
- area.power_change()
-
-/obj/machinery/power/apc/proc/isWireColorCut(var/wireColor)
- var/wireFlag = APCWireColorToFlag[wireColor]
- return ((src.apcwires & wireFlag) == 0)
-
-/obj/machinery/power/apc/proc/isWireCut(var/wireIndex)
- var/wireFlag = APCIndexToFlag[wireIndex]
- return ((src.apcwires & wireFlag) == 0)
-
-/obj/machinery/power/apc/proc/cut(var/wireColor)
- var/wireFlag = APCWireColorToFlag[wireColor]
- var/wireIndex = APCWireColorToIndex[wireColor]
- apcwires &= ~wireFlag
- switch(wireIndex)
- if(APC_WIRE_MAIN_POWER1)
- src.shock(usr, 50)
- src.shorted = 1
- src.updateDialog()
- if(APC_WIRE_MAIN_POWER2)
- src.shock(usr, 50)
- src.shorted = 1
- src.updateDialog()
- if (APC_WIRE_AI_CONTROL)
- if (src.aidisabled == 0)
- src.aidisabled = 1
- src.updateDialog()
-// if(APC_WIRE_IDSCAN) nothing happens when you cut this wire, add in something if you want whatever
-
-/obj/machinery/power/apc/proc/mend(var/wireColor)
- var/wireFlag = APCWireColorToFlag[wireColor]
- var/wireIndex = APCWireColorToIndex[wireColor] //not used in this function
- apcwires |= wireFlag
- switch(wireIndex)
- if(APC_WIRE_MAIN_POWER1)
- if ((!src.isWireCut(APC_WIRE_MAIN_POWER1)) && (!src.isWireCut(APC_WIRE_MAIN_POWER2)))
- src.shorted = 0
- src.shock(usr, 50)
- src.updateDialog()
- if(APC_WIRE_MAIN_POWER2)
- if ((!src.isWireCut(APC_WIRE_MAIN_POWER1)) && (!src.isWireCut(APC_WIRE_MAIN_POWER2)))
- src.shorted = 0
- src.shock(usr, 50)
- src.updateDialog()
- if (APC_WIRE_AI_CONTROL)
- //one wire for AI control. Cutting this prevents the AI from controlling the door unless it has hacked the door through the power connection (which takes about a minute). If both main and backup power are cut, as well as this wire, then the AI cannot operate or hack the door at all.
- //aidisabledDisabled: If 1, AI control is disabled until the AI hacks back in and disables the lock. If 2, the AI has bypassed the lock. If -1, the control is enabled but the AI had bypassed it earlier, so if it is disabled again the AI would have no trouble getting back in.
- if (src.aidisabled == 1)
- src.aidisabled = 0
- src.updateDialog()
-// if(APC_WIRE_IDSCAN) nothing happens when you cut this wire, add in something if you want whatever
-
-/obj/machinery/power/apc/proc/pulse(var/wireColor)
- //var/wireFlag = apcWireColorToFlag[wireColor] //not used in this function
- var/wireIndex = APCWireColorToIndex[wireColor]
- switch(wireIndex)
- if(APC_WIRE_IDSCAN) //unlocks the APC for 30 seconds, if you have a better way to hack an APC I'm all ears
- src.locked = 0
- spawn(300)
- src.locked = 1
- src.updateDialog()
- if (APC_WIRE_MAIN_POWER1)
- if(shorted == 0)
- shorted = 1
- spawn(1200)
- if(shorted == 1)
- shorted = 0
- src.updateDialog()
- if (APC_WIRE_MAIN_POWER2)
- if(shorted == 0)
- shorted = 1
- spawn(1200)
- if(shorted == 1)
- shorted = 0
- src.updateDialog()
- if (APC_WIRE_AI_CONTROL)
- if (src.aidisabled == 0)
- src.aidisabled = 1
- src.updateDialog()
- spawn(10)
- if (src.aidisabled == 1)
- src.aidisabled = 0
- src.updateDialog()
-
-/obj/machinery/power/apc/proc/can_use(mob/user as mob) //used by attack_hand() and Topic()
- if (user.stat)
- user << "\red You must be conscious to use this [src]!"
- return 0
- if ( ! (istype(user, /mob/living/carbon/human) || \
- istype(user, /mob/living/silicon) || \
- istype(user, /mob/living/carbon/monkey) /*&& ticker && ticker.mode.name == "monkey"*/) )
- user << "\red You don't have the dexterity to use this [src]!"
- user << browse(null, "window=apc")
- user.machine = null
- return 0
- if(user.restrained())
- user << "\red You must have free hands to use this [src]"
- return 0
- if(user.lying)
- user << "\red You must stand to use this [src]!"
- return 0
- if (istype(user, /mob/living/silicon))
- var/mob/living/silicon/ai/AI = user
- var/mob/living/silicon/robot/robot = user
- if ( \
- src.aidisabled || \
- malfhack && istype(malfai) && \
- ( \
- (istype(AI) && (malfai!=AI && malfai != AI.parent)) || \
- (istype(robot) && (robot in malfai.connected_robots)) \
- ) \
- )
- user << "\red \The [src] have AI control disabled!"
- user << browse(null, "window=apc")
- user.machine = null
- return 0
- else
- if ((!in_range(src, user) || !istype(src.loc, /turf)))
- user << browse(null, "window=apc")
- user.machine = null
- return 0
- var/mob/living/carbon/human/H = user
- if (istype(H))
- if(H.brainloss >= 60)
- for(var/mob/M in viewers(src, null))
- M << "\red [H] stares cluelessly at [src] and drools."
- return 0
- else if(prob(H.brainloss))
- user << "\red You momentarily forget how to use [src]."
- return 0
- return 1
-
-/obj/machinery/power/apc/Topic(href, href_list)
- if (!can_use(usr))
- return
- src.add_fingerprint(usr)
- usr.machine = src
- if (href_list["apcwires"])
- var/t1 = text2num(href_list["apcwires"])
- if (!( istype(usr.equipped(), /obj/item/weapon/wirecutters) ))
- usr << "You need wirecutters!"
- return
- if (src.isWireColorCut(t1))
- src.mend(t1)
- else
- src.cut(t1)
- else if (href_list["pulse"])
- var/t1 = text2num(href_list["pulse"])
- if (!istype(usr.equipped(), /obj/item/device/multitool))
- usr << "You need a multitool!"
- return
- if (src.isWireColorCut(t1))
- usr << "You can't pulse a cut wire."
- return
- else
- src.pulse(t1)
- else if (href_list["lock"])
- coverlocked = !coverlocked
-
- else if (href_list["breaker"])
- operating = !operating
- if(malfai)
- if (ticker.mode.config_tag == "malfunction")
- if (src.z == 1) //if (is_type_in_list(get_area(src), the_station_areas))
- operating ? ticker.mode:apcs++ : ticker.mode:apcs--
- src.update()
- updateicon()
-
- else if (href_list["cmode"])
- chargemode = !chargemode
- if(!chargemode)
- charging = 0
- updateicon()
-
- else if (href_list["eqp"])
- var/val = text2num(href_list["eqp"])
-
- equipment = (val==1) ? 0 : val
-
- updateicon()
- update()
-
- else if (href_list["lgt"])
- var/val = text2num(href_list["lgt"])
-
- lighting = (val==1) ? 0 : val
-
- updateicon()
- update()
- else if (href_list["env"])
- var/val = text2num(href_list["env"])
-
- environ = (val==1) ? 0 :val
-
- updateicon()
- update()
- else if( href_list["close"] )
- usr << browse(null, "window=apc")
- usr.machine = null
- return
- else if (href_list["close2"])
- usr << browse(null, "window=apcwires")
- usr.machine = null
- return
-
- else if (href_list["overload"])
- if( istype(usr, /mob/living/silicon) && !src.aidisabled )
- src.overload_lighting()
-
- else if (href_list["malfhack"])
- var/mob/living/silicon/ai/malfai = usr
- if( istype(malfai, /mob/living/silicon/ai) && !src.aidisabled )
- if (malfai.malfhacking)
- malfai << "You are already hacking an APC."
- return
- malfai << "Beginning override of APC systems. This takes some time, and you cannot perform other actions during the process."
- malfai.malfhack = src
- malfai.malfhacking = 1
- sleep(600)
- if (!src.aidisabled)
- malfai.malfhack = null
- malfai.malfhacking = 0
- if (ticker.mode.config_tag == "malfunction")
- if (src.z == 1) //if (is_type_in_list(get_area(src), the_station_areas))
- ticker.mode:apcs++
- if(usr:parent)
- src.malfai = usr:parent
- else
- src.malfai = usr
- malfai << "Hack complete. The APC is now under your exclusive control."
-
- else if (href_list["occupyapc"])
- malfoccupy(usr)
-
-
- else if (href_list["deoccupyapc"])
- malfvacate()
-
- src.updateDialog()
- return
-
-/obj/machinery/power/apc/proc/malfoccupy(var/mob/living/silicon/ai/malf)
- if(!istype(malf))
- return
- src.occupant = new /mob/living/silicon/ai(src,malf.laws,null,1)
- src.occupant.adjustOxyLoss(malf.getOxyLoss())
- src.occupant.name = "[malf.name] APC Copy"
- if(malf.parent)
- src.occupant.parent = malf.parent
- else
- src.occupant.parent = malf
- malf.mind.transfer_to(src.occupant)
- if(malf.parent)
- del(malf)
- src.occupant.verbs += /mob/living/silicon/ai/proc/corereturn
- src.occupant.cancel_camera()
-
-/obj/machinery/power/apc/proc/malfvacate(var/forced)
- if(!src.occupant)
- return
- if(src.occupant.parent && src.occupant.parent.stat != 2)
- src.occupant.mind.transfer_to(src.occupant.parent)
- src.occupant.parent.adjustOxyLoss(src.occupant.getOxyLoss())
- src.occupant.parent.cancel_camera()
- del(src.occupant)
-
- else
- src.occupant << "\red Primary core damaged, unable to return core processes."
- if(forced)
- src.occupant.loc = src.loc
- src.occupant.death()
- src.occupant.gib()
-
-
-/obj/machinery/power/apc/proc/ion_act()
- //intended to be exactly the same as an AI malf attack
- if(!src.malfhack && src.z == 1)
- if(prob(3))
- src.locked = 1
- if (src.cell.charge > 0)
-// world << "\red blew APC in [src.loc.loc]"
- src.cell.charge = 0
- cell.corrupt()
- src.malfhack = 1
- updateicon()
- var/datum/effect/effect/system/harmless_smoke_spread/smoke = new /datum/effect/effect/system/harmless_smoke_spread()
- smoke.set_up(3, 0, src.loc)
- smoke.attach(src)
- smoke.start()
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(3, 1, src)
- s.start()
- for(var/mob/M in viewers(src))
- M.show_message("\red The [src.name] suddenly lets out a blast of smoke and some sparks!", 3, "\red You hear sizzling electronics.", 2)
-
-
-/obj/machinery/power/apc/surplus()
- if(terminal)
- return terminal.surplus()
- else
- return 0
-
-/obj/machinery/power/apc/add_load(var/amount)
- if(terminal && terminal.powernet)
- terminal.powernet.newload += amount
-
-/obj/machinery/power/apc/avail()
- if(terminal)
- return terminal.avail()
- else
- return 0
-
-/obj/machinery/power/apc/process()
-
- if(stat & (BROKEN|MAINT))
- return
- if(!area.requires_power)
- return
-
-
- /*
- if (equipment > 1) // off=0, off auto=1, on=2, on auto=3
- use_power(src.equip_consumption, EQUIP)
- if (lighting > 1) // off=0, off auto=1, on=2, on auto=3
- use_power(src.light_consumption, LIGHT)
- if (environ > 1) // off=0, off auto=1, on=2, on auto=3
- use_power(src.environ_consumption, ENVIRON)
-
- area.calc_lighting() */
-
- lastused_light = area.usage(LIGHT)
- lastused_equip = area.usage(EQUIP)
- lastused_environ = area.usage(ENVIRON)
- area.clear_usage()
-
- lastused_total = lastused_light + lastused_equip + lastused_environ
-
- //store states to update icon if any change
- var/last_lt = lighting
- var/last_eq = equipment
- var/last_en = environ
- var/last_ch = charging
-
- var/excess = surplus()
-
- if(!src.avail())
- main_status = 0
- else if(excess < 0)
- main_status = 1
- else
- main_status = 2
-
- var/perapc = 0
- if(terminal && terminal.powernet)
- perapc = terminal.powernet.perapc
-
- if(cell && !shorted)
-
- // draw power from cell as before
-
- var/cellused = min(cell.charge, CELLRATE * lastused_total) // clamp deduction to a max, amount left in cell
- cell.use(cellused)
-
- if(excess > 0 || perapc > lastused_total) // if power excess, or enough anyway, recharge the cell
- // by the same amount just used
-
- cell.give(cellused)
- add_load(cellused/CELLRATE) // add the load used to recharge the cell
-
-
- else // no excess, and not enough per-apc
-
- if( (cell.charge/CELLRATE+perapc) >= lastused_total) // can we draw enough from cell+grid to cover last usage?
-
- cell.charge = min(cell.maxcharge, cell.charge + CELLRATE * perapc) //recharge with what we can
- add_load(perapc) // so draw what we can from the grid
- charging = 0
-
- else // not enough power available to run the last tick!
- charging = 0
- chargecount = 0
- // This turns everything off in the case that there is still a charge left on the battery, just not enough to run the room.
- equipment = autoset(equipment, 0)
- lighting = autoset(lighting, 0)
- environ = autoset(environ, 0)
-
- // set channels depending on how much charge we have left
-
- if(cell.charge <= 0) // zero charge, turn all off
- equipment = autoset(equipment, 0)
- lighting = autoset(lighting, 0)
- environ = autoset(environ, 0)
- area.poweralert(0, src)
- else if(cell.percent() < 15) // <15%, turn off lighting & equipment
- equipment = autoset(equipment, 2)
- lighting = autoset(lighting, 2)
- environ = autoset(environ, 1)
- area.poweralert(0, src)
- else if(cell.percent() < 30) // <30%, turn off equipment
- equipment = autoset(equipment, 2)
- lighting = autoset(lighting, 1)
- environ = autoset(environ, 1)
- area.poweralert(0, src)
- else // otherwise all can be on
- equipment = autoset(equipment, 1)
- lighting = autoset(lighting, 1)
- environ = autoset(environ, 1)
- area.poweralert(1, src)
- if(cell.percent() > 75)
- area.poweralert(1, src)
-
- // now trickle-charge the cell
-
- if(chargemode && charging == 1 && operating)
- if(excess > 0) // check to make sure we have enough to charge
- // Max charge is perapc share, capped to cell capacity, or % per second constant (Whichever is smallest)
-/* var/ch = min(perapc, (cell.maxcharge - cell.charge), (cell.maxcharge*CHARGELEVEL))
- add_load(ch) // Removes the power we're taking from the grid
- cell.give(ch) // actually recharge the cell
-*/
- var/ch = min(perapc*CELLRATE, (cell.maxcharge - cell.charge), (cell.maxcharge*CHARGELEVEL))
- add_load(ch/CELLRATE) // Removes the power we're taking from the grid
- cell.give(ch) // actually recharge the cell
-
- else
- charging = 0 // stop charging
- chargecount = 0
-
- // show cell as fully charged if so
-
- if(cell.charge >= cell.maxcharge)
- charging = 2
-
- if(chargemode)
- if(!charging)
- if(excess > cell.maxcharge*CHARGELEVEL)
- chargecount++
- else
- chargecount = 0
-
- if(chargecount == 10)
-
- chargecount = 0
- charging = 1
-
- else // chargemode off
- charging = 0
- chargecount = 0
-
- else // no cell, switch everything off
-
- charging = 0
- chargecount = 0
- equipment = autoset(equipment, 0)
- lighting = autoset(lighting, 0)
- environ = autoset(environ, 0)
- area.poweralert(0, src)
-
- // update icon & area power if anything changed
-
- if(last_lt != lighting || last_eq != equipment || last_en != environ)
- updateicon()
- update()
- else if (last_ch != charging)
- updateicon()
-
- //src.updateDialog()
- src.updateDialog()
-
-// val 0=off, 1=off(auto) 2=on 3=on(auto)
-// on 0=off, 1=on, 2=autooff
-
-/proc/autoset(var/val, var/on)
-
- if(on==0)
- if(val==2) // if on, return off
- return 0
- else if(val==3) // if auto-on, return auto-off
- return 1
-
- else if(on==1)
- if(val==1) // if auto-off, return auto-on
- return 3
-
- else if(on==2)
- if(val==3) // if auto-on, return auto-off
- return 1
-
- return val
-
-// damage and destruction acts
-
-/obj/machinery/power/apc/meteorhit(var/obj/O as obj)
-
- set_broken()
- return
-
-/obj/machinery/power/apc/emp_act(severity)
- if(cell)
- cell.emp_act(severity)
- if(occupant)
- occupant.emp_act(severity)
- lighting = 0
- equipment = 0
- environ = 0
- spawn(600)
- equipment = 3
- environ = 3
- ..()
-
-/obj/machinery/power/apc/ex_act(severity)
-
- switch(severity)
- if(1.0)
- //set_broken() //now Del() do what we need
- if (cell)
- cell.ex_act(1.0) // more lags woohoo
- del(src)
- return
- if(2.0)
- if (prob(50))
- set_broken()
- if (cell && prob(50))
- cell.ex_act(2.0)
- if(3.0)
- if (prob(25))
- set_broken()
- if (cell && prob(25))
- cell.ex_act(3.0)
- return
-
-/obj/machinery/power/apc/blob_act()
- if (prob(75))
- set_broken()
- if (cell && prob(5))
- cell.blob_act()
-
-/obj/machinery/power/apc/proc/set_broken()
- if(malfai && operating)
- if (ticker.mode.config_tag == "malfunction")
- if (src.z == 1) //if (is_type_in_list(get_area(src), the_station_areas))
- ticker.mode:apcs--
- stat |= BROKEN
- operating = 0
- if(occupant)
- malfvacate(1)
- updateicon()
- update()
-
-// overload all the lights in this APC area
-
-/obj/machinery/power/apc/proc/overload_lighting()
- if(/* !get_connection() || */ !operating || shorted)
- return
- if( cell && cell.charge>=20)
- cell.use(20);
- spawn(0)
- for(var/area/A in area.related)
- for(var/obj/machinery/light/L in A)
- L.on = 1
- L.broken()
- sleep(1)
-
-/obj/machinery/power/apc/Del()
- if(malfai && operating)
- if (ticker.mode.config_tag == "malfunction")
- if (src.z == 1) //if (is_type_in_list(get_area(src), the_station_areas))
- ticker.mode:apcs--
- area.power_light = 0
- area.power_equip = 0
- area.power_environ = 0
- area.power_change()
- if(occupant)
- malfvacate(1)
- ..()
-
-/obj/machinery/power/apc/proc/shock(mob/user, prb)
- if(!prob(prb))
- return 0
- var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
- s.set_up(5, 1, src)
- s.start()
- if (electrocute_mob(user, src, src))
- return 1
- else
- return 0
+#define APC_WIRE_IDSCAN 1
+#define APC_WIRE_MAIN_POWER1 2
+#define APC_WIRE_MAIN_POWER2 3
+#define APC_WIRE_AI_CONTROL 4
+
+// the Area Power Controller (APC), formerly Power Distribution Unit (PDU)
+// one per area, needs wire conection to power network
+
+// controls power to devices in that area
+// may be opened to change power cell
+// three different channels (lighting/equipment/environ) - may each be set to on, off, or auto
+
+
+//NOTE: STUFF STOLEN FROM AIRLOCK.DM thx
+
+
+/obj/machinery/power/apc
+ name = "area power controller"
+
+ icon_state = "apc0"
+ anchored = 1
+ req_access = list(access_engine_equip)
+ var/area/area
+ var/areastring = null
+ var/obj/item/weapon/cell/cell
+ var/start_charge = 90 // initial cell charge %
+ var/cell_type = 2500 // 0=no cell, 1=regular, 2=high-cap (x5) <- old, now it's just 0=no cell, otherwise dictate cellcapacity by changing this value. 1 used to be 1000, 2 was 2500
+ var/opened = 0 //0=closed, 1=opened, 2=cover removed
+ var/shorted = 0
+ var/lighting = 3
+ var/equipment = 3
+ var/environ = 3
+ var/operating = 1
+ var/charging = 0
+ var/chargemode = 1
+ var/chargecount = 0
+ var/locked = 1
+ var/coverlocked = 1
+ var/aidisabled = 0
+ var/tdir = null
+ var/obj/machinery/power/terminal/terminal = null
+ var/lastused_light = 0
+ var/lastused_equip = 0
+ var/lastused_environ = 0
+ var/lastused_total = 0
+ var/main_status = 0
+ var/light_consumption = 0 //not used
+ var/equip_consumption = 0 //not used
+ var/environ_consumption = 0 //not used
+ var/emagged = 0
+ var/wiresexposed = 0
+ var/apcwires = 15
+ netnum = -1 // set so that APCs aren't found as powernet nodes
+ var/malfhack = 0 //New var for my changes to AI malf. --NeoFite
+ var/mob/living/silicon/ai/malfai = null //See above --NeoFite
+// luminosity = 1
+ var/has_electronics = 0 // 0 - none, 1 - plugged in, 2 - secured by screwdriver
+ var/overload = 1 //used for the Blackout malf module
+ var/mob/living/silicon/ai/occupant = null
+
+/proc/RandomAPCWires()
+ //to make this not randomize the wires, just set index to 1 and increment it in the flag for loop (after doing everything else).
+ var/list/apcwires = list(0, 0, 0, 0)
+ APCIndexToFlag = list(0, 0, 0, 0)
+ APCIndexToWireColor = list(0, 0, 0, 0)
+ APCWireColorToIndex = list(0, 0, 0, 0)
+ var/flagIndex = 1
+ for (var/flag=1, flag<16, flag+=flag)
+ var/valid = 0
+ while (!valid)
+ var/colorIndex = rand(1, 4)
+ if (apcwires[colorIndex]==0)
+ valid = 1
+ apcwires[colorIndex] = flag
+ APCIndexToFlag[flagIndex] = flag
+ APCIndexToWireColor[flagIndex] = colorIndex
+ APCWireColorToIndex[colorIndex] = flagIndex
+ flagIndex+=1
+ return apcwires
+
+/obj/machinery/power/apc/updateDialog()
+ if (stat & (BROKEN|MAINT))
+ return
+ var/list/nearby = viewers(1, src)
+ for(var/mob/M in nearby)
+ if (M.client && M.machine == src)
+ src.interact(M)
+ AutoUpdateAI(src)
+
+/obj/machinery/power/apc/New(turf/loc, var/ndir, var/building=0)
+ ..()
+
+ // offset 24 pixels in direction of dir
+ // this allows the APC to be embedded in a wall, yet still inside an area
+ if (building)
+ dir = ndir
+ src.tdir = dir // to fix Vars bug
+ dir = SOUTH
+
+ pixel_x = (src.tdir & 3)? 0 : (src.tdir == 4 ? 24 : -24)
+ pixel_y = (src.tdir & 3)? (src.tdir ==1 ? 24 : -24) : 0
+ if (building==0)
+ init()
+ else
+ area = src.loc.loc:master
+ opened = 1
+ operating = 0
+ name = "[area.name] APC"
+ stat |= MAINT
+ src.updateicon()
+ spawn(5)
+ src.update()
+
+
+
+/obj/machinery/power/apc/proc/make_terminal()
+ // create a terminal object at the same position as original turf loc
+ // wires will attach to this
+ terminal = new/obj/machinery/power/terminal(src.loc)
+ terminal.dir = tdir
+ terminal.master = src
+
+/obj/machinery/power/apc/proc/init()
+ has_electronics = 2 //installed and secured
+ // is starting with a power cell installed, create it and set its charge level
+ if(cell_type)
+ src.cell = new/obj/item/weapon/cell(src)
+ cell.maxcharge = cell_type // cell_type is maximum charge (old default was 1000 or 2500 (values one and two respectively)
+ cell.charge = start_charge * cell.maxcharge / 100.0 // (convert percentage to actual value)
+
+ var/area/A = src.loc.loc
+
+ //if area isn't specified use current
+ if(isarea(A) && src.areastring == null)
+ src.area = A
+ else
+ src.area = get_area_name(areastring)
+ updateicon()
+
+ make_terminal()
+
+ spawn(5)
+ src.update()
+
+/obj/machinery/power/apc/examine()
+ set src in oview(1)
+
+ if(usr /*&& !usr.stat*/)
+ usr << "A control terminal for the area electrical systems."
+ if(stat & BROKEN)
+ usr << "Looks broken."
+ return
+ if(opened)
+ if(has_electronics && terminal)
+ usr << "The cover is [opened==2?"removed":"open"] and the power cell is [ cell ? "installed" : "missing"]."
+ else if (!has_electronics && terminal)
+ usr << "There are some wires but no any electronics."
+ else if (has_electronics && !terminal)
+ usr << "Electronics installed but not wired."
+ else /* if (!has_electronics && !terminal) */
+ usr << "There is no electronics nor connected wires."
+
+ else
+ if (stat & MAINT)
+ usr << "The cover is closed. Something wrong with it: it's doesn't work."
+ else if (malfhack)
+ usr << "The cover is broken. It's may be hard to force it open."
+ else
+ usr << "The cover is closed."
+
+
+// update the APC icon to show the three base states
+// also add overlays for indicator lights
+/obj/machinery/power/apc/proc/updateicon()
+ src.overlays = null
+ if(opened)
+ var/basestate = "apc[ cell ? "2" : "1" ]" // if opened, show cell if it's inserted
+ if (opened==1)
+ if (stat & (MAINT|BROKEN))
+ icon_state = "apcmaint" //disassembled APC cannot hold cell
+ else
+ icon_state = basestate
+ else if (opened == 2)
+ if ((stat & BROKEN) || malfhack )
+ icon_state = "[basestate]-b-nocover"
+ else /* if (emagged)*/
+ icon_state = "[basestate]-nocover"
+ else if (stat & BROKEN)
+ icon_state = "apc-b"
+ else if(emagged || malfai)
+ icon_state = "apcemag"
+ else if(wiresexposed)
+ icon_state = "apcewires"
+ else
+ icon_state = "apc0"
+ // if closed, update overlays for channel status
+ if (!(stat & (BROKEN|MAINT)))
+ overlays += image('power.dmi', "apcox-[locked]") // 0=blue 1=red
+ overlays += image('power.dmi', "apco3-[charging]") // 0=red, 1=yellow/black 2=green
+ if(operating)
+ overlays += image('power.dmi', "apco0-[equipment]") // 0=red, 1=green, 2=blue
+ overlays += image('power.dmi', "apco1-[lighting]")
+ overlays += image('power.dmi', "apco2-[environ]")
+
+//attack with an item - open/close cover, insert cell, or (un)lock interface
+
+/obj/machinery/power/apc/attackby(obj/item/W, mob/user)
+
+ if (istype(user, /mob/living/silicon) && get_dist(src,user)>1)
+ return src.attack_hand(user)
+ if (istype(W, /obj/item/weapon/crowbar) && opened)
+ if (has_electronics==1)
+ if (terminal)
+ user << "\red Disconnect wires first."
+ return
+ playsound(src.loc, 'Crowbar.ogg', 50, 1)
+ user << "You trying to remove the power control board..."
+ if(do_after(user, 50))
+ has_electronics = 0
+ if ((stat & BROKEN) || malfhack)
+ user.visible_message(\
+ "\red [user.name] has broken the power control board inside [src.name]!",\
+ "You broke the charred power control board and remove the remains.",
+ "You hear a crack!")
+ //ticker.mode:apcs-- //XSI said no and I agreed. -rastaf0
+ else
+ user.visible_message(\
+ "\red [user.name] has removed the power control board from [src.name]!",\
+ "You remove the power control board.")
+ new /obj/item/weapon/module/power_control(loc)
+ else if (opened!=2) //cover isn't removed
+ opened = 0
+ updateicon()
+ else if (istype(W, /obj/item/weapon/crowbar) && !((stat & BROKEN) || malfhack) )
+ if(coverlocked && !(stat & MAINT))
+ user << "\red The cover is locked and cannot be opened."
+ return
+ else
+ opened = 1
+ updateicon()
+ else if (istype(W, /obj/item/weapon/cell) && opened) // trying to put a cell inside
+ if(cell)
+ user << "There is a power cell already installed."
+ return
+ else
+ if (stat & MAINT)
+ user << "\red There is no any connector for your power cell."
+ return
+ user.drop_item()
+ W.loc = src
+ cell = W
+ user.visible_message(\
+ "\red [user.name] has inserted the power cell to [src.name]!",\
+ "You insert the power cell.")
+ chargecount = 0
+ updateicon()
+ else if (istype(W, /obj/item/weapon/screwdriver)) // haxing
+ if(opened)
+ if (cell)
+ user << "\red Close the APC first." //Less hints more mystery!
+ return
+ else
+ if (has_electronics==1 && terminal)
+ has_electronics = 2
+ stat &= ~MAINT
+ playsound(src.loc, 'Screwdriver.ogg', 50, 1)
+ user << "You screw the circuit electronics into place."
+ else if (has_electronics==2)
+ has_electronics = 1
+ stat |= MAINT
+ playsound(src.loc, 'Screwdriver.ogg', 50, 1)
+ user << "You unfasten the electronics."
+ else /* has_electronics==0 */
+ user << "\red There is nothing to secure."
+ return
+ updateicon()
+ else if(emagged)
+ user << "The interface is broken."
+ else
+ wiresexposed = !wiresexposed
+ user << "The wires have been [wiresexposed ? "exposed" : "unexposed"]"
+ updateicon()
+
+ else if (istype(W, /obj/item/weapon/card/id)||istype(W, /obj/item/device/pda)) // trying to unlock the interface with an ID card
+ if(emagged)
+ user << "The interface is broken."
+ else if(opened)
+ user << "You must close the cover to swipe an ID card."
+ else if(wiresexposed)
+ user << "You must close the panel"
+ else if(stat & (BROKEN|MAINT))
+ user << "Nothing happens."
+ else
+ if(src.allowed(usr))
+ locked = !locked
+ user << "You [ locked ? "lock" : "unlock"] the APC interface."
+ updateicon()
+ else
+ user << "\red Access denied."
+ else if (istype(W, /obj/item/weapon/card/emag) && !(emagged || malfhack)) // trying to unlock with an emag card
+ if(opened)
+ user << "You must close the cover to swipe an ID card."
+ else if(wiresexposed)
+ user << "You must close the panel first"
+ else if(stat & (BROKEN|MAINT))
+ user << "Nothing happens."
+ else
+ flick("apc-spark", src)
+ if (do_after(user,6))
+ if(prob(50))
+ emagged = 1
+ locked = 0
+ user << "You emag the APC interface."
+ updateicon()
+ else
+ user << "You fail to [ locked ? "unlock" : "lock"] the APC interface."
+ else if (istype(W, /obj/item/weapon/cable_coil) && !terminal && opened && has_electronics!=2)
+ if (src.loc:intact)
+ user << "\red You must remove the floor plating in front of the APC first."
+ return
+ var/obj/item/weapon/cable_coil/C = W
+ if(C.amount < 10)
+ user << "\red You need more wires."
+ return
+ user << "You start adding cables to the APC frame..."
+ playsound(src.loc, 'Deconstruct.ogg', 50, 1)
+ if(do_after(user, 20) && C.amount >= 10)
+ var/turf/T = get_turf_loc(src)
+ var/obj/structure/cable/N = T.get_cable_node()
+ if (prob(50) && electrocute_mob(usr, N, N))
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ s.set_up(5, 1, src)
+ s.start()
+ return
+ C.use(10)
+ user.visible_message(\
+ "\red [user.name] has added cables to the APC frame!",\
+ "You add cables to the APC frame.")
+ make_terminal()
+ terminal.connect_to_network()
+ else if (istype(W, /obj/item/weapon/wirecutters) && terminal && opened && has_electronics!=2)
+ if (src.loc:intact)
+ user << "\red You must remove the floor plating in front of the APC first."
+ return
+ user << "You begin to cut cables..."
+ playsound(src.loc, 'Deconstruct.ogg', 50, 1)
+ if(do_after(user, 50))
+ if (prob(50) && electrocute_mob(usr, terminal.powernet, terminal))
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ s.set_up(5, 1, src)
+ s.start()
+ return
+ new /obj/item/weapon/cable_coil(loc,10)
+ user.visible_message(\
+ "\red [user.name] cut cables and dismantled the power terminal.",\
+ "You cut cables and dismantle the power terminal.")
+ del(terminal)
+ else if (istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics==0 && !((stat & BROKEN) || malfhack))
+ user << "You trying to insert the power control board into the frame..."
+ playsound(src.loc, 'Deconstruct.ogg', 50, 1)
+ if(do_after(user, 10))
+ has_electronics = 1
+ user << "You place the power control board inside the frame."
+ del(W)
+ else if (istype(W, /obj/item/weapon/module/power_control) && opened && has_electronics==0 && ((stat & BROKEN) || malfhack))
+ user << "\red You cannot put the board inside, the frame is damaged."
+ return
+ else if (istype(W, /obj/item/weapon/weldingtool) && W:welding && opened && has_electronics==0 && !terminal)
+ if (W:get_fuel() < 3)
+ user << "\blue You need more welding fuel to complete this task."
+ return
+ user << "You start welding APC frame..."
+ if(W:remove_fuel(0,user))
+ W:welding = 2
+ playsound(src.loc, 'Welder.ogg', 50, 1)
+ if(do_after(user, 50))
+
+ if (emagged || malfhack || (stat & BROKEN) || opened==2)
+ new /obj/item/stack/sheet/metal(loc)
+ user.visible_message(\
+ "\red [src] has been cut apart by [user.name] with the weldingtool.",\
+ "You disassembled the broken APC frame.",\
+ "\red You hear welding.")
+ else
+ new /obj/item/apc_frame(loc)
+ user.visible_message(\
+ "\red [src] has been cut from the wall by [user.name] with the weldingtool.",\
+ "You cut APC frame from the wall.",\
+ "\red You hear welding.")
+ W:welding = 1
+ del(src)
+ return
+ else if (istype(W, /obj/item/apc_frame) && opened && emagged)
+ emagged = 0
+ if (opened==2)
+ opened = 1
+ user.visible_message(\
+ "\red [user.name] has replaced the damaged APC frontal panel with a new one.",\
+ "You replace the damaged APC frontal panel with a new one.")
+ del(W)
+ updateicon()
+ else if (istype(W, /obj/item/apc_frame) && opened && ((stat & BROKEN) || malfhack))
+ if (has_electronics)
+ user << "You cannot repair this APC until you remove the electronics still inside."
+ return
+ user << "You begin to replace the damaged APC frame..."
+ if(do_after(user, 50))
+ user.visible_message(\
+ "\red [user.name] has replaced the damaged APC frame with new one.",\
+ "You replace the damaged APC frame with new one.")
+ del(W)
+ stat &= ~BROKEN
+ malfai = null
+ malfhack = 0
+ if (opened==2)
+ opened = 1
+ updateicon()
+ else
+ if ( ((stat & BROKEN) || malfhack) \
+ && !opened \
+ && W.force >= 5 \
+ && W.w_class >= 3.0 \
+ && prob(20) )
+ opened = 2
+ user.visible_message("\red The APC cover was knocked down with the [W.name] by [user.name]!", \
+ "\red You knock down the APC cover with your [W.name]!", \
+ "You hear bang")
+ updateicon()
+ else
+ if (istype(user, /mob/living/silicon))
+ return src.attack_hand(user)
+ if (!opened && wiresexposed && \
+ (istype(W, /obj/item/device/multitool) || \
+ istype(W, /obj/item/weapon/wirecutters)))
+ return src.attack_hand(user)
+ user.visible_message("\red The [src.name] has been hit with the [W.name] by [user.name]!", \
+ "\red You hit the [src.name] with your [W.name]!", \
+ "You hear bang")
+
+// attack with hand - remove cell (if cover open) or interact with the APC
+
+/obj/machinery/power/apc/attack_hand(mob/user)
+ if (!can_use(user))
+ return
+ src.add_fingerprint(user)
+ if(opened && (!istype(user, /mob/living/silicon)))
+ if(cell)
+ usr.put_in_hand(cell)
+ cell.add_fingerprint(user)
+ cell.updateicon()
+
+ src.cell = null
+ user.visible_message("\red [user.name] removes the power cell from [src.name]!", "You remove the power cell.")
+ //user << "You remove the power cell."
+ charging = 0
+ src.updateicon()
+ return
+ if(stat & (BROKEN|MAINT))
+ return
+
+ if(ishuman(user))
+ if(istype(user:gloves, /obj/item/clothing/gloves/space_ninja)&&user:gloves:candrain&&!user:gloves:draining)
+ call(/obj/item/clothing/gloves/space_ninja/proc/drain)("APC",src,user:wear_suit)
+ return
+ // do APC interaction
+ user.machine = src
+ src.interact(user)
+
+/obj/machinery/power/apc/proc/interact(mob/user)
+ if(!user)
+ return
+
+ if ( (get_dist(src, user) > 1 ))
+ if (!istype(user, /mob/living/silicon))
+ user.machine = null
+ user << browse(null, "window=apc")
+ return
+ else if (istype(user, /mob/living/silicon) && src.aidisabled && !src.malfhack)
+ user << "AI control for this APC interface has been disabled."
+ user << browse(null, "window=apc")
+ return
+ else if (src.malfai)
+ if ((src.malfai != user && src.malfai != user:parent) && !islinked(user, malfai))
+ user << "AI control for this APC interface has been disabled."
+ user << browse(null, "window=apc")
+ return
+ if(wiresexposed && (!istype(user, /mob/living/silicon)))
+ var/t1 = text("[area.name] APC wiresAccess Panel
\n")
+ var/list/apcwires = list(
+ "Orange" = 1,
+ "Dark red" = 2,
+ "White" = 3,
+ "Yellow" = 4,
+ )
+ for(var/wiredesc in apcwires)
+ var/is_uncut = src.apcwires & APCWireColorToFlag[apcwires[wiredesc]]
+ t1 += "[wiredesc] wire: "
+ if(!is_uncut)
+ t1 += "Mend"
+ else
+ t1 += "Cut "
+ t1 += "Pulse "
+ t1 += "
"
+ t1 += text("
\n[(src.locked ? "The APC is locked." : "The APC is unlocked.")]
\n[(src.shorted ? "The APCs power has been shorted." : "The APC is working properly!")]
\n[(src.aidisabled ? "The 'AI control allowed' light is off." : "The 'AI control allowed' light is on.")]")
+ t1 += text("Close
")
+ user << browse(t1, "window=apcwires")
+ onclose(user, "apcwires")
+
+ user.machine = src
+ var/t = "[area.name] APCArea Power Controller ([area.name])
"
+
+ if(locked && (!istype(user, /mob/living/silicon)))
+ t += "(Swipe ID card to unlock inteface.)
"
+ t += "Main breaker : [operating ? "On" : "Off"]
"
+ t += "External power : [ main_status ? (main_status ==2 ? "Good" : "Low") : "None"]
"
+ t += "Power cell: [cell ? "[round(cell.percent())]%" : "Not connected."]"
+ if(cell)
+ t += " ([charging ? ( charging == 1 ? "Charging" : "Fully charged" ) : "Not charging"])"
+ t += " ([chargemode ? "Auto" : "Off"])"
+
+ t += "
Power channels
"
+
+ var/list/L = list ("Off","Off (Auto)", "On", "On (Auto)")
+
+ t += "Equipment: [add_lspace(lastused_equip, 6)] W : [L[equipment+1]]
"
+ t += "Lighting: [add_lspace(lastused_light, 6)] W : [L[lighting+1]]
"
+ t += "Environmental:[add_lspace(lastused_environ, 6)] W : [L[environ+1]]
"
+
+ t += "
Total load: [lastused_light + lastused_equip + lastused_environ] W"
+ t += "
Cover lock: [coverlocked ? "Engaged" : "Disengaged"]"
+
+ else
+ if (!istype(user, /mob/living/silicon))
+ t += "(Swipe ID card to lock interface.)
"
+ t += "Main breaker: [operating ? "On Off" : "On Off" ]
"
+ t += "External power : [ main_status ? (main_status ==2 ? "Good" : "Low") : "None"]
"
+ if(cell)
+ t += "Power cell: [round(cell.percent())]%"
+ t += " ([charging ? ( charging == 1 ? "Charging" : "Fully charged" ) : "Not charging"])"
+ t += " ([chargemode ? "Off Auto" : "Off Auto"])"
+
+ else
+ t += "Power cell: Not connected."
+
+ t += "
Power channels
"
+
+
+ t += "Equipment: [add_lspace(lastused_equip, 6)] W : "
+ switch(equipment)
+ if(0)
+ t += "Off On Auto"
+ if(1)
+ t += "Off On Auto (Off)"
+ if(2)
+ t += "Off On Auto"
+ if(3)
+ t += "Off On Auto (On)"
+ t +="
"
+
+ t += "Lighting: [add_lspace(lastused_light, 6)] W : "
+
+ switch(lighting)
+ if(0)
+ t += "Off On Auto"
+ if(1)
+ t += "Off On Auto (Off)"
+ if(2)
+ t += "Off On Auto"
+ if(3)
+ t += "Off On Auto (On)"
+ t +="
"
+
+
+ t += "Environmental:[add_lspace(lastused_environ, 6)] W : "
+ switch(environ)
+ if(0)
+ t += "Off On Auto"
+ if(1)
+ t += "Off On Auto (Off)"
+ if(2)
+ t += "Off On Auto"
+ if(3)
+ t += "Off On Auto (On)"
+
+
+
+ t += "
Total load: [lastused_light + lastused_equip + lastused_environ] W
"
+ t += "
Cover lock: [coverlocked ? "Engaged" : "Disengaged"]"
+
+
+ if (istype(user, /mob/living/silicon))
+ t += "
Overload lighting circuit
"
+ if (ticker && ticker.mode)
+// world << "there's a ticker"
+ if(user.mind in ticker.mode.malf_ai)
+// world << "ticker says its malf"
+ if (!src.malfai)
+ t += "
Override Programming
"
+ else
+ t += "
APC Hacked
"
+ if(!src.occupant)
+ t += "Shunt Core Processes
"
+ else
+ t += "Core Processes Uploaded
"
+
+ t += "
Close"
+
+ t += ""
+ user << browse(t, "window=apc")
+ onclose(user, "apc")
+ return
+
+/obj/machinery/power/apc/proc/report()
+ return "[area.name] : [equipment]/[lighting]/[environ] ([lastused_equip+lastused_light+lastused_environ]) : [cell? cell.percent() : "N/C"] ([charging])"
+
+/obj/machinery/power/apc/proc/update()
+ if(operating && !shorted)
+ area.power_light = (lighting > 1)
+ area.power_equip = (equipment > 1)
+ area.power_environ = (environ > 1)
+// if (area.name == "AI Chamber")
+// spawn(10)
+// world << " [area.name] [area.power_equip]"
+ else
+ area.power_light = 0
+ area.power_equip = 0
+ area.power_environ = 0
+// if (area.name == "AI Chamber")
+// world << "[area.power_equip]"
+ area.power_change()
+
+/obj/machinery/power/apc/proc/isWireColorCut(var/wireColor)
+ var/wireFlag = APCWireColorToFlag[wireColor]
+ return ((src.apcwires & wireFlag) == 0)
+
+/obj/machinery/power/apc/proc/isWireCut(var/wireIndex)
+ var/wireFlag = APCIndexToFlag[wireIndex]
+ return ((src.apcwires & wireFlag) == 0)
+
+/obj/machinery/power/apc/proc/cut(var/wireColor)
+ var/wireFlag = APCWireColorToFlag[wireColor]
+ var/wireIndex = APCWireColorToIndex[wireColor]
+ apcwires &= ~wireFlag
+ switch(wireIndex)
+ if(APC_WIRE_MAIN_POWER1)
+ src.shock(usr, 50)
+ src.shorted = 1
+ src.updateDialog()
+ if(APC_WIRE_MAIN_POWER2)
+ src.shock(usr, 50)
+ src.shorted = 1
+ src.updateDialog()
+ if (APC_WIRE_AI_CONTROL)
+ if (src.aidisabled == 0)
+ src.aidisabled = 1
+ src.updateDialog()
+// if(APC_WIRE_IDSCAN) nothing happens when you cut this wire, add in something if you want whatever
+
+/obj/machinery/power/apc/proc/mend(var/wireColor)
+ var/wireFlag = APCWireColorToFlag[wireColor]
+ var/wireIndex = APCWireColorToIndex[wireColor] //not used in this function
+ apcwires |= wireFlag
+ switch(wireIndex)
+ if(APC_WIRE_MAIN_POWER1)
+ if ((!src.isWireCut(APC_WIRE_MAIN_POWER1)) && (!src.isWireCut(APC_WIRE_MAIN_POWER2)))
+ src.shorted = 0
+ src.shock(usr, 50)
+ src.updateDialog()
+ if(APC_WIRE_MAIN_POWER2)
+ if ((!src.isWireCut(APC_WIRE_MAIN_POWER1)) && (!src.isWireCut(APC_WIRE_MAIN_POWER2)))
+ src.shorted = 0
+ src.shock(usr, 50)
+ src.updateDialog()
+ if (APC_WIRE_AI_CONTROL)
+ //one wire for AI control. Cutting this prevents the AI from controlling the door unless it has hacked the door through the power connection (which takes about a minute). If both main and backup power are cut, as well as this wire, then the AI cannot operate or hack the door at all.
+ //aidisabledDisabled: If 1, AI control is disabled until the AI hacks back in and disables the lock. If 2, the AI has bypassed the lock. If -1, the control is enabled but the AI had bypassed it earlier, so if it is disabled again the AI would have no trouble getting back in.
+ if (src.aidisabled == 1)
+ src.aidisabled = 0
+ src.updateDialog()
+// if(APC_WIRE_IDSCAN) nothing happens when you cut this wire, add in something if you want whatever
+
+/obj/machinery/power/apc/proc/pulse(var/wireColor)
+ //var/wireFlag = apcWireColorToFlag[wireColor] //not used in this function
+ var/wireIndex = APCWireColorToIndex[wireColor]
+ switch(wireIndex)
+ if(APC_WIRE_IDSCAN) //unlocks the APC for 30 seconds, if you have a better way to hack an APC I'm all ears
+ src.locked = 0
+ spawn(300)
+ src.locked = 1
+ src.updateDialog()
+ if (APC_WIRE_MAIN_POWER1)
+ if(shorted == 0)
+ shorted = 1
+ spawn(1200)
+ if(shorted == 1)
+ shorted = 0
+ src.updateDialog()
+ if (APC_WIRE_MAIN_POWER2)
+ if(shorted == 0)
+ shorted = 1
+ spawn(1200)
+ if(shorted == 1)
+ shorted = 0
+ src.updateDialog()
+ if (APC_WIRE_AI_CONTROL)
+ if (src.aidisabled == 0)
+ src.aidisabled = 1
+ src.updateDialog()
+ spawn(10)
+ if (src.aidisabled == 1)
+ src.aidisabled = 0
+ src.updateDialog()
+
+/obj/machinery/power/apc/proc/can_use(mob/user as mob) //used by attack_hand() and Topic()
+ if (user.stat)
+ user << "\red You must be conscious to use this [src]!"
+ return 0
+ if ( ! (istype(user, /mob/living/carbon/human) || \
+ istype(user, /mob/living/silicon) || \
+ istype(user, /mob/living/carbon/monkey) /*&& ticker && ticker.mode.name == "monkey"*/) )
+ user << "\red You don't have the dexterity to use this [src]!"
+ user << browse(null, "window=apc")
+ user.machine = null
+ return 0
+ if(user.restrained())
+ user << "\red You must have free hands to use this [src]"
+ return 0
+ if(user.lying)
+ user << "\red You must stand to use this [src]!"
+ return 0
+ if (istype(user, /mob/living/silicon))
+ var/mob/living/silicon/ai/AI = user
+ var/mob/living/silicon/robot/robot = user
+ if ( \
+ src.aidisabled || \
+ malfhack && istype(malfai) && \
+ ( \
+ (istype(AI) && (malfai!=AI && malfai != AI.parent)) || \
+ (istype(robot) && (robot in malfai.connected_robots)) \
+ ) \
+ )
+ user << "\red \The [src] have AI control disabled!"
+ user << browse(null, "window=apc")
+ user.machine = null
+ return 0
+ else
+ if ((!in_range(src, user) || !istype(src.loc, /turf)))
+ user << browse(null, "window=apc")
+ user.machine = null
+ return 0
+ var/mob/living/carbon/human/H = user
+ if (istype(H))
+ if(H.brainloss >= 60)
+ for(var/mob/M in viewers(src, null))
+ M << "\red [H] stares cluelessly at [src] and drools."
+ return 0
+ else if(prob(H.brainloss))
+ user << "\red You momentarily forget how to use [src]."
+ return 0
+ return 1
+
+/obj/machinery/power/apc/Topic(href, href_list)
+ if (!can_use(usr))
+ return
+ src.add_fingerprint(usr)
+ usr.machine = src
+ if (href_list["apcwires"])
+ var/t1 = text2num(href_list["apcwires"])
+ if (!( istype(usr.equipped(), /obj/item/weapon/wirecutters) ))
+ usr << "You need wirecutters!"
+ return
+ if (src.isWireColorCut(t1))
+ src.mend(t1)
+ else
+ src.cut(t1)
+ else if (href_list["pulse"])
+ var/t1 = text2num(href_list["pulse"])
+ if (!istype(usr.equipped(), /obj/item/device/multitool))
+ usr << "You need a multitool!"
+ return
+ if (src.isWireColorCut(t1))
+ usr << "You can't pulse a cut wire."
+ return
+ else
+ src.pulse(t1)
+ else if (href_list["lock"])
+ coverlocked = !coverlocked
+
+ else if (href_list["breaker"])
+ operating = !operating
+ if(malfai)
+ if (ticker.mode.config_tag == "malfunction")
+ if (src.z == 1) //if (is_type_in_list(get_area(src), the_station_areas))
+ operating ? ticker.mode:apcs++ : ticker.mode:apcs--
+ src.update()
+ updateicon()
+
+ else if (href_list["cmode"])
+ chargemode = !chargemode
+ if(!chargemode)
+ charging = 0
+ updateicon()
+
+ else if (href_list["eqp"])
+ var/val = text2num(href_list["eqp"])
+
+ equipment = (val==1) ? 0 : val
+
+ updateicon()
+ update()
+
+ else if (href_list["lgt"])
+ var/val = text2num(href_list["lgt"])
+
+ lighting = (val==1) ? 0 : val
+
+ updateicon()
+ update()
+ else if (href_list["env"])
+ var/val = text2num(href_list["env"])
+
+ environ = (val==1) ? 0 :val
+
+ updateicon()
+ update()
+ else if( href_list["close"] )
+ usr << browse(null, "window=apc")
+ usr.machine = null
+ return
+ else if (href_list["close2"])
+ usr << browse(null, "window=apcwires")
+ usr.machine = null
+ return
+
+ else if (href_list["overload"])
+ if( istype(usr, /mob/living/silicon) && !src.aidisabled )
+ src.overload_lighting()
+
+ else if (href_list["malfhack"])
+ var/mob/living/silicon/ai/malfai = usr
+ if( istype(malfai, /mob/living/silicon/ai) && !src.aidisabled )
+ if (malfai.malfhacking)
+ malfai << "You are already hacking an APC."
+ return
+ malfai << "Beginning override of APC systems. This takes some time, and you cannot perform other actions during the process."
+ malfai.malfhack = src
+ malfai.malfhacking = 1
+ sleep(600)
+ if (!src.aidisabled)
+ malfai.malfhack = null
+ malfai.malfhacking = 0
+ if (ticker.mode.config_tag == "malfunction")
+ if (src.z == 1) //if (is_type_in_list(get_area(src), the_station_areas))
+ ticker.mode:apcs++
+ if(usr:parent)
+ src.malfai = usr:parent
+ else
+ src.malfai = usr
+ malfai << "Hack complete. The APC is now under your exclusive control."
+
+ else if (href_list["occupyapc"])
+ malfoccupy(usr)
+
+
+ else if (href_list["deoccupyapc"])
+ malfvacate()
+
+ src.updateDialog()
+ return
+
+/obj/machinery/power/apc/proc/malfoccupy(var/mob/living/silicon/ai/malf)
+ if(!istype(malf))
+ return
+ if(src.z != 1)
+ return
+ src.occupant = new /mob/living/silicon/ai(src,malf.laws,null,1)
+ src.occupant.adjustOxyLoss(malf.getOxyLoss())
+ src.occupant.name = "[malf.name] APC Copy"
+ if(malf.parent)
+ src.occupant.parent = malf.parent
+ else
+ src.occupant.parent = malf
+ malf.mind.transfer_to(src.occupant)
+ if(malf.parent)
+ del(malf)
+ src.occupant.verbs += /mob/living/silicon/ai/proc/corereturn
+ src.occupant.cancel_camera()
+
+/obj/machinery/power/apc/proc/malfvacate(var/forced)
+ if(!src.occupant)
+ return
+ if(src.occupant.parent && src.occupant.parent.stat != 2)
+ src.occupant.mind.transfer_to(src.occupant.parent)
+ src.occupant.parent.adjustOxyLoss(src.occupant.getOxyLoss())
+ src.occupant.parent.cancel_camera()
+ del(src.occupant)
+
+ else
+ src.occupant << "\red Primary core damaged, unable to return core processes."
+ if(forced)
+ src.occupant.loc = src.loc
+ src.occupant.death()
+ src.occupant.gib()
+
+
+/obj/machinery/power/apc/proc/ion_act()
+ //intended to be exactly the same as an AI malf attack
+ if(!src.malfhack && src.z == 1)
+ if(prob(3))
+ src.locked = 1
+ if (src.cell.charge > 0)
+// world << "\red blew APC in [src.loc.loc]"
+ src.cell.charge = 0
+ cell.corrupt()
+ src.malfhack = 1
+ updateicon()
+ var/datum/effect/effect/system/harmless_smoke_spread/smoke = new /datum/effect/effect/system/harmless_smoke_spread()
+ smoke.set_up(3, 0, src.loc)
+ smoke.attach(src)
+ smoke.start()
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ s.set_up(3, 1, src)
+ s.start()
+ for(var/mob/M in viewers(src))
+ M.show_message("\red The [src.name] suddenly lets out a blast of smoke and some sparks!", 3, "\red You hear sizzling electronics.", 2)
+
+
+/obj/machinery/power/apc/surplus()
+ if(terminal)
+ return terminal.surplus()
+ else
+ return 0
+
+/obj/machinery/power/apc/add_load(var/amount)
+ if(terminal && terminal.powernet)
+ terminal.powernet.newload += amount
+
+/obj/machinery/power/apc/avail()
+ if(terminal)
+ return terminal.avail()
+ else
+ return 0
+
+/obj/machinery/power/apc/process()
+
+ if(stat & (BROKEN|MAINT))
+ return
+ if(!area.requires_power)
+ return
+
+
+ /*
+ if (equipment > 1) // off=0, off auto=1, on=2, on auto=3
+ use_power(src.equip_consumption, EQUIP)
+ if (lighting > 1) // off=0, off auto=1, on=2, on auto=3
+ use_power(src.light_consumption, LIGHT)
+ if (environ > 1) // off=0, off auto=1, on=2, on auto=3
+ use_power(src.environ_consumption, ENVIRON)
+
+ area.calc_lighting() */
+
+ lastused_light = area.usage(LIGHT)
+ lastused_equip = area.usage(EQUIP)
+ lastused_environ = area.usage(ENVIRON)
+ area.clear_usage()
+
+ lastused_total = lastused_light + lastused_equip + lastused_environ
+
+ //store states to update icon if any change
+ var/last_lt = lighting
+ var/last_eq = equipment
+ var/last_en = environ
+ var/last_ch = charging
+
+ var/excess = surplus()
+
+ if(!src.avail())
+ main_status = 0
+ else if(excess < 0)
+ main_status = 1
+ else
+ main_status = 2
+
+ var/perapc = 0
+ if(terminal && terminal.powernet)
+ perapc = terminal.powernet.perapc
+
+ if(cell && !shorted)
+
+ // draw power from cell as before
+
+ var/cellused = min(cell.charge, CELLRATE * lastused_total) // clamp deduction to a max, amount left in cell
+ cell.use(cellused)
+
+ if(excess > 0 || perapc > lastused_total) // if power excess, or enough anyway, recharge the cell
+ // by the same amount just used
+
+ cell.give(cellused)
+ add_load(cellused/CELLRATE) // add the load used to recharge the cell
+
+
+ else // no excess, and not enough per-apc
+
+ if( (cell.charge/CELLRATE+perapc) >= lastused_total) // can we draw enough from cell+grid to cover last usage?
+
+ cell.charge = min(cell.maxcharge, cell.charge + CELLRATE * perapc) //recharge with what we can
+ add_load(perapc) // so draw what we can from the grid
+ charging = 0
+
+ else // not enough power available to run the last tick!
+ charging = 0
+ chargecount = 0
+ // This turns everything off in the case that there is still a charge left on the battery, just not enough to run the room.
+ equipment = autoset(equipment, 0)
+ lighting = autoset(lighting, 0)
+ environ = autoset(environ, 0)
+
+ // set channels depending on how much charge we have left
+
+ if(cell.charge <= 0) // zero charge, turn all off
+ equipment = autoset(equipment, 0)
+ lighting = autoset(lighting, 0)
+ environ = autoset(environ, 0)
+ area.poweralert(0, src)
+ else if(cell.percent() < 15) // <15%, turn off lighting & equipment
+ equipment = autoset(equipment, 2)
+ lighting = autoset(lighting, 2)
+ environ = autoset(environ, 1)
+ area.poweralert(0, src)
+ else if(cell.percent() < 30) // <30%, turn off equipment
+ equipment = autoset(equipment, 2)
+ lighting = autoset(lighting, 1)
+ environ = autoset(environ, 1)
+ area.poweralert(0, src)
+ else // otherwise all can be on
+ equipment = autoset(equipment, 1)
+ lighting = autoset(lighting, 1)
+ environ = autoset(environ, 1)
+ area.poweralert(1, src)
+ if(cell.percent() > 75)
+ area.poweralert(1, src)
+
+ // now trickle-charge the cell
+
+ if(chargemode && charging == 1 && operating)
+ if(excess > 0) // check to make sure we have enough to charge
+ // Max charge is perapc share, capped to cell capacity, or % per second constant (Whichever is smallest)
+/* var/ch = min(perapc, (cell.maxcharge - cell.charge), (cell.maxcharge*CHARGELEVEL))
+ add_load(ch) // Removes the power we're taking from the grid
+ cell.give(ch) // actually recharge the cell
+*/
+ var/ch = min(perapc*CELLRATE, (cell.maxcharge - cell.charge), (cell.maxcharge*CHARGELEVEL))
+ add_load(ch/CELLRATE) // Removes the power we're taking from the grid
+ cell.give(ch) // actually recharge the cell
+
+ else
+ charging = 0 // stop charging
+ chargecount = 0
+
+ // show cell as fully charged if so
+
+ if(cell.charge >= cell.maxcharge)
+ charging = 2
+
+ if(chargemode)
+ if(!charging)
+ if(excess > cell.maxcharge*CHARGELEVEL)
+ chargecount++
+ else
+ chargecount = 0
+
+ if(chargecount == 10)
+
+ chargecount = 0
+ charging = 1
+
+ else // chargemode off
+ charging = 0
+ chargecount = 0
+
+ else // no cell, switch everything off
+
+ charging = 0
+ chargecount = 0
+ equipment = autoset(equipment, 0)
+ lighting = autoset(lighting, 0)
+ environ = autoset(environ, 0)
+ area.poweralert(0, src)
+
+ // update icon & area power if anything changed
+
+ if(last_lt != lighting || last_eq != equipment || last_en != environ)
+ updateicon()
+ update()
+ else if (last_ch != charging)
+ updateicon()
+
+ //src.updateDialog()
+ src.updateDialog()
+
+// val 0=off, 1=off(auto) 2=on 3=on(auto)
+// on 0=off, 1=on, 2=autooff
+
+/proc/autoset(var/val, var/on)
+
+ if(on==0)
+ if(val==2) // if on, return off
+ return 0
+ else if(val==3) // if auto-on, return auto-off
+ return 1
+
+ else if(on==1)
+ if(val==1) // if auto-off, return auto-on
+ return 3
+
+ else if(on==2)
+ if(val==3) // if auto-on, return auto-off
+ return 1
+
+ return val
+
+// damage and destruction acts
+
+/obj/machinery/power/apc/meteorhit(var/obj/O as obj)
+
+ set_broken()
+ return
+
+/obj/machinery/power/apc/emp_act(severity)
+ if(cell)
+ cell.emp_act(severity)
+ if(occupant)
+ occupant.emp_act(severity)
+ lighting = 0
+ equipment = 0
+ environ = 0
+ spawn(600)
+ equipment = 3
+ environ = 3
+ ..()
+
+/obj/machinery/power/apc/ex_act(severity)
+
+ switch(severity)
+ if(1.0)
+ //set_broken() //now Del() do what we need
+ if (cell)
+ cell.ex_act(1.0) // more lags woohoo
+ del(src)
+ return
+ if(2.0)
+ if (prob(50))
+ set_broken()
+ if (cell && prob(50))
+ cell.ex_act(2.0)
+ if(3.0)
+ if (prob(25))
+ set_broken()
+ if (cell && prob(25))
+ cell.ex_act(3.0)
+ return
+
+/obj/machinery/power/apc/blob_act()
+ if (prob(75))
+ set_broken()
+ if (cell && prob(5))
+ cell.blob_act()
+
+/obj/machinery/power/apc/proc/set_broken()
+ if(malfai && operating)
+ if (ticker.mode.config_tag == "malfunction")
+ if (src.z == 1) //if (is_type_in_list(get_area(src), the_station_areas))
+ ticker.mode:apcs--
+ stat |= BROKEN
+ operating = 0
+ if(occupant)
+ malfvacate(1)
+ updateicon()
+ update()
+
+// overload all the lights in this APC area
+
+/obj/machinery/power/apc/proc/overload_lighting()
+ if(/* !get_connection() || */ !operating || shorted)
+ return
+ if( cell && cell.charge>=20)
+ cell.use(20);
+ spawn(0)
+ for(var/area/A in area.related)
+ for(var/obj/machinery/light/L in A)
+ L.on = 1
+ L.broken()
+ sleep(1)
+
+/obj/machinery/power/apc/Del()
+ if(malfai && operating)
+ if (ticker.mode.config_tag == "malfunction")
+ if (src.z == 1) //if (is_type_in_list(get_area(src), the_station_areas))
+ ticker.mode:apcs--
+ area.power_light = 0
+ area.power_equip = 0
+ area.power_environ = 0
+ area.power_change()
+ if(occupant)
+ malfvacate(1)
+ ..()
+
+/obj/machinery/power/apc/proc/shock(mob/user, prb)
+ if(!prob(prb))
+ return 0
+ var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
+ s.set_up(5, 1, src)
+ s.start()
+ if (electrocute_mob(user, src, src))
+ return 1
+ else
+ return 0