From a1c19b78be3c258abe4df9c141e990f95e752d04 Mon Sep 17 00:00:00 2001 From: PsiOmega Date: Wed, 29 Oct 2014 14:00:11 +0100 Subject: [PATCH] Ports more of /tg/'s powernet code. Among other things this fixes a a bug where SMES would draw excess power from the powergrid they were outputting to, rather than drawing from. --- .../components/unary/cold_sink.dm | 5 - .../components/unary/heat_source.dm | 9 +- code/controllers/master_controller.dm | 53 +---- code/game/area/Space Station 13 areas.dm | 1 - code/game/gamemodes/events/power_failure.dm | 25 +-- code/game/machinery/machinery.dm | 15 -- code/modules/admin/verbs/debug.dm | 14 +- code/modules/power/apc.dm | 85 ++++---- code/modules/power/batteryrack.dm | 54 ++--- code/modules/power/cable.dm | 24 --- code/modules/power/power.dm | 2 +- code/modules/power/powernet.dm | 4 +- code/modules/power/smes.dm | 187 ++++++++++-------- code/modules/power/smes_construction.dm | 4 +- 14 files changed, 204 insertions(+), 278 deletions(-) diff --git a/code/ATMOSPHERICS/components/unary/cold_sink.dm b/code/ATMOSPHERICS/components/unary/cold_sink.dm index bd3c3b1796..8b99d853e3 100644 --- a/code/ATMOSPHERICS/components/unary/cold_sink.dm +++ b/code/ATMOSPHERICS/components/unary/cold_sink.dm @@ -181,13 +181,8 @@ /obj/machinery/atmospherics/unary/freezer/proc/set_power_level(var/new_power_setting) power_setting = new_power_setting - - var/old_power_usage = active_power_usage active_power_usage = max_power_usage * (power_setting/100) - if (use_power >= 2 && old_power_usage != active_power_usage) - force_power_update() - //dismantling code. copied from autolathe /obj/machinery/atmospherics/unary/freezer/attackby(var/obj/item/O as obj, var/mob/user as mob) if(istype(O, /obj/item/weapon/screwdriver)) diff --git a/code/ATMOSPHERICS/components/unary/heat_source.dm b/code/ATMOSPHERICS/components/unary/heat_source.dm index 15d416fff0..6660eac80a 100644 --- a/code/ATMOSPHERICS/components/unary/heat_source.dm +++ b/code/ATMOSPHERICS/components/unary/heat_source.dm @@ -18,7 +18,7 @@ use_power = 0 idle_power_usage = 5 //5 Watts for thermostat related circuitry active_power_usage //50 kW. The power rating of the heater - + var/max_power_usage = 20000 //power rating when the usage is turned up to 100 var/power_setting = 100 @@ -35,7 +35,7 @@ component_parts += new /obj/item/weapon/stock_parts/matter_bin(src) component_parts += new /obj/item/weapon/stock_parts/capacitor(src) component_parts += new /obj/item/weapon/stock_parts/capacitor(src) - + active_power_usage = max_power_usage * (power_setting/100) /obj/machinery/atmospherics/unary/heater/initialize() @@ -164,12 +164,7 @@ /obj/machinery/atmospherics/unary/heater/proc/set_power_level(var/new_power_setting) power_setting = new_power_setting - - var/old_power_usage = active_power_usage active_power_usage = max_power_usage * (power_setting/100) - - if (use_power >= 2 && old_power_usage != active_power_usage) - force_power_update() //dismantling code. copied from autolathe /obj/machinery/atmospherics/unary/heater/attackby(var/obj/item/O as obj, var/mob/user as mob) diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm index c316583a0b..bb73a63032 100644 --- a/code/controllers/master_controller.dm +++ b/code/controllers/master_controller.dm @@ -274,8 +274,6 @@ datum/controller/game_controller/proc/process_diseases() datum/controller/game_controller/proc/process_machines() process_machines_sort() process_machines_process() - process_machines_power() - process_machines_rebuild() /var/global/machinery_sort_required = 0 datum/controller/game_controller/proc/process_machines_sort() @@ -284,49 +282,14 @@ datum/controller/game_controller/proc/process_machines_sort() machines = dd_sortedObjectList(machines) datum/controller/game_controller/proc/process_machines_process() - var/i = 1 - while(i<=machines.len) - var/obj/machinery/Machine = machines[i] - if(Machine) - last_thing_processed = Machine.type - if(Machine.process() != PROCESS_KILL) - if(Machine) - i++ - continue - machines.Cut(i,i+1) - -datum/controller/game_controller/proc/process_machines_power() - var/i=1 - while(i<=active_areas.len) - var/area/A = active_areas[i] - if(A.powerupdate && A.master == A) - A.powerupdate -= 1 - A.clear_usage() - for(var/j = 1; j <= A.related.len; j++) - var/area/SubArea = A.related[j] - for(var/obj/machinery/M in SubArea) - if(M) - //check if the area has power for M's channel - //this will keep stat updated in case the machine is moved from one area to another. - M.power_change(A) //we've already made sure A is a master area, above. - - if(!(M.stat & NOPOWER) && M.use_power) - M.auto_use_power() - - if(A.apc.len && A.master == A) - i++ - continue - - A.powerupdate = 0 - active_areas.Cut(i,i+1) - -datum/controller/game_controller/proc/process_machines_rebuild() - if(controller_iteration % 150 == 0 || rebuild_active_areas) //Every 300 seconds we retest every area/machine - for(var/area/A in all_areas) - if(A == A.master) - A.powerupdate += 1 - active_areas |= A - rebuild_active_areas = 0 + for(var/obj/machinery/Machine in machines) + last_thing_processed = Machine.type + if(Machine.process() != PROCESS_KILL) + if(Machine) + if(Machine.use_power) + Machine.auto_use_power() + continue + machines -= Machine datum/controller/game_controller/proc/process_objects() diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm index 8085e9eb02..a74c59b95f 100755 --- a/code/game/area/Space Station 13 areas.dm +++ b/code/game/area/Space Station 13 areas.dm @@ -33,7 +33,6 @@ NOTE: there are two lists of areas in the end of this file: centcom and station var/eject = null var/debug = 0 - var/powerupdate = 10 //We give everything 10 ticks to settle out it's power usage. var/requires_power = 1 var/unlimited_power = 0 var/always_unpowered = 0 //this gets overriden to 1 for space in area/New() diff --git a/code/game/gamemodes/events/power_failure.dm b/code/game/gamemodes/events/power_failure.dm index 87dd5f335c..f9c474effb 100644 --- a/code/game/gamemodes/events/power_failure.dm +++ b/code/game/gamemodes/events/power_failure.dm @@ -9,13 +9,13 @@ var/area/current_area = get_area(S) if(current_area.type in skipped_areas || S.z != 1) continue - S.last_charge = S.charge - S.last_output = S.output - S.last_online = S.online + S.last_charge = S.charge + S.last_output_attempt = S.output_attempt + S.last_input_attempt = S.input_attempt S.charge = 0 - S.output = 0 - S.online = 0 - S.updateicon() + S.inputting(0) + S.outputting(0) + S.update_icon() S.power_change() @@ -36,9 +36,9 @@ if(current_area.type in skipped_areas || S.z != 1) continue S.charge = S.last_charge - S.output = S.last_output - S.online = S.last_online - S.updateicon() + S.output_attempt = S.last_output_attempt + S.input_attempt = S.last_input_attempt + S.update_icon() S.power_change() /proc/power_restore_quick(var/announce = 1) @@ -49,7 +49,8 @@ if(S.z != 1) continue S.charge = S.capacity - S.output = 200000 - S.online = 1 - S.updateicon() + S.output_level = 200000 + S.output_attempt = 1 + S.input_attempt = 1 + S.update_icon() S.power_change() diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm index 7f48ca8bcf..89f6c0593f 100644 --- a/code/game/machinery/machinery.dm +++ b/code/game/machinery/machinery.dm @@ -165,14 +165,6 @@ Class Procs: use_power = new_use_power - //force area power update - force_power_update() - -/obj/machinery/proc/force_power_update() - var/area/A = get_area(src) - if(A && A.master) - A.master.powerupdate = 1 - /obj/machinery/proc/auto_use_power() if(!powered(power_channel)) return 0 @@ -214,9 +206,6 @@ Class Procs: src.add_fingerprint(usr) - var/area/A = get_area(src) - A.master.powerupdate = 1 - return 0 /obj/machinery/attack_ai(mob/user as mob) @@ -257,13 +246,9 @@ Class Procs: src.add_fingerprint(user) - var/area/A = get_area(src) - A.master.powerupdate = 1 - return 0 /obj/machinery/proc/RefreshParts() //Placeholder proc for machines that are built using frames. - return return 0 /obj/machinery/proc/assign_uid() diff --git a/code/modules/admin/verbs/debug.dm b/code/modules/admin/verbs/debug.dm index 8eaf21b99e..480edb6b36 100644 --- a/code/modules/admin/verbs/debug.dm +++ b/code/modules/admin/verbs/debug.dm @@ -957,7 +957,7 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that for(var/obj/machinery/power/smes/SMES in world) if(SMES.anchored) - SMES.chargemode = 1 + SMES.input_attempt = 1 /client/proc/setup_supermatter_engine() set category = "Debug" @@ -1017,16 +1017,16 @@ But you can call procs that are of type /mob/living/carbon/human/proc/ for that else if(istype(M,/obj/machinery/power/smes)) //This is the SMES inside the engine room. We don't need much power. var/obj/machinery/power/smes/SMES = M - SMES.chargemode = 1 - SMES.chargelevel = 200000 - SMES.output = 75000 + SMES.input_attempt = 1 + SMES.input_level = 200000 + SMES.output_level = 75000 else if(istype(M.loc.loc,/area/engine/engine_smes)) //Set every SMES to charge and spit out 300,000 power between the 4 of them. if(istype(M,/obj/machinery/power/smes)) var/obj/machinery/power/smes/SMES = M - SMES.chargemode = 1 - SMES.chargelevel = 200000 - SMES.output = 75000 + SMES.input_attempt = 1 + SMES.input_level = 200000 + SMES.output_level = 75000 if(!found_the_pump && response == "Setup Completely") src << "\red Unable to locate air supply to fill up with coolant, adding some coolant around the supermatter" diff --git a/code/modules/power/apc.dm b/code/modules/power/apc.dm index c0c8e2653a..b239864560 100644 --- a/code/modules/power/apc.dm +++ b/code/modules/power/apc.dm @@ -1072,10 +1072,10 @@ if(!area.requires_power) return - 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 @@ -1086,45 +1086,33 @@ var/last_ch = charging var/excess = surplus() - var/power_excess = 0 - var/perapc = 0 - if(terminal && terminal.powernet) - perapc = terminal.powernet.perapc + if(!src.avail()) + main_status = 0 + else if(excess < 0) + main_status = 1 + else + main_status = 2 if(debug) - log_debug( "Status: [main_status] - Excess: [excess] - Last Equip: [lastused_equip] - Last Light: [lastused_light]") - - if(area.powerupdate) - log_debug("power update in [area.name] / [name]") + log_debug("Status: [main_status] - Excess: [excess] - Last Equip: [lastused_equip] - Last Light: [lastused_light] - Longterm: [longtermpower]") if(cell && !shorted) - //var/cell_charge = cell.charge - var/cell_maxcharge = cell.maxcharge + // draw power from cell as before to power the area + var/cellused = min(cell.charge, CELLRATE * lastused_total) // clamp deduction to a max, amount left in cell + cell.use(cellused) - // Calculate how much power the APC will try to get from the grid. - var/target_draw = lastused_total - if (src.attempt_charging()) - target_draw += min((cell_maxcharge - cell.charge), (cell_maxcharge*CHARGELEVEL))/CELLRATE - target_draw = min(target_draw, perapc) //limit power draw by perapc - - // try to draw power from the grid - var/power_drawn = 0 - if (src.avail()) - power_drawn = draw_power(target_draw) //get some power from the powernet - - //figure out how much power is left over after meeting demand - power_excess = power_drawn - lastused_total - - if (power_excess < 0) //couldn't get enough power from the grid, we will need to take from the power cell. - - charging = 0 - - var/required_power = -power_excess - if(cell.charge >= required_power*CELLRATE) // can we draw enough from cell to cover what's left over? - cell.use(required_power*CELLRATE) - - else if (autoflag != 0) // not enough power available to run the last tick! + if(excess > lastused_total) // if power excess recharge the cell + // by the same amount just used + var/draw = draw_power(cellused/CELLRATE) // draw the power needed to charge this cell + cell.give(draw * CELLRATE) + else // no excess, and not enough per-apc + if( (cell.charge/CELLRATE + excess) >= lastused_total) // can we draw enough from cell+grid to cover last usage? + var/draw = draw_power(excess) + cell.charge = min(cell.maxcharge, cell.charge + CELLRATE * draw) //recharge with what we can + 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) @@ -1132,13 +1120,6 @@ environ = autoset(environ, 0) autoflag = 0 - //Set external power status - if (!power_drawn) - main_status = 0 - else if (power_excess < 0) - main_status = 1 - else - main_status = 2 // Set channels depending on how much charge we have left @@ -1148,7 +1129,6 @@ else if(longtermpower > -10) longtermpower -= 2 - if(cell.charge >= 1250 || longtermpower > 0) // Put most likely at the top so we don't check it last, effeciency 101 if(autoflag != 3) equipment = autoset(equipment, 1) @@ -1181,28 +1161,33 @@ autoflag = 0 // now trickle-charge the cell + if(src.attempt_charging()) - if (power_excess > 0) // check to make sure we have enough to charge - cell.give(power_excess*CELLRATE) // actually recharge the cell + if(excess > 0) // check to make sure we have enough to charge + // Max charge is capped to % per second constant + var/ch = min(excess*CELLRATE, cell.maxcharge*CHARGELEVEL) + + ch = draw_power(ch/CELLRATE) // Removes the power we're taking from the grid + cell.give(ch*CELLRATE) // actually recharge the cell + else charging = 0 // stop charging chargecount = 0 // show cell as fully charged if so - if(cell.charge >= cell_maxcharge) + if(cell.charge >= cell.maxcharge) + cell.charge = cell.maxcharge charging = 2 - //if we have excess power for long enough, think about re-enable charging. if(chargemode) if(!charging) - //last_surplus() overestimates the amount of power available for charging, but it's equivalent to what APCs were doing before. - if(src.last_surplus()*CELLRATE >= cell_maxcharge*CHARGELEVEL) + if(excess > cell.maxcharge*CHARGELEVEL) chargecount++ else chargecount = 0 - charging = 0 if(chargecount >= 10) + chargecount = 0 charging = 1 @@ -1220,7 +1205,6 @@ area.poweralert(0, src) autoflag = 0 - // update icon & area power if anything changed if(last_lt != lighting || last_eq != equipment || last_en != environ) @@ -1228,7 +1212,6 @@ update() else if (last_ch != charging) queue_icon_update() - src.updateDialog() // val 0=off, 1=off(auto) 2=on 3=on(auto) // on 0=off, 1=on, 2=autooff diff --git a/code/modules/power/batteryrack.dm b/code/modules/power/batteryrack.dm index b620f74e2d..bfba755eb7 100644 --- a/code/modules/power/batteryrack.dm +++ b/code/modules/power/batteryrack.dm @@ -23,9 +23,9 @@ name = "power cell rack PSU" desc = "A rack of power cells working as a PSU." charge = 0 //you dont really want to make a potato PSU which already is overloaded - online = 0 - chargelevel = 0 - output = 0 + output_attempt = 0 + input_level = 0 + output_level = 0 input_level_max = 0 output_level_max = 0 icon_state = "gsmes" @@ -37,9 +37,9 @@ /obj/machinery/power/smes/batteryrack/substation name = "Substation PSU" desc = "A rack of power cells working as a PSU. This one seems to be equipped for higher power loads." - output = 150000 - chargelevel = 150000 - online = 1 + output_level = 150000 + input_level = 150000 + output_attempt = 1 // One high capacity cell, two regular cells. Lots of room for engineer upgrades // Also five basic capacitors. Again, upgradeable. @@ -89,13 +89,13 @@ capacity = C * 40 //Basic cells are such crap. Hyper cells needed to get on normal SMES levels. -/obj/machinery/power/smes/batteryrack/updateicon() +/obj/machinery/power/smes/batteryrack/update_icon() overlays.Cut() if(stat & BROKEN) return - if (online) + if (output_attempt) overlays += image('icons/obj/power.dmi', "gsmes_outputting") - if(charging) + if(inputting) overlays += image('icons/obj/power.dmi', "gsmes_charging") var/clevel = chargedisplay() @@ -113,7 +113,7 @@ if(open_hatch) if(istype(W, /obj/item/weapon/crowbar)) if (charge < (capacity / 100)) - if (!online && !chargemode) + if (!output_attempt && !input_attempt) playsound(get_turf(src), 'sound/items/Crowbar.ogg', 50, 1) var/obj/machinery/constructable_frame/machine_frame/M = new /obj/machinery/constructable_frame/machine_frame(src.loc) M.state = 2 @@ -130,7 +130,7 @@ user << "Better let [src] discharge before dismantling it." else if ((istype(W, /obj/item/weapon/stock_parts/capacitor) && (capacitors_amount < 5)) || (istype(W, /obj/item/weapon/cell) && (cells_amount < 5))) if (charge < (capacity / 100)) - if (!online && !chargemode) + if (!output_attempt && !input_attempt) user.drop_item() component_parts += W W.loc = src @@ -163,13 +163,13 @@ return -/obj/machinery/power/smes/batteryrack/makeshift/updateicon() +/obj/machinery/power/smes/batteryrack/makeshift/update_icon() overlays.Cut() if(stat & BROKEN) return - if (online) + if (output_attempt) overlays += image('icons/obj/power.dmi', "gsmes_outputting") - if(charging) + if(inputting) overlays += image('icons/obj/power.dmi', "gsmes_charging") if (overcharge_percent > 100) overlays += image('icons/obj/power.dmi', "gsmes_overcharge") @@ -234,35 +234,35 @@ //store machine state to see if we need to update the icon overlays var/last_disp = chargedisplay() - var/last_chrg = charging - var/last_onln = online + var/last_chrg = inputting + var/last_onln = output_attempt var/last_overcharge = overcharge_percent if(terminal) - if(chargemode) - var/target_load = min((capacity-charge)/SMESRATE, chargelevel) // charge at set rate, limited to spare capacity + if(input_attempt) + var/target_load = min((capacity-charge)/SMESRATE, input_level) // charge at set rate, limited to spare capacity var/actual_load = draw_power(target_load) // add the load to the terminal side network charge += actual_load * SMESRATE // increase the charge if (actual_load >= target_load) // did the powernet have enough power available for us? - charging = 1 + inputting = 1 else - charging = 0 + inputting = 0 - if(online) // if outputting - lastout = min( charge/SMESRATE, output) //limit output to that stored - charge -= lastout*SMESRATE // reduce the storage (may be recovered in /restore() if excessive) - add_avail(lastout) // add output to powernet (smes side) + if(output_attempt) // if outputting + output_used = min( charge/SMESRATE, output_level) //limit output to that stored + charge -= output_used*SMESRATE // reduce the storage (may be recovered in /restore() if excessive) + add_avail(output_used) // add output to powernet (smes side) if(charge < 0.0001) - online = 0 // stop output if charge falls to zero + outputting(0) // stop output if charge falls to zero overcharge_percent = round((charge / capacity) * 100) if (overcharge_percent > 115) //115% is the minimum overcharge for anything to happen overcharge_consequences() // only update icon if state changed - if(last_disp != chargedisplay() || last_chrg != charging || last_onln != online || ((overcharge_percent > 100) ^ (last_overcharge > 100))) - updateicon() + if(last_disp != chargedisplay() || last_chrg != inputting || last_onln != output_attempt || ((overcharge_percent > 100) ^ (last_overcharge > 100))) + update_icon() return #undef SMESRATE diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index 2c20e8f6c4..65f73c2770 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -212,30 +212,6 @@ obj/structure/cable/proc/cableColor(var/colorC) color_n = colorC color = color_n -//////////////////////////////////////////// -// Power related -/////////////////////////////////////////// - -obj/structure/cable/proc/add_avail(var/amount) - if(powernet) - powernet.newavail += amount - -obj/structure/cable/proc/add_load(var/amount) - if(powernet) - powernet.load += amount - -obj/structure/cable/proc/surplus() - if(powernet) - return powernet.avail-powernet.load - else - return 0 - -obj/structure/cable/proc/avail() - if(powernet) - return powernet.avail - else - return 0 - ///////////////////////////////////////////////// // Cable laying helpers //////////////////////////////////////////////// diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index bde1902af1..03b80bf552 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -352,7 +352,7 @@ source_area.use_power(drained_energy/CELLRATE) else if (istype(power_source,/datum/powernet)) var/drained_power = drained_energy/CELLRATE //convert from "joules" to "watts" - PN.load+=drained_power + PN.draw_power(drained_power) else if (istype(power_source, /obj/item/weapon/cell)) cell.use(drained_energy) return drained_energy diff --git a/code/modules/power/powernet.dm b/code/modules/power/powernet.dm index 9c32eb0b9c..98affbded0 100644 --- a/code/modules/power/powernet.dm +++ b/code/modules/power/powernet.dm @@ -21,7 +21,7 @@ //Returns the amount of excess power (before refunding to SMESs) from last tick. //This is for machines that might adjust their power consumption using this data. /datum/powernet/proc/last_surplus() - return max(avail - load, 0) + return netexcess /datum/powernet/proc/draw_power(var/amount) var/draw = between(0, amount, avail - load) @@ -89,7 +89,7 @@ //Therefore we can raise the amount of power rationed out to APCs on the assumption that those APCs that used less than perapc will continue to do so. //If that assumption fails, then some APCs will miss out on power next tick, however it will be rebalanced for the tick after. if (netexcess >= 0) - perapc_excess += min(netexcess/numapc, (avail - perapc) - perapc_excess) + perapc_excess = netexcess/numapc else perapc_excess = 0 diff --git a/code/modules/power/smes.dm b/code/modules/power/smes.dm index c39e922cae..3ec0b90ab7 100644 --- a/code/modules/power/smes.dm +++ b/code/modules/power/smes.dm @@ -11,7 +11,23 @@ density = 1 anchored = 1 use_power = 0 - var/output = 50000 //Amount of power it tries to output + + var/capacity = 5e6 // maximum charge + var/charge = 1e6 // actual charge + + var/input_attempt = 0 // 1 = attempting to charge, 0 = not attempting to charge + var/inputting = 0 // 1 = actually inputting, 0 = not inputting + var/input_level = 50000 // amount of power the SMES attempts to charge by + var/input_level_max = 200000 // cap on input_level + var/input_available = 0 // amount of charge available from input last tick + + var/output_attempt = 1 // 1 = attempting to output, 0 = not attempting to output + var/outputting = 1 // 1 = actually outputting, 0 = not outputting + var/output_level = 50000 // amount of power the SMES attempts to output + var/output_level_max = 200000 // cap on output_level + var/output_used = 0 // amount of power actually outputted. may be less than output_level if the powernet returns excess power + + /*var/output = 50000 //Amount of power it tries to output var/lastout = 0 //Amount of power it actually outputs to the powernet var/loaddemand = 0 //For use in restore() var/capacity = 5e6 //Maximum amount of power it can hold @@ -21,16 +37,17 @@ //var/chargecount = 0 var/chargelevel = 0 //Amount of power it tries to charge from powernet var/online = 1 //1 if it's outputting power, 0 if not. - var/name_tag = null - var/obj/machinery/power/terminal/terminal = null + */ + //Holders for powerout event. - var/last_output = 0 - var/last_charge = 0 - var/last_online = 0 + var/last_output_attempt = 0 + var/last_input_attempt = 0 + var/last_charge = 0 + var/open_hatch = 0 + var/name_tag = null var/building_terminal = 0 //Suggestions about how to avoid clickspam building several terminals accepted! - var/input_level_max = 200000 - var/output_level_max = 200000 + var/obj/machinery/power/terminal/terminal = null /obj/machinery/power/smes/New() ..() @@ -51,19 +68,19 @@ terminal.master = src if(!terminal.powernet) terminal.connect_to_network() - updateicon() + update_icon() return -/obj/machinery/power/smes/proc/updateicon() +/obj/machinery/power/smes/update_icon() overlays.Cut() if(stat & BROKEN) return - overlays += image('icons/obj/power.dmi', "smes-op[online]") + overlays += image('icons/obj/power.dmi', "smes-op[outputting]") - if(charging) + if(inputting) overlays += image('icons/obj/power.dmi', "smes-oc1") else - if(chargemode) + if(input_attempt) overlays += image('icons/obj/power.dmi', "smes-oc0") var/clevel = chargedisplay() @@ -79,55 +96,67 @@ /obj/machinery/power/smes/process() + if(stat & BROKEN) return //store machine state to see if we need to update the icon overlays var/last_disp = chargedisplay() - var/last_chrg = charging - var/last_onln = online + var/last_chrg = inputting + var/last_onln = outputting - if(terminal) - //If chargemod is set, try to charge - //Use charging to let the player know whether we were able to obtain our target load. - //TODO: Add a meter to tell players how much charge we are actually getting, and only set charging to 0 when we are unable to get any charge at all. - if(chargemode) - var/target_load = min((capacity-charge)/SMESRATE, chargelevel) // charge at set rate, limited to spare capacity - var/actual_load = draw_power(target_load) // add the load to the terminal side network - charge += actual_load * SMESRATE // increase the charge + //inputting + if(terminal && input_attempt) + input_available = terminal.surplus() - if (actual_load >= target_load) // did the powernet have enough power available for us? - charging = 1 - else - charging = 0 + if(inputting) + if(input_available > 0 && input_available >= input_level) // if there's power available, try to charge - if(online) // if outputting - lastout = min( charge/SMESRATE, output) //limit output to that stored - charge -= lastout*SMESRATE // reduce the storage (may be recovered in /restore() if excessive) - add_avail(lastout) // add output to powernet (smes side) - if(charge < 0.0001) - online = 0 // stop output if charge falls to zero + var/load = min((capacity-charge)/SMESRATE, input_level) // charge at set rate, limited to spare capacity + var/actual_load = terminal.draw_power(load) // draw power from the terminal side network + charge += actual_load * SMESRATE // increase the charge + + else // if not enough capcity + inputting = 0 // stop inputting + + else + if(input_attempt && input_available > 0 && input_available >= input_level) + inputting = 1 + + //outputting + if(outputting) + output_used = min( charge/SMESRATE, output_level) //limit output to that stored + + charge -= output_used*SMESRATE // reduce the storage (may be recovered in /restore() if excessive) + + add_avail(output_used) // add output to powernet (smes side) + + if(output_used < 0.0001) // either from no charge or set to 0 + outputting = 0 + investigate_log("lost power and turned off","singulo") + else if(output_attempt && charge > output_level && output_level > 0) + outputting = 1 + else + output_used = 0 // only update icon if state changed - if(last_disp != chargedisplay() || last_chrg != charging || last_onln != online) - updateicon() + if(last_disp != chargedisplay() || last_chrg != inputting || last_onln != outputting) + update_icon() + - return // called after all power processes are finished // restores charge level to smes if there was excess this ptick - - /obj/machinery/power/smes/proc/restore() if(stat & BROKEN) return - if(!online) - loaddemand = 0 + if(!outputting) + output_used = 0 return var/excess = powernet.netexcess // this was how much wasn't used on the network last ptick, minus any removed by other SMESes - excess = min(lastout, excess) // clamp it to how much was actually output by this SMES last ptick + excess = min(output_used, excess) // clamp it to how much was actually output by this SMES last ptick excess = min((capacity-charge)/SMESRATE, excess) // for safety, also limit recharge by space capacity of SMES (shouldn't happen) @@ -135,13 +164,13 @@ var/clev = chargedisplay() - charge += excess * SMESRATE + charge += excess * SMESRATE // restore unused power powernet.netexcess -= excess // remove the excess from the powernet, so later SMESes don't try to use it - loaddemand = lastout-excess + output_used -= excess - if(clev != chargedisplay() ) - updateicon() + if(clev != chargedisplay() ) //if needed updates the icons overlay + update_icon() return //Will return 1 on failure @@ -256,14 +285,14 @@ var/data[0] data["nameTag"] = name_tag data["storedCapacity"] = round(100.0*charge/capacity, 0.1) - data["charging"] = charging - data["chargeMode"] = chargemode - data["chargeLevel"] = chargelevel + data["charging"] = inputting + data["chargeMode"] = input_attempt + data["chargeLevel"] = input_level data["chargeMax"] = input_level_max - data["outputOnline"] = online - data["outputLevel"] = output + data["outputOnline"] = output_attempt + data["outputLevel"] = output_level data["outputMax"] = output_level_max - data["outputLoad"] = round(loaddemand) + data["outputLoad"] = round(output_used) // update the ui if it exists, returns null if no ui is passed/found ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open) @@ -294,40 +323,34 @@ if (!istype(src.loc, /turf) && !istype(usr, /mob/living/silicon/)) return 0 // Do not update ui - for(var/area/A in active_areas) - A.master.powerupdate = 3 - - if( href_list["cmode"] ) - chargemode = !chargemode - if(!chargemode) - charging = 0 - updateicon() + inputting(!inputting) + update_icon() else if( href_list["online"] ) - online = !online - updateicon() + outputting(!outputting) + update_icon() else if( href_list["input"] ) switch( href_list["input"] ) if("min") - chargelevel = 0 + input_level = 0 if("max") - chargelevel = input_level_max + input_level = input_level_max if("set") - chargelevel = input(usr, "Enter new input level (0-[input_level_max])", "SMES Input Power Control", chargelevel) as num - chargelevel = max(0, min(input_level_max, chargelevel)) // clamp to range + input_level = input(usr, "Enter new input level (0-[input_level_max])", "SMES Input Power Control", input_level) as num + input_level = max(0, min(input_level_max, input_level)) // clamp to range else if( href_list["output"] ) switch( href_list["output"] ) if("min") - output = 0 + output_level = 0 if("max") - output = output_level_max + output_level = output_level_max if("set") - output = input(usr, "Enter new output level (0-[output_level_max])", "SMES Output Power Control", output) as num - output = max(0, min(output_level_max, output)) // clamp to range + output_level = input(usr, "Enter new output level (0-[output_level_max])", "SMES Output Power Control", output_level) as num + output_level = max(0, min(output_level_max, output_level)) // clamp to range - investigate_log("input/output; [chargelevel>output?"":""][chargelevel]/[output] | Output-mode: [online?"on":"off"] | Input-mode: [chargemode?"auto":"off"] by [usr.key]","singulo") + investigate_log("input/output; [input_level>output_level?"":""][input_level]/[output_level] | Output-mode: [output_attempt?"on":"off"] | Input-mode: [input_attempt?"auto":"off"] by [usr.key]","singulo") return 1 @@ -359,27 +382,33 @@ smoke.attach(src) smoke.start() +/obj/machinery/power/smes/proc/inputting(var/do_input) + input_attempt = do_input + if(!input_attempt) + inputting = 0 + +/obj/machinery/power/smes/proc/outputting(var/do_output) + output_attempt = do_output + if(!output_attempt) + outputting = 0 /obj/machinery/power/smes/emp_act(severity) - online = 0 - charging = 0 - output = 0 + inputting(rand(0,1)) + outputting(rand(0,1)) + output_level = rand(0, output_level_max) + input_level = rand(0, input_level_max) charge -= 1e6/severity if (charge < 0) charge = 0 - spawn(100) - output = initial(output) - charging = initial(charging) - online = initial(online) + update_icon() ..() - /obj/machinery/power/smes/magical name = "magical power storage unit" desc = "A high-capacity superconducting magnetic energy storage (SMES) unit. Magically produces power." capacity = 9000000 - output = 250000 + output_level = 250000 /obj/machinery/power/smes/magical/process() charge = 5000000 diff --git a/code/modules/power/smes_construction.dm b/code/modules/power/smes_construction.dm index 891f231f8f..3332a2577e 100644 --- a/code/modules/power/smes_construction.dm +++ b/code/modules/power/smes_construction.dm @@ -174,7 +174,7 @@ A.set_broken() // Failing SMES has special icon overlay. -/obj/machinery/power/smes/buildable/updateicon() +/obj/machinery/power/smes/buildable/update_icon() if (failing) overlays.Cut() overlays += image('icons/obj/power.dmi', "smes-crit") @@ -196,7 +196,7 @@ user << "Safety circuit of [src] is preventing modifications while it's charged!" return - if (online || chargemode) + if (output_attempt || input_attempt) user << "Turn off the [src] first!" return