mirror of
https://github.com/cybergirlvannie/OpenSS13.git
synced 2026-07-19 19:52:51 +01:00
Added new trunk.
This commit is contained in:
+2765
File diff suppressed because one or more lines are too long
@@ -0,0 +1,23 @@
|
||||
/*
|
||||
* Atmoalter - base machine type for gas canisters, siphons, scrubbers, air regulator and filters, and heaters
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
obj/machinery/atmoalter
|
||||
|
||||
var
|
||||
obj/substance/gas/gas = null // the gas contents of the machine
|
||||
maximum // the maximum capacity of the gas
|
||||
|
||||
t_status // main valve status 1 = release, 2= siphon, 3 = stop, 4 = automatic
|
||||
t_per // main valve rate
|
||||
|
||||
c_per // pipe valve rate
|
||||
c_status // pipe vale status 0 = disconnected, 1 = release, 2 = accept, 3 = stop
|
||||
|
||||
obj/item/weapon/tank/holding // the tank item being held (or null)
|
||||
|
||||
max_valve = 1e6 // the maximum setting of both valves
|
||||
@@ -0,0 +1,440 @@
|
||||
/*
|
||||
* Canister - base gas canister object. Actual placed canister will be one of 6 types defined below
|
||||
*
|
||||
* Can release gas into atmosphere, fill or siphon gas from an attached tank,
|
||||
* or release or accept gas from an attached pipe connector.
|
||||
*
|
||||
*/
|
||||
|
||||
obj/machinery/atmoalter/canister
|
||||
name = "canister"
|
||||
icon = 'canister.dmi'
|
||||
density = 1
|
||||
|
||||
// from atmoalter
|
||||
maximum = 1.3E8
|
||||
t_status = 3.0
|
||||
t_per = 50.0
|
||||
c_per = 50.0
|
||||
c_status = 0.0
|
||||
holding = null
|
||||
|
||||
flags = FPRINT|DRIVABLE
|
||||
weight = 1.0E7
|
||||
|
||||
var
|
||||
color = "blue" // used to set icon_state
|
||||
health = 20.0 // health removed by attacks & fire
|
||||
destroyed = null // true if the canister has broken
|
||||
filled = 1.0 //fractional fullness at spawn 0=empty, 1=full
|
||||
|
||||
|
||||
// Create a new canister. This is called by all canister types
|
||||
// Create the gas contents object and set the maximum capacity
|
||||
|
||||
New()
|
||||
..()
|
||||
src.gas = new /obj/substance/gas( src )
|
||||
src.gas.maximum = src.maximum
|
||||
return
|
||||
|
||||
|
||||
// Update the icon state and overlays to reflect canister type and fullness
|
||||
|
||||
proc/update_icon()
|
||||
|
||||
var/air_in = src.gas.tot_gas() // the amount of gas in the canister
|
||||
|
||||
src.overlays = 0
|
||||
|
||||
if (destroyed)
|
||||
icon_state = "[color]-1"
|
||||
|
||||
else
|
||||
icon_state = "[color]"
|
||||
if(holding)
|
||||
overlays += image('canister.dmi', "can-oT")
|
||||
|
||||
if (air_in < 10)
|
||||
overlays += image('canister.dmi', "can-o0")
|
||||
else if (air_in < (src.gas.maximum * 0.2))
|
||||
overlays += image('canister.dmi', "can-o1")
|
||||
else if (air_in < (src.maximum * 0.6))
|
||||
overlays += image('canister.dmi', "can-o2")
|
||||
else
|
||||
overlays += image('canister.dmi', "can-o3")
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
// Timed process. Depending on valve state, release or accept gas
|
||||
|
||||
process()
|
||||
|
||||
if (src.destroyed)
|
||||
return
|
||||
var/T = src.loc
|
||||
if (istype(T, /turf))
|
||||
if (locate(/obj/move, T))
|
||||
T = locate(/obj/move, T)
|
||||
else
|
||||
T = null
|
||||
switch(src.t_status)
|
||||
if(1.0) // Valve set to release
|
||||
if (src.holding) // If holding a tank, release the gas into that tank
|
||||
var/t1 = src.gas.tot_gas()
|
||||
var/t2 = t1
|
||||
var/t = src.t_per
|
||||
if (src.t_per > t2)
|
||||
t = t2
|
||||
src.holding.gas.transfer_from(src.gas, t)
|
||||
else // If not holding a tank, release gas into the turf
|
||||
if (T)
|
||||
var/t1 = src.gas.tot_gas()
|
||||
var/t2 = t1
|
||||
var/t = src.t_per
|
||||
if (src.t_per > t2)
|
||||
t = t2
|
||||
src.gas.turf_add(T, t)
|
||||
src.update_icon()
|
||||
if(2.0) // Valve set to accept
|
||||
if (src.holding) // Siphon gas from the tank into the canister
|
||||
var/t1 = src.gas.tot_gas()
|
||||
var/t2 = src.maximum - t1
|
||||
var/t = src.t_per
|
||||
if (src.t_per > t2)
|
||||
t = t2
|
||||
src.gas.transfer_from(src.holding.gas, t)
|
||||
else // If no tank, do nothing
|
||||
src.t_status = 3
|
||||
src.update_icon()
|
||||
|
||||
|
||||
// Transfer for pipe valve is handled by /obj/machinery/connector process() proc
|
||||
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
src.update_icon()
|
||||
return
|
||||
|
||||
|
||||
//Returns the gas contents object
|
||||
|
||||
get_gas()
|
||||
return gas
|
||||
|
||||
|
||||
// Called when the turf location is burning
|
||||
// Reduce health, then check if destroyed
|
||||
|
||||
burn(fi_amount)
|
||||
src.health -= 1
|
||||
healthcheck()
|
||||
return
|
||||
|
||||
|
||||
// Called when attacked by a blob
|
||||
// Reduce health, then check if destroyed
|
||||
|
||||
blob_act()
|
||||
src.health -= 1
|
||||
healthcheck()
|
||||
return
|
||||
|
||||
// Called when hit by a meteor
|
||||
// Destroy the canister
|
||||
|
||||
meteorhit(var/obj/O)
|
||||
src.health = 0
|
||||
healthcheck()
|
||||
return
|
||||
|
||||
|
||||
// Called when hit by a projectile
|
||||
|
||||
las_act(flag)
|
||||
|
||||
if (flag == "bullet")
|
||||
src.health = 0
|
||||
spawn( 0 )
|
||||
healthcheck()
|
||||
return
|
||||
if (flag)
|
||||
var/turf/T = src.loc
|
||||
if (!( istype(T, /turf) ))
|
||||
return
|
||||
else
|
||||
T.firelevel = T.poison
|
||||
else
|
||||
src.health = 0
|
||||
spawn( 0 )
|
||||
healthcheck()
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
|
||||
// If the canister is damaged enough, destroy it and release all gas contained
|
||||
|
||||
proc/healthcheck()
|
||||
|
||||
if (src.health <= 10)
|
||||
var/T = src.loc
|
||||
if (!( istype(T, /turf) ))
|
||||
return
|
||||
src.gas.turf_add(T, -1.0)
|
||||
src.destroyed = 1
|
||||
src.density = 0
|
||||
update_icon()
|
||||
if (src.holding)
|
||||
src.holding.loc = src.loc
|
||||
src.holding = null
|
||||
if (src.t_status == 2)
|
||||
src.t_status = 3
|
||||
return
|
||||
|
||||
|
||||
// Monkey interact same as human
|
||||
|
||||
attack_paw(var/mob/user)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// Interact with canister, shows interaction window
|
||||
|
||||
attack_hand(var/mob/user)
|
||||
|
||||
if (src.destroyed)
|
||||
return
|
||||
user.machine = src
|
||||
var/tt
|
||||
switch(src.t_status) // Main valve
|
||||
if(1.0)
|
||||
tt = "Releasing <A href='?src=\ref[src];t=2'>Siphon (only tank)</A> <A href='?src=\ref[src];t=3'>Stop</A>"
|
||||
if(2.0)
|
||||
tt = "<A href='?src=\ref[src];t=1'>Release</A> Siphoning (only tank) <A href='?src=\ref[src];t=3'>Stop</A>"
|
||||
if(3.0)
|
||||
tt = "<A href='?src=\ref[src];t=1'>Release</A> <A href='?src=\ref[src];t=2'>Siphon (only tank)</A> Stopped"
|
||||
else
|
||||
var/ct = null
|
||||
switch(src.c_status) // Pipe valve
|
||||
if(1.0)
|
||||
ct = "Releasing <A href='?src=\ref[src];c=2'>Accept</A> <A href='?src=\ref[src];c=3'>Stop</A>"
|
||||
if(2.0)
|
||||
ct = "<A href='?src=\ref[src];c=1'>Release</A> Accepting <A href='?src=\ref[src];c=3'>Stop</A>"
|
||||
if(3.0)
|
||||
ct = "<A href='?src=\ref[src];c=1'>Release</A> <A href='?src=\ref[src];c=2'>Accept</A> Stopped"
|
||||
else
|
||||
ct = "Disconnected"
|
||||
|
||||
|
||||
var/dat = {"<TT><B>Canister Valves</B><BR>
|
||||
<FONT color = 'blue'><B>Contains/Capacity</B> [num2text(src.gas.tot_gas(), 20)] / [num2text(src.maximum, 20)]</FONT><BR>
|
||||
Upper Valve Status: [tt]<BR>
|
||||
\t[(src.holding ? "<A href='?src=\ref[src];tank=1'>Tank ([src.holding.gas.tot_gas()]</A>)" : null)]<BR>
|
||||
\t<A href='?src=\ref[src];tp=-[num2text(1000000.0, 7)]'>M</A> <A href='?src=\ref[src];tp=-10000'>-</A> <A href='?src=\ref[src];tp=-1000'>-</A> <A href='?src=\ref[src];tp=-100'>-</A> <A href='?src=\ref[src];tp=-1'>-</A> [src.t_per] <A href='?src=\ref[src];tp=1'>+</A> <A href='?src=\ref[src];tp=100'>+</A> <A href='?src=\ref[src];tp=1000'>+</A> <A href='?src=\ref[src];tp=10000'>+</A> <A href='?src=\ref[src];tp=[num2text(1000000.0, 7)]'>M</A><BR>
|
||||
Pipe Valve Status: [ct]<BR>
|
||||
\t<A href='?src=\ref[src];cp=-[num2text(1000000.0, 7)]'>M</A> <A href='?src=\ref[src];cp=-10000'>-</A> <A href='?src=\ref[src];cp=-1000'>-</A> <A href='?src=\ref[src];cp=-100'>-</A> <A href='?src=\ref[src];cp=-1'>-</A> [src.c_per] <A href='?src=\ref[src];cp=1'>+</A> <A href='?src=\ref[src];cp=100'>+</A> <A href='?src=\ref[src];cp=1000'>+</A> <A href='?src=\ref[src];cp=10000'>+</A> <A href='?src=\ref[src];cp=[num2text(1000000.0, 7)]'>M</A><BR>
|
||||
<BR>
|
||||
<A href='?src=\ref[user];mach_close=canister'>Close</A><BR>
|
||||
</TT>"}
|
||||
|
||||
user << browse(dat, "window=canister;size=600x300")
|
||||
return
|
||||
|
||||
|
||||
// Process topic link from interaction window
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
if (usr.stat || usr.restrained())
|
||||
return
|
||||
if ((get_dist(src, usr) <= 1 && istype(src.loc, /turf)))
|
||||
usr.machine = src
|
||||
|
||||
if (href_list["c"])
|
||||
var/c = text2num(href_list["c"])
|
||||
switch(c)
|
||||
if(1.0)
|
||||
src.c_status = 1
|
||||
if(2.0)
|
||||
c_status = 2
|
||||
if(3.0)
|
||||
src.c_status = 3
|
||||
|
||||
else if (href_list["t"])
|
||||
var/t = text2num(href_list["t"])
|
||||
if (src.t_status == 0)
|
||||
return
|
||||
switch(t)
|
||||
if(1.0)
|
||||
src.t_status = 1
|
||||
if(2.0)
|
||||
if (src.holding)
|
||||
src.t_status = 2
|
||||
else
|
||||
src.t_status = 3
|
||||
if(3.0)
|
||||
src.t_status = 3
|
||||
|
||||
else if (href_list["tp"])
|
||||
var/tp = text2num(href_list["tp"])
|
||||
src.t_per += tp
|
||||
src.t_per = min(max(round(src.t_per), 0), 1000000.0)
|
||||
|
||||
else if (href_list["cp"])
|
||||
var/cp = text2num(href_list["cp"])
|
||||
src.c_per += cp
|
||||
src.c_per = min(max(round(src.c_per), 0), 1000000.0)
|
||||
|
||||
else if (href_list["tank"])
|
||||
var/cp = text2num(href_list["tank"])
|
||||
if ((cp == 1 && src.holding))
|
||||
src.holding.loc = src.loc
|
||||
src.holding = null
|
||||
if (src.t_status == 2)
|
||||
src.t_status = 3
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
src.add_fingerprint(usr)
|
||||
update_icon()
|
||||
|
||||
else
|
||||
usr << browse(null, "window=canister")
|
||||
|
||||
|
||||
// Attack by an object
|
||||
// If a tank, insert the tank
|
||||
// If a wrench (and a connector is present), attach/unattach canister from pipe connector
|
||||
// Otherwise, damage the canister
|
||||
|
||||
attackby(var/obj/item/weapon/W, var/mob/user)
|
||||
|
||||
if ((istype(W, /obj/item/weapon/tank) && !( src.destroyed )))
|
||||
if (src.holding)
|
||||
return
|
||||
var/obj/item/weapon/tank/T = W
|
||||
user.drop_item()
|
||||
T.loc = src
|
||||
src.holding = T
|
||||
update_icon()
|
||||
|
||||
else if ((istype(W, /obj/item/weapon/wrench)))
|
||||
var/obj/machinery/connector/con = locate(/obj/machinery/connector, src.loc)
|
||||
|
||||
if (src.c_status) // note: don't check is cansiter is destroyed to allow user to unhook a broken cansiter
|
||||
src.anchored = 0
|
||||
src.c_status = 0
|
||||
user.show_message("\blue You have disconnected the canister.", 1)
|
||||
if(con)
|
||||
con.connected = null
|
||||
else
|
||||
if(con && !con.connected && !destroyed)
|
||||
src.anchored = 1
|
||||
src.c_status = 3
|
||||
user.show_message("\blue You have connected the canister.", 1)
|
||||
con.connected = src
|
||||
else
|
||||
user.show_message("\blue There is nothing here with which to connect the canister.", 1)
|
||||
else
|
||||
switch(W.damtype)
|
||||
if("fire")
|
||||
src.health -= W.force
|
||||
if("brute")
|
||||
src.health -= W.force * 0.5
|
||||
else
|
||||
src.healthcheck()
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
/*
|
||||
* The specific canister types
|
||||
*/
|
||||
|
||||
// Canister containing plasma
|
||||
|
||||
poisoncanister
|
||||
name = "Canister \[Plasma (Bio)\]"
|
||||
icon_state = "orange"
|
||||
color = "orange"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.update_icon()
|
||||
src.gas.plasma = 9.0E7*filled
|
||||
return
|
||||
|
||||
|
||||
// Canister containing oxygen
|
||||
|
||||
oxygencanister
|
||||
name = "Canister: \[O2\]"
|
||||
icon_state = "blue"
|
||||
color = "blue"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.gas.oxygen = 1.0E8*filled
|
||||
return
|
||||
|
||||
|
||||
// Canister containing N2O
|
||||
|
||||
anesthcanister
|
||||
name = "Canister: \[N2O\]"
|
||||
icon_state = "redws"
|
||||
color = "redws"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.gas.sl_gas = 1.0E8*filled
|
||||
return
|
||||
|
||||
|
||||
// Canister containing nitrogen
|
||||
|
||||
n2canister
|
||||
name = "Canister: \[N2\]"
|
||||
icon_state = "red"
|
||||
color = "red"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.gas.n2 = 1.0E8*filled
|
||||
return
|
||||
|
||||
|
||||
// Canister containing carbon dioxide
|
||||
|
||||
co2canister
|
||||
name = "Canister \[CO2\]"
|
||||
icon_state = "black"
|
||||
color = "black"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.gas.co2 = 1.0E8*filled
|
||||
return
|
||||
|
||||
|
||||
// Canister containing air mixture (21% O2, 79% N2)
|
||||
|
||||
aircanister
|
||||
name = "Canister \[Air\]"
|
||||
icon_state = "grey"
|
||||
color = "grey"
|
||||
|
||||
New()
|
||||
..()
|
||||
src.gas.oxygen = 2.1e7*filled
|
||||
src.gas.n2 = 7.9e7*filled
|
||||
return
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,254 @@
|
||||
/*
|
||||
* Heater - A machine that allows heating of gases.
|
||||
*
|
||||
* Can siphon/fill gas from ab attached tank, or connect to pipe network via a connector.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
obj/machinery/atmoalter/heater
|
||||
name = "heater"
|
||||
icon = 'stationobjs.dmi'
|
||||
icon_state = "heater1"
|
||||
density = 1
|
||||
|
||||
// from atmoalter
|
||||
maximum = 1.3E8
|
||||
anchored = 1.0
|
||||
t_status = 3.0
|
||||
t_per = 50.0
|
||||
c_per = 50.0
|
||||
c_status = 0.0
|
||||
holding = null // the inserted tank item, or null if none
|
||||
var
|
||||
h_tar = 20.0 // the target temperature (degC)
|
||||
h_status = 0.0 // the heater status 0=off, 1=on
|
||||
heatrate = 1500000.0 // the rate at which heating takes place
|
||||
|
||||
|
||||
// Create a new heater, set gas content & maximum capacity
|
||||
|
||||
New()
|
||||
|
||||
..()
|
||||
src.gas = new /obj/substance/gas( src )
|
||||
src.gas.maximum = src.maximum
|
||||
return
|
||||
|
||||
|
||||
// Set the heater's icon state depending on status
|
||||
|
||||
proc/setstate()
|
||||
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "heater-p"
|
||||
return
|
||||
|
||||
if (src.holding)
|
||||
src.icon_state = "heater1-h"
|
||||
else
|
||||
src.icon_state = "heater1"
|
||||
return
|
||||
|
||||
|
||||
// Timer process. Heat the contained gas towards the target temperature, and flow gas to/from tank is valve open.
|
||||
|
||||
process()
|
||||
|
||||
if(stat & NOPOWER) return
|
||||
use_power(5)
|
||||
|
||||
var/turf/T = src.loc
|
||||
if (istype(T, /turf))
|
||||
if (locate(/obj/move, T))
|
||||
T = locate(/obj/move, T)
|
||||
else
|
||||
T = null
|
||||
|
||||
|
||||
if (src.h_status) // true if heating on
|
||||
var/t1 = src.gas.tot_gas()
|
||||
if ((t1 > 0 && src.gas.temperature < (src.h_tar+T0C))) // note gas.temperature in kelvin but target temp in celcius
|
||||
var/increase = src.heatrate / t1
|
||||
var/n_temp = src.gas.temperature + increase
|
||||
src.gas.temperature = min(n_temp, (src.h_tar+T0C))
|
||||
|
||||
use_power( src.h_tar*8)
|
||||
|
||||
switch(src.t_status) // main valve; 1=release, 2=siphon, 3=stop
|
||||
if(1.0)
|
||||
if (src.holding)
|
||||
var/t1 = src.gas.tot_gas()
|
||||
var/t2 = t1
|
||||
var/t = src.t_per
|
||||
if (src.t_per > t2)
|
||||
t = t2
|
||||
src.holding.gas.transfer_from(src.gas, t)
|
||||
else
|
||||
src.t_status = 3
|
||||
if(2.0)
|
||||
if (src.holding)
|
||||
var/t1 = src.gas.tot_gas()
|
||||
var/t2 = src.maximum - t1
|
||||
var/t = src.t_per
|
||||
if (src.t_per > t2)
|
||||
t = t2
|
||||
src.gas.transfer_from(src.holding.gas, t)
|
||||
else
|
||||
src.t_status = 3
|
||||
else
|
||||
|
||||
// Pipe valve transfer handled by /obj/machinery/connector process()
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
src.setstate()
|
||||
return
|
||||
|
||||
|
||||
// monkey interact same as human
|
||||
|
||||
attack_paw(mob/user)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// interact, show window
|
||||
|
||||
attack_hand(var/mob/user)
|
||||
|
||||
if(stat & NOPOWER) return
|
||||
|
||||
user.machine = src
|
||||
var/tt
|
||||
switch(src.t_status)
|
||||
if(1.0)
|
||||
tt = "Releasing <A href='?src=\ref[src];t=2'>Siphon</A> <A href='?src=\ref[src];t=3'>Stop</A>"
|
||||
if(2.0)
|
||||
tt = "<A href='?src=\ref[src];t=1'>Release</A> Siphoning<A href='?src=\ref[src];t=3'>Stop</A>"
|
||||
if(3.0)
|
||||
tt = "<A href='?src=\ref[src];t=1'>Release</A> <A href='?src=\ref[src];t=2'>Siphon</A> Stopped"
|
||||
else
|
||||
|
||||
var/ht = null
|
||||
if (src.h_status)
|
||||
ht = "Heating <A href='?src=\ref[src];h=2'>Stop</A>"
|
||||
else
|
||||
ht = "<A href='?src=\ref[src];h=1'>Heat</A> Stopped"
|
||||
|
||||
var/ct = null
|
||||
switch(src.c_status)
|
||||
if(1.0)
|
||||
ct = "Releasing <A href='?src=\ref[src];c=2'>Accept</A> <A href='?src=\ref[src];ct=3'>Stop</A>"
|
||||
if(2.0)
|
||||
ct = "<A href='?src=\ref[src];c=1'>Release</A> Accepting <A href='?src=\ref[src];c=3'>Stop</A>"
|
||||
if(3.0)
|
||||
ct = "<A href='?src=\ref[src];c=1'>Release</A> <A href='?src=\ref[src];c=2'>Accept</A> Stopped"
|
||||
else
|
||||
ct = "Disconnected"
|
||||
|
||||
var/dat = text("<TT><B>Canister Valves</B><BR>\n<FONT color = 'blue'><B>Contains/Capacity</B> [] / []</FONT><BR>\nUpper Valve Status: [][]<BR>\n\t<A href='?src=\ref[];tp=-[]'>M</A> <A href='?src=\ref[];tp=-10000'>-</A> <A href='?src=\ref[];tp=-1000'>-</A> <A href='?src=\ref[];tp=-100'>-</A> <A href='?src=\ref[];tp=-1'>-</A> [] <A href='?src=\ref[];tp=1'>+</A> <A href='?src=\ref[];tp=100'>+</A> <A href='?src=\ref[];tp=1000'>+</A> <A href='?src=\ref[];tp=10000'>+</A> <A href='?src=\ref[];tp=[]'>M</A><BR>\nHeater Status: [] - []<BR>\n\tTrg Tmp: <A href='?src=\ref[];ht=-50'>-</A> <A href='?src=\ref[];ht=-5'>-</A> <A href='?src=\ref[];ht=-1'>-</A> [] <A href='?src=\ref[];ht=1'>+</A> <A href='?src=\ref[];ht=5'>+</A> <A href='?src=\ref[];ht=50'>+</A><BR>\n<BR>\nPipe Valve Status: []<BR>\n\t<A href='?src=\ref[];cp=-[]'>M</A> <A href='?src=\ref[];cp=-10000'>-</A> <A href='?src=\ref[];cp=-1000'>-</A> <A href='?src=\ref[];cp=-100'>-</A> <A href='?src=\ref[];cp=-1'>-</A> [] <A href='?src=\ref[];cp=1'>+</A> <A href='?src=\ref[];cp=100'>+</A> <A href='?src=\ref[];cp=1000'>+</A> <A href='?src=\ref[];cp=10000'>+</A> <A href='?src=\ref[];cp=[]'>M</A><BR>\n<BR>\n<A href='?src=\ref[];mach_close=canister'>Close</A><BR>\n</TT>", src.gas.tot_gas(), src.maximum, tt, (src.holding ? text("<BR><A href='?src=\ref[];tank=1'>Tank ([]</A>)", src, src.holding.gas.tot_gas()) : null), src, num2text(1000000.0, 7), src, src, src, src, src.t_per, src, src, src, src, src, num2text(1000000.0, 7), ht, (src.gas.tot_gas() ? (src.gas.temperature-T0C) : 20), src, src, src, src.h_tar, src, src, src, ct, src, num2text(1000000.0, 7), src, src, src, src, src.c_per, src, src, src, src, src, num2text(1000000.0, 7), user)
|
||||
user << browse(dat, "window=canister;size=600x300")
|
||||
return
|
||||
|
||||
|
||||
// handle topic links from interaction window
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
if (usr.stat || usr.restrained())
|
||||
return
|
||||
if ((get_dist(src, usr) <= 1 && istype(src.loc, /turf)))
|
||||
usr.machine = src
|
||||
|
||||
if (href_list["c"])
|
||||
var/c = text2num(href_list["c"])
|
||||
switch(c)
|
||||
if(1.0)
|
||||
src.c_status = 1
|
||||
if(2.0)
|
||||
src.c_status = 2
|
||||
if(3.0)
|
||||
src.c_status = 3
|
||||
else
|
||||
else if (href_list["t"])
|
||||
var/t = text2num(href_list["t"])
|
||||
if (src.t_status == 0)
|
||||
return
|
||||
switch(t)
|
||||
if(1.0)
|
||||
src.t_status = 1
|
||||
if(2.0)
|
||||
src.t_status = 2
|
||||
if(3.0)
|
||||
src.t_status = 3
|
||||
else
|
||||
else if (href_list["h"])
|
||||
var/h = text2num(href_list["h"])
|
||||
if (h == 1)
|
||||
src.h_status = 1
|
||||
else
|
||||
src.h_status = null
|
||||
else if (href_list["tp"])
|
||||
var/tp = text2num(href_list["tp"])
|
||||
src.t_per += tp
|
||||
src.t_per = min(max(round(src.t_per), 0), 1000000.0)
|
||||
else if (href_list["cp"])
|
||||
var/cp = text2num(href_list["cp"])
|
||||
src.c_per += cp
|
||||
src.c_per = min(max(round(src.c_per), 0), 1000000.0)
|
||||
else if (href_list["ht"])
|
||||
var/cp = text2num(href_list["ht"])
|
||||
src.h_tar += cp
|
||||
src.h_tar = min(max(round(src.h_tar), 0), 500)
|
||||
else if (href_list["tank"])
|
||||
var/cp = text2num(href_list["tank"])
|
||||
if ((cp == 1 && src.holding))
|
||||
src.holding.loc = src.loc
|
||||
src.holding = null
|
||||
if (src.t_status == 2)
|
||||
src.t_status = 3
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
src.add_fingerprint(usr)
|
||||
else
|
||||
usr << browse(null, "window=canister")
|
||||
return
|
||||
return
|
||||
|
||||
// attack by tank, insert the tank
|
||||
// attack by wrench, connect to pipe connector (if present)
|
||||
|
||||
attackby(var/obj/item/weapon/W, var/mob/user)
|
||||
|
||||
if (istype(W, /obj/item/weapon/tank))
|
||||
if (src.holding)
|
||||
return
|
||||
var/obj/item/weapon/tank/T = W
|
||||
user.drop_item()
|
||||
T.loc = src
|
||||
src.holding = T
|
||||
|
||||
else if (istype(W, /obj/item/weapon/wrench))
|
||||
var/obj/machinery/connector/con = locate(/obj/machinery/connector, src.loc)
|
||||
|
||||
if (src.c_status)
|
||||
src.anchored = 0
|
||||
src.c_status = 0
|
||||
user.show_message("\blue You have disconnected the heater.", 1)
|
||||
if(con)
|
||||
con.connected = null
|
||||
else
|
||||
if (con && !con.connected)
|
||||
src.anchored = 1
|
||||
src.c_status = 3
|
||||
user.show_message("\blue You have connected the heater.", 1)
|
||||
con.connected = src
|
||||
else
|
||||
user.show_message("\blue There is no connector here to attach the heater to.", 1)
|
||||
return
|
||||
|
||||
|
||||
@@ -0,0 +1,656 @@
|
||||
/*
|
||||
* siphs - base type including siphons, scrubbers, air regulators, and air filters
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
// base siph type
|
||||
|
||||
obj/machinery/atmoalter/siphs
|
||||
name = "siphs"
|
||||
density = 1
|
||||
weight = 1.0E7
|
||||
anchored = 1.0
|
||||
|
||||
// from atmoalter
|
||||
maximum = 1.3E8
|
||||
holding = null
|
||||
t_status = 3.0
|
||||
t_per = 50.0
|
||||
c_per = 50.0
|
||||
c_status = 0.0
|
||||
|
||||
var
|
||||
alterable = 1.0 // false if interface is locked (change with wrench)
|
||||
f_time = 1.0 // worldtime until automatic mode resumes; set to 30 seconds delay if a fire is present in turf
|
||||
//location = null // unknown/not used
|
||||
empty = null // if true, fullairsiphons are spawned without any gas content
|
||||
// otherwise, filled with air
|
||||
|
||||
|
||||
/* There are 6 types of siph objects:
|
||||
*
|
||||
* fullairsiphon - Siphon - Can hold a tank. Starts containing air. Automatic process releases air to maintain correct O2/N2 levels
|
||||
* fullairsiphon/port - Portable Siphon - same as fullairsiphon, but pushable.
|
||||
* fullairsiphon/air_vent - Air Regulator - Vent on floor, same as fullairsiphon but cannot hold a tank.
|
||||
*
|
||||
* scrubbers - Scrubber - Can hold a tank. Starts empty. Automatic process removes toxins from air and stores in gas content.
|
||||
* scubbers/port - Portable Scrubber - same as scrubbers but pushable.
|
||||
* scubbers/air_filter - Air Filter - Vent on floor, same as scrubbers but cannot hold a tank.
|
||||
*/
|
||||
|
||||
// new siphon object, create the gas content and set maximum capacity
|
||||
// Called by New() proc of all siph types
|
||||
|
||||
New()
|
||||
..()
|
||||
src.gas = new /obj/substance/gas( src )
|
||||
src.gas.maximum = src.maximum
|
||||
|
||||
|
||||
// Set main valve to release and max setting
|
||||
|
||||
proc/releaseall()
|
||||
src.t_status = 1
|
||||
src.t_per = max_valve
|
||||
return
|
||||
|
||||
|
||||
// Reset the siphon state. If "valve" is negative, main valve is set to release at that rate
|
||||
// If "valve" is positive, main valve set to siphon at that rate
|
||||
// If "auto" true, main valve set to automatic status
|
||||
// This routine is called by the siphonswitch computers to control the siphs
|
||||
|
||||
|
||||
proc/reset(valve, auto)
|
||||
if(c_status!=0)
|
||||
return
|
||||
|
||||
if (valve < 0)
|
||||
src.t_per = -valve
|
||||
src.t_status = 1
|
||||
else
|
||||
if (valve > 0)
|
||||
src.t_per = valve
|
||||
src.t_status = 2
|
||||
else
|
||||
src.t_status = 3
|
||||
if (auto)
|
||||
src.t_status = 4
|
||||
src.setstate()
|
||||
return
|
||||
|
||||
|
||||
// Release "amount" of gas into the turf
|
||||
|
||||
proc/release(amount, flag)
|
||||
var/T = src.loc
|
||||
if (!( istype(T, /turf) ))
|
||||
return
|
||||
if (locate(/obj/move, T))
|
||||
T = locate(/obj/move, T)
|
||||
if (!( amount ))
|
||||
return
|
||||
if (!( flag ))
|
||||
amount = min(amount, max_valve)
|
||||
src.gas.turf_add(T, amount)
|
||||
return
|
||||
|
||||
|
||||
// Siphon "amount" of gas from the turf
|
||||
|
||||
proc/siphon(amount, flag)
|
||||
|
||||
var/T = src.loc
|
||||
if (!( istype(T, /turf) ))
|
||||
return
|
||||
if (locate(/obj/move, T))
|
||||
T = locate(/obj/move, T)
|
||||
if (!( amount ))
|
||||
return
|
||||
if (!( flag ))
|
||||
amount = min(amount, 900000.0)
|
||||
src.gas.turf_take(T, amount)
|
||||
return
|
||||
|
||||
|
||||
// Set the icon state, depending on status (unpowered, holding a tank, or accepting or releasing gas)
|
||||
|
||||
proc/setstate()
|
||||
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "siphon:0"
|
||||
return
|
||||
|
||||
if (src.holding)
|
||||
src.icon_state = "siphon:T"
|
||||
else
|
||||
if (src.t_status != 3)
|
||||
src.icon_state = "siphon:1"
|
||||
else
|
||||
src.icon_state = "siphon:0"
|
||||
return
|
||||
|
||||
|
||||
// Returns true if the siphon/scrubber is a portable type
|
||||
|
||||
proc/portable()
|
||||
return istype(src, /obj/machinery/atmoalter/siphs/fullairsiphon/port) || istype(src, /obj/machinery/atmoalter/siphs/scrubbers/port)
|
||||
|
||||
|
||||
// Called when area power status changes. Siphons use the ENVIRON channel. Portable siphons/scrubbers do not use power.
|
||||
|
||||
power_change()
|
||||
|
||||
if( portable() )
|
||||
return
|
||||
|
||||
if(!powered(ENVIRON))
|
||||
spawn(rand(0,15))
|
||||
stat |= NOPOWER
|
||||
setstate()
|
||||
else
|
||||
stat &= ~NOPOWER
|
||||
setstate()
|
||||
|
||||
|
||||
// Timed process. Note scrubbers/air filters override this.
|
||||
// Accept or release gas depending on settings
|
||||
|
||||
process()
|
||||
if(stat & NOPOWER) return
|
||||
|
||||
if (src.t_status != 3)
|
||||
var/turf/T = src.loc
|
||||
if (istype(T, /turf))
|
||||
if (locate(/obj/move, T))
|
||||
T = locate(/obj/move, T)
|
||||
else
|
||||
T = null
|
||||
|
||||
switch(src.t_status) // main valve status
|
||||
if(1.0) // 1 = release
|
||||
if( !portable() ) use_power(50, ENVIRON)
|
||||
if (src.holding) // if tank inserted, fill tank
|
||||
var/t1 = src.gas.tot_gas()
|
||||
var/t2 = t1
|
||||
var/t = src.t_per
|
||||
if (src.t_per > t2)
|
||||
t = t2
|
||||
src.holding.gas.transfer_from(src.gas, t)
|
||||
else // otherwise release into turf
|
||||
if (T)
|
||||
var/t1 = src.gas.tot_gas()
|
||||
var/t2 = t1
|
||||
var/t = src.t_per
|
||||
if (src.t_per > t2)
|
||||
t = t2
|
||||
src.gas.turf_add(T, t)
|
||||
|
||||
if(2.0) // 2 = siphon
|
||||
if( !portable() ) use_power(50, ENVIRON)
|
||||
if (src.holding) // if tank inserted, draw from tank
|
||||
var/t1 = src.gas.tot_gas()
|
||||
var/t2 = src.maximum - t1
|
||||
var/t = src.t_per
|
||||
if (src.t_per > t2)
|
||||
t = t2
|
||||
src.gas.transfer_from(src.holding.gas, t)
|
||||
else // else take from turf atmosphere
|
||||
if (T)
|
||||
var/t1 = src.gas.tot_gas()
|
||||
var/t2 = src.maximum - t1
|
||||
var/t = src.t_per
|
||||
if (t > t2)
|
||||
t = t2
|
||||
|
||||
src.gas.turf_take(T, t)
|
||||
// 3 = stopped
|
||||
if(4.0) // 4 = automatic
|
||||
if( !portable() )
|
||||
use_power(50, ENVIRON)
|
||||
|
||||
if (T)
|
||||
if (T.firelevel > 900000.0)
|
||||
src.f_time = world.time + 300 // shut off automatic operation for 30 seconds if fire present
|
||||
else
|
||||
if (world.time > src.f_time)
|
||||
var/difference = CELLSTANDARD - (T.oxygen + T.n2)
|
||||
if (difference > 0)
|
||||
var/t1 = src.gas.tot_gas()
|
||||
if (difference > t1)
|
||||
difference = t1
|
||||
src.gas.turf_add(T, difference) // add gas to turf to maintain standard N2/O2 levels
|
||||
|
||||
// Pipe valve settings handled in /obj/machinery/connector/process()
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
src.setstate()
|
||||
return
|
||||
|
||||
|
||||
// Monkey interact same as human
|
||||
|
||||
attack_paw(user as mob)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// Interact, show window
|
||||
// Used by siphons and scrubbers, but air regulators and filters override
|
||||
|
||||
attack_hand(var/mob/user)
|
||||
|
||||
if(stat & NOPOWER) return
|
||||
user.machine = src
|
||||
var/tt
|
||||
switch(src.t_status)
|
||||
if(1.0)
|
||||
tt = "Releasing <A href='?src=\ref[src];t=2'>Siphon</A> <A href='?src=\ref[src];t=3'>Stop</A>"
|
||||
if(2.0)
|
||||
tt = "<A href='?src=\ref[src];t=1'>Release</A> Siphoning <A href='?src=\ref[src];t=3'>Stop</A>"
|
||||
if(3.0)
|
||||
tt = "<A href='?src=\ref[src];t=1'>Release</A> <A href='?src=\ref[src];t=2'>Siphon</A> Stopped <A href='?src=\ref[src];t=4'>Automatic</A>"
|
||||
else
|
||||
tt = "Automatic equalizers are on!"
|
||||
|
||||
var/ct = null
|
||||
switch(src.c_status)
|
||||
if(1.0)
|
||||
ct = "Releasing <A href='?src=\ref[src];c=2'>Accept</A> <A href='?src=\ref[src];c=3'>Stop</A>"
|
||||
if(2.0)
|
||||
ct = "<A href='?src=\ref[src];c=1'>Release</A> Accepting <A href='?src=\ref[src];c=3'>Stop</A>"
|
||||
if(3.0)
|
||||
ct = "<A href='?src=\ref[src];c=1'>Release</A> <A href='?src=\ref[src];c=2'>Accept</A> Stopped"
|
||||
else
|
||||
ct = "Disconnected"
|
||||
var/at = null
|
||||
if (src.t_status == 4)
|
||||
at = "Automatic On <A href='?src=\ref[src];t=3'>Stop</A>"
|
||||
var/dat = text("<TT><B>Canister Valves</B> []<BR>\n\t<FONT color = 'blue'><B>Contains/Capacity</B> [] / []</FONT><BR>\n\tUpper Valve Status: [] []<BR>\n\t\t<A href='?src=\ref[];tp=-[]'>M</A> <A href='?src=\ref[];tp=-10000'>-</A> <A href='?src=\ref[];tp=-1000'>-</A> <A href='?src=\ref[];tp=-100'>-</A> <A href='?src=\ref[];tp=-1'>-</A> [] <A href='?src=\ref[];tp=1'>+</A> <A href='?src=\ref[];tp=100'>+</A> <A href='?src=\ref[];tp=1000'>+</A> <A href='?src=\ref[];tp=10000'>+</A> <A href='?src=\ref[];tp=[]'>M</A><BR>\n\tPipe Valve Status: []<BR>\n\t\t<A href='?src=\ref[];cp=-[]'>M</A> <A href='?src=\ref[];cp=-10000'>-</A> <A href='?src=\ref[];cp=-1000'>-</A> <A href='?src=\ref[];cp=-100'>-</A> <A href='?src=\ref[];cp=-1'>-</A> [] <A href='?src=\ref[];cp=1'>+</A> <A href='?src=\ref[];cp=100'>+</A> <A href='?src=\ref[];cp=1000'>+</A> <A href='?src=\ref[];cp=10000'>+</A> <A href='?src=\ref[];cp=[]'>M</A><BR>\n<BR>\n\n<A href='?src=\ref[];mach_close=siphon'>Close</A><BR>\n\t</TT>", (!( src.alterable ) ? "<B>Valves are locked. Unlock with wrench!</B>" : "You can lock this interface with a wrench."), num2text(src.gas.tot_gas(), 10), num2text(src.maximum, 10), (src.t_status == 4 ? text("[]", at) : text("[]", tt)), (src.holding ? text("<BR>(<A href='?src=\ref[];tank=1'>Tank ([]</A>)", src, src.holding.gas.tot_gas()) : null), src, num2text(max_valve, 7), src, src, src, src, src.t_per, src, src, src, src, src, num2text(max_valve, 7), ct, src, num2text(max_valve, 7), src, src, src, src, src.c_per, src, src, src, src, src, num2text(max_valve, 7), user)
|
||||
user << browse(dat, "window=siphon;size=600x300")
|
||||
return
|
||||
|
||||
|
||||
// Handle topic links from interaction window
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
|
||||
if (usr.stat || usr.restrained())
|
||||
return
|
||||
if (!( src.alterable ))
|
||||
return
|
||||
if ((get_dist(src, usr) <= 1 && istype(src.loc, /turf)))
|
||||
usr.machine = src
|
||||
if (href_list["c"])
|
||||
var/c = text2num(href_list["c"])
|
||||
switch(c)
|
||||
if(1.0)
|
||||
src.c_status = 1
|
||||
if(2.0)
|
||||
src.c_status = 2
|
||||
if(3.0)
|
||||
src.c_status = 3
|
||||
|
||||
else if (href_list["t"])
|
||||
var/t = text2num(href_list["t"])
|
||||
if (src.t_status == 0)
|
||||
return
|
||||
switch(t)
|
||||
if(1.0)
|
||||
src.t_status = 1
|
||||
if(2.0)
|
||||
src.t_status = 2
|
||||
if(3.0)
|
||||
src.t_status = 3
|
||||
if(4.0)
|
||||
src.t_status = 4
|
||||
src.f_time = 1
|
||||
|
||||
else if (href_list["tp"])
|
||||
var/tp = text2num(href_list["tp"])
|
||||
src.t_per += tp
|
||||
src.t_per = min(max(round(src.t_per), 0), max_valve)
|
||||
else if (href_list["cp"])
|
||||
var/cp = text2num(href_list["cp"])
|
||||
src.c_per += cp
|
||||
src.c_per = min(max(round(src.c_per), 0), max_valve)
|
||||
else if (href_list["tank"])
|
||||
var/cp = text2num(href_list["tank"])
|
||||
if (cp == 1)
|
||||
src.holding.loc = src.loc
|
||||
src.holding = null
|
||||
if (src.t_status == 2)
|
||||
src.t_status = 3
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
src.add_fingerprint(usr)
|
||||
else
|
||||
usr << browse(null, "window=canister")
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
// Attack by item
|
||||
// Use tank to insert a tank into siphon
|
||||
// Use screwdriver to attach to a connector (if present)
|
||||
// Use wrench to lock/unlock the interface
|
||||
// Note air filters and air regulators override this proc since tanks cannot be inserted
|
||||
|
||||
attackby(var/obj/W as obj, mob/user as mob)
|
||||
|
||||
if (istype(W, /obj/item/weapon/tank)) // insert tank
|
||||
if (src.holding)
|
||||
return
|
||||
var/obj/item/weapon/tank/T = W
|
||||
user.drop_item()
|
||||
T.loc = src
|
||||
src.holding = T
|
||||
|
||||
else if (istype(W, /obj/item/weapon/screwdriver)) // connect/disconnect from connector
|
||||
var/obj/machinery/connector/con = locate(/obj/machinery/connector, src.loc)
|
||||
if (src.c_status)
|
||||
src.anchored = 0
|
||||
src.c_status = 0
|
||||
user.show_message("\blue You have disconnected the siphon.")
|
||||
if(con)
|
||||
con.connected = null
|
||||
else if (con && !con.connected)
|
||||
src.anchored = 1
|
||||
src.c_status = 3
|
||||
user.show_message("\blue You have connected the siphon.")
|
||||
con.connected = src
|
||||
else
|
||||
user.show_message("\blue There is nothing here to connect to the siphon.")
|
||||
|
||||
|
||||
else if (istype(W, /obj/item/weapon/wrench)) // lock/unlock the interface
|
||||
src.alterable = !( src.alterable )
|
||||
if (src.alterable)
|
||||
user << "\blue You unlock the interface!"
|
||||
else
|
||||
user << "\blue You lock the interface!"
|
||||
|
||||
|
||||
/*
|
||||
* Fullairsiphons - standard, air regulator, and portable
|
||||
*/
|
||||
|
||||
fullairsiphon
|
||||
name = "Air siphon"
|
||||
icon = 'turfs.dmi'
|
||||
icon_state = "siphon:0"
|
||||
|
||||
air_vent
|
||||
name = "Air regulator"
|
||||
icon = 'aircontrol.dmi'
|
||||
icon_state = "vent2"
|
||||
t_status = 4 // air regulator vents start in automatic mode
|
||||
alterable = 0 // with interface locked
|
||||
density = 0
|
||||
|
||||
port
|
||||
name = "Portable Siphon"
|
||||
icon = 'stationobjs.dmi'
|
||||
flags = FPRINT|DRIVABLE
|
||||
anchored = 0
|
||||
|
||||
|
||||
// Create a new fullairsiphon. Unless empty var is true, fill with 21% O2/79% N2
|
||||
|
||||
New()
|
||||
..()
|
||||
if(!empty)
|
||||
src.gas.oxygen = 2.73E7
|
||||
src.gas.n2 = 1.027E8
|
||||
|
||||
|
||||
// Reset the protable siphon
|
||||
|
||||
fullairsiphon/port/reset(valve, auto)
|
||||
if (valve < 0)
|
||||
src.t_per = -valve
|
||||
src.t_status = 1
|
||||
else
|
||||
if (valve > 0)
|
||||
src.t_per = valve
|
||||
src.t_status = 2
|
||||
else
|
||||
src.t_status = 3
|
||||
if (auto)
|
||||
src.t_status = 4
|
||||
src.setstate()
|
||||
return
|
||||
|
||||
// Attack air regulator with item
|
||||
// If screwdriver, attach/unattach from connector (if present)
|
||||
// If wrench, lock/unlock the interface
|
||||
|
||||
fullairsiphon/air_vent/attackby(obj/item/weapon/W, mob/user)
|
||||
|
||||
if (istype(W, /obj/item/weapon/screwdriver))
|
||||
if (src.c_status)
|
||||
src.anchored = 1
|
||||
src.c_status = 0
|
||||
else
|
||||
if (locate(/obj/machinery/connector, src.loc))
|
||||
src.anchored = 1
|
||||
src.c_status = 3
|
||||
else
|
||||
if (istype(W, /obj/item/weapon/wrench))
|
||||
src.alterable = !( src.alterable )
|
||||
return
|
||||
|
||||
|
||||
// Set the icon state of an air regulator vent
|
||||
|
||||
fullairsiphon/air_vent/setstate()
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "vent-p"
|
||||
return
|
||||
|
||||
if (src.t_status == 4)
|
||||
src.icon_state = "vent2"
|
||||
else
|
||||
if (src.t_status == 3)
|
||||
src.icon_state = "vent0"
|
||||
else
|
||||
src.icon_state = "vent1"
|
||||
return
|
||||
|
||||
|
||||
// Reset an air regulator vent. Only set automatic mode; do not change valve settings
|
||||
|
||||
fullairsiphon/air_vent/reset(valve, auto)
|
||||
|
||||
if (auto)
|
||||
src.t_status = 4
|
||||
return
|
||||
|
||||
/*
|
||||
* Scrubbers - standard, air filter, and portable
|
||||
*/
|
||||
|
||||
scrubbers
|
||||
name = "scrubbers"
|
||||
icon = 'turfs2.dmi'
|
||||
icon_state = "siphon:0"
|
||||
|
||||
air_filter
|
||||
name = "air filter"
|
||||
icon = 'aircontrol.dmi'
|
||||
icon_state = "vent2"
|
||||
t_status = 4 // air filter vents start in automatic mode
|
||||
alterable = 0 // with interface locked
|
||||
density = 0
|
||||
|
||||
port
|
||||
name = "Portable Siphon"
|
||||
icon = 'stationobjs.dmi'
|
||||
icon_state = "scrubber:0"
|
||||
flags = FPRINT|DRIVABLE
|
||||
anchored = 0.0
|
||||
|
||||
|
||||
// Timed process for scrubbers (overrides standard for siphs)
|
||||
|
||||
process()
|
||||
|
||||
if(stat & NOPOWER) return
|
||||
|
||||
if (src.t_status != 3) // unless stopped
|
||||
var/turf/T = src.loc // add all oxygen in gas contents to turf
|
||||
if (istype(T, /turf))
|
||||
if (locate(/obj/move, T))
|
||||
T = locate(/obj/move, T)
|
||||
if (T.firelevel < 900000.0)
|
||||
src.gas.turf_add_all_oxy(T)
|
||||
|
||||
else
|
||||
T = null
|
||||
|
||||
switch(src.t_status) // main valve status
|
||||
if(1.0) // 1 = release
|
||||
if( !portable() ) use_power(50, ENVIRON)
|
||||
|
||||
if (src.holding) // if a tank is inserted, fill tank with gas
|
||||
var/t1 = src.gas.tot_gas()
|
||||
var/t2 = t1
|
||||
var/t = src.t_per
|
||||
if (src.t_per > t2)
|
||||
t = t2
|
||||
src.holding.gas.transfer_from(src.gas, t)
|
||||
else // otherwise, release gas into turf atmosphere
|
||||
if (T)
|
||||
var/t1 = src.gas.tot_gas()
|
||||
var/t2 = t1
|
||||
var/t = src.t_per
|
||||
if (src.t_per > t2)
|
||||
t = t2
|
||||
src.gas.turf_add(T, t)
|
||||
|
||||
if(2.0) // 2 = siphon
|
||||
if( !portable() ) use_power(50, ENVIRON)
|
||||
if (src.holding) // if a tank is inserted, draw gas from tank into contents
|
||||
var/t1 = src.gas.tot_gas()
|
||||
var/t2 = src.maximum - t1
|
||||
var/t = src.t_per
|
||||
if (src.t_per > t2)
|
||||
t = t2
|
||||
src.gas.transfer_from(src.holding.gas, t)
|
||||
else // otherwise, siphon gas from the turf atmosphere
|
||||
if (T)
|
||||
var/t1 = src.gas.tot_gas()
|
||||
var/t2 = src.maximum - t1
|
||||
var/t = src.t_per
|
||||
if (t > t2)
|
||||
t = t2
|
||||
src.gas.turf_take(T, t)
|
||||
if(4.0) // 4 = automatic mode
|
||||
if( !portable() ) use_power(50, ENVIRON)
|
||||
if (T)
|
||||
if (T.firelevel > 900000.0)
|
||||
src.f_time = world.time + 300 // disable automatic mode for 30 seconds if a fire present
|
||||
else
|
||||
if (world.time > src.f_time)
|
||||
src.gas.extract_toxs(T) // remove toxins (co2, plasma, n2o) from turf into contents
|
||||
if( !portable() ) use_power(150, ENVIRON)
|
||||
var/contain = src.gas.tot_gas() // release excess contents back into turf atmosphere
|
||||
if (contain > 1.3E8)
|
||||
src.gas.turf_add(T, 1.3E8 - contain)
|
||||
|
||||
// Pipe valve status handled by /obj/machinery/connector/process()
|
||||
|
||||
src.setstate()
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
//Foreach goto(654)
|
||||
return
|
||||
|
||||
|
||||
// Set icon state of air filter vent depending on status
|
||||
|
||||
scrubbers/air_filter/setstate()
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "vent-p"
|
||||
return
|
||||
|
||||
if (src.t_status == 4)
|
||||
src.icon_state = "vent2"
|
||||
else
|
||||
if (src.t_status == 3)
|
||||
src.icon_state = "vent0"
|
||||
else
|
||||
src.icon_state = "vent1"
|
||||
return
|
||||
|
||||
|
||||
// Attack air filter vent by item
|
||||
// If screwdriver, attach/unattach from connector (if present)
|
||||
// If wrench, lock/unlock the interface
|
||||
|
||||
scrubbers/air_filter/attackby(obj/item/weapon/W, mob/user)
|
||||
|
||||
if (istype(W, /obj/item/weapon/screwdriver))
|
||||
if (src.c_status)
|
||||
src.anchored = 1
|
||||
src.c_status = 0
|
||||
else
|
||||
if (locate(/obj/machinery/connector, src.loc))
|
||||
src.anchored = 1
|
||||
src.c_status = 3
|
||||
else
|
||||
if (istype(W, /obj/item/weapon/wrench))
|
||||
src.alterable = !( src.alterable )
|
||||
return
|
||||
|
||||
// Reset an air filter vent. Only set automatic mode; do not change valve settings
|
||||
|
||||
scrubbers/air_filter/reset(valve, auto)
|
||||
|
||||
if (auto)
|
||||
src.t_status = 4
|
||||
src.setstate()
|
||||
return
|
||||
|
||||
|
||||
// Set icon state for portable scrubber
|
||||
|
||||
scrubbers/port/setstate()
|
||||
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "scrubber:0"
|
||||
return
|
||||
|
||||
if (src.holding)
|
||||
src.icon_state = "scrubber:T"
|
||||
else
|
||||
if (src.t_status != 3)
|
||||
src.icon_state = "scrubber:1"
|
||||
else
|
||||
src.icon_state = "scrubber:0"
|
||||
return
|
||||
|
||||
|
||||
// Reset valve status for portable scrubber
|
||||
|
||||
scrubbers/port/reset(valve, auto)
|
||||
if (valve < 0)
|
||||
src.t_per = -valve
|
||||
src.t_status = 1
|
||||
else
|
||||
if (valve > 0)
|
||||
src.t_per = valve
|
||||
src.t_status = 2
|
||||
else
|
||||
src.t_status = 3
|
||||
if (auto)
|
||||
src.t_status = 4
|
||||
src.setstate()
|
||||
return
|
||||
@@ -0,0 +1,82 @@
|
||||
/*
|
||||
* Computer -- the base computer machine
|
||||
*
|
||||
*
|
||||
* TODO: Eventual rewrite of computer system from scratch?
|
||||
*/
|
||||
|
||||
|
||||
obj/machinery/computer
|
||||
name = "computer"
|
||||
density = 1
|
||||
anchored = 1
|
||||
|
||||
// Note the icon files for computer objects should have a "broken" and "c_unpowered" state, unless the following procs are overridden.
|
||||
|
||||
|
||||
|
||||
// Called when area power state changes
|
||||
// Display the correct icon depending on the state of the machine
|
||||
|
||||
power_change()
|
||||
if(stat & BROKEN)
|
||||
icon_state = "broken"
|
||||
else
|
||||
if( powered() ) // Defaults to equipment channel
|
||||
icon_state = initial(icon_state)
|
||||
stat &= ~NOPOWER
|
||||
else
|
||||
spawn(rand(0, 15))
|
||||
src.icon_state = "c_unpowered"
|
||||
stat |= NOPOWER
|
||||
|
||||
|
||||
// Default timed process. Use power (as long as computer is operating)
|
||||
|
||||
process()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
use_power(250)
|
||||
|
||||
|
||||
// Default when hit by a meteor. Break the computer, and remove any verbs.
|
||||
|
||||
meteorhit(var/obj/O)
|
||||
for(var/x in src.verbs)
|
||||
src.verbs -= x
|
||||
src.icon_state = "broken"
|
||||
stat |= BROKEN
|
||||
|
||||
|
||||
// Default when attacked by blob. 50% change to break computer.
|
||||
|
||||
blob_act()
|
||||
if (prob(50))
|
||||
for(var/x in src.verbs)
|
||||
src.verbs -= x
|
||||
src.icon_state = "broken"
|
||||
src.stat |= BROKEN
|
||||
src.density = 0
|
||||
|
||||
|
||||
// Default when exploded. Delete or chance to break the computer
|
||||
|
||||
ex_act(severity)
|
||||
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
del(src)
|
||||
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
for(var/x in src.verbs)
|
||||
src.verbs -= x
|
||||
|
||||
src.icon_state = "broken"
|
||||
stat |= BROKEN
|
||||
if(3.0)
|
||||
if (prob(25))
|
||||
for(var/x in src.verbs)
|
||||
src.verbs -= x
|
||||
src.icon_state = "broken"
|
||||
stat |= BROKEN
|
||||
@@ -0,0 +1,156 @@
|
||||
/*
|
||||
* Airtunnel -- the airtunnel computer
|
||||
* Controls extention and retraction of the tunnel, and regulation of the atmosphere in it.
|
||||
*
|
||||
* Note: Currently, only 1 airtunnel per map can be operated; there is no link to the global airtunnel datum
|
||||
*/
|
||||
|
||||
|
||||
obj/machinery/computer/airtunnel
|
||||
name = "Air Tunnel Control"
|
||||
icon = 'airtunnelcomputer.dmi'
|
||||
icon_state = "console00"
|
||||
|
||||
|
||||
// Update icon_state depending on computer and airtunnel status
|
||||
|
||||
proc/update_icon()
|
||||
|
||||
if(stat & BROKEN)
|
||||
icon_state = "broken"
|
||||
return
|
||||
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "c_unpowered"
|
||||
return
|
||||
|
||||
var/status = 0
|
||||
if (SS13_airtunnel.operating == 1)
|
||||
status = "r"
|
||||
else if (SS13_airtunnel.operating == 2)
|
||||
status = "e"
|
||||
else
|
||||
var/obj/move/airtunnel/connector/C = pick(SS13_airtunnel.connectors)
|
||||
|
||||
if (C.current == C)
|
||||
status = 0
|
||||
else if (!( C.current.next ))
|
||||
status = 2
|
||||
else
|
||||
status = 1
|
||||
|
||||
src.icon_state = "console[SS13_airtunnel.siphon_status >= 2 ? "1" : "0"][status]"
|
||||
|
||||
|
||||
// Timed process
|
||||
// Update the icon, use power, and update interaction window for viewers
|
||||
|
||||
process()
|
||||
|
||||
src.update_icon()
|
||||
if(stat & (NOPOWER|BROKEN) )
|
||||
return
|
||||
use_power(250)
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
|
||||
|
||||
|
||||
// Monkey interct same as human
|
||||
|
||||
attack_paw(mob/user)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// Human interact
|
||||
// Show airtunnel status and interaction window
|
||||
|
||||
attack_hand(mob/user)
|
||||
|
||||
if(stat & (NOPOWER|BROKEN) )
|
||||
return
|
||||
|
||||
var/dat = "<HTML><BODY><TT><B>Air Tunnel Controls</B><BR>"
|
||||
user.machine = src
|
||||
|
||||
if (SS13_airtunnel.operating == 1)
|
||||
dat += "<B>Status:</B> RETRACTING<BR>"
|
||||
|
||||
else if (SS13_airtunnel.operating == 2)
|
||||
dat += "<B>Status:</B> EXPANDING<BR>"
|
||||
|
||||
else
|
||||
var/obj/move/airtunnel/connector/C = pick(SS13_airtunnel.connectors)
|
||||
|
||||
if (C.current == C)
|
||||
dat += "<B>Status:</B> Fully Retracted<BR>"
|
||||
else if (!( C.current.next ))
|
||||
dat += "<B>Status:</B> Fully Extended<BR>"
|
||||
else
|
||||
dat += "<B>Status:</B> Stopped Midway<BR>"
|
||||
|
||||
dat += "<A href='?src=\ref[src];retract=1'>Retract</A> <A href='?src=\ref[src];stop=1'>Stop</A> <A href='?src=\ref[src];extend=1'>Extend</A><BR>"
|
||||
dat += "<BR><B>Air Level:</B> [(SS13_airtunnel.air_stat ? "Acceptable" : "DANGEROUS")]<BR>"
|
||||
dat += "<B>Air System Status:</B> "
|
||||
|
||||
switch(SS13_airtunnel.siphon_status)
|
||||
if(0.0)
|
||||
dat += "Stopped "
|
||||
if(1.0)
|
||||
dat += "Siphoning (Siphons only) "
|
||||
if(2.0)
|
||||
dat += "Regulating (BOTH) "
|
||||
if(3.0)
|
||||
dat += "RELEASING MAX (Siphons only) "
|
||||
|
||||
dat += "<A href='?src=\ref[src];refresh=1'>(Refresh)</A><BR>"
|
||||
dat += "<A href='?src=\ref[src];release=1'>RELEASE (Siphons only)</A> <A href='?src=\ref[src];siphon=1'>Siphon (Siphons only)</A> <A href='?src=\ref[src];stop_siph=1'>Stop</A> <A href='?src=\ref[src];auto=1'>Regulate</A><BR>"
|
||||
dat += "<BR><BR><A href='?src=\ref[user];mach_close=computer'>Close</A></TT></BODY></HTML>"
|
||||
|
||||
user << browse(dat, "window=computer;size=400x500")
|
||||
|
||||
|
||||
// Handle topic links from interaction window
|
||||
// Control the airtunnel through the global datum
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
|
||||
if ((!( istype(usr, /mob/human) ) && (!( ticker ) || (ticker && ticker.mode != "monkey"))))
|
||||
usr << "\red You don't have the dexterity to do this!"
|
||||
return
|
||||
if ((usr.stat || usr.restrained()))
|
||||
return
|
||||
if ((usr.contents.Find(src) || (get_dist(src, usr) <= 1 && istype(src.loc, /turf))))
|
||||
usr.machine = src
|
||||
|
||||
if (href_list["retract"])
|
||||
SS13_airtunnel.retract()
|
||||
else if (href_list["stop"])
|
||||
SS13_airtunnel.operating = 0
|
||||
else if (href_list["extend"])
|
||||
SS13_airtunnel.extend()
|
||||
else if (href_list["release"])
|
||||
SS13_airtunnel.siphon_status = 3
|
||||
SS13_airtunnel.siphons()
|
||||
else if (href_list["siphon"])
|
||||
SS13_airtunnel.siphon_status = 1
|
||||
SS13_airtunnel.siphons()
|
||||
else if (href_list["stop_siph"])
|
||||
SS13_airtunnel.siphon_status = 0
|
||||
SS13_airtunnel.siphons()
|
||||
else if (href_list["auto"])
|
||||
SS13_airtunnel.siphon_status = 2
|
||||
SS13_airtunnel.siphons()
|
||||
else if (href_list["refresh"])
|
||||
SS13_airtunnel.siphons()
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Atmosphere -- the base type for atmosphere computers
|
||||
*
|
||||
* Two derived types:
|
||||
* Siphonsiwtch control the siphons and air filters/regulator in an area
|
||||
* Mastersiphonswitch controls all areas in the world, but isn't used in current maps as it's too powerful
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
obj/machinery/computer/atmosphere
|
||||
name = "atmosphere"
|
||||
icon = 'turfs.dmi'
|
||||
|
||||
|
||||
// Prototype: returns the contents of the area that the computer controls
|
||||
// Used to find all the siphon objects in the controlled region
|
||||
|
||||
proc/returnarea()
|
||||
return
|
||||
|
||||
|
||||
// The siphon switch derived type
|
||||
|
||||
siphonswitch
|
||||
name = "Area Air Control"
|
||||
icon_state = "switch"
|
||||
var
|
||||
otherarea // set this for the computer to control an area other than the one its in
|
||||
// e.g. set this to "testlab1" to control /area/testlab1
|
||||
area/area // the area to control. Defaults to the area containing the computer, unless otherarea is set.
|
||||
|
||||
|
||||
// Create a siphonswitch computer
|
||||
// Set the controlled area to the containing area, or to that in the "otherarea" var if set
|
||||
|
||||
New()
|
||||
..()
|
||||
|
||||
spawn(5) // wait for map to finish loading
|
||||
src.area = src.loc.loc
|
||||
if(otherarea)
|
||||
src.area = locate(text2path("/area/[otherarea]"))
|
||||
|
||||
|
||||
// Return the contents of the controlled area
|
||||
|
||||
returnarea()
|
||||
return area.contents
|
||||
|
||||
|
||||
// The verbs for siphonswitch and mastersiphonswitch
|
||||
// Siphons are controlled through the reset() proc for each
|
||||
|
||||
// Switch all siphons on
|
||||
|
||||
verb/siphon_all()
|
||||
set src in oview(1)
|
||||
if(stat & NOPOWER) return
|
||||
if (usr.stat)
|
||||
return
|
||||
usr << "Starting all siphon systems."
|
||||
for(var/obj/machinery/atmoalter/siphs/S in src.returnarea())
|
||||
S.reset(1, 0)
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
|
||||
// Turn off all siphons
|
||||
|
||||
verb/stop_all()
|
||||
set src in oview(1)
|
||||
if(stat & NOPOWER) return
|
||||
if (usr.stat)
|
||||
return
|
||||
usr << "Stopping all siphon systems."
|
||||
for(var/obj/machinery/atmoalter/siphs/S in src.returnarea())
|
||||
S.reset(0, 0)
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
|
||||
// Set all siphons to automatic mode
|
||||
|
||||
verb/auto_on()
|
||||
set src in oview(1)
|
||||
if(stat & NOPOWER) return
|
||||
if (usr.stat)
|
||||
return
|
||||
usr << "Starting automatic air control systems."
|
||||
for(var/obj/machinery/atmoalter/siphs/S in src.returnarea())
|
||||
S.reset(0, 1)
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
|
||||
// Set all scrubber type siphons to release
|
||||
|
||||
verb/release_scrubbers()
|
||||
set src in oview(1)
|
||||
|
||||
if(stat & NOPOWER) return
|
||||
if (usr.stat)
|
||||
return
|
||||
usr << "Releasing all scrubber toxins."
|
||||
for(var/obj/machinery/atmoalter/siphs/scrubbers/S in src.returnarea())
|
||||
S.reset(-1.0, 0)
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
|
||||
// Set all siphons to release
|
||||
|
||||
verb/release_all()
|
||||
set src in oview(1)
|
||||
if(stat & NOPOWER) return
|
||||
if (usr.stat)
|
||||
return
|
||||
usr << "Releasing all stored air."
|
||||
for(var/obj/machinery/atmoalter/siphs/S in src.returnarea())
|
||||
S.reset(-1.0, 0)
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
|
||||
|
||||
// The master siphon switch - controls all siphons in the world
|
||||
// Not used in current maps since it's rather too powerful
|
||||
|
||||
mastersiphonswitch
|
||||
name = "Master Air Control"
|
||||
|
||||
|
||||
// Return the world as the contolled area
|
||||
|
||||
returnarea()
|
||||
return world
|
||||
|
||||
@@ -0,0 +1,287 @@
|
||||
/*
|
||||
* Card -- the identification computer
|
||||
*
|
||||
* Used to alter the settings of an ID card
|
||||
* Also provides a crew manifest
|
||||
*
|
||||
*/
|
||||
|
||||
obj/machinery/computer/card
|
||||
name = "Identification Computer"
|
||||
icon = 'stationobjs.dmi'
|
||||
icon_state = "id_computer"
|
||||
|
||||
var
|
||||
obj/item/weapon/card/id/scan = null // The ID card used to authenticate
|
||||
// Must be assigned to Captain or Head of Personnel
|
||||
obj/item/weapon/card/id/modify = null // The ID card to modify
|
||||
authenticated = 0 // true if Capt/HoP card is authenticated
|
||||
mode = 0 // 0 = show card edit, 1 = show crew manifest
|
||||
printing = null // true if printing the crew manifest
|
||||
|
||||
|
||||
|
||||
// Attack with object same as interact
|
||||
|
||||
attackby(obj/I, mob/user)
|
||||
src.attack_hand(user)
|
||||
|
||||
|
||||
// Monkey interact same as human
|
||||
|
||||
attack_paw(mob/user)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// Human interact.
|
||||
// Show interaction window
|
||||
|
||||
attack_hand(mob/user)
|
||||
|
||||
if(stat & (NOPOWER|BROKEN) ) return
|
||||
|
||||
user.machine = src
|
||||
var/dat
|
||||
if (!( ticker ))
|
||||
return
|
||||
|
||||
if (src.mode)
|
||||
|
||||
var/d2 = "Confirm Identity: <A href='?src=\ref[src];scan=1'>[(src.scan ? text("[]", src.scan.name) : "----------")]</A>\n[(src.authenticated ? "You are logged in!" :"<A href='?src=\ref[src];auth=1'>{Log in}</A>")]"
|
||||
|
||||
var/d1 = "Please use security Records to modify entries.<BR>"
|
||||
for(var/datum/data/record/t in data_core.general)
|
||||
d1 += "[t.fields["name"]] - [t.fields["rank"]]<BR>"
|
||||
|
||||
dat = "<HTML><HEAD></HEAD><BODY><TT>[d2]<BR>\n<BR>\n<B>Crew Manifest:</B><BR>\n[d1]\n<BR>\n<A href='?src=\ref[src];print=1'>Print</A><BR>\n<BR>\n<A href='?src=\ref[src];mode=0'>Access ID modification console.</A><BR>\n</TT></BODY></HTML>"
|
||||
else
|
||||
var/d1 = "<A href='?src=\ref[src];auth=1'>{Log in}</A>"
|
||||
if ((src.authenticated && src.modify))
|
||||
var/vo = null
|
||||
var/va = null
|
||||
var/vl = null
|
||||
var/ve = null
|
||||
switch(src.modify.access_level)
|
||||
if(1.0)
|
||||
vo = "<A href='?src=\ref[src];vo=-1'>0</A> 1 <A href='?src=\ref[src];vo=2'>2</A> <A href='?src=\ref[src];vo=3'>3</A> <A href='?src=\ref[src];vo=4'>4</A> <A href='?src=\ref[src];vo=5'>5</A>"
|
||||
if(2.0)
|
||||
vo = "<A href='?src=\ref[src];vo=-1'>0</A> <A href='?src=\ref[src];vo=1'>1</A> 2 <A href='?src=\ref[src];vo=3'>3</A> <A href='?src=\ref[src];vo=4'>4</A> <A href='?src=\ref[src];vo=5'>5</A>"
|
||||
if(3.0)
|
||||
vo = "<A href='?src=\ref[src];vo=-1'>0</A> <A href='?src=\ref[src];vo=1'>1</A> <A href='?src=\ref[src];vo=2'>2</A> 3 <A href='?src=\ref[src];vo=4'>4</A> <A href='?src=\ref[src];vo=5'>5</A>"
|
||||
if(4.0)
|
||||
vo = "<A href='?src=\ref[src];vo=-1'>0</A> <A href='?src=\ref[src];vo=1'>1</A> <A href='?src=\ref[src];vo=2'>2</A> <A href='?src=\ref[src];vo=3'>3</A> 4 <A href='?src=\ref[src];vo=5'>5</A>"
|
||||
if(5.0)
|
||||
vo = "<A href='?src=\ref[src];vo=-1'>0</A> <A href='?src=\ref[src];vo=1'>1</A> <A href='?src=\ref[src];vo=2'>2</A> <A href='?src=\ref[src];vo=3'>3</A> <A href='?src=\ref[src];vo=4'>4</A> 5"
|
||||
else
|
||||
vo = "0 <A href='?src=\ref[src];vo=1'>1</A> <A href='?src=\ref[src];vo=2'>2</A> <A href='?src=\ref[src];vo=3'>3</A> <A href='?src=\ref[src];vo=4'>4</A> <A href='?src=\ref[src];vo=5'>5</A>"
|
||||
switch(src.modify.lab_access)
|
||||
if(1.0)
|
||||
vl = "<A href='?src=\ref[src];vl=-1'>0</A> 1 <A href='?src=\ref[src];vl=2'>2</A> <A href='?src=\ref[src];vl=3'>3</A> <A href='?src=\ref[src];vl=4'>4</A> <A href='?src=\ref[src];vl=5'>5</A>"
|
||||
if(2.0)
|
||||
vl = "<A href='?src=\ref[src];vl=-1'>0</A> <A href='?src=\ref[src];vl=1'>1</A> 2 <A href='?src=\ref[src];vl=3'>3</A> <A href='?src=\ref[src];vl=4'>4</A> <A href='?src=\ref[src];vl=5'>5</A>"
|
||||
if(3.0)
|
||||
vl = "<A href='?src=\ref[src];vl=-1'>0</A> <A href='?src=\ref[src];vl=1'>1</A> <A href='?src=\ref[src];vl=2'>2</A> 3 <A href='?src=\ref[src];vl=4'>4</A> <A href='?src=\ref[src];vl=5'>5</A>"
|
||||
if(4.0)
|
||||
vl = "<A href='?src=\ref[src];vl=-1'>0</A> <A href='?src=\ref[src];vl=1'>1</A> <A href='?src=\ref[src];vl=2'>2</A> <A href='?src=\ref[src];vl=3'>3</A> 4 <A href='?src=\ref[src];vl=5'>5</A>"
|
||||
if(5.0)
|
||||
vl = "<A href='?src=\ref[src];vl=-1'>0</A> <A href='?src=\ref[src];vl=1'>1</A> <A href='?src=\ref[src];vl=2'>2</A> <A href='?src=\ref[src];vl=3'>3</A> <A href='?src=\ref[src];vl=4'>4</A> 5"
|
||||
else
|
||||
vl = "0 <A href='?src=\ref[src];vl=1'>1</A> <A href='?src=\ref[src];vl=2'>2</A> <A href='?src=\ref[src];vl=3'>3</A> <A href='?src=\ref[src];vl=4'>4</A> <A href='?src=\ref[src];vl=5'>5</A>"
|
||||
switch(src.modify.engine_access)
|
||||
if(1.0)
|
||||
ve = "<A href='?src=\ref[src];ve=-1'>0</A> 1 <A href='?src=\ref[src];ve=2'>2</A> <A href='?src=\ref[src];ve=3'>3</A> <A href='?src=\ref[src];ve=4'>4</A> <A href='?src=\ref[src];ve=5'>5</A>"
|
||||
if(2.0)
|
||||
ve = "<A href='?src=\ref[src];ve=-1'>0</A> <A href='?src=\ref[src];ve=1'>1</A> 2 <A href='?src=\ref[src];ve=3'>3</A> <A href='?src=\ref[src];ve=4'>4</A> <A href='?src=\ref[src];ve=5'>5</A>"
|
||||
if(3.0)
|
||||
ve = "<A href='?src=\ref[src];ve=-1'>0</A> <A href='?src=\ref[src];ve=1'>1</A> <A href='?src=\ref[src];ve=2'>2</A> 3 <A href='?src=\ref[src];ve=4'>4</A> <A href='?src=\ref[src];ve=5'>5</A>"
|
||||
if(4.0)
|
||||
ve = "<A href='?src=\ref[src];ve=-1'>0</A> <A href='?src=\ref[src];ve=1'>1</A> <A href='?src=\ref[src];ve=2'>2</A> <A href='?src=\ref[src];ve=3'>3</A> 4 <A href='?src=\ref[src];ve=5'>5</A>"
|
||||
if(5.0)
|
||||
ve = "<A href='?src=\ref[src];ve=-1'>0</A> <A href='?src=\ref[src];ve=1'>1</A> <A href='?src=\ref[src];ve=2'>2</A> <A href='?src=\ref[src];ve=3'>3</A> <A href='?src=\ref[src];ve=4'>4</A> 5"
|
||||
else
|
||||
ve = "0 <A href='?src=\ref[src];ve=1'>1</A> <A href='?src=\ref[src];ve=2'>2</A> <A href='?src=\ref[src];ve=3'>3</A> <A href='?src=\ref[src];ve=4'>4</A> <A href='?src=\ref[src];ve=5'>5</A>"
|
||||
switch(src.modify.air_access)
|
||||
if(1.0)
|
||||
va = "<A href='?src=\ref[src];va=-1'>0</A> 1 <A href='?src=\ref[src];va=2'>2</A> <A href='?src=\ref[src];va=3'>3</A> <A href='?src=\ref[src];va=4'>4</A> <A href='?src=\ref[src];va=5'>5</A>"
|
||||
if(2.0)
|
||||
va = "<A href='?src=\ref[src];va=-1'>0</A> <A href='?src=\ref[src];va=1'>1</A> 2 <A href='?src=\ref[src];va=3'>3</A> <A href='?src=\ref[src];va=4'>4</A> <A href='?src=\ref[src];va=5'>5</A>"
|
||||
if(3.0)
|
||||
va = "<A href='?src=\ref[src];va=-1'>0</A> <A href='?src=\ref[src];va=1'>1</A> <A href='?src=\ref[src];va=2'>2</A> 3 <A href='?src=\ref[src];va=4'>4</A> <A href='?src=\ref[src];va=5'>5</A>"
|
||||
if(4.0)
|
||||
va = "<A href='?src=\ref[src];va=-1'>0</A> <A href='?src=\ref[src];va=1'>1</A> <A href='?src=\ref[src];va=2'>2</A> <A href='?src=\ref[src];va=3'>3</A> 4 <A href='?src=\ref[src];va=5'>5</A>"
|
||||
if(5.0)
|
||||
va = "<A href='?src=\ref[src];va=-1'>0</A> <A href='?src=\ref[src];va=1'>1</A> <A href='?src=\ref[src];va=2'>2</A> <A href='?src=\ref[src];va=3'>3</A> <A href='?src=\ref[src];va=4'>4</A> 5"
|
||||
else
|
||||
va = "0 <A href='?src=\ref[src];va=1'>1</A> <A href='?src=\ref[src];va=2'>2</A> <A href='?src=\ref[src];va=3'>3</A> <A href='?src=\ref[src];va=4'>4</A> <A href='?src=\ref[src];va=5'>5</A>"
|
||||
|
||||
var/list/L = list( "Research Assistant", "Staff Assistant", "Medical Assistant", "Technical Assistant", "Engineer", "Forensic Technician", "Research Technician", "Medical Doctor", "Captain", "Security Officer", "Medical Researcher", "Toxin Researcher", "Head of Research", "Head of Personnel", "Station Technician", "Atmospheric Technician", "Unassigned", "Systems", "Custom" )
|
||||
var/assign = ""
|
||||
if (istype(user, /mob/human))
|
||||
var/counter = 1
|
||||
for(var/t in L)
|
||||
assign += "<A href='?src=\ref[src];assign=[t]'>[t]</A> "
|
||||
counter++
|
||||
if (counter >= 3)
|
||||
assign += "<BR>"
|
||||
counter = 1
|
||||
|
||||
d1 = "[src.modify.name] :<BR>\nGeneral Access Level: [vo]<BR>\nLaboratory Access: [vl]<BR>\nReactor/Engine Access: [ve]<BR>\nMain Systems Access: [va]<BR>\nRegistered: <A href='?src=\ref[src];reg=1'>[src.modify.registered ? "[src.modify.registered]" : "{None: Click to modify}"]</A><BR>\nAssignment: [src.modify.assignment ? "[src.modify.assignment]" : "None"]<BR>\n[assign]<BR>"
|
||||
else
|
||||
var/counter = 1
|
||||
for(var/t in L)
|
||||
assign += "<A href='?src=\ref[src];assign=[t]'>[stars(t)]</A> "
|
||||
counter++
|
||||
if (counter >= 4)
|
||||
assign += "<BR>"
|
||||
counter = 1
|
||||
|
||||
d1 = "[stars(modify.name)] :<BR>\n[stars("General Access Level:")] [vo]<BR>\n[stars("Laboratory Access:")] [vl]<BR>\n[stars("Reactor/Engine Access:")] [ve]<BR>\n[stars("Main Systems Access:")] [va]<BR>\n[stars("Registered:")] <A href='?src=\ref[src];reg=1'>[src.modify.registered ? stars(src.modify.registered) : stars("{None: Click to modify}")]</A><BR>\n[stars("Assignment:")] [src.modify.assignment ? "[stars(src.modify.assignment)]" : "None"]<BR>\n[assign]<BR>"
|
||||
|
||||
|
||||
if (istype(user, /mob/human))
|
||||
dat = text("<TT><B>Identification Card Modifier</B><BR>\n<I>Please Insert the cards into the slots</I><BR>\nTarget: <A href='?src=\ref[];modify=1'>[]</A><BR>\nConfirm Identity: <A href='?src=\ref[];scan=1'>[]</A><BR>\n-----------------<BR>\n[]<BR>\n<BR>\n<BR>\n<A href='?src=\ref[];mode=1'>Access Crew Manifest</A><BR>\n</TT>", src, (src.modify ? text("[]", src.modify.name) : "----------"), src, (src.scan ? text("[]", src.scan.name) : "----------"), d1, src)
|
||||
else
|
||||
dat = text("<TT><B>[]</B><BR>\n<I>[]</I><BR>\n[] <A href='?src=\ref[];modify=1'>[]</A><BR>\n[] <A href='?src=\ref[];scan=1'>[]</A><BR>\n-----------------<BR>\n[]<BR>\n<BR>\n<BR>\n<A href='?src=\ref[];mode=1'>[]</A><BR>\n</TT>", stars("Identification Card Modifier"), stars("Please Insert the cards into the slots"), stars("Target:"), src, (src.modify ? text("[]", stars(src.modify.name)) : "----------"), stars("Confirm Identity:"), src, (src.scan ? text("[]", stars(src.scan.name)) : "----------"), d1, src, stars("Access Crew Manifest"))
|
||||
user << browse(dat, "window=id_com;size=400x500")
|
||||
|
||||
|
||||
// Handle topic links from interaction window
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
usr << browse(null, "window=id_com")
|
||||
return
|
||||
|
||||
if(usr.restrained() || usr.lying) return
|
||||
|
||||
if ((!( istype(usr, /mob/human) ) && (!( ticker ) || (ticker && ticker.mode != "monkey"))))
|
||||
usr << "\red You don't have the dexterity to do this!"
|
||||
return
|
||||
if ((usr.stat || usr.restrained()))
|
||||
return
|
||||
|
||||
if ((get_dist(src, usr) <= 1 && istype(src.loc, /turf)))
|
||||
usr.machine = src
|
||||
if (href_list["modify"])
|
||||
if (src.modify)
|
||||
src.modify.name = "[src.modify.registered]'s ID Card ([src.modify.access_level]>[src.modify.lab_access]-[src.modify.engine_access]-[src.modify.air_access])"
|
||||
src.modify.loc = src.loc
|
||||
src.modify = null
|
||||
else
|
||||
var/obj/item/I = usr.equipped()
|
||||
if (istype(I, /obj/item/weapon/card/id))
|
||||
usr.drop_item()
|
||||
I.loc = src
|
||||
src.modify = I
|
||||
src.authenticated = 0
|
||||
|
||||
if (href_list["scan"])
|
||||
if (src.scan)
|
||||
src.scan.loc = src.loc
|
||||
src.scan = null
|
||||
else
|
||||
var/obj/item/I = usr.equipped()
|
||||
if (istype(I, /obj/item/weapon/card/id))
|
||||
usr.drop_item()
|
||||
I.loc = src
|
||||
src.scan = I
|
||||
src.authenticated = 0
|
||||
|
||||
if (href_list["auth"])
|
||||
if ((!( src.authenticated ) && src.scan && (src.modify || src.mode)))
|
||||
if ((src.scan.assignment == "Captain" || src.scan.assignment == "Head of Personnel"))
|
||||
src.authenticated = 1
|
||||
|
||||
if (href_list["vo"])
|
||||
if (src.authenticated)
|
||||
var/t1 = text2num(href_list["vo"])
|
||||
if (t1 == -1.0)
|
||||
t1 = 0
|
||||
src.modify.access_level = t1
|
||||
|
||||
if (href_list["vl"])
|
||||
if (src.authenticated)
|
||||
var/t1 = text2num(href_list["vl"])
|
||||
if (t1 == -1.0)
|
||||
t1 = 0
|
||||
src.modify.lab_access = t1
|
||||
|
||||
if (href_list["ve"])
|
||||
if (src.authenticated)
|
||||
var/t1 = text2num(href_list["ve"])
|
||||
if (t1 == -1.0)
|
||||
t1 = 0
|
||||
src.modify.engine_access = t1
|
||||
|
||||
if (href_list["va"])
|
||||
if (src.authenticated)
|
||||
var/t1 = text2num(href_list["va"])
|
||||
if (t1 == -1.0)
|
||||
t1 = 0
|
||||
src.modify.air_access = t1
|
||||
|
||||
if (href_list["assign"])
|
||||
if (src.authenticated)
|
||||
var/t1 = href_list["assign"]
|
||||
|
||||
if(t1 == "Custom")
|
||||
t1 = input("Enter a custom job assignment.","Assignment")
|
||||
|
||||
src.modify.assignment = t1
|
||||
|
||||
if (href_list["reg"])
|
||||
if (src.authenticated)
|
||||
var/t2 = src.modify
|
||||
var/t1 = input(usr, "What name?", "ID computer", null) as text
|
||||
if ((src.authenticated && src.modify == t2 && get_dist(src, usr) <= 1 && istype(src.loc, /turf)))
|
||||
src.modify.registered = t1
|
||||
|
||||
if (href_list["mode"])
|
||||
src.mode = text2num(href_list["mode"])
|
||||
|
||||
if (href_list["print"])
|
||||
if (!( src.printing ))
|
||||
src.printing = 1
|
||||
sleep(50)
|
||||
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( src.loc )
|
||||
var/t1 = "<B>Crew Manifest:</B><BR>"
|
||||
for(var/datum/data/record/t in data_core.general)
|
||||
t1 += "<B>[t.fields["name"]]</B> - [t.fields["rank"]]<BR>"
|
||||
|
||||
P.info = "[t1]"
|
||||
P.name = "paper- 'Crew Manifest'"
|
||||
src.printing = null
|
||||
|
||||
if (href_list["mode"])
|
||||
src.authenticated = 0
|
||||
src.mode = text2num(href_list["mode"])
|
||||
if (src.modify)
|
||||
src.modify.name = "[src.modify.registered]'s ID Card ([src.modify.access_level]>[src.modify.lab_access]-[src.modify.engine_access]-[src.modify.air_access])"
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
else
|
||||
usr << browse(null, "window=id_com")
|
||||
|
||||
|
||||
// Called when area power state changes
|
||||
// Update machione stat and icon_state
|
||||
|
||||
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 = "id_unpowered"
|
||||
stat |= NOPOWER
|
||||
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/*
|
||||
* Communications -- the communications computer
|
||||
*
|
||||
* Used to call the emergency shuttle.
|
||||
*/
|
||||
|
||||
obj/machinery/computer/communications
|
||||
name = "communications"
|
||||
icon = 'stationobjs.dmi'
|
||||
icon_state = "comm_computer"
|
||||
|
||||
|
||||
// Call the shuttle
|
||||
|
||||
verb/call_shuttle()
|
||||
set src in oview(1)
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
if(stat & NOPOWER) return
|
||||
|
||||
if ((!( ticker ) || ticker.shuttle_location == 1))
|
||||
return
|
||||
|
||||
if( ticker.mode == "blob" ) // Shuttle cannot be called in blob mode
|
||||
usr << "Under directive 7-10, SS13 is quarantined until further notice."
|
||||
return
|
||||
|
||||
world << "\blue <B>Alert: The emergency shuttle has been called. It will arrive in T-10:00 minutes.</B>"
|
||||
if (!( ticker.timeleft ))
|
||||
ticker.timeleft = 6000
|
||||
ticker.timing = 1
|
||||
|
||||
|
||||
// Cancel the shuttle call
|
||||
|
||||
verb/cancel_call()
|
||||
set src in oview(1)
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
if(stat & NOPOWER) return
|
||||
if ((!( ticker ) || ticker.shuttle_location == 1 || ticker.timing == 0 || ticker.timeleft < 300))
|
||||
return
|
||||
if( ticker.mode == "blob" )
|
||||
return
|
||||
|
||||
world << "\blue <B>Alert: The shuttle is going back!</B>"
|
||||
ticker.timing = -1.0
|
||||
@@ -0,0 +1,114 @@
|
||||
/*
|
||||
* Data -- A computer that displays data
|
||||
*
|
||||
* All these do is display a list of entries, Each entry can be read to display information about it.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
obj/machinery/computer/data
|
||||
name = "data"
|
||||
icon = 'weap_sat.dmi'
|
||||
icon_state = "computer"
|
||||
|
||||
var
|
||||
list/topics = list( ) // An associative list of entries and content
|
||||
|
||||
|
||||
// Display the list of entries
|
||||
|
||||
verb/display()
|
||||
set src in oview(1)
|
||||
|
||||
for(var/x in src.topics)
|
||||
usr << "[x], \..."
|
||||
|
||||
usr << ""
|
||||
src.add_fingerprint(usr)
|
||||
return
|
||||
|
||||
|
||||
// Display the content of an entry, given the entry name as an argument
|
||||
|
||||
verb/read(topic as text)
|
||||
set src in oview(1)
|
||||
|
||||
if (src.topics[text("[]", topic)])
|
||||
usr << "<B>[topic]</B>\n\t [src.topics["[topic]"]]"
|
||||
else
|
||||
usr << "Unable to find- [topic]"
|
||||
src.add_fingerprint(usr)
|
||||
return
|
||||
|
||||
|
||||
|
||||
weapon
|
||||
name = "weapon"
|
||||
|
||||
info
|
||||
name = "Research Computer"
|
||||
|
||||
// Create the entries and content for this computer
|
||||
|
||||
New()
|
||||
..()
|
||||
src.topics["LOG(001)"] = "System: Deployment successful"
|
||||
src.topics["LOG(002)"] = "System: Safe orbit at inclination .003 established"
|
||||
src.topics["LOG(003)"] = "CenCom: Attempting test fire...ALERT(001)"
|
||||
src.topics["ALERT(001)"] = "System: Cannot attempt test fire"
|
||||
src.topics["LOG(004)"] = "System: Airlock accessed..."
|
||||
src.topics["LOG(005)"] = "System: System successfully reset...Generator engaged"
|
||||
src.topics["LOG(006)"] = "Physical: Super-heater (W005) added to power grid"
|
||||
src.topics["LOG(007)"] = "Physical: Amplifier (W007) added to power grid"
|
||||
src.topics["LOG(008)"] = "Physical: Plasma Energizer (W006) added to power grid"
|
||||
src.topics["LOG(009)"] = "Physical: Laser (W004) added to power grid"
|
||||
src.topics["LOG(010)"] = "Physical: Laser test firing"
|
||||
src.topics["LOG(011)"] = "Physical: Plasma added to Super-heater"
|
||||
src.topics["LOG(012)"] = "Physical: Orient N12.525,E22.124"
|
||||
src.topics["LOG(013)"] = "System: Location N12.525,E22.124"
|
||||
src.topics["LOG(014)"] = "Physical: Test fire...successful"
|
||||
src.topics["LOG(015)"] = "Physical: Airlock accessed..."
|
||||
src.topics["LOG(016)"] = "******: Disable locater systems"
|
||||
src.topics["LOG(017)"] = "System: Locater Beacon-Disengaged,CenCom link-Cut...ALERT(002)"
|
||||
src.topics["ALERT(002)"] = "System: Cannot seem to establish contact with Central Command"
|
||||
src.topics["LOG(018)"] = "******: Shutting down all systems...ALERT(003)"
|
||||
src.topics["ALERT(003)"] = "System: Power grid failure-Activating back-up power...ALERT(004)"
|
||||
src.topics["ALERT(004)"] = "System: Engine failure...All systems deactivated."
|
||||
|
||||
|
||||
// Overrides display verb to show a title
|
||||
|
||||
display()
|
||||
set src in oview(1)
|
||||
|
||||
usr << "<B>Research Information:</B>"
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
log
|
||||
name = "Log Computer"
|
||||
|
||||
|
||||
// Create the list for this computer
|
||||
|
||||
New()
|
||||
..()
|
||||
src.topics["Super-heater"] = "This turns a can of semi-liquid plasma into a super-heated ball of plasma."
|
||||
src.topics["Amplifier"] = "This increases the intensity of a laser."
|
||||
src.topics["Class 11 Laser"] = "This creates a very slow laser that is capable of penetrating most objects."
|
||||
src.topics["Plasma Energizer"] = "This combines super-heated plasma with a laser beam."
|
||||
src.topics["Generator"] = "This controls the entire power grid."
|
||||
src.topics["Mirror"] = "this can reflect LOW power lasers. HIGH power goes through it!"
|
||||
src.topics["Targetting Prism"] = "This focuses a laser coming from any direction forward."
|
||||
|
||||
|
||||
// Override display verb to show a title
|
||||
|
||||
display()
|
||||
set src in oview(1)
|
||||
|
||||
usr << "<B>Research Log:</B>"
|
||||
..()
|
||||
return
|
||||
|
||||
@@ -0,0 +1,133 @@
|
||||
/*
|
||||
* Engine -- engine computer
|
||||
*
|
||||
* Used to eject the engine section, and can also read the gas levels present at a gas sensor
|
||||
*
|
||||
* Most of the ejection logic is contained in the engine_eject datum
|
||||
*/
|
||||
|
||||
/obj/machinery/computer/engine
|
||||
name = "engine"
|
||||
icon = 'enginecomputer.dmi'
|
||||
var
|
||||
temp = null // temporary text string used for interaction window
|
||||
id = 1 // id of gas sensor to display
|
||||
obj/machinery/gas_sensor/gs // the gas sensor object
|
||||
access = "4000/0030" // the access levels required to start ejection timer (Capt, Head, or Engineer)
|
||||
allowed // the job assignments to eject (null = none)
|
||||
|
||||
|
||||
// Create the engine computer, and the global ejector datum if not already exisiting
|
||||
// Also find the gas sensor object matching "id"
|
||||
|
||||
New()
|
||||
if (!( engine_eject_control ))
|
||||
engine_eject_control = new /datum/engine_eject( )
|
||||
..()
|
||||
|
||||
spawn(5)
|
||||
for(var/obj/machinery/gas_sensor/G in machines)
|
||||
if(G.id == src.id)
|
||||
gs = G
|
||||
break
|
||||
|
||||
|
||||
// Timed process
|
||||
// Use power, update interaction window for viewers
|
||||
|
||||
process()
|
||||
if(stat & (NOPOWER|BROKEN) )
|
||||
return
|
||||
use_power(250)
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
|
||||
|
||||
// Attackby object - pass through to interact
|
||||
|
||||
attackby(var/obj/O, mob/user)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// Monkey interact same a human
|
||||
|
||||
attack_paw(var/mob/user as mob)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// Human interact
|
||||
// Show interaction window
|
||||
|
||||
attack_hand(var/mob/user as mob)
|
||||
if(stat & (NOPOWER|BROKEN) )
|
||||
return
|
||||
|
||||
user.machine = src
|
||||
var/dat
|
||||
if (src.temp)
|
||||
dat = "<TT>[src.temp]</TT><BR><BR><A href='?src=\ref[src];temp=1'>Clear Screen</A>"
|
||||
else if (engine_eject_control.status == 0)
|
||||
dat = "<B>Engine Gas Monitor</B><HR>"
|
||||
if(gs)
|
||||
dat += "[gs.sense_string()]"
|
||||
|
||||
else
|
||||
dat += "No sensor found."
|
||||
|
||||
dat += "<BR><B>Engine Ejection Module</B><HR>\nStatus: Docked<BR>\n<BR>\nCountdown: [engine_eject_control.timeleft]/60 <A href='?src=\ref[src];reset=1'>\[Reset\]</A><BR>\n<BR>\n<A href='?src=\ref[src];eject=1'>Eject Engine</A><BR>\n<BR>\n<A href='?src=\ref[user];mach_close=computer'>Close</A>"
|
||||
else
|
||||
if (engine_eject_control.status == 1)
|
||||
dat = "<B>Engine Ejection Module</B><HR>\nStatus: Ejecting<BR>\n<BR>\nCountdown: [engine_eject_control.timeleft]/60 \[Reset\]<BR>\n<BR>\n<A href='?src=\ref[src];stop=1'>Stop Ejection</A><BR>\n<BR>\n<A href='?src=\ref[user];mach_close=computer'>Close</A>"
|
||||
else
|
||||
dat = "<B>Engine Ejection Module</B><HR>\nStatus: Ejected<BR>\n<BR>\nCountdown: N/60 \[Reset\]<BR>\n<BR>\nEngine Ejected!<BR>\n<BR>\n<A href='?src=\ref[user];mach_close=computer'>Close</A>"
|
||||
user << browse(dat, "window=computer;size=400x500")
|
||||
|
||||
|
||||
// Handle topic links from interaction window
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
if ((!( istype(usr, /mob/human) ) && (!( ticker ) || (ticker && ticker.mode != "monkey"))))
|
||||
usr << "\red You don't have the dexterity to do this!"
|
||||
return
|
||||
if ((usr.stat || usr.restrained()))
|
||||
return
|
||||
if ((usr.contents.Find(src) || (get_dist(src, usr) <= 1 && istype(src.loc, /turf))))
|
||||
usr.machine = src
|
||||
|
||||
if (href_list["eject"])
|
||||
if (engine_eject_control.status == 0)
|
||||
src.temp = "Eject Engine?<BR><BR><B><A href='?src=\ref[src];eject2=1'>\[Swipe ID to initiate eject sequence\]</A></B><BR><A href='?src=\ref[src];temp=1'>Cancel</A>"
|
||||
|
||||
else if (href_list["eject2"]) // check ID card against access levels before ejecting
|
||||
var/obj/item/weapon/card/id/I = usr.equipped()
|
||||
if (istype(I))
|
||||
if(I.check_access(access,allowed))
|
||||
if (engine_eject_control.status == 0)
|
||||
engine_eject_control.ejectstart()
|
||||
src.temp = null
|
||||
else
|
||||
usr << "\red Access Denied."
|
||||
else if (href_list["stop"])
|
||||
if (engine_eject_control.status > 0)
|
||||
src.temp = text("Stop Ejection?<BR><BR><A href='?src=\ref[];stop2=1'>Yes</A><BR><A href='?src=\ref[];temp=1'>No</A>", src, src)
|
||||
|
||||
else if (href_list["stop2"])
|
||||
if (engine_eject_control.status > 0)
|
||||
engine_eject_control.stopcount()
|
||||
src.temp = null
|
||||
|
||||
else if (href_list["reset"])
|
||||
if (engine_eject_control.status == 0)
|
||||
engine_eject_control.resetcount()
|
||||
|
||||
else if (href_list["temp"])
|
||||
src.temp = null
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
@@ -0,0 +1,159 @@
|
||||
/*
|
||||
* /obj/machinery/computer/hologram_comp - Hologram computer
|
||||
*
|
||||
* /obj/machinery/holograp_proj - Hologram projector
|
||||
*
|
||||
* /obj/projection - Hologram projection
|
||||
*
|
||||
* Used to display a mob with variable skin colour, hair, etc.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* The hologram computer
|
||||
*/
|
||||
|
||||
|
||||
obj/machinery/computer/hologram_comp
|
||||
name = "Hologram Computer"
|
||||
icon = 'stationobjs.dmi'
|
||||
icon_state = "holo_console0"
|
||||
|
||||
var
|
||||
obj/machinery/hologram_proj/projector = null // the projector object associated with this computer
|
||||
temp = null // temporary text for interaction window (not used)
|
||||
lumens = 0.0 // brightness of the hologram skin image
|
||||
h_r = 245.0 //
|
||||
h_g = 245.0 // RGB settings for the hologram hair
|
||||
h_b = 245.0 //
|
||||
|
||||
|
||||
// Create a new computer
|
||||
// After world has finished loading, located the hologram projector to the north
|
||||
|
||||
New()
|
||||
..()
|
||||
spawn( 10 )
|
||||
src.projector = locate(/obj/machinery/hologram_proj, get_step(src.loc, NORTH))
|
||||
|
||||
|
||||
// Interact when double clicked
|
||||
// Possibly using this instead of usual attack_hand() because its designed to be used before game starts
|
||||
// However this doesn't seem to be necessary in the current code
|
||||
|
||||
DblClick()
|
||||
if (get_dist(src, usr) > 1)
|
||||
return 0
|
||||
src.show_console(usr)
|
||||
|
||||
|
||||
// Render a human male with the current settings
|
||||
// Set the projector to use the resulting icon
|
||||
|
||||
proc/render()
|
||||
var/icon/I = new /icon( 'human.dmi', "male" )
|
||||
if (src.lumens >= 0)
|
||||
I.Blend(rgb(src.lumens, src.lumens, src.lumens), 0)
|
||||
else
|
||||
I.Blend(rgb(- src.lumens, -src.lumens, -src.lumens), 1)
|
||||
I.Blend(new /icon( 'human.dmi', "mouth" ), 3)
|
||||
var/icon/U = new /icon( 'human.dmi', "diaper" )
|
||||
U.Blend(U, 3)
|
||||
U = new /icon( 'mob.dmi', "hair_a" )
|
||||
U.Blend(rgb(src.h_r, src.h_g, src.h_b), 0)
|
||||
I.Blend(U, 3)
|
||||
src.projector.projection.icon = I
|
||||
|
||||
|
||||
// Show interaction window
|
||||
|
||||
proc/show_console(var/mob/user)
|
||||
|
||||
var/dat
|
||||
user.machine = src
|
||||
if (src.temp)
|
||||
dat = "[temp]<BR><BR><A href='?src=\ref[src];temp=1'>Clear</A>"
|
||||
else
|
||||
dat = {"<B>Hologram Status:</B><HR>
|
||||
Power: <A href='?src=\ref[src];power=1'>[(src.projector.projection ? "On" : "Off")]</A><HR>
|
||||
<B>Hologram Control:</B><BR>
|
||||
Color Luminosity: [-src.lumens + 35]/220 <A href='?src=\ref[src];reset=1'>\[Reset\]</A><BR>
|
||||
Lighten: <A href='?src=\ref[src];light=1'>1</A> <A href='?src=\ref[src];light=10'>10</A><BR>
|
||||
Darken: <A href='?src=\ref[src];light=-1'>1</A> <A href='?src=\ref[src];light=-10'>10</A><BR>
|
||||
<BR>
|
||||
Hair Color: ([h_r],[h_g],[h_b]) <A href='?src=\ref[src];h_reset=1'>\[Reset\]</A><BR>
|
||||
Red (0-255): <A href='?src=\ref[src];h_r=-300'>\[0\]</A> <A href='?src=\ref[src];h_r=-10'>-10</A> <A href='?src=\ref[src];h_r=-1'>-1</A> [h_r] <A href='?src=\ref[src];h_r=1'>1</A> <A href='?src=\ref[src];h_r=10'>10</A> <A href='?src=\ref[src];h_r=300'>\[255\]</A><BR>
|
||||
Green (0-255): <A href='?src=\ref[src];h_g=-300'>\[0\]</A> <A href='?src=\ref[src];h_g=-10'>-10</A> <A href='?src=\ref[src];h_g=-1'>-1</A> [h_g] <A href='?src=\ref[src];h_g=1'>1</A> <A href='?src=\ref[src];h_g=10'>10</A> <A href='?src=\ref[src];h_g=300'>\[255\]</A><BR>
|
||||
Blue (0-255): <A href='?src=\ref[src];h_b=-300'>\[0\]</A> <A href='?src=\ref[src];h_b=-10'>-10</A> <A href='?src=\ref[src];h_b=-1'>-1</A> [h_b] <A href='?src=\ref[src];h_b=1'>1</A> <A href='?src=\ref[src];h_b=10'>10</A> <A href='?src=\ref[src];h_b=300'>\[255\]</A><BR>"}
|
||||
user << browse(dat, "window=hologram_console")
|
||||
|
||||
|
||||
// Handle topic links from window
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
if (get_dist(src, usr) <= 1)
|
||||
flick("holo_console1", src)
|
||||
if (href_list["power"])
|
||||
if (src.projector.projection) // remove the current projection
|
||||
src.projector.icon_state = "hologram0"
|
||||
del(src.projector.projection)
|
||||
else // create a new projection
|
||||
src.projector.projection = new /obj/projection( src.projector.loc )
|
||||
src.projector.projection.icon = 'human.dmi'
|
||||
src.projector.projection.icon_state = "male"
|
||||
src.projector.icon_state = "hologram1"
|
||||
src.render()
|
||||
else if (href_list["h_r"])
|
||||
if (src.projector.projection)
|
||||
src.h_r += text2num(href_list["h_r"])
|
||||
src.h_r = min(max(src.h_r, 0), 255)
|
||||
render()
|
||||
else if (href_list["h_g"])
|
||||
if (src.projector.projection)
|
||||
src.h_g += text2num(href_list["h_g"])
|
||||
src.h_g = min(max(src.h_g, 0), 255)
|
||||
render()
|
||||
else if (href_list["h_b"])
|
||||
if (src.projector.projection)
|
||||
src.h_b += text2num(href_list["h_b"])
|
||||
src.h_b = min(max(src.h_b, 0), 255)
|
||||
render()
|
||||
else if (href_list["light"])
|
||||
if (src.projector.projection)
|
||||
src.lumens += text2num(href_list["light"])
|
||||
src.lumens = min(max(src.lumens, -185.0), 35)
|
||||
render()
|
||||
else if (href_list["reset"])
|
||||
if (src.projector.projection)
|
||||
src.lumens = 0
|
||||
render()
|
||||
else if (href_list["temp"])
|
||||
src.temp = null
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.show_console(M)
|
||||
|
||||
|
||||
/*
|
||||
* The hologram projector
|
||||
*/
|
||||
|
||||
|
||||
obj/machinery/hologram_proj
|
||||
name = "Hologram Projector"
|
||||
icon = 'stationobjs.dmi'
|
||||
icon_state = "hologram0"
|
||||
anchored = 1
|
||||
var
|
||||
obj/projection/projection = null // the projection object
|
||||
|
||||
|
||||
/*
|
||||
* The projected hologram
|
||||
*/
|
||||
|
||||
/obj/projection
|
||||
name = "Projection"
|
||||
anchored = 1.0
|
||||
@@ -0,0 +1,399 @@
|
||||
/*
|
||||
* Med_data -- a computer that shows player medical data.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
|
||||
obj/machinery/computer/med_data
|
||||
name = "Medical Records"
|
||||
icon = 'weap_sat.dmi'
|
||||
icon_state = "computer"
|
||||
var
|
||||
obj/item/weapon/card/id/scan = null // ID card inserted in the computer
|
||||
authenticated = null // name on ID card (if has access)
|
||||
rank = null // job assignment of ID card
|
||||
screen = null // active screen displayed
|
||||
// 1=menu, 2=list of records, 3=maint. menu ,4=record edit
|
||||
datum/data/record/active1 = null // selected general record (from data_core.general)
|
||||
datum/data/record/active2 = null // selected medical record (from data_code.medical)
|
||||
a_id = null // not used
|
||||
temp = null // temporary text to show in window
|
||||
printing = null // true if printing a record
|
||||
allowed = "Medical Researcher/Medical Doctor/Head of Personnel/Captain" // the job assignments which have access
|
||||
access // the access levels which have access (none)
|
||||
|
||||
|
||||
// Monkey interact same as human
|
||||
|
||||
attack_paw(mob/user)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// Human interact
|
||||
// Show interaction window
|
||||
|
||||
attack_hand(mob/user)
|
||||
|
||||
var/dat
|
||||
if (src.temp) // show temporary text
|
||||
dat = "<TT>[temp]</TT><BR><BR><A href='?src=\ref[src];temp=1'>Clear Screen</A>"
|
||||
else // show ID card inserted
|
||||
dat = "Confirm Identity: <A href='?src=\ref[src];scan=1'>[src.scan ? "[src.scan.name]" : "----------"]</A><HR>"
|
||||
if (src.authenticated)
|
||||
switch(src.screen)
|
||||
if(1.0)
|
||||
dat += {"<A href='?src=\ref[src];search=1'>Search Records</A><BR>
|
||||
<A href='?src=\ref[src];list=1'>List Records</A><BR>
|
||||
<BR>
|
||||
<A href='?src=\ref[src];rec_m=1'>Record Maintenance</A><BR>
|
||||
<A href='?src=\ref[src];logout=1'>{Log Out}</A><BR>
|
||||
"}
|
||||
if(2.0)
|
||||
dat += "<B>Record List</B>:<HR>"
|
||||
for(var/datum/data/record/R in data_core.general)
|
||||
dat += "<A href='?src=\ref[src];d_rec=\ref[R]'>[R.fields["id"]]: [R.fields["name"]]<BR>"
|
||||
|
||||
dat += "<HR><A href='?src=\ref[src];main=1'>Back</A>"
|
||||
if(3.0)
|
||||
dat += {"<B>Records Maintenance</B><HR>
|
||||
<A href='?src=\ref[src];back=1'>Backup To Disk</A><BR>
|
||||
<A href='?src=\ref[src];u_load=1'>Upload From disk</A><BR>
|
||||
<A href='?src=\ref[src];del_all=1'>Delete All Records</A><BR>
|
||||
<BR>
|
||||
<A href='?src=\ref[src];main=1'>Back</A>"}
|
||||
|
||||
if(4.0)
|
||||
dat += "<CENTER><B>Medical Record</B></CENTER><BR>"
|
||||
if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1)))
|
||||
dat += {"Name: [src.active1.fields["name"]] ID: [src.active1.fields["id"]]<BR>
|
||||
Sex: <A href='?src=\ref[src];field=sex'>[src.active1.fields["sex"]]</A><BR>
|
||||
Age: <A href='?src=\ref[src];field=age'>[src.active1.fields["age"]]</A><BR>
|
||||
Fingerprint: <A href='?src=\ref[src];field=fingerprint'>[src.active1.fields["fingerprint"]]</A><BR>
|
||||
Physical Status: <A href='?src=\ref[src];field=p_stat'>[src.active1.fields["p_stat"]]</A><BR>
|
||||
Mental Status: <A href='?src=\ref[src];field=m_stat'>[src.active1.fields["m_stat"]]</A><BR>"}
|
||||
|
||||
else
|
||||
dat += "<B>General Record Lost!</B><BR>"
|
||||
if ((istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2)))
|
||||
dat += {"<BR>
|
||||
<CENTER><B>Medical Data</B></CENTER><BR>
|
||||
Blood Type: <A href='?src=\ref[src];field=b_type'>[src.active2.fields["b_type"]]</A><BR>
|
||||
<BR>
|
||||
Minor Disabilities: <A href='?src=\ref[src];field=mi_dis'>[src.active2.fields["mi_dis"]]</A><BR>
|
||||
Details: <A href='?src=\ref[src];field=mi_dis_d'>[src.active2.fields["mi_dis_d"]]</A><BR>
|
||||
<BR>
|
||||
Major Disabilities: <A href='?src=\ref[src];field=ma_dis'>[src.active2.fields["ma_dis"]]</A><BR>
|
||||
Details: <A href='?src=\ref[src];field=ma_dis_d'>[src.active2.fields["ma_dis_d"]]</A><BR>
|
||||
<BR>
|
||||
Allergies: <A href='?src=\ref[src];field=alg'>[src.active2.fields["alg"]]</A><BR>
|
||||
Details: <A href='?src=\ref[src];field=alg_d'>[src.active2.fields["alg_d"]]</A><BR>
|
||||
<BR>
|
||||
Current Diseases: <A href='?src=\ref[src];field=cdi'>[src.active2.fields["cdi"]]</A> (per disease info placed in log/comment section)<BR>
|
||||
Details: <A href='?src=\ref[src];field=cdi_d'>[src.active2.fields["cdi_d"]]</A><BR>
|
||||
<BR>
|
||||
Important Notes:<BR>
|
||||
<A href='?src=\ref[src];field=notes'>[src.active2.fields["notes"]]</A><BR>
|
||||
<BR>
|
||||
<CENTER><B>Comments/Log</B></CENTER><BR>"}
|
||||
|
||||
var/counter = 1
|
||||
while(src.active2.fields["com_[counter]"])
|
||||
dat += "[src.active2.fields["com_[counter]"]]<BR><A href='?src=\ref[src];del_c=[counter]'>Delete Entry</A><BR><BR>"
|
||||
counter++
|
||||
dat += "<A href='?src=\ref[src];add_c=1'>Add Entry</A><BR><BR>"
|
||||
dat += "<A href='?src=\ref[src];del_r=1'>Delete Record (Medical Only)</A><BR><BR>"
|
||||
else
|
||||
dat += "<B>Medical Record Lost!</B><BR>"
|
||||
dat += "<A href='?src=\ref[src];new=1'>New Record</A><BR><BR>"
|
||||
dat += "\n<A href='?src=\ref[src];print_p=1'>Print Record</A><BR>\n<A href='?src=\ref[src];list=1'>Back</A><BR>"
|
||||
|
||||
else
|
||||
dat += "<A href='?src=\ref[src];login=1'>{Log In}</A>"
|
||||
user << browse("<HEAD><TITLE>Medical Records</TITLE></HEAD><TT>[dat]</TT>", "window=med_rec")
|
||||
|
||||
|
||||
|
||||
// Handle topic links from interaction window
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
if (!( data_core.general.Find(src.active1) ))
|
||||
src.active1 = null
|
||||
if (!( data_core.medical.Find(src.active2) ))
|
||||
src.active2 = null
|
||||
if ((usr.stat || usr.restrained()))
|
||||
return
|
||||
if ((usr.contents.Find(src) || (get_dist(src, usr) <= 1 && istype(src.loc, /turf))))
|
||||
|
||||
usr.machine = src
|
||||
if (href_list["temp"])
|
||||
src.temp = null // close the temporary display
|
||||
if (href_list["scan"])
|
||||
if (src.scan)
|
||||
src.scan.loc = src.loc // remove ID card from computer
|
||||
src.scan = null
|
||||
else
|
||||
var/obj/item/I = usr.equipped()
|
||||
if (istype(I, /obj/item/weapon/card/id))
|
||||
usr.drop_item()
|
||||
I.loc = src // insert ID card into computer
|
||||
src.scan = I
|
||||
else if (href_list["logout"])
|
||||
src.authenticated = null
|
||||
src.screen = null
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
else if (href_list["login"]) // check inserted ID card against access requirements
|
||||
if (istype(src.scan, /obj/item/weapon/card/id))
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
if(scan.check_access(access, allowed))
|
||||
src.authenticated = src.scan.registered
|
||||
src.rank = src.scan.assignment
|
||||
src.screen = 1
|
||||
if (src.authenticated)
|
||||
if (href_list["list"])
|
||||
src.screen = 2
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
else if (href_list["rec_m"])
|
||||
src.screen = 3
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
else if (href_list["del_all"])
|
||||
src.temp = "Are you sure you wish to delete all records?<br>\n\t<A href='?src=\ref[src];temp=1;del_all2=1'>Yes</A><br>\n\t<A href='?src=\ref[src];temp=1'>No</A><br>"
|
||||
else if (href_list["del_all2"])
|
||||
for(var/datum/data/record/R in data_core.medical)
|
||||
del(R)
|
||||
src.temp = "All records deleted."
|
||||
else if (href_list["main"])
|
||||
src.screen = 1
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
|
||||
else if (href_list["field"]) // edit fields
|
||||
var/a1 = src.active1
|
||||
var/a2 = src.active2
|
||||
switch(href_list["field"])
|
||||
if("fingerprint")
|
||||
if (istype(src.active1, /datum/data/record))
|
||||
var/t1 = input("Please input fingerprint hash:", "Med. records", src.active1.fields["id"], null) as text
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || get_dist(src, usr) > 1 || src.active1 != a1))
|
||||
return
|
||||
src.active1.fields["fingerprint"] = t1
|
||||
if("sex")
|
||||
if (istype(src.active1, /datum/data/record))
|
||||
if (src.active1.fields["sex"] == "Male")
|
||||
src.active1.fields["sex"] = "Female"
|
||||
else
|
||||
src.active1.fields["sex"] = "Male"
|
||||
if("age")
|
||||
if (istype(src.active1, /datum/data/record))
|
||||
var/t1 = input("Please input age:", "Med. records", src.active1.fields["age"], null) as text
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || get_dist(src, usr) > 1 || src.active1 != a1))
|
||||
return
|
||||
src.active1.fields["age"] = t1
|
||||
if("mi_dis")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please input minor disabilities list:", "Med. records", src.active2.fields["mi_dis"], null) as text
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || get_dist(src, usr) > 1 || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["mi_dis"] = t1
|
||||
if("mi_dis_d")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please summarize minor dis.:", "Med. records", src.active2.fields["mi_dis_d"], null) as message
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || get_dist(src, usr) > 1 || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["mi_dis_d"] = t1
|
||||
if("ma_dis")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please input major diabilities list:", "Med. records", src.active2.fields["ma_dis"], null) as text
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || get_dist(src, usr) > 1 || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["ma_dis"] = t1
|
||||
if("ma_dis_d")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please summarize major dis.:", "Med. records", src.active2.fields["ma_dis_d"], null) as message
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || get_dist(src, usr) > 1 || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["ma_dis_d"] = t1
|
||||
if("alg")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please state allergies:", "Med. records", src.active2.fields["alg"], null) as text
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || get_dist(src, usr) > 1 || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["alg"] = t1
|
||||
if("alg_d")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please summarize allergies:", "Med. records", src.active2.fields["alg_d"], null) as message
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || get_dist(src, usr) > 1 || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["alg_d"] = t1
|
||||
if("cdi")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please state diseases:", "Med. records", src.active2.fields["cdi"], null) as text
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || get_dist(src, usr) > 1 || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["cdi"] = t1
|
||||
if("cdi_d")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please summarize diseases:", "Med. records", src.active2.fields["cdi_d"], null) as message
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || get_dist(src, usr) > 1 || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["cdi_d"] = t1
|
||||
if("notes")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please summarize notes:", "Med. records", src.active2.fields["notes"], null) as message
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || get_dist(src, usr) > 1 || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["notes"] = t1
|
||||
if("p_stat")
|
||||
if (istype(src.active1, /datum/data/record))
|
||||
src.temp = text("<B>Physical Condition:</B><BR>\n\t<A href='?src=\ref[];temp=1;p_stat=deceased'>*Deceased*</A><BR>\n\t<A href='?src=\ref[];temp=1;p_stat=unconscious'>*Unconscious*</A><BR>\n\t<A href='?src=\ref[];temp=1;p_stat=active'>Active</A><BR>\n\t<A href='?src=\ref[];temp=1;p_stat=unfit'>Physically Unfit</A><BR>", src, src, src, src)
|
||||
if("m_stat")
|
||||
if (istype(src.active1, /datum/data/record))
|
||||
src.temp = text("<B>Mental Condition:</B><BR>\n\t<A href='?src=\ref[];temp=1;m_stat=insane'>*Insane*</A><BR>\n\t<A href='?src=\ref[];temp=1;m_stat=unstable'>*Unstable*</A><BR>\n\t<A href='?src=\ref[];temp=1;m_stat=watch'>*Watch*</A><BR>\n\t<A href='?src=\ref[];temp=1;m_stat=stable'>Stable</A><BR>", src, src, src, src)
|
||||
if("b_type")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
src.temp = text("<B>Blood Type:</B><BR>\n\t<A href='?src=\ref[];temp=1;b_type=an'>A-</A> <A href='?src=\ref[];temp=1;b_type=ap'>A+</A><BR>\n\t<A href='?src=\ref[];temp=1;b_type=bn'>B-</A> <A href='?src=\ref[];temp=1;b_type=bp'>B+</A><BR>\n\t<A href='?src=\ref[];temp=1;b_type=abn'>AB-</A> <A href='?src=\ref[];temp=1;b_type=abp'>AB+</A><BR>\n\t<A href='?src=\ref[];temp=1;b_type=on'>O-</A> <A href='?src=\ref[];temp=1;b_type=op'>O+</A><BR>", src, src, src, src, src, src, src, src)
|
||||
|
||||
else if (href_list["p_stat"])
|
||||
if (src.active1)
|
||||
switch(href_list["p_stat"])
|
||||
if("deceased")
|
||||
src.active1.fields["p_stat"] = "*Deceased*"
|
||||
if("unconscious")
|
||||
src.active1.fields["p_stat"] = "*Unconscious*"
|
||||
if("active")
|
||||
src.active1.fields["p_stat"] = "Active"
|
||||
if("unfit")
|
||||
src.active1.fields["p_stat"] = "Physically Unfit"
|
||||
else if (href_list["m_stat"])
|
||||
if (src.active1)
|
||||
switch(href_list["m_stat"])
|
||||
if("insane")
|
||||
src.active1.fields["m_stat"] = "*Insane*"
|
||||
if("unstable")
|
||||
src.active1.fields["m_stat"] = "*Unstable*"
|
||||
if("watch")
|
||||
src.active1.fields["m_stat"] = "*Watch*"
|
||||
if("stable")
|
||||
src.active2.fields["m_stat"] = "Stable"
|
||||
|
||||
else if (href_list["b_type"])
|
||||
if (src.active2)
|
||||
switch(href_list["b_type"])
|
||||
if("an")
|
||||
src.active2.fields["b_type"] = "A-"
|
||||
if("bn")
|
||||
src.active2.fields["b_type"] = "B-"
|
||||
if("abn")
|
||||
src.active2.fields["b_type"] = "AB-"
|
||||
if("on")
|
||||
src.active2.fields["b_type"] = "O-"
|
||||
if("ap")
|
||||
src.active2.fields["b_type"] = "A+"
|
||||
if("bp")
|
||||
src.active2.fields["b_type"] = "B+"
|
||||
if("abp")
|
||||
src.active2.fields["b_type"] = "AB+"
|
||||
if("op")
|
||||
src.active2.fields["b_type"] = "O+"
|
||||
|
||||
else if (href_list["del_r"])
|
||||
if (src.active2)
|
||||
src.temp = text("Are you sure you wish to delete the record (Medical Portion Only)?<br>\n\t<A href='?src=\ref[];temp=1;del_r2=1'>Yes</A><br>\n\t<A href='?src=\ref[];temp=1'>No</A><br>", src, src)
|
||||
else if (href_list["del_r2"])
|
||||
if (src.active2)
|
||||
del(src.active2)
|
||||
else if (href_list["d_rec"])
|
||||
var/datum/data/record/R = locate(href_list["d_rec"])
|
||||
var/datum/data/record/M = locate(href_list["d_rec"])
|
||||
if (!( data_core.general.Find(R) ))
|
||||
src.temp = "Record Not Found!"
|
||||
return
|
||||
for(var/datum/data/record/E in data_core.medical)
|
||||
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
|
||||
M = E
|
||||
src.active1 = R
|
||||
src.active2 = M
|
||||
src.screen = 4
|
||||
else if (href_list["new"])
|
||||
if ((istype(src.active1, /datum/data/record) && !( istype(src.active2, /datum/data/record) )))
|
||||
var/datum/data/record/R = new /datum/data/record( )
|
||||
R.fields["name"] = src.active1.fields["name"]
|
||||
R.fields["id"] = src.active1.fields["id"]
|
||||
R.name = text("Medical Record #[]", R.fields["id"])
|
||||
R.fields["b_type"] = "Unknown"
|
||||
R.fields["mi_dis"] = "None"
|
||||
R.fields["mi_dis_d"] = "No minor disabilities have been declared."
|
||||
R.fields["ma_dis"] = "None"
|
||||
R.fields["ma_dis_d"] = "No major disabilities have been diagnosed."
|
||||
R.fields["alg"] = "None"
|
||||
R.fields["alg_d"] = "No allergies have been detected in this patient."
|
||||
R.fields["cdi"] = "None"
|
||||
R.fields["cdi_d"] = "No diseases have been diagnosed at the moment."
|
||||
R.fields["notes"] = "No notes."
|
||||
data_core.medical += R
|
||||
src.active2 = R
|
||||
src.screen = 4
|
||||
else if (href_list["add_c"])
|
||||
if (!( istype(src.active2, /datum/data/record) ))
|
||||
return
|
||||
var/a2 = src.active2
|
||||
var/t1 = input("Add Comment:", "Med. records", null, null) as message
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || get_dist(src, usr) > 1 || src.active2 != a2))
|
||||
return
|
||||
var/counter = 1
|
||||
while(src.active2.fields[text("com_[]", counter)])
|
||||
counter++
|
||||
src.active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [], 2053<BR>[]", src.authenticated, src.rank, time2text(world.realtime, "DDD MMM DD hh:mm:ss"), t1)
|
||||
else if (href_list["del_c"])
|
||||
if ((istype(src.active2, /datum/data/record) && src.active2.fields[text("com_[]", href_list["del_c"])]))
|
||||
src.active2.fields[text("com_[]", href_list["del_c"])] = "<B>Deleted</B>"
|
||||
else if (href_list["search"])
|
||||
var/t1 = input("Search String: (Name or ID)", "Med. records", null, null) as text
|
||||
if ((!( t1 ) || usr.stat || !( src.authenticated ) || usr.restrained() || get_dist(src, usr) > 1))
|
||||
return
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
t1 = lowertext(t1)
|
||||
for(var/datum/data/record/R in data_core.general)
|
||||
if ((lowertext(R.fields["name"]) == t1 || t1 == lowertext(R.fields["id"])))
|
||||
src.active1 = R
|
||||
if (!( src.active1 ))
|
||||
src.temp = text("Could not locate record [].", t1)
|
||||
else
|
||||
for(var/datum/data/record/E in data_core.medical)
|
||||
if ((E.fields["name"] == src.active1.fields["name"] || E.fields["id"] == src.active1.fields["id"]))
|
||||
src.active2 = E
|
||||
src.screen = 4
|
||||
else if (href_list["print_p"])
|
||||
if (!( src.printing ))
|
||||
src.printing = 1
|
||||
sleep(50)
|
||||
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( src.loc )
|
||||
P.info = "<CENTER><B>Medical Record</B></CENTER><BR>"
|
||||
if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1)))
|
||||
P.info += text("Name: [] ID: []<BR>\nSex: []<BR>\nAge: []<BR>\nFingerprint: []<BR>\nPhysical Status: []<BR>\nMental Status: []<BR>", src.active1.fields["name"], src.active1.fields["id"], src.active1.fields["sex"], src.active1.fields["age"], src.active1.fields["fingerprint"], src.active1.fields["p_stat"], src.active1.fields["m_stat"])
|
||||
else
|
||||
P.info += "<B>General Record Lost!</B><BR>"
|
||||
if ((istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2)))
|
||||
P.info += text("<BR>\n<CENTER><B>Medical Data</B></CENTER><BR>\nBlood Type: []<BR>\n<BR>\nMinor Disabilities: []<BR>\nDetails: []<BR>\n<BR>\nMajor Disabilities: []<BR>\nDetails: []<BR>\n<BR>\nAllergies: []<BR>\nDetails: []<BR>\n<BR>\nCurrent Diseases: [] (per disease info placed in log/comment section)<BR>\nDetails: []<BR>\n<BR>\nImportant Notes:<BR>\n\t[]<BR>\n<BR>\n<CENTER><B>Comments/Log</B></CENTER><BR>", src.active2.fields["b_type"], src.active2.fields["mi_dis"], src.active2.fields["mi_dis_d"], src.active2.fields["ma_dis"], src.active2.fields["ma_dis_d"], src.active2.fields["alg"], src.active2.fields["alg_d"], src.active2.fields["cdi"], src.active2.fields["cdi_d"], src.active2.fields["notes"])
|
||||
var/counter = 1
|
||||
while(src.active2.fields[text("com_[]", counter)])
|
||||
P.info += text("[]<BR>", src.active2.fields[text("com_[]", counter)])
|
||||
counter++
|
||||
else
|
||||
P.info += "<B>Medical Record Lost!</B><BR>"
|
||||
P.info += "</TT>"
|
||||
P.name = "paper- 'Medical Record'"
|
||||
src.printing = null
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
@@ -0,0 +1,226 @@
|
||||
/*
|
||||
* Pod computer -- controls launch of escape pods
|
||||
*
|
||||
* Mass driver - launches the pods
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* The pod computer
|
||||
*/
|
||||
|
||||
obj/machinery/computer/pod
|
||||
name = "Pod Launch Control"
|
||||
icon = 'escapepod.dmi'
|
||||
icon_state = "computer"
|
||||
|
||||
var
|
||||
id = 1.0 // ID of mass driver(s) and poddoors to control
|
||||
obj/machinery/mass_driver/connected = null // the controlled mass driver
|
||||
timing = 0.0 // true if counting down before launch
|
||||
time = 30.0 // time (seconds) to count down
|
||||
|
||||
// Note: Only one massdriver is located via connected, but all drivers with matching ID are fired together
|
||||
|
||||
|
||||
// Create a new pod computer
|
||||
// Locate and set a massdriver with the same ID
|
||||
|
||||
New()
|
||||
..()
|
||||
spawn( 5 )
|
||||
for(var/obj/machinery/mass_driver/M in machines)
|
||||
if (M.id == src.id)
|
||||
src.connected = M
|
||||
|
||||
|
||||
// Called to fire the driver
|
||||
// Open the poddoors with same ID, fire the matching mass drivers, then close the doors
|
||||
|
||||
proc/alarm()
|
||||
|
||||
if(stat & (NOPOWER|BROKEN)) return
|
||||
|
||||
if (!( src.connected ))
|
||||
viewers(null, null) << "Cannot locate mass driver connector. Cancelling firing sequence!"
|
||||
return
|
||||
|
||||
for(var/obj/machinery/door/poddoor/M in machines)
|
||||
if (M.id == src.id)
|
||||
spawn( 0 )
|
||||
M.openpod()
|
||||
return
|
||||
|
||||
sleep(20)
|
||||
|
||||
// Note updated from 40.93.3S source - all massdrivers with same ID are fired
|
||||
// (Previously, only the connected driver was fired)
|
||||
for(var/obj/machinery/mass_driver/M in machines)
|
||||
if(M.id == src.id)
|
||||
M.power = src.connected.power
|
||||
M.drive()
|
||||
//
|
||||
|
||||
sleep(50)
|
||||
for(var/obj/machinery/door/poddoor/M in machines)
|
||||
if (M.id == src.id)
|
||||
spawn( 0 )
|
||||
M.closepod()
|
||||
return
|
||||
|
||||
|
||||
// Monkey interact same as human
|
||||
|
||||
attack_paw(mob/user)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// Human interact, show window
|
||||
|
||||
attack_hand(mob/user)
|
||||
|
||||
if(stat & (NOPOWER|BROKEN)) return
|
||||
|
||||
var/dat = "<HTML><BODY><TT><B>Mass Driver Controls</B>"
|
||||
user.machine = src
|
||||
var/d2
|
||||
if (src.timing)
|
||||
d2 = "<A href='?src=\ref[src];time=0'>Stop Time Launch</A>"
|
||||
else
|
||||
d2 = "<A href='?src=\ref[src];time=1'>Initiate Time Launch</A>"
|
||||
var/second = src.time % 60
|
||||
var/minute = (src.time - second) / 60
|
||||
dat += {"<HR>
|
||||
Timer System: [d2]
|
||||
Time Left: [(minute ? "[minute]:" : null)][second] <A href='?src=\ref[src];tp=-30'>-</A> <A href='?src=\ref[src];tp=-1'>-</A> <A href='?src=\ref[src];tp=1'>+</A> <A href='?src=\ref[src];tp=30'>+</A>"}
|
||||
|
||||
if (src.connected)
|
||||
var/temp = ""
|
||||
var/list/L = list( 0.25, 0.5, 1, 2, 4, 8, 16 )
|
||||
for(var/t in L)
|
||||
if (t == src.connected.power)
|
||||
temp += "[t] "
|
||||
else
|
||||
temp += "<A href = '?src=\ref[src];power=[t]'>[t]</A> "
|
||||
|
||||
dat += "<HR>\nPower Level: [temp]<BR>\n<A href = '?src=\ref[src];alarm=1'>Firing Sequence</A><BR>\n<A href = '?src=\ref[src];drive=1'>Test Fire Driver</A><BR>\n<A href = '?src=\ref[src];door=1'>Toggle Outer Door</A><BR>"
|
||||
|
||||
else
|
||||
dat += "<BR>\n<A href = '?src=\ref[src];door=1'>Toggle Outer Door</A><BR>"
|
||||
|
||||
dat += "<BR><BR><A href='?src=\ref[user];mach_close=computer'>Close</A></TT></BODY></HTML>"
|
||||
user << browse(dat, "window=computer;size=400x500")
|
||||
|
||||
|
||||
// Handle topic links from interaction window
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
usr << browse(null, "window=computer")
|
||||
return
|
||||
|
||||
if(usr.restrained() || usr.lying) return
|
||||
|
||||
if ((!( istype(usr, /mob/human) ) && (!( ticker ) || (ticker && ticker.mode != "monkey"))))
|
||||
usr << "\red You don't have the dexterity to do this!"
|
||||
return
|
||||
if ((usr.stat || usr.restrained()))
|
||||
return
|
||||
if ((usr.contents.Find(src) || (get_dist(src, usr) <= 1 && istype(src.loc, /turf))))
|
||||
usr.machine = src
|
||||
if (href_list["power"])
|
||||
var/t = text2num(href_list["power"])
|
||||
t = min(max(0.25, t), 16)
|
||||
if (src.connected)
|
||||
src.connected.power = t
|
||||
else if (href_list["alarm"])
|
||||
src.alarm()
|
||||
else if (href_list["time"])
|
||||
src.timing = text2num(href_list["time"])
|
||||
else if (href_list["tp"])
|
||||
var/tp = text2num(href_list["tp"])
|
||||
src.time += tp
|
||||
src.time = min(max(round(src.time), 0), 120)
|
||||
else if (href_list["door"])
|
||||
for(var/obj/machinery/door/poddoor/M in machines)
|
||||
if (M.id == src.id)
|
||||
if (M.density)
|
||||
spawn( 0 )
|
||||
M.openpod()
|
||||
return
|
||||
else
|
||||
spawn( 0 )
|
||||
M.closepod()
|
||||
return
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
//Foreach goto(394)
|
||||
return
|
||||
|
||||
|
||||
// Timed process
|
||||
// Countdown timer and fire when zero reached
|
||||
|
||||
process()
|
||||
if(stat & (NOPOWER|BROKEN) )
|
||||
return
|
||||
use_power(250)
|
||||
|
||||
if (src.timing)
|
||||
if (src.time > 0)
|
||||
src.time = round(src.time) - 1
|
||||
else
|
||||
alarm()
|
||||
src.time = 0
|
||||
src.timing = 0
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* The mass driver
|
||||
*/
|
||||
|
||||
obj/machinery/mass_driver
|
||||
name = "mass driver"
|
||||
icon = 'stationobjs.dmi'
|
||||
icon_state = "mass_driver"
|
||||
anchored = 1
|
||||
var
|
||||
power = 1.0 // The power level to launch the pod
|
||||
id = 1.0 // ID of the mass driver. Pod computer must have matching ID.
|
||||
|
||||
|
||||
|
||||
// Fire the driver
|
||||
// All objects at the location (that have the DRIVABLE flag) are launched in the direction of the driver
|
||||
// Show the firing animation
|
||||
|
||||
proc/drive(amount)
|
||||
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
|
||||
use_power(500)
|
||||
for(var/obj/O in src.loc)
|
||||
if (O.flags & DRIVABLE)
|
||||
O.throwing = 1
|
||||
O.throwspeed = 100
|
||||
spawn( 0 )
|
||||
O.throwing(src.dir, src.power)
|
||||
return
|
||||
|
||||
flick("mass_driver1", src)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
/*
|
||||
* Prison shuttle -- prision shuttle control computer
|
||||
*
|
||||
* TODO: Allow prision shuttle Z level to be adjusted more easily (marker on map)
|
||||
*/
|
||||
|
||||
#define PRISON_SHUTTLE_Z 8 // Z level of the prison station
|
||||
|
||||
|
||||
obj/machinery/computer/prison_shuttle
|
||||
name = "prison shuttle"
|
||||
icon = 'shuttle.dmi'
|
||||
icon_state = "shuttlecom"
|
||||
|
||||
|
||||
// Take off verb
|
||||
// Move the shuttle (and all objects in it) between station and prison Z level
|
||||
|
||||
verb/take_off()
|
||||
set src in oview(1)
|
||||
|
||||
if ((usr.stat || usr.restrained()))
|
||||
return
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
if (prison_entered) // shuttle is at station
|
||||
var/A = locate(/area/shuttle)
|
||||
for(var/turf/T in A)
|
||||
if (T.z == 1)
|
||||
for(var/atom/movable/AM in T)
|
||||
AM.z = PRISON_SHUTTLE_Z
|
||||
var/turf/U = locate(T.x, T.y, PRISON_SHUTTLE_Z) // move to prison level
|
||||
U.oxygen = T.oxygen
|
||||
U.oldoxy = T.oldoxy
|
||||
U.tmpoxy = T.tmpoxy
|
||||
U.poison = T.poison
|
||||
U.oldpoison = T.oldpoison
|
||||
U.tmppoison = T.tmppoison
|
||||
U.co2 = T.co2
|
||||
U.oldco2 = T.oldco2
|
||||
U.tmpco2 = T.tmpco2
|
||||
del(T)
|
||||
prison_entered = null
|
||||
else if (!( prison_entered )) // shuttle is at prision
|
||||
if (ticker.shuttle_location != 1) // make sure emergency shuttle isn't at station
|
||||
var/A = locate(/area/shuttle_prison)
|
||||
for(var/turf/T in A)
|
||||
if (T.z == PRISON_SHUTTLE_Z)
|
||||
for(var/atom/movable/AM in T)
|
||||
AM.z = 1
|
||||
var/turf/U = locate(T.x, T.y, 1) // move to station level
|
||||
U.oxygen = T.oxygen
|
||||
U.oldoxy = T.oldoxy
|
||||
U.tmpoxy = T.tmpoxy
|
||||
U.poison = T.poison
|
||||
U.oldpoison = T.oldpoison
|
||||
U.tmppoison = T.tmppoison
|
||||
U.co2 = T.co2
|
||||
U.oldco2 = T.oldco2
|
||||
U.tmpco2 = T.tmpco2
|
||||
del(T)
|
||||
prison_entered = 1
|
||||
else
|
||||
usr << "\blue There is an obstructing shuttle!"
|
||||
|
||||
|
||||
// Restabalize verb
|
||||
// Set all shuttle locations to standard atmosphere settings
|
||||
|
||||
verb/restabalize()
|
||||
set src in oview(1)
|
||||
|
||||
viewers(null, null) << "\red <B>Restabalizing prison shuttle atmosphere!</B>"
|
||||
var/A = locate(/area/shuttle_prison)
|
||||
for(var/obj/move/T in A)
|
||||
T.firelevel = 0
|
||||
T.oxygen = O2STANDARD
|
||||
T.oldoxy = O2STANDARD
|
||||
T.tmpoxy = O2STANDARD
|
||||
T.poison = 0
|
||||
T.oldpoison = 0
|
||||
T.tmppoison = 0
|
||||
T.co2 = 0
|
||||
T.oldco2 = 0
|
||||
T.tmpco2 = 0
|
||||
T.sl_gas = 0
|
||||
T.osl_gas = 0
|
||||
T.tsl_gas = 0
|
||||
T.n2 = N2STANDARD
|
||||
T.on2 = N2STANDARD
|
||||
T.tn2 = N2STANDARD
|
||||
T.temp = T20C
|
||||
T.otemp = T20C
|
||||
T.ttemp = T20C
|
||||
|
||||
viewers(null, null) << "\red <B>Prison shuttle Restabalized!</B>"
|
||||
src.add_fingerprint(usr)
|
||||
@@ -0,0 +1,425 @@
|
||||
/*
|
||||
* Secure_data -- computer that displays security data about a player
|
||||
*
|
||||
*
|
||||
* Very similar to the med_data computer
|
||||
*/
|
||||
|
||||
|
||||
obj/machinery/computer/secure_data
|
||||
name = "Security Records"
|
||||
icon = 'weap_sat.dmi'
|
||||
icon_state = "computer"
|
||||
var
|
||||
obj/item/weapon/card/id/scan = null // the inserted ID card
|
||||
authenticated = null // the name on the ID card
|
||||
rank = null // the job assignment on the ID card
|
||||
screen = null // the screen to show in the window
|
||||
// 1=Search, 2=List, 3=Maint, 4=Edit record
|
||||
datum/data/record/active1 = null // record from data_core.general
|
||||
datum/data/record/active2 = null // record from data_core.security
|
||||
temp = null // temporary text display for window
|
||||
printing = null // true while printing a record
|
||||
|
||||
access = null // required access levels (none)
|
||||
allowed = "Security Officer/Forensic Technician/Prison Warden/Head of Personnel/Captain"
|
||||
// required job assignments to access records
|
||||
|
||||
// Monkey interact same as human
|
||||
|
||||
attack_paw(mob/user)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// Human interact, display window
|
||||
|
||||
attack_hand(mob/user)
|
||||
|
||||
if(stat & (NOPOWER|BROKEN) )
|
||||
return
|
||||
|
||||
var/dat
|
||||
if (src.temp)
|
||||
dat = text("<TT>[]</TT><BR><BR><A href='?src=\ref[];temp=1'>Clear Screen</A>", src.temp, src)
|
||||
else
|
||||
dat = text("Confirm Identity: <A href='?src=\ref[];scan=1'>[]</A><HR>", src, (src.scan ? text("[]", src.scan.name) : "----------"))
|
||||
if (src.authenticated)
|
||||
switch(src.screen)
|
||||
if(1.0)
|
||||
dat += text("<A href='?src=\ref[];search=1'>Search Records</A><BR>\n<A href='?src=\ref[];list=1'>List Records</A><BR>\n<A href='?src=\ref[];search_f=1'>Search Fingerprints</A><BR>\n<A href='?src=\ref[];new_r=1'>New Record</A><BR>\n<BR>\n<A href='?src=\ref[];rec_m=1'>Record Maintenance</A><BR>\n<A href='?src=\ref[];logout=1'>{Log Out}</A><BR>\n", src, src, src, src, src, src)
|
||||
if(2.0)
|
||||
dat += "<B>Record List</B>:<HR>"
|
||||
for(var/datum/data/record/R in data_core.general)
|
||||
dat += text("<A href='?src=\ref[];d_rec=\ref[]'>[]: []<BR>", src, R, R.fields["id"], R.fields["name"])
|
||||
|
||||
dat += text("<HR><A href='?src=\ref[];main=1'>Back</A>", src)
|
||||
if(3.0)
|
||||
dat += text("<B>Records Maintenance</B><HR>\n<A href='?src=\ref[];back=1'>Backup To Disk</A><BR>\n<A href='?src=\ref[];u_load=1'>Upload From disk</A><BR>\n<A href='?src=\ref[];del_all=1'>Delete All Records</A><BR>\n<BR>\n<A href='?src=\ref[];main=1'>Back</A>", src, src, src, src)
|
||||
if(4.0)
|
||||
dat += "<CENTER><B>Security Record</B></CENTER><BR>"
|
||||
if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1)))
|
||||
dat += text("Name: <A href='?src=\ref[];field=name'>[]</A> ID: <A href='?src=\ref[];field=id'>[]</A><BR>\nSex: <A href='?src=\ref[];field=sex'>[]</A><BR>\nAge: <A href='?src=\ref[];field=age'>[]</A><BR>\nRank: <A href='?src=\ref[];field=rank'>[]</A><BR>\nFingerprint: <A href='?src=\ref[];field=fingerprint'>[]</A><BR>\nPhysical Status: []<BR>\nMental Status: []<BR>", src, src.active1.fields["name"], src, src.active1.fields["id"], src, src.active1.fields["sex"], src, src.active1.fields["age"], src, src.active1.fields["rank"], src, src.active1.fields["fingerprint"], src.active1.fields["p_stat"], src.active1.fields["m_stat"])
|
||||
else
|
||||
dat += "<B>General Record Lost!</B><BR>"
|
||||
if ((istype(src.active2, /datum/data/record) && data_core.security.Find(src.active2)))
|
||||
dat += text("<BR>\n<CENTER><B>Security Data</B></CENTER><BR>\nCriminal Status: <A href='?src=\ref[];field=criminal'>[]</A><BR>\n<BR>\nMinor Crimes: <A href='?src=\ref[];field=mi_crim'>[]</A><BR>\nDetails: <A href='?src=\ref[];field=mi_crim_d'>[]</A><BR>\n<BR>\nMajor Crimes: <A href='?src=\ref[];field=ma_crim'>[]</A><BR>\nDetails: <A href='?src=\ref[];field=ma_crim_d'>[]</A><BR>\n<BR>\nImportant Notes:<BR>\n\t<A href='?src=\ref[];field=notes'>[]</A><BR>\n<BR>\n<CENTER><B>Comments/Log</B></CENTER><BR>", src, src.active2.fields["criminal"], src, src.active2.fields["mi_crim"], src, src.active2.fields["mi_crim_d"], src, src.active2.fields["ma_crim"], src, src.active2.fields["ma_crim_d"], src, src.active2.fields["notes"])
|
||||
var/counter = 1
|
||||
while(src.active2.fields[text("com_[]", counter)])
|
||||
dat += text("[]<BR><A href='?src=\ref[];del_c=[]'>Delete Entry</A><BR><BR>", src.active2.fields[text("com_[]", counter)], src, counter)
|
||||
counter++
|
||||
dat += text("<A href='?src=\ref[];add_c=1'>Add Entry</A><BR><BR>", src)
|
||||
dat += text("<A href='?src=\ref[];del_r=1'>Delete Record (Security Only)</A><BR><BR>", src)
|
||||
else
|
||||
dat += "<B>Security Record Lost!</B><BR>"
|
||||
dat += text("<A href='?src=\ref[];new=1'>New Record</A><BR><BR>", src)
|
||||
dat += text("\n<A href='?src=\ref[];dela_r=1'>Delete Record (ALL)</A><BR><BR>\n<A href='?src=\ref[];print_p=1'>Print Record</A><BR>\n<A href='?src=\ref[];list=1'>Back</A><BR>", src, src, src)
|
||||
else
|
||||
else
|
||||
dat += text("<A href='?src=\ref[];login=1'>{Log In}</A>", src)
|
||||
user << browse(text("<HEAD><TITLE>Security Records</TITLE></HEAD><TT>[]</TT>", dat), "window=secure_rec")
|
||||
|
||||
|
||||
// Handle topic links
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
if(stat & (NOPOWER|BROKEN) )
|
||||
return
|
||||
if (!( data_core.general.Find(src.active1) ))
|
||||
src.active1 = null
|
||||
if (!( data_core.security.Find(src.active2) ))
|
||||
src.active2 = null
|
||||
if ((usr.stat || usr.restrained()))
|
||||
return
|
||||
if ((usr.contents.Find(src) || (get_dist(src, usr) <= 1 && istype(src.loc, /turf))))
|
||||
usr.machine = src
|
||||
if (href_list["temp"])
|
||||
src.temp = null
|
||||
if (href_list["scan"])
|
||||
if (src.scan)
|
||||
src.scan.loc = src.loc
|
||||
src.scan = null
|
||||
else
|
||||
var/obj/item/I = usr.equipped()
|
||||
if (istype(I, /obj/item/weapon/card/id))
|
||||
usr.drop_item()
|
||||
I.loc = src
|
||||
src.scan = I
|
||||
else
|
||||
if (href_list["logout"])
|
||||
src.authenticated = null
|
||||
src.screen = null
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
else
|
||||
if (href_list["login"])
|
||||
if (istype(src.scan, /obj/item/weapon/card/id))
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
if (scan.check_access(access, allowed))
|
||||
src.authenticated = src.scan.registered
|
||||
src.rank = src.scan.assignment
|
||||
src.screen = 1
|
||||
if (src.authenticated)
|
||||
if (href_list["list"])
|
||||
src.screen = 2
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
else
|
||||
if (href_list["rec_m"])
|
||||
src.screen = 3
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
else
|
||||
if (href_list["del_all"])
|
||||
src.temp = text("Are you sure you wish to delete all records?<br>\n\t<A href='?src=\ref[];temp=1;del_all2=1'>Yes</A><br>\n\t<A href='?src=\ref[];temp=1'>No</A><br>", src, src)
|
||||
else
|
||||
if (href_list["del_all2"])
|
||||
for(var/datum/data/record/R in data_core.security)
|
||||
del(R)
|
||||
|
||||
src.temp = "All records deleted."
|
||||
else
|
||||
if (href_list["main"])
|
||||
src.screen = 1
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
else
|
||||
if (href_list["field"])
|
||||
var/a1 = src.active1
|
||||
var/a2 = src.active2
|
||||
switch(href_list["field"])
|
||||
if("name")
|
||||
if (istype(src.active1, /datum/data/record))
|
||||
var/t1 = input("Please input name:", "Secure. records", src.active1.fields["name"], null) as text
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || get_dist(src, usr) > 1 || src.active1 != a1))
|
||||
return
|
||||
src.active1.fields["name"] = t1
|
||||
if("id")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please input id:", "Secure. records", src.active1.fields["id"], null) as text
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || get_dist(src, usr) > 1 || src.active1 != a1))
|
||||
return
|
||||
src.active1.fields["id"] = t1
|
||||
if("fingerprint")
|
||||
if (istype(src.active1, /datum/data/record))
|
||||
var/t1 = input("Please input fingerprint hash:", "Secure. records", src.active1.fields["fingerprint"], null) as text
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || get_dist(src, usr) > 1 || src.active1 != a1))
|
||||
return
|
||||
src.active1.fields["fingerprint"] = t1
|
||||
if("sex")
|
||||
if (istype(src.active1, /datum/data/record))
|
||||
if (src.active1.fields["sex"] == "Male")
|
||||
src.active1.fields["sex"] = "Female"
|
||||
else
|
||||
src.active1.fields["sex"] = "Male"
|
||||
if("age")
|
||||
if (istype(src.active1, /datum/data/record))
|
||||
var/t1 = input("Please input age:", "Secure. records", src.active1.fields["age"], null) as text
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || get_dist(src, usr) > 1 || src.active1 != a1))
|
||||
return
|
||||
src.active1.fields["age"] = t1
|
||||
if("mi_crim")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please input minor disabilities list:", "Secure. records", src.active2.fields["mi_crim"], null) as text
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || get_dist(src, usr) > 1 || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["mi_crim"] = t1
|
||||
if("mi_crim_d")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please summarize minor dis.:", "Secure. records", src.active2.fields["mi_crim_d"], null) as message
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || get_dist(src, usr) > 1 || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["mi_crim_d"] = t1
|
||||
if("ma_crim")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please input major diabilities list:", "Secure. records", src.active2.fields["ma_crim"], null) as text
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || get_dist(src, usr) > 1 || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["ma_crim"] = t1
|
||||
if("ma_crim_d")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please summarize major dis.:", "Secure. records", src.active2.fields["ma_crim_d"], null) as message
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || get_dist(src, usr) > 1 || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["ma_crim_d"] = t1
|
||||
if("notes")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = input("Please summarize notes:", "Secure. records", src.active2.fields["notes"], null) as message
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || get_dist(src, usr) > 1 || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["notes"] = t1
|
||||
if("criminal")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
src.temp = text("<B>Criminal Status:</B><BR>\n\t<A href='?src=\ref[];temp=1;criminal2=none'>None</A><BR>\n\t<A href='?src=\ref[];temp=1;criminal2=arrest'>*Arrest*</A><BR>\n\t<A href='?src=\ref[];temp=1;criminal2=incarcerated'>Incarcerated</A><BR>\n\t<A href='?src=\ref[];temp=1;criminal2=parolled'>Parolled</A><BR>\n\t<A href='?src=\ref[];temp=1;criminal2=released'>Released</A><BR>", src, src, src, src, src)
|
||||
if("rank")
|
||||
var/list/L = list( "Head of Personnel", "Captain" )
|
||||
if ((istype(src.active1, /datum/data/record) && L.Find(src.rank)))
|
||||
src.temp = text("<B>Rank:</B><BR>\n<B>Assistants:</B><BR>\n<A href='?src=\ref[];temp=1;rank=res_assist'>Research Assistant</A><BR>\n<A href='?src=\ref[];temp=1;rank=staff_assist'>Staff Assistant</A><BR>\n<A href='?src=\ref[];temp=1;rank=med_assist'>Medical Assistant</A><BR>\n<A href='?src=\ref[];temp=1;rank=tech_assist'>Technical Assistant</A><BR>\n<B>Technicians:</B><BR>\n<A href='?src=\ref[];temp=1;rank=foren_tech'>Forensic Technician</A><BR>\n<A href='?src=\ref[];temp=1;rank=res_tech'>Research Technician</A><BR>\n<A href='?src=\ref[];temp=1;rank=stat_tech'>Station Technician</A><BR>\n<A href='?src=\ref[];temp=1;rank=atmo_tech'>Atmospheric Technician</A><BR>\n<A href='?src=\ref[];temp=1;rank=engineer'>Engineer (Engine Technician)\n<B>Researchers:</B><BR>\n<A href='?src=\ref[];temp=1;rank=med_res'>Medical Researcher</A><BR>\n<A href='?src=\ref[];temp=1;rank=tox_res'>Toxin Researcher</A><BR>\n<B>Officers:</B><BR>\n<A href='?src=\ref[];temp=1;rank=med_doc'>Medical Doctor</A><BR>\n<A href='?src=\ref[];temp=1;rank=secure_off'>Security Officer</A><BR>\n<B>Higher Officers:</B><BR>\n<A href='?src=\ref[];temp=1;rank=hoperson'>Head of Research</A><BR>\n<A href='?src=\ref[];temp=1;rank=horesearch'>Head of Personnel</A><BR>\n<A href='?src=\ref[];temp=1;rank=captain'>Captain</A><BR>", src, src, src, src, src, src, src, src, src, src, src, src, src, src, src, src)
|
||||
else
|
||||
else
|
||||
if (href_list["rank"])
|
||||
var/list/L = list( "Head of Personnel", "Captain" )
|
||||
if ((src.active1 && L.Find(src.rank)))
|
||||
switch(href_list["rank"])
|
||||
if("res_assist")
|
||||
src.active1.fields["rank"] = "Research Assistant"
|
||||
if("staff_assist")
|
||||
src.active1.fields["rank"] = "Staff Assistant"
|
||||
if("med_assist")
|
||||
src.active1.fields["rank"] = "Medical Assistant"
|
||||
if("tech_assist")
|
||||
src.active1.fields["rank"] = "Technical Assistant"
|
||||
if("foren_tech")
|
||||
src.active1.fields["rank"] = "Forensic Technician"
|
||||
if("res_tech")
|
||||
src.active1.fields["rank"] = "Research Technician"
|
||||
if("stat_tech")
|
||||
src.active1.fields["rank"] = "Station Technician"
|
||||
if("atmo_tech")
|
||||
src.active1.fields["rank"] = "Atmospheric Technician"
|
||||
if("engineer")
|
||||
src.active1.fields["rank"] = "Engineer"
|
||||
if("med_res")
|
||||
src.active1.fields["rank"] = "Medical Researcher"
|
||||
if("tox_res")
|
||||
src.active1.fields["rank"] = "Toxin Researcher"
|
||||
if("med_doc")
|
||||
src.active1.fields["rank"] = "Medical Doctor"
|
||||
if("secure_off")
|
||||
src.active1.fields["rank"] = "Security Officer"
|
||||
if("hoperson")
|
||||
src.active1.fields["rank"] = "Head of Research"
|
||||
if("horesearch")
|
||||
src.active1.fields["rank"] = "Head of Personnel"
|
||||
if("captain")
|
||||
src.active1.fields["rank"] = "Captain"
|
||||
|
||||
else
|
||||
if (href_list["criminal2"])
|
||||
if (src.active2)
|
||||
switch(href_list["criminal2"])
|
||||
if("none")
|
||||
src.active2.fields["criminal"] = "None"
|
||||
if("arrest")
|
||||
src.active2.fields["criminal"] = "*Arrest*"
|
||||
if("incarcerated")
|
||||
src.active2.fields["criminal"] = "Incarcerated"
|
||||
if("parolled")
|
||||
src.active2.fields["criminal"] = "Parolled"
|
||||
if("released")
|
||||
src.active2.fields["criminal"] = "Released"
|
||||
|
||||
else
|
||||
if (href_list["del_r"])
|
||||
if (src.active2)
|
||||
src.temp = text("Are you sure you wish to delete the record (Security Portion Only)?<br>\n\t<A href='?src=\ref[];temp=1;del_r2=1'>Yes</A><br>\n\t<A href='?src=\ref[];temp=1'>No</A><br>", src, src)
|
||||
else
|
||||
if (href_list["del_r2"])
|
||||
if (src.active2)
|
||||
|
||||
del(src.active2)
|
||||
else
|
||||
if (href_list["dela_r"])
|
||||
if (src.active1)
|
||||
src.temp = text("Are you sure you wish to delete the record (ALL)?<br>\n\t<A href='?src=\ref[];temp=1;dela_r2=1'>Yes</A><br>\n\t<A href='?src=\ref[];temp=1'>No</A><br>", src, src)
|
||||
else
|
||||
if (href_list["dela_r2"])
|
||||
for(var/datum/data/record/R in data_core.medical)
|
||||
if ((R.fields["name"] == src.active1.fields["name"] || R.fields["id"] == src.active1.fields["id"]))
|
||||
|
||||
del(R)
|
||||
|
||||
if (src.active2)
|
||||
|
||||
del(src.active2)
|
||||
if (src.active1)
|
||||
|
||||
del(src.active1)
|
||||
else
|
||||
if (href_list["d_rec"])
|
||||
var/datum/data/record/R = locate(href_list["d_rec"])
|
||||
var/S = locate(href_list["d_rec"])
|
||||
if (!( data_core.general.Find(R) ))
|
||||
src.temp = "Record Not Found!"
|
||||
return
|
||||
for(var/datum/data/record/E in data_core.security)
|
||||
if ((E.fields["name"] == R.fields["name"] || E.fields["id"] == R.fields["id"]))
|
||||
S = E
|
||||
|
||||
src.active1 = R
|
||||
src.active2 = S
|
||||
src.screen = 4
|
||||
else
|
||||
if (href_list["new_r"])
|
||||
var/datum/data/record/G = new /datum/data/record( )
|
||||
G.fields["name"] = "New Record"
|
||||
G.fields["id"] = text("[]", add_zero(num2hex(rand(1, 1.6777215E7)), 6))
|
||||
G.fields["rank"] = "Unassigned"
|
||||
G.fields["sex"] = "Male"
|
||||
G.fields["age"] = "Unknown"
|
||||
G.fields["fingerprint"] = "Unknown"
|
||||
G.fields["p_stat"] = "Active"
|
||||
G.fields["m_stat"] = "Stable"
|
||||
data_core.general += G
|
||||
src.active1 = G
|
||||
src.active2 = null
|
||||
else
|
||||
if (href_list["new"])
|
||||
if ((istype(src.active1, /datum/data/record) && !( istype(src.active2, /datum/data/record) )))
|
||||
var/datum/data/record/R = new /datum/data/record( )
|
||||
R.fields["name"] = src.active1.fields["name"]
|
||||
R.fields["id"] = src.active1.fields["id"]
|
||||
R.name = text("Security Record #[]", R.fields["id"])
|
||||
R.fields["criminal"] = "None"
|
||||
R.fields["mi_crim"] = "None"
|
||||
R.fields["mi_crim_d"] = "No minor crime convictions."
|
||||
R.fields["ma_crim"] = "None"
|
||||
R.fields["ma_crim_d"] = "No minor crime convictions."
|
||||
R.fields["notes"] = "No notes."
|
||||
data_core.security += R
|
||||
src.active2 = R
|
||||
src.screen = 4
|
||||
else
|
||||
if (href_list["add_c"])
|
||||
if (!( istype(src.active2, /datum/data/record) ))
|
||||
return
|
||||
var/a2 = src.active2
|
||||
var/t1 = input("Add Comment:", "Secure. records", null, null) as message
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || get_dist(src, usr) > 1 || src.active2 != a2))
|
||||
return
|
||||
var/counter = 1
|
||||
while(src.active2.fields[text("com_[]", counter)])
|
||||
counter++
|
||||
src.active2.fields[text("com_[]", counter)] = text("Made by [] ([]) on [], 2053<BR>[]", src.authenticated, src.rank, time2text(world.realtime, "DDD MMM DD hh:mm:ss"), t1)
|
||||
else
|
||||
if (href_list["del_c"])
|
||||
if ((istype(src.active2, /datum/data/record) && src.active2.fields[text("com_[]", href_list["del_c"])]))
|
||||
src.active2.fields[text("com_[]", href_list["del_c"])] = "<B>Deleted</B>"
|
||||
else
|
||||
if (href_list["search_f"])
|
||||
var/t1 = input("Search String: (Fingerprint)", "Secure. records", null, null) as text
|
||||
if ((!( t1 ) || usr.stat || !( src.authenticated ) || usr.restrained() || get_dist(src, usr) > 1))
|
||||
return
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
t1 = lowertext(t1)
|
||||
for(var/datum/data/record/R in data_core.general)
|
||||
if (lowertext(R.fields["fingerprint"]) == t1)
|
||||
src.active1 = R
|
||||
|
||||
if (!( src.active1 ))
|
||||
src.temp = text("Could not locate record [].", t1)
|
||||
else
|
||||
for(var/datum/data/record/E in data_core.security)
|
||||
if ((E.fields["name"] == src.active1.fields["name"] || E.fields["id"] == src.active1.fields["id"]))
|
||||
src.active2 = E
|
||||
|
||||
src.screen = 4
|
||||
else
|
||||
if (href_list["search"])
|
||||
var/t1 = input("Search String: (Name or ID)", "Secure. records", null, null) as text
|
||||
if ((!( t1 ) || usr.stat || !( src.authenticated ) || usr.restrained() || get_dist(src, usr) > 1))
|
||||
return
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
t1 = lowertext(t1)
|
||||
for(var/datum/data/record/R in data_core.general)
|
||||
if ((lowertext(R.fields["name"]) == t1 || t1 == lowertext(R.fields["id"])))
|
||||
src.active1 = R
|
||||
|
||||
if (!( src.active1 ))
|
||||
src.temp = text("Could not locate record [].", t1)
|
||||
else
|
||||
for(var/datum/data/record/E in data_core.security)
|
||||
if ((E.fields["name"] == src.active1.fields["name"] || E.fields["id"] == src.active1.fields["id"]))
|
||||
src.active2 = E
|
||||
|
||||
src.screen = 4
|
||||
else
|
||||
if (href_list["print_p"])
|
||||
if (!( src.printing ))
|
||||
src.printing = 1
|
||||
sleep(50)
|
||||
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( src.loc )
|
||||
P.info = "<CENTER><B>Security Record</B></CENTER><BR>"
|
||||
if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1)))
|
||||
P.info += text("Name: [] ID: []<BR>\nSex: []<BR>\nAge: []<BR>\nFingerprint: []<BR>\nPhysical Status: []<BR>\nMental Status: []<BR>", src.active1.fields["name"], src.active1.fields["id"], src.active1.fields["sex"], src.active1.fields["age"], src.active1.fields["fingerprint"], src.active1.fields["p_stat"], src.active1.fields["m_stat"])
|
||||
else
|
||||
P.info += "<B>General Record Lost!</B><BR>"
|
||||
if ((istype(src.active2, /datum/data/record) && data_core.security.Find(src.active2)))
|
||||
P.info += text("<BR>\n<CENTER><B>Security Data</B></CENTER><BR>\nCriminal Status: []<BR>\n<BR>\nMinor Crimes: []<BR>\nDetails: []<BR>\n<BR>\nMajor Crimes: []<BR>\nDetails: []<BR>\n<BR>\nImportant Notes:<BR>\n\t[]<BR>\n<BR>\n<CENTER><B>Comments/Log</B></CENTER><BR>", src.active2.fields["criminal"], src.active2.fields["mi_crim"], src.active2.fields["mi_crim_d"], src.active2.fields["ma_crim"], src.active2.fields["ma_crim_d"], src.active2.fields["notes"])
|
||||
var/counter = 1
|
||||
while(src.active2.fields[text("com_[]", counter)])
|
||||
P.info += text("[]<BR>", src.active2.fields[text("com_[]", counter)])
|
||||
counter++
|
||||
else
|
||||
P.info += "<B>Security Record Lost!</B><BR>"
|
||||
P.info += "</TT>"
|
||||
P.name = "paper- 'Security Record'"
|
||||
src.printing = null
|
||||
src.add_fingerprint(usr)
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
* Shuttle -- emergency shuttle control computer
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
obj/machinery/computer/shuttle
|
||||
name = "shuttle"
|
||||
icon = 'shuttle.dmi'
|
||||
icon_state = "shuttlecom"
|
||||
|
||||
var
|
||||
auth_need = 3 // number of authorizations needed to launch shuttle early
|
||||
list/authorized = list( ) // list of names of those authorizing the early launch
|
||||
allowed // ID card job assignmented needed to authorize (none)
|
||||
access = "2000" // ID card access level needed to authorize
|
||||
|
||||
|
||||
// Restabalize verb
|
||||
// Set all shuttle locations to standard atmosphere
|
||||
|
||||
verb/restabalize()
|
||||
set src in oview(1)
|
||||
|
||||
world << "\red <B>Restabalizing shuttle atmosphere!</B>"
|
||||
var/A = locate(/area/shuttle)
|
||||
for(var/obj/move/T in A)
|
||||
T.firelevel = 0
|
||||
T.oxygen = O2STANDARD
|
||||
T.oldoxy = O2STANDARD
|
||||
T.tmpoxy = O2STANDARD
|
||||
T.poison = 0
|
||||
T.oldpoison = 0
|
||||
T.tmppoison = 0
|
||||
T.co2 = 0
|
||||
T.oldco2 = 0
|
||||
T.tmpco2 = 0
|
||||
T.sl_gas = 0
|
||||
T.osl_gas = 0
|
||||
T.tsl_gas = 0
|
||||
T.n2 = N2STANDARD
|
||||
T.on2 = N2STANDARD
|
||||
T.tn2 = N2STANDARD
|
||||
T.temp = T20C
|
||||
T.otemp = T20C
|
||||
T.ttemp = T20C
|
||||
|
||||
world << "\red <B>Shuttle Restabalized!</B>"
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
|
||||
// Hijack verb
|
||||
// Can be used only by the traitor to end a round
|
||||
// Note can only occur when shuttle is at CC, not at the station level
|
||||
|
||||
verb/hijack()
|
||||
set src in oview(1)
|
||||
|
||||
if ((!( ticker ) || ticker.shuttle_location != shuttle_z))
|
||||
return
|
||||
if (usr != ticker.killer)
|
||||
return
|
||||
world << "\blue <B>Alert: The shuttle is has been hijacked prematurely by the traitor!</B>"
|
||||
ticker.timing = 0
|
||||
ticker.check_win()
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
|
||||
// Attack with object
|
||||
// Allows shuttle to be launched early if 3 ID card of sufficient level (from different holders) are used
|
||||
|
||||
attackby(obj/item/weapon/card/id/W, mob/user)
|
||||
|
||||
|
||||
if ((!( istype(W, /obj/item/weapon/card/id) ) || !( ticker ) || ticker.shuttle_location == shuttle_z || !( user )))
|
||||
return
|
||||
if (!W.check_access(access, allowed))
|
||||
user << text("The access level ([]) of [] card is not high enough. ", W.access_level, W.registered)
|
||||
return
|
||||
var/choice = alert(user, text("Would you like to (un)authorize a shortened launch time? [] authorization\s are still needed. Use abort to cancel all authorizations.", src.auth_need - src.authorized.len), "Shuttle Launch", "Authorize", "Repeal", "Abort")
|
||||
switch(choice)
|
||||
if("Authorize")
|
||||
src.authorized -= W.registered
|
||||
src.authorized += W.registered
|
||||
if (src.auth_need - src.authorized.len > 0)
|
||||
world << text("\blue <B>Alert: [] authorizations needed until shuttle is launched early</B>", src.auth_need - src.authorized.len)
|
||||
else
|
||||
world << "\blue <B>Alert: Shuttle launch time shortened to 10 seconds!</B>"
|
||||
ticker.timeleft = 100
|
||||
//src.authorized = null
|
||||
del(src.authorized)
|
||||
src.authorized = list( )
|
||||
if("Repeal")
|
||||
src.authorized -= W.registered
|
||||
world << text("\blue <B>Alert: [] authorizations needed until shuttle is launched early</B>", src.auth_need - src.authorized.len)
|
||||
if("Abort")
|
||||
world << "\blue <B>All authorizations to shorting time for shuttle launch have been revoked!</B>"
|
||||
src.authorized.len = 0
|
||||
src.authorized = list( )
|
||||
@@ -0,0 +1,146 @@
|
||||
/*
|
||||
* Door -- the base door type.
|
||||
* All other doors (airlocks, false walls, poddoors, firedoors and windowdoors) descend from this.
|
||||
*
|
||||
*/
|
||||
|
||||
obj/machinery/door
|
||||
name = "door"
|
||||
icon = 'doors.dmi'
|
||||
icon_state = "door1"
|
||||
opacity = 1
|
||||
density = 1
|
||||
anchored = 1
|
||||
|
||||
var
|
||||
visible = 1.0 // True for all except windowdoors; controls whether door becomes opaque when closed.
|
||||
|
||||
access = "0000" // ID card access levels
|
||||
allowed = null // ID card job assignment access
|
||||
|
||||
p_open = 0.0 // True if the wiring panel is open; currently only used for airlocks
|
||||
operating = null // True if door is currently opening/closing
|
||||
|
||||
|
||||
// Create a new door. Ensure that turf links are updated.
|
||||
|
||||
New()
|
||||
..()
|
||||
var/turf/T = src.loc
|
||||
if (istype(T, /turf))
|
||||
if (src.density)
|
||||
T.updatecell = 0
|
||||
T.buildlinks()
|
||||
|
||||
|
||||
// Called to open a door
|
||||
// Plays opening animation, updates icon state, ensures turf links are updated
|
||||
|
||||
proc/open()
|
||||
if (src.operating)
|
||||
return
|
||||
src.operating = 1
|
||||
flick(text("[]doorc0", (src.p_open ? "o_" : null)), src)
|
||||
src.icon_state = text("[]door0", (src.p_open ? "o_" : null))
|
||||
sleep(15)
|
||||
src.density = 0
|
||||
src.opacity = 0
|
||||
var/turf/T = src.loc
|
||||
if (istype(T, /turf))
|
||||
T.updatecell = 1
|
||||
T.buildlinks()
|
||||
src.operating = 0
|
||||
|
||||
|
||||
// Called to close a door.
|
||||
// Plays closing animation, updates icon state, ensures turf links are updated
|
||||
|
||||
proc/close()
|
||||
if (src.operating)
|
||||
return
|
||||
src.operating = 1
|
||||
flick(text("[]doorc1", (src.p_open ? "o_" : null)), src)
|
||||
src.icon_state = text("[]door1", (src.p_open ? "o_" : null))
|
||||
src.density = 1
|
||||
if (src.visible)
|
||||
src.opacity = 1
|
||||
var/turf/T = src.loc
|
||||
if (istype(T, /turf))
|
||||
T.updatecell = 0
|
||||
T.buildlinks()
|
||||
sleep(15)
|
||||
src.operating = 0
|
||||
|
||||
// Monkey attack same as human
|
||||
|
||||
attack_paw(mob/user)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// Attack with hand. If human and wearing an ID, same as attacking with the ID
|
||||
|
||||
attack_hand(mob/user as mob)
|
||||
if(istype(user, /mob/human))
|
||||
var/mob/human/H = user
|
||||
if(H.wear_id)
|
||||
attackby(H.wear_id, user)
|
||||
|
||||
|
||||
// Attack with an item
|
||||
// If an emag card, open the door if closed. Note: Door cannot be reclosed with an emag.
|
||||
// If anything else, check to see if user is wearing an ID (or the ID was used)
|
||||
// then check the ID access and open or close the door
|
||||
|
||||
attackby(obj/item/I, mob/user)
|
||||
|
||||
if (src.operating)
|
||||
return
|
||||
src.add_fingerprint(user)
|
||||
if ((src.density && istype(I, /obj/item/weapon/card/emag)))
|
||||
src.operating = 1
|
||||
flick("door_spark", src)
|
||||
sleep(6)
|
||||
src.operating = null
|
||||
open()
|
||||
return 1
|
||||
var/obj/item/weapon/card/id/card
|
||||
if (istype(user, /mob/human))
|
||||
var/mob/human/H = user
|
||||
card = H.wear_id
|
||||
if (istype(I, /obj/item/weapon/card/id))
|
||||
card = I
|
||||
else
|
||||
if (!( istype(card, /obj/item/weapon/card/id) ))
|
||||
return 0
|
||||
if (card.check_access(access, allowed))
|
||||
if (src.density)
|
||||
open()
|
||||
else
|
||||
close()
|
||||
else
|
||||
if (src.density)
|
||||
flick("door_deny", src)
|
||||
|
||||
|
||||
// If hit by a meteor, open the door
|
||||
|
||||
meteorhit(obj/M)
|
||||
src.open()
|
||||
return
|
||||
|
||||
// Attack by blob, chance to destroy the door.
|
||||
|
||||
blob_act()
|
||||
if(prob(20))
|
||||
del(src)
|
||||
|
||||
// Built-in proc called when the door moves location
|
||||
// Since doors do not move, this seems to be redundent
|
||||
|
||||
Move()
|
||||
..()
|
||||
if (src.density)
|
||||
var/turf/location = src.loc
|
||||
if (istype(location, /turf))
|
||||
location.updatecell = 0
|
||||
buildlinks()
|
||||
@@ -0,0 +1,209 @@
|
||||
/*
|
||||
* Airlock -- an airlock door.
|
||||
*
|
||||
* TODO: Make the interaction between the "test light" and the new power system more logical.
|
||||
* TODO: Make it possible to crowbar an airlock open if the area power is out (but bolts still up)
|
||||
*/
|
||||
|
||||
obj/machinery/door/airlock
|
||||
name = "airlock"
|
||||
icon = 'Door1.dmi'
|
||||
var
|
||||
blocked = null // true if door is welded shut
|
||||
powered = 1.0 // true if the test light is on
|
||||
locked = 0.0 // true if the door bolts are down (locked)
|
||||
wires = 511 // bitmask representing the 9 internal wires. Defaults to all connected
|
||||
// The wire conditions effect the "powered" and "locked" variables.
|
||||
|
||||
|
||||
// Called to open door.
|
||||
// Door must be unwelded, not locked, test light on, and area power present to open
|
||||
|
||||
open()
|
||||
if ((src.blocked || src.locked || !( src.powered )) || stat & NOPOWER)
|
||||
return
|
||||
use_power(50)
|
||||
..()
|
||||
|
||||
|
||||
// Called to close door
|
||||
// If test light is off or no area power, do not close
|
||||
|
||||
close()
|
||||
if (!( src.powered || stat & NOPOWER))
|
||||
return
|
||||
use_power(50)
|
||||
..()
|
||||
var/turf/T = src.loc
|
||||
if (T)
|
||||
T.firelevel = 0
|
||||
|
||||
|
||||
// Set the icon state and other variables, depending on the wires bitfield.
|
||||
|
||||
proc/update()
|
||||
if (((!( src.wires & 2 ) || !( src.wires & 8 ) || !( src.wires & 32 ) || !( src.wires & 64 ) || !( src.wires & 128 ) || !( src.wires & 256 )) && src.powered))
|
||||
src.locked = 1 // Door is locked if grey, blue, yellow, white, dk red or orange wires are cut and test light is on
|
||||
// Note bolts are not automatically raised - you must use a wrench to reset
|
||||
if ((!( src.wires & 1 ) && !( src.wires & 4 ) && !( src.wires & 16 )))
|
||||
src.powered = 0 // Test light goes off if black, green and red wires are cut
|
||||
else
|
||||
src.powered = 1 // Otherwise test light is on
|
||||
var/d = src.density
|
||||
if (src.blocked) // true if welded shut
|
||||
d = "l"
|
||||
src.icon_state = text("[]door[]", (src.p_open ? "o_" : null), d)
|
||||
return
|
||||
|
||||
|
||||
// Monkey interact same a human
|
||||
|
||||
attack_paw(mob/user)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// Human interact. If the door panel is open, show the wire interaction window. Otherwise, do standard door interaction.
|
||||
|
||||
attack_hand(mob/user)
|
||||
if (src.p_open)
|
||||
user.machine = src
|
||||
var/t1 = {"<B>Access Panel</B><br>
|
||||
Orange Wire: [(src.wires & 256 ? "<A href='?src=\ref[src];wires=256'>Cut Wire</A>" : "<A href='?src=\ref[src];wires=256'>Mend Wire</A>")]<br>
|
||||
Dark Red Wire: [(src.wires & 128 ? "<A href='?src=\ref[src];wires=128'>Cut Wire</A>" : "<A href='?src=\ref[src];wires=128'>Mend Wire</A>")]<br>
|
||||
White Wire: [(src.wires & 64 ? "<A href='?src=\ref[src];wires=64'>Cut Wire</A>" : "<A href='?src=\ref[src];wires=64'>Mend Wire</A>")]<br>
|
||||
Yellow Wire: [(src.wires & 32 ? "<A href='?src=\ref[src];wires=32'>Cut Wire</A>" : "<A href='?src=\ref[src];wires=32'>Mend Wire</A>")]<br>
|
||||
Red Wire: [(src.wires & 16 ? "<A href='?src=\ref[src];wires=16'>Cut Wire</A>" : "<A href='?src=\ref[src];wires=16'>Mend Wire</A>")]<br>
|
||||
Blue Wire: [(src.wires & 8 ? "<A href='?src=\ref[src];wires=8'>Cut Wire</A>" : "<A href='?src=\ref[src];wires=8'>Mend Wire</A>")]<br>
|
||||
Green Wire: [(src.wires & 4 ? "<A href='?src=\ref[src];wires=4'>Cut Wire</A>" : "<A href='?src=\ref[src];wires=4'>Mend Wire</A>")]<br>
|
||||
Grey Wire: [(src.wires & 2 ? "<A href='?src=\ref[src];wires=2'>Cut Wire</A>" : "<A href='?src=\ref[src];wires=2'>Mend Wire</A>")]<br>
|
||||
Black Wire: [(src.wires & 1 ? "<A href='?src=\ref[src];wires=1'>Cut Wire</A>" : "<A href='?src=\ref[src];wires=1'>Mend Wire</A>")]<br>
|
||||
<br>
|
||||
[(src.locked ? "The door bolts have fallen!" : "The door bolts look up.")]<br>
|
||||
[(src.powered ? "The test light is on." : "The test light is off!")]"}
|
||||
|
||||
|
||||
user << browse(t1, "window=airlock")
|
||||
else
|
||||
..(user)
|
||||
return
|
||||
|
||||
|
||||
// Handle topic links from interaction window. Cut/join wires if clicking with wirecutters
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
if (usr.stat || usr.restrained() )
|
||||
return
|
||||
if ((get_dist(src, usr) <= 1 && istype(src.loc, /turf)))
|
||||
usr.machine = src
|
||||
if (href_list["wires"])
|
||||
var/t1 = text2num(href_list["wires"])
|
||||
if (!( istype(usr.equipped(), /obj/item/weapon/wirecutters) ))
|
||||
return
|
||||
if (!( src.p_open ))
|
||||
return
|
||||
if (t1 & 1)
|
||||
if (src.wires & 1)
|
||||
src.wires &= ~1
|
||||
else
|
||||
src.wires |= 1
|
||||
else if (t1 & 2)
|
||||
if (src.wires & 2)
|
||||
src.wires &= ~2
|
||||
else
|
||||
src.wires |= 2
|
||||
else if (t1 & 4)
|
||||
if (src.wires & 4)
|
||||
src.wires &= ~4
|
||||
else
|
||||
src.wires |= 4
|
||||
else if (t1 & 8)
|
||||
if (src.wires & 8)
|
||||
src.wires &= ~8
|
||||
else
|
||||
src.wires |= 8
|
||||
else if (t1 & 16)
|
||||
if (src.wires & 16)
|
||||
src.wires &= ~16
|
||||
else
|
||||
src.wires |= 16
|
||||
else if (t1 & 32)
|
||||
if (src.wires & 32)
|
||||
src.wires &= ~32
|
||||
else
|
||||
src.wires |= 32
|
||||
else if (t1 & 64)
|
||||
if (src.wires & 64)
|
||||
src.wires &= ~64
|
||||
else
|
||||
src.wires |= 64
|
||||
else if (t1 & 128)
|
||||
if (src.wires & 128)
|
||||
src.wires &= ~128
|
||||
else
|
||||
src.wires |= 128
|
||||
else if (t1 & 256)
|
||||
if (src.wires & 256)
|
||||
src.wires &= ~256
|
||||
else
|
||||
src.wires |= 256
|
||||
src.update()
|
||||
add_fingerprint(usr)
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
return
|
||||
|
||||
|
||||
// Attack with item.
|
||||
// If weldingtool (and door is closed), weld/unweld the door
|
||||
// If wrench, and door has test light on, unlock the door (raise bolts)
|
||||
// If screwdriver, toggle door panel open/closed
|
||||
// If crowbar, and door is closed, not welded, test light off and not locked, open the door
|
||||
// Otherwise, do standard door attackby()
|
||||
|
||||
attackby(obj/item/weapon/C, mob/user)
|
||||
src.add_fingerprint(user)
|
||||
if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density))
|
||||
var/obj/item/weapon/weldingtool/W = C
|
||||
if(W.welding)
|
||||
if (W.weldfuel > 2)
|
||||
W.weldfuel -= 2
|
||||
else
|
||||
user << "Need more welding fuel!"
|
||||
return
|
||||
if (!( src.blocked ))
|
||||
src.blocked = 1
|
||||
else
|
||||
src.blocked = null
|
||||
src.update()
|
||||
return
|
||||
else if (istype(C, /obj/item/weapon/wrench))
|
||||
if (src.p_open)
|
||||
if (src.powered)
|
||||
src.locked = null
|
||||
else
|
||||
user << alert("You need power assist!", null, null, null, null, null)
|
||||
src.update()
|
||||
else if (istype(C, /obj/item/weapon/screwdriver))
|
||||
src.p_open = !( src.p_open )
|
||||
update()
|
||||
else if (istype(C, /obj/item/weapon/crowbar))
|
||||
if ((src.density && !( src.blocked ) && !( src.operating ) && !( src.powered ) && !( src.locked )))
|
||||
spawn( 0 )
|
||||
src.operating = 1
|
||||
flick(text("[]doorc0", (src.p_open ? "o_" : null)), src)
|
||||
src.icon_state = text("[]door0", (src.p_open ? "o_" : null))
|
||||
sleep(15)
|
||||
src.density = 0
|
||||
src.opacity = 0
|
||||
var/turf/T = src.loc
|
||||
if (istype(T, /turf))
|
||||
T.updatecell = 1
|
||||
T.buildlinks()
|
||||
src.operating = 0
|
||||
return
|
||||
else
|
||||
..()
|
||||
return
|
||||
|
||||
@@ -0,0 +1,57 @@
|
||||
/*
|
||||
* False_wall -- A fake wall that can be opened like a door.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
obj/machinery/door/false_wall
|
||||
name = "wall"
|
||||
icon = 'Doorf.dmi'
|
||||
|
||||
|
||||
// Create a false-wall door. Remove the pull verb as this gives away the doors position.
|
||||
|
||||
New()
|
||||
..()
|
||||
src.verbs -= /atom/movable/verb/pull
|
||||
|
||||
// Examine verb. Same result as a standard wall.
|
||||
|
||||
examine()
|
||||
set src in oview(1)
|
||||
|
||||
usr << "It looks like a regular wall"
|
||||
|
||||
// Monkey interact - if in monkey mode, same as human
|
||||
|
||||
attack_paw(mob/user)
|
||||
if ((ticker && ticker.mode == "monkey"))
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// Human interact - 25% chance to open the door
|
||||
|
||||
attack_hand(mob/user)
|
||||
|
||||
src.add_fingerprint(user)
|
||||
if (src.density)
|
||||
if (prob(25))
|
||||
open()
|
||||
else
|
||||
user << "\blue You push the wall but nothing happens!"
|
||||
else
|
||||
close()
|
||||
|
||||
// Attack by item
|
||||
// If a screwdriver, disassembly the false wall into components
|
||||
|
||||
attackby(obj/item/weapon/screwdriver/S, mob/user)
|
||||
|
||||
src.add_fingerprint(user)
|
||||
if (istype(S, /obj/item/weapon/screwdriver))
|
||||
new /obj/item/weapon/sheet/metal( src.loc )
|
||||
new /obj/d_girders( src.loc )
|
||||
del(src)
|
||||
return
|
||||
else
|
||||
..()
|
||||
@@ -0,0 +1,120 @@
|
||||
/*
|
||||
* Firedoor - a door automatically closed by the firealarm system
|
||||
*
|
||||
*/
|
||||
|
||||
obj/machinery/door/firedoor
|
||||
name = "firedoor"
|
||||
icon = 'Door1.dmi'
|
||||
icon_state = "door0"
|
||||
opacity = 0 // Firedoors start open
|
||||
density = 0 //
|
||||
var
|
||||
blocked = null // true if the door has been welded shut (can't be opened)
|
||||
|
||||
|
||||
// Standard open and close procs do not work with firedoors
|
||||
|
||||
open()
|
||||
usr << "This is a remote firedoor!"
|
||||
|
||||
|
||||
close()
|
||||
usr << "This is a remote firedoor!"
|
||||
|
||||
|
||||
|
||||
// Called when area power status changes. Firedoors use the ENVIRON channel.
|
||||
|
||||
power_change()
|
||||
if( powered(ENVIRON) )
|
||||
stat &= ~NOPOWER
|
||||
else
|
||||
stat |= NOPOWER
|
||||
|
||||
|
||||
// Attack by an item
|
||||
// If a welding tool, weld the door shut (or unweld)
|
||||
// If a crowbar. open the door.
|
||||
|
||||
attackby(obj/item/weapon/C, mob/user)
|
||||
|
||||
src.add_fingerprint(user)
|
||||
if ((istype(C, /obj/item/weapon/weldingtool) && !( src.operating ) && src.density))
|
||||
var/obj/item/weapon/weldingtool/W = C
|
||||
if(W.welding)
|
||||
if (W.weldfuel > 2)
|
||||
W.weldfuel -= 2
|
||||
if (!( src.blocked ))
|
||||
src.blocked = 1
|
||||
src.icon_state = "doorl"
|
||||
else
|
||||
src.blocked = 0
|
||||
src.icon_state = "door1"
|
||||
return
|
||||
else
|
||||
if (!( istype(C, /obj/item/weapon/crowbar) ))
|
||||
return
|
||||
if ((src.density && !( src.blocked ) && !( src.operating )))
|
||||
spawn( 0 )
|
||||
src.operating = 1
|
||||
flick("doorc0", src)
|
||||
src.icon_state = "door0"
|
||||
sleep(15)
|
||||
src.density = 0
|
||||
src.opacity = 0
|
||||
var/turf/T = src.loc
|
||||
if (istype(T, /turf))
|
||||
T.updatecell = 1
|
||||
T.buildlinks()
|
||||
src.operating = 0
|
||||
|
||||
|
||||
// Called to open a firedoor
|
||||
// Play opening animation, update icon state, and update turf links
|
||||
|
||||
proc/openfire()
|
||||
set src in oview(1)
|
||||
|
||||
if (stat & NOPOWER) return
|
||||
|
||||
if ((src.operating || src.blocked))
|
||||
return
|
||||
use_power(50, ENVIRON)
|
||||
src.operating = 1
|
||||
flick("doorc0", src)
|
||||
src.icon_state = "door0"
|
||||
sleep(15)
|
||||
src.density = 0
|
||||
src.opacity = 0
|
||||
var/turf/T = src.loc
|
||||
if (istype(T, /turf))
|
||||
T.updatecell = 1
|
||||
T.buildlinks()
|
||||
src.operating = 0
|
||||
|
||||
|
||||
// Called to close a firedoor.
|
||||
// Play closing animation, update icon state, and update turf links.
|
||||
|
||||
proc/closefire()
|
||||
set src in oview(1)
|
||||
|
||||
if (stat & NOPOWER) return
|
||||
|
||||
if (src.operating)
|
||||
return
|
||||
use_power(50, ENVIRON)
|
||||
src.operating = 1
|
||||
flick("doorc1", src)
|
||||
src.icon_state = "door1"
|
||||
src.density = 1
|
||||
src.opacity = 1
|
||||
var/turf/T = src.loc
|
||||
if (istype(T, /turf))
|
||||
T.updatecell = 0
|
||||
T.buildlinks()
|
||||
T.firelevel = 0
|
||||
sleep(15)
|
||||
src.operating = 0
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
/*
|
||||
* Poddoor -- A remotely controlled door. Operable from pod computers and remote door controls.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
obj/machinery/door/poddoor
|
||||
name = "poddoor"
|
||||
icon = 'Door1.dmi'
|
||||
icon_state = "pdoor1"
|
||||
var
|
||||
id = 1.0 // ID that must match that of the controlling device
|
||||
|
||||
|
||||
// Standard open() and close() procs do not work
|
||||
|
||||
open()
|
||||
usr << "This is a remote controlled door!"
|
||||
|
||||
close()
|
||||
usr << "This is a remote controlled door!"
|
||||
|
||||
|
||||
|
||||
// Attack by item.
|
||||
// If crowbar (and door unpowered), open the door
|
||||
|
||||
attackby(obj/item/weapon/C as obj, mob/user as mob)
|
||||
src.add_fingerprint(user)
|
||||
if (!( istype(C, /obj/item/weapon/crowbar) ))
|
||||
return
|
||||
if ((src.density && (stat & NOPOWER) && !( src.operating )))
|
||||
spawn( 0 )
|
||||
src.operating = 1
|
||||
flick("pdoorc0", src)
|
||||
src.icon_state = "pdoor0"
|
||||
sleep(15)
|
||||
src.density = 0
|
||||
src.opacity = 0
|
||||
var/turf/T = src.loc
|
||||
if (istype(T, /turf))
|
||||
T.updatecell = 1
|
||||
T.buildlinks()
|
||||
src.operating = 0
|
||||
return
|
||||
|
||||
// Called to open a poddoor
|
||||
|
||||
proc/openpod()
|
||||
set src in oview(1)
|
||||
|
||||
if(stat & NOPOWER) return
|
||||
|
||||
if (src.operating || !src.density)
|
||||
return
|
||||
src.operating = 1
|
||||
use_power(50)
|
||||
flick("pdoorc0", src)
|
||||
src.icon_state = "pdoor0"
|
||||
sleep(15)
|
||||
src.density = 0
|
||||
src.opacity = 0
|
||||
var/turf/T = src.loc
|
||||
if (istype(T, /turf))
|
||||
T.updatecell = 1
|
||||
T.buildlinks()
|
||||
src.operating = 0
|
||||
|
||||
|
||||
// Called to close a poddoor
|
||||
|
||||
proc/closepod()
|
||||
set src in oview(1)
|
||||
|
||||
if(stat & NOPOWER) return
|
||||
|
||||
if (src.operating || src.density)
|
||||
return
|
||||
use_power(50)
|
||||
src.operating = 1
|
||||
flick("pdoorc1", src)
|
||||
src.icon_state = "pdoor1"
|
||||
src.density = 1
|
||||
src.opacity = 1
|
||||
var/turf/T = src.loc
|
||||
if (istype(T, /turf))
|
||||
T.updatecell = 0
|
||||
T.buildlinks()
|
||||
sleep(15)
|
||||
src.operating = 0
|
||||
@@ -0,0 +1,136 @@
|
||||
/*
|
||||
* Window door -- A non-opaque door covering either the south or east edges of a turf
|
||||
*
|
||||
* If the door has an access requirement, the security door icon is substituted
|
||||
*/
|
||||
|
||||
|
||||
obj/machinery/door/window
|
||||
name = "interior door"
|
||||
icon = 'windoor.dmi'
|
||||
visible = 0.0 // Door is not opaque when closed
|
||||
flags = WINDOW
|
||||
opacity = 0
|
||||
|
||||
// Note dir var sets the 4 possible states - "door handle" points in the dir direction, slides in opposite dirn to open
|
||||
// dir=1 : Door on east edge, slides to south
|
||||
// dir=2: Door on east edge, slides to north
|
||||
// dir=4: Door on south edge, slides to west
|
||||
// dir=8: Door on south edge, slides to east
|
||||
|
||||
|
||||
// Create a new windowdoor. If access controls are set, use the alternate icon for security doors
|
||||
|
||||
New()
|
||||
..()
|
||||
var/turf/T = src.loc
|
||||
if (T)
|
||||
T.updatecell = 1
|
||||
T.buildlinks()
|
||||
if ( (access && access!="0000") || allowed)
|
||||
src.icon = 'security.dmi'
|
||||
|
||||
|
||||
// Override close() proc since windowdoors still update their turf when closed, unlike other doors.
|
||||
|
||||
close()
|
||||
..() // call standard door/close() proc
|
||||
var/turf/T = src.loc
|
||||
if (T)
|
||||
T.updatecell = 1 // turf still runs gas simulation
|
||||
T.buildlinks()
|
||||
return
|
||||
|
||||
|
||||
// If a mob bumps into the door, cycle the door (open then close)
|
||||
|
||||
Bumped(atom/movable/AM)
|
||||
if (!( ismob(AM) ))
|
||||
return
|
||||
src.cycle(AM,1)
|
||||
return
|
||||
|
||||
|
||||
// Attack by monkey same as human
|
||||
|
||||
attack_paw(mob/user)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// Human attack hand - cycle the door
|
||||
|
||||
attack_hand(mob/user)
|
||||
src.cycle(user,0)
|
||||
|
||||
|
||||
// Called to cycle a windowdoor
|
||||
// If an unsecured door, open for 5 seconds, then close again
|
||||
// Otherwise, check ID access levels and toggle open/closed state
|
||||
// arg bumped is true if called from the Bump proc (will not check ID in this case)
|
||||
|
||||
proc/cycle(mob/user, bumped=0)
|
||||
if (!( ticker )) // doors won't open until round has started
|
||||
return
|
||||
if (src.operating)
|
||||
return
|
||||
if (access && access=="0000" && !allowed) // unsecure door
|
||||
if (src.density)
|
||||
open() // open then close 5 seconds later
|
||||
sleep(50)
|
||||
close()
|
||||
return
|
||||
|
||||
if(bumped) // if called from Bump(), return now - you can't bump open a secure door
|
||||
return
|
||||
|
||||
var/obj/item/weapon/card/id/card // check if user is human and wearing ID
|
||||
if (istype(user, /mob/human))
|
||||
var/mob/human/H = user
|
||||
card = H.wear_id
|
||||
if (!( istype(card, /obj/item/weapon/card/id) ))
|
||||
return
|
||||
else
|
||||
return
|
||||
if (card.check_access(access, allowed)) // check access levels of worn ID
|
||||
if (src.density) // and toggle door open/closed depending on current state
|
||||
open()
|
||||
else
|
||||
close()
|
||||
else
|
||||
if (src.density)
|
||||
flick("door_deny", src)
|
||||
|
||||
|
||||
// Note attackby item (ID) handled by standard door proc
|
||||
|
||||
|
||||
// Called in turf/Enter() to see if windowdoor is passable, when turf being entered contains a windowdoor
|
||||
// O is the moving object
|
||||
// target is the turf it wants to move into
|
||||
|
||||
CheckPass(atom/movable/O, target)
|
||||
if (src.density) // only check if door is closed
|
||||
var/direct = get_dir(O, target)
|
||||
if ((direct == NORTH && src.dir & 12)) // moving north, and door is on south edge of target
|
||||
return 0 // can't pass
|
||||
else
|
||||
if ((direct == WEST && src.dir & 3)) // moving west, and door is on east edge of target
|
||||
return 0
|
||||
return 1
|
||||
|
||||
|
||||
// Called in turf/Enter() to see if windowdoor is passable, when turf entering from contains a windowdoor
|
||||
// O is the moving object
|
||||
// target is the turf it wants to move into
|
||||
|
||||
CheckExit(atom/movable/O, target)
|
||||
|
||||
if (src.density) // only check if door is closed
|
||||
var/direct = get_dir(O, target)
|
||||
if ((direct == SOUTH && src.dir & 12)) // moving south, and door is on south edge
|
||||
return 0
|
||||
else
|
||||
if ((direct == EAST && src.dir & 3)) // moving east, and door is on east edge
|
||||
return 0
|
||||
return 1
|
||||
|
||||
@@ -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.loc))
|
||||
|
||||
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,704 @@
|
||||
/*
|
||||
* 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
|
||||
chargecount = 0 // H9.6 FIX: If breaker is off, stop charging
|
||||
charging = 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,258 @@
|
||||
/*
|
||||
* Generator - The main power generation machine
|
||||
*
|
||||
* A generator makes power using the heat difference between the gas levels in two circulator machines.
|
||||
*
|
||||
*/
|
||||
|
||||
#define GENRATE 0.0015 // generator output coefficient
|
||||
|
||||
obj/machinery/power/generator
|
||||
name = "generator"
|
||||
desc = "A high efficiency thermoelectric generator."
|
||||
icon_state = "teg"
|
||||
anchored = 1
|
||||
density = 1
|
||||
|
||||
var
|
||||
obj/machinery/circulator/circ1 // the cold gas circulator; must be to west of generator
|
||||
obj/machinery/circulator/circ2 // the hot gas circulator; must be to east of generator
|
||||
|
||||
c1on = 0 // true if circulator 1 is on
|
||||
c2on = 0 // " " " 2 " "
|
||||
c1rate = 10 // circulator 1's pumping rate (percentage)
|
||||
c2rate = 10 // circulator 2's pumping rate (percentage)
|
||||
lastgen = 0 // the power generated in the last cycle
|
||||
lastgenlev = -1 // the last bargraph overlay level
|
||||
|
||||
|
||||
// Create a generator, and locate the two circulators on either side
|
||||
|
||||
New()
|
||||
..()
|
||||
|
||||
spawn(5)
|
||||
circ1 = locate(/obj/machinery/circulator) in get_step(src,WEST)
|
||||
circ2 = locate(/obj/machinery/circulator) in get_step(src,EAST)
|
||||
if(!circ1 || !circ2)
|
||||
stat |= BROKEN
|
||||
|
||||
updateicon()
|
||||
|
||||
|
||||
// Update the icon overlays depending on status and power output level
|
||||
|
||||
proc/updateicon()
|
||||
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
overlays = null
|
||||
else
|
||||
overlays = null
|
||||
|
||||
if(lastgenlev != 0)
|
||||
overlays += image('power.dmi', "teg-op[lastgenlev]")
|
||||
|
||||
overlays += image('power.dmi', "teg-oc[c1on][c2on]")
|
||||
|
||||
|
||||
// Generate power, depending on the gas amounts and temperatures in the circulators
|
||||
|
||||
// The device works as a semi-realistic heat engine; heat from the hot reservoir is converted to energy
|
||||
// at a set efficiency (65% of Carnot). The waste heat is dumped into the cold reservoir
|
||||
// This can only be sustained while the cold reservoir is cooler than the hot one.
|
||||
|
||||
process()
|
||||
|
||||
if(circ1 && circ2) // both circulators must be present
|
||||
|
||||
|
||||
var/gc = circ1.gas2.shc()
|
||||
var/gh = circ2.gas2.shc()
|
||||
|
||||
var/tc = circ1.gas2.temperature
|
||||
var/th = circ2.gas2.temperature
|
||||
var/deltat = th-tc
|
||||
|
||||
var/eta = (1-tc/th)*0.65 // efficiency 65% of Carnot
|
||||
|
||||
if(gc > 0 && deltat >0) // require some cold gas (for sink) and a positive temp gradient
|
||||
var/ghoc = gh/gc
|
||||
|
||||
//var/qc = gc*tc
|
||||
//var/qh = gh*th
|
||||
|
||||
var/fdt = 1/( (1-eta)*ghoc + 1) // min timestep
|
||||
|
||||
fdt = min(fdt, 0.1) // max timestep
|
||||
|
||||
var/q = fdt*eta*gh*(deltat) // heat generated
|
||||
|
||||
var/thp = th - fdt * deltat
|
||||
var/tcp = tc + fdt * (1 - eta) * (ghoc) * deltat
|
||||
|
||||
lastgen = q * GENRATE
|
||||
add_avail(lastgen)
|
||||
|
||||
circ1.ngas2.temperature = tcp
|
||||
circ2.ngas2.temperature = thp
|
||||
|
||||
else
|
||||
lastgen = 0
|
||||
|
||||
|
||||
// update icon overlays only if displayed level has changed
|
||||
|
||||
var/genlev = max(0, min( round(11*lastgen / 100000), 11))
|
||||
if(genlev != lastgenlev)
|
||||
lastgenlev = genlev
|
||||
updateicon()
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.interact(M)
|
||||
|
||||
|
||||
// Attack with hand, open interaction window
|
||||
|
||||
attack_hand(mob/user)
|
||||
|
||||
add_fingerprint(user)
|
||||
|
||||
if(stat & (BROKEN|NOPOWER)) return
|
||||
|
||||
interact(user)
|
||||
|
||||
|
||||
// Display interaction window
|
||||
|
||||
proc/interact(mob/user)
|
||||
|
||||
if ( (get_dist(src, user) > 1 ))
|
||||
user.machine = null
|
||||
user << browse(null, "window=teg")
|
||||
return
|
||||
|
||||
user.machine = src
|
||||
|
||||
var/t = "<PRE><B>Thermo-Electric Generator</B><HR>"
|
||||
|
||||
t += "Output : [round(lastgen)] W<BR><BR>"
|
||||
|
||||
t += "<B>Cold loop</B><BR>"
|
||||
t += "Temperature Inlet: [round(circ1.ngas1.temperature, 0.1)] K Outlet: [round(circ1.ngas2.temperature, 0.1)] K<BR>"
|
||||
|
||||
t += "Circulator: [c1on ? "<B>On</B> <A href = '?src=\ref[src];c1p=1'>Off</A>" : "<A href = '?src=\ref[src];c1p=1'>On</A> <B>Off</B> "]<BR>"
|
||||
t += "Rate: <A href = '?src=\ref[src];c1r=-3'>M</A> <A href = '?src=\ref[src];c1r=-2'>-</A> <A href = '?src=\ref[src];c1r=-1'>-</A> [add_lspace(c1rate,3)]% <A href = '?src=\ref[src];c1r=1'>+</A> <A href = '?src=\ref[src];c1r=2'>+</A> <A href = '?src=\ref[src];c1r=3'>M</A><BR>"
|
||||
|
||||
t += "<B>Hot loop</B><BR>"
|
||||
t += "Temperature Inlet: [round(circ2.ngas1.temperature, 0.1)] K Outlet: [round(circ2.ngas2.temperature, 0.1)] K<BR>"
|
||||
|
||||
t += "Circulator: [c2on ? "<B>On</B> <A href = '?src=\ref[src];c2p=1'>Off</A>" : "<A href = '?src=\ref[src];c2p=1'>On</A> <B>Off</B> "]<BR>"
|
||||
t += "Rate: <A href = '?src=\ref[src];c2r=-3'>M</A> <A href = '?src=\ref[src];c2r=-2'>-</A> <A href = '?src=\ref[src];c2r=-1'>-</A> [add_lspace(c2rate,3)]% <A href = '?src=\ref[src];c2r=1'>+</A> <A href = '?src=\ref[src];c2r=2'>+</A> <A href = '?src=\ref[src];c2r=3'>M</A><BR>"
|
||||
|
||||
t += "<BR><HR><A href='?src=\ref[src];close=1'>Close</A>"
|
||||
|
||||
t += "</PRE>"
|
||||
user << browse(t, "window=teg;size=460x300")
|
||||
return
|
||||
|
||||
|
||||
// Handle topic links from 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=teg")
|
||||
usr.machine = null
|
||||
return
|
||||
|
||||
else if( href_list["c1p"] )
|
||||
c1on = !c1on
|
||||
circ1.control(c1on, c1rate) // used to control the circulator power and rate settings
|
||||
updateicon()
|
||||
else if( href_list["c2p"] )
|
||||
c2on = !c2on
|
||||
circ2.control(c2on, c2rate)
|
||||
updateicon()
|
||||
|
||||
else if( href_list["c1r"] )
|
||||
|
||||
var/i = text2num(href_list["c1r"])
|
||||
|
||||
var/d = 0
|
||||
switch(i)
|
||||
if(-3)
|
||||
c1rate = 0
|
||||
if(3)
|
||||
c1rate = 100
|
||||
|
||||
if(1)
|
||||
d = 1
|
||||
if(-1)
|
||||
d = -1
|
||||
if(2)
|
||||
d = 10
|
||||
if(-2)
|
||||
d = -10
|
||||
|
||||
c1rate += d
|
||||
c1rate = max(1, min(100, c1rate)) // clamp to range
|
||||
|
||||
circ1.control(c1on, c1rate)
|
||||
updateicon()
|
||||
|
||||
else if( href_list["c2r"] )
|
||||
|
||||
var/i = text2num(href_list["c2r"])
|
||||
|
||||
var/d = 0
|
||||
switch(i)
|
||||
if(-3)
|
||||
c2rate = 0
|
||||
if(3)
|
||||
c2rate = 100
|
||||
|
||||
if(1)
|
||||
d = 1
|
||||
if(-1)
|
||||
d = -1
|
||||
if(2)
|
||||
d = 10
|
||||
if(-2)
|
||||
d = -10
|
||||
|
||||
c2rate += d
|
||||
c2rate = max(1, min(100, c2rate)) // clamp to range
|
||||
|
||||
circ2.control(c2on, c2rate)
|
||||
updateicon()
|
||||
|
||||
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=teg")
|
||||
usr.machine = null
|
||||
|
||||
return
|
||||
|
||||
|
||||
// When are power changes, perfrom default action and update icon overlays
|
||||
|
||||
power_change()
|
||||
..()
|
||||
updateicon()
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
/*
|
||||
* Power Monitor - reports the available power, load, and status of APCs on the same power network.
|
||||
*
|
||||
* Also allows (limited) remote control of APCs on same network
|
||||
*/
|
||||
|
||||
obj/machinery/power/monitor
|
||||
name = "power monitoring computer"
|
||||
icon = 'stationobjs.dmi'
|
||||
icon_state = "power_computer"
|
||||
density = 1
|
||||
anchored = 1
|
||||
var
|
||||
control = 0 // true if remote APC control is enabled
|
||||
access = "4000/2030/3004" // ID card access levels needed to enable remote control
|
||||
allowed = "Systems" // ID card job assignment needed to enable remote control
|
||||
|
||||
|
||||
// Attack with hand, show report window
|
||||
|
||||
attack_hand(mob/user)
|
||||
add_fingerprint(user)
|
||||
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
interact(user)
|
||||
|
||||
|
||||
// Attack with item
|
||||
// If ID card, check access and enable/disable remote APC control
|
||||
|
||||
attackby(obj/item/weapon/W, mob/user)
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
if (istype(W, /obj/item/weapon/card/id) ) // trying to toggle remote control with an ID card
|
||||
|
||||
var/obj/item/weapon/card/id/I = W
|
||||
if (I.check_access(access, allowed))
|
||||
control = !control
|
||||
user << "You [ control ? "enable" : "disable"] remote APC control."
|
||||
else
|
||||
user << "\red Access denied."
|
||||
else
|
||||
attack_hand(user) // otherwise interact as usual
|
||||
|
||||
// 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)
|
||||
|
||||
if(control)
|
||||
t += "<I><BIG>(Swipe ID card to disable remote control.)</BIG></I><BR>"
|
||||
else
|
||||
t += "<I><BIG>(Swipe ID card to enable remote control.)</BIG></I><BR>"
|
||||
|
||||
t += "Area Brkr./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)
|
||||
if(control)
|
||||
t += " (<A href='?src=\ref[src];apc=\ref[A];breaker=1'>[A.operating? " On" : "Off"]</A>)"
|
||||
else
|
||||
t += " ([A.operating? "On " : "Off"])"
|
||||
|
||||
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=450x740")
|
||||
|
||||
|
||||
// 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["breaker"])
|
||||
var/obj/machinery/power/apc/APC = locate(href_list["apc"])
|
||||
APC.operating = !APC.operating
|
||||
APC.update()
|
||||
APC.updateicon()
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.interact(M)
|
||||
else if( href_list["close"] )
|
||||
usr << browse(null, "window=powcomp")
|
||||
usr.machine = null
|
||||
return
|
||||
else
|
||||
usr << browse(null, "window=powcomp")
|
||||
usr.machine = null
|
||||
|
||||
// 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,338 @@
|
||||
/*
|
||||
* SMES -- Superconduction magnetic energy storage unit
|
||||
*
|
||||
* A machine that stores power.
|
||||
*
|
||||
* SMESes have two "sides" where the are connected to the cable network: Input and output.
|
||||
* The input side is connected via a terminal to the SMES; this is where the SMES draws power from to charge
|
||||
* The output side is directly wired to the SMES object; this is where the SMES outputs stored power
|
||||
* If the two sides are part of the same powernet, the SMES will still work correctly
|
||||
*
|
||||
* TODO: See note a proc/restore() below
|
||||
*/
|
||||
|
||||
#define SMESMAXCHARGELEVEL 60000 // This is the maximum rate at which you can charge the SMES
|
||||
|
||||
#define SMESMAXOUTPUT 60000 // This is the maxmium output power of the SMES
|
||||
|
||||
#define SMESRATE 0.05 // rate of internal charge to external power output
|
||||
|
||||
|
||||
/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
|
||||
var
|
||||
output = 30000 // the current power output level - limited to SMEXMAXOUTPUT
|
||||
lastout = 0 // the output during the last cycle
|
||||
loaddemand = 0 // the actual amount during the last cycle (may be lower if powernet load is lower)
|
||||
capacity = 5e6 // the total maximum charge capacity
|
||||
charge = 1e6 // the current charge level; default is 20% of maximum
|
||||
charging = 0 // true if charging
|
||||
chargemode = 0 // true if set to automatically charge
|
||||
chargecount = 0 // count of number of times excess power has been availiable (used to control when charging is started)
|
||||
chargelevel = 30000 // the amount of power to use to charge the SMES - limited to SMESMAXCHARGELEVEL
|
||||
online = 1 // true if online (outputing power)
|
||||
n_tag = null // a string nametag to display on the control panel (e.g. Main No. 1)
|
||||
obj/machinery/power/terminal/terminal = null // the input terminal connected to this SMES
|
||||
|
||||
|
||||
// Create a new SMES
|
||||
// After waiting for the powernets to be built, look for a matching terminal in the 4 cardinal directions
|
||||
// If found, store the terminal, otherwise mark the SMES as broken
|
||||
|
||||
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 must have wires pointing towards the SMES
|
||||
terminal = term
|
||||
break dir_loop
|
||||
|
||||
if(!terminal)
|
||||
stat |= BROKEN
|
||||
return
|
||||
|
||||
terminal.master = src
|
||||
|
||||
updateicon()
|
||||
|
||||
|
||||
|
||||
// Updates the SMES icon to show overlays representing charging state, online state, and charge level
|
||||
|
||||
proc/updateicon()
|
||||
|
||||
overlays = null
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
|
||||
overlays += image('power.dmi', "smes-op[online]")
|
||||
|
||||
if(charging)
|
||||
overlays += image('power.dmi', "smes-oc1")
|
||||
else
|
||||
if(chargemode)
|
||||
overlays += image('power.dmi', "smes-oc0")
|
||||
|
||||
var/clevel = chargedisplay()
|
||||
if(clevel>0)
|
||||
overlays += image('power.dmi', "smes-og[clevel]")
|
||||
|
||||
|
||||
// Returns the level (0-5) of the bargraph overlay (representing the charge level) to display
|
||||
|
||||
proc/chargedisplay()
|
||||
return round(5.5*charge/capacity)
|
||||
|
||||
|
||||
|
||||
// Timed process; recharge the SMES if power is available, output power if online
|
||||
|
||||
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,10)) // random count to switch to charging reduces thrashing
|
||||
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()
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.interact(M)
|
||||
|
||||
|
||||
|
||||
// A special routine for SMES
|
||||
// Called by the main game loop after all other power processes are finished
|
||||
// SMESes make availabe a set amount of power per cycle, but should only have as much power drained
|
||||
// as the actual load that cycle. This restore() proc restores the excess charge that wasn't really used.
|
||||
|
||||
// TODO: Make the charge restoration more logical. Either need a priority setting, or some way to evenly
|
||||
// share load between SMESes.
|
||||
|
||||
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()
|
||||
|
||||
|
||||
// Add a load amount. Loading is done throught the terminal's powernet for SMESes
|
||||
|
||||
add_load(var/amount)
|
||||
if(terminal && terminal.powernet)
|
||||
terminal.powernet.newload += amount
|
||||
|
||||
|
||||
// Attack to open interaction window
|
||||
|
||||
attack_hand(mob/user)
|
||||
|
||||
add_fingerprint(user)
|
||||
|
||||
if(stat & BROKEN) return
|
||||
|
||||
interact(user)
|
||||
|
||||
|
||||
// Display interaction window
|
||||
|
||||
proc/interact(mob/user)
|
||||
|
||||
if ( (get_dist(src, user) > 1 ))
|
||||
user.machine = null
|
||||
user << browse(null, "window=smes")
|
||||
return
|
||||
|
||||
user.machine = src
|
||||
|
||||
|
||||
var/t = "<TT><B>SMES Power Storage Unit</B> [n_tag? "([n_tag])" : null]<HR><PRE>"
|
||||
|
||||
t += "Stored capacity : [round(100.0*charge/capacity, 0.1)]%<BR><BR>"
|
||||
|
||||
t += "Input: [charging ? "Charging" : "Not Charging"] [chargemode ? "<B>Auto</B> <A href = '?src=\ref[src];cmode=1'>Off</A>" : "<A href = '?src=\ref[src];cmode=1'>Auto</A> <B>Off</B> "]<BR>"
|
||||
|
||||
|
||||
t += "Input level: <A href = '?src=\ref[src];input=-4'>M</A> <A href = '?src=\ref[src];input=-3'>-</A> <A href = '?src=\ref[src];input=-2'>-</A> <A href = '?src=\ref[src];input=-1'>-</A> [add_lspace(chargelevel,5)] <A href = '?src=\ref[src];input=1'>+</A> <A href = '?src=\ref[src];input=2'>+</A> <A href = '?src=\ref[src];input=3'>+</A> <A href = '?src=\ref[src];input=4'>M</A><BR>"
|
||||
|
||||
t += "<BR><BR>"
|
||||
|
||||
t += "Output: [online ? "<B>Online</B> <A href = '?src=\ref[src];online=1'>Offline</A>" : "<A href = '?src=\ref[src];online=1'>Online</A> <B>Offline</B> "]<BR>"
|
||||
|
||||
t += "Output level: <A href = '?src=\ref[src];output=-4'>M</A> <A href = '?src=\ref[src];output=-3'>-</A> <A href = '?src=\ref[src];output=-2'>-</A> <A href = '?src=\ref[src];output=-1'>-</A> [add_lspace(output,5)] <A href = '?src=\ref[src];output=1'>+</A> <A href = '?src=\ref[src];output=2'>+</A> <A href = '?src=\ref[src];output=3'>+</A> <A href = '?src=\ref[src];output=4'>M</A><BR>"
|
||||
|
||||
t += "Output load: [round(loaddemand)] W<BR>"
|
||||
|
||||
t += "<BR></PRE><HR><A href='?src=\ref[src];close=1'>Close</A>"
|
||||
|
||||
t += "</TT>"
|
||||
user << browse(t, "window=smes;size=460x300")
|
||||
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=smes")
|
||||
usr.machine = null
|
||||
return
|
||||
|
||||
else if( href_list["cmode"] )
|
||||
chargemode = !chargemode
|
||||
if(!chargemode)
|
||||
charging = 0
|
||||
updateicon()
|
||||
|
||||
else if( href_list["online"] )
|
||||
online = !online
|
||||
updateicon()
|
||||
else if( href_list["input"] )
|
||||
|
||||
var/i = text2num(href_list["input"])
|
||||
|
||||
var/d = 0
|
||||
switch(i)
|
||||
if(-4)
|
||||
chargelevel = 0
|
||||
if(4)
|
||||
chargelevel = SMESMAXCHARGELEVEL //30000
|
||||
|
||||
if(1)
|
||||
d = 100
|
||||
if(-1)
|
||||
d = -100
|
||||
if(2)
|
||||
d = 1000
|
||||
if(-2)
|
||||
d = -1000
|
||||
if(3)
|
||||
d = 10000
|
||||
if(-3)
|
||||
d = -10000
|
||||
|
||||
chargelevel += d
|
||||
chargelevel = max(0, min(SMESMAXCHARGELEVEL, chargelevel)) // clamp to range
|
||||
|
||||
else if( href_list["output"] )
|
||||
|
||||
var/i = text2num(href_list["output"])
|
||||
|
||||
var/d = 0
|
||||
switch(i)
|
||||
if(-4)
|
||||
output = 0
|
||||
if(4)
|
||||
output = SMESMAXOUTPUT //30000
|
||||
|
||||
if(1)
|
||||
d = 100
|
||||
if(-1)
|
||||
d = -100
|
||||
if(2)
|
||||
d = 1000
|
||||
if(-2)
|
||||
d = -1000
|
||||
if(3)
|
||||
d = 10000
|
||||
if(-3)
|
||||
d = -10000
|
||||
|
||||
output += d
|
||||
output = max(0, min(SMESMAXOUTPUT, output)) // clamp to range
|
||||
|
||||
|
||||
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=smes")
|
||||
usr.machine = null
|
||||
|
||||
return
|
||||
@@ -0,0 +1,135 @@
|
||||
/*
|
||||
* 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
|
||||
dir = SOUTH // the current direction of the solar panel
|
||||
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
|
||||
|
||||
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
|
||||
// As the object direction is changed, the overlay direction will echo it
|
||||
|
||||
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)
|
||||
|
||||
|
||||
// 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(dir) - 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(dir == 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
|
||||
dir = turn(dir, 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.dir // 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.dir) - 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"
|
||||
@@ -0,0 +1,240 @@
|
||||
/*
|
||||
* Turbine and compressor -- auxilliary power generation system
|
||||
*
|
||||
* TODO: Tweak values to make the aux generator useful. It was intended to generate large amounts of power,
|
||||
* but use up plasma too fast to be sustainable for a long time.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Compressor - not actually a power-connected machine, but only used with a turbine
|
||||
*/
|
||||
|
||||
#define COMPFRICTION 5e5 // a breaking friction coefficient (so compressor has a maximum speed
|
||||
// and spins down when unpowered)
|
||||
#define COMPSTARTERLOAD 2800 // the power load needed to run the starter
|
||||
|
||||
obj/machinery/compressor
|
||||
name = "compressor"
|
||||
desc = "The compressor stage of a gas turbine generator."
|
||||
icon = 'pipes.dmi'
|
||||
icon_state = "compressor"
|
||||
anchored = 1
|
||||
density = 1
|
||||
var
|
||||
obj/machinery/power/turbine/turbine // the associated turbine object
|
||||
obj/substance/gas/gas // the gas reservoir inside the compressor
|
||||
turf/inturf // the inlet turf (where gas is drawn in)
|
||||
starter = 0 // true if the starter is engaged
|
||||
rpm = 0 // the current spin rate
|
||||
rpmtarget = 0 // the target spin rate
|
||||
capacity = 1e6 // maximum gas capacity
|
||||
|
||||
|
||||
// Create a compressor. Set the inlet turf (one step to west) and the turbine (one step to east)
|
||||
|
||||
New()
|
||||
..()
|
||||
|
||||
gas = new/obj/substance/gas(src)
|
||||
gas.maximum = capacity
|
||||
inturf = get_step(src, WEST)
|
||||
|
||||
spawn(5)
|
||||
turbine = locate() in get_step(src, EAST)
|
||||
if(!turbine)
|
||||
stat |= BROKEN
|
||||
|
||||
|
||||
// Timed process. Make spin rate tend to the target rate, draw in gas.
|
||||
//set target rate to 1000 if starter is on, and display the icon overlay correspoinding to the current spin rate
|
||||
|
||||
process()
|
||||
|
||||
overlays = null
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
|
||||
rpm = 0.9* rpm + 0.1 * rpmtarget
|
||||
|
||||
|
||||
gas.turf_take(inturf, rpm/30000*capacity)
|
||||
|
||||
|
||||
rpm = max(0, rpm - (rpm*rpm)/COMPFRICTION)
|
||||
|
||||
|
||||
if(starter && !(stat & NOPOWER))
|
||||
use_power(2800)
|
||||
if(rpm<1000)
|
||||
rpmtarget = 1000
|
||||
else
|
||||
starter = 0
|
||||
else
|
||||
if(rpm<1000)
|
||||
rpmtarget = 0
|
||||
|
||||
|
||||
|
||||
if(rpm>50000)
|
||||
overlays += image('pipes.dmi', "comp-o4", FLY_LAYER)
|
||||
else if(rpm>10000)
|
||||
overlays += image('pipes.dmi', "comp-o3", FLY_LAYER)
|
||||
else if(rpm>2000)
|
||||
overlays += image('pipes.dmi', "comp-o2", FLY_LAYER)
|
||||
if(rpm>500)
|
||||
overlays += image('pipes.dmi', "comp-o1", FLY_LAYER)
|
||||
|
||||
|
||||
/*
|
||||
* Turbine - generates power and spins compressor depending on gas parameters inside the compressor
|
||||
*/
|
||||
|
||||
#define TURBPRES 90000000 // the "pressure" (gas amount * temperature) required to generate 30000 RPM
|
||||
#define TURBGENQ 20000 // coefficient relating spin rate to power generated
|
||||
#define TURBGENG 0.8 // linearity coefficient of spinrate/power curve (1=linear)
|
||||
|
||||
|
||||
obj/machinery/power/turbine
|
||||
name = "gas turbine generator"
|
||||
desc = "A gas turbine used to for backup power generation."
|
||||
icon = 'pipes.dmi'
|
||||
icon_state = "turbine"
|
||||
anchored = 1
|
||||
density = 1
|
||||
directwired = 1
|
||||
|
||||
var
|
||||
obj/machinery/compressor/compressor // the associated compressor
|
||||
turf/outturf // the outlet turf (1 step to east)
|
||||
lastgen // the power generated last cycle
|
||||
|
||||
|
||||
|
||||
|
||||
// Create a turbine. Sets the outlet turf (1 step to east) and the compressor (1 step to west)
|
||||
|
||||
New()
|
||||
..()
|
||||
|
||||
outturf = get_step(src, EAST)
|
||||
|
||||
spawn(5)
|
||||
|
||||
compressor = locate() in get_step(src, WEST)
|
||||
if(!compressor)
|
||||
stat |= BROKEN
|
||||
|
||||
|
||||
// Timed process.
|
||||
// Generate power depending on current rpm. Set new target rpm depending on compressor gas temperature and amount
|
||||
// Output gas to outlet turf. Update overlay if actually generating signifcant power
|
||||
|
||||
|
||||
process()
|
||||
|
||||
overlays = null
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
|
||||
lastgen = ((compressor.rpm / TURBGENQ)**TURBGENG) *TURBGENQ
|
||||
add_avail(lastgen)
|
||||
|
||||
if(compressor.gas.temperature > (T20C+50))
|
||||
var/newrpm = ((compressor.gas.temperature-T20C-50) * compressor.gas.tot_gas() / TURBPRES)*30000
|
||||
newrpm = max(0, newrpm)
|
||||
|
||||
if(!compressor.starter || newrpm > 1000)
|
||||
compressor.rpmtarget = newrpm
|
||||
|
||||
var/oamount = min(compressor.gas.tot_gas(), compressor.rpm/32000*compressor.capacity)
|
||||
|
||||
compressor.gas.turf_add(outturf, oamount)
|
||||
|
||||
outturf.firelevel = outturf.poison
|
||||
|
||||
if(lastgen > 100)
|
||||
overlays += image('pipes.dmi', "turb-o", FLY_LAYER)
|
||||
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.interact(M)
|
||||
|
||||
|
||||
// Attack hand, do user interaction
|
||||
|
||||
attack_hand(mob/user)
|
||||
|
||||
add_fingerprint(user)
|
||||
|
||||
if(stat & (BROKEN | NOPOWER)) return
|
||||
|
||||
interact(user)
|
||||
|
||||
|
||||
// Show the interaction window
|
||||
|
||||
proc/interact(mob/user)
|
||||
|
||||
if ( (get_dist(src, user) > 1 ) || (stat & (NOPOWER|BROKEN)) )
|
||||
user.machine = null
|
||||
user << browse(null, "window=turbine")
|
||||
return
|
||||
|
||||
user.machine = src
|
||||
|
||||
var/t = "<TT><B>Gas Turbine Generator</B><HR><PRE>"
|
||||
|
||||
var/gen = max(0, lastgen - (compressor.starter * COMPSTARTERLOAD) )
|
||||
t += "Generated power : [round(gen)] W<BR><BR>"
|
||||
|
||||
t += "Turbine: [round(compressor.rpm)] RPM<BR>"
|
||||
|
||||
t += "Starter: [ compressor.starter ? "<A href='?src=\ref[src];str=1'>Off</A> <B>On</B>" : "<B>Off</B> <A href='?src=\ref[src];str=1'>On</A>"]<BR>"
|
||||
|
||||
//t += "Gas: [compressor.gas.tostring()]<BR>"
|
||||
|
||||
t += "</PRE><HR><A href='?src=\ref[src];close=1'>Close</A>"
|
||||
|
||||
t += "</TT>"
|
||||
user << browse(t, "window=turbine")
|
||||
|
||||
return
|
||||
|
||||
|
||||
// Handle topic links from interaction window
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
if(stat & BROKEN)
|
||||
return
|
||||
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 (( usr.machine==src && (get_dist(src, usr) <= 1 && istype(src.loc, /turf))))
|
||||
|
||||
|
||||
if( href_list["close"] )
|
||||
usr << browse(null, "window=turbine")
|
||||
usr.machine = null
|
||||
return
|
||||
|
||||
else if( href_list["str"] )
|
||||
compressor.starter = !compressor.starter
|
||||
|
||||
spawn(0)
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.interact(M)
|
||||
|
||||
else
|
||||
usr << browse(null, "window=turbine")
|
||||
usr.machine = null
|
||||
|
||||
return
|
||||
@@ -0,0 +1,169 @@
|
||||
/*
|
||||
* The base machinery object
|
||||
*
|
||||
* Machines have a process() proc called approximately once per second while a game round is in progress
|
||||
* Thus they can perform repetative tasks, such as calculating pipe gas flow, power usage, etc.
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
obj/machinery
|
||||
|
||||
var
|
||||
p_dir = 0 // directions of regular pipes connected to this machine
|
||||
// bitwise-OR of cardinal directions to indicate multiple pipes
|
||||
h_dir = 0 // as above, but for heat-exchange pipes
|
||||
|
||||
capmult = 0 // used for gas flow - a capacity multiplier
|
||||
|
||||
stat = 0 // machinery status bitflags
|
||||
// currently used values: 1 - BROKEN ; 2 - NOPOWER
|
||||
|
||||
|
||||
// New() and Del() add and remove machines from the global "machines" list
|
||||
// This list is used to call the process() proc for all machines ~1 per second during a round
|
||||
|
||||
New()
|
||||
..()
|
||||
machines += src
|
||||
|
||||
Del()
|
||||
machines -= src
|
||||
..()
|
||||
|
||||
|
||||
// Called when an object is in an explosion
|
||||
// Higher "severity" means the object was further from the centre of the explosion
|
||||
|
||||
ex_act(severity)
|
||||
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
del(src)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
del(src)
|
||||
return
|
||||
if(3.0)
|
||||
if (prob(25))
|
||||
del(src)
|
||||
return
|
||||
|
||||
|
||||
// Called when attacked by a blob
|
||||
|
||||
blob_act()
|
||||
if(prob(25))
|
||||
del(src)
|
||||
|
||||
|
||||
/*
|
||||
* Prototype procs common to all /obj/machinery objects
|
||||
*/
|
||||
|
||||
|
||||
// Called for all /obj/machinery in the "machines" list, approximately once per second
|
||||
// by /datum/control/cellular/process() when a game round is active
|
||||
// Any regular action of the machine is executed by this proc.
|
||||
// For machines that are part of a pipe network, this routine also calculates the gas flow to/from this machine.
|
||||
|
||||
proc/process()
|
||||
return
|
||||
|
||||
/*
|
||||
* Pipe and gas-flow related prototypes
|
||||
*/
|
||||
|
||||
// Machines needing extra processing for gas flow in pipes place themselves in the "gasflowlist" global list
|
||||
// All machines in that list have gas_flow() executed after all process() procedures in the world have completed
|
||||
// Used to avoid order-of-execution problems in pipe flow.
|
||||
// This routine usually just replaces the current gas levels with the new ones calculated in the process() proc.
|
||||
|
||||
proc/gas_flow()
|
||||
return
|
||||
|
||||
|
||||
// Builds pipe-connections for adjacent machines
|
||||
// Called after map load, then again whenever a pipeline is altered.
|
||||
|
||||
proc/buildnodes()
|
||||
return
|
||||
|
||||
|
||||
// For pipe-connected machinery, returns self
|
||||
// For pipe objects, returns the pipeline object containing this.
|
||||
|
||||
proc/getline()
|
||||
if(p_dir || h_dir)
|
||||
return src
|
||||
|
||||
|
||||
// Returns true if this is a pipe (or h/e pipe) object, false otherwise
|
||||
|
||||
proc/ispipe()
|
||||
return 0
|
||||
|
||||
|
||||
// Returns the next connected pipe in a pipeline, or null if this is not a pipe object
|
||||
|
||||
proc/next(from)
|
||||
return null
|
||||
|
||||
|
||||
// Returns the "gas val", usually the total gas content divided by the capacty multiplier
|
||||
// Roughly, this is how full of gas the machine is.Used to calculate gas flow in and out of the machine.
|
||||
// Argument indicates which node is enequiring, for machines that have more than one gas reservoir
|
||||
|
||||
proc/get_gas_val(from)
|
||||
return null
|
||||
|
||||
|
||||
// Returns the gas reservoir object of a machine (or null if none)
|
||||
// Used during gas flow calculations
|
||||
|
||||
proc/get_gas(from)
|
||||
return null
|
||||
|
||||
/*
|
||||
* Power related prototypes
|
||||
*/
|
||||
|
||||
|
||||
// Returns true if the area has power on given channel (or doesn't require power).
|
||||
// defaults to equipment channel
|
||||
|
||||
proc/powered(var/chan = EQUIP)
|
||||
var/area/A = src.loc.loc // make sure it's in an area
|
||||
if(!A || !isarea(A))
|
||||
return 0 // if not, then not powered
|
||||
|
||||
return A.powered(chan) // return power status of the area
|
||||
|
||||
|
||||
// Increment the power usage stats for an area
|
||||
// usually called by a machine in its process() proc
|
||||
|
||||
proc/use_power(var/amount, var/chan=EQUIP) // defaults to Equipment channel
|
||||
var/area/A = src.loc.loc // make sure it's in an area
|
||||
if(!A || !isarea(A))
|
||||
return
|
||||
|
||||
A.use_power(amount, chan)
|
||||
|
||||
|
||||
// Called for all machines in an area whenever power settings of the area change
|
||||
// By default, sets NOPOWER flag if the equipment channel is off
|
||||
// Override for other behaviour
|
||||
|
||||
proc/power_change()
|
||||
|
||||
|
||||
if(powered())
|
||||
stat &= ~NOPOWER
|
||||
else
|
||||
|
||||
stat |= NOPOWER
|
||||
return
|
||||
|
||||
@@ -0,0 +1,170 @@
|
||||
/*
|
||||
* Pipe Misc -- Global procs and support routines used in pipe network calculations.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
// Build the list of pipeline objects. Called after world has loaded.
|
||||
|
||||
/proc/makepipelines()
|
||||
|
||||
|
||||
for(var/obj/machinery/pipes/P in machines) // look for a pipe
|
||||
|
||||
if(!P.pl) // if not already part of a line
|
||||
var/obj/machinery/pipeline/PL = new() // make a new pipeline
|
||||
plines += PL // add it to the global list
|
||||
P.buildnodes(PL) // and spread to all connected pipes
|
||||
|
||||
// After the above, all pipes in the world will be associated with a pipeline object
|
||||
|
||||
// Now set pipeline names (so they can be distinguished for debugging).
|
||||
|
||||
for(var/L = 1 to length(plines)) // for count of lines found
|
||||
var/obj/machinery/pipeline/PL = plines[L] // get the pipeline virtual object
|
||||
PL.name = "pipeline #[L]" // and set the name
|
||||
|
||||
// Next, find the pipes at the end of each pipeline, and use those to get an ordered list of all pipes in the pipeline
|
||||
// Then set the pipeline variables
|
||||
|
||||
for(var/obj/machinery/pipes/P in machines) // look for pipes
|
||||
|
||||
if(P.termination) // true if pipe is terminated (ends in blank or a machine)
|
||||
var/obj/machinery/pipeline/PL = P.pl // get the pipeline from the pipe's pl
|
||||
|
||||
var/list/pipes = pipelist(null, P) // get a list of pipes from P until terminated
|
||||
|
||||
PL.nodes = pipes // pipeline is this list of nodes
|
||||
PL.numnodes = pipes.len // with this many nodes
|
||||
PL.capmult = PL.numnodes+1 // with this flow multiplier
|
||||
|
||||
|
||||
// Now set the node connections for all machines that connect to pipelines.
|
||||
|
||||
for(var/obj/machinery/M in machines) // for all machines
|
||||
if(M.p_dir || M.h_dir) // which are pipe-connected
|
||||
if(!M.ispipe()) // is not a pipe itself
|
||||
M.buildnodes() // build the nodes, setting the links to the pipelines
|
||||
// also sets the vnodes for the pipelines
|
||||
|
||||
// Finally, make sure the pipeline nodes point to the terminating machines.
|
||||
|
||||
for(var/obj/machinery/pipeline/PL in plines) // for all lines
|
||||
PL.setterm() // orient the pipes and set the pipeline vnodes to the terminating machines
|
||||
|
||||
|
||||
|
||||
// Return a list of pipes, in order of connection
|
||||
// Starting at startnode, moving away from source
|
||||
|
||||
/proc/pipelist(var/obj/machinery/source, var/obj/machinery/startnode)
|
||||
|
||||
var/list/L = list()
|
||||
|
||||
var/obj/machinery/node = startnode
|
||||
var/obj/machinery/prev = source
|
||||
var/obj/machinery/newnode
|
||||
|
||||
while(node)
|
||||
L += node
|
||||
newnode = node.next(prev)
|
||||
prev = node
|
||||
|
||||
if(newnode && newnode.ispipe())
|
||||
node = newnode
|
||||
else
|
||||
break
|
||||
|
||||
return L
|
||||
|
||||
|
||||
// Returns the machine with compatible p_dir and level in 1 step in dir mdir from turf S
|
||||
// Note: "compatible" means the machine has a p_dir pointing towards S.
|
||||
// Returns null if no such machine is found
|
||||
|
||||
/proc/get_machine(var/level, var/turf/S, var/mdir)
|
||||
|
||||
var/flip = turn(mdir, 180)
|
||||
|
||||
var/turf/T = get_step(S, mdir)
|
||||
|
||||
for(var/obj/machinery/M in T.contents)
|
||||
if(M.level == level)
|
||||
if(M.p_dir & flip)
|
||||
return M
|
||||
|
||||
return null
|
||||
|
||||
|
||||
// Returns the machine with compatible h_dir and level in 1 step in dir mdir from turf S
|
||||
// Same as routine above, but for h/e rather than standard pipe.
|
||||
|
||||
/proc/get_he_machine(var/level, var/turf/S, mdir)
|
||||
|
||||
var/flip = turn(mdir, 180)
|
||||
|
||||
var/turf/T = get_step(S, mdir)
|
||||
|
||||
for(var/obj/machinery/M in T.contents)
|
||||
if(M.level == level)
|
||||
if(M.h_dir & flip)
|
||||
return M
|
||||
|
||||
return null
|
||||
|
||||
|
||||
// The main flow routine
|
||||
// Calculates the movement of "amount" gas between source and target machines
|
||||
// If amount is negative, flow is from source to target, and source gas level is reduced
|
||||
// If amount is positive, flow is from target to source, and source gas level is increased by a fraction of the target gas
|
||||
// The source's new gas level is stored in "sngas", which replaces the actual gas level in the gas_flow() proc for this machine.
|
||||
// Note the target's gas level isn't altered here; it will run this proc itself and alter it's own gas levels by the correct amount.
|
||||
|
||||
|
||||
/proc/calc_delta(obj/machinery/source, obj/substance/gas/sgas, obj/substance/gas/sngas, obj/machinery/target, amount)
|
||||
|
||||
var/obj/substance/gas/tgas = target.get_gas(source)
|
||||
|
||||
var/obj/substance/gas/ndelta = new()
|
||||
|
||||
if(amount < 0) // then flowing from source to target
|
||||
|
||||
ndelta.set_frac(sgas, -amount) // this is fraction of the gas which will be transfered to other node
|
||||
sngas.sub_delta(ndelta) // subtract off the fraction which is gone
|
||||
|
||||
else // flowing from target to source
|
||||
ndelta.set_frac(tgas, amount) // fraction of gas from the other node
|
||||
sngas.add_delta(ndelta) // add the fraction to the new gas resv
|
||||
|
||||
|
||||
// Called by all gas-handling machines when a pipe node is not present.
|
||||
// Also used by /obj/machinery/inlet
|
||||
// Calculates a leak between a gas reservoir (sgas, sngas) and turf T
|
||||
// Gas can flow both ways, if pipe is less full than the turf
|
||||
|
||||
|
||||
/obj/machinery/proc/flow_to_turf(var/obj/substance/gas/sgas, var/obj/substance/gas/sngas, var/turf/T)
|
||||
|
||||
|
||||
|
||||
var/t_tot = T.tot_gas() * 0.2 // partial pressure of turf gas at pipe, for the moment
|
||||
|
||||
var/delta_gt = FLOWFRAC * ( t_tot - sgas.tot_gas() / capmult )
|
||||
|
||||
|
||||
var/obj/substance/gas/ndelta = new()
|
||||
|
||||
if(delta_gt < 0) // flow from pipe to turf
|
||||
|
||||
ndelta.set_frac(sgas, -delta_gt) // ndelta contains gas to transfer to turf
|
||||
sngas.sub_delta(ndelta) // update new gas to remove the amount transfered
|
||||
ndelta.turf_add(T, -1) // add all of ndelta to turf
|
||||
|
||||
else // flow from turf to pipe
|
||||
|
||||
sngas.turf_take(T, delta_gt) // grab gas from turf and direcly add it to the new gas
|
||||
|
||||
T.res_vars() // update turf gas vars for both cases
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,145 @@
|
||||
/**
|
||||
* Alarm -- Provides a visual indication when air quality is unbreathable (toxins, low pressure, etc.)
|
||||
*
|
||||
*/
|
||||
|
||||
obj/machinery/alarm
|
||||
name = "alarm"
|
||||
icon = 'stationobjs.dmi'
|
||||
icon_state = "alarm:0"
|
||||
anchored = 1.0
|
||||
|
||||
|
||||
// Monitors location air quality and changes icon_state to reflect it
|
||||
|
||||
process()
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "alarm-p"
|
||||
return
|
||||
|
||||
use_power(5, ENVIRON)
|
||||
|
||||
var/safe = 1
|
||||
var/turf/T = src.loc
|
||||
if (!( istype(T, /turf) ))
|
||||
return
|
||||
if (locate(/obj/move, T))
|
||||
T = locate(/obj/move, T)
|
||||
var/turf_total = T.co2 + T.oxygen + T.poison + T.sl_gas + T.n2
|
||||
turf_total = max(turf_total, 1)
|
||||
var/t1 = turf_total / CELLSTANDARD * 100
|
||||
if (!( (90 < t1 && t1 < 110) ))
|
||||
safe = 0
|
||||
t1 = T.oxygen / turf_total * 100
|
||||
if (!( (20 < t1 && t1 < 30) ))
|
||||
safe = 0
|
||||
src.icon_state = text("alarm:[]", !( safe ))
|
||||
return
|
||||
|
||||
|
||||
// Called when area power status changes. Alarms use the ENVIRON channel
|
||||
|
||||
power_change()
|
||||
if( powered(ENVIRON) )
|
||||
stat &= ~NOPOWER
|
||||
else
|
||||
stat |= NOPOWER
|
||||
|
||||
// Examining an alarm provides an air quality readout the same as a handheld air analyzer
|
||||
|
||||
examine()
|
||||
set src in oview(1)
|
||||
|
||||
if (usr.stat || stat & NOPOWER)
|
||||
return
|
||||
if ((!( istype(usr, /mob/human) ) && (!( ticker ) || (ticker && ticker.mode != "monkey"))))
|
||||
usr << "\red You don't have the dexterity to do this!"
|
||||
return
|
||||
var/turf/T = src.loc
|
||||
if (!( istype(T, /turf) ))
|
||||
return
|
||||
|
||||
var/turf_total = T.co2 + T.oxygen + T.poison + T.sl_gas + T.n2
|
||||
turf_total = max(turf_total, 1)
|
||||
usr.show_message("\blue <B>Results:</B>", 1)
|
||||
var/t = ""
|
||||
var/t1 = turf_total / CELLSTANDARD * 100
|
||||
if ((90 < t1 && t1 < 110))
|
||||
usr.show_message(text("\blue Air Pressure: []%", t1), 1)
|
||||
else
|
||||
usr.show_message(text("\blue Air Pressure:\red []%", t1), 1)
|
||||
t1 = T.n2 / turf_total * 100
|
||||
t1 = round(t1, 0.0010)
|
||||
if ((60 < t1 && t1 < 80))
|
||||
t += text("<font color=blue>Nitrogen: []</font> ", t1)
|
||||
else
|
||||
t += text("<font color=red>Nitrogen: []</font> ", t1)
|
||||
t1 = T.oxygen / turf_total * 100
|
||||
t1 = round(t1, 0.0010)
|
||||
if ((20 < t1 && t1 < 24))
|
||||
t += text("<font color=blue>Oxygen: []</font> ", t1)
|
||||
else
|
||||
t += text("<font color=red>Oxygen: []</font> ", t1)
|
||||
t1 = T.poison / turf_total * 100
|
||||
t1 = round(t1, 0.0010)
|
||||
if (t1 < 0.5)
|
||||
t += text("<font color=blue>Plasma: []</font> ", t1)
|
||||
else
|
||||
t += text("<font color=red>Plasma: []</font> ", t1)
|
||||
t1 = T.co2 / turf_total * 100
|
||||
t1 = round(t1, 0.0010)
|
||||
if (t1 < 1)
|
||||
t += text("<font color=blue>CO2: []</font> ", t1)
|
||||
else
|
||||
t += text("<font color=red>CO2: []</font> ", t1)
|
||||
t1 = T.sl_gas / turf_total * 100
|
||||
t1 = round(t1, 0.0010)
|
||||
if (t1 < 5)
|
||||
t += text("<font color=blue>NO2: []</font>", t1)
|
||||
else
|
||||
t += text("<font color=red>NO2: []</font>", t1)
|
||||
usr.show_message(t, 1)
|
||||
usr.show_message(text("\blue \t Temperature: []°C", T.temp - T0C), 1)
|
||||
src.add_fingerprint(usr)
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Indicator -- Subtype of alarm, used to indicated air quality in the airtunnel
|
||||
*
|
||||
*/
|
||||
|
||||
obj/machinery/alarm/indicator
|
||||
name = "indicator"
|
||||
icon = 'airtunnel.dmi'
|
||||
icon_state = "indicator"
|
||||
|
||||
|
||||
// Monitors location air quality and changes icon_state to reflect it
|
||||
// Also sets airtunnel datum air status
|
||||
|
||||
process()
|
||||
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "indicator-p"
|
||||
return
|
||||
|
||||
var/safe = 1
|
||||
var/turf/T = src.loc
|
||||
if (!( istype(T, /turf) ))
|
||||
return
|
||||
if (locate(/obj/move, T))
|
||||
T = locate(/obj/move, T)
|
||||
var/turf_total = T.co2 + T.oxygen + T.poison + T.sl_gas + T.n2
|
||||
turf_total = max(turf_total, 1)
|
||||
var/t1 = turf_total / CELLSTANDARD * 100
|
||||
if (!( (90 < t1 && t1 < 110) ))
|
||||
safe = 0
|
||||
t1 = T.oxygen / turf_total * 100
|
||||
if (!( (20 < t1 && t1 < 30) ))
|
||||
safe = 0
|
||||
src.icon_state = text("indicator[]", safe)
|
||||
SS13_airtunnel.air_stat = safe
|
||||
return
|
||||
@@ -0,0 +1,69 @@
|
||||
/**
|
||||
* at_indicator -- Provides a visual indication of airtunnel status
|
||||
*
|
||||
*/
|
||||
|
||||
obj/machinery/at_indicator
|
||||
name = "Air Tunnel Indicator"
|
||||
icon = 'airtunnel.dmi'
|
||||
icon_state = "reader00"
|
||||
anchored = 1.0
|
||||
|
||||
process()
|
||||
if(! (stat & (BROKEN|NOPOWER)) )
|
||||
use_power(5, ENVIRON)
|
||||
src.update_icon()
|
||||
return
|
||||
|
||||
|
||||
// update the icon_state, depending on the status of the airtunnel
|
||||
|
||||
proc/update_icon()
|
||||
|
||||
if(stat & (BROKEN|NOPOWER) )
|
||||
icon_state = "reader_broken"
|
||||
return
|
||||
|
||||
var/status = 0
|
||||
if (SS13_airtunnel.operating == 1)
|
||||
status = "r"
|
||||
else if (SS13_airtunnel.operating == 2)
|
||||
status = "e"
|
||||
else
|
||||
var/obj/move/airtunnel/connector/C = pick(SS13_airtunnel.connectors)
|
||||
if (C.current == C)
|
||||
status = 0
|
||||
else
|
||||
if (!( C.current.next ))
|
||||
status = 2
|
||||
else
|
||||
status = 1
|
||||
src.icon_state = text("reader[][]", (SS13_airtunnel.siphon_status == 2 ? "1" : "0"), status)
|
||||
return
|
||||
|
||||
|
||||
// called when object is inside an explosion
|
||||
|
||||
ex_act(severity)
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
del(src)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
src.icon_state = "reader_broken"
|
||||
stat |= BROKEN
|
||||
if(3.0)
|
||||
if (prob(25))
|
||||
src.icon_state = "reader_broken"
|
||||
stat |= BROKEN
|
||||
else
|
||||
return
|
||||
|
||||
// called when object is attacked by a blob
|
||||
|
||||
blob_act()
|
||||
if (prob(50))
|
||||
src.icon_state = "reader_broken"
|
||||
stat |= BROKEN
|
||||
|
||||
@@ -0,0 +1,173 @@
|
||||
/*
|
||||
* Autolathe - Constructs objects from stocks of metal and glass
|
||||
*
|
||||
* Note: Currently only semi-implemented
|
||||
*
|
||||
*/
|
||||
|
||||
obj/machinery/autolathe
|
||||
|
||||
name = "Autolathe"
|
||||
icon = 'stationobjs.dmi'
|
||||
icon_state = "autolathe"
|
||||
anchored = 1
|
||||
var
|
||||
m_amount = 0 // amount (cc) of metal loaded
|
||||
g_amount = 0 // amount (cc) of glass loaded
|
||||
operating = 0 // true if the machine is operating
|
||||
opened = 0 // true if the machine is open (not fully implemented?)
|
||||
temp = null // temporary intaction window text
|
||||
|
||||
|
||||
// Feed in metal or glass stock, or open the autolathe
|
||||
|
||||
attackby(obj/item/weapon/O, mob/user)
|
||||
|
||||
if (istype(O, /obj/item/weapon/sheet/metal))
|
||||
if (src.m_amount < 150000.0)
|
||||
src.m_amount += O:height * O:width * O:length * 1000000.0
|
||||
O:amount--
|
||||
if (O:amount < 1)
|
||||
del(O)
|
||||
|
||||
else if (istype(O, /obj/item/weapon/sheet/glass))
|
||||
if (src.g_amount < 75000.0)
|
||||
src.g_amount += O:height * O:width * O:length * 1000000.0
|
||||
O:amount--
|
||||
if (O:amount < 1)
|
||||
del(O)
|
||||
|
||||
else if (istype(O, /obj/item/weapon/screwdriver))
|
||||
if (!( src.operating ))
|
||||
src.opened = !( src.opened )
|
||||
src.icon_state = text("autolathe[]", (src.opened ? "f" : null))
|
||||
else
|
||||
user << "\red The machine is in use. You can not maintain it now."
|
||||
else
|
||||
spawn( 0 )
|
||||
src.attack_hand(user)
|
||||
return
|
||||
|
||||
|
||||
// Monkey interact same a human
|
||||
|
||||
attack_paw(mob/user)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// Open interaction window
|
||||
// Currenty only pipe pieces can be made
|
||||
|
||||
attack_hand(mob/user)
|
||||
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
|
||||
var/dat
|
||||
if (src.temp)
|
||||
dat = text("<TT>[]</TT><BR><BR><A href='?src=\ref[];temp=1'>Clear Screen</A>", src.temp, src)
|
||||
else
|
||||
dat = text("<B>Metal Amount:</B> [] cm<sup>3</sup> (MAX: 150,000)<BR>\n<FONT color = blue><B>Glass Amount:</B></FONT> [] cm<sup>3</sup> (MAX: 75,000)<HR>", src.m_amount, src.g_amount)
|
||||
var/list/L = list( )
|
||||
|
||||
L["pipe"] = "Straight pipe (7500 cc)"
|
||||
L["bpipe"] = "Bent pipe (7500 cc)"
|
||||
L["hepipe"] = "Heat-exchange pipe (10000 cc)"
|
||||
L["bhepipe"] = "Bent heat-exchange pipe (10000 cc)"
|
||||
L["contr"] = "Pipe connector (10000 cc)"
|
||||
L["manif"] = "Pipe manifold (15000 cc)"
|
||||
L["junct"] = "Pipe junction (10000 cc)"
|
||||
L["vent"] = "Pipe vent (10000 cc)"
|
||||
/* L["screwdriver"] = "Make Screwdriver {40 cc}"
|
||||
L["wirecutters"] = "Make Wirecutters {80 cc}"
|
||||
L["wrench"] = "Make Wrench {150 cc}"
|
||||
L["crowbar"] = "Make Crowbar {150 cc}"
|
||||
L["screw"] = "Make Screw (1) {3 cc}"
|
||||
L["5screws"] = "Make Screws (5) {14 cc}"
|
||||
L["rod_t"] = "Make Rod (1x20) {20 cc}"
|
||||
L["rod_l"] = "Make Rod (5x250) {1250 cc}"
|
||||
L["grille_1"] = "Make Grille (250x250x1) {27345 cc}"
|
||||
L["sheet_1"] = "Make Sheet (20x10x.01) {2 cc}"
|
||||
L["sheet_2"] = "Make Sheet (30x10x.01) {3 cc}"
|
||||
L["sheet_3"] = "Make Sheet (30x20x.01) {6 cc}"
|
||||
L["sheet_4"] = "Make Sheet (30x30x.01) {9 cc}"
|
||||
L["sheet_5"] = "Make Sheet (62.5x62.5x4) {15625 cc}" */
|
||||
|
||||
|
||||
for(var/t in L)
|
||||
dat += "<A href='?src=\ref[src];make=[t]'>[L["[t]"]]<BR>"
|
||||
user << browse("<HEAD><TITLE>Autolathe Control Panel</TITLE></HEAD><TT>[dat]</TT>", "window=autolathe")
|
||||
return
|
||||
|
||||
// Called by topic links from interaction window
|
||||
// Make the chosen item
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
|
||||
|
||||
if ((usr.stat || usr.restrained()))
|
||||
return
|
||||
if(operating || (stat & NOPOWER))
|
||||
return
|
||||
if ( get_dist(src, usr) <= 1 && istype(src.loc, /turf) )
|
||||
usr.machine = src
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
if (href_list["temp"])
|
||||
src.temp = null
|
||||
|
||||
if(href_list["make"])
|
||||
|
||||
var/list/C = list()
|
||||
C["pipe"] = 7500
|
||||
C["bpipe"] = 7500
|
||||
C["hepipe"] = 10000
|
||||
C["bhepipe"] = 10000
|
||||
C["contr"] = 10000
|
||||
C["manif"] = 15000
|
||||
C["junct"] = 10000
|
||||
C["vent"] = 10000
|
||||
|
||||
var/item = href_list["make"]
|
||||
var/cost = C[item]
|
||||
|
||||
if(m_amount >= cost)
|
||||
m_amount -= cost
|
||||
operate()
|
||||
switch(item)
|
||||
if("pipe")
|
||||
new /obj/item/weapon/pipe{ ptype = 0 }(src.loc)
|
||||
if("bpipe")
|
||||
new /obj/item/weapon/pipe{ ptype = 1 }(src.loc)
|
||||
if("hepipe")
|
||||
new /obj/item/weapon/pipe{ ptype = 2 }(src.loc)
|
||||
if("bhepipe")
|
||||
new /obj/item/weapon/pipe{ ptype = 3 }(src.loc)
|
||||
if("contr")
|
||||
new /obj/item/weapon/pipe{ ptype = 4 }(src.loc)
|
||||
if("manif")
|
||||
new /obj/item/weapon/pipe{ ptype = 5 }(src.loc)
|
||||
if("junct")
|
||||
new /obj/item/weapon/pipe{ ptype = 6 }(src.loc)
|
||||
if("vent")
|
||||
new /obj/item/weapon/pipe{ ptype = 7 }(src.loc)
|
||||
|
||||
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
return
|
||||
|
||||
// Perform operation animation
|
||||
|
||||
proc/operate()
|
||||
|
||||
use_power(500)
|
||||
operating = 1
|
||||
flick("autolathe_c", src)
|
||||
sleep(16)
|
||||
flick("autolathe_o", src)
|
||||
sleep(8)
|
||||
operating = 0
|
||||
@@ -0,0 +1,49 @@
|
||||
/**
|
||||
* camera -- A security camera, allows remote viewing of its location from a security computer
|
||||
*
|
||||
* Note: Cameras do not use or need power.
|
||||
*
|
||||
*/
|
||||
|
||||
obj/machinery/camera
|
||||
name = "Security Camera"
|
||||
icon = 'stationobjs.dmi'
|
||||
icon_state = "camera"
|
||||
anchored = 1
|
||||
var
|
||||
network = "SS13" // must match the network var of a security computer to allow viewing from that computer
|
||||
c_tag = null // the displayed name of the camera when picking from a security computer
|
||||
status = 1.0 // 0 if camera has been disabled
|
||||
invuln = null // if true, camera will not be affected by explosions
|
||||
|
||||
|
||||
// attacking with wirecutters allows the camera to be disabled/enabled
|
||||
|
||||
attackby(obj/item/weapon/W, mob/user)
|
||||
|
||||
if (istype(W, /obj/item/weapon/wirecutters))
|
||||
src.status = !( src.status )
|
||||
if (!( src.status ))
|
||||
for(var/mob/O in viewers(user, null))
|
||||
O.show_message("\red [user] has deactivated [src]!", 1)
|
||||
src.icon_state = "camera1"
|
||||
else
|
||||
for(var/mob/O in viewers(user, null))
|
||||
O.show_message("\red [user] has reactivated [src]!", 1)
|
||||
src.icon_state = "camera"
|
||||
return
|
||||
|
||||
// called when object is in an explosion
|
||||
// if invuln flag is set, explosion has no effect
|
||||
|
||||
ex_act(severity)
|
||||
if(src.invuln)
|
||||
return
|
||||
else
|
||||
..(severity)
|
||||
return
|
||||
|
||||
// blob attacks have no effect
|
||||
|
||||
blob_act()
|
||||
return
|
||||
@@ -0,0 +1,100 @@
|
||||
/**
|
||||
* cell_charger -- Allows the charging of power cell (as used in APCs).
|
||||
*
|
||||
* Uses an overlay to display the current charge level of the inserted cell
|
||||
*
|
||||
*/
|
||||
|
||||
obj/machinery/cell_charger
|
||||
name = "cell charger"
|
||||
desc = "A charging unit for power cells."
|
||||
icon = 'power.dmi'
|
||||
icon_state = "ccharger0"
|
||||
anchored = 1
|
||||
var
|
||||
obj/item/weapon/cell/charging = null // the cell inserted for charging (or null if none)
|
||||
chargelevel = -1 // the (cached) charge indicator level (0-4)
|
||||
// set -1 to force the indicator to be updated
|
||||
|
||||
// insert a cell into the charger, unless there is already one inside
|
||||
|
||||
attackby(obj/item/weapon/W, mob/user)
|
||||
|
||||
if(stat & BROKEN) return
|
||||
|
||||
if(istype(W, /obj/item/weapon/cell))
|
||||
if(charging)
|
||||
user << "There is already a cell in the charger."
|
||||
return
|
||||
else
|
||||
user.drop_item()
|
||||
W.loc = src
|
||||
charging = W
|
||||
user << "You insert the cell into the charger."
|
||||
chargelevel = -1
|
||||
|
||||
|
||||
updateicon()
|
||||
|
||||
|
||||
// updates the icon_state and overlays to reflect a whether a cell is inserted and the charge state
|
||||
|
||||
proc/updateicon()
|
||||
|
||||
icon_state = "ccharger[charging ? 1 : 0]"
|
||||
|
||||
if(charging && !(stat & (BROKEN|NOPOWER)) )
|
||||
|
||||
var/newlevel = round( charging.percent() * 4.0 / 99 )
|
||||
|
||||
if(chargelevel != newlevel) // displayed charge level is cached, so as to only update the overlay when needed
|
||||
|
||||
overlays = null
|
||||
overlays += image('power.dmi', "ccharger-o[newlevel]")
|
||||
|
||||
chargelevel = newlevel
|
||||
|
||||
else
|
||||
overlays = null
|
||||
|
||||
|
||||
// removes the cell from the charger (if a cell is inserted)
|
||||
|
||||
attack_hand(mob/user)
|
||||
|
||||
add_fingerprint(user)
|
||||
|
||||
if(stat & BROKEN) return
|
||||
|
||||
if(charging)
|
||||
charging.loc = usr
|
||||
charging.layer = 20
|
||||
if (user.hand )
|
||||
user.l_hand = charging
|
||||
else
|
||||
user.r_hand = charging
|
||||
|
||||
charging.add_fingerprint(user)
|
||||
charging.updateicon()
|
||||
|
||||
src.charging = null
|
||||
user << "You remove the cell from the charger."
|
||||
chargelevel = -1
|
||||
updateicon()
|
||||
|
||||
// every cycle, increase the charge level of cell if inserted
|
||||
|
||||
process()
|
||||
|
||||
if(!charging || (stat & (BROKEN|NOPOWER)) )
|
||||
return
|
||||
|
||||
var/newch = charging.charge + 5
|
||||
newch = min(newch, charging.maxcharge) // limit to maximum charge capacity of the cell
|
||||
|
||||
use_power((newch - charging.charge) / CELLRATE)
|
||||
charging.charge = newch
|
||||
updateicon()
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,217 @@
|
||||
/*
|
||||
* Circulator - A gas pump and heat-exchanger
|
||||
* Part of the main engine generator system
|
||||
*
|
||||
* Machine contains two gas reservoirs. Gas flows from the pipe to the south into the first
|
||||
* Is pumped from the first reservoir to the second at "rate"
|
||||
* Then flows out of the second reservoir into the pipe at the north
|
||||
*/
|
||||
|
||||
obj/machinery/circulator
|
||||
name = "circulator/heat exchanger"
|
||||
desc = "A gas circulator pump and heat exchanger."
|
||||
icon = 'pipes.dmi'
|
||||
icon_state = "circ1-off"
|
||||
p_dir = 3 // pipes connect to north & south directions
|
||||
anchored = 1.0
|
||||
density = 1
|
||||
capmult = 1 // Since we have a separate reservoir connected to each node, capmult is 1
|
||||
|
||||
var
|
||||
side = 1 // Ciculators can be to the left or to the right of a generator. 1=left 2=right
|
||||
status = 0 // 0 = off, 1 = on, 2 = slow
|
||||
rate = 0 // the gas transfer rate between the two internal reservoirs
|
||||
maxrate = 400000 // the maximum transfer rate
|
||||
|
||||
obj/substance/gas/gas1 = null // the first gas reservoir, connected to node1 (south)
|
||||
obj/substance/gas/ngas1 = null
|
||||
|
||||
obj/substance/gas/gas2 = null // the second gas reservoir, connected to node 2 (north)
|
||||
obj/substance/gas/ngas2 = null
|
||||
|
||||
capacity = 6000000.0 // the maximum gas capacity of each reservoir
|
||||
|
||||
obj/machinery/node1 = null // the physical pipe object to the south
|
||||
obj/machinery/node2 = null // the physical pipe object to the north
|
||||
|
||||
obj/machinery/vnode1 // the pipeline object to the south
|
||||
obj/machinery/vnode2 // the pipeline object to the north
|
||||
|
||||
|
||||
|
||||
|
||||
// Create a new circulator object
|
||||
|
||||
New()
|
||||
..()
|
||||
gas1 = new/obj/substance/gas(src)
|
||||
gas1.maximum = capacity
|
||||
gas2 = new/obj/substance/gas(src)
|
||||
gas2.maximum = capacity
|
||||
|
||||
ngas1 = new/obj/substance/gas()
|
||||
ngas2 = new/obj/substance/gas()
|
||||
|
||||
gasflowlist += src
|
||||
|
||||
updateicon()
|
||||
|
||||
|
||||
// Find the pipe connections to the north and south
|
||||
// Set the node & vnode values
|
||||
|
||||
buildnodes()
|
||||
|
||||
var/turf/TS = get_step(src, SOUTH)
|
||||
var/turf/TN = get_step(src, NORTH)
|
||||
|
||||
for(var/obj/machinery/M in TS)
|
||||
|
||||
if(M && (M.p_dir & 1))
|
||||
node1 = M
|
||||
break
|
||||
|
||||
for(var/obj/machinery/M in TN)
|
||||
|
||||
if(M && (M.p_dir & 2))
|
||||
node2 = M
|
||||
break
|
||||
|
||||
|
||||
if(node1) vnode1 = node1.getline()
|
||||
|
||||
if(node2) vnode2 = node2.getline()
|
||||
|
||||
|
||||
// Set the current status and pumping rate (as a percentage)
|
||||
// Called by the generator object
|
||||
|
||||
proc/control(var/on, var/prate)
|
||||
|
||||
rate = prate/100*maxrate
|
||||
|
||||
if(status == 1)
|
||||
if(!on)
|
||||
status = 2 // switching from on to off makes the generator slow down for 3 seconds
|
||||
spawn(30)
|
||||
if(status == 2) // then switch to off
|
||||
status = 0
|
||||
updateicon()
|
||||
else if(status == 0)
|
||||
if(on)
|
||||
status = 1
|
||||
else // status ==2
|
||||
if(on)
|
||||
status = 1
|
||||
|
||||
updateicon()
|
||||
|
||||
|
||||
// Update the icon state, depending on the circulator settings
|
||||
|
||||
proc/updateicon()
|
||||
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "circ[side]-p"
|
||||
return
|
||||
|
||||
var/is
|
||||
switch(status)
|
||||
if(0)
|
||||
is = "off"
|
||||
if(1)
|
||||
is = "run"
|
||||
if(2)
|
||||
is = "slow"
|
||||
|
||||
icon_state = "circ[side]-[is]"
|
||||
|
||||
|
||||
// When the power of the area changes, to standard processing then update the icon state
|
||||
|
||||
power_change()
|
||||
..()
|
||||
updateicon()
|
||||
|
||||
|
||||
// Gas flow - update the gas reservoirs with the new values as set in process()
|
||||
|
||||
gas_flow()
|
||||
|
||||
gas1.replace_by(ngas1)
|
||||
gas2.replace_by(ngas2)
|
||||
|
||||
|
||||
// Main process. Pump gas between the reservoirs, then do standard gas flow to the connected nodes
|
||||
|
||||
process()
|
||||
|
||||
// if operating, pump from resv1 to resv2
|
||||
|
||||
if(! (stat & NOPOWER) ) // only do circulator step if powered; still do rest of gas flow at all times
|
||||
if(status==1 || status==2)
|
||||
gas2.transfer_from(gas1, status==1? rate : rate/2)
|
||||
use_power(rate/capacity * 100)
|
||||
ngas1.replace_by(gas1)
|
||||
ngas2.replace_by(gas2)
|
||||
|
||||
|
||||
// now do standard gas flow process
|
||||
|
||||
var/delta_gt
|
||||
|
||||
if(vnode1)
|
||||
delta_gt = FLOWFRAC * ( vnode1.get_gas_val(src) - gas1.tot_gas() / capmult)
|
||||
calc_delta( src, gas1, ngas1, vnode1, delta_gt)
|
||||
else
|
||||
leak_to_turf(1)
|
||||
|
||||
if(vnode2)
|
||||
delta_gt = FLOWFRAC * ( vnode2.get_gas_val(src) - gas2.tot_gas() / capmult)
|
||||
calc_delta( src, gas2, ngas2, vnode2, delta_gt)
|
||||
else
|
||||
leak_to_turf(2)
|
||||
|
||||
|
||||
// If nothing connected to either pipe node, leak the gas to the turf instead
|
||||
|
||||
proc/leak_to_turf(var/port)
|
||||
|
||||
var/turf/T
|
||||
|
||||
switch(port)
|
||||
if(1)
|
||||
T = get_step(src, SOUTH)
|
||||
if(2)
|
||||
T = get_step(src, NORTH)
|
||||
|
||||
if(T.density)
|
||||
T = src.loc
|
||||
if(T.density)
|
||||
return
|
||||
|
||||
switch(port)
|
||||
if(1)
|
||||
flow_to_turf(gas1, ngas1, T)
|
||||
if(2)
|
||||
flow_to_turf(gas2, ngas2, T)
|
||||
|
||||
|
||||
// Get the current gas fill level. Note since we have two reservoirs, value depends on which node is enquiring
|
||||
|
||||
get_gas_val(from)
|
||||
|
||||
if(from == vnode1)
|
||||
return gas1.tot_gas()/capmult
|
||||
else
|
||||
return gas2.tot_gas()/capmult
|
||||
|
||||
|
||||
// Get the gas reservoir object connected to node "from"
|
||||
|
||||
get_gas(from)
|
||||
|
||||
if(from == vnode1)
|
||||
return gas1
|
||||
else
|
||||
return gas2
|
||||
@@ -0,0 +1,137 @@
|
||||
/*
|
||||
* Connector -- Machine that links atmoalter machines (canisters, siphons, heaters) to a pipe network.
|
||||
*
|
||||
* Connection is performed by attacking the device to be connected with a wrench (or screwdriver)
|
||||
*/
|
||||
|
||||
|
||||
/obj/machinery/connector
|
||||
name = "connector"
|
||||
icon = 'pipes.dmi'
|
||||
desc = "A connector for gas canisters."
|
||||
icon_state = "connector"
|
||||
anchored = 1
|
||||
p_dir = 2
|
||||
capmult = 2
|
||||
|
||||
var
|
||||
obj/machinery/node = null // the pipe-connected machine or pipe
|
||||
obj/machinery/vnode = null // the pipe-connected pipeline, if node is a pipe
|
||||
|
||||
obj/machinery/atmoalter/connected = null // the connected device (canister, etc.), or null if none
|
||||
|
||||
obj/substance/gas/gas = null // the gas reservoir
|
||||
obj/substance/gas/ngas = null
|
||||
|
||||
capacity = 6000000.0 // the capacity of the gas reservoir. This value is actually used,
|
||||
// unlike most pipe-related objects
|
||||
|
||||
|
||||
// Create a new connector, create gas reservoir.
|
||||
// Pipe direction (p_dir) is same as icon dir
|
||||
//If a compatible machine is at the same location, and its c_status (pipe valve) is not 0, set the machine as connected
|
||||
|
||||
New()
|
||||
..()
|
||||
|
||||
p_dir = dir
|
||||
|
||||
gas = new/obj/substance/gas(src)
|
||||
gas.maximum = capacity
|
||||
ngas = new/obj/substance/gas()
|
||||
|
||||
gasflowlist += src
|
||||
spawn(5) // wait until world has finished loading
|
||||
var/obj/machinery/atmoalter/A = locate(/obj/machinery/atmoalter, src.loc) // find compatible machine in same loc
|
||||
|
||||
if(A && A.c_status != 0) // c_status=0 -> disconnected
|
||||
connected = A
|
||||
A.anchored = 1 // ensure canister etc. is anchored if connected
|
||||
|
||||
|
||||
// Find the machine/pipe that connects to this one
|
||||
|
||||
buildnodes()
|
||||
|
||||
var/turf/T = get_step(src.loc, src.dir)
|
||||
var/fdir = turn(src.p_dir, 180)
|
||||
|
||||
for(var/obj/machinery/M in T)
|
||||
if(M.p_dir & fdir)
|
||||
src.node = M
|
||||
break
|
||||
|
||||
if(node) vnode = node.getline()
|
||||
|
||||
|
||||
return
|
||||
|
||||
// Examine verb for the connector
|
||||
|
||||
examine()
|
||||
set src in oview(1)
|
||||
|
||||
if (usr.stat)
|
||||
return
|
||||
|
||||
if(connected)
|
||||
usr << "A pipe connector for gas equipment. It is connected to \an [connected.name]."
|
||||
else
|
||||
usr << "A pipe connector for gas equipment. It is unconnected."
|
||||
|
||||
|
||||
|
||||
// Return the gas fullness value
|
||||
|
||||
get_gas_val(from)
|
||||
return gas.tot_gas()/capmult
|
||||
|
||||
|
||||
// Return the gas reservoir
|
||||
|
||||
get_gas(from)
|
||||
return gas
|
||||
|
||||
|
||||
// Update gas values with the new ones calculated in process()
|
||||
|
||||
gas_flow()
|
||||
gas.replace_by(ngas)
|
||||
|
||||
|
||||
// Timed process. Calculate gas flow to connected node.
|
||||
// If a device is connected (canister etc.), transfer gas to/from reservoir depending on device valve settings.
|
||||
|
||||
process()
|
||||
var/delta_gt
|
||||
|
||||
if(vnode)
|
||||
|
||||
delta_gt = FLOWFRAC * ( vnode.get_gas_val(src) - gas.tot_gas() / capmult)
|
||||
calc_delta( src, gas, ngas, vnode, delta_gt)//, dbg)
|
||||
else
|
||||
leak_to_turf()
|
||||
|
||||
if(connected)
|
||||
var/amount
|
||||
if(connected.c_status == 1) // canister set to release
|
||||
|
||||
amount = min(connected.c_per, capacity - gas.tot_gas() ) // limit to space in connector
|
||||
amount = max(0, min(amount, connected.gas.tot_gas() ) ) // limit to amount in canister, or 0
|
||||
ngas.transfer_from( connected.gas, amount)
|
||||
else if(connected.c_status == 2) // canister set to accept
|
||||
|
||||
amount = min(connected.c_per, connected.gas.maximum - connected.gas.tot_gas()) //limit to space in canister
|
||||
amount = max(0, min(amount, gas.tot_gas() ) ) // limit to amount in connector, or 0
|
||||
|
||||
connected.gas.transfer_from( ngas, amount)
|
||||
|
||||
|
||||
// If pipe-connected node is missing, leak the gas to turf
|
||||
|
||||
proc/leak_to_turf()
|
||||
var/turf/T = get_step(src, dir)
|
||||
|
||||
if(T && !T.density)
|
||||
flow_to_turf(gas, ngas, T)
|
||||
|
||||
@@ -0,0 +1,421 @@
|
||||
/*
|
||||
* Cryo_cell -- used to heal mobs of major damage
|
||||
*
|
||||
* Needs a freezer unit attached by a (flex)pipe to operate.
|
||||
*
|
||||
* TODO: Cell does not seem to have a broken icon state, nor does breaking the cell affect overlays. Needs further work.
|
||||
*/
|
||||
|
||||
obj/machinery/cryo_cell
|
||||
name = "cryo cell"
|
||||
icon = 'Cryogenic2.dmi'
|
||||
icon_state = "celltop"
|
||||
density = 1
|
||||
anchored = 1
|
||||
p_dir = 8 // pipe direction is west
|
||||
capmult = 1 // capacity multiplier
|
||||
|
||||
var
|
||||
mob/occupant = null // the mob inside, or null if none
|
||||
|
||||
obj/substance/gas/gas = null // the gas reservoir
|
||||
obj/substance/gas/ngas = null // the new calculated gas
|
||||
|
||||
obj/overlay/O1 = null // the console overlay object
|
||||
obj/overlay/O2 = null // the base of cell overlay object
|
||||
|
||||
obj/machinery/line_in = null // the connected pipe
|
||||
obj/machinery/vnode = null // the connected pipeline of line_in
|
||||
|
||||
|
||||
// Create a cryo_cell
|
||||
// Pixel-displaced overlays are used to show the console and base of the cell, with the main icon being the cell top
|
||||
|
||||
New()
|
||||
..()
|
||||
src.layer = 5
|
||||
O1 = new /obj/overlay( )
|
||||
O1.icon = 'Cryogenic2.dmi'
|
||||
O1.icon_state = "cellconsole"
|
||||
O1.pixel_y = -32.0
|
||||
O1.layer = 4
|
||||
|
||||
O2 = new /obj/overlay( )
|
||||
O2.icon = 'Cryogenic2.dmi'
|
||||
O2.icon_state = "cellbottom"
|
||||
O2.pixel_y = -32.0
|
||||
|
||||
src.pixel_y = 32
|
||||
|
||||
add_overlays()
|
||||
|
||||
src.gas = new /obj/substance/gas( null )
|
||||
gas.temperature = T20C
|
||||
src.ngas = new /obj/substance/gas (null)
|
||||
ngas.temperature = T20C
|
||||
|
||||
gasflowlist += src
|
||||
|
||||
|
||||
// Find the connected (flex)pipe and its pipeline object
|
||||
|
||||
buildnodes()
|
||||
|
||||
var/turf/T = src.loc
|
||||
|
||||
line_in = get_machine(level, T, p_dir )
|
||||
|
||||
if(line_in) vnode = line_in.getline()
|
||||
|
||||
|
||||
|
||||
// Called to set the object overlays to the stored values
|
||||
|
||||
proc/add_overlays()
|
||||
src.overlays = list(O1, O2)
|
||||
|
||||
|
||||
// Gas procs
|
||||
|
||||
|
||||
// Return gas fullness value
|
||||
|
||||
get_gas_val(from)
|
||||
return gas.tot_gas()
|
||||
|
||||
|
||||
// Return the gas reservoir
|
||||
|
||||
get_gas(from)
|
||||
return gas
|
||||
|
||||
|
||||
// Update gas levels with new levels calculated in process()
|
||||
|
||||
gas_flow()
|
||||
gas.replace_by(ngas)
|
||||
|
||||
|
||||
|
||||
// Called when area power state changes
|
||||
// If no power, update icon states to show unpowered versions
|
||||
|
||||
power_change()
|
||||
..()
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "celltop-p"
|
||||
O1.icon_state="cellconsole-p"
|
||||
O2.icon_state="cellbottom-p"
|
||||
else
|
||||
icon_state = "celltop[ occupant ? "_1" : ""]"
|
||||
O1.icon_state ="cellconsole"
|
||||
O2.icon_state ="cellbottom"
|
||||
|
||||
add_overlays()
|
||||
|
||||
|
||||
// Timed process
|
||||
// Perform gas flow, use area power
|
||||
|
||||
process()
|
||||
|
||||
if(vnode)
|
||||
var/delta_gt = FLOWFRAC * ( vnode.get_gas_val(src) - gas.tot_gas() / capmult)
|
||||
calc_delta( src, gas, ngas, vnode, delta_gt)
|
||||
else
|
||||
leak_to_turf()
|
||||
|
||||
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
use_power(500)
|
||||
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
|
||||
|
||||
// Called if no pipe is present
|
||||
// Leak gas contents to turf to west
|
||||
|
||||
proc/leak_to_turf()
|
||||
var/turf/T = get_step(src, WEST)
|
||||
|
||||
if(T.density)
|
||||
T = src.loc
|
||||
if(T.density)
|
||||
return
|
||||
|
||||
flow_to_turf(gas, ngas, T)
|
||||
|
||||
|
||||
// Cryocell verbs
|
||||
|
||||
|
||||
// Eject the occupant
|
||||
|
||||
verb/move_eject()
|
||||
set src in oview(1)
|
||||
|
||||
if (usr.stat != 0)
|
||||
return
|
||||
src.go_out()
|
||||
add_fingerprint(usr)
|
||||
|
||||
|
||||
// Move the player into the cell
|
||||
// Cell must be powered, can't already have an occupant, and player can't be wearing anything.
|
||||
// If all true, move the player inside and update the view
|
||||
|
||||
verb/move_inside()
|
||||
set src in oview(1)
|
||||
|
||||
if (usr.stat != 0 || stat & NOPOWER)
|
||||
return
|
||||
if (src.occupant)
|
||||
usr << "\blue <B>The cell is already occupied!</B>"
|
||||
return
|
||||
if (usr.abiotic())
|
||||
usr << "Subject may not have abiotic items on."
|
||||
return
|
||||
usr.pulling = null
|
||||
usr.client.perspective = EYE_PERSPECTIVE
|
||||
usr.client.eye = src
|
||||
usr.loc = src
|
||||
src.occupant = usr
|
||||
src.icon_state = "celltop_1"
|
||||
for(var/obj/O in src)
|
||||
O.loc = src.loc
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
|
||||
// Attack by item
|
||||
// A special case - only works with the pseudo-item representing grabbing another player
|
||||
// Make standard checks, then move grabbed player into the cell, and update their view.
|
||||
|
||||
attackby(obj/item/weapon/grab/G, mob/user)
|
||||
|
||||
if (stat & NOPOWER) return
|
||||
|
||||
if ((!( istype(G, /obj/item/weapon/grab) ) || !( ismob(G.affecting) )))
|
||||
return
|
||||
if (src.occupant)
|
||||
user << "\blue <B>The cell is already occupied!</B>"
|
||||
return
|
||||
if (G.affecting.abiotic())
|
||||
user << "Subject may not have abiotic items on."
|
||||
return
|
||||
var/mob/M = G.affecting
|
||||
if (M.client)
|
||||
M.client.perspective = EYE_PERSPECTIVE
|
||||
M.client.eye = src
|
||||
M.loc = src
|
||||
src.occupant = M
|
||||
src.icon_state = "celltop_1"
|
||||
for(var/obj/O in src)
|
||||
del(O)
|
||||
src.add_fingerprint(user)
|
||||
del(G)
|
||||
|
||||
|
||||
// Monkey interact same as human
|
||||
|
||||
attack_paw(mob/user)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// Human interact, show status window of machine and occupant
|
||||
// No topic links, since all control is handled through the freezer unit
|
||||
|
||||
attack_hand(mob/user)
|
||||
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
|
||||
user.machine = src
|
||||
if (istype(user, /mob/human))
|
||||
var/dat = "<font color='blue'> <B>System Statistics:</B></FONT><BR>"
|
||||
if (src.gas.temperature > T0C)
|
||||
dat += text("<font color='red'>\tTemperature (°C): [] (MUST be below 0, add coolant to mixture)</FONT><BR>", round(src.gas.temperature-T0C, 0.1))
|
||||
else
|
||||
dat += text("<font color='blue'>\tTemperature (°C): [] </FONT><BR>", round(src.gas.temperature-T0C, 0.1))
|
||||
if (src.gas.plasma < 1)
|
||||
dat += text("<font color='red'>\tPlasma Units: [] (Add plasma to mixture!)</FONT><BR>", round(src.gas.plasma, 0.1))
|
||||
else
|
||||
dat += text("<font color='blue'>\tPlasma Units: []</FONT><BR>", round(src.gas.plasma, 0.1))
|
||||
if (src.gas.oxygen < 1)
|
||||
dat += text("<font color='red'>\tOxygen Units: [] (Add oxygen to mixture!)</FONT><BR>", round(src.gas.oxygen, 0.1))
|
||||
else
|
||||
dat += text("<font color='blue'>\tOxygen Units: []</FONT><BR>", round(src.gas.oxygen, 0.1))
|
||||
if (src.occupant)
|
||||
dat += "<font color='blue'><B>Occupant Statistics:</B></FONT><BR>"
|
||||
var/t1
|
||||
switch(src.occupant.stat)
|
||||
if(0.0)
|
||||
t1 = "Conscious"
|
||||
if(1.0)
|
||||
t1 = "Unconscious"
|
||||
if(2.0)
|
||||
t1 = "*dead*"
|
||||
else
|
||||
dat += text("[]\tHealth %: [] ([])</FONT><BR>", (src.occupant.health > 50 ? "<font color='blue'>" : "<font color='red'>"), src.occupant.health, t1)
|
||||
dat += text("[]\t-Respiratory Damage %: []</FONT><BR>", (src.occupant.oxyloss < 60 ? "<font color='blue'>" : "<font color='red'>"), src.occupant.oxyloss)
|
||||
dat += text("[]\t-Toxin Content %: []</FONT><BR>", (src.occupant.toxloss < 60 ? "<font color='blue'>" : "<font color='red'>"), src.occupant.toxloss)
|
||||
dat += text("[]\t-Burn Severity %: []</FONT>", (src.occupant.fireloss < 60 ? "<font color='blue'>" : "<font color='red'>"), src.occupant.fireloss)
|
||||
dat += text("<BR><BR><A href='?src=\ref[];mach_close=cryo'>Close</A>", user)
|
||||
user << browse(dat, "window=cryo;size=400x500")
|
||||
else
|
||||
var/dat = text("<font color='blue'> <B>[]</B></FONT><BR>", stars("System Statistics:"))
|
||||
if (src.gas.temperature > T0C)
|
||||
dat += text("<font color='red'>\t[]</FONT><BR>", stars(text("Temperature (C): [] (MUST be below 0, add coolant to mixture)", round(src.gas.temperature-T0C, 0.1))))
|
||||
else
|
||||
dat += text("<font color='blue'>\t[] </FONT><BR>", stars(text("Temperature(C): []", round(src.gas.temperature-T0C, 0.1))))
|
||||
if (src.gas.plasma < 1)
|
||||
dat += text("<font color='red'>\t[]</FONT><BR>", stars(text("Plasma Units: [] (Add plasma to mixture!)", round(src.gas.plasma, 0.1))))
|
||||
else
|
||||
dat += text("<font color='blue'>\t[]</FONT><BR>", stars(text("Plasma Units: []", round(src.gas.plasma, 0.1))))
|
||||
if (src.gas.oxygen < 1)
|
||||
dat += text("<font color='red'>\t[]</FONT><BR>", stars(text("Oxygen Units: [] (Add oxygen to mixture!)", round(src.gas.oxygen, 0.1))))
|
||||
else
|
||||
dat += text("<font color='blue'>\t[]</FONT><BR>", stars(text("Oxygen Units: []", round(src.gas.oxygen, 0.1))))
|
||||
if (src.occupant)
|
||||
dat += "<font color='blue'><B>Occupant Statistics:</B></FONT><BR>"
|
||||
var/t1 = null
|
||||
switch(src.occupant.stat)
|
||||
if(0.0)
|
||||
t1 = "Conscious"
|
||||
if(1.0)
|
||||
t1 = "Unconscious"
|
||||
if(2.0)
|
||||
t1 = "*dead*"
|
||||
else
|
||||
dat += text("[]\t[]</FONT><BR>", (src.occupant.health > 50 ? "<font color='blue'>" : "<font color='red'>"), stars(text("Health %: [] ([])", src.occupant.health, t1)))
|
||||
dat += text("[]\t[]</FONT><BR>", (src.occupant.oxyloss < 60 ? "<font color='blue'>" : "<font color='red'>"), stars(text("-Respiratory Damage %: []", src.occupant.oxyloss)))
|
||||
dat += text("[]\t[]</FONT><BR>", (src.occupant.toxloss < 60 ? "<font color='blue'>" : "<font color='red'>"), stars(text("-Toxin Content %: []", src.occupant.toxloss)))
|
||||
dat += text("[]\t[]</FONT>", (src.occupant.fireloss < 60 ? "<font color='blue'>" : "<font color='red'>"), stars(text("-Burn Severity %: []", src.occupant.fireloss)))
|
||||
dat += text("<BR><BR><A href='?src=\ref[];mach_close=cryo'>Close</A>", user)
|
||||
user << browse(dat, "window=cryo;size=400x500")
|
||||
|
||||
|
||||
// Called to remove the occupant of a cell
|
||||
// Reset the view back to normal
|
||||
|
||||
proc/go_out()
|
||||
|
||||
if (!( src.occupant ))
|
||||
return
|
||||
for(var/obj/O in src)
|
||||
O.loc = src.loc
|
||||
|
||||
if (src.occupant.client)
|
||||
src.occupant.client.eye = src.occupant.client.mob
|
||||
src.occupant.client.perspective = MOB_PERSPECTIVE
|
||||
src.occupant.loc = src.loc
|
||||
src.occupant = null
|
||||
src.icon_state = "celltop"
|
||||
|
||||
|
||||
// Called when client tries to move while inside the cell
|
||||
// If the user is able to move, leave the cell
|
||||
|
||||
relaymove(mob/user)
|
||||
|
||||
if (user.stat)
|
||||
return
|
||||
src.go_out()
|
||||
|
||||
|
||||
// Called in mob/Life() proc while mob is inside the cell
|
||||
// Actually heal the occupant, while using up plasma and oxygen from the cell
|
||||
|
||||
alter_health(mob/M)
|
||||
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
|
||||
if (M.health < 0)
|
||||
if ((src.gas.temperature > T0C || src.gas.plasma < 1))
|
||||
return
|
||||
if (M.stat == 2)
|
||||
return
|
||||
if (src.gas.oxygen >= 1)
|
||||
src.ngas.oxygen--
|
||||
if (M.oxyloss >= 10)
|
||||
var/amount = max(0.15, 2)
|
||||
M.oxyloss -= amount
|
||||
else
|
||||
M.oxyloss = 0
|
||||
M.health = 100 - M.oxyloss - M.toxloss - M.fireloss - M.bruteloss
|
||||
if ((src.gas.temperature < T0C && src.gas.plasma >= 1))
|
||||
src.ngas.plasma--
|
||||
if (M.toxloss > 5)
|
||||
var/amount = max(0.1, 2)
|
||||
M.toxloss -= amount
|
||||
else
|
||||
M.toxloss = 0
|
||||
M.health = 100 - M.oxyloss - M.toxloss - M.fireloss - M.bruteloss
|
||||
if (istype(M, /mob/human))
|
||||
var/mob/human/H = M
|
||||
var/ok = 0
|
||||
for(var/organ in H.organs)
|
||||
var/obj/item/weapon/organ/external/affecting = H.organs[text("[]", organ)]
|
||||
ok += affecting.heal_damage(5, 5)
|
||||
|
||||
if (ok)
|
||||
H.UpdateDamageIcon()
|
||||
else
|
||||
H.UpdateDamage()
|
||||
else
|
||||
if (M.fireloss > 15)
|
||||
var/amount = max(0.3, 2)
|
||||
M.fireloss -= amount
|
||||
else
|
||||
M.fireloss = 0
|
||||
if (M.bruteloss > 10)
|
||||
var/amount = max(0.3, 2)
|
||||
M.bruteloss -= amount
|
||||
else
|
||||
M.bruteloss = 0
|
||||
M.health = 100 - M.oxyloss - M.toxloss - M.fireloss - M.bruteloss
|
||||
M.paralysis += 5
|
||||
if (src.gas.temperature < (60+T0C))
|
||||
src.gas.temperature = min(src.gas.temperature + 1, 60+T0C)
|
||||
|
||||
for(var/mob/E in viewers(1, src))
|
||||
if ((E.client && E.machine == src))
|
||||
src.attack_hand(E)
|
||||
|
||||
|
||||
|
||||
// Explosion - delete the cell or break it
|
||||
|
||||
ex_act(severity)
|
||||
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
del(src)
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
for(var/x in src.verbs)
|
||||
src.verbs -= x
|
||||
src.icon_state = "broken"
|
||||
|
||||
|
||||
// Blob attack - break the cell
|
||||
|
||||
blob_act()
|
||||
for(var/x in src.verbs)
|
||||
src.verbs -= x
|
||||
src.icon_state = "broken"
|
||||
src.density = 0
|
||||
|
||||
|
||||
|
||||
/* Unused
|
||||
|
||||
allow_drop()
|
||||
return 0
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,124 @@
|
||||
/*
|
||||
* dispenser - A dispenser unit for oxygen and plasma tanks.
|
||||
*
|
||||
* Note: tanks cannot be reinserted.
|
||||
*/
|
||||
|
||||
obj/machinery/dispenser
|
||||
desc = "A simple yet bulky one-way storage device for gas tanks. Holds 10 plasma and 10 oxygen tanks."
|
||||
name = "Tank Storage Unit"
|
||||
icon = 'turfs2.dmi'
|
||||
icon_state = "dispenser"
|
||||
density = 1
|
||||
anchored = 1
|
||||
var
|
||||
o2tanks = 10.0 // number of oxygen tanks
|
||||
pltanks = 10.0 // number of plasma tanks
|
||||
|
||||
|
||||
// if unit powered, use a small amount of power
|
||||
|
||||
process()
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
use_power(5)
|
||||
|
||||
|
||||
// attack by monkey same as attack by human
|
||||
|
||||
attack_paw(mob/user)
|
||||
return src.attack_hand(user)
|
||||
|
||||
// attack by human - show window to dispense a tank of either kind
|
||||
|
||||
attack_hand(mob/user)
|
||||
|
||||
user.machine = src
|
||||
var/dat = text("<TT><B>Loaded Tank Dispensing Unit</B><BR>\n<FONT color = 'blue'><B>Oxygen</B>: []</FONT> []<BR>\n<FONT color = 'orange'><B>Plasma</B>: []</FONT> []<BR>\n</TT>", src.o2tanks, (src.o2tanks ? text("<A href='?src=\ref[];oxygen=1'>Dispense</A>", src) : "empty"), src.pltanks, (src.pltanks ? text("<A href='?src=\ref[];plasma=1'>Dispense</A>", src) : "empty"))
|
||||
user << browse(dat, "window=dispenser")
|
||||
return
|
||||
|
||||
// dispense a tank when topic link is clicked on from 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 ((usr.contents.Find(src) || (get_dist(src, usr) <= 1 && istype(src.loc, /turf))))
|
||||
usr.machine = src
|
||||
|
||||
if (href_list["oxygen"])
|
||||
if (text2num(href_list["oxygen"]))
|
||||
if (src.o2tanks > 0)
|
||||
use_power(5)
|
||||
new /obj/item/weapon/tank/oxygentank( src.loc )
|
||||
src.o2tanks--
|
||||
if (istype(src.loc, /mob))
|
||||
attack_hand(src.loc)
|
||||
|
||||
else if (href_list["plasma"])
|
||||
if (text2num(href_list["plasma"]))
|
||||
if (src.pltanks > 0)
|
||||
use_power(5)
|
||||
new /obj/item/weapon/tank/plasmatank( src.loc )
|
||||
src.pltanks--
|
||||
if (istype(src.loc, /mob))
|
||||
attack_hand(src.loc)
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
|
||||
usr << browse(null, "window=dispenser")
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
// explosion, blob and meteor-hit actions - have a chance to dump all held tanks
|
||||
|
||||
ex_act(severity)
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
del(src)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
del(src)
|
||||
return
|
||||
if(3.0)
|
||||
if (prob(25))
|
||||
while(src.o2tanks > 0)
|
||||
new /obj/item/weapon/tank/oxygentank( src.loc )
|
||||
src.o2tanks--
|
||||
while(src.pltanks > 0)
|
||||
new /obj/item/weapon/tank/plasmatank( src.loc )
|
||||
src.pltanks--
|
||||
else
|
||||
return
|
||||
|
||||
blob_act()
|
||||
|
||||
if (prob(25))
|
||||
while(src.o2tanks > 0)
|
||||
new /obj/item/weapon/tank/oxygentank( src.loc )
|
||||
src.o2tanks--
|
||||
while(src.pltanks > 0)
|
||||
new /obj/item/weapon/tank/plasmatank( src.loc )
|
||||
src.pltanks--
|
||||
del(src)
|
||||
|
||||
meteorhit()
|
||||
|
||||
while(src.o2tanks > 0)
|
||||
new /obj/item/weapon/tank/oxygentank( src.loc )
|
||||
src.o2tanks--
|
||||
while(src.pltanks > 0)
|
||||
new /obj/item/weapon/tank/plasmatank( src.loc )
|
||||
src.pltanks--
|
||||
del(src)
|
||||
return
|
||||
@@ -0,0 +1,61 @@
|
||||
/*
|
||||
* Door_control -- A remote control for opening/closing poddoors
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
obj/machinery/door_control
|
||||
name = "remote door control"
|
||||
icon = 'stationobjs.dmi'
|
||||
icon_state = "doorctrl0"
|
||||
desc = "A remote control switch for a door."
|
||||
anchored = 1.0
|
||||
var
|
||||
id = null // id must match that of the poddoor to operate
|
||||
|
||||
|
||||
// attack by monkey same as human
|
||||
|
||||
attack_paw(mob/user)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// attack by an item same as empty hand
|
||||
|
||||
attackby(nothing, mob/user)
|
||||
return src.attack_hand(user)
|
||||
|
||||
// attack by hand, toggle all poddoors with same id
|
||||
|
||||
attack_hand(mob/user)
|
||||
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
use_power(5)
|
||||
icon_state = "doorctrl1"
|
||||
|
||||
for(var/obj/machinery/door/poddoor/M in machines)
|
||||
if (M.id == src.id)
|
||||
if (M.density)
|
||||
spawn( 0 )
|
||||
M.openpod()
|
||||
return
|
||||
else
|
||||
spawn( 0 )
|
||||
M.closepod()
|
||||
return
|
||||
|
||||
spawn(15)
|
||||
if(!(stat & NOPOWER))
|
||||
icon_state = "doorctrl0"
|
||||
|
||||
|
||||
// area power changed, set the icon_state to unpowered
|
||||
|
||||
power_change()
|
||||
..()
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "doorctrl-p"
|
||||
else
|
||||
icon_state = "doorctrl0"
|
||||
|
||||
@@ -0,0 +1,188 @@
|
||||
/*
|
||||
* Firealarm - Machine that controls firealarm triggering in an area
|
||||
*
|
||||
* When fire present, triggers flashing area icon and closes firedoors.
|
||||
*/
|
||||
|
||||
obj/machinery/firealarm
|
||||
name = "firealarm"
|
||||
icon = 'items.dmi'
|
||||
icon_state = "firealarm"
|
||||
anchored = 1
|
||||
var
|
||||
detecting = 1 // true if the alarm is working, false if disabled
|
||||
//working = 1 // unused
|
||||
time = 10.0 // seconds left until alarm triggered
|
||||
timing = 0 // true if counting down timer
|
||||
|
||||
|
||||
// Called if the location turf is on fire; triggers the alarm if so
|
||||
|
||||
burn(fi_amount)
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
if(src.detecting) src.alarm()
|
||||
return
|
||||
|
||||
|
||||
// Attack with item, if wirecutters connect/disconnect fire detector
|
||||
// Otherwise, trigger the alarm
|
||||
|
||||
attackby(obj/item/weapon/W, mob/user)
|
||||
if (istype(W, /obj/item/weapon/wirecutters))
|
||||
src.detecting = !( src.detecting )
|
||||
if (src.detecting)
|
||||
viewers(user, null) << "\red [user] has reconnected [src]'s detecting unit!"
|
||||
else
|
||||
viewers(user, null) << "\red [user] has disconnected [src]'s detecting unit!"
|
||||
else
|
||||
src.alarm()
|
||||
src.add_fingerprint(user)
|
||||
return
|
||||
|
||||
|
||||
// Timed process. Countdown if set to trigger after time.
|
||||
|
||||
process()
|
||||
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
|
||||
use_power(10, ENVIRON)
|
||||
|
||||
if (src.timing)
|
||||
if (src.time > 0)
|
||||
src.time = round(src.time) - 1
|
||||
else
|
||||
alarm()
|
||||
src.time = 0
|
||||
src.timing = 0
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
return
|
||||
|
||||
|
||||
// When area power state changes, disable alarm if no power in ENVIRON channel
|
||||
|
||||
power_change()
|
||||
if(powered(ENVIRON))
|
||||
stat &= ~NOPOWER
|
||||
icon_state = "firealarm"
|
||||
else
|
||||
spawn(rand(0,15))
|
||||
stat |= NOPOWER
|
||||
icon_state = "firealarm-p"
|
||||
|
||||
// Monkey interact same as human
|
||||
|
||||
attack_paw(mob/user)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// Interact and show window
|
||||
// Garbled text if a monkey
|
||||
|
||||
attack_hand(mob/user)
|
||||
|
||||
if(user.stat || stat&NOPOWER) return
|
||||
|
||||
user.machine = src
|
||||
var/area/A = src.loc
|
||||
var/d1
|
||||
var/d2
|
||||
if (istype(user, /mob/human))
|
||||
A = A.loc
|
||||
|
||||
if (A.fire)
|
||||
d1 = "<A href='?src=\ref[src];reset=1'>Reset - Lockdown</A>"
|
||||
else
|
||||
d1 = "<A href='?src=\ref[src];alarm=1'>Alarm - Lockdown</A>"
|
||||
if (src.timing)
|
||||
d2 = "<A href='?src=\ref[src];time=0'>Stop Time Lock</A>"
|
||||
else
|
||||
d2 = "<A href='?src=\ref[src];time=1'>Initiate Time Lock</A>"
|
||||
var/second = src.time % 60
|
||||
var/minute = (src.time - second) / 60
|
||||
var/dat = text("<HTML><HEAD></HEAD><BODY><TT><B>Fire alarm</B> []\n<HR>\nTimer System: []<BR>\nTime Left: [][] <A href='?src=\ref[];tp=-30'>-</A> <A href='?src=\ref[];tp=-1'>-</A> <A href='?src=\ref[];tp=1'>+</A> <A href='?src=\ref[];tp=30'>+</A>\n</TT></BODY></HTML>", d1, d2, (minute ? text("[]:", minute) : null), second, src, src, src, src)
|
||||
user << browse(dat, "window=firealarm")
|
||||
else
|
||||
A = A.loc
|
||||
if (A.fire)
|
||||
d1 = text("<A href='?src=\ref[];reset=1'>[]</A>", src, stars("Reset - Lockdown"))
|
||||
else
|
||||
d1 = text("<A href='?src=\ref[];alarm=1'>[]</A>", src, stars("Alarm - Lockdown"))
|
||||
if (src.timing)
|
||||
d2 = text("<A href='?src=\ref[];time=0'>[]</A>", src, stars("Stop Time Lock"))
|
||||
else
|
||||
d2 = text("<A href='?src=\ref[];time=1'>[]</A>", src, stars("Initiate Time Lock"))
|
||||
var/second = src.time % 60
|
||||
var/minute = (src.time - second) / 60
|
||||
var/dat = text("<HTML><HEAD></HEAD><BODY><TT><B>[]</B> []\n<HR>\nTimer System: []<BR>\nTime Left: [][] <A href='?src=\ref[];tp=-30'>-</A> <A href='?src=\ref[];tp=-1'>-</A> <A href='?src=\ref[];tp=1'>+</A> <A href='?src=\ref[];tp=30'>+</A>\n</TT></BODY></HTML>", stars("Fire alarm"), d1, d2, (minute ? text("[]:", minute) : null), second, src, src, src, src)
|
||||
user << browse(dat, "window=firealarm")
|
||||
return
|
||||
|
||||
|
||||
// Handle topic links from interaction window
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
if (usr.stat || stat&NOPOWER)
|
||||
return
|
||||
|
||||
if ((usr.contents.Find(src) || (get_dist(src, usr) <= 1 && istype(src.loc, /turf))))
|
||||
usr.machine = src
|
||||
|
||||
if (href_list["reset"])
|
||||
src.reset()
|
||||
|
||||
else if (href_list["alarm"])
|
||||
src.alarm()
|
||||
|
||||
else if (href_list["time"])
|
||||
src.timing = text2num(href_list["time"])
|
||||
|
||||
else if (href_list["tp"])
|
||||
var/tp = text2num(href_list["tp"])
|
||||
src.time += tp
|
||||
src.time = min(max(round(src.time), 0), 120)
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
src.add_fingerprint(usr)
|
||||
else
|
||||
usr << browse(null, "window=firealarm")
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
// Reset the alarm. Area icon updated, all firedoors in area opened.
|
||||
|
||||
proc/reset()
|
||||
var/area/A = src.loc
|
||||
A = A.loc
|
||||
if (!( istype(A, /area) ))
|
||||
return
|
||||
A.fire = 0
|
||||
A.mouse_opacity = 0
|
||||
A.updateicon()
|
||||
|
||||
for(var/obj/machinery/door/firedoor/D in A)
|
||||
if (D.density)
|
||||
spawn( 0 )
|
||||
D.openfire()
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
// Trigger the alarm. Calls area/firealert()
|
||||
|
||||
proc/alarm()
|
||||
var/area/A = src.loc
|
||||
A = A.loc
|
||||
if (!( istype(A, /area) ))
|
||||
return
|
||||
A.firealert()
|
||||
return
|
||||
@@ -0,0 +1,390 @@
|
||||
/*
|
||||
* Freezer -- freezer part of cryocell system.
|
||||
* attaches to the cryocell via a (flex)pipe
|
||||
*
|
||||
* TODO: Better handling of gas flow when freezer is turned off
|
||||
* TODO: Improve flask finding in process()
|
||||
* TODO: Logically, the freezer should warm the environment somewhat just like a real freezer
|
||||
*/
|
||||
|
||||
obj/machinery/freezer
|
||||
name = "freezer"
|
||||
icon = 'Cryogenic2.dmi'
|
||||
icon_state = "freezer_0"
|
||||
density = 1
|
||||
p_dir = 4 // the pipe connection direction (west)
|
||||
anchored = 1
|
||||
capmult = 1 // capacity multiplier
|
||||
|
||||
var
|
||||
connector = null // the flask connecter overlay object
|
||||
obj/machinery/line_out = null // the pipe object connected
|
||||
obj/machinery/vnode = null // the pipeline object associated with line_out
|
||||
c_used = 1.0 // coolant amount used
|
||||
status = 0.0 // true if cooling
|
||||
t_flags = 3.0 // bitflags for oxygen (bit-0) and plasma (bit-1) delivery
|
||||
transfer = 0.0 // true if transfering to cryocell
|
||||
temperature = 60.0+T0C // the temperature setpoint (kelvin)
|
||||
|
||||
obj/substance/gas/gas // the gas reservoir
|
||||
obj/substance/gas/ngas // the new value of the gas reservoir
|
||||
|
||||
|
||||
// Create a new freezer
|
||||
// Create the overlay object for the flask connectors
|
||||
// Create the 3 flasks (as contents of the freezer)
|
||||
// Allocate the gas reservoir and register with the gasflowlist
|
||||
|
||||
New()
|
||||
..()
|
||||
var/obj/overlay/O1 = new /obj/overlay( )
|
||||
O1.icon = 'Cryogenic2.dmi'
|
||||
O1.icon_state = "canister connector_0"
|
||||
O1.pixel_y = -16.0
|
||||
src.overlays += O1
|
||||
src.connector = O1
|
||||
new /obj/item/weapon/flasks/oxygen( src )
|
||||
new /obj/item/weapon/flasks/coolant( src )
|
||||
new /obj/item/weapon/flasks/plasma( src )
|
||||
rebuild_overlay()
|
||||
|
||||
gas = new/obj/substance/gas()
|
||||
ngas = new/obj/substance/gas()
|
||||
|
||||
gasflowlist += src
|
||||
|
||||
|
||||
// Find the (flex)pipe connected to the freezer
|
||||
|
||||
buildnodes()
|
||||
var/turf/T = src.loc
|
||||
|
||||
line_out = get_machine(level, T, p_dir )
|
||||
|
||||
if(line_out) vnode = line_out.getline() // the pipeline associated with the pipe
|
||||
|
||||
|
||||
// Update gas levels with the new levels calculated in process()
|
||||
|
||||
gas_flow()
|
||||
gas.replace_by(ngas)
|
||||
|
||||
|
||||
// Called to leak gas to the turf one step east, if the pipe is not present
|
||||
|
||||
proc/leak_to_turf()
|
||||
var/turf/T = get_step(src, EAST)
|
||||
|
||||
if(T.density)
|
||||
T = src.loc
|
||||
if(T.density)
|
||||
return
|
||||
|
||||
flow_to_turf(gas, ngas, T)
|
||||
|
||||
|
||||
// Returns the gas fullness value
|
||||
|
||||
get_gas_val(from)
|
||||
return gas.tot_gas()
|
||||
|
||||
|
||||
// Returns the gas reservoir
|
||||
|
||||
get_gas(from)
|
||||
return gas
|
||||
|
||||
|
||||
// Interact by monkey same as human
|
||||
|
||||
attack_paw(mob/user)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// Interact by human
|
||||
// Show the interaction window
|
||||
|
||||
attack_hand(mob/user)
|
||||
|
||||
user.machine = src
|
||||
|
||||
if ((!( istype(usr, /mob/human) ) && (!( ticker ) || (ticker && ticker.mode != "monkey"))))
|
||||
var/d1
|
||||
if (locate(/obj/item/weapon/flasks, src))
|
||||
var/counter = 1
|
||||
|
||||
for(var/obj/item/weapon/flasks/F in src)
|
||||
d1 += text("<A href = '?src=\ref[];flask=[]'><B>Flask []</B></A>: [] / [] / []<BR>", src, counter, counter, F.oxygen, F.plasma, F.coolant)
|
||||
counter++
|
||||
//Foreach goto(78)
|
||||
d1 += "Key: Oxygen / Plasma / Coolant<BR>"
|
||||
else
|
||||
d1 = "<B>No flasks!</B>"
|
||||
var/t1 = null
|
||||
switch(src.t_flags)
|
||||
if(0.0)
|
||||
t1 = text("<A href = '?src=\ref[];oxygen=1'>Oxygen-No</A> <A href = '?src=\ref[];plasma=1'>Plasma-No</A>", src, src)
|
||||
if(1.0)
|
||||
t1 = text("<A href = '?src=\ref[];oxygen=0'>Oxygen-Yes</A> <A href = '?src=\ref[];plasma=1'>Plasma-No</A>", src, src)
|
||||
if(2.0)
|
||||
t1 = text("<A href = '?src=\ref[];oxygen=1'>Oxygen-No</A> <A href = '?src=\ref[];plasma=0'>Plasma-Yes</A>", src, src)
|
||||
if(3.0)
|
||||
t1 = text("<A href = '?src=\ref[];oxygen=0'>Oxygen-Yes</A> <A href = '?src=\ref[];plasma=0'>Plasma-Yes</A>", src, src)
|
||||
else
|
||||
var/t2 = null
|
||||
if (src.status)
|
||||
t2 = text("Cooling-[] <A href = '?src=\ref[];cool=0'>Stop</A>", src.c_used, src)
|
||||
else
|
||||
t2 = text("<A href = '?src=\ref[];cool=1'>Cool</A> Stopped", src)
|
||||
var/dat = text("<HTML><HEAD></HEAD><BODY><TT><BR>\n\t\t<B>Temperature</B>: []<BR>\n\t\t<B>Transfer Status</B>: []<BR>\n\t\t <B>Chemicals Used</B>: []<BR>\n\t\t<B>Freezer status</B>: []<BR>\n\t\t <A href='?src=\ref[];cp=-5'>-</A> <A href='?src=\ref[];cp=-1'>-</A> [] <A href='?src=\ref[];cp=1'>+</A> <A href='?src=\ref[];cp=5'>+</A><BR>\n<BR>\n\t[]<BR>\n<BR>\n<BR>\n\t<A href='?src=\ref[];mach_close=freezer'>Close</A><BR>\n\t</TT></BODY></HTML>", src.temperature-T0C, (src.transfer ? text("Transfering <A href='?src=\ref[];transfer=0'>Stop</A>", src) : text("<A href='?src=\ref[];transfer=1'>Transfer</A> Stopped", src)), t1, t2, src, src, src.c_used, src, src, d1, user)
|
||||
user << browse(dat, "window=freezer;size=400x500")
|
||||
else
|
||||
var/d1 = null
|
||||
if (locate(/obj/item/weapon/flasks, src))
|
||||
var/counter = 1
|
||||
for(var/obj/item/weapon/flasks/F in src)
|
||||
d1 += text("<A href = '?src=\ref[];flask=[]'><B>[] []</B></A>: []<BR>", src, counter, stars("Flask"), counter, stars(text("[] / [] / []", F.oxygen, F.plasma, F.coolant)))
|
||||
counter++
|
||||
//Foreach goto(380)
|
||||
d1 += "Key: Oxygen / Plasma / Coolant<BR>"
|
||||
else
|
||||
d1 = "<B>No flasks!</B>"
|
||||
var/t1 = null
|
||||
switch(src.t_flags)
|
||||
if(0.0)
|
||||
t1 = text("<A href = '?src=\ref[];oxygen=1'>[]</A> <A href = '?src=\ref[];plasma=1'>[]</A>", src, stars("Oxygen-No"), src, stars("Plasma-No"))
|
||||
if(1.0)
|
||||
t1 = text("<A href = '?src=\ref[];oxygen=0'>[]</A> <A href = '?src=\ref[];plasma=1'>[]</A>", src, stars("Oxygen-Yes"), src, stars("Plasma-No"))
|
||||
if(2.0)
|
||||
t1 = text("<A href = '?src=\ref[];oxygen=1'>[]</A> <A href = '?src=\ref[];plasma=0'>[]</A>", src, stars("Oxygen-No"), src, stars("Plasma-Yes"))
|
||||
if(3.0)
|
||||
t1 = text("<A href = '?src=\ref[];oxygen=0'>[]</A> <A href = '?src=\ref[];plasma=0'>[]</A>", src, stars("Oxygen-Yes"), src, stars("Plasma-Yes"))
|
||||
else
|
||||
var/t2 = null
|
||||
if (src.status)
|
||||
t2 = text("Cooling-[] <A href = '?src=\ref[];cool=0'>[]</A>", src.c_used, src, stars("Stop"))
|
||||
else
|
||||
t2 = text("<A href = '?src=\ref[];cool=1'>Cool</A> []", src, stars("Stopped"))
|
||||
var/dat = text("<HTML><HEAD></HEAD><BODY><TT><BR>\n\t\t<B>[]</B>: []<BR>\n\t\t<B>[]</B>: []<BR>\n\t\t <B>[]</B>: []<BR>\n\t\t<B>[]</B>: []<BR>\n\t\t <A href='?src=\ref[];cp=-5'>-</A> <A href='?src=\ref[];cp=-1'>-</A> [] <A href='?src=\ref[];cp=1'>+</A> <A href='?src=\ref[];cp=5'>+</A><BR>\n<BR>\n\t[]<BR>\n<BR>\n<BR>\n\t<A href='?src=\ref[];mach_close=freezer'>Close</A>\n\t</TT></BODY></HTML>", stars("Temperature"), src.temperature-T0C, stars("Transfer Status"), (src.transfer ? text("Transfering <A href='?src=\ref[];transfer=0'>Stop</A>", src) : text("<A href='?src=\ref[];transfer=1'>Transfer</A> Stopped", src)), stars("Chemicals Used"), t1, stars("Freezer status"), t2, src, src, src.c_used, src, src, d1, user)
|
||||
user << browse(dat, "window=freezer;size=400x500")
|
||||
|
||||
|
||||
// Handle topic links from interaction window
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
if ((!( istype(usr, /mob/human) ) && (!( ticker ) || (ticker && ticker.mode != "monkey"))))
|
||||
usr << "\red You don't have the dexterity to do this!"
|
||||
return
|
||||
if ((usr.stat || usr.restrained()))
|
||||
return
|
||||
if ((usr.contents.Find(src) || (get_dist(src, usr) <= 1 && istype(src.loc, /turf))))
|
||||
usr.machine = src
|
||||
if (href_list["cp"])
|
||||
var/cp = text2num(href_list["cp"])
|
||||
src.c_used += cp
|
||||
src.c_used = min(max(round(src.c_used), 0), 10)
|
||||
if (href_list["oxygen"])
|
||||
var/t1 = text2num(href_list["oxygen"])
|
||||
if (t1)
|
||||
src.t_flags |= 1
|
||||
else
|
||||
src.t_flags &= 65534
|
||||
if (href_list["plasma"])
|
||||
var/t1 = text2num(href_list["plasma"])
|
||||
if (t1)
|
||||
src.t_flags |= 2
|
||||
else
|
||||
src.t_flags &= 65533
|
||||
if (href_list["cool"])
|
||||
src.status = text2num(href_list["cool"])
|
||||
src.icon_state = text("freezer_[]", src.status)
|
||||
if (href_list["transfer"])
|
||||
src.transfer = text2num(href_list["transfer"])
|
||||
if (href_list["flask"])
|
||||
var/t1 = text2num(href_list["flask"])
|
||||
if (t1 <= src.contents.len)
|
||||
var/obj/F = src.contents[t1]
|
||||
F.loc = src.loc
|
||||
src.rebuild_overlay()
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
|
||||
// Attack with item
|
||||
// If a flask, add to contents and rebuild overlays
|
||||
|
||||
attackby(obj/item/weapon/flasks/F, mob/user)
|
||||
|
||||
if (!( istype(F, /obj/item/weapon/flasks) ))
|
||||
return
|
||||
if (src.contents.len >= 3)
|
||||
user << "\blue All slots are full!"
|
||||
return
|
||||
else
|
||||
user.drop_item()
|
||||
F.loc = src
|
||||
src.rebuild_overlay()
|
||||
|
||||
|
||||
// Called when area power state changes
|
||||
// Set icon state depending on power status
|
||||
|
||||
power_change()
|
||||
..()
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "freezer_0"
|
||||
else
|
||||
src.icon_state = "freezer_[status]"
|
||||
|
||||
|
||||
// Called to update the overlays of the connector and flasks
|
||||
|
||||
proc/rebuild_overlay()
|
||||
for(var/x in src.overlays)
|
||||
src.overlays -= x
|
||||
|
||||
src.overlays += src.connector
|
||||
var/counter = 0
|
||||
|
||||
for(var/obj/item/weapon/flasks/F in src.contents)
|
||||
var/obj/overlay/O = new /obj/overlay( )
|
||||
O.icon = F.icon
|
||||
O.icon_state = F.icon_state
|
||||
O.pixel_y = -17.0
|
||||
O.pixel_x = counter * 12
|
||||
src.overlays += O
|
||||
counter++
|
||||
if (counter >= 3)
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
// Timed process
|
||||
// Deplete flasks and cool/add to gas reservoir as appropriate
|
||||
// Perform flow into pipe
|
||||
// Note: Flask finding/depletion process is rather inefficient - rewrite?
|
||||
// TODO: Make gas flow when not transfering from flasks
|
||||
|
||||
process()
|
||||
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
|
||||
use_power(50)
|
||||
|
||||
var/obj/item/weapon/flasks/F1
|
||||
var/obj/item/weapon/flasks/F2
|
||||
var/obj/item/weapon/flasks/F3
|
||||
if (src.contents.len >= 3)
|
||||
F3 = src.contents[3]
|
||||
if (src.contents.len >= 2)
|
||||
F2 = src.contents[2]
|
||||
if (src.contents.len >= 1)
|
||||
F1 = src.contents[1]
|
||||
var/u_cool = 0
|
||||
if (src.status)
|
||||
u_cool = src.c_used
|
||||
|
||||
if ((F2 && F2.coolant))
|
||||
if (F2.coolant >= u_cool)
|
||||
F2.coolant -= u_cool
|
||||
else
|
||||
u_cool = F2.coolant
|
||||
F2.coolant = 0
|
||||
|
||||
else if ((F1 && F1.coolant))
|
||||
if (F1.coolant >= u_cool)
|
||||
F1.coolant -= u_cool
|
||||
else
|
||||
u_cool = F1.coolant
|
||||
F1.coolant = 0
|
||||
|
||||
else if ((F3 && F3.coolant))
|
||||
if (F3.coolant >= u_cool)
|
||||
F3.coolant -= u_cool
|
||||
else
|
||||
u_cool = F3.coolant
|
||||
F3.coolant = 0
|
||||
else
|
||||
u_cool = 0
|
||||
|
||||
if (u_cool)
|
||||
src.temperature = max((-100.0+T0C), src.temperature - (u_cool * 5) )
|
||||
use_power(200)
|
||||
|
||||
src.temperature = min(src.temperature + 5, 20+T0C)
|
||||
if (src.transfer)
|
||||
var/u_oxy = 0
|
||||
var/u_pla = 0
|
||||
|
||||
if (src.t_flags & 1)
|
||||
u_oxy = 1
|
||||
if ((F1 && F1.oxygen))
|
||||
if (F1.oxygen >= u_oxy)
|
||||
F1.oxygen -= u_oxy
|
||||
else
|
||||
u_oxy = F1.oxygen
|
||||
F1.oxygen = 0
|
||||
else
|
||||
if ((F2 && F2.oxygen))
|
||||
if (F2.oxygen >= u_oxy)
|
||||
F2.oxygen -= u_oxy
|
||||
else
|
||||
u_oxy = F2.oxygen
|
||||
F2.oxygen = 0
|
||||
else
|
||||
if ((F3 && F3.oxygen))
|
||||
if (F3.oxygen >= u_oxy)
|
||||
F3.oxygen -= u_oxy
|
||||
else
|
||||
u_oxy = F3.oxygen
|
||||
F3.oxygen = 0
|
||||
else
|
||||
u_oxy = 0
|
||||
|
||||
if (src.t_flags & 2)
|
||||
u_pla = 1
|
||||
if ((F3 && F3.plasma))
|
||||
if (F3.plasma >= u_pla)
|
||||
F3.plasma -= u_pla
|
||||
else
|
||||
u_pla = F3.plasma
|
||||
F3.plasma = 0
|
||||
else
|
||||
if ((F2 && F2.plasma))
|
||||
if (F2.plasma >= u_pla)
|
||||
F2.plasma -= u_pla
|
||||
else
|
||||
u_pla = F2.plasma
|
||||
F2.plasma = 0
|
||||
else
|
||||
if ((F1 && F1.plasma))
|
||||
if (F1.plasma >= u_pla)
|
||||
F1.plasma -= u_pla
|
||||
else
|
||||
u_pla = F1.plasma
|
||||
F1.plasma = 0
|
||||
else
|
||||
u_pla = 0
|
||||
if ( (u_oxy + u_pla) > 0)
|
||||
ngas.oxygen += u_oxy
|
||||
ngas.plasma += u_pla
|
||||
ngas.temperature = src.temperature
|
||||
spawn( 1 )
|
||||
if (src.line_out)
|
||||
|
||||
if(vnode)
|
||||
var/delta_gt = FLOWFRAC * ( vnode.get_gas_val(src) - gas.tot_gas() / capmult)
|
||||
calc_delta( src, gas, ngas, vnode, delta_gt)
|
||||
else
|
||||
leak_to_turf()
|
||||
|
||||
return
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
return
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
/*
|
||||
* Gas_sensor - Provides remote reading of the current gas conditions at location
|
||||
* Read from engine computers.
|
||||
*
|
||||
*/
|
||||
|
||||
obj/machinery/gas_sensor
|
||||
name = "gas sensor"
|
||||
icon = 'stationobjs.dmi'
|
||||
icon_state = "gsensor"
|
||||
desc = "A remote sensor for atmospheric gas composition."
|
||||
anchored = 1
|
||||
var
|
||||
id // Engine computer must have matching id
|
||||
|
||||
|
||||
// Return a string showing gas values & temperature at object location
|
||||
|
||||
proc/sense_string()
|
||||
|
||||
var/t = ""
|
||||
|
||||
var/turf/T = src.loc
|
||||
|
||||
var/turf_total = T.tot_gas()
|
||||
|
||||
var/t1 = add_tspace("[round(turf_total / CELLSTANDARD * 100, 0.1)]%",6)
|
||||
t += "<PRE>Pressure: [t1] Temperature: [round(T.temp - T0C,0.1)]°C<BR>"
|
||||
|
||||
if(turf_total == 0)
|
||||
t+="O2: 0 N2: 0 CO2: 0><BR>Plasma: 0 N20: 0"
|
||||
else
|
||||
t1 = add_tspace(round(T.oxygen/turf_total * 100, 0.1),5)
|
||||
|
||||
t += "O2: [t1] "
|
||||
|
||||
t1 = add_tspace(round(T.n2/turf_total * 100, 0.1),5)
|
||||
|
||||
t += "N2: [t1] "
|
||||
|
||||
t1 = add_tspace(round(T.co2/turf_total * 100, 0.01),5)
|
||||
|
||||
t += "CO2: [t1]<BR>"
|
||||
|
||||
t1 = add_tspace(round(T.poison/turf_total * 100, 0.001),5)
|
||||
|
||||
t += "Plasma: [t1] "
|
||||
|
||||
t1 = add_tspace(round(T.sl_gas/turf_total * 100, 0.001),5)
|
||||
|
||||
t += "N2O: [t1]"
|
||||
|
||||
t += "</PRE>"
|
||||
|
||||
return t
|
||||
@@ -0,0 +1,68 @@
|
||||
/*
|
||||
* Igniter -- Togglable igniter, as used in the engine.
|
||||
*
|
||||
* Sets turf location on fire if enough plasma is present
|
||||
*
|
||||
*/
|
||||
|
||||
obj/machinery/igniter
|
||||
|
||||
name = "igniter"
|
||||
icon = 'stationobjs.dmi'
|
||||
icon_state = "igniter1"
|
||||
anchored = 1.0
|
||||
var
|
||||
on = 1.0 // true if the igniter is turned on
|
||||
|
||||
|
||||
// Initializes the icon state
|
||||
|
||||
New()
|
||||
..()
|
||||
icon_state = "igniter[on]"
|
||||
|
||||
|
||||
// Called if area loses/gains power
|
||||
// sets the icon_state off if no power available
|
||||
|
||||
power_change()
|
||||
..()
|
||||
if(!( stat & NOPOWER) )
|
||||
icon_state = "igniter[src.on]"
|
||||
else
|
||||
icon_state = "igniter0"
|
||||
|
||||
|
||||
// monkey attack same as human if in monkey mode
|
||||
|
||||
attack_paw(mob/user as mob)
|
||||
if ((ticker && ticker.mode == "monkey"))
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// When attacked, toggle the igniter on/off
|
||||
|
||||
attack_hand(mob/user as mob)
|
||||
|
||||
..()
|
||||
add_fingerprint(user)
|
||||
if(stat & NOPOWER) return
|
||||
|
||||
use_power(50)
|
||||
src.on = !( src.on )
|
||||
src.icon_state = text("igniter[]", src.on)
|
||||
return
|
||||
|
||||
|
||||
// if turned on (and powered), ignite the turf if enough plasma present
|
||||
|
||||
process()
|
||||
|
||||
if (src.on && !(stat & NOPOWER) )
|
||||
var/turf/T = src.loc
|
||||
if (locate(/obj/move, T))
|
||||
T = locate(/obj/move, T)
|
||||
if (T.firelevel < 900000.0)
|
||||
T.firelevel = T.poison
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
* Injector -- allows transfer of gas across a wall when attacked by a gas tank
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
obj/machinery/injector
|
||||
name = "injector"
|
||||
icon = 'stationobjs.dmi'
|
||||
icon_state = "injector"
|
||||
density = 1
|
||||
anchored = 1
|
||||
flags = WINDOW // Unsure why flagged as a window
|
||||
|
||||
|
||||
// When attacked by a tank item, transfer the tank's gas contents to the turf behind the injector
|
||||
|
||||
attackby(var/obj/item/weapon/W, var/mob/user)
|
||||
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
use_power(25)
|
||||
|
||||
var/obj/item/weapon/tank/ptank = W
|
||||
if (!( istype(ptank, /obj/item/weapon/tank) ))
|
||||
return
|
||||
|
||||
var/turf/T = get_step(src.loc, get_dir(user, src))
|
||||
ptank.gas.turf_add(T, -1.0)
|
||||
src.add_fingerprint(user)
|
||||
return
|
||||
|
||||
@@ -0,0 +1,103 @@
|
||||
/*
|
||||
* Inlet -- Pipe inlet object
|
||||
* Equalizes gas content between its turf and the pipe.
|
||||
* Thus can also act as an outlet if the pipe has more gas in it than the turf.
|
||||
*
|
||||
* Similar to /obj/machinery/vent, except that vents flow only one way (from pipe to the turf)
|
||||
*/
|
||||
|
||||
obj/machinery/inlet
|
||||
name = "inlet"
|
||||
icon = 'pipes.dmi'
|
||||
icon_state = "inlet"
|
||||
desc = "A gas pipe inlet."
|
||||
anchored = 1
|
||||
p_dir = 2 // default pipe direction is south
|
||||
capmult = 2
|
||||
|
||||
var
|
||||
obj/machinery/node // the connected object
|
||||
obj/machinery/vnode // the connected pipeline object (if node is a pipe)
|
||||
|
||||
obj/substance/gas/gas // the gas reservoir
|
||||
obj/substance/gas/ngas // the new gas reservoir (as calculated in process())
|
||||
|
||||
capacity = 6000000 // nominal gas capacity; not actually used
|
||||
|
||||
|
||||
// Create a new inlet. Pipe connection direction is set same as icon direction, thus p_dir does not need to be set
|
||||
// when placing inlet on map. Create gas reservoir and register self with the gasflowlist
|
||||
|
||||
New()
|
||||
|
||||
..()
|
||||
p_dir = dir
|
||||
gas = new/obj/substance/gas(src)
|
||||
gas.maximum = capacity
|
||||
ngas = new/obj/substance/gas()
|
||||
gasflowlist += src
|
||||
|
||||
|
||||
// Find the connected pipe or machine
|
||||
|
||||
buildnodes()
|
||||
|
||||
var/turf/T = get_step(src.loc, src.dir)
|
||||
var/fdir = turn(src.p_dir, 180)
|
||||
|
||||
for(var/obj/machinery/M in T)
|
||||
if(M.p_dir & fdir)
|
||||
src.node = M
|
||||
break
|
||||
|
||||
if(node) vnode = node.getline()
|
||||
|
||||
return
|
||||
|
||||
|
||||
// Returns the gas fullness value. Capmult is 2 for inlets because they in effect have two connections: the pipe, and the turf
|
||||
|
||||
get_gas_val(from)
|
||||
return gas.tot_gas()/capmult
|
||||
|
||||
|
||||
// Return the internal gas reservoir
|
||||
|
||||
get_gas(from)
|
||||
return gas
|
||||
|
||||
|
||||
// After all machine process()es in world are complete, update the current gas levels with the new calculated levels
|
||||
|
||||
gas_flow()
|
||||
gas.replace_by(ngas)
|
||||
|
||||
|
||||
// Timed process. Calculate gas flow to and from the turf, and to and from the connected pipe
|
||||
|
||||
process()
|
||||
var/delta_gt
|
||||
|
||||
var/turf/T = src.loc
|
||||
|
||||
if(T && !T.density)
|
||||
flow_to_turf(gas, ngas, T) // act as gas leak at the turf we are located on
|
||||
|
||||
if(vnode)
|
||||
delta_gt = FLOWFRAC * ( vnode.get_gas_val(src) - gas.tot_gas() / capmult)
|
||||
calc_delta( src, gas, ngas, vnode, delta_gt)
|
||||
else
|
||||
leak_to_turf()
|
||||
|
||||
|
||||
// If no node is present, leak the contents to the turf position the node would be.
|
||||
// note this is a leak from the node, not the inlet itself
|
||||
// thus acts as a link between the inlet turf and the turf in step(dir)
|
||||
|
||||
proc/leak_to_turf()
|
||||
|
||||
var/turf/T = get_step(src, dir)
|
||||
if(T && !T.density)
|
||||
flow_to_turf(gas, ngas, T)
|
||||
|
||||
|
||||
@@ -0,0 +1,113 @@
|
||||
/*
|
||||
* Junction - a junction between standard and heat-exchanger pipe.
|
||||
*
|
||||
*/
|
||||
|
||||
obj/machinery/junction
|
||||
name = "junction"
|
||||
icon = 'junct-pipe.dmi'
|
||||
icon_state = "junction"
|
||||
desc = "A junction between regular and heat-exchanger pipework."
|
||||
anchored = 1
|
||||
dir = 2
|
||||
p_dir = 1 // junctions are unique in that the have both p_dir (standard pipe) and h_dir (h/e pipe) set
|
||||
h_dir = 2 //
|
||||
capmult = 2
|
||||
|
||||
var/obj/substance/gas/gas = null // the gas reservoir
|
||||
var/obj/substance/gas/ngas = null
|
||||
|
||||
var/obj/machinery/node1 = null // the node connecting to the h/e pipe
|
||||
var/obj/machinery/node2 = null // the node connecting to the standard pipe
|
||||
|
||||
var/obj/machinery/vnode1 // the pipeline object of the h/e pipe
|
||||
var/obj/machinery/vnode2 // the pipeline object of the standard pipe
|
||||
|
||||
var/capacity = 6000000 // nominal gas capacity
|
||||
|
||||
|
||||
// Create a new junction, create gas reservoir
|
||||
// Calculated p_dir and h_dir from the icon dir
|
||||
|
||||
New()
|
||||
..()
|
||||
gas = new/obj/substance/gas(src)
|
||||
ngas = new/obj/substance/gas()
|
||||
gasflowlist += src
|
||||
|
||||
h_dir = dir // the h/e pipe is in icon dir
|
||||
p_dir = turn(dir, 180) // the reg pipe is in opposite dir
|
||||
|
||||
|
||||
// Find the connected machines or pipes
|
||||
|
||||
buildnodes()
|
||||
|
||||
var/turf/T = src.loc
|
||||
|
||||
node1 = get_he_machine(level, T, h_dir ) // the h/e pipe
|
||||
|
||||
node2 = get_machine(level, T , p_dir ) // the regular pipe
|
||||
|
||||
if(node1) vnode1 = node1.getline()
|
||||
if(node2) vnode2 = node2.getline()
|
||||
|
||||
return
|
||||
|
||||
|
||||
// Replace gas levels with the newly calculated values
|
||||
|
||||
gas_flow()
|
||||
gas.replace_by(ngas)
|
||||
|
||||
|
||||
// Calculate the flow through the junction
|
||||
|
||||
process()
|
||||
var/delta_gt
|
||||
|
||||
if(vnode1)
|
||||
delta_gt = FLOWFRAC * ( vnode1.get_gas_val(src) - gas.tot_gas() / capmult)
|
||||
calc_delta( src, gas, ngas, vnode1, delta_gt)
|
||||
else
|
||||
leak_to_turf(1)
|
||||
|
||||
if(vnode2)
|
||||
delta_gt = FLOWFRAC * ( vnode2.get_gas_val(src) - gas.tot_gas() / capmult)
|
||||
calc_delta( src, gas, ngas, vnode2, delta_gt)
|
||||
|
||||
else
|
||||
leak_to_turf(2)
|
||||
|
||||
|
||||
// Return the gas fullness value
|
||||
|
||||
get_gas_val(from)
|
||||
return gas.tot_gas()/capmult
|
||||
|
||||
|
||||
// Return the gas reservoir
|
||||
|
||||
get_gas(from)
|
||||
return gas
|
||||
|
||||
|
||||
// If a node is not connected, leak gas to the turf location
|
||||
|
||||
proc/leak_to_turf(var/port)
|
||||
var/turf/T
|
||||
|
||||
switch(port)
|
||||
if(1)
|
||||
T = get_step(src, dir)
|
||||
if(2)
|
||||
T = get_step(src, turn(dir, 180) )
|
||||
|
||||
if(T.density)
|
||||
T = src.loc
|
||||
if(T.density)
|
||||
return
|
||||
|
||||
flow_to_turf(gas, ngas, T)
|
||||
|
||||
|
||||
@@ -0,0 +1,94 @@
|
||||
/*
|
||||
* Light_switch - Controls the lighting of an area
|
||||
* Can have multiple switches per area, they will interact correctly
|
||||
* Set the "otherarea" var to control the lighting of a remote area (non-loc)
|
||||
*/
|
||||
|
||||
|
||||
obj/machinery/light_switch
|
||||
desc = "A light switch"
|
||||
name = null
|
||||
icon = 'power.dmi'
|
||||
icon_state = "light1"
|
||||
anchored = 1.0
|
||||
var
|
||||
on = 1 // true if currently switched on
|
||||
area/area = null // holds the area object that this switch controls
|
||||
otherarea = null // By default, the switch controls the area it is located in.
|
||||
// By setting this string, the switch will control the area
|
||||
// matching the path "/area/(otherarea)"
|
||||
// this allows remote light switches located outside the area controlled (e.g. brig)
|
||||
|
||||
|
||||
// Create a new switch
|
||||
|
||||
New()
|
||||
..()
|
||||
spawn(5) // wait for world to completely load
|
||||
src.area = src.loc.loc // by default, switch contains the area it is in
|
||||
|
||||
if(otherarea) // setting this var to control a different area
|
||||
src.area = locate(text2path("/area/[otherarea]"))
|
||||
|
||||
if(!name)
|
||||
name = "light switch ([area.name])"
|
||||
|
||||
src.on = src.area.lightswitch // default on/off state is set by the area vars
|
||||
updateicon()
|
||||
|
||||
|
||||
// Update the icon state to on, off, or unpowered
|
||||
|
||||
proc/updateicon()
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "light-p"
|
||||
else
|
||||
if(on)
|
||||
icon_state = "light1"
|
||||
else
|
||||
icon_state = "light0"
|
||||
|
||||
|
||||
// Examine verb
|
||||
|
||||
examine()
|
||||
set src in oview(1)
|
||||
if(usr && !usr.stat)
|
||||
usr << "A light switch. It is [on? "on" : "off"]."
|
||||
|
||||
|
||||
// Monkey interact same as human
|
||||
|
||||
attack_paw(mob/user)
|
||||
src.attack_hand(user)
|
||||
|
||||
|
||||
// Interact, switch the switch
|
||||
|
||||
attack_hand(mob/user)
|
||||
|
||||
on = !on
|
||||
|
||||
area.lightswitch = on
|
||||
updateicon()
|
||||
|
||||
// Update all other light switches in this area to same state
|
||||
|
||||
for(var/obj/machinery/light_switch/L in area)
|
||||
L.on = on
|
||||
L.updateicon()
|
||||
|
||||
area.updateicon() // update the area icon_state to set the darkness overlay
|
||||
|
||||
|
||||
// When area power status of the lighting channel changes, update the switch status
|
||||
|
||||
power_change()
|
||||
|
||||
if(!otherarea)
|
||||
if(powered(LIGHT))
|
||||
stat &= ~NOPOWER
|
||||
else
|
||||
stat |= NOPOWER
|
||||
|
||||
updateicon()
|
||||
@@ -0,0 +1,148 @@
|
||||
/*
|
||||
* Manifold - Machine that allows three gas lines to be connected together.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
obj/machinery/manifold
|
||||
name = "manifold"
|
||||
icon = 'pipes.dmi'
|
||||
icon_state = "manifold"
|
||||
desc = "A three-port gas manifold."
|
||||
anchored = 1
|
||||
dir = 2
|
||||
p_dir = 14
|
||||
capmult = 3
|
||||
|
||||
var
|
||||
n1dir // direction of node1
|
||||
n2dir // direction of node2
|
||||
// "dir" is the direction of node3
|
||||
|
||||
obj/substance/gas/gas = null // the gas reservoir
|
||||
obj/substance/gas/ngas = null
|
||||
capacity = 6000000.0 // nominal gas capacity
|
||||
|
||||
obj/machinery/node1 = null // }
|
||||
obj/machinery/node2 = null // } the machine connected to each port
|
||||
obj/machinery/node3 = null // }
|
||||
|
||||
obj/machinery/vnode1 // }
|
||||
obj/machinery/vnode2 // } the pipeline connected to each port, if nodeX is a pipe object
|
||||
obj/machinery/vnode3 // }
|
||||
|
||||
|
||||
|
||||
// Create a new manifold. Pipe p_dir is calculated from the icon dir, so p_dir does not need to be set on map.
|
||||
|
||||
New()
|
||||
..()
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
p_dir = 13 //NORTH|EAST|WEST
|
||||
|
||||
if(SOUTH)
|
||||
p_dir = 14 //SOUTH|EAST|WEST
|
||||
|
||||
if(EAST)
|
||||
p_dir = 7 //EAST|NORTH|SOUTH
|
||||
|
||||
if(WEST)
|
||||
p_dir = 11 //WEST|NORTH|SOUTH
|
||||
|
||||
|
||||
|
||||
src.gas = new /obj/substance/gas( src )
|
||||
src.gas.maximum = src.capacity
|
||||
src.ngas = new /obj/substance/gas()
|
||||
gasflowlist += src
|
||||
|
||||
|
||||
// Find the connected machines/pipelines for each port
|
||||
|
||||
buildnodes()
|
||||
var/turf/T = src.loc
|
||||
|
||||
node3 = get_machine( level, T, dir ) // the side port
|
||||
|
||||
n1dir = turn(dir, 90)
|
||||
n2dir = turn(dir,-90)
|
||||
|
||||
node1 = get_machine( level, T , n1dir ) // the main flow dir
|
||||
|
||||
|
||||
node2 = get_machine( level, T , n2dir )
|
||||
|
||||
|
||||
if(node1) vnode1 = node1.getline()
|
||||
if(node2) vnode2 = node2.getline()
|
||||
if(node3) vnode3 = node3.getline()
|
||||
|
||||
return
|
||||
|
||||
|
||||
// Replace the gas levels with the new levels calculated in process()
|
||||
|
||||
gas_flow()
|
||||
gas.replace_by(ngas)
|
||||
|
||||
|
||||
// Calculate the gas flow to/from each port
|
||||
|
||||
process()
|
||||
var/delta_gt
|
||||
|
||||
if(vnode1)
|
||||
delta_gt = FLOWFRAC * ( vnode1.get_gas_val(src) - gas.tot_gas() / capmult)
|
||||
calc_delta( src, gas, ngas, vnode1, delta_gt)
|
||||
else
|
||||
leak_to_turf(1)
|
||||
|
||||
if(vnode2)
|
||||
delta_gt = FLOWFRAC * ( vnode2.get_gas_val(src) - gas.tot_gas() / capmult)
|
||||
calc_delta( src, gas, ngas, vnode2, delta_gt)
|
||||
else
|
||||
leak_to_turf(2)
|
||||
|
||||
if(vnode3)
|
||||
delta_gt = FLOWFRAC * ( vnode3.get_gas_val(src) - gas.tot_gas() / capmult)
|
||||
calc_delta( src, gas, ngas, vnode3, delta_gt)
|
||||
else
|
||||
leak_to_turf(3)
|
||||
|
||||
|
||||
// Return the gas fullness value
|
||||
|
||||
get_gas_val(from)
|
||||
return gas.tot_gas()/capmult
|
||||
|
||||
|
||||
// Return the gas reservoir
|
||||
|
||||
get_gas(from)
|
||||
return gas
|
||||
|
||||
|
||||
// If a node is not connected, leak the gas into the turf in that direction
|
||||
|
||||
proc/leak_to_turf(var/port)
|
||||
|
||||
var/turf/T
|
||||
|
||||
switch(port)
|
||||
if(1)
|
||||
T = get_step(src, n1dir)
|
||||
if(2)
|
||||
T = get_step(src, n2dir)
|
||||
if(3)
|
||||
T = get_step(src, dir)
|
||||
|
||||
if(T.density)
|
||||
T = src.loc
|
||||
if(T.density)
|
||||
return
|
||||
|
||||
flow_to_turf(gas, ngas, T)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,88 @@
|
||||
/*
|
||||
* Meter -- a machine that shows the flow rate of gas in a pipe on the same turf
|
||||
*
|
||||
* The meter actually reads a moving average of the flow var of the pipeline object associated with the pipe.
|
||||
* Note that the value can be negative if the flow is going through the pipe "backwards"
|
||||
*
|
||||
* TODO: Add an icon overlay showing the actual movement direction of the gas.
|
||||
*/
|
||||
|
||||
obj/machinery/meter
|
||||
name = "meter"
|
||||
icon = 'pipes.dmi'
|
||||
icon_state = "meterX"
|
||||
anchored = 1
|
||||
var
|
||||
obj/machinery/pipes/target = null // the pipe object to monitor
|
||||
average = 0 // the exponential moving average of the flow rate
|
||||
|
||||
|
||||
|
||||
// Create a new meter. Find the target pipe in the same location as the meter
|
||||
|
||||
New()
|
||||
..()
|
||||
src.target = locate(/obj/machinery/pipes, src.loc)
|
||||
average = 0
|
||||
return
|
||||
|
||||
|
||||
// Timed process.
|
||||
// Read flow rate from the pipeline object of the target pipe
|
||||
// Calculate exponentially weighted moving average of flow rate
|
||||
// Update icon state of flow rate bargraph
|
||||
|
||||
process()
|
||||
|
||||
if(!target)
|
||||
icon_state = "meterX"
|
||||
return
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "meter0"
|
||||
return
|
||||
|
||||
use_power(5)
|
||||
|
||||
average = 0.5 * average + 0.5 * target.pl.flow
|
||||
|
||||
var/val = min(18, round( 18.99 * ((abs(average) / 2500000)**0.25)) )
|
||||
icon_state = "meter[val]"
|
||||
|
||||
|
||||
// If the meter is clicked on, report the flow rate and temperature of the gas
|
||||
|
||||
Click()
|
||||
|
||||
if (get_dist(usr, src) <= 3)
|
||||
if (src.target)
|
||||
usr << text("\blue <B>Results:\nMass flow []%\nTemperature [] K</B>", round(100*abs(average)/6e6, 0.1), round(target.pl.gas.temperature,0.1))
|
||||
else
|
||||
usr << "\blue <B>Results: Connection Error!</B>"
|
||||
else
|
||||
usr << "\blue <B>You are too far away.</B>"
|
||||
return
|
||||
|
||||
// Disabled routines
|
||||
|
||||
/*
|
||||
/obj/machinery/meter/proc/pressure()
|
||||
|
||||
if(src.target && src.target.gas)
|
||||
return (average * target.gas.temperature)/100000.0
|
||||
else
|
||||
return 0
|
||||
*/
|
||||
|
||||
/*
|
||||
/obj/machinery/meter/examine()
|
||||
set src in oview(1)
|
||||
|
||||
var/t = "A gas flow meter. "
|
||||
if (src.target)
|
||||
t += text("Results:\nMass flow []%\nPressure [] kPa", round(100*average/src.target.gas.maximum, 0.1), round(pressure(), 0.1) )
|
||||
else
|
||||
t += "It is not functioning."
|
||||
|
||||
usr << t
|
||||
|
||||
*/
|
||||
@@ -0,0 +1,280 @@
|
||||
/*
|
||||
* Nuclearbomb -- A nuclear explosive
|
||||
*
|
||||
* Requires authentication disk and code to activate
|
||||
*
|
||||
* As used in "Nuclear" mode.
|
||||
*
|
||||
* TODO: Unify explosion proc with other explosions (plamsabombs, etc.)
|
||||
*
|
||||
*/
|
||||
|
||||
obj/machinery/nuclearbomb
|
||||
desc = "Uh oh."
|
||||
name = "Nuclear Fission Explosive"
|
||||
icon = 'stationobjs.dmi'
|
||||
icon_state = "nuclearbomb0"
|
||||
density = 1
|
||||
flags = FPRINT|DRIVABLE
|
||||
|
||||
var
|
||||
extended = 0 // True if bomb is deployed
|
||||
timeleft = 60.0 // Time (seconds) until explosion
|
||||
timing = 0 // True if counting down the timer
|
||||
r_code = "ADMIN" // The activation code of the nuke
|
||||
code = "" // The code typed in
|
||||
yes_code = 0 // True if typed code matches
|
||||
safety = 1 // False to enable bomb to explode
|
||||
obj/item/weapon/disk/nuclear/auth = null // The authenication disk of the nuke, or null if none inserted
|
||||
|
||||
|
||||
// Create a nuclear bomb.
|
||||
// nuke_code is a global integer randomly set between 10000 and 99999
|
||||
|
||||
New()
|
||||
|
||||
if (nuke_code)
|
||||
src.r_code = "[nuke_code]"
|
||||
..()
|
||||
|
||||
|
||||
// Timed process
|
||||
// If timing, count down the timer and explode when expires
|
||||
// Update interaction window of viewing clients
|
||||
|
||||
process()
|
||||
|
||||
if (src.timing)
|
||||
src.timeleft--
|
||||
if (src.timeleft <= 0)
|
||||
explode()
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
|
||||
|
||||
// Monkey interact same as human
|
||||
|
||||
attack_paw(mob/user)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// Human interact
|
||||
// If already deployed, show the interaction window
|
||||
// Otherwise, deploy and anchor the bomb
|
||||
|
||||
attack_hand(mob/user)
|
||||
if (src.extended) // Bomb deployed?
|
||||
user.machine = src
|
||||
|
||||
// insert auth disk here
|
||||
var/dat = {"<TT><B>Nuclear Fission Explosive</B><BR>
|
||||
Auth. Disk: <A href='?src=\ref[src];auth=1'>[(src.auth ? "++++++++++" : "----------")]</A><HR>"}
|
||||
|
||||
if (src.auth) // auth disk inserted
|
||||
if (src.yes_code) // and code is correct
|
||||
// show full control panel
|
||||
dat += {"
|
||||
<B>Status</B>: [(src.timing ? "Func/Set" : "Functional")]-[(src.safety ? "Safe" : "Engaged")]<BR>
|
||||
<B>Timer</B>: [src.timeleft]<BR>
|
||||
<BR>
|
||||
Timer: [(src.timing ? "On" : "Off")] <A href='?src=\ref[src];timer=1'>Toggle</A><BR>
|
||||
Time: <A href='?src=\ref[src];time=-10'>-</A> <A href='?src=\ref[src];time=-1'>-</A> [src.timeleft] <A href='?src=\ref[src];time=1'>+</A> <A href='?src=\ref[src];time=10'>+</A><BR>
|
||||
<BR>
|
||||
Safety: [(src.safety ? "On" : "Off")] <A href='?src=\ref[src];safety=1'>Toggle</A><BR>
|
||||
Anchor: [(src.anchored ? "Engaged" : "Off")] <A href='?src=\ref[src];anchor=1'>Toggle</A><BR>
|
||||
"}
|
||||
|
||||
else // otherwise, lock controls until code entered
|
||||
|
||||
dat += {"
|
||||
<B>Status</B>: Auth. S2-[(src.safety ? "Safe" : "Engaged")]<BR>
|
||||
<B>Timer</B>: [src.timeleft]<BR>
|
||||
<BR>\nTimer: [(src.timing ? "On" : "Off")] Toggle<BR>
|
||||
Time: - - [src.timeleft] + +<BR>
|
||||
<BR>
|
||||
Safety: [(src.safety ? "On" : "Off")] Toggle<BR>
|
||||
Anchor: [(src.anchored ? "Engaged" : "Off")] Toggle<BR>
|
||||
"}
|
||||
|
||||
else
|
||||
if (src.timing) // auth disk removed, but counting down, lock controls
|
||||
|
||||
dat += {"
|
||||
<B>Status</B>: Set-[(src.safety ? "Safe" : "Engaged")]<BR>
|
||||
<B>Timer</B>: [src.timeleft]<BR>
|
||||
<BR>
|
||||
Timer: [(src.timing ? "On" : "Off")] Toggle<BR>
|
||||
Time: - - [src.timeleft] + +<BR>
|
||||
<BR>
|
||||
Safety: [(src.safety ? "On" : "Off")] Toggle<BR>
|
||||
Anchor: [(src.anchored ? "Engaged" : "Off")] Toggle<BR>
|
||||
"}
|
||||
|
||||
else // also lock controls if not counting, no auth disk
|
||||
|
||||
dat += {"
|
||||
<B>Status</B>: Auth. S1-[(src.safety ? "Safe" : "Engaged")]<BR>
|
||||
<B>Timer</B>: [src.timeleft]<BR>
|
||||
<BR>
|
||||
Timer: [(src.timing ? "On" : "Off")] Toggle<BR>
|
||||
Time: - - [src.timeleft] + +<BR>
|
||||
<BR>
|
||||
Safety: [(src.safety ? "On" : "Off")] Toggle<BR>
|
||||
Anchor: [(src.anchored ? "Engaged" : "Off")] Toggle<BR>
|
||||
"}
|
||||
|
||||
var/message = "AUTH"
|
||||
|
||||
if (src.auth)
|
||||
message = "[src.code]"
|
||||
if (src.yes_code)
|
||||
message = "*****"
|
||||
// The keypad - enter code here
|
||||
dat += {"<HR>
|
||||
[message]<BR>
|
||||
<A href='?src=\ref[src];type=1'>1</A>-<A href='?src=\ref[src];type=2'>2</A>-<A href='?src=\ref[src];type=3'>3</A><BR>
|
||||
<A href='?src=\ref[src];type=4'>4</A>-<A href='?src=\ref[src];type=5'>5</A>-<A href='?src=\ref[src];type=6'>6</A><BR>
|
||||
<A href='?src=\ref[src];type=7'>7</A>-<A href='?src=\ref[src];type=8'>8</A>-<A href='?src=\ref[src];type=9'>9</A><BR>
|
||||
<A href='?src=\ref[src];type=R'>R</A>-<A href='?src=\ref[src];type=0'>0</A>-<A href='?src=\ref[src];type=E'>E</A><BR>
|
||||
</TT>"}
|
||||
user << browse(dat, "window=nuclearbomb;size=300x400")
|
||||
|
||||
else // Deploy and anchor the bomb.
|
||||
|
||||
src.anchored = 1
|
||||
flick("nuclearbombc", src)
|
||||
src.icon_state = "nuclearbomb1"
|
||||
src.extended = 1
|
||||
return
|
||||
|
||||
|
||||
// Handle topic links from 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 ((usr.contents.Find(src) || (get_dist(src, usr) <= 1 && istype(src.loc, /turf))))
|
||||
usr.machine = src
|
||||
|
||||
if (href_list["auth"]) // auth link - if disk already inserted, remove it
|
||||
if (src.auth)
|
||||
src.auth.loc = src.loc
|
||||
src.yes_code = 0
|
||||
src.auth = null
|
||||
else // if not inserted, check that it's in the player's hand
|
||||
var/obj/item/I = usr.equipped()
|
||||
if (istype(I, /obj/item/weapon/disk/nuclear))
|
||||
usr.drop_item()
|
||||
I.loc = src
|
||||
src.auth = I
|
||||
if (src.auth)
|
||||
if (href_list["type"]) // keypad typing
|
||||
if (href_list["type"] == "E") // enter the current code, check against nuke code
|
||||
if (src.code == src.r_code)
|
||||
src.yes_code = 1
|
||||
src.code = null
|
||||
else
|
||||
src.code = "ERROR"
|
||||
else
|
||||
if (href_list["type"] == "R") // reset code
|
||||
src.yes_code = 0
|
||||
src.code = null
|
||||
else
|
||||
src.code += "[href_list["type"]]" // otherwise, add a digit
|
||||
if (length(src.code) > 5)
|
||||
src.code = "ERROR"
|
||||
if (src.yes_code)
|
||||
if (href_list["time"])
|
||||
var/time = text2num(href_list["time"])
|
||||
src.timeleft += time
|
||||
src.timeleft = min(max(round(src.timeleft), 5), 600)
|
||||
if (href_list["timer"])
|
||||
if (src.timing == -1.0)
|
||||
return
|
||||
src.timing = !( src.timing )
|
||||
if (src.timing)
|
||||
src.icon_state = "nuclearbomb2"
|
||||
else
|
||||
src.icon_state = "nuclearbomb1"
|
||||
if (href_list["safety"])
|
||||
src.safety = !( src.safety )
|
||||
if (href_list["anchor"])
|
||||
src.anchored = !( src.anchored )
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
else
|
||||
usr << browse(null, "window=nuclearbomb")
|
||||
return
|
||||
|
||||
|
||||
// On explosion, only (potentially) delete nuke if not about to explode
|
||||
|
||||
ex_act()
|
||||
if (src.timing == -1.0)
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
|
||||
|
||||
// Blob attack same as explosion
|
||||
|
||||
blob_act()
|
||||
|
||||
if (src.timing == -1.0)
|
||||
return
|
||||
else
|
||||
return ..()
|
||||
|
||||
|
||||
// Explode the nuke, destroying almost everything around
|
||||
// TODO: Unify this explosion proc with others
|
||||
|
||||
proc/explode()
|
||||
|
||||
if (src.safety)
|
||||
src.timing = 0
|
||||
return
|
||||
src.timing = -1.0
|
||||
src.yes_code = 0
|
||||
src.icon_state = "nuclearbomb3"
|
||||
sleep(20) // 2 second delay
|
||||
var/turf/T = src.loc
|
||||
while(!( istype(T, /turf) ))
|
||||
T = T.loc
|
||||
var/min = 50
|
||||
var/med = 250
|
||||
var/max = 500
|
||||
var/sw = locate(1, 1, T.z) // explosion encompasses whole of z-level
|
||||
var/ne = locate(world.maxx, world.maxy, T.z)
|
||||
|
||||
defer_powernet_rebuild = 1 // Prevent powenet being rebuilt when cable objects deleted
|
||||
|
||||
for(var/turf/U in block(sw, ne))
|
||||
var/zone = 4
|
||||
if ((U.y <= T.y + max && U.y >= T.y - max && U.x <= T.x + max && U.x >= T.x - max))
|
||||
zone = 3
|
||||
if ((U.y <= T.y + med && U.y >= T.y - med && U.x <= T.x + med && U.x >= T.x - med))
|
||||
zone = 2
|
||||
if ((U.y <= T.y + min && U.y >= T.y - min && U.x <= T.x + min && U.x >= T.x - min))
|
||||
zone = 1
|
||||
for(var/atom/A in U)
|
||||
A.ex_act(zone)
|
||||
|
||||
U.ex_act(zone)
|
||||
U.buildlinks()
|
||||
|
||||
|
||||
defer_powernet_rebuild = 0 // Renable powernet rebuilt
|
||||
makepowernets() // And do so
|
||||
ticker.nuclear(src.z) // inform gameticker that nuke exploded
|
||||
del(src)
|
||||
@@ -0,0 +1,183 @@
|
||||
/*
|
||||
* Pipeline -- The pipeline machine responsible for gas flow through pipes.
|
||||
*
|
||||
* Pipelines are logical, not physical objects, and do not exist at a location in the world.
|
||||
* They are collections of /obj/machinery/pipes objects that form an unbroken connection.
|
||||
*
|
||||
* By consolidating the gas content of a series of pipes into one pipeline, the number of gas flow calculations is reduced.
|
||||
* This also allows faster flow of gas through long lines.
|
||||
* For instance, if each pipe segment performed as an independent object, it would take at least 10 seconds for any gas
|
||||
* to flow through a 10-segment pipe,
|
||||
*/
|
||||
|
||||
|
||||
obj/machinery/pipeline // logical pipeline consisting of multiple /obj/machinery/pipes
|
||||
|
||||
name = "pipeline"
|
||||
invisibility = 101 // since pipelines do not exist as tangible objects, they are set invisible
|
||||
capmult = 0 // actual capmult will be the number of pipe segments + 1
|
||||
|
||||
var
|
||||
list/nodes = list() // the list of /obj/machinery/pipes objects in this pipeline
|
||||
// nodes will be sorted during creation so that adjacent pipes are adjacent in the list
|
||||
numnodes = 0 // the number of nodes
|
||||
|
||||
obj/substance/gas/gas = null // the gas reservoir for this pipeline
|
||||
obj/substance/gas/ngas = null // the new calculated gas levels
|
||||
|
||||
obj/machinery/vnode1 // the machine connected to the start of this pipeline (or null if none)
|
||||
obj/machinery/vnode2 // the machine connected to the end of this pipeline (or null if none)
|
||||
|
||||
flow = 0 // flow rate through this pipe, calculated from the gas flowing into or out of each end.
|
||||
// can be negative if flowing backwards.
|
||||
|
||||
|
||||
// Create a new pipeline. Create gas reservoir
|
||||
// Register self with gasflowlist since this object has a gas_flow() proc.
|
||||
|
||||
New()
|
||||
..()
|
||||
|
||||
gas = new/obj/substance/gas(src)
|
||||
ngas = new/obj/substance/gas()
|
||||
|
||||
gasflowlist += src
|
||||
|
||||
|
||||
// Sets the vnode1 & vnode2 values to the machines connected at each end of the pipe
|
||||
// Also orientates the pipes in the node list so that for each pipe, node1 points to previous entry, and node2 points to next
|
||||
|
||||
proc/setterm()
|
||||
//first make sure pipes are oriented correctly
|
||||
|
||||
var/obj/machinery/M = null
|
||||
|
||||
for(var/obj/machinery/pipes/P in nodes)
|
||||
if(!M) // special case for 1st pipe
|
||||
if(P.node1 && P.node1.ispipe())
|
||||
|
||||
P.flip() // flip if node1 is a pipe
|
||||
|
||||
else
|
||||
if(P.node1 != M) //other cases, flip if node1 doesn't point to previous node
|
||||
P.flip() // (including if it is null)
|
||||
|
||||
P.updateicon()
|
||||
|
||||
M = P // the previous node
|
||||
|
||||
|
||||
|
||||
// pipes are now ordered so that n1/n2 is in same order as pipeline list
|
||||
|
||||
var/obj/machinery/pipes/P = nodes[1] // 1st node in list
|
||||
vnode1 = P.node1 // n1 points to 1st machine
|
||||
P = nodes[nodes.len] // last node in list
|
||||
vnode2 = P.node2 // n2 points to last machine
|
||||
|
||||
|
||||
// confirm node connections are valid for the machines at each end of the pipeline
|
||||
// not needed in initial makepipelines, but may be if new pipeline is constructed
|
||||
|
||||
if(vnode1)
|
||||
vnode1.buildnodes()
|
||||
if(vnode2)
|
||||
vnode2.buildnodes()
|
||||
|
||||
return
|
||||
|
||||
|
||||
// Return the gas fullness value
|
||||
// For pipelines, capmult is set to (number of pipe segements)+1
|
||||
// Thus the longer the pipeline, the bigger the gas reservoir appears
|
||||
|
||||
get_gas_val(from)
|
||||
return gas.tot_gas()/capmult
|
||||
|
||||
|
||||
// Return the gas reservoir for the pipeline
|
||||
|
||||
get_gas(from)
|
||||
return gas
|
||||
|
||||
|
||||
// Update the current gas levels to that calculated in process()
|
||||
|
||||
gas_flow()
|
||||
gas.replace_by(ngas)
|
||||
|
||||
|
||||
// Timed process for the pipeline.
|
||||
// First do heat-exchange for every node in this pipeline
|
||||
// The do standard gas flow from each end of the pipeline.
|
||||
// Also update "flow" variable to show rate of flow through the complete pipeline.
|
||||
|
||||
process()
|
||||
|
||||
if(!numnodes) // check to see if there are any nodes in the pipeline
|
||||
return // if none, skip it. Used because some PLs may get zero lengthed during pipe laying
|
||||
|
||||
// heat exchange for whole pipeline
|
||||
|
||||
var/gtemp = ngas.temperature // cached current temperature for heat exch calc
|
||||
var/tot_node = ngas.tot_gas() / numnodes // fraction of gas in this node
|
||||
|
||||
|
||||
if(tot_node>0.1) // no pipe contents, don't heat
|
||||
for(var/obj/machinery/pipes/P in src.nodes) // for each segment of pipe
|
||||
P.heat_exchange(ngas, tot_node, numnodes, gtemp) // exchange heat with its turf
|
||||
|
||||
|
||||
// now do standard gas flow proc
|
||||
|
||||
var/delta_gt
|
||||
|
||||
if(vnode1)
|
||||
delta_gt = FLOWFRAC * ( vnode1.get_gas_val(src) - gas.tot_gas() / capmult)
|
||||
calc_delta( src, gas, ngas, vnode1, delta_gt)
|
||||
|
||||
flow = delta_gt
|
||||
else
|
||||
leak_to_turf(1)
|
||||
|
||||
if(vnode2)
|
||||
delta_gt = FLOWFRAC * ( vnode2.get_gas_val(src) - gas.tot_gas() / capmult)
|
||||
calc_delta( src, gas, ngas, vnode2, delta_gt)
|
||||
|
||||
flow -= delta_gt
|
||||
else
|
||||
leak_to_turf(2)
|
||||
|
||||
|
||||
// Depending on which end is leaking, vent gas contents into turf
|
||||
|
||||
// Note: added some temporary error-checking to fix runtime errors when blob destroys pipes
|
||||
// full pipe damage system will remove the need for this
|
||||
|
||||
proc/leak_to_turf(var/port)
|
||||
|
||||
var/turf/T
|
||||
var/obj/machinery/pipes/P
|
||||
var/list/ndirs
|
||||
|
||||
switch(port)
|
||||
if(1)
|
||||
P = nodes[1] // 1st node in list
|
||||
|
||||
if(P)
|
||||
ndirs = P.get_node_dirs()
|
||||
T = get_step(P, ndirs[1])
|
||||
|
||||
|
||||
if(2)
|
||||
P = nodes[nodes.len] // last node in list
|
||||
|
||||
if(P)
|
||||
ndirs = P.get_node_dirs()
|
||||
T = get_step(P, ndirs[2])
|
||||
|
||||
if(!T || T.density)
|
||||
return
|
||||
|
||||
flow_to_turf(gas, ngas, T)
|
||||
|
||||
@@ -0,0 +1,391 @@
|
||||
/*
|
||||
* Pipes -- the basic object in the pipe network
|
||||
*
|
||||
* Pipes do not directly contain gas, but unbroken chains of pipes are assembled into /obj/machinery/pipeline objects
|
||||
* Pipelines contain a single gas reservoir that encompass all the gas that would be each individual pipe.
|
||||
*
|
||||
* TODO: Complete routines for pipe disassembly, damage, and exploding under pressure.
|
||||
* TODO: Finalize method of showing broken pipes & pipe ends.
|
||||
* TODO: Implement some method of capacity regulation
|
||||
*/
|
||||
|
||||
obj/machinery/pipes
|
||||
name = "pipes"
|
||||
icon = 'reg_pipe.dmi'
|
||||
icon_state = "12"
|
||||
anchored = 1
|
||||
|
||||
/* var/p_dir - inherited from /obj/machinery, is a bitfield of directions of pipe connections from this one */
|
||||
|
||||
var
|
||||
capacity = 6000000.0 // nominal gas capacity of each pipe segment - not actually used
|
||||
obj/machinery/node1 = null // the 1st connected node
|
||||
obj/machinery/node2 = null // the 2nd connected node
|
||||
termination = 0 // >0 if this is an end pipe in a pipeline
|
||||
insulation = NORMPIPERATE // lower insulation value means pipe temperature is exchanged with turf at a faster rate
|
||||
|
||||
obj/machinery/pipeline/pl // the pipeline object which contains this pipe
|
||||
health = 10 // the health of the pipe (not yet implemented)
|
||||
|
||||
|
||||
// Create a new pipe, and update the p_dir according to the icon_state.
|
||||
|
||||
New()
|
||||
..()
|
||||
update()
|
||||
|
||||
|
||||
// Update the p_dir bitfield according to the current icon state
|
||||
// Icons_states for each pipe state match the correct p_dir value, so pipes placed on the map
|
||||
// do not need the p_dir state set at compile time, since it is calculated at spawn.
|
||||
|
||||
proc/update()
|
||||
p_dir = text2num(icon_state)
|
||||
|
||||
|
||||
// Return true as this is a pipe. All other machines return false.
|
||||
|
||||
ispipe()
|
||||
return 1
|
||||
|
||||
|
||||
// Find the machines or pipes which connect to this one
|
||||
// Argument is the current pipeline object being built
|
||||
// If another pipe segment is found, call this routine for that pipe to propagate the connection
|
||||
|
||||
buildnodes(var/obj/machinery/pipeline/line)
|
||||
|
||||
// First find the machines/pipes that connect to this pipe
|
||||
|
||||
var/list/dirs = get_dirs()
|
||||
|
||||
node1 = get_machine(level, src.loc, dirs[1])
|
||||
node2 = get_machine(level, src.loc, dirs[2])
|
||||
|
||||
if(pl) // If the pipeline is already set, there is no need to propagate anymore
|
||||
return
|
||||
|
||||
updateicon() // Update the icon_state according to p_dir and other states
|
||||
|
||||
pl = line // Set the pipeline of the pipe segment
|
||||
|
||||
termination = 0
|
||||
|
||||
if(node1 && node1.ispipe() ) // If node1 is a pipe, propagate this pipeline object to it
|
||||
|
||||
node1.buildnodes(line)
|
||||
else
|
||||
termination++ // Otherwise we are at an end of the pipeline
|
||||
|
||||
if(node2 && node2.ispipe() ) // If node2 is a pipe, propagate this pipeline object to it
|
||||
node2.buildnodes(line)
|
||||
else
|
||||
termination++ // Otherwise we are at the end of the pipeline
|
||||
|
||||
|
||||
|
||||
// Flip the node order of a pipe
|
||||
|
||||
proc/flip()
|
||||
|
||||
var/obj/machinery/tempnode = node1
|
||||
node1 = node2
|
||||
node2 = tempnode
|
||||
return
|
||||
|
||||
|
||||
// Return the next pipe object in the node chain
|
||||
// Argument "from" is the node we are approaching from; if null, returns the first actual pipe found
|
||||
|
||||
next(var/obj/machinery/from)
|
||||
|
||||
if(from == null) // if from null, then return the next actual pipe
|
||||
if(node1 && node1.ispipe() )
|
||||
return node1
|
||||
if(node2 && node2.ispipe() )
|
||||
return node2
|
||||
return null // else return null if no real pipe connected
|
||||
|
||||
else if(from == node1) // otherwise, return the node opposite the incoming one
|
||||
return node2
|
||||
else
|
||||
return node1
|
||||
|
||||
|
||||
// Returns the pipeline object that this pipe is in
|
||||
|
||||
getline()
|
||||
return pl
|
||||
|
||||
|
||||
// Finds the actual directions corresponding to the p_dir bitfield
|
||||
// Returns as a list (dir1, dir2, p_dir)
|
||||
// Note this direction order is not guaranteed to be the same order as node1 & node2
|
||||
// For that, use get_node_dirs()
|
||||
|
||||
proc/get_dirs()
|
||||
var/b1
|
||||
var/b2
|
||||
|
||||
for(var/d in cardinal)
|
||||
if(p_dir & d)
|
||||
if(!b1)
|
||||
b1 = d
|
||||
else if(!b2)
|
||||
b2 = d
|
||||
|
||||
return list(b1, b2, p_dir)
|
||||
|
||||
|
||||
// Returns a list of the directions of a pipe, matched to nodes (if present)
|
||||
// Note unlike get_dirs(), 1st direction on list is always the direction of node1, 2nd is node2
|
||||
|
||||
proc/get_node_dirs()
|
||||
var/list/dirs = get_dirs()
|
||||
|
||||
|
||||
if(!node1 && !node2) // no nodes - just return the standard dirs
|
||||
return dirs // note extra p_dir on end of list is unimportant
|
||||
else
|
||||
if(node1)
|
||||
var/d1 = get_dir(src, node1) // find the direction of node1
|
||||
if(d1==dirs[1]) // if it matches
|
||||
return dirs // then dirs list is correct
|
||||
else
|
||||
return list(dirs[2], dirs[1]) // otherwise return the list swapped
|
||||
|
||||
else // node2 must be valid
|
||||
var/d2 = get_dir(src, node2) // direction of node2
|
||||
if(d2==dirs[2]) // matches
|
||||
return dirs // dirs list is correct
|
||||
else
|
||||
return list(dirs[2], dirs[1]) // otherwise swap order
|
||||
|
||||
|
||||
// Update the icon_state and overlays
|
||||
// Depends on pipe level and visibility, broken status, and whether this is an unterminated end of a pipe
|
||||
|
||||
proc/updateicon()
|
||||
|
||||
var/turf/T = src.loc
|
||||
|
||||
var/is = "[p_dir]"
|
||||
|
||||
if(stat & BROKEN)
|
||||
is += "-b"
|
||||
|
||||
// Set invisibility status depending on whether this pipe is below floor level
|
||||
// Also sets a faded (alpha blended) icon_state for the pipe so it can be shown with a T-scanner
|
||||
|
||||
if ((src.level == 1 && isturf(src.loc) && T.intact))
|
||||
src.invisibility = 101
|
||||
is += "-f"
|
||||
|
||||
else
|
||||
src.invisibility = null
|
||||
|
||||
src.icon_state = is
|
||||
|
||||
// If either node is null, this is an unterminated pipe
|
||||
// Show special overlays to indicate this
|
||||
|
||||
var/list/dirs = get_node_dirs()
|
||||
|
||||
overlays = null
|
||||
if(!node1 && !node2) // neither end of pipe is connected
|
||||
overlays += image('pipes.dmi', "discon", FLY_LAYER, dirs[1])
|
||||
overlays += image('pipes.dmi', "discon", FLY_LAYER, dirs[2])
|
||||
|
||||
else if(!node1) // node1 is not connected
|
||||
overlays += image('pipes.dmi', "discon", FLY_LAYER, dirs[1])
|
||||
|
||||
else if(!node2) // node2 is not connected
|
||||
overlays += image('pipes.dmi', "discon", FLY_LAYER, dirs[2])
|
||||
|
||||
return
|
||||
|
||||
|
||||
// Called when a pipe is revealed or hidden when a floor tile is removed, etc.
|
||||
// Just call updateicon(), since all is handled there already
|
||||
|
||||
hide(var/i)
|
||||
updateicon()
|
||||
|
||||
|
||||
|
||||
// Exchange heat between a pipe and the turf it is on
|
||||
// Called by /obj/machinery/pipeline/process()
|
||||
//
|
||||
|
||||
proc/heat_exchange(var/obj/substance/gas/gas, var/tot_node, var/numnodes, var/temp)
|
||||
|
||||
var/turf/T = src.loc // turf location of pipe
|
||||
if(T.density) return
|
||||
|
||||
if( level != 1) // no heat exchange for under-floor pipes
|
||||
if(istype(T,/turf/space)) // heat exchange less efficient in space (no conduction)
|
||||
gas.temperature += ( T.temp - temp) / (3.0 * insulation * numnodes)
|
||||
else
|
||||
|
||||
var/delta_T = (T.temp - temp) / (insulation) // normal turf
|
||||
|
||||
gas.temperature += delta_T / numnodes // heat the pipe due to turf temperature
|
||||
|
||||
var/tot_turf = max(1, T.tot_gas())
|
||||
T.temp -= delta_T*min(10,tot_node/tot_turf) // also heat the turf due to pipe temp
|
||||
T.res_vars() // ensure turf tmp vars are updated
|
||||
|
||||
else // if level 1 but in space, perform cooling anyway - exposed pipes
|
||||
if(istype(T,/turf/space))
|
||||
gas.temperature += ( T.temp - temp) / (3.0 * insulation * numnodes)
|
||||
|
||||
|
||||
|
||||
|
||||
// Routines to allow cutting and damage of pipes
|
||||
// Not yet implemented
|
||||
|
||||
/*
|
||||
attackby(obj/item/weapon/W, mob/user)
|
||||
|
||||
if (istype(W, /obj/item/weapon/weldingtool))
|
||||
var/obj/item/weapon/weldingtool/WT = W
|
||||
if(WT.welding && WT.weldfuel > 3)
|
||||
WT.weldfuel -=3
|
||||
|
||||
user << "\blue Cutting the pipe. Stand still as this takes some time."
|
||||
var/turf/T = user.loc
|
||||
sleep(50)
|
||||
|
||||
if ((user.loc == T && user.equipped() == W))
|
||||
|
||||
// make pipe fitting
|
||||
sleep(1)
|
||||
|
||||
else
|
||||
var/aforce = W.force
|
||||
|
||||
src.health = max(0, src.health - aforce)
|
||||
|
||||
healthcheck()
|
||||
|
||||
return
|
||||
|
||||
proc/healthcheck()
|
||||
//if(health<1)
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* Heat_exch - Heat-exchange pipe subtype. Same as a standard pipe, but uses different icon, has lower insulation value
|
||||
* Also uses h_dir for connection direction bitfield instead of p_dir
|
||||
*/
|
||||
|
||||
heat_exch
|
||||
icon = 'heat_pipe.dmi'
|
||||
name = "heat exchange pipe"
|
||||
desc = "A bundle of small pipes designed for maximum heat transfer."
|
||||
insulation = HEATPIPERATE
|
||||
|
||||
/* h_dir - inherited from /obj/machinery */
|
||||
|
||||
|
||||
// Update h_dir from the icon state
|
||||
|
||||
update()
|
||||
h_dir = text2num(icon_state)
|
||||
|
||||
|
||||
// Update icon_state and overlays depending in h_dir connections and whether nodes are present
|
||||
|
||||
updateicon()
|
||||
|
||||
var/list/dirs = get_node_dirs()
|
||||
|
||||
var/is = "[h_dir]"
|
||||
|
||||
if(stat & BROKEN)
|
||||
is += "-b"
|
||||
|
||||
src.icon_state = is
|
||||
|
||||
overlays = null
|
||||
|
||||
if(!node1 && !node2)
|
||||
overlays += image('pipes.dmi', "discon-he", FLY_LAYER, dirs[1])
|
||||
overlays += image('pipes.dmi', "discon-he", FLY_LAYER, dirs[2])
|
||||
else if(!node1)
|
||||
overlays += image('pipes.dmi', "discon-he", FLY_LAYER, dirs[1])
|
||||
else if(!node2)
|
||||
overlays += image('pipes.dmi', "discon-he", FLY_LAYER, dirs[2])
|
||||
return
|
||||
|
||||
|
||||
// Return list of directions corresponding to h_dir bitflags
|
||||
|
||||
get_dirs()
|
||||
var/b1
|
||||
var/b2
|
||||
|
||||
for(var/d in cardinal)
|
||||
if(h_dir & d)
|
||||
if(!b1)
|
||||
b1 = d
|
||||
else if(!b2)
|
||||
b2 = d
|
||||
|
||||
return list(b1, b2, h_dir)
|
||||
|
||||
|
||||
// Find the nodes that connect to this pipe
|
||||
// If they are pipes themselves, propagate the set pipeline object to them
|
||||
|
||||
buildnodes(var/obj/machinery/pipeline/line)
|
||||
|
||||
src.level = 2 // h/e pipe cannot be put underfloor
|
||||
|
||||
var/list/dirs = get_dirs()
|
||||
|
||||
node1 = get_he_machine(level, src.loc, dirs[1])
|
||||
node2 = get_he_machine(level, src.loc, dirs[2])
|
||||
|
||||
if(pl)
|
||||
return
|
||||
|
||||
updateicon()
|
||||
|
||||
pl = line
|
||||
|
||||
termination = 0
|
||||
|
||||
if(node1 && node1.ispipe() )
|
||||
|
||||
node1.buildnodes(line)
|
||||
else
|
||||
termination++
|
||||
|
||||
if(node2 && node2.ispipe() )
|
||||
node2.buildnodes(line)
|
||||
else
|
||||
termination++
|
||||
|
||||
|
||||
// Flexpipe sub-type. Identical to standard pipe except for appearance, since capacity differences are not implemented
|
||||
// Currently only used between freezer/cryocell
|
||||
|
||||
flexipipe
|
||||
desc = "Flexible hose-like piping."
|
||||
name = "flexipipe"
|
||||
icon = 'wire.dmi'
|
||||
capacity = 10.0
|
||||
p_dir = 12.0
|
||||
|
||||
|
||||
// High-capacity pipe subtype. Not implemented.
|
||||
|
||||
high_capacity
|
||||
desc = "A large bore pipe with high capacity."
|
||||
name = "high capacity"
|
||||
icon = 'hi_pipe.dmi'
|
||||
density = 1
|
||||
capacity = 1.8E7
|
||||
@@ -0,0 +1,201 @@
|
||||
/*
|
||||
* Pod -- escape pod.
|
||||
*
|
||||
* Pilotable object that can carry people and other objects
|
||||
*
|
||||
* TODO: Work out whats going on at low speeds <=10 in process()
|
||||
* TODO: Limit the capcity of the pod in some way - current carrying capacity is infinite
|
||||
* Could use a simple count or based on item weight, w_class, etc.
|
||||
*/
|
||||
|
||||
obj/machinery/pod
|
||||
name = "Escape Pod"
|
||||
icon = 'escapepod.dmi'
|
||||
icon_state = "pod"
|
||||
density = 1
|
||||
flags = FPRINT|DRIVABLE
|
||||
anchored = 1
|
||||
|
||||
var
|
||||
id = 1.0 // Not used
|
||||
speed = 10.0 // The current speed, in tiles per second, roughly
|
||||
capacity = null // Not used
|
||||
|
||||
|
||||
// Timed process
|
||||
// Move the pod depending on its speed and direction
|
||||
|
||||
process()
|
||||
if (src.speed)
|
||||
if (src.speed <= 10) // at low speed
|
||||
var/t1 = 10 - src.speed // very odd - step (with delay) an inverse number of times?
|
||||
//var t1 = speed // consider replacing with this - much more controllable! - Hobnob
|
||||
while(t1 > 0)
|
||||
step(src, src.dir)
|
||||
sleep(1)
|
||||
t1--
|
||||
else // at high speed
|
||||
var/t1 = round(src.speed / 5) // step speed/5 times per process
|
||||
while(t1 > 0)
|
||||
step(src, src.dir)
|
||||
t1--
|
||||
|
||||
|
||||
// Called when pod bumps into something
|
||||
// Set the speed to zero
|
||||
|
||||
Bump(var/atom/A)
|
||||
spawn( 0 )
|
||||
..()
|
||||
src.speed = 0
|
||||
|
||||
|
||||
// Called when client attempts to move, and is inside a pod
|
||||
// direction is the direction key the client used
|
||||
|
||||
relaymove(mob/user, direction)
|
||||
|
||||
if (user.stat)
|
||||
return
|
||||
if ((user in src)) // make sure player is inside this pod
|
||||
|
||||
if (direction & 1) // North pressed
|
||||
src.speed = max(src.speed - 1, 1) // slow down to minimum speed (1)
|
||||
|
||||
else if (direction & 2) // South pressed
|
||||
src.speed++ // Increase speed up to maximum (10)
|
||||
if (src.speed > 10)
|
||||
src.speed = 10
|
||||
if (direction & 4) // East pressed
|
||||
src.dir = turn(src.dir, -90.0) // Turn clockwise
|
||||
|
||||
else if (direction & 8) // West pressed
|
||||
src.dir = turn(src.dir, 90) // Turn anticlockwise
|
||||
|
||||
|
||||
|
||||
// Pod Verbs
|
||||
|
||||
|
||||
// Eject from pod - place player behind pod and restore view
|
||||
|
||||
verb/eject()
|
||||
set src = usr.loc
|
||||
|
||||
if (usr.stat)
|
||||
return
|
||||
var/mob/M = usr
|
||||
M.loc = src.loc
|
||||
if (M.client)
|
||||
M.client.eye = M.client.mob
|
||||
M.client.perspective = MOB_PERSPECTIVE
|
||||
step(M, turn(src.dir, 180))
|
||||
|
||||
|
||||
// Board the pod - place player inside the pod and set the view to follow the pod
|
||||
|
||||
verb/board()
|
||||
set src in oview(1)
|
||||
|
||||
if (usr.stat)
|
||||
return
|
||||
var/mob/M = usr
|
||||
if (M.client)
|
||||
M.client.perspective = EYE_PERSPECTIVE
|
||||
M.client.eye = src
|
||||
M.loc = src
|
||||
return
|
||||
|
||||
|
||||
// Load pod - whatever the player is pulling gets loaded into the pod (including other players)
|
||||
|
||||
verb/load()
|
||||
set src in oview(1)
|
||||
|
||||
if (usr.stat)
|
||||
return
|
||||
if (( ( istype(usr, /mob/human) ) && (!( ticker ) || (ticker && ticker.mode != "monkey"))))
|
||||
var/mob/human/H = usr
|
||||
|
||||
if ((H.pulling && !( H.pulling.anchored )))
|
||||
|
||||
H.pulling.loc = src
|
||||
|
||||
if (ismob(H.pulling))
|
||||
var/mob/M = H.pulling
|
||||
if (M.client)
|
||||
M.client.perspective = EYE_PERSPECTIVE
|
||||
M.client.eye = src
|
||||
for(var/mob/O in viewers(src, null))
|
||||
if ((O.client && !( O.blinded )))
|
||||
O << text("\blue <B> [] loads [] into []!</B>", H, H.pulling, src)
|
||||
H.pulling = null
|
||||
return
|
||||
|
||||
|
||||
// Unload a pod - remove an item or mob from the pod
|
||||
// If a client mob, restore their view settings
|
||||
|
||||
verb/unload(var/atom/movable/A in src.contents)
|
||||
set src in oview(1)
|
||||
|
||||
if (usr.stat)
|
||||
return
|
||||
if (istype(A, /atom/movable))
|
||||
A.loc = src.loc
|
||||
for(var/mob/O in viewers(src, null))
|
||||
if ((O.client && !( O.blinded )))
|
||||
O << text("\blue <B> [] unloads [] from []!</B>", usr, A, src)
|
||||
//Foreach goto(54)
|
||||
if (ismob(A))
|
||||
var/mob/M = A
|
||||
if (M.client)
|
||||
M.client.perspective = MOB_PERSPECTIVE
|
||||
M.client.eye = M
|
||||
step(A, turn(src.dir, 180))
|
||||
return
|
||||
|
||||
|
||||
// Damage procs
|
||||
|
||||
// Hit by meteor - eject/unload everything from the pod
|
||||
|
||||
meteorhit(var/obj/O)
|
||||
|
||||
if (O.icon_state == "flaming")
|
||||
for(var/obj/item/I in src)
|
||||
I.loc = src.loc
|
||||
|
||||
for(var/mob/M in src)
|
||||
M.loc = src.loc
|
||||
if (M.client)
|
||||
M.client.eye = M.client.mob
|
||||
M.client.perspective = MOB_PERSPECTIVE
|
||||
|
||||
del(src)
|
||||
|
||||
|
||||
// In explosion - eject everything and destroy pod
|
||||
|
||||
ex_act(severity)
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
for(var/atom/movable/A in src)
|
||||
A.loc = src.loc
|
||||
A.ex_act(severity)
|
||||
del(src)
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
for(var/atom/movable/A in src)
|
||||
A.loc = src.loc
|
||||
A.ex_act(severity)
|
||||
del(src)
|
||||
|
||||
|
||||
// Blob attack - eject everything and destroy pod
|
||||
|
||||
blob_act()
|
||||
|
||||
for(var/atom/movable/A in src)
|
||||
A.loc = src.loc
|
||||
del(src)
|
||||
@@ -0,0 +1,53 @@
|
||||
/**
|
||||
* Recharger -- A recharger is a piece of Machinery that re-supplys tazers and lazers.
|
||||
*
|
||||
* TODO: Need seriously improved documentation on this object. Most of the procs and
|
||||
* variables seem to live elsewhere, need a project decision on how these cases
|
||||
* get documented and referenced.
|
||||
*/
|
||||
obj/machinery/recharger
|
||||
anchored = 1.0
|
||||
icon = 'stationobjs.dmi'
|
||||
icon_state = "recharger0"
|
||||
name = "recharger"
|
||||
|
||||
var
|
||||
obj/item/weapon/gun/energy/charging = null // the weapon being charged, or null if none
|
||||
|
||||
// attacking with a gun inserts the gun into the charger
|
||||
|
||||
attackby(obj/item/weapon/G, mob/user)
|
||||
if (src.charging)
|
||||
return
|
||||
if (istype(G, /obj/item/weapon/gun/energy))
|
||||
user.drop_item()
|
||||
G.loc = src
|
||||
src.charging = G
|
||||
|
||||
// hand attack removes the gun from the charger (and leaves it on the same turf)
|
||||
|
||||
attack_hand(mob/user)
|
||||
src.add_fingerprint(user)
|
||||
if (src.charging)
|
||||
src.charging.update_icon()
|
||||
src.charging.loc = src.loc
|
||||
src.charging = null
|
||||
|
||||
// monkey attack same as human if in monkey mode
|
||||
|
||||
attack_paw(mob/user)
|
||||
if ((ticker && ticker.mode == "monkey"))
|
||||
return src.attack_hand(user)
|
||||
|
||||
// if a gun is inserted, recharge once per second until fully charged
|
||||
|
||||
process()
|
||||
if (src.charging && ! (stat & NOPOWER) )
|
||||
if (src.charging.charges < 10)
|
||||
src.charging.charges++
|
||||
src.icon_state = "recharger1"
|
||||
use_power(250)
|
||||
else
|
||||
src.icon_state = "recharger2"
|
||||
else
|
||||
src.icon_state = "recharger0"
|
||||
@@ -0,0 +1,198 @@
|
||||
/*
|
||||
* Recon -- reconaissance pod
|
||||
*
|
||||
* Very similar to escape pods, except can carry only 1 person
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
obj/machinery/recon
|
||||
name = "1-Person Reconaissance Pod"
|
||||
icon = 'escapepod.dmi'
|
||||
icon_state = "recon"
|
||||
density = 1
|
||||
flags = FPRINT|DRIVABLE
|
||||
anchored = 1
|
||||
var
|
||||
speed = 1 // the current speed, turfs/second
|
||||
|
||||
|
||||
// Timed process
|
||||
// Move according to current speed and direction
|
||||
|
||||
process()
|
||||
if (src.speed)
|
||||
if (src.speed <= 10)
|
||||
var/t1 = 10 - src.speed // See note for pod/process()
|
||||
// var/t1 = src.speed
|
||||
while(t1 > 0)
|
||||
step(src, src.dir)
|
||||
sleep(1)
|
||||
t1--
|
||||
else
|
||||
var/t1 = round(src.speed / 5)
|
||||
while(t1 > 0)
|
||||
step(src, src.dir)
|
||||
t1--
|
||||
|
||||
|
||||
// Called when we bump into a dense object
|
||||
// Set speed to zero
|
||||
|
||||
Bump()
|
||||
spawn( 0 )
|
||||
..()
|
||||
src.speed = 0
|
||||
|
||||
|
||||
// Called by client/Move() when player tries to move while inside a recon
|
||||
// direction is the key pressed
|
||||
|
||||
relaymove(mob/user, direction)
|
||||
if (user.stat)
|
||||
return
|
||||
|
||||
if ((user in src))
|
||||
if (direction & 1) // North
|
||||
src.speed = max(src.speed - 1, 1) // Slow down
|
||||
|
||||
else if (direction & 2) // South
|
||||
src.speed++ // Speed up
|
||||
|
||||
if (direction & 4) // East
|
||||
src.dir = turn(src.dir, -90.0) // Turn clockwise
|
||||
|
||||
else if (direction & 8) // West
|
||||
src.dir = turn(src.dir, 90) // Turn anticlockwise
|
||||
|
||||
if (direction & 16) // Centre
|
||||
src.speed = 30 // Speed boost
|
||||
else
|
||||
src.speed = min(src.speed, 10) // otherwise max speed is 10 turfs/second
|
||||
|
||||
|
||||
// Recon verbs
|
||||
|
||||
|
||||
// Eject from the recon, reset view to player
|
||||
|
||||
verb/eject()
|
||||
set src = usr.loc
|
||||
|
||||
if (usr.stat)
|
||||
return
|
||||
var/mob/M = usr
|
||||
M.loc = src.loc
|
||||
if (M.client)
|
||||
M.client.eye = M.client.mob
|
||||
M.client.perspective = MOB_PERSPECTIVE
|
||||
|
||||
|
||||
// Board the recon, set view to follow the object
|
||||
|
||||
verb/board()
|
||||
set src in oview(1)
|
||||
|
||||
if (usr.stat)
|
||||
return
|
||||
if (locate(/mob, src))
|
||||
usr << "There is no room! You can only fit one person."
|
||||
return
|
||||
var/mob/M = usr
|
||||
if (M.client)
|
||||
M.client.perspective = EYE_PERSPECTIVE
|
||||
M.client.eye = src
|
||||
M.loc = src
|
||||
|
||||
|
||||
// Load the recon with the pulled object
|
||||
// Note recons can carry only items, unlike escape pobs which can carry any movable object
|
||||
|
||||
verb/load()
|
||||
set src in oview(1)
|
||||
|
||||
if (usr.stat)
|
||||
return
|
||||
if ((( istype(usr, /mob/human) ) && (!( ticker ) || (ticker && ticker.mode != "monkey"))))
|
||||
var/mob/human/H = usr
|
||||
if ((H.pulling && !( H.pulling.anchored )))
|
||||
if (!( istype(H.pulling, /obj/item/weapon) ))
|
||||
usr << "You may only place items in."
|
||||
else
|
||||
if ((locate(/mob, src) && ismob(H.pulling)))
|
||||
usr << "There is no room! You can only fit one person."
|
||||
else
|
||||
H.pulling.loc = src
|
||||
if (ismob(H.pulling))
|
||||
var/mob/M = H.pulling
|
||||
if (M.client)
|
||||
M.client.perspective = EYE_PERSPECTIVE
|
||||
M.client.eye = src
|
||||
for(var/mob/O in viewers(src, null))
|
||||
if ((O.client && !( O.blinded )))
|
||||
O << text("\blue <B> [] loads [] into []!</B>", H, H.pulling, src)
|
||||
//Foreach goto(204)
|
||||
H.pulling = null
|
||||
|
||||
|
||||
// Unload an object from the recon
|
||||
// If a player, reset the player's view to normal
|
||||
|
||||
verb/unload(atom/movable/A in src)
|
||||
set src in oview(1)
|
||||
|
||||
if (usr.stat)
|
||||
return
|
||||
if (istype(A, /atom/movable))
|
||||
A.loc = src.loc
|
||||
for(var/mob/O in view(src, null))
|
||||
if ((O.client && !( O.blinded )))
|
||||
O << text("\blue <B> [] unloads [] from []!</B>", usr, A, src)
|
||||
//Foreach goto(53)
|
||||
if (ismob(A))
|
||||
var/mob/M = A
|
||||
if (M.client)
|
||||
M.client.perspective = MOB_PERSPECTIVE
|
||||
M.client.eye = M
|
||||
|
||||
|
||||
// Damage procs
|
||||
|
||||
// Meteor hit, dump all contents and delete recon
|
||||
|
||||
meteorhit(var/obj/O)
|
||||
if (O.icon_state == "flaming")
|
||||
for(var/obj/item/I in src)
|
||||
I.loc = src.loc
|
||||
|
||||
for(var/mob/M in src)
|
||||
M.loc = src.loc
|
||||
if (M.client)
|
||||
M.client.eye = M.client.mob
|
||||
M.client.perspective = MOB_PERSPECTIVE
|
||||
del(src)
|
||||
|
||||
|
||||
// Explosion, dump all contents and explode them, then delete recon
|
||||
|
||||
ex_act(severity)
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
for(var/atom/movable/A in src)
|
||||
A.loc = src.loc
|
||||
A.ex_act(severity)
|
||||
del(src)
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
for(var/atom/movable/A in src)
|
||||
A.loc = src.loc
|
||||
A.ex_act(severity)
|
||||
del(src)
|
||||
|
||||
|
||||
// Blob attack, dump contents and delete recon
|
||||
|
||||
blob_act()
|
||||
for(var/atom/movable/A in src)
|
||||
A.loc = src.loc
|
||||
del(src)
|
||||
@@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Sec_lock -- Control for opening paired security doors
|
||||
* As used in brig, prision station, etc.
|
||||
* Requires ID card to operate
|
||||
*
|
||||
* TODO: Merge security checks in Topic() proc
|
||||
*/
|
||||
|
||||
obj/machinery/sec_lock
|
||||
name = "Security Pad"
|
||||
icon = 'stationobjs.dmi'
|
||||
icon_state = "sec_lock"
|
||||
anchored = 1.0
|
||||
|
||||
var
|
||||
obj/item/weapon/card/id/scan = null // the inserted ID card
|
||||
a_type = 0 // position of the controlled doors
|
||||
//0 = doors S/SE, 1 = SW/(SW+W), 2 = NW/(NW+W)
|
||||
obj/machinery/door/d1 = null // the 1st door to control
|
||||
obj/machinery/door/d2 = null // the 2nd door to control
|
||||
access = "5500" // ID access level required to operate lock
|
||||
allowed = "Prison Security/Prison Warden/Security Officer/Head of Personnel/Captain"
|
||||
// Job titles required to operate lock
|
||||
|
||||
// Create a new sec_lock
|
||||
// Looks for 1st & 2nd controlled doors at positions determined by a_type
|
||||
|
||||
New()
|
||||
..()
|
||||
spawn( 2 ) // wait for world to finished loading
|
||||
if (src.a_type == 1)
|
||||
src.d2 = locate(/obj/machinery/door, locate(src.x - 2, src.y - 1, src.z))
|
||||
src.d1 = locate(/obj/machinery/door, get_step(src, SOUTHWEST))
|
||||
else
|
||||
if (src.a_type == 2)
|
||||
src.d2 = locate(/obj/machinery/door, locate(src.x - 2, src.y + 1, src.z))
|
||||
src.d1 = locate(/obj/machinery/door, get_step(src, NORTHWEST))
|
||||
else
|
||||
src.d1 = locate(/obj/machinery/door, get_step(src, SOUTH))
|
||||
src.d2 = locate(/obj/machinery/door, get_step(src, SOUTHEAST))
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
|
||||
// Monkey interact same as human
|
||||
|
||||
attack_paw(mob/user)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// Interact, show window
|
||||
|
||||
attack_hand(mob/user)
|
||||
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
use_power(10)
|
||||
|
||||
if (src.loc == user.loc)
|
||||
var/dat = {"<B>Security Pad:</B><BR>
|
||||
Keycard: [src.scan ? "<A href='?src=\ref[src];card=1'>[src.scan.name]</A>" : "<A href='?src=\ref[src];card=1'>-----</A>"]<BR>
|
||||
<A href='?src=\ref[src];door1=1'>Toggle Outer Door</A><BR>
|
||||
<A href='?src=\ref[src];door2=1'>Toggle Inner Door</A><BR>
|
||||
<BR>
|
||||
<A href='?src=\ref[src];em_cl=1'>Emergency Close</A><BR>
|
||||
<A href='?src=\ref[src];em_op=1'>Emergency Open</A><BR>"}
|
||||
|
||||
user << browse(dat, "window=sec_lock")
|
||||
return
|
||||
|
||||
|
||||
// Attack by item, same as attack with empty hand
|
||||
|
||||
attackby(nothing, mob/user)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
// Handle topic links from interction window
|
||||
// Note: user can insert an ID card by attacking the 'card' link with a card equipped
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
|
||||
|
||||
if ((!( istype(usr, /mob/human) ) && (!( ticker ) || (ticker && ticker.mode != "monkey"))))
|
||||
usr << "\red You don't have the dexterity to do this!"
|
||||
return
|
||||
if ((usr.stat || usr.restrained()))
|
||||
return
|
||||
if ((!( src.d1 ) || !( src.d2 )))
|
||||
usr << "\red Error: Cannot interface with door security!"
|
||||
return
|
||||
if ((usr.contents.Find(src) || (get_dist(src, usr) <= 1 && istype(src.loc, /turf))))
|
||||
usr.machine = src
|
||||
if (href_list["card"]) // clicked card link
|
||||
if (src.scan) // if card already present, remove the card
|
||||
src.scan.loc = src.loc
|
||||
src.scan = null
|
||||
else // otherwise
|
||||
var/obj/item/weapon/card/id/I = usr.equipped() // check to see if an ID card is equipped
|
||||
if (istype(I, /obj/item/weapon/card/id))
|
||||
usr.drop_item()
|
||||
I.loc = src
|
||||
src.scan = I // and insert the ID card
|
||||
if (href_list["door1"])
|
||||
if (src.scan)
|
||||
if (scan.check_access(access, allowed))
|
||||
if (src.d1.density)
|
||||
spawn( 0 )
|
||||
src.d1.open()
|
||||
return
|
||||
else
|
||||
spawn( 0 )
|
||||
src.d1.close()
|
||||
return
|
||||
if (href_list["door2"])
|
||||
if (src.scan)
|
||||
if (scan.check_access(access, allowed))
|
||||
if (src.d2.density)
|
||||
spawn( 0 )
|
||||
src.d2.open()
|
||||
return
|
||||
else
|
||||
spawn( 0 )
|
||||
src.d2.close()
|
||||
return
|
||||
if (href_list["em_cl"])
|
||||
if (src.scan)
|
||||
if (scan.check_access(access, allowed))
|
||||
if (!( src.d1.density ))
|
||||
src.d1.close()
|
||||
return
|
||||
sleep(1)
|
||||
spawn( 0 )
|
||||
if (!( src.d2.density ))
|
||||
src.d2.close()
|
||||
return
|
||||
if (href_list["em_op"])
|
||||
if (src.scan)
|
||||
if (scan.check_access(access, allowed))
|
||||
spawn( 0 )
|
||||
if (src.d1.density)
|
||||
src.d1.open()
|
||||
return
|
||||
sleep(1)
|
||||
spawn( 0 )
|
||||
if (src.d2.density)
|
||||
src.d2.open()
|
||||
return
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
for(var/mob/M in src.loc)
|
||||
if ((M.client && M.machine == src))
|
||||
spawn( 0 )
|
||||
src.attack_hand(M)
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
/*
|
||||
* Shuttle - machines for shuttle propulsion
|
||||
*
|
||||
* These do nothing, but are used in certain places as graphical elements
|
||||
*
|
||||
* TODO: Make them actually do something? This would require significant coding for moving objects.
|
||||
*/
|
||||
|
||||
obj/machinery/shuttle
|
||||
name = "shuttle"
|
||||
icon = 'shuttle.dmi'
|
||||
|
||||
engine
|
||||
name = "engine"
|
||||
density = 1
|
||||
anchored = 1.0
|
||||
|
||||
heater
|
||||
name = "heater"
|
||||
icon_state = "heater"
|
||||
|
||||
platform
|
||||
name = "platform"
|
||||
icon_state = "platform"
|
||||
|
||||
propulsion
|
||||
name = "propulsion"
|
||||
icon_state = "propulsion"
|
||||
opacity = 1
|
||||
|
||||
burst
|
||||
left
|
||||
name = "left"
|
||||
icon_state = "burst_l"
|
||||
right
|
||||
name = "right"
|
||||
icon_state = "burst_r"
|
||||
|
||||
router
|
||||
name = "router"
|
||||
icon_state = "router"
|
||||
@@ -0,0 +1,320 @@
|
||||
/*
|
||||
* Sleeper -- allows a mob to be preserved without further damage
|
||||
*
|
||||
* /obj/machinery/sleeper -- the sleeper itself
|
||||
*
|
||||
* /obj/machinery/computer/sleep_console -- the control console
|
||||
*
|
||||
* TODO: Sleepers currently do not use or need power. If altered, need to make the occupant suffer if the power goes out.
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
* The sleeper
|
||||
*/
|
||||
|
||||
obj/machinery/sleeper
|
||||
name = "sleeper"
|
||||
icon = 'Cryogenic2.dmi'
|
||||
icon_state = "sleeper_0"
|
||||
density = 1
|
||||
anchored = 1
|
||||
var
|
||||
mob/occupant = null // the mob in the sleeper, or null if none
|
||||
|
||||
|
||||
// Eject verb
|
||||
// Remove the occupant from the sleeper
|
||||
|
||||
verb/eject()
|
||||
set src in oview(1)
|
||||
|
||||
if (usr.stat != 0)
|
||||
return
|
||||
src.go_out()
|
||||
add_fingerprint(usr)
|
||||
|
||||
|
||||
// Move inside verb
|
||||
// Insert the mob you are pulling into the sleeper
|
||||
// Sleeper must be empty, and mob cannot be wearing anything
|
||||
|
||||
verb/move_inside()
|
||||
set src in oview(1)
|
||||
|
||||
if (usr.stat != 0)
|
||||
return
|
||||
if (src.occupant)
|
||||
usr << "\blue <B>The sleeper is already occupied!</B>"
|
||||
return
|
||||
if (usr.abiotic())
|
||||
usr << "Subject may not have abiotic items on."
|
||||
return
|
||||
usr.pulling = null
|
||||
usr.client.perspective = EYE_PERSPECTIVE
|
||||
usr.client.eye = src
|
||||
usr.loc = src
|
||||
src.occupant = usr
|
||||
src.icon_state = "sleeper_1"
|
||||
for(var/obj/O in src)
|
||||
del(O)
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
|
||||
// Attack by item
|
||||
// Only used for the grab pseudo-item, places the grabbed mob in the sleeper
|
||||
|
||||
attackby(obj/item/weapon/grab/G, mob/user)
|
||||
|
||||
if ((!( istype(G, /obj/item/weapon/grab) ) || !( ismob(G.affecting) )))
|
||||
return
|
||||
if (src.occupant)
|
||||
user << "\blue <B>The sleeper is already occupied!</B>"
|
||||
return
|
||||
if (G.affecting.abiotic())
|
||||
user << "Subject may not have abiotic items on."
|
||||
return
|
||||
var/mob/M = G.affecting
|
||||
if (M.client)
|
||||
M.client.perspective = EYE_PERSPECTIVE
|
||||
M.client.eye = src
|
||||
M.loc = src
|
||||
src.occupant = M
|
||||
src.icon_state = "sleeper_1"
|
||||
for(var/obj/O in src)
|
||||
O.loc = src.loc
|
||||
|
||||
src.add_fingerprint(user)
|
||||
|
||||
del(G)
|
||||
|
||||
|
||||
// Called to remove a mob from the sleeper
|
||||
// If a client, reset the view to normal
|
||||
|
||||
proc/go_out()
|
||||
if (!( src.occupant ))
|
||||
return
|
||||
for(var/obj/O in src)
|
||||
O.loc = src.loc
|
||||
|
||||
if (src.occupant.client)
|
||||
src.occupant.client.eye = src.occupant.client.mob
|
||||
src.occupant.client.perspective = MOB_PERSPECTIVE
|
||||
src.occupant.loc = src.loc
|
||||
src.occupant = null
|
||||
src.icon_state = "sleeper_0"
|
||||
|
||||
|
||||
// Called to inject rejuve chemicals into the occupant
|
||||
// Maximum is 60 units
|
||||
|
||||
proc/inject(mob/user)
|
||||
|
||||
if (src.occupant)
|
||||
if (src.occupant.rejuv < 60)
|
||||
src.occupant.rejuv = 60
|
||||
user << text("Occupant now has [] units of rejuvenation in his/her bloodstream.", src.occupant.rejuv)
|
||||
else
|
||||
user << "No occupant!"
|
||||
|
||||
|
||||
// Shows the health statistics of the occupant
|
||||
// Does not seem to be used?
|
||||
|
||||
proc/check(mob/user)
|
||||
if (src.occupant)
|
||||
user << "\blue <B>Occupant ([src.occupant]) Statistics:</B>"
|
||||
var/t1
|
||||
switch(src.occupant.stat)
|
||||
if(0.0)
|
||||
t1 = "Conscious"
|
||||
if(1.0)
|
||||
t1 = "Unconscious"
|
||||
if(2.0)
|
||||
t1 = "*dead*"
|
||||
else
|
||||
user << "[(src.occupant.health > 50 ? "\blue " : "\red ")]\t Health %: [src.occupant.health] ([t1])"
|
||||
user << "[(src.occupant.oxyloss < 60 ? "\blue " : "\red ")]\t -Respiratory Damage %: [src.occupant.oxyloss]"
|
||||
user << "[(src.occupant.toxloss < 60 ? "\blue " : "\red ")]\t -Toxin Content %: [src.occupant.toxloss]"
|
||||
user << "[(src.occupant.fireloss < 60 ? "\blue " : "\red ")]\t -Burn Severity %: [src.occupant.fireloss]"
|
||||
user << "\blue Expected time till occupant can safely awake: (note: If health is below 20% these times are inaccurate)"
|
||||
user << "\blue \t [src.occupant.paralysis / 5] second\s (if around 1 or 2 the sleeper is keeping them asleep.)"
|
||||
else
|
||||
user << "\blue There is no one inside!"
|
||||
return
|
||||
|
||||
|
||||
// Called in mob/Life() while the occupant is inside
|
||||
// Sets the health settings of the occupant
|
||||
|
||||
alter_health(mob/M)
|
||||
|
||||
if (M.health > 0)
|
||||
if (M.oxyloss >= 10)
|
||||
var/amount = max(0.15, 1)
|
||||
M.oxyloss -= amount
|
||||
else
|
||||
M.oxyloss = 0
|
||||
M.health = 100 - M.oxyloss - M.toxloss - M.fireloss - M.bruteloss
|
||||
M.paralysis -= 4
|
||||
M.weakened -= 4
|
||||
M.stunned -= 4
|
||||
if (M.paralysis <= 1)
|
||||
M.paralysis = 3
|
||||
if (M.weakened <= 1)
|
||||
M.weakened = 3
|
||||
if (M.stunned <= 1)
|
||||
M.stunned = 3
|
||||
if (M.rejuv < 3)
|
||||
M.rejuv = 4
|
||||
|
||||
|
||||
// Explosion damage
|
||||
// Chance to remove the occupant and explode them, then delete the sleeper
|
||||
|
||||
ex_act(severity)
|
||||
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
for(var/atom/movable/A in src)
|
||||
A.loc = src.loc
|
||||
A.ex_act(severity)
|
||||
del(src)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
for(var/atom/movable/A in src)
|
||||
A.loc = src.loc
|
||||
A.ex_act(severity)
|
||||
del(src)
|
||||
return
|
||||
if(3.0)
|
||||
if (prob(25))
|
||||
for(var/atom/movable/A in src)
|
||||
A.loc = src.loc
|
||||
A.ex_act(severity)
|
||||
del(src)
|
||||
return
|
||||
|
||||
|
||||
// Blob attack, remove the occupant and delete
|
||||
|
||||
blob_act()
|
||||
for(var/atom/movable/A in src)
|
||||
A.loc = src.loc
|
||||
del(src)
|
||||
|
||||
|
||||
/* Unused
|
||||
|
||||
allow_drop()
|
||||
return 0
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
* The sleep console
|
||||
*/
|
||||
|
||||
|
||||
obj/machinery/computer/sleep_console
|
||||
name = "sleep console"
|
||||
icon = 'Cryogenic2.dmi'
|
||||
icon_state = "sleeperconsole"
|
||||
var
|
||||
obj/machinery/sleeper/connected = null // the associated sleeper
|
||||
|
||||
|
||||
// Create a new sleep console
|
||||
// Locate the connected sleeper 1 step west
|
||||
|
||||
New()
|
||||
..()
|
||||
spawn( 5 ) // wait for world to finish loading
|
||||
src.connected = locate(/obj/machinery/sleeper, get_step(src, WEST))
|
||||
|
||||
|
||||
// Monkey interact same as human
|
||||
|
||||
attack_paw(mob/user)
|
||||
return src.attack_hand(user)
|
||||
|
||||
// Human interact
|
||||
// Show the interaction window
|
||||
|
||||
attack_hand(mob/user)
|
||||
if (src.connected)
|
||||
var/mob/occupant = src.connected.occupant
|
||||
var/dat = "<font color='blue'><B>Occupant Statistics:</B></FONT><BR>"
|
||||
if (occupant)
|
||||
var/t1
|
||||
switch(occupant.stat)
|
||||
if(0.0)
|
||||
t1 = "Conscious"
|
||||
if(1.0)
|
||||
t1 = "Unconscious"
|
||||
if(2.0)
|
||||
t1 = "*dead*"
|
||||
else
|
||||
dat += "[occupant.health > 50 ? "<font color='blue'>" : "<font color='red'>"]\tHealth %: [occupant.health] ([t1])</FONT><BR>"
|
||||
dat += "[occupant.oxyloss < 60 ? "<font color='blue'>" : "<font color='red'>"]\t-Respiratory Damage %: [occupant.oxyloss]</FONT><BR>"
|
||||
dat += "[occupant.toxloss < 60 ? "<font color='blue'>" : "<font color='red'>"]\t-Toxin Content %: [occupant.toxloss]</FONT><BR>"
|
||||
dat += "[occupant.fireloss < 60 ? "<font color='blue'>" : "<font color='red'>"]\t-Burn Severity %: [occupant.fireloss]</FONT><BR>"
|
||||
dat += "<BR>Paralysis Summary %: [occupant.paralysis] ([round(occupant.paralysis / 4)] seconds left!)</FONT><BR>"
|
||||
dat += "<HR><A href='?src=\ref[src];refresh=1'>Refresh</A><BR><A href='?src=\ref[src];rejuv=1'>Inject Rejuvenators</A>"
|
||||
else
|
||||
dat += "The sleeper is empty."
|
||||
dat += "<BR><BR><A href='?src=\ref[user];mach_close=sleeper'>Close</A>"
|
||||
user << browse(dat, "window=sleeper;size=400x500")
|
||||
|
||||
|
||||
// Handle topic links from interaction window
|
||||
|
||||
Topic(href, href_list)
|
||||
..()
|
||||
if ((usr.stat || usr.restrained()))
|
||||
return
|
||||
if ((usr.contents.Find(src) || (get_dist(src, usr) <= 1 && istype(src.loc, /turf))))
|
||||
usr.machine = src
|
||||
if (href_list["rejuv"])
|
||||
if (src.connected)
|
||||
src.connected.inject(usr)
|
||||
if (href_list["refresh"])
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
//Foreach goto(123)
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
|
||||
// Timed process - just update interaction window for those viewing
|
||||
|
||||
process()
|
||||
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
|
||||
|
||||
// Called when area power state changes
|
||||
// no change - sleeper works without power
|
||||
// Note overrides standard /obj/machinery/computer/power_change()
|
||||
|
||||
power_change()
|
||||
return
|
||||
|
||||
|
||||
// Explosion damage, chance to delete the sleeper console
|
||||
|
||||
ex_act(severity)
|
||||
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
del(src)
|
||||
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
del(src)
|
||||
@@ -0,0 +1,185 @@
|
||||
/*
|
||||
* Valve - on/off valve machine, prevents gas flow through a pipe when off
|
||||
*
|
||||
* Valves work by having two internal gas reservoirs, and flowing between them only when open.
|
||||
*/
|
||||
|
||||
obj/machinery/valve
|
||||
name = "valve"
|
||||
icon = 'pipes.dmi'
|
||||
icon_state = "valve0"
|
||||
desc = "A gas valve."
|
||||
anchored = 1
|
||||
capmult = 2
|
||||
var
|
||||
obj/substance/gas/gas1 = null // gas reservoir connected to node1
|
||||
obj/substance/gas/ngas1 = null
|
||||
|
||||
obj/substance/gas/gas2 = null // gas reservoir connected to node2
|
||||
obj/substance/gas/ngas2 = null
|
||||
|
||||
capacity = 6000000.0
|
||||
|
||||
obj/machinery/node1 = null // pipe/machine connected to gas1
|
||||
obj/machinery/node2 = null // pipe/machine connected to gas2
|
||||
obj/machinery/vnode1 = null // pipeline of node1
|
||||
obj/machinery/vnode2 = null // pipeline of node2
|
||||
id = "v1" // Not implemented: planned id to control valves remotely
|
||||
open = 0 // true if the valve is open
|
||||
|
||||
|
||||
// Create a valve, create gas reservoirs.
|
||||
// p_dir calculated from icon direction
|
||||
|
||||
New()
|
||||
..()
|
||||
gas1 = new/obj/substance/gas(src)
|
||||
ngas1 = new/obj/substance/gas()
|
||||
gas2 = new/obj/substance/gas(src)
|
||||
ngas2 = new/obj/substance/gas()
|
||||
|
||||
gasflowlist += src
|
||||
switch(dir)
|
||||
if(1, 2)
|
||||
p_dir = 3
|
||||
if(4,8)
|
||||
p_dir = 12
|
||||
|
||||
icon_state = "valve[open]"
|
||||
|
||||
// Examine verb
|
||||
|
||||
examine()
|
||||
set src in oview(1)
|
||||
if(usr.stat)
|
||||
return
|
||||
|
||||
usr << "[desc] It is [ open? "open" : "closed"]."
|
||||
|
||||
|
||||
// Find the connected nodes
|
||||
|
||||
buildnodes()
|
||||
|
||||
var/turf/T = src.loc
|
||||
|
||||
node1 = get_machine(level, T, dir ) // the h/e pipe
|
||||
|
||||
node2 = get_machine(level, T , turn(dir, 180) ) // the regular pipe
|
||||
|
||||
if(node1) vnode1 = node1.getline()
|
||||
if(node2) vnode2 = node2.getline()
|
||||
|
||||
return
|
||||
|
||||
|
||||
// Update the gas values with the newly calculated values
|
||||
|
||||
gas_flow()
|
||||
|
||||
gas1.replace_by(ngas1)
|
||||
gas2.replace_by(ngas2)
|
||||
|
||||
|
||||
// Perform flow into and out of the valve, and if open, between the two reservoirs
|
||||
|
||||
process()
|
||||
|
||||
var/delta_gt
|
||||
|
||||
if(vnode1)
|
||||
delta_gt = FLOWFRAC * ( vnode1.get_gas_val(src) - gas1.tot_gas() / capmult)
|
||||
calc_delta( src, gas1, ngas1, vnode1, delta_gt)
|
||||
|
||||
else
|
||||
leak_to_turf(1)
|
||||
|
||||
if(vnode2)
|
||||
delta_gt = FLOWFRAC * ( vnode2.get_gas_val(src) - gas2.tot_gas() / capmult)
|
||||
calc_delta( src, gas2, ngas2, vnode2, delta_gt)
|
||||
|
||||
else
|
||||
leak_to_turf(2)
|
||||
|
||||
|
||||
if(open) // valve operating, so transfer btwen resv1 & 2
|
||||
|
||||
delta_gt = FLOWFRAC * (gas1.tot_gas() / capmult - gas2.tot_gas() / capmult)
|
||||
|
||||
var/obj/substance/gas/ndelta = new()
|
||||
|
||||
if(delta_gt < 0) // then flowing from R2 to R1
|
||||
|
||||
ndelta.set_frac(gas2, -delta_gt)
|
||||
|
||||
ngas2.sub_delta(ndelta)
|
||||
ngas1.add_delta(ndelta)
|
||||
|
||||
else // flowing from R1 to R2
|
||||
ndelta.set_frac(gas1, delta_gt)
|
||||
ngas2.add_delta(ndelta)
|
||||
ngas1.sub_delta(ndelta)
|
||||
|
||||
|
||||
// Return the gas fullness value. Two reservoirs, so which value returned depends on who's asking
|
||||
|
||||
get_gas_val(from)
|
||||
if(from == vnode2)
|
||||
return gas2.tot_gas()/capmult
|
||||
else
|
||||
return gas1.tot_gas()/capmult
|
||||
|
||||
// Return the corresponding gas resevoir connected to the given node
|
||||
|
||||
get_gas(from)
|
||||
if(from == vnode2)
|
||||
return gas2
|
||||
return gas1
|
||||
|
||||
// Leak gas to turf if either node is null
|
||||
|
||||
proc/leak_to_turf(var/port)
|
||||
var/turf/T
|
||||
|
||||
|
||||
switch(port)
|
||||
if(1)
|
||||
T = get_step(src, dir)
|
||||
if(2)
|
||||
T = get_step(src, turn(dir, 180) )
|
||||
|
||||
if(T.density)
|
||||
T = src.loc
|
||||
if(T.density)
|
||||
return
|
||||
|
||||
if(port==1)
|
||||
flow_to_turf(gas1, ngas1, T)
|
||||
else
|
||||
flow_to_turf(gas2, ngas2, T)
|
||||
|
||||
// Monkey interact same as human
|
||||
|
||||
attack_paw(mob/user)
|
||||
attack_hand(user)
|
||||
|
||||
|
||||
// Interact, toggle open/closed state, show correct animation, set correct final icon state
|
||||
|
||||
attack_hand(mob/user)
|
||||
..()
|
||||
add_fingerprint(user)
|
||||
// if(stat & NOPOWER) return
|
||||
|
||||
// use_power(5)
|
||||
|
||||
if(!open) // now opening
|
||||
flick("valve01", src)
|
||||
icon_state = "valve1"
|
||||
sleep(10)
|
||||
else // now closing
|
||||
flick("valve10", src)
|
||||
icon_state = "valve0"
|
||||
sleep(10)
|
||||
open = !open
|
||||
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* Vent - Machine which dumps pipe gas contents into turf
|
||||
*
|
||||
* Similar to an inlet, except only works one way (pipe->turf)
|
||||
*/
|
||||
|
||||
|
||||
obj/machinery/vent
|
||||
name = "vent"
|
||||
icon = 'pipes.dmi'
|
||||
icon_state = "vent"
|
||||
desc = "A gas pipe outlet vent."
|
||||
anchored = 1
|
||||
p_dir = 2
|
||||
capmult = 2
|
||||
|
||||
var
|
||||
obj/machinery/node // the connected object
|
||||
obj/machinery/vnode // the connected pipeline (if node is a pipe)
|
||||
obj/substance/gas/gas // the gas reservoir
|
||||
obj/substance/gas/ngas // the new gas reservoir after calculating flow
|
||||
capacity = 6000000 // nominal gas capacity
|
||||
|
||||
|
||||
// Create a new vent. Pipe connection p_dir is calculated from icon dir, so p_dir does not need to be set on map.
|
||||
// Create the gas reservoir and register with the gasflowlist.
|
||||
|
||||
New()
|
||||
..()
|
||||
p_dir = dir
|
||||
gas = new/obj/substance/gas(src)
|
||||
gas.maximum = capacity
|
||||
ngas = new/obj/substance/gas()
|
||||
gasflowlist += src
|
||||
|
||||
|
||||
// Find the connected machine or pipe to the vent pipe.
|
||||
|
||||
buildnodes()
|
||||
var/turf/T = get_step(src.loc, src.dir)
|
||||
var/fdir = turn(src.p_dir, 180)
|
||||
|
||||
for(var/obj/machinery/M in T)
|
||||
if(M.p_dir & fdir)
|
||||
src.node = M
|
||||
break
|
||||
|
||||
if(node) vnode = node.getline()
|
||||
|
||||
return
|
||||
|
||||
|
||||
// Get the gas fullness value.
|
||||
|
||||
get_gas_val(from)
|
||||
return gas.tot_gas()/2
|
||||
|
||||
// Get the gas reservoir object
|
||||
|
||||
get_gas(from)
|
||||
return gas
|
||||
|
||||
|
||||
// Replace the gas level by the new level calculated in process()
|
||||
|
||||
gas_flow()
|
||||
gas.replace_by(ngas)
|
||||
|
||||
|
||||
// Timed process. Dump gas into turf, then do standard flow calc for connected pipe.
|
||||
|
||||
process()
|
||||
var/delta_gt
|
||||
|
||||
var/turf/T = src.loc
|
||||
|
||||
delta_gt = FLOWFRAC * (gas.tot_gas() / capmult)
|
||||
ngas.turf_add(T, delta_gt)
|
||||
if(vnode)
|
||||
delta_gt = FLOWFRAC * ( vnode.get_gas_val(src) - gas.tot_gas() / capmult)
|
||||
calc_delta( src, gas, ngas, vnode, delta_gt)//, dbg)
|
||||
else
|
||||
leak_to_turf()
|
||||
|
||||
|
||||
// Leak from pipe to turf if no node connected
|
||||
|
||||
proc/leak_to_turf()
|
||||
|
||||
var/turf/T = get_step(src, dir)
|
||||
if(T && !T.density)
|
||||
flow_to_turf(gas, ngas, T)
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
|
||||
/proc/dd_run_tests()
|
||||
|
||||
var/test_classes = typesof(/obj/test)
|
||||
for(var/class in test_classes)
|
||||
var/obj/test/tester = new class( )
|
||||
for(var/test in tester.verbs)
|
||||
call(tester, test)()
|
||||
if (!( tester.success ))
|
||||
else
|
||||
//Foreach continue //goto(59)
|
||||
if (!( tester.success ))
|
||||
world << "Test failed."
|
||||
return
|
||||
//Foreach goto(26)
|
||||
world << "All tests passed."
|
||||
return
|
||||
|
||||
/obj/test/proc/die(message)
|
||||
|
||||
src.success = 0
|
||||
CRASH(message)
|
||||
return
|
||||
@@ -0,0 +1,140 @@
|
||||
|
||||
/proc/dd_file2list(file_path, separator)
|
||||
|
||||
var/file
|
||||
if (separator == null)
|
||||
separator = "\n"
|
||||
if (isfile(file_path))
|
||||
file = file_path
|
||||
else
|
||||
file = file( file_path )
|
||||
return dd_text2list(file2text(file), separator)
|
||||
return
|
||||
|
||||
/proc/dd_replacetext(text, search_string, replacement_string)
|
||||
|
||||
var/textList = dd_text2list(text, search_string)
|
||||
return dd_list2text(textList, replacement_string)
|
||||
return
|
||||
|
||||
/proc/dd_replaceText(text, search_string, replacement_string)
|
||||
|
||||
var/textList = dd_text2List(text, search_string)
|
||||
return dd_list2text(textList, replacement_string)
|
||||
return
|
||||
|
||||
/proc/dd_hasprefix(text, prefix)
|
||||
|
||||
var/start = 1
|
||||
var/end = length(prefix) + 1
|
||||
return findtext(text, prefix, start, end)
|
||||
return
|
||||
|
||||
/proc/dd_hasPrefix(text, prefix)
|
||||
|
||||
var/start = 1
|
||||
var/end = length(prefix) + 1
|
||||
return findText(text, prefix, start, end)
|
||||
return
|
||||
|
||||
/proc/dd_hassuffix(text, suffix)
|
||||
|
||||
var/start = length(text) - length(suffix)
|
||||
if (start)
|
||||
return findtext(text, suffix, start, null)
|
||||
return
|
||||
|
||||
/proc/dd_hasSuffix(text, suffix)
|
||||
|
||||
var/start = length(text) - length(suffix)
|
||||
if (start)
|
||||
return findText(text, suffix, start, null)
|
||||
return
|
||||
|
||||
/proc/dd_text2list(text, separator)
|
||||
|
||||
var/textlength = length(text)
|
||||
var/separatorlength = length(separator)
|
||||
var/textList = new /list( )
|
||||
var/searchPosition = 1
|
||||
var/findPosition = 1
|
||||
while(1)
|
||||
findPosition = findtext(text, separator, searchPosition, 0)
|
||||
var/buggyText = copytext(text, searchPosition, findPosition)
|
||||
textList += text("[]", buggyText)
|
||||
searchPosition = findPosition + separatorlength
|
||||
if (findPosition == 0)
|
||||
return textList
|
||||
else
|
||||
if (searchPosition > textlength)
|
||||
textList += ""
|
||||
return textList
|
||||
return
|
||||
|
||||
/proc/dd_text2List(text, separator)
|
||||
|
||||
var/textlength = length(text)
|
||||
var/separatorlength = length(separator)
|
||||
var/textList = new /list( )
|
||||
var/searchPosition = 1
|
||||
var/findPosition = 1
|
||||
while(1)
|
||||
findPosition = findText(text, separator, searchPosition, 0)
|
||||
var/buggyText = copytext(text, searchPosition, findPosition)
|
||||
textList += text("[]", buggyText)
|
||||
searchPosition = findPosition + separatorlength
|
||||
if (findPosition == 0)
|
||||
return textList
|
||||
else
|
||||
if (searchPosition > textlength)
|
||||
textList += ""
|
||||
return textList
|
||||
return
|
||||
|
||||
/proc/dd_list2text(var/list/the_list, separator)
|
||||
|
||||
var/total = the_list.len
|
||||
if (total == 0)
|
||||
return
|
||||
var/newText = text("[]", the_list[1])
|
||||
var/count = 2
|
||||
while(count <= total)
|
||||
if (separator)
|
||||
newText += separator
|
||||
newText += text("[]", the_list[count])
|
||||
count++
|
||||
return newText
|
||||
return
|
||||
|
||||
/proc/dd_centertext(message, length)
|
||||
|
||||
var/new_message = message
|
||||
var/size = length(message)
|
||||
if (size == length)
|
||||
return new_message
|
||||
if (size > length)
|
||||
return copytext(new_message, 1, length + 1)
|
||||
var/delta = length - size
|
||||
if (delta == 1)
|
||||
return new_message + " "
|
||||
if (delta % 2)
|
||||
new_message = " " + new_message
|
||||
delta--
|
||||
delta = delta / 2
|
||||
var/spaces = ""
|
||||
var/count = null
|
||||
count = 1
|
||||
while(count <= delta)
|
||||
spaces += " "
|
||||
count++
|
||||
return spaces + new_message + spaces
|
||||
return
|
||||
|
||||
/proc/dd_limittext(message, length)
|
||||
|
||||
var/size = length(message)
|
||||
if (size <= length)
|
||||
return message
|
||||
else
|
||||
return copytext(message, 1, length + 1)
|
||||
return
|
||||
+474
@@ -0,0 +1,474 @@
|
||||
// NOTE WELL!
|
||||
// Only include this file when debugging locally
|
||||
// Do not include in release versions
|
||||
|
||||
|
||||
#define VARSICON 1
|
||||
#define SDEBUG 1
|
||||
|
||||
/turf/verb/Flow()
|
||||
set category = "Debug"
|
||||
//set hidden = 1
|
||||
|
||||
for(var/turf/T in range(5))
|
||||
|
||||
var/obj/mark/O = locate(/obj/mark/, T)
|
||||
|
||||
if(!O)
|
||||
O = new /obj/mark(T)
|
||||
else
|
||||
O.overlays = null
|
||||
|
||||
var/obj/move/OM = locate(/obj/move/, T)
|
||||
|
||||
if(OM)
|
||||
|
||||
if(! OM.updatecell)
|
||||
O.icon_state = "x2"
|
||||
else
|
||||
O.icon_state = "blank"
|
||||
|
||||
for(var/atom/U in OM.FindTurfs() )
|
||||
var/dirn = get_dir(OM, U)
|
||||
if(dirn == 1)
|
||||
O.overlays += image('mark.dmi', OM.airdir==1?"up":"fup")
|
||||
else if(dirn == 2)
|
||||
O.overlays += image('mark.dmi', OM.airdir==2?"dn":"fdn")
|
||||
else if(dirn == 4)
|
||||
O.overlays += image('mark.dmi', OM.airdir==4?"rt":"frt")
|
||||
else if(dirn == 8)
|
||||
O.overlays += image('mark.dmi', OM.airdir==8?"lf":"flf")
|
||||
|
||||
else
|
||||
|
||||
if(!(T.updatecell))
|
||||
O.icon_state = "x2"
|
||||
else
|
||||
O.icon_state = "blank"
|
||||
|
||||
if(T.airN)
|
||||
O.overlays += image('mark.dmi', T.airdir==1?"up":"fup")
|
||||
|
||||
if(T.airS)
|
||||
O.overlays += image('mark.dmi', T.airdir==2?"dn":"fdn")
|
||||
|
||||
if(T.airW)
|
||||
O.overlays += image('mark.dmi', T.airdir==8?"lf":"flf")
|
||||
|
||||
if(T.airE)
|
||||
O.overlays += image('mark.dmi', T.airdir==4?"rt":"frt")
|
||||
|
||||
|
||||
if(T.condN)
|
||||
O.overlays += image('mark.dmi', T.condN == 1?"yup":"rup")
|
||||
|
||||
if(T.condS)
|
||||
O.overlays += image('mark.dmi', T.condS == 1?"ydn":"rdn")
|
||||
|
||||
if(T.condE)
|
||||
O.overlays += image('mark.dmi', T.condE == 1?"yrt":"rrt")
|
||||
|
||||
if(T.condW)
|
||||
O.overlays += image('mark.dmi', T.condW == 1?"ylf":"rlf")
|
||||
|
||||
|
||||
/turf/verb/Clear()
|
||||
set category = "Debug"
|
||||
//set hidden = 1
|
||||
for(var/obj/mark/O in world)
|
||||
del(O)
|
||||
|
||||
|
||||
/proc/numbericon(var/tn as text,var/s = 0)
|
||||
|
||||
var/image/I = image('mark.dmi', "blank")
|
||||
|
||||
if(lentext(tn)>8)
|
||||
tn = "*"
|
||||
|
||||
var/len = lentext(tn)
|
||||
|
||||
for(var/d = 1 to lentext(tn))
|
||||
|
||||
|
||||
var/char = copytext(tn, len-d+1, len-d+2)
|
||||
|
||||
if(char == " ")
|
||||
continue
|
||||
|
||||
var/image/ID = image('mark.dmi', char)
|
||||
|
||||
ID.pixel_x = -(d-1)*4
|
||||
ID.pixel_y = s
|
||||
//if(d>1) I.Shift(WEST, (d-1)*8)
|
||||
|
||||
I.overlays += ID
|
||||
|
||||
|
||||
|
||||
return I
|
||||
|
||||
|
||||
/turf/verb/Stats()
|
||||
set category = "Debug"
|
||||
for(var/turf/T in range(5))
|
||||
|
||||
var/obj/mark/O = locate(/obj/mark/, T)
|
||||
|
||||
if(!O)
|
||||
O = new /obj/mark(T)
|
||||
else
|
||||
O.overlays = null
|
||||
|
||||
|
||||
var/temp = round(T.temp-T0C, 0.1)
|
||||
|
||||
O.overlays += numbericon("[temp]C")
|
||||
|
||||
var/pres = round(T.tot_gas() / CELLSTANDARD * 100, 0.1)
|
||||
|
||||
O.overlays += numbericon("[pres]", -8)
|
||||
O.mark = "[temp]/[pres]"
|
||||
|
||||
|
||||
/turf/verb/Pipes()
|
||||
set category = "Debug"
|
||||
|
||||
for(var/turf/T in range(6))
|
||||
|
||||
//world << "Turf [T] at ([T.x],[T.y])"
|
||||
|
||||
for(var/obj/machinery/M in T)
|
||||
//world <<" Mach [M] with pdir=[M.p_dir]"
|
||||
|
||||
if(M && M.p_dir)
|
||||
|
||||
//world << "Accepted"
|
||||
var/obj/mark/O = locate(/obj/mark/, T)
|
||||
|
||||
if(!O)
|
||||
O = new /obj/mark(T)
|
||||
else
|
||||
O.overlays = null
|
||||
|
||||
if(istype(M, /obj/machinery/pipes))
|
||||
var/obj/machinery/pipes/P = M
|
||||
O.overlays += numbericon("[plines.Find(P.pl)] ", -20)
|
||||
M = P.pl
|
||||
|
||||
|
||||
var/obj/substance/gas/G = M.get_gas()
|
||||
|
||||
if(G)
|
||||
|
||||
var/cap = round( 100*(G.tot_gas()/ M.capmult / 6e6), 0.1)
|
||||
var/temp = round(G.temperature - T0C, 0.1)
|
||||
O.overlays += numbericon("[temp]C", 0)
|
||||
O.overlays += numbericon("[cap]", -8)
|
||||
|
||||
break
|
||||
|
||||
/turf/verb/Cables()
|
||||
set category = "Debug"
|
||||
|
||||
for(var/turf/T in range(6))
|
||||
|
||||
//world << "Turf [T] at ([T.x],[T.y])"
|
||||
|
||||
var/obj/mark/O = locate(/obj/mark/, T)
|
||||
|
||||
if(!O)
|
||||
O = new /obj/mark(T)
|
||||
else
|
||||
O.overlays = null
|
||||
|
||||
var/marked = 0
|
||||
for(var/obj/M in T)
|
||||
//world <<" Mach [M] with pdir=[M.p_dir]"
|
||||
|
||||
|
||||
if(M && istype(M, /obj/cable/))
|
||||
|
||||
|
||||
var/obj/cable/C = M
|
||||
//world << "Accepted"
|
||||
|
||||
O.overlays += numbericon("[C.netnum] " , marked)
|
||||
|
||||
marked -= 8
|
||||
|
||||
else if(M && istype(M, /obj/machinery/power/))
|
||||
|
||||
var/obj/machinery/power/P = M
|
||||
O.overlays += numbericon("*[P.netnum] " , marked)
|
||||
marked -= 8
|
||||
|
||||
if(!marked)
|
||||
del(O)
|
||||
|
||||
/turf/verb/Solar()
|
||||
set category = "Debug"
|
||||
|
||||
for(var/turf/T in range(6))
|
||||
|
||||
//world << "Turf [T] at ([T.x],[T.y])"
|
||||
|
||||
var/obj/mark/O = locate(/obj/mark/, T)
|
||||
|
||||
if(!O)
|
||||
O = new /obj/mark(T)
|
||||
else
|
||||
O.overlays = null
|
||||
|
||||
|
||||
var/obj/machinery/power/solar/S
|
||||
|
||||
S = locate(/obj/machinery/power/solar, T)
|
||||
|
||||
if(S)
|
||||
|
||||
O.overlays += numbericon("[S.obscured] " , 0)
|
||||
O.overlays += numbericon("[round(S.sunfrac*100,0.1)] " , -12)
|
||||
|
||||
else
|
||||
del(O)
|
||||
|
||||
/mob/verb/Showports()
|
||||
set category = "Debug"
|
||||
|
||||
var/turf/T
|
||||
var/obj/machinery/pipes/P
|
||||
var/list/ndirs
|
||||
|
||||
for(var/obj/machinery/pipeline/PL in plines)
|
||||
|
||||
var/num = plines.Find(PL)
|
||||
|
||||
P = PL.nodes[1] // 1st node in list
|
||||
ndirs = P.get_node_dirs()
|
||||
|
||||
T = get_step(P, ndirs[1])
|
||||
|
||||
var/obj/mark/O = new(T)
|
||||
|
||||
O.overlays += numbericon("[num] * 1 ", -4)
|
||||
O.overlays += numbericon("[ndirs[1]] - [ndirs[2]]",-16)
|
||||
|
||||
|
||||
P = PL.nodes[PL.nodes.len] // last node in list
|
||||
|
||||
ndirs = P.get_node_dirs()
|
||||
T = get_step(P, ndirs[2])
|
||||
|
||||
O = new(T)
|
||||
|
||||
O.overlays += numbericon("[num] * 2 ", -4)
|
||||
O.overlays += numbericon("[ndirs[1]] - [ndirs[2]]", -16)
|
||||
|
||||
/atom/verb/delete()
|
||||
set category = "Debug"
|
||||
set src in view()
|
||||
|
||||
del(src)
|
||||
|
||||
|
||||
/area/verb/dark()
|
||||
set category = "Debug"
|
||||
|
||||
if(src.icon_state == "dark")
|
||||
icon_state = null
|
||||
else
|
||||
icon_state = "dark"
|
||||
|
||||
/area/verb/power()
|
||||
set category = "Debug"
|
||||
|
||||
power_equip = !power_equip
|
||||
power_environ = !power_environ
|
||||
|
||||
world << "Power ([src]) = [power_equip]"
|
||||
|
||||
power_change()
|
||||
|
||||
// *****RM
|
||||
/mob/verb/Jump(var/area/A in world)
|
||||
set category = "Debug"
|
||||
set desc = "Area to jump to"
|
||||
set src = usr
|
||||
|
||||
var/list/L = list()
|
||||
|
||||
for(var/turf/T in A)
|
||||
if(!T.density)
|
||||
var/clear = 1
|
||||
for(var/obj/O in T)
|
||||
if(O.density)
|
||||
clear = 0
|
||||
break
|
||||
if(clear)
|
||||
L+=T
|
||||
|
||||
src.loc = pick(L)
|
||||
|
||||
// *****
|
||||
|
||||
|
||||
/mob/verb/ShowPlasma()
|
||||
set category = "Debug"
|
||||
Plasma()
|
||||
|
||||
/mob/verb/Blobcount()
|
||||
set category = "Debug"
|
||||
world << "Blob count: [blobs.len]"
|
||||
|
||||
|
||||
/mob/verb/Blobkill()
|
||||
set category = "Debug"
|
||||
blobs = list()
|
||||
world << "Blob killed."
|
||||
|
||||
/mob/verb/Blobmode()
|
||||
set category = "Debug"
|
||||
world << "Event=[ticker.event]"
|
||||
world << "Time =[(ticker.event_time - world.realtime)/10]s"
|
||||
|
||||
/mob/verb/Blobnext()
|
||||
set category = "Debug"
|
||||
ticker.event_time = world.realtime
|
||||
|
||||
|
||||
/mob/verb/callshuttle()
|
||||
set category = "Debug"
|
||||
ticker.timeleft = 300
|
||||
ticker.timing = 1
|
||||
|
||||
/mob/verb/apcs()
|
||||
set category = "Debug"
|
||||
for(var/obj/machinery/power/apc/APC in world)
|
||||
world << APC.report()
|
||||
|
||||
/mob/verb/Globals()
|
||||
set category = "Debug"
|
||||
|
||||
debugobj = new()
|
||||
|
||||
debugobj.debuglist = list( powernets, plines, vote, config, admins, ticker, SS13_airtunnel, sun )
|
||||
|
||||
|
||||
world << "<A href='?src=\ref[debugobj];Vars=1'>Debug</A>"
|
||||
/*for(var/obj/O in plines)
|
||||
|
||||
world << "<A href='?src=\ref[O];Vars=1'>[O.name]</A>"
|
||||
*/
|
||||
|
||||
/mob/verb/Debug()
|
||||
set category = "Debug"
|
||||
Debug = !Debug
|
||||
|
||||
world << "Debugging [Debug ? "On" : "Off"]"
|
||||
|
||||
|
||||
/mob/verb/Mach()
|
||||
set category = "Debug"
|
||||
|
||||
var/n = 0
|
||||
for(var/obj/machinery/M in world)
|
||||
n++
|
||||
if(! (M in machines) )
|
||||
world << "[M] [M.type]: not in list"
|
||||
|
||||
world << "in world: [n]; in list:[machines.len]"
|
||||
|
||||
|
||||
/mob/verb/air()
|
||||
set category = "Debug"
|
||||
|
||||
Air()
|
||||
|
||||
/proc/Air()
|
||||
|
||||
|
||||
var/area/A = locate(/area/airintake)
|
||||
|
||||
var/atot = 0
|
||||
for(var/turf/T in A)
|
||||
atot += T.tot_gas()
|
||||
|
||||
var/ptot = 0
|
||||
for(var/obj/machinery/pipeline/PL in plines)
|
||||
if(PL.suffix == "d")
|
||||
ptot += PL.ngas.tot_gas()
|
||||
|
||||
var/vtot = 0
|
||||
for(var/obj/machinery/atmoalter/V in machines)
|
||||
if(V.suffix == "d")
|
||||
vtot += V.gas.tot_gas()
|
||||
|
||||
var/ctot = 0
|
||||
for(var/obj/machinery/connector/C in machines)
|
||||
if(C.suffix == "d")
|
||||
ctot += C.ngas.tot_gas()
|
||||
|
||||
|
||||
var/tot = atot + ptot + vtot + ctot
|
||||
|
||||
world.log << "A=[num2text(atot,10)] P=[num2text(ptot,10)] V=[num2text(vtot,10)] C=[num2text(ctot,10)] : Total=[num2text(tot,10)]"
|
||||
|
||||
/mob/verb/Revive()
|
||||
set category = "Debug"
|
||||
|
||||
fireloss = 0
|
||||
toxloss = 0
|
||||
bruteloss = 0
|
||||
oxyloss = 0
|
||||
paralysis = 0
|
||||
stunned = 0
|
||||
weakened = 0
|
||||
health = 100
|
||||
if(stat > 1) stat=0
|
||||
disabilities = initial(disabilities)
|
||||
sdisabilities = initial(sdisabilities)
|
||||
for(var/obj/item/weapon/organ/external/e in src)
|
||||
e.brute_dam = 0.0
|
||||
e.burn_dam = 0.0
|
||||
e.bandaged = 0.0
|
||||
e.wound_size = 0.0
|
||||
e.max_damage = initial(e.max_damage)
|
||||
e.update_icon()
|
||||
if(src.type == /mob/human)
|
||||
var/mob/human/H = src
|
||||
H.UpdateDamageIcon()
|
||||
|
||||
|
||||
/mob/verb/Smoke()
|
||||
set category = "Debug"
|
||||
|
||||
var/obj/effects/smoke/O = new /obj/effects/smoke( src.loc )
|
||||
O.dir = pick(NORTH, SOUTH, EAST, WEST)
|
||||
spawn( 0 )
|
||||
O.Life()
|
||||
|
||||
/proc/Plasma()
|
||||
|
||||
var/mplas = 0
|
||||
|
||||
for(var/obj/machinery/M in machines)
|
||||
if(M.suffix=="dbgp")
|
||||
|
||||
var/obj/substance/gas/G = M.get_gas()
|
||||
var/p = G.plasma
|
||||
|
||||
mplas += p
|
||||
|
||||
world.log << "[M]=[num2text(p, 10)] \..."
|
||||
|
||||
|
||||
var/tplas = 0
|
||||
|
||||
for(var/turf/station/engine/floor/T in world)
|
||||
tplas += T.poison
|
||||
|
||||
world.log << "\nTotals: M=[num2text(mplas, 10)] T=[num2text(tplas, 10)], all = [num2text(mplas+tplas, 10)]"
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,194 @@
|
||||
/proc/add_zero(t, u)
|
||||
|
||||
while(length(t) < u)
|
||||
t = text("0[]", t)
|
||||
return t
|
||||
|
||||
/proc/add_lspace(t, u)
|
||||
while(length(t) < u)
|
||||
t = " [t]"
|
||||
return t
|
||||
|
||||
/proc/add_tspace(t, u)
|
||||
while(length(t) < u)
|
||||
t = "[t] "
|
||||
return t
|
||||
|
||||
/obj/bomb/New()
|
||||
|
||||
..() //*****RM
|
||||
switch(btype)
|
||||
if(0) // radio
|
||||
var/obj/item/weapon/assembly/r_i_ptank/R = new /obj/item/weapon/assembly/r_i_ptank( src.loc )
|
||||
var/obj/item/weapon/tank/plasmatank/p3 = new /obj/item/weapon/tank/plasmatank( R )
|
||||
var/obj/item/weapon/radio/signaler/p1 = new /obj/item/weapon/radio/signaler( R )
|
||||
var/obj/item/weapon/igniter/p2 = new /obj/item/weapon/igniter( R )
|
||||
R.part1 = p1
|
||||
R.part2 = p2
|
||||
R.part3 = p3
|
||||
p1.master = R
|
||||
p2.master = R
|
||||
p3.master = R
|
||||
R.status = explosive
|
||||
p1.b_stat = 0
|
||||
p2.status = 1
|
||||
p3.gas.temperature = btemp + T0C
|
||||
//SN src = null
|
||||
|
||||
if(1) // prox
|
||||
var/obj/item/weapon/assembly/m_i_ptank/R = new /obj/item/weapon/assembly/m_i_ptank( src.loc )
|
||||
var/obj/item/weapon/tank/plasmatank/p3 = new /obj/item/weapon/tank/plasmatank( R )
|
||||
var/obj/item/weapon/prox_sensor/p1 = new /obj/item/weapon/prox_sensor( R )
|
||||
var/obj/item/weapon/igniter/p2 = new /obj/item/weapon/igniter( R )
|
||||
R.part1 = p1
|
||||
R.part2 = p2
|
||||
R.part3 = p3
|
||||
p1.master = R
|
||||
p2.master = R
|
||||
p3.master = R
|
||||
R.status = explosive
|
||||
|
||||
p3.gas.temperature = btemp +T0C
|
||||
p2.status = 1
|
||||
|
||||
|
||||
if(src.active)
|
||||
R.part1.state = 1
|
||||
R.part1.icon_state = text("motion[]", 1)
|
||||
R.c_state(1, src)
|
||||
|
||||
if(2) // time
|
||||
|
||||
var/obj/item/weapon/assembly/t_i_ptank/R = new /obj/item/weapon/assembly/t_i_ptank( src.loc )
|
||||
var/obj/item/weapon/tank/plasmatank/p3 = new /obj/item/weapon/tank/plasmatank( R )
|
||||
var/obj/item/weapon/timer/p1 = new /obj/item/weapon/timer( R )
|
||||
var/obj/item/weapon/igniter/p2 = new /obj/item/weapon/igniter( R )
|
||||
R.part1 = p1
|
||||
R.part2 = p2
|
||||
R.part3 = p3
|
||||
p1.master = R
|
||||
p2.master = R
|
||||
p3.master = R
|
||||
R.status = explosive
|
||||
|
||||
p3.gas.temperature = btemp +T0C
|
||||
p2.status = 1
|
||||
|
||||
del(src)
|
||||
return
|
||||
|
||||
/obj/proc/throwing(t_dir, rs)
|
||||
|
||||
if (src.throwspeed <= 1)
|
||||
src.throwing = 0
|
||||
src.throwspeed--
|
||||
if (rs == 0)
|
||||
rs = 1
|
||||
if (src.throwing)
|
||||
if (rs == 1)
|
||||
step(src, t_dir)
|
||||
sleep(1)
|
||||
spawn( 0 )
|
||||
throwing(t_dir, rs)
|
||||
return
|
||||
else
|
||||
if (rs > 1)
|
||||
var/t = null
|
||||
while(t < rs)
|
||||
step(src, t_dir)
|
||||
t++
|
||||
sleep(10)
|
||||
spawn( 0 )
|
||||
src.throwing(t_dir, rs)
|
||||
return
|
||||
else
|
||||
step(src, t_dir)
|
||||
sleep(10 / rs)
|
||||
spawn( 0 )
|
||||
throwing(t_dir, rs)
|
||||
return
|
||||
else
|
||||
//*****RM
|
||||
//src.density = 0
|
||||
if(istype(src, /obj/item))
|
||||
src.density = 0
|
||||
|
||||
//*****
|
||||
return
|
||||
|
||||
|
||||
//*****RM
|
||||
|
||||
/obj/Bump(atom/O)
|
||||
|
||||
if (src.throwing)
|
||||
//world<<"[src] bumped into [O] and stopped"
|
||||
src.throwing = 0
|
||||
..()
|
||||
|
||||
//*****
|
||||
/atom/proc/burn(fi_amount)
|
||||
|
||||
return
|
||||
|
||||
/atom/movable/Move()
|
||||
|
||||
var/atom/A = src.loc
|
||||
. = ..()
|
||||
src.move_speed = world.time - src.l_move_time
|
||||
src.l_move_time = world.time
|
||||
src.m_flag = 1
|
||||
if ((A != src.loc && A && A.z == src.z))
|
||||
src.last_move = get_dir(A, src.loc)
|
||||
return
|
||||
|
||||
|
||||
/proc/cleanstring(var/t)
|
||||
|
||||
var/index = findtext(t, "\n")
|
||||
while(index)
|
||||
t = copytext(t, 1, index) + "#" + copytext(t, index+1)
|
||||
index = findtext(t, "\n")
|
||||
|
||||
|
||||
index = findtext(t, "\t")
|
||||
while(index)
|
||||
t = copytext(t, 1, index) + "#" + copytext(t, index+1)
|
||||
index = findtext(t, "\t")
|
||||
|
||||
|
||||
return t
|
||||
|
||||
|
||||
/datum/config/New()
|
||||
|
||||
for(var/M in modes)
|
||||
pickprob[M] = 1
|
||||
|
||||
/datum/config/proc/pickmode()
|
||||
var/total = 0
|
||||
var/list/accum = list()
|
||||
|
||||
for(var/M in modes)
|
||||
total += pickprob[M]
|
||||
accum[M] = total
|
||||
|
||||
//world << "[M] [pickprob[M]] [accum[M]]"
|
||||
|
||||
var/r = total-(rand()*total)
|
||||
|
||||
//world << "Chosen value is [r]"
|
||||
|
||||
for(var/M in modes)
|
||||
if(pickprob[M]>0 && accum[M]>=r)
|
||||
//world << "Returning mode [M]"
|
||||
return M
|
||||
|
||||
//world << "Failed to pick gamemode in config/pickmode()"
|
||||
|
||||
return null
|
||||
|
||||
/proc/upperfirst(var/t as text)
|
||||
return uppertext(copytext(t,1,2))+copytext(t,2)
|
||||
|
||||
|
||||
@@ -0,0 +1,202 @@
|
||||
|
||||
/obj/move/airtunnel/process()
|
||||
|
||||
if (!( src.deployed ))
|
||||
return null
|
||||
else
|
||||
..()
|
||||
return
|
||||
|
||||
/obj/move/airtunnel/connector/create()
|
||||
|
||||
src.current = src
|
||||
src.next = new /obj/move/airtunnel( null )
|
||||
src.next.master = src.master
|
||||
src.next.previous = src
|
||||
spawn( 0 )
|
||||
src.next.create(36, src.y)
|
||||
return
|
||||
return
|
||||
|
||||
/obj/move/airtunnel/connector/wall/create()
|
||||
|
||||
src.current = src
|
||||
src.next = new /obj/move/airtunnel/wall( null )
|
||||
src.next.master = src.master
|
||||
src.next.previous = src
|
||||
spawn( 0 )
|
||||
src.next.create(36, src.y)
|
||||
return
|
||||
return
|
||||
|
||||
/obj/move/airtunnel/connector/wall/process()
|
||||
|
||||
return
|
||||
|
||||
/obj/move/airtunnel/wall/create(num, y_coord)
|
||||
|
||||
if (((num < 7 || (num > 14 && num < 21)) && y_coord == 72))
|
||||
src.next = new /obj/move/airtunnel( null )
|
||||
else
|
||||
src.next = new /obj/move/airtunnel/wall( null )
|
||||
src.next.master = src.master
|
||||
src.next.previous = src
|
||||
if (num > 1)
|
||||
spawn( 0 )
|
||||
src.next.create(num - 1, y_coord)
|
||||
return
|
||||
return
|
||||
|
||||
/obj/move/airtunnel/wall/move_right()
|
||||
|
||||
flick("wall-m", src)
|
||||
return ..()
|
||||
return
|
||||
|
||||
/obj/move/airtunnel/wall/move_left()
|
||||
|
||||
flick("wall-m", src)
|
||||
return ..()
|
||||
return
|
||||
|
||||
/obj/move/airtunnel/wall/process()
|
||||
|
||||
return
|
||||
|
||||
/obj/move/airtunnel/proc/move_left()
|
||||
|
||||
src.relocate(get_step(src, WEST))
|
||||
if ((src.next && src.next.deployed))
|
||||
return src.next.move_left()
|
||||
else
|
||||
return src.next
|
||||
return
|
||||
|
||||
/obj/move/airtunnel/proc/move_right()
|
||||
|
||||
src.relocate(get_step(src, EAST))
|
||||
if ((src.previous && src.previous.deployed))
|
||||
src.previous.move_right()
|
||||
return src.previous
|
||||
return
|
||||
|
||||
/obj/move/airtunnel/proc/create(num, y_coord)
|
||||
|
||||
if (y_coord == 72)
|
||||
if ((num < 7 || (num > 14 && num < 21)))
|
||||
src.next = new /obj/move/airtunnel( null )
|
||||
else
|
||||
src.next = new /obj/move/airtunnel/wall( null )
|
||||
else
|
||||
src.next = new /obj/move/airtunnel( null )
|
||||
src.next.master = src.master
|
||||
src.next.previous = src
|
||||
if (num > 1)
|
||||
spawn( 0 )
|
||||
src.next.create(num - 1, y_coord)
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
/datum/air_tunnel/air_tunnel1/New()
|
||||
|
||||
..()
|
||||
for(var/obj/move/airtunnel/A in locate(/area/airtunnel1))
|
||||
A.master = src
|
||||
A.create()
|
||||
src.connectors += A
|
||||
//Foreach goto(21)
|
||||
return
|
||||
|
||||
/datum/air_tunnel/proc/siphons()
|
||||
|
||||
switch(src.siphon_status)
|
||||
if(0.0)
|
||||
for(var/obj/machinery/atmoalter/siphs/S in locate(/area/airtunnel1))
|
||||
S.t_status = 3
|
||||
//Foreach goto(42)
|
||||
if(1.0)
|
||||
for(var/obj/machinery/atmoalter/siphs/fullairsiphon/S in locate(/area/airtunnel1))
|
||||
S.t_status = 2
|
||||
S.t_per = 1000000.0
|
||||
//Foreach goto(86)
|
||||
for(var/obj/machinery/atmoalter/siphs/scrubbers/S in locate(/area/airtunnel1))
|
||||
S.t_status = 3
|
||||
//Foreach goto(136)
|
||||
if(2.0)
|
||||
for(var/obj/machinery/atmoalter/siphs/S in locate(/area/airtunnel1))
|
||||
S.t_status = 4
|
||||
//Foreach goto(180)
|
||||
if(3.0)
|
||||
for(var/obj/machinery/atmoalter/siphs/fullairsiphon/S in locate(/area/airtunnel1))
|
||||
S.t_status = 1
|
||||
S.t_per = 1000000.0
|
||||
//Foreach goto(224)
|
||||
for(var/obj/machinery/atmoalter/siphs/scrubbers/S in locate(/area/airtunnel1))
|
||||
S.t_status = 3
|
||||
//Foreach goto(274)
|
||||
else
|
||||
return
|
||||
|
||||
/datum/air_tunnel/proc/stop()
|
||||
|
||||
src.operating = 0
|
||||
return
|
||||
|
||||
/datum/air_tunnel/proc/extend()
|
||||
|
||||
if (src.operating)
|
||||
return
|
||||
src.operating = 2
|
||||
while(src.operating == 2)
|
||||
var/ok = 1
|
||||
for(var/obj/move/airtunnel/connector/A in src.connectors)
|
||||
if (!( A.current.next ))
|
||||
src.operating = 0
|
||||
return
|
||||
if (!( A.move_left() ))
|
||||
ok = 0
|
||||
//Foreach goto(56)
|
||||
if (!( ok ))
|
||||
src.operating = 0
|
||||
else
|
||||
for(var/obj/move/airtunnel/connector/A in src.connectors)
|
||||
if (A.current)
|
||||
A.current.next.loc = get_step(A.current.loc, EAST)
|
||||
A.current = A.current.next
|
||||
A.current.deployed = 1
|
||||
else
|
||||
src.operating = 0
|
||||
//Foreach goto(150)
|
||||
sleep(20)
|
||||
return
|
||||
|
||||
/datum/air_tunnel/proc/retract()
|
||||
|
||||
if (src.operating)
|
||||
return
|
||||
src.operating = 1
|
||||
while(src.operating == 1)
|
||||
var/ok = 1
|
||||
for(var/obj/move/airtunnel/connector/A in src.connectors)
|
||||
if (A.current == A)
|
||||
src.operating = 0
|
||||
return
|
||||
if (A.current)
|
||||
A.current.loc = null
|
||||
A.current.deployed = 0
|
||||
A.current = A.current.previous
|
||||
else
|
||||
ok = 0
|
||||
//Foreach goto(56)
|
||||
if (!( ok ))
|
||||
src.operating = 0
|
||||
else
|
||||
for(var/obj/move/airtunnel/connector/A in src.connectors)
|
||||
if (!( A.current.move_right() ))
|
||||
src.operating = 0
|
||||
//Foreach goto(188)
|
||||
sleep(20)
|
||||
return
|
||||
+331
@@ -0,0 +1,331 @@
|
||||
/area
|
||||
var/fire = null
|
||||
level = null
|
||||
name = "area"
|
||||
mouse_opacity = 0
|
||||
var/lightswitch = 1
|
||||
|
||||
var/eject = null
|
||||
|
||||
var/requires_power = 1
|
||||
var/power_equip = 1
|
||||
var/power_light = 1
|
||||
var/power_environ = 1
|
||||
|
||||
var/used_equip = 0
|
||||
var/used_light = 0
|
||||
var/used_environ = 0
|
||||
|
||||
var/numturfs = 0
|
||||
var/linkarea = null
|
||||
var/area/linked = null
|
||||
var/no_air = null
|
||||
|
||||
/area/aircontrol
|
||||
name = "aircontrol"
|
||||
linkarea = "airintake"
|
||||
/area/airintake
|
||||
name = "air intake"
|
||||
/area/airtunnel1
|
||||
name = "airtunnel"
|
||||
/area/control_room
|
||||
name = "control room"
|
||||
/area/controlaccess
|
||||
name = "control access"
|
||||
/area/crew_quarters
|
||||
name = "crew quarters"
|
||||
/area/decontamination
|
||||
name = "decon"
|
||||
/area/dummy
|
||||
|
||||
/area/engine
|
||||
name = "engine"
|
||||
/area/engine_access
|
||||
name = "engine access"
|
||||
/area/escapezone
|
||||
name = "escape zone"
|
||||
/area/hallways
|
||||
name = "hallway"
|
||||
/area/hallways/centralhall
|
||||
name = "central hall"
|
||||
/area/hallways/eastairlock
|
||||
name = "east airlock"
|
||||
/area/hallways/labaccess
|
||||
name = "lab access"
|
||||
/area/hallways/loungehall
|
||||
name = "lounge hall"
|
||||
/area/lounge
|
||||
name = "lounge"
|
||||
/area/medical
|
||||
name = "medical bay"
|
||||
/area/medicalstorage
|
||||
name = "medical storage"
|
||||
/area/oxygen_storage
|
||||
name = "gas storage"
|
||||
/area/security
|
||||
name = "security"
|
||||
linkarea = "brig"
|
||||
/area/shuttle
|
||||
requires_power = 0
|
||||
name = "shuttle"
|
||||
/area/shuttle_airlock
|
||||
name = "shuttle airlock"
|
||||
/area/shuttle_prison
|
||||
name = "prison shuttle"
|
||||
requires_power = 0
|
||||
/area/sleep_area
|
||||
name = "sleep area"
|
||||
/area/solar_con
|
||||
name = "solar power control"
|
||||
/area/start
|
||||
name = "start area"
|
||||
/area/supply_station
|
||||
name = "supply station"
|
||||
/area/testlab1
|
||||
name = "testlab1"
|
||||
/area/testlab2
|
||||
name = "testlab2"
|
||||
/area/testlab3
|
||||
name = "testlab3"
|
||||
/area/testlab4
|
||||
name = "testlab4"
|
||||
/area/aux_engine
|
||||
name = "aux. engine"
|
||||
/area/toolstorage
|
||||
name = "tool storage"
|
||||
/area/tech_storage
|
||||
name = "technical storage"
|
||||
/area/toxinlab
|
||||
name = "toxin lab"
|
||||
/area/vehicles
|
||||
requires_power = 0
|
||||
/area/vehicles/shuttle1
|
||||
/area/vehicles/shuttle2
|
||||
/area/vehicles/shuttle3
|
||||
|
||||
// new areas
|
||||
|
||||
/area/sleep_area_annexe
|
||||
name = "sleep area annexe"
|
||||
/area/south_access
|
||||
name = "southern access corridor"
|
||||
/area/transport_tube
|
||||
name = "transport tube"
|
||||
/area/shuttle_docking_arm
|
||||
name = "shuttle docking arm"
|
||||
/area/secure_storage
|
||||
name = "secure stores"
|
||||
/area/emergency_storage
|
||||
name = "emergency stores"
|
||||
/area/morgue
|
||||
name = "morgue"
|
||||
/area/repair_bay
|
||||
name = "repair bay"
|
||||
/area/engine/engine_gas_storage
|
||||
name = "engine gas storage"
|
||||
/area/engine/engine_storage
|
||||
name = "engine storage"
|
||||
/area/engine/engine_hallway
|
||||
name = "engine hallway"
|
||||
/area/engine/generator
|
||||
name = "generator room"
|
||||
/area/engine/combustion
|
||||
name = "combustion chamber"
|
||||
/area/engine/engine_control
|
||||
name = "engine control"
|
||||
/area/engine/engine_mon
|
||||
name = "engine monitoring"
|
||||
/area/station_teleport
|
||||
name = "SS13 teleporter"
|
||||
/area/chapel
|
||||
name = "chapel"
|
||||
/area/attack_ship
|
||||
name = "attack ship"
|
||||
/area/security_sub
|
||||
name = "security annexe"
|
||||
/area/aux_storage
|
||||
name = "aux. storage"
|
||||
/area/eva_storage
|
||||
name = "EVA storage"
|
||||
|
||||
/area/weapon_sat
|
||||
name = "weapon sat"
|
||||
requires_power = 0
|
||||
/area/med_sat
|
||||
name = "med. sat"
|
||||
requires_power = 0
|
||||
|
||||
/area/secret_base
|
||||
name = "secret base"
|
||||
no_air = 1
|
||||
power_equip = 0
|
||||
power_light = 0
|
||||
power_environ = 0
|
||||
|
||||
/area/prison
|
||||
name = "prison"
|
||||
requires_power = 0
|
||||
|
||||
/area/control_station
|
||||
name = "control station"
|
||||
requires_power = 0
|
||||
|
||||
/area/brig
|
||||
name = "brig"
|
||||
|
||||
|
||||
|
||||
/area/New()
|
||||
|
||||
..()
|
||||
src.icon = 'alert.dmi'
|
||||
src.layer = 10
|
||||
|
||||
if(!requires_power)
|
||||
power_light = 1
|
||||
power_equip = 1
|
||||
power_environ = 1
|
||||
|
||||
spawn(5)
|
||||
for(var/turf/T in src) // count the number of turfs (for lighting calc)
|
||||
numturfs++ // spawned with a delay so turfs can finish loading
|
||||
if(no_air)
|
||||
T.oxygen = 0 // remove air if so specified for this area
|
||||
T.n2 = 0
|
||||
T.res_vars()
|
||||
|
||||
if(linkarea)
|
||||
linked = locate(text2path("/area/[linkarea]")) // area linked to this for power calcs
|
||||
|
||||
|
||||
spawn(15)
|
||||
src.power_change() // all machines set to current power level, also updates lighting icon
|
||||
|
||||
/area/vehicles/New()
|
||||
|
||||
..()
|
||||
sleep(1)
|
||||
var/obj/shut_controller/S = new /obj/shut_controller( )
|
||||
shuttles += S
|
||||
for(var/obj/move/O in src)
|
||||
S.parts += O
|
||||
O.master = S
|
||||
//Foreach goto(42)
|
||||
return
|
||||
|
||||
/area/proc/firealert()
|
||||
|
||||
if (!( src.fire ))
|
||||
src.fire = 1
|
||||
src.updateicon()
|
||||
src.mouse_opacity = 0
|
||||
for(var/obj/machinery/door/firedoor/D in src)
|
||||
if (!( D.density ))
|
||||
spawn( 0 )
|
||||
D.closefire()
|
||||
return
|
||||
//Foreach goto(74)
|
||||
return
|
||||
|
||||
|
||||
/area/proc/updateicon()
|
||||
|
||||
if( fire || eject )
|
||||
if(power_environ)
|
||||
if(fire && !eject)
|
||||
icon_state = "blue"
|
||||
else if(!fire && eject)
|
||||
icon_state = "red"
|
||||
else
|
||||
icon_state = "blue-red"
|
||||
else
|
||||
if(lightswitch && power_light)
|
||||
icon_state = null
|
||||
else
|
||||
icon_state = "dark"
|
||||
else
|
||||
if(lightswitch && power_light)
|
||||
icon_state = null
|
||||
else
|
||||
icon_state = "dark"
|
||||
|
||||
/*
|
||||
#define EQUIP 1
|
||||
#define LIGHT 2
|
||||
#define ENVIRON 3
|
||||
*/
|
||||
|
||||
/area/proc/powered(var/chan) // return true if the area has power to given channel
|
||||
if(!requires_power)
|
||||
return 1
|
||||
switch(chan)
|
||||
if(EQUIP)
|
||||
return power_equip
|
||||
if(LIGHT)
|
||||
return power_light
|
||||
if(ENVIRON)
|
||||
return power_environ
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
// called when power status changes
|
||||
|
||||
/area/proc/power_change()
|
||||
|
||||
for(var/obj/machinery/M in src) // for each machine in the area
|
||||
M.power_change() // reverify power status (to update icons etc.)
|
||||
|
||||
spawn(rand(15,25))
|
||||
src.updateicon()
|
||||
|
||||
|
||||
if(linked)
|
||||
linked.power_equip = power_equip
|
||||
linked.power_light = power_light
|
||||
linked.power_environ = power_environ
|
||||
linked.power_change()
|
||||
|
||||
|
||||
|
||||
|
||||
/area/proc/usage(var/chan)
|
||||
var/used = 0
|
||||
switch(chan)
|
||||
if(LIGHT)
|
||||
used += used_light
|
||||
if(EQUIP)
|
||||
used += used_equip
|
||||
if(ENVIRON)
|
||||
used += used_environ
|
||||
if(TOTAL)
|
||||
used += used_light + used_equip + used_environ
|
||||
|
||||
if(linked)
|
||||
return linked.usage(chan) + used
|
||||
else
|
||||
return used
|
||||
|
||||
/area/proc/clear_usage()
|
||||
if(linked)
|
||||
linked.clear_usage()
|
||||
used_equip = 0
|
||||
used_light = 0
|
||||
used_environ = 0
|
||||
|
||||
/area/proc/use_power(var/amount, var/chan)
|
||||
|
||||
switch(chan)
|
||||
if(EQUIP)
|
||||
used_equip += amount
|
||||
if(LIGHT)
|
||||
used_light += amount
|
||||
if(ENVIRON)
|
||||
used_environ += amount
|
||||
|
||||
#define LIGHTING_POWER 8 // power (W) per turf used for lighting
|
||||
|
||||
/area/proc/calc_lighting()
|
||||
if(lightswitch && power_light)
|
||||
used_light += numturfs * LIGHTING_POWER
|
||||
|
||||
+303
@@ -0,0 +1,303 @@
|
||||
/obj/blob/New(loc, var/h = 30)
|
||||
|
||||
blobs += src
|
||||
|
||||
src.health = h
|
||||
src.dir = pick(1,2,4,8)
|
||||
//world << "new blob #[blobs.len]"
|
||||
src.update()
|
||||
|
||||
..(loc)
|
||||
|
||||
/obj/blob/Del()
|
||||
blobs -= src
|
||||
//world << "del blob #[blobs.len]"
|
||||
..()
|
||||
|
||||
|
||||
/proc/bloblife()
|
||||
|
||||
if(blobs.len>0)
|
||||
|
||||
for(var/i = 1 to 25)
|
||||
|
||||
var/obj/blob/B = pick(blobs)
|
||||
|
||||
var/turf/BL = B.loc
|
||||
|
||||
for(var/atom/A in B.loc)
|
||||
A.blob_act()
|
||||
|
||||
B.Life()
|
||||
BL.buildlinks()
|
||||
|
||||
|
||||
/obj/blob/proc/Life()
|
||||
|
||||
var/turf/U = src.loc
|
||||
|
||||
if (locate(/obj/move, U))
|
||||
U = locate(/obj/move, U)
|
||||
if(U.density == 1)
|
||||
del(src)
|
||||
|
||||
if(U.poison> 200000)
|
||||
src.health -= round(U.poison/200000)
|
||||
src.update()
|
||||
|
||||
var/p = health * (U.n2/11376000 + U.oxygen/1008000 + U.co2/200)
|
||||
|
||||
if(!istype(U, /turf/space))
|
||||
p+=2
|
||||
|
||||
if(!prob(p))
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
for(var/dirn in cardinal)
|
||||
var/turf/T = get_step(src, dirn)
|
||||
|
||||
//if(istype(U, /turf/space) && istype(T, /turf/space)) // don't propagate into space
|
||||
// if( !(locate(/obj/move) in U) && !(locate(/obj/move) in T))
|
||||
// continue
|
||||
|
||||
if(istype(T.loc, /area/sleep_area) && prob(90)) // slow down growth in sleep area
|
||||
continue
|
||||
|
||||
|
||||
|
||||
var/obj/blob/B = new /obj/blob(U, src.health)
|
||||
|
||||
if(T.Enter(B,src) && !(locate(/obj/blob) in T))
|
||||
B.loc = T // open cell, so expand
|
||||
else
|
||||
if(prob(50)) // closed cell, 50% chance to not expand
|
||||
if(!locate(/obj/blob) in T)
|
||||
for(var/atom/A in T) // otherwise explode contents of turf
|
||||
A.blob_act()
|
||||
|
||||
T.blob_act()
|
||||
T.buildlinks()
|
||||
del(B)
|
||||
|
||||
/obj/blob/burn(fi_amount)
|
||||
|
||||
src.health-= round(fi_amount/500000)
|
||||
|
||||
src.update()
|
||||
|
||||
/obj/blob/ex_act(severity)
|
||||
switch(severity)
|
||||
if(1)
|
||||
del(src)
|
||||
if(2)
|
||||
src.health -= rand(20,30)
|
||||
src.update()
|
||||
if(3)
|
||||
src.health -= rand(15,25)
|
||||
src.update()
|
||||
|
||||
|
||||
/obj/blob/proc/update()
|
||||
if(health<=0)
|
||||
del(src)
|
||||
return
|
||||
if(health<10)
|
||||
icon_state = "blobc0"
|
||||
return
|
||||
if(health<20)
|
||||
icon_state = "blobb0"
|
||||
return
|
||||
icon_state = "bloba0"
|
||||
|
||||
|
||||
|
||||
/obj/blob/las_act(flag)
|
||||
|
||||
if (flag == "bullet")
|
||||
health -= 10
|
||||
update()
|
||||
else
|
||||
health -= 20
|
||||
update()
|
||||
|
||||
|
||||
/obj/blob/attackby(var/obj/item/weapon/W, var/mob/user)
|
||||
for(var/mob/O in viewers(src, null))
|
||||
O.show_message(text("\red <B>The blob has been attacked with [][] </B>", W, (user ? text(" by [].", user) : ".")), 1)
|
||||
//Foreach goto(20)
|
||||
|
||||
var/damage = W.force / 4.0
|
||||
|
||||
if(istype(W, /obj/item/weapon/weldingtool))
|
||||
var/obj/item/weapon/weldingtool/WT = W
|
||||
|
||||
if(WT.welding)
|
||||
damage = 15
|
||||
|
||||
|
||||
src.health -= damage
|
||||
src.update()
|
||||
return
|
||||
|
||||
/obj/blob/examine()
|
||||
set src in oview(1)
|
||||
|
||||
usr << "A mysterious alien blob-like organism."
|
||||
|
||||
|
||||
/proc/blob_event()
|
||||
|
||||
if(!ticker.event_time) // initial event timing
|
||||
|
||||
ticker.event_time = world.realtime + rand(200, 900) // sometime between 20s to 1m30s after round start
|
||||
|
||||
|
||||
if(world.realtime < ticker.event_time) // return if not yet reached the next event
|
||||
return
|
||||
|
||||
|
||||
switch(ticker.event)
|
||||
if(0)
|
||||
var/dat = "<FONT size = 3><B>Cent. Com. Update</B>: Biohazard Alert.</FONT><HR>"
|
||||
|
||||
dat += "Reports indicate the probable transfer of a biohazardous agent onto Spacestation 13 during the last crew deployment cycle.<BR>"
|
||||
dat += "Preliminary analysis of the organism classifies it as a level 5 biohazard. Its origin is unknown.<BR>"
|
||||
dat += "Cent. Com. has issued a directive 7-10 for SS13. The station is to be considered quarantined.<BR>"
|
||||
dat += "Orders for all SS13 personnel follows:<BR>"
|
||||
dat += " 1. Do not leave the quarantine area.<BR>"
|
||||
dat += " 2. Locate any outbreaks of the organism on the station.<BR>"
|
||||
dat += " 3. If found, use any neccesary means to contain the organism.<BR>"
|
||||
dat += " 4. Avoid damage to the capital infrastructure of the station.<BR>"
|
||||
dat += "<BR>Note in the event of a quarantine breach or uncontrolled spread of the biohazard, the directive 7-10 may be upgraded to a directive 7-12 without further notice.<BR>"
|
||||
dat += "Message ends."
|
||||
|
||||
|
||||
for(var/obj/machinery/computer/communications/C in machines)
|
||||
if(! (C.stat & (BROKEN|NOPOWER) ) )
|
||||
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( C.loc )
|
||||
P.name = "paper- 'Cent. Com. Biohazard Alert.'"
|
||||
P.info = dat
|
||||
//Foreach goto(1830)
|
||||
world << "<FONT size = 3><B>Cent. Com. Update</B>: Biohazard Alert.</FONT>"
|
||||
world << "\red Summary downloaded and printed out at all communications consoles."
|
||||
|
||||
ticker.event = 1
|
||||
|
||||
ticker.event_time = world.realtime + 600*rand(5,10) // next event 5-10 minutes later
|
||||
if(1)
|
||||
world << "<FONT size = 3><B>Cent. Com. Update</B>: Biohazard Alert.</FONT>"
|
||||
world << "\red Confirmed outbreak of level 5 biohazard aboard SS13."
|
||||
world << "\red All personnel must contain the outbreak."
|
||||
|
||||
ticker.event = 2
|
||||
ticker.event_time = world.realtime + 600 // now check every minute
|
||||
|
||||
if(2)
|
||||
if(blobs.len > 500)
|
||||
world << "<FONT size = 3><B>Cent. Com. Update</B>: Biohazard Alert.</FONT>"
|
||||
world << "\red Uncontrolled spread of the biohazard onboard the station."
|
||||
world << "\red Cent. Com, has issued a directive 7-12 for Spacestation 13."
|
||||
world << "\red Estimated time until directive implementation: 60 seconds."
|
||||
ticker.event = 3
|
||||
ticker.event_time = world.realtime + 600
|
||||
else
|
||||
ticker.event_time = world.realtime + 600
|
||||
if(3)
|
||||
ticker.event = 4
|
||||
var/turf/T = locate("landmark*blob-directive")
|
||||
|
||||
if(T)
|
||||
while(!( istype(T, /turf) ))
|
||||
T = T.loc
|
||||
else
|
||||
T = locate(45,45,1)
|
||||
|
||||
var/min = 50
|
||||
var/med = 250
|
||||
var/max = 500
|
||||
var/sw = locate(1, 1, T.z)
|
||||
var/ne = locate(world.maxx, world.maxy, T.z)
|
||||
defer_powernet_rebuild = 1
|
||||
for(var/turf/U in block(sw, ne))
|
||||
var/zone = 4
|
||||
if ((U.y <= T.y + max && U.y >= T.y - max && U.x <= T.x + max && U.x >= T.x - max))
|
||||
zone = 3
|
||||
if ((U.y <= T.y + med && U.y >= T.y - med && U.x <= T.x + med && U.x >= T.x - med))
|
||||
zone = 2
|
||||
if ((U.y <= T.y + min && U.y >= T.y - min && U.x <= T.x + min && U.x >= T.x - min))
|
||||
zone = 1
|
||||
for(var/atom/A in U)
|
||||
A.ex_act(zone)
|
||||
U.ex_act(zone)
|
||||
U.buildlinks()
|
||||
|
||||
defer_powernet_rebuild = 0
|
||||
makepowernets()
|
||||
|
||||
|
||||
|
||||
/datum/station_state/proc/count()
|
||||
for(var/turf/T in world)
|
||||
if(T.z != 1)
|
||||
continue
|
||||
|
||||
if(istype(T,/turf/station/floor))
|
||||
if(!(T:burnt))
|
||||
src.floor+=2
|
||||
else
|
||||
src.floor++
|
||||
|
||||
else if(istype(T, /turf/station/engine/floor))
|
||||
src.floor+=2
|
||||
|
||||
else if(istype(T, /turf/station/wall))
|
||||
if(T:intact)
|
||||
src.wall+=2
|
||||
else
|
||||
src.wall++
|
||||
|
||||
else if(istype(T, /turf/station/r_wall))
|
||||
if(T:intact)
|
||||
src.r_wall+=2
|
||||
else
|
||||
src.r_wall++
|
||||
|
||||
|
||||
|
||||
for(var/obj/O in world)
|
||||
if(O.z != 1)
|
||||
continue
|
||||
|
||||
if(istype(O, /obj/window))
|
||||
src.window++
|
||||
else if(istype(O, /obj/grille))
|
||||
if(!O:destroyed)
|
||||
src.grille++
|
||||
else if(istype(O, /obj/machinery/door))
|
||||
src.door++
|
||||
else if(istype(O, /obj/machinery))
|
||||
src.mach++
|
||||
|
||||
|
||||
/datum/station_state/proc/score(var/datum/station_state/result)
|
||||
|
||||
var/r1a = min( result.floor / floor, 1.0)
|
||||
var/r1b = min(result.r_wall/ r_wall, 1.0)
|
||||
var/r1c = min(result.wall / wall, 1.0)
|
||||
|
||||
var/r2a = min(result.window / window, 1.0)
|
||||
var/r2b = min(result.door / door, 1.0)
|
||||
var/r2c = min(result.grille / grille, 1.0)
|
||||
|
||||
var/r3 = min(result.mach / mach, 1.0)
|
||||
|
||||
|
||||
//world.log << "Blob scores:[r1b] [r1c] / [r2a] [r2b] [r2c] / [r3] [r1a]"
|
||||
|
||||
return (4*(r1b+r1c) + 2*(r2a+r2b+r2c) + r3+r1a)/16.0
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,801 @@
|
||||
#define REGULATE_RATE 5
|
||||
|
||||
|
||||
/obj/item/weapon/organ/proc/process()
|
||||
|
||||
return
|
||||
|
||||
/obj/item/weapon/organ/proc/receive_chem(chemical as obj)
|
||||
|
||||
return
|
||||
|
||||
/obj/item/weapon/organ/external/proc/take_damage(brute, burn)
|
||||
|
||||
if ((brute <= 0 && burn <= 0))
|
||||
return 0
|
||||
if ((src.brute_dam + src.burn_dam + brute + burn) < src.max_damage)
|
||||
src.brute_dam += brute
|
||||
src.burn_dam += burn
|
||||
else
|
||||
var/can_inflict = src.max_damage - (src.brute_dam + src.burn_dam)
|
||||
if (can_inflict)
|
||||
if ((brute > 0 && burn > 0))
|
||||
var/ratio = brute / (brute + burn)
|
||||
src.brute_dam += ratio * can_inflict
|
||||
src.burn_dam += (1 - ratio) * can_inflict
|
||||
else
|
||||
if (brute > 0)
|
||||
src.brute_dam += brute
|
||||
else
|
||||
src.burn_dam += burn
|
||||
else
|
||||
return 0
|
||||
return src.update_icon()
|
||||
return
|
||||
|
||||
/obj/item/weapon/organ/external/proc/heal_damage(brute, burn)
|
||||
|
||||
src.brute_dam = max(0, src.brute_dam - brute)
|
||||
src.burn_dam = max(0, src.brute_dam - burn)
|
||||
return update_icon()
|
||||
return
|
||||
|
||||
// new damage icon system
|
||||
// returns just the brute/burn damage code
|
||||
|
||||
/obj/item/weapon/organ/external/proc/d_i_text()
|
||||
|
||||
var/tburn = 0
|
||||
var/tbrute = 0
|
||||
|
||||
if(burn_dam ==0)
|
||||
tburn =0
|
||||
else if (src.burn_dam < (src.max_damage * 0.25 / 2))
|
||||
tburn = 1
|
||||
else if (src.burn_dam < (src.max_damage * 0.75 / 2))
|
||||
tburn = 2
|
||||
else
|
||||
tburn = 3
|
||||
|
||||
if (src.brute_dam == 0)
|
||||
tbrute = 0
|
||||
else if (src.brute_dam < (src.max_damage * 0.25 / 2))
|
||||
tbrute = 1
|
||||
else if (src.brute_dam < (src.max_damage * 0.75 / 2))
|
||||
tbrute = 2
|
||||
else
|
||||
tbrute = 3
|
||||
|
||||
return "[tbrute][tburn]"
|
||||
|
||||
// new damage icon system
|
||||
// adjusted to set d_i_state to brute/burn code only (without r_name0 as before)
|
||||
|
||||
/obj/item/weapon/organ/external/proc/update_icon()
|
||||
|
||||
var/n_is = "[d_i_text()]"
|
||||
if (n_is != src.d_i_state)
|
||||
src.d_i_state = n_is
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
return
|
||||
|
||||
/obj/substance/proc/leak(turf)
|
||||
|
||||
return
|
||||
|
||||
/obj/substance/chemical/proc/volume()
|
||||
|
||||
var/amount = 0
|
||||
for(var/item in src.chemicals)
|
||||
var/datum/chemical/C = src.chemicals[item]
|
||||
if (istype(C, /datum/chemical))
|
||||
amount += C.return_property("volume")
|
||||
//Foreach goto(24)
|
||||
return amount
|
||||
return
|
||||
|
||||
/obj/substance/chemical/proc/split(amount)
|
||||
|
||||
var/obj/substance/chemical/S = new /obj/substance/chemical( null )
|
||||
var/tot_volume = src.volume()
|
||||
if (amount > tot_volume)
|
||||
amount = tot_volume
|
||||
for(var/item in src.chemicals)
|
||||
var/C = src.chemicals[item]
|
||||
if (istype(C, /datum/chemical))
|
||||
S.chemicals[item] = C
|
||||
src.chemicals[item] = null
|
||||
//Foreach goto(60)
|
||||
return S
|
||||
else
|
||||
if (tot_volume <= 0)
|
||||
return S
|
||||
else
|
||||
for(var/item in src.chemicals)
|
||||
var/datum/chemical/C = src.chemicals[item]
|
||||
if (istype(C, /datum/chemical))
|
||||
var/datum/chemical/N = new C.type( null )
|
||||
C.copy_data(N)
|
||||
var/amt = C.return_property("volume") * amount / tot_volume
|
||||
C.moles -= amt * C.density / C.molarmass
|
||||
if (C.moles == 0)
|
||||
//C = null
|
||||
del(C)
|
||||
N.moles += amt * N.density / N.molarmass
|
||||
S.chemicals[text("[]", N.name)] = N
|
||||
//Foreach goto(161)
|
||||
return S
|
||||
return
|
||||
|
||||
/obj/substance/chemical/proc/transfer_from(var/obj/substance/chemical/S as obj, amount)
|
||||
|
||||
var/volume = src.volume()
|
||||
var/s_volume = S.volume()
|
||||
if (amount > s_volume)
|
||||
amount = s_volume
|
||||
if (src.maximum)
|
||||
if (amount > (src.maximum - volume))
|
||||
amount = src.maximum - volume
|
||||
if (amount >= s_volume)
|
||||
for(var/item in S.chemicals)
|
||||
var/datum/chemical/C = S.chemicals[item]
|
||||
if (istype(C, /datum/chemical))
|
||||
var/datum/chemical/N = null
|
||||
N = src.chemicals[item]
|
||||
if (!( N ))
|
||||
N = new C.type( null )
|
||||
C.copy_data(N)
|
||||
N.moles += C.moles
|
||||
//C = null
|
||||
del(C)
|
||||
//Foreach goto(106)
|
||||
else
|
||||
var/obj/substance/chemical/U = S.split(amount)
|
||||
for(var/item in U.chemicals)
|
||||
var/datum/chemical/C = U.chemicals[item]
|
||||
if (istype(C, /datum/chemical))
|
||||
var/datum/chemical/N = src.chemicals[item]
|
||||
if (!( N ))
|
||||
N = new C.type( null )
|
||||
C.copy_data(N)
|
||||
src.chemicals[item] = N
|
||||
N.moles += C.moles
|
||||
//C = null
|
||||
del(C)
|
||||
//Foreach goto(251)
|
||||
//U = null
|
||||
del(U)
|
||||
var/datum/chemical/C = null
|
||||
for(var/t in src.chemicals)
|
||||
C = src.chemicals[text("[]", t)]
|
||||
if (istype(C, /datum/chemical))
|
||||
C.react(src)
|
||||
//Foreach goto(403)
|
||||
return amount
|
||||
return
|
||||
|
||||
/obj/substance/chemical/proc/transfer_mob(var/mob/M as mob, amount)
|
||||
|
||||
if (!( ismob(M) ))
|
||||
return
|
||||
var/obj/substance/chemical/S = src.split(amount)
|
||||
for(var/item in S.chemicals)
|
||||
var/datum/chemical/C = S.chemicals[item]
|
||||
if (istype(C, /datum/chemical))
|
||||
C.injected(M)
|
||||
//Foreach goto(44)
|
||||
//S = null
|
||||
del(S)
|
||||
return
|
||||
|
||||
/obj/substance/chemical/proc/dropper_mob(M as mob, amount)
|
||||
|
||||
if (!( ismob(M) ))
|
||||
return
|
||||
var/obj/substance/chemical/S = src.split(amount)
|
||||
for(var/item in S.chemicals)
|
||||
var/datum/chemical/C = S.chemicals[item]
|
||||
if (istype(C, /datum/chemical))
|
||||
C.injected(M, "eye")
|
||||
//Foreach goto(44)
|
||||
//S = null
|
||||
del(S)
|
||||
return
|
||||
|
||||
/obj/substance/chemical/Del()
|
||||
|
||||
for(var/item in src.chemicals)
|
||||
//src.chemicals[item] = null
|
||||
del(src.chemicals[item])
|
||||
//Foreach goto(17)
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
/* --------------------------
|
||||
|
||||
heat = amount * temperature(abs)
|
||||
|
||||
heat is conserved between exchanges
|
||||
|
||||
---------------------------- */
|
||||
|
||||
//fractional multipliers of heat
|
||||
#define TURF_ADD_FRAC 0.95 //cooling due to release of gas into tile
|
||||
#define TURF_TAKE_FRAC 1.06 //heating due to pressurization into pipework
|
||||
|
||||
// Not used?
|
||||
/obj/substance/gas/leak(T as turf)
|
||||
|
||||
turf_add(T, src.co2 + src.oxygen + src.plasma + src.n2)
|
||||
return
|
||||
|
||||
/obj/substance/gas/proc/tot_gas()
|
||||
|
||||
return src.co2 + src.oxygen + src.plasma + src.sl_gas + src.n2
|
||||
return
|
||||
|
||||
/obj/substance/gas/proc/transfer_from(var/obj/substance/gas/target as obj, amount)
|
||||
|
||||
if ((!( istype(target, /obj/substance/gas) ) || !( amount )))
|
||||
return
|
||||
var/t1 = target.co2 + target.oxygen + target.plasma + target.sl_gas + target.n2
|
||||
if (!( t1 ))
|
||||
return
|
||||
if (amount > t1)
|
||||
amount = t1
|
||||
var/t2 = src.co2 + src.oxygen + src.plasma + src.sl_gas + src.n2
|
||||
if (amount < 0)
|
||||
amount = t1
|
||||
if ((src.maximum > 0 && (src.maximum - t2) < amount))
|
||||
amount = src.maximum - t2
|
||||
var/t_oxy = amount * target.oxygen / t1
|
||||
var/t_pla = amount * target.plasma / t1
|
||||
var/t_co2 = amount * target.co2 / t1
|
||||
var/t_sl_gas = amount * target.sl_gas / t1
|
||||
var/t_n2 = amount * target.n2 / t1
|
||||
var/t3 = t1 + t2
|
||||
var/t4 = t2 * src.temperature
|
||||
var/t5 = t1 * target.temperature
|
||||
if (t3 > 0)
|
||||
src.temperature = (t4 + t5) / t3
|
||||
src.co2 += t_co2
|
||||
src.oxygen += t_oxy
|
||||
src.plasma += t_pla
|
||||
src.sl_gas += t_sl_gas
|
||||
src.n2 += t_n2
|
||||
target.oxygen -= t_oxy
|
||||
target.co2 -= t_co2
|
||||
target.plasma -= t_pla
|
||||
target.sl_gas -= t_sl_gas
|
||||
target.n2 -= t_n2
|
||||
return
|
||||
|
||||
/obj/substance/gas/proc/clear()
|
||||
|
||||
src.oxygen = 0
|
||||
src.plasma = 0
|
||||
src.co2 = 0
|
||||
src.sl_gas = 0
|
||||
src.n2 = 0
|
||||
return
|
||||
|
||||
/obj/substance/gas/proc/has_gas()
|
||||
|
||||
return (src.co2 + src.oxygen + src.plasma + src.sl_gas + src.n2) > 0
|
||||
return
|
||||
|
||||
/obj/substance/gas/proc/turf_add(var/turf/target as turf, amount)
|
||||
|
||||
if (((!( istype(target, /turf) ) && !( istype(target, /obj/move) )) || !( amount )))
|
||||
return
|
||||
if (locate(/obj/move, target))
|
||||
target = locate(/obj/move, target)
|
||||
var/t2 = src.co2 + src.oxygen + src.plasma + src.sl_gas + src.n2
|
||||
if (amount < 0)
|
||||
amount = src.plasma + src.oxygen + src.co2 + src.sl_gas + src.n2
|
||||
if (!( t2 ))
|
||||
return
|
||||
var/t_oxy = amount * src.oxygen / t2
|
||||
var/t_pla = amount * src.plasma / t2
|
||||
var/t_co2 = amount * src.co2 / t2
|
||||
var/t_sl_gas = amount * src.sl_gas / t2
|
||||
var/t_n2 = amount * src.n2 / t2
|
||||
|
||||
src.co2 -= t_co2
|
||||
src.oxygen -= t_oxy
|
||||
src.plasma -= t_pla
|
||||
src.sl_gas -= t_sl_gas
|
||||
src.n2 -= t_n2
|
||||
|
||||
var/ttotal = target.tot_gas()
|
||||
|
||||
target.oxygen += t_oxy
|
||||
target.co2 += t_co2
|
||||
target.poison += t_pla
|
||||
target.sl_gas += t_sl_gas
|
||||
target.n2 += t_n2
|
||||
|
||||
target.temp = ( target.temp * ttotal + (amount * temperature)*TURF_ADD_FRAC ) / (ttotal + amount)
|
||||
//target.heat += amount * src.temperature
|
||||
target.res_vars()
|
||||
|
||||
return
|
||||
|
||||
/obj/substance/gas/proc/turf_add_all_oxy(var/turf/target as turf)
|
||||
|
||||
var/t_gas = tot_gas()
|
||||
var/t_turf = target.tot_gas()
|
||||
|
||||
if(t_gas>0)
|
||||
|
||||
var/heat_change = oxygen * temperature
|
||||
|
||||
//target.heat += heat_change
|
||||
if( (t_turf + oxygen) >0 )
|
||||
target.temp = ( target.temp * t_turf + heat_change ) / ( t_turf + oxygen )
|
||||
|
||||
target.oxygen += oxygen
|
||||
|
||||
|
||||
var/nonoxy = tot_gas() - oxygen
|
||||
|
||||
if(nonoxy>0)
|
||||
|
||||
temperature = ( temperature * tot_gas() - heat_change )/(nonoxy)
|
||||
else
|
||||
temperature = T20C
|
||||
|
||||
oxygen = 0
|
||||
target.res_vars()
|
||||
|
||||
return
|
||||
|
||||
/obj/substance/gas/proc/turf_take(var/turf/target as turf, amount)
|
||||
|
||||
if (((!( istype(target, /turf) ) && !( istype(target, /obj/move) )) || !( amount )))
|
||||
return
|
||||
if (locate(/obj/move, target))
|
||||
target = locate(/obj/move, target)
|
||||
|
||||
var/t1 = target.co2 + target.oxygen + target.poison + target.sl_gas + target.n2
|
||||
if (!( t1 ))
|
||||
return
|
||||
var/t2 = src.co2 + src.oxygen + src.plasma + src.sl_gas + src.n2
|
||||
|
||||
if (amount > 0)
|
||||
if ((src.maximum > 0 && (src.maximum - t2) < amount))
|
||||
amount = src.maximum - t2
|
||||
else
|
||||
amount = src.plasma + src.oxygen + src.co2 + src.sl_gas + src.n2
|
||||
|
||||
if (amount > t1)
|
||||
amount = t1
|
||||
|
||||
var/turf_total = target.poison + target.oxygen + target.co2 + target.sl_gas + target.n2
|
||||
|
||||
// var/heat_gain = (turf_total ? amount / turf_total * target.heat : 0)
|
||||
// var/temp_gain = (turf_total ? target.heat / turf_total : 0)
|
||||
|
||||
var/heat_gain = (turf_total ? amount * target.temp : 0)
|
||||
|
||||
|
||||
var/t_oxy = amount * target.oxygen / t1
|
||||
var/t_pla = amount * target.poison / t1
|
||||
var/t_co2 = amount * target.co2 / t1
|
||||
var/t_sl_gas = amount * target.sl_gas / t1
|
||||
var/t_n2 = amount * target.n2 / t1
|
||||
|
||||
|
||||
/*
|
||||
|
||||
var/t3 = t1 + t2
|
||||
var/t4 = t2 * src.temperature
|
||||
var/t5 = t1 * temp_gain
|
||||
if (t3 > 0)
|
||||
src.temperature = (t4 + t5) / t3
|
||||
else
|
||||
src.temperature = 0
|
||||
*/
|
||||
if(t2+amount>0)
|
||||
temperature = (temperature*t2 + heat_gain * TURF_TAKE_FRAC)/(t2+amount)
|
||||
|
||||
|
||||
src.co2 += t_co2
|
||||
src.oxygen += t_oxy
|
||||
src.plasma += t_pla
|
||||
src.sl_gas += t_sl_gas
|
||||
src.n2 += t_n2
|
||||
|
||||
target.oxygen -= t_oxy
|
||||
target.co2 -= t_co2
|
||||
target.poison -= t_pla
|
||||
target.sl_gas -= t_sl_gas
|
||||
target.n2 -= t_n2
|
||||
//target.heat -= heat_gain // no temp change; we just take a proportional amount of all gases
|
||||
target.res_vars()
|
||||
return
|
||||
|
||||
/* original version
|
||||
/obj/substance/gas/proc/extract_toxs(var/turf/target as turf)
|
||||
|
||||
if ((!( istype(target, /turf) ) && !( istype(target, /obj/move) )))
|
||||
return
|
||||
if (locate(/obj/move, target))
|
||||
target = locate(/obj/move, target)
|
||||
var/co2_diff = target.co2 - 0
|
||||
var/oxy_diff = target.oxygen - O2STANDARD
|
||||
var/no2_diff = target.sl_gas - 0
|
||||
var/n2_diff = target.n2 - N2STANDARD
|
||||
var/plas_diff = target.poison - 0
|
||||
if (co2_diff < 0)
|
||||
co2_diff = 0
|
||||
if (oxy_diff < 0)
|
||||
oxy_diff = 0
|
||||
if (no2_diff < 0)
|
||||
no2_diff = 0
|
||||
if (n2_diff < 0)
|
||||
n2_diff = 0
|
||||
if (plas_diff < 0)
|
||||
plas_diff = 0
|
||||
var/turf_total = target.poison + target.oxygen + target.co2 + target.sl_gas + target.n2
|
||||
var/air_total = co2_diff + oxy_diff + no2_diff + n2_diff + plas_diff
|
||||
var/heat_gain = (turf_total ? air_total / turf_total * target.heat : null)
|
||||
var/temp_gain = (turf_total ? target.heat / turf_total + TD0 : 0)
|
||||
src.co2 += co2_diff
|
||||
src.oxygen += oxy_diff
|
||||
src.sl_gas += no2_diff
|
||||
src.n2 += n2_diff
|
||||
src.plasma += plas_diff
|
||||
target.co2 -= co2_diff
|
||||
target.oxygen -= oxy_diff
|
||||
target.sl_gas -= no2_diff
|
||||
target.n2 -= n2_diff
|
||||
target.poison -= plas_diff
|
||||
var/t3 = turf_total + air_total
|
||||
var/t4 = turf_total * src.temperature
|
||||
var/t5 = air_total * temp_gain
|
||||
if (t3 > 0)
|
||||
src.temperature = (t4 + t5) / t3
|
||||
else
|
||||
src.temperature = 0
|
||||
target.heat -= heat_gain
|
||||
target.res_vars()
|
||||
return
|
||||
*/
|
||||
|
||||
|
||||
|
||||
// modified version
|
||||
/obj/substance/gas/proc/extract_toxs(var/turf/target as turf)
|
||||
if ((!( istype(target, /turf) ) && !( istype(target, /obj/move) )))
|
||||
return
|
||||
if (locate(/obj/move, target))
|
||||
target = locate(/obj/move, target)
|
||||
var/co2_diff = max(0, target.co2 - 0)
|
||||
var/oxy_diff = max(0,target.oxygen - O2STANDARD)
|
||||
var/no2_diff = max(0, target.sl_gas - 0)
|
||||
var/n2_diff = max(0,target.n2 - N2STANDARD)
|
||||
var/plas_diff = max(0,target.poison - 0)
|
||||
|
||||
var/turf_total = target.poison + target.oxygen + target.co2 + target.sl_gas + target.n2
|
||||
var/air_total = co2_diff + oxy_diff + no2_diff + n2_diff + plas_diff
|
||||
|
||||
|
||||
var/heat_gain = (turf_total ? air_total * target.temp : null)
|
||||
//var/temp_gain = (turf_total ? target.heat / turf_total + TD0 : 0)
|
||||
|
||||
src.co2 += co2_diff
|
||||
src.oxygen += oxy_diff
|
||||
src.sl_gas += no2_diff
|
||||
src.n2 += n2_diff
|
||||
src.plasma += plas_diff
|
||||
|
||||
target.co2 -= co2_diff
|
||||
target.oxygen -= oxy_diff
|
||||
target.sl_gas -= no2_diff
|
||||
target.n2 -= n2_diff
|
||||
target.poison -= plas_diff
|
||||
|
||||
|
||||
var/gasheat1 = temperature * tot_gas()
|
||||
var/gastot2 = tot_gas() + air_total
|
||||
|
||||
if(gastot2 > 0)
|
||||
temperature = (gasheat1 + heat_gain)/( gastot2 )
|
||||
else
|
||||
temperature = T20C
|
||||
|
||||
var/turftot2 = turf_total - air_total
|
||||
if(turftot2>0)
|
||||
target.temp = ( target.temp*turf_total - heat_gain)/(turftot2)
|
||||
|
||||
//target.heat -= heat_gain
|
||||
|
||||
//make stored temperature closer to nominal (20C)
|
||||
src.temperature += (T20C - src.temperature) / REGULATE_RATE
|
||||
|
||||
|
||||
target.res_vars()
|
||||
return
|
||||
|
||||
//
|
||||
|
||||
|
||||
/obj/substance/gas/proc/merge_into(var/obj/substance/gas/target as obj)
|
||||
|
||||
if (!( istype(target, /obj/substance/gas) ))
|
||||
return
|
||||
var/s_tot = src.tot_gas()
|
||||
var/t_tot = target.tot_gas()
|
||||
var/amount = s_tot + t_tot
|
||||
if (amount > 0 && t_tot > 0)
|
||||
src.temperature = (s_tot*src.temperature + t_tot*target.temperature) / amount
|
||||
|
||||
src.co2 += target.co2
|
||||
src.oxygen += target.oxygen
|
||||
src.plasma += target.plasma
|
||||
src.sl_gas += target.sl_gas
|
||||
src.n2 += target.n2
|
||||
target.oxygen = 0
|
||||
target.plasma = 0
|
||||
target.co2 = 0
|
||||
target.sl_gas = 0
|
||||
target.n2 = 0
|
||||
return
|
||||
|
||||
|
||||
// sets src to a given fraction of the gas (without affecting the gas)
|
||||
/obj/substance/gas/proc/set_frac(var/obj/substance/gas/gas, amount)
|
||||
|
||||
var/tot = gas.tot_gas()
|
||||
|
||||
if(tot>0) // if gas is 0, do nothing
|
||||
|
||||
var/frac = amount / tot
|
||||
|
||||
src.oxygen = frac * gas.oxygen
|
||||
src.co2 = frac * gas.co2
|
||||
src.plasma = frac * gas.plasma
|
||||
src.sl_gas = frac * gas.sl_gas
|
||||
src.n2 = frac * gas.n2
|
||||
|
||||
src.temperature = gas.temperature
|
||||
|
||||
|
||||
// same as merge_into except the target is not zeroed
|
||||
// calc temperature from added gas
|
||||
// delta should always be positive
|
||||
/obj/substance/gas/proc/add_delta(var/obj/substance/gas/target)
|
||||
|
||||
|
||||
var/s_tot = src.tot_gas()
|
||||
var/t_tot = target.tot_gas()
|
||||
|
||||
if(t_tot < 0)
|
||||
world.log << "Called add_delta with negative delta: [src.loc] : [src.tostring()] + [target.tostring()]"
|
||||
|
||||
var/amount = s_tot + t_tot
|
||||
if (amount>0) // only set temp if adding gas, not subtracting
|
||||
src.temperature = (s_tot*src.temperature + t_tot*target.temperature) / amount
|
||||
|
||||
src.co2 += target.co2
|
||||
src.oxygen += target.oxygen
|
||||
src.plasma += target.plasma
|
||||
src.sl_gas += target.sl_gas
|
||||
src.n2 += target.n2
|
||||
|
||||
|
||||
// subtract a (+ve) delta. Do not affect temperature since just a proportional change
|
||||
/obj/substance/gas/proc/sub_delta(var/obj/substance/gas/target)
|
||||
|
||||
src.co2 -= target.co2
|
||||
src.oxygen -= target.oxygen
|
||||
src.plasma -= target.plasma
|
||||
src.sl_gas -= target.sl_gas
|
||||
src.n2 -= target.n2
|
||||
|
||||
|
||||
|
||||
|
||||
// replaces gas values of src with n - updates during gas_flow step
|
||||
/obj/substance/gas/proc/replace_by(var/obj/substance/gas/n)
|
||||
oxygen = n.oxygen
|
||||
plasma = n.plasma
|
||||
sl_gas = n.sl_gas
|
||||
co2 = n.co2
|
||||
n2 = n.n2
|
||||
temperature = n.temperature
|
||||
|
||||
//do nothing to values of n
|
||||
|
||||
// relative "specific heat capacity" of gas contents
|
||||
/obj/substance/gas/proc/shc()
|
||||
return 2*co2 + 1.5*n2 + oxygen + 0.5*sl_gas + 1.2*plasma
|
||||
|
||||
|
||||
/obj/substance/gas/proc/tostring()
|
||||
return "Tot: [src.tot_gas()] ; [oxygen]/[n2]/#[plasma]/[co2]/[sl_gas] ; Temp:[temperature]"
|
||||
|
||||
|
||||
/turf/proc/tostring()
|
||||
var/obj/substance/gas/G = src.get_gas()
|
||||
return G.tostring()
|
||||
|
||||
/datum/chemical/pathogen/proc/process(source as obj)
|
||||
|
||||
return
|
||||
|
||||
/datum/chemical/proc/react(S as obj)
|
||||
|
||||
return
|
||||
|
||||
/datum/chemical/proc/react_organ(O as obj)
|
||||
|
||||
return
|
||||
|
||||
/datum/chemical/proc/injected(M as mob, zone)
|
||||
|
||||
if (zone == null)
|
||||
zone = "body"
|
||||
return
|
||||
|
||||
/datum/chemical/proc/copy_data(var/datum/chemical/C)
|
||||
|
||||
C.molarmass = src.molarmass
|
||||
C.density = src.density
|
||||
C.chem_formula = src.chem_formula
|
||||
return
|
||||
|
||||
/datum/chemical/proc/return_property(property)
|
||||
|
||||
switch(property)
|
||||
if("moles")
|
||||
return src.moles
|
||||
if("mass")
|
||||
return src.moles * src.molarmass
|
||||
if("density")
|
||||
return src.density
|
||||
if("volume")
|
||||
return src.moles * src.molarmass / src.density
|
||||
else
|
||||
return
|
||||
|
||||
/datum/chemical/pl_coag/react(obj/substance/chemical/S as obj)
|
||||
|
||||
var/datum/chemical/l_plas/C = S.chemicals["plasma-l"]
|
||||
if (istype(C, /datum/chemical/l_plas))
|
||||
if (C.moles < src.moles)
|
||||
src.moles -= C.moles
|
||||
var/datum/chemical/waste/W = S.chemicals["waste-l"]
|
||||
if (istype(W, /datum/chemical/waste))
|
||||
W.moles += C.moles
|
||||
else
|
||||
W = new /datum/chemical/waste( )
|
||||
S.chemicals["waste-l"] = W
|
||||
W.moles += C.moles
|
||||
//C = null
|
||||
del(C)
|
||||
else
|
||||
C.moles -= src.moles
|
||||
var/datum/chemical/waste/W = S.chemicals["waste-l"]
|
||||
if (istype(W, /datum/chemical/waste))
|
||||
W.moles += src.moles
|
||||
else
|
||||
W = new /datum/chemical/waste( )
|
||||
S.chemicals["waste-l"] = W
|
||||
W.moles += src.moles
|
||||
src.moles = 0
|
||||
if (src.moles <= 0)
|
||||
//SN src = null
|
||||
del(src)
|
||||
return
|
||||
return
|
||||
|
||||
/datum/chemical/pl_coag/injected(var/mob/M as mob, zone)
|
||||
|
||||
var/volume = src.return_property("volume")
|
||||
switch(zone)
|
||||
if("eye")
|
||||
M.eye_stat -= volume * 2
|
||||
M.eye_stat = max(0, M.eye_stat)
|
||||
else
|
||||
if (M.health >= 0)
|
||||
if ((volume * 4) >= M.toxloss)
|
||||
M.toxloss = 0
|
||||
else
|
||||
M.toxloss -= volume * 4
|
||||
M.antitoxs += volume * 180
|
||||
M.health = 100 - M.oxyloss - M.toxloss - M.fireloss - M.bruteloss
|
||||
return
|
||||
|
||||
/datum/chemical/l_plas/injected(var/mob/M as mob, zone)
|
||||
|
||||
var/volume = src.return_property("volume")
|
||||
switch(zone)
|
||||
if("eye")
|
||||
M.eye_stat += volume * 5
|
||||
M.eye_blurry += volume * 3
|
||||
if (M.eye_stat >= 20)
|
||||
M << "\red Your eyes start to burn badly!"
|
||||
M.disabilities |= 1
|
||||
if (prob(M.eye_stat - 20 + 1))
|
||||
M << "\red You go blind!"
|
||||
M.sdisabilities |= 1
|
||||
else
|
||||
M.plasma += volume * 6
|
||||
for(var/obj/item/weapon/implant/tracking/T in M)
|
||||
M.plasma += 1
|
||||
//T = null
|
||||
del(T)
|
||||
//Foreach goto(133)
|
||||
return
|
||||
|
||||
/datum/chemical/s_tox/injected(var/mob/M as mob, zone)
|
||||
|
||||
var/volume = src.return_property("volume")
|
||||
switch(zone)
|
||||
if("eye")
|
||||
M.eye_blind += volume * 10
|
||||
M.eye_blurry += volume * 15
|
||||
else
|
||||
M.paralysis += volume * 12
|
||||
M.stat = 1
|
||||
return
|
||||
|
||||
/datum/chemical/epil/injected(var/mob/M as mob, zone)
|
||||
|
||||
var/volume = src.return_property("volume")
|
||||
switch(zone)
|
||||
if("eye")
|
||||
M.eye_blind += volume * 5
|
||||
M.eye_stat += volume * 2
|
||||
M.eye_blurry += volume * 20
|
||||
if (M.eye_stat >= 20)
|
||||
M << "\red Your eyes start to burn badly!"
|
||||
M.disabilities |= 1
|
||||
if (prob(M.eye_stat - 20 + 1))
|
||||
M << "\red You go blind!"
|
||||
M.sdisabilities |= 1
|
||||
else
|
||||
M.r_epil += volume * 60
|
||||
return
|
||||
|
||||
/datum/chemical/ch_cou/injected(var/mob/M as mob, zone)
|
||||
|
||||
var/volume = src.return_property("volume")
|
||||
switch(zone)
|
||||
if("eye")
|
||||
M.eye_blind += volume * 2
|
||||
M.eye_stat += volume * 3
|
||||
M.eye_blurry += volume * 20
|
||||
M << "\red Your eyes start to burn badly!"
|
||||
M.disabilities |= 1
|
||||
if (prob(M.eye_stat - 20 + 1))
|
||||
M << "\red You go blind!"
|
||||
M.sdisabilities |= 1
|
||||
else
|
||||
M.r_ch_cou += volume * 60
|
||||
return
|
||||
|
||||
/datum/chemical/rejuv/injected(var/mob/M as mob, zone)
|
||||
|
||||
var/volume = src.return_property("volume")
|
||||
switch(zone)
|
||||
if("eye")
|
||||
M.eye_stat -= volume * 5
|
||||
M.eye_blurry += volume * 5
|
||||
M.eye_stat = max(0, M.eye_stat)
|
||||
else
|
||||
M.rejuv += volume * 3
|
||||
if (M.paralysis)
|
||||
M.paralysis = 3
|
||||
if (M.weakened)
|
||||
M.weakened = 3
|
||||
if (M.stunned)
|
||||
M.stunned = 3
|
||||
return
|
||||
@@ -0,0 +1,193 @@
|
||||
|
||||
/proc/colour2html(colour)
|
||||
var/T
|
||||
for(T in html_colours)
|
||||
if (ckey(T) == ckey(colour))
|
||||
else
|
||||
//Foreach continue //goto(12)
|
||||
if (!( T ))
|
||||
world.log << text("Warning! Could not find matching colour entry for '[]'.", colour)
|
||||
return "#FFFFFF"
|
||||
return "#" + uppertext(html_colours[text("[]", colour)])
|
||||
return
|
||||
|
||||
/proc/HTMLAssociate(colour, html)
|
||||
|
||||
if (html_colours.Find(colour))
|
||||
world.log << text("Changing [] from [] to []!", colour, html_colours[colour], html)
|
||||
html_colours[colour] = html
|
||||
return
|
||||
|
||||
/proc/LoadHTMLAssociations()
|
||||
|
||||
var/F = new /savefile( "s_html.sav" )
|
||||
F["html_colours"] >> html_colours
|
||||
if (!( html_colours ))
|
||||
html_colours = list( )
|
||||
if (!( html_colours.len ))
|
||||
HTMLAssociate("aliceblue", "f0f8ff")
|
||||
HTMLAssociate("antiquewhite", "faebd7")
|
||||
HTMLAssociate("aqua", "00ffff")
|
||||
HTMLAssociate("aquamarine", "7fffd4")
|
||||
HTMLAssociate("azure", "f0ffff")
|
||||
HTMLAssociate("beige", "f5f5dc")
|
||||
HTMLAssociate("bisque", "ffe4c4")
|
||||
HTMLAssociate("black", "000000")
|
||||
HTMLAssociate("blanchedalmond", "ffebcd")
|
||||
HTMLAssociate("blue", "0000ff")
|
||||
HTMLAssociate("blueviolet", "8a2be2")
|
||||
HTMLAssociate("brown", "a52a2a")
|
||||
HTMLAssociate("burlywood", "deb887")
|
||||
HTMLAssociate("cadetblue", "5f9ea0")
|
||||
HTMLAssociate("chartreuse", "7fff00")
|
||||
HTMLAssociate("chocolate", "d2691e")
|
||||
HTMLAssociate("coral", "ff7f50")
|
||||
HTMLAssociate("cornflowerblue", "6495ed")
|
||||
HTMLAssociate("cornsilk", "fff8dc")
|
||||
HTMLAssociate("crimson", "dc143c")
|
||||
HTMLAssociate("cyan", "00ffff")
|
||||
HTMLAssociate("darkblue", "00008b")
|
||||
HTMLAssociate("darkcyan", "008b8b")
|
||||
HTMLAssociate("darkgoldenrod", "b8b60b")
|
||||
HTMLAssociate("darkgrey", "a9a9a9")
|
||||
HTMLAssociate("darkgray", "a9a9a9")
|
||||
HTMLAssociate("darkgreen", "006400")
|
||||
HTMLAssociate("darkkhaki", "bdb76b")
|
||||
HTMLAssociate("darkmagenta", "8b008b")
|
||||
HTMLAssociate("darkolivegreen", "556b2f")
|
||||
HTMLAssociate("darkorange", "ff8c00")
|
||||
HTMLAssociate("darkorchid", "9932cc")
|
||||
HTMLAssociate("darkred", "8b0000")
|
||||
HTMLAssociate("darksalmon", "e9967a")
|
||||
HTMLAssociate("darkseagreen", "8fbc8f")
|
||||
HTMLAssociate("darkslateblue", "483d8b")
|
||||
HTMLAssociate("darkslategrey", "2f4f4f")
|
||||
HTMLAssociate("darkslategray", "2f4f4f")
|
||||
HTMLAssociate("darkturquoise", "00ced1")
|
||||
HTMLAssociate("darkviolet", "9400d3")
|
||||
HTMLAssociate("deeppink", "ff1493")
|
||||
HTMLAssociate("deepskyblue", "00bfff")
|
||||
HTMLAssociate("dimgrey", "696969")
|
||||
HTMLAssociate("dimgray", "696969")
|
||||
HTMLAssociate("dodgerblue", "1e90ff")
|
||||
HTMLAssociate("firebrick", "b22222")
|
||||
HTMLAssociate("floralwhite", "fffaf0")
|
||||
HTMLAssociate("forestgreen", "228b22")
|
||||
HTMLAssociate("fuchsia", "ff00ff")
|
||||
HTMLAssociate("gainsboro", "dcdcdc")
|
||||
HTMLAssociate("ghostwhite", "f8f8ff")
|
||||
HTMLAssociate("gold", "ffd700")
|
||||
HTMLAssociate("goldenrod", "daa520")
|
||||
HTMLAssociate("grey", "808080")
|
||||
HTMLAssociate("gray", "808080")
|
||||
HTMLAssociate("green", "008000")
|
||||
HTMLAssociate("greenyellow", "adff2f")
|
||||
HTMLAssociate("honeydew", "f0fff0")
|
||||
HTMLAssociate("hotpink", "ff69b4")
|
||||
HTMLAssociate("indianred", "cd5c5c")
|
||||
HTMLAssociate("indigo", "4b0082")
|
||||
HTMLAssociate("ivory", "fffff0")
|
||||
HTMLAssociate("khaki", "f0e68c")
|
||||
HTMLAssociate("lavender", "e6e6fa")
|
||||
HTMLAssociate("lavenderblush", "fff0f5")
|
||||
HTMLAssociate("lawngreen", "7cfc00")
|
||||
HTMLAssociate("lemonchiffon", "fffacd")
|
||||
HTMLAssociate("lightblue", "add8e6")
|
||||
HTMLAssociate("lightcoral", "f08080")
|
||||
HTMLAssociate("lightcyan", "e0ffff")
|
||||
HTMLAssociate("lightgoldenrod", "fafad2")
|
||||
HTMLAssociate("lightgreen", "90ee90")
|
||||
HTMLAssociate("lightgrey", "d3d3d3")
|
||||
HTMLAssociate("lightgray", "d3d3d3")
|
||||
HTMLAssociate("lightpink", "ffb6c1")
|
||||
HTMLAssociate("lightsalmon", "ffa07a")
|
||||
HTMLAssociate("lightseagreen", "20b2aa")
|
||||
HTMLAssociate("lightskyblue", "87cefa")
|
||||
HTMLAssociate("lightslategrey", "778899")
|
||||
HTMLAssociate("lightslategray", "778899")
|
||||
HTMLAssociate("lightsteelblue", "b0c4de")
|
||||
HTMLAssociate("lightyellow", "ffffe0")
|
||||
HTMLAssociate("lime", "00ff00")
|
||||
HTMLAssociate("limegreen", "32cd32")
|
||||
HTMLAssociate("linen", "faf0e6")
|
||||
HTMLAssociate("magenta", "ff00ff")
|
||||
HTMLAssociate("maroon", "800000")
|
||||
HTMLAssociate("mediumaquamarine", "66cdaa")
|
||||
HTMLAssociate("mediumblue", "0000cd")
|
||||
HTMLAssociate("mediumorchid", "ba55d3")
|
||||
HTMLAssociate("mediumpurple", "9370db")
|
||||
HTMLAssociate("mediumseagreen", "3cb371")
|
||||
HTMLAssociate("mediumslateblue", "7b68ee")
|
||||
HTMLAssociate("mediumspringgreen", "00fa9a")
|
||||
HTMLAssociate("mediumturquoise", "48d1cc")
|
||||
HTMLAssociate("mediumvioletred", "c71585")
|
||||
HTMLAssociate("midnightblue", "191970")
|
||||
HTMLAssociate("mintcream", "f5fffa")
|
||||
HTMLAssociate("mistyrose", "ffe4e1")
|
||||
HTMLAssociate("moccasin", "ffe4b5")
|
||||
HTMLAssociate("navajowhite", "ffdead")
|
||||
HTMLAssociate("navy", "000080")
|
||||
HTMLAssociate("oldlace", "fdf5e6")
|
||||
HTMLAssociate("olive", "808000")
|
||||
HTMLAssociate("olivedrab", "6b8e23")
|
||||
HTMLAssociate("orange", "ffa500")
|
||||
HTMLAssociate("orangered", "ff4500")
|
||||
HTMLAssociate("orchid", "da70d6")
|
||||
HTMLAssociate("palegoldenrod", "eee8aa")
|
||||
HTMLAssociate("palegreen", "98fb98")
|
||||
HTMLAssociate("paleturquoise", "afeeee")
|
||||
HTMLAssociate("palevioletred", "db7093")
|
||||
HTMLAssociate("papayawhip", "ffefd5")
|
||||
HTMLAssociate("peachpuff", "ffdab9")
|
||||
HTMLAssociate("peru", "cd853f")
|
||||
HTMLAssociate("pink", "ffc0cd")
|
||||
HTMLAssociate("plum", "dda0dd")
|
||||
HTMLAssociate("powderblue", "b0e0e6")
|
||||
HTMLAssociate("purple", "800080")
|
||||
HTMLAssociate("red", "ff0000")
|
||||
HTMLAssociate("rosybrown", "bc8f8f")
|
||||
HTMLAssociate("royalblue", "4169e1")
|
||||
HTMLAssociate("saddlebrown", "8b4513")
|
||||
HTMLAssociate("salmon", "fa8072")
|
||||
HTMLAssociate("sandybrown", "f4a460")
|
||||
HTMLAssociate("seagreen", "2e8b57")
|
||||
HTMLAssociate("seashell", "fff5ee")
|
||||
HTMLAssociate("sienna", "a0522d")
|
||||
HTMLAssociate("silver", "c0c0c0")
|
||||
HTMLAssociate("skyblue", "87ceed")
|
||||
HTMLAssociate("slateblue", "6a5acd")
|
||||
HTMLAssociate("slategrey", "708090")
|
||||
HTMLAssociate("slategray", "708090")
|
||||
HTMLAssociate("snow", "fffafa")
|
||||
HTMLAssociate("springgreen", "00ff7f")
|
||||
HTMLAssociate("steelblue", "4682b4")
|
||||
HTMLAssociate("tan", "d2b48c")
|
||||
HTMLAssociate("teal", "008080")
|
||||
HTMLAssociate("thistle", "d8bfd8")
|
||||
HTMLAssociate("tomato", "ff6347")
|
||||
HTMLAssociate("turquoise", "40e0d0")
|
||||
HTMLAssociate("violet", "ee82ee")
|
||||
HTMLAssociate("wheat", "f5deb3")
|
||||
HTMLAssociate("white", "ffffff")
|
||||
HTMLAssociate("whitesmoke", "f5f5f5")
|
||||
HTMLAssociate("yellow", "ffff00")
|
||||
HTMLAssociate("yellowgreen", "a9cd32")
|
||||
return
|
||||
|
||||
/proc/SaveHTMLAssociations()
|
||||
|
||||
var/F = new /savefile( "s_html.sav" )
|
||||
F["html_colours"] << html_colours
|
||||
return
|
||||
|
||||
/world/New()
|
||||
|
||||
..()
|
||||
LoadHTMLAssociations()
|
||||
return
|
||||
|
||||
/world/Del()
|
||||
|
||||
SaveHTMLAssociations()
|
||||
..()
|
||||
return
|
||||
@@ -0,0 +1,225 @@
|
||||
/obj/machinery/computer/security/New()
|
||||
..()
|
||||
if(!maplevel)
|
||||
src.verbs -= /obj/machinery/computer/security/verb/station_map
|
||||
|
||||
/obj/machinery/computer/security/attack_paw(var/mob/user as mob)
|
||||
|
||||
return src.attack_hand(user)
|
||||
return
|
||||
|
||||
/obj/machinery/computer/security/attack_hand(var/mob/user as mob)
|
||||
|
||||
if(stat & (NOPOWER|BROKEN) ) return
|
||||
|
||||
var/list/L = list( )
|
||||
user.machine = src
|
||||
for(var/obj/machinery/camera/C in world)
|
||||
if (C.network == src.network)
|
||||
L[text("[][]", C.c_tag, (C.status ? null : " (Deactivated)"))] = C
|
||||
//Foreach goto(31)
|
||||
L["Cancel"] = "Cancel"
|
||||
var/t = input(user, "Which camera should you change to?") as null|anything in L
|
||||
|
||||
if(!t)
|
||||
user.machine = null
|
||||
return 0
|
||||
|
||||
var/obj/machinery/camera/C = L[t]
|
||||
if (t == "Cancel")
|
||||
user.machine = null
|
||||
return 0
|
||||
if ((get_dist(user, src) > 1 || user.machine != src || user.blinded || !( user.canmove ) || !( C.status )))
|
||||
user.machine = null
|
||||
return 0
|
||||
else
|
||||
src.current = C
|
||||
use_power(50)
|
||||
spawn( 5 )
|
||||
attack_hand(user)
|
||||
return
|
||||
return
|
||||
|
||||
/obj/machinery/computer/security/check_eye(var/mob/user as mob)
|
||||
|
||||
if ((get_dist(user, src) > 1 || !( user.canmove ) || user.blinded || !( src.current ) || !( src.current.status )))
|
||||
return null
|
||||
user.reset_view(src.current)
|
||||
return 1
|
||||
return
|
||||
|
||||
|
||||
/obj/datacore/proc/manifest()
|
||||
|
||||
for(var/mob/human/H in world)
|
||||
if ((H.start && !( findtext(H.rname, "Syndicate ", 1, null) )))
|
||||
var/datum/data/record/G = new /datum/data/record( )
|
||||
var/datum/data/record/M = new /datum/data/record( )
|
||||
var/datum/data/record/S = new /datum/data/record( )
|
||||
var/obj/item/weapon/card/id/C = H.wear_id
|
||||
if (C)
|
||||
G.fields["rank"] = C.assignment
|
||||
else
|
||||
G.fields["rank"] = "Unassigned"
|
||||
G.fields["name"] = H.rname
|
||||
G.fields["id"] = text("[]", add_zero(num2hex(rand(1, 1.6777215E7)), 6))
|
||||
M.fields["name"] = G.fields["name"]
|
||||
M.fields["id"] = G.fields["id"]
|
||||
S.fields["name"] = G.fields["name"]
|
||||
S.fields["id"] = G.fields["id"]
|
||||
if (H.gender == "female")
|
||||
G.fields["sex"] = "Female"
|
||||
else
|
||||
G.fields["sex"] = "Male"
|
||||
G.fields["age"] = text("[]", H.age)
|
||||
G.fields["fingerprint"] = text("[]", md5(H.primary.uni_identity))
|
||||
G.fields["p_stat"] = "Active"
|
||||
G.fields["m_stat"] = "Stable"
|
||||
M.fields["b_type"] = text("[]", H.b_type)
|
||||
M.fields["mi_dis"] = "None"
|
||||
M.fields["mi_dis_d"] = "No minor disabilities have been declared."
|
||||
M.fields["ma_dis"] = "None"
|
||||
M.fields["ma_dis_d"] = "No major disabilities have been diagnosed."
|
||||
M.fields["alg"] = "None"
|
||||
M.fields["alg_d"] = "No allergies have been detected in this patient."
|
||||
M.fields["cdi"] = "None"
|
||||
M.fields["cdi_d"] = "No diseases have been diagnosed at the moment."
|
||||
M.fields["notes"] = "No notes."
|
||||
S.fields["criminal"] = "None"
|
||||
S.fields["mi_crim"] = "None"
|
||||
S.fields["mi_crim_d"] = "No minor crime convictions."
|
||||
S.fields["ma_crim"] = "None"
|
||||
S.fields["ma_crim_d"] = "No minor crime convictions."
|
||||
S.fields["notes"] = "No notes."
|
||||
src.general += G
|
||||
src.medical += M
|
||||
src.security += S
|
||||
//Foreach goto(15)
|
||||
return
|
||||
|
||||
/turf/space/attack_paw(mob/user as mob)
|
||||
|
||||
return src.attack_hand(user)
|
||||
return
|
||||
|
||||
/turf/space/attack_hand(mob/user as mob)
|
||||
|
||||
if ((user.restrained() || !( user.pulling )))
|
||||
return
|
||||
if (user.pulling.anchored)
|
||||
return
|
||||
if ((user.pulling.loc != user.loc && get_dist(user, user.pulling) > 1))
|
||||
return
|
||||
if (ismob(user.pulling))
|
||||
var/mob/M = user.pulling
|
||||
var/t = M.pulling
|
||||
M.pulling = null
|
||||
step(user.pulling, get_dir(user.pulling.loc, src))
|
||||
M.pulling = t
|
||||
else
|
||||
step(user.pulling, get_dir(user.pulling.loc, src))
|
||||
return
|
||||
|
||||
/turf/space/attackby(obj/item/weapon/tile/T as obj, mob/user as mob)
|
||||
|
||||
if (istype(T, /obj/item/weapon/tile))
|
||||
T.build(src)
|
||||
T.amount--
|
||||
T.add_fingerprint(user)
|
||||
if (T.amount < 1)
|
||||
user.u_equip(T)
|
||||
//SN src = null
|
||||
del(T)
|
||||
return
|
||||
return
|
||||
|
||||
/turf/space/updatecell()
|
||||
|
||||
return
|
||||
|
||||
/turf/space/conduction()
|
||||
return
|
||||
|
||||
/turf/space/Entered(atom/movable/A as mob|obj)
|
||||
|
||||
..()
|
||||
if ((!( A ) || src != A.loc || istype(null, /obj/beam)))
|
||||
return
|
||||
if (!( A.last_move ))
|
||||
return
|
||||
if (locate(/obj/move, src))
|
||||
return 1
|
||||
if ((ismob(A) && src.x > 2 && src.x < (world.maxx - 2) ))
|
||||
var/mob/M = A
|
||||
if ((!( M.restrained() ) && M.canmove))
|
||||
var/t1 = 5
|
||||
if (locate(/obj/grille, oview(1, M)))
|
||||
if (!( M.l_hand ))
|
||||
t1 -= 2
|
||||
else
|
||||
if (M.l_hand.w_class <= 2)
|
||||
t1 -= 1
|
||||
if (!( M.r_hand ))
|
||||
t1 -= 2
|
||||
else
|
||||
if (M.r_hand.w_class <= 2)
|
||||
t1 -= 1
|
||||
else
|
||||
if (locate(/turf/station, oview(1, M)))
|
||||
if (!( M.l_hand ))
|
||||
t1 -= 1
|
||||
else
|
||||
if (M.l_hand.w_class <= 2)
|
||||
t1 -= 0.5
|
||||
if (!( M.r_hand ))
|
||||
t1 -= 1
|
||||
else
|
||||
if (M.r_hand.w_class <= 2)
|
||||
t1 -= 0.5
|
||||
t1 = round(t1)
|
||||
if (t1 < 5)
|
||||
if (prob(t1))
|
||||
M << "\blue <B>You slipped!</B>"
|
||||
else
|
||||
spawn( 5 )
|
||||
if (src == A.loc)
|
||||
spawn( 0 )
|
||||
src.Entered(A)
|
||||
return
|
||||
return
|
||||
return 0
|
||||
if (src.x <= 2)
|
||||
if (src.z >= 10)
|
||||
if (world.maxz < 10)
|
||||
world.maxz++
|
||||
A.z++
|
||||
else
|
||||
A.z = 9
|
||||
else
|
||||
A.z++
|
||||
A.x = world.maxx - 2
|
||||
spawn( 0 )
|
||||
if ((A && A.loc))
|
||||
A.loc.Entered(A)
|
||||
return
|
||||
else
|
||||
if (A.x >= (world.maxx - 1) )
|
||||
if (A.z > 3)
|
||||
A.z--
|
||||
else
|
||||
A.z = 1
|
||||
A.x = 3
|
||||
spawn( 0 )
|
||||
if ((A && A.loc))
|
||||
A.loc.Entered(A)
|
||||
return
|
||||
else
|
||||
spawn( 5 )
|
||||
if ((A && !( A.anchored ) && A.loc == src))
|
||||
if (step(A, A.last_move))
|
||||
else
|
||||
spawn( 0 )
|
||||
src.Entered(A)
|
||||
return
|
||||
return
|
||||
return
|
||||
@@ -0,0 +1,36 @@
|
||||
|
||||
|
||||
/obj/item/weapon/flasks/examine()
|
||||
set src in oview(1)
|
||||
|
||||
usr << text("The flask is []% full", (src.oxygen + src.plasma + src.coolant) * 100 / 500)
|
||||
usr << "The flask can ONLY store liquids."
|
||||
return
|
||||
|
||||
/mob/human/abiotic()
|
||||
|
||||
if ((src.l_hand && !( src.l_hand.abstract )) || (src.r_hand && !( src.r_hand.abstract )) || (src.back || src.wear_mask || src.head || src.shoes || src.w_uniform || src.wear_suit || src.w_radio || src.glasses || src.ears || src.gloves))
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
return
|
||||
|
||||
/mob/proc/abiotic()
|
||||
|
||||
if ((src.l_hand && !( src.l_hand.abstract )) || (src.r_hand && !( src.r_hand.abstract )) || src.back || src.wear_mask)
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
return
|
||||
|
||||
/datum/data/function/proc/reset()
|
||||
|
||||
return
|
||||
|
||||
/datum/data/function/proc/r_input(href, href_list, mob/user as mob)
|
||||
|
||||
return
|
||||
|
||||
/datum/data/function/proc/display()
|
||||
|
||||
return
|
||||
@@ -0,0 +1,91 @@
|
||||
|
||||
// shows a browser pop-up window listing the variables in a datum
|
||||
|
||||
/proc/Vars(datum/D in view())
|
||||
set category = "Debug"
|
||||
|
||||
var/dat = "<HEAD><TITLE>Vars for "
|
||||
|
||||
if(istype(D, /atom)) // if the datum is an atom
|
||||
var/atom/A = D // do special handling
|
||||
dat += "[A.name] : [A.type] \ref[A]</TITLE></HEAD><BODY>"
|
||||
|
||||
#ifdef VARSICON
|
||||
if(A.icon) // if the atom has an icon, display it
|
||||
dat += variable(usr, "icon", new/icon(A.icon, A.icon_state, A.dir))
|
||||
#endif
|
||||
|
||||
else // not an atom
|
||||
dat += "[D] : [D.type] \ref[D]</TITLE><HEAD><BODY>"
|
||||
|
||||
|
||||
for(var/V in D.vars) // for each variable in the datum
|
||||
dat += variable(usr, V, D.vars[V]) //get the text for that variable
|
||||
|
||||
dat += "</BODY>"
|
||||
usr << browse(dat, "window=\ref[D]") // display the browser pop-up
|
||||
|
||||
|
||||
// return a HTML formatted string displaying a variable
|
||||
|
||||
/proc/variable(user, vname, val)
|
||||
|
||||
var/t
|
||||
|
||||
if(vname == "*") // true if this variable is part of a list
|
||||
t = "<FONT COLOR=#404040 SIZE=-1>* [val]" // so format smaller grey text, and just show the value
|
||||
else // otherwise show the name and value without formatting
|
||||
if(istext(val))
|
||||
t = "<FONT>[vname] = \"[val]\"" // place quotes around text values
|
||||
else
|
||||
t = "<FONT>[vname] = [val]"
|
||||
|
||||
|
||||
if(istype(val,/icon)) // if this variable is an icon, display it
|
||||
|
||||
#ifdef VARSICON
|
||||
var/rnd = rand(1,10000) // use random number in filename to avoid conflicts
|
||||
user << browse_rsc(val, "tmp\ref[val][rnd].png") // precache the icon image file
|
||||
t+="<IMG SRC=\"tmp\ref[val][rnd].png\">" // and add the icon to the HTML
|
||||
#endif
|
||||
|
||||
|
||||
else if(istype(val, /datum)) // if this is a datum object
|
||||
var/datum/dval = val // add a link to the object to the HTML
|
||||
t+= " ([dval.type]) <A href='?src=\ref[val];Vars=1'><FONT SIZE=-2>\ref[val]</FONT></A>"
|
||||
|
||||
if("[val]" == "/list") // if this is a list object
|
||||
t += " (length [length(val)])</FONT><BR>"
|
||||
|
||||
if( (vname!="vars") && (vname!="verbs") && length(val)<500) // and it's not vars or verbs, or too long
|
||||
|
||||
for(var/lv in val) // loop through all items in the list
|
||||
t += variable(user, "*", lv) // and display them
|
||||
|
||||
else
|
||||
t += "</FONT><BR>"
|
||||
|
||||
return t // return the formatted text
|
||||
|
||||
// topic handler for linked objects
|
||||
// invoked when user clicks on an object link in the datum vars pop-up
|
||||
// note all other Topic procs should call ..() first so this can be called
|
||||
|
||||
/datum/Topic(href, href_list)
|
||||
|
||||
if(href_list["Vars"]) // if this link came from the vars window
|
||||
|
||||
Vars(src) // invoke a new window for this object
|
||||
|
||||
|
||||
/mob/proc/Delete(atom/A in view())
|
||||
set category = "Debug"
|
||||
|
||||
switch( alert("Are you sure you wish to delete \the [A.name] at ([A.x],[A.y],[A.z]) ?", "Admin Delete Object","Yes","No") )
|
||||
if("Yes")
|
||||
|
||||
if(config.logadmin) world.log << "ADMIN: [usr.key] deleted [A.name] at ([A.x],[A.y],[A.z])"
|
||||
|
||||
|
||||
del(A)
|
||||
|
||||
+2632
File diff suppressed because it is too large
Load Diff
+984
@@ -0,0 +1,984 @@
|
||||
|
||||
/proc/scram(n)
|
||||
|
||||
var/t = ""
|
||||
var/p = null
|
||||
p = 1
|
||||
while(p <= n)
|
||||
t = text("[][]", t, rand(1, 9))
|
||||
p++
|
||||
return t
|
||||
return
|
||||
|
||||
/obj/machinery/computer/dna/attack_paw(mob/user as mob)
|
||||
|
||||
return src.attack_hand(user)
|
||||
return
|
||||
|
||||
/obj/machinery/computer/dna/attack_hand(mob/user as mob)
|
||||
|
||||
if(stat & (NOPOWER|BROKEN) )
|
||||
return
|
||||
|
||||
user.machine = src
|
||||
if (istype(user, /mob/human))
|
||||
var/dat = text("<I>Please Insert the cards into the slots</I><BR>\n\t\t\t\tFunction Disk: <A href='?src=\ref[];scan=1'>[]</A><BR>\n\t\t\t\tTarget Disk: <A href='?src=\ref[];modify=1'>[]</A><BR>\n\t\t\t\tAux. Data Disk: <A href='?src=\ref[];modify2=1'>[]</A><BR>\n\t\t\t\t\t(Not always used!)<BR>\n\t\t\t\t[]", src, (src.scan ? text("[]", src.scan.name) : "----------"), src, (src.modify ? text("[]", src.modify.name) : "----------"), src, (src.modify2 ? text("[]", src.modify2.name) : "----------"), (src.scan ? text("<A href='?src=\ref[];execute=1'>Execute Function</A>", src) : "No function disk inserted!"))
|
||||
if (src.temp)
|
||||
dat = text("[]<BR><BR><A href='?src=\ref[];clear=1'>Clear Message</A>", src.temp, src)
|
||||
user << browse(dat, "window=dna_comp")
|
||||
else
|
||||
var/dat = text("<I>[]</I><BR>\n\t\t\t\t[] <A href='?src=\ref[];scan=1'>[]</A><BR>\n\t\t\t\t[] <A href='?src=\ref[];modify=1'>[]</A><BR>\n\t\t\t\t[] <A href='?src=\ref[];modify2=1'>[]</A><BR>\n\t\t\t\t\t(Not always used!)<BR>\n\t\t\t\t[]", stars("Please Insert the cards into the slots"), stars("Function Disk:"), src, (src.scan ? text("[]", src.scan.name) : "----------"), stars("Target Disk:"), src, (src.modify ? text("[]", src.modify.name) : "----------"), stars("Aux. Data Disk:"), src, (src.modify2 ? text("[]", src.modify2.name) : "----------"), (src.scan ? text("<A href='?src=\ref[];execute=1'>[]</A>", src, stars("Execute Function")) : stars("No function disk inserted!")))
|
||||
if (src.temp)
|
||||
dat = text("[]<BR><BR><A href='?src=\ref[];clear=1'>[]", stars(src.temp), src, stars("Clear Message</A>"))
|
||||
user << browse(dat, "window=dna_comp")
|
||||
return
|
||||
|
||||
/obj/machinery/computer/dna/Topic(href, href_list)
|
||||
..()
|
||||
if ((!( istype(usr, /mob/human) ) && (!( ticker ) || (ticker && ticker.mode != "monkey"))))
|
||||
usr << "\red You don't have the dexterity to do this!"
|
||||
return
|
||||
if ((usr.stat || usr.restrained()))
|
||||
return
|
||||
if ((usr.contents.Find(src) || (get_dist(src, usr) <= 1 && istype(src.loc, /turf))))
|
||||
usr.machine = src
|
||||
if (href_list["modify"])
|
||||
if (src.modify)
|
||||
src.modify.loc = src.loc
|
||||
src.modify = null
|
||||
src.mode = null
|
||||
else
|
||||
var/obj/item/I = usr.equipped()
|
||||
if (istype(I, /obj/item/weapon/card/data))
|
||||
usr.drop_item()
|
||||
I.loc = src
|
||||
src.modify = I
|
||||
src.mode = null
|
||||
if (href_list["modify2"])
|
||||
if (src.modify2)
|
||||
src.modify2.loc = src.loc
|
||||
src.modify2 = null
|
||||
src.mode = null
|
||||
else
|
||||
var/obj/item/I = usr.equipped()
|
||||
if (istype(I, /obj/item/weapon/card/data))
|
||||
usr.drop_item()
|
||||
I.loc = src
|
||||
src.modify2 = I
|
||||
src.mode = null
|
||||
if (href_list["scan"])
|
||||
if (src.scan)
|
||||
src.scan.loc = src.loc
|
||||
src.scan = null
|
||||
src.mode = null
|
||||
else
|
||||
var/obj/item/I = usr.equipped()
|
||||
if (istype(I, /obj/item/weapon/card/data))
|
||||
usr.drop_item()
|
||||
I.loc = src
|
||||
src.scan = I
|
||||
src.mode = null
|
||||
if (href_list["clear"])
|
||||
src.temp = null
|
||||
if (href_list["execute"])
|
||||
if ((src.scan && src.scan.function))
|
||||
switch(src.scan.function)
|
||||
if("data_mutate")
|
||||
if (src.modify)
|
||||
if (!( findtext(src.scan.data, "-", 1, null) ))
|
||||
if ((src.modify.data && src.scan.data && length(src.modify.data) >= length(src.scan.data)))
|
||||
src.modify.data = text("[][]", src.scan.data, (length(src.modify.data) > length(src.scan.data) ? copytext(src.modify.data, length(src.scan.data) + 1, length(src.modify.data) + 1) : null))
|
||||
else
|
||||
src.temp = "Disk Failure: Cannot examine data! (Null or wrong format)"
|
||||
else
|
||||
var/d = findtext(src.modify.data, "-", 1, null)
|
||||
var/t = copytext(src.modify.data, d + 1, length(src.modify.data) + 1)
|
||||
d = text2num(copytext(1, d, null))
|
||||
if ((d && t && src.modify.data && src.scan.data && length(src.modify.data) >= (length(t) + d - 1) ))
|
||||
src.modify.data = text("[][][]", copytext(src.modify.data, 1, d), t, (length(src.modify.data) > length(t) + d ? copytext(src.modify.data, length(t) + d, length(src.modify.data) + 1) : null))
|
||||
else
|
||||
src.temp = "Disk Failure: Cannot examine data! (Null or wrong format)"
|
||||
else
|
||||
src.temp = "Disk Failure: Cannot read target disk!"
|
||||
if("dna_seq")
|
||||
src.temp = "<TT>DNA Systems Help:\nHuman DNA sequences: (Compressed in *.dna format version 10.76)\n\tSpecies Identification Marker: (28 chromosomes)\n\t\t5BDFE293BA5500F9FFFD500AAFFE\n\tStructural Enzymes:\n\t\tCDE375C9A6C25A7DBDA50EC05AC6CEB63\n\t\tNote: The first id set is used for DNA clean up operations.\n\tUsed Enzymes:\n\t\t493DB249EB6D13236100A37000800AB71\n\tSpecies/Genus Classification: <I>Homo Sapien</I>\n\nMonkey DNA sequences: (Compressed in *.dna format version 10.76)\n\tSpecies Identification Marker: (16 chromosomes)\n\t\t2B6696D2B127E5A4\n\tStructural Enzymes:\n\t\tCDEAF5B90AADBC6BA8033DB0A7FD613FA\n\t\tNote: The first id set is used for DNA clean up operations.\n\tUsed Enzymes:\n\t\tC8FFFE7EC09D80AEDEDB9A5A0B4085B61\n\tSpecies/Genus Classification: Generic Monkey\n</TT>>"
|
||||
if("dna_help")
|
||||
src.temp = "<TT>DNA Systems Help:\nThe DNA systems consists 3 systems.\nI. DNA Scanner/Implanter - This system is slightly advanced to use. It accepts\n\t1 disk. Before you wish to run a function/program you must implant the\n\tdisk data into the temporary memory. Note that once this is done the disk can\n\tbe removed to place a data disk in.\nII. DNA computer - This is a simple yet fast computer that basically operates on data.\nIII. Restructurer - This device reorganizes the anatomical structure of the subject\n\taccording to the DNA sequences. Please note that it is illegal to perform a\n\ttransfer from one species to or from the <I>Homo sapiens</I> species but\n\thuman to human is acceptable under UNSD guidlines.\n\tNote: This machine is programmed to operate on specific preprogrammed species with\n\tspecialized anatomical blueprints hard coded into its databanks. It cannot operate\n\ton other species. (Current: Human, Monkey)\n\nData Disks:\n\tThese run on 2 (or 3) types: DNA scanner program disks and data modification\nfunctions (and disk modification functions)\n\nDisk-Copy\n\tThis erases the target disk and completely copies the data from the aux. disk.\nDisk-Erase\n\tThis erases everything on the target disk.\nData-Clear\n\tThis erases (clears) only the data.\n\nData-Trunicate\n\tThis removes data from the target disk (parameters gathered from data slot on target\n\tdisk). This fuction has 4 modes (a,b,c,default) defined by this way. (mode id)(#)\n\ta - This cuts # data from the end. (ex a1 on ABCD = ABC)\n\tb - This cuts # data from the beginning. (ex b1 on ABCD = BCD)\n\tc - This limits the data from the end. (ex c1 on ABCD = A)\n\tdefault - This limits the data from the end. (ex 1 on ABCD = D)\nData-Add\n\tThis adds thedata on the aux. disk to the data on the target disk.\nData-Sramble\n\tThis scrambles the data on the target disk. The length is equal to\n\tthe length of the original data.\nData-Input\n\tThis lets you input data into the data slot of any data disk.\n\tNote: This doesn't work only on storage.\nData-Mutate\n\tThis basically inserts text. You follow this format:\n\tpos-text (or just text for automatic pos 1)\n\tie 2-IVE on FOUR yields FIVE\n</TT>"
|
||||
if("data_add")
|
||||
if (src.modify)
|
||||
if (src.modify2)
|
||||
if ((src.modify.data && src.modify2.data))
|
||||
src.modify.data += src.modify2
|
||||
src.temp = text("Done!<BR>New Data:<BR>[]", src.modify.data)
|
||||
else
|
||||
src.temp = "Cannot read data! (may be null)"
|
||||
else
|
||||
src.temp = "Disk Failure: Cannot read aux. data disk!"
|
||||
else
|
||||
src.temp = "Disk Failure: Cannot read target disk!"
|
||||
if("data_scramble")
|
||||
if (src.modify)
|
||||
if (length(text("[]", src.modify.data)) >= 1)
|
||||
src.modify.data = scram(length(text("[]", src.modify.data)))
|
||||
src.temp = text("Data scrambled: []", src.modify.data)
|
||||
else
|
||||
src.temp = "No data to scramble"
|
||||
else
|
||||
src.temp = "Disk Failure: Cannot read target disk!"
|
||||
if("data_input")
|
||||
if (src.modify)
|
||||
var/dat = input(usr, ">", text("[]", src.name), null) as text
|
||||
var/s = src.scan
|
||||
var/m = src.modify
|
||||
if ((usr.stat || usr.restrained() || src.modify != m || src.scan != s))
|
||||
return
|
||||
if ((get_dist(src, usr) <= 1 && istype(src.loc, /turf)))
|
||||
src.modify.data = dat
|
||||
else
|
||||
src.temp = "Disk Failure: Cannot read target disk!"
|
||||
if("disk_copy")
|
||||
if (src.modify)
|
||||
if (src.modify2)
|
||||
src.modify.function = src.modify2.function
|
||||
src.modify.data = src.modify2.data
|
||||
src.modify.special = src.modify2.special
|
||||
src.temp = "All disk data/programs copied."
|
||||
else
|
||||
src.temp = "Disk Failure: Cannot read aux. data disk!"
|
||||
else
|
||||
src.temp = "Disk Failure: Cannot read target disk!"
|
||||
if("disk_dis")
|
||||
if (src.modify)
|
||||
src.temp = text("Function: [][]<BR>Data: []", src.modify.function, (src.modify.special ? text("-[]", src.modify.special) : null), src.modify.data)
|
||||
else
|
||||
src.temp = "Disk Failure: Cannot read target disk!"
|
||||
if("disk_erase")
|
||||
if (src.modify)
|
||||
src.modify.data = null
|
||||
src.modify.function = "storage"
|
||||
src.modify.special = null
|
||||
src.temp = "All Disk contents deleted."
|
||||
else
|
||||
src.temp = "Disk Failure: Cannot read target disk!"
|
||||
if("data_clear")
|
||||
if (src.modify)
|
||||
src.modify.data = null
|
||||
src.temp = "Disk data cleared."
|
||||
else
|
||||
src.temp = "Disk Failure: Cannot read target disk!"
|
||||
if("data_trun")
|
||||
if (src.modify)
|
||||
if ((src.modify.data && src.scan.data))
|
||||
var/l1 = length(src.modify.data)
|
||||
var/l2 = max(round(text2num(src.scan.data)), 1)
|
||||
switch(copytext(src.modify.data, 1, 2))
|
||||
if("a")
|
||||
if (l1 > l2)
|
||||
src.modify.data = copytext(src.modify.data, 1, (l1 - l2) + 1)
|
||||
else
|
||||
src.modify.data = ""
|
||||
src.temp = text("Done!<BR>New Data:<BR>[]", src.modify.data)
|
||||
if("b")
|
||||
if (l1 > l2)
|
||||
src.modify.data = copytext(src.modify.data, l2, l1 + 1)
|
||||
else
|
||||
src.modify.data = ""
|
||||
src.temp = text("Done!<BR>New Data:<BR>[]", src.modify.data)
|
||||
if("c")
|
||||
if (l1 >= l2)
|
||||
src.modify.data = copytext(src.modify.data, l1 - l2, l1 + 1)
|
||||
src.temp = text("Done!<BR>New Data:<BR>[]", src.modify.data)
|
||||
else
|
||||
if (l1 >= l2)
|
||||
src.modify.data = copytext(src.modify.data, 1, l2 + 1)
|
||||
src.temp = text("Done!<BR>New Data:<BR>[]", src.modify.data)
|
||||
else
|
||||
src.temp = "Cannot read data! (may be null and note that function data slot is used instead of aux disk!!)"
|
||||
else
|
||||
src.temp = "Disk Failure: Cannot read target disk!"
|
||||
else
|
||||
else
|
||||
src.temp = "System Failure: Cannot read disk function!"
|
||||
src.add_fingerprint(usr)
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
//Foreach goto(1764)
|
||||
return
|
||||
|
||||
/obj/machinery/computer/dna/ex_act(severity)
|
||||
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
//SN src = null
|
||||
del(src)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
//SN src = null
|
||||
del(src)
|
||||
return
|
||||
else
|
||||
return
|
||||
|
||||
/obj/machinery/dna_scanner/allow_drop()
|
||||
|
||||
return 0
|
||||
return
|
||||
|
||||
/obj/machinery/dna_scanner/relaymove(mob/user as mob)
|
||||
|
||||
if (user.stat)
|
||||
return
|
||||
src.go_out()
|
||||
return
|
||||
|
||||
/obj/machinery/dna_scanner/verb/eject()
|
||||
set src in oview(1)
|
||||
|
||||
if (usr.stat != 0)
|
||||
return
|
||||
src.go_out()
|
||||
add_fingerprint(usr)
|
||||
return
|
||||
|
||||
/obj/machinery/dna_scanner/verb/move_inside()
|
||||
set src in oview(1)
|
||||
|
||||
if (usr.stat != 0)
|
||||
return
|
||||
if (src.occupant)
|
||||
usr << "\blue <B>The scanner is already occupied!</B>"
|
||||
return
|
||||
if (usr.abiotic())
|
||||
usr << "\blue <B>Subject cannot have abiotic items on.</B>"
|
||||
return
|
||||
usr.pulling = null
|
||||
usr.client.perspective = EYE_PERSPECTIVE
|
||||
usr.client.eye = src
|
||||
usr.loc = src
|
||||
src.occupant = usr
|
||||
src.icon_state = "scanner_1"
|
||||
for(var/obj/O in src)
|
||||
//O = null
|
||||
del(O)
|
||||
//Foreach goto(124)
|
||||
src.add_fingerprint(usr)
|
||||
return
|
||||
|
||||
/obj/machinery/dna_scanner/attackby(obj/item/weapon/grab/G as obj, user as mob)
|
||||
|
||||
if ((!( istype(G, /obj/item/weapon/grab) ) || !( ismob(G.affecting) )))
|
||||
return
|
||||
if (src.occupant)
|
||||
user << "\blue <B>The scanner is already occupied!</B>"
|
||||
return
|
||||
if (G.affecting.abiotic())
|
||||
user << "\blue <B>Subject cannot have abiotic items on.</B>"
|
||||
return
|
||||
var/mob/M = G.affecting
|
||||
if (M.client)
|
||||
M.client.perspective = EYE_PERSPECTIVE
|
||||
M.client.eye = src
|
||||
M.loc = src
|
||||
src.occupant = M
|
||||
src.icon_state = "scanner_1"
|
||||
for(var/obj/O in src)
|
||||
O.loc = src.loc
|
||||
//Foreach goto(154)
|
||||
src.add_fingerprint(user)
|
||||
//G = null
|
||||
del(G)
|
||||
return
|
||||
|
||||
/obj/machinery/dna_scanner/proc/go_out()
|
||||
|
||||
if ((!( src.occupant ) || src.locked))
|
||||
return
|
||||
for(var/obj/O in src)
|
||||
O.loc = src.loc
|
||||
//Foreach goto(30)
|
||||
if (src.occupant.client)
|
||||
src.occupant.client.eye = src.occupant.client.mob
|
||||
src.occupant.client.perspective = MOB_PERSPECTIVE
|
||||
src.occupant.loc = src.loc
|
||||
src.occupant = null
|
||||
src.icon_state = "scanner_0"
|
||||
return
|
||||
|
||||
/obj/machinery/dna_scanner/ex_act(severity)
|
||||
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
for(var/atom/movable/A as mob|obj in src)
|
||||
A.loc = src.loc
|
||||
ex_act(severity)
|
||||
//Foreach goto(35)
|
||||
//SN src = null
|
||||
del(src)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
for(var/atom/movable/A as mob|obj in src)
|
||||
A.loc = src.loc
|
||||
ex_act(severity)
|
||||
//Foreach goto(108)
|
||||
//SN src = null
|
||||
del(src)
|
||||
return
|
||||
if(3.0)
|
||||
if (prob(25))
|
||||
for(var/atom/movable/A as mob|obj in src)
|
||||
A.loc = src.loc
|
||||
ex_act(severity)
|
||||
//Foreach goto(181)
|
||||
//SN src = null
|
||||
del(src)
|
||||
return
|
||||
else
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/dna_scanner/blob_act()
|
||||
|
||||
if(prob(50))
|
||||
for(var/atom/movable/A as mob|obj in src)
|
||||
A.loc = src.loc
|
||||
del(src)
|
||||
|
||||
/obj/machinery/scan_console/ex_act(severity)
|
||||
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
//SN src = null
|
||||
del(src)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
//SN src = null
|
||||
del(src)
|
||||
return
|
||||
else
|
||||
return
|
||||
|
||||
/obj/machinery/scan_console/blob_act()
|
||||
|
||||
if(prob(50))
|
||||
del(src)
|
||||
|
||||
/obj/machinery/scan_console/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
|
||||
|
||||
/obj/machinery/scan_console/New()
|
||||
|
||||
..()
|
||||
spawn( 5 )
|
||||
src.connected = locate(/obj/machinery/dna_scanner, get_step(src, WEST))
|
||||
return
|
||||
return
|
||||
|
||||
/obj/machinery/scan_console/process()
|
||||
|
||||
if(stat & NOPOWER)
|
||||
return
|
||||
use_power(250)
|
||||
|
||||
var/mob/M
|
||||
if (!( src.status ))
|
||||
return
|
||||
if (!( src.func ))
|
||||
src.temp = "No function loaded into memory core!"
|
||||
src.status = null
|
||||
if ((src.connected && src.connected.occupant))
|
||||
M = src.connected.occupant
|
||||
if (src.status == "load")
|
||||
src.prog_p1 = null
|
||||
src.prog_p2 = null
|
||||
src.prog_p3 = null
|
||||
src.prog_p4 = null
|
||||
switch(src.func)
|
||||
if("dna_trun")
|
||||
if (src.data)
|
||||
src.prog_p1 = copytext(src.data, 1, 2)
|
||||
src.prog_p2 = text2num(src.data)
|
||||
src.prog_p3 = src.special
|
||||
src.status = "dna_trun"
|
||||
src.temp = "Executing trunication function on occupant."
|
||||
else
|
||||
src.temp = "No data implanted in core memory."
|
||||
src.status = null
|
||||
if("dna_scan")
|
||||
if (src.special)
|
||||
if (src.scan)
|
||||
if (istype(M, /mob))
|
||||
switch(src.special)
|
||||
if("UI")
|
||||
src.temp = text("Scan Complete:<BR>Data downloaded to disk!<BR>Unique Identifier: []", M.primary.uni_identity)
|
||||
src.scan.data = M.primary.uni_identity
|
||||
if("SE")
|
||||
src.temp = text("Scan Complete:<BR>Data downloaded to disk!<BR>Structural Enzymes: []", M.primary.struc_enzyme)
|
||||
src.scan.data = M.primary.struc_enzyme
|
||||
if("UE")
|
||||
src.temp = text("Scan Complete:<BR>Data downloaded to disk!<BR>Used Enzynmes: []", M.primary.use_enzyme)
|
||||
src.scan.data = M.primary.use_enzyme
|
||||
if("SI")
|
||||
src.temp = text("Scan Complete:<BR>Data downloaded to disk!<BR>Species Identifier: []", M.primary.spec_identity)
|
||||
src.scan.data = M.primary.spec_identity
|
||||
else
|
||||
else
|
||||
src.temp = "No occupant to scan!"
|
||||
else
|
||||
src.temp = "Error: No disk to upload data to."
|
||||
else
|
||||
src.temp = "Error: Function program errors."
|
||||
src.status = null
|
||||
if("dna_replace")
|
||||
if ((src.data && src.special))
|
||||
src.prog_p1 = src.special
|
||||
src.prog_p2 = src.data
|
||||
src.status = "dna_replace"
|
||||
src.temp = "Executing repalcement function on occupant."
|
||||
else
|
||||
src.temp = "Error: No DNA data loaded into core or function program errors."
|
||||
src.status = null
|
||||
if("dna_add")
|
||||
if ((src.data && src.special))
|
||||
src.prog_p1 = src.special
|
||||
src.prog_p2 = src.data
|
||||
src.status = "dna_add"
|
||||
src.temp = "Executing addition function on occupant."
|
||||
else
|
||||
src.temp = "Error: No DNA data loaded into core or function program errors."
|
||||
src.status = null
|
||||
else
|
||||
src.temp = "Cannot execute program!"
|
||||
src.status = null
|
||||
else
|
||||
if (src.status == "dna_trun")
|
||||
if (istype(M, /mob))
|
||||
var/t = null
|
||||
switch(src.prog_p3)
|
||||
if("UI")
|
||||
t = M.primary.uni_identity
|
||||
if("SE")
|
||||
t = M.primary.struc_enzyme
|
||||
if("UE")
|
||||
t = M.primary.use_enzyme
|
||||
if("SI")
|
||||
t = M.primary.spec_identity
|
||||
else
|
||||
if (!( src.prog_p4 ))
|
||||
switch(src.prog_p1)
|
||||
if("a")
|
||||
src.prog_p4 = length(t)
|
||||
if("b")
|
||||
src.prog_p4 = 1
|
||||
else
|
||||
else
|
||||
if (src.prog_p1 == "a")
|
||||
src.prog_p4--
|
||||
else
|
||||
if (src.prog_p1 == "b")
|
||||
src.prog_p4--
|
||||
switch(src.prog_p1)
|
||||
if("a")
|
||||
if (src.prog_p4 <= 0)
|
||||
src.temp = "Trunication complete"
|
||||
src.status = null
|
||||
else
|
||||
t = copytext(t, 1, length(t))
|
||||
src.temp = text("Trunicating []'s DNA sequence...<BR>[]<BR>Status: [] units left.<BR><BR><A href='?src=\ref[];abort=1'>Emergency Abort</A>", M.name, t, src.prog_p4, src)
|
||||
if("b")
|
||||
if (src.prog_p4 <= 0)
|
||||
src.temp = "Trunication complete"
|
||||
src.status = null
|
||||
else
|
||||
t = copytext(t, 2, length(t) + 1)
|
||||
src.temp = text("Trunicating []'s DNA sequence...<BR>[]<BR>Status: [] units left.<BR><BR><A href='?src=\ref[];abort=1'>Emergency Abort</A>", M.name, t, src.prog_p4, src)
|
||||
if("c")
|
||||
if (length(t) <= src.prog_p2)
|
||||
src.temp = "Limitation complete"
|
||||
src.status = null
|
||||
else
|
||||
t = copytext(t, 1, length(t))
|
||||
src.temp = text("Limiting []'s DNA sequence...<BR>[]<BR>Status: [] units converting to [] units.<BR><BR><A href='?src=\ref[];abort=1'>Emergency Abort</A>", M.name, t, length(t), src.prog_p2, src)
|
||||
else
|
||||
if (length(t) <= src.prog_p2)
|
||||
src.temp = "Limitation complete"
|
||||
src.status = null
|
||||
else
|
||||
t = copytext(t, 2, length(t) + 1)
|
||||
src.temp = text("Limiting []'s DNA sequence...<BR>[]<BR>Status: [] units converting to [] units.<BR><BR><A href='?src=\ref[];abort=1'>Emergency Abort</A>", M.name, t, length(t), src.prog_p2, src)
|
||||
switch(src.prog_p3)
|
||||
if("UI")
|
||||
M.primary.uni_identity = t
|
||||
if("SE")
|
||||
M.primary.struc_enzyme = t
|
||||
if("UE")
|
||||
M.primary.use_enzyme = t
|
||||
if("SI")
|
||||
M.primary.spec_identity = t
|
||||
else
|
||||
else
|
||||
src.temp = "Process terminated due to lack of occupant in DNA chamber."
|
||||
src.status = null
|
||||
else
|
||||
if (src.status == "dna_replace")
|
||||
if (istype(M, /mob))
|
||||
var/t = null
|
||||
switch(src.prog_p1)
|
||||
if("UI")
|
||||
t = M.primary.uni_identity
|
||||
if("SE")
|
||||
t = M.primary.struc_enzyme
|
||||
if("UE")
|
||||
t = M.primary.use_enzyme
|
||||
if("SI")
|
||||
t = M.primary.spec_identity
|
||||
else
|
||||
if (!( src.prog_p4 ))
|
||||
src.prog_p4 = 1
|
||||
else
|
||||
src.prog_p4++
|
||||
if ((src.prog_p4 > length(t) || src.prog_p4 > length(src.prog_p2)))
|
||||
src.temp = "Replacement complete"
|
||||
src.status = null
|
||||
else
|
||||
t = text("[][][]", copytext(t, 1, src.prog_p4), copytext(src.prog_p2, src.prog_p4, src.prog_p4 + 1), (src.prog_p4 < length(t) ? copytext(t, src.prog_p4 + 1, length(t) + 1) : null))
|
||||
src.temp = text("Replacing []'s DNA sequence...<BR>[]<BR>Target: []<BR>Status: At position []<BR><BR><A href='?src=\ref[];abort=1'>Emergency Abort</A>", M.name, t, src.prog_p2, src.prog_p4, src)
|
||||
switch(src.prog_p1)
|
||||
if("UI")
|
||||
M.primary.uni_identity = t
|
||||
if("SE")
|
||||
M.primary.struc_enzyme = t
|
||||
if("UE")
|
||||
M.primary.use_enzyme = t
|
||||
if("SI")
|
||||
M.primary.spec_identity = t
|
||||
else
|
||||
else
|
||||
src.temp = "Process terminated due to lack of occupant in DNA chamber."
|
||||
src.status = null
|
||||
else
|
||||
if (src.status == "dna_add")
|
||||
if (istype(M, /mob))
|
||||
var/t = null
|
||||
switch(src.prog_p1)
|
||||
if("UI")
|
||||
t = M.primary.uni_identity
|
||||
if("SE")
|
||||
t = M.primary.struc_enzyme
|
||||
if("UE")
|
||||
t = M.primary.use_enzyme
|
||||
if("SI")
|
||||
t = M.primary.spec_identity
|
||||
else
|
||||
if (!( src.prog_p4 ))
|
||||
src.prog_p4 = 1
|
||||
else
|
||||
src.prog_p4++
|
||||
if (src.prog_p4 > length(src.prog_p2))
|
||||
src.temp = "Addition complete"
|
||||
src.status = null
|
||||
else
|
||||
t = text("[][]", t, copytext(src.prog_p2, src.prog_p4, src.prog_p4 + 1))
|
||||
src.temp = text("Adding to []'s DNA sequence...<BR>[]<BR>Adding: []<BR>Position: []<BR><BR><A href='?src=\ref[];abort=1'>Emergency Abort</A>", M.name, t, src.prog_p2, src.prog_p4, src)
|
||||
switch(src.prog_p1)
|
||||
if("UI")
|
||||
M.primary.uni_identity = t
|
||||
if("SE")
|
||||
M.primary.struc_enzyme = t
|
||||
if("UE")
|
||||
M.primary.use_enzyme = t
|
||||
if("SI")
|
||||
M.primary.spec_identity = t
|
||||
else
|
||||
else
|
||||
src.temp = "Process terminated due to lack of occupant in DNA chamber."
|
||||
src.status = null
|
||||
else
|
||||
src.status = null
|
||||
src.temp = "Unknown system error."
|
||||
for(var/mob/O in viewers(1, src))
|
||||
if ((O.client && O.machine == src))
|
||||
src.attack_hand(O)
|
||||
//Foreach goto(1755)
|
||||
return
|
||||
|
||||
/obj/machinery/scan_console/attack_paw(user as mob)
|
||||
|
||||
return src.attack_hand(user)
|
||||
return
|
||||
|
||||
/obj/machinery/scan_console/attack_hand(user as mob)
|
||||
|
||||
if(stat & (NOPOWER|BROKEN) )
|
||||
return
|
||||
|
||||
var/dat
|
||||
if (src.temp)
|
||||
dat = text("[]<BR><BR><A href='?src=\ref[];clear=1'>Clear Message</A>", src.temp, src)
|
||||
else
|
||||
if (src.connected)
|
||||
var/mob/occupant = src.connected.occupant
|
||||
dat = "<font color='blue'><B>Occupant Statistics:</B></FONT><BR>"
|
||||
if (occupant)
|
||||
var/t1
|
||||
switch(occupant.stat)
|
||||
if(0.0)
|
||||
t1 = "Conscious"
|
||||
if(1.0)
|
||||
t1 = "Unconscious"
|
||||
else
|
||||
t1 = "*dead*"
|
||||
dat += text("[]\tHealth %: [] ([])</FONT><BR><BR>", (occupant.health > 50 ? "<font color='blue'>" : "<font color='red'>"), occupant.health, t1)
|
||||
else
|
||||
dat += "The scanner is empty.<BR>"
|
||||
if (!( src.connected.locked ))
|
||||
dat += text("<A href='?src=\ref[];locked=1'>Lock (Unlocked)</A><BR>", src)
|
||||
else
|
||||
dat += text("<A href='?src=\ref[];locked=1'>Unlock (Locked)</A><BR>", src)
|
||||
dat += text("Disk: <A href='?src=\ref[];scan=1'>[]</A><BR>\n[]<BR>\n[]<BR>", src,
|
||||
(src.scan ? text("[]", src.scan.name) : "----------"),
|
||||
(src.scan ? text("<A href='?src=\ref[];u_dat=1'>Upload Data</A>", src) : "No disk to upload"),
|
||||
((src.data || src.func || src.special) ? text("<A href='?src=\ref[];c_dat=1'>Clear Data</A><BR><A href='?src=\ref[];e_dat=1'>Execute Data</A><BR>Function Type: [][]<BR>Data: []", src, src, src.func, (src.special ? text("-[]", src.special) : null), src.data) : "No data uploaded"))
|
||||
dat += text("<BR><BR><A href='?src=\ref[];mach_close=scanner'>Close</A>", user)
|
||||
user << browse(dat, "window=scanner;size=400x500")
|
||||
return
|
||||
|
||||
/obj/machinery/scan_console/Topic(href, href_list)
|
||||
..()
|
||||
if ((!( istype(usr, /mob/human) ) && (!( ticker ) || (ticker && ticker.mode != "monkey"))))
|
||||
usr << "\red You don't have the dexterity to do this!"
|
||||
return
|
||||
if ((usr.stat || usr.restrained()))
|
||||
return
|
||||
if ((usr.contents.Find(src) || get_dist(src, usr) <= 1 && istype(src.loc, /turf)))
|
||||
usr.machine = src
|
||||
if (href_list["locked"])
|
||||
if ((src.connected && src.connected.occupant))
|
||||
src.connected.locked = !( src.connected.locked )
|
||||
if (href_list["scan"])
|
||||
if (src.scan)
|
||||
src.scan.loc = src.loc
|
||||
src.scan = null
|
||||
else
|
||||
var/obj/item/I = usr.equipped()
|
||||
if (istype(I, /obj/item/weapon/card/data))
|
||||
usr.drop_item()
|
||||
I.loc = src
|
||||
src.scan = I
|
||||
if (href_list["u_dat"])
|
||||
if ((src.scan && !( src.status )))
|
||||
if ((src.scan.function && src.scan.function != "storage"))
|
||||
src.func = src.scan.function
|
||||
src.special = src.scan.special
|
||||
if (src.scan.data)
|
||||
src.data = src.scan.data
|
||||
else
|
||||
src.temp = "No disk found or core data access lock out!"
|
||||
if (href_list["c_dat"])
|
||||
if (!( src.status ))
|
||||
src.func = null
|
||||
src.data = null
|
||||
src.special = null
|
||||
else
|
||||
src.temp = "No disk found or core data access lock out!"
|
||||
if (href_list["clear"])
|
||||
src.temp = null
|
||||
if (href_list["abort"])
|
||||
src.status = null
|
||||
if (href_list["e_dat"])
|
||||
if (!( src.status ))
|
||||
src.status = "load"
|
||||
src.temp = "Loading..."
|
||||
src.add_fingerprint(usr)
|
||||
for(var/mob/M in viewers(1, src))
|
||||
if ((M.client && M.machine == src))
|
||||
src.attack_hand(M)
|
||||
//Foreach goto(484)
|
||||
return
|
||||
|
||||
/obj/machinery/restruct/allow_drop()
|
||||
|
||||
return 0
|
||||
return
|
||||
|
||||
/obj/machinery/restruct/verb/eject()
|
||||
set src in oview(1)
|
||||
|
||||
if (usr.stat != 0)
|
||||
return
|
||||
src.go_out()
|
||||
add_fingerprint(usr)
|
||||
return
|
||||
|
||||
/obj/machinery/restruct/verb/operate()
|
||||
set src in oview(1)
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
if ((src.occupant && src.occupant.primary))
|
||||
switch(src.occupant.primary.spec_identity)
|
||||
if("5BDFE293BA5500F9FFFD500AAFFE")
|
||||
if (!( istype(src.occupant, /mob/human) ))
|
||||
for(var/obj/O in src.occupant)
|
||||
//O = null
|
||||
del(O)
|
||||
//Foreach goto(78)
|
||||
var/mob/human/O = new /mob/human( src )
|
||||
var/mob/M = src.occupant
|
||||
O.start = 1
|
||||
O.primary = M.primary
|
||||
M.primary = null
|
||||
var/t1 = hex2num(copytext(O.primary.uni_identity, 25, 28))
|
||||
if (t1 < 125)
|
||||
O.gender = "male"
|
||||
else
|
||||
O.gender = "female"
|
||||
M << "Genetic Transversal Complete!"
|
||||
if (M.client)
|
||||
M << "Transferring..."
|
||||
M.client.mob = O
|
||||
O << "Neural Sequencing Complete!"
|
||||
O.loc = src
|
||||
src.occupant = O
|
||||
//M = null
|
||||
del(M)
|
||||
src.occupant = O
|
||||
src.occupant << "Done!"
|
||||
if("2B6696D2B127E5A4")
|
||||
if (!( istype(src.occupant, /mob/monkey) ))
|
||||
for(var/obj/O in src.occupant)
|
||||
//O = null
|
||||
del(O)
|
||||
//Foreach goto(337)
|
||||
var/mob/monkey/O = new /mob/monkey( src )
|
||||
var/mob/M = src.occupant
|
||||
O.start = 1
|
||||
O.primary = M.primary
|
||||
M.primary = null
|
||||
M << "Genetic Transversal Complete!"
|
||||
if (M.client)
|
||||
M << "Transferring..."
|
||||
M.client.mob = O
|
||||
O << "Neural Sequencing Complete!"
|
||||
O.loc = src
|
||||
O << "Genetic Transversal Complete!"
|
||||
src.occupant = O
|
||||
//M = null
|
||||
del(M)
|
||||
O.name = text("monkey ([])", copytext(md5(src.occupant.primary.uni_identity), 2, 6))
|
||||
src.occupant << "Done!"
|
||||
else
|
||||
if (istype(src.occupant, /mob/human))
|
||||
var/mob/human/H = src.occupant
|
||||
if (reg_dna[text("[]", H.primary.uni_identity)])
|
||||
H.rname = reg_dna[text("[]", H.primary.uni_identity)]
|
||||
else
|
||||
if (findname("Unknown"))
|
||||
var/counter = 1
|
||||
while(findname(text("Unknown #[]", counter)))
|
||||
counter++
|
||||
H.rname = text("Unknown #[]", counter)
|
||||
else
|
||||
H.rname = "Unknown"
|
||||
reg_dna[text("[]", H.primary.uni_identity)] = H.rname
|
||||
H << text("\red <B>Your name is now [].</B>", H.rname)
|
||||
var/speak = (length(H.primary.struc_enzyme) >= 25 ? hex2num(copytext(H.primary.struc_enzyme, 22, 25)) : 9999)
|
||||
var/ears = (length(H.primary.struc_enzyme) >= 10 ? hex2num(copytext(H.primary.struc_enzyme, 7, 10)) : 9999)
|
||||
var/vision = (length(H.primary.struc_enzyme) >= 16 ? hex2num(copytext(H.primary.struc_enzyme, 13, 16)) : 1)
|
||||
var/mental1 = (length(H.primary.struc_enzyme) >= 31 ? hex2num(copytext(H.primary.struc_enzyme, 28, 31)) : 1)
|
||||
var/mental2 = (length(H.primary.struc_enzyme) >= 28 ? hex2num(copytext(H.primary.struc_enzyme, 25, 28)) : 1)
|
||||
var/speak2 = (length(H.primary.struc_enzyme) >= 22 ? hex2num(copytext(H.primary.struc_enzyme, 19, 22)) : 1)
|
||||
H.sdisabilities = 0
|
||||
H.disabilities = 0
|
||||
if (speak < 3776)
|
||||
H.disabilities = H.disabilities | 4
|
||||
else
|
||||
if (speak > 3776)
|
||||
H.sdisabilities = H.sdisabilities | 2
|
||||
if (speak2 < 2640)
|
||||
H.disabilities = H.disabilities | 16
|
||||
if (ears > 3226)
|
||||
H.sdisabilities = H.sdisabilities | 4
|
||||
if (vision < 1447)
|
||||
H.sdisabilities = H.sdisabilities | 1
|
||||
else
|
||||
if (vision > 1447)
|
||||
H.disabilities = H.disabilities | 1
|
||||
if (mental1 < 1742)
|
||||
H.disabilities = H.disabilities | 2
|
||||
if (mental2 < 1452)
|
||||
H.disabilities = H.disabilities | 8
|
||||
var/t1 = null
|
||||
if (length(H.primary.uni_identity) >= 20)
|
||||
t1 = copytext(H.primary.uni_identity, 19, 21)
|
||||
if (hex2num(t1) > 127)
|
||||
H.gender = "female"
|
||||
else
|
||||
H.gender = "male"
|
||||
else
|
||||
H.gender = "neuter"
|
||||
if (length(H.primary.uni_identity) >= 18)
|
||||
t1 = copytext(H.primary.uni_identity, 17, 19)
|
||||
H.ns_tone = hex2num(t1)
|
||||
H.ns_tone = -H.ns_tone + 35
|
||||
else
|
||||
H.ns_tone = 1
|
||||
H.ns_tone = -H.ns_tone + 35
|
||||
if (length(H.primary.uni_identity) >= 16)
|
||||
t1 = copytext(H.primary.uni_identity, 15, 17)
|
||||
H.b_eyes = hex2num(t1)
|
||||
else
|
||||
H.b_eyes = 255
|
||||
if (length(H.primary.uni_identity) >= 14)
|
||||
t1 = copytext(H.primary.uni_identity, 13, 15)
|
||||
H.g_eyes = hex2num(t1)
|
||||
else
|
||||
H.g_eyes = 255
|
||||
if (length(H.primary.uni_identity) >= 12)
|
||||
t1 = copytext(H.primary.uni_identity, 11, 13)
|
||||
H.r_eyes = hex2num(t1)
|
||||
else
|
||||
H.r_eyes = 255
|
||||
if (length(H.primary.uni_identity) >= 10)
|
||||
t1 = copytext(H.primary.uni_identity, 9, 11)
|
||||
H.nb_hair = hex2num(t1)
|
||||
else
|
||||
H.nb_hair = 255
|
||||
if (length(H.primary.uni_identity) >= 8)
|
||||
t1 = copytext(H.primary.uni_identity, 7, 9)
|
||||
H.ng_hair = hex2num(t1)
|
||||
else
|
||||
H.ng_hair = 255
|
||||
if (length(H.primary.uni_identity) >= 6)
|
||||
t1 = copytext(H.primary.uni_identity, 5, 7)
|
||||
H.nr_hair = hex2num(t1)
|
||||
else
|
||||
H.nr_hair = 255
|
||||
H.r_hair = H.nr_hair
|
||||
H.g_hair = H.ng_hair
|
||||
H.b_hair = H.nb_hair
|
||||
H.s_tone = H.ns_tone
|
||||
H.update_face()
|
||||
H.update_body()
|
||||
return
|
||||
|
||||
/obj/machinery/restruct/verb/move_inside()
|
||||
set src in oview(1)
|
||||
|
||||
if (usr.stat != 0)
|
||||
return
|
||||
if (src.occupant)
|
||||
usr << "\blue <B>The scanner is already occupied!</B>"
|
||||
return
|
||||
if (usr.abiotic())
|
||||
usr << "\blue <B>Subject cannot have abiotic items on.</B>"
|
||||
return
|
||||
usr.pulling = null
|
||||
usr.client.perspective = EYE_PERSPECTIVE
|
||||
usr.client.eye = src
|
||||
usr.loc = src
|
||||
src.occupant = usr
|
||||
src.icon_state = "restruct_1"
|
||||
for(var/obj/O in src)
|
||||
//O = null
|
||||
del(O)
|
||||
//Foreach goto(124)
|
||||
src.add_fingerprint(usr)
|
||||
return
|
||||
|
||||
/obj/machinery/restruct/relaymove(mob/user as mob)
|
||||
|
||||
if (user.stat)
|
||||
return
|
||||
src.go_out()
|
||||
return
|
||||
|
||||
/obj/machinery/restruct/attackby(obj/item/weapon/grab/G as obj, user as mob)
|
||||
|
||||
if ((!( istype(G, /obj/item/weapon/grab) ) || !( ismob(G.affecting) )))
|
||||
return
|
||||
if (src.occupant)
|
||||
user << "\blue <B>The machine is already occupied!</B>"
|
||||
return
|
||||
if (G.affecting.abiotic())
|
||||
user << "\blue <B>Subject cannot have abiotic items on.</B>"
|
||||
return
|
||||
var/mob/M = G.affecting
|
||||
if (M.client)
|
||||
M.client.perspective = EYE_PERSPECTIVE
|
||||
M.client.eye = src
|
||||
M.loc = src
|
||||
src.occupant = M
|
||||
src.icon_state = "restruct_1"
|
||||
for(var/obj/O in src)
|
||||
O.loc = src.loc
|
||||
//Foreach goto(154)
|
||||
src.add_fingerprint(user)
|
||||
//G = null
|
||||
del(G)
|
||||
return
|
||||
|
||||
/obj/machinery/restruct/proc/go_out()
|
||||
|
||||
if ((!( src.occupant ) || src.locked))
|
||||
return
|
||||
for(var/obj/O in src)
|
||||
O.loc = src.loc
|
||||
//Foreach goto(30)
|
||||
if (src.occupant.client)
|
||||
src.occupant.client.eye = src.occupant.client.mob
|
||||
src.occupant.client.perspective = MOB_PERSPECTIVE
|
||||
src.occupant.loc = src.loc
|
||||
src.occupant = null
|
||||
src.icon_state = "restruct_0"
|
||||
return
|
||||
|
||||
/obj/machinery/restruct/ex_act(severity)
|
||||
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
for(var/atom/movable/A as mob|obj in src)
|
||||
A.loc = src.loc
|
||||
ex_act(severity)
|
||||
//Foreach goto(35)
|
||||
//SN src = null
|
||||
del(src)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
for(var/atom/movable/A as mob|obj in src)
|
||||
A.loc = src.loc
|
||||
ex_act(severity)
|
||||
//Foreach goto(108)
|
||||
//SN src = null
|
||||
del(src)
|
||||
return
|
||||
if(3.0)
|
||||
if (prob(25))
|
||||
for(var/atom/movable/A as mob|obj in src)
|
||||
A.loc = src.loc
|
||||
ex_act(severity)
|
||||
//Foreach goto(181)
|
||||
//SN src = null
|
||||
del(src)
|
||||
return
|
||||
else
|
||||
return
|
||||
|
||||
/obj/machinery/restruct/blob_act()
|
||||
|
||||
if(prob(50))
|
||||
for(var/atom/movable/A as mob|obj in src)
|
||||
A.loc = src.loc
|
||||
del(src)
|
||||
+205
@@ -0,0 +1,205 @@
|
||||
#define ENGINE_EJECT_Z 6
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/turf/station/engine/attack_paw(var/mob/user as mob)
|
||||
|
||||
return src.attack_hand(user)
|
||||
|
||||
/turf/station/engine/attack_hand(var/mob/user as mob)
|
||||
|
||||
if ((!( user.canmove ) || user.restrained() || !( user.pulling )))
|
||||
return
|
||||
if (user.pulling.anchored)
|
||||
return
|
||||
if ((user.pulling.loc != user.loc && get_dist(user, user.pulling) > 1))
|
||||
return
|
||||
if (ismob(user.pulling))
|
||||
var/mob/M = user.pulling
|
||||
var/mob/t = M.pulling
|
||||
M.pulling = null
|
||||
step(user.pulling, get_dir(user.pulling.loc, src))
|
||||
M.pulling = t
|
||||
else
|
||||
step(user.pulling, get_dir(user.pulling.loc, src))
|
||||
return
|
||||
|
||||
/turf/station/engine/attackby(obj/item/weapon/C as obj, mob/user as mob)
|
||||
|
||||
if (istype(C, /obj/item/weapon/pipe) )
|
||||
var/obj/item/weapon/pipe/P = C
|
||||
P.turf_place(src, user)
|
||||
|
||||
/turf/station/engine/floor/ex_act(severity)
|
||||
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
//SN src = null
|
||||
var/turf/space/S = new /turf/space( locate(src.x, src.y, src.z) )
|
||||
S.buildlinks()
|
||||
del(src)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
//SN src = null
|
||||
var/turf/space/S = new /turf/space( locate(src.x, src.y, src.z) )
|
||||
S.buildlinks()
|
||||
|
||||
del(src)
|
||||
return
|
||||
else
|
||||
return
|
||||
|
||||
/turf/station/engine/floor/blob_act()
|
||||
return
|
||||
|
||||
/datum/engine_eject/proc/ejectstart()
|
||||
|
||||
if (!( src.status ))
|
||||
if (src.timeleft <= 0)
|
||||
src.timeleft = 60
|
||||
world << "\red <B>Alert: Ejection Sequence for Engine Module has been engaged.</B>"
|
||||
world << text("\red <B>Ejection Time in T-[] seconds!</B>", src.timeleft)
|
||||
src.resetting = 0
|
||||
|
||||
var/list/EA = engine_areas()
|
||||
|
||||
for(var/area/A in EA)
|
||||
A.eject = 1
|
||||
A.updateicon()
|
||||
|
||||
src.status = 1
|
||||
for(var/obj/machinery/computer/engine/E in machines)
|
||||
E.icon_state = "engaging"
|
||||
//Foreach goto(113)
|
||||
spawn( 0 )
|
||||
src.countdown()
|
||||
return
|
||||
return
|
||||
|
||||
/datum/engine_eject/proc/resetcount()
|
||||
|
||||
if (!( src.status ))
|
||||
src.resetting = 1
|
||||
sleep(50)
|
||||
if (src.resetting)
|
||||
src.timeleft = 60
|
||||
world << "\red <B>Alert: Ejection Sequence Countdown for Engine Module has been reset.</B>"
|
||||
return
|
||||
|
||||
/datum/engine_eject/proc/countdone()
|
||||
|
||||
src.status = -1.0
|
||||
|
||||
var/list/E = engine_areas()
|
||||
|
||||
var/list/engineturfs = list()
|
||||
for(var/area/EA in E)
|
||||
EA.eject = 0
|
||||
EA.updateicon()
|
||||
for(var/turf/ET in EA)
|
||||
engineturfs += ET
|
||||
|
||||
defer_powernet_rebuild = 1
|
||||
for(var/turf/T in engineturfs)
|
||||
var/turf/S = new T.type( locate(T.x, T.y, ENGINE_EJECT_Z) )
|
||||
|
||||
var/area/A = T.loc
|
||||
|
||||
for(var/atom/movable/AM as mob|obj in T)
|
||||
AM.loc = S
|
||||
S.oxygen = T.oxygen
|
||||
S.oldoxy = T.oldoxy
|
||||
S.tmpoxy = T.tmpoxy
|
||||
S.poison = T.poison
|
||||
S.oldpoison = T.oldpoison
|
||||
S.tmppoison = T.tmppoison
|
||||
S.co2 = T.co2
|
||||
S.oldco2 = T.oldco2
|
||||
S.tmpco2 = T.tmpco2
|
||||
S.sl_gas = T.sl_gas
|
||||
S.osl_gas = T.osl_gas
|
||||
S.tsl_gas = T.tsl_gas
|
||||
S.n2 = T.n2
|
||||
S.on2 = T.on2
|
||||
S.tn2 = T.tn2
|
||||
S.temp = T.temp
|
||||
S.ttemp = T.ttemp
|
||||
S.otemp = T.otemp
|
||||
S.firelevel = T.firelevel
|
||||
//Foreach goto(100)
|
||||
S.buildlinks()
|
||||
|
||||
|
||||
|
||||
A.contents += S
|
||||
var/turf/P = new T.type( locate(T.x, T.y, T.z) )
|
||||
var/area/D = locate(/area/dummy)
|
||||
D.contents += P
|
||||
|
||||
//T = null
|
||||
|
||||
del(T)
|
||||
P.buildlinks()
|
||||
|
||||
|
||||
|
||||
//Foreach goto(60)
|
||||
defer_powernet_rebuild = 0
|
||||
makepowernets()
|
||||
world << "\red <B>Engine Ejected!</B>"
|
||||
for(var/obj/machinery/computer/engine/CE in machines)
|
||||
CE.icon_state = "engaged"
|
||||
//Foreach goto(392)
|
||||
return
|
||||
|
||||
/datum/engine_eject/proc/stopcount()
|
||||
|
||||
if (src.status > 0)
|
||||
src.status = 0
|
||||
world << "\red <B>Alert: Ejection Sequence for Engine Module has been disengaged!</B>"
|
||||
|
||||
var/list/E = engine_areas()
|
||||
|
||||
for(var/area/A in E)
|
||||
A.eject = 0
|
||||
A.updateicon()
|
||||
|
||||
for(var/obj/machinery/computer/engine/CE in machines)
|
||||
CE.icon_state = null
|
||||
//Foreach goto(84)
|
||||
return
|
||||
|
||||
/datum/engine_eject/proc/countdown()
|
||||
|
||||
if (src.timeleft <= 0)
|
||||
spawn( 0 )
|
||||
countdone()
|
||||
return
|
||||
return
|
||||
if (src.status > 0)
|
||||
src.timeleft--
|
||||
if ((src.timeleft <= 15 || src.timeleft == 30))
|
||||
world << text("\red <B>[] seconds until engine ejection.</B>", src.timeleft)
|
||||
spawn( 10 )
|
||||
src.countdown()
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
//returns a list of areas that are under /area/engine
|
||||
/datum/engine_eject/proc/engine_areas()
|
||||
var/list/L = list()
|
||||
for(var/area/A in world)
|
||||
if(istype(A, /area/engine))
|
||||
L += A
|
||||
|
||||
return L
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
+372
@@ -0,0 +1,372 @@
|
||||
/* Most recent changes (Since H9.6)
|
||||
|
||||
Contining reorg of obj/machinery code
|
||||
Changed how solar panel directions are displayed, to fix the rotation display bug.
|
||||
|
||||
Added remote APC control the power_monitor
|
||||
Fixed a bug where APCs would continue to draw power for cell charging even when the breaker was off.
|
||||
|
||||
Added CO2 to gasbomb proc (plasmatank/proc/release())
|
||||
|
||||
Moved computer objects ex_act() to base type (since all are identical)
|
||||
|
||||
|
||||
|
||||
(Since H9.5)
|
||||
|
||||
Started pipelaying system, /obj/item/weapon/pipe.
|
||||
|
||||
Added burning icon for labcoat
|
||||
Fixed a minor airsystem bug for /obj/moves
|
||||
Fixed admin toggle of mode-voting message (now reports state of allowvotemode correctly)
|
||||
Engine ejection now carries over firelevel of turfs
|
||||
Fixed bug with aux engine not working if started too quickly.
|
||||
|
||||
Converted pipelines to use list exclusively, rather than numbers (so that list can be modified)
|
||||
Continues pipe laying - some checking of new lines now done, needs 2-pipe case
|
||||
|
||||
Finished pipe laying - needs checking for all cases
|
||||
|
||||
Updated autolathe to make pipe fittings
|
||||
|
||||
Changed maximum circulator rates to give a better range of working values.
|
||||
Fixed firealarm triggering when unpowered.
|
||||
Made a temporary fix to runtime errors when blob attacks pipes (until full pipe damage system implemented).
|
||||
|
||||
Code reorganization of obj/machinery continued.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/* To-do list
|
||||
|
||||
Bugs:
|
||||
hearing inside closets/pods
|
||||
check head protection when hit by tank etc.
|
||||
|
||||
Double message at end of round.
|
||||
|
||||
gas progagation btwen obj/move & turfs - no flow
|
||||
due to turf/updatecell not counting /obj/moves as sources
|
||||
//firelevel lost when ejecting engine
|
||||
|
||||
|
||||
bug with two single-length pipes overlaying - pipeline ends up with no members
|
||||
|
||||
alarm continuing when power out?
|
||||
|
||||
|
||||
|
||||
New:
|
||||
|
||||
recode obj/move stuff to use turfs exclusively?
|
||||
|
||||
make regular glass melt in fire
|
||||
Blood splatters, can sample DNA & analyze
|
||||
also blood stains on clothing - attacker & defender
|
||||
|
||||
whole body anaylzer in medbay - shows damage areas in popup?
|
||||
|
||||
try station map maximizing use of image rather than icon
|
||||
|
||||
useful world/Topic commands
|
||||
|
||||
flow rate maximum for pipes - slowest of two connected notes
|
||||
|
||||
system for breaking / making pipes, handle deletion, pipeline spliting/rejoining etc.
|
||||
|
||||
|
||||
add power-off mode for computers & other equipment (with reboot time)
|
||||
|
||||
make grilles conductive for shocks (again)
|
||||
|
||||
for prison warden/sec - baton allows precise targeting
|
||||
|
||||
portable generator - hook to wire system
|
||||
|
||||
modular repair/construction system
|
||||
maintainance key
|
||||
diagnostic tool
|
||||
modules - module construction
|
||||
|
||||
|
||||
hats/caps
|
||||
suit?
|
||||
|
||||
build/unbuild engine floor with rf sheet
|
||||
|
||||
crowbar opens airlocks when no power
|
||||
|
||||
*/
|
||||
|
||||
|
||||
var
|
||||
|
||||
world_message = "Welcome to SS13!"
|
||||
savefile_ver = "3"
|
||||
SS13_version = "40.93.2H9.6"
|
||||
changes = {"<FONT color='blue'><B>Changes from base version 40.93.2</B></FONT><BR>
|
||||
<HR>
|
||||
<p><B>Version 40.93.2H9.6</B>
|
||||
<ul>
|
||||
<li> Started pipelaying system, Pipe cutting/damage not yet complete.
|
||||
<li>Added burning icon for labcoat
|
||||
<li>Fixed a minor airsystem bug for /obj/moves
|
||||
<li>Fixed admin toggle of mode-voting message (now reports state of allowvotemode correctly)
|
||||
<li>Engine ejection now carries over firelevel of turfs
|
||||
<li>Fixed bug with aux engine not working if started too quickly.
|
||||
<li>Updated autolathe to make pipe fittings
|
||||
<li>Lowererd maximum circulator rates to give a better range of working values.
|
||||
<li>Fixed firealarm triggering when unpowered.
|
||||
<li>Made a temporary fix to runtime errors when blob attacks pipes (until full pipe damage system implemented).
|
||||
<li>Code reorganization of /obj/machinery continued.
|
||||
</ul>
|
||||
<p><B>Version 40.93.2H9.5</B>
|
||||
<ul>
|
||||
<li>Fixed a few bugs with reinforced windows.
|
||||
<li>Adding turbine generator to aux. engine.
|
||||
<li>Added Hikato's Sandbox mode.
|
||||
<li>Fixed bug with repairing walls and cable visibility.
|
||||
</ul>
|
||||
<p><B>Version 40.93.2H9.4</B>
|
||||
<ul>
|
||||
<li>Initial version of new generator (not yet completly working). Redesigned and remapped engine and generator.
|
||||
<li>T-scanners now have a chance to reveal cloakers when in range.
|
||||
<li>Fire extinguishers and throwing object can be used to manoeuvre in space to a limited extent.
|
||||
<li>SMESes now more user-friendly, will charge automatically if power available.
|
||||
<li>Can now config so votes from dead players aren't counted.
|
||||
<li>Can now config so player votes default to no vote.
|
||||
<li>Players can now reply to Admin PMs.
|
||||
</ul>
|
||||
<p><B>Version 40.93.2H9.3</B>
|
||||
<ul>
|
||||
<li>Added main power storage devices (SMES). Reconfigured map power system to use them.
|
||||
<li>Added backup solar power generators and added them to the map.
|
||||
<li>Added custom job name assignments through the ID computer.
|
||||
<li>Engine cannot be ejected now without sufficient ID access.
|
||||
<li>Cable can now be directly connected from a turf to a power device (SMES, generator, etc.)
|
||||
<li>Admins & above can now observe when not dead. (Now fixed).
|
||||
<li>Solar panel controllers can now be set to rotate the panels at a given rate.
|
||||
<li>Fixed a problem with client inactivity discounting votes much too soon.
|
||||
</ul>
|
||||
<p><B>Version 40.93.2H9.2</B>
|
||||
<ul>
|
||||
<li>Added some new admin options,
|
||||
<li>Added 1st test version of engine power generator.
|
||||
<li>Rewrote canister/pipework connection routines to fix a gas conservation bug.
|
||||
<li>Valves don't require power to switch anymore.
|
||||
<li>T-scanners can now be clipped on belts.
|
||||
<li>Added a cell recharger.
|
||||
<li>Some small map changes.
|
||||
<li>Fixed crashes with admin Vars command.
|
||||
<li>Fixed cable-cutting bug that sometimes did not update the power network.
|
||||
<li>Fixed bugs when making reinforced glass.
|
||||
<li>Destroyed canisters can now be disconnected from a pipe.
|
||||
</ul>
|
||||
<p><B>Version 40.93.2H9.1</B>
|
||||
<ul>
|
||||
<li>Cable item added. Cable cutting now works. Cable laying started.
|
||||
<li>Fixed stacking bug with tiles, sheets etc.
|
||||
<li>Newly laid cable now merges with existing powernets.
|
||||
<li>Added power supply from a dummy generator object for testing. Power switching logic still buggy.
|
||||
<li>Cables now affected by explosions & fire. Automatically rebuild power network when deleted.
|
||||
<li>Improved power switching logic.
|
||||
<li>Addeed high-capacity power cells to some key area APCs.
|
||||
<li>Most machines now cannot be operated when unpowered.
|
||||
<li>Made the station cable layout much more redundant. It's no long possible to disable the whole grid with a single cut.
|
||||
<li>Added a monitoring computer to the engine.
|
||||
<li>Canisters are now attached to a connector with a wrench (more logical than a screwdriver).
|
||||
<li>It's now hazardous to cut or modify powered cable without proper protection.
|
||||
<li>Grilles can now be electrified, and have a chance of shocking someone if attacked.
|
||||
</ul>
|
||||
<p><B>Version 40.93.2H9</B>
|
||||
<ul>
|
||||
<li>APC added, with test functionality. Started adding power requirements to machinery objects. (Wire system, power generators & cell charging not yet implemented.)
|
||||
<li>Fixed bug with lightswitches that wouldn't turn back on.
|
||||
<li>Power usage added for most machines. APCs currently running only on battery power, no way to recharge. Underfloor wire system placed but non-operational.
|
||||
<li>Some background events added to Blob mode.
|
||||
<li>Fixed some air propagation bugs and optimized some procedures.
|
||||
<li>Power networks created, but not functional as yet.
|
||||
<li>Added a scanner for underfloor wires and pipes.
|
||||
<li>Modified underfloor hiding system to be more general.
|
||||
</ul>
|
||||
<p><B>Version 40.93.2H8</B>
|
||||
<ul>
|
||||
<li>Fixed bug with cryo freezer and flask changing.
|
||||
<li>Fixed numerous runtime errors.
|
||||
<li>Re-added nuclear mode to vote and config file.
|
||||
<li>Char setup now autoloaded if your savefile exist
|
||||
<li>Added reset button to char setup.
|
||||
<li>Fixed move-to-top while dead.
|
||||
<li>Fixed bug with voting before round begins.
|
||||
<li>Fixed bug with engine ejection areas.
|
||||
<li>Started work on power system. Lightswitches added to map. Area icon system updated.
|
||||
<li>Fixed spawning on top of dense objects.
|
||||
<li>Later enterers now get ID card access levels corresponding to their job.
|
||||
</ul>
|
||||
<p><B>Version 40.93.2H7.1D</B>
|
||||
<ul>
|
||||
<li>Total overhaul of pipework system. Circulators, manifolds, junctions, pipelines added.
|
||||
<li>Heat exchange pipe added. Pipes now affect and are affected by turf temperature.
|
||||
<li>Made connected canisters automatically anchored at startup.
|
||||
<li>Removed redundant heat variable from turfs.
|
||||
<li>Tweaked pipe-turf heat exchange to avoid thermal runaway.
|
||||
<li>Added valves and vents to pipework system. Fixed gas loss problem with connectors.
|
||||
<li>Added Captain specific closet and jumpsuite.
|
||||
</ul>
|
||||
<p><B>Version 40.93.2H7.0D</B>
|
||||
<ul>
|
||||
<li>Total overhaul of gas temperature system. Fixed temp. loss problem with scrubbers/vents
|
||||
</ul>
|
||||
<p><B>Version 40.93.2H6.4D</B>
|
||||
<ul>
|
||||
<li>Added player voting system for server reboot and game mode
|
||||
<li>Added config options for voting system
|
||||
<li>Made mode choice persistent across server reboots
|
||||
<li>Removed vote delay after server reboot
|
||||
<li>Tweaked pipework operation slightly
|
||||
<li>Fixed bug with ID computer
|
||||
<li>Added reinforced windows, reinf. glass sheets, etc.
|
||||
<li>Fixed a win condition bug with location of stolen item in traitor mode
|
||||
</ul>
|
||||
<p><B>Version 40.93.2H6.3D</B>
|
||||
<ul>
|
||||
<li>Fixed firelarms so they can be sabotaged successfully
|
||||
<li>"Random" mode added (like secret but actual mode is announced)
|
||||
<li>Fixed more bugs with DNA-scanner
|
||||
<li>Fixed cryocell bug with gas transfer
|
||||
<li>Moved all testing verbs to admin-only
|
||||
<li>Re-wrote damage icon system to fix standing mob image and skin tone change bugs
|
||||
<li>Added external config file for logging options
|
||||
<li>Enabled config of secret/random mode pick probabilities
|
||||
</ul>
|
||||
<p><B>Version 40.93.2H6.2D</B>
|
||||
<ul>
|
||||
<li>Fixed bug with floor tile stacking/use.
|
||||
<li>Say/OOC now strips control characters.
|
||||
<li>Fixed call error in rwall disassembly.
|
||||
<li>Fixed pulling after item anchoring.
|
||||
<li>Adjusted pipe/connector logic to enable pipework.
|
||||
<li>Fixed background bug with certain procs.
|
||||
<li>Fixed Engineer security levels in job info text.
|
||||
</ul>
|
||||
<p><B>Version 40.93.2H6.1D</B>
|
||||
<ul><li>Airflow system changed to use cached FindTurfs (2x faster).
|
||||
<li>Cell, Flow and Clear test verbs added to check airflow changes.
|
||||
<li>Added Vars verb for object state checking.
|
||||
<li>Current XYZ added to statpanel (for testing).
|
||||
<li>Fixed score report in blob mode.
|
||||
<li>Start_now added to admin commands.
|
||||
<li>Partially fixed bug with standing mob image after death.
|
||||
<li>Default movement speed is now run.
|
||||
</ul>
|
||||
<p><B>Version 40.93.2H6</B>
|
||||
<ul>
|
||||
<li>Timer interface auto-closes on drop.
|
||||
<li>Fixed welding doors with non-active welder.
|
||||
<li>Fixed self-deletion bug with bombs.
|
||||
<li>Added new Blob gameplay mode.
|
||||
<li>Fixed shuttle & eject positioning logic for non-default maps.
|
||||
<li>Mass drivers with same ID now all fire together.
|
||||
<li>Server logging of logon, logoff & OOC added.
|
||||
</ul>
|
||||
<p><B>Version 40.93.2H5</B>
|
||||
<ul>
|
||||
<li>Added move-to-top verb to sort item stacks.
|
||||
<li>Gasmask, firealarm, and eject alarm overlays changed to alpha-blend textures.
|
||||
<li>Doors allow empty-handed click to open (if wearing correct ID).
|
||||
<li>Dedicated remote door controller added for poddoors.
|
||||
<li>Poddoor icon changed.
|
||||
<li>Alarm icon changed. Now reports air stats on examine.
|
||||
<li>Timer/Igniter & Timer/Igniter/Plasmatank assemblies added.
|
||||
<li>Bombs act as firebombs if plasma tank hole isn't bored.
|
||||
<li>Fixed airflow bug with interior doors.
|
||||
<li>Security computers now have minimap of station.
|
||||
<li>Arm verb added to proximity detectors/assemblies.
|
||||
<li>Proximity detectors fire if they bump.
|
||||
<li>Timer and Motion assemblies state icons added.
|
||||
<li>Meteors can now explode (sometimes).
|
||||
</ul>
|
||||
"}
|
||||
datum/air_tunnel/air_tunnel1/SS13_airtunnel = null
|
||||
datum/control/cellular/cellcontrol = null
|
||||
datum/control/gameticker/ticker = null
|
||||
obj/datacore/data_core = null
|
||||
obj/overlay/plmaster = null
|
||||
obj/overlay/slmaster = null
|
||||
going = 1.0
|
||||
master_mode = "random"//"extended"
|
||||
|
||||
persistent_file = "mode.txt"
|
||||
|
||||
obj/ctf_assist/ctf = null
|
||||
nuke_code = null
|
||||
poll_controller = null
|
||||
datum/engine_eject/engine_eject_control = null
|
||||
host = null
|
||||
obj/hud/main_hud = null
|
||||
obj/hud/hud2/main_hud2 = null
|
||||
ooc_allowed = 1.0
|
||||
dna_ident = 1.0
|
||||
abandon_allowed = 1.0
|
||||
enter_allowed = 1.0
|
||||
shuttle_frozen = 0.0
|
||||
prison_entered = null
|
||||
|
||||
list/html_colours = new/list(0)
|
||||
list/occupations = list( "Engineer", "Engineer", "Security Officer", "Security Officer", "Forensic Technician", "Medical Researcher", "Research Technician", "Toxin Researcher", "Atmospheric Technician", "Medical Doctor", "Station Technician", "Head of Personnel", "Head of Research", "Prison Security", "Prison Security", "Prison Doctor", "Prison Warden" )
|
||||
list/assistant_occupations = list( "Technical Assistant", "Medical Assistant", "Research Assistant", "Staff Assistant" )
|
||||
list/bombers = list( )
|
||||
list/admins = list( )
|
||||
list/shuttles = list( )
|
||||
list/reg_dna = list( )
|
||||
list/banned = list( )
|
||||
|
||||
|
||||
//
|
||||
shuttle_z = 10 //default
|
||||
list/monkeystart = list()
|
||||
list/blobstart = list()
|
||||
list/blobs = list()
|
||||
list/cardinal = list( NORTH, EAST, SOUTH, WEST )
|
||||
|
||||
|
||||
datum/station_state/start_state = null
|
||||
datum/config/config = null
|
||||
datum/vote/vote = null
|
||||
datum/sun/sun = null
|
||||
|
||||
list/plines = list()
|
||||
list/gasflowlist = list()
|
||||
list/machines = list()
|
||||
|
||||
list/powernets = null
|
||||
|
||||
defer_powernet_rebuild = 0 // true if net rebuild will be called manually after an event
|
||||
|
||||
Debug = 0 // global debug switch
|
||||
|
||||
datum/debug/debugobj
|
||||
|
||||
datum/moduletypes/mods = new()
|
||||
|
||||
wavesecret = 0
|
||||
|
||||
world
|
||||
mob = /mob/human
|
||||
turf = /turf/space
|
||||
area = /area
|
||||
view = "15x15"
|
||||
|
||||
hub = "Exadv1.spacestation13"
|
||||
hub_password = "kMZy3U5jJHSiBQjr"
|
||||
//hub = "Hobnob.SS13D"
|
||||
//hub = "Stephen001.CustomSpaceStation13"
|
||||
name = "Space Station 13"
|
||||
|
||||
|
||||
|
||||
//visibility = 0
|
||||
|
||||
//loop_checks = 0
|
||||
@@ -0,0 +1,140 @@
|
||||
var
|
||||
hsboxspawn = 0
|
||||
list
|
||||
hrefs = list(
|
||||
"hsbsuit" = "Suit Up (Space Travel Gear)",
|
||||
"hsbmetal" = "Spawn 50 Metal",
|
||||
"hsbglass" = "Spawn 50 Glass",
|
||||
"hsbairlock" = "Spawn Airlock",
|
||||
"hsbregulator" = "Spawn Air Regulator",
|
||||
"hsbfilter" = "Spawn Air Filter",
|
||||
"hsbcanister" = "Spawn Canister",
|
||||
"hsbfueltank" = "Spawn Welding Fuel Tank",
|
||||
"hsbwater tank" = "Spawn Water Tank",
|
||||
"hsbtoolbox" = "Spawn Toolbox",
|
||||
"hsbmedkit" = "Spawn Medical Kit")
|
||||
|
||||
mob
|
||||
var
|
||||
datum/hSB/sandbox = null
|
||||
proc
|
||||
CanBuild()
|
||||
if(master_mode == "sandbox")
|
||||
sandbox = new/datum/hSB
|
||||
sandbox.owner = src.ckey
|
||||
if(src.client.holder)
|
||||
sandbox.admin = 1
|
||||
verbs += new/mob/proc/sandbox_panel
|
||||
sandbox_panel()
|
||||
if(sandbox)
|
||||
sandbox.update()
|
||||
|
||||
datum/hSB
|
||||
var
|
||||
owner = null
|
||||
admin = 0
|
||||
proc
|
||||
update()
|
||||
var/hsbpanel = "<center><b>h_Sandbox Panel</b></center><hr>"
|
||||
if(admin)
|
||||
hsbpanel += "<b>Administration Tools:</b><br>"
|
||||
hsbpanel += "- <a href=\"?\ref[src];hsb=hsbtobj\">Toggle Object Spawning</a><br><br>"
|
||||
hsbpanel += "<b>Regular Tools:</b><br>"
|
||||
for(var/T in hrefs)
|
||||
hsbpanel += "- <a href=\"?\ref[src];hsb=[T]\">[hrefs[T]]</a><br>"
|
||||
if(hsboxspawn)
|
||||
hsbpanel += "- <a href=\"?\ref[src];hsb=hsbobj\">Spawn Object</a><br><br>"
|
||||
usr << browse(hsbpanel, "window=hsbpanel")
|
||||
Topic(href, href_list)
|
||||
if(!(src.owner == usr.ckey)) return
|
||||
if(href_list["hsb"])
|
||||
switch(href_list["hsb"])
|
||||
if("hsbtobj")
|
||||
if(!admin) return
|
||||
if(hsboxspawn)
|
||||
world << "<b>Sandbox: [usr.key] has disabled object spawning!</b>"
|
||||
hsboxspawn = 0
|
||||
return
|
||||
if(!hsboxspawn)
|
||||
world << "<b>Sandbox: [usr.key] has enabled object spawning!</b>"
|
||||
hsboxspawn = 1
|
||||
return
|
||||
if("hsbsuit")
|
||||
var/mob/human/P = usr
|
||||
if(P.wear_suit)
|
||||
P.wear_suit.loc = P.loc
|
||||
P.wear_suit.layer = initial(P.wear_suit.layer)
|
||||
P.wear_suit = null
|
||||
P.wear_suit = new/obj/item/weapon/clothing/suit/sp_suit(P)
|
||||
P.wear_suit.layer = 20
|
||||
if(P.head)
|
||||
P.head.loc = P.loc
|
||||
P.head.layer = initial(P.head.layer)
|
||||
P.head = null
|
||||
P.head = new/obj/item/weapon/clothing/head/s_helmet(P)
|
||||
P.head.layer = 20
|
||||
if(P.wear_mask)
|
||||
P.wear_mask.loc = P.loc
|
||||
P.wear_mask.layer = initial(P.wear_mask.layer)
|
||||
P.wear_mask = null
|
||||
P.wear_mask = new/obj/item/weapon/clothing/mask/gasmask(P)
|
||||
P.wear_mask.layer = 20
|
||||
if(P.back)
|
||||
P.back.loc = P.loc
|
||||
P.back.layer = initial(P.back.layer)
|
||||
P.back = null
|
||||
P.back = new/obj/item/weapon/tank/jetpack(P)
|
||||
P.back.layer = 20
|
||||
P.internal = P.back
|
||||
if("hsbmetal")
|
||||
var/obj/item/weapon/sheet/hsb = new/obj/item/weapon/sheet/metal
|
||||
hsb.amount = 50
|
||||
hsb.loc = usr.loc
|
||||
if("hsbglass")
|
||||
var/obj/item/weapon/sheet/hsb = new/obj/item/weapon/sheet/glass
|
||||
hsb.amount = 50
|
||||
hsb.loc = usr.loc
|
||||
if("hsbairlock")
|
||||
var/obj/machinery/door/hsb = new/obj/machinery/door/airlock
|
||||
var/r_access = input(usr, "What general access will this airlock require?", "Sandbox:") as num
|
||||
var/r_lab = input(usr, "What laboratory access will this airlock require?", "Sandbox:") as num
|
||||
var/r_engine = input(usr, "What engine access will this airlock require?", "Sandbox:") as num
|
||||
var/r_air = input(usr, "What air access will this airlock require?", "Sandbox:") as num
|
||||
|
||||
hsb.access = "[r_access][r_lab][r_engine][r_air]"
|
||||
|
||||
hsb.loc = usr.loc
|
||||
hsb.loc.buildlinks()
|
||||
usr << "<b>Sandbox: Created an airlock requiring at least [r_access]>[r_lab]-[r_engine]-[r_air] access."
|
||||
if("hsbregulator")
|
||||
var/obj/machinery/atmoalter/siphs/fullairsiphon/hsb = new/obj/machinery/atmoalter/siphs/fullairsiphon/air_vent
|
||||
hsb.loc = usr.loc
|
||||
if("hsbfilter")
|
||||
var/obj/machinery/atmoalter/siphs/scrubbers/hsb = new/obj/machinery/atmoalter/siphs/scrubbers/air_filter
|
||||
hsb.loc = usr.loc
|
||||
if("hsbcanister")
|
||||
var/list/hsbcanisters = typesof(/obj/machinery/atmoalter/canister/) - /obj/machinery/atmoalter/canister/
|
||||
var/hsbcanister = input(usr, "Choose a canister to spawn.", "Sandbox:") in hsbcanisters + "Cancel"
|
||||
if(!(hsbcanister == "Cancel"))
|
||||
new hsbcanister(usr.loc)
|
||||
if("hsbfueltank")
|
||||
var/obj/hsb = new/obj/weldfueltank
|
||||
hsb.loc = usr.loc
|
||||
if("hsbwatertank")
|
||||
var/obj/hsb = new/obj/watertank
|
||||
hsb.loc = usr.loc
|
||||
if("hsbtoolbox")
|
||||
var/obj/item/weapon/storage/hsb = new/obj/item/weapon/storage/toolbox
|
||||
for(var/obj/item/weapon/radio/T in hsb)
|
||||
del(T)
|
||||
new/obj/item/weapon/crowbar (hsb)
|
||||
hsb.loc = usr.loc
|
||||
if("hsbmedkit")
|
||||
var/obj/item/weapon/storage/firstaid/hsb = new/obj/item/weapon/storage/firstaid/regular
|
||||
hsb.loc = usr.loc
|
||||
if("hsbobj")
|
||||
if(!hsboxspawn) return
|
||||
var/list/hsbitems = typesof(/obj/)
|
||||
var/hsbitem = input(usr, "Choose an object to spawn.", "Sandbox:") in hsbitems + "Cancel"
|
||||
if(!(hsbitem == "Cancel"))
|
||||
new hsbitem(usr.loc)
|
||||
@@ -0,0 +1,78 @@
|
||||
|
||||
/proc/hex2num(hex)
|
||||
|
||||
if (!( istext(hex) ))
|
||||
CRASH("hex2num not given a hexadecimal string argument (user error)")
|
||||
return
|
||||
var/num = 0
|
||||
var/power = 0
|
||||
var/i = null
|
||||
i = length(hex)
|
||||
while(i > 0)
|
||||
var/char = copytext(hex, i, i + 1)
|
||||
switch(char)
|
||||
if("0")
|
||||
power++
|
||||
goto Label_290
|
||||
if("9", "8", "7", "6", "5", "4", "3", "2", "1")
|
||||
num += text2num(char) * 16 ** power
|
||||
if("a", "A")
|
||||
num += 16 ** power * 10
|
||||
if("b", "B")
|
||||
num += 16 ** power * 11
|
||||
if("c", "C")
|
||||
num += 16 ** power * 12
|
||||
if("d", "D")
|
||||
num += 16 ** power * 13
|
||||
if("e", "E")
|
||||
num += 16 ** power * 14
|
||||
if("f", "F")
|
||||
num += 16 ** power * 15
|
||||
else
|
||||
CRASH("hex2num given non-hexadecimal string (user error)")
|
||||
return
|
||||
power++
|
||||
Label_290:
|
||||
i--
|
||||
return num
|
||||
return
|
||||
|
||||
/proc/num2hex(num, placeholder)
|
||||
|
||||
if (placeholder == null)
|
||||
placeholder = 2
|
||||
if (!( isnum(num) ))
|
||||
CRASH("num2hex not given a numeric argument (user error)")
|
||||
return
|
||||
if (!( num ))
|
||||
return "0"
|
||||
var/hex = ""
|
||||
var/i = 0
|
||||
while(16 ** i < num)
|
||||
i++
|
||||
var/power = null
|
||||
power = i - 1
|
||||
while(power >= 0)
|
||||
var/val = round(num / 16 ** power)
|
||||
num -= val * 16 ** power
|
||||
switch(val)
|
||||
if(9.0, 8.0, 7.0, 6.0, 5.0, 4.0, 3.0, 2.0, 1.0, 0.0)
|
||||
hex += text("[]", val)
|
||||
if(10.0)
|
||||
hex += "A"
|
||||
if(11.0)
|
||||
hex += "B"
|
||||
if(12.0)
|
||||
hex += "C"
|
||||
if(13.0)
|
||||
hex += "D"
|
||||
if(14.0)
|
||||
hex += "E"
|
||||
if(15.0)
|
||||
hex += "F"
|
||||
else
|
||||
power--
|
||||
while(length(hex) < placeholder)
|
||||
hex = text("0[]", hex)
|
||||
return hex
|
||||
return
|
||||
@@ -0,0 +1,257 @@
|
||||
|
||||
/obj/begin/verb/ready()
|
||||
set src in usr.loc
|
||||
|
||||
|
||||
if ((!( istype(usr, /mob/human) ) || usr.start))
|
||||
usr << "You have already started!"
|
||||
return
|
||||
var/mob/human/M = usr
|
||||
src.get_dna_ready(M)
|
||||
if ((!( M.w_uniform ) && !( ticker )))
|
||||
if (M.gender == "female")
|
||||
M.w_uniform = new /obj/item/weapon/clothing/under/pink( M )
|
||||
else
|
||||
M.w_uniform = new /obj/item/weapon/clothing/under/blue( M )
|
||||
M.w_uniform.layer = 20
|
||||
M.shoes = new /obj/item/weapon/clothing/shoes/brown( M )
|
||||
M.shoes.layer = 20
|
||||
else
|
||||
M << "You will have to find clothes from the station."
|
||||
if ((ticker && !( M.l_hand )))
|
||||
var/obj/item/weapon/card/id/I = new /obj/item/weapon/card/id( M )
|
||||
var/list/L = list( "Technical Assistant", "Research Assistant", "Staff Assistant", "Medical Assistant" )
|
||||
var/choose
|
||||
if (L.Find(M.occupation1))
|
||||
choose = M.occupation1
|
||||
else
|
||||
choose = pick(L)
|
||||
switch(choose)
|
||||
if("Research Assistant")
|
||||
I.assignment = "Research Assistant"
|
||||
I.registered = M.rname
|
||||
I.access_level = 1
|
||||
I.lab_access = 1
|
||||
I.engine_access = 0
|
||||
I.air_access = 0
|
||||
if("Technical Assistant")
|
||||
I.assignment = "Technical Assistant"
|
||||
I.registered = M.rname
|
||||
I.access_level = 1
|
||||
I.lab_access = 0
|
||||
I.engine_access = 0
|
||||
I.air_access = 1
|
||||
if("Medical Assistant")
|
||||
I.assignment = "Medical Assistant"
|
||||
I.registered = M.rname
|
||||
I.access_level = 1
|
||||
I.lab_access = 1
|
||||
I.engine_access = 0
|
||||
I.air_access = 0
|
||||
if("Staff Assistant")
|
||||
I.assignment = "Staff Assistant"
|
||||
I.registered = M.rname
|
||||
I.access_level = 2
|
||||
I.lab_access = 0
|
||||
I.engine_access = 0
|
||||
I.air_access = 0
|
||||
else
|
||||
I.name = text("[]'s ID Card ([]>[]-[]-[])", I.registered, I.access_level, I.lab_access, I.engine_access, I.air_access)
|
||||
I.layer = 20
|
||||
M.l_hand = I
|
||||
M.start = 1
|
||||
M.update_face()
|
||||
M.update_body()
|
||||
return
|
||||
|
||||
/obj/begin/verb/enter()
|
||||
set src in usr.loc
|
||||
|
||||
if(config.loggame) world.log << "GAME: [usr.key] entered as [usr.name]"
|
||||
|
||||
if (!( enter_allowed ))
|
||||
usr << "\blue There is an administrative lock on entering the game!"
|
||||
return
|
||||
if ((!( usr.start ) || !( istype(usr, /mob/human) )))
|
||||
usr << "\blue <B>You aren't ready! Use the ready verb on this pad to set up your character!</B>"
|
||||
return
|
||||
if (ctf)
|
||||
var/obj/rogue = locate("landmark*CTF-rogue")
|
||||
usr.loc = rogue.loc
|
||||
usr << "<B>It's CTF mode. You are a late joiner so you are a Rogue!</B>"
|
||||
usr << "\blue Now teleporting."
|
||||
if (ticker)
|
||||
var/mob/H = usr
|
||||
if (istype(H, /mob/human))
|
||||
reg_dna[text("[]", H.primary.uni_identity)] = H.rname
|
||||
return
|
||||
var/mob/human/M = usr
|
||||
var/list/start_loc = list( )
|
||||
if ((M.key in list( "Thief jack", "Link43130", "Hutchy2k1", "Easty", "Exadv1" )))
|
||||
start_loc["Supply Station"] = locate(77, 40, 7)
|
||||
|
||||
var/area/A = locate(/area/sleep_area)
|
||||
var/list/L = list( )
|
||||
for(var/turf/T in A)
|
||||
if(T.isempty())
|
||||
L += T
|
||||
//Foreach goto(239)
|
||||
start_loc["SS13"] = pick(L)
|
||||
|
||||
|
||||
|
||||
if (locate(text("spstart[]", M.ckey)))
|
||||
for(var/obj/sp_start/S in world)
|
||||
if (S.tag == text("spstart[]", M.ckey))
|
||||
start_loc[text("[]", S.desc)] = S
|
||||
//Foreach goto(295)
|
||||
var/option = input(M, "Where should you start?", "Start Selector", null) in start_loc
|
||||
if ((!( usr.start ) || !( istype(usr, /mob/human) ) || usr.loc != src.loc))
|
||||
return
|
||||
if (ticker)
|
||||
reg_dna[text("[]", M.primary.uni_identity)] = M.rname
|
||||
var/obj/sp_start/S = start_loc[option]
|
||||
if (istype(S, /obj/sp_start))
|
||||
M << "\blue Now teleporting to special location."
|
||||
if (S.special == 2)
|
||||
for(var/obj/O in M)
|
||||
//O = null
|
||||
del(O)
|
||||
//Foreach goto(492)
|
||||
M.loc = S.loc
|
||||
else
|
||||
if (S.special == 3)
|
||||
for(var/obj/O in M)
|
||||
//O = null
|
||||
del(O)
|
||||
//Foreach goto(560)
|
||||
var/obj/O = new /mob/monkey( S.loc )
|
||||
M.client.mob = O
|
||||
O.loc = S.loc
|
||||
//M = null
|
||||
del(M)
|
||||
else
|
||||
M.loc = S.loc //was O.loc
|
||||
else
|
||||
if (isturf(S))
|
||||
M << "\blue Now teleporting."
|
||||
M.loc = S
|
||||
return
|
||||
|
||||
/obj/begin/proc/get_dna_ready(var/mob/user as mob)
|
||||
|
||||
var/mob/human/M = user
|
||||
if (!( M.primary ))
|
||||
M.r_hair = M.nr_hair
|
||||
M.b_hair = M.nb_hair
|
||||
M.g_hair = M.ng_hair
|
||||
M.s_tone = M.ns_tone
|
||||
var/t1 = rand(1000, 1500)
|
||||
dna_ident += t1
|
||||
if (dna_ident > 65536.0)
|
||||
dna_ident = rand(1, 1500)
|
||||
M.primary = new /obj/dna( null )
|
||||
M.primary.uni_identity = text("[]", add_zero(num2hex(dna_ident), 4))
|
||||
var/t2 = add_zero(num2hex(M.nr_hair), 2)
|
||||
M.primary.uni_identity = text("[][]", M.primary.uni_identity, t2)
|
||||
t2 = add_zero(num2hex(M.ng_hair), 2)
|
||||
M.primary.uni_identity = text("[][]", M.primary.uni_identity, t2)
|
||||
t2 = add_zero(num2hex(M.nb_hair), 2)
|
||||
M.primary.uni_identity = text("[][]", M.primary.uni_identity, t2)
|
||||
t2 = add_zero(num2hex(M.r_eyes), 2)
|
||||
M.primary.uni_identity = text("[][]", M.primary.uni_identity, t2)
|
||||
t2 = add_zero(num2hex(M.g_eyes), 2)
|
||||
M.primary.uni_identity = text("[][]", M.primary.uni_identity, t2)
|
||||
t2 = add_zero(num2hex(M.b_eyes), 2)
|
||||
M.primary.uni_identity = text("[][]", M.primary.uni_identity, t2)
|
||||
t2 = add_zero(num2hex( -M.ns_tone + 35), 2)
|
||||
M.primary.uni_identity = text("[][]", M.primary.uni_identity, t2)
|
||||
t2 = (M.gender == "male" ? text("[]", num2hex(rand(1, 124))) : text("[]", num2hex(rand(127, 250))))
|
||||
if (length(t2) < 2)
|
||||
M.primary.uni_identity = text("[]0[]", M.primary.uni_identity, t2)
|
||||
else
|
||||
M.primary.uni_identity = text("[][]", M.primary.uni_identity, t2)
|
||||
M.primary.spec_identity = "5BDFE293BA5500F9FFFD500AAFFE"
|
||||
M.primary.struc_enzyme = "CDE375C9A6C25A7DBDA50EC05AC6CEB63"
|
||||
if (rand(1, 3125) == 13)
|
||||
M.need_gl = 1
|
||||
M.be_epil = 1
|
||||
M.be_cough = 1
|
||||
M.be_tur = 1
|
||||
M.be_stut = 1
|
||||
|
||||
var/b_vis
|
||||
if (M.need_gl)
|
||||
b_vis = add_zero(text("[]", num2hex(rand(10, 1400))), 3)
|
||||
M.disabilities = M.disabilities | 1
|
||||
M << "\blue You need glasses!"
|
||||
else
|
||||
b_vis = "5A7"
|
||||
var/epil
|
||||
if (M.be_epil)
|
||||
epil = add_zero(text("[]", num2hex(rand(10, 1400))), 3)
|
||||
M.disabilities = M.disabilities | 2
|
||||
M << "\blue You are epileptic!"
|
||||
else
|
||||
epil = "6CE"
|
||||
var/cough
|
||||
if (M.be_cough)
|
||||
cough = add_zero(text("[]", num2hex(rand(10, 1400))), 3)
|
||||
M.disabilities = M.disabilities | 4
|
||||
M << "\blue You have a chronic coughing syndrome!"
|
||||
else
|
||||
cough = "EC0"
|
||||
var/Tourette
|
||||
if (M.be_tur)
|
||||
epil = add_zero(text("[]", num2hex(rand(10, 1400))), 3)
|
||||
M.disabilities = M.disabilities | 8
|
||||
M << "\blue You have Tourette syndrome!"
|
||||
else
|
||||
Tourette = "5AC"
|
||||
var/stutter
|
||||
if (M.be_stut)
|
||||
stutter = add_zero(text("[]", num2hex(rand(10, 1400))), 3)
|
||||
M.disabilities = M.disabilities | 16
|
||||
M << "\blue You have a stuttering problem!"
|
||||
else
|
||||
stutter = "A50"
|
||||
M.primary.struc_enzyme = text("CDE375C9A6C2[]DBD[][][][]B63", b_vis, stutter, cough, Tourette, epil)
|
||||
M.primary.use_enzyme = "493DB249EB6D13236100A37000800AB71"
|
||||
M.primary.n_chromo = 28
|
||||
return
|
||||
|
||||
/turf/station/command/floor/updatecell()
|
||||
|
||||
src.oxygen = O2STANDARD
|
||||
src.firelevel = 0
|
||||
src.co2 = 0
|
||||
src.poison = 0
|
||||
src.sl_gas = 0
|
||||
src.n2 = N2STANDARD
|
||||
return
|
||||
|
||||
/turf/station/command/conduction()
|
||||
return
|
||||
|
||||
/turf/station/command/floor/attack_paw(user as mob)
|
||||
|
||||
return src.attack_hand(user)
|
||||
return
|
||||
|
||||
/turf/station/command/floor/attack_hand(var/mob/user as mob)
|
||||
|
||||
if ((!( user.canmove ) || user.restrained() || !( user.pulling )))
|
||||
return
|
||||
if (user.pulling.anchored)
|
||||
return
|
||||
if ((user.pulling.loc != user.loc && get_dist(user, user.pulling) > 1))
|
||||
return
|
||||
if (ismob(user.pulling))
|
||||
var/mob/M = user.pulling
|
||||
var/mob/t = M.pulling
|
||||
M.pulling = null
|
||||
step(user.pulling, get_dir(user.pulling.loc, src))
|
||||
M.pulling = t
|
||||
else
|
||||
step(user.pulling, get_dir(user.pulling.loc, src))
|
||||
return
|
||||
@@ -0,0 +1,27 @@
|
||||
|
||||
/proc/invertHTML(HTMLstring)
|
||||
|
||||
if (!( istext(HTMLstring) ))
|
||||
CRASH("Given non-text argument!")
|
||||
return
|
||||
else
|
||||
if (length(HTMLstring) != 7)
|
||||
CRASH("Given non-HTML argument!")
|
||||
return
|
||||
var/textr = copytext(HTMLstring, 2, 4)
|
||||
var/textg = copytext(HTMLstring, 4, 6)
|
||||
var/textb = copytext(HTMLstring, 6, 8)
|
||||
var/r = hex2num(textr)
|
||||
var/g = hex2num(textg)
|
||||
var/b = hex2num(textb)
|
||||
textr = num2hex(255 - r)
|
||||
textg = num2hex(255 - g)
|
||||
textb = num2hex(255 - b)
|
||||
if (length(textr) < 2)
|
||||
textr = text("0[]", textr)
|
||||
if (length(textg) < 2)
|
||||
textr = text("0[]", textg)
|
||||
if (length(textb) < 2)
|
||||
textr = text("0[]", textb)
|
||||
return text("#[][][]", textr, textg, textb)
|
||||
return
|
||||
+5737
File diff suppressed because it is too large
Load Diff
+7128
File diff suppressed because it is too large
Load Diff
+106
@@ -0,0 +1,106 @@
|
||||
|
||||
// module datum.
|
||||
// this is per-object instance, and shows the condition of the modules in the object
|
||||
// actual modules needed is referenced through modulestypes and the object type
|
||||
|
||||
/datum/module
|
||||
var/status // bits set if working, 0 if broken
|
||||
var/installed // bits set if installed, 0 if missing
|
||||
|
||||
// moduletypes datum
|
||||
// this is per-object type, and shows the modules needed for a type of object
|
||||
|
||||
/datum/moduletypes
|
||||
var/list/modcount = list() // assoc list of the count of modules for a type
|
||||
|
||||
|
||||
var/list/modules = list( // global associative list
|
||||
"/obj/machinery/power/apc" = "card_reader,power_control,id_auth,cell_power,cell_charge")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/datum/module/New(var/obj/O)
|
||||
|
||||
var/type = O.type // the type of the creating object
|
||||
|
||||
var/mneed = mods.inmodlist(type) // find if this type has modules defined
|
||||
|
||||
if(!mneed) // not found in module list?
|
||||
del(src) // delete self, thus ending proc
|
||||
|
||||
var/needed = mods.getbitmask(type) // get a bitmask for the number of modules in this object
|
||||
status = needed
|
||||
installed = needed
|
||||
|
||||
/datum/moduletypes/proc/addmod(var/type, var/modtextlist)
|
||||
|
||||
modules += type // index by type text
|
||||
modules[type] = modtextlist
|
||||
|
||||
|
||||
/datum/moduletypes/proc/inmodlist(var/type)
|
||||
return ("[type]" in modules)
|
||||
|
||||
/datum/moduletypes/proc/getbitmask(var/type)
|
||||
var/count = modcount["[type]"]
|
||||
if(count)
|
||||
return 2**count-1
|
||||
|
||||
var/modtext = modules["[type]"]
|
||||
var/num = 1
|
||||
var/pos = 1
|
||||
|
||||
while(1)
|
||||
pos = findText(modtext, ",", pos, 0)
|
||||
if(!pos)
|
||||
break
|
||||
else
|
||||
pos++
|
||||
num++
|
||||
|
||||
modcount += "[type]"
|
||||
modcount["[type]"] = num
|
||||
|
||||
return 2**num-1
|
||||
|
||||
|
||||
/obj/item/weapon/module
|
||||
icon = 'module.dmi'
|
||||
icon_state = "std_module"
|
||||
w_class = 2.0
|
||||
s_istate = "electronic"
|
||||
flags = FPRINT|DRIVABLE|TABLEPASS
|
||||
var/mtype = 1 // 1=electronic 2=hardware
|
||||
|
||||
/obj/item/weapon/module/card_reader
|
||||
name = "card reader module"
|
||||
icon_state = "card_mod"
|
||||
desc = "An electronic module for reading data and ID cards."
|
||||
|
||||
/obj/item/weapon/module/power_control
|
||||
name = "power control module"
|
||||
icon_state = "power_mod"
|
||||
desc = "Heavy-duty switching circuits for power control."
|
||||
|
||||
/obj/item/weapon/module/id_auth
|
||||
name = "ID authentication module"
|
||||
icon_state = "id_mod"
|
||||
desc = "A module allowing secure authorization of ID cards."
|
||||
var/access = null
|
||||
var/allowed = null
|
||||
|
||||
/obj/item/weapon/module/cell_power
|
||||
name = "power cell regulator module"
|
||||
icon_state = "power_mod"
|
||||
desc = "A converter and regulator allowing the use of power cells."
|
||||
|
||||
/obj/item/weapon/module/cell_power
|
||||
name = "power cell charger module"
|
||||
icon_state = "power_mod"
|
||||
desc = "Charging circuits for power cells."
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,416 @@
|
||||
/obj/item/weapon/t_scanner/attack_self(mob/user)
|
||||
|
||||
on = !on
|
||||
icon_state = "t-scanner[on]"
|
||||
|
||||
if(on)
|
||||
src.process()
|
||||
|
||||
|
||||
/obj/item/weapon/t_scanner/proc/process()
|
||||
|
||||
while(on)
|
||||
for(var/turf/T in range(1, src.loc) )
|
||||
|
||||
if(!T.intact)
|
||||
continue
|
||||
|
||||
for(var/obj/O in T.contents)
|
||||
|
||||
if(O.level != 1)
|
||||
continue
|
||||
|
||||
if(O.invisibility == 101)
|
||||
O.invisibility = 0
|
||||
spawn(10)
|
||||
if(O)
|
||||
var/turf/U = O.loc
|
||||
if(U.intact)
|
||||
O.invisibility = 101
|
||||
|
||||
var/mob/human/M = locate() in T
|
||||
if(M && M.invisibility == 2)
|
||||
M.invisibility = 0
|
||||
spawn(2)
|
||||
if(M)
|
||||
M.invisibility = 2
|
||||
|
||||
|
||||
sleep(10)
|
||||
|
||||
|
||||
|
||||
// test flashlight object
|
||||
/obj/item/weapon/flashlight/attack_self(mob/user)
|
||||
|
||||
on = !on
|
||||
icon_state = "flight[on]"
|
||||
|
||||
if(on)
|
||||
img = image('turfs2.dmi', "light", 11)
|
||||
user:body_standing += img
|
||||
else
|
||||
if(img)
|
||||
user:body_standing -= img
|
||||
del(img)
|
||||
|
||||
|
||||
|
||||
///obj/item/weapon/flashlight/dropped()
|
||||
// on = 0
|
||||
|
||||
|
||||
|
||||
|
||||
// pipe item
|
||||
// used in constrction of pipe system; can be carried, moved, rotated, unlike static pipes
|
||||
// does not carry gas at this time
|
||||
|
||||
/obj/item/weapon/pipe/New()
|
||||
..()
|
||||
|
||||
update()
|
||||
|
||||
//update the name and icon of the pipe item depending on the type
|
||||
|
||||
/obj/item/weapon/pipe/proc/update()
|
||||
var/list/nlist = list("pipe", "bent pipe", "h/e pipe", "bent h/e pipe", "connector", "manifold", "junction", "vent")
|
||||
name = nlist[ptype+1] + " fitting"
|
||||
updateicon()
|
||||
|
||||
//update the icon of the item
|
||||
|
||||
/obj/item/weapon/pipe/proc/updateicon()
|
||||
|
||||
var/list/islist = list("straight", "bend", "he-straight", "he-bend", "connector", "manifold", "junction", "vent")
|
||||
|
||||
icon_state = islist[ptype + 1]
|
||||
|
||||
if(invisibility) // true if placed under floor
|
||||
icon -= rgb(0,0,0,128) // fade the icon
|
||||
else
|
||||
icon = initial(icon) // otherwise reset to inital icon
|
||||
|
||||
// called to hide or unhide a pipe
|
||||
// i=true if hiding
|
||||
|
||||
/obj/item/weapon/pipe/hide(var/i)
|
||||
|
||||
invisibility = i ? 101 : 0 // make hidden pipe items invisible
|
||||
updateicon()
|
||||
|
||||
|
||||
//called when a turf is attacked with a pipe item
|
||||
// place the pipe on the turf, setting pipe level to 1 (underfloor) if the turf is not intact
|
||||
|
||||
/obj/item/weapon/pipe/proc/turf_place(turf/T, mob/user)
|
||||
|
||||
if(!isturf(user.loc))
|
||||
return
|
||||
|
||||
if(get_dist(T,user) > 1)
|
||||
user << "You can't lay pipe at a place that far away."
|
||||
return
|
||||
|
||||
if(!T.intact && (ptype == 2 || ptype == 3 || ptype == 6) )
|
||||
user << "That type of pipe cannot be laid under the floor."
|
||||
return
|
||||
|
||||
|
||||
user.drop_item() // drop the pipe at the user's feet
|
||||
src.loc = T
|
||||
|
||||
level = 2 // defaults to above floor laying
|
||||
|
||||
if(!T.intact)
|
||||
level = 1 // if floor is not intact, make a low-level pipe
|
||||
|
||||
anchored = 1 // anchor the item so that it can't be dragged around if placed
|
||||
// otherwise able to drag underfloor pipes into intact turfs
|
||||
|
||||
|
||||
// called when an item is dropped
|
||||
|
||||
/obj/item/weapon/pipe/dropped(mob/user)
|
||||
src.anchored = 0 // set unanchored if dropped manually. Will be set anchored if placed (above)
|
||||
|
||||
|
||||
// rotate the pipe item clockwise
|
||||
|
||||
/obj/item/weapon/pipe/verb/rotate()
|
||||
set src in view(1)
|
||||
|
||||
if ( usr.stat || usr.restrained() )
|
||||
return
|
||||
|
||||
var/turf/T = src.loc
|
||||
if(isturf(T) && T.intact && level==1) // if the pipe is underfloor, don't rotate
|
||||
return // incase the pipe has been revaled with a t-scanner
|
||||
|
||||
src.dir = turn(src.dir, -90)
|
||||
return
|
||||
|
||||
// returns the p_dir from the pipe item type and dir
|
||||
|
||||
/obj/item/weapon/pipe/proc/get_pdir()
|
||||
|
||||
var/flip = turn(dir, 180)
|
||||
var/cw = turn(dir, -90)
|
||||
var/acw = turn(dir, 90)
|
||||
|
||||
switch(ptype)
|
||||
if(0)
|
||||
return dir|flip
|
||||
if(1)
|
||||
return dir|cw
|
||||
if(2,3)
|
||||
return 0
|
||||
if(4,7)
|
||||
return dir
|
||||
if(5)
|
||||
return dir|cw|acw
|
||||
if(6)
|
||||
return flip
|
||||
|
||||
return 0
|
||||
|
||||
// return the h_dir (heat-exchange pipes) from the type and the dir
|
||||
|
||||
/obj/item/weapon/pipe/proc/get_hdir()
|
||||
|
||||
var/flip = turn(dir, 180)
|
||||
var/cw = turn(dir, -90)
|
||||
|
||||
switch(ptype)
|
||||
if(0,1,4,5,7)
|
||||
return 0
|
||||
if(2)
|
||||
return dir|flip
|
||||
if(3)
|
||||
return dir|cw
|
||||
if(6)
|
||||
return dir
|
||||
|
||||
return 0
|
||||
|
||||
// test verb
|
||||
|
||||
/obj/item/weapon/pipe/verb/inc()
|
||||
set src in view(1)
|
||||
|
||||
ptype = (ptype+1)%8
|
||||
update()
|
||||
|
||||
/obj/item/weapon/pipe/attackby(obj/item/weapon/W, mob/user)
|
||||
|
||||
var/turf/T = src.loc
|
||||
if(T.intact && level==1) // if the pipe is underfloor, don't interact
|
||||
return // in case the pipe has been revealed with a t-scanner
|
||||
|
||||
var/pipedir = src.get_pdir()|src.get_hdir() // all possible pipe dirs including h/e
|
||||
|
||||
if (istype(W, /obj/item/weapon/weldingtool) )
|
||||
var/obj/item/weapon/weldingtool/WT = W
|
||||
if (WT.welding && WT.weldfuel>=0)
|
||||
WT.weldfuel--
|
||||
|
||||
for(var/obj/machinery/M in T) // check to make sure no other pipes conflit with this one
|
||||
|
||||
if(M.level == src.level) // only on same level
|
||||
if( (M.p_dir & pipedir) || (M.h_dir & pipedir) ) // matches at least one direction on either type of pipe
|
||||
user << "There is already a pipe at that location and position."
|
||||
return
|
||||
|
||||
|
||||
// no conflicts found
|
||||
|
||||
// 0 1 2 3 4 5 6 7
|
||||
//"pipe", "bent pipe", "h/e pipe", "bent h/e pipe", "connector", "manifold", "junction" vent
|
||||
|
||||
var/obj/machinery/pipes/P
|
||||
|
||||
switch(ptype)
|
||||
if(0,1) // straight or bent pipe
|
||||
P = new/obj/machinery/pipes(T)
|
||||
|
||||
P.icon_state = "[pipedir]"
|
||||
P.level = level
|
||||
P.update()
|
||||
P.updateicon()
|
||||
|
||||
var/list/dirs = P.get_dirs()
|
||||
|
||||
P.node1 = get_machine(P.level, P.loc, dirs[1])
|
||||
P.node2 = get_machine(P.level, P.loc, dirs[2])
|
||||
|
||||
if(2,3) // straight or bent h/e pipe
|
||||
P = new/obj/machinery/pipes/heat_exch(T)
|
||||
P.icon_state = "[pipedir]"
|
||||
P.level = 2
|
||||
P.update()
|
||||
P.updateicon()
|
||||
|
||||
var/list/dirs = P.get_dirs()
|
||||
|
||||
P.node1 = get_he_machine(P.level, P.loc, dirs[1])
|
||||
P.node2 = get_he_machine(P.level, P.loc, dirs[2])
|
||||
|
||||
if(4) // connector
|
||||
var/obj/machinery/connector/C = new(T)
|
||||
C.dir = src.dir
|
||||
C.p_dir = src.dir
|
||||
C.level = level
|
||||
|
||||
C.buildnodes()
|
||||
|
||||
setlineterm(C.node, C.vnode)
|
||||
|
||||
|
||||
if(5) //manifold
|
||||
var/obj/machinery/manifold/M = new(T)
|
||||
M.dir = dir
|
||||
M.p_dir = pipedir
|
||||
M.level = level
|
||||
M.buildnodes()
|
||||
setlineterm(M.node1, M.vnode1)
|
||||
setlineterm(M.node2, M.vnode2)
|
||||
setlineterm(M.node3, M.vnode3)
|
||||
|
||||
if(6) //junctions
|
||||
var/obj/machinery/junction/J = new(T)
|
||||
J.dir = dir
|
||||
J.p_dir = src.get_pdir()
|
||||
J.h_dir = src.get_hdir()
|
||||
J.level = 2
|
||||
|
||||
J.buildnodes()
|
||||
setlineterm(J.node1, J.vnode1)
|
||||
setlineterm(J.node2, J.vnode2)
|
||||
|
||||
if(7) // vent
|
||||
var/obj/machinery/vent/V = new(T)
|
||||
V.dir = src.dir
|
||||
V.p_dir = src.dir
|
||||
V.level = level
|
||||
|
||||
V.buildnodes()
|
||||
|
||||
setlineterm(V.node, V.vnode)
|
||||
|
||||
|
||||
// for pipe objects, now do updating of pipelines if needed
|
||||
switch(ptype)
|
||||
if(0,1,2,3) // new regular or or h/e pipe
|
||||
|
||||
// number of pipes connected to P
|
||||
var/pipecon = (P.node1 && P.node1.ispipe()) + (P.node2 && P.node2.ispipe())
|
||||
|
||||
if(Debug) world << "Pipecon [pipecon]"
|
||||
|
||||
if(!pipecon) // simplest case - no connection pipes (but may be machines)
|
||||
var/obj/machinery/pipeline/PL = new() // create a new pipeline
|
||||
P.buildnodes(PL) // set new pipe to use new pl
|
||||
PL.nodes += P // and add it
|
||||
PL.numnodes = 1
|
||||
PL.capmult = 2
|
||||
plines += PL // and new pipeline to the global list
|
||||
PL.setterm() // and ensure any connections to machines are made
|
||||
PL.name = "pipeline #[plines.Find(PL)]" // set the name
|
||||
|
||||
else if(pipecon == 1) // single connected pipe
|
||||
|
||||
var/obj/machinery/pipes/CP // the connected pipe
|
||||
|
||||
if(P.node1 && P.node1.ispipe()) // find the connected pipe
|
||||
CP = P.node1
|
||||
else
|
||||
CP = P.node2
|
||||
|
||||
var/obj/machinery/pipeline/PL = CP.pl // the pipeline we connected to
|
||||
|
||||
P.buildnodes(PL) // set the pipeline and nodes of any adjoining pipes
|
||||
|
||||
if(PL.nodes[1] == CP) // if the connected pipe is at start of line nodes list
|
||||
PL.nodes.Insert(1, P) // insert new pipe into start of node list
|
||||
else
|
||||
PL.nodes += P // otherwise, insert it at end
|
||||
PL.numnodes++
|
||||
PL.capmult++
|
||||
PL.setterm() // connect to any machines
|
||||
|
||||
CP.termination = 0 // connected pipe no longer terminal
|
||||
|
||||
else //(pipecon==2)
|
||||
|
||||
var/obj/machinery/pipes/CP1 = P.node1
|
||||
var/obj/machinery/pipes/CP2 = P.node2
|
||||
|
||||
var/obj/machinery/pipeline/PL1 = CP1.pl
|
||||
var/obj/machinery/pipeline/PL2 = CP2.pl
|
||||
|
||||
if(PL1 == PL2) // special case - completing a loop
|
||||
// make sure to check if this works properly
|
||||
P.buildnodes(PL1)
|
||||
|
||||
PL1.nodes += P
|
||||
PL1.numnodes++
|
||||
PL1.capmult++
|
||||
PL1.setterm()
|
||||
|
||||
CP1.termination = 0
|
||||
CP2.termination = 0
|
||||
|
||||
PL1.vnode1 = PL1 // link pipeline to self
|
||||
PL1.vnode2 = PL1
|
||||
|
||||
else // separate pipelines
|
||||
|
||||
P.buildnodes(PL1)
|
||||
|
||||
CP1.termination = 0
|
||||
CP2.termination = 0
|
||||
|
||||
var/list/plist
|
||||
if(PL1.nodes[1] == CP1)
|
||||
plist = pipelist(null, PL1.nodes[PL1.nodes.len])
|
||||
else
|
||||
plist = pipelist(null, PL1.nodes[1])
|
||||
|
||||
PL1.gas.transfer_from(PL2.gas, -1)
|
||||
PL1.ngas.transfer_from(PL2.ngas, -1)
|
||||
|
||||
plines -= PL2
|
||||
for(var/obj/machinery/pipes/OP in PL2.nodes)
|
||||
OP.pl = PL1
|
||||
|
||||
PL1.nodes = plist
|
||||
PL1.numnodes = plist.len
|
||||
PL1.capmult = plist.len+1
|
||||
|
||||
|
||||
PL1.setterm()
|
||||
|
||||
del(PL2)
|
||||
|
||||
|
||||
|
||||
del(src) // remove the pipe item
|
||||
|
||||
return
|
||||
|
||||
|
||||
// ensure that setterm() is called for a newly connected pipeline
|
||||
|
||||
/proc/setlineterm(var/obj/machinery/node, var/obj/machinery/vnode)
|
||||
|
||||
if(vnode)
|
||||
if( istype(vnode, /obj/machinery/pipeline) )
|
||||
|
||||
|
||||
var/obj/machinery/pipeline/PL = vnode
|
||||
node.buildnodes(PL)
|
||||
PL.setterm()
|
||||
else
|
||||
node.buildnodes()
|
||||
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
/obj/New()
|
||||
..()
|
||||
// mod = new(src) // creates a module datum for this obj of type
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,355 @@
|
||||
//#define AMAP
|
||||
|
||||
/obj/machinery/computer/security/verb/station_map()
|
||||
set name = ".map"
|
||||
set src in view(1)
|
||||
usr.machine = src
|
||||
|
||||
if(config.loggame) world.log << "GAME: [usr]([usr.key]) used station map L[maplevel] in [src.loc.loc]"
|
||||
|
||||
src.drawmap(usr)
|
||||
|
||||
/obj/machinery/computer/security/proc/drawmap(var/mob/user as mob)
|
||||
|
||||
var/icx = round(world.maxx/16) + 1
|
||||
var/icy = round(world.maxy/16) + 1
|
||||
|
||||
var/xoff = round( (icx*16-world.maxx)-2)
|
||||
var/yoff = round( (icy*16-world.maxy)-2)
|
||||
|
||||
var/icount = icx * icy
|
||||
|
||||
|
||||
var/list/imap = list()
|
||||
|
||||
#ifdef AMAP
|
||||
|
||||
for(var/i = 0; i<icount; i++)
|
||||
imap += icon('imap.dmi', "blank")
|
||||
imap += icon('imap.dmi', "blank")
|
||||
|
||||
//world << "[icount] images in list"
|
||||
|
||||
|
||||
for(var/wx = 1 ; wx <= world.maxx; wx++)
|
||||
|
||||
for(var/wy = 1; wy <= world.maxy; wy++)
|
||||
|
||||
var/turf/T = locate(wx, wy, maplevel)
|
||||
|
||||
var/colour
|
||||
var/colour2
|
||||
|
||||
|
||||
|
||||
if(!T)
|
||||
colour = rgb(0,0,0)
|
||||
|
||||
else
|
||||
var/sense = 1
|
||||
switch("[T.type]")
|
||||
if("/turf/space")
|
||||
colour = rgb(10,10,10)
|
||||
sense = 0
|
||||
|
||||
if("/turf/station/floor")
|
||||
colour = rgb(150,150,150)
|
||||
var/turf/station/floor/TF = T
|
||||
if(TF.burnt == 1)
|
||||
sense = 0
|
||||
colour = rgb(130,130,130)
|
||||
|
||||
if("/turf/station/engine/floor")
|
||||
colour = rgb(128,128,128)
|
||||
if("/turf/station/wall")
|
||||
colour = rgb(96,96,96)
|
||||
|
||||
if("/turf/station/r_wall")
|
||||
colour = rgb(128,96,96)
|
||||
|
||||
if("/turf/station/command/floor", "/turf/station/command/floor/other")
|
||||
colour = rgb(240,240,240)
|
||||
|
||||
if("/turf/station/command/wall", "/turf/station/command/wall/other")
|
||||
colour = rgb(140,140,140)
|
||||
|
||||
else
|
||||
colour = rgb(0,40,0)
|
||||
|
||||
|
||||
|
||||
|
||||
if(sense)
|
||||
|
||||
for(var/atom/AM in T.contents)
|
||||
|
||||
if(istype(AM, /obj/machinery/door) && !istype(AM, /obj/machinery/door/window))
|
||||
if(AM.density)
|
||||
colour = rgb(96,96,192)
|
||||
colour2 = colour
|
||||
else
|
||||
colour = rgb(128,192,128)
|
||||
|
||||
if(istype(AM, /obj/machinery/alarm))
|
||||
colour = rgb(0,255,0)
|
||||
colour2 = colour
|
||||
if(AM.icon_state=="alarm:1")
|
||||
colour = rgb(255,255,0)
|
||||
colour2 = rgb(255,128,0)
|
||||
|
||||
if(istype(AM, /mob))
|
||||
if(AM:client)
|
||||
colour = rgb(255,0,0)
|
||||
else
|
||||
colour = rgb(255,128,128)
|
||||
|
||||
colour2 = rgb(192,0,0)
|
||||
|
||||
var/area/A = T.loc
|
||||
|
||||
if(A.fire)
|
||||
|
||||
var/red = getr(colour)
|
||||
var/green = getg(colour)
|
||||
var/blue = getb(colour)
|
||||
|
||||
|
||||
green = min(255, green+40)
|
||||
blue = min(255, blue+40)
|
||||
|
||||
colour = rgb(red, green, blue)
|
||||
|
||||
if(!colour2 && !T.density)
|
||||
|
||||
var/turf_total = T.co2 + T.oxygen + T.poison + T.sl_gas + T.n2
|
||||
|
||||
|
||||
var/t1 = turf_total / CELLSTANDARD * 150
|
||||
|
||||
|
||||
if(t1<=100)
|
||||
colour2 = rgb(t1*2.55,0,0)
|
||||
else
|
||||
t1 = min(100, t1-100)
|
||||
colour2 = rgb(255, t1*2.55, t1*2.55)
|
||||
|
||||
if(!colour2)
|
||||
colour2 = colour
|
||||
|
||||
var/ix = round((wx*2+xoff)/32)
|
||||
var/iy = round((wy*2+yoff)/32)
|
||||
|
||||
var/rx = ((wx*2+xoff)%32) + 1
|
||||
var/ry = ((wy*2+yoff)%32) + 1
|
||||
|
||||
//world << "trying [ix],[iy] : [ix+icx*iy]"
|
||||
var/icon/I = imap[1+(ix + icx*iy)*2]
|
||||
var/icon/I2 = imap[2+(ix + icx*iy)*2]
|
||||
|
||||
|
||||
//world << "icon: \icon[I]"
|
||||
|
||||
I.DrawBox(colour, rx, ry, rx+1, ry+1)
|
||||
|
||||
I2.DrawBox(colour2, rx, ry, rx+1, ry+1)
|
||||
|
||||
|
||||
user.clearmap()
|
||||
|
||||
user.mapobjs = list()
|
||||
|
||||
|
||||
for(var/i=0; i<icount;i++)
|
||||
var/obj/screen/H = new /obj/screen()
|
||||
|
||||
H.screen_loc = "[5 + i%icx],[6+ round(i/icx)]"
|
||||
|
||||
//world<<"\icon[I] at [H.screen_loc]"
|
||||
|
||||
H.name = (i==0)?"maprefresh":"map"
|
||||
|
||||
var/icon/HI = new/icon
|
||||
|
||||
var/icon/I = imap[i*2+1]
|
||||
var/icon/J = imap[i*2+2]
|
||||
|
||||
HI.Insert(I, frame=1, delay = 5)
|
||||
HI.Insert(J, frame=2, delay = 5)
|
||||
|
||||
del(I)
|
||||
del(J)
|
||||
H.icon = HI
|
||||
H.layer = 25
|
||||
usr.mapobjs += H
|
||||
#else
|
||||
|
||||
for(var/i = 0; i<icount; i++)
|
||||
imap += icon('imap.dmi', "blank")
|
||||
|
||||
for(var/wx = 1 ; wx <= world.maxx; wx++)
|
||||
|
||||
for(var/wy = 1; wy <= world.maxy; wy++)
|
||||
|
||||
var/turf/T = locate(wx, wy, maplevel)
|
||||
|
||||
var/colour
|
||||
|
||||
if(!T)
|
||||
colour = rgb(0,0,0)
|
||||
|
||||
else
|
||||
var/sense = 1
|
||||
switch("[T.type]")
|
||||
if("/turf/space")
|
||||
colour = rgb(10,10,10)
|
||||
sense = 0
|
||||
|
||||
if("/turf/station/floor", "/turf/station/engine/floor")
|
||||
var/turf_total = T.co2 + T.oxygen + T.poison + T.sl_gas + T.n2
|
||||
var/t1 = turf_total / CELLSTANDARD * 175
|
||||
|
||||
if(t1<=100)
|
||||
colour = rgb(0,0,t1*2.55)
|
||||
else
|
||||
t1 = min(100, t1-100)
|
||||
colour = rgb( t1*2.55, t1*2.55, 255)
|
||||
|
||||
if("/turf/station/wall")
|
||||
colour = rgb(96,96,96)
|
||||
|
||||
if("/turf/station/r_wall")
|
||||
colour = rgb(128,96,96)
|
||||
|
||||
if("/turf/station/command/floor", "/turf/station/command/floor/other")
|
||||
colour = rgb(240,240,240)
|
||||
|
||||
if("/turf/station/command/wall", "/turf/station/command/wall/other")
|
||||
colour = rgb(140,140,140)
|
||||
|
||||
else
|
||||
colour = rgb(0,40,0)
|
||||
|
||||
|
||||
if(sense)
|
||||
|
||||
for(var/atom/AM in T.contents)
|
||||
|
||||
if(istype(AM, /obj/machinery/door) && !istype(AM, /obj/machinery/door/window))
|
||||
if(AM.density)
|
||||
colour = rgb(0,96,192)
|
||||
else
|
||||
colour = rgb(96,192,128)
|
||||
|
||||
if(istype(AM, /obj/machinery/alarm))
|
||||
colour = rgb(0,255,0)
|
||||
|
||||
if(AM.icon_state=="alarm:1")
|
||||
colour = rgb(255,255,0)
|
||||
|
||||
if(istype(AM, /mob))
|
||||
if(AM:client)
|
||||
colour = rgb(255,0,0)
|
||||
else
|
||||
colour = rgb(255,128,128)
|
||||
|
||||
//if(istype(AM, /obj/blob))
|
||||
// colour = rgb(255,0,255)
|
||||
|
||||
var/area/A = T.loc
|
||||
|
||||
if(A.fire)
|
||||
|
||||
var/red = getr(colour)
|
||||
var/green = getg(colour)
|
||||
var/blue = getb(colour)
|
||||
|
||||
|
||||
green = min(255, green+40)
|
||||
blue = min(255, blue+40)
|
||||
|
||||
colour = rgb(red, green, blue)
|
||||
|
||||
var/ix = round((wx*2+xoff)/32)
|
||||
var/iy = round((wy*2+yoff)/32)
|
||||
|
||||
var/rx = ((wx*2+xoff)%32) + 1
|
||||
var/ry = ((wy*2+yoff)%32) + 1
|
||||
|
||||
//world << "trying [ix],[iy] : [ix+icx*iy]"
|
||||
var/icon/I = imap[1+(ix + icx*iy)]
|
||||
|
||||
|
||||
//world << "icon: \icon[I]"
|
||||
|
||||
I.DrawBox(colour, rx, ry, rx+1, ry+1)
|
||||
|
||||
|
||||
user.clearmap()
|
||||
|
||||
user.mapobjs = list()
|
||||
|
||||
|
||||
for(var/i=0; i<icount;i++)
|
||||
var/obj/screen/H = new /obj/screen()
|
||||
|
||||
H.screen_loc = "[5 + i%icx],[6+ round(i/icx)]"
|
||||
|
||||
//world<<"\icon[I] at [H.screen_loc]"
|
||||
|
||||
H.name = (i==0)?"maprefresh":"map"
|
||||
|
||||
var/icon/I = imap[i+1]
|
||||
|
||||
H.icon = I
|
||||
del(I)
|
||||
H.layer = 25
|
||||
usr.mapobjs += H
|
||||
|
||||
#endif
|
||||
|
||||
user.client.screen += user.mapobjs
|
||||
|
||||
src.close(user)
|
||||
|
||||
/* if(seccomp == src)
|
||||
drawmap(user)
|
||||
else
|
||||
user.clearmap()*/
|
||||
return
|
||||
|
||||
|
||||
|
||||
/obj/machinery/computer/security/proc/close(mob/user)
|
||||
spawn(20)
|
||||
var/using = null
|
||||
if(user.mapobjs)
|
||||
for(var/obj/machinery/computer/security/seccomp in oview(1,user))
|
||||
if(seccomp == src)
|
||||
using = 1
|
||||
break
|
||||
if(using)
|
||||
close(user)
|
||||
else
|
||||
user.clearmap()
|
||||
|
||||
|
||||
return
|
||||
|
||||
proc/getr(col)
|
||||
return hex2num( copytext(col, 2,4))
|
||||
|
||||
proc/getg(col)
|
||||
return hex2num( copytext(col, 4,6))
|
||||
|
||||
proc/getb(col)
|
||||
return hex2num( copytext(col, 6))
|
||||
|
||||
|
||||
/mob/proc/clearmap()
|
||||
src.client.screen -= src.mapobjs
|
||||
for(var/obj/screen/O in mapobjs)
|
||||
del(O)
|
||||
|
||||
mapobjs = null
|
||||
src.machine = null
|
||||
|
||||
+706
@@ -0,0 +1,706 @@
|
||||
|
||||
// the power cell
|
||||
// charge from 0 to 100%
|
||||
// fits in PDU to provide backup power
|
||||
|
||||
/obj/item/weapon/cell/New()
|
||||
..()
|
||||
|
||||
charge = charge * maxcharge/100.0 // map obj has charge as percentage, convert to real value here
|
||||
|
||||
spawn(5)
|
||||
updateicon()
|
||||
|
||||
|
||||
/obj/item/weapon/cell/proc/updateicon()
|
||||
|
||||
if(maxcharge == 1000)
|
||||
icon_state = "cell"
|
||||
else
|
||||
icon_state = "hpcell"
|
||||
|
||||
overlays = null
|
||||
|
||||
if(charge < 0.01)
|
||||
return
|
||||
else if(charge/maxcharge >=0.995)
|
||||
overlays += image('power.dmi', "cell-o2")
|
||||
else
|
||||
overlays += image('power.dmi', "cell-o1")
|
||||
|
||||
/obj/item/weapon/cell/proc/percent() // return % charge of cell
|
||||
return 100.0*charge/maxcharge
|
||||
|
||||
/obj/item/weapon/cell/examine()
|
||||
set src in view(1)
|
||||
if(usr && !usr.stat)
|
||||
if(maxcharge == 1000)
|
||||
usr << "[desc]\nThe charge meter reads [round(src.percent() )]%."
|
||||
else
|
||||
usr << "A high-capacity rechargable electrochemical power cell.\nThe charge meter reads [round(src.percent() )]%."
|
||||
|
||||
|
||||
|
||||
// the power cable object
|
||||
|
||||
/obj/cable/New()
|
||||
..()
|
||||
|
||||
|
||||
// ensure d1 & d2 reflect the icon_state for entering and exiting cable
|
||||
|
||||
var/dash = findtext(icon_state, "-")
|
||||
|
||||
d1 = text2num( copytext( icon_state, 1, dash ) )
|
||||
|
||||
d2 = text2num( copytext( icon_state, dash+1 ) )
|
||||
|
||||
var/turf/T = src.loc // hide if turf is not intact
|
||||
|
||||
if(level==1) hide(T.intact)
|
||||
|
||||
|
||||
/obj/cable/Del() // called when a cable is deleted
|
||||
|
||||
if(!defer_powernet_rebuild) // set if network will be rebuilt manually
|
||||
|
||||
if(netnum && powernets && powernets.len >= netnum) // make sure cable & powernet data is valid
|
||||
var/datum/powernet/PN = powernets[netnum]
|
||||
PN.cut_cable(src) // updated the powernets
|
||||
else
|
||||
if(Debug) world.log << "Defered cable deletion at [x],[y]: #[netnum]"
|
||||
..() // then go ahead and delete the cable
|
||||
|
||||
/obj/cable/hide(var/i)
|
||||
|
||||
invisibility = i ? 101 : 0
|
||||
updateicon()
|
||||
|
||||
/obj/cable/proc/updateicon()
|
||||
if(invisibility)
|
||||
//icon_state = "[d1]-[d2]"
|
||||
//icon -= rgb(0,0,0,128)
|
||||
icon_state = "[d1]-[d2]-f"
|
||||
else
|
||||
//icon = initial(icon)
|
||||
icon_state = "[d1]-[d2]"
|
||||
|
||||
|
||||
/obj/cable/attackby(obj/item/weapon/W, mob/user)
|
||||
|
||||
var/turf/T = src.loc
|
||||
if(T.intact)
|
||||
return
|
||||
|
||||
if(istype(W, /obj/item/weapon/wirecutters))
|
||||
|
||||
if(src.d1) // 0-X cables are 1 unit, X-X cables are 2 units long
|
||||
new/obj/item/weapon/cable_coil(T, 2)
|
||||
else
|
||||
new/obj/item/weapon/cable_coil(T, 1)
|
||||
|
||||
for(var/mob/O in viewers(src, null))
|
||||
O.show_message("[user] cuts the cable.", 1)
|
||||
|
||||
shock(user, 50)
|
||||
|
||||
defer_powernet_rebuild = 0 // to fix no-action bug
|
||||
del(src)
|
||||
|
||||
return // not needed, but for clarity
|
||||
|
||||
|
||||
else if(istype(W, /obj/item/weapon/cable_coil))
|
||||
var/obj/item/weapon/cable_coil/coil = W
|
||||
|
||||
coil.cable_join(src, user)
|
||||
//note do shock in cable_join
|
||||
else
|
||||
shock(user, 10)
|
||||
|
||||
src.add_fingerprint(user)
|
||||
|
||||
// shock the user with probability prb
|
||||
|
||||
/obj/cable/proc/shock(mob/user, prb)
|
||||
|
||||
if(!prob(prb))
|
||||
return
|
||||
|
||||
if(!netnum) // unconnected cable is unpowered
|
||||
return
|
||||
|
||||
var/datum/powernet/PN // find the powernet
|
||||
if(powernets && powernets.len >= netnum)
|
||||
PN = powernets[netnum]
|
||||
|
||||
if(PN && PN.avail > 0) // is it powered?
|
||||
|
||||
|
||||
|
||||
var/prot = 0
|
||||
|
||||
if(istype(user, /mob/human))
|
||||
var/mob/human/H = user
|
||||
if(H.gloves)
|
||||
var/obj/item/weapon/clothing/gloves/G = H.gloves
|
||||
|
||||
prot = G.elec_protect
|
||||
|
||||
if(prot == 10) // elec insulted gloves protect completely
|
||||
return
|
||||
|
||||
prot++
|
||||
|
||||
var/obj/effects/sparks/O = new /obj/effects/sparks( src.loc )
|
||||
O.dir = pick(NORTH, SOUTH, EAST, WEST)
|
||||
spawn( 0 )
|
||||
O.Life()
|
||||
|
||||
if(PN.avail > 10000)
|
||||
user.burn(5e7/prot)
|
||||
|
||||
user << "\red <B>You feel a powerful shock course through your body!</B>"
|
||||
sleep(1)
|
||||
|
||||
user.stunned = 120/prot
|
||||
user.weakened = 20/prot
|
||||
//Foreach goto(72)
|
||||
for(var/mob/M in hearers(src, null))
|
||||
if(M == user)
|
||||
continue
|
||||
if (!( M.blinded ))
|
||||
M << "\red [user.name] was shocked by the cable!"
|
||||
else
|
||||
M << "\red You hear a heavy electrical crack."
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/obj/cable/ex_act(severity)
|
||||
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
del(src)
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
new/obj/item/weapon/cable_coil(src.loc, src.d1 ? 2 : 1)
|
||||
del(src)
|
||||
|
||||
if(3.0)
|
||||
if (prob(25))
|
||||
new/obj/item/weapon/cable_coil(src.loc, src.d1 ? 2 : 1)
|
||||
del(src)
|
||||
else
|
||||
return
|
||||
|
||||
/obj/cable/burn(fi_amount)
|
||||
|
||||
if(fi_amount > 1800000)
|
||||
var/turf/T = src.loc
|
||||
if(!T.intact)
|
||||
if(prob(10))
|
||||
defer_powernet_rebuild = 0
|
||||
del(src)
|
||||
|
||||
|
||||
|
||||
|
||||
// the cable coil object, used for laying cable
|
||||
|
||||
/obj/item/weapon/cable_coil/New(loc, length = MAXCOIL)
|
||||
src.amount = length
|
||||
pixel_x = rand(-2,2)
|
||||
pixel_y = rand(-2,2)
|
||||
updateicon()
|
||||
..(loc)
|
||||
|
||||
|
||||
/obj/item/weapon/cable_coil/proc/updateicon()
|
||||
if(amount == 1)
|
||||
icon_state = "coil1"
|
||||
name = "cable piece"
|
||||
else if(amount == 2)
|
||||
icon_state = "coil2"
|
||||
name = "cable piece"
|
||||
else
|
||||
icon_state = "coil"
|
||||
name = "cable coil"
|
||||
|
||||
/obj/item/weapon/cable_coil/examine()
|
||||
set src in view(1)
|
||||
|
||||
if(amount == 1)
|
||||
usr << "A short piece of power cable."
|
||||
else if(amount == 1)
|
||||
usr << "A piece of power cable."
|
||||
else
|
||||
usr << "A coil of power cable. There are [amount] lengths of cable in the coil."
|
||||
|
||||
|
||||
|
||||
/obj/item/weapon/cable_coil/attackby(obj/item/weapon/W, mob/user)
|
||||
|
||||
if( istype(W, /obj/item/weapon/wirecutters) && src.amount > 1)
|
||||
src.amount--
|
||||
new/obj/item/weapon/cable_coil(user.loc, 1)
|
||||
user << "You cut a piece off the cable coil."
|
||||
src.updateicon()
|
||||
return
|
||||
|
||||
else if( istype(W, /obj/item/weapon/cable_coil) )
|
||||
var/obj/item/weapon/cable_coil/C = W
|
||||
if(C.amount == MAXCOIL)
|
||||
user << "The coil is too long, you cannot add any more cable to it."
|
||||
return
|
||||
|
||||
if( (C.amount + src.amount <= MAXCOIL) )
|
||||
C.amount += src.amount
|
||||
user << "You join the cable coils together."
|
||||
C.updateicon()
|
||||
del(src)
|
||||
return
|
||||
|
||||
else
|
||||
user << "You transfer [MAXCOIL - src.amount ] length\s of cable from one coil to the other."
|
||||
src.amount -= (MAXCOIL-C.amount)
|
||||
src.updateicon()
|
||||
C.amount = MAXCOIL
|
||||
C.updateicon()
|
||||
return
|
||||
|
||||
|
||||
|
||||
/obj/item/weapon/cable_coil/proc/use(var/used)
|
||||
if(src.amount < used)
|
||||
return 0
|
||||
else if (src.amount == used)
|
||||
del(src)
|
||||
else
|
||||
amount -= used
|
||||
updateicon()
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
// called when cable_coil is clicked on a turf/station/floor
|
||||
|
||||
/obj/item/weapon/cable_coil/proc/turf_place(turf/station/floor/F, mob/user)
|
||||
|
||||
if(!isturf(user.loc))
|
||||
return
|
||||
|
||||
if(get_dist(F,user) > 1)
|
||||
user << "You can't lay cable at a place that far away."
|
||||
return
|
||||
|
||||
if(F.intact) // if floor is intact, complain
|
||||
user << "You can't lay cable there unless the floor tiles are removed."
|
||||
return
|
||||
|
||||
else
|
||||
var/dirn
|
||||
|
||||
if(user.loc == F)
|
||||
dirn = user.dir // if laying on the tile we're on, lay in the direction we're facing
|
||||
else
|
||||
dirn = get_dir(F, user)
|
||||
|
||||
for(var/obj/cable/LC in F)
|
||||
if(LC.d1 == dirn || LC.d2 == dirn)
|
||||
user << "There's already a cable at that position."
|
||||
return
|
||||
|
||||
var/obj/cable/C = new(F)
|
||||
C.d1 = 0
|
||||
C.d2 = dirn
|
||||
C.add_fingerprint(user)
|
||||
C.updateicon()
|
||||
C.update_network()
|
||||
use(1)
|
||||
//src.laying = 1
|
||||
//last = C
|
||||
|
||||
|
||||
// called when cable_coil is click on an installed obj/cable
|
||||
|
||||
/obj/item/weapon/cable_coil/proc/cable_join(obj/cable/C, mob/user)
|
||||
|
||||
|
||||
var/turf/U = user.loc
|
||||
if(!isturf(U))
|
||||
return
|
||||
|
||||
var/turf/T = C.loc
|
||||
|
||||
if(!isturf(T) || T.intact) // sanity checks, also stop use interacting with T-scanner revealed cable
|
||||
return
|
||||
|
||||
if(get_dist(C, user) > 1) // make sure it's close enough
|
||||
user << "You can't lay cable at a place that far away."
|
||||
return
|
||||
|
||||
|
||||
if(U == T) // do nothing if we clicked a cable we're standing on
|
||||
return // may change later if can think of something logical to do
|
||||
|
||||
var/dirn = get_dir(C, user)
|
||||
|
||||
if(C.d1 == dirn || C.d2 == dirn) // one end of the clicked cable is pointing towards us
|
||||
if(U.intact) // can't place a cable if the floor is complete
|
||||
user << "You can't lay cable there unless the floor tiles are removed."
|
||||
return
|
||||
else
|
||||
// cable is pointing at us, we're standing on an open tile
|
||||
// so create a stub pointing at the clicked cable on our tile
|
||||
|
||||
var/fdirn = turn(dirn, 180) // the opposite direction
|
||||
|
||||
for(var/obj/cable/LC in U) // check to make sure there's not a cable there already
|
||||
if(LC.d1 == fdirn || LC.d2 == fdirn)
|
||||
user << "There's already a cable at that position."
|
||||
return
|
||||
|
||||
var/obj/cable/NC = new(U)
|
||||
NC.d1 = 0
|
||||
NC.d2 = fdirn
|
||||
NC.add_fingerprint()
|
||||
NC.updateicon()
|
||||
NC.update_network()
|
||||
use(1)
|
||||
C.shock(user, 25)
|
||||
|
||||
return
|
||||
else if(C.d1 == 0) // exisiting cable doesn't point at our position, so see if it's a stub
|
||||
// if so, make it a full cable pointing from it's old direction to our dirn
|
||||
|
||||
var/nd1 = C.d2 // these will be the new directions
|
||||
var/nd2 = dirn
|
||||
|
||||
if(nd1 > nd2) // swap directions to match icons/states
|
||||
nd1 = dirn
|
||||
nd2 = C.d2
|
||||
|
||||
|
||||
for(var/obj/cable/LC in T) // check to make sure there's no matching cable
|
||||
if(LC == C) // skip the cable we're interacting with
|
||||
continue
|
||||
if(LC.d1 == nd1 || LC.d2 == nd1 || LC.d1 == nd2 || LC.d2 == nd2) // make sure no cable matches either direction
|
||||
user << "There's already a cable at that position."
|
||||
return
|
||||
C.shock(user, 25)
|
||||
del(C)
|
||||
var/obj/cable/NC = new(T)
|
||||
NC.d1 = nd1
|
||||
NC.d2 = nd2
|
||||
NC.add_fingerprint()
|
||||
NC.updateicon()
|
||||
NC.update_network()
|
||||
|
||||
use(1)
|
||||
|
||||
return
|
||||
|
||||
|
||||
// called when a new cable is created
|
||||
// can be 1 of 3 outcomes:
|
||||
// 1. Isolated cable (or only connects to isolated machine) -> create new powernet
|
||||
// 2. Joins to end or bridges loop of a single network (may also connect isolated machine) -> add to old network
|
||||
// 3. Bridges gap between 2 networks -> merge the networks (must rebuild lists also)
|
||||
|
||||
|
||||
|
||||
/obj/cable/proc/update_network()
|
||||
// easy way: do /makepowernets again
|
||||
makepowernets()
|
||||
// do things more logically if this turns out to be too slow
|
||||
// may just do this for case 3 anyway (simpler than refreshing list)
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// the powernet datum
|
||||
// each contiguous network of cables & nodes
|
||||
|
||||
|
||||
// rebuild all power networks from scratch
|
||||
|
||||
/proc/makepowernets()
|
||||
|
||||
var/netcount = 0
|
||||
powernets = list()
|
||||
|
||||
for(var/obj/cable/PC in world)
|
||||
PC.netnum = 0
|
||||
for(var/obj/machinery/power/M in machines)
|
||||
if(M.netnum >=0)
|
||||
M.netnum = 0
|
||||
|
||||
|
||||
for(var/obj/cable/PC in world)
|
||||
if(!PC.netnum)
|
||||
PC.netnum = ++netcount
|
||||
|
||||
if(Debug) world.log << "Starting mpn at [PC.x],[PC.y] ([PC.d1]/[PC.d2]) #[netcount]"
|
||||
powernet_nextlink(PC, PC.netnum)
|
||||
|
||||
if(Debug) world.log << "[netcount] powernets found"
|
||||
|
||||
for(var/L = 1 to netcount)
|
||||
var/datum/powernet/PN = new()
|
||||
//PN.tag = "powernet #[L]"
|
||||
powernets += PN
|
||||
PN.number = L
|
||||
|
||||
|
||||
for(var/obj/cable/C in world)
|
||||
var/datum/powernet/PN = powernets[C.netnum]
|
||||
PN.cables += C
|
||||
|
||||
for(var/obj/machinery/power/M in machines)
|
||||
if(M.netnum<=0) // APCs have netnum=-1 so they don't count as network nodes directly
|
||||
continue
|
||||
|
||||
M.powernet = powernets[M.netnum]
|
||||
M.powernet.nodes += M
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// returns a list of all power-related objects (nodes, cable, junctions) in turf,
|
||||
// excluding source, that match the direction d
|
||||
// if unmarked==1, only return those with netnum==0
|
||||
|
||||
/proc/power_list(var/turf/T, var/source, var/d, var/unmarked=0)
|
||||
var/list/result = list()
|
||||
var/fdir = (!d)? 0 : turn(d, 180) // the opposite direction to d (or 0 if d==0)
|
||||
|
||||
for(var/obj/machinery/power/P in T)
|
||||
if(P.netnum < 0) // exclude APCs
|
||||
continue
|
||||
|
||||
if(P.directwired) // true if this machine covers the whole turf (so can be joined to a cable on neighbour turf)
|
||||
if(!unmarked || !P.netnum)
|
||||
result += P
|
||||
else if(d == 0) // otherwise, need a 0-X cable on same turf to connect
|
||||
if(!unmarked || !P.netnum)
|
||||
result += P
|
||||
|
||||
|
||||
for(var/obj/cable/C in T)
|
||||
if(C.d1 == fdir || C.d2 == fdir)
|
||||
if(!unmarked || !C.netnum)
|
||||
result += C
|
||||
|
||||
result -= source
|
||||
|
||||
return result
|
||||
|
||||
|
||||
/obj/cable/proc/get_connections()
|
||||
|
||||
var/list/res = list() // this will be a list of all connected power objects
|
||||
|
||||
var/turf/T
|
||||
if(!d1)
|
||||
T = src.loc // if d1=0, same turf as src
|
||||
else
|
||||
T = get_step(src, d1)
|
||||
|
||||
res += power_list(T, src , d1, 1)
|
||||
|
||||
T = get_step(src, d2)
|
||||
|
||||
res += power_list(T, src, d2, 1)
|
||||
|
||||
return res
|
||||
|
||||
|
||||
|
||||
|
||||
/proc/powernet_nextlink(var/obj/O, var/num)
|
||||
|
||||
var/list/P
|
||||
|
||||
//world.log << "start: [O] at [O.x].[O.y]"
|
||||
|
||||
|
||||
while(1)
|
||||
|
||||
if( istype(O, /obj/cable) )
|
||||
var/obj/cable/C = O
|
||||
|
||||
C.netnum = num
|
||||
|
||||
else if( istype(O, /obj/machinery/power) )
|
||||
|
||||
var/obj/machinery/power/M = O
|
||||
|
||||
M.netnum = num
|
||||
|
||||
|
||||
if( istype(O, /obj/cable) )
|
||||
var/obj/cable/C = O
|
||||
|
||||
P = C.get_connections()
|
||||
|
||||
else if( istype(O, /obj/machinery/power) )
|
||||
|
||||
var/obj/machinery/power/M = O
|
||||
|
||||
P = M.get_connections()
|
||||
|
||||
if(P.len == 0)
|
||||
//world.log << "end1"
|
||||
return
|
||||
|
||||
O = P[1]
|
||||
|
||||
|
||||
for(var/L = 2 to P.len)
|
||||
|
||||
powernet_nextlink(P[L], num)
|
||||
|
||||
//world.log << "next: [O] at [O.x].[O.y]"
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
// cut a powernet at this cable object
|
||||
|
||||
/datum/powernet/proc/cut_cable(var/obj/cable/C)
|
||||
|
||||
var/turf/T1 = C.loc
|
||||
if(C.d1)
|
||||
T1 = get_step(C, C.d1)
|
||||
|
||||
var/turf/T2 = get_step(C, C.d2)
|
||||
|
||||
var/list/P1 = power_list(T1, C, C.d1) // what joins on to cut cable in dir1
|
||||
|
||||
var/list/P2 = power_list(T2, C, C.d2) // what joins on to cut cable in dir2
|
||||
|
||||
if(Debug)
|
||||
for(var/obj/O in P1)
|
||||
world.log << "P1: [O] at [O.x] [O.y] : [istype(O, /obj/cable) ? "[O:d1]/[O:d2]" : null] "
|
||||
for(var/obj/O in P2)
|
||||
world.log << "P2: [O] at [O.x] [O.y] : [istype(O, /obj/cable) ? "[O:d1]/[O:d2]" : null] "
|
||||
|
||||
|
||||
|
||||
if(P1.len == 0 || P2.len ==0) // if nothing in either list, then the cable was an endpoint
|
||||
// no need to rebuild the powernet, just remove cut cable from the list
|
||||
cables -= C
|
||||
if(Debug) world.log << "Was end of cable"
|
||||
return
|
||||
|
||||
// zero the netnum of all cables & nodes in this powernet
|
||||
|
||||
for(var/obj/cable/OC in cables)
|
||||
OC.netnum = 0
|
||||
for(var/obj/machinery/power/OM in nodes)
|
||||
OM.netnum = 0
|
||||
|
||||
|
||||
// remove the cut cable from the network
|
||||
C.netnum = -1
|
||||
C.loc = null
|
||||
cables -= C
|
||||
|
||||
|
||||
|
||||
|
||||
powernet_nextlink(P1[1], number) // propagate network from 1st side of cable, using current netnum
|
||||
|
||||
// now test to see if propagation reached to the other side
|
||||
// if so, then there's a loop in the network
|
||||
|
||||
var/notlooped = 0
|
||||
for(var/obj/O in P2)
|
||||
if( istype(O, /obj/machinery/power) )
|
||||
var/obj/machinery/power/OM = O
|
||||
if(OM.netnum != number)
|
||||
notlooped = 1
|
||||
break
|
||||
else if( istype(O, /obj/cable) )
|
||||
var/obj/cable/OC = O
|
||||
if(OC.netnum != number)
|
||||
notlooped = 1
|
||||
break
|
||||
|
||||
if(notlooped)
|
||||
|
||||
// not looped, so make a new powernet
|
||||
|
||||
var/datum/powernet/PN = new()
|
||||
//PN.tag = "powernet #[L]"
|
||||
powernets += PN
|
||||
PN.number = powernets.len
|
||||
|
||||
if(Debug) world.log << "Was not looped: spliting PN#[number] ([cables.len];[nodes.len])"
|
||||
|
||||
for(var/obj/cable/OC in cables)
|
||||
|
||||
if(!OC.netnum) // non-connected cables will have netnum==0, since they weren't reached by propagation
|
||||
|
||||
OC.netnum = PN.number
|
||||
cables -= OC
|
||||
PN.cables += OC // remove from old network & add to new one
|
||||
|
||||
for(var/obj/machinery/power/OM in nodes)
|
||||
if(!OM.netnum)
|
||||
OM.netnum = PN.number
|
||||
OM.powernet = PN
|
||||
nodes -= OM
|
||||
PN.nodes += OM // same for power machines
|
||||
|
||||
if(Debug)
|
||||
world.log << "Old PN#[number] : ([cables.len];[nodes.len])"
|
||||
world.log << "New PN#[PN.number] : ([PN.cables.len];[PN.nodes.len])"
|
||||
|
||||
else
|
||||
if(Debug)
|
||||
world.log << "Was looped."
|
||||
//there is a loop, so nothing to be done
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
|
||||
|
||||
/datum/powernet/proc/reset()
|
||||
load = newload
|
||||
newload = 0
|
||||
avail = newavail
|
||||
newavail = 0
|
||||
|
||||
|
||||
viewload = 0.8*viewload + 0.2*load
|
||||
|
||||
viewload = round(viewload)
|
||||
|
||||
var/numapc = 0
|
||||
|
||||
for(var/obj/machinery/power/terminal/term in nodes)
|
||||
if( istype( term.master, /obj/machinery/power/apc ) )
|
||||
numapc++
|
||||
|
||||
if(numapc)
|
||||
perapc = avail/numapc
|
||||
|
||||
netexcess = avail - load
|
||||
|
||||
if( netexcess > 100) // if there was excess power last cycle
|
||||
for(var/obj/machinery/power/smes/S in nodes) // find the SMESes in the network
|
||||
S.restore() // and restore some of the power that was used
|
||||
|
||||
|
||||
|
||||
+145
@@ -0,0 +1,145 @@
|
||||
|
||||
|
||||
/obj/shut_controller/proc/rotate(direct)
|
||||
|
||||
var/SE_X = 1
|
||||
var/SE_Y = 1
|
||||
var/SW_X = 1
|
||||
var/SW_Y = 1
|
||||
var/NE_X = 1
|
||||
var/NE_Y = 1
|
||||
var/NW_X = 1
|
||||
var/NW_Y = 1
|
||||
for(var/obj/move/M in src.parts)
|
||||
if (M.x < SW_X)
|
||||
SW_X = M.x
|
||||
if (M.x > SE_X)
|
||||
SE_X = M.x
|
||||
if (M.y < SW_Y)
|
||||
SW_Y = M.y
|
||||
if (M.y > NW_Y)
|
||||
NW_Y = M.y
|
||||
if (M.y > NE_Y)
|
||||
NE_Y = M.y
|
||||
if (M.y < SE_Y)
|
||||
SE_Y = M.y
|
||||
if (M.x > NE_X)
|
||||
NE_X = M.x
|
||||
if (M.x < NW_X)
|
||||
NW_X = M.y
|
||||
//Foreach goto(75)
|
||||
var/length = abs(NE_X - NW_X)
|
||||
var/width = abs(NE_Y - SE_Y)
|
||||
var/obj/random = pick(src.parts)
|
||||
var/s_direct = null
|
||||
switch(s_direct)
|
||||
if(1.0)
|
||||
switch(direct)
|
||||
if(90.0)
|
||||
var/tx = SE_X
|
||||
var/ty = SE_Y
|
||||
var/t_z = random.z
|
||||
for(var/obj/move/M in src.parts)
|
||||
M.ty = -M.x - tx
|
||||
M.tx = -M.y - ty
|
||||
var/T = locate(M.x, M.y, 11)
|
||||
M.relocate(T)
|
||||
M.ty = -M.ty
|
||||
M.tx += length
|
||||
//Foreach goto(374)
|
||||
for(var/obj/move/M in src.parts)
|
||||
M.tx += tx
|
||||
M.ty += ty
|
||||
var/T = locate(M.tx, M.ty, t_z)
|
||||
M.relocate(T, 90)
|
||||
//Foreach goto(468)
|
||||
if(-90.0)
|
||||
var/tx = SE_X
|
||||
var/ty = SE_Y
|
||||
var/t_z = random.z
|
||||
for(var/obj/move/M in src.parts)
|
||||
M.ty = M.x - tx
|
||||
M.tx = M.y - ty
|
||||
var/T = locate(M.x, M.y, 11)
|
||||
M.relocate(T)
|
||||
M.ty = -M.ty
|
||||
M.ty += width
|
||||
//Foreach goto(571)
|
||||
for(var/obj/move/M in src.parts)
|
||||
M.tx += tx
|
||||
M.ty += ty
|
||||
var/T = locate(M.tx, M.ty, t_z)
|
||||
M.relocate(T, -90.0)
|
||||
//Foreach goto(663)
|
||||
else
|
||||
else
|
||||
return
|
||||
|
||||
/obj/shuttle/door/verb/open()
|
||||
set src in oview(1)
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
if (src.operating)
|
||||
return
|
||||
src.operating = 1
|
||||
flick("doorc0", src)
|
||||
src.icon_state = "door0"
|
||||
sleep(15)
|
||||
src.density = 0
|
||||
src.opacity = 0
|
||||
src.verbs -= /obj/shuttle/door/verb/open
|
||||
src.verbs += /obj/shuttle/door/proc/close
|
||||
src.operating = 0
|
||||
|
||||
src.loc.buildlinks()
|
||||
|
||||
return
|
||||
|
||||
/obj/shuttle/door/proc/close()
|
||||
set src in oview(1)
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
if (src.operating)
|
||||
return
|
||||
src.operating = 1
|
||||
flick("doorc1", src)
|
||||
src.icon_state = "door1"
|
||||
src.density = 1
|
||||
if (src.visible)
|
||||
src.opacity = 1
|
||||
sleep(15)
|
||||
src.verbs += /obj/shuttle/door/verb/open
|
||||
src.verbs -= /obj/shuttle/door/proc/close
|
||||
src.operating = 0
|
||||
|
||||
src.loc.buildlinks()
|
||||
return
|
||||
|
||||
/turf/station/shuttle/ex_act(severity)
|
||||
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
//SN src = null
|
||||
var/turf/space/S = new /turf/space( locate(src.x, src.y, src.z) )
|
||||
S.buildlinks()
|
||||
|
||||
del(src)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(50))
|
||||
//SN src = null
|
||||
var/turf/space/S = new /turf/space( locate(src.x, src.y, src.z) )
|
||||
S.buildlinks()
|
||||
|
||||
del(src)
|
||||
return
|
||||
else
|
||||
return
|
||||
|
||||
/turf/station/shuttle/blob_act()
|
||||
if(prob(20))
|
||||
|
||||
var/turf/space/S = new /turf/space( locate(src.x, src.y, src.z) )
|
||||
S.buildlinks()
|
||||
|
||||
del(src)
|
||||
@@ -0,0 +1,568 @@
|
||||
|
||||
/proc/SetupOccupationsList()
|
||||
|
||||
var/list/new_occupations = list( )
|
||||
for(var/occupation in occupations)
|
||||
if (!( new_occupations.Find(occupation) ))
|
||||
new_occupations[occupation] = 1
|
||||
else
|
||||
new_occupations[occupation] += 1
|
||||
//Foreach goto(23)
|
||||
occupations = new_occupations
|
||||
return
|
||||
|
||||
/proc/DivideOccupations()
|
||||
|
||||
var/list/occupations1 = list( )
|
||||
var/list/occupations2 = list( )
|
||||
var/list/occupations3 = list( )
|
||||
var/list/final_occupations = list( )
|
||||
var/list/unassigned_mobs = list( )
|
||||
var/list/occupation_choices = occupations.Copy()
|
||||
occupation_choices = shuffle(occupation_choices)
|
||||
for(var/occupation in occupations + assistant_occupations)
|
||||
occupations1[occupation] = list( )
|
||||
occupations2[occupation] = list( )
|
||||
occupations3[occupation] = list( )
|
||||
final_occupations[occupation] = list( )
|
||||
//Foreach goto(78)
|
||||
occupations1["Captain"] = list( )
|
||||
occupations2["Captain"] = list( )
|
||||
occupations3["Captain"] = list( )
|
||||
final_occupations["Captain"] = list( )
|
||||
for(var/mob/human/M in world)
|
||||
if ((!( M.client ) || !( M.start ) || M.already_placed))
|
||||
else
|
||||
unassigned_mobs += M
|
||||
if (M.occupation1 != "No Preference")
|
||||
occupations1[M.occupation1] += M
|
||||
if (M.occupation2 != "No Preference")
|
||||
occupations2[M.occupation2] += M
|
||||
if (M.occupation3 != "No Preference")
|
||||
occupations3[M.occupation3] += M
|
||||
//Foreach goto(187)
|
||||
for(var/occupation in occupations)
|
||||
occupations1[occupation] = shuffle(occupations1[occupation])
|
||||
occupations2[occupation] = shuffle(occupations2[occupation])
|
||||
occupations3[occupation] = shuffle(occupations3[occupation])
|
||||
//Foreach goto(339)
|
||||
occupations1["Captain"] = shuffle(occupations1["Captain"])
|
||||
occupations2["Captain"] = shuffle(occupations2["Captain"])
|
||||
occupations3["Captain"] = shuffle(occupations3["Captain"])
|
||||
var/list/captain_choice = occupations1["Captain"]
|
||||
if (captain_choice.len)
|
||||
final_occupations["Captain"] = captain_choice[1]
|
||||
occupation_choices -= "Captain"
|
||||
unassigned_mobs -= final_occupations["Captain"]
|
||||
if (!( final_occupations["Captain"] ))
|
||||
captain_choice = occupations2["Captain"]
|
||||
if (captain_choice.len)
|
||||
final_occupations["Captain"] = captain_choice[1]
|
||||
occupation_choices -= "Captain"
|
||||
unassigned_mobs -= final_occupations["Captain"]
|
||||
if (!( final_occupations["Captain"] ))
|
||||
captain_choice = occupations3["Captain"]
|
||||
if (captain_choice.len)
|
||||
final_occupations["Captain"] = captain_choice[1]
|
||||
occupation_choices -= "Captain"
|
||||
unassigned_mobs -= final_occupations["Captain"]
|
||||
if (!( final_occupations["Captain"] ))
|
||||
var/list/contenders = list( )
|
||||
for(var/mob/human/M in world)
|
||||
if (M.client)
|
||||
contenders += M
|
||||
//Foreach goto(691)
|
||||
var/mob/human/M = pick(contenders)
|
||||
final_occupations["Captain"] = M
|
||||
occupation_choices -= "Captain"
|
||||
unassigned_mobs -= final_occupations["Captain"]
|
||||
occupations1[text("[]", M.occupation1)] -= M
|
||||
occupations2[text("[]", M.occupation2)] -= M
|
||||
occupations3[text("[]", M.occupation3)] -= M
|
||||
for(var/mob/human/M in unassigned_mobs)
|
||||
if (assistant_occupations.Find(M.occupation1))
|
||||
M.Assign_Rank(M.occupation1)
|
||||
unassigned_mobs -= M
|
||||
//Foreach goto(844)
|
||||
for(var/occupation in occupation_choices)
|
||||
var/list/L = occupations1[occupation]
|
||||
if (L.len)
|
||||
var/eligible = occupations[occupation]
|
||||
var/multiple = eligible > 1
|
||||
while(eligible--)
|
||||
var/M = null
|
||||
var/i = null
|
||||
i = 1
|
||||
while((i <= L.len && !( M )))
|
||||
if (unassigned_mobs.Find(L[i]))
|
||||
M = L[i]
|
||||
i++
|
||||
if (M)
|
||||
if (multiple)
|
||||
final_occupations[occupation] += M
|
||||
else
|
||||
final_occupations[occupation] = M
|
||||
unassigned_mobs -= M
|
||||
if (eligible < 1)
|
||||
occupation_choices -= occupation
|
||||
if ((!( occupation_choices.len ) || !( unassigned_mobs.len )))
|
||||
else
|
||||
//Foreach continue //goto(913)
|
||||
for(var/mob/human/M in unassigned_mobs)
|
||||
if (assistant_occupations.Find(M.occupation2))
|
||||
M.Assign_Rank(M.occupation2)
|
||||
unassigned_mobs -= M
|
||||
//Foreach goto(1158)
|
||||
for(var/occupation in occupation_choices)
|
||||
var/list/L = occupations2[occupation]
|
||||
if (L.len)
|
||||
var/eligible = occupations[occupation]
|
||||
var/multiple = eligible > 1
|
||||
if (multiple)
|
||||
var/list/X = final_occupations[occupation]
|
||||
eligible -= X.len
|
||||
while(eligible--)
|
||||
var/M = null
|
||||
var/i = null
|
||||
i = 1
|
||||
while((i <= L.len && !( M )))
|
||||
if (unassigned_mobs.Find(L[i]))
|
||||
M = L[i]
|
||||
i++
|
||||
if (M)
|
||||
if (multiple)
|
||||
final_occupations[occupation] += M
|
||||
else
|
||||
final_occupations[occupation] = M
|
||||
unassigned_mobs -= M
|
||||
if (eligible < 1)
|
||||
occupation_choices -= occupation
|
||||
if ((!( occupation_choices.len ) || !( unassigned_mobs.len )))
|
||||
else
|
||||
//Foreach continue //goto(1227)
|
||||
for(var/mob/human/M in unassigned_mobs)
|
||||
if (assistant_occupations.Find(M.occupation3))
|
||||
M.Assign_Rank(M.occupation3)
|
||||
unassigned_mobs -= M
|
||||
//Foreach goto(1502)
|
||||
for(var/occupation in occupation_choices)
|
||||
var/list/L = occupations3[occupation]
|
||||
if (L.len)
|
||||
var/eligible = occupations[occupation]
|
||||
var/multiple = eligible > 1
|
||||
if (multiple)
|
||||
var/list/X = final_occupations[occupation]
|
||||
eligible -= X.len
|
||||
while(eligible--)
|
||||
var/M = null
|
||||
var/i = null
|
||||
i = 1
|
||||
while((i <= L.len && !( M )))
|
||||
if (unassigned_mobs.Find(L[i]))
|
||||
M = L[i]
|
||||
i++
|
||||
if (M)
|
||||
if (multiple)
|
||||
final_occupations[occupation] += M
|
||||
else
|
||||
final_occupations[occupation] = M
|
||||
unassigned_mobs -= M
|
||||
if (eligible < 1)
|
||||
occupation_choices -= occupation
|
||||
//Foreach goto(1571)
|
||||
if (unassigned_mobs.len)
|
||||
unassigned_mobs = shuffle(unassigned_mobs)
|
||||
for(var/mob/human/M in unassigned_mobs)
|
||||
if (occupation_choices.len)
|
||||
var/occupation = pick(occupation_choices)
|
||||
final_occupations[occupation] = M
|
||||
occupation_choices -= occupation
|
||||
unassigned_mobs -= M
|
||||
break ////
|
||||
//Foreach goto(1846)
|
||||
for(var/occupation in final_occupations)
|
||||
var/mob/human/M = final_occupations[occupation]
|
||||
if (ismob(M))
|
||||
M.Assign_Rank(occupation)
|
||||
else
|
||||
if (istype(M, /list))
|
||||
for(var/mob/human/E in final_occupations[occupation])
|
||||
E.Assign_Rank(occupation)
|
||||
//Foreach goto(2003)
|
||||
//Foreach goto(1931)
|
||||
for(var/mob/human/M in unassigned_mobs)
|
||||
M.Assign_Rank(pick("Research Assistant", "Technical Assistant", "Medical Assistant", "Staff Assistant"))
|
||||
//Foreach goto(2051)
|
||||
return
|
||||
|
||||
/proc/shuffle(var/list/shufflelist)
|
||||
|
||||
if (!( shufflelist ))
|
||||
return
|
||||
var/list/old_list = shufflelist.Copy()
|
||||
var/list/new_list = list( )
|
||||
while(old_list.len)
|
||||
var/item = old_list[rand(1, old_list.len)]
|
||||
new_list += item
|
||||
old_list -= item
|
||||
return new_list
|
||||
return
|
||||
|
||||
/world/New()
|
||||
|
||||
..()
|
||||
spawn( 0 )
|
||||
SetupOccupationsList()
|
||||
return
|
||||
return
|
||||
|
||||
/mob/human/verb/char_setup()
|
||||
|
||||
if (src.start)
|
||||
return
|
||||
src.ShowChoices()
|
||||
return
|
||||
|
||||
/mob/human/proc/ShowChoices()
|
||||
|
||||
var/list/destructive = assistant_occupations.Copy()
|
||||
var/dat = "<html><body>"
|
||||
dat += text("<b>Name:</b> <a href=\"byond://?src=\ref[];rname=input\"><b>[]</b></a><br>", src, src.rname)
|
||||
dat += text("<b>Gender:</b> <a href=\"byond://?src=\ref[];gender=input\"><b>[]</b></a><br>", src, (src.gender == "male" ? "Male" : "Female"))
|
||||
dat += text("<b>Age</b> - <a href='byond://?src=\ref[];age=input'>[]</a><hr>", src, src.age)
|
||||
dat += "<hr><b>Occupation Choices</b>:<br>"
|
||||
if (destructive.Find(src.occupation1))
|
||||
dat += text("\t<a href=\"byond://?src=\ref[];occ=1\"><b>[]</b></a><br>", src, src.occupation1)
|
||||
else
|
||||
if (src.occupation1 != "No Preference")
|
||||
dat += text("\tFirst Choice: <a href=\"byond://?src=\ref[];occ=1\"><b>[]</b></a><br>", src, src.occupation1)
|
||||
if (destructive.Find(src.occupation2))
|
||||
dat += text("\tSecond Choice: <a href=\"byond://?src=\ref[];occ=2\"><b>[]</b></a><BR>", src, src.occupation2)
|
||||
else
|
||||
if (src.occupation2 != "No Preference")
|
||||
dat += text("\tSecond Choice: <a href=\"byond://?src=\ref[];occ=2\"><b>[]</b></a><BR>", src, src.occupation2)
|
||||
if (destructive.Find(src.occupation3))
|
||||
dat += text("\tLast Choice: <a href=\"byond://?src=\ref[];occ=3\"><b>[]</b></a><BR>", src, src.occupation3)
|
||||
else
|
||||
if (src.occupation3 != "No Preference")
|
||||
dat += text("\tLast Choice: <a href=\"byond://?src=\ref[];occ=3\"><b>[]</b></a><BR>", src, src.occupation3)
|
||||
else
|
||||
dat += text("\tLast Choice: <a href=\"byond://?src=\ref[];occ=3\">No Preference</a><br>", src)
|
||||
else
|
||||
dat += text("\tSecond Choice: <a href=\"byond://?src=\ref[];occ=2\">No Preference</a><br>", src)
|
||||
else
|
||||
dat += text("\t<a href=\"byond://?src=\ref[];occ=1\">No Preference</a><br>", src)
|
||||
dat += "<hr><b>Body Data</b><br>"
|
||||
dat += text("<b>Blood Type:</b> <a href='byond://?src=\ref[];b_type=input'>[]</a><br>", src, src.b_type)
|
||||
dat += text("<b>Skin Tone:</b> <a href='byond://?src=\ref[];ns_tone=input'>[]/220</a><br>", src, -src.ns_tone + 35)
|
||||
dat += text("<b>Hair Color:</b> <font color=\"#[][][]\">test</font><br>", num2hex(src.nr_hair, 2), num2hex(src.ng_hair, 2), num2hex(src.nb_hair))
|
||||
dat += text(" <b><font color=\"#[]0000\">Red</font></b> - <a href='byond://?src=\ref[];nr_hair=input'>[]</a>", num2hex(src.nr_hair, 2), src, src.nr_hair)
|
||||
dat += text(" <b><font color=\"#00[]00\">Green</font></b> - <a href='byond://?src=\ref[];ng_hair=input'>[]</a>", num2hex(src.ng_hair, 2), src, src.ng_hair)
|
||||
dat += text(" <b><font color=\"#0000[]\">Blue</font></b> - <a href='byond://?src=\ref[];nb_hair=input'>[]</a>", num2hex(src.nb_hair, 2), src, src.nb_hair)
|
||||
dat += text("<br> <b>Style</b> - <a href='byond://?src=\ref[];h_style=input'>[]</a>", src, src.h_style)
|
||||
dat += text("<br><b>Eye Color:</b> <font color=\"#[][][]\">test</font><br>", num2hex(src.r_eyes, 2), num2hex(src.g_eyes, 2), num2hex(src.b_eyes, 2))
|
||||
dat += text(" <b><font color=\"#[]0000\">Red</font></b> - <a href='byond://?src=\ref[];r_eyes=input'>[]</a>", num2hex(src.r_eyes, 2), src, src.r_eyes)
|
||||
dat += text(" <b><font color=\"#00[]00\">Green</font></b> - <a href='byond://?src=\ref[];g_eyes=input'>[]</a>", num2hex(src.g_eyes, 2), src, src.g_eyes)
|
||||
dat += text(" <b><font color=\"#0000[]\">Blue</font></b> - <a href='byond://?src=\ref[];b_eyes=input'>[]</a>", num2hex(src.b_eyes, 2), src, src.b_eyes)
|
||||
dat += "<hr><b>Disabilities</b><br>"
|
||||
dat += text("Need Glasses: <a href=\"byond://?src=\ref[];n_gl=1\"><b>[]</b></a><br>", src, (src.need_gl ? "Yes" : "No"))
|
||||
dat += text("Epileptic: <a href=\"byond://?src=\ref[];b_ep=1\"><b>[]</b></a><br>", src, (src.be_epil ? "Yes" : "No"))
|
||||
dat += text("Tourette Syndrome: <a href=\"byond://?src=\ref[];b_tur=1\"><b>[]</b></a><br>", src, (src.be_tur ? "Yes" : "No"))
|
||||
dat += text("Chronic Cough: <a href=\"byond://?src=\ref[];b_co=1\"><b>[]</b></a><br>", src, (src.be_cough ? "Yes" : "No"))
|
||||
dat += text("Stutter: <a href=\"byond://?src=\ref[];b_stut=1\"><b>[]</b></a><br>", src, (src.be_stut ? "Yes" : "No"))
|
||||
dat += "<hr>"
|
||||
dat += text("<a href='byond://?src=\ref[];load=1'>Load Setup</a><br>", src)
|
||||
dat += text("<a href='byond://?src=\ref[];save=1'>Save Setup</a><br>", src)
|
||||
dat += text("<a href='byond://?src=\ref[];reset_all=1'>Reset Setup</a><br>", src)
|
||||
dat += "</body></html>"
|
||||
src << browse(dat, "window=mob_occupations;size=300x600")
|
||||
return
|
||||
|
||||
/mob/human/proc/SetChoices(occ)
|
||||
|
||||
if (occ == null)
|
||||
occ = 1
|
||||
var/HTML = "<body>"
|
||||
HTML += "<tt><center>"
|
||||
switch(occ)
|
||||
if(1.0)
|
||||
HTML += "<b>Which occupation would you like most?</b><br><br>"
|
||||
if(2.0)
|
||||
HTML += "<b>Which occupation would you like if you couldn't have your first?</b><br><br>"
|
||||
if(3.0)
|
||||
HTML += "<b>Which occupation would you like if you couldn't have the others?</b><br><br>"
|
||||
else
|
||||
for(var/job in uniquelist(occupations + assistant_occupations) )
|
||||
HTML += text("<a href=\"byond://?src=\ref[];occ=[];job=[]\">[]</a><br>", src, occ, job, job)
|
||||
//Foreach goto(105)
|
||||
HTML += text("<a href=\"byond://?src=\ref[];occ=[];job=Captain\">Captain</a><br>", src, occ)
|
||||
HTML += "<br>"
|
||||
HTML += text("<a href=\"byond://?src=\ref[];occ=[];job=No Preference\">\[No Preference\]</a><br>", src, occ)
|
||||
HTML += text("<a href=\"byond://?src=\ref[];occ=[];cancel\">\[Cancel\]</a>", src, occ)
|
||||
HTML += "</center></tt>"
|
||||
usr << browse(HTML, "window=mob_occupation;size=320x500")
|
||||
return
|
||||
|
||||
/proc/uniquelist(var/list/L)
|
||||
var/list/K = list()
|
||||
for(var/item in L)
|
||||
if(!(item in K))
|
||||
K += item
|
||||
|
||||
return K
|
||||
|
||||
|
||||
/mob/human/proc/SetJob(occ, job)
|
||||
|
||||
if (occ == null)
|
||||
occ = 1
|
||||
if (job == null)
|
||||
job = "Captain"
|
||||
if ((!( occupations.Find(job) ) && !( assistant_occupations.Find(job) ) && job != "Captain"))
|
||||
return
|
||||
switch(occ)
|
||||
if(1.0)
|
||||
if (job == src.occupation1)
|
||||
usr << browse(null, "window=mob_occupation")
|
||||
return
|
||||
else
|
||||
if (job == "No Preference")
|
||||
src.occupation1 = "No Preference"
|
||||
else
|
||||
if (job == src.occupation2)
|
||||
job = src.occupation1
|
||||
src.occupation1 = src.occupation2
|
||||
src.occupation2 = job
|
||||
else
|
||||
if (job == src.occupation3)
|
||||
job = src.occupation1
|
||||
src.occupation1 = src.occupation3
|
||||
src.occupation3 = job
|
||||
else
|
||||
src.occupation1 = job
|
||||
if(2.0)
|
||||
if (job == src.occupation2)
|
||||
src << browse(null, "window=mob_occupation")
|
||||
return
|
||||
else
|
||||
if (job == "No Preference")
|
||||
if (src.occupation3 != "No Preference")
|
||||
src.occupation2 = src.occupation3
|
||||
src.occupation3 = "No Preference"
|
||||
else
|
||||
src.occupation2 = "No Preference"
|
||||
else
|
||||
if (job == src.occupation1)
|
||||
if (src.occupation2 == "No Preference")
|
||||
src << browse(null, "window=mob_occupation")
|
||||
return
|
||||
job = src.occupation2
|
||||
src.occupation2 = src.occupation1
|
||||
src.occupation1 = job
|
||||
else
|
||||
if (job == src.occupation3)
|
||||
job = src.occupation2
|
||||
src.occupation2 = src.occupation3
|
||||
src.occupation3 = job
|
||||
else
|
||||
src.occupation2 = job
|
||||
if(3.0)
|
||||
if (job == src.occupation3)
|
||||
usr << browse(null, "window=mob_occupation")
|
||||
return
|
||||
else
|
||||
if (job == "No Preference")
|
||||
src.occupation3 = "No Preference"
|
||||
else
|
||||
if (job == src.occupation1)
|
||||
if (src.occupation3 == "No Preference")
|
||||
src << browse(null, "window=mob_occupation")
|
||||
return
|
||||
job = src.occupation3
|
||||
src.occupation3 = src.occupation1
|
||||
src.occupation1 = job
|
||||
else
|
||||
if (job == src.occupation2)
|
||||
if (src.occupation3 == "No Preference")
|
||||
src << browse(null, "window=mob_occupation")
|
||||
return
|
||||
job = src.occupation3
|
||||
src.occupation3 = src.occupation2
|
||||
src.occupation2 = job
|
||||
else
|
||||
src.occupation3 = job
|
||||
else
|
||||
src.ShowChoices()
|
||||
src << browse(null, "window=mob_occupation")
|
||||
return
|
||||
|
||||
/mob/human/proc/Assign_Rank(rank)
|
||||
|
||||
if (rank == "Captain")
|
||||
world << text("<b>[] is the captain!</b>", src)
|
||||
if (!( src.w_radio ))
|
||||
var/obj/item/weapon/radio/headset/H = new /obj/item/weapon/radio/headset( src )
|
||||
src.w_radio = H
|
||||
H.layer = 20
|
||||
if (!( src.back ))
|
||||
var/obj/item/weapon/storage/backpack/H = new /obj/item/weapon/storage/backpack( src )
|
||||
src.back = H
|
||||
H.layer = 20
|
||||
if (!( src.glasses ))
|
||||
if (src.disabilities & 1)
|
||||
var/obj/item/weapon/clothing/glasses/regular/G = new /obj/item/weapon/clothing/glasses/regular( src )
|
||||
src.glasses = G
|
||||
G.layer = 20
|
||||
if ((!( src.belt ) && src.w_uniform))
|
||||
var/obj/item/weapon/radio/signaler/S = new /obj/item/weapon/radio/signaler( src )
|
||||
src.belt = S
|
||||
S.layer = 20
|
||||
if ((!( src.r_store ) && src.w_uniform))
|
||||
var/obj/item/weapon/pen/S = new /obj/item/weapon/pen( src )
|
||||
src.r_store = S
|
||||
S.layer = 20
|
||||
if ((src.client && !( src.wear_id ) && src.w_uniform))
|
||||
var/obj/item/weapon/card/id/C = new /obj/item/weapon/card/id( src )
|
||||
src.wear_id = C
|
||||
C.assignment = rank
|
||||
C.layer = 20
|
||||
C.registered = src.rname
|
||||
switch(C.assignment)
|
||||
if("Research Assistant")
|
||||
C.access_level = 1
|
||||
C.lab_access = 1
|
||||
C.engine_access = 0
|
||||
C.air_access = 0
|
||||
if("Technical Assistant")
|
||||
C.access_level = 1
|
||||
C.lab_access = 0
|
||||
C.engine_access = 1
|
||||
C.air_access = 0
|
||||
if("Staff Assistant")
|
||||
C.access_level = 2
|
||||
C.lab_access = 0
|
||||
C.engine_access = 0
|
||||
C.air_access = 0
|
||||
if("Medical Assistant")
|
||||
if (!( src.l_hand ))
|
||||
var/obj/item/weapon/storage/firstaid/regular/W = new /obj/item/weapon/storage/firstaid/regular( src )
|
||||
src.l_hand = W
|
||||
W.layer = 20
|
||||
src.UpdateClothing()
|
||||
C.access_level = 1
|
||||
C.lab_access = 1
|
||||
C.engine_access = 0
|
||||
C.air_access = 0
|
||||
if("Engineer")
|
||||
if (!( src.l_hand ))
|
||||
var/obj/item/weapon/storage/toolbox/W = new /obj/item/weapon/storage/toolbox( src )
|
||||
src.l_hand = W
|
||||
W.layer = 20
|
||||
src.UpdateClothing()
|
||||
C.access_level = 2
|
||||
C.lab_access = 1
|
||||
C.engine_access = 3
|
||||
C.air_access = 0
|
||||
if("Research Technician")
|
||||
C.access_level = 2
|
||||
C.lab_access = 3
|
||||
C.engine_access = 0
|
||||
C.air_access = 0
|
||||
if("Forensic Technician")
|
||||
C.access_level = 3
|
||||
C.lab_access = 2
|
||||
C.engine_access = 0
|
||||
C.air_access = 0
|
||||
if("Medical Doctor")
|
||||
if (!( src.l_hand ))
|
||||
var/obj/item/weapon/storage/firstaid/regular/W = new /obj/item/weapon/storage/firstaid/regular( src )
|
||||
src.l_hand = W
|
||||
W.layer = 20
|
||||
src.UpdateClothing()
|
||||
C.access_level = 2
|
||||
C.lab_access = 0
|
||||
C.engine_access = 0
|
||||
C.air_access = 0
|
||||
if("Prison Doctor")
|
||||
if (!( src.l_hand ))
|
||||
var/obj/item/weapon/storage/firstaid/regular/W = new /obj/item/weapon/storage/firstaid/regular( src )
|
||||
src.l_hand = W
|
||||
W.layer = 20
|
||||
src.UpdateClothing()
|
||||
C.access_level = 3
|
||||
C.lab_access = 0
|
||||
C.engine_access = 0
|
||||
C.air_access = 0
|
||||
if("Captain")
|
||||
C.access_level = 5
|
||||
C.air_access = 5
|
||||
C.engine_access = 5
|
||||
C.lab_access = 5
|
||||
if("Security Officer")
|
||||
if (!( src.l_hand ))
|
||||
var/obj/item/weapon/handcuffs/W = new /obj/item/weapon/handcuffs( src )
|
||||
src.l_hand = W
|
||||
W.layer = 20
|
||||
src.UpdateClothing()
|
||||
C.access_level = 3
|
||||
C.lab_access = 0
|
||||
C.engine_access = 0
|
||||
C.air_access = 0
|
||||
if("Prison Security")
|
||||
if (!( src.l_hand ))
|
||||
var/obj/item/weapon/handcuffs/W = new /obj/item/weapon/handcuffs( src )
|
||||
src.l_hand = W
|
||||
W.layer = 20
|
||||
src.UpdateClothing()
|
||||
C.access_level = 3
|
||||
C.lab_access = 0
|
||||
C.engine_access = 0
|
||||
C.air_access = 0
|
||||
if("Medical Researcher")
|
||||
C.access_level = 2
|
||||
C.lab_access = 5
|
||||
C.engine_access = 0
|
||||
C.air_access = 0
|
||||
if("Toxin Researcher")
|
||||
C.access_level = 2
|
||||
C.lab_access = 5
|
||||
C.engine_access = 0
|
||||
C.air_access = 0
|
||||
if("Head of Research")
|
||||
C.access_level = 4
|
||||
C.air_access = 2
|
||||
C.engine_access = 2
|
||||
C.lab_access = 5
|
||||
if("Head of Personnel")
|
||||
C.access_level = 4
|
||||
C.air_access = 2
|
||||
C.engine_access = 2
|
||||
C.lab_access = 4
|
||||
if("Prison Warden")
|
||||
C.access_level = 4
|
||||
C.air_access = 2
|
||||
C.engine_access = 2
|
||||
C.lab_access = 4
|
||||
if("Station Technician")
|
||||
if (!( src.l_hand ))
|
||||
var/obj/item/weapon/storage/toolbox/W = new /obj/item/weapon/storage/toolbox( src )
|
||||
src.l_hand = W
|
||||
W.layer = 20
|
||||
src.UpdateClothing()
|
||||
C.access_level = 2
|
||||
C.lab_access = 0
|
||||
C.engine_access = 2
|
||||
C.air_access = 3
|
||||
if("Atmospheric Technician")
|
||||
C.access_level = 3
|
||||
C.lab_access = 0
|
||||
C.engine_access = 0
|
||||
C.air_access = 4
|
||||
else
|
||||
C.name = text("[]'s ID Card ([]>[]-[]-[])", C.registered, C.access_level, C.lab_access, C.engine_access, C.air_access)
|
||||
src << text("<B>You are the [].</B>", C.assignment)
|
||||
var/obj/S = locate(text("start*[]", C.assignment))
|
||||
if ((istype(S, /obj/start) && istype(S.loc, /turf) && !( ctf )))
|
||||
src << "\blue <B>You have been teleported to your new starting location!</B>"
|
||||
src.loc = S.loc
|
||||
return
|
||||
+99
@@ -0,0 +1,99 @@
|
||||
/*
|
||||
/datum/sun
|
||||
var/angle
|
||||
var/dx
|
||||
var/dy
|
||||
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/datum/sun/New()
|
||||
rate = rand(75,125)/100 // 75% - 125% of standard rotation
|
||||
if(prob(50))
|
||||
rate = -rate
|
||||
|
||||
// calculate the sun's position given the time of day
|
||||
|
||||
/datum/sun/proc/calc_position()
|
||||
|
||||
counter++
|
||||
if(counter<50) // count 50 pticks (50 seconds, roughly - about a 5deg change)
|
||||
return
|
||||
counter = 0
|
||||
|
||||
angle = ((rate*world.realtime/100)%360 + 360)%360 // gives about a 60 minute rotation time
|
||||
// now 45 - 75 minutes, depending on rate
|
||||
// now calculate and cache the (dx,dy) increments for line drawing
|
||||
|
||||
var/s = sin(angle)
|
||||
var/c = cos(angle)
|
||||
|
||||
if(c == 0)
|
||||
|
||||
dx = 0
|
||||
dy = s
|
||||
|
||||
else if( abs(s) < abs(c))
|
||||
|
||||
dx = s / abs(c)
|
||||
dy = c / abs(c)
|
||||
|
||||
else
|
||||
dx = s/abs(s)
|
||||
dy = c / abs(s)
|
||||
|
||||
|
||||
for(var/obj/machinery/power/solar/S in machines)
|
||||
occlusion(S)
|
||||
|
||||
|
||||
|
||||
// for a solar panel, trace towards sun to see if we're in shadow
|
||||
|
||||
/datum/sun/proc/occlusion(var/obj/machinery/power/solar/S)
|
||||
|
||||
var/ax = S.x // start at the solar panel
|
||||
var/ay = S.y
|
||||
|
||||
for(var/i = 1 to 20) // 20 steps is enough
|
||||
ax += dx // do step
|
||||
ay += dy
|
||||
|
||||
var/turf/T = locate( round(ax,0.5),round(ay,0.5),S.z)
|
||||
|
||||
if(T.x == 1 || T.x==world.maxx || T.y==1 || T.y==world.maxy) // not obscured if we reach the edge
|
||||
break
|
||||
|
||||
if(T.density) // if we hit a solid turf, panel is obscured
|
||||
S.obscured = 1
|
||||
return
|
||||
|
||||
S.obscured = 0 // if hit the edge or steped 20 times, not obscured
|
||||
S.updatefrac()
|
||||
|
||||
|
||||
//returns the north-zero clockwise angle in degrees, given a direction
|
||||
|
||||
/proc/dir2angle(var/D)
|
||||
switch(D)
|
||||
if(1)
|
||||
return 0
|
||||
if(2)
|
||||
return 180
|
||||
if(4)
|
||||
return 90
|
||||
if(8)
|
||||
return 270
|
||||
if(5)
|
||||
return 45
|
||||
if(6)
|
||||
return 135
|
||||
if(9)
|
||||
return 315
|
||||
if(10)
|
||||
return 225
|
||||
else
|
||||
return null
|
||||
|
||||
|
||||
+335
@@ -0,0 +1,335 @@
|
||||
/datum/vote/New()
|
||||
|
||||
nextvotetime = world.timeofday // + 10*config.votedelay
|
||||
|
||||
|
||||
/datum/vote/proc/canvote()
|
||||
|
||||
var/excess = world.timeofday - vote.nextvotetime
|
||||
|
||||
if(excess < -10000) // handle clock-wrapping problems - very long delay (>20 hrs) if wrapped
|
||||
vote.nextvotetime = world.timeofday
|
||||
return 1
|
||||
return (excess >= 0)
|
||||
|
||||
|
||||
|
||||
/datum/vote/proc/nextwait()
|
||||
return timetext( round( (nextvotetime - world.timeofday)/10) )
|
||||
|
||||
/datum/vote/proc/endwait()
|
||||
return timetext( round( (votetime - world.timeofday)/10) )
|
||||
|
||||
/datum/vote/proc/timetext(var/interval)
|
||||
var/minutes = round(interval / 60)
|
||||
var/seconds = round(interval % 60)
|
||||
|
||||
var/tmin = "[minutes>0?num2text(minutes)+"min":null]"
|
||||
var/tsec = "[seconds>0?num2text(seconds)+"sec":null]"
|
||||
|
||||
if(tmin && tsec) // hack to skip inter-space if either field is blank
|
||||
return "[tmin] [tsec]"
|
||||
else
|
||||
if(!tmin && !tsec) // return '0sec' if 0 time left
|
||||
return "0sec"
|
||||
return "[tmin][tsec]"
|
||||
|
||||
/datum/vote/proc/getvotes()
|
||||
|
||||
var/list/L = list()
|
||||
|
||||
|
||||
for(var/mob/M in world)
|
||||
if(M.client && M.client.inactivity < 1200) // clients inactive for 2 minutes don't count
|
||||
L[M.client.vote] += 1
|
||||
|
||||
|
||||
return L
|
||||
|
||||
|
||||
/datum/vote/proc/endvote()
|
||||
|
||||
if(!voting) // means that voting was aborted by an admin
|
||||
return
|
||||
|
||||
world << "\red <B>***Voting has closed.</B>"
|
||||
|
||||
if(config.logvote) world.log << "VOTE: Voting closed, result was [winner]"
|
||||
|
||||
voting = 0
|
||||
nextvotetime = world.timeofday + 10*config.votedelay
|
||||
|
||||
for(var/mob/M in world) // clear vote window from all clients
|
||||
if(M.client)
|
||||
M << browse(null, "window=vote")
|
||||
M.client.showvote = 0
|
||||
|
||||
calcwin()
|
||||
|
||||
if(mode)
|
||||
var/wintext = upperfirst(winner)
|
||||
if(winner=="default")
|
||||
world << "Result is \red No change."
|
||||
return
|
||||
|
||||
// otherwise change mode
|
||||
|
||||
|
||||
world << "Result is change to \red [wintext]"
|
||||
|
||||
|
||||
// write resulting mode to savefile
|
||||
|
||||
var/F = file(persistent_file)
|
||||
fdel(F)
|
||||
F << winner
|
||||
|
||||
if(ticker)
|
||||
world <<"\red <B>World will reboot in 10 seconds</B>"
|
||||
|
||||
sleep(100)
|
||||
if(config.loggame) world.log << "GAME: Rebooting due to mode vote "
|
||||
world.Reboot()
|
||||
else
|
||||
master_mode = winner
|
||||
|
||||
else
|
||||
|
||||
if(winner=="default")
|
||||
world << "Result is \red No restart."
|
||||
return
|
||||
|
||||
world << "Result is \red Restart round."
|
||||
|
||||
world <<"\red <B>World will reboot in 5 seconds</B>"
|
||||
|
||||
sleep(50)
|
||||
if(config.loggame) world.log << "GAME: Rebooting due to restart vote"
|
||||
world.Reboot()
|
||||
return
|
||||
|
||||
|
||||
/datum/vote/proc/calcwin()
|
||||
|
||||
var/list/votes = getvotes()
|
||||
|
||||
if(vote.mode)
|
||||
var/best = -1
|
||||
|
||||
for(var/v in votes)
|
||||
if(v=="none")
|
||||
continue
|
||||
if(best < votes[v])
|
||||
best = votes[v]
|
||||
|
||||
|
||||
var/list/winners = list()
|
||||
|
||||
for(var/v in votes)
|
||||
if(votes[v] == best)
|
||||
winners += v
|
||||
|
||||
var/ret = ""
|
||||
|
||||
|
||||
for(var/w in winners)
|
||||
if(lentext(ret) > 0)
|
||||
ret += "/"
|
||||
if(w=="default")
|
||||
winners = list("default")
|
||||
ret = "No change"
|
||||
break
|
||||
else
|
||||
ret += upperfirst(w)
|
||||
|
||||
|
||||
|
||||
if(winners.len != 1)
|
||||
ret = "Tie: " + ret
|
||||
|
||||
|
||||
if(winners.len == 0)
|
||||
vote.winner = "default"
|
||||
ret = "No change"
|
||||
else
|
||||
vote.winner = pick(winners)
|
||||
|
||||
return ret
|
||||
else
|
||||
|
||||
if(votes["default"] < votes["restart"])
|
||||
|
||||
vote.winner = "restart"
|
||||
return "Restart"
|
||||
else
|
||||
vote.winner = "default"
|
||||
return "No restart"
|
||||
|
||||
|
||||
/mob/verb/vote()
|
||||
|
||||
|
||||
usr.client.showvote = 1
|
||||
|
||||
|
||||
var/text = "<HTML><HEAD><TITLE>Voting</TITLE></HEAD><BODY scroll=no>"
|
||||
|
||||
var/footer = "<HR><A href='?src=\ref[vote];voter=\ref[src];vclose=1'>Close</A></BODY></HTML>"
|
||||
|
||||
|
||||
if(config.votenodead && usr.stat == 2)
|
||||
text += "Voting while dead has been disallowed."
|
||||
text += footer
|
||||
usr << browse(text, "window=vote")
|
||||
usr.client.showvote = 0
|
||||
usr.client.vote = "none"
|
||||
return
|
||||
|
||||
if(vote.voting)
|
||||
// vote in progress, do the current
|
||||
|
||||
text += "Vote to [vote.mode?"change mode":"restart round"] in progress.<BR>"
|
||||
text += "[vote.endwait()] until voting is closed.<BR>"
|
||||
|
||||
var/list/votes = vote.getvotes()
|
||||
|
||||
if(vote.mode) // true if changing mode
|
||||
|
||||
text += "Current game mode is: <B>[master_mode]</B>.<BR>Select the mode to change to:<UL>"
|
||||
|
||||
for(var/md in vote.vmodes)
|
||||
var/disp = upperfirst(md)
|
||||
if(md=="default")
|
||||
disp = "No change"
|
||||
|
||||
//world << "[md]|[disp]|[src.client.vote]|[votes[md]]"
|
||||
|
||||
if(src.client.vote == md)
|
||||
text += "<LI><B>[disp]</B>"
|
||||
else
|
||||
text += "<LI><A href='?src=\ref[vote];voter=\ref[src];vote=[md]'>[disp]</A>"
|
||||
|
||||
text += "[votes[md]>0?" - [votes[md]] vote\s":null]<BR>"
|
||||
|
||||
text += "</UL>"
|
||||
|
||||
text +="<p>Current winner: <B>[vote.calcwin()]</B><BR>"
|
||||
|
||||
text += footer
|
||||
|
||||
usr << browse(text, "window=vote")
|
||||
|
||||
else // voting to restart
|
||||
|
||||
text += "Restart the world?<BR><UL>"
|
||||
|
||||
var/list/VL = list("default","restart")
|
||||
|
||||
for(var/md in VL)
|
||||
var/disp = (md=="default"? "No":"Yes")
|
||||
|
||||
if(src.client.vote == md)
|
||||
text += "<LI><B>[disp]</B>"
|
||||
else
|
||||
text += "<LI><A href='?src=\ref[vote];voter=\ref[src];vote=[md]'>[disp]</A>"
|
||||
|
||||
text += "[votes[md]>0?" - [votes[md]] vote\s":null]<BR>"
|
||||
|
||||
text += "</UL>"
|
||||
|
||||
text +="<p>Current winner: <B>[vote.calcwin()]</B><BR>"
|
||||
|
||||
text += footer
|
||||
|
||||
usr << browse(text, "window=vote")
|
||||
|
||||
|
||||
else //no vote in progress
|
||||
|
||||
|
||||
if(!config.allowvoterestart && !config.allowvotemode)
|
||||
text += "<P>Player voting is disabled.</BODY></HTML>"
|
||||
|
||||
usr << browse(text, "window=vote")
|
||||
usr.client.showvote = 0
|
||||
return
|
||||
|
||||
if(!vote.canvote()) // not time to vote yet
|
||||
if(config.allowvoterestart) text+="Voting to restart is enabled.<BR>"
|
||||
if(config.allowvotemode) text+="Voting to change mode is enabled.<BR>"
|
||||
|
||||
text+="<BR><P>Next vote can begin in [vote.nextwait()]."
|
||||
text+=footer
|
||||
|
||||
usr << browse(text, "window=vote")
|
||||
|
||||
else // voting can begin
|
||||
if(config.allowvoterestart)
|
||||
text += "<A href='?src=\ref[vote];voter=\ref[src];vmode=1'>Begin restart vote.</A><BR>"
|
||||
if(config.allowvotemode)
|
||||
text += "<A href='?src=\ref[vote];voter=\ref[src];vmode=2'>Begin change mode vote.</A><BR>"
|
||||
|
||||
text += footer
|
||||
usr << browse(text, "window=vote")
|
||||
|
||||
spawn(20)
|
||||
if(usr.client && usr.client.showvote)
|
||||
usr.vote()
|
||||
else
|
||||
usr << browse(null, "window=vote")
|
||||
|
||||
return
|
||||
|
||||
|
||||
/datum/vote/Topic(href, href_list)
|
||||
..()
|
||||
|
||||
var/mob/M = locate(href_list["voter"]) // mob of player that clicked link
|
||||
|
||||
if(href_list["vclose"])
|
||||
|
||||
if(M)
|
||||
M << browse(null, "window=vote")
|
||||
M.client.showvote = 0
|
||||
return
|
||||
|
||||
if(href_list["vmode"])
|
||||
if(vote.voting)
|
||||
return
|
||||
|
||||
if(!vote.canvote() ) // double check even though this shouldn't happen
|
||||
return
|
||||
|
||||
vote.mode = text2num(href_list["vmode"])-1 // hack to yield 0=restart, 1=changemode
|
||||
vote.voting = 1 // now voting
|
||||
vote.votetime = world.timeofday + config.voteperiod*10 // when the vote will end
|
||||
|
||||
spawn(config.voteperiod*10)
|
||||
vote.endvote()
|
||||
|
||||
world << "\red<B>*** A vote to [vote.mode?"change game mode":"restart"] has been initiated by [M.key].</B>"
|
||||
world << "\red You have [vote.timetext(config.voteperiod)] to vote."
|
||||
|
||||
if(config.logvote) world.log << "VOTE: Voting to [vote.mode?"change mode":"restart round"] started by [M.name]/[M.key]"
|
||||
|
||||
for(var/mob/CM in world)
|
||||
if(CM.client)
|
||||
if(config.votenodefault || (config.votenodead && CM.stat == 2))
|
||||
CM.client.vote = "none"
|
||||
else
|
||||
CM.client.vote = "default"
|
||||
|
||||
if(M) M.vote()
|
||||
return
|
||||
|
||||
|
||||
return
|
||||
|
||||
if(href_list["vote"] && vote.voting)
|
||||
if(M)
|
||||
M.client.vote = href_list["vote"]
|
||||
|
||||
//world << "Setting client [M.key]'s vote to: [href_list["vote"]]."
|
||||
|
||||
M.vote()
|
||||
return
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user