Files
CHOMPStation2/code/modules/power/smes.dm
Ccomp5950 6af132b834 APC bugfix after someone messed with mah areas!
This was probably bound to happen either way the previous version was based upon a faulty understanding of how the areas worked this is much more robust and only messes with the master areas
and master areas needing power updates call power updates for the each of it's child areas.  Also added where messing with SMESes called for an update on all areas power consumption, probably
not required but doing so either way.

We also rebuild the active_areas list every 5 minutes, if you get a engineer that wants to build a new area off of the station with APC's set rebuild_all_areas in the master controller and it will
update instantly, otherwise wait 5 minutes.  The only downside to this 5 minutes is you might get free energy until that area becomes active.
2014-04-01 03:06:58 -05:00

323 lines
9.0 KiB
Plaintext

// the SMES
// stores power
#define SMESMAXCHARGELEVEL 200000
#define SMESMAXOUTPUT 200000
/obj/machinery/power/smes
name = "power storage unit"
desc = "A high-capacity superconducting magnetic energy storage (SMES) unit."
icon_state = "smes"
density = 1
anchored = 1
use_power = 0
var/output = 50000
var/lastout = 0
var/loaddemand = 0
var/capacity = 5e6
var/charge = 1e6
var/charging = 0
var/chargemode = 0
var/chargecount = 0
var/chargelevel = 50000
var/online = 1
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
/obj/machinery/power/smes/New()
..()
spawn(5)
dir_loop:
for(var/d in cardinal)
var/turf/T = get_step(src, d)
for(var/obj/machinery/power/terminal/term in T)
if(term && term.dir == turn(d, 180))
terminal = term
break dir_loop
if(!terminal)
stat |= BROKEN
return
terminal.master = src
updateicon()
return
/obj/machinery/power/smes/proc/updateicon()
overlays.Cut()
if(stat & BROKEN) return
overlays += image('icons/obj/power.dmi', "smes-op[online]")
if(charging)
overlays += image('icons/obj/power.dmi', "smes-oc1")
else
if(chargemode)
overlays += image('icons/obj/power.dmi', "smes-oc0")
var/clevel = chargedisplay()
if(clevel>0)
overlays += image('icons/obj/power.dmi', "smes-og[clevel]")
return
/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
//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
if(terminal)
var/excess = terminal.surplus()
if(charging)
if(excess >= 0) // if there's power available, try to charge
var/load = min((capacity-charge)/SMESRATE, chargelevel) // charge at set rate, limited to spare capacity
charge += load * SMESRATE // increase the charge
add_load(load) // add the load to the terminal side network
else // if not enough capcity
charging = 0 // stop charging
chargecount = 0
else
if(chargemode)
if(chargecount > rand(3,6))
charging = 1
chargecount = 0
if(excess > chargelevel)
chargecount++
else
chargecount = 0
else
chargecount = 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(charge < 0.0001)
online = 0 // stop output if charge falls to zero
// only update icon if state changed
if(last_disp != chargedisplay() || last_chrg != charging || last_onln != online)
updateicon()
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
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((capacity-charge)/SMESRATE, excess) // for safety, also limit recharge by space capacity of SMES (shouldn't happen)
// now recharge this amount
var/clev = chargedisplay()
charge += excess * SMESRATE
powernet.netexcess -= excess // remove the excess from the powernet, so later SMESes don't try to use it
loaddemand = lastout-excess
if(clev != chargedisplay() )
updateicon()
return
/obj/machinery/power/smes/add_load(var/amount)
if(terminal && terminal.powernet)
terminal.powernet.newload += amount
/obj/machinery/power/smes/attack_ai(mob/user)
add_fingerprint(user)
ui_interact(user)
/obj/machinery/power/smes/attack_hand(mob/user)
add_fingerprint(user)
ui_interact(user)
/obj/machinery/power/smes/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null)
if(stat & BROKEN)
return
// this is the data which will be sent to the ui
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["chargeMax"] = SMESMAXCHARGELEVEL
data["outputOnline"] = online
data["outputLevel"] = output
data["outputMax"] = SMESMAXOUTPUT
data["outputLoad"] = round(loaddemand)
// 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)
if (!ui)
// the ui does not exist, so we'll create a new() one
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
ui = new(user, src, ui_key, "smes.tmpl", "SMES Power Storage Unit", 540, 380)
// when the ui is first opened this is the data it will use
ui.set_initial_data(data)
// open the new ui window
ui.open()
// auto update every Master Controller tick
ui.set_auto_update(1)
/obj/machinery/power/smes/Topic(href, href_list)
..()
if (usr.stat || usr.restrained() )
return
if (!(istype(usr, /mob/living/carbon/human) || ticker) && ticker.mode.name != "monkey")
if(!istype(usr, /mob/living/silicon/ai))
usr << "\red You don't have the dexterity to do this!"
return
//world << "[href] ; [href_list[href]]"
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()
else if( href_list["online"] )
online = !online
updateicon()
else if( href_list["input"] )
switch( href_list["input"] )
if("min")
chargelevel = 0
if("max")
chargelevel = SMESMAXCHARGELEVEL //30000
if("set")
chargelevel = input(usr, "Enter new input level (0-[SMESMAXCHARGELEVEL])", "SMES Input Power Control", chargelevel) as num
chargelevel = max(0, min(SMESMAXCHARGELEVEL, chargelevel)) // clamp to range
else if( href_list["output"] )
switch( href_list["output"] )
if("min")
output = 0
if("max")
output = SMESMAXOUTPUT //30000
if("set")
output = input(usr, "Enter new output level (0-[SMESMAXOUTPUT])", "SMES Output Power Control", output) as num
output = max(0, min(SMESMAXOUTPUT, output)) // clamp to range
investigate_log("input/output; [chargelevel>output?"<font color='green'>":"<font color='red'>"][chargelevel]/[output]</font> | Output-mode: [online?"<font color='green'>on</font>":"<font color='red'>off</font>"] | Input-mode: [chargemode?"<font color='green'>auto</font>":"<font color='red'>off</font>"] by [usr.key]","singulo")
return 1
/obj/machinery/power/smes/proc/ion_act()
if(src.z == 1)
if(prob(1)) //explosion
world << "\red SMES explosion in [src.loc.loc]"
for(var/mob/M in viewers(src))
M.show_message("\red The [src.name] is making strange noises!", 3, "\red You hear sizzling electronics.", 2)
sleep(10*pick(4,5,6,7,10,14))
var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread()
smoke.set_up(3, 0, src.loc)
smoke.attach(src)
smoke.start()
explosion(src.loc, -1, 0, 1, 3, 0)
del(src)
return
if(prob(15)) //Power drain
world << "\red SMES power drain in [src.loc.loc]"
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(3, 1, src)
s.start()
if(prob(50))
emp_act(1)
else
emp_act(2)
if(prob(5)) //smoke only
world << "\red SMES smoke in [src.loc.loc]"
var/datum/effect/effect/system/smoke_spread/smoke = new /datum/effect/effect/system/smoke_spread()
smoke.set_up(3, 0, src.loc)
smoke.attach(src)
smoke.start()
/obj/machinery/power/smes/emp_act(severity)
online = 0
charging = 0
output = 0
charge -= 1e6/severity
if (charge < 0)
charge = 0
spawn(100)
output = initial(output)
charging = initial(charging)
online = initial(online)
..()
/obj/machinery/power/smes/magical
name = "magical power storage unit"
desc = "A high-capacity superconducting magnetic energy storage (SMES) unit. Magically produces power."
process()
capacity = INFINITY
charge = INFINITY
..()
/proc/rate_control(var/S, var/V, var/C, var/Min=1, var/Max=5, var/Limit=null)
var/href = "<A href='?src=\ref[S];rate control=1;[V]"
var/rate = "[href]=-[Max]'>-</A>[href]=-[Min]'>-</A> [(C?C : 0)] [href]=[Min]'>+</A>[href]=[Max]'>+</A>"
if(Limit) return "[href]=-[Limit]'>-</A>"+rate+"[href]=[Limit]'>+</A>"
return rate
#undef SMESRATE