From 91e3ced65e6f5bff4121a9b5dad27fb4ea39522b Mon Sep 17 00:00:00 2001 From: Atlantiscze Date: Tue, 5 May 2015 18:49:11 +0200 Subject: [PATCH] Powersink Fix - Fixes powersinks lasting for infinite duration before exploding. - Minor adjustment to powersink drain rates. Powersink now drains up to 1.5MW instead of 1MW. It also attempts to drain up to 5kW instead of 2kW from each APC, unless powernet supplies enough power. They can still be overpowered by pumping more than 1.5MW into the grid, which is possible if you either install more coils into main SMES, or use the solars. Even 1MW of default SMES is enough to slow the drain effect considerably, espicially if you can isolate it with breakers. - Fixes "APC Flickering" issues caused by powersinks. Powersinks are now processed immediately after powernets, which ensures they are first to take power from that powernet. This is unfortunately necessary as APCs would take power first, which is not desired. - Minor refactor while i was at it - absolute paths, span classes, visible_message() instead of for cycle. No gameplay effect. --- code/controllers/master_controller.dm | 5 + code/game/objects/items/devices/powersink.dm | 179 ++++++++++--------- 2 files changed, 95 insertions(+), 89 deletions(-) diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index bb5a3e48b04..25cccde7710 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -328,6 +328,11 @@ datum/controller/game_controller/proc/process_pipenets() for(var/datum/powernet/Powernet in powernets) Powernet.reset() + // This is necessary to ensure powersinks are always the first devices that drain power from powernet. + // Otherwise APCs or other stuff go first, resulting in bad things happening. + for(var/obj/item/device/powersink/S in processing_objects) + S.drain() + datum/controller/game_controller/proc/process_nano() last_thing_processed = /datum/nanoui var/i = 1 diff --git a/code/game/objects/items/devices/powersink.dm b/code/game/objects/items/devices/powersink.dm index 8b2469d2dd4..4acd673ca60 100644 --- a/code/game/objects/items/devices/powersink.dm +++ b/code/game/objects/items/devices/powersink.dm @@ -14,108 +14,109 @@ matter = list("metal" = 750,"waste" = 750) origin_tech = "powerstorage=3;syndicate=5" - var/drain_rate = 1000000 // amount of power to drain per tick - var/dissipation_rate = 20000 - var/power_drained = 0 // has drained this much power - var/max_power = 5e9 // maximum power that can be drained before exploding - var/mode = 0 // 0 = off, 1=clamped (off), 2=operating - + var/drain_rate = 1500000 // amount of power to drain per tick + var/apc_drain_rate = 5000 // Max. amount drained from single APC. In Watts. + var/dissipation_rate = 20000 // Passive dissipation of drained power. In Watts. + var/power_drained = 0 // Amount of power drained. + var/max_power = 5e9 // Detonation point. + var/mode = 0 // 0 = off, 1=clamped (off), 2=operating + var/drained_this_tick = 0 // This is unfortunately necessary to ensure we process powersinks BEFORE other machinery such as APCs. + var/datum/powernet/PN // Our powernet var/obj/structure/cable/attached // the attached cable - attackby(var/obj/item/I, var/mob/user) - if(istype(I, /obj/item/weapon/screwdriver)) - if(mode == 0) - var/turf/T = loc - if(isturf(T) && !T.intact) - attached = locate() in T - if(!attached) - user << "No exposed cable here to attach to." - return - else - anchored = 1 - mode = 1 - user << "You attach the device to the cable." - for(var/mob/M in viewers(user)) - if(M == user) continue - M << "[user] attaches the power sink to the cable." - return +/obj/item/device/powersink/attackby(var/obj/item/I, var/mob/user) + if(istype(I, /obj/item/weapon/screwdriver)) + if(mode == 0) + var/turf/T = loc + if(isturf(T) && !T.intact) + attached = locate() in T + if(!attached) + user << "No exposed cable here to attach to." + return else - user << "Device must be placed over an exposed cable to attach to it." + anchored = 1 + mode = 1 + src.visible_message("[user] attaches [src] to the cable!") return else - if (mode == 2) - processing_objects.Remove(src) // Now the power sink actually stops draining the station's power if you unhook it. --NeoFite - anchored = 0 - mode = 0 - user << "You detach the device from the cable." - for(var/mob/M in viewers(user)) - if(M == user) continue - M << "[user] detaches the power sink from the cable." - SetLuminosity(0) - icon_state = "powersink0" - + user << "Device must be placed over an exposed cable to attach to it." return else - ..() + if (mode == 2) + processing_objects.Remove(src) // Now the power sink actually stops draining the station's power if you unhook it. --NeoFite + anchored = 0 + mode = 0 + src.visible_message("[user] detaches [src] from the cable!") + SetLuminosity(0) + icon_state = "powersink0" - attack_ai() + return + else + ..() + +/obj/item/device/powersink/attack_ai() + return + +/obj/item/device/powersink/attack_hand(var/mob/user) + switch(mode) + if(0) + ..() + if(1) + src.visible_message("[user] activates [src]!") + mode = 2 + icon_state = "powersink1" + processing_objects.Add(src) + if(2) //This switch option wasn't originally included. It exists now. --NeoFite + src.visible_message("[user] deactivates [src]!") + mode = 1 + SetLuminosity(0) + icon_state = "powersink0" + processing_objects.Remove(src) + +/obj/item/device/powersink/proc/drain() + if(!attached) return - attack_hand(var/mob/user) - switch(mode) - if(0) - ..() + if(drained_this_tick) + return - if(1) - user << "You activate the device!" - for(var/mob/M in viewers(user)) - if(M == user) continue - M << "[user] activates the power sink!" - mode = 2 - icon_state = "powersink1" - processing_objects.Add(src) + var/drained = 0 - if(2) //This switch option wasn't originally included. It exists now. --NeoFite - user << "You deactivate the device!" - for(var/mob/M in viewers(user)) - if(M == user) continue - M << "[user] deactivates the power sink!" - mode = 1 - SetLuminosity(0) - icon_state = "powersink0" - processing_objects.Remove(src) + if(!PN) + return - process() - power_drained -= min(dissipation_rate, power_drained) - if(attached) - var/datum/powernet/PN = attached.get_powernet() - if(PN) - SetLuminosity(12) - PN.trigger_warning() - // found a powernet, so drain up to max power from it - var/drained = PN.draw_power(drain_rate) - - // if tried to drain more than available on powernet - // 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) - var/cur_charge = A.cell.charge / CELLRATE - var/drain_val = min(2000, cur_charge) - - A.cell.use(drain_val * CELLRATE) - drained += drain_val + SetLuminosity(12) + PN.trigger_warning() + // found a powernet, so drain up to max power from it + drained = PN.draw_power(drain_rate) + // if tried to drain more than available on powernet + // 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) + var/cur_charge = A.cell.charge / CELLRATE + var/drain_val = min(apc_drain_rate, cur_charge) + A.cell.use(drain_val * CELLRATE) + drained += drain_val + power_drained += drained - if(power_drained > max_power * 0.95) - playsound(src, 'sound/effects/screech.ogg', 100, 1, 1) - if(power_drained >= max_power) - processing_objects.Remove(src) - explosion(src.loc, 3,6,9,12) - del(src) +/obj/item/device/powersink/process() + drained_this_tick = 0 + power_drained -= min(dissipation_rate, power_drained) + if(power_drained > max_power * 0.95) + playsound(src, 'sound/effects/screech.ogg', 100, 1, 1) + if(power_drained >= max_power) + processing_objects.Remove(src) + explosion(src.loc, 3,6,9,12) + del(src) + if(attached && attached.powernet) + PN = attached.powernet + else + PN = null \ No newline at end of file