mirror of
https://github.com/cybergirlvannie/OpenSS13.git
synced 2026-07-12 00:02:25 +01:00
Further code conversion, some of /obj/machinery/power to new format
This commit is contained in:
+1
-82
@@ -2598,53 +2598,8 @@ Total SMES charging rate should not exceed total power generation rate, or an ov
|
||||
icon = 'wire.dmi'
|
||||
|
||||
|
||||
/obj/machinery/power
|
||||
name = null
|
||||
icon = 'power.dmi'
|
||||
anchored = 1.0
|
||||
var/datum/powernet/powernet = null
|
||||
var/netnum = 0
|
||||
var/directwired = 1 // by default, power machines are connected by a cable in a neighbouring turf
|
||||
// if set to 0, requires a 0-X cable on this turf
|
||||
|
||||
/obj/machinery/power/apc
|
||||
name = "area power controller"
|
||||
|
||||
icon_state = "apc0"
|
||||
anchored = 1
|
||||
var/area/area
|
||||
var/obj/item/weapon/cell/cell
|
||||
var/start_charge = 90 // initial cell charge %
|
||||
var/cell_type = 1 // 0=no cell, 1=regular, 2=high-cap (x5)
|
||||
var/opened = 0
|
||||
var/lighting = 3
|
||||
var/equipment = 3
|
||||
var/environ = 3
|
||||
var/operating = 1
|
||||
var/charging = 0
|
||||
var/chargemode = 1
|
||||
var/chargecount = 0
|
||||
var/locked = 1
|
||||
var/coverlocked = 1
|
||||
var/tdir = null
|
||||
var/obj/machinery/power/terminal/terminal = null
|
||||
var/lastused_light = 0
|
||||
var/lastused_equip = 0
|
||||
var/lastused_environ = 0
|
||||
var/lastused_total = 0
|
||||
var/main_status = 0
|
||||
netnum = -1 // set so that APCs aren't found as powernet nodes
|
||||
var/access = "4000/0002/0030"
|
||||
var/allowed = "Systems"
|
||||
|
||||
/obj/machinery/power/terminal
|
||||
name = "terminal"
|
||||
icon_state = "term"
|
||||
desc = "An underfloor wiring terminal for power equipment"
|
||||
level = 1
|
||||
var/obj/machinery/power/master = null
|
||||
anchored = 1
|
||||
directwired = 0 // must have a cable on same turf connecting to terminal
|
||||
|
||||
/obj/machinery/power/generator
|
||||
name = "generator"
|
||||
@@ -2663,12 +2618,7 @@ Total SMES charging rate should not exceed total power generation rate, or an ov
|
||||
var/lastgen = 0
|
||||
var/lastgenlev = -1
|
||||
|
||||
/obj/machinery/power/monitor
|
||||
name = "power monitoring computer"
|
||||
icon = 'stationobjs.dmi'
|
||||
icon_state = "power_computer"
|
||||
density = 1
|
||||
anchored = 1
|
||||
|
||||
|
||||
#define SMESMAXCHARGELEVEL 60000
|
||||
#define SMESMAXOUTPUT 60000
|
||||
@@ -2692,38 +2642,7 @@ Total SMES charging rate should not exceed total power generation rate, or an ov
|
||||
var/n_tag = null
|
||||
var/obj/machinery/power/terminal/terminal = null
|
||||
|
||||
/obj/machinery/power/solar
|
||||
name = "solar panel"
|
||||
desc = "A solar electrical generator."
|
||||
icon = 'power.dmi'
|
||||
icon_state = "sp_base"
|
||||
anchored = 1
|
||||
density = 1
|
||||
directwired = 1
|
||||
var/id = 1
|
||||
var/obscured = 0
|
||||
var/sunfrac = 0
|
||||
var/adir = SOUTH
|
||||
var/ndir = SOUTH
|
||||
var/turn_angle = 0
|
||||
var/obj/machinery/power/solar_control/control
|
||||
|
||||
/obj/machinery/power/solar_control
|
||||
name = "solar panel control"
|
||||
desc = "A controller for solar panel arrays."
|
||||
icon = 'enginecomputer.dmi'
|
||||
icon_state = "solar_con"
|
||||
anchored = 1
|
||||
density = 1
|
||||
directwired = 1
|
||||
var/id = 1
|
||||
var/cdir = 0
|
||||
var/gen = 0
|
||||
var/lastgen = 0
|
||||
var/track = 0 // on/off
|
||||
var/trackrate = 600 // 300-900 seconds
|
||||
var/trackdir = 1 // 0 =CCW, 1=CW
|
||||
var/nexttime = 0
|
||||
|
||||
/obj/machinery/power/portable_gen
|
||||
name = "portable generator"
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
/*
|
||||
* Power Machines -- Base type of machines that connect to the cable network.
|
||||
*
|
||||
* Includes generator, SMES, APC, Solar panels, etc.
|
||||
*
|
||||
* Note: While almost all machines comsume power, most do so through their area use_power() proc.
|
||||
* Power machines are those that connect directly to the /obj/cable network and supply and use power from it.
|
||||
*/
|
||||
|
||||
|
||||
obj/machinery/power
|
||||
name = null
|
||||
icon = 'power.dmi'
|
||||
anchored = 1.0
|
||||
|
||||
var
|
||||
datum/powernet/powernet = null // The powernet connected to this machine.
|
||||
// powernets are the data structures that hold information (power usage,
|
||||
// connected devices, etc.) about a contiguous network of cables and devices.
|
||||
|
||||
netnum = 0 // the number of the connected powernet (index of the global list/powernets).
|
||||
// if 0 or -1, the machine is not connected to a powernet.
|
||||
|
||||
directwired = 1 // by default, power machines are connected by a cable in a neighbouring turf
|
||||
// if set to 0, requires stub cable (ending at the centre) on this turf
|
||||
|
||||
|
||||
// Common helper procs for all power machines
|
||||
// Some machines override these.
|
||||
|
||||
|
||||
// Add an amount of power to the connected powernet
|
||||
// Done by generator-type machines to make power available
|
||||
|
||||
proc/add_avail(var/amount)
|
||||
if(powernet)
|
||||
powernet.newavail += amount
|
||||
|
||||
|
||||
// Add an amount of load to the connected powernet
|
||||
// Done by machines that draw power from the network
|
||||
|
||||
proc/add_load(var/amount)
|
||||
if(powernet)
|
||||
powernet.newload += amount
|
||||
|
||||
|
||||
// Returns the surplus power available on the connected powernet
|
||||
|
||||
proc/surplus()
|
||||
if(powernet)
|
||||
return powernet.avail-powernet.load
|
||||
else
|
||||
return 0
|
||||
|
||||
|
||||
// Returns the total available power (neglecting current load) available on the connected powernet
|
||||
|
||||
proc/avail()
|
||||
if(powernet)
|
||||
return powernet.avail
|
||||
else
|
||||
return 0
|
||||
|
||||
|
||||
// Routines used when constructing power cable networks
|
||||
|
||||
// Returns a list of cables that connect to this machine
|
||||
// Searches all turfs within 1 step for a cable that points towards the machine
|
||||
// If the machine is non-directwired, calls and returns get_indirect_connections() instead
|
||||
|
||||
proc/get_connections()
|
||||
|
||||
if(!directwired)
|
||||
return get_indirect_connections()
|
||||
|
||||
var/list/res = list()
|
||||
var/cdir
|
||||
|
||||
for(var/turf/T in orange(1, src))
|
||||
|
||||
cdir = get_dir(T, src)
|
||||
|
||||
for(var/obj/cable/C in T)
|
||||
|
||||
if(C.netnum)
|
||||
continue
|
||||
|
||||
if(C.d1 == cdir || C.d2 == cdir)
|
||||
res += C
|
||||
|
||||
return res
|
||||
|
||||
|
||||
// Returns a list of stub cables (1/2 length cables that end in the centre of a turf)
|
||||
// On the same turf as a non-directwired machine.
|
||||
|
||||
proc/get_indirect_connections()
|
||||
|
||||
var/list/res = list()
|
||||
|
||||
for(var/obj/cable/C in src.loc)
|
||||
|
||||
if(C.netnum)
|
||||
continue
|
||||
|
||||
if(C.d1 == 0)
|
||||
res += C
|
||||
|
||||
return res
|
||||
|
||||
|
||||
// Attacking a power machine with a cable_coil object attaches a wire to the machine
|
||||
// leading from the turf the player is standing on.
|
||||
// Only machines with directwired=1 need or use this.
|
||||
|
||||
attackby(obj/item/weapon/W, mob/user)
|
||||
|
||||
if(istype(W, /obj/item/weapon/cable_coil))
|
||||
|
||||
var/obj/item/weapon/cable_coil/coil = W
|
||||
|
||||
var/turf/T = user.loc
|
||||
|
||||
if(T.intact || !istype(T, /turf/station/floor))
|
||||
return
|
||||
|
||||
if(get_dist(src, user) > 1)
|
||||
return
|
||||
|
||||
if(!directwired) // only for attaching to directwired machines
|
||||
return
|
||||
|
||||
var/dirn = get_dir(user, src)
|
||||
|
||||
|
||||
for(var/obj/cable/LC in T)
|
||||
if(LC.d1 == dirn || LC.d2 == dirn)
|
||||
user << "There's already a cable at that position."
|
||||
return
|
||||
|
||||
var/obj/cable/NC = new(T)
|
||||
NC.d1 = 0
|
||||
NC.d2 = dirn
|
||||
NC.add_fingerprint()
|
||||
NC.updateicon()
|
||||
NC.update_network()
|
||||
coil.use(1)
|
||||
return
|
||||
else
|
||||
..()
|
||||
return
|
||||
@@ -0,0 +1,702 @@
|
||||
/*
|
||||
* APC - Area power controller.
|
||||
*
|
||||
* APCs control the distribution of power from the cable power network to each area
|
||||
* They have three channels, equipment, lighting, and environmental, which can be independently controlled
|
||||
* Each channel may be switched off to reduce power demand, and may do so automatically.
|
||||
*
|
||||
* The APC contains a power cell object that is used as a backup power supply for the area, which charges when
|
||||
* external power is sufficient. The cell may also be removed if the cover lock is diengaged.
|
||||
*
|
||||
* The APC controls require an ID card swipe to be unlocked. Once unlocked, each channel can be controlled.
|
||||
*
|
||||
* TODO: More graceful behaviour when there is more than one APC per area. Currenly, they may conflict if this happens.
|
||||
* and cell drain rate is not accurate.
|
||||
* TODO: Extend logic when a cell is not inserted. Currently, the APC turns off completely if no cell is inside.
|
||||
* Would be better to do some kind of channel switching depending on available external power.
|
||||
* TODO: Reduction of thrashing when total load exceeds demand. Perhaps needs some kind of (settable?) priority
|
||||
* for each APC, so more important APCs are powered first. Thrashing occurs because all APCs see surplus power,
|
||||
* then switch on charging, which reduces available power below the limit, thus causing all APCs to stop charging.
|
||||
* Fix requires some kind of cumulative load variable in the powenet, but map order processing of this would be
|
||||
* unsuitable.
|
||||
*/
|
||||
|
||||
|
||||
obj/machinery/power/apc
|
||||
name = "area power controller"
|
||||
|
||||
icon_state = "apc0"
|
||||
anchored = 1
|
||||
netnum = -1 // Always -1, set so that APCs aren't found as powernet nodes
|
||||
// instead, all connections are done through the associated terminal object
|
||||
var
|
||||
area/area // the area that this APC controls
|
||||
obj/item/weapon/cell/cell // the power cell object inserted in this APC (or null if none)
|
||||
start_charge = 90 // initial cell charge %
|
||||
cell_type = 1 // the cell type: 0=no cell, 1=regular, 2=high-cap (x5)
|
||||
opened = 0 // true if the APC is opened (cell exposed)
|
||||
locked = 1 // true if the APC interface is locked (non-alterable)
|
||||
coverlocked = 1 // true if the APC cover is locked
|
||||
|
||||
lighting = 3 // The status of the 3 area power channels
|
||||
equipment = 3 // 0=Off, 1=Auto Off, 2=On, 3=Auto On
|
||||
environ = 3 // When set to "auto", the channel will change between states depending on power conditions
|
||||
|
||||
operating = 1 // True if the APC is turned on (main breaker)
|
||||
charging = 0 // Cell: 0=Not charging 1=Charging, 2=Fully Charged
|
||||
chargemode = 1 // Cell charging mode 0=Off 1=Auto (charge whenever power available)
|
||||
chargecount = 0 // Count used to ensure power status is stable before switching to charging mode
|
||||
|
||||
tdir = null // Direction of APC from terminal
|
||||
obj/machinery/power/terminal/terminal = null // The associated power terminal
|
||||
|
||||
lastused_light = 0 // Last power usage of lighting channel in this area
|
||||
lastused_equip = 0 // Last power usage of equipment channel
|
||||
lastused_environ = 0 // Last power usage of environmental channel
|
||||
lastused_total = 0 // Total last power usage of this area
|
||||
|
||||
main_status = 0 // Main power (powernet) status: 0=Node, 1=Low, 2=Good
|
||||
access = "4000/0002/0030" // ID card access levels needed to lock/unlock interface
|
||||
allowed = "Systems" // ID card job assignment needed to lock/unlock interface
|
||||
|
||||
|
||||
|
||||
// Create an APC
|
||||
|
||||
New()
|
||||
..()
|
||||
|
||||
// offset 24 pixels in direction of dir
|
||||
// this allows the APC to be embedded in a wall, yet still inside an area
|
||||
|
||||
tdir = dir
|
||||
dir = SOUTH // to fix Vars bug
|
||||
|
||||
// Pixel offsets so that APC actually appears embedded in the wall
|
||||
pixel_x = (tdir & 3)? 0 : (tdir == 4 ? 24 : -24)
|
||||
pixel_y = (tdir & 3)? (tdir ==1 ? 24 : -24) : 0
|
||||
|
||||
|
||||
// if starting with a power cell installed, create it and set its charge level
|
||||
if(cell_type)
|
||||
src.cell = new/obj/item/weapon/cell(src)
|
||||
cell.maxcharge = cell_type==1 ? 1000 : 5000 // if type=2, make a hp cell
|
||||
cell.charge = start_charge * cell.maxcharge / 100.0 // (convert percentage to actual value)
|
||||
|
||||
|
||||
var/area/A = src.loc.loc // the area this APC controls
|
||||
|
||||
if(isarea(A))
|
||||
src.area = A
|
||||
|
||||
updateicon()
|
||||
|
||||
// create a terminal object at the same position as original turf loc
|
||||
// wires will attach to this rather than the APC itself
|
||||
|
||||
terminal = new/obj/machinery/power/terminal(src.loc)
|
||||
terminal.dir = tdir
|
||||
terminal.master = src
|
||||
|
||||
spawn(5)
|
||||
update()
|
||||
|
||||
|
||||
// Examine verb
|
||||
|
||||
examine()
|
||||
set src in oview(1)
|
||||
|
||||
if(stat & BROKEN) return
|
||||
|
||||
if(usr && !usr.stat)
|
||||
usr << "A control terminal for the area electrical systems."
|
||||
if(opened)
|
||||
usr << "The cover is open and the power cell is [ cell ? "installed" : "missing"]."
|
||||
else
|
||||
usr << "The cover is closed."
|
||||
|
||||
|
||||
// Update the APC icon to show the three base states (normal, opened with cell, opened without cell)
|
||||
// also add overlays for indicator lights
|
||||
|
||||
proc/updateicon()
|
||||
if(opened)
|
||||
icon_state = "[ cell ? "apc2" : "apc1" ]" // if opened, show cell if it's inserted
|
||||
src.overlays = null // also delete all overlays
|
||||
else
|
||||
icon_state = "apc0"
|
||||
|
||||
// if closed, update overlays for channel status
|
||||
|
||||
src.overlays = null
|
||||
|
||||
overlays += image('power.dmi', "apcox-[locked]") // 0=blue 1=red
|
||||
overlays += image('power.dmi', "apco3-[charging]") // 0=red, 1=yellow/black 2=green
|
||||
|
||||
|
||||
if(operating)
|
||||
overlays += image('power.dmi', "apco0-[equipment]") // 0=red, 1=green, 2=blue
|
||||
overlays += image('power.dmi', "apco1-[lighting]")
|
||||
overlays += image('power.dmi', "apco2-[environ]")
|
||||
|
||||
|
||||
//Attack with an item - open/close cover, insert cell, or (un)lock interface
|
||||
|
||||
attackby(obj/item/weapon/W, mob/user)
|
||||
|
||||
if(stat & BROKEN) return
|
||||
|
||||
if (istype(W, /obj/item/weapon/screwdriver)) // screwdriver means open or close the cover
|
||||
if(opened)
|
||||
opened = 0
|
||||
updateicon()
|
||||
else
|
||||
if(coverlocked)
|
||||
user << "The cover is locked and cannot be opened."
|
||||
else
|
||||
opened = 1
|
||||
updateicon()
|
||||
|
||||
else if (istype(W, /obj/item/weapon/cell) && opened) // trying to put a cell inside
|
||||
if(cell)
|
||||
user << "There is a power cell already installed."
|
||||
else
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
cell = W
|
||||
user << "You insert the power cell."
|
||||
chargecount = 0
|
||||
|
||||
updateicon()
|
||||
else if (istype(W, /obj/item/weapon/card/id) ) // trying to unlock the interface with an ID card
|
||||
|
||||
if(opened)
|
||||
user << "You must close the cover to swipe an ID card."
|
||||
else
|
||||
var/obj/item/weapon/card/id/I = W
|
||||
if (I.check_access(access, allowed))
|
||||
locked = !locked
|
||||
user << "You [ locked ? "lock" : "unlock"] the APC interface."
|
||||
updateicon()
|
||||
else
|
||||
user << "\red Access denied."
|
||||
|
||||
else if (istype(W, /obj/item/weapon/card/emag) ) // trying to unlock with an emag card
|
||||
|
||||
if(opened)
|
||||
user << "You must close the cover to swipe an ID card."
|
||||
else
|
||||
flick("apc-spark", src)
|
||||
sleep(6)
|
||||
if(prob(50))
|
||||
locked = !locked
|
||||
user << "You [ locked ? "lock" : "unlock"] the APC interface."
|
||||
updateicon()
|
||||
else
|
||||
user << "You fail to [ locked ? "unlock" : "lock"] the APC interface."
|
||||
|
||||
|
||||
// Attack with hand - remove cell (if present and cover open) or interact with the APC
|
||||
|
||||
attack_hand(mob/user)
|
||||
|
||||
add_fingerprint(user)
|
||||
|
||||
if(stat & BROKEN) return
|
||||
|
||||
if(opened)
|
||||
if(cell)
|
||||
cell.loc = usr
|
||||
cell.layer = 20
|
||||
if (user.hand )
|
||||
user.l_hand = cell
|
||||
else
|
||||
user.r_hand = cell
|
||||
|
||||
cell.add_fingerprint(user)
|
||||
cell.updateicon()
|
||||
|
||||
src.cell = null
|
||||
user << "You remove the power cell."
|
||||
charging = 0
|
||||
src.updateicon()
|
||||
|
||||
else
|
||||
// do APC interaction
|
||||
src.interact(user)
|
||||
|
||||
|
||||
// Shows APC interaction window
|
||||
|
||||
proc/interact(mob/user)
|
||||
|
||||
if ( (get_dist(src, user) > 1 ))
|
||||
user.machine = null
|
||||
user << browse(null, "window=apc")
|
||||
return
|
||||
|
||||
user.machine = src
|
||||
var/t = "<TT><B>Area Power Controller</B> ([area.name])<HR>"
|
||||
|
||||
if(locked) // If interface is locked, show status only
|
||||
t += "<I>(Swipe ID card to unlock inteface.)</I><BR>"
|
||||
t += "Main breaker : <B>[operating ? "On" : "Off"]</B><BR>"
|
||||
t += "External power : <B>[ main_status ? (main_status ==2 ? "<FONT COLOR=#004000>Good</FONT>" : "<FONT COLOR=#D09000>Low</FONT>") : "<FONT COLOR=#F00000>None</FONT>"]</B><BR>"
|
||||
t += "Power cell: <B>[cell ? "[round(cell.percent())]%" : "<FONT COLOR=red>Not connected.</FONT>"]</B>"
|
||||
if(cell)
|
||||
t += " ([charging ? ( charging == 1 ? "Charging" : "Fully charged" ) : "Not charging"])"
|
||||
t += " ([chargemode ? "Auto" : "Off"])"
|
||||
|
||||
t += "<BR><HR>Power channels<BR><PRE>"
|
||||
|
||||
var/list/L = list ("Off","Off (Auto)", "On", "On (Auto)")
|
||||
|
||||
t += "Equipment: [add_lspace(lastused_equip, 6)] W : <B>[L[equipment+1]]</B><BR>"
|
||||
t += "Lighting: [add_lspace(lastused_light, 6)] W : <B>[L[lighting+1]]</B><BR>"
|
||||
t += "Environmental:[add_lspace(lastused_environ, 6)] W : <B>[L[environ+1]]</B><BR>"
|
||||
|
||||
t += "<BR>Total load: [lastused_light + lastused_equip + lastused_environ] W</PRE>"
|
||||
t += "<HR>Cover lock: <B>[coverlocked ? "Engaged" : "Disengaged"]</B>"
|
||||
|
||||
else // If interface is unlocked, show status and control links
|
||||
t += "<I>(Swipe ID card to lock interface.)</I><BR>"
|
||||
t += "Main breaker: [operating ? "<B>On</B> <A href='?src=\ref[src];breaker=1'>Off</A>" : "<A href='?src=\ref[src];breaker=1'>On</A> <B>Off</B>" ]<BR>"
|
||||
t += "External power : <B>[ main_status ? (main_status ==2 ? "<FONT COLOR=#004000>Good</FONT>" : "<FONT COLOR=#D09000>Low</FONT>") : "<FONT COLOR=#F00000>None</FONT>"]</B><BR>"
|
||||
if(cell)
|
||||
t += "Power cell: <B>[round(cell.percent())]%</B>"
|
||||
t += " ([charging ? ( charging == 1 ? "Charging" : "Fully charged" ) : "Not charging"])"
|
||||
t += " ([chargemode ? "<A href='?src=\ref[src];cmode=1'>Off</A> <B>Auto</B>" : "<B>Off</B> <A href='?src=\ref[src];cmode=1'>Auto</A>"])"
|
||||
|
||||
else
|
||||
t += "Power cell: <B><FONT COLOR=red>Not connected.</FONT></B>"
|
||||
|
||||
t += "<BR><HR>Power channels<BR><PRE>"
|
||||
|
||||
|
||||
t += "Equipment: [add_lspace(lastused_equip, 6)] W : "
|
||||
switch(equipment)
|
||||
if(0)
|
||||
t += "<B>Off</B> <A href='?src=\ref[src];eqp=2'>On</A> <A href='?src=\ref[src];eqp=3'>Auto</A>"
|
||||
if(1)
|
||||
t += "<A href='?src=\ref[src];eqp=1'>Off</A> <A href='?src=\ref[src];eqp=2'>On</A> <B>Auto (Off)</B>"
|
||||
if(2)
|
||||
t += "<A href='?src=\ref[src];eqp=1'>Off</A> <B>On</B> <A href='?src=\ref[src];eqp=3'>Auto</A>"
|
||||
if(3)
|
||||
t += "<A href='?src=\ref[src];eqp=1'>Off</A> <A href='?src=\ref[src];eqp=2'>On</A> <B>Auto (On)</B>"
|
||||
t +="<BR>"
|
||||
|
||||
t += "Lighting: [add_lspace(lastused_light, 6)] W : "
|
||||
|
||||
switch(lighting)
|
||||
if(0)
|
||||
t += "<B>Off</B> <A href='?src=\ref[src];lgt=2'>On</A> <A href='?src=\ref[src];lgt=3'>Auto</A>"
|
||||
if(1)
|
||||
t += "<A href='?src=\ref[src];lgt=1'>Off</A> <A href='?src=\ref[src];lgt=2'>On</A> <B>Auto (Off)</B>"
|
||||
if(2)
|
||||
t += "<A href='?src=\ref[src];lgt=1'>Off</A> <B>On</B> <A href='?src=\ref[src];lgt=3'>Auto</A>"
|
||||
if(3)
|
||||
t += "<A href='?src=\ref[src];lgt=1'>Off</A> <A href='?src=\ref[src];lgt=2'>On</A> <B>Auto (On)</B>"
|
||||
t +="<BR>"
|
||||
|
||||
|
||||
t += "Environmental:[add_lspace(lastused_environ, 6)] W : "
|
||||
switch(environ)
|
||||
if(0)
|
||||
t += "<B>Off</B> <A href='?src=\ref[src];env=2'>On</A> <A href='?src=\ref[src];env=3'>Auto</A>"
|
||||
if(1)
|
||||
t += "<A href='?src=\ref[src];env=1'>Off</A> <A href='?src=\ref[src];env=2'>On</A> <B>Auto (Off)</B>"
|
||||
if(2)
|
||||
t += "<A href='?src=\ref[src];env=1'>Off</A> <B>On</B> <A href='?src=\ref[src];env=3'>Auto</A>"
|
||||
if(3)
|
||||
t += "<A href='?src=\ref[src];env=1'>Off</A> <A href='?src=\ref[src];env=2'>On</A> <B>Auto (On)</B>"
|
||||
|
||||
|
||||
|
||||
t += "<BR>Total load: [lastused_light + lastused_equip + lastused_environ] W</PRE>"
|
||||
t += "<HR>Cover lock: [coverlocked ? "<B><A href='?src=\ref[src];lock=1'>Engaged</A></B>" : "<B><A href='?src=\ref[src];lock=1'>Disengaged</A></B>"]"
|
||||
|
||||
t += "<BR><HR><A href='?src=\ref[src];close=1'>Close</A>"
|
||||
|
||||
t += "</TT>"
|
||||
user << browse(t, "window=apc")
|
||||
return
|
||||
|
||||
|
||||
//Returns a string showing the status of the APC.
|
||||
|
||||
proc/report()
|
||||
return "[area.name] : [equipment]/[lighting]/[environ] ([lastused_equip+lastused_light+lastused_environ]) : [cell? cell.percent() : "N/C"] ([charging])"
|
||||
|
||||
|
||||
|
||||
// Called whenever the status of an APC control changes.
|
||||
// Sets the underlying area power status variables, and informs the area that something has changed.
|
||||
|
||||
proc/update()
|
||||
if(operating)
|
||||
area.power_light = (lighting > 1)
|
||||
area.power_equip = (equipment > 1)
|
||||
area.power_environ = (environ > 1)
|
||||
else
|
||||
area.power_light = 0
|
||||
area.power_equip = 0
|
||||
area.power_environ = 0
|
||||
|
||||
area.power_change()
|
||||
|
||||
|
||||
// Handle topic links from the interaction window
|
||||
|
||||
Topic(href, href_list)
|
||||
|
||||
..()
|
||||
|
||||
if (usr.stat || usr.restrained() )
|
||||
return
|
||||
if ((!( istype(usr, /mob/human) ) && (!( ticker ) || (ticker && ticker.mode != "monkey"))))
|
||||
usr << "\red You don't have the dexterity to do this!"
|
||||
return
|
||||
|
||||
if (( (get_dist(src, usr) <= 1 && istype(src.loc, /turf))))
|
||||
|
||||
usr.machine = src
|
||||
if (href_list["lock"])
|
||||
coverlocked = !coverlocked
|
||||
|
||||
else if (href_list["breaker"])
|
||||
operating = !operating
|
||||
src.update()
|
||||
updateicon()
|
||||
|
||||
else if (href_list["cmode"])
|
||||
chargemode = !chargemode
|
||||
if(!chargemode)
|
||||
charging = 0
|
||||
updateicon()
|
||||
|
||||
else if (href_list["eqp"])
|
||||
var/val = text2num(href_list["eqp"])
|
||||
|
||||
equipment = (val==1) ? 0 : val
|
||||
|
||||
updateicon()
|
||||
update()
|
||||
|
||||
else if (href_list["lgt"])
|
||||
var/val = text2num(href_list["lgt"])
|
||||
|
||||
lighting = (val==1) ? 0 : val
|
||||
|
||||
updateicon()
|
||||
update()
|
||||
else if (href_list["env"])
|
||||
var/val = text2num(href_list["env"])
|
||||
|
||||
environ = (val==1) ? 0 :val
|
||||
|
||||
updateicon()
|
||||
update()
|
||||
else if( href_list["close"] )
|
||||
usr << browse(null, "window=apc")
|
||||
usr.machine = null
|
||||
return
|
||||
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.interact(M)
|
||||
//Foreach goto(275)
|
||||
else
|
||||
usr << browse(null, "window=apc")
|
||||
usr.machine = null
|
||||
|
||||
return
|
||||
|
||||
|
||||
// Helper functions for interfacing to the powernet
|
||||
// Overriden for APC since they connect to the powernet only through the terminal
|
||||
|
||||
// Return the surplus power of the powernet
|
||||
|
||||
surplus()
|
||||
if(terminal)
|
||||
return terminal.surplus()
|
||||
else
|
||||
return 0
|
||||
|
||||
|
||||
// Add a load amount to the powernet
|
||||
|
||||
add_load(var/amount)
|
||||
if(terminal && terminal.powernet)
|
||||
terminal.powernet.newload += amount
|
||||
|
||||
|
||||
// Return the available power (neglecting load) of the powernet
|
||||
|
||||
avail()
|
||||
if(terminal)
|
||||
return terminal.avail()
|
||||
else
|
||||
return 0
|
||||
|
||||
// Constant - amount of power used to charge the power cell
|
||||
|
||||
#define CHARGELEVEL 500
|
||||
|
||||
|
||||
// APC timed process - executed ~once per second
|
||||
// Calculates the channel settings and cell charging status depending on area power usage,
|
||||
// power available from the network, and cell charge level.
|
||||
|
||||
process()
|
||||
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
|
||||
if(!area.requires_power) // set for an area if it never requires power
|
||||
return
|
||||
|
||||
area.calc_lighting() // calculate the power used for lighting an area (by number of turfs)
|
||||
|
||||
// Find the cumulative power usage for the APC's area. Then reset it.
|
||||
|
||||
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
|
||||
|
||||
|
||||
//cache control states so to update icon only if any change during this proc
|
||||
var/last_lt = lighting
|
||||
var/last_eq = equipment
|
||||
var/last_en = environ
|
||||
var/last_ch = charging
|
||||
|
||||
|
||||
var/excess = surplus()
|
||||
|
||||
// Set the external power display depending on the surplus power on the powernet
|
||||
|
||||
if(!src.avail())
|
||||
main_status = 0
|
||||
else if(excess < 0)
|
||||
main_status = 1
|
||||
else
|
||||
main_status = 2
|
||||
|
||||
|
||||
// Perapc is the calculated power surplus evenly divided by every APC in the network. This is used in some
|
||||
// anti-thrashing calculations
|
||||
|
||||
var/perapc = 0
|
||||
if(terminal && terminal.powernet)
|
||||
perapc = terminal.powernet.perapc
|
||||
|
||||
if(cell) // If a power cell is present
|
||||
|
||||
// draw power from cell
|
||||
|
||||
var/cellused = min(cell.charge, CELLRATE * lastused_total) // clamp deduction to a max, amount left in cell
|
||||
|
||||
cell.charge -= cellused // reduce the cell charge level
|
||||
|
||||
|
||||
|
||||
// set channels depending on how much charge we have left
|
||||
|
||||
|
||||
if(cell.charge <= 0) // zero charge, turn all off
|
||||
equipment = autoset(equipment, 2)
|
||||
lighting = autoset(lighting, 2)
|
||||
environ = autoset(environ, 2)
|
||||
else if(cell.percent() < 15) // <15%, turn off lighting & equipment
|
||||
equipment = autoset(equipment, 2)
|
||||
lighting = autoset(lighting, 2)
|
||||
environ = autoset(environ, 1)
|
||||
else if(cell.percent() < 30) // <30%, turn off equipment
|
||||
equipment = autoset(equipment, 2)
|
||||
lighting = autoset(lighting, 1)
|
||||
environ = autoset(environ, 1)
|
||||
else // otherwise all can be on
|
||||
equipment = autoset(equipment, 1)
|
||||
lighting = autoset(lighting, 1)
|
||||
environ = autoset(environ, 1)
|
||||
|
||||
|
||||
if(excess > 0 || perapc > lastused_total) // if power excess, or enough anyway, recharge the cell
|
||||
// by the same amount just used
|
||||
|
||||
cell.charge = min(cell.maxcharge, cell.charge + cellused)
|
||||
|
||||
add_load(cellused/CELLRATE) // add the load used to recharge the cell
|
||||
|
||||
|
||||
else // no excess, and not enough per-apc
|
||||
|
||||
if( (cell.charge/CELLRATE+perapc) >= lastused_total) // can we draw enough from cell+grid to cover last usage?
|
||||
|
||||
cell.charge = min(cell.maxcharge, cell.charge + CELLRATE * perapc) //recharge with what we can
|
||||
|
||||
add_load(perapc) // so draw what we can from the grid
|
||||
charging = 0
|
||||
|
||||
else // not enough!
|
||||
charging = 0 // kill everything
|
||||
chargecount = 0
|
||||
equipment = autoset(equipment, 0)
|
||||
lighting = autoset(lighting, 0)
|
||||
environ = autoset(environ, 0)
|
||||
|
||||
|
||||
|
||||
// now trickle-charge the cell
|
||||
|
||||
|
||||
if(chargemode && charging == 1)
|
||||
if(excess > 0) // check to make sure we have enough to charge
|
||||
|
||||
var/ch = min(CHARGELEVEL, (cell.maxcharge - cell.charge)/CELLRATE ) // clamp charging to max free in cell
|
||||
|
||||
ch = min(ch, perapc) // clamp charging to our share
|
||||
|
||||
add_load(CHARGELEVEL)
|
||||
|
||||
cell.charge += 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)
|
||||
charging = 2
|
||||
|
||||
// switch between charging and not depending on stability of external power
|
||||
|
||||
if(chargemode)
|
||||
if(!charging)
|
||||
if(excess > CHARGELEVEL)
|
||||
chargecount++
|
||||
else
|
||||
chargecount = 0
|
||||
|
||||
|
||||
if(chargecount == 5) // right amount of excess power must be available for 5 second before switching to charge
|
||||
|
||||
chargecount = 0
|
||||
charging = 1
|
||||
|
||||
else // chargemode off
|
||||
charging = 0
|
||||
chargecount = 0
|
||||
|
||||
|
||||
|
||||
|
||||
else
|
||||
// no cell
|
||||
|
||||
// for now, switch everything off
|
||||
|
||||
// TODO: Something more logical here, depending on excess external power
|
||||
|
||||
charging = 0
|
||||
chargecount = 0
|
||||
equipment = autoset(equipment, 0)
|
||||
lighting = autoset(lighting, 0)
|
||||
environ = autoset(environ, 0)
|
||||
|
||||
|
||||
|
||||
// update icon & area power only if anything changed
|
||||
|
||||
if(last_lt != lighting || last_eq != equipment || last_en != environ || last_ch != charging)
|
||||
updateicon()
|
||||
update()
|
||||
|
||||
// update any player looking at the interaction window
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.interact(M)
|
||||
|
||||
|
||||
// If APC hit by a meteor, break it
|
||||
|
||||
meteorhit(var/obj/O)
|
||||
set_broken()
|
||||
return
|
||||
|
||||
// APC in explosion, chance to break depending on the severity
|
||||
|
||||
ex_act(severity)
|
||||
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
set_broken()
|
||||
del(src)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
set_broken()
|
||||
if(3.0)
|
||||
if (prob(25))
|
||||
set_broken()
|
||||
else
|
||||
return
|
||||
|
||||
// Blob attack
|
||||
|
||||
blob_act()
|
||||
if (prob(50))
|
||||
set_broken()
|
||||
|
||||
|
||||
// Called to set the APC into a broken state.
|
||||
// Set Stat and broken icon_state, inform area to turn everything off.
|
||||
// Can't (yet) be fixed again.
|
||||
|
||||
proc/set_broken()
|
||||
stat |= BROKEN
|
||||
icon_state = "apc-b"
|
||||
overlays = null
|
||||
|
||||
operating = 0
|
||||
update()
|
||||
|
||||
|
||||
// Global helper proc, used only in apc/process()
|
||||
// returns the new state of a channel control, given the current settings
|
||||
// This is so a channel can switch between AutoOn and AutoOff depending on available power levels
|
||||
// But a channel set to On will stay on until power is zero, when it will switch to Off and stay there
|
||||
|
||||
// val 0=off, 1=off(auto) 2=on 3=on(auto)
|
||||
// on 0=off, 1=on, 2=autooff
|
||||
|
||||
/proc/autoset(var/val, var/on)
|
||||
|
||||
if(on==0)
|
||||
if(val==2) // if on, return off
|
||||
return 0
|
||||
else if(val==3) // if auto-on, return auto-off
|
||||
return 1
|
||||
|
||||
else if(on==1)
|
||||
if(val==1) // if auto-off, return auto-on
|
||||
return 3
|
||||
|
||||
else if(on==2)
|
||||
if(val==3) // if auto-on, return auto-off
|
||||
return 1
|
||||
|
||||
return val
|
||||
|
||||
|
||||
@@ -0,0 +1,107 @@
|
||||
/*
|
||||
* Power Monitor - reports the available power, load, and status of APCs on the same power network.
|
||||
*
|
||||
* TODO: Make the power monitor also able to remote-control APCs (with sufficient ID access) to shut down things remotely.
|
||||
*/
|
||||
|
||||
obj/machinery/power/monitor
|
||||
name = "power monitoring computer"
|
||||
icon = 'stationobjs.dmi'
|
||||
icon_state = "power_computer"
|
||||
density = 1
|
||||
anchored = 1
|
||||
|
||||
|
||||
// Attack with hand, show report window
|
||||
|
||||
attack_hand(mob/user)
|
||||
add_fingerprint(user)
|
||||
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
interact(user)
|
||||
|
||||
|
||||
// Show the interaction window to the user
|
||||
|
||||
proc/interact(mob/user)
|
||||
|
||||
if ( (get_dist(src, user) > 1 ) || (stat & (BROKEN|NOPOWER)) )
|
||||
user.machine = null
|
||||
user << browse(null, "window=powcomp")
|
||||
return
|
||||
|
||||
|
||||
user.machine = src
|
||||
var/t = "<TT><B>Power Monitoring</B><HR>"
|
||||
|
||||
|
||||
if(!powernet)
|
||||
t += "\red No connection"
|
||||
else
|
||||
|
||||
var/list/L = list()
|
||||
for(var/obj/machinery/power/terminal/term in powernet.nodes)
|
||||
if(istype(term.master, /obj/machinery/power/apc))
|
||||
var/obj/machinery/power/apc/A = term.master
|
||||
L += A
|
||||
|
||||
t += "<PRE>Total power: [powernet.avail] W<BR>Total load: [num2text(powernet.viewload,10)] W<BR>"
|
||||
|
||||
t += "<FONT SIZE=-1>"
|
||||
|
||||
if(L.len > 0)
|
||||
|
||||
t += "Area Eqp./Lgt./Env. Load Cell<HR>"
|
||||
|
||||
var/list/S = list(" Off","AOff"," On", " AOn")
|
||||
var/list/chg = list("N","C","F")
|
||||
|
||||
for(var/obj/machinery/power/apc/A in L)
|
||||
|
||||
t += copytext(add_tspace(A.area.name, 30), 1, 30)
|
||||
t += " [S[A.equipment+1]] [S[A.lighting+1]] [S[A.environ+1]] [add_lspace(A.lastused_total, 6)] [A.cell ? "[add_lspace(round(A.cell.percent()), 3)]% [chg[A.charging+1]]" : " N/C"]<BR>"
|
||||
|
||||
t += "</FONT></PRE>"
|
||||
|
||||
t += "<BR><HR><A href='?src=\ref[src];close=1'>Close</A></TT>"
|
||||
|
||||
user << browse(t, "window=powcomp;size=420x700")
|
||||
|
||||
|
||||
// Handle topic links from the interaction window (close only at the moment)
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
if( href_list["close"] )
|
||||
usr << browse(null, "window=powcomp")
|
||||
usr.machine = null
|
||||
return
|
||||
|
||||
// Timed process - use power, update window to viewers
|
||||
|
||||
process()
|
||||
if(!(stat & (NOPOWER|BROKEN)) )
|
||||
|
||||
use_power(250)
|
||||
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.interact(M)
|
||||
|
||||
|
||||
// Power changed in location area - update icon to unpowered state, set stat
|
||||
|
||||
power_change()
|
||||
|
||||
if(stat & BROKEN)
|
||||
icon_state = "broken"
|
||||
else
|
||||
if( powered() )
|
||||
icon_state = initial(icon_state)
|
||||
stat &= ~NOPOWER
|
||||
else
|
||||
spawn(rand(0, 15))
|
||||
src.icon_state = "c_unpowered"
|
||||
stat |= NOPOWER
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Solar -- Solar panel power generator machine.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
#define SOLARGENRATE 1500 // maximum power output of a single panel when it is facing exactly towards the sun
|
||||
|
||||
obj/machinery/power/solar
|
||||
name = "solar panel"
|
||||
desc = "A solar electrical generator."
|
||||
icon = 'power.dmi'
|
||||
icon_state = "sp_base"
|
||||
anchored = 1
|
||||
density = 1
|
||||
directwired = 1
|
||||
var
|
||||
id = 1 // solar_control must have matching id (and be on same powernet) to control this machine
|
||||
obscured = 0 // true if the panel is in shadow (thus does not generate power)
|
||||
sunfrac = 0 // fraction (0.0-1.0) of the maximum exposure of the solar panel to the sun
|
||||
// calculated from the relative angle of the sun and the panel
|
||||
adir = SOUTH // the current direction of the solar panel
|
||||
ndir = SOUTH // the new set direction of the panel
|
||||
turn_angle = 0 // the angle to turn through to get to the set angle; -45 or +45
|
||||
obj/machinery/power/solar_control/control // the controller for this panel
|
||||
|
||||
|
||||
// Create a new solar panel
|
||||
// Search the connected powernet for a solar_control with matching ID; if found, set as the controller
|
||||
|
||||
New()
|
||||
..()
|
||||
spawn(10) // wait until sure powernets have been built
|
||||
updateicon()
|
||||
updatefrac()
|
||||
|
||||
if(powernet)
|
||||
for(var/obj/machinery/power/solar_control/SC in powernet.nodes)
|
||||
if(SC.id == id)
|
||||
control = SC
|
||||
|
||||
|
||||
// Updates the icon for the solar panel
|
||||
// The object icon is just the base, with the panel itself being an 8-direction overlay
|
||||
|
||||
proc/updateicon()
|
||||
src.overlays = null
|
||||
if(stat & BROKEN)
|
||||
overlays += image('power.dmi', "solar_panel-b", FLY_LAYER)
|
||||
else
|
||||
overlays += image('power.dmi', "solar_panel", FLY_LAYER, adir)
|
||||
|
||||
|
||||
// Calculate the fraction of power produced by the panel
|
||||
// Depends if the panel is obscured by shadow, and the relative angle of the panel and the sun
|
||||
// The global /datum/sun/sun holds the current sun position
|
||||
|
||||
proc/updatefrac()
|
||||
|
||||
if(obscured)
|
||||
sunfrac = 0
|
||||
return
|
||||
|
||||
var/p_angle = dir2angle(adir) - sun.angle
|
||||
|
||||
if(abs(p_angle) > 90) // if facing more than 90deg from sun, zero output
|
||||
sunfrac = 0
|
||||
return
|
||||
|
||||
sunfrac = cos(p_angle)*cos(p_angle) // this is the fraction of the panel area which subtends the sun's output
|
||||
|
||||
|
||||
// Timed process. Generate power (if in sunlight), and turn the current panel angle if it is not at the set angle
|
||||
|
||||
process()
|
||||
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
|
||||
if(!obscured)
|
||||
var/sgen = SOLARGENRATE * sunfrac
|
||||
add_avail(sgen)
|
||||
if(powernet && control)
|
||||
if(control in powernet.nodes)
|
||||
control.gen += sgen // notify the controller of how much was generated
|
||||
|
||||
|
||||
if(adir == ndir) // if current angle == set angle, stop turning
|
||||
turn_angle = 0
|
||||
else // otherwise turn
|
||||
spawn(rand(0,10)) // slight random delay is to stop all panels turning in lockstep
|
||||
adir = turn(adir, turn_angle)
|
||||
updateicon()
|
||||
updatefrac() // update the panel icon and the fractional power production for the new angle
|
||||
|
||||
|
||||
// Makes the panel broken and updates the icon to the broken state
|
||||
// No way to fix panels (yet)
|
||||
|
||||
proc/broken()
|
||||
stat |= BROKEN
|
||||
updateicon()
|
||||
|
||||
|
||||
// When hit by a meteor, break
|
||||
|
||||
meteorhit()
|
||||
broken()
|
||||
|
||||
|
||||
// In an explosion, totally destroyed or a chance of breaking, depending on severity
|
||||
|
||||
ex_act(severity)
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
//SN src = null
|
||||
del(src)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
broken()
|
||||
if(3.0)
|
||||
if (prob(25))
|
||||
broken()
|
||||
return
|
||||
|
||||
|
||||
// Blob attack
|
||||
|
||||
blob_act()
|
||||
if (prob(50))
|
||||
broken()
|
||||
src.density = 0
|
||||
@@ -0,0 +1,288 @@
|
||||
/*
|
||||
* Solar_control -- A machine that controls solar panels (/obj/machinery/power/solar)
|
||||
*
|
||||
* The controller must be on the same powernet and have the same id value as the solar panel
|
||||
*/
|
||||
|
||||
|
||||
obj/machinery/power/solar_control
|
||||
name = "solar panel control"
|
||||
desc = "A controller for solar panel arrays."
|
||||
icon = 'enginecomputer.dmi'
|
||||
icon_state = "solar_con"
|
||||
anchored = 1
|
||||
density = 1
|
||||
directwired = 1
|
||||
var
|
||||
id = 1 // must match that of the solar panels to control
|
||||
cdir = 0 // the current direction of the controlled solar panels
|
||||
gen = 0 // the current power generation by the controlled panels
|
||||
lastgen = 0 // the last power generation value from the previous cycle
|
||||
track = 0 // direction tracking on/off
|
||||
trackrate = 600 // time between tracking turns, 300-900 seconds
|
||||
trackdir = 1 // direction to turn when tracking, 0 =CCW, 1=CW
|
||||
nexttime = 0 // timeofday until next tracking turn
|
||||
|
||||
|
||||
// Create a new solar controller.
|
||||
|
||||
New()
|
||||
..()
|
||||
|
||||
spawn(15) // wait for powernets to be built after map load
|
||||
|
||||
if(powernet)
|
||||
for(var/obj/machinery/power/solar/S in powernet.nodes)
|
||||
if(S.id == id)
|
||||
cdir = S.adir // find the contorlled solar panels and set the current direction to match
|
||||
updateicon() // also update the icon overlay
|
||||
|
||||
|
||||
// Update the icon_state
|
||||
// If broken or unpowered, set those states
|
||||
// Otherwise, add an overlay showing the current panel direction
|
||||
|
||||
proc/updateicon()
|
||||
if(stat & BROKEN)
|
||||
icon_state = "broken"
|
||||
overlays = null
|
||||
return
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "c_unpowered"
|
||||
overlays = null
|
||||
return
|
||||
|
||||
icon_state = "solar_con"
|
||||
overlays = null
|
||||
if(cdir > 0)
|
||||
overlays += image('enginecomputer.dmi', "solcon-o", FLY_LAYER, cdir)
|
||||
|
||||
|
||||
|
||||
// Attack by hand, open interaction window
|
||||
|
||||
attack_hand(mob/user)
|
||||
add_fingerprint(user)
|
||||
|
||||
if(stat & (BROKEN | NOPOWER)) return
|
||||
|
||||
interact(user)
|
||||
|
||||
|
||||
// Timed process
|
||||
// Update lastgen so it has the value of total power generated by panels last cycle
|
||||
// Reset the current generation value to zero (to be added to in each /solar/process() proc)
|
||||
// If tracking, rotate the panels if next tracking turn timer has expired
|
||||
|
||||
process()
|
||||
lastgen = gen
|
||||
gen = 0
|
||||
|
||||
if(stat & (NOPOWER | BROKEN))
|
||||
return
|
||||
|
||||
use_power(250)
|
||||
|
||||
if(track && nexttime < world.timeofday)
|
||||
if(trackdir)
|
||||
cdir = turn(cdir, -45)
|
||||
else
|
||||
cdir = turn(cdir, 45)
|
||||
set_panels(cdir)
|
||||
|
||||
nexttime = world.timeofday + 10*trackrate
|
||||
updateicon()
|
||||
|
||||
|
||||
// Update all players view interaction window
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.interact(M)
|
||||
|
||||
|
||||
// Display the interaction window
|
||||
|
||||
proc/interact(mob/user)
|
||||
|
||||
if ( (get_dist(src, user) > 1 ))
|
||||
user.machine = null
|
||||
user << browse(null, "window=solcon")
|
||||
return
|
||||
|
||||
user.machine = src
|
||||
|
||||
var/t = "<TT><B>Solar Generator Control</B><HR><PRE>"
|
||||
|
||||
t += "Generated power : [round(lastgen)] W<BR><BR>"
|
||||
|
||||
t += "Current panel orientation: <B>[uppertext(dir2text(cdir))]</B><BR>"
|
||||
|
||||
t += "<HR>Set orientation:<BR>"
|
||||
|
||||
var/list/D = list(-1, NORTHWEST, NORTH, NORTHEAST, -1, WEST, 0, EAST, -1, SOUTHWEST, SOUTH, SOUTHEAST)
|
||||
var/list/disp = list("|", "|", "", "-", "/", "\\", "", "-", "\\", "/")
|
||||
|
||||
for(var/d in D)
|
||||
if(d == 0)
|
||||
t += " "
|
||||
continue
|
||||
if(d == -1)
|
||||
t += "<BR> "
|
||||
continue
|
||||
|
||||
if(d==cdir)
|
||||
t +=" [disp[d]]"
|
||||
else
|
||||
t +=" <A href='?src=\ref[src];dir=[d]'>O</A>"
|
||||
|
||||
|
||||
t += "<HR><BR><BR>"
|
||||
|
||||
t += "Tracking: [ track ? "<A href='?src=\ref[src];track=1'>Off</A> <B>On</B>" : "<B>Off</B> <A href='?src=\ref[src];track=1'>On</A>"]"
|
||||
|
||||
t += " [trackdir ? "<A href='?src=\ref[src];tdir=1'>CCW</A> <B>CW</B>" : "<B>CCW</B> <A href='?src=\ref[src];tdir=1'>CW</A>"]<BR>"
|
||||
|
||||
t += "Rate: <A href='?src=\ref[src];trk=-3'>-</A> <A href='?src=\ref[src];trk=-2'>-</A> <A href='?src=\ref[src];trk=-1'>-</A> [trackrate] <A href='?src=\ref[src];trk=1'>+</A> <A href='?src=\ref[src];trk=2'>+</A> <A href='?src=\ref[src];trk=3'>+</A> (seconds per turn)<BR>"
|
||||
|
||||
t += "</PRE><HR><A href='?src=\ref[src];close=1'>Close</A>"
|
||||
|
||||
t += "</TT>"
|
||||
user << browse(t, "window=solcon")
|
||||
|
||||
return
|
||||
|
||||
|
||||
// Handle topic links from the interaction window
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
|
||||
if (usr.stat || usr.restrained() )
|
||||
return
|
||||
if ((!( istype(usr, /mob/human) ) && (!( ticker ) || (ticker && ticker.mode != "monkey"))))
|
||||
usr << "\red You don't have the dexterity to do this!"
|
||||
return
|
||||
|
||||
//world << "[href] ; [href_list[href]]"
|
||||
|
||||
if (( usr.machine==src && (get_dist(src, usr) <= 1 && istype(src.loc, /turf))))
|
||||
|
||||
|
||||
if( href_list["close"] )
|
||||
usr << browse(null, "window=solcon")
|
||||
usr.machine = null
|
||||
return
|
||||
|
||||
else if( href_list["dir"] )
|
||||
cdir = text2num(href_list["dir"])
|
||||
|
||||
spawn(1)
|
||||
set_panels(cdir)
|
||||
|
||||
updateicon()
|
||||
else if( href_list["tdir"] )
|
||||
trackdir = !trackdir
|
||||
|
||||
else if( href_list["track"] )
|
||||
track = !track
|
||||
nexttime = world.timeofday + 10*trackrate
|
||||
|
||||
else if( href_list["trk"] )
|
||||
var/inc = text2num(href_list["trk"])
|
||||
|
||||
switch(inc)
|
||||
if(1, -1)
|
||||
trackrate += inc
|
||||
if(2,-2)
|
||||
trackrate += 10*inc/abs(inc)
|
||||
if(3,-3)
|
||||
trackrate += 100*inc/abs(inc)
|
||||
|
||||
trackrate = min( max(trackrate, 10), 900)
|
||||
nexttime = world.timeofday + 10*trackrate
|
||||
|
||||
spawn(0)
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.interact(M)
|
||||
|
||||
else
|
||||
usr << browse(null, "window=solcon")
|
||||
usr.machine = null
|
||||
|
||||
return
|
||||
|
||||
|
||||
// Set a new set direction for all panels controlled by this controller
|
||||
|
||||
proc/set_panels(var/cdir)
|
||||
if(powernet)
|
||||
for(var/obj/machinery/power/solar/S in powernet.nodes)
|
||||
if(S.id == id)
|
||||
S.control = src
|
||||
|
||||
var/delta = dir2angle(S.adir) - dir2angle(cdir)
|
||||
|
||||
delta = (delta+360)%360
|
||||
|
||||
if(delta>180)
|
||||
S.turn_angle = -45
|
||||
else
|
||||
S.turn_angle = 45
|
||||
|
||||
S.ndir = cdir
|
||||
|
||||
|
||||
// Called when area power changes; update icons and stat to reflect state of equipment channel power
|
||||
|
||||
power_change()
|
||||
|
||||
if( powered() )
|
||||
stat &= ~NOPOWER
|
||||
updateicon()
|
||||
else
|
||||
spawn(rand(0, 15))
|
||||
stat |= NOPOWER
|
||||
updateicon()
|
||||
|
||||
|
||||
// Set the solar_control as broken
|
||||
|
||||
proc/broken()
|
||||
stat |= BROKEN
|
||||
updateicon()
|
||||
|
||||
|
||||
// If hit by a meteor, break
|
||||
|
||||
meteorhit()
|
||||
|
||||
broken()
|
||||
return
|
||||
|
||||
|
||||
// If in an explosion, delete or chance to break depending on severity
|
||||
|
||||
ex_act(severity)
|
||||
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
//SN src = null
|
||||
del(src)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
broken()
|
||||
if(3.0)
|
||||
if (prob(25))
|
||||
broken()
|
||||
return
|
||||
|
||||
// Attack by blob, chance to break
|
||||
|
||||
blob_act()
|
||||
if (prob(50))
|
||||
broken()
|
||||
src.density = 0
|
||||
|
||||
@@ -0,0 +1,45 @@
|
||||
/*
|
||||
* Terminal -- A wiring terminal power machine.
|
||||
*
|
||||
* A terminal does not do anything of itself. It is used to connect powernets to other power machines,
|
||||
* either for those where direct connection is undesirable (APCs)
|
||||
* or for those that need to be connected to two separate powernets (SMESes).
|
||||
*
|
||||
*/
|
||||
|
||||
obj/machinery/power/terminal
|
||||
name = "terminal"
|
||||
icon_state = "term"
|
||||
desc = "An underfloor wiring terminal for power equipment"
|
||||
level = 1 // the terminal is always underfloor (level=1)
|
||||
anchored = 1
|
||||
directwired = 0 // must have a cable on same turf connecting to terminal
|
||||
|
||||
var
|
||||
obj/machinery/power/master = null // the master power machine this terminal connects to
|
||||
|
||||
|
||||
// Create a new terminal. The terminal is underfloor (level=1), so hide it if the floor is intact.
|
||||
|
||||
// Note: terminals are auto-created when APCs are spawned
|
||||
// All cable connections go to this object instead of the APC
|
||||
// This solves the problem of having the APC in a wall yet also inside an area
|
||||
|
||||
New()
|
||||
..()
|
||||
var/turf/T = src.loc
|
||||
if(level==1) hide(T.intact)
|
||||
|
||||
|
||||
// Hide the terminal if "i" is true.
|
||||
// Sets the terminal icon to invisible and to a faded icon_state
|
||||
// This is done so T-scanners need only changes the invisibility setting to reveal a faded terminal icon
|
||||
|
||||
hide(var/i)
|
||||
|
||||
if(i)
|
||||
invisibility = 101
|
||||
icon_state = "term-f"
|
||||
else
|
||||
invisibility = 0
|
||||
icon_state = "term"
|
||||
File diff suppressed because it is too large
Load Diff
@@ -4,8 +4,8 @@
|
||||
|
||||
// BEGIN_INTERNALS
|
||||
/*
|
||||
FILE: Code\newobjects.dm
|
||||
DIR: Code Code\Machinery Code\Machinery\Atmoalter
|
||||
FILE: Code\!atoms.dm
|
||||
DIR: Code Code\Machinery\Atmoalter Code\Machinery\Power
|
||||
MAP_ICON_TYPE: 0
|
||||
AUTO_FILE_DIR: ON
|
||||
*/
|
||||
@@ -15,6 +15,7 @@ AUTO_FILE_DIR: ON
|
||||
#define FILE_DIR "Code"
|
||||
#define FILE_DIR "Code/Machinery"
|
||||
#define FILE_DIR "Code/Machinery/Atmoalter"
|
||||
#define FILE_DIR "Code/Machinery/Power"
|
||||
#define FILE_DIR "Icons"
|
||||
#define FILE_DIR "Interface"
|
||||
// END_FILE_DIR
|
||||
@@ -91,5 +92,11 @@ AUTO_FILE_DIR: ON
|
||||
#include "Code\Machinery\Atmoalter\canister.dm"
|
||||
#include "Code\Machinery\Atmoalter\heater.dm"
|
||||
#include "Code\Machinery\Atmoalter\siphs.dm"
|
||||
#include "Code\Machinery\Power\_power.dm"
|
||||
#include "Code\Machinery\Power\apc.dm"
|
||||
#include "Code\Machinery\Power\monitor.dm"
|
||||
#include "Code\Machinery\Power\solar.dm"
|
||||
#include "Code\Machinery\Power\solar_control.dm"
|
||||
#include "Code\Machinery\Power\terminal.dm"
|
||||
// END_INCLUDE
|
||||
|
||||
|
||||
Reference in New Issue
Block a user