Files
vgstation13/code/modules/power/smes.dm
2014-05-03 19:26:15 -08:00

424 lines
13 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/opened = 0
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()
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/smes
component_parts += new /obj/item/weapon/stock_parts/matter_bin
component_parts += new /obj/item/weapon/stock_parts/matter_bin
component_parts += new /obj/item/weapon/stock_parts/matter_bin
component_parts += new /obj/item/weapon/stock_parts/matter_bin
component_parts += new /obj/item/weapon/stock_parts/manipulator
component_parts += new /obj/item/weapon/stock_parts/manipulator
component_parts += new /obj/item/weapon/stock_parts/manipulator
component_parts += new /obj/item/weapon/stock_parts/micro_laser
component_parts += new /obj/item/weapon/stock_parts/micro_laser
component_parts += new /obj/item/weapon/stock_parts/micro_laser
component_parts += new /obj/item/weapon/stock_parts/console_screen
component_parts += new /obj/item/weapon/stock_parts/console_screen
RefreshParts()
return
/obj/machinery/power/smes/proc/make_terminal(const/mob/user)
if (user.loc == loc)
user << "<span class=\"warning\">Terminal creation aborted, you must not be on the same tile with SME.</span>"
return 2
playsound(get_turf(src), 'sound/items/zip.ogg', 100, 1)
if(do_after(user, 100))
var/tempDir = get_dir(user, src)
switch(tempDir)
if (NORTHEAST, SOUTHEAST)
tempDir = EAST
if (NORTHWEST, SOUTHWEST)
tempDir = WEST
terminal = new /obj/machinery/power/terminal(get_step(src, tempDir))
terminal.dir = user.dir
terminal.master = src
return 0
user << "<span class=\"warning\">You moved!</span>"
return 1
/obj/machinery/power/smes/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob) //these can only be moved by being reconstructed, solves having to remake the powernet.
if(istype(W, /obj/item/weapon/screwdriver))
if(!opened)
src.opened = 1
//src.icon_state = "smes_t"
user << "You open the maintenance hatch of [src]"
else
src.opened = 0
//src.icon_state = "smes"
user << "You close the maintenance hatch of [src]"
if(opened)
if(istype(W, /obj/item/weapon/crowbar))
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
M.icon_state = "box_1"
for(var/obj/I in component_parts)
if(I.reliability != 100 && crit_fail)
I.crit_fail = 1
I.loc = src.loc
del(src)
return 1
else if(istype(W, /obj/item/weapon/cable_coil) && !terminal)
var/obj/item/weapon/cable_coil/CC = W
if (CC.amount < 10)
user << "<span class=\"warning\">You need 10 length cable coil to make a terminal.</span>"
return
user << "<span class=\"notice\">You start adding cable to the SME.</span>"
if (make_terminal(user))
return
CC.use(10)
user.visible_message(\
"\red [user.name] has added cables to the SMES!",\
"You added cables the SMES.")
terminal.connect_to_network()
src.stat = 0
else if(istype(W, /obj/item/weapon/wirecutters) && terminal)
var/tempTDir = get_step(src.loc, WEST)
if(tempTDir:intact)
user << "\red You must remove the floor plating in front of the SMES first."
return
user << "You begin to cut the cables..."
playsound(get_turf(src), 'sound/items/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 the cables and dismantled the power terminal.",\
"You cut the cables and dismantle the power terminal.")
del(terminal)
else
user.set_machine(src)
interact(user)
return 1
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)
src.add_hiddenprint(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
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