diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index 616ef4c6c9..1a3cce2cf9 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -112,23 +112,6 @@ Class Procs:
var/interact_offline = 0 // Can the machine be interacted with while de-powered.
var/global/gl_uid = 1
-/obj/machinery/drain_power(var/drain_check)
-
- if(drain_check)
- return 1
-
- if(!powered())
- return 0
-
- var/area/area = get_area(src)
- if(!area)
- return 0
-
- var/obj/machinery/power/apc/apc = area.get_apc()
- if(!apc)
- return 0
- return apc.drain_power()
-
/obj/machinery/New(l, d=0)
..(l)
if(d)
diff --git a/code/game/objects/items/devices/powersink.dm b/code/game/objects/items/devices/powersink.dm
index e8ca9c3929..cf92db9a39 100644
--- a/code/game/objects/items/devices/powersink.dm
+++ b/code/game/objects/items/devices/powersink.dm
@@ -100,11 +100,17 @@
// now look for APCs and drain their cells
if(drained < drain_rate)
for(var/obj/machinery/power/terminal/T in PN.nodes)
+ // Enough power drained this tick, no need to torture more APCs
+ if(drained >= drain_rate)
+ break
if(istype(T.master, /obj/machinery/power/apc))
var/obj/machinery/power/apc/A = T.master
if(A.operating && A.cell)
- A.cell.charge = max(0, A.cell.charge - (2000 * CELLRATE))
- power_drained += 2000
+ var/cur_charge = A.cell.charge / CELLRATE
+ var/drain_val = min(2000, cur_charge)
+
+ A.cell.use(drain_val * CELLRATE)
+ drained += drain_val
if(power_drained > max_power * 0.95)
diff --git a/code/modules/clothing/spacesuits/rig/modules/computer.dm b/code/modules/clothing/spacesuits/rig/modules/computer.dm
index 71293ef450..1b2befa59a 100644
--- a/code/modules/clothing/spacesuits/rig/modules/computer.dm
+++ b/code/modules/clothing/spacesuits/rig/modules/computer.dm
@@ -411,30 +411,33 @@
drain_complete(H)
return
- var/target_drained = interfaced_with.drain_power()
+ if(holder.cell.fully_charged())
+ H << "Your power sink flashes an amber light; your rig cell is full."
+ drain_complete(H)
+ return
+
+ // Attempts to drain up to 40kW, determines this value from remaining cell capacity to ensure we don't drain too much..
+ var/to_drain = min(40000, ((holder.cell.maxcharge - holder.cell.charge) / CELLRATE))
+ var/target_drained = interfaced_with.drain_power(0,0,to_drain)
if(target_drained <= 0)
H << "Your power sink flashes a red light; there is no power left in [interfaced_with]."
drain_complete(H)
return
- holder.cell.charge += target_drained
+ holder.cell.give(target_drained * CELLRATE)
total_power_drained += target_drained
- if(holder.cell.charge > holder.cell.maxcharge)
- H << "Your power sink flashes an amber light; your rig cell is full."
- holder.cell.charge = holder.cell.maxcharge
- drain_complete(H)
- return
+
return 1
/obj/item/rig_module/power_sink/proc/drain_complete(var/mob/living/M)
if(!interfaced_with)
- if(M) M << "Total power drained: [total_power_drained]W."
+ if(M) M << "Total power drained: [round(total_power_drained/1000)]kJ."
else
- if(M) M << "Total power drained from [interfaced_with]: [total_power_drained]W."
- interfaced_with.drain_power(0,1) // Damage the victim.
+ if(M) M << "Total power drained from [interfaced_with]: [round(total_power_drained/1000)]kJ."
+ interfaced_with.drain_power(0,1,0) // Damage the victim.
interfaced_with = null
total_power_drained = 0
\ No newline at end of file
diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm
index 05c1953822..aeebc30bb3 100644
--- a/code/modules/mob/living/silicon/robot/robot.dm
+++ b/code/modules/mob/living/silicon/robot/robot.dm
@@ -182,7 +182,7 @@ var/list/robot_verbs_default = list(
lawsync()
photosync()
-/mob/living/silicon/robot/drain_power(var/drain_check)
+/mob/living/silicon/robot/drain_power(var/drain_check, var/surge, var/amount = 0)
if(drain_check)
return 1
@@ -190,14 +190,15 @@ var/list/robot_verbs_default = list(
if(!cell || !cell.charge)
return 0
- if(cell.charge)
- src << "Warning: Unauthorized access through power channel 12 detected."
- var/drained_power = rand(200,400)
- if(cell.charge < drained_power)
- drained_power = cell.charge
- cell.use(drained_power)
- return drained_power
+ // Actual amount to drain from cell, using CELLRATE
+ var/cell_amount = amount * CELLRATE
+ if(cell.charge > cell_amount)
+ // Spam Protection
+ if(prob(10))
+ src << "Warning: Unauthorized access through power channel [rand(11,29)] detected!"
+ cell.use(cell_amount)
+ return amount
return 0
// setup the PDA and its name
diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm
index f414fbf915..1d0150ecf6 100644
--- a/code/modules/mob/mob.dm
+++ b/code/modules/mob/mob.dm
@@ -66,7 +66,7 @@
// If drain_check is set it will not actually drain power, just return a value.
// If surge is set, it will destroy/damage the recipient and not return any power.
// Not sure where to define this, so it can sit here for the rest of time.
-/atom/proc/drain_power(var/drain_check,var/surge)
+/atom/proc/drain_power(var/drain_check,var/surge, var/amount = 0)
return -1
// Show a message to all mobs in earshot of this one
diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm
index 2e766d2f83..d6fd780a40 100644
--- a/code/modules/power/apc.dm
+++ b/code/modules/power/apc.dm
@@ -116,7 +116,7 @@
if(terminal)
terminal.connect_to_network()
-/obj/machinery/power/apc/drain_power(var/drain_check, var/surge)
+/obj/machinery/power/apc/drain_power(var/drain_check, var/surge, var/amount = 0)
if(drain_check)
return 1
@@ -131,7 +131,10 @@
update_icon()
return 0
- return cell.drain_power(drain_check)
+ if(terminal && terminal.powernet)
+ terminal.powernet.trigger_warning()
+
+ return cell.drain_power(drain_check, surge, amount)
/obj/machinery/power/apc/New(turf/loc, var/ndir, var/building=0)
..()
@@ -178,10 +181,10 @@
del(cell) // qdel
if(terminal)
disconnect_terminal()
-
+
//If there's no more APC then there shouldn't be a cause for alarm I guess
area.poweralert(1, src) //so that alarms don't go on forever
-
+
..()
/obj/machinery/power/apc/proc/make_terminal()
diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm
index 27e1fc3a2b..de072d8d5a 100644
--- a/code/modules/power/cable.dm
+++ b/code/modules/power/cable.dm
@@ -36,7 +36,7 @@ By design, d1 is the smallest direction and d2 is the highest
color = COLOR_RED
var/obj/machinery/power/breakerbox/breaker_box
-/obj/structure/cable/drain_power(var/drain_check)
+/obj/structure/cable/drain_power(var/drain_check, var/surge, var/amount = 0)
if(drain_check)
return 1
@@ -44,18 +44,7 @@ By design, d1 is the smallest direction and d2 is the highest
var/datum/powernet/PN = get_powernet()
if(!PN) return 0
- var/drained_power = round(rand(200,400)/2)
- var/drained_this_tick = PN.draw_power(drained_power)
-
- if(drained_this_tick < drained_power)
- for(var/obj/machinery/power/terminal/T in PN.nodes)
- if(istype(T.master, /obj/machinery/power/apc))
- var/obj/machinery/power/apc/AP = T.master
- if(AP.emagged)
- continue
- drained_power += AP.drain_power() //Indirect draw won't emag the APC, should this be amended?
-
- return drained_power
+ return PN.draw_power(amount)
/obj/structure/cable/yellow
color = COLOR_YELLOW
diff --git a/code/modules/power/cell.dm b/code/modules/power/cell.dm
index b76086b567..36ab1047a3 100644
--- a/code/modules/power/cell.dm
+++ b/code/modules/power/cell.dm
@@ -9,16 +9,17 @@
spawn(5)
updateicon()
-/obj/item/weapon/cell/drain_power(var/drain_check)
+/obj/item/weapon/cell/drain_power(var/drain_check, var/surge, var/amount = 0)
if(drain_check)
return 1
- var/drained_power = rand(200,400)
- if(charge < drained_power)
- drained_power = charge
- use(drained_power)
- return drained_power
+ if(charge <= 0)
+ return 0
+
+ var/cell_amt = min((amount * CELLRATE), charge)
+ use(cell_amt)
+ return cell_amt / CELLRATE
/obj/item/weapon/cell/proc/updateicon()
overlays.Cut()
diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm
index 76b712d4cb..4836c3601c 100644
--- a/code/modules/power/power.dm
+++ b/code/modules/power/power.dm
@@ -24,6 +24,14 @@
//////////////////////////////
// common helper procs for all power machines
+/obj/machinery/power/drain_power(var/drain_check, var/surge, var/amount = 0)
+ if(drain_check)
+ return 1
+
+ if(powernet && powernet.avail)
+ powernet.trigger_warning()
+ return powernet.draw_power(amount)
+
/obj/machinery/power/proc/add_avail(var/amount)
if(powernet)
powernet.newavail += amount
diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm
index 61677068b8..11bcef5881 100644
--- a/code/modules/power/smes.dm
+++ b/code/modules/power/smes.dm
@@ -1,6 +1,7 @@
// the SMES
// stores power
+#define SMESRATE 0.05
#define SMESMAXCHARGELEVEL 250000
#define SMESMAXOUTPUT 250000
@@ -43,22 +44,15 @@
var/obj/machinery/power/terminal/terminal = null
var/should_be_mapped = 0 // If this is set to 0 it will send out warning on New()
-/obj/machinery/power/smes/drain_power(var/drain_check)
+/obj/machinery/power/smes/drain_power(var/drain_check, var/surge, var/amount = 0)
if(drain_check)
return 1
- if(!charge)
- return 0
+ var/smes_amt = min((amount * SMESRATE), charge)
+ charge -= smes_amt
+ return smes_amt / SMESRATE
- if(charge)
- var/drained_power = rand(200,400)
- if(charge < drained_power)
- drained_power = charge
- charge -= drained_power
- return drained_power
-
- return 0
/obj/machinery/power/smes/New()
..()
@@ -112,9 +106,6 @@
/obj/machinery/power/smes/proc/chargedisplay()
return round(5.5*charge/(capacity ? capacity : 5e6))
-#define SMESRATE 0.05 // rate of internal charge to external power
-
-
/obj/machinery/power/smes/process()
if(stat & BROKEN) return
@@ -420,4 +411,4 @@
/obj/machinery/power/smes/magical/process()
charge = 5000000
- ..()
+ ..()