Added new trunk.

This commit is contained in:
stephen001
2008-05-23 17:36:21 +00:00
parent 7311e37c43
commit 5968a3e6bb
172 changed files with 4 additions and 9 deletions
+2765
View File
File diff suppressed because one or more lines are too long
+23
View File
@@ -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
+440
View File
@@ -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
+254
View File
@@ -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
+656
View File
@@ -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
+82
View File
@@ -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
+156
View File
@@ -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)
+133
View File
@@ -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
+287
View File
@@ -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
+47
View File
@@ -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
+114
View File
@@ -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
+133
View File
@@ -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)
+159
View File
@@ -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
+399
View File
@@ -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)
+226
View File
@@ -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)
+425
View File
@@ -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)
+99
View File
@@ -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( )
View File
+146
View File
@@ -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()
+209
View File
@@ -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
+57
View File
@@ -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
..()
+120
View File
@@ -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
+90
View File
@@ -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
+136
View File
@@ -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
+152
View File
@@ -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
+704
View File
@@ -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
+258
View File
@@ -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()
+157
View File
@@ -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
+338
View File
@@ -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
+135
View File
@@ -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
+288
View File
@@ -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
+45
View File
@@ -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"
+240
View File
@@ -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
+169
View File
@@ -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
+170
View File
@@ -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
+145
View File
@@ -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: []&deg;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
+69
View File
@@ -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
+173
View File
@@ -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
+49
View File
@@ -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
+100
View File
@@ -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()
+217
View File
@@ -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
+137
View File
@@ -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)
+421
View File
@@ -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 (&deg;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 (&deg;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
*/
+124
View File
@@ -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
+61
View File
@@ -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"
+188
View File
@@ -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
+390
View File
@@ -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
+55
View File
@@ -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)]&deg;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
+68
View File
@@ -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
+32
View File
@@ -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
+103
View File
@@ -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)
+113
View File
@@ -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)
+94
View File
@@ -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()
+148
View File
@@ -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)
+88
View File
@@ -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
*/
+280
View File
@@ -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)
+183
View File
@@ -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)
+391
View File
@@ -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
+201
View File
@@ -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)
+53
View File
@@ -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"
+198
View File
@@ -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)
+160
View File
@@ -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
+41
View File
@@ -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"
+320
View File
@@ -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)
+185
View File
@@ -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
+95
View File
@@ -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)
+23
View File
@@ -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
+140
View File
@@ -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
View File
@@ -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)]"
+194
View File
@@ -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)
+202
View File
@@ -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
View File
@@ -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
View File
@@ -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
+1564
View File
File diff suppressed because it is too large Load Diff
+2266
View File
File diff suppressed because it is too large Load Diff
+801
View File
@@ -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
+193
View File
@@ -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
+225
View File
@@ -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
+36
View File
@@ -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
+91
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+984
View File
@@ -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
View File
@@ -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
View File
@@ -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
+140
View File
@@ -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)
+78
View File
@@ -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
+257
View File
@@ -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
+27
View File
@@ -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
View File
File diff suppressed because it is too large Load Diff
+7128
View File
File diff suppressed because it is too large Load Diff
+106
View File
@@ -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."
+416
View File
@@ -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()
+7
View File
@@ -0,0 +1,7 @@
/obj/New()
..()
// mod = new(src) // creates a module datum for this obj of type
+355
View File
@@ -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
View File
@@ -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
View File
@@ -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)
+568
View File
@@ -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
View File
@@ -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
View File
@@ -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