Files
CHOMPStation2/code/modules/power/smes.dm
mwerezak 90af78ac44 Increases SM power output
Should safely run to 700 kW. Returned starting SMES charge back to
original value to compensate. Engine omnifilters now start off on round
start.
2014-09-12 23:01:15 -04:00

391 lines
13 KiB
Plaintext

// the SMES
// stores power
#define SMESMAXCHARGELEVEL 250000
#define SMESMAXOUTPUT 250000
/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 //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
var/charge = 1.0e6 //Current amount of power it holds
var/charging = 0 //1 if it's actually charging, 0 if not
var/chargemode = 0 //1 if it's trying to charge, 0 if not.
//var/chargecount = 0
var/chargelevel = 50000 //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/open_hatch = 0
var/building_terminal = 0 //Suggestions about how to avoid clickspam building several terminals accepted!
var/input_level_max = SMESMAXCHARGELEVEL
var/output_level_max = SMESMAXOUTPUT
/obj/machinery/power/smes/New()
..()
spawn(5)
if(!powernet)
connect_to_network()
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
if(!terminal.powernet)
terminal.connect_to_network()
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)
//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 = add_load(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
else
charging = 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
//Will return 1 on failure
/obj/machinery/power/smes/proc/make_terminal(const/mob/user)
if (user.loc == loc)
user << "<span class='warning'>You must not be on the same tile as the [src].</span>"
return 1
//Direction the terminal will face to
var/tempDir = get_dir(user, src)
switch(tempDir)
if (NORTHEAST, SOUTHEAST)
tempDir = EAST
if (NORTHWEST, SOUTHWEST)
tempDir = WEST
var/turf/tempLoc = get_step(src, reverse_direction(tempDir))
if (istype(tempLoc, /turf/space))
user << "<span class='warning'>You can't build a terminal on space.</span>"
return 1
else if (istype(tempLoc))
if(tempLoc.intact)
user << "<span class='warning'>You must remove the floor plating first.</span>"
return 1
user << "<span class='notice'>You start adding cable to the [src].</span>"
if(do_after(user, 50))
terminal = new /obj/machinery/power/terminal(tempLoc)
terminal.dir = tempDir
terminal.master = src
return 0
return 1
/obj/machinery/power/smes/add_load(var/amount)
if(terminal && terminal.powernet)
return terminal.powernet.draw_power(amount)
return 0
/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/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
if(istype(W, /obj/item/weapon/screwdriver))
if(!open_hatch)
open_hatch = 1
user << "<span class='notice'>You open the maintenance hatch of [src].</span>"
else
open_hatch = 0
user << "<span class='notice'>You close the maintenance hatch of [src].</span>"
if (open_hatch)
if(istype(W, /obj/item/weapon/cable_coil) && !terminal && !building_terminal)
building_terminal = 1
var/obj/item/weapon/cable_coil/CC = W
if (CC.amount < 10)
user << "<span class='warning'>You need more cables.</span>"
building_terminal = 0
return
if (make_terminal(user))
building_terminal = 0
return
building_terminal = 0
CC.use(10)
user.visible_message(\
"<span class='notice'>[user.name] has added cables to the [src].</span>",\
"<span class='notice'>You added cables to the [src].</span>")
terminal.connect_to_network()
stat = 0
else if(istype(W, /obj/item/weapon/wirecutters) && terminal && !building_terminal)
building_terminal = 1
var/turf/tempTDir = terminal.loc
if (istype(tempTDir))
if(tempTDir.intact)
user << "<span class='warning'>You must remove the floor plating first.</span>"
else
user << "<span class='notice'>You begin to cut the cables...</span>"
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()
building_terminal = 0
return
new /obj/item/weapon/cable_coil(loc,10)
user.visible_message(\
"<span class='notice'>[user.name] cut the cables and dismantled the power terminal.</span>",\
"<span class='notice'>You cut the cables and dismantle the power terminal.</span>")
del(terminal)
building_terminal = 0
/obj/machinery/power/smes/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
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"] = input_level_max
data["outputOnline"] = online
data["outputLevel"] = output
data["outputMax"] = output_level_max
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, force_open)
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 = 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
else if( href_list["output"] )
switch( href_list["output"] )
if("min")
output = 0
if("max")
output = 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
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
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, 1, 0)
del(src)
return
if(prob(15)) //Power drain
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
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."
output = SMESMAXOUTPUT
/obj/machinery/power/smes/magical/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