mirror of
https://github.com/CHOMPstation/CHOMPstation.git
synced 2026-08-21 19:16:22 +01:00
Fixes merge conflict
This commit is contained in:
@@ -0,0 +1,289 @@
|
||||
#define ADIABATIC_EXPONENT 0.667 //Actually adiabatic exponent - 1.
|
||||
|
||||
/obj/machinery/atmospherics/pipeturbine
|
||||
name = "turbine"
|
||||
desc = "A gas turbine. Converting pressure into energy since 1884."
|
||||
icon = 'icons/obj/pipeturbine.dmi'
|
||||
icon_state = "turbine"
|
||||
anchored = 0
|
||||
density = 1
|
||||
|
||||
var/efficiency = 0.4
|
||||
var/kin_energy = 0
|
||||
var/datum/gas_mixture/air_in = new
|
||||
var/datum/gas_mixture/air_out = new
|
||||
var/volume_ratio = 0.2
|
||||
var/kin_loss = 0.001
|
||||
|
||||
var/dP = 0
|
||||
|
||||
var/obj/machinery/atmospherics/node1
|
||||
var/obj/machinery/atmospherics/node2
|
||||
|
||||
var/datum/pipe_network/network1
|
||||
var/datum/pipe_network/network2
|
||||
|
||||
New()
|
||||
..()
|
||||
air_in.volume = 200
|
||||
air_out.volume = 800
|
||||
volume_ratio = air_in.volume / (air_in.volume + air_out.volume)
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
initialize_directions = EAST|WEST
|
||||
if(SOUTH)
|
||||
initialize_directions = EAST|WEST
|
||||
if(EAST)
|
||||
initialize_directions = NORTH|SOUTH
|
||||
if(WEST)
|
||||
initialize_directions = NORTH|SOUTH
|
||||
|
||||
Del()
|
||||
loc = null
|
||||
|
||||
if(node1)
|
||||
node1.disconnect(src)
|
||||
del(network1)
|
||||
if(node2)
|
||||
node2.disconnect(src)
|
||||
del(network2)
|
||||
|
||||
node1 = null
|
||||
node2 = null
|
||||
|
||||
..()
|
||||
|
||||
process()
|
||||
..()
|
||||
if(anchored && !(stat&BROKEN))
|
||||
kin_energy *= 1 - kin_loss
|
||||
dP = max(air_in.return_pressure() - air_out.return_pressure(), 0)
|
||||
if(dP > 10)
|
||||
kin_energy += 1/ADIABATIC_EXPONENT * dP * air_in.volume * (1 - volume_ratio**ADIABATIC_EXPONENT) * efficiency
|
||||
air_in.temperature *= volume_ratio**ADIABATIC_EXPONENT
|
||||
|
||||
var/datum/gas_mixture/air_all = new
|
||||
air_all.volume = air_in.volume + air_out.volume
|
||||
air_all.merge(air_in.remove_ratio(1))
|
||||
air_all.merge(air_out.remove_ratio(1))
|
||||
|
||||
air_in.merge(air_all.remove(volume_ratio))
|
||||
air_out.merge(air_all)
|
||||
|
||||
update_icon()
|
||||
|
||||
if (network1)
|
||||
network1.update = 1
|
||||
if (network2)
|
||||
network2.update = 1
|
||||
|
||||
update_icon()
|
||||
overlays.Cut()
|
||||
if (dP > 10)
|
||||
overlays += image('icons/obj/pipeturbine.dmi', "moto-turb")
|
||||
if (kin_energy > 100000)
|
||||
overlays += image('icons/obj/pipeturbine.dmi', "low-turb")
|
||||
if (kin_energy > 500000)
|
||||
overlays += image('icons/obj/pipeturbine.dmi', "med-turb")
|
||||
if (kin_energy > 1000000)
|
||||
overlays += image('icons/obj/pipeturbine.dmi', "hi-turb")
|
||||
|
||||
attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype(W, /obj/item/weapon/wrench))
|
||||
anchored = !anchored
|
||||
user << "\blue You [anchored ? "secure" : "unsecure"] the bolts holding [src] to the floor."
|
||||
|
||||
if(anchored)
|
||||
if(dir & (NORTH|SOUTH))
|
||||
initialize_directions = EAST|WEST
|
||||
else if(dir & (EAST|WEST))
|
||||
initialize_directions = NORTH|SOUTH
|
||||
|
||||
initialize()
|
||||
build_network()
|
||||
if (node1)
|
||||
node1.initialize()
|
||||
node1.build_network()
|
||||
if (node2)
|
||||
node2.initialize()
|
||||
node2.build_network()
|
||||
else
|
||||
if(node1)
|
||||
node1.disconnect(src)
|
||||
del(network1)
|
||||
if(node2)
|
||||
node2.disconnect(src)
|
||||
del(network2)
|
||||
|
||||
node1 = null
|
||||
node2 = null
|
||||
|
||||
else
|
||||
..()
|
||||
|
||||
verb/rotate_clockwise()
|
||||
set category = "Object"
|
||||
set name = "Rotate Circulator (Clockwise)"
|
||||
set src in view(1)
|
||||
|
||||
if (usr.stat || usr.restrained() || anchored)
|
||||
return
|
||||
|
||||
src.dir = turn(src.dir, -90)
|
||||
|
||||
|
||||
verb/rotate_anticlockwise()
|
||||
set category = "Object"
|
||||
set name = "Rotate Circulator (Counterclockwise)"
|
||||
set src in view(1)
|
||||
|
||||
if (usr.stat || usr.restrained() || anchored)
|
||||
return
|
||||
|
||||
src.dir = turn(src.dir, 90)
|
||||
|
||||
//Goddamn copypaste from binary base class because atmospherics machinery API is not damn flexible
|
||||
network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
|
||||
if(reference == node1)
|
||||
network1 = new_network
|
||||
|
||||
else if(reference == node2)
|
||||
network2 = new_network
|
||||
|
||||
if(new_network.normal_members.Find(src))
|
||||
return 0
|
||||
|
||||
new_network.normal_members += src
|
||||
|
||||
return null
|
||||
|
||||
initialize()
|
||||
if(node1 && node2) return
|
||||
|
||||
var/node2_connect = turn(dir, -90)
|
||||
var/node1_connect = turn(dir, 90)
|
||||
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node1_connect))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node1 = target
|
||||
break
|
||||
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node2_connect))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node2 = target
|
||||
break
|
||||
|
||||
build_network()
|
||||
if(!network1 && node1)
|
||||
network1 = new /datum/pipe_network()
|
||||
network1.normal_members += src
|
||||
network1.build_network(node1, src)
|
||||
|
||||
if(!network2 && node2)
|
||||
network2 = new /datum/pipe_network()
|
||||
network2.normal_members += src
|
||||
network2.build_network(node2, src)
|
||||
|
||||
|
||||
return_network(obj/machinery/atmospherics/reference)
|
||||
build_network()
|
||||
|
||||
if(reference==node1)
|
||||
return network1
|
||||
|
||||
if(reference==node2)
|
||||
return network2
|
||||
|
||||
return null
|
||||
|
||||
reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
|
||||
if(network1 == old_network)
|
||||
network1 = new_network
|
||||
if(network2 == old_network)
|
||||
network2 = new_network
|
||||
|
||||
return 1
|
||||
|
||||
return_network_air(datum/pipe_network/reference)
|
||||
var/list/results = list()
|
||||
|
||||
if(network1 == reference)
|
||||
results += air_in
|
||||
if(network2 == reference)
|
||||
results += air_out
|
||||
|
||||
return results
|
||||
|
||||
disconnect(obj/machinery/atmospherics/reference)
|
||||
if(reference==node1)
|
||||
del(network1)
|
||||
node1 = null
|
||||
|
||||
else if(reference==node2)
|
||||
del(network2)
|
||||
node2 = null
|
||||
|
||||
return null
|
||||
|
||||
|
||||
/obj/machinery/power/turbinemotor
|
||||
name = "motor"
|
||||
desc = "Electrogenerator. Converts rotation into power."
|
||||
icon = 'icons/obj/pipeturbine.dmi'
|
||||
icon_state = "motor"
|
||||
anchored = 0
|
||||
density = 1
|
||||
|
||||
var/kin_to_el_ratio = 0.1 //How much kinetic energy will be taken from turbine and converted into electricity
|
||||
var/obj/machinery/atmospherics/pipeturbine/turbine
|
||||
|
||||
New()
|
||||
..()
|
||||
spawn(1)
|
||||
updateConnection()
|
||||
|
||||
proc/updateConnection()
|
||||
turbine = null
|
||||
if(src.loc && anchored)
|
||||
turbine = locate(/obj/machinery/atmospherics/pipeturbine) in get_step(src,dir)
|
||||
if (turbine.stat & (BROKEN) || !turbine.anchored || turn(turbine.dir,180) != dir)
|
||||
turbine = null
|
||||
|
||||
process()
|
||||
updateConnection()
|
||||
if(!turbine || !anchored || stat & (BROKEN))
|
||||
return
|
||||
|
||||
var/power_generated = kin_to_el_ratio * turbine.kin_energy
|
||||
turbine.kin_energy -= power_generated
|
||||
add_avail(power_generated)
|
||||
|
||||
|
||||
attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(istype(W, /obj/item/weapon/wrench))
|
||||
anchored = !anchored
|
||||
turbine = null
|
||||
user << "\blue You [anchored ? "secure" : "unsecure"] the bolts holding [src] to the floor."
|
||||
updateConnection()
|
||||
else
|
||||
..()
|
||||
|
||||
verb/rotate_clock()
|
||||
set category = "Object"
|
||||
set name = "Rotate Motor Clockwise"
|
||||
set src in view(1)
|
||||
|
||||
if (usr.stat || usr.restrained() || anchored)
|
||||
return
|
||||
|
||||
src.dir = turn(src.dir, -90)
|
||||
|
||||
verb/rotate_anticlock()
|
||||
set category = "Object"
|
||||
set name = "Rotate Motor Counterclockwise"
|
||||
set src in view(1)
|
||||
|
||||
if (usr.stat || usr.restrained() || anchored)
|
||||
return
|
||||
|
||||
src.dir = turn(src.dir, 90)
|
||||
@@ -0,0 +1,130 @@
|
||||
//--------------------------------------------
|
||||
// Omni device port types
|
||||
//--------------------------------------------
|
||||
#define ATM_NONE 0
|
||||
#define ATM_INPUT 1
|
||||
#define ATM_OUTPUT 2
|
||||
|
||||
#define ATM_O2 3
|
||||
#define ATM_N2 4
|
||||
#define ATM_CO2 5
|
||||
#define ATM_P 6 //Phoron
|
||||
#define ATM_N2O 7
|
||||
|
||||
//--------------------------------------------
|
||||
// Omni device cached icon list
|
||||
//--------------------------------------------
|
||||
var/global/list/omni_icons[]
|
||||
|
||||
/proc/gen_omni_icons()
|
||||
omni_icons = new()
|
||||
var/icon/omni = new('icons/obj/atmospherics/omni_devices.dmi')
|
||||
|
||||
for(var/state in omni.IconStates())
|
||||
if(!state || findtext(state, "map"))
|
||||
continue
|
||||
|
||||
var/image/I = image('icons/obj/atmospherics/omni_devices.dmi', icon_state = state)
|
||||
|
||||
if(findtext(state, "pipe"))
|
||||
for(var/pipe_color in pipe_colors)
|
||||
I = image('icons/obj/atmospherics/omni_devices.dmi', icon_state = state)
|
||||
I.color = pipe_colors[pipe_color]
|
||||
var/cache_name = state
|
||||
if(I.color)
|
||||
cache_name += "_[pipe_colors[pipe_color]]"
|
||||
omni_icons[cache_name] = I
|
||||
else
|
||||
omni_icons[state] = I
|
||||
|
||||
|
||||
//--------------------------------------------
|
||||
// Omni port datum
|
||||
//
|
||||
// Used by omni devices to manage connections
|
||||
// to other atmospheric objects.
|
||||
//--------------------------------------------
|
||||
/datum/omni_port
|
||||
var/obj/machinery/atmospherics/omni/master
|
||||
var/dir
|
||||
var/update = 1
|
||||
var/mode = 0
|
||||
var/concentration = 0
|
||||
var/con_lock = 0
|
||||
var/transfer_moles = 0
|
||||
var/datum/gas_mixture/air
|
||||
var/obj/machinery/atmospherics/node
|
||||
var/datum/pipe_network/network
|
||||
|
||||
/datum/omni_port/New(var/obj/machinery/atmospherics/omni/M, var/direction = NORTH)
|
||||
..()
|
||||
dir = direction
|
||||
if(istype(M))
|
||||
master = M
|
||||
air = new
|
||||
air.volume = 200
|
||||
|
||||
/datum/omni_port/proc/connect()
|
||||
if(node)
|
||||
return
|
||||
master.initialize()
|
||||
master.build_network()
|
||||
if(node)
|
||||
node.initialize()
|
||||
node.build_network()
|
||||
|
||||
/datum/omni_port/proc/disconnect()
|
||||
if(node)
|
||||
node.disconnect(master)
|
||||
master.disconnect(node)
|
||||
|
||||
|
||||
//--------------------------------------------
|
||||
// Need to find somewhere else for these
|
||||
//--------------------------------------------
|
||||
|
||||
#define PIPE_COLOR_RED "#ff0000"
|
||||
#define PIPE_COLOR_BLUE "#0000ff"
|
||||
#define PIPE_COLOR_CYAN "#00ffff"
|
||||
#define PIPE_COLOR_GREEN "#00ff00"
|
||||
#define PIPE_COLOR_YELLOW "#ffcc00"
|
||||
#define PIPE_COLOR_PURPLE "#5c1ec0"
|
||||
|
||||
var/global/list/pipe_colors = list("grey" = null, "red" = PIPE_COLOR_RED, "blue" = PIPE_COLOR_BLUE, "cyan" = PIPE_COLOR_CYAN, "green" = PIPE_COLOR_GREEN, "yellow" = PIPE_COLOR_YELLOW, "purple" = PIPE_COLOR_PURPLE)
|
||||
|
||||
|
||||
//returns a text string based on the direction flag input
|
||||
// if capitalize is true, it will return the string capitalized
|
||||
// otherwise it will return the direction string in lower case
|
||||
/proc/dir_name(var/dir, var/capitalize = 0)
|
||||
var/string = null
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
string = "North"
|
||||
if(SOUTH)
|
||||
string = "South"
|
||||
if(EAST)
|
||||
string = "East"
|
||||
if(WEST)
|
||||
string = "West"
|
||||
|
||||
if(!capitalize && string)
|
||||
string = lowertext(string)
|
||||
|
||||
return string
|
||||
|
||||
//returns a direction flag based on the string passed to it
|
||||
// case insensitive
|
||||
/proc/dir_flag(var/dir)
|
||||
dir = lowertext(dir)
|
||||
switch(dir)
|
||||
if("north")
|
||||
return NORTH
|
||||
if("south")
|
||||
return SOUTH
|
||||
if("east")
|
||||
return EAST
|
||||
if("west")
|
||||
return WEST
|
||||
else
|
||||
return 0
|
||||
@@ -0,0 +1,282 @@
|
||||
//--------------------------------------------
|
||||
// Gas filter - omni variant
|
||||
//--------------------------------------------
|
||||
/obj/machinery/atmospherics/omni/filter
|
||||
name = "omni gas filter"
|
||||
icon_state = "map_filter"
|
||||
|
||||
var/list/filters = new()
|
||||
var/datum/omni_port/input
|
||||
var/datum/omni_port/output
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/Del()
|
||||
input = null
|
||||
output = null
|
||||
filters.Cut()
|
||||
..()
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/sort_ports()
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(P.update)
|
||||
if(output == P)
|
||||
output = null
|
||||
if(input == P)
|
||||
input = null
|
||||
if(filters.Find(P))
|
||||
filters -= P
|
||||
|
||||
P.air.volume = 200
|
||||
switch(P.mode)
|
||||
if(ATM_INPUT)
|
||||
input = P
|
||||
if(ATM_OUTPUT)
|
||||
output = P
|
||||
if(ATM_O2 to ATM_N2O)
|
||||
filters += P
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/error_check()
|
||||
if(!input || !output || !filters)
|
||||
return 1
|
||||
if(filters.len < 1 || filters.len > 2) //requires 1 or 2 filters ~otherwise why are you using a filter?
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/process()
|
||||
..()
|
||||
if(!on)
|
||||
return 0
|
||||
|
||||
if(!input || !output)
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/output_air = output.air //BYOND doesn't like referencing "output.air.return_pressure()" so we need to make a direct reference
|
||||
var/datum/gas_mixture/input_air = input.air // it's completely happy with them if they're in a loop though i.e. "P.air.return_pressure()"... *shrug*
|
||||
|
||||
var/output_pressure = output_air.return_pressure()
|
||||
|
||||
if(output_pressure >= target_pressure)
|
||||
return
|
||||
for(var/datum/omni_port/P in filters)
|
||||
if(P.air.return_pressure() >= target_pressure)
|
||||
return
|
||||
|
||||
var/pressure_delta = target_pressure - output_pressure
|
||||
|
||||
if(input_air.return_temperature() > 0)
|
||||
input.transfer_moles = pressure_delta * output_air.volume / (input_air.return_temperature() * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
if(input.transfer_moles > 0)
|
||||
var/datum/gas_mixture/removed = input_air.remove(input.transfer_moles)
|
||||
|
||||
if(!removed)
|
||||
return
|
||||
|
||||
for(var/datum/omni_port/P in filters)
|
||||
var/datum/gas_mixture/filtered_out = new
|
||||
filtered_out.temperature = removed.return_temperature()
|
||||
|
||||
switch(P.mode)
|
||||
if(ATM_O2)
|
||||
filtered_out.oxygen = removed.oxygen
|
||||
removed.oxygen = 0
|
||||
if(ATM_N2)
|
||||
filtered_out.nitrogen = removed.nitrogen
|
||||
removed.nitrogen = 0
|
||||
if(ATM_CO2)
|
||||
filtered_out.carbon_dioxide = removed.carbon_dioxide
|
||||
removed.carbon_dioxide = 0
|
||||
if(ATM_P)
|
||||
filtered_out.phoron = removed.phoron
|
||||
removed.phoron = 0
|
||||
if(ATM_N2O)
|
||||
if(removed.trace_gases.len>0)
|
||||
for(var/datum/gas/sleeping_agent/trace_gas in removed.trace_gases)
|
||||
if(istype(trace_gas))
|
||||
removed.trace_gases -= trace_gas
|
||||
filtered_out.trace_gases += trace_gas
|
||||
else
|
||||
filtered_out = null
|
||||
|
||||
P.air.merge(filtered_out)
|
||||
if(P.network)
|
||||
P.network.update = 1
|
||||
|
||||
output_air.merge(removed)
|
||||
if(output.network)
|
||||
output.network.update = 1
|
||||
|
||||
input.transfer_moles = 0
|
||||
if(input.network)
|
||||
input.network.update = 1
|
||||
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null)
|
||||
usr.set_machine(src)
|
||||
|
||||
var/list/data = new()
|
||||
|
||||
data = build_uidata()
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data)
|
||||
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "omni_filter.tmpl", "Omni Filter Control", 330, 330)
|
||||
ui.set_initial_data(data)
|
||||
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/proc/build_uidata()
|
||||
var/list/data = new()
|
||||
|
||||
data["power"] = on
|
||||
data["config"] = configuring
|
||||
|
||||
var/portData[0]
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(!configuring && P.mode == 0)
|
||||
continue
|
||||
|
||||
var/input = 0
|
||||
var/output = 0
|
||||
var/filter = 1
|
||||
var/f_type = null
|
||||
switch(P.mode)
|
||||
if(ATM_INPUT)
|
||||
input = 1
|
||||
filter = 0
|
||||
if(ATM_OUTPUT)
|
||||
output = 1
|
||||
filter = 0
|
||||
if(ATM_O2 to ATM_N2O)
|
||||
f_type = mode_send_switch(P.mode)
|
||||
|
||||
portData[++portData.len] = list("dir" = dir_name(P.dir, capitalize = 1), \
|
||||
"input" = input, \
|
||||
"output" = output, \
|
||||
"filter" = filter, \
|
||||
"f_type" = f_type)
|
||||
|
||||
if(portData.len)
|
||||
data["ports"] = portData
|
||||
if(output)
|
||||
data["pressure"] = target_pressure
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/proc/mode_send_switch(var/mode = ATM_NONE)
|
||||
switch(mode)
|
||||
if(ATM_O2)
|
||||
return "Oxygen"
|
||||
if(ATM_N2)
|
||||
return "Nitrogen"
|
||||
if(ATM_CO2)
|
||||
return "Carbon Dioxide"
|
||||
if(ATM_P)
|
||||
return "Phoron" //*cough* Plasma *cough*
|
||||
if(ATM_N2O)
|
||||
return "Nitrous Oxide"
|
||||
else
|
||||
return null
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/Topic(href, href_list)
|
||||
if(..()) return
|
||||
switch(href_list["command"])
|
||||
if("power")
|
||||
if(!configuring)
|
||||
on = !on
|
||||
else
|
||||
on = 0
|
||||
if("configure")
|
||||
configuring = !configuring
|
||||
if(configuring)
|
||||
on = 0
|
||||
|
||||
//only allows config changes when in configuring mode ~otherwise you'll get weird pressure stuff going on
|
||||
if(configuring && !on)
|
||||
switch(href_list["command"])
|
||||
if("set_pressure")
|
||||
var/new_pressure = input(usr,"Enter new output pressure (0-4500kPa)","Pressure control",target_pressure) as num
|
||||
target_pressure = between(0, new_pressure, 4500)
|
||||
if("switch_mode")
|
||||
switch_mode(dir_flag(href_list["dir"]), mode_return_switch(href_list["mode"]))
|
||||
if("switch_filter")
|
||||
var/new_filter = input(usr,"Select filter mode:","Change filter",href_list["mode"]) in list("None", "Oxygen", "Nitrogen", "Carbon Dioxide", "Phoron", "Nitrous Oxide")
|
||||
switch_filter(dir_flag(href_list["dir"]), mode_return_switch(new_filter))
|
||||
|
||||
update_icon()
|
||||
nanomanager.update_uis(src)
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/proc/mode_return_switch(var/mode)
|
||||
switch(mode)
|
||||
if("Oxygen")
|
||||
return ATM_O2
|
||||
if("Nitrogen")
|
||||
return ATM_N2
|
||||
if("Carbon Dioxide")
|
||||
return ATM_CO2
|
||||
if("Phoron")
|
||||
return ATM_P
|
||||
if("Nitrous Oxide")
|
||||
return ATM_N2O
|
||||
if("in")
|
||||
return ATM_INPUT
|
||||
if("out")
|
||||
return ATM_OUTPUT
|
||||
if("None")
|
||||
return ATM_NONE
|
||||
else
|
||||
return null
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/proc/switch_filter(var/dir, var/mode)
|
||||
//check they aren't trying to disable the input or output ~this can only happen if they hack the cached tmpl file
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(P.dir == dir)
|
||||
if(P.mode == ATM_INPUT || P.mode == ATM_OUTPUT)
|
||||
return
|
||||
|
||||
switch_mode(dir, mode)
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/proc/switch_mode(var/port, var/mode)
|
||||
if(mode == null || !port)
|
||||
return
|
||||
var/datum/omni_port/target_port = null
|
||||
var/list/other_ports = new()
|
||||
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(P.dir == port)
|
||||
target_port = P
|
||||
else
|
||||
other_ports += P
|
||||
|
||||
var/previous_mode = null
|
||||
if(target_port)
|
||||
previous_mode = target_port.mode
|
||||
target_port.mode = mode
|
||||
if(target_port.mode != previous_mode)
|
||||
handle_port_change(target_port)
|
||||
else
|
||||
return
|
||||
else
|
||||
return
|
||||
|
||||
for(var/datum/omni_port/P in other_ports)
|
||||
if(P.mode == mode)
|
||||
var/old_mode = P.mode
|
||||
P.mode = previous_mode
|
||||
if(P.mode != old_mode)
|
||||
handle_port_change(P)
|
||||
|
||||
update_ports()
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/proc/handle_port_change(var/datum/omni_port/P)
|
||||
switch(P.mode)
|
||||
if(ATM_NONE)
|
||||
initialize_directions &= ~P.dir
|
||||
P.disconnect()
|
||||
else
|
||||
initialize_directions |= P.dir
|
||||
P.connect()
|
||||
P.update = 1
|
||||
@@ -0,0 +1,301 @@
|
||||
//--------------------------------------------
|
||||
// Gas mixer - omni variant
|
||||
//--------------------------------------------
|
||||
/obj/machinery/atmospherics/omni/mixer
|
||||
name = "omni gas mixer"
|
||||
icon_state = "map_mixer"
|
||||
|
||||
var/list/inputs = new()
|
||||
var/datum/omni_port/output
|
||||
|
||||
//setup tags for initial concentration values (must be decimal)
|
||||
var/tag_north_con
|
||||
var/tag_south_con
|
||||
var/tag_east_con
|
||||
var/tag_west_con
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/New()
|
||||
..()
|
||||
if(mapper_set())
|
||||
var/con = 0
|
||||
for(var/datum/omni_port/P in ports)
|
||||
switch(P.dir)
|
||||
if(NORTH)
|
||||
if(tag_north_con && tag_north == 1)
|
||||
P.concentration = tag_north_con
|
||||
con += max(0, tag_north_con)
|
||||
if(SOUTH)
|
||||
if(tag_south_con && tag_south == 1)
|
||||
P.concentration = tag_south_con
|
||||
con += max(0, tag_south_con)
|
||||
if(EAST)
|
||||
if(tag_east_con && tag_east == 1)
|
||||
P.concentration = tag_east_con
|
||||
con += max(0, tag_east_con)
|
||||
if(WEST)
|
||||
if(tag_west_con && tag_west == 1)
|
||||
P.concentration = tag_west_con
|
||||
con += max(0, tag_west_con)
|
||||
|
||||
//mappers who are bad at maths will be punished (total concentration must be 100%)
|
||||
if(con != 1)
|
||||
tag_north_con = null
|
||||
tag_south_con = null
|
||||
tag_east_con = null
|
||||
tag_west_con = null
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/Del()
|
||||
inputs.Cut()
|
||||
output = null
|
||||
..()
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/sort_ports()
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(P.update)
|
||||
if(output == P)
|
||||
output = null
|
||||
if(inputs.Find(P))
|
||||
inputs -= P
|
||||
|
||||
P.air.volume = 200
|
||||
switch(P.mode)
|
||||
if(ATM_INPUT)
|
||||
inputs += P
|
||||
if(ATM_OUTPUT)
|
||||
output = P
|
||||
|
||||
if(!mapper_set())
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
P.concentration = 1 / max(1, inputs.len)
|
||||
|
||||
if(output)
|
||||
output.air.volume *= 0.75 * inputs.len
|
||||
output.concentration = 1
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/proc/mapper_set()
|
||||
return (tag_north_con || tag_south_con || tag_east_con || tag_west_con)
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/error_check()
|
||||
if(!output || !inputs)
|
||||
return 1
|
||||
if(inputs.len < 2 || inputs.len > 3) //requires 2 or 3 inputs ~otherwise why are you using a mixer?
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/process()
|
||||
..()
|
||||
if(!on)
|
||||
return 0
|
||||
|
||||
var/datum/gas_mixture/output_air = output.air
|
||||
var/output_pressure = output_air.return_pressure()
|
||||
|
||||
|
||||
if(output_pressure >= target_pressure * 0.999)
|
||||
//No need to mix if target is already full! - 0.1% margin of error so we minimize processing minor gas volumes
|
||||
return 1
|
||||
|
||||
//Calculate necessary moles to transfer using PV=nRT
|
||||
|
||||
var/pressure_delta = target_pressure - output_pressure
|
||||
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
if(P.air.return_temperature() > 0)
|
||||
P.transfer_moles = (P.concentration * pressure_delta) * output_air.return_volume() / (P.air.return_temperature() * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
var/ratio_check = null
|
||||
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
if(!P.transfer_moles)
|
||||
return
|
||||
if(P.air.total_moles() < P.transfer_moles)
|
||||
ratio_check = 1
|
||||
continue
|
||||
|
||||
if(ratio_check)
|
||||
var/list/ratio_list = new()
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
ratio_list.Add(P.air.total_moles() / P.transfer_moles)
|
||||
|
||||
var/ratio = min(ratio_list)
|
||||
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
P.transfer_moles *= ratio
|
||||
|
||||
|
||||
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
if(P.transfer_moles > 0)
|
||||
output_air.merge(P.air.remove(P.transfer_moles))
|
||||
if(P.network)
|
||||
P.network.update = 1
|
||||
P.transfer_moles = 0
|
||||
|
||||
if(output.network)
|
||||
output.network.update = 1
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null)
|
||||
usr.set_machine(src)
|
||||
|
||||
var/list/data = new()
|
||||
|
||||
data = build_uidata()
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data)
|
||||
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "omni_mixer.tmpl", "Omni Mixer Control", 360, 330)
|
||||
ui.set_initial_data(data)
|
||||
|
||||
ui.open()
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/proc/build_uidata()
|
||||
var/list/data = new()
|
||||
|
||||
data["power"] = on
|
||||
data["config"] = configuring
|
||||
|
||||
var/portData[0]
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(!configuring && P.mode == 0)
|
||||
continue
|
||||
|
||||
var/input = 0
|
||||
var/output = 0
|
||||
switch(P.mode)
|
||||
if(ATM_INPUT)
|
||||
input = 1
|
||||
if(ATM_OUTPUT)
|
||||
output = 1
|
||||
|
||||
portData[++portData.len] = list("dir" = dir_name(P.dir, capitalize = 1), \
|
||||
"concentration" = P.concentration, \
|
||||
"input" = input, \
|
||||
"output" = output, \
|
||||
"con_lock" = P.con_lock)
|
||||
|
||||
if(portData.len)
|
||||
data["ports"] = portData
|
||||
if(output)
|
||||
data["pressure"] = target_pressure
|
||||
|
||||
return data
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/Topic(href, href_list)
|
||||
if(..()) return
|
||||
|
||||
switch(href_list["command"])
|
||||
if("power")
|
||||
if(!configuring)
|
||||
on = !on
|
||||
else
|
||||
on = 0
|
||||
if("configure")
|
||||
configuring = !configuring
|
||||
if(configuring)
|
||||
on = 0
|
||||
|
||||
//only allows config changes when in configuring mode ~otherwise you'll get weird pressure stuff going on
|
||||
if(configuring && !on)
|
||||
switch(href_list["command"])
|
||||
if("set_pressure")
|
||||
var/new_pressure = input(usr,"Enter new output pressure (0-4500kPa)","Pressure control",target_pressure) as num
|
||||
target_pressure = between(0, new_pressure, 4500)
|
||||
if("switch_mode")
|
||||
switch_mode(dir_flag(href_list["dir"]), href_list["mode"])
|
||||
if("switch_con")
|
||||
change_concentration(dir_flag(href_list["dir"]))
|
||||
if("switch_conlock")
|
||||
con_lock(dir_flag(href_list["dir"]))
|
||||
|
||||
update_icon()
|
||||
nanomanager.update_uis(src)
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/proc/switch_mode(var/port = NORTH, var/mode = ATM_NONE)
|
||||
if(mode != ATM_INPUT && mode != ATM_OUTPUT)
|
||||
switch(mode)
|
||||
if("in")
|
||||
mode = ATM_INPUT
|
||||
if("out")
|
||||
mode = ATM_OUTPUT
|
||||
else
|
||||
mode = ATM_NONE
|
||||
|
||||
for(var/datum/omni_port/P in ports)
|
||||
var/old_mode = P.mode
|
||||
if(P.dir == port)
|
||||
switch(mode)
|
||||
if(ATM_INPUT)
|
||||
if(P.mode == ATM_OUTPUT)
|
||||
return
|
||||
P.mode = mode
|
||||
if(ATM_OUTPUT)
|
||||
P.mode = mode
|
||||
if(ATM_NONE)
|
||||
if(P.mode == ATM_OUTPUT)
|
||||
return
|
||||
if(P.mode == ATM_INPUT && inputs.len > 2)
|
||||
P.mode = mode
|
||||
else if(P.mode == ATM_OUTPUT && mode == ATM_OUTPUT)
|
||||
P.mode = ATM_INPUT
|
||||
if(P.mode != old_mode)
|
||||
switch(P.mode)
|
||||
if(ATM_NONE)
|
||||
initialize_directions &= ~P.dir
|
||||
P.disconnect()
|
||||
else
|
||||
initialize_directions |= P.dir
|
||||
P.connect()
|
||||
P.update = 1
|
||||
|
||||
update_ports()
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/proc/change_concentration(var/port = NORTH)
|
||||
tag_north_con = null
|
||||
tag_south_con = null
|
||||
tag_east_con = null
|
||||
tag_west_con = null
|
||||
|
||||
var/old_con = 0
|
||||
var/non_locked = 0
|
||||
var/remain_con = 1
|
||||
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
if(P.dir == port)
|
||||
old_con = P.concentration
|
||||
else if(!P.con_lock)
|
||||
non_locked++
|
||||
else
|
||||
remain_con -= P.concentration
|
||||
|
||||
//return if no adjustable ports
|
||||
if(non_locked < 1)
|
||||
return
|
||||
|
||||
var/new_con = (input(usr,"Enter a new concentration (0-[round(remain_con * 100, 0.5)])%","Concentration control", min(remain_con, old_con)*100) as num) / 100
|
||||
|
||||
//cap it between 0 and the max remaining concentration
|
||||
new_con = between(0, new_con, remain_con)
|
||||
|
||||
//new_con = min(remain_con, new_con)
|
||||
|
||||
//clamp remaining concentration so we don't go into negatives
|
||||
remain_con = max(0, remain_con - new_con)
|
||||
|
||||
//distribute remaining concentration between unlocked ports evenly
|
||||
remain_con /= max(1, non_locked)
|
||||
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
if(P.dir == port)
|
||||
P.concentration = new_con
|
||||
else if(!P.con_lock)
|
||||
P.concentration = remain_con
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/proc/con_lock(var/port = NORTH)
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
if(P.dir == port)
|
||||
P.con_lock = !P.con_lock
|
||||
@@ -0,0 +1,278 @@
|
||||
//--------------------------------------------
|
||||
// Base omni device
|
||||
//--------------------------------------------
|
||||
/obj/machinery/atmospherics/omni
|
||||
name = "omni device"
|
||||
icon = 'icons/obj/atmospherics/omni_devices.dmi'
|
||||
icon_state = "base"
|
||||
use_power = 1
|
||||
initialize_directions = 0
|
||||
|
||||
var/on = 0
|
||||
var/configuring = 0
|
||||
var/target_pressure = ONE_ATMOSPHERE
|
||||
|
||||
var/tag_north = ATM_NONE
|
||||
var/tag_south = ATM_NONE
|
||||
var/tag_east = ATM_NONE
|
||||
var/tag_west = ATM_NONE
|
||||
|
||||
var/overlays_on[5]
|
||||
var/overlays_off[5]
|
||||
var/overlays_error[2]
|
||||
var/underlays_current[4]
|
||||
|
||||
var/list/ports = new()
|
||||
|
||||
/obj/machinery/atmospherics/omni/New()
|
||||
..()
|
||||
icon_state = "base"
|
||||
|
||||
ports = new()
|
||||
for(var/d in cardinal)
|
||||
var/datum/omni_port/new_port = new(src, d)
|
||||
switch(d)
|
||||
if(NORTH)
|
||||
new_port.mode = tag_north
|
||||
if(SOUTH)
|
||||
new_port.mode = tag_south
|
||||
if(EAST)
|
||||
new_port.mode = tag_east
|
||||
if(WEST)
|
||||
new_port.mode = tag_west
|
||||
if(new_port.mode > 0)
|
||||
initialize_directions |= d
|
||||
ports += new_port
|
||||
|
||||
build_icons()
|
||||
|
||||
/obj/machinery/atmospherics/omni/update_icon()
|
||||
if(stat & NOPOWER)
|
||||
overlays = overlays_off
|
||||
on = 0
|
||||
else if(error_check())
|
||||
overlays = overlays_error
|
||||
on = 0
|
||||
else
|
||||
overlays = on ? (overlays_on) : (overlays_off)
|
||||
|
||||
underlays = underlays_current
|
||||
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/omni/proc/error_check()
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/omni/power_change()
|
||||
var/old_stat = stat
|
||||
..()
|
||||
if(old_stat != stat)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/omni/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if(istype(W, /obj/item/device/pipe_painter)) //for updating the color of connected pipe ends
|
||||
for(var/datum/omni_port/P in ports)
|
||||
P.update = 1
|
||||
update_ports()
|
||||
return
|
||||
|
||||
if(!istype(W, /obj/item/weapon/wrench))
|
||||
return ..()
|
||||
|
||||
var/int_pressure = 0
|
||||
for(var/datum/omni_port/P in ports)
|
||||
int_pressure += P.air.return_pressure()
|
||||
var/datum/gas_mixture/env_air = loc.return_air()
|
||||
if ((int_pressure - env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
|
||||
user << "<span class='warning'>You cannot unwrench [src], it is too exerted due to internal pressure.</span>"
|
||||
add_fingerprint(user)
|
||||
return 1
|
||||
user << "\blue You begin to unfasten \the [src]..."
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
if(do_after(user, 40))
|
||||
user.visible_message( \
|
||||
"[user] unfastens \the [src].", \
|
||||
"\blue You have unfastened \the [src].", \
|
||||
"You hear a ratchet.")
|
||||
new /obj/item/pipe(loc, make_from=src)
|
||||
del(src)
|
||||
|
||||
/obj/machinery/atmospherics/omni/attack_hand(user as mob)
|
||||
if(..())
|
||||
return
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
ui_interact(user)
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/omni/proc/build_icons()
|
||||
if(!omni_icons)
|
||||
gen_omni_icons()
|
||||
|
||||
var/core_icon = null
|
||||
if(istype(src, /obj/machinery/atmospherics/omni/mixer))
|
||||
core_icon = "mixer"
|
||||
else if(istype(src, /obj/machinery/atmospherics/omni/filter))
|
||||
core_icon = "filter"
|
||||
else
|
||||
return
|
||||
|
||||
//directional icons are layers 1-4, with the core icon on layer 5
|
||||
if(core_icon)
|
||||
overlays_off[5] = omni_icons[core_icon]
|
||||
overlays_on[5] = omni_icons[core_icon + "_glow"]
|
||||
|
||||
overlays_error[1] = omni_icons[core_icon]
|
||||
overlays_error[2] = omni_icons["error"]
|
||||
|
||||
/obj/machinery/atmospherics/omni/proc/update_port_icons()
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(P.update)
|
||||
var/ref_layer = 0
|
||||
switch(P.dir)
|
||||
if(NORTH)
|
||||
ref_layer = 1
|
||||
if(SOUTH)
|
||||
ref_layer = 2
|
||||
if(EAST)
|
||||
ref_layer = 3
|
||||
if(WEST)
|
||||
ref_layer = 4
|
||||
|
||||
if(!ref_layer)
|
||||
continue
|
||||
|
||||
var/list/port_icons = select_port_icons(P)
|
||||
if(port_icons)
|
||||
if(P.node)
|
||||
underlays_current[ref_layer] = omni_icons[port_icons["pipe_icon"]]
|
||||
else
|
||||
underlays_current[ref_layer] = null
|
||||
overlays_off[ref_layer] = omni_icons[port_icons["off_icon"]]
|
||||
overlays_on[ref_layer] = omni_icons[port_icons["on_icon"]]
|
||||
else
|
||||
underlays_current[ref_layer] = null
|
||||
overlays_off[ref_layer] = null
|
||||
overlays_on[ref_layer] = null
|
||||
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/omni/proc/select_port_icons(var/datum/omni_port/P)
|
||||
if(!istype(P))
|
||||
return
|
||||
|
||||
if(P.mode > 0)
|
||||
var/ic_dir = dir_name(P.dir)
|
||||
var/ic_on = ic_dir
|
||||
var/ic_off = ic_dir
|
||||
switch(P.mode)
|
||||
if(ATM_INPUT)
|
||||
ic_on += "_in_glow"
|
||||
ic_off += "_in"
|
||||
if(ATM_OUTPUT)
|
||||
ic_on += "_out_glow"
|
||||
ic_off += "_out"
|
||||
if(ATM_O2 to ATM_N2O)
|
||||
ic_on += "_filter"
|
||||
ic_off += "_out"
|
||||
|
||||
var/pipe_state = ic_dir + "_pipe"
|
||||
if(P.node)
|
||||
if(P.node.color)
|
||||
pipe_state += "_[P.node.color]"
|
||||
|
||||
return list("on_icon" = ic_on, "off_icon" = ic_off, "pipe_icon" = pipe_state)
|
||||
|
||||
/obj/machinery/atmospherics/omni/proc/update_ports()
|
||||
sort_ports()
|
||||
update_port_icons()
|
||||
for(var/datum/omni_port/P in ports)
|
||||
P.update = 0
|
||||
|
||||
/obj/machinery/atmospherics/omni/proc/sort_ports()
|
||||
return
|
||||
|
||||
|
||||
// Housekeeping and pipe network stuff below
|
||||
|
||||
/obj/machinery/atmospherics/omni/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(reference == P.node)
|
||||
P.network = new_network
|
||||
break
|
||||
|
||||
if(new_network.normal_members.Find(src))
|
||||
return 0
|
||||
|
||||
new_network.normal_members += src
|
||||
|
||||
return null
|
||||
|
||||
/obj/machinery/atmospherics/omni/Del()
|
||||
loc = null
|
||||
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(P.node)
|
||||
P.node.disconnect(src)
|
||||
del(P.network)
|
||||
P.node = null
|
||||
|
||||
..()
|
||||
|
||||
/obj/machinery/atmospherics/omni/initialize()
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(P.node || P.mode == 0)
|
||||
continue
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src, P.dir))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
P.node = target
|
||||
break
|
||||
|
||||
for(var/datum/omni_port/P in ports)
|
||||
P.update = 1
|
||||
|
||||
update_ports()
|
||||
|
||||
/obj/machinery/atmospherics/omni/build_network()
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(!P.network && P.node)
|
||||
P.network = new /datum/pipe_network()
|
||||
P.network.normal_members += src
|
||||
P.network.build_network(P.node, src)
|
||||
|
||||
/obj/machinery/atmospherics/omni/return_network(obj/machinery/atmospherics/reference)
|
||||
build_network()
|
||||
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(reference == P.node)
|
||||
return P.network
|
||||
|
||||
return null
|
||||
|
||||
/obj/machinery/atmospherics/omni/reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(P.network == old_network)
|
||||
P.network = new_network
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/atmospherics/omni/return_network_air(datum/pipe_network/reference)
|
||||
var/list/results = list()
|
||||
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(P.network == reference)
|
||||
results += P.air
|
||||
|
||||
return results
|
||||
|
||||
/obj/machinery/atmospherics/omni/disconnect(obj/machinery/atmospherics/reference)
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(reference == P.node)
|
||||
del(P.network)
|
||||
P.node = null
|
||||
P.update = 1
|
||||
break
|
||||
|
||||
update_ports()
|
||||
|
||||
return null
|
||||
@@ -1,3 +1,8 @@
|
||||
#define EXTERNAL_PRESSURE_BOUND ONE_ATMOSPHERE
|
||||
#define INTERNAL_PRESSURE_BOUND 0
|
||||
#define PRESSURE_CHECKS 1
|
||||
#undefine
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_pump
|
||||
icon = 'icons/obj/atmospherics/vent_pump.dmi'
|
||||
icon_state = "off"
|
||||
@@ -14,14 +19,19 @@
|
||||
var/on = 0
|
||||
var/pump_direction = 1 //0 = siphoning, 1 = releasing
|
||||
|
||||
var/external_pressure_bound = ONE_ATMOSPHERE
|
||||
var/internal_pressure_bound = 0
|
||||
var/external_pressure_bound = EXTERNAL_PRESSURE_BOUND
|
||||
var/internal_pressure_bound = INTERNAL_PRESSURE_BOUND
|
||||
|
||||
var/pressure_checks = 1
|
||||
var/pressure_checks = PRESSURE_CHECKS
|
||||
//1: Do not pass external_pressure_bound
|
||||
//2: Do not pass internal_pressure_bound
|
||||
//3: Do not pass either
|
||||
|
||||
// Used when handling incoming radio signals requesting default settings
|
||||
var/external_pressure_bound_default = EXTERNAL_PRESSURE_BOUND
|
||||
var/internal_pressure_bound_default = INTERNAL_PRESSURE_BOUND
|
||||
var/pressure_checks_default = PRESSURE_CHECKS
|
||||
|
||||
var/welded = 0 // Added for aliens -- TLE
|
||||
|
||||
var/frequency = 1439
|
||||
@@ -205,7 +215,10 @@
|
||||
on = !on
|
||||
|
||||
if(signal.data["checks"] != null)
|
||||
pressure_checks = text2num(signal.data["checks"])
|
||||
if (signal.data["checks"] == "default")
|
||||
pressure_checks = pressure_checks_default
|
||||
else
|
||||
pressure_checks = text2num(signal.data["checks"])
|
||||
|
||||
if(signal.data["checks_toggle"] != null)
|
||||
pressure_checks = (pressure_checks?0:3)
|
||||
@@ -214,18 +227,24 @@
|
||||
pump_direction = text2num(signal.data["direction"])
|
||||
|
||||
if(signal.data["set_internal_pressure"] != null)
|
||||
internal_pressure_bound = between(
|
||||
0,
|
||||
text2num(signal.data["set_internal_pressure"]),
|
||||
ONE_ATMOSPHERE*50
|
||||
)
|
||||
if (signal.data["set_internal_pressure"] == "default")
|
||||
internal_pressure_bound = internal_pressure_bound_default
|
||||
else
|
||||
internal_pressure_bound = between(
|
||||
0,
|
||||
text2num(signal.data["set_internal_pressure"]),
|
||||
ONE_ATMOSPHERE*50
|
||||
)
|
||||
|
||||
if(signal.data["set_external_pressure"] != null)
|
||||
external_pressure_bound = between(
|
||||
0,
|
||||
text2num(signal.data["set_external_pressure"]),
|
||||
ONE_ATMOSPHERE*50
|
||||
)
|
||||
if (signal.data["set_external_pressure"] == "default")
|
||||
external_pressure_bound = external_pressure_bound_default
|
||||
else
|
||||
external_pressure_bound = between(
|
||||
0,
|
||||
text2num(signal.data["set_external_pressure"]),
|
||||
ONE_ATMOSPHERE*50
|
||||
)
|
||||
|
||||
if(signal.data["adjust_internal_pressure"] != null)
|
||||
internal_pressure_bound = between(
|
||||
@@ -235,6 +254,8 @@
|
||||
)
|
||||
|
||||
if(signal.data["adjust_external_pressure"] != null)
|
||||
|
||||
|
||||
external_pressure_bound = between(
|
||||
0,
|
||||
external_pressure_bound + text2num(signal.data["adjust_external_pressure"]),
|
||||
|
||||
+22
-12
@@ -220,15 +220,16 @@ obj/machinery/atmospherics/pipe/simple/pipeline_expansion()
|
||||
return list(node1, node2)
|
||||
|
||||
obj/machinery/atmospherics/pipe/simple/update_icon()
|
||||
if(node1&&node2)
|
||||
switch(pipe_color)
|
||||
if ("red") color = COLOR_RED
|
||||
if ("blue") color = COLOR_BLUE
|
||||
if ("cyan") color = COLOR_CYAN
|
||||
if ("green") color = COLOR_GREEN
|
||||
if ("yellow") color = "#FFCC00"
|
||||
if ("purple") color = "#5C1EC0"
|
||||
if ("grey") color = null
|
||||
switch(pipe_color)
|
||||
if ("red") color = COLOR_RED
|
||||
if ("blue") color = COLOR_BLUE
|
||||
if ("cyan") color = COLOR_CYAN
|
||||
if ("green") color = COLOR_GREEN
|
||||
if ("yellow") color = "#FFCC00"
|
||||
if ("purple") color = "#5C1EC0"
|
||||
if ("grey") color = null
|
||||
|
||||
if(node1 && node2)
|
||||
icon_state = "intact[invisibility ? "-f" : "" ]"
|
||||
|
||||
//var/node1_direction = get_dir(src, node1)
|
||||
@@ -237,8 +238,14 @@ obj/machinery/atmospherics/pipe/simple/update_icon()
|
||||
//dir = node1_direction|node2_direction
|
||||
|
||||
else
|
||||
if(!node1&&!node2)
|
||||
del(src) //TODO: silent deleting looks weird
|
||||
if(!node1 && !node2)
|
||||
var/turf/T = get_turf(src)
|
||||
new /obj/item/pipe(loc, make_from=src)
|
||||
for (var/obj/machinery/meter/meter in T)
|
||||
if (meter.target == src)
|
||||
new /obj/item/pipe_meter(T)
|
||||
del(meter)
|
||||
del(src)
|
||||
var/have_node1 = node1?1:0
|
||||
var/have_node2 = node2?1:0
|
||||
icon_state = "exposed[have_node1][have_node2][invisibility ? "-f" : "" ]"
|
||||
@@ -265,6 +272,9 @@ obj/machinery/atmospherics/pipe/simple/initialize()
|
||||
node2 = target
|
||||
break
|
||||
|
||||
if(!node1 && !node2)
|
||||
del(src)
|
||||
return
|
||||
|
||||
var/turf/T = src.loc // hide if turf is not intact
|
||||
hide(T.intact)
|
||||
@@ -1107,4 +1117,4 @@ obj/machinery/atmospherics/pipe/vent/hide(var/i) //to make the little pipe secti
|
||||
icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]intact"
|
||||
dir = get_dir(src, node1)
|
||||
else
|
||||
icon_state = "exposed"
|
||||
icon_state = "exposed"
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
var/list/accesses = list()
|
||||
var/giv_name = "NOT SPECIFIED"
|
||||
var/reason = "NOT SPECIFIED"
|
||||
var/duration = 0
|
||||
var/duration = 5
|
||||
|
||||
var/list/internal_log = list()
|
||||
var/mode = 0 // 0 - making pass, 1 - viewing logs
|
||||
@@ -117,18 +117,20 @@
|
||||
if (href_list["choice"])
|
||||
switch(href_list["choice"])
|
||||
if ("giv_name")
|
||||
var/nam = input("Person pass is issued to", "Name", name)
|
||||
var/nam = strip_html_simple(input("Person pass is issued to", "Name", giv_name) as text|null)
|
||||
if (nam)
|
||||
giv_name = strip_html_simple(nam)
|
||||
giv_name = nam
|
||||
if ("reason")
|
||||
var/reas = input("Reason why pass is issued", "Reason", reason)
|
||||
reason = strip_html_simple(reas)
|
||||
var/reas = strip_html_simple(input("Reason why pass is issued", "Reason", reason) as text|null)
|
||||
if(reas)
|
||||
reason = reas
|
||||
if ("duration")
|
||||
var/dur = input("Duration (in minutes) during which pass is valid.", "Duration") as num
|
||||
if (dur > 0 && dur < 30)
|
||||
duration = dur
|
||||
else
|
||||
usr << "<span class='warning'>Invalid duration.</span>"
|
||||
var/dur = input("Duration (in minutes) during which pass is valid (up to 30 minutes).", "Duration") as num|null
|
||||
if (dur)
|
||||
if (dur > 0 && dur <= 30)
|
||||
duration = dur
|
||||
else
|
||||
usr << "<span class='warning'>Invalid duration.</span>"
|
||||
if ("access")
|
||||
var/A = text2num(href_list["access"])
|
||||
if (A in accesses)
|
||||
@@ -147,6 +149,7 @@
|
||||
else
|
||||
giver.loc = src.loc
|
||||
giver = null
|
||||
accesses.Cut()
|
||||
else
|
||||
var/obj/item/I = usr.get_active_hand()
|
||||
if (istype(I, /obj/item/weapon/card/id))
|
||||
|
||||
@@ -11,7 +11,7 @@
|
||||
circuit = "/obj/item/weapon/circuitboard/atmoscontrol"
|
||||
var/obj/machinery/alarm/current
|
||||
var/overridden = 0 //not set yet, can't think of a good way to do it
|
||||
req_access = list(access_ce)
|
||||
req_access = list(access_atmospherics)
|
||||
|
||||
|
||||
/obj/machinery/computer/atmoscontrol/attack_ai(var/mob/user as mob)
|
||||
@@ -156,12 +156,14 @@
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
if(href_list["atmos_unlock"])
|
||||
switch(href_list["atmos_unlock"])
|
||||
if("0")
|
||||
current.air_doors_close(1)
|
||||
if("1")
|
||||
current.air_doors_open(1)
|
||||
//commenting this out because it causes compile errors
|
||||
//I tried fixing it but wasn't sucessful.
|
||||
//if(href_list["atmos_unlock"])
|
||||
// switch(href_list["atmos_unlock"])
|
||||
// if("0")
|
||||
// current.alarm_area.air_doors_close()
|
||||
// if("1")
|
||||
// current.alarm_area.air_doors_open()
|
||||
|
||||
if(href_list["atmos_alarm"])
|
||||
if (current.alarm_area.atmosalert(2))
|
||||
|
||||
@@ -198,7 +198,7 @@
|
||||
return list(access_sec_doors, access_forensics_lockers, access_morgue, access_maint_tunnels, access_court)
|
||||
if("Medical Doctor")
|
||||
return list(access_medical, access_morgue, access_surgery)
|
||||
if("Botanist") // -- TLE
|
||||
if("Gardener") // -- TLE
|
||||
return list(access_hydroponics, access_morgue) // Removed tox and chem access because STOP PISSING OFF THE CHEMIST GUYS // //Removed medical access because WHAT THE FUCK YOU AREN'T A DOCTOR YOU GROW WHEAT //Given Morgue access because they have a viable means of cloning.
|
||||
if("Librarian") // -- TLE
|
||||
return list(access_library)
|
||||
@@ -496,7 +496,7 @@
|
||||
return "Code Gold"
|
||||
|
||||
/proc/get_all_jobs()
|
||||
return list("Assistant", "Captain", "Head of Personnel", "Bartender", "Chef", "Botanist", "Quartermaster", "Cargo Technician",
|
||||
return list("Assistant", "Captain", "Head of Personnel", "Bartender", "Chef", "Gardener", "Quartermaster", "Cargo Technician",
|
||||
"Shaft Miner", "Clown", "Mime", "Janitor", "Librarian", "Lawyer", "Chaplain", "Chief Engineer", "Station Engineer",
|
||||
"Atmospheric Technician", "Roboticist", "Chief Medical Officer", "Medical Doctor", "Chemist", "Geneticist", "Virologist",
|
||||
"Research Director", "Scientist", "Head of Security", "Warden", "Detective", "Security Officer")
|
||||
|
||||
@@ -227,7 +227,7 @@ Alien plants should do something if theres a lot of poison
|
||||
del(src)
|
||||
|
||||
|
||||
/obj/effect/alien/flesh/weeds/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
/obj/effect/alien/flesh/weeds/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
if(exposed_temperature > 300)
|
||||
health -= 5
|
||||
healthcheck()
|
||||
|
||||
@@ -0,0 +1,207 @@
|
||||
/*
|
||||
The Big Bad NT Operating System
|
||||
*/
|
||||
|
||||
/datum/file/program/ntos
|
||||
name = "Nanotrasen Operating System"
|
||||
extension = "prog"
|
||||
active_state = "ntos"
|
||||
var/obj/item/part/computer/storage/current // the drive being viewed, null for desktop/computer
|
||||
var/fileop = "runfile"
|
||||
|
||||
/*
|
||||
Generate a basic list of files in the selected scope
|
||||
*/
|
||||
|
||||
/datum/file/program/ntos/proc/list_files()
|
||||
if(!computer || !current) return null
|
||||
return current.files
|
||||
|
||||
|
||||
/datum/file/program/ntos/proc/filegrid(var/list/filelist)
|
||||
var/dat = "<table border='0' align='left'>"
|
||||
var/i = 0
|
||||
for(var/datum/file/F in filelist)
|
||||
i++
|
||||
if(i==1)
|
||||
dat += "<tr>"
|
||||
if(i>= 6)
|
||||
i = 0
|
||||
dat += "</tr>"
|
||||
continue
|
||||
dat += {"
|
||||
<td>
|
||||
<center><a href='?src=\ref[src];[fileop]=\ref[F]'>
|
||||
<img src=\ref[F.image]><br>
|
||||
<span>[F.name]</span>
|
||||
</a></center>
|
||||
</td>"}
|
||||
|
||||
dat += "</tr></table>"
|
||||
return dat
|
||||
|
||||
//
|
||||
// I am separating this from filegrid so that I don't have to
|
||||
// make metadata peripheral files
|
||||
//
|
||||
/datum/file/program/ntos/proc/desktop(var/peripheralop = "viewperipheral")
|
||||
var/dat = "<table border='0' align='left'>"
|
||||
var/i = 0
|
||||
var/list/peripherals = list(computer.hdd,computer.floppy,computer.cardslot)
|
||||
for(var/obj/item/part/computer/C in peripherals)
|
||||
if(!istype(C)) continue
|
||||
i++
|
||||
if(i==1)
|
||||
dat += "<tr>"
|
||||
if(i>= 6)
|
||||
i = 0
|
||||
dat += "</tr>"
|
||||
continue
|
||||
dat += {"
|
||||
<td>
|
||||
<a href='?src=\ref[src];[peripheralop]=\ref[C]'>
|
||||
\icon[C]<br>
|
||||
<span>[C.name]</span>
|
||||
</a>
|
||||
</td>"}
|
||||
|
||||
dat += "</tr></table>"
|
||||
return dat
|
||||
|
||||
|
||||
/datum/file/program/ntos/proc/window(var/title,var/buttonbar,var/content)
|
||||
return {"
|
||||
<div class='filewin'>
|
||||
<div class='titlebar'>[title] <a href='?src=\ref[src];winclose'><img src=\ref['icons/ntos/tb_close.png']></a></div>
|
||||
<div class='buttonbar'>[buttonbar]</div>
|
||||
<div class='contentpane'>[content]</div>
|
||||
</div>"}
|
||||
|
||||
/datum/file/program/ntos/proc/buttonbar(var/type = 0)
|
||||
switch(type)
|
||||
if(0) // FILE OPERATIONS
|
||||
return {""}
|
||||
|
||||
/datum/file/program/ntos/interact()
|
||||
if(!interactable())
|
||||
return
|
||||
var/dat = {"
|
||||
<html>
|
||||
<head>
|
||||
<title>Nanotrasen Operating System</title>
|
||||
<style>
|
||||
div.filewin {
|
||||
position:absolute;
|
||||
left:80px;
|
||||
top:114px;
|
||||
width:480px;
|
||||
height:360px;
|
||||
border:2px inset black;
|
||||
background-color:#F0F0F0;
|
||||
overflow:auto
|
||||
}
|
||||
div.titlebar {
|
||||
position:fixed;
|
||||
left:80px;
|
||||
top:60px;
|
||||
width:480px;
|
||||
height:18px;
|
||||
padding:1px;
|
||||
padding-left:8px;
|
||||
border:none;
|
||||
background-color:#2020a0;
|
||||
color:#FFFFFF;
|
||||
z-index:5
|
||||
}
|
||||
.titlebar a {
|
||||
position:absolute;
|
||||
right:4px;
|
||||
display: block;
|
||||
width:16px;
|
||||
height:100%;
|
||||
background-color:#000000;
|
||||
color:#808080;
|
||||
}
|
||||
div.buttonbar {
|
||||
position:fixed;
|
||||
left:80px;
|
||||
top:78px;
|
||||
width:480px;
|
||||
height:36px;
|
||||
padding:2px;
|
||||
background-color:#f0d0d0;
|
||||
}
|
||||
div.contentpane {
|
||||
padding:4px;
|
||||
width:100%;
|
||||
height:100%
|
||||
}
|
||||
table a {
|
||||
display: block;
|
||||
height: 100%;
|
||||
width: 100%;
|
||||
text-decoration: none;
|
||||
color: black;
|
||||
text-align:center;
|
||||
}
|
||||
table span {
|
||||
background-color: #E0E0E0;
|
||||
font-family: verdana;
|
||||
font-size: 12px;
|
||||
}
|
||||
td {
|
||||
width: 64;
|
||||
height: 64;
|
||||
overflow: hidden;
|
||||
valign: "top";
|
||||
}
|
||||
a img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
</style>
|
||||
</head>
|
||||
|
||||
<body><div style='width:640px;height:480px; border:2px solid black;padding:8px;background-position:center;background-image:url(\ref['nano/images/uiBackground.png'])'>"}
|
||||
|
||||
var/list/files = list_files()
|
||||
if(current)
|
||||
dat +=window(current.name,buttonbar(),filegrid(files))
|
||||
else
|
||||
dat += desktop()
|
||||
|
||||
dat += "</div></body></html>"
|
||||
|
||||
usr << browse(dat, "window=\ref[computer];size=670x510")
|
||||
onclose(usr, "\ref[computer]")
|
||||
|
||||
/datum/file/program/ntos/Topic(href, list/href_list)
|
||||
if(!interactable() || ..(href,href_list))
|
||||
return
|
||||
|
||||
if("viewperipheral" in href_list) // open drive, show status of peripheral
|
||||
var/obj/item/part/computer/C = locate(href_list["viewperipheral"])
|
||||
if(istype(C,/obj/item/part/computer/storage))
|
||||
current = C
|
||||
interact()
|
||||
return
|
||||
// else ???
|
||||
if(istype(C,/obj/item/part/computer/cardslot))
|
||||
if(computer.cardslot.reader != null)
|
||||
computer.cardslot.remove()
|
||||
if(istype(C,/obj/item/part/computer/cardslot/dual))
|
||||
if(computer.cardslot.writer != null)
|
||||
computer.cardslot.remove(computer.cardslot.writer)
|
||||
if(computer.cardslot.reader != null)
|
||||
computer.cardslot.remove(computer.cardslot.reader)
|
||||
interact()
|
||||
return
|
||||
|
||||
// distinct from close, this is the file dialog window
|
||||
if("winclose" in href_list)
|
||||
current = null
|
||||
interact()
|
||||
return
|
||||
|
||||
#undef MAX_ROWS
|
||||
#undef MAX_COLUMNS
|
||||
@@ -0,0 +1,182 @@
|
||||
/*
|
||||
Okay so my last effort to have a central BIOS function was interesting
|
||||
but completely unmaintainable, I have scrapped it.
|
||||
|
||||
The parts that were actually useful will be put here in functions instead.
|
||||
If we want a central bios function we can add one that just indexes them.
|
||||
That should at least allow sensible debugging.
|
||||
*/
|
||||
|
||||
/obj/machinery/computer3
|
||||
|
||||
/*
|
||||
interactable(user): performs all standard sanity checks
|
||||
Call in topic() and interact().
|
||||
*/
|
||||
proc/interactable(var/mob/user)
|
||||
if( !src || !user || stat || user.stat || user.lying || user.blinded )
|
||||
return 0
|
||||
if(!program)
|
||||
return 0
|
||||
|
||||
if(!istype(loc,/turf) || !istype(user.loc,/turf)) // todo handheld maybe
|
||||
return 0
|
||||
|
||||
if(istype(user,/mob/living/silicon))
|
||||
if(!program.ai_allowed)
|
||||
user << "\blue You are forbidden from accessing this program."
|
||||
return 0
|
||||
else
|
||||
if(program.human_controls)
|
||||
if(!ishuman(user))
|
||||
user << "\red Your body can't work the controls!"
|
||||
return 0
|
||||
if(user.restrained())
|
||||
user << "\red You need a free hand!"
|
||||
return 0
|
||||
|
||||
if(!in_range(src,user))
|
||||
// telekinesis check
|
||||
if(ishuman(user) && istype(user.get_active_hand(),/obj/item/tk_grab))
|
||||
if(program.human_controls)
|
||||
user << "\red It's too complicated to work at a distance!"
|
||||
return 0
|
||||
add_fingerprint(user)
|
||||
user.set_machine(src)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
add_fingerprint(user)
|
||||
user.set_machine(src)
|
||||
return 1
|
||||
|
||||
/*
|
||||
Deduplicates an item list and gives you range and direction.
|
||||
This is used for networking so you can determine which of several
|
||||
identically named objects you're referring to.
|
||||
*/
|
||||
proc/format_atomlist(var/list/atoms)
|
||||
var/list/output = list()
|
||||
for(var/atom/A in atoms)
|
||||
var/title = "[A] (Range [get_dist(A,src)] meters, [dir2text(get_dir(src,A))])"
|
||||
output[title] = A
|
||||
return output
|
||||
|
||||
/*
|
||||
This is used by the camera monitoring program to see if you're still in range
|
||||
*/
|
||||
check_eye(var/mob/user as mob)
|
||||
if(!interactable(user) || user.machine != src)
|
||||
if(user.machine == src)
|
||||
user.unset_machine()
|
||||
return null
|
||||
|
||||
var/datum/file/program/security/S = program
|
||||
if( !istype(S) || !S.current || !S.current.status || !camnet )
|
||||
if( user.machine == src )
|
||||
user.unset_machine()
|
||||
return null
|
||||
|
||||
user.reset_view(S.current)
|
||||
return 1
|
||||
|
||||
/*
|
||||
List all files, including removable disks and data cards
|
||||
(I don't know why but I don't want to rip data cards out.
|
||||
It just seems... interesting?)
|
||||
*/
|
||||
proc/list_files(var/typekey = null)
|
||||
var/list/files = list()
|
||||
if(hdd)
|
||||
files += hdd.files
|
||||
if(floppy && floppy.inserted)
|
||||
files += floppy.inserted.files
|
||||
if(cardslot && istype(cardslot.reader,/obj/item/weapon/card/data))
|
||||
files += cardslot.reader:files
|
||||
if(!ispath(typekey))
|
||||
return files
|
||||
|
||||
var/i = 1
|
||||
while(i<=files.len)
|
||||
if(istype(files[i],typekey))
|
||||
i++
|
||||
continue
|
||||
files.Cut(i,i+1)
|
||||
return files
|
||||
|
||||
/*
|
||||
Crash the computer with an error.
|
||||
Todo: redo
|
||||
*/
|
||||
proc/Crash(var/errorcode = PROG_CRASH)
|
||||
if(!src)
|
||||
return null
|
||||
|
||||
switch(errorcode)
|
||||
if(PROG_CRASH)
|
||||
if(usr)
|
||||
usr << "\red The program crashed!"
|
||||
usr << browse(null,"\ref[src]")
|
||||
Reset()
|
||||
|
||||
if(MISSING_PERIPHERAL)
|
||||
Reset()
|
||||
if(usr)
|
||||
usr << browse("<h2>ERROR: Missing or disabled component</h2><b>A hardware failure has occured. Please insert or replace the missing or damaged component and restart the computer.</b>","window=\ref[src]")
|
||||
|
||||
if(BUSTED_ASS_COMPUTER)
|
||||
Reset()
|
||||
os.error = BUSTED_ASS_COMPUTER
|
||||
if(usr)
|
||||
usr << browse("<h2>ERROR: Missing or disabled component</h2><b>A hardware failure has occured. Please insert or replace the missing or damaged component and restart the computer.</b>","window=\ref[src]")
|
||||
|
||||
if(MISSING_PROGRAM)
|
||||
Reset()
|
||||
if(usr)
|
||||
usr << browse("<h2>ERROR: No associated program</h2><b>This file requires a specific program to open, which cannot be located. Please install the related program and try again.</b>","window=\ref[src]")
|
||||
|
||||
if(FILE_DRM)
|
||||
Reset()
|
||||
if(usr)
|
||||
usr << browse("<h2>ERROR: File operation prohibited</h2><b>Copy protection exception: missing authorization token.</b>","window=\ref[src]")
|
||||
|
||||
if(NETWORK_FAILURE)
|
||||
Reset()
|
||||
if(usr)
|
||||
usr << browse("<h2>ERROR: Networking exception: Unable to connect to remote host.</b>","window=\ref[src]")
|
||||
|
||||
|
||||
else
|
||||
if(usr)
|
||||
usr << "\red The program crashed!"
|
||||
usr << browse(null,"\ref[src]")
|
||||
testing("computer/Crash() - unknown error code [errorcode]")
|
||||
Reset()
|
||||
return null
|
||||
|
||||
#define ANY_DRIVE 0
|
||||
#define PREFER_FLOPPY 1
|
||||
#define PREFER_CARD 2
|
||||
#define PREFER_HDD 4
|
||||
|
||||
|
||||
// required_location: only put on preferred devices
|
||||
proc/writefile(var/datum/file/F, var/where = ANY_DRIVE, var/required_location = 0)
|
||||
if(where != ANY_DRIVE)
|
||||
if((where&PREFER_FLOPPY) && floppy && floppy.addfile(F))
|
||||
return 1
|
||||
if((where&PREFER_CARD) && cardslot && cardslot.addfile(F))
|
||||
return 1
|
||||
if((where&PREFER_HDD) && hdd && hdd.addfile(F))
|
||||
return 1
|
||||
|
||||
if(required_location)
|
||||
return 0
|
||||
|
||||
if(floppy && floppy.addfile(F))
|
||||
return 1
|
||||
if(cardslot && cardslot.addfile(F))
|
||||
return 1
|
||||
if(hdd && hdd.addfile(F))
|
||||
return 1
|
||||
return 0
|
||||
@@ -0,0 +1,302 @@
|
||||
// Computer3 circuitboard specifically
|
||||
/obj/item/part/computer/circuitboard
|
||||
density = 0
|
||||
anchored = 0
|
||||
w_class = 2.0
|
||||
name = "Circuit board"
|
||||
icon = 'icons/obj/module.dmi'
|
||||
icon_state = "id_mod"
|
||||
item_state = "electronic"
|
||||
origin_tech = "programming=2"
|
||||
var/id = null
|
||||
var/frequency = null
|
||||
var/build_path = null
|
||||
var/board_type = "computer"
|
||||
var/list/req_components = null
|
||||
var/powernet = null
|
||||
var/list/records = null
|
||||
var/frame_desc = null
|
||||
|
||||
var/datum/file/program/OS = new/datum/file/program/ntos
|
||||
|
||||
/obj/machinery/computer3/proc/disassemble(mob/user as mob) // todo
|
||||
return
|
||||
|
||||
|
||||
/obj/structure/computer3frame
|
||||
density = 1
|
||||
anchored = 0
|
||||
name = "computer frame"
|
||||
icon = 'icons/obj/stock_parts.dmi'
|
||||
icon_state = "0"
|
||||
var/state = 0
|
||||
|
||||
var/obj/item/part/computer/circuitboard/circuit = null
|
||||
var/completed = /obj/machinery/computer
|
||||
|
||||
// Computer3 components - a carbon copy of the list from
|
||||
// computer.dm; however, we will need to check to make sure
|
||||
// we don't install more components than the computer frame
|
||||
// can handle. This will be different for certain formfactors.
|
||||
|
||||
var/max_components = 4
|
||||
var/list/components = list()
|
||||
|
||||
// Storage
|
||||
var/obj/item/part/computer/storage/hdd/hdd = null
|
||||
var/obj/item/part/computer/storage/removable/floppy = null
|
||||
// Networking
|
||||
var/obj/item/part/computer/networking/radio/radio = null // not handled the same as other networks
|
||||
var/obj/item/part/computer/networking/cameras/camnet = null // just plain special
|
||||
var/obj/item/part/computer/networking/net = null // Proximity, area, or cable network
|
||||
var/obj/item/part/computer/networking/subspace/centcom = null // only for offstation communications
|
||||
|
||||
// Card reader - note the HoP reader is a subtype
|
||||
var/obj/item/part/computer/cardslot/cardslot = null
|
||||
|
||||
// Misc & special purpose
|
||||
var/obj/item/part/computer/ai_holder/cradle = null
|
||||
var/obj/item/part/computer/toybox/toybox = null
|
||||
|
||||
// Battery must be installed BEFORE wiring the computer.
|
||||
// if installing it in an existing computer, you will have to
|
||||
// get back to this state first.
|
||||
var/obj/item/weapon/cell/battery = null
|
||||
|
||||
/obj/structure/computer3frame/server
|
||||
name = "server frame"
|
||||
completed = /obj/machinery/computer3/server
|
||||
max_components = 6
|
||||
/obj/structure/computer3frame/wallcomp
|
||||
name = "wall-computer frame"
|
||||
completed = /obj/machinery/computer3/wall_comp
|
||||
max_components = 3
|
||||
/obj/structure/computer3frame/laptop
|
||||
name = "laptop frame"
|
||||
completed = /obj/machinery/computer3/laptop
|
||||
max_components = 3
|
||||
|
||||
/obj/structure/computer3frame/attackby(obj/item/P as obj, mob/user as mob)
|
||||
switch(state)
|
||||
if(0)
|
||||
if(istype(P, /obj/item/weapon/wrench))
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
if(do_after(user, 20))
|
||||
user << "\blue You wrench the frame into place."
|
||||
src.anchored = 1
|
||||
src.state = 1
|
||||
if(istype(P, /obj/item/weapon/weldingtool))
|
||||
var/obj/item/weapon/weldingtool/WT = P
|
||||
if(!WT.remove_fuel(0, user))
|
||||
user << "The welding tool must be on to complete this task."
|
||||
return
|
||||
playsound(src.loc, 'sound/items/Welder.ogg', 50, 1)
|
||||
if(do_after(user, 20))
|
||||
if(!src || !WT.isOn()) return
|
||||
user << "\blue You deconstruct the frame."
|
||||
new /obj/item/stack/sheet/metal( src.loc, 5 )
|
||||
del(src)
|
||||
if(1)
|
||||
if(istype(P, /obj/item/weapon/wrench))
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
if(do_after(user, 20))
|
||||
user << "\blue You unfasten the frame."
|
||||
src.anchored = 0
|
||||
src.state = 0
|
||||
if(istype(P, /obj/item/weapon/circuitboard) && !circuit)
|
||||
var/obj/item/weapon/circuitboard/B = P
|
||||
if(B.board_type == "computer")
|
||||
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
|
||||
user << "\blue You place the circuit board inside the frame."
|
||||
src.icon_state = "1"
|
||||
src.circuit = P
|
||||
user.drop_item()
|
||||
P.loc = src
|
||||
else
|
||||
user << "\red This frame does not accept circuit boards of this type!"
|
||||
if(istype(P, /obj/item/weapon/screwdriver) && circuit)
|
||||
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
|
||||
user << "\blue You screw the circuit board into place."
|
||||
src.state = 2
|
||||
src.icon_state = "2"
|
||||
if(istype(P, /obj/item/weapon/crowbar) && circuit)
|
||||
playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
|
||||
user << "\blue You remove the circuit board."
|
||||
src.state = 1
|
||||
src.icon_state = "0"
|
||||
circuit.loc = src.loc
|
||||
src.circuit = null
|
||||
if(2)
|
||||
if(istype(P, /obj/item/weapon/screwdriver) && circuit)
|
||||
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
|
||||
user << "\blue You unfasten the circuit board."
|
||||
src.state = 1
|
||||
src.icon_state = "1"
|
||||
|
||||
if(istype(P, /obj/item/weapon/crowbar))
|
||||
if(battery)
|
||||
playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
|
||||
if(do_after(10))
|
||||
battery.loc = loc
|
||||
user << "\blue You remove [battery]."
|
||||
battery = null
|
||||
else
|
||||
user << "\red There's no battery to remove!"
|
||||
|
||||
if(istype(P, /obj/item/weapon/cell))
|
||||
if(!battery)
|
||||
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
|
||||
if(do_after(5))
|
||||
battery = P
|
||||
P.loc = src
|
||||
user << "\blue You insert [battery]."
|
||||
else
|
||||
user << "\red There's already \an [battery] in [src]!"
|
||||
|
||||
|
||||
if(istype(P, /obj/item/weapon/cable_coil))
|
||||
if(P:amount >= 5)
|
||||
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
|
||||
if(do_after(user, 20))
|
||||
if(P)
|
||||
P:amount -= 5
|
||||
if(!P:amount) del(P)
|
||||
user << "\blue You add cables to the frame."
|
||||
src.state = 3
|
||||
src.icon_state = "3"
|
||||
if(3)
|
||||
if(istype(P, /obj/item/weapon/wirecutters))
|
||||
if(components.len)
|
||||
user << "There are parts in the way!"
|
||||
return
|
||||
playsound(src.loc, 'sound/items/Wirecutter.ogg', 50, 1)
|
||||
user << "\blue You remove the cables."
|
||||
src.state = 2
|
||||
src.icon_state = "2"
|
||||
var/obj/item/weapon/cable_coil/A = new /obj/item/weapon/cable_coil( src.loc )
|
||||
A.amount = 5
|
||||
|
||||
if(istype(P, /obj/item/weapon/crowbar)) // complicated check
|
||||
remove_peripheral()
|
||||
|
||||
if(istype(P, /obj/item/stack/sheet/glass))
|
||||
if(P:amount >= 2)
|
||||
playsound(src.loc, 'sound/items/Deconstruct.ogg', 50, 1)
|
||||
if(do_after(user, 20))
|
||||
if(P)
|
||||
P:use(2)
|
||||
user << "\blue You put in the glass panel."
|
||||
src.state = 4
|
||||
src.icon_state = "4"
|
||||
if(4)
|
||||
if(istype(P, /obj/item/weapon/crowbar))
|
||||
playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
|
||||
user << "\blue You remove the glass panel."
|
||||
src.state = 3
|
||||
src.icon_state = "3"
|
||||
new /obj/item/stack/sheet/glass( src.loc, 2 )
|
||||
if(istype(P, /obj/item/weapon/screwdriver))
|
||||
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
|
||||
user << "\blue You connect the monitor."
|
||||
var/obj/machinery/computer3/B = new src.circuit.build_path ( src.loc, built=1 )
|
||||
/*if(circuit.powernet) B:powernet = circuit.powernet
|
||||
if(circuit.id) B:id = circuit.id
|
||||
//if(circuit.records) B:records = circuit.records
|
||||
if(circuit.frequency) B:frequency = circuit.frequency
|
||||
if(istype(circuit,/obj/item/weapon/circuitboard/supplycomp))
|
||||
var/obj/machinery/computer/supplycomp/SC = B
|
||||
var/obj/item/weapon/circuitboard/supplycomp/C = circuit
|
||||
SC.can_order_contraband = C.contraband_enabled*/
|
||||
B.circuit = circuit
|
||||
circuit.loc = B
|
||||
if(circuit.OS)
|
||||
circuit.OS.computer = B
|
||||
B.RefreshParts() // todo
|
||||
del(src)
|
||||
|
||||
/*
|
||||
This will remove peripherals if you specify one, but the main function is to
|
||||
allow the user to remove a part specifically.
|
||||
*/
|
||||
/obj/structure/computer3frame/proc/remove_peripheral(var/obj/item/I = null)
|
||||
if(!components || !components.len)
|
||||
usr << "\red There are no components in [src] to take out!"
|
||||
return 0
|
||||
if(!I)
|
||||
I = input(usr, "Remove which component?","Remove component", null) as null|obj in components
|
||||
|
||||
if(I)
|
||||
playsound(src.loc, 'sound/items/Crowbar.ogg', 50, 1)
|
||||
if(do_after(usr,25))
|
||||
if(I==hdd)
|
||||
components -= hdd
|
||||
hdd.loc = loc
|
||||
hdd = null
|
||||
else if(I==floppy)
|
||||
components -= floppy
|
||||
floppy.loc = loc
|
||||
floppy = null
|
||||
else if(I==radio)
|
||||
components -= radio
|
||||
radio.loc = loc
|
||||
radio = null
|
||||
else if(I==camnet)
|
||||
components -= camnet
|
||||
camnet.loc = loc
|
||||
camnet = null
|
||||
else if(I==net)
|
||||
components -= net
|
||||
net.loc = loc
|
||||
net = null
|
||||
else if(I==cradle)
|
||||
components -= cradle
|
||||
cradle.loc = loc
|
||||
cradle = null
|
||||
else if(I==toybox)
|
||||
components -= toybox
|
||||
toybox.loc = loc
|
||||
toybox = null
|
||||
else
|
||||
warning("Erronous component in computerframe/remove_peripheral: [I]")
|
||||
I.loc = loc
|
||||
usr << "\blue You remove [I]"
|
||||
return 1
|
||||
return 0
|
||||
/obj/structure/computer3frame/proc/insert_peripheral(var/obj/item/I)
|
||||
if(components.len >= max_components)
|
||||
usr << "There isn't room in [src] for another component!"
|
||||
return 0
|
||||
switch(I.type)
|
||||
if(/obj/item/part/computer/storage/hdd)
|
||||
if(hdd)
|
||||
usr << "There is already \an [hdd] in [src]!"
|
||||
return 0
|
||||
hdd = I
|
||||
components += hdd
|
||||
hdd.loc = src
|
||||
if(/obj/item/part/computer/storage/removable)
|
||||
if(floppy)
|
||||
usr << "There is already \an [floppy] in [src]!"
|
||||
return 0
|
||||
floppy = I
|
||||
components += floppy
|
||||
floppy.loc = src
|
||||
if(/obj/item/part/computer/networking/radio)
|
||||
if(radio)
|
||||
usr << "There is already \an [radio] in [src]!"
|
||||
return 0
|
||||
radio = I
|
||||
components += radio
|
||||
radio.loc = src
|
||||
if(/obj/item/part/computer/networking/cameras)
|
||||
if(camnet)
|
||||
usr << "There is already \an [camnet] in [src]!"
|
||||
return 0
|
||||
camnet = I
|
||||
components += camnet
|
||||
camnet.loc = src
|
||||
if(/obj/item/part/computer/networking)
|
||||
if(net)
|
||||
usr << "There is already \an [net] in [src]!"
|
||||
|
||||
|
||||
@@ -0,0 +1,198 @@
|
||||
|
||||
/*
|
||||
Objects used to construct computers, and objects that can be inserted into them, etc.
|
||||
|
||||
TODO:
|
||||
* Synthesizer part (toybox, injectors, etc)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
/obj/item/part/computer
|
||||
name = "computer part"
|
||||
desc = "Holy jesus you donnit now"
|
||||
gender = PLURAL
|
||||
icon = 'icons/obj/stock_parts.dmi'
|
||||
icon_state = "hdd1"
|
||||
w_class = 2.0
|
||||
|
||||
var/emagged = 0
|
||||
crit_fail = 0
|
||||
|
||||
// the computer that this device is attached to
|
||||
var/obj/machinery/computer3/computer
|
||||
|
||||
// If the computer is attacked by an item it will reference this to decide which peripheral(s) are affected.
|
||||
var/list/attackby_types = list()
|
||||
proc/allow_attackby(var/obj/item/I as obj,var/mob/user as mob)
|
||||
|
||||
for(var/typekey in attackby_types)
|
||||
if(istype(I,typekey))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
proc/init(var/obj/machinery/computer/target)
|
||||
computer = target
|
||||
// continue to handle all other type-specific procedures
|
||||
|
||||
/*
|
||||
Below are all the miscellaneous components
|
||||
For storage drives, see storage.dm
|
||||
For networking parts, see
|
||||
*/
|
||||
|
||||
/obj/item/part/computer/ai_holder
|
||||
name = "intelliCard computer module"
|
||||
desc = "Contains a specialized nacelle for dealing with highly sensitive equipment without interference."
|
||||
|
||||
attackby_types = list(/obj/item/device/aicard)
|
||||
|
||||
var/mob/living/silicon/ai/occupant = null
|
||||
var/busy = 0
|
||||
|
||||
// Ninja gloves check
|
||||
attack_hand(mob/user as mob)
|
||||
if(ishuman(user) && istype(user:gloves, /obj/item/clothing/gloves/space_ninja) && user:gloves:candrain && !user:gloves:draining)
|
||||
if(user:wear_suit:s_control)
|
||||
user:wear_suit.transfer_ai("AIFIXER","NINJASUIT",src,user)
|
||||
else
|
||||
user << "\red <b>ERROR</b>: \black Remote access channel disabled."
|
||||
return
|
||||
..()
|
||||
|
||||
attackby(obj/I as obj,mob/user as mob)
|
||||
if(computer && !computer.stat)
|
||||
if(istype(I, /obj/item/device/aicard))
|
||||
I:transfer_ai("AIFIXER","AICARD",src,user)
|
||||
if(computer.program)
|
||||
computer.program.update_icon()
|
||||
computer.update_icon()
|
||||
computer.occupant = occupant
|
||||
..()
|
||||
return
|
||||
|
||||
/*
|
||||
ID computer cardslot - reading and writing slots
|
||||
*/
|
||||
|
||||
/obj/item/part/computer/cardslot
|
||||
name = "magnetic card slot"
|
||||
desc = "Contains a slot for reading magnetic swipe cards."
|
||||
|
||||
var/obj/item/weapon/card/reader = null
|
||||
var/obj/item/weapon/card/writer = null // so that you don't need to typecast dual cardslots, but pretend it's not here
|
||||
// alternately pretend they did it to save money on manufacturing somehow
|
||||
var/dualslot = 0 // faster than typechecking
|
||||
attackby_types = list(/obj/item/weapon/card)
|
||||
|
||||
attackby(var/obj/item/I as obj, var/mob/user as mob)
|
||||
if(istype(I,/obj/item/weapon/card))
|
||||
insert(I)
|
||||
return
|
||||
..(I,user)
|
||||
|
||||
proc/insert(var/obj/item/weapon/card/card)
|
||||
if(!computer)
|
||||
return 0
|
||||
if(reader != null)
|
||||
usr << "There is already something in the slot!"
|
||||
return 0
|
||||
if(istype(card,/obj/item/weapon/card/emag)) // emag reader slot
|
||||
usr << "You insert \the [card], and the computer grinds, sparks, and beeps. After a moment, the card ejects itself."
|
||||
computer.emagged = 1
|
||||
return 1
|
||||
var/mob/living/L = usr
|
||||
L.drop_item()
|
||||
card.loc = src
|
||||
reader = card
|
||||
|
||||
proc/remove()
|
||||
reader.loc = loc
|
||||
var/mob/living/carbon/human/user = usr
|
||||
if(istype(user) && !user.get_active_hand())
|
||||
user.put_in_hands(reader)
|
||||
else
|
||||
reader.loc = computer.loc
|
||||
reader = null
|
||||
|
||||
// Authorizes the user based on the computer's requirements
|
||||
proc/authenticate()
|
||||
return computer.check_access(reader)
|
||||
|
||||
proc/addfile(var/datum/file/F)
|
||||
if(!dualslot || !istype(writer,/obj/item/weapon/card/data))
|
||||
return 0
|
||||
var/obj/item/weapon/card/data/D = writer
|
||||
if(D.files.len > 3)
|
||||
return 0
|
||||
D.files += F
|
||||
return 1
|
||||
|
||||
/obj/item/part/computer/cardslot/dual
|
||||
name = "magnetic card reader"
|
||||
desc = "Contains slots for inserting magnetic swipe cards for reading and writing."
|
||||
dualslot = 1
|
||||
|
||||
insert(var/obj/item/weapon/card/card,var/slot = 0)
|
||||
if(!computer)
|
||||
return 0
|
||||
|
||||
if(istype(card,/obj/item/weapon/card/emag) && !reader) // emag reader slot
|
||||
usr.visible_message("[computer]'s screen flickers for a moment.","You insert \the [card]. After a moment, the card ejects itself, and [computer] beeps.","[computer] beeps.")
|
||||
computer.emagged = 1
|
||||
return 1
|
||||
|
||||
if(slot == 1) // 1: writer
|
||||
if(writer != null)
|
||||
usr << "There's already a card in that slot!"
|
||||
return 0
|
||||
var/mob/living/L = usr
|
||||
L.drop_item()
|
||||
card.loc = src
|
||||
writer = card
|
||||
return 1
|
||||
else if(slot == 2) // 2: reader
|
||||
if(reader != null)
|
||||
usr << "There's already a card in that slot!"
|
||||
return 0
|
||||
var/mob/living/L = usr
|
||||
L.drop_item()
|
||||
card.loc = src
|
||||
reader = card
|
||||
return 1
|
||||
else // 0: auto
|
||||
if(reader && writer)
|
||||
usr << "Both slots are full!"
|
||||
return 0
|
||||
var/mob/living/L = usr
|
||||
L.drop_item()
|
||||
card.loc = src
|
||||
if(reader)
|
||||
writer = card
|
||||
computer.updateUsrDialog()
|
||||
return 1
|
||||
if(istype(card,/obj/item/weapon/card/id) && !(access_change_ids in card:access) && !writer) // not authorized
|
||||
writer = card
|
||||
computer.updateUsrDialog()
|
||||
return 1
|
||||
if(!reader)
|
||||
reader = card
|
||||
computer.updateUsrDialog()
|
||||
return 1
|
||||
return 0
|
||||
|
||||
remove(var/obj/item/weapon/card/card)
|
||||
if(card != reader && card != writer)
|
||||
return
|
||||
|
||||
if(card == reader) reader = null
|
||||
if(card == writer) writer = null
|
||||
card.loc = loc
|
||||
|
||||
var/mob/living/carbon/human/user = usr
|
||||
if(ishuman(user) && !user.get_active_hand())
|
||||
user.put_in_hands(card)
|
||||
else
|
||||
card.loc = computer.loc
|
||||
|
||||
|
||||
@@ -0,0 +1,458 @@
|
||||
/obj/machinery/computer3
|
||||
name = "computer"
|
||||
icon = 'icons/obj/computer3.dmi'
|
||||
icon_state = "frame"
|
||||
density = 1
|
||||
anchored = 1.0
|
||||
|
||||
idle_power_usage = 20
|
||||
active_power_usage = 50
|
||||
|
||||
var/allow_disassemble = 1
|
||||
var/legacy_icon = 0 // if 1, use old style icons
|
||||
var/show_keyboard = 1
|
||||
|
||||
// These is all you should need to change when creating a new computer.
|
||||
// If there is no default program, the OS will run instead.
|
||||
// If there is no hard drive, but there is a default program, the OS rom on
|
||||
// the circuitboard will be overridden.
|
||||
|
||||
// For these, typepaths are used, NOT objects
|
||||
|
||||
var/default_prog = null // the program running when spawned
|
||||
var/list/spawn_files = list() // files added when spawned
|
||||
var/list/spawn_parts = list(/obj/item/part/computer/storage/hdd/big) // peripherals to spawn
|
||||
|
||||
// Computer3 components - put an object in them in New() when not built
|
||||
// I used to have a more pliable /list, but the ambiguities
|
||||
// there in how many of what you had was killing me, especially
|
||||
// when you had to search the list to find what you had.
|
||||
|
||||
// Mostly decorative, holds the OS rom
|
||||
var/obj/item/part/computer/circuitboard/circuit
|
||||
|
||||
// Storage
|
||||
var/obj/item/part/computer/storage/hdd/hdd = null
|
||||
var/obj/item/part/computer/storage/removable/floppy = null
|
||||
// Networking
|
||||
var/obj/item/part/computer/networking/radio/radio = null // not handled the same as other networks
|
||||
var/obj/item/part/computer/networking/cameras/camnet = null // just plain special
|
||||
var/obj/item/part/computer/networking/net = null // Proximity, area, or cable network
|
||||
|
||||
// Card reader - note the HoP reader is a subtype
|
||||
var/obj/item/part/computer/cardslot/cardslot = null
|
||||
|
||||
// Misc & special purpose
|
||||
var/obj/item/part/computer/ai_holder/cradle = null
|
||||
var/obj/item/part/computer/toybox/toybox = null
|
||||
var/mob/living/silicon/ai/occupant = null
|
||||
|
||||
|
||||
// Legacy variables
|
||||
// camera networking - overview (???)
|
||||
var/mapping = 0
|
||||
var/last_pic = 1.0
|
||||
|
||||
// Purely graphical effect
|
||||
var/icon/kb = null
|
||||
|
||||
// These are necessary in order to consolidate all computer types into one
|
||||
var/datum/wires/wires = null
|
||||
var/powernet = null
|
||||
|
||||
// Used internally
|
||||
var/datum/file/program/program = null // the active program (null if defaulting to os)
|
||||
var/datum/file/program/os = null // the base code of the machine (os or hardcoded program)
|
||||
|
||||
// If you want the computer to have a UPS, add a battery during construction. This is useful for things like
|
||||
// the comms computer, solar trackers, etc, that should function when all else is off.
|
||||
// Laptops will require batteries and have no mains power.
|
||||
|
||||
var/obj/item/weapon/cell/battery = null // uninterruptible power supply aka battery
|
||||
|
||||
|
||||
verb/ResetComputer()
|
||||
set name = "Reset Computer"
|
||||
set category = "Object"
|
||||
set src in view(1)
|
||||
|
||||
if(usr.stat || usr.restrained() || usr.lying || !istype(usr, /mob/living))
|
||||
usr << "\red You can't do that."
|
||||
return
|
||||
|
||||
if(!Adjacent(usr))
|
||||
usr << "You can't reach it."
|
||||
return
|
||||
|
||||
Reset()
|
||||
|
||||
New(var/L, var/built = 0)
|
||||
..()
|
||||
spawn(2)
|
||||
power_change()
|
||||
|
||||
if(show_keyboard)
|
||||
var/kb_state = "kb[rand(1,15)]"
|
||||
kb = image('icons/obj/computer3.dmi',icon_state=kb_state)
|
||||
overlays += kb
|
||||
|
||||
if(!built)
|
||||
if(!circuit || !istype(circuit))
|
||||
circuit = new(src)
|
||||
if(circuit.OS)
|
||||
os = circuit.OS
|
||||
circuit.OS.computer = src
|
||||
else
|
||||
os = null
|
||||
|
||||
// separated into its own function because blech
|
||||
spawn_parts()
|
||||
|
||||
if(default_prog) // Add the default software if applicable
|
||||
var/datum/file/program/P = new default_prog
|
||||
if(hdd)
|
||||
hdd.addfile(P,1)
|
||||
program = P
|
||||
if(!os)
|
||||
os = P
|
||||
else if(floppy)
|
||||
floppy.inserted = new(floppy)
|
||||
floppy.files = floppy.inserted.files
|
||||
floppy.addfile(P)
|
||||
program = P
|
||||
else
|
||||
circuit.OS = P
|
||||
circuit.OS.computer = src
|
||||
os = circuit.OS
|
||||
circuit.name = "Circuitboard ([P])"
|
||||
|
||||
|
||||
if(hdd) // Spawn files
|
||||
for(var/typekey in spawn_files)
|
||||
hdd.addfile(new typekey,1)
|
||||
|
||||
if(program)
|
||||
program.execute(os)
|
||||
update_icon()
|
||||
|
||||
|
||||
proc/update_spawn_files()
|
||||
for(var/typekey in spawn_files)
|
||||
hdd.addfile(new typekey,1)
|
||||
|
||||
proc/spawn_parts()
|
||||
for(var/typekey in spawn_parts)
|
||||
|
||||
if(ispath(typekey,/obj/item/part/computer/storage/removable))
|
||||
if(floppy) continue
|
||||
floppy = new typekey(src)
|
||||
floppy.init(src)
|
||||
continue
|
||||
if(ispath(typekey,/obj/item/part/computer/storage/hdd))
|
||||
if(hdd) continue
|
||||
hdd = new typekey(src)
|
||||
hdd.init(src)
|
||||
continue
|
||||
|
||||
if(ispath(typekey,/obj/item/part/computer/networking/cameras))
|
||||
if(camnet) continue
|
||||
camnet = new typekey(src)
|
||||
camnet.init(src)
|
||||
continue
|
||||
if(ispath(typekey,/obj/item/part/computer/networking/radio))
|
||||
if(radio) continue
|
||||
radio = new typekey(src)
|
||||
radio.init(src)
|
||||
continue
|
||||
if(ispath(typekey,/obj/item/part/computer/networking))
|
||||
if(net) continue
|
||||
net = new typekey(src)
|
||||
net.init(src)
|
||||
continue
|
||||
|
||||
if(ispath(typekey,/obj/item/part/computer/cardslot))
|
||||
if(cardslot) continue
|
||||
cardslot = new typekey(src)
|
||||
cardslot.init(src)
|
||||
continue
|
||||
if(ispath(typekey,/obj/item/part/computer/ai_holder))
|
||||
if(cradle) continue
|
||||
cradle = new typekey(src)
|
||||
cradle.init(src)
|
||||
if(ispath(typekey,/obj/item/part/computer/toybox))
|
||||
if(toybox) continue
|
||||
toybox = new typekey(src)
|
||||
toybox.init(src)
|
||||
continue
|
||||
|
||||
if(ispath(typekey,/obj/item/weapon/cell))
|
||||
if(battery) continue
|
||||
battery = new typekey(src)
|
||||
continue
|
||||
|
||||
proc/Reset(var/error = 0)
|
||||
for(var/mob/living/M in range(1))
|
||||
M << browse(null,"window=\ref[src]")
|
||||
if(program)
|
||||
program.Reset()
|
||||
program = null
|
||||
req_access = os.req_access
|
||||
update_icon()
|
||||
|
||||
// todo does this do enough
|
||||
|
||||
|
||||
meteorhit(var/obj/O as obj)
|
||||
for(var/x in verbs)
|
||||
verbs -= x
|
||||
set_broken()
|
||||
return
|
||||
|
||||
|
||||
emp_act(severity)
|
||||
if(prob(20/severity)) set_broken()
|
||||
..()
|
||||
|
||||
|
||||
ex_act(severity)
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
del(src)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(25))
|
||||
del(src)
|
||||
return
|
||||
if (prob(50))
|
||||
for(var/x in verbs)
|
||||
verbs -= x
|
||||
set_broken()
|
||||
if(3.0)
|
||||
if (prob(25))
|
||||
for(var/x in verbs)
|
||||
verbs -= x
|
||||
set_broken()
|
||||
else
|
||||
return
|
||||
|
||||
|
||||
blob_act()
|
||||
if (prob(75))
|
||||
set_broken()
|
||||
density = 0
|
||||
|
||||
/*
|
||||
Computers have the capability to use a battery backup.
|
||||
Note that auto_use_power's return value is strictly whether
|
||||
or not it is successfully powered.
|
||||
|
||||
This allows laptops, and also allows you to create computers that
|
||||
remain active when:
|
||||
|
||||
* the APC is destroy'd, emag'd, malf'd, emp'd, ninja'd etc
|
||||
* the computer was built in an unpowered zone
|
||||
* the station power is out, cables are cut, etc
|
||||
|
||||
By default, most computers will NOT spawn with a battery backup, and
|
||||
SHOULD not. Players can take apart a computer to insert the battery
|
||||
if they want to ensure, for example, the AI upload remains when the
|
||||
power is cut off.
|
||||
|
||||
Make sure to use use_power() a bunch in peripherals code
|
||||
*/
|
||||
auto_use_power()
|
||||
if(!powered(power_channel))
|
||||
if(battery && battery.charge > 0)
|
||||
if(use_power == 1)
|
||||
battery.use(idle_power_usage)
|
||||
else
|
||||
battery.use(active_power_usage)
|
||||
return 1
|
||||
return 0
|
||||
if(src.use_power == 1)
|
||||
use_power(idle_power_usage,power_channel)
|
||||
else if(src.use_power >= 2)
|
||||
use_power(active_power_usage,power_channel)
|
||||
return 1
|
||||
|
||||
use_power(var/amount, var/chan = -1)
|
||||
if(chan == -1)
|
||||
chan = power_channel
|
||||
|
||||
var/area/A = get_area(loc)
|
||||
if(istype(A) && A.master && A.master.powered(chan))
|
||||
A.master.use_power(amount, chan)
|
||||
else if(battery && battery.charge > 0)
|
||||
battery.use(amount)
|
||||
|
||||
power_change()
|
||||
if( !powered(power_channel) && (!battery || battery.charge <= 0) )
|
||||
stat |= NOPOWER
|
||||
else
|
||||
stat &= ~NOPOWER
|
||||
|
||||
process()
|
||||
auto_use_power()
|
||||
power_change()
|
||||
update_icon()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
|
||||
if(program)
|
||||
program.process()
|
||||
return
|
||||
|
||||
if(os)
|
||||
program = os
|
||||
os.process()
|
||||
return
|
||||
|
||||
|
||||
proc/set_broken()
|
||||
icon_state = "computer_b"
|
||||
stat |= BROKEN
|
||||
crit_fail = 1
|
||||
if(program)
|
||||
program.error = BUSTED_ASS_COMPUTER
|
||||
if(os)
|
||||
os.error = BUSTED_ASS_COMPUTER
|
||||
|
||||
attackby(I as obj, mob/user as mob)
|
||||
if(istype(I, /obj/item/weapon/screwdriver) && allow_disassemble)
|
||||
disassemble(user)
|
||||
return
|
||||
|
||||
/*
|
||||
+++++++++++
|
||||
|IMPORTANT| If you add a peripheral, put it in this list
|
||||
+++++++++++ --------------------------------------------
|
||||
*/
|
||||
var/list/peripherals = list(hdd,floppy,radio,net,cardslot,cradle) //camnet, toybox removed
|
||||
|
||||
var/list/p_list = list()
|
||||
for(var/obj/item/part/computer/C in peripherals)
|
||||
if(!isnull(C) && C.allow_attackby(I,user))
|
||||
p_list += C
|
||||
if(p_list.len)
|
||||
var/obj/item/part/computer/P = null
|
||||
if(p_list.len == 1)
|
||||
P = p_list[1]
|
||||
else
|
||||
P = input(user,"Which component?") as null|anything in p_list
|
||||
|
||||
if(P)
|
||||
P.attackby(I,user)
|
||||
return
|
||||
..()
|
||||
|
||||
attack_hand(var/mob/user as mob)
|
||||
if(stat)
|
||||
Reset()
|
||||
return
|
||||
|
||||
// I don't want to deal with computers that you can't walk up to and use
|
||||
// there is still cardauth anyway
|
||||
//if(!allowed(user))
|
||||
// return
|
||||
|
||||
if(program)
|
||||
if(program.computer != src) // floppy disk may have been removed, etc
|
||||
Reset()
|
||||
attack_hand(user)
|
||||
return
|
||||
if(program.error)
|
||||
Crash(program.error)
|
||||
return
|
||||
user.set_machine(src)
|
||||
program.attack_hand(user) // will normally translate to program/interact()
|
||||
return
|
||||
|
||||
if(os)
|
||||
program = os
|
||||
user.set_machine(src)
|
||||
os.attack_hand(user)
|
||||
return
|
||||
|
||||
user << "\The [src] won't boot!"
|
||||
|
||||
attack_ai(var/mob/user as mob) // copypasta because server racks lose attack_hand()
|
||||
if(stat)
|
||||
Reset()
|
||||
return
|
||||
|
||||
if(program)
|
||||
if(program.computer != src) // floppy disk may have been removed, etc
|
||||
Reset()
|
||||
attack_ai(user)
|
||||
return
|
||||
if(program.error)
|
||||
Crash(program.error)
|
||||
return
|
||||
user.set_machine(src)
|
||||
program.attack_hand(user) // will normally translate to program/interact()
|
||||
return
|
||||
|
||||
if(os)
|
||||
program = os
|
||||
user.set_machine(src)
|
||||
os.attack_hand(user)
|
||||
return
|
||||
|
||||
user << "\The [src] won't boot!"
|
||||
|
||||
interact()
|
||||
if(stat)
|
||||
Reset()
|
||||
return
|
||||
if(!allowed(usr) || !usr in view(1))
|
||||
usr.unset_machine()
|
||||
return
|
||||
|
||||
if(program)
|
||||
program.interact()
|
||||
return
|
||||
|
||||
if(os)
|
||||
program = os
|
||||
os.interact()
|
||||
return
|
||||
|
||||
update_icon()
|
||||
if(legacy_icon)
|
||||
icon_state = initial(icon_state)
|
||||
// Broken
|
||||
if(stat & BROKEN)
|
||||
icon_state += "b"
|
||||
|
||||
// Powered
|
||||
else if(stat & NOPOWER)
|
||||
icon_state = initial(icon_state)
|
||||
icon_state += "0"
|
||||
return
|
||||
if(stat)
|
||||
overlays.Cut()
|
||||
return
|
||||
if(program)
|
||||
overlays = list(program.overlay)
|
||||
if(show_keyboard)
|
||||
overlays += kb
|
||||
name = "[program.name] [initial(name)]"
|
||||
else if(os)
|
||||
overlays = list(os.overlay)
|
||||
if(show_keyboard)
|
||||
overlays += kb
|
||||
name = initial(name)
|
||||
else
|
||||
var/global/image/generic = image('icons/obj/computer3.dmi',icon_state="osod") // orange screen of death
|
||||
overlays = list(generic)
|
||||
if(show_keyboard)
|
||||
overlays += kb
|
||||
name = initial(name) + " (orange screen of death)"
|
||||
|
||||
/obj/machinery/computer3/wall_comp
|
||||
name = "terminal"
|
||||
icon = 'icons/obj/computer3.dmi'
|
||||
icon_state = "wallframe"
|
||||
density = 0
|
||||
pixel_y = -3
|
||||
show_keyboard = 0
|
||||
@@ -0,0 +1,34 @@
|
||||
/*
|
||||
1. Do NOT confuse Computer.Crash(errorcode) with byond CRASH(message)
|
||||
2 Do NOT talk about fight club.
|
||||
3 If this if your first night here, you have to crash the computer.
|
||||
4 Where am I?
|
||||
5 Someone help me, please...
|
||||
6. Be sure to use computer.use_power() appropriately. Laptops should run out of battery occasionally.
|
||||
7 Everyone fights, no-one quits. If you don't do your job, I'll crash you myself.
|
||||
6 Don't allow more than 42 angels to dance on the head of a pin.
|
||||
5. Once a computer has spawned, they are just like the rest, except when they aren't.
|
||||
4 Get me four glasses of apple juice.
|
||||
3. Components are only added or removed when disassembled and rebuilt. However, they may be EMP'd.
|
||||
2 Only you can prevent friendly fire.
|
||||
1 Do not talk about fight club.
|
||||
2. If a component subtype needs to be handled separately (removable drives, radio networks), declare it separately.
|
||||
3 Television rules the nation
|
||||
4. interactable() does all the sanity checks, adds fingerprints, sets machines, initializes popup, and makes a damn fine pot of coffee.
|
||||
5 Love conquers all.
|
||||
6 If at all possible, do a barrel roll.
|
||||
7. Don't forget to use the network verify function to make sure you still have access to remote machines.
|
||||
|
||||
|
||||
|
||||
|
||||
TODO:
|
||||
* "Nothing left to call the shuttle" check
|
||||
* Communications terminal printing - move it to a printer of some sort? Make a printer peripheral--but then which ones print the comms?
|
||||
* Remove the partially transparent border on program screens, as it clashes with some frames
|
||||
* Chop the corners on program screens now that screen sizes are standard
|
||||
* ntos:
|
||||
* Needs a text editor/viewer
|
||||
* Needs file copy and file move - I think I know how I'm gonna do it
|
||||
* Needs a peripheral view (eject disks and cards, network actions, ???)
|
||||
*/
|
||||
@@ -0,0 +1,254 @@
|
||||
/obj/machinery/computer3/HolodeckControl
|
||||
default_prog = /datum/file/program/holodeck
|
||||
|
||||
|
||||
// Todo: I personally would like to add a second holodeck in the theater for making appropriate playgrounds.
|
||||
// perhaps a holodeck association keyfile?
|
||||
// One more thing while I'm here
|
||||
// C3 allows multiple computers to run this program, but it was designed on the assumption that only one would, ever
|
||||
// I am not going to add or remove anything right now, I'm just porting it
|
||||
|
||||
|
||||
/datum/file/program/holodeck
|
||||
name = "Holodeck Control Console"
|
||||
desc = "Used to control a nearby holodeck."
|
||||
active_state = "holocontrol"
|
||||
var/area/linkedholodeck = null
|
||||
var/area/target = null
|
||||
var/active = 0
|
||||
var/list/holographic_items = list()
|
||||
var/damaged = 0
|
||||
var/last_change = 0
|
||||
var/emagged = 0
|
||||
|
||||
|
||||
interact()
|
||||
if(!interactable())
|
||||
return
|
||||
var/dat = "<h3>Current Loaded Programs</h3>"
|
||||
dat += "<A href='?src=\ref[src];emptycourt'>((Empty Court)</font>)</A><BR>"
|
||||
dat += "<A href='?src=\ref[src];boxingcourt'>((Boxing Court)</font>)</A><BR>"
|
||||
dat += "<A href='?src=\ref[src];basketball'>((Basketball Court)</font>)</A><BR>"
|
||||
dat += "<A href='?src=\ref[src];thunderdomecourt'>((Thunderdome Court)</font>)</A><BR>"
|
||||
dat += "<A href='?src=\ref[src];beach'>((Beach)</font>)</A><BR>"
|
||||
// dat += "<A href='?src=\ref[src];turnoff'>((Shutdown System)</font>)</A><BR>"
|
||||
|
||||
dat += "<span class='notice'>Please ensure that only holographic weapons are used in the holodeck if a combat simulation has been loaded.</span><BR>"
|
||||
|
||||
if(emagged)
|
||||
dat += "<A href='?src=\ref[src];burntest'>(<font color=red>Begin Atmospheric Burn Simulation</font>)</A><BR>"
|
||||
dat += "Ensure the holodeck is empty before testing.<BR>"
|
||||
dat += "<BR>"
|
||||
dat += "<A href='?src=\ref[src];wildlifecarp'>(<font color=red>Begin Wildlife Simulation</font>)</A><BR>"
|
||||
dat += "Ensure the holodeck is empty before testing.<BR>"
|
||||
dat += "<BR>"
|
||||
if(issilicon(usr))
|
||||
dat += "<A href='?src=\ref[src];AIoverride'>(<font color=green>Re-Enable Safety Protocols?</font>)</A><BR>"
|
||||
dat += "Safety Protocols are <font class='bad'>DISABLED</font><BR>"
|
||||
else
|
||||
if(issilicon(usr))
|
||||
dat += "<A href='?src=\ref[src];AIoverride'>(<font color=red>Override Safety Protocols?</font>)</A><BR>"
|
||||
dat += "<BR>"
|
||||
dat += "Safety Protocols are <font class='good'>ENABLED</font><BR>"
|
||||
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
return
|
||||
|
||||
|
||||
Topic(var/href, var/list/href_list)
|
||||
if(!interactable() || ..(href,href_list))
|
||||
return
|
||||
|
||||
if("emptycourt" in href_list)
|
||||
target = locate(/area/holodeck/source_emptycourt)
|
||||
if(target)
|
||||
loadProgram(target)
|
||||
|
||||
else if("boxingcourt" in href_list)
|
||||
target = locate(/area/holodeck/source_boxingcourt)
|
||||
if(target)
|
||||
loadProgram(target)
|
||||
|
||||
else if("basketball" in href_list)
|
||||
target = locate(/area/holodeck/source_basketball)
|
||||
if(target)
|
||||
loadProgram(target)
|
||||
|
||||
else if("thunderdomecourt" in href_list)
|
||||
target = locate(/area/holodeck/source_thunderdomecourt)
|
||||
if(target)
|
||||
loadProgram(target)
|
||||
|
||||
else if("beach" in href_list)
|
||||
target = locate(/area/holodeck/source_beach)
|
||||
if(target)
|
||||
loadProgram(target)
|
||||
|
||||
else if("turnoff" in href_list)
|
||||
target = locate(/area/holodeck/source_plating)
|
||||
if(target)
|
||||
loadProgram(target)
|
||||
|
||||
else if("burntest" in href_list)
|
||||
if(!emagged) return
|
||||
target = locate(/area/holodeck/source_burntest)
|
||||
if(target)
|
||||
loadProgram(target)
|
||||
|
||||
else if("wildlifecarp" in href_list)
|
||||
if(!emagged) return
|
||||
target = locate(/area/holodeck/source_wildlife)
|
||||
if(target)
|
||||
loadProgram(target)
|
||||
|
||||
else if("AIoverride" in href_list)
|
||||
if(!issilicon(usr)) return
|
||||
emagged = !emagged
|
||||
if(emagged)
|
||||
message_admins("[key_name_admin(usr)] overrode the holodeck's safeties")
|
||||
log_game("[key_name(usr)] overrided the holodeck's safeties")
|
||||
else
|
||||
message_admins("[key_name_admin(usr)] restored the holodeck's safeties")
|
||||
log_game("[key_name(usr)] restored the holodeck's safeties")
|
||||
|
||||
interact()
|
||||
return
|
||||
|
||||
Reset()
|
||||
emergencyShutdown()
|
||||
|
||||
process()
|
||||
if(active)
|
||||
if(!checkInteg(linkedholodeck))
|
||||
damaged = 1
|
||||
target = locate(/area/holodeck/source_plating)
|
||||
if(target)
|
||||
loadProgram(target)
|
||||
active = 0
|
||||
for(var/mob/M in range(10,src))
|
||||
M.show_message("The holodeck overloads!")
|
||||
|
||||
|
||||
for(var/turf/T in linkedholodeck)
|
||||
if(prob(30))
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
||||
s.set_up(2, 1, T)
|
||||
s.start()
|
||||
T.ex_act(3)
|
||||
T.hotspot_expose(1000,500,1)
|
||||
|
||||
|
||||
for(var/item in holographic_items)
|
||||
if(!(get_turf(item) in linkedholodeck))
|
||||
derez(item, 0)
|
||||
|
||||
|
||||
|
||||
proc/derez(var/obj/obj , var/silent = 1)
|
||||
holographic_items.Remove(obj)
|
||||
|
||||
if(obj == null)
|
||||
return
|
||||
|
||||
if(isobj(obj))
|
||||
var/mob/M = obj.loc
|
||||
if(ismob(M))
|
||||
M.u_equip(obj)
|
||||
M.update_icons() //so their overlays update
|
||||
|
||||
if(!silent)
|
||||
var/obj/oldobj = obj
|
||||
obj.visible_message("The [oldobj.name] fades away!")
|
||||
del(obj)
|
||||
|
||||
proc/checkInteg(var/area/A)
|
||||
for(var/turf/T in A)
|
||||
if(istype(T, /turf/space))
|
||||
return 0
|
||||
|
||||
return 1
|
||||
|
||||
proc/togglePower(var/toggleOn = 0)
|
||||
|
||||
if(toggleOn)
|
||||
var/area/targetsource = locate(/area/holodeck/source_emptycourt)
|
||||
holographic_items = targetsource.copy_contents_to(linkedholodeck)
|
||||
|
||||
spawn(30)
|
||||
for(var/obj/effect/landmark/L in linkedholodeck)
|
||||
if(L.name=="Atmospheric Test Start")
|
||||
spawn(20)
|
||||
var/turf/T = get_turf(L)
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
||||
s.set_up(2, 1, T)
|
||||
s.start()
|
||||
if(T)
|
||||
T.temperature = 5000
|
||||
T.hotspot_expose(50000,50000,1)
|
||||
|
||||
active = 1
|
||||
else
|
||||
for(var/item in holographic_items)
|
||||
derez(item)
|
||||
var/area/targetsource = locate(/area/holodeck/source_plating)
|
||||
targetsource.copy_contents_to(linkedholodeck , 1)
|
||||
active = 0
|
||||
|
||||
|
||||
proc/loadProgram(var/area/A)
|
||||
|
||||
if(world.time < (last_change + 25))
|
||||
if(world.time < (last_change + 15))//To prevent super-spam clicking, reduced process size and annoyance -Sieve
|
||||
return
|
||||
for(var/mob/M in range(3,src))
|
||||
M.show_message("\b ERROR. Recalibrating projetion apparatus.")
|
||||
last_change = world.time
|
||||
return
|
||||
|
||||
last_change = world.time
|
||||
active = 1
|
||||
|
||||
for(var/item in holographic_items)
|
||||
derez(item)
|
||||
|
||||
for(var/obj/effect/decal/cleanable/blood/B in linkedholodeck)
|
||||
del(B)
|
||||
|
||||
for(var/mob/living/simple_animal/hostile/carp/C in linkedholodeck)
|
||||
del(C)
|
||||
|
||||
holographic_items = A.copy_contents_to(linkedholodeck , 1)
|
||||
|
||||
if(emagged)
|
||||
for(var/obj/item/weapon/holo/esword/H in linkedholodeck)
|
||||
H.damtype = BRUTE
|
||||
|
||||
spawn(30)
|
||||
for(var/obj/effect/landmark/L in linkedholodeck)
|
||||
if(L.name=="Atmospheric Test Start")
|
||||
spawn(20)
|
||||
var/turf/T = get_turf(L)
|
||||
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
|
||||
s.set_up(2, 1, T)
|
||||
s.start()
|
||||
if(T)
|
||||
T.temperature = 5000
|
||||
T.hotspot_expose(50000,50000,1)
|
||||
if(L.name=="Holocarp Spawn")
|
||||
new /mob/living/simple_animal/hostile/carp(L.loc)
|
||||
|
||||
|
||||
proc/emergencyShutdown()
|
||||
//Get rid of any items
|
||||
for(var/item in holographic_items)
|
||||
derez(item)
|
||||
//Turn it back to the regular non-holographic room
|
||||
target = locate(/area/holodeck/source_plating)
|
||||
if(target)
|
||||
loadProgram(target)
|
||||
|
||||
var/area/targetsource = locate(/area/holodeck/source_plating)
|
||||
targetsource.copy_contents_to(linkedholodeck , 1)
|
||||
active = 0
|
||||
|
||||
@@ -0,0 +1,47 @@
|
||||
/obj/machinery/computer3/operating
|
||||
default_prog = /datum/file/program/op_monitor
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/networking/prox)
|
||||
icon_state = "frame-med"
|
||||
|
||||
/datum/file/program/op_monitor
|
||||
name = "operating table monitor"
|
||||
desc = "Monitors patient status during surgery."
|
||||
active_state = "operating"
|
||||
var/mob/living/carbon/human/patient = null
|
||||
var/obj/machinery/optable/table = null
|
||||
|
||||
|
||||
/datum/file/program/op_monitor/interact()
|
||||
if(!interactable())
|
||||
return
|
||||
if(!computer.net)
|
||||
computer.Crash(MISSING_PERIPHERAL)
|
||||
return
|
||||
table = computer.net.connect_to(/obj/machinery/optable,table)
|
||||
|
||||
var/dat = ""
|
||||
if(table)
|
||||
dat += "<B>Patient information:</B><BR>"
|
||||
if(src.table && (src.table.check_victim()))
|
||||
src.patient = src.table.victim
|
||||
dat += {"<B>Patient Status:</B> [patient.stat ? "Non-Responsive" : "Stable"]<BR>
|
||||
<B>Blood Type:</B> [patient.b_type]<BR>
|
||||
<BR>
|
||||
<B>Health:</B> [round(patient.health)]<BR>
|
||||
<B>Brute Damage:</B> [round(patient.getBruteLoss())]<BR>
|
||||
<B>Toxins Damage:</B> [round(patient.getToxLoss())]<BR>
|
||||
<B>Fire Damage:</B> [round(patient.getFireLoss())]<BR>
|
||||
<B>Suffocation Damage:</B> [round(patient.getOxyLoss())]<BR>
|
||||
"}
|
||||
else
|
||||
src.patient = null
|
||||
dat += "<B>No patient detected</B>"
|
||||
else
|
||||
dat += "<B>Operating table not found.</B>"
|
||||
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
/datum/file/program/op_monitor/Topic()
|
||||
if(!interactable())
|
||||
return
|
||||
..()
|
||||
@@ -0,0 +1,117 @@
|
||||
/obj/machinery/computer3/aifixer
|
||||
default_prog = /datum/file/program/aifixer
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd/big,/obj/item/part/computer/ai_holder)
|
||||
icon_state = "frame-rnd"
|
||||
|
||||
|
||||
/datum/file/program/aifixer
|
||||
name = "AI system integrity restorer"
|
||||
desc = "Repairs and revives artificial intelligence cores."
|
||||
image = 'icons/ntos/airestore.png'
|
||||
active_state = "ai-fixer-empty"
|
||||
req_access = list(access_captain, access_robotics, access_heads)
|
||||
|
||||
update_icon()
|
||||
if(!computer || !computer.cradle)
|
||||
overlay.icon_state = "ai-fixer-404"
|
||||
return // what
|
||||
|
||||
if(!computer.cradle.occupant)
|
||||
overlay.icon_state = "ai-fixer-empty"
|
||||
else
|
||||
if (computer.cradle.occupant.health >= 0 && computer.cradle.occupant.stat != 2)
|
||||
overlay.icon_state = "ai-fixer-full"
|
||||
else
|
||||
overlay.icon_state = "ai-fixer-404"
|
||||
computer.update_icon()
|
||||
|
||||
interact()
|
||||
if(!interactable())
|
||||
return
|
||||
|
||||
if(!computer.cradle)
|
||||
computer.Crash(MISSING_PERIPHERAL)
|
||||
return
|
||||
|
||||
popup.set_content(aifixer_menu())
|
||||
popup.open()
|
||||
return
|
||||
|
||||
proc/aifixer_menu()
|
||||
var/dat = ""
|
||||
if (computer.cradle.occupant)
|
||||
var/laws
|
||||
dat += "<h3>Stored AI: [computer.cradle.occupant.name]</h3>"
|
||||
dat += "<b>System integrity:</b> [(computer.cradle.occupant.health+100)/2]%<br>"
|
||||
|
||||
if (computer.cradle.occupant.laws.zeroth)
|
||||
laws += "<b>0:</b> [computer.cradle.occupant.laws.zeroth]<BR>"
|
||||
|
||||
var/number = 1
|
||||
for (var/index = 1, index <= computer.cradle.occupant.laws.inherent.len, index++)
|
||||
var/law = computer.cradle.occupant.laws.inherent[index]
|
||||
if (length(law) > 0)
|
||||
laws += "<b>[number]:</b> [law]<BR>"
|
||||
number++
|
||||
|
||||
for (var/index = 1, index <= computer.cradle.occupant.laws.supplied.len, index++)
|
||||
var/law = computer.cradle.occupant.laws.supplied[index]
|
||||
if (length(law) > 0)
|
||||
laws += "<b>[number]:</b> [law]<BR>"
|
||||
number++
|
||||
|
||||
dat += "<b>Laws:</b><br>[laws]<br>"
|
||||
|
||||
if (computer.cradle.occupant.stat == 2)
|
||||
dat += "<span class='bad'>AI non-functional</span>"
|
||||
else
|
||||
dat += "<span class='good'>AI functional</span>"
|
||||
if (!computer.cradle.busy)
|
||||
dat += "<br><br>[topic_link(src,"fix","Begin Reconstruction")]"
|
||||
else
|
||||
dat += "<br><br>Reconstruction in process, please wait.<br>"
|
||||
dat += "<br>[topic_link(src,"close","Close")]"
|
||||
return dat
|
||||
|
||||
Topic(var/href, var/list/href_list)
|
||||
if(!interactable() || !computer.cradle || ..(href,href_list))
|
||||
return
|
||||
|
||||
if ("fix" in href_list)
|
||||
var/mob/living/silicon/ai/occupant = computer.cradle.occupant
|
||||
if(!occupant) return
|
||||
|
||||
computer.cradle.busy = 1
|
||||
computer.overlays += image('icons/obj/computer.dmi', "ai-fixer-on")
|
||||
|
||||
var/i = 0
|
||||
while (occupant.health < 100)
|
||||
if(!computer || (computer.stat&~MAINT)) // takes some time, keep checking
|
||||
break
|
||||
|
||||
occupant.adjustOxyLoss(-1)
|
||||
occupant.adjustFireLoss(-1)
|
||||
occupant.adjustToxLoss(-1)
|
||||
occupant.adjustBruteLoss(-1)
|
||||
occupant.updatehealth()
|
||||
if (occupant.health >= 0 && computer.cradle.occupant.stat == 2)
|
||||
occupant.stat = 0
|
||||
occupant.lying = 0
|
||||
dead_mob_list -= occupant
|
||||
living_mob_list += occupant
|
||||
update_icon()
|
||||
|
||||
i++
|
||||
if(i == 5)
|
||||
computer.use_power(50) // repairing an AI is nontrivial. laptop battery may not be enough.
|
||||
computer.power_change() // if the power runs out, set stat
|
||||
i = 0
|
||||
|
||||
computer.updateUsrDialog()
|
||||
|
||||
sleep(10)
|
||||
computer.cradle.busy = 0
|
||||
computer.overlays -= image('icons/obj/computer.dmi', "ai-fixer-on")
|
||||
|
||||
computer.updateUsrDialog()
|
||||
return
|
||||
@@ -0,0 +1,180 @@
|
||||
/obj/machinery/computer3/arcade
|
||||
default_prog = /datum/file/program/arcade
|
||||
spawn_parts = list(/obj/item/part/computer/toybox) //NO HDD - the game is loaded on the circuitboard's OS slot
|
||||
|
||||
/obj/item/part/computer/toybox
|
||||
var/list/prizes = list( /obj/item/weapon/storage/box/snappops = 2,
|
||||
/obj/item/toy/blink = 2,
|
||||
/obj/item/clothing/under/syndicate/tacticool = 2,
|
||||
/obj/item/toy/sword = 2,
|
||||
/obj/item/toy/gun = 2,
|
||||
/obj/item/toy/crossbow = 2,
|
||||
/obj/item/clothing/suit/syndicatefake = 2,
|
||||
/obj/item/weapon/storage/fancy/crayons = 2,
|
||||
/obj/item/toy/spinningtoy = 2,
|
||||
/obj/item/toy/prize/ripley = 1,
|
||||
/obj/item/toy/prize/fireripley = 1,
|
||||
/obj/item/toy/prize/deathripley = 1,
|
||||
/obj/item/toy/prize/gygax = 1,
|
||||
/obj/item/toy/prize/durand = 1,
|
||||
/obj/item/toy/prize/honk = 1,
|
||||
/obj/item/toy/prize/marauder = 1,
|
||||
/obj/item/toy/prize/seraph = 1,
|
||||
/obj/item/toy/prize/mauler = 1,
|
||||
/obj/item/toy/prize/odysseus = 1,
|
||||
/obj/item/toy/prize/phazon = 1
|
||||
)
|
||||
proc/dispense()
|
||||
if(computer && !computer.stat)
|
||||
var/prizeselect = pickweight(prizes)
|
||||
new prizeselect(computer.loc)
|
||||
if(istype(prizeselect, /obj/item/toy/gun)) //Ammo comes with the gun
|
||||
new /obj/item/toy/ammo/gun(computer.loc)
|
||||
else if(istype(prizeselect, /obj/item/clothing/suit/syndicatefake)) //Helmet is part of the suit
|
||||
new /obj/item/clothing/head/syndicatefake(computer.loc)
|
||||
feedback_inc("arcade_win_normal")
|
||||
computer.use_power(500)
|
||||
|
||||
|
||||
/datum/file/program/arcade
|
||||
desc = "The best arcade game ever produced by Nanotrasen's short-lived entertainment divison."
|
||||
//headcanon: they also ported E.T. for the atari 2600, superman 64, and basically every other movie tie-in game ever
|
||||
|
||||
active_state = "generic"
|
||||
|
||||
var/turtle = 0
|
||||
var/enemy_name = "Space Villian"
|
||||
var/temp = "Winners Don't Use Spacedrugs" //Temporary message, for attack messages, etc
|
||||
var/player_hp = 30 //Player health/attack points
|
||||
var/player_mp = 10
|
||||
var/enemy_hp = 45 //Enemy health/attack points
|
||||
var/enemy_mp = 20
|
||||
var/gameover = 0
|
||||
var/blocked = 0 //Player cannot attack/heal while set
|
||||
|
||||
/datum/file/program/arcade/New()
|
||||
..()
|
||||
var/name_action
|
||||
var/name_part1
|
||||
var/name_part2
|
||||
|
||||
name_action = pick("Defeat ", "Annihilate ", "Save ", "Strike ", "Stop ", "Destroy ", "Robust ", "Romance ", "Pwn ", "Own ", "ERP ")
|
||||
|
||||
name_part1 = pick("the Automatic ", "Farmer ", "Lord ", "Professor ", "the Cuban ", "the Evil ", "the Dread King ", "the Space ", "Lord ", "the Great ", "Duke ", "General ")
|
||||
name_part2 = pick("Melonoid", "Murdertron", "Sorcerer", "Ruin", "Jeff", "Ectoplasm", "Crushulon", "Uhangoid", "Vhakoid", "Peteoid", "slime", "Griefer", "ERPer", "Lizard Man", "Unicorn")
|
||||
|
||||
enemy_name = replacetext(name_part1, "the ", "") + name_part2
|
||||
name = (name_action + name_part1 + name_part2)
|
||||
|
||||
|
||||
/datum/file/program/arcade/interact()
|
||||
if(!interactable())
|
||||
return
|
||||
var/dat// = topic_link(src,"close","Close")
|
||||
dat = "<center><h4>[enemy_name]</h4></center>"
|
||||
|
||||
dat += "<br><center><h3>[temp]</h3></center>"
|
||||
dat += "<br><center>Health: [player_hp] | Magic: [player_mp] | Enemy Health: [enemy_hp]</center>"
|
||||
|
||||
if (gameover)
|
||||
dat += "<center><b>[topic_link(src,"newgame","New Game")]"
|
||||
else
|
||||
dat += "<center><b>[topic_link(src,"attack","Attack")] | [topic_link(src,"heal","Heal")] | [topic_link(src,"charge","Recharge Power")]"
|
||||
|
||||
dat += "</b></center>"
|
||||
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
/datum/file/program/arcade/Topic(href, list/href_list)
|
||||
if(!interactable() || ..(href,href_list))
|
||||
return
|
||||
if (!blocked && !gameover)
|
||||
if ("attack" in href_list)
|
||||
blocked = 1
|
||||
var/attackamt = rand(2,6)
|
||||
temp = "You attack for [attackamt] damage!"
|
||||
computer.updateUsrDialog()
|
||||
if(turtle > 0)
|
||||
turtle--
|
||||
|
||||
sleep(10)
|
||||
enemy_hp -= attackamt
|
||||
arcade_action()
|
||||
|
||||
else if ("heal" in href_list)
|
||||
blocked = 1
|
||||
var/pointamt = rand(1,3)
|
||||
var/healamt = rand(6,8)
|
||||
temp = "You use [pointamt] magic to heal for [healamt] damage!"
|
||||
computer.updateUsrDialog()
|
||||
turtle++
|
||||
|
||||
sleep(10)
|
||||
player_mp -= pointamt
|
||||
player_hp += healamt
|
||||
blocked = 1
|
||||
computer.updateUsrDialog()
|
||||
arcade_action()
|
||||
|
||||
else if ("charge" in href_list)
|
||||
blocked = 1
|
||||
var/chargeamt = rand(4,7)
|
||||
temp = "You regain [chargeamt] points"
|
||||
player_mp += chargeamt
|
||||
if(turtle > 0)
|
||||
turtle--
|
||||
|
||||
computer.updateUsrDialog()
|
||||
sleep(10)
|
||||
arcade_action()
|
||||
|
||||
if ("newgame" in href_list) //Reset everything
|
||||
temp = "New Round"
|
||||
player_hp = 30
|
||||
player_mp = 10
|
||||
enemy_hp = 45
|
||||
enemy_mp = 20
|
||||
gameover = 0
|
||||
turtle = 0
|
||||
computer.updateUsrDialog()
|
||||
|
||||
|
||||
/datum/file/program/arcade/proc/arcade_action()
|
||||
if ((enemy_mp <= 0) || (enemy_hp <= 0))
|
||||
if(!gameover)
|
||||
gameover = 1
|
||||
temp = "[enemy_name] has fallen! Rejoice!"
|
||||
if(computer.toybox)
|
||||
computer.toybox.dispense()
|
||||
|
||||
else if ((enemy_mp <= 5) && (prob(70)))
|
||||
var/stealamt = rand(2,3)
|
||||
temp = "[enemy_name] steals [stealamt] of your power!"
|
||||
player_mp -= stealamt
|
||||
|
||||
if (player_mp <= 0)
|
||||
gameover = 1
|
||||
sleep(10)
|
||||
temp = "You have been drained! GAME OVER"
|
||||
feedback_inc("arcade_loss_mana_normal")
|
||||
|
||||
else if ((enemy_hp <= 10) && (enemy_mp > 4))
|
||||
temp = "[enemy_name] heals for 4 health!"
|
||||
enemy_hp += 4
|
||||
enemy_mp -= 4
|
||||
|
||||
else
|
||||
var/attackamt = rand(3,6)
|
||||
temp = "[enemy_name] attacks for [attackamt] damage!"
|
||||
player_hp -= attackamt
|
||||
|
||||
if ((player_mp <= 0) || (player_hp <= 0))
|
||||
gameover = 1
|
||||
temp = "You have been crushed! GAME OVER"
|
||||
feedback_inc("arcade_loss_hp_normal")
|
||||
|
||||
if(interactable())
|
||||
computer.updateUsrDialog()
|
||||
blocked = 0
|
||||
return
|
||||
@@ -0,0 +1,110 @@
|
||||
/obj/machinery/computer3/atmos_alert
|
||||
default_prog = /datum/file/program/atmos_alert
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/networking/radio)
|
||||
icon_state = "frame-eng"
|
||||
|
||||
/datum/file/program/atmos_alert
|
||||
name = "atmospheric alert monitor"
|
||||
desc = "Recieves alerts over the radio."
|
||||
active_state = "alert:2"
|
||||
refresh = 1
|
||||
var/list/priority_alarms = list()
|
||||
var/list/minor_alarms = list()
|
||||
|
||||
|
||||
execute(var/datum/file/program/source)
|
||||
..(source)
|
||||
|
||||
if(!computer.radio)
|
||||
computer.Crash(MISSING_PERIPHERAL)
|
||||
|
||||
computer.radio.set_frequency(1437,RADIO_ATMOSIA)
|
||||
|
||||
|
||||
Reset()
|
||||
..()
|
||||
// Never save your work
|
||||
priority_alarms.Cut()
|
||||
minor_alarms.Cut()
|
||||
|
||||
|
||||
// This will be called as long as the program is running on the parent computer
|
||||
// and the computer has the radio peripheral
|
||||
receive_signal(datum/signal/signal)
|
||||
if(!signal || signal.encryption) return
|
||||
|
||||
var/zone = signal.data["zone"]
|
||||
var/severity = signal.data["alert"]
|
||||
if(!zone || !severity) return
|
||||
|
||||
minor_alarms -= zone
|
||||
priority_alarms -= zone
|
||||
if(severity=="severe")
|
||||
priority_alarms += zone
|
||||
else if (severity=="minor")
|
||||
minor_alarms += zone
|
||||
update_icon()
|
||||
return
|
||||
|
||||
|
||||
interact()
|
||||
if(!interactable())
|
||||
return
|
||||
if(!computer.radio)
|
||||
computer.Crash(MISSING_PERIPHERAL)
|
||||
|
||||
popup.set_content(return_text())
|
||||
popup.open()
|
||||
|
||||
|
||||
update_icon()
|
||||
..()
|
||||
if(priority_alarms.len > 0)
|
||||
overlay.icon_state = "alert:2"
|
||||
else if(minor_alarms.len > 0)
|
||||
overlay.icon_state = "alert:1"
|
||||
else
|
||||
overlay.icon_state = "alert:0"
|
||||
|
||||
if(computer)
|
||||
computer.update_icon()
|
||||
|
||||
|
||||
proc/return_text()
|
||||
var/priority_text = "<h2>Priority Alerts:</h2>"
|
||||
var/minor_text = "<h2>Minor Alerts:</h2>"
|
||||
|
||||
if(priority_alarms.len)
|
||||
for(var/zone in priority_alarms)
|
||||
priority_text += "<FONT color='red'><B>[format_text(zone)]</B></FONT> [topic_link(src,"priority_clear=[ckey(zone)]","X")]<BR>"
|
||||
else
|
||||
priority_text += "No priority alerts detected.<BR>"
|
||||
|
||||
if(minor_alarms.len)
|
||||
for(var/zone in minor_alarms)
|
||||
minor_text += "<B>[format_text(zone)]</B> [topic_link(src,"minor_clear=[ckey(zone)]","X")]<BR>"
|
||||
else
|
||||
minor_text += "No minor alerts detected.<BR>"
|
||||
|
||||
return "[priority_text]<BR><HR>[minor_text]<BR>[topic_link(src,"close","Close")]"
|
||||
|
||||
|
||||
Topic(var/href, var/list/href_list)
|
||||
if(!interactable() || ..(href,href_list))
|
||||
return
|
||||
|
||||
if("priority_clear" in href_list)
|
||||
var/removing_zone = href_list["priority_clear"]
|
||||
for(var/zone in priority_alarms)
|
||||
if(ckey(zone) == removing_zone)
|
||||
usr << "\green Priority Alert for area [zone] cleared."
|
||||
priority_alarms -= zone
|
||||
|
||||
if("minor_clear" in href_list)
|
||||
var/removing_zone = href_list["minor_clear"]
|
||||
for(var/zone in minor_alarms)
|
||||
if(ckey(zone) == removing_zone)
|
||||
usr << "\green Minor Alert for area [zone] cleared."
|
||||
minor_alarms -= zone
|
||||
|
||||
computer.updateUsrDialog()
|
||||
@@ -0,0 +1,277 @@
|
||||
/*
|
||||
Camera monitoring computers
|
||||
|
||||
NOTE: If we actually split the station camera network into regions that will help with sorting through the
|
||||
tediously large list of cameras. The new camnet_key architecture lets you switch between keys easily,
|
||||
so you don't lose the capability of seeing everything, you just switch to a subnet.
|
||||
*/
|
||||
|
||||
/obj/machinery/computer3/security
|
||||
default_prog = /datum/file/program/security
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/networking/cameras)
|
||||
spawn_files = list(/datum/file/camnet_key)
|
||||
icon_state = "frame-sec"
|
||||
|
||||
|
||||
/obj/machinery/computer3/security/wooden_tv
|
||||
name = "security cameras"
|
||||
desc = "An old TV hooked into the stations camera network."
|
||||
icon = 'icons/obj/computer.dmi'
|
||||
icon_state = "security_det"
|
||||
|
||||
legacy_icon = 1
|
||||
allow_disassemble = 0
|
||||
|
||||
// No operating system
|
||||
New()
|
||||
..(built=0)
|
||||
os = program
|
||||
circuit.OS = os
|
||||
|
||||
|
||||
/obj/machinery/computer3/security/mining
|
||||
name = "Outpost Cameras"
|
||||
desc = "Used to access the various cameras on the outpost."
|
||||
spawn_files = list(/datum/file/camnet_key/mining)
|
||||
|
||||
/*
|
||||
Camera monitoring computers, wall-mounted
|
||||
*/
|
||||
/obj/machinery/computer3/wall_comp/telescreen
|
||||
default_prog = /datum/file/program/security
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/networking/cameras)
|
||||
spawn_files = list(/datum/file/camnet_key)
|
||||
|
||||
/obj/machinery/computer3/wall_comp/telescreen/entertainment
|
||||
desc = "Damn, they better have /tg/thechannel on these things."
|
||||
spawn_files = list(/datum/file/camnet_key/entertainment)
|
||||
|
||||
|
||||
/*
|
||||
File containing an encrypted camera network key.
|
||||
|
||||
(Where by encrypted I don't actually mean encrypted at all)
|
||||
*/
|
||||
/datum/file/camnet_key
|
||||
name = "Security Camera Network Main Key"
|
||||
var/title = "Station"
|
||||
var/desc = "Connects to station security cameras."
|
||||
var/list/networks = list("SS13")
|
||||
var/screen = "cameras"
|
||||
|
||||
execute(var/datum/file/source)
|
||||
if(istype(source,/datum/file/program/security))
|
||||
var/datum/file/program/security/prog = source
|
||||
prog.key = src
|
||||
prog.camera_list = null
|
||||
return
|
||||
if(istype(source,/datum/file/program/ntos))
|
||||
for(var/obj/item/part/computer/storage/S in list(computer.hdd,computer.floppy))
|
||||
for(var/datum/file/F in S.files)
|
||||
if(istype(F,/datum/file/program/security))
|
||||
var/datum/file/program/security/Sec = F
|
||||
Sec.key = src
|
||||
Sec.camera_list = null
|
||||
Sec.execute(source)
|
||||
return
|
||||
computer.Crash(MISSING_PROGRAM)
|
||||
|
||||
/datum/file/camnet_key/mining
|
||||
name = "Mining Camera Network Key"
|
||||
title = "mining station"
|
||||
desc = "Connects to mining security cameras."
|
||||
networks = list("MINE")
|
||||
screen = "miningcameras"
|
||||
|
||||
/datum/file/camnet_key/research
|
||||
name = "Research Camera Network Key"
|
||||
title = "research"
|
||||
networks = list("RD")
|
||||
|
||||
/datum/file/camnet_key/bombrange
|
||||
name = "R&D Bomb Range Camera Network Key"
|
||||
title = "bomb range"
|
||||
desc = "Monitors the bomb range."
|
||||
networks = list("Toxins")
|
||||
|
||||
/datum/file/camnet_key/xeno
|
||||
name = "R&D Misc. Research Camera Network Key"
|
||||
title = "special research"
|
||||
networks = list("Misc")
|
||||
|
||||
/datum/file/camnet_key/singulo
|
||||
name = "Singularity Camera Network Key"
|
||||
title = "singularity"
|
||||
networks = list("Singularity")
|
||||
|
||||
/datum/file/camnet_key/entertainment
|
||||
name = "Entertainment Channel Encryption Key"
|
||||
title = "entertainment"
|
||||
desc = "Damn, I hope they have /tg/thechannel on here."
|
||||
networks = list("thunder")
|
||||
screen = "entertainment"
|
||||
|
||||
/datum/file/camnet_key/creed
|
||||
name = "Special Ops Camera Encryption Key"
|
||||
title = "special ops"
|
||||
desc = "Connects to special ops secure camera feeds."
|
||||
networks = list("CREED")
|
||||
|
||||
/datum/file/camnet_key/prison
|
||||
name = "Prison Camera Network Key"
|
||||
title = "prison"
|
||||
desc = "Monitors the prison."
|
||||
networks = list("Prison")
|
||||
|
||||
|
||||
|
||||
/*
|
||||
Computer part needed to connect to cameras
|
||||
*/
|
||||
|
||||
/obj/item/part/computer/networking/cameras
|
||||
name = "camera network access module"
|
||||
desc = "Connects a computer to the camera network."
|
||||
|
||||
// I have no idea what the following does
|
||||
var/mapping = 0//For the overview file, interesting bit of code.
|
||||
|
||||
//proc/camera_list(var/datum/file/camnet_key/key)
|
||||
get_machines(var/datum/file/camnet_key/key)
|
||||
if (!computer || computer.z > 6)
|
||||
return null
|
||||
|
||||
var/list/L = list()
|
||||
for(var/obj/machinery/camera/C in cameranet.cameras)
|
||||
var/list/temp = C.network & key.networks
|
||||
if(temp.len)
|
||||
L.Add(C)
|
||||
|
||||
//camera_sort(L)
|
||||
|
||||
return L
|
||||
verify_machine(var/obj/machinery/camera/C,var/datum/file/camnet_key/key = null)
|
||||
if(!istype(C) || !C.can_use())
|
||||
return 0
|
||||
|
||||
if(key)
|
||||
var/list/temp = C.network & key.networks
|
||||
if(!temp.len)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/*
|
||||
Camera monitoring program
|
||||
|
||||
The following things should break you out of the camera view:
|
||||
* The computer resetting, being damaged, losing power, etc
|
||||
* The program quitting
|
||||
* Closing the window
|
||||
* Going out of range of the computer
|
||||
* Becoming incapacitated
|
||||
* The camera breaking, emping, disconnecting, etc
|
||||
*/
|
||||
|
||||
/datum/file/program/security
|
||||
name = "camera monitor"
|
||||
desc = "Connets to the Nanotrasen Camera Network"
|
||||
image = 'icons/ntos/camera.png'
|
||||
active_state = "camera-static"
|
||||
|
||||
var/datum/file/camnet_key/key = null
|
||||
var/last_pic = 1.0
|
||||
var/last_camera_refresh = 0
|
||||
var/camera_list = null
|
||||
|
||||
var/obj/machinery/camera/current = null
|
||||
|
||||
execute(var/datum/file/program/caller)
|
||||
..(caller)
|
||||
if(computer && !key)
|
||||
var/list/fkeys = computer.list_files(/datum/file/camnet_key)
|
||||
if(fkeys && fkeys.len)
|
||||
key = fkeys[1]
|
||||
update_icon()
|
||||
computer.update_icon()
|
||||
for(var/mob/living/L in viewers(1))
|
||||
if(!istype(L,/mob/living/silicon/ai) && L.machine == src)
|
||||
L.reset_view(null)
|
||||
|
||||
|
||||
Reset()
|
||||
..()
|
||||
current = null
|
||||
for(var/mob/living/L in viewers(1))
|
||||
if(!istype(L,/mob/living/silicon/ai) && L.machine == src)
|
||||
L.reset_view(null)
|
||||
|
||||
interact()
|
||||
if(!interactable())
|
||||
return
|
||||
|
||||
if(!computer.camnet)
|
||||
computer.Crash(MISSING_PERIPHERAL)
|
||||
return
|
||||
|
||||
if(!key)
|
||||
var/list/fkeys = computer.list_files(/datum/file/camnet_key)
|
||||
if(fkeys && fkeys.len)
|
||||
key = fkeys[1]
|
||||
update_icon()
|
||||
computer.update_icon()
|
||||
if(!key)
|
||||
return
|
||||
|
||||
if(computer.camnet.verify_machine(current))
|
||||
usr.reset_view(current)
|
||||
|
||||
if(world.time - last_camera_refresh > 50 || !camera_list)
|
||||
last_camera_refresh = world.time
|
||||
|
||||
var/list/temp_list = computer.camnet.get_machines(key)
|
||||
|
||||
camera_list = "Network Key: [key.title] [topic_link(src,"keyselect","\[ Select key \]")]<hr>"
|
||||
for(var/obj/machinery/camera/C in temp_list)
|
||||
if(C.status)
|
||||
camera_list += "[C.c_tag] - [topic_link(src,"show=\ref[C]","Show")]<br>"
|
||||
else
|
||||
camera_list += "[C.c_tag] - <b>DEACTIVATED</b><br>"
|
||||
//camera_list += "<br>" + topic_link(src,"close","Close")
|
||||
|
||||
popup.set_content(camera_list)
|
||||
popup.open()
|
||||
|
||||
|
||||
update_icon()
|
||||
if(key)
|
||||
overlay.icon_state = key.screen
|
||||
name = key.title + " Camera Monitor"
|
||||
else
|
||||
overlay.icon_state = "camera-static"
|
||||
name = initial(name)
|
||||
|
||||
|
||||
|
||||
Topic(var/href,var/list/href_list)
|
||||
if(!interactable() || !computer.camnet || ..(href,href_list))
|
||||
return
|
||||
|
||||
if("show" in href_list)
|
||||
var/obj/machinery/camera/C = locate(href_list["show"])
|
||||
current = C
|
||||
usr.reset_view(C)
|
||||
interact()
|
||||
return
|
||||
|
||||
if("keyselect" in href_list)
|
||||
current = null
|
||||
usr.reset_view(null)
|
||||
key = input(usr,"Select a camera network key:", "Key Select", null) as null|anything in computer.list_files(/datum/file/camnet_key)
|
||||
camera_list = null
|
||||
update_icon()
|
||||
computer.update_icon()
|
||||
if(key)
|
||||
interact()
|
||||
else
|
||||
usr << "The screen turns to static."
|
||||
return
|
||||
@@ -0,0 +1,347 @@
|
||||
/obj/machinery/computer3/card
|
||||
default_prog = /datum/file/program/card_comp
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/cardslot/dual)
|
||||
/obj/machinery/computer3/card/hop
|
||||
default_prog = /datum/file/program/card_comp
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/cardslot/dual)
|
||||
spawn_files = list(/datum/file/program/arcade, /datum/file/program/security, /datum/file/camnet_key/mining, /datum/file/camnet_key/entertainment,/datum/file/camnet_key/prison)
|
||||
|
||||
|
||||
/obj/machinery/computer3/card/centcom
|
||||
default_prog = /datum/file/program/card_comp/centcom
|
||||
|
||||
/datum/file/program/card_comp
|
||||
name = "identification card console"
|
||||
desc = "Used to modify magnetic strip ID cards."
|
||||
image = 'icons/ntos/cardcomp.png'
|
||||
active_state = "id"
|
||||
|
||||
var/obj/item/weapon/card/id/reader = null
|
||||
var/obj/item/weapon/card/id/writer = null
|
||||
|
||||
var/mode = 0
|
||||
var/auth = 0
|
||||
var/printing = 0
|
||||
|
||||
proc/list_jobs()
|
||||
return get_all_jobs() + "Custom"
|
||||
|
||||
// creates the block with the script in it
|
||||
// cache the result since it's almost constant but not quite
|
||||
// the list of jobs won't change after all...
|
||||
proc/scriptblock()
|
||||
var/global/dat = null
|
||||
var/counter = 0
|
||||
var jobs_all = ""
|
||||
jobs_all += "<table><tr><td></td><td><b>Command</b></td>"
|
||||
|
||||
jobs_all += "</tr><tr height='20'><td><b>Special</b></font></td>"//Captain in special because he is head of heads ~Intercross21
|
||||
jobs_all += "<td weight='100'><a href='?src=\ref[src];;assign=Captain'>Captain</a></td>"
|
||||
jobs_all += "<td weight='100'><a href='?src=\ref[src];;assign=Custom'>Custom</a></td>"
|
||||
|
||||
counter = 0
|
||||
jobs_all += "</tr><tr><td><font color='#A50000'><b>Security</b></font></td>"//Red
|
||||
for(var/job in security_positions)
|
||||
counter++
|
||||
if(counter >= 6)
|
||||
jobs_all += "</tr><tr height='20'><td></td><td></td>"
|
||||
counter = 0
|
||||
jobs_all += "<td height='20' weight='100'><a href='?src=\ref[src];assign=[job]'>[replacetext(job, " ", " ")]</a></td>"
|
||||
|
||||
counter = 0
|
||||
jobs_all += "</tr><tr><td><font color='#FFA500'><b>Engineering</b></font></td>"//Orange
|
||||
for(var/job in engineering_positions)
|
||||
counter++
|
||||
if(counter >= 6)
|
||||
jobs_all += "</tr><tr height='20'><td></td><td></td>"
|
||||
counter = 0
|
||||
jobs_all += "<td height='20' weight='100'><a href='?src=\ref[src];assign=[job]'>[replacetext(job, " ", " ")]</a></td>"
|
||||
|
||||
counter = 0
|
||||
jobs_all += "</tr><tr height='20'><td><font color='#008000'><b>Medical</b></font></td>"//Green
|
||||
for(var/job in medical_positions)
|
||||
counter++
|
||||
if(counter >= 6)
|
||||
jobs_all += "</tr><tr height='20'><td></td><td></td>"
|
||||
counter = 0
|
||||
jobs_all += "<td weight='100'><a href='?src=\ref[src];assign=[job]'>[replacetext(job, " ", " ")]</a></td>"
|
||||
|
||||
counter = 0
|
||||
jobs_all += "</tr><tr height='20'><td><font color='#800080'><b>Science</b></font></td>"//Purple
|
||||
for(var/job in science_positions)
|
||||
counter++
|
||||
if(counter >= 6)
|
||||
jobs_all += "</tr><tr height='20'><td></td><td></td>"
|
||||
counter = 0
|
||||
jobs_all += "<td weight='100'><a href='?src=\ref[src];assign=[job]'>[replacetext(job, " ", " ")]</a></td>"
|
||||
|
||||
counter = 0
|
||||
jobs_all += "</tr><tr height='20'><td><font color='#808080'><b>Civilian</b></font></td>"//Grey
|
||||
for(var/job in civilian_positions)
|
||||
counter++
|
||||
if(counter >= 6)
|
||||
jobs_all += "</tr><tr height='20'><td></td><td></td>"
|
||||
counter = 0
|
||||
jobs_all += "<td weight='100'><a href='?src=\ref[src];assign=[job]'>[replacetext(job, " ", " ")]</a></td>"
|
||||
|
||||
dat = {"<script type="text/javascript">
|
||||
function markRed(){
|
||||
var nameField = document.getElementById('namefield');
|
||||
nameField.style.backgroundColor = "#FFDDDD";
|
||||
}
|
||||
function markGreen(){
|
||||
var nameField = document.getElementById('namefield');
|
||||
nameField.style.backgroundColor = "#DDFFDD";
|
||||
}
|
||||
function markAccountGreen(){
|
||||
var nameField = document.getElementById('accountfield');
|
||||
nameField.style.backgroundColor = "#DDFFDD";
|
||||
}
|
||||
function markAccountRed(){
|
||||
var nameField = document.getElementById('accountfield');
|
||||
nameField.style.backgroundColor = "#FFDDDD";
|
||||
}
|
||||
function showAll(){
|
||||
var allJobsSlot = document.getElementById('alljobsslot');
|
||||
allJobsSlot.innerHTML = "<a href='#' onclick='hideAll()'>hide</a><br>"+ "[jobs_all]";
|
||||
}
|
||||
function hideAll(){
|
||||
var allJobsSlot = document.getElementById('alljobsslot');
|
||||
allJobsSlot.innerHTML = "<a href='#' onclick='showAll()'>[(writer.assignment) ? writer.assignment : "Unassgied"]</a>";
|
||||
}
|
||||
</script>"}
|
||||
return dat
|
||||
|
||||
// creates the list of access rights on the card
|
||||
proc/accessblock()
|
||||
var/accesses = "<div align='center'><b>Access</b></div>"
|
||||
accesses += "<table style='width:100%'>"
|
||||
accesses += "<tr>"
|
||||
for(var/i = 1; i <= 7; i++)
|
||||
accesses += "<td style='width:14%'><b>[get_region_accesses_name(i)]:</b></td>"
|
||||
accesses += "</tr><tr>"
|
||||
for(var/i = 1; i <= 7; i++)
|
||||
accesses += "<td style='width:14%' valign='top'>"
|
||||
for(var/A in get_region_accesses(i))
|
||||
if(A in writer.access)
|
||||
accesses += topic_link(src,"access=[A]","<font color='red'>[replacetext(get_access_desc(A), " ", " ")]</font>") + " "
|
||||
else
|
||||
accesses += topic_link(src,"access=[A]",replacetext(get_access_desc(A), " ", " ")) + " "
|
||||
accesses += "<br>"
|
||||
accesses += "</td>"
|
||||
accesses += "</tr></table>"
|
||||
return accesses
|
||||
|
||||
proc/card_modify_menu()
|
||||
//assume peripherals and cards, do checks for them in interact
|
||||
|
||||
// Header
|
||||
var/dat = "<div align='center'><br>"
|
||||
dat += topic_link(src,"remove=writer","Remove [writer.name]") + " || "
|
||||
dat += topic_link(src,"remove=reader","Remove [reader.name]") + " <br> "
|
||||
dat += topic_link(src,"mode=1","Access Crew Manifest") + " || "
|
||||
dat += topic_link(src,"logout","Log Out") + "</div>"
|
||||
dat += "<hr>" + scriptblock()
|
||||
|
||||
// form for renaming the ID
|
||||
dat += "<form name='cardcomp' action='byond://' method='get'>"
|
||||
dat += "<input type='hidden' name='src' value='\ref[src]'>"
|
||||
dat += "<b>registered_name:</b> <input type='text' id='namefield' name='reg' value='[writer.registered_name]' style='width:250px; background-color:white;' onchange='markRed()'>"
|
||||
dat += "<input type='submit' value='Rename' onclick='markGreen()'>"
|
||||
dat += "</form>"
|
||||
|
||||
// form for changing assignment, taken care of by scriptblock() mostly
|
||||
var/assign_temp = writer.assignment
|
||||
if(!assign_temp || assign_temp == "") assign_temp = "Unassigned"
|
||||
dat += "<b>Assignment:</b> [assign_temp] <span id='alljobsslot'><a href='#' onclick='showAll()'>change</a></span>"
|
||||
|
||||
// list of access rights
|
||||
dat += accessblock()
|
||||
|
||||
return dat
|
||||
|
||||
proc/login_menu()
|
||||
//assume peripherals and cards, do checks for them in interact
|
||||
var/dat = "<br><i>Please insert the cards into the slots</i><br>"
|
||||
|
||||
if(istype(writer))
|
||||
dat += "Target: [topic_link(src,"remove=writer",writer.name)]<br>"
|
||||
else
|
||||
dat += "Target: [topic_link(src,"insert=writer","--------")]<br>"
|
||||
|
||||
if(istype(reader))
|
||||
dat += "Confirm Identity: [topic_link(src,"remove=reader",reader.name)]<br>"
|
||||
else
|
||||
dat += "Confirm Identity: [topic_link(src,"insert=reader","--------")]<br>"
|
||||
dat += "[topic_link(src,"auth","{Log in}")]<br><hr>"
|
||||
dat += topic_link(src,"mode=1","Access Crew Manifest")
|
||||
return dat
|
||||
|
||||
proc/show_manifest()
|
||||
// assume linked_db since called by interact()
|
||||
var/crew = ""
|
||||
var/list/L = list()
|
||||
for (var/datum/data/record/t in data_core.general)
|
||||
var/R = t.fields["name"] + " - " + t.fields["rank"]
|
||||
L += R
|
||||
for(var/R in sortList(L))
|
||||
crew += "[R]<br>"
|
||||
return "<tt><b>Crew Manifest:</b><br>Please use security record computer to modify entries.<br><br>[crew][topic_link(src,"print","Print")]<br><br>[topic_link(src,"mode=0","Access ID modification console.")]<br></tt>"
|
||||
|
||||
// These are here partly in order to be overwritten by the centcom card computer code
|
||||
proc/authenticate()
|
||||
if(access_change_ids in reader.access)
|
||||
return 1
|
||||
if(istype(usr,/mob/living/silicon/ai))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
proc/set_default_access(var/jobname)
|
||||
var/datum/job/jobdatum
|
||||
for(var/jobtype in typesof(/datum/job))
|
||||
var/datum/job/J = new jobtype
|
||||
if(ckey(J.title) == ckey(jobname))
|
||||
jobdatum = J
|
||||
break
|
||||
if(jobdatum)
|
||||
writer.access = jobdatum.get_access() // ( istype(src,/obj/machinery/computer/card/centcom) ? get_centcom_access(t1)
|
||||
|
||||
|
||||
interact()
|
||||
if(!interactable()) return
|
||||
|
||||
if(!computer.cardslot || !computer.cardslot.dualslot)
|
||||
computer.Crash(MISSING_PERIPHERAL)
|
||||
return
|
||||
|
||||
reader = computer.cardslot.reader
|
||||
writer = computer.cardslot.writer
|
||||
|
||||
var/dat
|
||||
|
||||
switch(mode)
|
||||
if(0)
|
||||
if( !istype(writer) || !istype(reader) )
|
||||
auth = 0
|
||||
if( !auth )
|
||||
dat = login_menu()
|
||||
else
|
||||
dat = card_modify_menu()
|
||||
if(1)
|
||||
dat = show_manifest()
|
||||
|
||||
|
||||
popup.width = 940
|
||||
popup.height = 520
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
return
|
||||
|
||||
|
||||
Topic(href, list/href_list)
|
||||
if(!interactable() || !computer.cardslot || ..(href,href_list))
|
||||
return
|
||||
// todo distance/disability checks
|
||||
|
||||
if("mode" in href_list)
|
||||
mode = text2num(href_list["mode"])
|
||||
if(mode != 0 && mode != 1)
|
||||
mode = 0
|
||||
|
||||
auth = 0 // always log out if switching modes just in case
|
||||
|
||||
if("remove" in href_list)
|
||||
var/which = href_list["remove"]
|
||||
if(which == "writer")
|
||||
computer.cardslot.remove(computer.cardslot.writer)
|
||||
else
|
||||
computer.cardslot.remove(computer.cardslot.reader)
|
||||
auth = 0
|
||||
|
||||
if("insert" in href_list)
|
||||
var/obj/item/weapon/card/card = usr.get_active_hand()
|
||||
if(!istype(card)) return
|
||||
|
||||
var/which = href_list["insert"]
|
||||
if(which == "writer")
|
||||
computer.cardslot.insert(card,1)
|
||||
else
|
||||
computer.cardslot.insert(card,2)
|
||||
|
||||
if("print" in href_list)
|
||||
if (printing)
|
||||
return
|
||||
|
||||
printing = 1
|
||||
sleep(50)
|
||||
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( computer.loc )
|
||||
P.info = "<B>Crew Manifest:</B><BR>"
|
||||
var/list/L = list()
|
||||
for (var/datum/data/record/t in data_core.general)
|
||||
var/R = t.fields["name"] + " - " + t.fields["rank"]
|
||||
L += R
|
||||
for(var/R in sortList(L))
|
||||
P.info += "[R]<br>"
|
||||
P.name = "paper- 'Crew Manifest'"
|
||||
printing = 0
|
||||
|
||||
if("auth" in href_list)
|
||||
auth = 0
|
||||
if(istype(reader) && istype(writer) && authenticate())
|
||||
auth = 1
|
||||
|
||||
if("logout" in href_list)
|
||||
auth = 0
|
||||
|
||||
// Actual ID changing
|
||||
|
||||
if("access" in href_list)
|
||||
if(auth)
|
||||
var/access_type = text2num(href_list["access"])
|
||||
writer.access ^= list(access_type) //logical xor: remove if present, add if not
|
||||
|
||||
if("assign" in href_list)
|
||||
if(auth)
|
||||
var/t1 = href_list["assign"]
|
||||
if(t1 == "Custom")
|
||||
var/temp_t = copytext(sanitize(input("Enter a custom job assignment.","Assignment")),1,MAX_MESSAGE_LEN)
|
||||
if(temp_t)
|
||||
t1 = temp_t
|
||||
set_default_access(t1)
|
||||
|
||||
writer.assignment = t1
|
||||
writer.name = text("[writer.registered_name]'s ID Card ([writer.assignment])")
|
||||
|
||||
if("reg" in href_list)
|
||||
if(auth)
|
||||
writer.registered_name = href_list["reg"]
|
||||
writer.name = text("[writer.registered_name]'s ID Card ([writer.assignment])")
|
||||
|
||||
computer.updateUsrDialog()
|
||||
return
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/datum/file/program/card_comp/centcom
|
||||
name = "CentCom identification console"
|
||||
drm = 1
|
||||
|
||||
list_jobs()
|
||||
return get_all_centcom_jobs() + "Custom"
|
||||
|
||||
accessblock()
|
||||
var/accesses = "<h5>Central Command:</h5>"
|
||||
for(var/A in get_all_centcom_access())
|
||||
if(A in writer.access)
|
||||
accesses += topic_link(src,"access=[A]","<font color='red'>[replacetext(get_centcom_access_desc(A), " ", " ")]</font>") + " "
|
||||
else
|
||||
accesses += topic_link(src,"access=[A]",replacetext(get_centcom_access_desc(A), " ", " ")) + " "
|
||||
return accesses
|
||||
|
||||
authenticate()
|
||||
if(access_cent_captain in reader.access)
|
||||
return 1
|
||||
return 0
|
||||
@@ -0,0 +1,363 @@
|
||||
/obj/machinery/computer3/cloning
|
||||
default_prog = /datum/file/program/cloning
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/storage/removable,/obj/item/part/computer/networking/prox)
|
||||
|
||||
/datum/file/program/cloning
|
||||
name = "cloning console"
|
||||
desc = "Connects to cloning machinery through the local network."
|
||||
active_state = "dna_old"
|
||||
|
||||
req_access = list(access_heads) //Only used for record deletion right now.
|
||||
|
||||
var/obj/machinery/dna_scannernew/scanner = null //Linked scanner. For scanning.
|
||||
var/obj/machinery/clonepod/pod1 = null //Linked cloning pod.
|
||||
|
||||
var/temp = "Inactive"
|
||||
var/scantemp_ckey
|
||||
var/scantemp = "Ready to Scan"
|
||||
var/menu = 1 //Which menu screen to display
|
||||
var/list/records = list()
|
||||
var/datum/data/record/active_record = null
|
||||
var/loading = 0 // Nice loading text
|
||||
var/has_disk = 0
|
||||
|
||||
proc/updatemodules()
|
||||
if(!computer.net) return
|
||||
|
||||
if(scanner && pod1)
|
||||
if(!computer.net.verify_machine(scanner))
|
||||
scanner = null
|
||||
if(!computer.net.verify_machine(pod1))
|
||||
pod1 = null
|
||||
|
||||
if(!scanner || !pod1)
|
||||
var/list/nearby = computer.net.get_machines()
|
||||
scanner = locate(/obj/machinery/dna_scannernew) in nearby
|
||||
pod1 = locate(/obj/machinery/clonepod) in nearby
|
||||
|
||||
if (pod1)
|
||||
pod1.connected = src // Some variable the pod needs
|
||||
|
||||
proc/ScanningMenu()
|
||||
if (isnull(scanner))
|
||||
return "<font class='bad'>ERROR: No Scanner detected!</font><br>"
|
||||
|
||||
var/dat = "<h3>Scanner Functions</h3>"
|
||||
dat += "<div class='statusDisplay'>"
|
||||
|
||||
if (!scanner.occupant)
|
||||
dat += "Scanner Unoccupied"
|
||||
else if(loading)
|
||||
dat += "[scanner.occupant] => Scanning..."
|
||||
else
|
||||
if (scanner.occupant.ckey != scantemp_ckey)
|
||||
scantemp = "Ready to Scan"
|
||||
scantemp_ckey = scanner.occupant.ckey
|
||||
dat += "[scanner.occupant] => [scantemp]"
|
||||
|
||||
dat += "</div>"
|
||||
|
||||
if (scanner.occupant)
|
||||
dat += topic_link(src,"scan","Start Scan") + "<br>"
|
||||
if(scanner.locked)
|
||||
dat += topic_link(src,"lock","Unlock Scanner")
|
||||
else
|
||||
dat += topic_link(src,"lock","Lock Scanner")
|
||||
else
|
||||
dat += fake_link("Start Scan")
|
||||
|
||||
// Footer
|
||||
dat += "<h3>Database Functions</h3>"
|
||||
if (records.len > 0)
|
||||
dat += topic_link(src,"menu=2","View Records ([records.len])") + "<br>"
|
||||
else
|
||||
dat += fake_link("View Records (0)")
|
||||
|
||||
if (has_disk)
|
||||
dat += topic_link(src,"eject_disk","Eject Disk") + "<br>"
|
||||
return dat
|
||||
|
||||
proc/RecordsList()
|
||||
var/dat = "<h3>Current records</h3>"
|
||||
dat += topic_link(src,"menu=1","<< Back") + "<br><br>"
|
||||
for(var/datum/data/record/R in records)
|
||||
dat += "<h4>[R.fields["name"]]</h4>Scan ID [R.fields["id"]] " + topic_link(src,"view_rec=\ref[R]","View Record")
|
||||
return dat
|
||||
|
||||
proc/ShowRecord()
|
||||
var/dat = "<h3>Selected Record</h3>"
|
||||
dat += topic_link(src,"menu=2","<< Back") + "<br><br>"
|
||||
|
||||
if (!active_record)
|
||||
dat += "<font class='bad'>Record not found.</font>"
|
||||
else
|
||||
dat += "<h4>[active_record.fields["name"]]</h4>"
|
||||
dat += "Scan ID [active_record.fields["id"]] [topic_link(src,"clone","Clone")]<br>"
|
||||
|
||||
var/obj/item/weapon/implant/health/H = locate(active_record.fields["imp"])
|
||||
|
||||
if ((H) && (istype(H)))
|
||||
dat += "<b>Health Implant Data:</b><br />[H.sensehealth()]<br><br />"
|
||||
else
|
||||
dat += "<font class='bad'>Unable to locate Health Implant.</font><br /><br />"
|
||||
|
||||
dat += "<b>Unique Identifier:</b><br /><span class='highlight'>[active_record.fields["UI"]]</span><br>"
|
||||
dat += "<b>Structural Enzymes:</b><br /><span class='highlight'>[active_record.fields["SE"]]</span><br>"
|
||||
|
||||
if (has_disk)
|
||||
dat += "<div class='block'>"
|
||||
dat += "<h4>Inserted Disk</h4>"
|
||||
dat += "<b>Contents:</b> "
|
||||
if (computer.floppy.inserted.files.len == 0)
|
||||
dat += "<i>Empty</i>"
|
||||
else
|
||||
for(var/datum/file/data/genome/G in computer.floppy.inserted.files)
|
||||
dat += topic_link(src,"loadfile=\ref[G]","[G.name]") + "<br>"
|
||||
|
||||
dat += "<br /><br /><b>Save to Disk:<b><br />"
|
||||
dat += topic_link(src,"save_disk=ue","Unique Identifier + Unique Enzymes") + "<br />"
|
||||
dat += topic_link(src,"save_disk=ui","Unique Identifier") + "<br />"
|
||||
dat += topic_link(src,"save_disk=se","Structural Enzymes") + "<br />"
|
||||
dat += "</div>"
|
||||
|
||||
dat += "<font size=1>[topic_link(src,"del_rec","Delete Record")]</font>"
|
||||
return dat
|
||||
proc/ConfirmDelete()
|
||||
var/dat = "[temp]<br>"
|
||||
dat += "<h3>Confirm Record Deletion</h3>"
|
||||
|
||||
dat += "<b>[topic_link(src,"del_rec","Scan card to confirm")]</b><br>"
|
||||
dat += "<b>[topic_link(src,"menu=3","Cancel")]</b>"
|
||||
return dat
|
||||
|
||||
interact()
|
||||
if(!interactable())
|
||||
return
|
||||
|
||||
updatemodules()
|
||||
|
||||
var/dat = ""
|
||||
dat += topic_link(src,"refresh","Refresh")
|
||||
dat += "<h3>Cloning Pod Status</h3>"
|
||||
dat += "<div class='statusDisplay'>[temp] </div>"
|
||||
|
||||
has_disk = (computer.floppy && computer.floppy.inserted)
|
||||
if(!active_record && menu > 2)
|
||||
menu = 2
|
||||
|
||||
switch(menu)
|
||||
if(1)
|
||||
dat += ScanningMenu()
|
||||
|
||||
if(2)
|
||||
dat += RecordsList()
|
||||
|
||||
if(3)
|
||||
dat += ShowRecord()
|
||||
|
||||
if(4)
|
||||
dat = ConfirmDelete() // not (+=), this is how it used to be, just putting it in a function
|
||||
|
||||
if(!popup)
|
||||
popup = new(usr, "\ref[computer]", "Cloning System Control")
|
||||
popup.set_title_image(usr.browse_rsc_icon(overlay.icon, overlay.icon_state))
|
||||
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
return
|
||||
|
||||
Topic(var/href, var/list/href_list)
|
||||
if(loading || !interactable())
|
||||
return
|
||||
|
||||
if (href_list["menu"])
|
||||
menu = text2num(href_list["menu"])
|
||||
else if (("scan" in href_list) && !isnull(scanner))
|
||||
scantemp = ""
|
||||
|
||||
loading = 1
|
||||
computer.updateUsrDialog()
|
||||
|
||||
spawn(20)
|
||||
scan_mob(scanner.occupant)
|
||||
|
||||
loading = 0
|
||||
computer.updateUsrDialog()
|
||||
|
||||
|
||||
//No locking an open scanner.
|
||||
else if (("lock" in href_list) && !isnull(scanner))
|
||||
if ((!scanner.locked) && (scanner.occupant))
|
||||
scanner.locked = 1
|
||||
else
|
||||
scanner.locked = 0
|
||||
|
||||
else if ("view_rec" in href_list)
|
||||
active_record = locate(href_list["view_rec"])
|
||||
if(istype(active_record,/datum/data/record))
|
||||
if ( !active_record.fields["ckey"] || active_record.fields["ckey"] == "" )
|
||||
del(active_record)
|
||||
temp = "<font class='bad'>Record Corrupt</font>"
|
||||
else
|
||||
menu = 3
|
||||
else
|
||||
active_record = null
|
||||
temp = "Record missing."
|
||||
|
||||
else if ("del_rec" in href_list)
|
||||
if ((!active_record) || (menu < 3))
|
||||
return
|
||||
if (menu == 3) //If we are viewing a record, confirm deletion
|
||||
temp = "Delete record?"
|
||||
menu = 4
|
||||
|
||||
else if (menu == 4)
|
||||
var/obj/item/weapon/card/id/C = usr.get_active_hand()
|
||||
if (istype(C)||istype(C, /obj/item/device/pda))
|
||||
if(check_access(C))
|
||||
temp = "[active_record.fields["name"]] => Record deleted."
|
||||
records.Remove(active_record)
|
||||
del(active_record)
|
||||
menu = 2
|
||||
else
|
||||
temp = "<font class='bad'>Access Denied.</font>"
|
||||
|
||||
else if ("eject_disk" in href_list)
|
||||
if(computer.floppy)
|
||||
computer.floppy.eject_disk()
|
||||
|
||||
else if("loadfile" in href_list)
|
||||
|
||||
var/datum/file/data/genome/G = locate(href_list["loadfile"]) in computer.floppy.files
|
||||
if(!istype(G))
|
||||
temp = "<font class='bad'>Load error.</font>"
|
||||
computer.updateUsrDialog()
|
||||
return
|
||||
switch(G.type)
|
||||
if(/datum/file/data/genome/UI)
|
||||
active_record.fields["UI"] = G.content
|
||||
if(/datum/file/data/genome/UE)
|
||||
active_record.fields["name"] = G.real_name
|
||||
if(/datum/file/data/genome/SE)
|
||||
active_record.fields["SE"] = G.content
|
||||
if(/datum/file/data/genome/cloning)
|
||||
active_record = G:record
|
||||
else if("savefile" in href_list)
|
||||
if (!active_record || !computer || !computer.floppy)
|
||||
temp = "<font class='bad'>Save error.</font>"
|
||||
computer.updateUsrDialog()
|
||||
return
|
||||
var/rval = 0
|
||||
switch(href_list["save_disk"])
|
||||
if("ui")
|
||||
var/datum/file/data/genome/UI/ui = new
|
||||
ui.content = active_record.fields["UI"]
|
||||
ui.real_name = active_record.fields["name"]
|
||||
rval = computer.floppy.addfile(ui)
|
||||
if("ue")
|
||||
var/datum/file/data/genome/UI/UE/ui = new
|
||||
ui.content = active_record.fields["UI"]
|
||||
ui.real_name = active_record.fields["name"]
|
||||
rval = computer.floppy.addfile(ui)
|
||||
if("se")
|
||||
var/datum/file/data/genome/SE/se = new
|
||||
se.content = active_record.fields["SE"]
|
||||
se.real_name = active_record.fields["name"]
|
||||
rval = computer.floppy.addfile(se)
|
||||
if("clone")
|
||||
var/datum/file/data/genome/cloning/c = new
|
||||
c.record = active_record
|
||||
c.real_name = active_record.fields["name"]
|
||||
rval = computer.floppy.addfile(c)
|
||||
if(!rval)
|
||||
temp = "<font class='bad'>Disk write error.</font>"
|
||||
|
||||
else if ("refresh" in href_list)
|
||||
computer.updateUsrDialog()
|
||||
|
||||
else if ("clone" in href_list)
|
||||
//Look for that player! They better be dead!
|
||||
if(active_record)
|
||||
//Can't clone without someone to clone. Or a pod. Or if the pod is busy. Or full of gibs.
|
||||
if(!pod1)
|
||||
temp = "<font class='bad'>No Clonepod detected.</font>"
|
||||
else if(pod1.occupant)
|
||||
temp = "<font class='bad'>Clonepod is currently occupied.</font>"
|
||||
else if(pod1.mess)
|
||||
temp = "<font class='bad'>Clonepod malfunction.</font>"
|
||||
else if(!config.revival_cloning)
|
||||
temp = "<font class='bad'>Unable to initiate cloning cycle.</font>"
|
||||
else if(pod1.growclone(active_record.fields["ckey"], active_record.fields["name"], active_record.fields["UI"], active_record.fields["SE"], active_record.fields["mind"], active_record.fields["mrace"]))
|
||||
temp = "[active_record.fields["name"]] => <font class='good'>Cloning cycle in progress...</font>"
|
||||
records.Remove(active_record)
|
||||
del(active_record)
|
||||
menu = 1
|
||||
else
|
||||
temp = "[active_record.fields["name"]] => <font class='bad'>Initialisation failure.</font>"
|
||||
|
||||
else
|
||||
temp = "<font class='bad'>Data corruption.</font>"
|
||||
|
||||
computer.add_fingerprint(usr)
|
||||
computer.updateUsrDialog()
|
||||
return
|
||||
|
||||
proc/scan_mob(mob/living/carbon/human/subject as mob)
|
||||
if ((isnull(subject)) || (!(ishuman(subject))) || (!subject.dna))
|
||||
scantemp = "<font class='bad'>Unable to locate valid genetic data.</font>"
|
||||
return
|
||||
if (!getbrain(subject))
|
||||
scantemp = "<font class='bad'>No signs of intelligence detected.</font>"
|
||||
return
|
||||
if (subject.suiciding == 1)
|
||||
scantemp = "<font class='bad'>Subject's brain is not responding to scanning stimuli.</font>"
|
||||
return
|
||||
if ((!subject.ckey) || (!subject.client))
|
||||
scantemp = "<font class='bad'>Mental interface failure.</font>"
|
||||
return
|
||||
if (NOCLONE in subject.mutations)
|
||||
scantemp = "<font class='bad'>Mental interface failure.</font>"
|
||||
return
|
||||
if (!isnull(find_record(subject.ckey)))
|
||||
scantemp = "<font class='average'>Subject already in database.</font>"
|
||||
return
|
||||
|
||||
subject.dna.check_integrity()
|
||||
|
||||
var/datum/data/record/R = new /datum/data/record( )
|
||||
if(subject.dna)
|
||||
R.fields["mrace"] = subject.dna.mutantrace
|
||||
R.fields["UI"] = subject.dna.uni_identity
|
||||
R.fields["SE"] = subject.dna.struc_enzymes
|
||||
else
|
||||
R.fields["mrace"] = null
|
||||
R.fields["UI"] = null
|
||||
R.fields["SE"] = null
|
||||
R.fields["ckey"] = subject.ckey
|
||||
R.fields["name"] = subject.real_name
|
||||
R.fields["id"] = copytext(md5(subject.real_name), 2, 6)
|
||||
|
||||
|
||||
|
||||
//Add an implant if needed
|
||||
var/obj/item/weapon/implant/health/imp = locate(/obj/item/weapon/implant/health, subject)
|
||||
if (isnull(imp))
|
||||
imp = new /obj/item/weapon/implant/health(subject)
|
||||
imp.implanted = subject
|
||||
R.fields["imp"] = "\ref[imp]"
|
||||
//Update it if needed
|
||||
else
|
||||
R.fields["imp"] = "\ref[imp]"
|
||||
|
||||
if (!isnull(subject.mind)) //Save that mind so traitors can continue traitoring after cloning.
|
||||
R.fields["mind"] = "\ref[subject.mind]"
|
||||
|
||||
records += R
|
||||
scantemp = "Subject successfully scanned."
|
||||
|
||||
//Find a specific record by key.
|
||||
proc/find_record(var/find_key)
|
||||
for(var/datum/data/record/R in records)
|
||||
if (R.fields["ckey"] == find_key)
|
||||
return R
|
||||
return null
|
||||
@@ -0,0 +1,384 @@
|
||||
/obj/machinery/computer3/communications
|
||||
default_prog = /datum/file/program/communications
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/networking/radio/subspace)
|
||||
|
||||
/obj/machinery/computer3/communications/captain
|
||||
default_prog = /datum/file/program/communications
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/networking/radio/subspace,/obj/item/part/computer/cardslot/dual)
|
||||
spawn_files = list(/datum/file/program/card_comp, /datum/file/program/security, /datum/file/program/crew, /datum/file/program/arcade,
|
||||
/datum/file/camnet_key, /datum/file/camnet_key/entertainment, /datum/file/camnet_key/singulo)
|
||||
|
||||
|
||||
/datum/file/program/communications
|
||||
var/const/STATE_DEFAULT = 1
|
||||
var/const/STATE_CALLSHUTTLE = 2
|
||||
var/const/STATE_CANCELSHUTTLE = 3
|
||||
var/const/STATE_MESSAGELIST = 4
|
||||
var/const/STATE_VIEWMESSAGE = 5
|
||||
var/const/STATE_DELMESSAGE = 6
|
||||
var/const/STATE_STATUSDISPLAY = 7
|
||||
var/const/STATE_ALERT_LEVEL = 8
|
||||
var/const/STATE_CONFIRM_LEVEL = 9
|
||||
|
||||
|
||||
/datum/file/program/communications
|
||||
name = "Centcom communications relay"
|
||||
desc = "Used to connect to Centcom."
|
||||
active_state = "comm"
|
||||
req_access = list(access_heads)
|
||||
|
||||
var/prints_intercept = 1
|
||||
var/authenticated = 0
|
||||
var/list/messagetitle = list()
|
||||
var/list/messagetext = list()
|
||||
var/currmsg = 0
|
||||
var/aicurrmsg = 0
|
||||
var/state = STATE_DEFAULT
|
||||
var/aistate = STATE_DEFAULT
|
||||
var/message_cooldown = 0
|
||||
var/centcomm_message_cooldown = 0
|
||||
var/tmp_alertlevel = 0
|
||||
|
||||
var/status_display_freq = "1435"
|
||||
var/stat_msg1
|
||||
var/stat_msg2
|
||||
|
||||
Reset()
|
||||
..()
|
||||
authenticated = 0
|
||||
state = STATE_DEFAULT
|
||||
aistate = STATE_DEFAULT
|
||||
|
||||
|
||||
Topic(var/href, var/list/href_list)
|
||||
if(!interactable() || !computer.radio || ..(href,href_list) )
|
||||
return
|
||||
if (computer.z > 1)
|
||||
usr << "\red <b>Unable to establish a connection</b>: \black You're too far away from the station!"
|
||||
return
|
||||
|
||||
if("main" in href_list)
|
||||
state = STATE_DEFAULT
|
||||
if("login" in href_list)
|
||||
var/mob/M = usr
|
||||
var/obj/item/I = M.get_active_hand()
|
||||
if(I)
|
||||
I = I.GetID()
|
||||
if(istype(I,/obj/item/weapon/card/id) && check_access(I))
|
||||
authenticated = 1
|
||||
if(access_captain in I.GetAccess())
|
||||
authenticated = 2
|
||||
if(istype(I,/obj/item/weapon/card/emag))
|
||||
authenticated = 2
|
||||
computer.emagged = 1
|
||||
if("logout" in href_list)
|
||||
authenticated = 0
|
||||
|
||||
if("swipeidseclevel" in href_list)
|
||||
var/mob/M = usr
|
||||
var/obj/item/I = M.get_active_hand()
|
||||
I = I.GetID()
|
||||
|
||||
if (istype(I,/obj/item/weapon/card/id))
|
||||
if(access_captain in I.GetAccess())
|
||||
var/old_level = security_level
|
||||
if(!tmp_alertlevel) tmp_alertlevel = SEC_LEVEL_GREEN
|
||||
if(tmp_alertlevel < SEC_LEVEL_GREEN) tmp_alertlevel = SEC_LEVEL_GREEN
|
||||
if(tmp_alertlevel > SEC_LEVEL_BLUE) tmp_alertlevel = SEC_LEVEL_BLUE //Cannot engage delta with this
|
||||
set_security_level(tmp_alertlevel)
|
||||
if(security_level != old_level)
|
||||
//Only notify the admins if an actual change happened
|
||||
log_game("[key_name(usr)] has changed the security level to [get_security_level()].")
|
||||
message_admins("[key_name_admin(usr)] has changed the security level to [get_security_level()].")
|
||||
switch(security_level)
|
||||
if(SEC_LEVEL_GREEN)
|
||||
feedback_inc("alert_comms_green",1)
|
||||
if(SEC_LEVEL_BLUE)
|
||||
feedback_inc("alert_comms_blue",1)
|
||||
tmp_alertlevel = 0
|
||||
else:
|
||||
usr << "You are not authorized to do this."
|
||||
tmp_alertlevel = 0
|
||||
state = STATE_DEFAULT
|
||||
else
|
||||
usr << "You need to swipe your ID."
|
||||
if("announce" in href_list)
|
||||
if(authenticated==2)
|
||||
if(message_cooldown) return
|
||||
var/input = stripped_input(usr, "Please choose a message to announce to the station crew.", "What?")
|
||||
if(!input || !interactable())
|
||||
return
|
||||
captain_announce(input)//This should really tell who is, IE HoP, CE, HoS, RD, Captain
|
||||
log_say("[key_name(usr)] has made a captain announcement: [input]")
|
||||
message_admins("[key_name_admin(usr)] has made a captain announcement.", 1)
|
||||
message_cooldown = 1
|
||||
spawn(600)//One minute cooldown
|
||||
message_cooldown = 0
|
||||
|
||||
if("callshuttle" in href_list)
|
||||
state = STATE_DEFAULT
|
||||
if(authenticated)
|
||||
state = STATE_CALLSHUTTLE
|
||||
if("callshuttle2" in href_list)
|
||||
if(!computer.radio.subspace)
|
||||
return
|
||||
if(authenticated)
|
||||
call_shuttle_proc(usr)
|
||||
if(emergency_shuttle.online())
|
||||
post_status("shuttle")
|
||||
state = STATE_DEFAULT
|
||||
if("cancelshuttle" in href_list)
|
||||
state = STATE_DEFAULT
|
||||
if(authenticated)
|
||||
state = STATE_CANCELSHUTTLE
|
||||
if("messagelist" in href_list)
|
||||
currmsg = 0
|
||||
state = STATE_MESSAGELIST
|
||||
if("viewmessage" in href_list)
|
||||
state = STATE_VIEWMESSAGE
|
||||
if (!currmsg)
|
||||
if(href_list["message-num"])
|
||||
currmsg = text2num(href_list["message-num"])
|
||||
else
|
||||
state = STATE_MESSAGELIST
|
||||
if("delmessage" in href_list)
|
||||
state = (currmsg) ? STATE_DELMESSAGE : STATE_MESSAGELIST
|
||||
if("delmessage2" in href_list)
|
||||
if(authenticated)
|
||||
if(currmsg)
|
||||
var/title = messagetitle[currmsg]
|
||||
var/text = messagetext[currmsg]
|
||||
messagetitle.Remove(title)
|
||||
messagetext.Remove(text)
|
||||
if(currmsg == aicurrmsg)
|
||||
aicurrmsg = 0
|
||||
currmsg = 0
|
||||
state = STATE_MESSAGELIST
|
||||
else
|
||||
state = STATE_VIEWMESSAGE
|
||||
if("status" in href_list)
|
||||
state = STATE_STATUSDISPLAY
|
||||
|
||||
// Status display stuff
|
||||
if("setstat" in href_list)
|
||||
switch(href_list["statdisp"])
|
||||
if("message")
|
||||
post_status("message", stat_msg1, stat_msg2)
|
||||
if("alert")
|
||||
post_status("alert", href_list["alert"])
|
||||
else
|
||||
post_status(href_list["statdisp"])
|
||||
|
||||
if("setmsg1" in href_list)
|
||||
stat_msg1 = reject_bad_text(input("Line 1", "Enter Message Text", stat_msg1) as text|null, 40)
|
||||
computer.updateDialog()
|
||||
if("setmsg2" in href_list)
|
||||
stat_msg2 = reject_bad_text(input("Line 2", "Enter Message Text", stat_msg2) as text|null, 40)
|
||||
computer.updateDialog()
|
||||
|
||||
// OMG CENTCOMM LETTERHEAD
|
||||
if("MessageCentcomm" in href_list)
|
||||
if(!computer.radio.subspace)
|
||||
return
|
||||
if(authenticated==2)
|
||||
if(centcomm_message_cooldown)
|
||||
usr << "Arrays recycling. Please stand by."
|
||||
return
|
||||
var/input = stripped_input(usr, "Please choose a message to transmit to Centcomm via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "")
|
||||
if(!input || !interactable())
|
||||
return
|
||||
Centcomm_announce(input, usr)
|
||||
usr << "Message transmitted."
|
||||
log_say("[key_name(usr)] has made a Centcomm announcement: [input]")
|
||||
centcomm_message_cooldown = 1
|
||||
spawn(600)//10 minute cooldown
|
||||
centcomm_message_cooldown = 0
|
||||
|
||||
|
||||
// OMG SYNDICATE ...LETTERHEAD
|
||||
if("MessageSyndicate" in href_list)
|
||||
if((authenticated==2) && (computer.emagged))
|
||||
if(centcomm_message_cooldown)
|
||||
usr << "Arrays recycling. Please stand by."
|
||||
return
|
||||
var/input = stripped_input(usr, "Please choose a message to transmit to \[ABNORMAL ROUTING CORDINATES\] via quantum entanglement. Please be aware that this process is very expensive, and abuse will lead to... termination. Transmission does not guarantee a response.", "To abort, send an empty message.", "")
|
||||
if(!input || !interactable())
|
||||
return
|
||||
Syndicate_announce(input, usr)
|
||||
usr << "Message transmitted."
|
||||
log_say("[key_name(usr)] has made a Syndicate announcement: [input]")
|
||||
centcomm_message_cooldown = 1
|
||||
spawn(600)//10 minute cooldown
|
||||
centcomm_message_cooldown = 0
|
||||
|
||||
if("RestoreBackup" in href_list)
|
||||
usr << "Backup routing data restored!"
|
||||
computer.emagged = 0
|
||||
computer.updateDialog()
|
||||
|
||||
|
||||
|
||||
// AI interface
|
||||
if("ai-main" in href_list)
|
||||
aicurrmsg = 0
|
||||
aistate = STATE_DEFAULT
|
||||
if("ai-callshuttle" in href_list)
|
||||
aistate = STATE_CALLSHUTTLE
|
||||
if("ai-callshuttle2" in href_list)
|
||||
if(!computer.radio.subspace)
|
||||
return
|
||||
call_shuttle_proc(usr)
|
||||
aistate = STATE_DEFAULT
|
||||
if("ai-messagelist" in href_list)
|
||||
aicurrmsg = 0
|
||||
aistate = STATE_MESSAGELIST
|
||||
if("ai-viewmessage" in href_list)
|
||||
aistate = STATE_VIEWMESSAGE
|
||||
if (!aicurrmsg)
|
||||
if(href_list["message-num"])
|
||||
aicurrmsg = text2num(href_list["message-num"])
|
||||
else
|
||||
aistate = STATE_MESSAGELIST
|
||||
if("ai-delmessage" in href_list)
|
||||
aistate = (aicurrmsg) ? STATE_DELMESSAGE : STATE_MESSAGELIST
|
||||
if("ai-delmessage2" in href_list)
|
||||
if(aicurrmsg)
|
||||
var/title = messagetitle[aicurrmsg]
|
||||
var/text = messagetext[aicurrmsg]
|
||||
messagetitle.Remove(title)
|
||||
messagetext.Remove(text)
|
||||
if(currmsg == aicurrmsg)
|
||||
currmsg = 0
|
||||
aicurrmsg = 0
|
||||
aistate = STATE_MESSAGELIST
|
||||
if("ai-status" in href_list)
|
||||
aistate = STATE_STATUSDISPLAY
|
||||
|
||||
if("securitylevel" in href_list)
|
||||
tmp_alertlevel = text2num( href_list["newalertlevel"] )
|
||||
if(!tmp_alertlevel) tmp_alertlevel = 0
|
||||
state = STATE_CONFIRM_LEVEL
|
||||
|
||||
if("changeseclevel" in href_list)
|
||||
state = STATE_ALERT_LEVEL
|
||||
|
||||
computer.updateUsrDialog()
|
||||
|
||||
|
||||
|
||||
proc/main_menu()
|
||||
var/dat = ""
|
||||
if (computer.radio.subspace)
|
||||
if(emergency_shuttle.online() && emergency_shuttle.location())
|
||||
var/timeleft = emergency_shuttle.estimate_arrival_time()
|
||||
dat += "<B>Emergency shuttle</B>\n<BR>\nETA: [timeleft / 60 % 60]:[add_zero(num2text(timeleft % 60), 2)]<BR>"
|
||||
refresh = 1
|
||||
else
|
||||
refresh = 0
|
||||
if (authenticated)
|
||||
dat += "<BR>\[ <A HREF='?src=\ref[src];logout'>Log Out</A> \]"
|
||||
if (authenticated==2)
|
||||
dat += "<BR>\[ <A HREF='?src=\ref[src];announce'>Make An Announcement</A> \]"
|
||||
if(computer.emagged == 0)
|
||||
dat += "<BR>\[ <A HREF='?src=\ref[src];MessageCentcomm'>Send an emergency message to Centcomm</A> \]"
|
||||
else
|
||||
dat += "<BR>\[ <A HREF='?src=\ref[src];MessageSyndicate'>Send an emergency message to \[UNKNOWN\]</A> \]"
|
||||
dat += "<BR>\[ <A HREF='?src=\ref[src];RestoreBackup'>Restore Backup Routing Data</A> \]"
|
||||
|
||||
dat += "<BR>\[ <A HREF='?src=\ref[src];changeseclevel'>Change alert level</A> \]"
|
||||
if(emergency_shuttle.location())
|
||||
if (emergency_shuttle.online())
|
||||
dat += "<BR>\[ <A HREF='?src=\ref[src];cancelshuttle'>Cancel Shuttle Call</A> \]"
|
||||
else
|
||||
dat += "<BR>\[ <A HREF='?src=\ref[src];callshuttle'>Call Emergency Shuttle</A> \]"
|
||||
|
||||
dat += "<BR>\[ <A HREF='?src=\ref[src];status'>Set Status Display</A> \]"
|
||||
else
|
||||
dat += "<BR>\[ <A HREF='?src=\ref[src];login'>Log In</A> \]"
|
||||
dat += "<BR>\[ <A HREF='?src=\ref[src];messagelist'>Message List</A> \]"
|
||||
return dat
|
||||
|
||||
proc/confirm_menu(var/prompt,var/yes_option)
|
||||
return "Are you sure you want to [prompt]? \[ [topic_link(src,yes_option,"OK")] | [topic_link(src,"main","Cancel")] \]"
|
||||
|
||||
interact()
|
||||
if(!interactable())
|
||||
return
|
||||
if(!computer.radio)
|
||||
computer.Crash(MISSING_PERIPHERAL)
|
||||
return
|
||||
|
||||
var/dat = ""
|
||||
switch(state)
|
||||
if(STATE_DEFAULT)
|
||||
dat = main_menu()
|
||||
if(STATE_CALLSHUTTLE)
|
||||
dat = confirm_menu("call the shuttle","callshuttle2")
|
||||
if(STATE_CANCELSHUTTLE)
|
||||
dat = confirm_menu("cancel the shuttle","cancelshuttle2")
|
||||
if(STATE_MESSAGELIST)
|
||||
dat += "Messages:"
|
||||
for(var/i = 1; i<=messagetitle.len; i++)
|
||||
dat += "<BR><A HREF='?src=\ref[src];viewmessage;message-num=[i]'>[messagetitle[i]]</A>"
|
||||
if(STATE_VIEWMESSAGE)
|
||||
if (currmsg)
|
||||
dat += "<B>[messagetitle[currmsg]]</B><BR><BR>[messagetext[currmsg]]"
|
||||
if (authenticated)
|
||||
dat += "<BR><BR>\[ <A HREF='?src=\ref[src];delmessage'>Delete \]"
|
||||
else
|
||||
state = STATE_MESSAGELIST
|
||||
interact()
|
||||
return
|
||||
if(STATE_DELMESSAGE)
|
||||
if (currmsg)
|
||||
dat += "Are you sure you want to delete this message? \[ <A HREF='?src=\ref[src];delmessage2'>OK</A> | <A HREF='?src=\ref[src];viewmessage'>Cancel</A> \]"
|
||||
else
|
||||
state = STATE_MESSAGELIST
|
||||
interact()
|
||||
return
|
||||
if(STATE_STATUSDISPLAY)
|
||||
dat += "\[ <A HREF='?src=\ref[src];main'>Back</A> \]<BR>"
|
||||
dat += "Set Status Displays<BR>"
|
||||
dat += "\[ <A HREF='?src=\ref[src];setstat;statdisp=blank'>Clear</A> \]<BR>"
|
||||
dat += "\[ <A HREF='?src=\ref[src];setstat;statdisp=shuttle'>Shuttle ETA</A> \]<BR>"
|
||||
dat += "\[ <A HREF='?src=\ref[src];setstat;statdisp=message'>Message</A> \]"
|
||||
dat += "<ul><li> Line 1: <A HREF='?src=\ref[src];setmsg1'>[ stat_msg1 ? stat_msg1 : "(none)"]</A>"
|
||||
dat += "<li> Line 2: <A HREF='?src=\ref[src];setmsg2'>[ stat_msg2 ? stat_msg2 : "(none)"]</A></ul><br>"
|
||||
dat += "\[ Alert: <A HREF='?src=\ref[src];setstat;statdisp=alert;alert=default'>None</A> |"
|
||||
dat += " <A HREF='?src=\ref[src];setstat;statdisp=alert;alert=redalert'>Red Alert</A> |"
|
||||
dat += " <A HREF='?src=\ref[src];setstat;statdisp=alert;alert=lockdown'>Lockdown</A> |"
|
||||
dat += " <A HREF='?src=\ref[src];setstat;statdisp=alert;alert=biohazard'>Biohazard</A> \]<BR><HR>"
|
||||
if(STATE_ALERT_LEVEL)
|
||||
dat += "Current alert level: [get_security_level()]<BR>"
|
||||
if(security_level == SEC_LEVEL_DELTA)
|
||||
dat += "<font color='red'><b>The self-destruct mechanism is active. Find a way to deactivate the mechanism to lower the alert level or evacuate.</b></font>"
|
||||
else
|
||||
dat += "<A HREF='?src=\ref[src];securitylevel;newalertlevel=[SEC_LEVEL_BLUE]'>Blue</A><BR>"
|
||||
dat += "<A HREF='?src=\ref[src];securitylevel;newalertlevel=[SEC_LEVEL_GREEN]'>Green</A>"
|
||||
if(STATE_CONFIRM_LEVEL)
|
||||
dat += "Current alert level: [get_security_level()]<BR>"
|
||||
dat += "Confirm the change to: [num2seclevel(tmp_alertlevel)]<BR>"
|
||||
dat += "<A HREF='?src=\ref[src];swipeidseclevel'>Swipe ID</A> to confirm change.<BR>"
|
||||
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
|
||||
|
||||
proc/post_status(var/command, var/data1, var/data2)
|
||||
var/datum/radio_frequency/frequency = radio_controller.return_frequency(1435)
|
||||
|
||||
if(!frequency) return
|
||||
|
||||
var/datum/signal/status_signal = new
|
||||
status_signal.source = src
|
||||
status_signal.transmission_method = 1
|
||||
status_signal.data["command"] = command
|
||||
|
||||
switch(command)
|
||||
if("message")
|
||||
status_signal.data["msg1"] = data1
|
||||
status_signal.data["msg2"] = data2
|
||||
if("alert")
|
||||
status_signal.data["picture_state"] = data1
|
||||
|
||||
frequency.post_signal(src, status_signal)
|
||||
@@ -0,0 +1,78 @@
|
||||
/obj/machinery/computer3/crew
|
||||
default_prog = /datum/file/program/crew
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/networking/radio)
|
||||
icon_state = "frame-med"
|
||||
|
||||
/datum/file/program/crew
|
||||
name = "Crew Monitoring Console"
|
||||
desc = "Used to monitor active health sensors built into most of the crew's uniforms."
|
||||
active_state = "crew"
|
||||
var/list/tracked = list( )
|
||||
|
||||
interact(mob/user)
|
||||
if(!interactable())
|
||||
return
|
||||
|
||||
scan()
|
||||
var/t = "<TT><B>Crew Monitoring</B><HR>"
|
||||
t += "<BR><A href='?src=\ref[src];update=1'>Refresh</A> "
|
||||
t += "<A href='?src=\ref[src];close=1'>Close</A><BR>"
|
||||
t += "<table><tr><td width='40%'>Name</td><td width='20%'>Vitals</td><td width='40%'>Position</td></tr>"
|
||||
var/list/logs = list()
|
||||
for(var/obj/item/clothing/under/C in src.tracked)
|
||||
var/log = ""
|
||||
var/turf/pos = get_turf(C)
|
||||
if((C) && (C.has_sensor) && (pos) && (pos.z == computer.z) && C.sensor_mode)
|
||||
if(istype(C.loc, /mob/living/carbon/human))
|
||||
|
||||
var/mob/living/carbon/human/H = C.loc
|
||||
|
||||
var/dam1 = round(H.getOxyLoss(),1)
|
||||
var/dam2 = round(H.getToxLoss(),1)
|
||||
var/dam3 = round(H.getFireLoss(),1)
|
||||
var/dam4 = round(H.getBruteLoss(),1)
|
||||
|
||||
var/life_status = "[H.stat > 1 ? "<font color=red>Deceased</font>" : "Living"]"
|
||||
var/damage_report = "(<font color='blue'>[dam1]</font>/<font color='green'>[dam2]</font>/<font color='orange'>[dam3]</font>/<font color='red'>[dam4]</font>)"
|
||||
|
||||
if(H.wear_id)
|
||||
log += "<tr><td width='40%'>[H.wear_id.name]</td>"
|
||||
else
|
||||
log += "<tr><td width='40%'>Unknown</td>"
|
||||
|
||||
switch(C.sensor_mode)
|
||||
if(1)
|
||||
log += "<td width='15%'>[life_status]</td><td width='40%'>Not Available</td></tr>"
|
||||
if(2)
|
||||
log += "<td width='20%'>[life_status] [damage_report]</td><td width='40%'>Not Available</td></tr>"
|
||||
if(3)
|
||||
var/area/player_area = get_area(H)
|
||||
log += "<td width='20%'>[life_status] [damage_report]</td><td width='40%'>[player_area.name] ([pos.x], [pos.y])</td></tr>"
|
||||
logs += log
|
||||
logs = sortList(logs)
|
||||
for(var/log in logs)
|
||||
t += log
|
||||
t += "</table>"
|
||||
t += "</FONT></PRE></TT>"
|
||||
|
||||
popup.set_content(t)
|
||||
popup.open()
|
||||
|
||||
|
||||
proc/scan()
|
||||
for(var/obj/item/clothing/under/C in world)
|
||||
if((C.has_sensor) && (istype(C.loc, /mob/living/carbon/human)))
|
||||
tracked |= C
|
||||
return 1
|
||||
|
||||
Topic(href, list/href_list)
|
||||
if(!interactable() || !computer.cardslot || ..(href,href_list))
|
||||
return
|
||||
if( href_list["close"] )
|
||||
usr << browse(null, "window=crewcomp")
|
||||
usr.unset_machine()
|
||||
return
|
||||
if(href_list["update"])
|
||||
interact()
|
||||
//src.updateUsrDialog()
|
||||
return
|
||||
@@ -0,0 +1,3 @@
|
||||
/obj/machinery/computer3/customs
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/networking/radio/subspace,/obj/item/part/computer/networking/cameras)
|
||||
spawn_files = list(/datum/file/program/arcade,/datum/file/program/security,/datum/file/camnet_key/entertainment,/datum/file/program/crew)
|
||||
@@ -0,0 +1,84 @@
|
||||
|
||||
|
||||
/obj/machinery/computer3/aiupload
|
||||
name = "AI Upload"
|
||||
desc = "Used to upload laws to the AI."
|
||||
icon_state = "frame-rnd"
|
||||
circuit = "/obj/item/part/board/circuit/aiupload"
|
||||
var/mob/living/silicon/ai/current = null
|
||||
var/opened = 0
|
||||
|
||||
|
||||
verb/AccessInternals()
|
||||
set category = "Object"
|
||||
set name = "Access Computer's Internals"
|
||||
set src in oview(1)
|
||||
if(!Adjacent(usr) || usr.restrained() || usr.lying || usr.stat || istype(usr, /mob/living/silicon) || !istype(usr, /mob/living))
|
||||
return
|
||||
|
||||
opened = !opened
|
||||
if(opened)
|
||||
usr << "\blue The access panel is now open."
|
||||
else
|
||||
usr << "\blue The access panel is now closed."
|
||||
return
|
||||
|
||||
|
||||
attackby(obj/item/weapon/aiModule/module as obj, mob/user as mob)
|
||||
if (user.z > 6)
|
||||
user << "\red <b>Unable to establish a connection</b>: \black You're too far away from the station!"
|
||||
return
|
||||
if(istype(module, /obj/item/weapon/aiModule))
|
||||
module.install(src)
|
||||
else
|
||||
return ..()
|
||||
|
||||
|
||||
attack_hand(var/mob/user as mob)
|
||||
if(src.stat & NOPOWER)
|
||||
usr << "The upload computer has no power!"
|
||||
return
|
||||
if(src.stat & BROKEN)
|
||||
usr << "The upload computer is broken!"
|
||||
return
|
||||
|
||||
src.current = select_active_ai(user)
|
||||
|
||||
if (!src.current)
|
||||
usr << "No active AIs detected."
|
||||
else
|
||||
usr << "[src.current.name] selected for law changes."
|
||||
return
|
||||
|
||||
|
||||
|
||||
/obj/machinery/computer3/borgupload
|
||||
name = "Cyborg Upload"
|
||||
desc = "Used to upload laws to Cyborgs."
|
||||
icon_state = "frame-rnd"
|
||||
circuit = "/obj/item/part/board/circuit/borgupload"
|
||||
var/mob/living/silicon/robot/current = null
|
||||
|
||||
|
||||
attackby(obj/item/weapon/aiModule/module as obj, mob/user as mob)
|
||||
if(istype(module, /obj/item/weapon/aiModule))
|
||||
module.install(src)
|
||||
else
|
||||
return ..()
|
||||
|
||||
|
||||
attack_hand(var/mob/user as mob)
|
||||
if(src.stat & NOPOWER)
|
||||
usr << "The upload computer has no power!"
|
||||
return
|
||||
if(src.stat & BROKEN)
|
||||
usr << "The upload computer is broken!"
|
||||
return
|
||||
|
||||
src.current = freeborg()
|
||||
|
||||
if (!src.current)
|
||||
usr << "No free cyborgs detected."
|
||||
else
|
||||
usr << "[src.current.name] selected for law changes."
|
||||
return
|
||||
@@ -0,0 +1,509 @@
|
||||
/*
|
||||
I hate to make this a todo, but I cannot possibly complete all of computer3
|
||||
if I have to rearchitecture datacores and everything else that uses them right now.
|
||||
|
||||
In the future the datacore should probably be a server, perhaps on station, perhaps on centcom,
|
||||
with data records as files probably. It's not difficult unless you're trying to do a million
|
||||
impossible things before breakfast.
|
||||
*/
|
||||
|
||||
/obj/machinery/computer3/med_data
|
||||
default_prog = /datum/file/program/med_data
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/cardslot,/obj/item/part/computer/networking/radio)
|
||||
|
||||
|
||||
/obj/machinery/computer3/laptop/medical
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/cardslot,/obj/item/part/computer/networking/radio)
|
||||
spawn_files = list(/datum/file/program/arcade,/datum/file/program/crew,/datum/file/program/med_data)
|
||||
|
||||
/datum/file/program/med_data
|
||||
name = "Medical Records"
|
||||
desc = "This can be used to check medical records."
|
||||
active_state = "medcomp"
|
||||
req_one_access = list(access_medical, access_forensics_lockers)
|
||||
|
||||
var/obj/item/weapon/card/id/scan = null
|
||||
var/authenticated = null
|
||||
var/rank = null
|
||||
var/screen = null
|
||||
var/datum/data/record/active1 = null
|
||||
var/datum/data/record/active2 = null
|
||||
var/a_id = null
|
||||
var/temp = null
|
||||
var/printing = null
|
||||
|
||||
|
||||
proc/authenticate()
|
||||
if(access_medical in scan.access)
|
||||
return 1
|
||||
if(istype(usr,/mob/living/silicon/ai))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
interact()
|
||||
if(!computer.cardslot)
|
||||
computer.Crash(MISSING_PERIPHERAL)
|
||||
return
|
||||
usr.set_machine(src)
|
||||
scan = computer.cardslot.reader
|
||||
if(!interactable())
|
||||
return
|
||||
if (computer.z > 6)
|
||||
usr << "\red <b>Unable to establish a connection</b>: \black You're too far away from the station!"
|
||||
return
|
||||
var/dat
|
||||
|
||||
if (temp)
|
||||
dat = text("<TT>[src.temp]</TT><BR><BR><A href='?src=\ref[src];temp=1'>Clear Screen</A>")
|
||||
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 += {"
|
||||
<A href='?src=\ref[src];search=1'>Search Records</A>
|
||||
<BR><A href='?src=\ref[src];screen=2'>List Records</A>
|
||||
<BR>
|
||||
<BR><A href='?src=\ref[src];screen=5'>Virus Database</A>
|
||||
<BR><A href='?src=\ref[src];screen=6'>Medbot Tracking</A>
|
||||
<BR>
|
||||
<BR><A href='?src=\ref[src];screen=3'>Record Maintenance</A>
|
||||
<BR><A href='?src=\ref[src];logout=1'>{Log Out}</A><BR>
|
||||
"}
|
||||
if(2.0)
|
||||
dat += "<B>Record List</B>:<HR>"
|
||||
if(!isnull(data_core.general))
|
||||
for(var/datum/data/record/R in sortRecord(data_core.general))
|
||||
dat += text("<A href='?src=\ref[];d_rec=\ref[]'>[]: []<BR>", src, R, R.fields["id"], R.fields["name"])
|
||||
//Foreach goto(132)
|
||||
dat += text("<HR><A href='?src=\ref[];screen=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[];screen=1'>Back</A>", src, src, src, src)
|
||||
if(4.0)
|
||||
var/icon/front = new(active1.fields["photo"], dir = SOUTH)
|
||||
var/icon/side = new(active1.fields["photo"], dir = WEST)
|
||||
usr << browse_rsc(front, "front.png")
|
||||
usr << browse_rsc(side, "side.png")
|
||||
dat += "<CENTER><B>Medical Record</B></CENTER><BR>"
|
||||
if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1)))
|
||||
dat += "<table><tr><td>Name: [active1.fields["name"]] \
|
||||
ID: [active1.fields["id"]]<BR>\n \
|
||||
Sex: <A href='?src=\ref[src];field=sex'>[active1.fields["sex"]]</A><BR>\n \
|
||||
Age: <A href='?src=\ref[src];field=age'>[active1.fields["age"]]</A><BR>\n \
|
||||
Fingerprint: <A href='?src=\ref[src];field=fingerprint'>[active1.fields["fingerprint"]]</A><BR>\n \
|
||||
Physical Status: <A href='?src=\ref[src];field=p_stat'>[active1.fields["p_stat"]]</A><BR>\n \
|
||||
Mental Status: <A href='?src=\ref[src];field=m_stat'>[active1.fields["m_stat"]]</A><BR></td><td align = center valign = top> \
|
||||
Photo:<br><img src=front.png height=64 width=64 border=5><img src=side.png height=64 width=64 border=5></td></tr></table>"
|
||||
else
|
||||
dat += "<B>General Record Lost!</B><BR>"
|
||||
if ((istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2)))
|
||||
dat += text("<BR>\n<CENTER><B>Medical Data</B></CENTER><BR>\nBlood Type: <A href='?src=\ref[];field=b_type'>[]</A><BR>\nDNA: <A href='?src=\ref[];field=b_dna'>[]</A><BR>\n<BR>\nMinor Disabilities: <A href='?src=\ref[];field=mi_dis'>[]</A><BR>\nDetails: <A href='?src=\ref[];field=mi_dis_d'>[]</A><BR>\n<BR>\nMajor Disabilities: <A href='?src=\ref[];field=ma_dis'>[]</A><BR>\nDetails: <A href='?src=\ref[];field=ma_dis_d'>[]</A><BR>\n<BR>\nAllergies: <A href='?src=\ref[];field=alg'>[]</A><BR>\nDetails: <A href='?src=\ref[];field=alg_d'>[]</A><BR>\n<BR>\nCurrent Diseases: <A href='?src=\ref[];field=cdi'>[]</A> (per disease info placed in log/comment section)<BR>\nDetails: <A href='?src=\ref[];field=cdi_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["b_type"], src, src.active2.fields["b_dna"], src, src.active2.fields["mi_dis"], src, src.active2.fields["mi_dis_d"], src, src.active2.fields["ma_dis"], src, src.active2.fields["ma_dis_d"], src, src.active2.fields["alg"], src, src.active2.fields["alg_d"], src, src.active2.fields["cdi"], src, src.active2.fields["cdi_d"], src, decode(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 (Medical Only)</A><BR><BR>", src)
|
||||
else
|
||||
dat += "<B>Medical Record Lost!</B><BR>"
|
||||
dat += text("<A href='?src=\ref[src];new=1'>New Record</A><BR><BR>")
|
||||
dat += text("\n<A href='?src=\ref[];print_p=1'>Print Record</A><BR>\n<A href='?src=\ref[];screen=2'>Back</A><BR>", src, src)
|
||||
if(5.0)
|
||||
dat += "<CENTER><B>Virus Database</B></CENTER>"
|
||||
/* Advanced diseases is weak! Feeble! Glory to virus2!
|
||||
for(var/Dt in typesof(/datum/disease/))
|
||||
var/datum/disease/Dis = new Dt(0)
|
||||
if(istype(Dis, /datum/disease/advance))
|
||||
continue // TODO (tm): Add advance diseases to the virus database which no one uses.
|
||||
if(!Dis.desc)
|
||||
continue
|
||||
dat += "<br><a href='?src=\ref[src];vir=[Dt]'>[Dis.name]</a>"
|
||||
*/
|
||||
for (var/ID in virusDB)
|
||||
var/datum/data/record/v = virusDB[ID]
|
||||
dat += "<br><a href='?src=\ref[src];vir=\ref[v]'>[v.fields["name"]]</a>"
|
||||
|
||||
dat += "<br><a href='?src=\ref[src];screen=1'>Back</a>"
|
||||
if(6.0)
|
||||
dat += "<center><b>Medical Robot Monitor</b></center>"
|
||||
dat += "<a href='?src=\ref[src];screen=1'>Back</a>"
|
||||
dat += "<br><b>Medical Robots:</b>"
|
||||
var/bdat = null
|
||||
for(var/obj/machinery/bot/medbot/M in world)
|
||||
|
||||
if(M.z != computer.z) continue //only find medibots on the same z-level as the computer
|
||||
var/turf/bl = get_turf(M)
|
||||
if(bl) //if it can't find a turf for the medibot, then it probably shouldn't be showing up
|
||||
bdat += "[M.name] - <b>\[[bl.x],[bl.y]\]</b> - [M.on ? "Online" : "Offline"]<br>"
|
||||
if((!isnull(M.reagent_glass)) && M.use_beaker)
|
||||
bdat += "Reservoir: \[[M.reagent_glass.reagents.total_volume]/[M.reagent_glass.reagents.maximum_volume]\]<br>"
|
||||
else
|
||||
bdat += "Using Internal Synthesizer.<br>"
|
||||
if(!bdat)
|
||||
dat += "<br><center>None detected</center>"
|
||||
else
|
||||
dat += "<br>[bdat]"
|
||||
|
||||
else
|
||||
else
|
||||
dat += text("<A href='?src=\ref[];login=1'>{Log In}</A>", src)
|
||||
popup.width = 600
|
||||
popup.height = 400
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(usr.browse_rsc_icon(computer.icon, computer.icon_state))
|
||||
popup.open()
|
||||
return
|
||||
|
||||
Topic(href, href_list)
|
||||
if(!interactable() || !computer.cardslot || ..(href,href_list))
|
||||
return
|
||||
if (!( data_core.general.Find(src.active1) ))
|
||||
src.active1 = null
|
||||
if (!( data_core.medical.Find(src.active2) ))
|
||||
src.active2 = null
|
||||
|
||||
if (href_list["temp"])
|
||||
src.temp = null
|
||||
|
||||
if (href_list["scan"])
|
||||
if (scan)
|
||||
if(istype(usr,/mob/living/carbon/human) && !usr.get_active_hand())
|
||||
computer.cardslot.remove(scan)
|
||||
else
|
||||
scan.loc = get_turf(src)
|
||||
scan = null
|
||||
else
|
||||
var/obj/item/I = usr.get_active_hand()
|
||||
if (istype(I, /obj/item/weapon/card/id))
|
||||
computer.cardslot.insert(I)
|
||||
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(usr, /mob/living/silicon/ai))
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
src.authenticated = usr.name
|
||||
src.rank = "AI"
|
||||
src.screen = 1
|
||||
|
||||
else if (istype(usr, /mob/living/silicon/robot))
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
src.authenticated = usr.name
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
src.rank = "[R.modtype] [R.braintype]"
|
||||
src.screen = 1
|
||||
|
||||
else if (istype(src.scan, /obj/item/weapon/card/id))
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
|
||||
if (src.check_access(src.scan))
|
||||
src.authenticated = src.scan.registered_name
|
||||
src.rank = src.scan.assignment
|
||||
src.screen = 1
|
||||
|
||||
if (src.authenticated)
|
||||
|
||||
if(href_list["screen"])
|
||||
src.screen = text2num(href_list["screen"])
|
||||
if(src.screen < 1)
|
||||
src.screen = 1
|
||||
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
|
||||
if(href_list["vir"])
|
||||
var/datum/data/record/v = locate(href_list["vir"])
|
||||
src.temp = "<center>GNAv2 based virus lifeform V-[v.fields["id"]]</center>"
|
||||
src.temp += "<br><b>Name:</b> <A href='?src=\ref[src];field=vir_name;edit_vir=\ref[v]'>[v.fields["name"]]</A>"
|
||||
src.temp += "<br><b>Antigen:</b> [v.fields["antigen"]]"
|
||||
src.temp += "<br><b>Spread:</b> [v.fields["spread type"]] "
|
||||
src.temp += "<br><b>Details:</b><br> <A href='?src=\ref[src];field=vir_desc;edit_vir=\ref[v]'>[v.fields["description"]]</A>"
|
||||
|
||||
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)
|
||||
|
||||
if (href_list["del_all2"])
|
||||
for(var/datum/data/record/R in data_core.medical)
|
||||
//R = null
|
||||
del(R)
|
||||
//Foreach goto(494)
|
||||
src.temp = "All records deleted."
|
||||
|
||||
if (href_list["field"])
|
||||
var/a1 = src.active1
|
||||
var/a2 = src.active2
|
||||
switch(href_list["field"])
|
||||
if("fingerprint")
|
||||
if (istype(src.active1, /datum/data/record))
|
||||
var/t1 = copytext(sanitize(input("Please input fingerprint hash:", "Med. records", src.active1.fields["fingerprint"], null) as text),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || 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 num
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active1 != a1))
|
||||
return
|
||||
src.active1.fields["age"] = t1
|
||||
if("mi_dis")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = copytext(sanitize(input("Please input minor disabilities list:", "Med. records", src.active2.fields["mi_dis"], null) as text),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["mi_dis"] = t1
|
||||
if("mi_dis_d")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = copytext(sanitize(input("Please summarize minor dis.:", "Med. records", src.active2.fields["mi_dis_d"], null) as message),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["mi_dis_d"] = t1
|
||||
if("ma_dis")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = copytext(sanitize(input("Please input major diabilities list:", "Med. records", src.active2.fields["ma_dis"], null) as text),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["ma_dis"] = t1
|
||||
if("ma_dis_d")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = copytext(sanitize(input("Please summarize major dis.:", "Med. records", src.active2.fields["ma_dis_d"], null) as message),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["ma_dis_d"] = t1
|
||||
if("alg")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = copytext(sanitize(input("Please state allergies:", "Med. records", src.active2.fields["alg"], null) as text),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["alg"] = t1
|
||||
if("alg_d")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = copytext(sanitize(input("Please summarize allergies:", "Med. records", src.active2.fields["alg_d"], null) as message),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["alg_d"] = t1
|
||||
if("cdi")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = copytext(sanitize(input("Please state diseases:", "Med. records", src.active2.fields["cdi"], null) as text),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["cdi"] = t1
|
||||
if("cdi_d")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = copytext(sanitize(input("Please summarize diseases:", "Med. records", src.active2.fields["cdi_d"], null) as message),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active2 != a2))
|
||||
return
|
||||
src.active2.fields["cdi_d"] = t1
|
||||
if("notes")
|
||||
if (istype(src.active2, /datum/data/record))
|
||||
var/t1 = copytext(html_encode(input("Please summarize notes:", "Med. records", html_decode(src.active2.fields["notes"]), null) as message),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || 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=ssd'>*SSD*</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>\n\t<A href='?src=\ref[];temp=1;p_stat=disabled'>Disabled</A><BR>", src, 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)
|
||||
if("b_dna")
|
||||
if (istype(src.active1, /datum/data/record))
|
||||
var/t1 = copytext(sanitize(input("Please input DNA hash:", "Med. records", src.active1.fields["dna"], null) as text),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active1 != a1))
|
||||
return
|
||||
src.active1.fields["dna"] = t1
|
||||
if("vir_name")
|
||||
var/datum/data/record/v = locate(href_list["edit_vir"])
|
||||
if (v)
|
||||
var/t1 = copytext(sanitize(input("Please input pathogen name:", "VirusDB", v.fields["name"], null) as text),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active1 != a1))
|
||||
return
|
||||
v.fields["name"] = t1
|
||||
if("vir_desc")
|
||||
var/datum/data/record/v = locate(href_list["edit_vir"])
|
||||
if (v)
|
||||
var/t1 = copytext(sanitize(input("Please input information about pathogen:", "VirusDB", v.fields["description"], null) as message),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active1 != a1))
|
||||
return
|
||||
v.fields["description"] = t1
|
||||
else
|
||||
|
||||
if (href_list["p_stat"])
|
||||
if (src.active1)
|
||||
switch(href_list["p_stat"])
|
||||
if("deceased")
|
||||
src.active1.fields["p_stat"] = "*Deceased*"
|
||||
if("ssd")
|
||||
src.active1.fields["p_stat"] = "*SSD*"
|
||||
if("active")
|
||||
src.active1.fields["p_stat"] = "Active"
|
||||
if("unfit")
|
||||
src.active1.fields["p_stat"] = "Physically Unfit"
|
||||
if("disabled")
|
||||
src.active1.fields["p_stat"] = "Disabled"
|
||||
|
||||
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.active1.fields["m_stat"] = "Stable"
|
||||
|
||||
|
||||
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+"
|
||||
|
||||
|
||||
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)
|
||||
|
||||
if (href_list["del_r2"])
|
||||
if (src.active2)
|
||||
//src.active2 = null
|
||||
del(src.active2)
|
||||
|
||||
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
|
||||
else
|
||||
//Foreach continue //goto(2540)
|
||||
src.active1 = R
|
||||
src.active2 = M
|
||||
src.screen = 4
|
||||
|
||||
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["b_dna"] = "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
|
||||
|
||||
if (href_list["add_c"])
|
||||
if (!( istype(src.active2, /datum/data/record) ))
|
||||
return
|
||||
var/a2 = src.active2
|
||||
var/t1 = copytext(sanitize(input("Add Comment:", "Med. records", null, null) as message),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( src.authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || src.active2 != a2))
|
||||
return
|
||||
var/counter = 1
|
||||
while(src.active2.fields[text("com_[]", counter)])
|
||||
counter++
|
||||
src.active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]<BR>[t1]")
|
||||
|
||||
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>"
|
||||
|
||||
if (href_list["search"])
|
||||
var/t1 = input("Search String: (Name, DNA, or ID)", "Med. records", null, null) as text
|
||||
if ((!( t1 ) || usr.stat || !( src.authenticated ) || usr.restrained() || ((!interactable()) && (!istype(usr, /mob/living/silicon)))))
|
||||
return
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
t1 = lowertext(t1)
|
||||
for(var/datum/data/record/R in data_core.medical)
|
||||
if ((lowertext(R.fields["name"]) == t1 || t1 == lowertext(R.fields["id"]) || t1 == lowertext(R.fields["b_dna"])))
|
||||
src.active2 = R
|
||||
else
|
||||
//Foreach continue //goto(3229)
|
||||
if (!( src.active2 ))
|
||||
src.temp = text("Could not locate record [].", t1)
|
||||
else
|
||||
for(var/datum/data/record/E in data_core.general)
|
||||
if ((E.fields["name"] == src.active2.fields["name"] || E.fields["id"] == src.active2.fields["id"]))
|
||||
src.active1 = E
|
||||
else
|
||||
//Foreach continue //goto(3334)
|
||||
src.screen = 4
|
||||
|
||||
if (href_list["print_p"])
|
||||
if (!( src.printing ))
|
||||
src.printing = 1
|
||||
var/datum/data/record/record1 = null
|
||||
var/datum/data/record/record2 = null
|
||||
if ((istype(src.active1, /datum/data/record) && data_core.general.Find(src.active1)))
|
||||
record1 = active1
|
||||
if ((istype(src.active2, /datum/data/record) && data_core.medical.Find(src.active2)))
|
||||
record2 = active2
|
||||
sleep(50)
|
||||
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( computer.loc )
|
||||
P.info = "<CENTER><B>Medical Record</B></CENTER><BR>"
|
||||
if (record1)
|
||||
P.info += text("Name: [] ID: []<BR>\nSex: []<BR>\nAge: []<BR>\nFingerprint: []<BR>\nPhysical Status: []<BR>\nMental Status: []<BR>", record1.fields["name"], record1.fields["id"], record1.fields["sex"], record1.fields["age"], record1.fields["fingerprint"], record1.fields["p_stat"], record1.fields["m_stat"])
|
||||
P.name = text("Medical Record ([])", record1.fields["name"])
|
||||
else
|
||||
P.info += "<B>General Record Lost!</B><BR>"
|
||||
P.name = "Medical Record"
|
||||
if (record2)
|
||||
P.info += text("<BR>\n<CENTER><B>Medical Data</B></CENTER><BR>\nBlood Type: []<BR>\nDNA: []<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>", record2.fields["b_type"], record2.fields["b_dna"], record2.fields["mi_dis"], record2.fields["mi_dis_d"], record2.fields["ma_dis"], record2.fields["ma_dis_d"], record2.fields["alg"], record2.fields["alg_d"], record2.fields["cdi"], record2.fields["cdi_d"], decode(record2.fields["notes"]))
|
||||
var/counter = 1
|
||||
while(record2.fields[text("com_[]", counter)])
|
||||
P.info += text("[]<BR>", record2.fields[text("com_[]", counter)])
|
||||
counter++
|
||||
else
|
||||
P.info += "<B>Medical Record Lost!</B><BR>"
|
||||
P.info += "</TT>"
|
||||
src.printing = null
|
||||
|
||||
interact()
|
||||
return
|
||||
@@ -0,0 +1,450 @@
|
||||
/obj/machinery/computer3/message_monitor
|
||||
default_prog = /datum/file/program/message_mon
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/networking/prox)
|
||||
|
||||
|
||||
//BROKEN AS HELL, DON'T USE UNTIL FIXED
|
||||
|
||||
/datum/file/program/message_mon
|
||||
name = "Message Monitor Console"
|
||||
desc = "Used to Monitor the crew's messages, that are sent via PDA. Can also be used to view Request Console messages."
|
||||
active_state = "comm_logs"
|
||||
var/hack_icon = "comm_logsc"
|
||||
var/normal_icon = "comm_logs"
|
||||
|
||||
//Server linked to.
|
||||
var/obj/machinery/message_server/linkedServer = null
|
||||
//Sparks effect - For emag
|
||||
//var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread
|
||||
|
||||
//Messages - Saves me time if I want to change something.
|
||||
var/noserver = "<span class='alert'>ALERT: No server detected.</span>"
|
||||
var/incorrectkey = "<span class='warning'>ALERT: Incorrect decryption key!</span>"
|
||||
var/defaultmsg = "<span class='notice'>Welcome. Please select an option.</span>"
|
||||
var/rebootmsg = "<span class='warning'>%$&(£: Critical %$$@ Error // !RestArting! <lOadiNg backUp iNput ouTput> - ?pLeaSe wAit!</span>"
|
||||
|
||||
//Computer properties
|
||||
var/screen = 0 // 0 = Main menu, 1 = Message Logs, 2 = Hacked screen, 3 = Custom Message
|
||||
var/hacking = 0 // Is it being hacked into by the AI/Cyborg
|
||||
var/emag = 0 // When it is emagged.
|
||||
var/message = "<span class='notice'>System bootup complete. Please select an option.</span>" // The message that shows on the main menu.
|
||||
var/auth = 0 // Are they authenticated?
|
||||
var/optioncount = 7
|
||||
|
||||
// Custom Message Properties
|
||||
var/customsender = "System Administrator"
|
||||
var/obj/item/device/pda/customrecepient = null
|
||||
var/customjob = "Admin"
|
||||
var/custommessage = "This is a test, please ignore."
|
||||
|
||||
|
||||
procinitialize()
|
||||
if(!linkedServer)
|
||||
if(message_servers && message_servers.len > 0)
|
||||
linkedServer = message_servers[1]
|
||||
return
|
||||
|
||||
|
||||
update_icon()
|
||||
if(emag || hacking)
|
||||
overlay.icon_state = hack_icon
|
||||
else
|
||||
overlay.icon_state = normal_icon
|
||||
computer.update_icon()
|
||||
|
||||
interact()
|
||||
if(!interactable())
|
||||
return
|
||||
//If the computer is being hacked or is emagged, display the reboot message.
|
||||
if(hacking || emag)
|
||||
message = rebootmsg
|
||||
var/dat = "<head><title>Message Monitor Console</title></head><body>"
|
||||
dat += "<center><h2>Message Monitor Console</h2></center><hr>"
|
||||
dat += "<center><h4><font color='blue'[message]</h5></center>"
|
||||
|
||||
if(auth)
|
||||
dat += "<h4><dd><A href='?src=\ref[src];auth=1'>	<font color='green'>\[Authenticated\]</font></a>	/"
|
||||
dat += " Server Power: <A href='?src=\ref[src];active=1'>[src.linkedServer && src.linkedServer.active ? "<font color='green'>\[On\]</font>":"<font color='red'>\[Off\]</font>"]</a></h4>"
|
||||
else
|
||||
dat += "<h4><dd><A href='?src=\ref[src];auth=1'>	<font color='red'>\[Unauthenticated\]</font></a>	/"
|
||||
dat += " Server Power: <u>[src.linkedServer && src.linkedServer.active ? "<font color='green'>\[On\]</font>":"<font color='red'>\[Off\]</font>"]</u></h4>"
|
||||
|
||||
if(hacking || emag)
|
||||
screen = 2
|
||||
else if(!auth || !linkedServer || (linkedServer.stat & (NOPOWER|BROKEN)))
|
||||
if(!linkedServer || (linkedServer.stat & (NOPOWER|BROKEN))) message = noserver
|
||||
screen = 0
|
||||
|
||||
switch(screen)
|
||||
//Main menu
|
||||
if(0)
|
||||
//	 = TAB
|
||||
var/i = 0
|
||||
dat += "<dd><A href='?src=\ref[src];find=1'>	[++i]. Link To A Server</a></dd>"
|
||||
if(auth)
|
||||
if(!linkedServer || (linkedServer.stat & (NOPOWER|BROKEN)))
|
||||
dat += "<dd><A>	ERROR: Server not found!</A><br></dd>"
|
||||
else
|
||||
dat += "<dd><A href='?src=\ref[src];view=1'>	[++i]. View Message Logs </a><br></dd>"
|
||||
dat += "<dd><A href='?src=\ref[src];viewr=1'>	[++i]. View Request Console Logs </a></br></dd>"
|
||||
dat += "<dd><A href='?src=\ref[src];clear=1'>	[++i]. Clear Message Logs</a><br></dd>"
|
||||
dat += "<dd><A href='?src=\ref[src];clearr=1'>	[++i]. Clear Request Console Logs</a><br></dd>"
|
||||
dat += "<dd><A href='?src=\ref[src];pass=1'>	[++i]. Set Custom Key</a><br></dd>"
|
||||
dat += "<dd><A href='?src=\ref[src];msg=1'>	[++i]. Send Admin Message</a><br></dd>"
|
||||
else
|
||||
for(var/n = ++i; n <= optioncount; n++)
|
||||
dat += "<dd><font color='blue'>	[n]. ---------------</font><br></dd>"
|
||||
if((istype(usr, /mob/living/silicon/ai) || istype(usr, /mob/living/silicon/robot)) && (usr.mind.special_role && usr.mind.original == usr))
|
||||
//Malf/Traitor AIs can bruteforce into the system to gain the Key.
|
||||
dat += "<dd><A href='?src=\ref[src];hack=1'><i><font color='Red'>*&@#. Bruteforce Key</font></i></font></a><br></dd>"
|
||||
else
|
||||
dat += "<br>"
|
||||
|
||||
//Bottom message
|
||||
if(!auth)
|
||||
dat += "<br><hr><dd><span class='notice'>Please authenticate with the server in order to show additional options.</span>"
|
||||
else
|
||||
dat += "<br><hr><dd><span class='warning'>Reg, #514 forbids sending messages to a Head of Staff containing Erotic Rendering Properties.</span>"
|
||||
|
||||
//Message Logs
|
||||
if(1)
|
||||
var/index = 0
|
||||
//var/recipient = "Unspecified" //name of the person
|
||||
//var/sender = "Unspecified" //name of the sender
|
||||
//var/message = "Blank" //transferred message
|
||||
dat += "<center><A href='?src=\ref[src];back=1'>Back</a> - <A href='?src=\ref[src];refresh=1'>Refresh</center><hr>"
|
||||
dat += "<table border='1' width='100%'><tr><th width = '5%'>X</th><th width='15%'>Sender</th><th width='15%'>Recipient</th><th width='300px' word-wrap: break-word>Message</th></tr>"
|
||||
for(var/datum/data_pda_msg/pda in src.linkedServer.pda_msgs)
|
||||
index++
|
||||
if(index > 3000)
|
||||
break
|
||||
// Del - Sender - Recepient - Message
|
||||
// X - Al Green - Your Mom - WHAT UP!?
|
||||
dat += "<tr><td width = '5%'><center><A href='?src=\ref[src];delete=\ref[pda]' style='color: rgb(255,0,0)'>X</a></center></td><td width='15%'>[pda.sender]</td><td width='15%'>[pda.recipient]</td><td width='300px'>[pda.message]</td></tr>"
|
||||
dat += "</table>"
|
||||
//Hacking screen.
|
||||
if(2)
|
||||
if(istype(usr, /mob/living/silicon/ai) || istype(usr, /mob/living/silicon/robot))
|
||||
dat += "Brute-forcing for server key.<br> It will take 20 seconds for every character that the password has."
|
||||
dat += "In the meantime, this console can reveal your true intentions if you let someone access it. Make sure no humans enter the room during that time."
|
||||
else
|
||||
//It's the same message as the one above but in binary. Because robots understand binary and humans don't... well I thought it was clever.
|
||||
dat += {"01000010011100100111010101110100011001010010110<br>
|
||||
10110011001101111011100100110001101101001011011100110011<br>
|
||||
10010000001100110011011110111001000100000011100110110010<br>
|
||||
10111001001110110011001010111001000100000011010110110010<br>
|
||||
10111100100101110001000000100100101110100001000000111011<br>
|
||||
10110100101101100011011000010000001110100011000010110101<br>
|
||||
10110010100100000001100100011000000100000011100110110010<br>
|
||||
10110001101101111011011100110010001110011001000000110011<br>
|
||||
00110111101110010001000000110010101110110011001010111001<br>
|
||||
00111100100100000011000110110100001100001011100100110000<br>
|
||||
10110001101110100011001010111001000100000011101000110100<br>
|
||||
00110000101110100001000000111010001101000011001010010000<br>
|
||||
00111000001100001011100110111001101110111011011110111001<br>
|
||||
00110010000100000011010000110000101110011001011100010000<br>
|
||||
00100100101101110001000000111010001101000011001010010000<br>
|
||||
00110110101100101011000010110111001110100011010010110110<br>
|
||||
10110010100101100001000000111010001101000011010010111001<br>
|
||||
10010000001100011011011110110111001110011011011110110110<br>
|
||||
00110010100100000011000110110000101101110001000000111001<br>
|
||||
00110010101110110011001010110000101101100001000000111100<br>
|
||||
10110111101110101011100100010000001110100011100100111010<br>
|
||||
10110010100100000011010010110111001110100011001010110111<br>
|
||||
00111010001101001011011110110111001110011001000000110100<br>
|
||||
10110011000100000011110010110111101110101001000000110110<br>
|
||||
00110010101110100001000000111001101101111011011010110010<br>
|
||||
10110111101101110011001010010000001100001011000110110001<br>
|
||||
10110010101110011011100110010000001101001011101000010111<br>
|
||||
00010000001001101011000010110101101100101001000000111001<br>
|
||||
10111010101110010011001010010000001101110011011110010000<br>
|
||||
00110100001110101011011010110000101101110011100110010000<br>
|
||||
00110010101101110011101000110010101110010001000000111010<br>
|
||||
00110100001100101001000000111001001101111011011110110110<br>
|
||||
10010000001100100011101010111001001101001011011100110011<br>
|
||||
10010000001110100011010000110000101110100001000000111010<br>
|
||||
001101001011011010110010100101110"}
|
||||
|
||||
//Fake messages
|
||||
if(3)
|
||||
dat += "<center><A href='?src=\ref[src];back=1'>Back</a> - <A href='?src=\ref[src];Reset=1'>Reset</a></center><hr>"
|
||||
|
||||
dat += {"<table border='1' width='100%'>
|
||||
<tr><td width='20%'><A href='?src=\ref[src];select=Sender'>Sender</a></td>
|
||||
<td width='20%'><A href='?src=\ref[src];select=RecJob'>Sender's Job</a></td>
|
||||
<td width='20%'><A href='?src=\ref[src];select=Recepient'>Recipient</a></td>
|
||||
<td width='300px' word-wrap: break-word><A href='?src=\ref[src];select=Message'>Message</a></td></tr>"}
|
||||
//Sender - Sender's Job - Recepient - Message
|
||||
//Al Green- Your Dad - Your Mom - WHAT UP!?
|
||||
|
||||
dat += {"<tr><td width='20%'>[customsender]</td>
|
||||
<td width='20%'>[customjob]</td>
|
||||
<td width='20%'>[customrecepient ? customrecepient.owner : "NONE"]</td>
|
||||
<td width='300px'>[custommessage]</td></tr>"}
|
||||
dat += "</table><br><center><A href='?src=\ref[src];select=Send'>Send</a>"
|
||||
|
||||
//Request Console Logs
|
||||
if(4)
|
||||
|
||||
var/index = 0
|
||||
/* data_rc_msg
|
||||
X - 5%
|
||||
var/rec_dpt = "Unspecified" //name of the person - 15%
|
||||
var/send_dpt = "Unspecified" //name of the sender- 15%
|
||||
var/message = "Blank" //transferred message - 300px
|
||||
var/stamp = "Unstamped" - 15%
|
||||
var/id_auth = "Unauthenticated" - 15%
|
||||
var/priority = "Normal" - 10%
|
||||
*/
|
||||
dat += "<center><A href='?src=\ref[src];back=1'>Back</a> - <A href='?src=\ref[src];refresh=1'>Refresh</center><hr>"
|
||||
dat += {"<table border='1' width='100%'><tr><th width = '5%'>X</th><th width='15%'>Sending Dep.</th><th width='15%'>Receiving Dep.</th>
|
||||
<th width='300px' word-wrap: break-word>Message</th><th width='15%'>Stamp</th><th width='15%'>ID Auth.</th><th width='15%'>Priority.</th></tr>"}
|
||||
for(var/datum/data_rc_msg/rc in src.linkedServer.rc_msgs)
|
||||
index++
|
||||
if(index > 3000)
|
||||
break
|
||||
// Del - Sender - Recepient - Message
|
||||
// X - Al Green - Your Mom - WHAT UP!?
|
||||
dat += {"<tr><td width = '5%'><center><A href='?src=\ref[src];deleter=\ref[rc]' style='color: rgb(255,0,0)'>X</a></center></td><td width='15%'>[rc.send_dpt]</td>
|
||||
<td width='15%'>[rc.rec_dpt]</td><td width='300px'>[rc.message]</td><td width='15%'>[rc.stamp]</td><td width='15%'>[rc.id_auth]</td><td width='15%'>[rc.priority]</td></tr>"}
|
||||
dat += "</table>"
|
||||
|
||||
|
||||
popup.width = 700
|
||||
popup.height = 700
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(usr.browse_rsc_icon(computer.icon, computer.icon_state))
|
||||
popup.open()
|
||||
return
|
||||
|
||||
|
||||
proc/BruteForce(mob/usr as mob)
|
||||
if(isnull(linkedServer))
|
||||
usr << "<span class='warning'>Could not complete brute-force: Linked Server Disconnected!</span>"
|
||||
else
|
||||
var/currentKey = src.linkedServer.decryptkey
|
||||
usr << "<span class='warning'>Brute-force completed! The key is '[currentKey]'.</span>"
|
||||
src.hacking = 0
|
||||
src.active_state = normal_icon
|
||||
src.screen = 0 // Return the screen back to normal
|
||||
|
||||
proc/UnmagConsole()
|
||||
src.active_state = normal_icon
|
||||
src.emag = 0
|
||||
|
||||
proc/ResetMessage()
|
||||
customsender = "System Administrator"
|
||||
customrecepient = null
|
||||
custommessage = "This is a test, please ignore."
|
||||
customjob = "Admin"
|
||||
|
||||
Topic(var/href, var/list/href_list)
|
||||
if(!interactable() || ..(href,href_list))
|
||||
return
|
||||
|
||||
if ("auth" in href_list)
|
||||
if(auth)
|
||||
auth = 0
|
||||
screen = 0
|
||||
else
|
||||
var/dkey = trim(input(usr, "Please enter the decryption key.") as text|null)
|
||||
if(dkey && dkey != "")
|
||||
if(src.linkedServer.decryptkey == dkey)
|
||||
auth = 1
|
||||
else
|
||||
message = incorrectkey
|
||||
|
||||
//Turn the server on/off.
|
||||
if ("active" in href_list)
|
||||
if(auth) linkedServer.active = !linkedServer.active
|
||||
//Find a server
|
||||
if ("find" in href_list)
|
||||
if(message_servers && message_servers.len > 1)
|
||||
src.linkedServer = input(usr,"Please select a server.", "Select a server.", null) as null|anything in message_servers
|
||||
message = "<span class='alert'>NOTICE: Server selected.</span>"
|
||||
else if(message_servers && message_servers.len > 0)
|
||||
linkedServer = message_servers[1]
|
||||
message = "<span class='notice'>NOTICE: Only Single Server Detected - Server selected.</span>"
|
||||
else
|
||||
message = noserver
|
||||
|
||||
//View the logs - KEY REQUIRED
|
||||
if ("view" in href_list)
|
||||
if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN)))
|
||||
message = noserver
|
||||
else
|
||||
if(auth)
|
||||
src.screen = 1
|
||||
|
||||
//Clears the logs - KEY REQUIRED
|
||||
if ("clear" in href_list)
|
||||
if(!linkedServer || (src.linkedServer.stat & (NOPOWER|BROKEN)))
|
||||
message = noserver
|
||||
else
|
||||
if(auth)
|
||||
src.linkedServer.pda_msgs = list()
|
||||
message = "<span class='notice'>NOTICE: Logs cleared.</span>"
|
||||
//Clears the request console logs - KEY REQUIRED
|
||||
if ("clearr" in href_list)
|
||||
if(!linkedServer || (src.linkedServer.stat & (NOPOWER|BROKEN)))
|
||||
message = noserver
|
||||
else
|
||||
if(auth)
|
||||
src.linkedServer.rc_msgs = list()
|
||||
message = "<span class='notice'>NOTICE: Logs cleared.</span>"
|
||||
//Change the password - KEY REQUIRED
|
||||
if ("pass" in href_list)
|
||||
if(!linkedServer || (src.linkedServer.stat & (NOPOWER|BROKEN)))
|
||||
message = noserver
|
||||
else
|
||||
if(auth)
|
||||
var/dkey = trim(input(usr, "Please enter the decryption key.") as text|null)
|
||||
if(dkey && dkey != "")
|
||||
if(src.linkedServer.decryptkey == dkey)
|
||||
var/newkey = trim(input(usr,"Please enter the new key (3 - 16 characters max):"))
|
||||
if(length(newkey) <= 3)
|
||||
message = "<span class='notice'>NOTICE: Decryption key too short!</span>"
|
||||
else if(length(newkey) > 16)
|
||||
message = "<span class='notice'>NOTICE: Decryption key too long!</span>"
|
||||
else if(newkey && newkey != "")
|
||||
src.linkedServer.decryptkey = newkey
|
||||
message = "<span class='notice'>NOTICE: Decryption key set.</span>"
|
||||
else
|
||||
message = incorrectkey
|
||||
|
||||
//Hack the Console to get the password
|
||||
if ("hack" in href_list)
|
||||
if((istype(usr, /mob/living/silicon/ai) || istype(usr, /mob/living/silicon/robot)) && (usr.mind.special_role && usr.mind.original == usr))
|
||||
src.hacking = 1
|
||||
src.screen = 2
|
||||
src.active_state = hack_icon
|
||||
//Time it takes to bruteforce is dependant on the password length.
|
||||
spawn(100*length(src.linkedServer.decryptkey))
|
||||
if(src && src.linkedServer && usr)
|
||||
BruteForce(usr)
|
||||
//Delete the log.
|
||||
if ("delete" in href_list)
|
||||
//Are they on the view logs screen?
|
||||
if(screen == 1)
|
||||
if(!linkedServer || (src.linkedServer.stat & (NOPOWER|BROKEN)))
|
||||
message = noserver
|
||||
else //if(istype(href_list["delete"], /datum/data_pda_msg))
|
||||
src.linkedServer.pda_msgs -= locate(href_list["delete"])
|
||||
message = "<span class='notice'>NOTICE: Log Deleted!</span>"
|
||||
//Delete the request console log.
|
||||
if ("deleter" in href_list)
|
||||
//Are they on the view logs screen?
|
||||
if(screen == 4)
|
||||
if(!linkedServer || (src.linkedServer.stat & (NOPOWER|BROKEN)))
|
||||
message = noserver
|
||||
else //if(istype(href_list["delete"], /datum/data_pda_msg))
|
||||
src.linkedServer.rc_msgs -= locate(href_list["deleter"])
|
||||
message = "<span class='notice'>NOTICE: Log Deleted!</span>"
|
||||
//Create a custom message
|
||||
if ("msg" in href_list)
|
||||
if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN)))
|
||||
message = noserver
|
||||
else
|
||||
if(auth)
|
||||
src.screen = 3
|
||||
//Fake messaging selection - KEY REQUIRED
|
||||
if ("select" in href_list)
|
||||
if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN)))
|
||||
message = noserver
|
||||
screen = 0
|
||||
else
|
||||
switch(href_list["select"])
|
||||
|
||||
//Reset
|
||||
if("Reset")
|
||||
ResetMessage()
|
||||
|
||||
//Select Your Name
|
||||
if("Sender")
|
||||
customsender = input(usr, "Please enter the sender's name.") as text|null
|
||||
|
||||
//Select Receiver
|
||||
if("Recepient")
|
||||
//Get out list of viable PDAs
|
||||
var/list/obj/item/device/pda/sendPDAs = list()
|
||||
for(var/obj/item/device/pda/P in PDAs)
|
||||
if(!P.owner || P.toff || P.hidden) continue
|
||||
sendPDAs += P
|
||||
if(PDAs && PDAs.len > 0)
|
||||
customrecepient = input(usr, "Select a PDA from the list.") as null|anything in sortAtom(sendPDAs)
|
||||
else
|
||||
customrecepient = null
|
||||
|
||||
|
||||
//Enter custom job
|
||||
if("RecJob")
|
||||
customjob = input(usr, "Please enter the sender's job.") as text|null
|
||||
|
||||
//Enter message
|
||||
if("Message")
|
||||
custommessage = input(usr, "Please enter your message.") as text|null
|
||||
custommessage = copytext(sanitize(custommessage), 1, MAX_MESSAGE_LEN)
|
||||
|
||||
//Send message
|
||||
if("Send")
|
||||
|
||||
if(isnull(customsender) || customsender == "")
|
||||
customsender = "UNKNOWN"
|
||||
|
||||
if(isnull(customrecepient))
|
||||
message = "<span class='notice'>NOTICE: No recepient selected!</span>"
|
||||
return src.attack_hand(usr)
|
||||
|
||||
if(isnull(custommessage) || custommessage == "")
|
||||
message = "<span class='notice'>NOTICE: No message entered!</span>"
|
||||
return src.attack_hand(usr)
|
||||
|
||||
var/obj/item/device/pda/PDARec = null
|
||||
for (var/obj/item/device/pda/P in PDAs)
|
||||
if (!P.owner || P.toff || P.hidden) continue
|
||||
if(P.owner == customsender)
|
||||
PDARec = P
|
||||
//Sender isn't faking as someone who exists
|
||||
if(isnull(PDARec))
|
||||
src.linkedServer.send_pda_message("[customrecepient.owner]", "[customsender]","[custommessage]")
|
||||
customrecepient.tnote += "<i><b>← From <a href='byond://?src=\ref[customrecepient];choice=Message;target=\ref[src]'>[customsender]</a> ([customjob]):</b></i><br>[custommessage]<br>"
|
||||
if (!customrecepient.silent)
|
||||
playsound(customrecepient.loc, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
for (var/mob/O in hearers(3, customrecepient.loc))
|
||||
O.show_message(text("\icon[customrecepient] *[customrecepient.ttone]*"))
|
||||
if( customrecepient.loc && ishuman(customrecepient.loc) )
|
||||
var/mob/living/carbon/human/H = customrecepient.loc
|
||||
H << "\icon[customrecepient] <b>Message from [customsender] ([customjob]), </b>\"[custommessage]\" (<a href='byond://?src=\ref[src];choice=Message;skiprefresh=1;target=\ref[src]'>Reply</a>)"
|
||||
log_pda("[usr] (PDA: [customsender]) sent \"[custommessage]\" to [customrecepient.owner]")
|
||||
customrecepient.overlays.Cut()
|
||||
customrecepient.overlays += image('icons/obj/pda.dmi', "pda-r")
|
||||
//Sender is faking as someone who exists
|
||||
else
|
||||
src.linkedServer.send_pda_message("[customrecepient.owner]", "[PDARec.owner]","[custommessage]")
|
||||
customrecepient.tnote += "<i><b>← From <a href='byond://?src=\ref[customrecepient];choice=Message;target=\ref[PDARec]'>[PDARec.owner]</a> ([customjob]):</b></i><br>[custommessage]<br>"
|
||||
if (!customrecepient.silent)
|
||||
playsound(customrecepient.loc, 'sound/machines/twobeep.ogg', 50, 1)
|
||||
for (var/mob/O in hearers(3, customrecepient.loc))
|
||||
O.show_message(text("\icon[customrecepient] *[customrecepient.ttone]*"))
|
||||
if( customrecepient.loc && ishuman(customrecepient.loc) )
|
||||
var/mob/living/carbon/human/H = customrecepient.loc
|
||||
H << "\icon[customrecepient] <b>Message from [PDARec.owner] ([customjob]), </b>\"[custommessage]\" (<a href='byond://?src=\ref[customrecepient];choice=Message;skiprefresh=1;target=\ref[PDARec]'>Reply</a>)"
|
||||
log_pda("[usr] (PDA: [PDARec.owner]) sent \"[custommessage]\" to [customrecepient.owner]")
|
||||
customrecepient.overlays.Cut()
|
||||
customrecepient.overlays += image('icons/obj/pda.dmi', "pda-r")
|
||||
//Finally..
|
||||
ResetMessage()
|
||||
|
||||
//Request Console Logs - KEY REQUIRED
|
||||
if("viewr" in href_list)
|
||||
if(src.linkedServer == null || (src.linkedServer.stat & (NOPOWER|BROKEN)))
|
||||
message = noserver
|
||||
else
|
||||
if(auth)
|
||||
src.screen = 4
|
||||
|
||||
//usr << href_list["select"]
|
||||
|
||||
if ("back" in href_list)
|
||||
src.screen = 0
|
||||
interact()
|
||||
@@ -0,0 +1,48 @@
|
||||
/obj/machinery/computer3/powermonitor
|
||||
default_prog = /datum/file/program/powermon
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/networking/cable)
|
||||
icon_state = "frame-eng"
|
||||
|
||||
/datum/file/program/powermon
|
||||
name = "power monitoring console"
|
||||
desc = "It monitors APC status."
|
||||
active_state = "power"
|
||||
|
||||
proc/format(var/obj/machinery/power/apc/A)
|
||||
var/static/list/S = list(" Off","AOff"," On", " AOn")
|
||||
var/static/list/chg = list("N","C","F")
|
||||
return "[copytext(add_tspace("\The [A.area]", 30), 1, 30)] [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>"
|
||||
|
||||
interact()
|
||||
if(!interactable())
|
||||
return
|
||||
if(!computer.net)
|
||||
computer.Crash(MISSING_PERIPHERAL)
|
||||
return
|
||||
var/list/L = computer.net.get_machines(/obj/machinery/power/apc)
|
||||
var/t = ""
|
||||
t += "<A href='?src=\ref[src]'>Refresh</A><br /><br />"
|
||||
if(!L || !L.len)
|
||||
t += "No connection"
|
||||
else
|
||||
var/datum/powernet/powernet = computer.net.connect_to(/datum/powernet,null)
|
||||
if(powernet)
|
||||
t += "<PRE>Total power: [powernet.avail] W<BR>Total load: [num2text(powernet.viewload,10)] W<BR>"
|
||||
else
|
||||
t += "<PRE><i>Power statistics unavailable</i><BR>"
|
||||
t += "<FONT SIZE=-1>"
|
||||
|
||||
if(L.len > 0)
|
||||
t += "Area Eqp./Lgt./Env. Load Cell<HR>"
|
||||
for(var/obj/machinery/power/apc/A in L)
|
||||
t += src.format(A)
|
||||
t += "</FONT></PRE>"
|
||||
|
||||
popup.set_content(t)
|
||||
popup.open()
|
||||
|
||||
Topic(var/href, var/list/href_list)
|
||||
if(!interactable() || ..(href,href_list))
|
||||
return
|
||||
interact()
|
||||
@@ -0,0 +1,100 @@
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
|
||||
/obj/machinery/computer3/prisoner
|
||||
default_prog = /datum/file/program/prisoner
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/networking/radio)
|
||||
icon_state = "frame-sec"
|
||||
|
||||
/datum/file/program/prisoner
|
||||
name = "Prisoner Management Console"
|
||||
active_state = "explosive"
|
||||
req_access = list(access_armory)
|
||||
|
||||
var/id = 0.0
|
||||
var/temp = null
|
||||
var/status = 0
|
||||
var/timeleft = 60
|
||||
var/stop = 0.0
|
||||
var/screen = 0 // 0 - No Access Denied, 1 - Access allowed
|
||||
|
||||
|
||||
interact()
|
||||
if(!interactable())
|
||||
return
|
||||
var/dat
|
||||
dat += "<B>Prisoner Implant Manager System</B><BR>"
|
||||
if(screen == 0)
|
||||
dat += "<HR><A href='?src=\ref[src];lock=1'>Unlock Console</A>"
|
||||
else if(screen == 1)
|
||||
dat += "<HR>Chemical Implants<BR>"
|
||||
var/turf/Tr = null
|
||||
for(var/obj/item/weapon/implant/chem/C in world)
|
||||
Tr = get_turf(C)
|
||||
if((Tr) && (Tr.z != computer.z)) continue//Out of range
|
||||
if(!C.implanted) continue
|
||||
dat += "[C.imp_in.name] | Remaining Units: [C.reagents.total_volume] | Inject: "
|
||||
dat += "<A href='?src=\ref[src];inject1=\ref[C]'>(<font color=red>(1)</font>)</A>"
|
||||
dat += "<A href='?src=\ref[src];inject5=\ref[C]'>(<font color=red>(5)</font>)</A>"
|
||||
dat += "<A href='?src=\ref[src];inject10=\ref[C]'>(<font color=red>(10)</font>)</A><BR>"
|
||||
dat += "********************************<BR>"
|
||||
dat += "<HR>Tracking Implants<BR>"
|
||||
for(var/obj/item/weapon/implant/tracking/T in world)
|
||||
Tr = get_turf(T)
|
||||
if((Tr) && (Tr.z != computer.z)) continue//Out of range
|
||||
if(!T.implanted) continue
|
||||
var/loc_display = "Unknown"
|
||||
var/mob/living/carbon/M = T.imp_in
|
||||
if(M.z == 1 && !istype(M.loc, /turf/space))
|
||||
var/turf/mob_loc = get_turf(M)
|
||||
loc_display = mob_loc.loc
|
||||
if(T.malfunction)
|
||||
loc_display = pick(teleportlocs)
|
||||
dat += "ID: [T.id] | Location: [loc_display]<BR>"
|
||||
dat += "<A href='?src=\ref[src];warn=\ref[T]'>(<i>Send Message</i></font>)</A> |<BR>"
|
||||
dat += "********************************<BR>"
|
||||
dat += "<HR><A href='?src=\ref[src];lock=1'>Lock Console</A>"
|
||||
|
||||
popup.width = 400
|
||||
popup.height = 500
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(usr.browse_rsc_icon(computer.icon, computer.icon_state))
|
||||
popup.open()
|
||||
return
|
||||
|
||||
|
||||
process()
|
||||
if(!..())
|
||||
interact()
|
||||
return
|
||||
|
||||
|
||||
Topic(href, href_list)
|
||||
if(!interactable() || ..(href,href_list))
|
||||
return
|
||||
|
||||
if(href_list["inject1"])
|
||||
var/obj/item/weapon/implant/I = locate(href_list["inject1"])
|
||||
if(I) I.activate(1)
|
||||
|
||||
else if(href_list["inject5"])
|
||||
var/obj/item/weapon/implant/I = locate(href_list["inject5"])
|
||||
if(I) I.activate(5)
|
||||
|
||||
else if(href_list["inject10"])
|
||||
var/obj/item/weapon/implant/I = locate(href_list["inject10"])
|
||||
if(I) I.activate(10)
|
||||
|
||||
else if(href_list["lock"])
|
||||
screen = !screen
|
||||
|
||||
else if(href_list["warn"])
|
||||
var/warning = copytext(sanitize(input(usr,"Message:","Enter your message here!","")),1,MAX_MESSAGE_LEN)
|
||||
if(!warning) return
|
||||
var/obj/item/weapon/implant/I = locate(href_list["warn"])
|
||||
if((I)&&(I.imp_in))
|
||||
var/mob/living/carbon/R = I.imp_in
|
||||
R << "\green You hear a voice in your head saying: '[warning]'"
|
||||
|
||||
interact()
|
||||
return
|
||||
|
||||
|
||||
@@ -0,0 +1,242 @@
|
||||
//Config stuff
|
||||
#define PRISON_MOVETIME 150 //Time to station is milliseconds.
|
||||
#define PRISON_STATION_AREATYPE "/area/shuttle/prison/station" //Type of the prison shuttle area for station
|
||||
#define PRISON_DOCK_AREATYPE "/area/shuttle/prison/prison" //Type of the prison shuttle area for dock
|
||||
|
||||
var/prison_shuttle_moving_to_station = 0
|
||||
var/prison_shuttle_moving_to_prison = 0
|
||||
var/prison_shuttle_at_station = 0
|
||||
var/prison_shuttle_can_send = 1
|
||||
var/prison_shuttle_time = 0
|
||||
var/prison_shuttle_timeleft = 0
|
||||
|
||||
/obj/machinery/computer3/prison_shuttle
|
||||
name = "Prison Shuttle Console"
|
||||
icon = 'icons/obj/computer.dmi'
|
||||
icon_state = "shuttle"
|
||||
req_access = list(access_security)
|
||||
circuit = "/obj/item/part/board/circuit/prison_shuttle"
|
||||
var/temp = null
|
||||
var/hacked = 0
|
||||
var/allowedtocall = 0
|
||||
var/prison_break = 0
|
||||
|
||||
|
||||
attackby(I as obj, user as mob)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
attack_ai(var/mob/user as mob)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
attack_paw(var/mob/user as mob)
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
attackby(I as obj, user as mob)
|
||||
if(istype(I, /obj/item/tool/screwdriver))
|
||||
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
|
||||
if(do_after(user, 20))
|
||||
var/obj/structure/computerframe/A = new /obj/structure/computerframe( src.loc )
|
||||
var/obj/item/part/board/circuit/prison_shuttle/M = new /obj/item/part/board/circuit/prison_shuttle( A )
|
||||
for (var/obj/C in src)
|
||||
C.loc = src.loc
|
||||
A.circuit = M
|
||||
A.anchored = 1
|
||||
|
||||
if (src.stat & BROKEN)
|
||||
user << "\blue The broken glass falls out."
|
||||
new /obj/item/trash/shard( src.loc )
|
||||
A.state = 3
|
||||
A.icon_state = "3"
|
||||
else
|
||||
user << "\blue You disconnect the monitor."
|
||||
A.state = 4
|
||||
A.icon_state = "4"
|
||||
|
||||
del(src)
|
||||
else if(istype(I,/obj/item/card/emag) && (!hacked))
|
||||
hacked = 1
|
||||
user << "\blue You disable the lock."
|
||||
else
|
||||
return src.attack_hand(user)
|
||||
|
||||
|
||||
attack_hand(var/mob/user as mob)
|
||||
if(!src.allowed(user) && (!hacked))
|
||||
user << "\red Access Denied."
|
||||
return
|
||||
if(prison_break)
|
||||
user << "\red Unable to locate shuttle."
|
||||
return
|
||||
if(..())
|
||||
return
|
||||
user.set_machine(src)
|
||||
post_signal("prison")
|
||||
var/dat
|
||||
if (src.temp)
|
||||
dat = src.temp
|
||||
else
|
||||
dat += {"<b>Location:</b> [prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison ? "Moving to station ([prison_shuttle_timeleft] Secs.)":prison_shuttle_at_station ? "Station":"Dock"]<BR>
|
||||
[prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison ? "\n*Shuttle already called*<BR>\n<BR>":prison_shuttle_at_station ? "\n<A href='?src=\ref[src];sendtodock=1'>Send to Dock</A><BR>\n<BR>":"\n<A href='?src=\ref[src];sendtostation=1'>Send to Station</A><BR>\n<BR>"]
|
||||
\n<A href='?src=\ref[user];mach_close=computer'>Close</A>"}
|
||||
|
||||
//user << browse(dat, "window=computer;size=575x450")
|
||||
//onclose(user, "computer")
|
||||
var/datum/browser/popup = new(user, "computer", name, 575, 450)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
return
|
||||
|
||||
|
||||
Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))) || (istype(usr, /mob/living/silicon)))
|
||||
usr.set_machine(src)
|
||||
|
||||
if (href_list["sendtodock"])
|
||||
if (!prison_can_move())
|
||||
usr << "\red The prison shuttle is unable to leave."
|
||||
return
|
||||
if(!prison_shuttle_at_station|| prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return
|
||||
post_signal("prison")
|
||||
usr << "\blue The prison shuttle has been called and will arrive in [(PRISON_MOVETIME/10)] seconds."
|
||||
src.temp += "Shuttle sent.<BR><BR><A href='?src=\ref[src];mainmenu=1'>OK</A>"
|
||||
src.updateUsrDialog()
|
||||
prison_shuttle_moving_to_prison = 1
|
||||
prison_shuttle_time = world.timeofday + PRISON_MOVETIME
|
||||
spawn(0)
|
||||
prison_process()
|
||||
|
||||
else if (href_list["sendtostation"])
|
||||
if (!prison_can_move())
|
||||
usr << "\red The prison shuttle is unable to leave."
|
||||
return
|
||||
if(prison_shuttle_at_station || prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return
|
||||
post_signal("prison")
|
||||
usr << "\blue The prison shuttle has been called and will arrive in [(PRISON_MOVETIME/10)] seconds."
|
||||
src.temp += "Shuttle sent.<BR><BR><A href='?src=\ref[src];mainmenu=1'>OK</A>"
|
||||
src.updateUsrDialog()
|
||||
prison_shuttle_moving_to_station = 1
|
||||
prison_shuttle_time = world.timeofday + PRISON_MOVETIME
|
||||
spawn(0)
|
||||
prison_process()
|
||||
|
||||
else if (href_list["mainmenu"])
|
||||
src.temp = null
|
||||
|
||||
src.add_fingerprint(usr)
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
|
||||
proc/prison_can_move()
|
||||
if(prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return 0
|
||||
else return 1
|
||||
|
||||
/*
|
||||
proc/prison_break()
|
||||
switch(prison_break)
|
||||
if (0)
|
||||
if(!prison_shuttle_at_station || prison_shuttle_moving_to_prison) return
|
||||
|
||||
prison_shuttle_moving_to_prison = 1
|
||||
prison_shuttle_at_station = prison_shuttle_at_station
|
||||
|
||||
if (!prison_shuttle_moving_to_prison || !prison_shuttle_moving_to_station)
|
||||
prison_shuttle_time = world.timeofday + PRISON_MOVETIME
|
||||
spawn(0)
|
||||
prison_process()
|
||||
prison_break = 1
|
||||
if(1)
|
||||
prison_break = 0
|
||||
*/
|
||||
|
||||
proc/post_signal(var/command)
|
||||
var/datum/radio_frequency/frequency = radio_controller.return_frequency(1311)
|
||||
if(!frequency) return
|
||||
var/datum/signal/status_signal = new
|
||||
status_signal.source = src
|
||||
status_signal.transmission_method = 1
|
||||
status_signal.data["command"] = command
|
||||
frequency.post_signal(src, status_signal)
|
||||
return
|
||||
|
||||
|
||||
proc/prison_process()
|
||||
while(prison_shuttle_time - world.timeofday > 0)
|
||||
var/ticksleft = prison_shuttle_time - world.timeofday
|
||||
|
||||
if(ticksleft > 1e5)
|
||||
prison_shuttle_time = world.timeofday + 10 // midnight rollover
|
||||
|
||||
prison_shuttle_timeleft = (ticksleft / 10)
|
||||
sleep(5)
|
||||
prison_shuttle_moving_to_station = 0
|
||||
prison_shuttle_moving_to_prison = 0
|
||||
|
||||
switch(prison_shuttle_at_station)
|
||||
|
||||
if(0)
|
||||
prison_shuttle_at_station = 1
|
||||
if (prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return
|
||||
|
||||
if (!prison_can_move())
|
||||
usr << "\red The prison shuttle is unable to leave."
|
||||
return
|
||||
|
||||
var/area/start_location = locate(/area/shuttle/prison/prison)
|
||||
var/area/end_location = locate(/area/shuttle/prison/station)
|
||||
|
||||
var/list/dstturfs = list()
|
||||
var/throwy = world.maxy
|
||||
|
||||
for(var/turf/T in end_location)
|
||||
dstturfs += T
|
||||
if(T.y < throwy)
|
||||
throwy = T.y
|
||||
// hey you, get out of the way!
|
||||
for(var/turf/T in dstturfs)
|
||||
// find the turf to move things to
|
||||
var/turf/D = locate(T.x, throwy - 1, 1)
|
||||
//var/turf/E = get_step(D, SOUTH)
|
||||
for(var/atom/movable/AM as mob|obj in T)
|
||||
AM.Move(D)
|
||||
if(istype(T, /turf/simulated))
|
||||
del(T)
|
||||
start_location.move_contents_to(end_location)
|
||||
|
||||
if(1)
|
||||
prison_shuttle_at_station = 0
|
||||
if (prison_shuttle_moving_to_station || prison_shuttle_moving_to_prison) return
|
||||
|
||||
if (!prison_can_move())
|
||||
usr << "\red The prison shuttle is unable to leave."
|
||||
return
|
||||
|
||||
var/area/start_location = locate(/area/shuttle/prison/station)
|
||||
var/area/end_location = locate(/area/shuttle/prison/prison)
|
||||
|
||||
var/list/dstturfs = list()
|
||||
var/throwy = world.maxy
|
||||
|
||||
for(var/turf/T in end_location)
|
||||
dstturfs += T
|
||||
if(T.y < throwy)
|
||||
throwy = T.y
|
||||
|
||||
// hey you, get out of the way!
|
||||
for(var/turf/T in dstturfs)
|
||||
// find the turf to move things to
|
||||
var/turf/D = locate(T.x, throwy - 1, 1)
|
||||
//var/turf/E = get_step(D, SOUTH)
|
||||
for(var/atom/movable/AM as mob|obj in T)
|
||||
AM.Move(D)
|
||||
if(istype(T, /turf/simulated))
|
||||
del(T)
|
||||
start_location.move_contents_to(end_location)
|
||||
return
|
||||
@@ -0,0 +1,211 @@
|
||||
/obj/machinery/computer3/robotics
|
||||
default_prog = /datum/file/program/borg_control
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/networking/radio)
|
||||
icon_state = "frame-rnd"
|
||||
|
||||
/datum/file/program/borg_control
|
||||
name = "Cyborg Control"
|
||||
desc = "Used to remotely lockdown or detonate linked Cyborgs."
|
||||
active_state = "robot"
|
||||
var/id = 0.0
|
||||
var/temp = null
|
||||
var/status = 0
|
||||
var/timeleft = 60
|
||||
var/stop = 0.0
|
||||
var/screen = 0 // 0 - Main Menu, 1 - Cyborg Status, 2 - Kill 'em All! -- In text
|
||||
req_access = list(access_robotics)
|
||||
|
||||
proc/start_sequence()
|
||||
do
|
||||
if(src.stop)
|
||||
src.stop = 0
|
||||
return
|
||||
src.timeleft--
|
||||
sleep(10)
|
||||
while(src.timeleft)
|
||||
|
||||
for(var/mob/living/silicon/robot/R in mob_list)
|
||||
if(!R.scrambledcodes)
|
||||
R.self_destruct()
|
||||
return
|
||||
|
||||
|
||||
interact()
|
||||
if(!interactable() || computer.z > 6)
|
||||
return
|
||||
var/dat
|
||||
if (src.temp)
|
||||
dat = "<TT>[src.temp]</TT><BR><BR><A href='?src=\ref[src];temp=1'>Clear Screen</A>"
|
||||
else
|
||||
if(screen == 0)
|
||||
//dat += "<h3>Cyborg Control Console</h3><BR>"
|
||||
dat += "<A href='?src=\ref[src];screen=1'>1. Cyborg Status</A><BR>"
|
||||
dat += "<A href='?src=\ref[src];screen=2'>2. Emergency Full Destruct</A><BR>"
|
||||
if(screen == 1)
|
||||
for(var/mob/living/silicon/robot/R in mob_list)
|
||||
if(istype(usr, /mob/living/silicon/ai))
|
||||
if (R.connected_ai != usr)
|
||||
continue
|
||||
if(istype(usr, /mob/living/silicon/robot))
|
||||
if (R != usr)
|
||||
continue
|
||||
if(R.scrambledcodes)
|
||||
continue
|
||||
|
||||
dat += "[R.name] |"
|
||||
if(R.stat)
|
||||
dat += " Not Responding |"
|
||||
else if (!R.canmove)
|
||||
dat += " Locked Down |"
|
||||
else
|
||||
dat += " Operating Normally |"
|
||||
if (!R.canmove)
|
||||
else if(R.cell)
|
||||
dat += " Battery Installed ([R.cell.charge]/[R.cell.maxcharge]) |"
|
||||
else
|
||||
dat += " No Cell Installed |"
|
||||
if(R.module)
|
||||
dat += " Module Installed ([R.module.name]) |"
|
||||
else
|
||||
dat += " No Module Installed |"
|
||||
if(R.connected_ai)
|
||||
dat += " Slaved to [R.connected_ai.name] |"
|
||||
else
|
||||
dat += " Independent from AI |"
|
||||
if (istype(usr, /mob/living/silicon))
|
||||
if(issilicon(usr) && is_special_character(usr) && !R.emagged)
|
||||
dat += "<A href='?src=\ref[src];magbot=\ref[R]'>(<i>Hack</i>)</A> "
|
||||
dat += "<A href='?src=\ref[src];stopbot=\ref[R]'>(<i>[R.canmove ? "Lockdown" : "Release"]</i>)</A> "
|
||||
dat += "<A href='?src=\ref[src];killbot=\ref[R]'>(<i>Destroy</i>)</A>"
|
||||
dat += "<BR>"
|
||||
dat += "<A href='?src=\ref[src];screen=0'>(Return to Main Menu)</A><BR>"
|
||||
if(screen == 2)
|
||||
if(!src.status)
|
||||
dat += {"<BR><B>Emergency Robot Self-Destruct</B><HR>\nStatus: Off<BR>
|
||||
\n<BR>
|
||||
\nCountdown: [src.timeleft]/60 <A href='?src=\ref[src];reset=1'>\[Reset\]</A><BR>
|
||||
\n<BR>
|
||||
\n<A href='?src=\ref[src];killall'>Start Sequence</A><BR>
|
||||
\n<BR>
|
||||
\n<A href='?src=\ref[usr];close'>Close</A>"}
|
||||
else
|
||||
dat = {"<B>Emergency Robot Self-Destruct</B><HR>\nStatus: Activated<BR>
|
||||
\n<BR>
|
||||
\nCountdown: [src.timeleft]/60 \[Reset\]<BR>
|
||||
\n<BR>\n<A href='?src=\ref[src];stop=1'>Stop Sequence</A><BR>
|
||||
\n<BR>
|
||||
\n<A href='?src=\ref[usr];mach_close=computer'>Close</A>"}
|
||||
dat += "<A href='?src=\ref[src];screen=0'>(Return to Main Menu)</A><BR>"
|
||||
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
return
|
||||
|
||||
Topic(var/href, var/list/href_list)
|
||||
if(!interactable() || ..(href,href_list))
|
||||
return
|
||||
|
||||
if ("killall" in href_list)
|
||||
src.temp = {"Destroy Robots?<BR>
|
||||
<BR><B><A href='?src=\ref[src];do_killall'>\[Swipe ID to initiate destruction sequence\]</A></B><BR>
|
||||
<A href='?src=\ref[src];temp=1'>Cancel</A>"}
|
||||
|
||||
if ("do_killall" in href_list)
|
||||
var/obj/item/weapon/card/id/I = usr.get_active_hand()
|
||||
if (istype(I, /obj/item/device/pda))
|
||||
var/obj/item/device/pda/pda = I
|
||||
I = pda.id
|
||||
if (istype(I))
|
||||
if(src.check_access(I))
|
||||
if (!status)
|
||||
message_admins("\blue [key_name_admin(usr)] has initiated the global cyborg killswitch!")
|
||||
log_game("\blue [key_name(usr)] has initiated the global cyborg killswitch!")
|
||||
src.status = 1
|
||||
src.start_sequence()
|
||||
src.temp = null
|
||||
|
||||
else
|
||||
usr << "\red Access Denied."
|
||||
|
||||
if ("stop" in href_list)
|
||||
src.temp = {"
|
||||
Stop Robot Destruction Sequence?<BR>
|
||||
<BR><A href='?src=\ref[src];stop2=1'>Yes</A><BR>
|
||||
<A href='?src=\ref[src];temp=1'>No</A>"}
|
||||
|
||||
if ("stop2" in href_list)
|
||||
src.stop = 1
|
||||
src.temp = null
|
||||
src.status = 0
|
||||
|
||||
if ("reset" in href_list)
|
||||
src.timeleft = 60
|
||||
|
||||
if ("temp" in href_list)
|
||||
src.temp = null
|
||||
if ("screen" in href_list)
|
||||
switch(href_list["screen"])
|
||||
if("0")
|
||||
screen = 0
|
||||
if("1")
|
||||
screen = 1
|
||||
if("2")
|
||||
screen = 2
|
||||
if ("killbot" in href_list)
|
||||
if(computer.allowed(usr))
|
||||
var/mob/living/silicon/robot/R = locate(href_list["killbot"])
|
||||
if(R)
|
||||
var/choice = input("Are you certain you wish to detonate [R.name]?") in list("Confirm", "Abort")
|
||||
if(choice == "Confirm")
|
||||
if(R && istype(R))
|
||||
if(R.mind && R.mind.special_role && R.emagged)
|
||||
R << "Extreme danger. Termination codes detected. Scrambling security codes and automatic AI unlink triggered."
|
||||
R.ResetSecurityCodes()
|
||||
|
||||
else
|
||||
message_admins("\blue [key_name_admin(usr)] detonated [R.name]!")
|
||||
log_game("\blue [key_name_admin(usr)] detonated [R.name]!")
|
||||
R.self_destruct()
|
||||
else
|
||||
usr << "\red Access Denied."
|
||||
|
||||
if ("stopbot" in href_list)
|
||||
if(computer.allowed(usr))
|
||||
var/mob/living/silicon/robot/R = locate(href_list["stopbot"])
|
||||
if(R && istype(R)) // Extra sancheck because of input var references
|
||||
var/choice = input("Are you certain you wish to [R.canmove ? "lock down" : "release"] [R.name]?") in list("Confirm", "Abort")
|
||||
if(choice == "Confirm")
|
||||
if(R && istype(R))
|
||||
message_admins("\blue [key_name_admin(usr)] [R.canmove ? "locked down" : "released"] [R.name]!")
|
||||
log_game("[key_name(usr)] [R.canmove ? "locked down" : "released"] [R.name]!")
|
||||
R.canmove = !R.canmove
|
||||
if (R.lockcharge)
|
||||
// R.cell.charge = R.lockcharge
|
||||
R.lockcharge = !R.lockcharge
|
||||
R << "Your lockdown has been lifted!"
|
||||
else
|
||||
R.lockcharge = !R.lockcharge
|
||||
// R.cell.charge = 0
|
||||
R << "You have been locked down!"
|
||||
|
||||
else
|
||||
usr << "\red Access Denied."
|
||||
|
||||
if ("magbot" in href_list)
|
||||
if(computer.allowed(usr))
|
||||
var/mob/living/silicon/robot/R = locate(href_list["magbot"])
|
||||
if(R)
|
||||
var/choice = input("Are you certain you wish to hack [R.name]?") in list("Confirm", "Abort")
|
||||
if(choice == "Confirm")
|
||||
if(R && istype(R))
|
||||
// message_admins("\blue [key_name_admin(usr)] emagged [R.name] using robotic console!")
|
||||
log_game("[key_name(usr)] emagged [R.name] using robotic console!")
|
||||
R.emagged = 1
|
||||
if(R.mind.special_role)
|
||||
R.verbs += /mob/living/silicon/robot/proc/ResetSecurityCodes
|
||||
|
||||
interact()
|
||||
return
|
||||
|
||||
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,610 @@
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
|
||||
/obj/machinery/computer3/secure_data
|
||||
default_prog = /datum/file/program/secure_data
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/cardslot,/obj/item/part/computer/networking/radio)
|
||||
icon_state = "frame-sec"
|
||||
|
||||
/obj/machinery/computer3/laptop/secure_data
|
||||
default_prog = /datum/file/program/secure_data
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd/big,/obj/item/part/computer/cardslot,/obj/item/part/computer/networking/radio)
|
||||
icon_state = "laptop"
|
||||
|
||||
|
||||
/datum/file/program/secure_data
|
||||
name = "Security Records"
|
||||
desc = "Used to view and edit personnel's security records"
|
||||
active_state = "security"
|
||||
image = 'icons/ntos/records.png'
|
||||
|
||||
req_one_access = list(access_security, access_forensics_lockers)
|
||||
|
||||
var/obj/item/weapon/card/id/scan = null
|
||||
var/authenticated = null
|
||||
var/rank = null
|
||||
var/screen = null
|
||||
var/datum/data/record/active1 = null
|
||||
var/datum/data/record/active2 = null
|
||||
var/a_id = null
|
||||
var/temp = null
|
||||
var/printing = null
|
||||
var/can_change_id = 0
|
||||
var/list/Perp
|
||||
var/tempname = null
|
||||
//Sorting Variables
|
||||
var/sortBy = "name"
|
||||
var/order = 1 // -1 = Descending - 1 = Ascending
|
||||
|
||||
|
||||
|
||||
proc/authenticate()
|
||||
if(access_security in scan.access || access_forensics_lockers in scan.access )
|
||||
return 1
|
||||
if(istype(usr,/mob/living/silicon/ai))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
interact()
|
||||
if(!computer.cardslot)
|
||||
computer.Crash(MISSING_PERIPHERAL)
|
||||
return
|
||||
usr.set_machine(src)
|
||||
scan = computer.cardslot.reader
|
||||
if(!interactable())
|
||||
return
|
||||
return
|
||||
if (computer.z > 6)
|
||||
usr << "\red <b>Unable to establish a connection</b>: \black You're too far away from the station!"
|
||||
return
|
||||
var/dat
|
||||
|
||||
if (temp)
|
||||
dat = text("<TT>[]</TT><BR><BR><A href='?src=\ref[];choice=Clear Screen'>Clear Screen</A>", temp, src)
|
||||
else
|
||||
dat = text("Confirm Identity: <A href='?src=\ref[];choice=Confirm Identity'>[]</A><HR>", src, (scan ? text("[]", scan.name) : "----------"))
|
||||
if (authenticated)
|
||||
switch(screen)
|
||||
if(1.0)
|
||||
dat += {"
|
||||
<p style='text-align:center;'>"}
|
||||
dat += text("<A href='?src=\ref[];choice=Search Records'>Search Records</A><BR>", src)
|
||||
dat += text("<A href='?src=\ref[];choice=New Record (General)'>New Record</A><BR>", src)
|
||||
dat += {"
|
||||
</p>
|
||||
<table style="text-align:center;" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<th>Records:</th>
|
||||
</tr>
|
||||
</table>
|
||||
<table style="text-align:center;" border="1" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<th><A href='?src=\ref[src];choice=Sorting;sort=name'>Name</A></th>
|
||||
<th><A href='?src=\ref[src];choice=Sorting;sort=id'>ID</A></th>
|
||||
<th><A href='?src=\ref[src];choice=Sorting;sort=rank'>Rank</A></th>
|
||||
<th><A href='?src=\ref[src];choice=Sorting;sort=fingerprint'>Fingerprints</A></th>
|
||||
<th>Criminal Status</th>
|
||||
</tr>"}
|
||||
if(!isnull(data_core.general))
|
||||
for(var/datum/data/record/R in sortRecord(data_core.general, sortBy, order))
|
||||
var/crimstat = ""
|
||||
for(var/datum/data/record/E in data_core.security)
|
||||
if ((E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"]))
|
||||
crimstat = E.fields["criminal"]
|
||||
var/background
|
||||
switch(crimstat)
|
||||
if("*Arrest*")
|
||||
background = "'background-color:#DC143C;'"
|
||||
if("Incarcerated")
|
||||
background = "'background-color:#CD853F;'"
|
||||
if("Parolled")
|
||||
background = "'background-color:#CD853F;'"
|
||||
if("Released")
|
||||
background = "'background-color:#3BB9FF;'"
|
||||
if("None")
|
||||
background = "'background-color:#00FF7F;'"
|
||||
if("")
|
||||
background = "'background-color:#00FF00;'"
|
||||
crimstat = "No Record."
|
||||
dat += text("<tr style=[]><td><A href='?src=\ref[];choice=Browse Record;d_rec=\ref[]'>[]</a></td>", background, src, R, R.fields["name"])
|
||||
dat += text("<td>[]</td>", R.fields["id"])
|
||||
dat += text("<td>[]</td>", R.fields["rank"])
|
||||
dat += text("<td>[]</td>", R.fields["fingerprint"])
|
||||
dat += text("<td>[]</td></tr>", crimstat)
|
||||
dat += "</table><hr width='75%' />"
|
||||
dat += text("<A href='?src=\ref[];choice=Record Maintenance'>Record Maintenance</A><br><br>", src)
|
||||
dat += text("<A href='?src=\ref[];choice=Log Out'>{Log Out}</A>",src)
|
||||
if(2.0)
|
||||
dat += "<B>Records Maintenance</B><HR>"
|
||||
dat += "<BR><A href='?src=\ref[src];choice=Delete All Records'>Delete All Records</A><BR><BR><A href='?src=\ref[src];choice=Return'>Back</A>"
|
||||
if(3.0)
|
||||
dat += "<CENTER><B>Security Record</B></CENTER><BR>"
|
||||
if ((istype(active1, /datum/data/record) && data_core.general.Find(active1)))
|
||||
var/icon/front = new(active1.fields["photo"], dir = SOUTH)
|
||||
var/icon/side = new(active1.fields["photo"], dir = WEST)
|
||||
usr << browse_rsc(front, "front.png")
|
||||
usr << browse_rsc(side, "side.png")
|
||||
dat += text("<table><tr><td> \
|
||||
Name: <A href='?src=\ref[src];choice=Edit Field;field=name'>[active1.fields["name"]]</A><BR> \
|
||||
ID: <A href='?src=\ref[src];choice=Edit Field;field=id'>[active1.fields["id"]]</A><BR>\n \
|
||||
Sex: <A href='?src=\ref[src];choice=Edit Field;field=sex'>[active1.fields["sex"]]</A><BR>\n \
|
||||
Age: <A href='?src=\ref[src];choice=Edit Field;field=age'>[active1.fields["age"]]</A><BR>\n \
|
||||
Rank: <A href='?src=\ref[src];choice=Edit Field;field=rank'>[active1.fields["rank"]]</A><BR>\n \
|
||||
Fingerprint: <A href='?src=\ref[src];choice=Edit Field;field=fingerprint'>[active1.fields["fingerprint"]]</A><BR>\n \
|
||||
Physical Status: [active1.fields["p_stat"]]<BR>\n \
|
||||
Mental Status: [active1.fields["m_stat"]]<BR></td> \
|
||||
<td align = center valign = top>Photo:<br><img src=front.png height=80 width=80 border=4> \
|
||||
<img src=side.png height=80 width=80 border=4></td></tr></table>")
|
||||
else
|
||||
dat += "<B>General Record Lost!</B><BR>"
|
||||
if ((istype(active2, /datum/data/record) && data_core.security.Find(active2)))
|
||||
dat += text("<BR>\n<CENTER><B>Security Data</B></CENTER><BR>\nCriminal Status: <A href='?src=\ref[];choice=Edit Field;field=criminal'>[]</A><BR>\n<BR>\nMinor Crimes: <A href='?src=\ref[];choice=Edit Field;field=mi_crim'>[]</A><BR>\nDetails: <A href='?src=\ref[];choice=Edit Field;field=mi_crim_d'>[]</A><BR>\n<BR>\nMajor Crimes: <A href='?src=\ref[];choice=Edit Field;field=ma_crim'>[]</A><BR>\nDetails: <A href='?src=\ref[];choice=Edit Field;field=ma_crim_d'>[]</A><BR>\n<BR>\nImportant Notes:<BR>\n\t<A href='?src=\ref[];choice=Edit Field;field=notes'>[]</A><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, decode(active2.fields["notes"]))
|
||||
var/counter = 1
|
||||
while(active2.fields[text("com_[]", counter)])
|
||||
dat += text("[]<BR><A href='?src=\ref[];choice=Delete Entry;del_c=[]'>Delete Entry</A><BR><BR>", active2.fields[text("com_[]", counter)], src, counter)
|
||||
counter++
|
||||
dat += text("<A href='?src=\ref[];choice=Add Entry'>Add Entry</A><BR><BR>", src)
|
||||
dat += text("<A href='?src=\ref[];choice=Delete Record (Security)'>Delete Record (Security Only)</A><BR><BR>", src)
|
||||
else
|
||||
dat += "<B>Security Record Lost!</B><BR>"
|
||||
dat += text("<A href='?src=\ref[];choice=New Record (Security)'>New Security Record</A><BR><BR>", src)
|
||||
dat += text("\n<A href='?src=\ref[];choice=Delete Record (ALL)'>Delete Record (ALL)</A><BR><BR>\n<A href='?src=\ref[];choice=Print Record'>Print Record</A><BR>\n<A href='?src=\ref[];choice=Return'>Back</A><BR>", src, src, src)
|
||||
if(4.0)
|
||||
if(!Perp.len)
|
||||
dat += text("ERROR. String could not be located.<br><br><A href='?src=\ref[];choice=Return'>Back</A>", src)
|
||||
else
|
||||
dat += {"
|
||||
<table style="text-align:center;" cellspacing="0" width="100%">
|
||||
<tr> "}
|
||||
dat += text("<th>Search Results for '[]':</th>", tempname)
|
||||
dat += {"
|
||||
</tr>
|
||||
</table>
|
||||
<table style="text-align:center;" border="1" cellspacing="0" width="100%">
|
||||
<tr>
|
||||
<th>Name</th>
|
||||
<th>ID</th>
|
||||
<th>Rank</th>
|
||||
<th>Fingerprints</th>
|
||||
<th>Criminal Status</th>
|
||||
</tr> "}
|
||||
for(var/i=1, i<=Perp.len, i += 2)
|
||||
var/crimstat = ""
|
||||
var/datum/data/record/R = Perp[i]
|
||||
if(istype(Perp[i+1],/datum/data/record/))
|
||||
var/datum/data/record/E = Perp[i+1]
|
||||
crimstat = E.fields["criminal"]
|
||||
var/background
|
||||
switch(crimstat)
|
||||
if("*Arrest*")
|
||||
background = "'background-color:#DC143C;'"
|
||||
if("Incarcerated")
|
||||
background = "'background-color:#CD853F;'"
|
||||
if("Parolled")
|
||||
background = "'background-color:#CD853F;'"
|
||||
if("Released")
|
||||
background = "'background-color:#3BB9FF;'"
|
||||
if("None")
|
||||
background = "'background-color:#00FF7F;'"
|
||||
if("")
|
||||
background = "'background-color:#FFFFFF;'"
|
||||
crimstat = "No Record."
|
||||
dat += text("<tr style=[]><td><A href='?src=\ref[];choice=Browse Record;d_rec=\ref[]'>[]</a></td>", background, src, R, R.fields["name"])
|
||||
dat += text("<td>[]</td>", R.fields["id"])
|
||||
dat += text("<td>[]</td>", R.fields["rank"])
|
||||
dat += text("<td>[]</td>", R.fields["fingerprint"])
|
||||
dat += text("<td>[]</td></tr>", crimstat)
|
||||
dat += "</table><hr width='75%' />"
|
||||
dat += text("<br><A href='?src=\ref[];choice=Return'>Return to index.</A>", src)
|
||||
else
|
||||
else
|
||||
dat += text("<A href='?src=\ref[];choice=Log In'>{Log In}</A>", src)
|
||||
popup.width = 600
|
||||
popup.height = 400
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(usr.browse_rsc_icon(computer.icon, computer.icon_state))
|
||||
popup.open()
|
||||
return
|
||||
|
||||
/*Revised /N
|
||||
I can't be bothered to look more of the actual code outside of switch but that probably needs revising too.
|
||||
What a mess.*/
|
||||
Topic(href, href_list)
|
||||
if(!interactable() || !computer.cardslot || ..(href,href_list))
|
||||
return
|
||||
if (!( data_core.general.Find(active1) ))
|
||||
active1 = null
|
||||
if (!( data_core.security.Find(active2) ))
|
||||
active2 = null
|
||||
switch(href_list["choice"])
|
||||
// SORTING!
|
||||
if("Sorting")
|
||||
// Reverse the order if clicked twice
|
||||
if(sortBy == href_list["sort"])
|
||||
if(order == 1)
|
||||
order = -1
|
||||
else
|
||||
order = 1
|
||||
else
|
||||
// New sorting order!
|
||||
sortBy = href_list["sort"]
|
||||
order = initial(order)
|
||||
//BASIC FUNCTIONS
|
||||
if("Clear Screen")
|
||||
temp = null
|
||||
|
||||
if ("Return")
|
||||
screen = 1
|
||||
active1 = null
|
||||
active2 = null
|
||||
|
||||
if("Confirm Identity")
|
||||
if (scan)
|
||||
if(istype(usr,/mob/living/carbon/human) && !usr.get_active_hand())
|
||||
computer.cardslot.remove(scan)
|
||||
else
|
||||
scan.loc = get_turf(src)
|
||||
scan = null
|
||||
else
|
||||
var/obj/item/I = usr.get_active_hand()
|
||||
if (istype(I, /obj/item/weapon/card/id))
|
||||
computer.cardslot.insert(I)
|
||||
scan = I
|
||||
|
||||
if("Log Out")
|
||||
authenticated = null
|
||||
screen = null
|
||||
active1 = null
|
||||
active2 = null
|
||||
|
||||
if("Log In")
|
||||
if (istype(usr, /mob/living/silicon/ai))
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
src.authenticated = usr.name
|
||||
src.rank = "AI"
|
||||
src.screen = 1
|
||||
else if (istype(usr, /mob/living/silicon/robot))
|
||||
src.active1 = null
|
||||
src.active2 = null
|
||||
src.authenticated = usr.name
|
||||
var/mob/living/silicon/robot/R = usr
|
||||
src.rank = "[R.modtype] [R.braintype]"
|
||||
src.screen = 1
|
||||
else if (istype(scan, /obj/item/weapon/card/id))
|
||||
active1 = null
|
||||
active2 = null
|
||||
if(authenticate())
|
||||
authenticated = scan.registered_name
|
||||
rank = scan.assignment
|
||||
screen = 1
|
||||
//RECORD FUNCTIONS
|
||||
if("Search Records")
|
||||
var/t1 = input("Search String: (Partial Name or ID or Fingerprints or Rank)", "Secure. records", null, null) as text
|
||||
if ((!( t1 ) || usr.stat || !( authenticated ) || usr.restrained() || !interactable()))
|
||||
return
|
||||
Perp = new/list()
|
||||
t1 = lowertext(t1)
|
||||
var/list/components = text2list(t1, " ")
|
||||
if(components.len > 5)
|
||||
return //Lets not let them search too greedily.
|
||||
for(var/datum/data/record/R in data_core.general)
|
||||
var/temptext = R.fields["name"] + " " + R.fields["id"] + " " + R.fields["fingerprint"] + " " + R.fields["rank"]
|
||||
for(var/i = 1, i<=components.len, i++)
|
||||
if(findtext(temptext,components[i]))
|
||||
var/prelist = new/list(2)
|
||||
prelist[1] = R
|
||||
Perp += prelist
|
||||
for(var/i = 1, i<=Perp.len, i+=2)
|
||||
for(var/datum/data/record/E in data_core.security)
|
||||
var/datum/data/record/R = Perp[i]
|
||||
if ((E.fields["name"] == R.fields["name"] && E.fields["id"] == R.fields["id"]))
|
||||
Perp[i+1] = E
|
||||
tempname = t1
|
||||
screen = 4
|
||||
|
||||
if("Record Maintenance")
|
||||
screen = 2
|
||||
active1 = null
|
||||
active2 = null
|
||||
|
||||
if ("Browse Record")
|
||||
var/datum/data/record/R = locate(href_list["d_rec"])
|
||||
var/S = locate(href_list["d_rec"])
|
||||
if (!( data_core.general.Find(R) ))
|
||||
temp = "Record Not Found!"
|
||||
else
|
||||
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
|
||||
active1 = R
|
||||
active2 = S
|
||||
screen = 3
|
||||
|
||||
/* if ("Search Fingerprints")
|
||||
var/t1 = input("Search String: (Fingerprint)", "Secure. records", null, null) as text
|
||||
if ((!( t1 ) || usr.stat || !( authenticated ) || usr.restrained() || (!interactable()) && (!istype(usr, /mob/living/silicon))))
|
||||
return
|
||||
active1 = null
|
||||
active2 = null
|
||||
t1 = lowertext(t1)
|
||||
for(var/datum/data/record/R in data_core.general)
|
||||
if (lowertext(R.fields["fingerprint"]) == t1)
|
||||
active1 = R
|
||||
if (!( active1 ))
|
||||
temp = text("Could not locate record [].", t1)
|
||||
else
|
||||
for(var/datum/data/record/E in data_core.security)
|
||||
if ((E.fields["name"] == active1.fields["name"] || E.fields["id"] == active1.fields["id"]))
|
||||
active2 = E
|
||||
screen = 3 */
|
||||
|
||||
if ("Print Record")
|
||||
if (!( printing ))
|
||||
printing = 1
|
||||
var/datum/data/record/record1 = null
|
||||
var/datum/data/record/record2 = null
|
||||
if ((istype(active1, /datum/data/record) && data_core.general.Find(active1)))
|
||||
record1 = active1
|
||||
if ((istype(active2, /datum/data/record) && data_core.security.Find(active2)))
|
||||
record2 = active2
|
||||
sleep(50)
|
||||
var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( computer.loc )
|
||||
P.info = "<CENTER><B>Security Record</B></CENTER><BR>"
|
||||
if (record1)
|
||||
P.info += text("Name: [] ID: []<BR>\nSex: []<BR>\nAge: []<BR>\nFingerprint: []<BR>\nPhysical Status: []<BR>\nMental Status: []<BR>", record1.fields["name"], record1.fields["id"], record1.fields["sex"], record1.fields["age"], record1.fields["fingerprint"], record1.fields["p_stat"], record1.fields["m_stat"])
|
||||
P.name = text("Security Record ([])", record1.fields["name"])
|
||||
else
|
||||
P.info += "<B>General Record Lost!</B><BR>"
|
||||
P.name = "Security Record"
|
||||
if (record2)
|
||||
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>", record2.fields["criminal"], record2.fields["mi_crim"], record2.fields["mi_crim_d"], record2.fields["ma_crim"], record2.fields["ma_crim_d"], decode(record2.fields["notes"]))
|
||||
var/counter = 1
|
||||
while(record2.fields[text("com_[]", counter)])
|
||||
P.info += text("[]<BR>", record2.fields[text("com_[]", counter)])
|
||||
counter++
|
||||
else
|
||||
P.info += "<B>Security Record Lost!</B><BR>"
|
||||
P.info += "</TT>"
|
||||
printing = null
|
||||
computer.updateUsrDialog()
|
||||
//RECORD DELETE
|
||||
if ("Delete All Records")
|
||||
temp = ""
|
||||
temp += "Are you sure you wish to delete all Security records?<br>"
|
||||
temp += "<a href='?src=\ref[src];choice=Purge All Records'>Yes</a><br>"
|
||||
temp += "<a href='?src=\ref[src];choice=Clear Screen'>No</a>"
|
||||
|
||||
if ("Purge All Records")
|
||||
for(var/datum/data/record/R in data_core.security)
|
||||
del(R)
|
||||
temp = "All Security records deleted."
|
||||
|
||||
if ("Add Entry")
|
||||
if (!( istype(active2, /datum/data/record) ))
|
||||
return
|
||||
var/a2 = active2
|
||||
var/t1 = copytext(sanitize(input("Add Comment:", "Secure. records", null, null) as message),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active2 != a2))
|
||||
return
|
||||
var/counter = 1
|
||||
while(active2.fields[text("com_[]", counter)])
|
||||
counter++
|
||||
active2.fields[text("com_[counter]")] = text("Made by [authenticated] ([rank]) on [time2text(world.realtime, "DDD MMM DD hh:mm:ss")], [game_year]<BR>[t1]")
|
||||
|
||||
if ("Delete Record (ALL)")
|
||||
if (active1)
|
||||
temp = "<h5>Are you sure you wish to delete the record (ALL)?</h5>"
|
||||
temp += "<a href='?src=\ref[src];choice=Delete Record (ALL) Execute'>Yes</a><br>"
|
||||
temp += "<a href='?src=\ref[src];choice=Clear Screen'>No</a>"
|
||||
|
||||
if ("Delete Record (Security)")
|
||||
if (active2)
|
||||
temp = "<h5>Are you sure you wish to delete the record (Security Portion Only)?</h5>"
|
||||
temp += "<a href='?src=\ref[src];choice=Delete Record (Security) Execute'>Yes</a><br>"
|
||||
temp += "<a href='?src=\ref[src];choice=Clear Screen'>No</a>"
|
||||
|
||||
if ("Delete Entry")
|
||||
if ((istype(active2, /datum/data/record) && active2.fields[text("com_[]", href_list["del_c"])]))
|
||||
active2.fields[text("com_[]", href_list["del_c"])] = "<B>Deleted</B>"
|
||||
//RECORD CREATE
|
||||
if ("New Record (Security)")
|
||||
if ((istype(active1, /datum/data/record) && !( istype(active2, /datum/data/record) )))
|
||||
var/datum/data/record/R = new /datum/data/record()
|
||||
R.fields["name"] = active1.fields["name"]
|
||||
R.fields["id"] = 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 major crime convictions."
|
||||
R.fields["notes"] = "No notes."
|
||||
data_core.security += R
|
||||
active2 = R
|
||||
screen = 3
|
||||
|
||||
if ("New Record (General)")
|
||||
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["real_rank"] = "Unassigned"
|
||||
G.fields["sex"] = "Male"
|
||||
G.fields["age"] = "Unknown"
|
||||
G.fields["fingerprint"] = "Unknown"
|
||||
G.fields["p_stat"] = "Active"
|
||||
G.fields["m_stat"] = "Stable"
|
||||
G.fields["species"] = "Human"
|
||||
data_core.general += G
|
||||
active1 = G
|
||||
active2 = null
|
||||
|
||||
//FIELD FUNCTIONS
|
||||
if ("Edit Field")
|
||||
var/a1 = active1
|
||||
var/a2 = active2
|
||||
switch(href_list["field"])
|
||||
if("name")
|
||||
if (istype(active1, /datum/data/record))
|
||||
var/t1 = input("Please input name:", "Secure. records", active1.fields["name"], null) as text
|
||||
if ((!( t1 ) || !length(trim(t1)) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon)))) || active1 != a1)
|
||||
return
|
||||
active1.fields["name"] = t1
|
||||
if("id")
|
||||
if (istype(active2, /datum/data/record))
|
||||
var/t1 = copytext(sanitize(input("Please input id:", "Secure. records", active1.fields["id"], null) as text),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active1 != a1))
|
||||
return
|
||||
active1.fields["id"] = t1
|
||||
if("fingerprint")
|
||||
if (istype(active1, /datum/data/record))
|
||||
var/t1 = copytext(sanitize(input("Please input fingerprint hash:", "Secure. records", active1.fields["fingerprint"], null) as text),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active1 != a1))
|
||||
return
|
||||
active1.fields["fingerprint"] = t1
|
||||
if("sex")
|
||||
if (istype(active1, /datum/data/record))
|
||||
if (active1.fields["sex"] == "Male")
|
||||
active1.fields["sex"] = "Female"
|
||||
else
|
||||
active1.fields["sex"] = "Male"
|
||||
if("age")
|
||||
if (istype(active1, /datum/data/record))
|
||||
var/t1 = input("Please input age:", "Secure. records", active1.fields["age"], null) as num
|
||||
if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active1 != a1))
|
||||
return
|
||||
active1.fields["age"] = t1
|
||||
if("mi_crim")
|
||||
if (istype(active2, /datum/data/record))
|
||||
var/t1 = copytext(sanitize(input("Please input minor disabilities list:", "Secure. records", active2.fields["mi_crim"], null) as text),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active2 != a2))
|
||||
return
|
||||
active2.fields["mi_crim"] = t1
|
||||
if("mi_crim_d")
|
||||
if (istype(active2, /datum/data/record))
|
||||
var/t1 = copytext(sanitize(input("Please summarize minor dis.:", "Secure. records", active2.fields["mi_crim_d"], null) as message),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active2 != a2))
|
||||
return
|
||||
active2.fields["mi_crim_d"] = t1
|
||||
if("ma_crim")
|
||||
if (istype(active2, /datum/data/record))
|
||||
var/t1 = copytext(sanitize(input("Please input major diabilities list:", "Secure. records", active2.fields["ma_crim"], null) as text),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active2 != a2))
|
||||
return
|
||||
active2.fields["ma_crim"] = t1
|
||||
if("ma_crim_d")
|
||||
if (istype(active2, /datum/data/record))
|
||||
var/t1 = copytext(sanitize(input("Please summarize major dis.:", "Secure. records", active2.fields["ma_crim_d"], null) as message),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active2 != a2))
|
||||
return
|
||||
active2.fields["ma_crim_d"] = t1
|
||||
if("notes")
|
||||
if (istype(active2, /datum/data/record))
|
||||
var/t1 = copytext(html_encode(input("Please summarize notes:", "Secure. records", html_decode(active2.fields["notes"]), null) as message),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active2 != a2))
|
||||
return
|
||||
active2.fields["notes"] = t1
|
||||
if("criminal")
|
||||
if (istype(active2, /datum/data/record))
|
||||
temp = "<h5>Criminal Status:</h5>"
|
||||
temp += "<ul>"
|
||||
temp += "<li><a href='?src=\ref[src];choice=Change Criminal Status;criminal2=none'>None</a></li>"
|
||||
temp += "<li><a href='?src=\ref[src];choice=Change Criminal Status;criminal2=arrest'>*Arrest*</a></li>"
|
||||
temp += "<li><a href='?src=\ref[src];choice=Change Criminal Status;criminal2=incarcerated'>Incarcerated</a></li>"
|
||||
temp += "<li><a href='?src=\ref[src];choice=Change Criminal Status;criminal2=parolled'>Parolled</a></li>"
|
||||
temp += "<li><a href='?src=\ref[src];choice=Change Criminal Status;criminal2=released'>Released</a></li>"
|
||||
temp += "</ul>"
|
||||
if("rank")
|
||||
var/list/L = list( "Head of Personnel", "Captain", "AI" )
|
||||
//This was so silly before the change. Now it actually works without beating your head against the keyboard. /N
|
||||
if ((istype(active1, /datum/data/record) && L.Find(rank)))
|
||||
temp = "<h5>Rank:</h5>"
|
||||
temp += "<ul>"
|
||||
for(var/rank in joblist)
|
||||
temp += "<li><a href='?src=\ref[src];choice=Change Rank;rank=[rank]'>[rank]</a></li>"
|
||||
temp += "</ul>"
|
||||
else
|
||||
alert(usr, "You do not have the required rank to do this!")
|
||||
if("species")
|
||||
if (istype(active1, /datum/data/record))
|
||||
var/t1 = copytext(sanitize(input("Please enter race:", "General records", active1.fields["species"], null) as message),1,MAX_MESSAGE_LEN)
|
||||
if ((!( t1 ) || !( authenticated ) || usr.stat || usr.restrained() || (!interactable() && (!istype(usr, /mob/living/silicon))) || active1 != a1))
|
||||
return
|
||||
active1.fields["species"] = t1
|
||||
|
||||
//TEMPORARY MENU FUNCTIONS
|
||||
else//To properly clear as per clear screen.
|
||||
temp=null
|
||||
switch(href_list["choice"])
|
||||
if ("Change Rank")
|
||||
if (active1)
|
||||
active1.fields["rank"] = href_list["rank"]
|
||||
if(href_list["rank"] in joblist)
|
||||
active1.fields["real_rank"] = href_list["real_rank"]
|
||||
|
||||
if ("Change Criminal Status")
|
||||
if (active2)
|
||||
for(var/mob/living/carbon/human/H in player_list)
|
||||
H.hud_updateflag |= 1 << WANTED_HUD
|
||||
switch(href_list["criminal2"])
|
||||
if("none")
|
||||
active2.fields["criminal"] = "None"
|
||||
if("arrest")
|
||||
active2.fields["criminal"] = "*Arrest*"
|
||||
if("incarcerated")
|
||||
active2.fields["criminal"] = "Incarcerated"
|
||||
if("parolled")
|
||||
active2.fields["criminal"] = "Parolled"
|
||||
if("released")
|
||||
active2.fields["criminal"] = "Released"
|
||||
|
||||
if ("Delete Record (Security) Execute")
|
||||
if (active2)
|
||||
del(active2)
|
||||
|
||||
if ("Delete Record (ALL) Execute")
|
||||
if (active1)
|
||||
for(var/datum/data/record/R in data_core.medical)
|
||||
if ((R.fields["name"] == active1.fields["name"] || R.fields["id"] == active1.fields["id"]))
|
||||
del(R)
|
||||
else
|
||||
del(active1)
|
||||
if (active2)
|
||||
del(active2)
|
||||
else
|
||||
temp = "This function does not appear to be working at the moment. Our apologies."
|
||||
|
||||
//computer.updateUsrDialog()
|
||||
interact()
|
||||
return
|
||||
|
||||
/obj/machinery/computer3/secure_data/emp_act(severity)
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
..(severity)
|
||||
return
|
||||
|
||||
for(var/datum/data/record/R in data_core.security)
|
||||
if(prob(10/severity))
|
||||
switch(rand(1,6))
|
||||
if(1)
|
||||
R.fields["name"] = "[pick(pick(first_names_male), pick(first_names_female))] [pick(last_names)]"
|
||||
if(2)
|
||||
R.fields["sex"] = pick("Male", "Female")
|
||||
if(3)
|
||||
R.fields["age"] = rand(5, 85)
|
||||
if(4)
|
||||
R.fields["criminal"] = pick("None", "*Arrest*", "Incarcerated", "Parolled", "Released")
|
||||
if(5)
|
||||
R.fields["p_stat"] = pick("*Unconcious*", "Active", "Physically Unfit")
|
||||
if(6)
|
||||
R.fields["m_stat"] = pick("*Insane*", "*Unstable*", "*Watch*", "Stable")
|
||||
continue
|
||||
|
||||
else if(prob(1))
|
||||
del(R)
|
||||
continue
|
||||
|
||||
..(severity)
|
||||
|
||||
/obj/machinery/computer3/secure_data/detective_computer
|
||||
icon = 'icons/obj/computer.dmi'
|
||||
icon_state = "messyfiles"
|
||||
@@ -0,0 +1,75 @@
|
||||
/*
|
||||
This may not migrate to C3. It's basically a machine in the guise of a computer;
|
||||
there is nothing interactive about it.
|
||||
*/
|
||||
|
||||
/obj/machinery/computer3/shuttle
|
||||
name = "Shuttle"
|
||||
desc = "For shuttle control."
|
||||
icon_state = "shuttle"
|
||||
var/auth_need = 3.0
|
||||
var/list/authorized = list( )
|
||||
|
||||
|
||||
attackby(var/obj/item/card/W as obj, var/mob/user as mob)
|
||||
if(stat & (BROKEN|NOPOWER)) return
|
||||
if ((!( istype(W, /obj/item/card) ) || !( ticker ) || emergency_shuttle.location != 1 || !( user ))) return
|
||||
if (istype(W, /obj/item/card/id)||istype(W, /obj/item/device/pda))
|
||||
if (istype(W, /obj/item/device/pda))
|
||||
var/obj/item/device/pda/pda = W
|
||||
W = pda.id
|
||||
if (!W:access) //no access
|
||||
user << "The access level of [W:registered_name]\'s card is not high enough. "
|
||||
return
|
||||
|
||||
var/list/cardaccess = W:access
|
||||
if(!istype(cardaccess, /list) || !cardaccess.len) //no access
|
||||
user << "The access level of [W:registered_name]\'s card is not high enough. "
|
||||
return
|
||||
|
||||
if(!(access_heads in W:access)) //doesn't have this access
|
||||
user << "The access level of [W:registered_name]\'s card is not high enough. "
|
||||
return 0
|
||||
|
||||
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")
|
||||
if(emergency_shuttle.location != 1 && user.get_active_hand() != W)
|
||||
return 0
|
||||
switch(choice)
|
||||
if("Authorize")
|
||||
src.authorized -= W:registered_name
|
||||
src.authorized += W:registered_name
|
||||
if (src.auth_need - src.authorized.len > 0)
|
||||
message_admins("[key_name_admin(user)] has authorized early shuttle launch")
|
||||
log_game("[user.ckey] has authorized early shuttle launch")
|
||||
world << text("\blue <B>Alert: [] authorizations needed until shuttle is launched early</B>", src.auth_need - src.authorized.len)
|
||||
else
|
||||
message_admins("[key_name_admin(user)] has launched the shuttle")
|
||||
log_game("[user.ckey] has launched the shuttle early")
|
||||
world << "\blue <B>Alert: Shuttle launch time shortened to 10 seconds!</B>"
|
||||
emergency_shuttle.online = 1
|
||||
emergency_shuttle.settimeleft(10)
|
||||
//src.authorized = null
|
||||
del(src.authorized)
|
||||
src.authorized = list( )
|
||||
|
||||
if("Repeal")
|
||||
src.authorized -= W:registered_name
|
||||
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( )
|
||||
|
||||
else if (istype(W, /obj/item/card/emag) && !emagged)
|
||||
var/choice = alert(user, "Would you like to launch the shuttle?","Shuttle control", "Launch", "Cancel")
|
||||
|
||||
if(!emagged && emergency_shuttle.location == 1 && user.get_active_hand() == W)
|
||||
switch(choice)
|
||||
if("Launch")
|
||||
world << "\blue <B>Alert: Shuttle launch time shortened to 10 seconds!</B>"
|
||||
emergency_shuttle.settimeleft( 10 )
|
||||
emagged = 1
|
||||
if("Cancel")
|
||||
return
|
||||
return
|
||||
@@ -0,0 +1,246 @@
|
||||
//Config stuff
|
||||
#define SPECOPS_MOVETIME 600 //Time to station is milliseconds. 60 seconds, enough time for everyone to be on the shuttle before it leaves.
|
||||
#define SPECOPS_STATION_AREATYPE "/area/shuttle/specops/station" //Type of the spec ops shuttle area for station
|
||||
#define SPECOPS_DOCK_AREATYPE "/area/shuttle/specops/centcom" //Type of the spec ops shuttle area for dock
|
||||
|
||||
var/specops_shuttle_moving_to_station = 0
|
||||
var/specops_shuttle_moving_to_centcom = 0
|
||||
var/specops_shuttle_at_station = 0
|
||||
var/specops_shuttle_can_send = 1
|
||||
var/specops_shuttle_time = 0
|
||||
var/specops_shuttle_timeleft = 0
|
||||
|
||||
/obj/machinery/computer3/specops_shuttle
|
||||
name = "Spec. Ops. Shuttle Console"
|
||||
icon = 'icons/obj/computer.dmi'
|
||||
icon_state = "shuttle"
|
||||
req_access = list(access_cent_specops)
|
||||
var/temp = null
|
||||
var/hacked = 0
|
||||
var/allowedtocall = 0
|
||||
|
||||
/proc/specops_process()
|
||||
var/area/centcom/control/cent_com = locate()//To find announcer. This area should exist for this proc to work.
|
||||
var/area/centcom/specops/special_ops = locate()//Where is the specops area located?
|
||||
var/mob/living/silicon/decoy/announcer = locate() in cent_com//We need a fake AI to announce some stuff below. Otherwise it will be wonky.
|
||||
|
||||
var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values.
|
||||
var/message = "THE SPECIAL OPERATIONS SHUTTLE IS PREPARING FOR LAUNCH"//Initial message shown.
|
||||
if(announcer)
|
||||
announcer.say(message)
|
||||
message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD"
|
||||
announcer.say(message)
|
||||
|
||||
while(specops_shuttle_time - world.timeofday > 0)
|
||||
var/ticksleft = specops_shuttle_time - world.timeofday
|
||||
|
||||
if(ticksleft > 1e5)
|
||||
specops_shuttle_time = world.timeofday + 10 // midnight rollover
|
||||
specops_shuttle_timeleft = (ticksleft / 10)
|
||||
|
||||
//All this does is announce the time before launch.
|
||||
if(announcer)
|
||||
var/rounded_time_left = round(specops_shuttle_timeleft)//Round time so that it will report only once, not in fractions.
|
||||
if(rounded_time_left in message_tracker)//If that time is in the list for message announce.
|
||||
message = "ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN"
|
||||
if(rounded_time_left==0)
|
||||
message = "ALERT: TAKEOFF"
|
||||
announcer.say(message)
|
||||
message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle.
|
||||
//Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that.
|
||||
|
||||
sleep(5)
|
||||
|
||||
specops_shuttle_moving_to_station = 0
|
||||
specops_shuttle_moving_to_centcom = 0
|
||||
|
||||
specops_shuttle_at_station = 1
|
||||
if (specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return
|
||||
|
||||
if (!specops_can_move())
|
||||
usr << "\red The Special Operations shuttle is unable to leave."
|
||||
return
|
||||
|
||||
//Begin Marauder launchpad.
|
||||
spawn(0)//So it parallel processes it.
|
||||
for(var/obj/machinery/door/poddoor/M in special_ops)
|
||||
switch(M.id)
|
||||
if("ASSAULT0")
|
||||
spawn(10)//1 second delay between each.
|
||||
M.open()
|
||||
if("ASSAULT1")
|
||||
spawn(20)
|
||||
M.open()
|
||||
if("ASSAULT2")
|
||||
spawn(30)
|
||||
M.open()
|
||||
if("ASSAULT3")
|
||||
spawn(40)
|
||||
M.open()
|
||||
|
||||
sleep(10)
|
||||
|
||||
var/spawn_marauder[] = new()
|
||||
for(var/obj/effect/landmark/L in landmarks_list)
|
||||
if(L.name == "Marauder Entry")
|
||||
spawn_marauder.Add(L)
|
||||
for(var/obj/effect/landmark/L in landmarks_list)
|
||||
if(L.name == "Marauder Exit")
|
||||
var/obj/effect/portal/P = new(L.loc)
|
||||
P.invisibility = 101//So it is not seen by anyone.
|
||||
P.failchance = 0//So it has no fail chance when teleporting.
|
||||
P.target = pick(spawn_marauder)//Where the marauder will arrive.
|
||||
spawn_marauder.Remove(P.target)
|
||||
|
||||
sleep(10)
|
||||
|
||||
for(var/obj/machinery/mass_driver/M in special_ops)
|
||||
switch(M.id)
|
||||
if("ASSAULT0")
|
||||
spawn(10)
|
||||
M.drive()
|
||||
if("ASSAULT1")
|
||||
spawn(20)
|
||||
M.drive()
|
||||
if("ASSAULT2")
|
||||
spawn(30)
|
||||
M.drive()
|
||||
if("ASSAULT3")
|
||||
spawn(40)
|
||||
M.drive()
|
||||
|
||||
sleep(50)//Doors remain open for 5 seconds.
|
||||
|
||||
for(var/obj/machinery/door/poddoor/M in special_ops)
|
||||
switch(M.id)//Doors close at the same time.
|
||||
if("ASSAULT0")
|
||||
spawn(0)
|
||||
M.close()
|
||||
if("ASSAULT1")
|
||||
spawn(0)
|
||||
M.close()
|
||||
if("ASSAULT2")
|
||||
spawn(0)
|
||||
M.close()
|
||||
if("ASSAULT3")
|
||||
spawn(0)
|
||||
M.close()
|
||||
special_ops.readyreset()//Reset firealarm after the team launched.
|
||||
//End Marauder launchpad.
|
||||
|
||||
var/area/start_location = locate(/area/shuttle/specops/centcom)
|
||||
var/area/end_location = locate(/area/shuttle/specops/station)
|
||||
|
||||
var/list/dstturfs = list()
|
||||
var/throwy = world.maxy
|
||||
|
||||
for(var/turf/T in end_location)
|
||||
dstturfs += T
|
||||
if(T.y < throwy)
|
||||
throwy = T.y
|
||||
|
||||
// hey you, get out of the way!
|
||||
for(var/turf/T in dstturfs)
|
||||
// find the turf to move things to
|
||||
var/turf/D = locate(T.x, throwy - 1, 1)
|
||||
//var/turf/E = get_step(D, SOUTH)
|
||||
for(var/atom/movable/AM as mob|obj in T)
|
||||
AM.Move(D)
|
||||
if(istype(T, /turf/simulated))
|
||||
del(T)
|
||||
|
||||
start_location.move_contents_to(end_location)
|
||||
|
||||
for(var/turf/T in get_area_turfs(end_location) )
|
||||
var/mob/M = locate(/mob) in T
|
||||
M << "\red You have arrived to [station_name]. Commence operation!"
|
||||
|
||||
/proc/specops_can_move()
|
||||
if(specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return 0
|
||||
else return 1
|
||||
|
||||
/obj/machinery/computer3/specops_shuttle/attackby(I as obj, user as mob)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/computer3/specops_shuttle/attack_ai(var/mob/user as mob)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/computer3/specops_shuttle/attack_paw(var/mob/user as mob)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/computer3/specops_shuttle/attackby(I as obj, user as mob)
|
||||
if(istype(I,/obj/item/card/emag))
|
||||
user << "\blue The electronic systems in this console are far too advanced for your primitive hacking peripherals."
|
||||
else
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/computer3/specops_shuttle/attack_hand(var/mob/user as mob)
|
||||
if(!allowed(user))
|
||||
user << "\red Access Denied."
|
||||
return
|
||||
|
||||
if (sent_strike_team == 0)
|
||||
usr << "\red The strike team has not yet deployed."
|
||||
return
|
||||
|
||||
if(..())
|
||||
return
|
||||
|
||||
user.set_machine(src)
|
||||
var/dat
|
||||
if (temp)
|
||||
dat = temp
|
||||
else
|
||||
dat += {"
|
||||
<b>Location:</b> [specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "Departing for [station_name] in ([specops_shuttle_timeleft] seconds.)":specops_shuttle_at_station ? "Station":"Dock"]<BR>
|
||||
[specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom ? "\n*The Special Ops. shuttle is already leaving.*<BR>\n<BR>":specops_shuttle_at_station ? "\n<A href='?src=\ref[src];sendtodock=1'>Shuttle Offline</A><BR>\n<BR>":"\n<A href='?src=\ref[src];sendtostation=1'>Depart to [station_name]</A><BR>\n<BR>"]
|
||||
\n<A href='?src=\ref[user];mach_close=computer'>Close</A>"}
|
||||
|
||||
//user << browse(dat, "window=computer;size=575x450")
|
||||
//onclose(user, "computer")
|
||||
var/datum/browser/popup = new(user, "computer", "Special Operations Shuttle", 575, 450)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
return
|
||||
|
||||
/obj/machinery/computer3/specops_shuttle/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if ((usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon)))
|
||||
usr.set_machine(src)
|
||||
|
||||
if (href_list["sendtodock"])
|
||||
if(!specops_shuttle_at_station|| specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return
|
||||
|
||||
usr << "\blue Central Command will not allow the Special Operations shuttle to return."
|
||||
return
|
||||
|
||||
else if (href_list["sendtostation"])
|
||||
if(specops_shuttle_at_station || specops_shuttle_moving_to_station || specops_shuttle_moving_to_centcom) return
|
||||
|
||||
if (!specops_can_move())
|
||||
usr << "\red The Special Operations shuttle is unable to leave."
|
||||
return
|
||||
|
||||
usr << "\blue The Special Operations shuttle will arrive on [station_name] in [(SPECOPS_MOVETIME/10)] seconds."
|
||||
|
||||
temp += "Shuttle departing.<BR><BR><A href='?src=\ref[src];mainmenu=1'>OK</A>"
|
||||
updateUsrDialog()
|
||||
|
||||
var/area/centcom/specops/special_ops = locate()
|
||||
if(special_ops)
|
||||
special_ops.readyalert()//Trigger alarm for the spec ops area.
|
||||
specops_shuttle_moving_to_station = 1
|
||||
|
||||
specops_shuttle_time = world.timeofday + SPECOPS_MOVETIME
|
||||
spawn(0)
|
||||
specops_process()
|
||||
|
||||
else if (href_list["mainmenu"])
|
||||
temp = null
|
||||
|
||||
add_fingerprint(usr)
|
||||
updateUsrDialog()
|
||||
return
|
||||
@@ -0,0 +1,97 @@
|
||||
/obj/machinery/computer3/station_alert
|
||||
default_prog = /datum/file/program/station_alert
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/networking/radio)
|
||||
icon_state = "frame-eng"
|
||||
|
||||
|
||||
/datum/file/program/station_alert
|
||||
name = "Station Alert Console"
|
||||
desc = "Used to access the station's automated alert system."
|
||||
active_state = "alert:0"
|
||||
var/alarms = list("Fire"=list(), "Atmosphere"=list(), "Power"=list())
|
||||
|
||||
interact(mob/user)
|
||||
usr.set_machine(src)
|
||||
if(!interactable())
|
||||
return
|
||||
var/dat = "<HEAD><TITLE>Current Station Alerts</TITLE><META HTTP-EQUIV='Refresh' CONTENT='10'></HEAD><BODY>\n"
|
||||
dat += "<A HREF='?src=\ref[user];mach_close=alerts'>Close</A><br><br>"
|
||||
for (var/cat in src.alarms)
|
||||
dat += text("<B>[]</B><BR>\n", cat)
|
||||
var/list/L = src.alarms[cat]
|
||||
if (L.len)
|
||||
for (var/alarm in L)
|
||||
var/list/alm = L[alarm]
|
||||
var/area/A = alm[1]
|
||||
var/list/sources = alm[3]
|
||||
dat += "<NOBR>"
|
||||
dat += "• "
|
||||
dat += "[A.name]"
|
||||
if (sources.len > 1)
|
||||
dat += text(" - [] sources", sources.len)
|
||||
dat += "</NOBR><BR>\n"
|
||||
else
|
||||
dat += "-- All Systems Nominal<BR>\n"
|
||||
dat += "<BR>\n"
|
||||
//user << browse(dat, "window=alerts")
|
||||
//onclose(user, "alerts")
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(usr.browse_rsc_icon(computer.icon, computer.icon_state))
|
||||
popup.open()
|
||||
return
|
||||
|
||||
|
||||
Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
proc/triggerAlarm(var/class, area/A, var/O, var/alarmsource)
|
||||
var/list/L = src.alarms[class]
|
||||
for (var/I in L)
|
||||
if (I == A.name)
|
||||
var/list/alarm = L[I]
|
||||
var/list/sources = alarm[3]
|
||||
if (!(alarmsource in sources))
|
||||
sources += alarmsource
|
||||
return 1
|
||||
var/obj/machinery/camera/C = null
|
||||
var/list/CL = null
|
||||
if (O && istype(O, /list))
|
||||
CL = O
|
||||
if (CL.len == 1)
|
||||
C = CL[1]
|
||||
else if (O && istype(O, /obj/machinery/camera))
|
||||
C = O
|
||||
L[A.name] = list(A, (C) ? C : O, list(alarmsource))
|
||||
return 1
|
||||
|
||||
|
||||
proc/cancelAlarm(var/class, area/A as area, obj/origin)
|
||||
var/list/L = src.alarms[class]
|
||||
var/cleared = 0
|
||||
for (var/I in L)
|
||||
if (I == A.name)
|
||||
var/list/alarm = L[I]
|
||||
var/list/srcs = alarm[3]
|
||||
if (origin in srcs)
|
||||
srcs -= origin
|
||||
if (srcs.len == 0)
|
||||
cleared = 1
|
||||
L -= I
|
||||
return !cleared
|
||||
|
||||
|
||||
|
||||
process()
|
||||
var/active_alarms = 0
|
||||
for (var/cat in src.alarms)
|
||||
var/list/L = src.alarms[cat]
|
||||
if(L.len) active_alarms = 1
|
||||
if(active_alarms)
|
||||
active_state = "alert:2"
|
||||
else
|
||||
active_state = "alert:0"
|
||||
..()
|
||||
return
|
||||
@@ -0,0 +1,103 @@
|
||||
#define SYNDICATE_SHUTTLE_MOVE_TIME 240
|
||||
#define SYNDICATE_SHUTTLE_COOLDOWN 200
|
||||
|
||||
/obj/machinery/computer3/syndicate_station
|
||||
name = "syndicate shuttle terminal"
|
||||
icon = 'icons/obj/computer.dmi'
|
||||
icon_state = "syndishuttle"
|
||||
req_access = list(access_syndicate)
|
||||
var/area/curr_location
|
||||
var/moving = 0
|
||||
var/lastMove = 0
|
||||
|
||||
|
||||
/obj/machinery/computer3/syndicate_station/New()
|
||||
curr_location= locate(/area/syndicate_station/start)
|
||||
|
||||
|
||||
/obj/machinery/computer3/syndicate_station/proc/syndicate_move_to(area/destination as area)
|
||||
if(moving) return
|
||||
if(lastMove + SYNDICATE_SHUTTLE_COOLDOWN > world.time) return
|
||||
var/area/dest_location = locate(destination)
|
||||
if(curr_location == dest_location) return
|
||||
|
||||
moving = 1
|
||||
lastMove = world.time
|
||||
|
||||
if(curr_location.z != dest_location.z)
|
||||
var/area/transit_location = locate(/area/syndicate_station/transit)
|
||||
curr_location.move_contents_to(transit_location)
|
||||
curr_location = transit_location
|
||||
sleep(SYNDICATE_SHUTTLE_MOVE_TIME)
|
||||
|
||||
curr_location.move_contents_to(dest_location)
|
||||
curr_location = dest_location
|
||||
moving = 0
|
||||
return 1
|
||||
|
||||
|
||||
/obj/machinery/computer3/syndicate_station/attackby(obj/item/I as obj, mob/user as mob)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/computer3/syndicate_station/attack_ai(mob/user as mob)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/computer3/syndicate_station/attack_paw(mob/user as mob)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/computer3/syndicate_station/attack_hand(mob/user as mob)
|
||||
if(!allowed(user))
|
||||
user << "\red Access Denied"
|
||||
return
|
||||
|
||||
user.set_machine(src)
|
||||
|
||||
var/dat = {"Location: [curr_location]<br>
|
||||
Ready to move[max(lastMove + SYNDICATE_SHUTTLE_COOLDOWN - world.time, 0) ? " in [max(round((lastMove + SYNDICATE_SHUTTLE_COOLDOWN - world.time) * 0.1), 0)] seconds" : ": now"]<br>
|
||||
<a href='?src=\ref[src];syndicate=1'>Syndicate Space</a><br>
|
||||
<a href='?src=\ref[src];station_nw=1'>North West of SS13</a> |
|
||||
<a href='?src=\ref[src];station_n=1'>North of SS13</a> |
|
||||
<a href='?src=\ref[src];station_ne=1'>North East of SS13</a><br>
|
||||
<a href='?src=\ref[src];station_sw=1'>South West of SS13</a> |
|
||||
<a href='?src=\ref[src];station_s=1'>South of SS13</a> |
|
||||
<a href='?src=\ref[src];station_se=1'>South East of SS13</a><br>
|
||||
<a href='?src=\ref[src];mining=1'>North East of the Mining Asteroid</a><br>
|
||||
<a href='?src=\ref[user];mach_close=computer'>Close</a>"}
|
||||
|
||||
user << browse(dat, "window=computer;size=575x450")
|
||||
onclose(user, "computer")
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/computer3/syndicate_station/Topic(href, href_list)
|
||||
if(!isliving(usr)) return
|
||||
var/mob/living/user = usr
|
||||
|
||||
if(in_range(src, user) || istype(user, /mob/living/silicon))
|
||||
user.set_machine(src)
|
||||
|
||||
if(href_list["syndicate"])
|
||||
syndicate_move_to(/area/syndicate_station/start)
|
||||
else if(href_list["station_nw"])
|
||||
syndicate_move_to(/area/syndicate_station/northwest)
|
||||
else if(href_list["station_n"])
|
||||
syndicate_move_to(/area/syndicate_station/north)
|
||||
else if(href_list["station_ne"])
|
||||
syndicate_move_to(/area/syndicate_station/northeast)
|
||||
else if(href_list["station_sw"])
|
||||
syndicate_move_to(/area/syndicate_station/southwest)
|
||||
else if(href_list["station_s"])
|
||||
syndicate_move_to(/area/syndicate_station/south)
|
||||
else if(href_list["station_se"])
|
||||
syndicate_move_to(/area/syndicate_station/southeast)
|
||||
// else if(href_list["commssat"])
|
||||
// syndicate_move_to(/area/syndicate_station/commssat)
|
||||
else if(href_list["mining"])
|
||||
syndicate_move_to(/area/syndicate_station/mining)
|
||||
|
||||
add_fingerprint(usr)
|
||||
updateUsrDialog()
|
||||
return
|
||||
|
||||
/obj/machinery/computer3/syndicate_station/bullet_act(var/obj/item/projectile/Proj)
|
||||
visible_message("[Proj] ricochets off [src]!") //let's not let them fuck themselves in the rear
|
||||
@@ -0,0 +1,259 @@
|
||||
//Config stuff
|
||||
#define SYNDICATE_ELITE_MOVETIME 600 //Time to station is deciseconds. 60 seconds, enough time for everyone to be on the shuttle before it leaves.
|
||||
#define SYNDICATE_ELITE_STATION_AREATYPE "/area/shuttle/syndicate_elite/station" //Type of the spec ops shuttle area for station
|
||||
#define SYNDICATE_ELITE_DOCK_AREATYPE "/area/shuttle/syndicate_elite/mothership" //Type of the spec ops shuttle area for dock
|
||||
|
||||
var/syndicate_elite_shuttle_moving_to_station = 0
|
||||
var/syndicate_elite_shuttle_moving_to_mothership = 0
|
||||
var/syndicate_elite_shuttle_at_station = 0
|
||||
var/syndicate_elite_shuttle_can_send = 1
|
||||
var/syndicate_elite_shuttle_time = 0
|
||||
var/syndicate_elite_shuttle_timeleft = 0
|
||||
|
||||
/obj/machinery/computer3/syndicate_elite_shuttle
|
||||
name = "Elite Syndicate Squad Shuttle Console"
|
||||
icon = 'icons/obj/computer.dmi'
|
||||
icon_state = "syndishuttle"
|
||||
req_access = list(access_cent_specops)
|
||||
var/temp = null
|
||||
var/hacked = 0
|
||||
var/allowedtocall = 0
|
||||
|
||||
/proc/syndicate_elite_process()
|
||||
var/area/syndicate_mothership/control/syndicate_ship = locate()//To find announcer. This area should exist for this proc to work.
|
||||
var/area/syndicate_mothership/elite_squad/elite_squad = locate()//Where is the specops area located?
|
||||
var/mob/living/silicon/decoy/announcer = locate() in syndicate_ship//We need a fake AI to announce some stuff below. Otherwise it will be wonky.
|
||||
|
||||
var/message_tracker[] = list(0,1,2,3,5,10,30,45)//Create a a list with potential time values.
|
||||
var/message = "THE SYNDICATE ELITE SHUTTLE IS PREPARING FOR LAUNCH"//Initial message shown.
|
||||
if(announcer)
|
||||
announcer.say(message)
|
||||
// message = "ARMORED SQUAD TAKE YOUR POSITION ON GRAVITY LAUNCH PAD"
|
||||
// announcer.say(message)
|
||||
|
||||
while(syndicate_elite_shuttle_time - world.timeofday > 0)
|
||||
var/ticksleft = syndicate_elite_shuttle_time - world.timeofday
|
||||
|
||||
if(ticksleft > 1e5)
|
||||
syndicate_elite_shuttle_time = world.timeofday // midnight rollover
|
||||
syndicate_elite_shuttle_timeleft = (ticksleft / 10)
|
||||
|
||||
//All this does is announce the time before launch.
|
||||
if(announcer)
|
||||
var/rounded_time_left = round(syndicate_elite_shuttle_timeleft)//Round time so that it will report only once, not in fractions.
|
||||
if(rounded_time_left in message_tracker)//If that time is in the list for message announce.
|
||||
message = "ALERT: [rounded_time_left] SECOND[(rounded_time_left!=1)?"S":""] REMAIN"
|
||||
if(rounded_time_left==0)
|
||||
message = "ALERT: TAKEOFF"
|
||||
announcer.say(message)
|
||||
message_tracker -= rounded_time_left//Remove the number from the list so it won't be called again next cycle.
|
||||
//Should call all the numbers but lag could mean some issues. Oh well. Not much I can do about that.
|
||||
|
||||
sleep(5)
|
||||
|
||||
syndicate_elite_shuttle_moving_to_station = 0
|
||||
syndicate_elite_shuttle_moving_to_mothership = 0
|
||||
|
||||
syndicate_elite_shuttle_at_station = 1
|
||||
if (syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return
|
||||
|
||||
if (!syndicate_elite_can_move())
|
||||
usr << "\red The Syndicate Elite shuttle is unable to leave."
|
||||
return
|
||||
|
||||
sleep(600)
|
||||
/*
|
||||
//Begin Marauder launchpad.
|
||||
spawn(0)//So it parallel processes it.
|
||||
for(var/obj/machinery/door/poddoor/M in elite_squad)
|
||||
switch(M.id)
|
||||
if("ASSAULT0")
|
||||
spawn(10)//1 second delay between each.
|
||||
M.open()
|
||||
if("ASSAULT1")
|
||||
spawn(20)
|
||||
M.open()
|
||||
if("ASSAULT2")
|
||||
spawn(30)
|
||||
M.open()
|
||||
if("ASSAULT3")
|
||||
spawn(40)
|
||||
M.open()
|
||||
|
||||
sleep(10)
|
||||
|
||||
var/spawn_marauder[] = new()
|
||||
for(var/obj/effect/landmark/L in landmarks_list)
|
||||
if(L.name == "Marauder Entry")
|
||||
spawn_marauder.Add(L)
|
||||
for(var/obj/effect/landmark/L in landmarks_list)
|
||||
if(L.name == "Marauder Exit")
|
||||
var/obj/effect/portal/P = new(L.loc)
|
||||
P.invisibility = 101//So it is not seen by anyone.
|
||||
P.failchance = 0//So it has no fail chance when teleporting.
|
||||
P.target = pick(spawn_marauder)//Where the marauder will arrive.
|
||||
spawn_marauder.Remove(P.target)
|
||||
|
||||
sleep(10)
|
||||
|
||||
for(var/obj/machinery/mass_driver/M in elite_squad)
|
||||
switch(M.id)
|
||||
if("ASSAULT0")
|
||||
spawn(10)
|
||||
M.drive()
|
||||
if("ASSAULT1")
|
||||
spawn(20)
|
||||
M.drive()
|
||||
if("ASSAULT2")
|
||||
spawn(30)
|
||||
M.drive()
|
||||
if("ASSAULT3")
|
||||
spawn(40)
|
||||
M.drive()
|
||||
|
||||
sleep(50)//Doors remain open for 5 seconds.
|
||||
|
||||
for(var/obj/machinery/door/poddoor/M in elite_squad)
|
||||
switch(M.id)//Doors close at the same time.
|
||||
if("ASSAULT0")
|
||||
spawn(0)
|
||||
M.close()
|
||||
if("ASSAULT1")
|
||||
spawn(0)
|
||||
M.close()
|
||||
if("ASSAULT2")
|
||||
spawn(0)
|
||||
M.close()
|
||||
if("ASSAULT3")
|
||||
spawn(0)
|
||||
M.close()
|
||||
*/
|
||||
elite_squad.readyreset()//Reset firealarm after the team launched.
|
||||
//End Marauder launchpad.
|
||||
/*
|
||||
var/obj/explosionmarker = locate("Syndicate Breach Area")
|
||||
if(explosionmarker)
|
||||
var/turf/simulated/T = explosionmarker.loc
|
||||
if(T)
|
||||
explosion(T,4,6,8,10,0)
|
||||
|
||||
sleep(40)
|
||||
// proc/explosion(turf/epicenter, devastation_range, heavy_impact_range, light_impact_range, flash_range, adminlog = 1)
|
||||
|
||||
*/
|
||||
var/area/start_location = locate(/area/shuttle/syndicate_elite/mothership)
|
||||
var/area/end_location = locate(/area/shuttle/syndicate_elite/station)
|
||||
|
||||
var/list/dstturfs = list()
|
||||
var/throwy = world.maxy
|
||||
|
||||
for(var/turf/T in end_location)
|
||||
dstturfs = T
|
||||
if(T.y < throwy)
|
||||
throwy = T.y
|
||||
|
||||
// hey you, get out of the way!
|
||||
for(var/turf/T in dstturfs)
|
||||
// find the turf to move things to
|
||||
var/turf/D = locate(T.x, throwy - 1, 1)
|
||||
//var/turf/E = get_step(D, SOUTH)
|
||||
for(var/atom/movable/AM as mob|obj in T)
|
||||
AM.Move(D)
|
||||
if(istype(T, /turf/simulated))
|
||||
del(T)
|
||||
|
||||
start_location.move_contents_to(end_location)
|
||||
|
||||
for(var/turf/T in get_area_turfs(end_location) )
|
||||
var/mob/M = locate(/mob) in T
|
||||
M << "\red You have arrived to [station_name]. Commence operation!"
|
||||
|
||||
/proc/syndicate_elite_can_move()
|
||||
if(syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return 0
|
||||
else return 1
|
||||
|
||||
/obj/machinery/computer3/syndicate_elite_shuttle/attackby(I as obj, user as mob)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/computer3/syndicate_elite_shuttle/attack_ai(var/mob/user as mob)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/computer3/syndicate_elite_shuttle/attack_paw(var/mob/user as mob)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/computer3/syndicate_elite_shuttle/attackby(I as obj, user as mob)
|
||||
if(istype(I,/obj/item/card/emag))
|
||||
user << "\blue The electronic systems in this console are far too advanced for your primitive hacking peripherals."
|
||||
else
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/computer3/syndicate_elite_shuttle/attack_hand(var/mob/user as mob)
|
||||
if(!allowed(user))
|
||||
user << "\red Access Denied."
|
||||
return
|
||||
|
||||
// if (sent_syndicate_strike_team == 0)
|
||||
// usr << "\red The strike team has not yet deployed."
|
||||
// return
|
||||
|
||||
if(..())
|
||||
return
|
||||
|
||||
user.set_machine(src)
|
||||
var/dat
|
||||
if (temp)
|
||||
dat = temp
|
||||
else
|
||||
dat = {"<b>Location:</b> [syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership ? "Departing for [station_name] in ([syndicate_elite_shuttle_timeleft] seconds.)":syndicate_elite_shuttle_at_station ? "Station":"Dock"]<BR>
|
||||
[syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership ? "\n*The Syndicate Elite shuttle is already leaving.*<BR>\n<BR>":syndicate_elite_shuttle_at_station ? "\n<A href='?src=\ref[src];sendtodock=1'>Shuttle Offline</A><BR>\n<BR>":"\n<A href='?src=\ref[src];sendtostation=1'>Depart to [station_name]</A><BR>\n<BR>"]
|
||||
\n<A href='?src=\ref[user];mach_close=computer'>Close</A>"}
|
||||
|
||||
//user << browse(dat, "window=computer;size=575x450")
|
||||
//onclose(user, "computer")
|
||||
var/datum/browser/popup = new(user, "computer", "Special Operations Shuttle", 575, 450)
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
|
||||
popup.open()
|
||||
return
|
||||
|
||||
/obj/machinery/computer3/syndicate_elite_shuttle/Topic(href, href_list)
|
||||
if(..())
|
||||
return
|
||||
|
||||
if ((usr.contents.Find(src) || (in_range(src, usr) && istype(loc, /turf))) || (istype(usr, /mob/living/silicon)))
|
||||
usr.set_machine(src)
|
||||
|
||||
if (href_list["sendtodock"])
|
||||
if(!syndicate_elite_shuttle_at_station|| syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return
|
||||
|
||||
usr << "\blue The Syndicate will not allow the Elite Squad shuttle to return."
|
||||
return
|
||||
|
||||
else if (href_list["sendtostation"])
|
||||
if(syndicate_elite_shuttle_at_station || syndicate_elite_shuttle_moving_to_station || syndicate_elite_shuttle_moving_to_mothership) return
|
||||
|
||||
if (!specops_can_move())
|
||||
usr << "\red The Syndicate Elite shuttle is unable to leave."
|
||||
return
|
||||
|
||||
usr << "\blue The Syndicate Elite shuttle will arrive on [station_name] in [(SYNDICATE_ELITE_MOVETIME/10)] seconds."
|
||||
|
||||
temp = "Shuttle departing.<BR><BR><A href='?src=\ref[src];mainmenu=1'>OK</A>"
|
||||
updateUsrDialog()
|
||||
|
||||
var/area/syndicate_mothership/elite_squad/elite_squad = locate()
|
||||
if(elite_squad)
|
||||
elite_squad.readyalert()//Trigger alarm for the spec ops area.
|
||||
syndicate_elite_shuttle_moving_to_station = 1
|
||||
|
||||
syndicate_elite_shuttle_time = world.timeofday + SYNDICATE_ELITE_MOVETIME
|
||||
spawn(0)
|
||||
syndicate_elite_process()
|
||||
|
||||
|
||||
else if (href_list["mainmenu"])
|
||||
temp = null
|
||||
|
||||
add_fingerprint(usr)
|
||||
updateUsrDialog()
|
||||
return
|
||||
@@ -0,0 +1,34 @@
|
||||
/obj/machinery/computer3/laptop/vended
|
||||
default_prog = /datum/file/program/welcome
|
||||
|
||||
|
||||
/datum/file/program/welcome
|
||||
name = "Welcome Screen"
|
||||
desc = "First time boot splash screen"
|
||||
active_state = "osod"
|
||||
image = 'icons/ntos/program.png'
|
||||
|
||||
|
||||
interact()
|
||||
usr.set_machine(src)
|
||||
if(!interactable())
|
||||
return
|
||||
var/dat = ""
|
||||
dat += "<center><span style='font-size:24pt'><b>Welcome to NTOS</b></span></center>"
|
||||
dat += "<center><span style='font-size:8pt'>Thank you for choosing NTOS, your gateway to the future of mobile computing technology, sponsored by Nanotrasen (R)</span></center><br>"
|
||||
dat += "<span style='font-size:12pt'><b>Getting started with NTOS:</b></span><br>"
|
||||
dat += "To leave a current program, click the X button in the top right corner of the window. This will return you to the NTOS desktop. \
|
||||
From the desktop, you can open the hard drive, usually located in the top left corner to access all the programs installed on your computer. \
|
||||
When you rented your laptop, you were supplied with programs that your Nanotrasen Issued ID has given you access to use. \
|
||||
In the event of a serious error, the right click menu will give you the ability to reset your computer. To open and close your laptop, alt-click your device.\
|
||||
If you have any questions or technical issues, please contact your local computer technical experts at your local Central Command."
|
||||
popup.set_content(dat)
|
||||
popup.set_title_image(usr.browse_rsc_icon(computer.icon, computer.icon_state))
|
||||
popup.open()
|
||||
return
|
||||
|
||||
Topic(href, href_list)
|
||||
if(!interactable() || ..(href,href_list))
|
||||
return
|
||||
interact()
|
||||
return
|
||||
@@ -0,0 +1,166 @@
|
||||
// I am deciding that for sayustation's purposes directories are right out,
|
||||
// we can't even get backpacks to work right with recursion, and that
|
||||
// actually fucking matters. Metadata too, that can be added if ever needed.
|
||||
|
||||
/*
|
||||
Files are datums that can be stored in digital storage devices
|
||||
*/
|
||||
|
||||
/datum/file
|
||||
var/name = "File"
|
||||
var/extension = "dat"
|
||||
var/volume = 10 // in KB
|
||||
var/image = 'icons/ntos/file.png' // determines the icon to use, found in icons/ntos
|
||||
var/obj/machinery/computer3/computer // the parent computer, if fixed
|
||||
var/obj/item/part/computer/storage/device // the device that is containing this file
|
||||
|
||||
var/drm = 0 // Copy protection, called by copy() and move()
|
||||
var/readonly = 0 // Edit protection, called by edit(), which is just a failcheck proc
|
||||
|
||||
proc/execute(var/datum/file/source)
|
||||
return
|
||||
|
||||
//
|
||||
// Copy file to device.
|
||||
// If you overwrite this function, use the return value to make sure it succeeded
|
||||
//
|
||||
proc/copy(var/obj/item/part/computer/storage/dest)
|
||||
if(!computer || computer.crit_fail) return null
|
||||
if(drm)
|
||||
if(!computer.emagged)
|
||||
return null
|
||||
var/datum/file/F = new type()
|
||||
if(!dest.addfile(F))
|
||||
return null // todo: arf here even though the player can't do a damn thing due to concurrency
|
||||
return F
|
||||
|
||||
//
|
||||
// Move file to device
|
||||
// Returns null on failure even though the existing file doesn't go away
|
||||
//
|
||||
proc/move(var/obj/item/part/computer/storage/dest)
|
||||
if(!computer || computer.crit_fail) return null
|
||||
if(drm)
|
||||
if(!computer.emagged)
|
||||
return null
|
||||
var/obj/item/part/computer/storage/current = device
|
||||
if(!dest.addfile(src))
|
||||
return null
|
||||
current.removefile(src)
|
||||
return src
|
||||
|
||||
//
|
||||
// Determines if the file is editable. This does not use the DRM flag,
|
||||
// but instead the readonly flag.
|
||||
//
|
||||
|
||||
proc/edit()
|
||||
if(!computer || computer.crit_fail)
|
||||
return 0
|
||||
if(readonly && !computer.emagged)
|
||||
return 0 //
|
||||
return 1
|
||||
|
||||
/*
|
||||
Centcom root authorization certificate
|
||||
|
||||
Non-destructive, officially sanctioned.
|
||||
Has the same effect on computers as an emag.
|
||||
*/
|
||||
/datum/file/centcom_auth
|
||||
name = "Centcom Root Access Token"
|
||||
extension = "auth"
|
||||
volume = 100
|
||||
copy()
|
||||
return null
|
||||
|
||||
/*
|
||||
A file that contains information
|
||||
*/
|
||||
|
||||
/datum/file/data
|
||||
|
||||
var/content = "content goes here"
|
||||
var/file_increment = 1
|
||||
var/binary = 0 // determines if the file can't be opened by editor
|
||||
|
||||
// Set the content to a specific amount, increase filesize appropriately.
|
||||
proc/set_content(var/text)
|
||||
content = text
|
||||
if(file_increment > 1)
|
||||
volume = round(file_increment * length(text))
|
||||
|
||||
copy(var/obj/O)
|
||||
var/datum/file/data/D = ..(O)
|
||||
if(D)
|
||||
D.content = content
|
||||
D.readonly = readonly
|
||||
|
||||
New()
|
||||
if(content)
|
||||
if(file_increment > 1)
|
||||
volume = round(file_increment * length(content))
|
||||
|
||||
/*
|
||||
A generic file that contains text
|
||||
*/
|
||||
|
||||
/datum/file/data/text
|
||||
name = "Text File"
|
||||
extension = "txt"
|
||||
image = 'icons/ntos/file.png'
|
||||
content = ""
|
||||
file_increment = 0.002 // 0.002 kilobytes per character (1024 characters per KB)
|
||||
|
||||
/datum/file/data/text/ClownProphecy
|
||||
name = "Clown Prophecy"
|
||||
content = "HONKhHONKeHONKlHONKpHONKHONmKHONKeHONKHONKpHONKlHONKeHONKaHONKsHONKe"
|
||||
|
||||
|
||||
/*
|
||||
A file that contains research
|
||||
*/
|
||||
|
||||
/datum/file/data/research
|
||||
name = "Untitled Research"
|
||||
binary = 1
|
||||
content = "Untitled Tier X Research"
|
||||
var/datum/tech/stored // the actual tech contents
|
||||
volume = 1440
|
||||
|
||||
/*
|
||||
A file that contains genetic information
|
||||
*/
|
||||
|
||||
/datum/file/data/genome
|
||||
name = "Genetic Buffer"
|
||||
binary = 1
|
||||
var/real_name = "Poop"
|
||||
|
||||
|
||||
/datum/file/data/genome/SE
|
||||
name = "Structural Enzymes"
|
||||
var/mutantrace = null
|
||||
|
||||
/datum/file/data/genome/UE
|
||||
name = "Unique Enzymes"
|
||||
|
||||
/*
|
||||
the way genome computers now work, a subtype is the wrong way to do this;
|
||||
it will no longer be picked up. You can change this later if you need to.
|
||||
for now put it on a disk
|
||||
|
||||
/datum/file/data/genome/UE/GodEmperorOfMankind
|
||||
name = "G.E.M.K."
|
||||
content = "066000033000000000AF00330660FF4DB002690"
|
||||
label = "God Emperor of Mankind"
|
||||
*/
|
||||
/datum/file/data/genome/UI
|
||||
name = "Unique Identifier"
|
||||
|
||||
/datum/file/data/genome/UI/UE
|
||||
name = "Unique Identifier + Unique Enzymes"
|
||||
|
||||
/datum/file/data/genome/cloning
|
||||
name = "Cloning Data"
|
||||
var/datum/data/record/record
|
||||
@@ -0,0 +1,154 @@
|
||||
/*
|
||||
Computer3 portable computer.
|
||||
|
||||
Battery powered only; it does not use the APC network at all.
|
||||
|
||||
When picked up, becomes an inert item. This item can be put in a recharger,
|
||||
or set down and re-opened into the original machine. While closed, the computer
|
||||
has the MAINT stat flag. If you want to ignore this, you will have to bitmask it out.
|
||||
|
||||
The unused(?) alt+click will toggle laptops open and closed. If we find a better
|
||||
answer for this in the future, by all means use it. I just don't want it limited
|
||||
to the verb, which is SIGNIFICANTLY less accessible than shutting a laptop.
|
||||
Ctrl-click would work for closing the machine, since it's anchored, but not for
|
||||
opening it back up again. And obviously, I don't want to override shift-click.
|
||||
There's no double-click because that's used in regular click events. Alt-click is the
|
||||
only obvious one left.
|
||||
*/
|
||||
|
||||
|
||||
/obj/item/device/laptop
|
||||
name = "Laptop Computer"
|
||||
desc = "A clamshell portable computer. It is closed."
|
||||
icon = 'icons/obj/computer3.dmi'
|
||||
icon_state = "laptop-closed"
|
||||
item_state = "laptop-inhand"
|
||||
pixel_x = 2
|
||||
pixel_y = -3
|
||||
w_class = 3
|
||||
|
||||
var/obj/machinery/computer3/laptop/stored_computer = null
|
||||
|
||||
verb/open_computer()
|
||||
set name = "open laptop"
|
||||
set category = "Object"
|
||||
set src in view(1)
|
||||
|
||||
if(usr.stat || usr.restrained() || usr.lying || !istype(usr, /mob/living))
|
||||
usr << "\red You can't do that."
|
||||
return
|
||||
|
||||
if(!Adjacent(usr))
|
||||
usr << "You can't reach it."
|
||||
return
|
||||
|
||||
if(!istype(loc,/turf))
|
||||
usr << "[src] is too bulky! You'll have to set it down."
|
||||
return
|
||||
|
||||
if(!stored_computer)
|
||||
if(contents.len)
|
||||
for(var/obj/O in contents)
|
||||
O.loc = loc
|
||||
usr << "\The [src] crumbles to pieces."
|
||||
spawn(5)
|
||||
del src
|
||||
return
|
||||
|
||||
|
||||
stored_computer.loc = loc
|
||||
stored_computer.stat &= ~MAINT
|
||||
stored_computer.update_icon()
|
||||
loc = null
|
||||
usr << "You open \the [src]."
|
||||
|
||||
spawn(5)
|
||||
del src
|
||||
|
||||
AltClick()
|
||||
if(Adjacent(usr))
|
||||
open_computer()
|
||||
|
||||
/obj/machinery/computer3/laptop
|
||||
name = "Laptop Computer"
|
||||
desc = "A clamshell portable computer. It is open."
|
||||
|
||||
icon_state = "laptop"
|
||||
density = 0
|
||||
pixel_x = 2
|
||||
pixel_y = -3
|
||||
show_keyboard = 0
|
||||
|
||||
var/obj/item/device/laptop/portable = null
|
||||
|
||||
New(var/L, var/built = 0)
|
||||
if(!built && !battery)
|
||||
battery = new /obj/item/weapon/cell(src)
|
||||
..(L,built)
|
||||
|
||||
verb/close_computer()
|
||||
set name = "Close Laptop"
|
||||
set category = "Object"
|
||||
set src in view(1)
|
||||
|
||||
if(usr.stat || usr.restrained() || usr.lying || !istype(usr, /mob/living))
|
||||
usr << "\red You can't do that."
|
||||
return
|
||||
|
||||
if(!Adjacent(usr))
|
||||
usr << "You can't reach it."
|
||||
return
|
||||
|
||||
if(istype(loc,/obj/item/device/laptop))
|
||||
testing("Close closed computer")
|
||||
return
|
||||
if(!istype(loc,/turf))
|
||||
testing("Odd computer location: [loc] - close laptop")
|
||||
return
|
||||
|
||||
if(stat&BROKEN)
|
||||
usr << "\The [src] is broken! You can't quite get it closed."
|
||||
return
|
||||
|
||||
if(!portable)
|
||||
portable=new
|
||||
portable.stored_computer = src
|
||||
|
||||
portable.loc = loc
|
||||
loc = portable
|
||||
stat |= MAINT
|
||||
usr << "You close \the [src]."
|
||||
|
||||
auto_use_power()
|
||||
if(stat&MAINT)
|
||||
return
|
||||
if(use_power && istype(battery) && battery.charge > 0)
|
||||
if(use_power == 1)
|
||||
battery.use(idle_power_usage)
|
||||
else
|
||||
battery.use(active_power_usage)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
use_power(var/amount, var/chan = -1)
|
||||
if(battery && battery.charge > 0)
|
||||
battery.use(amount)
|
||||
|
||||
power_change()
|
||||
if( !battery || battery.charge <= 0 )
|
||||
stat |= NOPOWER
|
||||
else
|
||||
stat &= ~NOPOWER
|
||||
|
||||
Del()
|
||||
if(istype(loc,/obj/item/device/laptop))
|
||||
var/obj/O = loc
|
||||
spawn(5)
|
||||
if(O)
|
||||
del O
|
||||
..()
|
||||
|
||||
|
||||
AltClick()
|
||||
if(Adjacent(usr))
|
||||
close_computer()
|
||||
@@ -0,0 +1,398 @@
|
||||
/obj/machinery/lapvend
|
||||
name = "Laptop Vendor"
|
||||
desc = "A generic vending machine."
|
||||
icon = 'icons/obj/vending.dmi'
|
||||
icon_state = "robotics"
|
||||
layer = 2.9
|
||||
anchored = 1
|
||||
density = 1
|
||||
var/datum/browser/popup = null
|
||||
var/obj/machinery/computer3/laptop/vended/newlap = null
|
||||
var/obj/item/device/laptop/relap = null
|
||||
var/vendmode = 0
|
||||
|
||||
|
||||
var/cardreader = 0
|
||||
var/floppy = 0
|
||||
var/radionet = 0
|
||||
var/camera = 0
|
||||
var/network = 0
|
||||
var/power = 0
|
||||
|
||||
|
||||
/obj/machinery/lapvend/New()
|
||||
..()
|
||||
spawn(4)
|
||||
power_change()
|
||||
return
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/lapvend/blob_act()
|
||||
if (prob(50))
|
||||
spawn(0)
|
||||
del(src)
|
||||
return
|
||||
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/lapvend/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if(vendmode == 1)
|
||||
if(istype(W, /obj/item/weapon/card))
|
||||
var/obj/item/weapon/card/I = W
|
||||
scan_card(I)
|
||||
vendmode = 0
|
||||
if(vendmode == 3)
|
||||
if(istype(W,/obj/item/weapon/card))
|
||||
var/obj/item/weapon/card/I = W
|
||||
reimburse(I)
|
||||
vendmode = 0
|
||||
if(vendmode == 0)
|
||||
if(istype(W, /obj/item/device/laptop))
|
||||
var/obj/item/device/laptop/L = W
|
||||
relap = L
|
||||
calc_reimburse(L)
|
||||
usr.drop_item()
|
||||
L.loc = src
|
||||
vendmode = 3
|
||||
usr << "<span class='notice'>You slot your [L.name] into \The [src.name]</span>"
|
||||
else
|
||||
..()
|
||||
|
||||
|
||||
/obj/machinery/lapvend/attack_hand(mob/user as mob)
|
||||
user.set_machine(src)
|
||||
var/vendorname = (src.name) //import the machine's name
|
||||
var/dat = "<TT><center><b>[vendorname]</b></center><hr /><br>" //display the name, and added a horizontal rule
|
||||
if(vendmode == 0)
|
||||
dat += "<center><b>Please choose your laptop customization options</b></center><br>"
|
||||
dat += "<center>Your comptuer will automatically be loaded with any programs you can use after the transaction is complete."
|
||||
dat += "<center><b>Some programs will require additional components to be installed!</center></b><hr /><br>"
|
||||
dat += "<center><b>HDD (Required)</b> : Added</center><br>"
|
||||
dat += "<center><b>Card Reader</b> : <A href='?src=\ref[src];choice=single_add'>Single (50)</a> | <A href='?src=\ref[src];choice=dual_add'>Dual (125)</a><br>"
|
||||
dat += "<center><b>Floppy Drive</b>: <A href='?src=\ref[src];choice=floppy_add'>Add (50)</a><br>"
|
||||
dat += "<center><b>Radio Network card</b> <A href='?src=\ref[src];choice=radio_add'>Add (50)</a><br>"
|
||||
dat += "<center><b>Camera Card</b> <A href='?src=\ref[src];choice=camnet_add'>Add (100)</a><br>"
|
||||
dat += "<center><b> Network card</b> <A href='?src=\ref[src];choice=area_add'>Area (75)</a> <A href='?src=\ref[src];choice=prox_add'>Adjacent (50)</a><A href='?src=\ref[src];choice=cable_add'>Powernet (25)</a><br>"
|
||||
dat += "<hr /><center> Power source upgrade</center> <A href='?src=\ref[src];choice=high_add'>Extended (175)</a> <A href='?src=\ref[src];choice=super_add'>Unreal (250)</a>"
|
||||
|
||||
if(vendmode == 0 || vendmode == 1)
|
||||
dat += "<hr /><br><center>Cart</center><br>"
|
||||
dat += "<b>Total: [total()]</b><br>"
|
||||
if(cardreader == 1)
|
||||
dat += "<A href='?src=\ref[src];choice=single_rem'>Card Reader: (single) (50)</a><br>"
|
||||
else if (cardreader == 2)
|
||||
dat += "<A href='?src=\ref[src];choice=dual_rem'>Card Reader: (double) (125)</a><br>"
|
||||
else
|
||||
dat += "Card Reader: None<br>"
|
||||
if(floppy == 0)
|
||||
dat += "Floppy Drive: None<br>"
|
||||
else
|
||||
dat += "<A href='?src=\ref[src];choice=floppy_rem'>Floppy Drive: Added (50)</a><br>"
|
||||
if(radionet == 1)
|
||||
dat += "<A href='?src=\ref[src];choice=radio_rem'>Radio Card: Added (50)</a><br>"
|
||||
else
|
||||
dat += "Radio Card: None<br>"
|
||||
if(camera == 1)
|
||||
dat += "<A href='?src=\ref[src];choice=camnet_rem'>Camera Card: Added (100)</a><br>"
|
||||
else
|
||||
dat += "Camera Card: None<br>"
|
||||
if(network == 1)
|
||||
dat += "<A href='?src=\ref[src];choice=area_rem'>Network card: Area (75)</a><br>"
|
||||
else if(network == 2)
|
||||
dat += "<A href='?src=\ref[src];choice=prox_rem'>Network card: Adjacent (50)</a><br>"
|
||||
else if(network == 3)
|
||||
dat += "<A href='?src=\ref[src];choice=cable_rem'>Network card: Powernet (25)</a><br>"
|
||||
else
|
||||
dat += "Network card: None"
|
||||
if (power == 0)
|
||||
dat += "Power source: Regular"
|
||||
else if (power == 1)
|
||||
dat += "<A href='?src=\ref[src];choice=high_rem'>Power source: Extended (175)</a><br>"
|
||||
else
|
||||
dat += "<A href='?src=\ref[src];choice=super_rem'>Power source: Unreal (250)</a><br>"
|
||||
|
||||
if(vendmode == 0)
|
||||
dat += "<br><A href='?src=\ref[src];choice=vend'>Vend Laptop</a>"
|
||||
|
||||
if(vendmode == 1)
|
||||
dat += "Please swipe your card and enter your PIN to complete the transaction"
|
||||
|
||||
if(vendmode == 3)
|
||||
dat += "Please swipe your card and enter your PIN to be finish returning your computer<br>"
|
||||
dat += "<a href='?src=\ref[src];choice=cancel'>Cancel</a>"
|
||||
|
||||
|
||||
|
||||
|
||||
popup = new(user, "lapvend", name, 450, 500)
|
||||
popup.set_content(dat)
|
||||
popup.open()
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/lapvend/Topic(href, href_list)
|
||||
if ((usr.contents.Find(src) || (in_range(src, usr) && istype(src.loc, /turf))))
|
||||
usr.set_machine(src)
|
||||
switch(href_list["choice"])
|
||||
if("single_add")
|
||||
cardreader = 1
|
||||
if ("dual_add")
|
||||
cardreader = 2
|
||||
if ("floppy_add")
|
||||
floppy = 1
|
||||
if ("radio_add")
|
||||
radionet = 1
|
||||
if ("camnet_add")
|
||||
camera = 1
|
||||
if ("area_add")
|
||||
network = 1
|
||||
if ("prox_add")
|
||||
network = 2
|
||||
if ("cable_add")
|
||||
network = 3
|
||||
if ("high_add")
|
||||
power = 1
|
||||
if ("super_add")
|
||||
power = 2
|
||||
|
||||
if ("single_rem" || "dual_rem")
|
||||
cardreader = 0
|
||||
if ("floppy_rem")
|
||||
floppy = 0
|
||||
if ("radio_rem")
|
||||
radionet = 0
|
||||
if ("camnet_rem")
|
||||
camera = 0
|
||||
if ("area_rem" || "prox_rem" || "cable_rem")
|
||||
network = 0
|
||||
if ("high_rem" || "super_rem")
|
||||
power = 0
|
||||
|
||||
if("vend")
|
||||
vendmode = 1
|
||||
|
||||
if("cancel")
|
||||
relap.loc = src.loc
|
||||
relap = null
|
||||
vendmode = 0
|
||||
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
|
||||
/obj/machinery/lapvend/proc/vend()
|
||||
if(cardreader > 0)
|
||||
if(cardreader == 1)
|
||||
newlap.spawn_parts += (/obj/item/part/computer/cardslot)
|
||||
else
|
||||
newlap.spawn_parts += (/obj/item/part/computer/cardslot/dual)
|
||||
if(floppy == 1)
|
||||
newlap.spawn_parts += (/obj/item/part/computer/storage/removable)
|
||||
if(radionet == 1)
|
||||
newlap.spawn_parts += (/obj/item/part/computer/networking/radio)
|
||||
if(camera == 1)
|
||||
newlap.spawn_parts += (/obj/item/part/computer/networking/cameras)
|
||||
if (network == 1)
|
||||
newlap.spawn_parts += (/obj/item/part/computer/networking/area)
|
||||
if (network == 2)
|
||||
newlap.spawn_parts += (/obj/item/part/computer/networking/prox)
|
||||
if (network == 3)
|
||||
newlap.spawn_parts += (/obj/item/part/computer/networking/cable)
|
||||
if (power == 1)
|
||||
del(newlap.battery)
|
||||
newlap.battery = new /obj/item/weapon/cell/high(newlap)
|
||||
if (power == 2)
|
||||
del(newlap.battery)
|
||||
newlap.battery = new /obj/item/weapon/cell/super(newlap)
|
||||
|
||||
newlap.spawn_parts()
|
||||
|
||||
/obj/machinery/lapvend/proc/scan_card(var/obj/item/weapon/card/I)
|
||||
if (istype(I, /obj/item/weapon/card/id))
|
||||
var/obj/item/weapon/card/id/C = I
|
||||
visible_message("<span class='info'>[usr] swipes a card through [src].</span>")
|
||||
if(vendor_account)
|
||||
var/attempt_pin = input("Enter pin code", "Vendor transaction") as num
|
||||
var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2)
|
||||
if(D)
|
||||
var/transaction_amount = total()
|
||||
if(transaction_amount <= D.money)
|
||||
|
||||
//transfer the money
|
||||
D.money -= transaction_amount
|
||||
vendor_account.money += transaction_amount
|
||||
|
||||
//Transaction logs
|
||||
var/datum/transaction/T = new()
|
||||
T.target_name = "[vendor_account.owner_name] (via [src.name])"
|
||||
T.purpose = "Purchase of Laptop"
|
||||
if(transaction_amount > 0)
|
||||
T.amount = "([transaction_amount])"
|
||||
else
|
||||
T.amount = "[transaction_amount]"
|
||||
T.source_terminal = src.name
|
||||
T.date = current_date_string
|
||||
T.time = worldtime2text()
|
||||
D.transaction_log.Add(T)
|
||||
//
|
||||
T = new()
|
||||
T.target_name = D.owner_name
|
||||
T.purpose = "Purchase of Laptop"
|
||||
T.amount = "[transaction_amount]"
|
||||
T.source_terminal = src.name
|
||||
T.date = current_date_string
|
||||
T.time = worldtime2text()
|
||||
vendor_account.transaction_log.Add(T)
|
||||
|
||||
newlap = new /obj/machinery/computer3/laptop/vended(src.loc)
|
||||
|
||||
choose_progs(C)
|
||||
vend()
|
||||
popup.close()
|
||||
newlap.close_computer()
|
||||
newlap = null
|
||||
cardreader = 0
|
||||
floppy = 0
|
||||
radionet = 0
|
||||
camera = 0
|
||||
network = 0
|
||||
power = 0
|
||||
else
|
||||
usr << "\icon[src]<span class='warning'>You don't have that much money!</span>"
|
||||
else
|
||||
usr << "\icon[src]<span class='warning'>Unable to access account. Check security settings and try again.</span>"
|
||||
else
|
||||
usr << "\icon[src]<span class='warning'>Unable to access vendor account. Please record the machine ID and call CentComm Support.</span>"
|
||||
|
||||
/obj/machinery/lapvend/proc/total()
|
||||
var/total = 0
|
||||
|
||||
if(cardreader == 1)
|
||||
total += 50
|
||||
if(cardreader == 2)
|
||||
total += 125
|
||||
if(floppy == 1)
|
||||
total += 50
|
||||
if(radionet == 1)
|
||||
total += 50
|
||||
if(camera == 1)
|
||||
total += 100
|
||||
if(network == 1)
|
||||
total += 75
|
||||
if(network == 2)
|
||||
total += 50
|
||||
if(network == 3)
|
||||
total += 25
|
||||
if(power == 1)
|
||||
total += 175
|
||||
if(power == 2)
|
||||
total += 250
|
||||
|
||||
return total
|
||||
|
||||
/obj/machinery/lapvend/proc/choose_progs(var/obj/item/weapon/card/id/C)
|
||||
if(access_security in C.access)
|
||||
newlap.spawn_files += (/datum/file/program/secure_data)
|
||||
newlap.spawn_files += (/datum/file/camnet_key)
|
||||
newlap.spawn_files += (/datum/file/program/security)
|
||||
if(access_armory in C.access)
|
||||
newlap.spawn_files += (/datum/file/program/prisoner)
|
||||
if(access_atmospherics in C.access)
|
||||
newlap.spawn_files += (/datum/file/program/atmos_alert)
|
||||
if(access_change_ids in C.access)
|
||||
newlap.spawn_files += (/datum/file/program/card_comp)
|
||||
if(access_heads in C.access)
|
||||
newlap.spawn_files += (/datum/file/program/communications)
|
||||
if(access_medical in C.access)
|
||||
newlap.spawn_files += (/datum/file/program/crew)
|
||||
newlap.spawn_files += (/datum/file/program/med_data)
|
||||
if(access_engine in C.access)
|
||||
newlap.spawn_files += (/datum/file/program/powermon)
|
||||
if(access_research in C.access)
|
||||
newlap.spawn_files += (/datum/file/camnet_key/research)
|
||||
newlap.spawn_files += (/datum/file/camnet_key/bombrange)
|
||||
newlap.spawn_files += (/datum/file/camnet_key/xeno)
|
||||
if(access_rd in C.access)
|
||||
newlap.spawn_files += (/datum/file/program/borg_control)
|
||||
if(access_cent_specops in C.access)
|
||||
newlap.spawn_files += (/datum/file/camnet_key/creed)
|
||||
newlap.spawn_files += (/datum/file/program/arcade)
|
||||
newlap.spawn_files += (/datum/file/camnet_key/entertainment)
|
||||
newlap.update_spawn_files()
|
||||
|
||||
/obj/machinery/lapvend/proc/calc_reimburse(var/obj/item/device/laptop/L)
|
||||
if(istype(L.stored_computer.cardslot,/obj/item/part/computer/cardslot))
|
||||
cardreader = 1
|
||||
if(istype(L.stored_computer.cardslot,/obj/item/part/computer/cardslot/dual))
|
||||
cardreader = 2
|
||||
if(istype(L.stored_computer.floppy,/obj/item/part/computer/storage/removable))
|
||||
floppy = 1
|
||||
if(istype(L.stored_computer.radio,/obj/item/part/computer/networking/radio))
|
||||
radionet = 1
|
||||
if(istype(L.stored_computer.camnet,/obj/item/part/computer/networking/cameras))
|
||||
camera = 1
|
||||
if(istype(L.stored_computer.net,/obj/item/part/computer/networking/area))
|
||||
network = 1
|
||||
if(istype(L.stored_computer.net,/obj/item/part/computer/networking/prox))
|
||||
network = 2
|
||||
if(istype(L.stored_computer.net,/obj/item/part/computer/networking/cable))
|
||||
network = 3
|
||||
if(istype(L.stored_computer.battery, /obj/item/weapon/cell/high))
|
||||
power = 1
|
||||
if(istype(L.stored_computer.battery, /obj/item/weapon/cell/super))
|
||||
power = 2
|
||||
|
||||
|
||||
|
||||
/obj/machinery/lapvend/proc/reimburse(var/obj/item/weapon/card/I)
|
||||
if (istype(I, /obj/item/weapon/card/id))
|
||||
var/obj/item/weapon/card/id/C = I
|
||||
visible_message("<span class='info'>[usr] swipes a card through [src].</span>")
|
||||
if(vendor_account)
|
||||
var/attempt_pin = input("Enter pin code", "Vendor transaction") as num
|
||||
var/datum/money_account/D = attempt_account_access(C.associated_account_number, attempt_pin, 2)
|
||||
if(D)
|
||||
var/transaction_amount = total()
|
||||
|
||||
//transfer the money
|
||||
D.money += transaction_amount
|
||||
vendor_account.money -= transaction_amount
|
||||
|
||||
//Transaction logs
|
||||
var/datum/transaction/T = new()
|
||||
T.target_name = "[vendor_account.owner_name] (via [src.name])"
|
||||
T.purpose = "Return purchase of Laptop"
|
||||
if(transaction_amount > 0)
|
||||
T.amount = "([transaction_amount])"
|
||||
else
|
||||
T.amount = "[transaction_amount]"
|
||||
T.source_terminal = src.name
|
||||
T.date = current_date_string
|
||||
T.time = worldtime2text()
|
||||
D.transaction_log.Add(T)
|
||||
//
|
||||
T = new()
|
||||
T.target_name = D.owner_name
|
||||
T.purpose = "Return purchase of Laptop"
|
||||
T.amount = "[transaction_amount]"
|
||||
T.source_terminal = src.name
|
||||
T.date = current_date_string
|
||||
T.time = worldtime2text()
|
||||
vendor_account.transaction_log.Add(T)
|
||||
|
||||
del(relap)
|
||||
|
||||
vendmode = 0
|
||||
cardreader = 0
|
||||
floppy = 0
|
||||
radionet = 0
|
||||
camera = 0
|
||||
network = 0
|
||||
power = 0
|
||||
|
||||
else
|
||||
usr << "\icon[src]<span class='warning'>Unable to access account. Check security settings and try again.</span>"
|
||||
else
|
||||
usr << "\icon[src]<span class='warning'>Unable to access vendor account. Please record the machine ID and call CentComm Support.</span>"
|
||||
@@ -0,0 +1,236 @@
|
||||
/obj/item/part/computer/networking
|
||||
name = "Computer networking component"
|
||||
|
||||
/*
|
||||
This is the public-facing proc used by NETUP.
|
||||
It does additional checking before and after calling get_machines()
|
||||
|
||||
*/
|
||||
proc/connect_to(var/typekey,var/atom/previous)
|
||||
if(!computer || computer.stat)
|
||||
return null
|
||||
|
||||
if(istype(previous,typekey) && verify_machine(previous))
|
||||
return previous
|
||||
|
||||
var/result = get_machines(typekey)
|
||||
|
||||
if(!result)
|
||||
return null
|
||||
|
||||
if(islist(result))
|
||||
var/list/R = result
|
||||
if(R.len == 0)
|
||||
return null
|
||||
else if(R.len == 1)
|
||||
return R[1]
|
||||
else
|
||||
var/list/atomlist = computer.format_atomlist(R)
|
||||
result = input("Select:","Multiple destination machines located",atomlist[1]) as null|anything in atomlist
|
||||
return atomlist[result]
|
||||
|
||||
if(isobj(result))
|
||||
return result
|
||||
|
||||
return null // ?
|
||||
|
||||
/*
|
||||
This one is used to determine the candidate machines.
|
||||
It may return an object, a list of objects, or null.
|
||||
|
||||
Overwite this on any networking component.
|
||||
*/
|
||||
proc/get_machines(var/typekey)
|
||||
return list()
|
||||
|
||||
/*
|
||||
This is used to verify that an existing machine is within the network.
|
||||
Calling NETUP() with an object argument will run this check, and if
|
||||
the object is still accessible, it will be used. Otherwise, another
|
||||
search will be run.
|
||||
|
||||
Overwrite this on any networking component.
|
||||
*/
|
||||
proc/verify_machine(var/obj/previous)
|
||||
return 0
|
||||
|
||||
/*
|
||||
Provides radio/signaler functionality, and also
|
||||
network-connects to anything on the same z-level
|
||||
which is tuned to the same frequency.
|
||||
*/
|
||||
/obj/item/part/computer/networking/radio
|
||||
name = "Wireless networking component"
|
||||
desc = "Radio module for computers"
|
||||
|
||||
var/datum/radio_frequency/radio_connection = null
|
||||
var/frequency = 1459
|
||||
var/filter = null
|
||||
var/range = null
|
||||
var/subspace = 0
|
||||
|
||||
init()
|
||||
..()
|
||||
spawn(5)
|
||||
radio_connection = radio_controller.add_object(src, src.frequency, src.filter)
|
||||
|
||||
proc/set_frequency(new_frequency)
|
||||
if(radio_controller)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = radio_controller.add_object(src, frequency, filter)
|
||||
else
|
||||
frequency = new_frequency
|
||||
spawn(rand(5,10))
|
||||
set_frequency(new_frequency)
|
||||
|
||||
receive_signal(var/datum/signal/signal)
|
||||
if(!signal || !computer || (computer.stat&~MAINT)) // closed laptops use maint, allow it
|
||||
return
|
||||
if(computer.program)
|
||||
computer.program.receive_signal(signal)
|
||||
|
||||
proc/post_signal(var/datum/signal/signal)
|
||||
if(!computer || (computer.stat&~MAINT) || !computer.program) return
|
||||
if(!radio_connection) return
|
||||
|
||||
radio_connection.post_signal(src,signal,filter,range)
|
||||
|
||||
get_machines(var/typekey)
|
||||
if(!radio_connection || !radio_connection.frequency)
|
||||
return list()
|
||||
var/list/result = list()
|
||||
var/turf/T = get_turf(loc)
|
||||
var/z_level = T.z
|
||||
for(var/obj/O in radio_connection.devices)
|
||||
if(istype(O,typekey))
|
||||
T = get_turf(O)
|
||||
if(istype(O) && (subspace || (O.z == z_level))) // radio does not work across z-levels
|
||||
result |= O
|
||||
return result
|
||||
|
||||
verify_machine(var/obj/previous)
|
||||
if(!previous) return 0
|
||||
if(subspace)
|
||||
return ( radio_connection && (previous in radio_connection.devices) )
|
||||
else
|
||||
var/turf/T = get_turf(loc)
|
||||
var/turf/O = get_turf(previous)
|
||||
if(!T || !O)
|
||||
return 0
|
||||
return ( radio_connection && (previous in radio_connection.devices) && (T.z == O.z))
|
||||
|
||||
/*
|
||||
Subspace networking: Communicates off-station. Allows centcom communications.
|
||||
*/
|
||||
/obj/item/part/computer/networking/radio/subspace
|
||||
name = "subspace networking terminal"
|
||||
desc = "Communicates long distances and through spatial anomalies."
|
||||
subspace = 1
|
||||
|
||||
/*
|
||||
APC (/area) networking
|
||||
*/
|
||||
|
||||
/obj/item/part/computer/networking/area
|
||||
name = "short-wave networking terminal"
|
||||
desc = "Connects to nearby computers through the area power network"
|
||||
|
||||
get_machines(var/typekey)
|
||||
var/area/A = get_area(loc)
|
||||
if(!istype(A) || A == /area)
|
||||
return list()
|
||||
if(typekey == null)
|
||||
typekey = /obj/machinery
|
||||
var/list/machines = list()
|
||||
for(var/area/area in A.related)
|
||||
for(var/obj/O in area.contents)
|
||||
if(istype(O,typekey))
|
||||
machines |= O
|
||||
return machines
|
||||
verify_machine(var/obj/previous)
|
||||
if(!previous) return 0
|
||||
var/area/A = get_area(src)
|
||||
if( A && A == get_area(previous) )
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/*
|
||||
Proximity networking: Connects to machines or computers adjacent to this device
|
||||
*/
|
||||
/obj/item/part/computer/networking/prox
|
||||
name = "proximity networking terminal"
|
||||
desc = "Connects a computer to adjacent machines"
|
||||
|
||||
get_machines(var/typekey)
|
||||
var/turf/T = get_turf(loc)
|
||||
if(!istype(T))
|
||||
return list()
|
||||
if(typekey == null)
|
||||
typekey = /obj/machinery
|
||||
var/list/machines = list()
|
||||
for(var/d in cardinal)
|
||||
var/turf/T2 = get_step(T,d)
|
||||
for(var/obj/O in T2)
|
||||
if(istype(O,typekey))
|
||||
machines += O
|
||||
return machines
|
||||
|
||||
verify_machine(var/obj/previous)
|
||||
if(!previous)
|
||||
return 0
|
||||
if(get_dist(get_turf(previous),get_turf(loc)) == 1)
|
||||
return 1
|
||||
return 0
|
||||
/*
|
||||
Cable networking: Not currently used
|
||||
*/
|
||||
|
||||
/obj/item/part/computer/networking/cable
|
||||
name = "cable networking terminal"
|
||||
desc = "Connects to other machines on the same cable network."
|
||||
|
||||
get_machines(var/typekey)
|
||||
// if(istype(computer,/obj/machinery/computer/laptop)) // laptops move, this could get breaky
|
||||
// return list()
|
||||
var/turf/T = get_turf(loc)
|
||||
var/datum/powernet/P = null
|
||||
for(var/obj/structure/cable/C in T)
|
||||
if(C.d1 == 0)
|
||||
P = C.powernet
|
||||
break
|
||||
if(!P)
|
||||
return list()
|
||||
if(!typekey)
|
||||
typekey = /obj/machinery
|
||||
else if(typekey == /datum/powernet)
|
||||
return list(P)
|
||||
var/list/candidates = list()
|
||||
for(var/atom/A in P.nodes)
|
||||
if(istype(A,typekey))
|
||||
candidates += A
|
||||
else if(istype(A,/obj/machinery/power/terminal))
|
||||
var/obj/machinery/power/terminal/PT = A
|
||||
if(istype(PT.master,typekey))
|
||||
candidates += PT.master
|
||||
return candidates
|
||||
|
||||
verify_machine(var/obj/previous)
|
||||
if(!previous)
|
||||
return 0
|
||||
var/turf/T = get_turf(loc)
|
||||
var/datum/powernet/P = null
|
||||
for(var/obj/structure/cable/C in T)
|
||||
if(C.d1 == 0)
|
||||
P = C.powernet
|
||||
break
|
||||
if(istype(previous,/datum/powernet))
|
||||
if(previous == P)
|
||||
return 1
|
||||
return 0
|
||||
T = get_turf(previous.loc)
|
||||
for(var/obj/structure/cable/C in T)
|
||||
if(C.d1 == 0 && (C.powernet == P))
|
||||
return 1
|
||||
return 0
|
||||
|
||||
@@ -0,0 +1,404 @@
|
||||
|
||||
/*
|
||||
Programs are a file that can be executed
|
||||
*/
|
||||
|
||||
/datum/file/program
|
||||
name = "Untitled"
|
||||
extension = "prog"
|
||||
image = 'icons/ntos/program.png'
|
||||
var/desc = "An unidentifiable program."
|
||||
|
||||
var/image/overlay = null // Icon to be put on top of the computer frame.
|
||||
|
||||
var/active_state = "generic" // the icon_state that the computer goes to when the program is active
|
||||
|
||||
drm = 0 // prevents a program from being copied
|
||||
var/refresh = 0 // if true, computer does screen updates during process().
|
||||
var/error = 0 // set by background programs so an error pops up when used
|
||||
|
||||
var/human_controls = 0 // if true, non-human animals cannot interact with this program (monkeys, xenos, etc)
|
||||
var/ai_allowed = 1 // if true, silicon mobs (AI/cyborg) are allowed to use this program.
|
||||
|
||||
var/datum/browser/popup = null
|
||||
|
||||
// ID access: Note that computer3 does not normally check your ID.
|
||||
// By default this is only really used for inserted cards.
|
||||
var/list/req_access = list() // requires all of these UNLESS below succeeds
|
||||
var/list/req_one_access = list() // requires one of these
|
||||
|
||||
|
||||
/datum/file/program/New()
|
||||
..()
|
||||
if(!active_state)
|
||||
active_state = "generic"
|
||||
overlay = image('icons/obj/computer3.dmi',icon_state = active_state)
|
||||
|
||||
|
||||
/datum/file/program/proc/decode(text)
|
||||
//adds line breaks
|
||||
text = replacetext(text, "\n","<BR>")
|
||||
return text
|
||||
|
||||
|
||||
|
||||
/datum/file/program/execute(var/datum/file/source)
|
||||
if(computer && !computer.stat)
|
||||
computer.program = src
|
||||
computer.req_access = req_access
|
||||
computer.req_one_access = req_one_access
|
||||
update_icon()
|
||||
computer.update_icon()
|
||||
if(usr)
|
||||
usr << browse(null, "window=\ref[computer]")
|
||||
computer.attack_hand(usr)
|
||||
|
||||
..()
|
||||
|
||||
/*
|
||||
Standard Topic() for links
|
||||
*/
|
||||
|
||||
/datum/file/program/Topic(href, href_list)
|
||||
return
|
||||
|
||||
/*
|
||||
The computer object will transfer all empty-hand calls to the program (this includes AIs, Cyborgs, and Monkies)
|
||||
*/
|
||||
/datum/file/program/proc/interact()
|
||||
return
|
||||
|
||||
/*
|
||||
Standard receive_signal()
|
||||
*/
|
||||
|
||||
/datum/file/program/proc/receive_signal(var/datum/signal/signal)
|
||||
return
|
||||
/*
|
||||
The computer object will transfer all attackby() calls to the program
|
||||
If the item is a valid interactable object, return 1. Else, return 0.
|
||||
This helps identify what to use to actually hit the computer with, and
|
||||
what can be used to interact with it.
|
||||
|
||||
Screwdrivers will, by default, never call program/attackby(). That's used
|
||||
for deconstruction instead.
|
||||
*/
|
||||
|
||||
|
||||
/datum/file/program/proc/attackby(O as obj, user as mob)
|
||||
return
|
||||
|
||||
/*
|
||||
Try not to overwrite this proc, I'd prefer we stayed
|
||||
with interact() as the main proc
|
||||
*/
|
||||
/datum/file/program/proc/attack_hand(mob/user as mob)
|
||||
usr = user
|
||||
interact()
|
||||
|
||||
/*
|
||||
Called when the computer is rebooted or the program exits/restarts.
|
||||
Be sure not to save any work. Do NOT start the program again.
|
||||
If it is the os, the computer will run it again automatically.
|
||||
|
||||
Also, we are deleting the browser window on the chance that this is happening
|
||||
when the computer is damaged or disassembled, causing us to lose our computer.
|
||||
The popup window's title is a reference to the computer, making it unique, so
|
||||
it could introduce bugs in that case.
|
||||
*/
|
||||
/datum/file/program/proc/Reset()
|
||||
error = 0
|
||||
update_icon()
|
||||
if(popup)
|
||||
popup.close()
|
||||
del popup
|
||||
return
|
||||
|
||||
/*
|
||||
The computer object will transfer process() calls to the program.
|
||||
*/
|
||||
/datum/file/program/proc/process()
|
||||
if(refresh && computer && !computer.stat)
|
||||
computer.updateDialog()
|
||||
update_icon()
|
||||
|
||||
/datum/file/program/proc/update_icon()
|
||||
return
|
||||
|
||||
/datum/file/program/proc/check_access(obj/item/I)
|
||||
if( (!istype(req_access) || !req_access.len) && (!istype(req_one_access) || !req_one_access.len) ) //no requirements
|
||||
return 1
|
||||
|
||||
if(!I)
|
||||
return 0
|
||||
|
||||
var/list/iAccess = I.GetAccess()
|
||||
if(!iAccess || !iAccess.len)
|
||||
return 0
|
||||
|
||||
var/list/temp = req_one_access & iAccess
|
||||
if(temp.len) // a required access in item access list
|
||||
return 1
|
||||
temp = req_access - iAccess
|
||||
if(temp.len) // a required access not in item access list
|
||||
return 0
|
||||
return 1
|
||||
|
||||
|
||||
/*
|
||||
Because this does sanity checks I have added the code to make a popup here.
|
||||
It also does sanity checks there that should prevent some edge case madness.
|
||||
*/
|
||||
/datum/file/program/proc/interactable(var/mob/user = usr)
|
||||
if(computer && computer.interactable(user))
|
||||
if(!popup)
|
||||
popup = new(user, "\ref[computer]", name, nref=src)
|
||||
popup.set_title_image(usr.browse_rsc_icon(overlay.icon, overlay.icon_state))
|
||||
popup.set_title_buttons(topic_link(src,"quit","<img src=\ref['icons/ntos/tb_close.png']>"))
|
||||
if(popup.user != user)
|
||||
popup.user = user
|
||||
popup.set_title_image(usr.browse_rsc_icon(overlay.icon, overlay.icon_state))
|
||||
popup.set_title(name)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
/datum/file/program/proc/fake_link(var/text)
|
||||
return "<span class='linkOff'>[text]</span>"
|
||||
|
||||
/*
|
||||
Meant for text (not icons) -
|
||||
lists all installed drives and their files
|
||||
|
||||
I am NOT adding a computer sanity check here,
|
||||
because why the flying fuck would you get to this
|
||||
proc before having run it at least once?
|
||||
If you cause runtimes with this function
|
||||
may the shame of all ages come upon you.
|
||||
*/
|
||||
/datum/file/program/proc/list_all_files_by_drive(var/typekey,var/linkop = "runfile")
|
||||
var/dat = ""
|
||||
if(!typekey) typekey = /datum/file
|
||||
if(computer.hdd)
|
||||
dat += "<h3>[computer.hdd]</h3>"
|
||||
for(var/datum/file/F in computer.hdd.files)
|
||||
if(istype(F,typekey))
|
||||
dat += topic_link(src,"[linkop]=\ref[F]",F.name) + "<br>"
|
||||
if(computer.hdd.files.len == 0)
|
||||
dat += "<i>No files</i><br>"
|
||||
dat += "<br>"
|
||||
|
||||
if(computer.floppy)
|
||||
if(!computer.floppy.inserted)
|
||||
dat += "<h3>[computer.floppy] - <span class='linkOff'>Eject</span></h3><br><br>"
|
||||
else
|
||||
dat += "<h3>[computer.floppy] - [topic_link(src,"eject_disk","Eject")]</h3>"
|
||||
for(var/datum/file/F in computer.floppy.inserted.files)
|
||||
dat += topic_link(src,"[linkop]=\ref[F]",F.name) + "<br>"
|
||||
if(computer.floppy.inserted.files.len == 0)
|
||||
dat += "<i>No files</i><br>"
|
||||
dat += "<br>"
|
||||
|
||||
if(computer.cardslot && istype(computer.cardslot.reader,/obj/item/weapon/card/data))
|
||||
dat += "<h3>[computer.cardslot.reader] - [topic_link(src,"eject_card=reader","Eject")]</h3>"
|
||||
var/obj/item/weapon/card/data/D = computer.cardslot.reader
|
||||
for(var/datum/file/F in D.files)
|
||||
dat += topic_link(src,"[linkop]=\ref[F]",F.name) + "<br>"
|
||||
if(D.files.len == 0)
|
||||
dat += "<i>No files</i><br>"
|
||||
return dat
|
||||
|
||||
// You don't NEED to use this version of topic() for this, you can do it yourself if you prefer
|
||||
// If you do, do the interactable() check first, please, I don't want to repeat it here. It's not hard.
|
||||
/datum/file/program/Topic(var/href,var/list/href_list)
|
||||
if(!computer)
|
||||
return 0
|
||||
|
||||
//
|
||||
// usage: eject_disk
|
||||
// only functions if there is a removable drive
|
||||
//
|
||||
if("eject_disk" in href_list)
|
||||
if(computer.floppy)
|
||||
computer.floppy.eject_disk()
|
||||
return 1
|
||||
//
|
||||
// usage: eject_card | eject_card=reader | eject_card=writer
|
||||
// only functions if there is a cardslot
|
||||
//
|
||||
if("eject_card" in href_list)
|
||||
if(computer.cardslot)
|
||||
if(computer.cardslot.dualslot && href_list["eject_card"] == "writer")
|
||||
computer.cardslot.remove(computer.cardslot.writer)
|
||||
else
|
||||
computer.cardslot.remove(computer.cardslot.reader)
|
||||
return 1
|
||||
//
|
||||
// usage: runfile=\ref[file]
|
||||
// executes the file
|
||||
//
|
||||
if("runfile" in href_list)
|
||||
var/datum/file/F = locate(href_list["runfile"])
|
||||
if(F && F.computer == computer)
|
||||
F.execute(src)
|
||||
return 1
|
||||
|
||||
if("close" in href_list)
|
||||
usr.unset_machine()
|
||||
popup.close()
|
||||
return 1
|
||||
//
|
||||
// usage: quit
|
||||
// unloads the program, returning control to the OS
|
||||
//
|
||||
if("quit" in href_list)
|
||||
computer.program = null
|
||||
usr << browse(null,"window=\ref[computer]") // ntos will need to resize the window
|
||||
computer.update_icon()
|
||||
computer.updateDialog()
|
||||
return 1
|
||||
return 0
|
||||
|
||||
|
||||
/datum/file/program/RD
|
||||
name = "R&D Manager"
|
||||
image = 'icons/ntos/research.png'
|
||||
desc = "A software suit for generic research and development machinery interaction. Comes pre-packaged with extensive cryptographic databanks for secure connections with external devices."
|
||||
active_state = "rdcomp"
|
||||
volume = 11000
|
||||
|
||||
/datum/file/program/RDserv
|
||||
name = "R&D Server"
|
||||
image = 'icons/ntos/server.png'
|
||||
active_state = "rdcomp"
|
||||
volume = 9000
|
||||
|
||||
/datum/file/program/SuitSensors
|
||||
name = "Crew Monitoring"
|
||||
image = 'icons/ntos/monitoring.png'
|
||||
active_state = "crew"
|
||||
volume = 3400
|
||||
|
||||
/datum/file/program/Genetics
|
||||
name = "Genetics Suite"
|
||||
image = 'icons/ntos/genetics.png'
|
||||
desc = "A sophisticated software suite containing read-only genetics hardware specifications and a highly compressed genome databank."
|
||||
active_state = "dna"
|
||||
volume = 8000
|
||||
|
||||
/datum/file/program/Cloning
|
||||
name = "Cloning Platform"
|
||||
image = 'icons/ntos/cloning.png'
|
||||
desc = "A software platform for accessing external cloning apparatus."
|
||||
active_state = "dna"
|
||||
volume = 7000
|
||||
|
||||
/datum/file/program/TCOMmonitor
|
||||
name = "TComm Monitor"
|
||||
image = 'icons/ntos/tcomms.png'
|
||||
active_state = "comm_monitor"
|
||||
volume = 5500
|
||||
|
||||
/datum/file/program/TCOMlogs
|
||||
name = "TComm Log View"
|
||||
image = 'icons/ntos/tcomms.png'
|
||||
active_state = "comm_logs"
|
||||
volume = 5230
|
||||
|
||||
/datum/file/program/TCOMtraffic
|
||||
name = "TComm Traffic"
|
||||
image = 'icons/ntos/tcomms.png'
|
||||
active_state = "generic"
|
||||
volume = 8080
|
||||
|
||||
/datum/file/program/securitycam
|
||||
name = "Sec-Cam Viewport"
|
||||
image = 'icons/ntos/camera.png'
|
||||
drm = 1
|
||||
active_state = "cameras"
|
||||
volume = 2190
|
||||
|
||||
/datum/file/program/securityrecords
|
||||
name = "Security Records"
|
||||
image = 'icons/ntos/records.png'
|
||||
drm = 1
|
||||
active_state = "security"
|
||||
volume = 2520
|
||||
|
||||
/datum/file/program/medicalrecords
|
||||
name = "Medical Records"
|
||||
image = 'icons/ntos/medical.png'
|
||||
drm = 1
|
||||
active_state = "medcomp"
|
||||
volume = 5000
|
||||
|
||||
/datum/file/program/SMSmonitor
|
||||
name = "Messaging Monitor"
|
||||
image = 'icons/ntos/pda.png'
|
||||
active_state = "comm_monitor"
|
||||
volume = 3070
|
||||
|
||||
/datum/file/program/OperationMonitor
|
||||
name = "OR Monitor"
|
||||
image = 'icons/ntos/operating.png'
|
||||
active_state = "operating"
|
||||
volume = 4750
|
||||
|
||||
/datum/file/program/PodLaunch
|
||||
name = "Pod Launch"
|
||||
active_state = "computer_generic"
|
||||
volume = 520
|
||||
|
||||
/datum/file/program/powermon
|
||||
name = "Power Grid"
|
||||
image = 'icons/ntos/power.png'
|
||||
active_state = "power"
|
||||
volume = 7200
|
||||
|
||||
/datum/file/program/prisoner
|
||||
name = "Prisoner Control"
|
||||
image = 'icons/ntos/prison.png'
|
||||
drm = 1
|
||||
active_state = "power"
|
||||
volume = 5000
|
||||
|
||||
/datum/file/program/borg_control
|
||||
name = "Cyborg Maint"
|
||||
image = 'icons/ntos/borgcontrol.png'
|
||||
active_state = "robot"
|
||||
volume = 9050
|
||||
|
||||
/datum/file/program/AIupload
|
||||
name = "AI Upload"
|
||||
image = 'icons/ntos/aiupload.png'
|
||||
active_state = "command"
|
||||
volume = 5000
|
||||
|
||||
/datum/file/program/Cyborgupload
|
||||
name = "Cyborg Upload"
|
||||
image = 'icons/ntos/borgupload.png'
|
||||
active_state = "command"
|
||||
volume = 5000
|
||||
|
||||
/datum/file/program/Exosuit
|
||||
name = "Exosuit Monitor"
|
||||
image = 'icons/ntos/exocontrol.png'
|
||||
active_state = "mecha"
|
||||
volume = 7000
|
||||
|
||||
/datum/file/program/EmergencyShuttle
|
||||
name = "Shuttle Console"
|
||||
active_state = "shuttle"
|
||||
volume = 10000
|
||||
|
||||
/datum/file/program/Stationalert
|
||||
name = "Alert Monitor"
|
||||
image = 'icons/ntos/alerts.png'
|
||||
active_state = "computer_generic"
|
||||
volume = 10150
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,44 @@
|
||||
|
||||
|
||||
/obj/item/weapon/disk/file/arcade
|
||||
name = "Arcade game grab pack"
|
||||
desc = "A program install disk."
|
||||
icon = 'icons/obj/stock_parts.dmi'
|
||||
icon_state = "datadisk_arcade"
|
||||
spawn_files = list(/datum/file/program/arcade,/datum/file/program/arcade,/datum/file/program/arcade,/datum/file/program/arcade)
|
||||
|
||||
/*/obj/item/weapon/disk/file/aifixer
|
||||
name = "AI System Integrity Restorer"
|
||||
desc = "A program install disk."
|
||||
icon = 'icons/obj/stock_parts.dmi'
|
||||
icon_state = "datadisk_arcade"
|
||||
spawn_files = list(/datum/file/program/aifixer)*/
|
||||
|
||||
/obj/item/weapon/disk/file/atmos_alert
|
||||
name = "Atmospheric Alert Notifier"
|
||||
desc = "A program install disk."
|
||||
icon = 'icons/obj/stock_parts.dmi'
|
||||
icon_state = "datadisk_arcade"
|
||||
spawn_files = list(/datum/file/program/atmos_alert)
|
||||
|
||||
/obj/item/weapon/disk/file/cameras
|
||||
name = "Camera Viewer"
|
||||
desc = "A program install disk."
|
||||
icon = 'icons/obj/stock_parts.dmi'
|
||||
icon_state = "datadisk_arcade"
|
||||
spawn_files = list(/datum/file/program/security)
|
||||
|
||||
/obj/item/weapon/disk/file/card
|
||||
name = "ID Card Modifier"
|
||||
desc = "A program install disk."
|
||||
icon = 'icons/obj/stock_parts.dmi'
|
||||
icon_state = "datadisk_arcade"
|
||||
spawn_files = list(/datum/file/program/card_comp)
|
||||
/*
|
||||
/obj/item/weapon/disk/file/genetics
|
||||
name = "Genetics & Cloning"
|
||||
desc = "A program install disk."
|
||||
icon = 'icons/obj/stock_parts.dmi'
|
||||
icon_state = "datadisk_arcade"
|
||||
spawn_files = list(/datum/file/program/cloning,/datum/file/program/dnascanner)
|
||||
*/
|
||||
@@ -0,0 +1,32 @@
|
||||
/*
|
||||
Todo:
|
||||
I can probably get away with a global list on servers that contains database sort of stuff
|
||||
(replacing the datacore probably)
|
||||
with the justification that they loadbalance and duplicate data across each other. As long as
|
||||
one server-type computer exists, the station will still have access to datacore-type info.
|
||||
|
||||
I can doubtless use this for station alerts as well, which is good, because I was sort of
|
||||
wondering how the hell I was going to port that.
|
||||
|
||||
Also todo: Server computers should maybe generate heat the way the R&D server does?
|
||||
At least the rack computer probably should.
|
||||
*/
|
||||
|
||||
/obj/machinery/computer3/server
|
||||
name = "server"
|
||||
icon = 'icons/obj/computer3.dmi'
|
||||
icon_state = "serverframe"
|
||||
show_keyboard = 0
|
||||
|
||||
/obj/machinery/computer3/server/rack
|
||||
name = "server rack"
|
||||
icon_state = "rackframe"
|
||||
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd,/obj/item/part/computer/networking/radio/subspace)
|
||||
|
||||
update_icon()
|
||||
//overlays.Cut()
|
||||
return
|
||||
|
||||
attack_hand() // Racks have no screen, only AI can use them
|
||||
return
|
||||
@@ -0,0 +1,184 @@
|
||||
/*
|
||||
Computer devices that can store programs, files, etc.
|
||||
*/
|
||||
|
||||
/obj/item/part/computer/storage
|
||||
name = "Storage Device"
|
||||
desc = "A device used for storing and retrieving digital information."
|
||||
|
||||
// storage capacity, kb
|
||||
var/volume = 0
|
||||
var/max_volume = 64 // should be enough for anyone
|
||||
|
||||
var/driveletter = null // drive letter according to the computer
|
||||
|
||||
var/list/files = list() // a list of files in the memory (ALL files)
|
||||
var/removeable = 0 // determinse if the storage device is a removable hard drive (ie floppy)
|
||||
|
||||
|
||||
var/writeprotect = 0 // determines if the drive forbids writing.
|
||||
// note that write-protect is hardware and does not respect emagging.
|
||||
|
||||
var/list/spawnfiles = list()// For mappers, special drives, and data disks
|
||||
|
||||
New()
|
||||
..()
|
||||
if(islist(spawnfiles))
|
||||
if(removeable && spawnfiles.len)
|
||||
var/obj/item/part/computer/storage/removable/R = src
|
||||
R.inserted = new(src)
|
||||
if(writeprotect)
|
||||
R.inserted.writeprotect = 1
|
||||
for(var/typekey in spawnfiles)
|
||||
addfile(new typekey(),1)
|
||||
|
||||
// Add a file to the hard drive, returns 0 if failed
|
||||
// forced is used when spawning files on a write-protect drive
|
||||
proc/addfile(var/datum/file/F,var/forced = 0)
|
||||
if(!F || crit_fail || (F in files))
|
||||
return 1
|
||||
if(writeprotect && !forced)
|
||||
return 0
|
||||
if(volume + F.volume > max_volume)
|
||||
if(!forced)
|
||||
return 0
|
||||
max_volume = volume + F.volume
|
||||
|
||||
files.Add(F)
|
||||
volume += F.volume
|
||||
F.computer = computer
|
||||
F.device = src
|
||||
return 1
|
||||
proc/removefile(var/datum/file/F,var/forced = 0)
|
||||
if(!F || !(F in files))
|
||||
return 1
|
||||
if(writeprotect && !forced)
|
||||
return 0
|
||||
|
||||
files -= F
|
||||
volume -= F.volume
|
||||
if(F.device == src)
|
||||
F.device = null
|
||||
F.computer = null
|
||||
return 1
|
||||
|
||||
init(var/obj/machinery/computer/target)
|
||||
computer = target
|
||||
for(var/datum/file/F in files)
|
||||
F.computer = computer
|
||||
|
||||
/*
|
||||
Standard hard drives for computers. Used in computer construction
|
||||
*/
|
||||
|
||||
/obj/item/part/computer/storage/hdd
|
||||
name = "Hard Drive"
|
||||
max_volume = 25000
|
||||
icon_state = "hdd1"
|
||||
|
||||
|
||||
/obj/item/part/computer/storage/hdd/big
|
||||
name = "Big Hard Drive"
|
||||
max_volume = 50000
|
||||
icon_state = "hdd2"
|
||||
|
||||
/obj/item/part/computer/storage/hdd/gigantic
|
||||
name = "Gigantic Hard Drive"
|
||||
max_volume = 75000
|
||||
icon_state = "hdd3"
|
||||
|
||||
/*
|
||||
Removeable hard drives for portable storage
|
||||
*/
|
||||
|
||||
/obj/item/part/computer/storage/removable
|
||||
name = "Disk Drive"
|
||||
max_volume = 3000
|
||||
removeable = 1
|
||||
|
||||
attackby_types = list(/obj/item/weapon/disk/file, /obj/item/weapon/pen)
|
||||
var/obj/item/weapon/disk/file/inserted = null
|
||||
|
||||
proc/eject_disk(var/forced = 0)
|
||||
if(!forced)
|
||||
return
|
||||
files = list()
|
||||
inserted.loc = computer.loc
|
||||
if(usr)
|
||||
if(!usr.get_active_hand())
|
||||
usr.put_in_active_hand(inserted)
|
||||
else if(forced && !usr.get_inactive_hand())
|
||||
usr.put_in_inactive_hand(inserted)
|
||||
for(var/datum/file/F in inserted.files)
|
||||
F.computer = null
|
||||
inserted = null
|
||||
|
||||
|
||||
attackby(obj/O as obj, mob/user as mob)
|
||||
if(inserted && istype(O,/obj/item/weapon/pen))
|
||||
usr << "You use [O] to carefully pry [inserted] out of [src]."
|
||||
eject_disk(forced = 1)
|
||||
return
|
||||
|
||||
if(istype(O,/obj/item/weapon/disk/file))
|
||||
if(inserted)
|
||||
usr << "There's already a disk in [src]!"
|
||||
return
|
||||
|
||||
usr << "You insert [O] into [src]."
|
||||
usr.drop_item()
|
||||
O.loc = src
|
||||
inserted = O
|
||||
writeprotect = inserted.writeprotect
|
||||
|
||||
files = inserted.files
|
||||
for(var/datum/file/F in inserted.files)
|
||||
F.computer = computer
|
||||
|
||||
return
|
||||
|
||||
..()
|
||||
|
||||
addfile(var/datum/file/F)
|
||||
if(!F || !inserted)
|
||||
return 0
|
||||
|
||||
if(F in inserted.files)
|
||||
return 1
|
||||
|
||||
if(inserted.volume + F.volume > inserted.max_volume)
|
||||
return 0
|
||||
|
||||
inserted.files.Add(F)
|
||||
F.computer = computer
|
||||
F.device = inserted
|
||||
return 1
|
||||
|
||||
/*
|
||||
Removable hard drive presents...
|
||||
removeable disk!
|
||||
*/
|
||||
|
||||
/obj/item/weapon/disk/file
|
||||
//parent_type = /obj/item/part/computer/storage // todon't: do this
|
||||
name = "Data Disk"
|
||||
desc = "A device that can be inserted and removed into computers easily as a form of portable data storage. This one stores 1 Megabyte"
|
||||
var/list/files
|
||||
var/list/spawn_files = list()
|
||||
var/writeprotect = 0
|
||||
var/volume = 0
|
||||
var/max_volume = 1028
|
||||
|
||||
|
||||
New()
|
||||
..()
|
||||
icon_state = "datadisk[rand(0,6)]"
|
||||
src.pixel_x = rand(-5, 5)
|
||||
src.pixel_y = rand(-5, 5)
|
||||
files = list()
|
||||
if(istype(spawn_files))
|
||||
for(var/typekey in spawn_files)
|
||||
var/datum/file/F = new typekey()
|
||||
F.device = src
|
||||
files += F
|
||||
volume += F.volume
|
||||
@@ -0,0 +1,86 @@
|
||||
|
||||
/obj/machinery/computer3/testing
|
||||
spawn_files = list(/datum/file/program/aifixer,/datum/file/program/arcade,/datum/file/program/atmos_alert,
|
||||
/datum/file/program/security,/datum/file/program/card_comp,
|
||||
/datum/file/program/borg_control,/datum/file/program/holodeck, /datum/file/program/communications,
|
||||
/datum/file/program/crew,/datum/file/program/op_monitor, /datum/file/program/powermon,
|
||||
|
||||
/datum/file/camnet_key,/datum/file/camnet_key/mining,/datum/file/camnet_key/entertainment,/datum/file/camnet_key/research,
|
||||
/datum/file/camnet_key/bombrange,/datum/file/camnet_key/xeno,/datum/file/camnet_key/singulo,/datum/file/camnet_key/prison)
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd/big,/obj/item/part/computer/storage/removable,/obj/item/part/computer/ai_holder,
|
||||
/obj/item/part/computer/networking/radio/subspace,/obj/item/part/computer/networking/cameras,
|
||||
/obj/item/part/computer/cardslot/dual,/obj/item/part/computer/networking/area)
|
||||
New(var/L,var/built=0)
|
||||
if(!built && !battery)
|
||||
battery = new /obj/item/weapon/cell(src)
|
||||
..(L,built)
|
||||
|
||||
/obj/machinery/computer3/laptop/testing
|
||||
spawn_files = list(/datum/file/program/aifixer,/datum/file/program/arcade,/datum/file/program/atmos_alert,
|
||||
/datum/file/program/security,/datum/file/program/card_comp,
|
||||
/datum/file/program/borg_control,/datum/file/program/holodeck, /datum/file/program/communications,
|
||||
/datum/file/program/crew,/datum/file/program/op_monitor, /datum/file/program/powermon,
|
||||
|
||||
/datum/file/camnet_key,/datum/file/camnet_key/mining,/datum/file/camnet_key/entertainment,/datum/file/camnet_key/research,
|
||||
/datum/file/camnet_key/bombrange,/datum/file/camnet_key/xeno,/datum/file/camnet_key/singulo,/datum/file/camnet_key/prison)
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd/big,/obj/item/part/computer/storage/removable,/obj/item/part/computer/ai_holder,
|
||||
/obj/item/part/computer/networking/radio/subspace,/obj/item/part/computer/networking/cameras,
|
||||
/obj/item/part/computer/cardslot/dual,/obj/item/part/computer/networking/area)
|
||||
New(var/L,var/built=0)
|
||||
if(!built && !battery)
|
||||
battery = new /obj/item/weapon/cell/super(src)
|
||||
..(L,built)
|
||||
|
||||
/obj/machinery/computer3/wall_comp/testing
|
||||
spawn_files = list(/datum/file/program/aifixer,/datum/file/program/arcade,/datum/file/program/atmos_alert,
|
||||
/datum/file/program/security,/datum/file/program/card_comp,
|
||||
/datum/file/program/borg_control,/datum/file/program/holodeck, /datum/file/program/communications,
|
||||
/datum/file/program/crew,/datum/file/program/op_monitor, /datum/file/program/powermon,
|
||||
|
||||
/datum/file/camnet_key,/datum/file/camnet_key/mining,/datum/file/camnet_key/entertainment,/datum/file/camnet_key/research,
|
||||
/datum/file/camnet_key/bombrange,/datum/file/camnet_key/xeno,/datum/file/camnet_key/singulo,/datum/file/camnet_key/prison)
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd/big,/obj/item/part/computer/storage/removable,/obj/item/part/computer/ai_holder,
|
||||
/obj/item/part/computer/networking/radio/subspace,/obj/item/part/computer/networking/cameras,
|
||||
/obj/item/part/computer/cardslot/dual,/obj/item/part/computer/networking/area)
|
||||
New(var/L,var/built=0)
|
||||
if(!built && !battery)
|
||||
battery = new /obj/item/weapon/cell(src)
|
||||
..(L,built)
|
||||
|
||||
/obj/machinery/computer3/server/testing
|
||||
spawn_files = list(/datum/file/program/aifixer,/datum/file/program/arcade,/datum/file/program/atmos_alert,
|
||||
/datum/file/program/security,/datum/file/program/card_comp,
|
||||
/datum/file/program/borg_control,/datum/file/program/holodeck, /datum/file/program/communications,
|
||||
/datum/file/program/crew,/datum/file/program/op_monitor, /datum/file/program/powermon,
|
||||
|
||||
/datum/file/camnet_key,/datum/file/camnet_key/mining,/datum/file/camnet_key/entertainment,/datum/file/camnet_key/research,
|
||||
/datum/file/camnet_key/bombrange,/datum/file/camnet_key/xeno,/datum/file/camnet_key/singulo,/datum/file/camnet_key/prison)
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd/big,/obj/item/part/computer/storage/removable,/obj/item/part/computer/ai_holder,
|
||||
/obj/item/part/computer/networking/radio/subspace,/obj/item/part/computer/networking/cameras,
|
||||
/obj/item/part/computer/cardslot/dual,/obj/item/part/computer/networking/area)
|
||||
New(var/L,var/built=0)
|
||||
if(!built && !battery)
|
||||
battery = new /obj/item/weapon/cell(src)
|
||||
..(L,built)
|
||||
|
||||
/obj/machinery/computer3/server/rack/testing
|
||||
spawn_files = list(/datum/file/program/aifixer,/datum/file/program/arcade,/datum/file/program/atmos_alert,
|
||||
/datum/file/program/security,/datum/file/program/card_comp,
|
||||
/datum/file/program/borg_control,/datum/file/program/holodeck, /datum/file/program/communications,
|
||||
/datum/file/program/crew,/datum/file/program/op_monitor, /datum/file/program/powermon,
|
||||
|
||||
/datum/file/camnet_key,/datum/file/camnet_key/mining,/datum/file/camnet_key/entertainment,/datum/file/camnet_key/research,
|
||||
/datum/file/camnet_key/bombrange,/datum/file/camnet_key/xeno,/datum/file/camnet_key/singulo,/datum/file/camnet_key/prison)
|
||||
spawn_parts = list(/obj/item/part/computer/storage/hdd/big,/obj/item/part/computer/storage/removable,/obj/item/part/computer/ai_holder,
|
||||
/obj/item/part/computer/networking/radio/subspace,/obj/item/part/computer/networking/cameras,
|
||||
/obj/item/part/computer/cardslot/dual,/obj/item/part/computer/networking/area)
|
||||
New(var/L,var/built=0)
|
||||
if(!built && !battery)
|
||||
battery = new /obj/item/weapon/cell(src)
|
||||
..(L,built)
|
||||
|
||||
/obj/item/weapon/storage/box/testing_disks
|
||||
New()
|
||||
..()
|
||||
for(var/typekey in typesof(/obj/item/weapon/disk/file) - /obj/item/weapon/disk/file)
|
||||
new typekey(src)
|
||||
@@ -0,0 +1,29 @@
|
||||
/*
|
||||
Computer3 law changes:
|
||||
|
||||
* Laws are a file type
|
||||
* Connecting to the AI requires a network connection
|
||||
* Connecting to a borg requires a radio or network.
|
||||
|
||||
*/
|
||||
|
||||
/datum/file/ai_law
|
||||
var/list/hacklaws = null
|
||||
var/zerolaw = null
|
||||
var/list/corelaws = null
|
||||
var/list/auxlaws = null
|
||||
|
||||
var/configurable = 0
|
||||
|
||||
// override this when you need to be able to alter the parameters of the lawset
|
||||
proc/configure()
|
||||
return
|
||||
|
||||
execute(var/datum/file/program/source)
|
||||
if(istype(usr,/mob/living/silicon))
|
||||
return
|
||||
if(istype(source,/datum/file/program/ntos))
|
||||
if(configurable)
|
||||
configure()
|
||||
return
|
||||
if(istype(source,/datum/file/program/upload/ai))
|
||||
@@ -0,0 +1,13 @@
|
||||
/*
|
||||
Note that as with existing ai upload, this is not an interactive program.
|
||||
That means that the work is done in execute() rather than interact()
|
||||
*/
|
||||
|
||||
/datum/file/program/upload/ai
|
||||
execute(var/datum/file/program/source)
|
||||
if(!interactable() || istype(usr,/mob/living/silicon))
|
||||
return 0
|
||||
if(!computer.net)
|
||||
usr << "An indecipherable set of code flicks across the screen. Nothing else happens."
|
||||
return
|
||||
var/list/results = computer.net.get_machines
|
||||
+17
-18
@@ -63,9 +63,11 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh)
|
||||
|
||||
if(!istype(S))
|
||||
del src
|
||||
return
|
||||
|
||||
if(!S.zone)
|
||||
del src
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/air_contents = S.return_air()
|
||||
//get liquid fuels on the ground.
|
||||
@@ -84,9 +86,10 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh)
|
||||
air_contents.trace_gases.Remove(fuel)
|
||||
|
||||
//check if there is something to combust
|
||||
if(!air_contents.check_recombustability(liquid))
|
||||
if(!air_contents.check_combustability(liquid))
|
||||
//del src
|
||||
RemoveFire()
|
||||
return
|
||||
|
||||
//get a firelevel and set the icon
|
||||
firelevel = air_contents.calculate_firelevel(liquid)
|
||||
@@ -104,19 +107,20 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh)
|
||||
//im not sure how to implement a version that works for every creature so for now monkeys are firesafe
|
||||
for(var/mob/living/carbon/human/M in loc)
|
||||
M.FireBurn(firelevel, air_contents.temperature, air_contents.return_pressure() ) //Burn the humans!
|
||||
|
||||
loc.fire_act(air_contents, air_contents.temperature, air_contents.return_volume())
|
||||
for(var/atom/A in loc)
|
||||
A.fire_act(air_contents, air_contents.temperature, air_contents.return_volume())
|
||||
//spread
|
||||
for(var/direction in cardinal)
|
||||
if(S.open_directions & direction) //Grab all valid bordering tiles
|
||||
var/turf/simulated/enemy_tile = get_step(S, direction)
|
||||
|
||||
var/turf/simulated/enemy_tile = get_step(S, direction)
|
||||
|
||||
if(istype(enemy_tile))
|
||||
if(istype(enemy_tile))
|
||||
if(S.open_directions & direction) //Grab all valid bordering tiles
|
||||
var/datum/gas_mixture/acs = enemy_tile.return_air()
|
||||
var/obj/effect/decal/cleanable/liquid_fuel/liq = locate() in enemy_tile
|
||||
if(!acs) continue
|
||||
if(!acs.check_recombustability(liq)) continue
|
||||
if(!acs.check_combustability(liq)) continue
|
||||
//If extinguisher mist passed over the turf it's trying to spread to, don't spread and
|
||||
//reduce firelevel.
|
||||
if(enemy_tile.fire_protection > world.time-30)
|
||||
@@ -128,22 +132,17 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh)
|
||||
if( prob( 50 + 50 * (firelevel/vsc.fire_firelevel_multiplier) ) && S.CanPass(null, enemy_tile, 0,0) && enemy_tile.CanPass(null, S, 0,0))
|
||||
new/obj/fire(enemy_tile,firelevel)
|
||||
|
||||
else
|
||||
enemy_tile.adjacent_fire_act(loc, air_contents, air_contents.temperature, air_contents.return_volume())
|
||||
|
||||
//seperate part of the present gas
|
||||
//this is done to prevent the fire burning all gases in a single pass
|
||||
var/datum/gas_mixture/flow = air_contents.remove_ratio(vsc.fire_consuption_rate)
|
||||
///////////////////////////////// FLOW HAS BEEN CREATED /// DONT DELETE THE FIRE UNTIL IT IS MERGED BACK OR YOU WILL DELETE AIR ///////////////////////////////////////////////
|
||||
|
||||
if(flow)
|
||||
|
||||
if(flow.check_recombustability(liquid))
|
||||
//Ensure flow temperature is higher than minimum fire temperatures.
|
||||
//this creates some energy ex nihilo but is necessary to get a fire started
|
||||
//lets just pretend this energy comes from the ignition source and dont mention this again
|
||||
//flow.temperature = max(PHORON_MINIMUM_BURN_TEMPERATURE+0.1,flow.temperature)
|
||||
|
||||
//burn baby burn!
|
||||
|
||||
flow.zburn(liquid,1)
|
||||
//burn baby burn!
|
||||
flow.zburn(liquid,1)
|
||||
//merge the air back
|
||||
S.assume_air(flow)
|
||||
|
||||
@@ -275,9 +274,9 @@ datum/gas_mixture/proc/check_combustability(obj/effect/decal/cleanable/liquid_fu
|
||||
if(oxygen && (phoron || fuel || liquid))
|
||||
if(liquid)
|
||||
return 1
|
||||
if (phoron >= 0.1)
|
||||
if(QUANTIZE(phoron * vsc.fire_consuption_rate) >= 0.1)
|
||||
return 1
|
||||
if(fuel && fuel.moles >= 0.1)
|
||||
if(fuel && QUANTIZE(fuel.moles * vsc.fire_consuption_rate) >= 0.1)
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
+1
-1
@@ -118,7 +118,7 @@ obj/var/contaminated = 0
|
||||
/mob/living/carbon/human/proc/burn_eyes()
|
||||
//The proc that handles eye burning.
|
||||
if(prob(20)) src << "\red Your eyes burn!"
|
||||
var/datum/organ/internal/eyes/E = internal_organs["eyes"]
|
||||
var/datum/organ/internal/eyes/E = internal_organs_by_name["eyes"]
|
||||
E.damage += 2.5
|
||||
eye_blurry = min(eye_blurry+1.5,50)
|
||||
if (prob(max(0,E.damage - 15) + 1) &&!eye_blind)
|
||||
|
||||
@@ -26,6 +26,10 @@
|
||||
#endif
|
||||
|
||||
var/turf/unsim = get_step(src, d)
|
||||
|
||||
if(!unsim)
|
||||
continue
|
||||
|
||||
block = unsim.c_airblock(src)
|
||||
|
||||
if(block & AIR_BLOCKED)
|
||||
@@ -75,6 +79,10 @@
|
||||
#endif
|
||||
|
||||
var/turf/unsim = get_step(src, d)
|
||||
|
||||
if(!unsim) //edge of map
|
||||
continue
|
||||
|
||||
var/block = unsim.c_airblock(src)
|
||||
if(block & AIR_BLOCKED)
|
||||
|
||||
@@ -108,6 +116,8 @@
|
||||
if(istype(unsim, /turf/simulated))
|
||||
|
||||
var/turf/simulated/sim = unsim
|
||||
sim.open_directions |= reverse_dir[d]
|
||||
|
||||
if(air_master.has_valid_zone(sim))
|
||||
|
||||
//Might have assigned a zone, since this happens for each direction.
|
||||
|
||||
+15
-11
@@ -856,11 +856,19 @@ proc/anim(turf/location as turf,target as mob|obj,a_icon,a_icon_state as text,fl
|
||||
var/old_icon_state1 = T.icon_state
|
||||
var/old_icon1 = T.icon
|
||||
|
||||
var/turf/X = new T.type(B)
|
||||
var/turf/X = B.ChangeTurf(T.type)
|
||||
X.dir = old_dir1
|
||||
X.icon_state = old_icon_state1
|
||||
X.icon = old_icon1 //Shuttle floors are in shuttle.dmi while the defaults are floors.dmi
|
||||
|
||||
var/turf/simulated/ST = T
|
||||
if(istype(ST) && ST.zone)
|
||||
var/turf/simulated/SX = X
|
||||
if(!SX.air)
|
||||
SX.make_air()
|
||||
SX.air.copy_from(ST.zone.air)
|
||||
ST.zone.remove(ST)
|
||||
|
||||
/* Quick visual fix for some weird shuttle corner artefacts when on transit space tiles */
|
||||
if(direction && findtext(X.icon_state, "swall_s"))
|
||||
|
||||
@@ -909,16 +917,7 @@ proc/anim(turf/location as turf,target as mob|obj,a_icon,a_icon_state as text,fl
|
||||
toupdate += X
|
||||
|
||||
if(turftoleave)
|
||||
var/turf/ttl = new turftoleave(T)
|
||||
|
||||
// var/area/AR2 = ttl.loc
|
||||
|
||||
// if(AR2.lighting_use_dynamic) //TODO: rewrite this code so it's not messed by lighting ~Carn
|
||||
// ttl.opacity = !ttl.opacity
|
||||
// ttl.sd_SetOpacity(!ttl.opacity)
|
||||
|
||||
fromupdate += ttl
|
||||
|
||||
fromupdate += T.ChangeTurf(turftoleave)
|
||||
else
|
||||
T.ChangeTurf(/turf/space)
|
||||
|
||||
@@ -1378,3 +1377,8 @@ var/list/WALLITEMS = list(
|
||||
|
||||
/proc/format_text(text)
|
||||
return replacetext(replacetext(text,"\proper ",""),"\improper ","")
|
||||
|
||||
/proc/topic_link(var/datum/D, var/arglist, var/content)
|
||||
if(istype(arglist,/list))
|
||||
arglist = list2params(arglist)
|
||||
return "<a href='?src=\ref[D];[arglist]'>[content]</a>"
|
||||
|
||||
+10
-5
@@ -295,14 +295,19 @@
|
||||
|
||||
// Simple helper to face what you clicked on, in case it should be needed in more than one place
|
||||
/mob/proc/face_atom(var/atom/A)
|
||||
if( stat || buckled || !A || !x || !y || !A.x || !A.y ) return
|
||||
if( stat || (buckled && !buckled.movable) || !A || !x || !y || !A.x || !A.y ) return
|
||||
var/dx = A.x - x
|
||||
var/dy = A.y - y
|
||||
if(!dx && !dy) return
|
||||
|
||||
var/direction
|
||||
if(abs(dx) < abs(dy))
|
||||
if(dy > 0) usr.dir = NORTH
|
||||
else usr.dir = SOUTH
|
||||
if(dy > 0) direction = NORTH
|
||||
else direction = SOUTH
|
||||
else
|
||||
if(dx > 0) usr.dir = EAST
|
||||
else usr.dir = WEST
|
||||
if(dx > 0) direction = EAST
|
||||
else direction = WEST
|
||||
usr.dir = direction
|
||||
if(buckled && buckled.movable)
|
||||
buckled.dir = direction
|
||||
buckled.handle_rotation()
|
||||
@@ -39,7 +39,12 @@ datum/light_source
|
||||
var/list/effect = list()
|
||||
var/__x = 0 //x coordinate at last update
|
||||
var/__y = 0 //y coordinate at last update
|
||||
var/l_color
|
||||
var/__z = 0 //z coordinate at last update
|
||||
|
||||
var/_l_color //do not use directly, only used as reference for updating
|
||||
var/col_r
|
||||
var/col_g
|
||||
var/col_b
|
||||
|
||||
|
||||
New(atom/A)
|
||||
@@ -47,9 +52,10 @@ datum/light_source
|
||||
CRASH("The first argument to the light object's constructor must be the atom that is the light source. Expected atom, received '[A]' instead.")
|
||||
..()
|
||||
owner = A
|
||||
l_color = owner.l_color
|
||||
readrgb(owner.l_color)
|
||||
__x = owner.x
|
||||
__y = owner.y
|
||||
__z = owner.z
|
||||
// the lighting object maintains a list of all light sources
|
||||
lighting_controller.lights += src
|
||||
|
||||
@@ -61,12 +67,13 @@ datum/light_source
|
||||
return 1 //causes it to be removed from our list of lights. The garbage collector will then destroy it.
|
||||
|
||||
// check to see if we've moved since last update
|
||||
if(owner.x != __x || owner.y != __y)
|
||||
if(owner.x != __x || owner.y != __y || owner.z != __z)
|
||||
__x = owner.x
|
||||
__y = owner.y
|
||||
__z = owner.z
|
||||
changed = 1
|
||||
|
||||
if (owner.l_color != l_color)
|
||||
if (owner.l_color != _l_color)
|
||||
changed = 1
|
||||
|
||||
if(changed)
|
||||
@@ -79,19 +86,19 @@ datum/light_source
|
||||
proc/remove_effect()
|
||||
// before we apply the effect we remove the light's current effect.
|
||||
for(var/turf/T in effect) // negate the effect of this light source
|
||||
T.update_lumcount(-effect[T], l_color, 1)
|
||||
T.update_lumcount(-effect[T], col_r, col_g, col_b, 1)
|
||||
effect.Cut() // clear the effect list
|
||||
|
||||
proc/add_effect()
|
||||
// only do this if the light is turned on and is on the map
|
||||
if(owner.loc && owner.luminosity > 0)
|
||||
l_color = owner.l_color
|
||||
readrgb(owner.l_color)
|
||||
effect = list()
|
||||
for(var/turf/T in view(owner.get_light_range(),owner))
|
||||
var/delta_lumen = lum(T)
|
||||
if(delta_lumen > 0)
|
||||
effect[T] = delta_lumen
|
||||
T.update_lumcount(delta_lumen, l_color, 0)
|
||||
T.update_lumcount(delta_lumen, col_r, col_g, col_b, 0)
|
||||
|
||||
return 0
|
||||
else
|
||||
@@ -116,6 +123,15 @@ datum/light_source
|
||||
else
|
||||
return sqrtTable[owner.trueLuminosity] - dist
|
||||
|
||||
proc/readrgb(col)
|
||||
_l_color = col
|
||||
if(col)
|
||||
col_r = GetRedPart(col)
|
||||
col_g = GetGreenPart(col)
|
||||
col_b = GetBluePart(col)
|
||||
else
|
||||
col_r = null
|
||||
|
||||
atom
|
||||
var/datum/light_source/light
|
||||
var/trueLuminosity = 0 // Typically 'luminosity' squared. The builtin luminosity must remain linear.
|
||||
@@ -214,45 +230,38 @@ turf
|
||||
var/lighting_lumcount = 0
|
||||
var/lighting_changed = 0
|
||||
var/color_lighting_lumcount = 0
|
||||
var/list/colors = list()
|
||||
|
||||
var/lumcount_r = 0
|
||||
var/lumcount_g = 0
|
||||
var/lumcount_b = 0
|
||||
var/light_col_sources = 0
|
||||
|
||||
turf/space
|
||||
lighting_lumcount = 4 //starlight
|
||||
|
||||
turf/proc/update_lumcount(amount, _lcolor, removing = 0)
|
||||
turf/proc/update_lumcount(amount, col_r, col_g, col_b, removing = 0)
|
||||
lighting_lumcount += amount
|
||||
var/blended
|
||||
|
||||
if (_lcolor)
|
||||
if (removing)
|
||||
colors.Remove(_lcolor) // Remove the color that's leaving us from our list.
|
||||
if(!isnull(col_r)) //col_r is the "key" var, if it's null so will the rest
|
||||
if(removing)
|
||||
light_col_sources--
|
||||
lumcount_r -= col_r
|
||||
lumcount_g -= col_g
|
||||
lumcount_b -= col_b
|
||||
else
|
||||
light_col_sources++
|
||||
lumcount_r += col_r
|
||||
lumcount_g += col_g
|
||||
lumcount_b += col_b
|
||||
|
||||
if (colors && !colors.len)
|
||||
l_color = null // All our color is gone, no color for us.
|
||||
else if (colors && colors.len > 1)
|
||||
var/maxdepth = 3 // Will blend 3 colors, anymore than that and it looks bad or we will get lag on every tile update.
|
||||
var/currentblended = colors
|
||||
if (colors.len > maxdepth)
|
||||
currentblended = MixColors(colors.Copy(1,maxdepth+1))
|
||||
if(light_col_sources)
|
||||
var/r_avg = max(0, min(255, round(lumcount_r / light_col_sources, 16) + 15))
|
||||
var/g_avg = max(0, min(255, round(lumcount_g / light_col_sources, 16) + 15))
|
||||
var/b_avg = max(0, min(255, round(lumcount_b / light_col_sources, 16) + 15))
|
||||
l_color = rgb(r_avg, g_avg, b_avg)
|
||||
else
|
||||
l_color = null
|
||||
|
||||
if (currentblended)
|
||||
//world << "Ended up with [currentblended]"
|
||||
l_color = currentblended // blended the remaining colors so apply it.
|
||||
else
|
||||
l_color = null // Something went wrong, no color for you.
|
||||
else
|
||||
l_color = colors[colors.len]
|
||||
else // we added a color.
|
||||
colors.Add(_lcolor) // Add the base color to the list.
|
||||
if (l_color && _lcolor && l_color != _lcolor) // Blend colors.
|
||||
blended = MixColors(list(l_color,_lcolor))
|
||||
|
||||
if (blended)
|
||||
l_color = blended // If we had a blended color, this is what we get otherwise.
|
||||
else
|
||||
l_color = _lcolor // Basecolor is our color.
|
||||
|
||||
// if ((l_color != LIGHT_WHITE && l_color != "#FFF") || removing)
|
||||
color_lighting_lumcount = max(color_lighting_lumcount + amount, 0) // Minimum of 0.
|
||||
|
||||
if(!lighting_changed)
|
||||
@@ -298,7 +307,8 @@ turf/proc/shift_to_subarea()
|
||||
|
||||
// pomf - If we have a lighting color that is not null, apply the new tag to seperate the areas.
|
||||
if (l_color)
|
||||
new_tag += "[l_color][color_lighting_lumcount]" // pomf - We append the color lighting lumcount so we can have colored lights.
|
||||
// pomf - We append the (rounded!) color lighting lumcount so we can have colored lights.
|
||||
new_tag += "[l_color][min(max(round(color_lighting_lumcount,1),0),lighting_controller.lighting_states)]"
|
||||
|
||||
if(Area.tag!=new_tag) //skip if already in this area
|
||||
var/area/A = locate(new_tag) // find an appropriate area
|
||||
|
||||
@@ -0,0 +1,264 @@
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
|
||||
|
||||
// Controls the emergency shuttle
|
||||
|
||||
var/global/datum/emergency_shuttle_controller/emergency_shuttle
|
||||
|
||||
/datum/emergency_shuttle_controller
|
||||
var/datum/shuttle/ferry/emergency/shuttle
|
||||
var/list/escape_pods
|
||||
|
||||
var/launch_time //the time at which the shuttle will be launched
|
||||
var/auto_recall = 0 //if set, the shuttle will be auto-recalled
|
||||
var/auto_recall_time //the time at which the shuttle will be auto-recalled
|
||||
var/evac = 0 //1 = emergency evacuation, 0 = crew transfer
|
||||
var/wait_for_launch = 0 //if the shuttle is waiting to launch
|
||||
var/autopilot = 1 //set to 0 to disable the shuttle automatically launching
|
||||
|
||||
var/deny_shuttle = 0 //allows admins to prevent the shuttle from being called
|
||||
var/departed = 0 //if the shuttle has left the station at least once
|
||||
|
||||
|
||||
/datum/emergency_shuttle_controller/proc/process()
|
||||
if (wait_for_launch)
|
||||
if (auto_recall && world.time >= auto_recall_time)
|
||||
recall()
|
||||
if (world.time >= launch_time) //time to launch the shuttle
|
||||
stop_launch_countdown()
|
||||
|
||||
if (!shuttle.location) //leaving from the station
|
||||
//launch the pods!
|
||||
for (var/datum/shuttle/ferry/escape_pod/pod in escape_pods)
|
||||
if (!pod.arming_controller || pod.arming_controller.armed)
|
||||
pod.launch(src)
|
||||
|
||||
if (autopilot)
|
||||
shuttle.launch(src)
|
||||
|
||||
//called when the shuttle has arrived.
|
||||
/datum/emergency_shuttle_controller/proc/shuttle_arrived()
|
||||
if (!shuttle.location) //at station
|
||||
if (autopilot)
|
||||
set_launch_countdown(SHUTTLE_LEAVETIME) //get ready to return
|
||||
|
||||
if (evac)
|
||||
captain_announce("The Emergency Shuttle has docked with the station. You have approximately [round(estimate_launch_time()/60,1)] minutes to board the Emergency Shuttle.")
|
||||
world << sound('sound/AI/shuttledock.ogg')
|
||||
else
|
||||
captain_announce("The scheduled Crew Transfer Shuttle has docked with the station. It will depart in approximately [round(emergency_shuttle.estimate_launch_time()/60,1)] minutes.")
|
||||
|
||||
//arm the escape pods
|
||||
if (evac)
|
||||
for (var/datum/shuttle/ferry/escape_pod/pod in escape_pods)
|
||||
if (pod.arming_controller)
|
||||
pod.arming_controller.arm()
|
||||
|
||||
//begins the launch countdown and sets the amount of time left until launch
|
||||
/datum/emergency_shuttle_controller/proc/set_launch_countdown(var/seconds)
|
||||
wait_for_launch = 1
|
||||
launch_time = world.time + seconds*10
|
||||
|
||||
/datum/emergency_shuttle_controller/proc/stop_launch_countdown()
|
||||
wait_for_launch = 0
|
||||
|
||||
//calls the shuttle for an emergency evacuation
|
||||
/datum/emergency_shuttle_controller/proc/call_evac()
|
||||
if(!can_call()) return
|
||||
|
||||
//set the launch timer
|
||||
autopilot = 1
|
||||
set_launch_countdown(get_shuttle_prep_time())
|
||||
auto_recall_time = rand(world.time + 300, launch_time - 300)
|
||||
|
||||
//reset the shuttle transit time if we need to
|
||||
shuttle.move_time = SHUTTLE_TRANSIT_DURATION
|
||||
|
||||
evac = 1
|
||||
captain_announce("An emergency evacuation shuttle has been called. It will arrive in approximately [round(estimate_arrival_time()/60)] minutes.")
|
||||
world << sound('sound/AI/shuttlecalled.ogg')
|
||||
for(var/area/A in world)
|
||||
if(istype(A, /area/hallway))
|
||||
A.readyalert()
|
||||
|
||||
//calls the shuttle for a routine crew transfer
|
||||
/datum/emergency_shuttle_controller/proc/call_transfer()
|
||||
if(!can_call()) return
|
||||
|
||||
//set the launch timer
|
||||
autopilot = 1
|
||||
set_launch_countdown(get_shuttle_prep_time())
|
||||
auto_recall_time = rand(world.time + 300, launch_time - 300)
|
||||
|
||||
//reset the shuttle transit time if we need to
|
||||
shuttle.move_time = SHUTTLE_TRANSIT_DURATION
|
||||
|
||||
captain_announce("A crew transfer has been scheduled. The shuttle has been called. It will arrive in approximately [round(estimate_arrival_time()/60)] minutes.")
|
||||
|
||||
//recalls the shuttle
|
||||
/datum/emergency_shuttle_controller/proc/recall()
|
||||
if (!can_recall()) return
|
||||
|
||||
wait_for_launch = 0
|
||||
shuttle.cancel_launch(src)
|
||||
|
||||
if (evac)
|
||||
captain_announce("The emergency shuttle has been recalled.")
|
||||
world << sound('sound/AI/shuttlerecalled.ogg')
|
||||
|
||||
for(var/area/A in world)
|
||||
if(istype(A, /area/hallway))
|
||||
A.readyreset()
|
||||
evac = 0
|
||||
else
|
||||
captain_announce("The scheduled crew transfer has been cancelled.")
|
||||
|
||||
/datum/emergency_shuttle_controller/proc/can_call()
|
||||
if (deny_shuttle)
|
||||
return 0
|
||||
if (shuttle.moving_status != SHUTTLE_IDLE || !shuttle.location) //must be idle at centcom
|
||||
return 0
|
||||
if (wait_for_launch) //already launching
|
||||
return 0
|
||||
return 1
|
||||
|
||||
//this only returns 0 if it would absolutely make no sense to recall
|
||||
//e.g. the shuttle is already at the station or wasn't called to begin with
|
||||
//other reasons for the shuttle not being recallable should be handled elsewhere
|
||||
/datum/emergency_shuttle_controller/proc/can_recall()
|
||||
if (shuttle.moving_status == SHUTTLE_INTRANSIT) //if the shuttle is already in transit then it's too late
|
||||
return 0
|
||||
if (!shuttle.location) //already at the station.
|
||||
return 0
|
||||
if (!wait_for_launch) //we weren't going anywhere, anyways...
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/datum/emergency_shuttle_controller/proc/get_shuttle_prep_time()
|
||||
// During mutiny rounds, the shuttle takes twice as long.
|
||||
if(ticker && istype(ticker.mode,/datum/game_mode/mutiny))
|
||||
return SHUTTLE_PREPTIME * 3 //15 minutes
|
||||
|
||||
return SHUTTLE_PREPTIME
|
||||
|
||||
|
||||
/*
|
||||
These procs are not really used by the controller itself, but are for other parts of the
|
||||
game whose logic depends on the emergency shuttle.
|
||||
*/
|
||||
|
||||
//returns 1 if the shuttle is docked at the station and waiting to leave
|
||||
/datum/emergency_shuttle_controller/proc/waiting_to_leave()
|
||||
if (shuttle.location)
|
||||
return 0 //not at station
|
||||
return (wait_for_launch || shuttle.moving_status != SHUTTLE_INTRANSIT)
|
||||
|
||||
//so we don't have emergency_shuttle.shuttle.location everywhere
|
||||
/datum/emergency_shuttle_controller/proc/location()
|
||||
if (!shuttle)
|
||||
return 1 //if we dont have a shuttle datum, just act like it's at centcom
|
||||
return shuttle.location
|
||||
|
||||
//returns the time left until the shuttle arrives at it's destination, in seconds
|
||||
/datum/emergency_shuttle_controller/proc/estimate_arrival_time()
|
||||
var/eta
|
||||
if (shuttle.has_arrive_time())
|
||||
//we are in transition and can get an accurate ETA
|
||||
eta = shuttle.arrive_time
|
||||
else
|
||||
//otherwise we need to estimate the arrival time using the scheduled launch time
|
||||
eta = launch_time + shuttle.move_time*10 + shuttle.warmup_time*10
|
||||
return (eta - world.time)/10
|
||||
|
||||
//returns the time left until the shuttle launches, in seconds
|
||||
/datum/emergency_shuttle_controller/proc/estimate_launch_time()
|
||||
return (launch_time - world.time)/10
|
||||
|
||||
/datum/emergency_shuttle_controller/proc/has_eta()
|
||||
return (wait_for_launch || shuttle.moving_status != SHUTTLE_IDLE)
|
||||
|
||||
//returns 1 if the shuttle has gone to the station and come back at least once,
|
||||
//used for game completion checking purposes
|
||||
/datum/emergency_shuttle_controller/proc/returned()
|
||||
return (departed && shuttle.moving_status == SHUTTLE_IDLE && shuttle.location) //we've gone to the station at least once, no longer in transit and are idle back at centcom
|
||||
|
||||
//returns 1 if the shuttle is not idle at centcom
|
||||
/datum/emergency_shuttle_controller/proc/online()
|
||||
if (!shuttle.location) //not at centcom
|
||||
return 1
|
||||
if (wait_for_launch || shuttle.moving_status != SHUTTLE_IDLE)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//returns 1 if the shuttle is currently in transit (or just leaving) to the station
|
||||
/datum/emergency_shuttle_controller/proc/going_to_station()
|
||||
return (!shuttle.direction && shuttle.moving_status != SHUTTLE_IDLE)
|
||||
|
||||
//returns 1 if the shuttle is currently in transit (or just leaving) to centcom
|
||||
/datum/emergency_shuttle_controller/proc/going_to_centcom()
|
||||
return (shuttle.direction && shuttle.moving_status != SHUTTLE_IDLE)
|
||||
|
||||
|
||||
/datum/emergency_shuttle_controller/proc/get_status_panel_eta()
|
||||
if (online())
|
||||
if (shuttle.has_arrive_time())
|
||||
var/timeleft = emergency_shuttle.estimate_arrival_time()
|
||||
return "ETA-[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]"
|
||||
|
||||
if (waiting_to_leave())
|
||||
if (shuttle.moving_status == SHUTTLE_WARMUP)
|
||||
return "Departing..."
|
||||
|
||||
var/timeleft = emergency_shuttle.estimate_launch_time()
|
||||
return "ETD-[(timeleft / 60) % 60]:[add_zero(num2text(timeleft % 60), 2)]"
|
||||
|
||||
return ""
|
||||
/*
|
||||
Some slapped-together star effects for maximum spess immershuns. Basically consists of a
|
||||
spawner, an ender, and bgstar. Spawners create bgstars, bgstars shoot off into a direction
|
||||
until they reach a starender.
|
||||
*/
|
||||
|
||||
/obj/effect/bgstar
|
||||
name = "star"
|
||||
var/speed = 10
|
||||
var/direction = SOUTH
|
||||
layer = 2 // TURF_LAYER
|
||||
|
||||
/obj/effect/bgstar/New()
|
||||
..()
|
||||
pixel_x += rand(-2,30)
|
||||
pixel_y += rand(-2,30)
|
||||
var/starnum = pick("1", "1", "1", "2", "3", "4")
|
||||
|
||||
icon_state = "star"+starnum
|
||||
|
||||
speed = rand(2, 5)
|
||||
|
||||
/obj/effect/bgstar/proc/startmove()
|
||||
|
||||
while(src)
|
||||
sleep(speed)
|
||||
step(src, direction)
|
||||
for(var/obj/effect/starender/E in loc)
|
||||
del(src)
|
||||
|
||||
|
||||
/obj/effect/starender
|
||||
invisibility = 101
|
||||
|
||||
/obj/effect/starspawner
|
||||
invisibility = 101
|
||||
var/spawndir = SOUTH
|
||||
var/spawning = 0
|
||||
|
||||
/obj/effect/starspawner/West
|
||||
spawndir = WEST
|
||||
|
||||
/obj/effect/starspawner/proc/startspawn()
|
||||
spawning = 1
|
||||
while(spawning)
|
||||
sleep(rand(2, 30))
|
||||
var/obj/effect/bgstar/S = new/obj/effect/bgstar(locate(x,y,z))
|
||||
S.direction = spawndir
|
||||
spawn()
|
||||
S.startmove()
|
||||
@@ -32,8 +32,10 @@ datum/controller/game_controller
|
||||
var/last_thing_processed
|
||||
var/mob/list/expensive_mobs = list()
|
||||
var/rebuild_active_areas = 0
|
||||
|
||||
var/list/shuttle_list //for debugging and VV
|
||||
|
||||
var/list/shuttle_list // For debugging and VV
|
||||
var/datum/ore_distribution/asteroid_ore_map // For debugging and VV.
|
||||
|
||||
|
||||
datum/controller/game_controller/New()
|
||||
//There can be only one master_controller. Out with the old and in with the new.
|
||||
@@ -52,7 +54,8 @@ datum/controller/game_controller/New()
|
||||
|
||||
if(!syndicate_code_phrase) syndicate_code_phrase = generate_code_phrase()
|
||||
if(!syndicate_code_response) syndicate_code_response = generate_code_phrase()
|
||||
if(!emergency_shuttle) emergency_shuttle = new /datum/shuttle_controller/emergency_shuttle()
|
||||
if(!emergency_shuttle) emergency_shuttle = new /datum/emergency_shuttle_controller()
|
||||
if(!shuttle_controller) shuttle_controller = new /datum/shuttle_controller()
|
||||
|
||||
datum/controller/game_controller/proc/setup()
|
||||
world.tick_lag = config.Ticklag
|
||||
@@ -67,9 +70,6 @@ datum/controller/game_controller/proc/setup()
|
||||
if(!ticker)
|
||||
ticker = new /datum/controller/gameticker()
|
||||
|
||||
if(!shuttles) setup_shuttles()
|
||||
shuttle_list = shuttles
|
||||
|
||||
setup_objects()
|
||||
setupgenetics()
|
||||
setupfactions()
|
||||
@@ -82,8 +82,11 @@ datum/controller/game_controller/proc/setup()
|
||||
make_mining_asteroid_secret()
|
||||
|
||||
//Create the mining ore distribution map.
|
||||
var/datum/ore_distribution/O = new()
|
||||
O.populate_distribution_map()
|
||||
asteroid_ore_map = new /datum/ore_distribution()
|
||||
asteroid_ore_map.populate_distribution_map()
|
||||
|
||||
//Set up spawn points.
|
||||
populate_spawn_points()
|
||||
|
||||
spawn(0)
|
||||
if(ticker)
|
||||
@@ -135,6 +138,7 @@ datum/controller/game_controller/proc/process()
|
||||
|
||||
vote.process()
|
||||
transfer_controller.process()
|
||||
shuttle_controller.process()
|
||||
process_newscaster()
|
||||
|
||||
//AIR
|
||||
@@ -230,7 +234,7 @@ datum/controller/game_controller/proc/process()
|
||||
total_cost = air_cost + sun_cost + mobs_cost + diseases_cost + machines_cost + objects_cost + networks_cost + powernets_cost + nano_cost + events_cost + ticker_cost
|
||||
|
||||
var/end_time = world.timeofday
|
||||
if(end_time < start_time)
|
||||
if(end_time < start_time) //why not just use world.time instead?
|
||||
start_time -= 864000 //deciseconds in a day
|
||||
sleep( round(minimum_ticks - (end_time - start_time),1) )
|
||||
else
|
||||
|
||||
@@ -1,287 +1,305 @@
|
||||
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
|
||||
|
||||
// Controls the emergency shuttle
|
||||
var/global/datum/shuttle_controller/shuttle_controller
|
||||
|
||||
|
||||
// these define the time taken for the shuttle to get to SS13
|
||||
// and the time before it leaves again
|
||||
#define SHUTTLE_PREPTIME 300 // 5 minutes = 300 seconds - after this time, the shuttle cannot be recalled
|
||||
#define SHUTTLE_LEAVETIME 180 // 3 minutes = 180 seconds - the duration for which the shuttle will wait at the station
|
||||
#define SHUTTLE_TRANSIT_DURATION 300 // 5 minutes = 300 seconds - how long it takes for the shuttle to get to the station
|
||||
#define SHUTTLE_TRANSIT_DURATION_RETURN 120 // 2 minutes = 120 seconds - for some reason it takes less time to come back, go figure.
|
||||
/datum/shuttle_controller
|
||||
var/list/shuttles //maps shuttle tags to shuttle datums, so that they can be looked up.
|
||||
var/list/process_shuttles //simple list of shuttles, for processing
|
||||
|
||||
var/global/datum/shuttle_controller/emergency_shuttle/emergency_shuttle
|
||||
/datum/shuttle_controller/proc/process()
|
||||
//process ferry shuttles
|
||||
for (var/datum/shuttle/ferry/shuttle in process_shuttles)
|
||||
if (shuttle.process_state)
|
||||
shuttle.process()
|
||||
|
||||
/datum/shuttle_controller/emergency_shuttle
|
||||
var/datum/shuttle/ferry/emergency/shuttle
|
||||
var/list/escape_pods
|
||||
|
||||
/datum/shuttle_controller/New()
|
||||
shuttles = list()
|
||||
process_shuttles = list()
|
||||
|
||||
var/datum/shuttle/ferry/shuttle
|
||||
|
||||
var/launch_time //the time at which the shuttle will be launched
|
||||
var/auto_recall = 0 //if set, the shuttle will be auto-recalled
|
||||
var/auto_recall_time //the time at which the shuttle will be auto-recalled
|
||||
var/evac = 0 //1 = emergency evacuation, 0 = crew transfer
|
||||
var/wait_for_launch = 0 //if the shuttle is waiting to launch
|
||||
// Escape shuttle and pods
|
||||
shuttle = new/datum/shuttle/ferry/emergency()
|
||||
shuttle.location = 1
|
||||
shuttle.warmup_time = 10
|
||||
shuttle.area_offsite = locate(/area/shuttle/escape/centcom)
|
||||
shuttle.area_station = locate(/area/shuttle/escape/station)
|
||||
shuttle.area_transition = locate(/area/shuttle/escape/transit)
|
||||
shuttle.docking_controller_tag = "escape_shuttle"
|
||||
shuttle.dock_target_station = "escape_dock"
|
||||
shuttle.dock_target_offsite = "centcom_dock"
|
||||
shuttle.transit_direction = NORTH
|
||||
shuttle.move_time = SHUTTLE_TRANSIT_DURATION_RETURN
|
||||
//shuttle.docking_controller_tag = "supply_shuttle"
|
||||
//shuttle.dock_target_station = "cargo_bay"
|
||||
shuttles["Escape"] = shuttle
|
||||
process_shuttles += shuttle
|
||||
|
||||
var/deny_shuttle = 0 //allows admins to prevent the shuttle from being called
|
||||
var/departed = 0 //if the shuttle has left the station at least once
|
||||
shuttle = new/datum/shuttle/ferry/escape_pod()
|
||||
shuttle.location = 0
|
||||
shuttle.warmup_time = 0
|
||||
shuttle.area_station = locate(/area/shuttle/escape_pod1/station)
|
||||
shuttle.area_offsite = locate(/area/shuttle/escape_pod1/centcom)
|
||||
shuttle.area_transition = locate(/area/shuttle/escape_pod1/transit)
|
||||
shuttle.docking_controller_tag = "escape_pod_1"
|
||||
shuttle.dock_target_station = "escape_pod_1_berth"
|
||||
shuttle.dock_target_offsite = "escape_pod_1_recovery"
|
||||
shuttle.transit_direction = NORTH
|
||||
shuttle.move_time = SHUTTLE_TRANSIT_DURATION_RETURN + rand(-30, 60) //randomize this so it seems like the pods are being picked up one by one
|
||||
process_shuttles += shuttle
|
||||
shuttles["Escape Pod 1"] = shuttle
|
||||
|
||||
/datum/shuttle_controller/emergency_shuttle/proc/setup_pods()
|
||||
escape_pods = list()
|
||||
shuttle = new/datum/shuttle/ferry/escape_pod()
|
||||
shuttle.location = 0
|
||||
shuttle.warmup_time = 0
|
||||
shuttle.area_station = locate(/area/shuttle/escape_pod2/station)
|
||||
shuttle.area_offsite = locate(/area/shuttle/escape_pod2/centcom)
|
||||
shuttle.area_transition = locate(/area/shuttle/escape_pod2/transit)
|
||||
shuttle.docking_controller_tag = "escape_pod_2"
|
||||
shuttle.dock_target_station = "escape_pod_2_berth"
|
||||
shuttle.dock_target_offsite = "escape_pod_2_recovery"
|
||||
shuttle.transit_direction = NORTH
|
||||
shuttle.move_time = SHUTTLE_TRANSIT_DURATION_RETURN + rand(-30, 60) //randomize this so it seems like the pods are being picked up one by one
|
||||
process_shuttles += shuttle
|
||||
shuttles["Escape Pod 2"] = shuttle
|
||||
|
||||
var/datum/shuttle/ferry/escape_pod/pod
|
||||
|
||||
pod = new()
|
||||
pod.location = 0
|
||||
pod.warmup_time = 0
|
||||
pod.area_station = locate(/area/shuttle/escape_pod1/station)
|
||||
pod.area_offsite = locate(/area/shuttle/escape_pod1/centcom)
|
||||
pod.area_transition = locate(/area/shuttle/escape_pod1/transit)
|
||||
pod.travel_time = SHUTTLE_TRANSIT_DURATION_RETURN
|
||||
escape_pods += pod
|
||||
|
||||
pod = new()
|
||||
pod.location = 0
|
||||
pod.warmup_time = 0
|
||||
pod.area_station = locate(/area/shuttle/escape_pod2/station)
|
||||
pod.area_offsite = locate(/area/shuttle/escape_pod2/centcom)
|
||||
pod.area_transition = locate(/area/shuttle/escape_pod2/transit)
|
||||
pod.travel_time = SHUTTLE_TRANSIT_DURATION_RETURN
|
||||
escape_pods += pod
|
||||
|
||||
pod = new()
|
||||
pod.location = 0
|
||||
pod.warmup_time = 0
|
||||
pod.area_station = locate(/area/shuttle/escape_pod3/station)
|
||||
pod.area_offsite = locate(/area/shuttle/escape_pod3/centcom)
|
||||
pod.area_transition = locate(/area/shuttle/escape_pod3/transit)
|
||||
pod.travel_time = SHUTTLE_TRANSIT_DURATION_RETURN
|
||||
escape_pods += pod
|
||||
shuttle = new/datum/shuttle/ferry/escape_pod()
|
||||
shuttle.location = 0
|
||||
shuttle.warmup_time = 0
|
||||
shuttle.area_station = locate(/area/shuttle/escape_pod3/station)
|
||||
shuttle.area_offsite = locate(/area/shuttle/escape_pod3/centcom)
|
||||
shuttle.area_transition = locate(/area/shuttle/escape_pod3/transit)
|
||||
shuttle.docking_controller_tag = "escape_pod_3"
|
||||
shuttle.dock_target_station = "escape_pod_3_berth"
|
||||
shuttle.dock_target_offsite = "escape_pod_3_recovery"
|
||||
shuttle.transit_direction = EAST
|
||||
shuttle.move_time = SHUTTLE_TRANSIT_DURATION_RETURN + rand(-30, 60) //randomize this so it seems like the pods are being picked up one by one
|
||||
process_shuttles += shuttle
|
||||
shuttles["Escape Pod 3"] = shuttle
|
||||
|
||||
//There is no pod 4, apparently.
|
||||
|
||||
pod = new()
|
||||
pod.location = 0
|
||||
pod.warmup_time = 0
|
||||
pod.area_station = locate(/area/shuttle/escape_pod5/station)
|
||||
pod.area_offsite = locate(/area/shuttle/escape_pod5/centcom)
|
||||
pod.area_transition = locate(/area/shuttle/escape_pod5/transit)
|
||||
pod.travel_time = SHUTTLE_TRANSIT_DURATION_RETURN
|
||||
escape_pods += pod
|
||||
shuttle = new/datum/shuttle/ferry/escape_pod()
|
||||
shuttle.location = 0
|
||||
shuttle.warmup_time = 0
|
||||
shuttle.area_station = locate(/area/shuttle/escape_pod5/station)
|
||||
shuttle.area_offsite = locate(/area/shuttle/escape_pod5/centcom)
|
||||
shuttle.area_transition = locate(/area/shuttle/escape_pod5/transit)
|
||||
shuttle.docking_controller_tag = "escape_pod_5"
|
||||
shuttle.dock_target_station = "escape_pod_5_berth"
|
||||
shuttle.dock_target_offsite = "escape_pod_5_recovery"
|
||||
shuttle.transit_direction = EAST //should this be WEST? I have no idea.
|
||||
shuttle.move_time = SHUTTLE_TRANSIT_DURATION_RETURN + rand(-30, 60) //randomize this so it seems like the pods are being picked up one by one
|
||||
process_shuttles += shuttle
|
||||
shuttles["Escape Pod 5"] = shuttle
|
||||
|
||||
//give the emergency shuttle controller it's shuttles
|
||||
emergency_shuttle.shuttle = shuttles["Escape"]
|
||||
emergency_shuttle.escape_pods = list(
|
||||
shuttles["Escape Pod 1"],
|
||||
shuttles["Escape Pod 2"],
|
||||
shuttles["Escape Pod 3"],
|
||||
shuttles["Escape Pod 5"],
|
||||
)
|
||||
|
||||
// Supply shuttle
|
||||
shuttle = new/datum/shuttle/ferry/supply()
|
||||
shuttle.location = 1
|
||||
shuttle.warmup_time = 10
|
||||
shuttle.area_offsite = locate(/area/supply/dock)
|
||||
shuttle.area_station = locate(/area/supply/station)
|
||||
shuttle.docking_controller_tag = "supply_shuttle"
|
||||
shuttle.dock_target_station = "cargo_bay"
|
||||
shuttles["Supply"] = shuttle
|
||||
process_shuttles += shuttle
|
||||
|
||||
supply_controller.shuttle = shuttle
|
||||
|
||||
// Admin shuttles.
|
||||
shuttle = new()
|
||||
shuttle.location = 1
|
||||
shuttle.warmup_time = 10
|
||||
shuttle.area_offsite = locate(/area/shuttle/transport1/centcom)
|
||||
shuttle.area_station = locate(/area/shuttle/transport1/station)
|
||||
shuttle.docking_controller_tag = "centcom_shuttle"
|
||||
shuttle.dock_target_station = "centcom_shuttle_dock_airlock"
|
||||
shuttle.dock_target_offsite = "centcom_shuttle_bay"
|
||||
shuttles["Centcom"] = shuttle
|
||||
process_shuttles += shuttle
|
||||
|
||||
shuttle = new()
|
||||
shuttle.location = 1
|
||||
shuttle.warmup_time = 10 //want some warmup time so people can cancel.
|
||||
shuttle.area_offsite = locate(/area/shuttle/administration/centcom)
|
||||
shuttle.area_station = locate(/area/shuttle/administration/station)
|
||||
shuttle.docking_controller_tag = "admin_shuttle"
|
||||
shuttle.dock_target_station = "admin_shuttle_dock_airlock"
|
||||
shuttle.dock_target_offsite = "admin_shuttle_bay"
|
||||
shuttles["Administration"] = shuttle
|
||||
process_shuttles += shuttle
|
||||
|
||||
shuttle = new()
|
||||
shuttle.area_offsite = locate(/area/shuttle/alien/base)
|
||||
shuttle.area_station = locate(/area/shuttle/alien/mine)
|
||||
shuttles["Alien"] = shuttle
|
||||
//process_shuttles += shuttle //don't need to process this. It can only be moved using admin magic anyways.
|
||||
|
||||
// Public shuttles
|
||||
shuttle = new()
|
||||
shuttle.location = 1
|
||||
shuttle.warmup_time = 10
|
||||
shuttle.area_offsite = locate(/area/shuttle/constructionsite/site)
|
||||
shuttle.area_station = locate(/area/shuttle/constructionsite/station)
|
||||
shuttle.docking_controller_tag = "engineering_shuttle"
|
||||
shuttle.dock_target_station = "engineering_dock_airlock"
|
||||
shuttle.dock_target_offsite = "engineering_station_airlock"
|
||||
shuttles["Engineering"] = shuttle
|
||||
process_shuttles += shuttle
|
||||
|
||||
shuttle = new()
|
||||
shuttle.warmup_time = 10
|
||||
shuttle.area_offsite = locate(/area/shuttle/mining/outpost)
|
||||
shuttle.area_station = locate(/area/shuttle/mining/station)
|
||||
shuttle.docking_controller_tag = "mining_shuttle"
|
||||
shuttle.dock_target_station = "mining_dock_airlock"
|
||||
shuttle.dock_target_offsite = "mining_outpost_airlock"
|
||||
shuttles["Mining"] = shuttle
|
||||
process_shuttles += shuttle
|
||||
|
||||
shuttle = new()
|
||||
shuttle.warmup_time = 10
|
||||
shuttle.area_offsite = locate(/area/shuttle/research/outpost)
|
||||
shuttle.area_station = locate(/area/shuttle/research/station)
|
||||
shuttle.docking_controller_tag = "research_shuttle"
|
||||
shuttle.dock_target_station = "research_dock_airlock"
|
||||
shuttle.dock_target_offsite = "research_outpost_dock"
|
||||
shuttles["Research"] = shuttle
|
||||
process_shuttles += shuttle
|
||||
|
||||
// ERT Shuttle
|
||||
var/datum/shuttle/ferry/multidock/specops/ERT = new()
|
||||
ERT.location = 0
|
||||
ERT.warmup_time = 10
|
||||
ERT.area_offsite = locate(/area/shuttle/specops/station) //centcom is the home station, the Exodus is offsite
|
||||
ERT.area_station = locate(/area/shuttle/specops/centcom)
|
||||
ERT.docking_controller_tag = "specops_shuttle_port"
|
||||
ERT.docking_controller_tag_station = "specops_shuttle_port"
|
||||
ERT.docking_controller_tag_offsite = "specops_shuttle_fore"
|
||||
ERT.dock_target_station = "specops_centcom_dock"
|
||||
ERT.dock_target_offsite = "specops_dock_airlock"
|
||||
shuttles["Special Operations"] = ERT
|
||||
process_shuttles += ERT
|
||||
|
||||
//Vox Shuttle.
|
||||
var/datum/shuttle/multi_shuttle/VS = new/datum/shuttle/multi_shuttle()
|
||||
VS.origin = locate(/area/shuttle/vox/station)
|
||||
|
||||
VS.destinations = list(
|
||||
"Fore Starboard Solars" = locate(/area/vox_station/northeast_solars),
|
||||
"Fore Port Solars" = locate(/area/vox_station/northwest_solars),
|
||||
"Aft Starboard Solars" = locate(/area/vox_station/southeast_solars),
|
||||
"Aft Port Solars" = locate(/area/vox_station/southwest_solars),
|
||||
"Mining asteroid" = locate(/area/vox_station/mining)
|
||||
)
|
||||
|
||||
VS.announcer = "NSV Icarus"
|
||||
VS.arrival_message = "Attention, Exodus, we just tracked a small target bypassing our defensive perimeter. Can't fire on it without hitting the station - you've got incoming visitors, like it or not."
|
||||
VS.departure_message = "Your guests are pulling away, Exodus - moving too fast for us to draw a bead on them. Looks like they're heading out of the system at a rapid clip."
|
||||
VS.interim = locate(/area/vox_station/transit)
|
||||
|
||||
VS.warmup_time = 0
|
||||
shuttles["Vox Skipjack"] = VS
|
||||
|
||||
//Nuke Ops shuttle.
|
||||
var/datum/shuttle/multi_shuttle/MS = new/datum/shuttle/multi_shuttle()
|
||||
MS.origin = locate(/area/syndicate_station/start)
|
||||
|
||||
MS.destinations = list(
|
||||
"Northwest of the station" = locate(/area/syndicate_station/northwest),
|
||||
"North of the station" = locate(/area/syndicate_station/north),
|
||||
"Northeast of the station" = locate(/area/syndicate_station/northeast),
|
||||
"Southwest of the station" = locate(/area/syndicate_station/southwest),
|
||||
"South of the station" = locate(/area/syndicate_station/south),
|
||||
"Southeast of the station" = locate(/area/syndicate_station/southeast),
|
||||
"Telecomms Satellite" = locate(/area/syndicate_station/commssat),
|
||||
"Mining Asteroid" = locate(/area/syndicate_station/mining)
|
||||
)
|
||||
|
||||
MS.announcer = "NSV Icarus"
|
||||
MS.arrival_message = "Attention, Exodus, you have a large signature approaching the station - looks unarmed to surface scans. We're too far out to intercept - brace for visitors."
|
||||
MS.departure_message = "Your visitors are on their way out of the system, Exodus, burning delta-v like it's nothing. Good riddance."
|
||||
MS.interim = locate(/area/syndicate_station/transit)
|
||||
|
||||
MS.warmup_time = 0
|
||||
shuttles["Syndicate"] = MS
|
||||
|
||||
|
||||
/datum/shuttle_controller/emergency_shuttle/proc/process()
|
||||
if (wait_for_launch)
|
||||
if (auto_recall && world.time >= auto_recall_time)
|
||||
recall()
|
||||
if (world.time >= launch_time) //time to launch the shuttle
|
||||
wait_for_launch = 0
|
||||
|
||||
//set the travel time
|
||||
if (!shuttle.location) //leaving from the station
|
||||
//launch the pods!
|
||||
for (var/datum/shuttle/ferry/escape_pod/pod in escape_pods)
|
||||
pod.launch(src)
|
||||
//This is called by gameticker after all the machines and radio frequencies have been properly initialized
|
||||
/datum/shuttle_controller/proc/setup_shuttle_docks()
|
||||
var/datum/shuttle/shuttle
|
||||
var/datum/shuttle/ferry/multidock/multidock
|
||||
var/list/dock_controller_map = list() //so we only have to iterate once through each list
|
||||
|
||||
//multidock shuttles
|
||||
var/list/dock_controller_map_station = list()
|
||||
var/list/dock_controller_map_offsite = list()
|
||||
|
||||
for (var/shuttle_tag in shuttles)
|
||||
shuttle = shuttles[shuttle_tag]
|
||||
if (shuttle.docking_controller_tag)
|
||||
dock_controller_map[shuttle.docking_controller_tag] = shuttle
|
||||
if (istype(shuttle, /datum/shuttle/ferry/multidock))
|
||||
multidock = shuttle
|
||||
dock_controller_map_station[multidock.docking_controller_tag_station] = multidock
|
||||
dock_controller_map_offsite[multidock.docking_controller_tag_offsite] = multidock
|
||||
|
||||
//escape pod arming controllers
|
||||
var/datum/shuttle/ferry/escape_pod/pod
|
||||
var/list/pod_controller_map = list()
|
||||
for (var/datum/shuttle/ferry/escape_pod/P in emergency_shuttle.escape_pods)
|
||||
if (P.dock_target_station)
|
||||
pod_controller_map[P.dock_target_station] = P
|
||||
|
||||
//search for the controllers, if we have one.
|
||||
if (dock_controller_map.len)
|
||||
for (var/obj/machinery/embedded_controller/radio/C in machines) //only radio controllers are supported at the moment
|
||||
if (istype(C.program, /datum/computer/file/embedded_program/docking))
|
||||
if (C.id_tag in dock_controller_map)
|
||||
shuttle = dock_controller_map[C.id_tag]
|
||||
shuttle.docking_controller = C.program
|
||||
dock_controller_map -= C.id_tag
|
||||
|
||||
//escape pods
|
||||
if(istype(C, /obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod) && istype(shuttle, /datum/shuttle/ferry/escape_pod))
|
||||
var/obj/machinery/embedded_controller/radio/simple_docking_controller/escape_pod/EPC = C
|
||||
EPC.pod = shuttle
|
||||
|
||||
if (C.id_tag in dock_controller_map_station)
|
||||
multidock = dock_controller_map_station[C.id_tag]
|
||||
if (istype(multidock))
|
||||
multidock.docking_controller_station = C.program
|
||||
dock_controller_map_station -= C.id_tag
|
||||
if (C.id_tag in dock_controller_map_offsite)
|
||||
multidock = dock_controller_map_offsite[C.id_tag]
|
||||
if (istype(multidock))
|
||||
multidock.docking_controller_offsite = C.program
|
||||
dock_controller_map_offsite -= C.id_tag
|
||||
|
||||
shuttle.travel_time = SHUTTLE_TRANSIT_DURATION_RETURN
|
||||
else
|
||||
shuttle.travel_time = SHUTTLE_TRANSIT_DURATION
|
||||
|
||||
shuttle.launch(src)
|
||||
//escape pods
|
||||
if (C.id_tag in pod_controller_map)
|
||||
pod = pod_controller_map[C.id_tag]
|
||||
if (istype(C.program, /datum/computer/file/embedded_program/docking/simple/escape_pod/))
|
||||
pod.arming_controller = C.program
|
||||
|
||||
//process the shuttles
|
||||
if (shuttle.in_use)
|
||||
shuttle.process_shuttle()
|
||||
for (var/datum/shuttle/ferry/escape_pod/pod in escape_pods)
|
||||
if (pod.in_use)
|
||||
pod.process_shuttle()
|
||||
|
||||
//called when the shuttle has arrived.
|
||||
/datum/shuttle_controller/emergency_shuttle/proc/shuttle_arrived()
|
||||
if (!shuttle.location) //at station
|
||||
launch_time = world.time + SHUTTLE_LEAVETIME*10
|
||||
wait_for_launch = 1 //get ready to return
|
||||
|
||||
//so we don't have emergency_shuttle.shuttle.location everywhere
|
||||
/datum/shuttle_controller/emergency_shuttle/proc/location()
|
||||
if (!shuttle)
|
||||
return 1 //if we dont have a shuttle datum, just act like it's at centcom
|
||||
return shuttle.location
|
||||
|
||||
//calls the shuttle for an emergency evacuation
|
||||
/datum/shuttle_controller/emergency_shuttle/proc/call_evac()
|
||||
if(!can_call()) return
|
||||
//sanity check
|
||||
if (dock_controller_map.len || dock_controller_map_station.len || dock_controller_map_offsite.len)
|
||||
var/dat = ""
|
||||
for (var/dock_tag in dock_controller_map + dock_controller_map_station + dock_controller_map_offsite)
|
||||
dat += "\"[dock_tag]\", "
|
||||
world << "\red \b warning: shuttles with docking tags [dat] could not find their controllers!"
|
||||
|
||||
//set the launch timer
|
||||
launch_time = world.time + get_shuttle_prep_time()*10
|
||||
auto_recall_time = rand(world.time + 300, launch_time - 300)
|
||||
wait_for_launch = 1
|
||||
|
||||
evac = 1
|
||||
captain_announce("An emergency evacuation shuttle has been called. It will arrive in approximately [round(estimate_arrival_time()/60)] minutes.")
|
||||
world << sound('sound/AI/shuttlecalled.ogg')
|
||||
for(var/area/A in world)
|
||||
if(istype(A, /area/hallway))
|
||||
A.readyalert()
|
||||
|
||||
//calls the shuttle for a routine crew transfer
|
||||
/datum/shuttle_controller/emergency_shuttle/proc/call_transfer()
|
||||
if(!can_call()) return
|
||||
|
||||
//set the launch timer
|
||||
launch_time = world.time + get_shuttle_prep_time()
|
||||
auto_recall_time = rand(world.time + 300, launch_time - 300)
|
||||
wait_for_launch = 1
|
||||
|
||||
captain_announce("A crew transfer has been initiated. The shuttle has been called. It will arrive in [round(estimate_arrival_time()/60)] minutes.")
|
||||
|
||||
//recalls the shuttle
|
||||
/datum/shuttle_controller/emergency_shuttle/proc/recall()
|
||||
if (!can_recall()) return
|
||||
|
||||
wait_for_launch = 0
|
||||
shuttle.cancel_launch(src)
|
||||
|
||||
if (evac)
|
||||
captain_announce("The emergency shuttle has been recalled.")
|
||||
world << sound('sound/AI/shuttlerecalled.ogg')
|
||||
|
||||
for(var/area/A in world)
|
||||
if(istype(A, /area/hallway))
|
||||
A.readyreset()
|
||||
evac = 0
|
||||
else
|
||||
captain_announce("The scheduled crew transfer has been cancelled.")
|
||||
|
||||
/datum/shuttle_controller/emergency_shuttle/proc/can_call()
|
||||
if (deny_shuttle)
|
||||
return 0
|
||||
if (shuttle.moving_status != SHUTTLE_IDLE || !shuttle.location) //must be idle at centcom
|
||||
return 0
|
||||
if (wait_for_launch) //already launching
|
||||
return 0
|
||||
return 1
|
||||
|
||||
//this only returns 0 if it would absolutely make no sense to recall
|
||||
//e.g. the shuttle is already at the station or wasn't called to begin with
|
||||
//other reasons for the shuttle not being recallable should be handled elsewhere
|
||||
/datum/shuttle_controller/emergency_shuttle/proc/can_recall()
|
||||
if (shuttle.moving_status == SHUTTLE_INTRANSIT) //if the shuttle is already in transit then it's too late
|
||||
return 0
|
||||
if (!shuttle.location) //already at the station.
|
||||
return 0
|
||||
if (!wait_for_launch) //we weren't going anywhere, anyways...
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/datum/shuttle_controller/emergency_shuttle/proc/get_shuttle_prep_time()
|
||||
// During mutiny rounds, the shuttle takes twice as long.
|
||||
if(ticker && istype(ticker.mode,/datum/game_mode/mutiny))
|
||||
return SHUTTLE_PREPTIME * 3 //15 minutes
|
||||
|
||||
return SHUTTLE_PREPTIME
|
||||
|
||||
|
||||
/*
|
||||
These procs are not really used by the controller itself, but are for other parts of the
|
||||
game whose logic depends on the emergency shuttle.
|
||||
*/
|
||||
|
||||
//returns the time left until the shuttle arrives at it's destination, in seconds
|
||||
/datum/shuttle_controller/emergency_shuttle/proc/estimate_arrival_time()
|
||||
var/eta
|
||||
if (isnull(shuttle.jump_time))
|
||||
eta = launch_time + shuttle.travel_time
|
||||
else
|
||||
eta = shuttle.jump_time + shuttle.travel_time
|
||||
return (eta - world.time)/10
|
||||
|
||||
//returns the time left until the shuttle launches, in seconds
|
||||
/datum/shuttle_controller/emergency_shuttle/proc/estimate_launch_time()
|
||||
return (launch_time - world.time)/10
|
||||
|
||||
/datum/shuttle_controller/emergency_shuttle/proc/has_eta()
|
||||
return (wait_for_launch || shuttle.moving_status != SHUTTLE_IDLE)
|
||||
|
||||
//returns 1 if the shuttle has gone to the station and come back at least once,
|
||||
//used for game completion checking purposes
|
||||
/datum/shuttle_controller/emergency_shuttle/proc/returned()
|
||||
return (departed && shuttle.moving_status != SHUTTLE_IDLE && shuttle.location) //we've gone to the station at least once, no longer in transit and are idle back at centcom
|
||||
|
||||
//returns 1 if the shuttle is not idle at centcom
|
||||
/datum/shuttle_controller/emergency_shuttle/proc/online()
|
||||
if (!shuttle.location) //not at centcom
|
||||
return 1
|
||||
if (wait_for_launch || shuttle.moving_status != SHUTTLE_IDLE)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//returns 1 if the shuttle is currently in transit (or just leaving) to the station
|
||||
/datum/shuttle_controller/emergency_shuttle/proc/going_to_station()
|
||||
return (!shuttle.direction && shuttle.moving_status != SHUTTLE_IDLE)
|
||||
|
||||
//returns 1 if the shuttle is currently in transit (or just leaving) to centcom
|
||||
/datum/shuttle_controller/emergency_shuttle/proc/going_to_centcom()
|
||||
return (shuttle.direction && shuttle.moving_status != SHUTTLE_IDLE)
|
||||
|
||||
//returns 1 if the shuttle is docked at the station and waiting to leave
|
||||
/datum/shuttle_controller/emergency_shuttle/proc/waiting_to_leave()
|
||||
if (shuttle.location)
|
||||
return 0 //not at station
|
||||
if (!wait_for_launch)
|
||||
return 0 //not going anywhere
|
||||
if (shuttle.moving_status != SHUTTLE_IDLE)
|
||||
return 0 //shuttle is doing stuff
|
||||
return 1
|
||||
|
||||
/*
|
||||
Some slapped-together star effects for maximum spess immershuns. Basically consists of a
|
||||
spawner, an ender, and bgstar. Spawners create bgstars, bgstars shoot off into a direction
|
||||
until they reach a starender.
|
||||
*/
|
||||
|
||||
/obj/effect/bgstar
|
||||
name = "star"
|
||||
var/speed = 10
|
||||
var/direction = SOUTH
|
||||
layer = 2 // TURF_LAYER
|
||||
|
||||
/obj/effect/bgstar/New()
|
||||
..()
|
||||
pixel_x += rand(-2,30)
|
||||
pixel_y += rand(-2,30)
|
||||
var/starnum = pick("1", "1", "1", "2", "3", "4")
|
||||
|
||||
icon_state = "star"+starnum
|
||||
|
||||
speed = rand(2, 5)
|
||||
|
||||
/obj/effect/bgstar/proc/startmove()
|
||||
|
||||
while(src)
|
||||
sleep(speed)
|
||||
step(src, direction)
|
||||
for(var/obj/effect/starender/E in loc)
|
||||
del(src)
|
||||
|
||||
|
||||
/obj/effect/starender
|
||||
invisibility = 101
|
||||
|
||||
/obj/effect/starspawner
|
||||
invisibility = 101
|
||||
var/spawndir = SOUTH
|
||||
var/spawning = 0
|
||||
|
||||
/obj/effect/starspawner/West
|
||||
spawndir = WEST
|
||||
|
||||
/obj/effect/starspawner/proc/startspawn()
|
||||
spawning = 1
|
||||
while(spawning)
|
||||
sleep(rand(2, 30))
|
||||
var/obj/effect/bgstar/S = new/obj/effect/bgstar(locate(x,y,z))
|
||||
S.direction = spawndir
|
||||
spawn()
|
||||
S.startmove()
|
||||
|
||||
|
||||
//makes all shuttles docked to something at round start go into the docked state
|
||||
for (var/shuttle_tag in shuttles)
|
||||
shuttle = shuttles[shuttle_tag]
|
||||
shuttle.dock()
|
||||
|
||||
@@ -1,6 +1,27 @@
|
||||
//TODO: rewrite and standardise all controller datums to the datum/controller type
|
||||
//TODO: allow all controllers to be deleted for clean restarts (see WIP master controller stuff) - MC done - lighting done
|
||||
|
||||
/client/proc/show_distribution_map()
|
||||
set category = "Debug"
|
||||
set name = "Show Distribution Map"
|
||||
set desc = "Print the asteroid ore distribution map to the world."
|
||||
|
||||
if(!holder) return
|
||||
|
||||
if(master_controller && master_controller.asteroid_ore_map)
|
||||
master_controller.asteroid_ore_map.print_distribution_map()
|
||||
|
||||
/client/proc/remake_distribution_map()
|
||||
set category = "Debug"
|
||||
set name = "Remake Distribution Map"
|
||||
set desc = "Rebuild the asteroid ore distribution map."
|
||||
|
||||
if(!holder) return
|
||||
|
||||
if(master_controller && master_controller.asteroid_ore_map)
|
||||
master_controller.asteroid_ore_map = new /datum/ore_distribution()
|
||||
master_controller.asteroid_ore_map.populate_distribution_map()
|
||||
|
||||
/client/proc/restart_controller(controller in list("Master","Failsafe","Lighting","Supply"))
|
||||
set category = "Debug"
|
||||
set name = "Restart Controller"
|
||||
@@ -27,8 +48,7 @@
|
||||
message_admins("Admin [key_name_admin(usr)] has restarted the [controller] controller.")
|
||||
return
|
||||
|
||||
|
||||
/client/proc/debug_controller(controller in list("Master","Failsafe","Ticker","Lighting","Air","Jobs","Sun","Radio","Supply","Emergency Shuttle","Configuration","pAI", "Cameras", "Transfer Controller"))
|
||||
/client/proc/debug_controller(controller in list("Master","Failsafe","Ticker","Lighting","Air","Jobs","Sun","Radio","Supply","Shuttles","Emergency Shuttle","Configuration","pAI", "Cameras", "Transfer Controller"))
|
||||
set category = "Debug"
|
||||
set name = "Debug Controller"
|
||||
set desc = "Debug the various periodic loop controllers for the game (be careful!)"
|
||||
@@ -62,6 +82,9 @@
|
||||
if("Supply")
|
||||
debug_variables(supply_controller)
|
||||
feedback_add_details("admin_verb","DSupply")
|
||||
if("Shuttles")
|
||||
debug_variables(shuttle_controller)
|
||||
feedback_add_details("admin_verb","DShuttles")
|
||||
if("Emergency Shuttle")
|
||||
debug_variables(emergency_shuttle)
|
||||
feedback_add_details("admin_verb","DEmergency")
|
||||
|
||||
+10
-4
@@ -13,6 +13,7 @@
|
||||
var/body_elements
|
||||
var/head_content = ""
|
||||
var/content = ""
|
||||
var/title_buttons = ""
|
||||
|
||||
|
||||
/datum/browser/New(nuser, nwindow_id, ntitle = 0, nwidth = 0, nheight = 0, var/atom/nref = null)
|
||||
@@ -29,9 +30,15 @@
|
||||
ref = nref
|
||||
add_stylesheet("common", 'html/browser/common.css') // this CSS sheet is common to all UIs
|
||||
|
||||
/datum/browser/proc/set_title(ntitle)
|
||||
title = format_text(ntitle)
|
||||
|
||||
/datum/browser/proc/add_head_content(nhead_content)
|
||||
head_content = nhead_content
|
||||
|
||||
/datum/browser/proc/set_title_buttons(ntitle_buttons)
|
||||
title_buttons = ntitle_buttons
|
||||
|
||||
/datum/browser/proc/set_window_options(nwindow_options)
|
||||
window_options = nwindow_options
|
||||
|
||||
@@ -75,7 +82,7 @@
|
||||
</head>
|
||||
<body scroll=auto>
|
||||
<div class='uiWrapper'>
|
||||
[title ? "<div class='uiTitleWrapper'><div [title_attributes]><tt>[title]</tt></div></div>" : ""]
|
||||
[title ? "<div class='uiTitleWrapper'><div [title_attributes]><tt>[title]</tt></div><div class='uiTitleButtons'>[title_buttons]</div></div>" : ""]
|
||||
<div class='uiContent'>
|
||||
"}
|
||||
|
||||
@@ -137,7 +144,7 @@
|
||||
// Otherwise, the user mob's machine var will be reset directly.
|
||||
//
|
||||
/proc/onclose(mob/user, windowid, var/atom/ref=null)
|
||||
if(!user.client) return
|
||||
if(!user || !user.client) return
|
||||
var/param = "null"
|
||||
if(ref)
|
||||
param = "\ref[ref]"
|
||||
@@ -159,11 +166,10 @@
|
||||
//world << "windowclose: [atomref]"
|
||||
if(atomref!="null") // if passed a real atomref
|
||||
var/hsrc = locate(atomref) // find the reffed atom
|
||||
var/href = "close=1"
|
||||
if(hsrc)
|
||||
//world << "[src] Topic [href] [hsrc]"
|
||||
usr = src.mob
|
||||
src.Topic(href, params2list(href), hsrc) // this will direct to the atom's
|
||||
src.Topic("close=1", list("close"="1"), hsrc) // this will direct to the atom's
|
||||
return // Topic() proc via client.Topic()
|
||||
|
||||
// no atomref specified (or not found)
|
||||
|
||||
@@ -146,7 +146,7 @@ proc/get_id_photo(var/mob/living/carbon/human/H)
|
||||
if(E.status & ORGAN_ROBOT)
|
||||
temp.MapColors(rgb(77,77,77), rgb(150,150,150), rgb(28,28,28), rgb(0,0,0))
|
||||
preview_icon.Blend(temp, ICON_OVERLAY)
|
||||
|
||||
|
||||
//Tail
|
||||
if(H.species.tail && H.species.flags & HAS_TAIL)
|
||||
temp = new/icon("icon" = 'icons/effects/species.dmi', "icon_state" = "[H.species.tail]_s")
|
||||
@@ -188,7 +188,7 @@ proc/get_id_photo(var/mob/living/carbon/human/H)
|
||||
if("Bartender")
|
||||
clothes_s = new /icon('icons/mob/uniform.dmi', "ba_suit_s")
|
||||
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
|
||||
if("Botanist")
|
||||
if("Gardener")
|
||||
clothes_s = new /icon('icons/mob/uniform.dmi', "hydroponics_s")
|
||||
clothes_s.Blend(new /icon('icons/mob/feet.dmi', "black"), ICON_UNDERLAY)
|
||||
if("Chef")
|
||||
|
||||
@@ -108,12 +108,19 @@
|
||||
|
||||
playSpecials(curturf,effectin,soundin)
|
||||
|
||||
var/obj/structure/stool/bed/chair/C = null
|
||||
if(isliving(teleatom))
|
||||
var/mob/living/L = teleatom
|
||||
if(L.buckled)
|
||||
C = L.buckled
|
||||
if(force_teleport)
|
||||
teleatom.forceMove(destturf)
|
||||
playSpecials(destturf,effectout,soundout)
|
||||
else
|
||||
if(teleatom.Move(destturf))
|
||||
playSpecials(destturf,effectout,soundout)
|
||||
if(C)
|
||||
C.forceMove(destturf)
|
||||
|
||||
destarea.Entered(teleatom)
|
||||
|
||||
|
||||
@@ -631,6 +631,10 @@ var/list/ghostteleportlocs = list()
|
||||
name = "Engineering Shuttle Access"
|
||||
icon_state = "asmaint"
|
||||
|
||||
/area/maintenance/engi_engine
|
||||
name = "Engine Maintenance"
|
||||
icon_state = "asmaint"
|
||||
|
||||
/area/maintenance/asmaint2
|
||||
name = "Science Maintenance"
|
||||
icon_state = "asmaint"
|
||||
@@ -795,6 +799,10 @@ var/list/ghostteleportlocs = list()
|
||||
name = "\improper Engineering Dormitories"
|
||||
icon_state = "Sleep"
|
||||
|
||||
/area/crew_quarters/sleep/engi_wash
|
||||
name = "\improper Engineering Washroom"
|
||||
icon_state = "toilet"
|
||||
|
||||
/area/crew_quarters/sleep/sec
|
||||
name = "\improper Security Dormitories"
|
||||
icon_state = "Sleep"
|
||||
@@ -1362,9 +1370,13 @@ var/list/ghostteleportlocs = list()
|
||||
icon_state = "janitor"
|
||||
|
||||
/area/hydroponics
|
||||
name = "Hydroponics"
|
||||
name = "\improper Hydroponics"
|
||||
icon_state = "hydro"
|
||||
|
||||
/area/hydroponics/garden
|
||||
name = "\improper Garden"
|
||||
icon_state = "garden"
|
||||
|
||||
//rnd (Research and Development
|
||||
|
||||
/area/rnd/lab
|
||||
@@ -1385,7 +1397,15 @@ var/list/ghostteleportlocs = list()
|
||||
|
||||
/area/rnd/xenobiology
|
||||
name = "\improper Xenobiology Lab"
|
||||
icon_state = "toxlab"
|
||||
icon_state = "xeno_lab"
|
||||
|
||||
/area/rnd/xenobiology/xenoflora_storage
|
||||
name = "\improper Xenoflora Storage"
|
||||
icon_state = "xeno_f_store"
|
||||
|
||||
/area/rnd/xenobiology/xenoflora
|
||||
name = "\improper Xenoflora Lab"
|
||||
icon_state = "xeno_f_lab"
|
||||
|
||||
/area/rnd/storage
|
||||
name = "\improper Toxins Storage"
|
||||
@@ -1685,6 +1705,10 @@ var/list/ghostteleportlocs = list()
|
||||
name = "\improper AI Chamber"
|
||||
icon_state = "ai_chamber"
|
||||
|
||||
/area/turret_protected/ai_cyborg_station
|
||||
name = "\improper Cyborg Station"
|
||||
icon_state = "ai_cyborg"
|
||||
|
||||
/area/turret_protected/aisat
|
||||
name = "\improper AI Satellite"
|
||||
icon_state = "ai"
|
||||
|
||||
+50
-11
@@ -71,32 +71,71 @@
|
||||
/area/proc/atmosalert(danger_level)
|
||||
// if(type==/area) //No atmos alarms in space
|
||||
// return 0 //redudant
|
||||
|
||||
//Check all the alarms before lowering atmosalm. Raising is perfectly fine.
|
||||
for (var/area/RA in related)
|
||||
for (var/obj/machinery/alarm/AA in RA)
|
||||
if ( !(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted)
|
||||
danger_level = max(danger_level, AA.danger_level)
|
||||
|
||||
if(danger_level != atmosalm)
|
||||
//updateicon()
|
||||
//mouse_opacity = 0
|
||||
if (danger_level==2)
|
||||
if (danger_level < 1 && atmosalm >= 1)
|
||||
//closing the doors on red and opening on green provides a bit of hysteresis that will hopefully prevent fire doors from opening and closing repeatedly due to noise
|
||||
air_doors_open()
|
||||
|
||||
if (danger_level < 2 && atmosalm >= 2)
|
||||
for(var/area/RA in related)
|
||||
for(var/obj/machinery/camera/C in RA)
|
||||
C.network.Remove("Atmosphere Alarms")
|
||||
for (var/obj/machinery/alarm/AA in RA)
|
||||
AA.update_icon()
|
||||
for(var/mob/living/silicon/aiPlayer in player_list)
|
||||
aiPlayer.cancelAlarm("Atmosphere", src, src)
|
||||
for(var/obj/machinery/computer/station_alert/a in machines)
|
||||
a.cancelAlarm("Atmosphere", src, src)
|
||||
|
||||
if (danger_level >= 2 && atmosalm < 2)
|
||||
var/list/cameras = list()
|
||||
for(var/area/RA in related)
|
||||
//updateicon()
|
||||
for(var/obj/machinery/camera/C in RA)
|
||||
cameras += C
|
||||
C.network.Add("Atmosphere Alarms")
|
||||
for (var/obj/machinery/alarm/AA in RA)
|
||||
AA.update_icon()
|
||||
for(var/mob/living/silicon/aiPlayer in player_list)
|
||||
aiPlayer.triggerAlarm("Atmosphere", src, cameras, src)
|
||||
for(var/obj/machinery/computer/station_alert/a in machines)
|
||||
a.triggerAlarm("Atmosphere", src, cameras, src)
|
||||
else if (atmosalm == 2)
|
||||
for(var/area/RA in related)
|
||||
for(var/obj/machinery/camera/C in RA)
|
||||
C.network.Remove("Atmosphere Alarms")
|
||||
for(var/mob/living/silicon/aiPlayer in player_list)
|
||||
aiPlayer.cancelAlarm("Atmosphere", src, src)
|
||||
for(var/obj/machinery/computer/station_alert/a in machines)
|
||||
a.cancelAlarm("Atmosphere", src, src)
|
||||
air_doors_close()
|
||||
|
||||
atmosalm = danger_level
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/area/proc/air_doors_close()
|
||||
if(!src.master.air_doors_activated)
|
||||
src.master.air_doors_activated = 1
|
||||
for(var/obj/machinery/door/firedoor/E in src.master.all_doors)
|
||||
if(!E:blocked)
|
||||
if(E.operating)
|
||||
E:nextstate = CLOSED
|
||||
else if(!E.density)
|
||||
spawn(0)
|
||||
E.close()
|
||||
|
||||
/area/proc/air_doors_open()
|
||||
if(src.master.air_doors_activated)
|
||||
src.master.air_doors_activated = 0
|
||||
for(var/obj/machinery/door/firedoor/E in src.master.all_doors)
|
||||
if(!E:blocked)
|
||||
if(E.operating)
|
||||
E:nextstate = OPEN
|
||||
else if(E.density)
|
||||
spawn(0)
|
||||
E.open()
|
||||
|
||||
|
||||
/area/proc/firealert()
|
||||
if(name == "Space") //no fire alarms in space
|
||||
return
|
||||
|
||||
@@ -401,7 +401,7 @@
|
||||
occupantData["structuralEnzymes"] = null
|
||||
occupantData["radiationLevel"] = null
|
||||
else
|
||||
occupantData["name"] = connected.occupant.name
|
||||
occupantData["name"] = connected.occupant.real_name
|
||||
occupantData["stat"] = connected.occupant.stat
|
||||
occupantData["isViableSubject"] = 1
|
||||
if (NOCLONE in connected.occupant.mutations || !src.connected.occupant.dna)
|
||||
@@ -551,7 +551,7 @@
|
||||
if (href_list["selectUIBlock"] && href_list["selectUISubblock"]) // This chunk of code updates selected block / sub-block based on click
|
||||
var/select_block = text2num(href_list["selectUIBlock"])
|
||||
var/select_subblock = text2num(href_list["selectUISubblock"])
|
||||
if ((select_block <= 13) && (select_block >= 1))
|
||||
if ((select_block <= DNA_UI_LENGTH) && (select_block >= 1))
|
||||
src.selected_ui_block = select_block
|
||||
if ((select_subblock <= DNA_BLOCK_SIZE) && (select_subblock >= 1))
|
||||
src.selected_ui_subblock = select_subblock
|
||||
@@ -704,7 +704,7 @@
|
||||
databuf.types = DNA2_BUF_UE
|
||||
databuf.dna = src.connected.occupant.dna.Clone()
|
||||
if(ishuman(connected.occupant))
|
||||
databuf.dna.real_name=connected.occupant.name
|
||||
databuf.dna.real_name=connected.occupant.dna.real_name
|
||||
databuf.name = "Unique Identifier"
|
||||
src.buffers[bufferId] = databuf
|
||||
return 1
|
||||
@@ -715,7 +715,7 @@
|
||||
databuf.types = DNA2_BUF_UI|DNA2_BUF_UE
|
||||
databuf.dna = src.connected.occupant.dna.Clone()
|
||||
if(ishuman(connected.occupant))
|
||||
databuf.dna.real_name=connected.occupant.name
|
||||
databuf.dna.real_name=connected.occupant.dna.real_name
|
||||
databuf.name = "Unique Identifier + Unique Enzymes"
|
||||
src.buffers[bufferId] = databuf
|
||||
return 1
|
||||
@@ -726,7 +726,7 @@
|
||||
databuf.types = DNA2_BUF_SE
|
||||
databuf.dna = src.connected.occupant.dna.Clone()
|
||||
if(ishuman(connected.occupant))
|
||||
databuf.dna.real_name=connected.occupant.name
|
||||
databuf.dna.real_name=connected.occupant.dna.real_name
|
||||
databuf.name = "Structural Enzymes"
|
||||
src.buffers[bufferId] = databuf
|
||||
return 1
|
||||
|
||||
@@ -87,7 +87,7 @@
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/* temperature_expose(datum/gas_mixture/air, temperature, volume) Blob is currently fireproof
|
||||
/* fire_act(datum/gas_mixture/air, temperature, volume) Blob is currently fireproof
|
||||
if(temperature > T0C+200)
|
||||
health -= 0.01 * temperature
|
||||
update()
|
||||
|
||||
@@ -111,12 +111,13 @@
|
||||
src.visible_message("<span class='warning'>[src] transforms!</span>")
|
||||
|
||||
src.verbs -= /mob/proc/changeling_change_species
|
||||
spawn(10) src.verbs += /mob/proc/changeling_change_species
|
||||
H.set_species(S,null,1) //Until someone moves body colour into DNA, they're going to have to use the default.
|
||||
|
||||
H.set_species(S)
|
||||
spawn(10)
|
||||
src.verbs += /mob/proc/changeling_change_species
|
||||
src.regenerate_icons()
|
||||
|
||||
changeling_update_languages(changeling.absorbed_languages)
|
||||
|
||||
feedback_add_details("changeling_powers","TR")
|
||||
|
||||
return 1
|
||||
|
||||
@@ -154,7 +154,7 @@
|
||||
return
|
||||
return
|
||||
|
||||
/obj/effect/biomass/temperature_expose(null, temp, volume) //hotspots kill biomass
|
||||
/obj/effect/biomass/fire_act(null, temp, volume) //hotspots kill biomass
|
||||
del src
|
||||
|
||||
|
||||
|
||||
@@ -239,7 +239,7 @@
|
||||
return
|
||||
return
|
||||
|
||||
/obj/effect/spacevine/temperature_expose(null, temp, volume) //hotspots kill vines
|
||||
/obj/effect/spacevine/fire_act(null, temp, volume) //hotspots kill vines
|
||||
del src
|
||||
|
||||
//Carn: Spacevines random event.
|
||||
|
||||
@@ -130,7 +130,7 @@ var/global/datum/controller/gameticker/ticker
|
||||
//here to initialize the random events nicely at round start
|
||||
setup_economy()
|
||||
|
||||
setup_shuttle_docks()
|
||||
shuttle_controller.setup_shuttle_docks()
|
||||
|
||||
spawn(0)//Forking here so we dont have to wait for this to finish
|
||||
mode.post_setup()
|
||||
|
||||
@@ -106,9 +106,19 @@ VOX HEIST ROUNDTYPE
|
||||
vox.f_style = "Shaved"
|
||||
for(var/datum/organ/external/limb in vox.organs)
|
||||
limb.status &= ~(ORGAN_DESTROYED | ORGAN_ROBOT)
|
||||
|
||||
//Now apply cortical stack.
|
||||
var/datum/organ/external/E = vox.get_organ("head")
|
||||
var/obj/item/weapon/implant/cortical/I = new(vox)
|
||||
I.imp_in = vox
|
||||
I.implanted = 1
|
||||
I.part = E
|
||||
E.implants += I
|
||||
cortical_stacks += I
|
||||
|
||||
vox.equip_vox_raider()
|
||||
vox.regenerate_icons()
|
||||
|
||||
|
||||
raider.objectives = raid_objectives
|
||||
greet_vox(raider)
|
||||
|
||||
@@ -272,9 +282,9 @@ datum/game_mode/proc/auto_declare_completion_heist()
|
||||
return 1
|
||||
|
||||
/datum/game_mode/heist/check_finished()
|
||||
// DO NOT FORGET TO FIX THIS.
|
||||
//if (!(is_raider_crew_alive()) || (vox_shuttle_location && (vox_shuttle_location == "start")))
|
||||
// return 1
|
||||
var/datum/shuttle/multi_shuttle/skipjack = shuttle_controller.shuttles["Vox Skipjack"]
|
||||
if (!(is_raider_crew_alive()) || (skipjack && skipjack.returned_home))
|
||||
return 1
|
||||
return ..()
|
||||
|
||||
/datum/game_mode/heist/cleanup()
|
||||
@@ -284,4 +294,4 @@ datum/game_mode/proc/auto_declare_completion_heist()
|
||||
//maybe send the player a message that they've gone home/been kidnapped? Someone responsible for vox lore should write that.
|
||||
Del(M)
|
||||
for (var/obj/O in skipjack.contents)
|
||||
Del(O) //no hiding in lockers or anything
|
||||
Del(O) //no hiding in lockers or anything
|
||||
|
||||
@@ -11,7 +11,7 @@ datum/directive/terminations/alien_fraud
|
||||
datum/directive/terminations/alien_fraud/get_crew_to_terminate()
|
||||
var/list/aliens[0]
|
||||
for(var/mob/M in player_list)
|
||||
if (is_alien(M) && M.is_ready())
|
||||
if (M.is_ready() && is_alien(M))
|
||||
aliens.Add(M)
|
||||
return aliens
|
||||
|
||||
|
||||
@@ -6,7 +6,7 @@ datum/directive/bluespace_contagion
|
||||
proc/get_infection_candidates()
|
||||
var/list/candidates[0]
|
||||
for(var/mob/M in player_list)
|
||||
if (!M.is_mechanical() && M.is_ready())
|
||||
if (M.is_ready() && !M.is_mechanical())
|
||||
candidates.Add(M)
|
||||
return candidates
|
||||
|
||||
@@ -14,7 +14,7 @@ datum/directive/bluespace_contagion/get_description()
|
||||
return {"
|
||||
<p>
|
||||
A manufactured and near-undetectable virus is spreading on NanoTrasen stations.
|
||||
The pathogen travels by bluespace after maturing for one day.
|
||||
The pathogen travels by bluespace after maturing for one day and meets the Sol Health Organisation standards for a class X biological threat, warranting use of lethal force to contain an outbreak.
|
||||
No treatment has yet been discovered. Personnel onboard [station_name()] have been infected. Further information is classified.
|
||||
</p>
|
||||
"}
|
||||
@@ -34,7 +34,7 @@ datum/directive/bluespace_contagion/initialize()
|
||||
special_orders = list(
|
||||
"Quarantine these personnel: [list2text(infected_names, ", ")].",
|
||||
"Allow one hour for a cure to be manufactured.",
|
||||
"If no cure arrives after that time, execute the infected.")
|
||||
"If no cure arrives after that time, execute and burn the infected.")
|
||||
|
||||
datum/directive/bluespace_contagion/meets_prerequisites()
|
||||
var/list/candidates = get_infection_candidates()
|
||||
|
||||
@@ -8,7 +8,7 @@ datum/directive/terminations/financial_crisis/get_crew_to_terminate()
|
||||
var/list/civilians[0]
|
||||
var/list/candidates = civilian_positions - "Head of Personnel"
|
||||
for(var/mob/M in player_list)
|
||||
if (candidates.Find(M.mind.assigned_role) && M.is_ready())
|
||||
if (M.is_ready() && candidates.Find(M.mind.assigned_role))
|
||||
civilians.Add(M)
|
||||
return civilians
|
||||
|
||||
@@ -16,7 +16,7 @@ datum/directive/terminations/financial_crisis/get_description()
|
||||
return {"
|
||||
<p>
|
||||
[system_name()] system banks in financial crisis. Local emergency situation ongoing.
|
||||
NT Funds redistributed, impact upon civilian department expected.
|
||||
NT Funds redistributed in accordance with financial regulations covered by employee contracts, impact upon civilian department expected.
|
||||
Further information is classified.
|
||||
</p>
|
||||
"}
|
||||
|
||||
@@ -16,14 +16,14 @@ datum/directive/ipc_virus
|
||||
proc/get_ipcs()
|
||||
var/list/machines[0]
|
||||
for(var/mob/M in player_list)
|
||||
if (M.get_species() == "Machine" && M.is_ready())
|
||||
if (M.is_ready() && M.get_species() == "Machine")
|
||||
machines.Add(M)
|
||||
return machines
|
||||
|
||||
proc/get_roboticists()
|
||||
var/list/roboticists[0]
|
||||
for(var/mob/M in player_list)
|
||||
if (roboticist_roles.Find(M.mind.assigned_role) && M.is_ready())
|
||||
if (M.is_ready() && roboticist_roles.Find(M.mind.assigned_role))
|
||||
roboticists.Add(M)
|
||||
return roboticists
|
||||
|
||||
|
||||
@@ -10,7 +10,7 @@ datum/directive/research_to_ripleys
|
||||
proc/get_researchers()
|
||||
var/list/researchers[0]
|
||||
for(var/mob/M in player_list)
|
||||
if (is_researcher(M) && M.is_ready())
|
||||
if (M.is_ready() && is_researcher(M))
|
||||
researchers.Add(M)
|
||||
return researchers
|
||||
|
||||
|
||||
@@ -13,7 +13,7 @@ datum/directive/tau_ceti_needs_women
|
||||
proc/get_crew_of_target_gender()
|
||||
var/list/targets[0]
|
||||
for(var/mob/M in player_list)
|
||||
if(is_target_gender(M) && !M.is_mechanical() && M.is_ready())
|
||||
if(M.is_ready() && is_target_gender(M) && !M.is_mechanical())
|
||||
targets.Add(M)
|
||||
return targets
|
||||
|
||||
@@ -63,7 +63,7 @@ datum/directive/tau_ceti_needs_women/meets_prerequisites()
|
||||
var/females = 0
|
||||
var/males = 0
|
||||
for(var/mob/M in player_list)
|
||||
if(!M.is_mechanical() && M.get_species() != "Diona" && M.is_ready())
|
||||
if(M.is_ready() && !M.is_mechanical() && M.get_species() != "Diona")
|
||||
var/gender = M.get_gender()
|
||||
if(gender == MALE)
|
||||
males++
|
||||
|
||||
@@ -27,13 +27,47 @@ datum/game_mode/mutiny
|
||||
|
||||
proc/reveal_directives()
|
||||
spawn(rand(1 MINUTE, 3 MINUTES))
|
||||
fluff.announce_incoming_fax()
|
||||
command_alert("Incoming emergency directive: Captain's office fax machine, [station_name()].","Emergency Transmission")
|
||||
spawn(rand(3 MINUTES, 5 MINUTES))
|
||||
send_pda_message()
|
||||
spawn(rand(3 MINUTES, 5 MINUTES))
|
||||
fluff.announce_directives()
|
||||
spawn(rand(2 MINUTES, 3 MINUTE))
|
||||
fluff.announce_ert_unavailable()
|
||||
|
||||
var/list/reasons = list(
|
||||
"political instability",
|
||||
"quantum fluctuations",
|
||||
"hostile raiders",
|
||||
"derelict station debris",
|
||||
"REDACTED",
|
||||
"ancient alien artillery",
|
||||
"solar magnetic storms",
|
||||
"sentient time-travelling killbots",
|
||||
"gravitational anomalies",
|
||||
"wormholes to another dimension",
|
||||
"a telescience mishap",
|
||||
"radiation flares",
|
||||
"supermatter dust",
|
||||
"leaks into a negative reality",
|
||||
"antiparticle clouds",
|
||||
"residual bluespace energy",
|
||||
"suspected syndicate operatives",
|
||||
"malfunctioning von Neumann probe swarms",
|
||||
"shadowy interlopers",
|
||||
"a stranded Vox arkship",
|
||||
"haywire IPC constructs",
|
||||
"rogue Unathi exiles",
|
||||
"artifacts of eldritch horror",
|
||||
"a brain slug infestation",
|
||||
"killer bugs that lay eggs in the husks of the living",
|
||||
"a deserted transport carrying xenomorph specimens",
|
||||
"an emissary for the gestalt requesting a security detail",
|
||||
"a Tajaran slave rebellion",
|
||||
"radical Skrellian transevolutionaries",
|
||||
"classified security operations",
|
||||
"science-defying raw elemental chaos"
|
||||
)
|
||||
command_alert("The presence of [pick(reasons)] in the region is tying up all available local emergency resources; emergency response teams cannot be called at this time.","Emergency Transmission")
|
||||
|
||||
// Returns an array in case we want to expand on this later.
|
||||
proc/get_head_loyalist_candidates()
|
||||
|
||||
@@ -4,19 +4,6 @@
|
||||
New(datum/game_mode/mutiny/M)
|
||||
mode = M
|
||||
|
||||
proc/centcom_announce(text)
|
||||
world << {"
|
||||
<font color='#FFA500'><hr><center><b>:-:=:-: CENTRAL COMMAND ANNOUNCEMENT :-:=:-:</b></center><hr></font>
|
||||
[text]
|
||||
"}
|
||||
world << sound('sound/AI/commandreport.ogg')
|
||||
|
||||
proc/announce_incoming_fax()
|
||||
centcom_announce({"
|
||||
<b>Incoming Emergency Directive:</b>
|
||||
<i>Captain's Office Fax Machine, [station_name()]</i>
|
||||
"})
|
||||
|
||||
proc/announce_directives()
|
||||
for (var/obj/machinery/faxmachine/fax in world)
|
||||
if (fax.department == "Captain's Office")
|
||||
@@ -84,46 +71,6 @@ They don't care about us they only care about WEALTH and POWER... Share this mes
|
||||
|
||||
Be safe, friend.\" (Unable to Reply)</p>"}
|
||||
|
||||
|
||||
proc/announce_ert_unavailable()
|
||||
// I might have gotten a little carried away.
|
||||
centcom_announce({"
|
||||
<p>The presence of [pick(
|
||||
"political instability",
|
||||
"quantum fluctuations",
|
||||
"hostile raiders",
|
||||
"derelict station debris",
|
||||
"REDACTED",
|
||||
"ancient alien artillery",
|
||||
"solar magnetic storms",
|
||||
"sentient time-travelling killbots",
|
||||
"gravitational anomalies",
|
||||
"wormholes to another dimension",
|
||||
"a telescience mishap",
|
||||
"radiation flares",
|
||||
"supermatter dust",
|
||||
"leaks into a negative reality",
|
||||
"antiparticle clouds",
|
||||
"residual bluespace energy",
|
||||
"suspected syndicate operatives",
|
||||
"malfunctioning von Neumann probe swarms",
|
||||
"shadowy interlopers",
|
||||
"a stranded Vox arkship",
|
||||
"haywire IPC constructs",
|
||||
"rogue Unathi exiles",
|
||||
"artifacts of eldritch horror",
|
||||
"a brain slug infestation",
|
||||
"killer bugs that lay eggs in the husks of the living",
|
||||
"a deserted transport carrying xenomorph specimens",
|
||||
"an emissary for the gestalt requesting a security detail",
|
||||
"a Tajaran slave rebellion",
|
||||
"radical Skrellian transevolutionaries",
|
||||
"classified security operations",
|
||||
"science-defying raw elemental chaos")]
|
||||
in the region is tying up all available local emergency resources;
|
||||
<b>emergency response teams</b> can not be called at this time.</p>
|
||||
"})
|
||||
|
||||
proc/announce()
|
||||
world << "<B>The current game mode is - Mutiny!</B>"
|
||||
world << {"
|
||||
@@ -157,7 +104,7 @@ Both keys are required to activate the <b>Emergency Authentication Device (EAD)<
|
||||
NanoTrasen has praised the efforts of Captain [mode.head_loyalist] and loyal members of [their(mode.head_loyalist)] crew, who recently managed to put down a mutiny--amid a local interstellar crisis--aboard the <b>[station_name()]</b>, a research station in [system_name()].
|
||||
The mutiny was spurred by a top secret directive sent to the station, presumably in response to the crisis within the system.
|
||||
Despite the mutiny, the crew was successful in implementing the directive and activating their on-board emergency authentication device.
|
||||
[mode.mutineers.len] members of the station's personnel were charged with sedition against the company and if found guilty will be sentenced to life incarceration.
|
||||
[mode.mutineers.len] members of the station's personnel were charged with terrorist action against the Company and, if found guilty by a Sol magistrate, will be sentenced to life incarceration.
|
||||
NanoTrasen will be awarding [mode.loyalists.len] members of the crew with the [loyalist_tag("Star of Loyalty")], following their successful efforts, at a ceremony this coming Thursday.
|
||||
[mode.body_count.len] are believed to have died during the coup.
|
||||
<p>NanoTrasen's image will forever be haunted by the fact that a mutiny took place on one of its own stations.</p>
|
||||
@@ -168,7 +115,7 @@ NanoTrasen will be awarding [mode.loyalists.len] members of the crew with the [l
|
||||
NanoTrasen has praised the efforts of Captain [mode.head_loyalist] and loyal members of [their(mode.head_loyalist)] crew, who recently managed to put down a mutiny--amid a local interstellar crisis--aboard the <b>[station_name()]</b>, a research station in [system_name()].
|
||||
The mutiny was spurred by a top secret directive sent to the station, presumably in response to the crisis within the system.
|
||||
Despite the mutiny, the crew was successful in implementing the directive. Unfortunately, they failed to notify Central Command of their successes due to a breach in the chain of command.
|
||||
[mode.mutineers.len] members of the station's personnel were charged with sedition against the Company and if found guilty will be sentenced to life incarceration.
|
||||
[mode.mutineers.len] members of the station's personnel were charged with terrorist action against the Company and, if found guilty by a Sol magistrate, will be sentenced to life incarceration.
|
||||
NanoTrasen will be awarding [mode.loyalists.len] members of the crew with the [loyalist_tag("Star of Loyalty")], following their mostly successful efforts, at a ceremony this coming Thursday.
|
||||
[mode.body_count.len] are believed to have died during the coup.
|
||||
<p>NanoTrasen's image will forever be haunted by the fact that a mutiny took place on one of its own stations.</p>
|
||||
@@ -180,7 +127,7 @@ NanoTrasen has been thrust into turmoil following an apparent mutiny by key pers
|
||||
The mutiny was spurred by a top secret directive sent to the station, presumably in response to the crisis within the system.
|
||||
No further information has yet emerged from the station or its crew, who are presumed to be in holding with NanoTrasen investigators.
|
||||
NanoTrasen officials refuse to comment.
|
||||
Sources indicate that [mode.mutineers.len] members of the station's personnel are currently under investigation for mutiny, and [mode.loyalists.len] crew are currently providing evidence to investigators, believed to be the 'loyal' station personnel.
|
||||
Sources indicate that [mode.mutineers.len] members of the station's personnel are currently under investigation for terrorist activity, and [mode.loyalists.len] crew are currently providing evidence to investigators, believed to be the 'loyal' station personnel.
|
||||
[mode.body_count.len] are believed to have died during the coup.
|
||||
<p>NanoTrasen's image will forever be haunted by the fact that a mutiny took place on one of its own stations.</p>
|
||||
"}
|
||||
@@ -198,7 +145,7 @@ NanoTrasen has reprimanded [mode.loyalists.len] members of the crew for failing
|
||||
|
||||
proc/mutineer_major_victory()
|
||||
return {"
|
||||
NanoTrasen has praised the efforts of [mode.head_mutineer.assigned_role] [mode.head_mutineer] and several other members of the crew, who recently seized control of a research station in [system_name()]--<b>[station_name()]</b>--amid a local interstellar crisis.
|
||||
NanoTrasen has praised the efforts of [mode.head_mutineer.assigned_role] [mode.head_mutineer] and several other members of the crew, who recently seized control of a company station in [system_name()]--<b>[station_name()]</b>--amid a local interstellar crisis.
|
||||
What appears to have been a "legitimate" mutiny was spurred by a top secret directive sent to the station, presumably in response to the crisis within the system.
|
||||
It has been revealed that the directive was invalid and fraudulent. Company officials have not released a statement about the source of the directive.
|
||||
Thanks to the efforts of the resistant members of the crew, the directive was not carried out.
|
||||
|
||||
@@ -45,8 +45,8 @@
|
||||
flag = CHEF
|
||||
department_flag = CIVILIAN
|
||||
faction = "Station"
|
||||
total_positions = 1
|
||||
spawn_positions = 1
|
||||
total_positions = 2
|
||||
spawn_positions = 2
|
||||
supervisors = "the head of personnel"
|
||||
selection_color = "#dddddd"
|
||||
access = list(access_hydroponics, access_bar, access_kitchen, access_morgue)
|
||||
@@ -70,12 +70,12 @@
|
||||
|
||||
|
||||
/datum/job/hydro
|
||||
title = "Botanist"
|
||||
title = "Gardener"
|
||||
flag = BOTANIST
|
||||
department_flag = CIVILIAN
|
||||
faction = "Station"
|
||||
total_positions = 3
|
||||
spawn_positions = 2
|
||||
total_positions = 2
|
||||
spawn_positions = 1
|
||||
supervisors = "the head of personnel"
|
||||
selection_color = "#dddddd"
|
||||
access = list(access_hydroponics, access_bar, access_kitchen, access_morgue) // Removed tox and chem access because STOP PISSING OFF THE CHEMIST GUYS // //Removed medical access because WHAT THE FUCK YOU AREN'T A DOCTOR YOU GROW WHEAT //Given Morgue access because they have a viable means of cloning.
|
||||
|
||||
@@ -42,13 +42,13 @@
|
||||
flag = SCIENTIST
|
||||
department_flag = MEDSCI
|
||||
faction = "Station"
|
||||
total_positions = 5
|
||||
total_positions = 6
|
||||
spawn_positions = 3
|
||||
supervisors = "the research director"
|
||||
selection_color = "#ffeeff"
|
||||
access = list(access_robotics, access_tox, access_tox_storage, access_research, access_xenobiology, access_xenoarch)
|
||||
minimal_access = list(access_tox, access_tox_storage, access_research, access_xenoarch)
|
||||
alt_titles = list("Xenoarcheologist", "Anomalist", "Phoron Researcher")
|
||||
alt_titles = list("Xenoarcheologist", "Anomalist", "Phoron Researcher", "Xenobotanist")
|
||||
|
||||
equip(var/mob/living/carbon/human/H)
|
||||
if(!H) return 0
|
||||
|
||||
@@ -429,8 +429,18 @@ var/global/datum/controller/occupations/job_master
|
||||
H.equip_to_slot_or_del(BPK, slot_back,1)
|
||||
|
||||
//TODO: Generalize this by-species
|
||||
if(H.species && (H.species.name == "Tajaran" || H.species.name == "Unathi"))
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(H),slot_shoes,1)
|
||||
if(H.species)
|
||||
if(H.species.name == "Tajaran" || H.species.name == "Unathi")
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/shoes/sandal(H),slot_shoes,1)
|
||||
else if(H.species.name == "Vox")
|
||||
H.equip_to_slot_or_del(new /obj/item/clothing/mask/breath(src), slot_wear_mask)
|
||||
if(!H.r_hand)
|
||||
H.equip_to_slot_or_del(new /obj/item/weapon/tank/nitrogen(src), slot_r_hand)
|
||||
H.internal = H.r_hand
|
||||
else if (!H.l_hand)
|
||||
H.equip_to_slot_or_del(new /obj/item/weapon/tank/nitrogen(src), slot_l_hand)
|
||||
H.internal = H.l_hand
|
||||
H.internals.icon_state = "internal1"
|
||||
|
||||
H << "<B>You are the [alt_title ? alt_title : rank].</B>"
|
||||
H << "<b>As the [alt_title ? alt_title : rank] you answer directly to [job.supervisors]. Special circumstances may change this.</b>"
|
||||
|
||||
@@ -87,7 +87,7 @@ var/list/science_positions = list(
|
||||
var/list/civilian_positions = list(
|
||||
"Head of Personnel",
|
||||
"Bartender",
|
||||
"Botanist",
|
||||
"Gardener",
|
||||
"Chef",
|
||||
"Janitor",
|
||||
"Librarian",
|
||||
|
||||
@@ -36,8 +36,6 @@ var/list/whitelist = list()
|
||||
return 1
|
||||
if(species == "human" || species == "Human")
|
||||
return 1
|
||||
if(species == "machine" || species == "Machine")
|
||||
return 1
|
||||
if(check_rights(R_ADMIN, 0))
|
||||
return 1
|
||||
if(!alien_whitelist)
|
||||
|
||||
@@ -137,8 +137,4 @@
|
||||
if(iscarbon(W:affecting))
|
||||
take_victim(W:affecting,usr)
|
||||
del(W)
|
||||
return
|
||||
user.drop_item()
|
||||
if(W && W.loc)
|
||||
W.loc = src.loc
|
||||
return
|
||||
return
|
||||
@@ -332,8 +332,7 @@
|
||||
else
|
||||
dat += "<td>[e.display_name]</td><td>-</td><td>-</td><td>Not Found</td>"
|
||||
dat += "</tr>"
|
||||
for(var/organ_name in occupant.internal_organs)
|
||||
var/datum/organ/internal/i = occupant.internal_organs[organ_name]
|
||||
for(var/datum/organ/internal/i in occupant.internal_organs)
|
||||
var/mech = ""
|
||||
if(i.robotic == 1)
|
||||
mech = "Assisted:"
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
active_power_usage = 8
|
||||
power_channel = ENVIRON
|
||||
req_one_access = list(access_atmospherics, access_engine_equip)
|
||||
var/breach_detection = 1 // Whether to use automatic breach detection or not
|
||||
var/frequency = 1439
|
||||
//var/skipprocess = 0 //Experimenting
|
||||
var/alarm_frequency = 1437
|
||||
@@ -214,8 +215,7 @@
|
||||
danger_level = overall_danger_level()
|
||||
|
||||
if (old_level != danger_level)
|
||||
refresh_danger_level()
|
||||
update_icon()
|
||||
apply_danger_level(danger_level)
|
||||
|
||||
if (old_pressurelevel != pressure_dangerlevel)
|
||||
if (breach_detected())
|
||||
@@ -276,17 +276,20 @@
|
||||
|
||||
if(!istype(location))
|
||||
return 0
|
||||
|
||||
|
||||
if(breach_detection == 0)
|
||||
return 0
|
||||
|
||||
var/datum/gas_mixture/environment = location.return_air()
|
||||
var/environment_pressure = environment.return_pressure()
|
||||
var/pressure_levels = TLV["pressure"]
|
||||
|
||||
|
||||
if (environment_pressure <= pressure_levels[1]) //low pressures
|
||||
if (!(mode == AALARM_MODE_PANIC || mode == AALARM_MODE_CYCLE))
|
||||
return 1
|
||||
|
||||
|
||||
return 0
|
||||
|
||||
|
||||
|
||||
/obj/machinery/alarm/proc/master_is_operating()
|
||||
return alarm_area.master_air_alarm && !(alarm_area.master_air_alarm.stat & (NOPOWER|BROKEN))
|
||||
@@ -314,7 +317,12 @@
|
||||
if((stat & (NOPOWER|BROKEN)) || shorted)
|
||||
icon_state = "alarmp"
|
||||
return
|
||||
switch(max(danger_level, alarm_area.atmosalm))
|
||||
|
||||
var/icon_level = danger_level
|
||||
if (alarm_area.atmosalm)
|
||||
icon_level = max(icon_level, 1) //if there's an atmos alarm but everything is okay locally, no need to go past yellow
|
||||
|
||||
switch(icon_level)
|
||||
if (0)
|
||||
icon_state = "alarm0"
|
||||
if (1)
|
||||
@@ -397,14 +405,12 @@
|
||||
return 1
|
||||
|
||||
/obj/machinery/alarm/proc/apply_mode()
|
||||
var/current_pressures = TLV["pressure"]
|
||||
var/target_pressure = (current_pressures[2] + current_pressures[3])/2
|
||||
switch(mode)
|
||||
if(AALARM_MODE_SCRUBBING)
|
||||
for(var/device_id in alarm_area.air_scrub_names)
|
||||
send_signal(device_id, list("power"= 1, "co2_scrub"= 1, "scrubbing"= 1, "panic_siphon"= 0) )
|
||||
for(var/device_id in alarm_area.air_vent_names)
|
||||
send_signal(device_id, list("power"= 1, "checks"= 1, "set_external_pressure"= target_pressure) )
|
||||
send_signal(device_id, list("power"= 1, "checks"= "default", "set_external_pressure"= "default") )
|
||||
|
||||
if(AALARM_MODE_PANIC, AALARM_MODE_CYCLE)
|
||||
for(var/device_id in alarm_area.air_scrub_names)
|
||||
@@ -416,13 +422,13 @@
|
||||
for(var/device_id in alarm_area.air_scrub_names)
|
||||
send_signal(device_id, list("power"= 1, "panic_siphon"= 1) )
|
||||
for(var/device_id in alarm_area.air_vent_names)
|
||||
send_signal(device_id, list("power"= 1, "checks"= 1, "set_external_pressure"= target_pressure) )
|
||||
send_signal(device_id, list("power"= 1, "checks"= "default", "set_external_pressure"= "default") )
|
||||
|
||||
if(AALARM_MODE_FILL)
|
||||
for(var/device_id in alarm_area.air_scrub_names)
|
||||
send_signal(device_id, list("power"= 0) )
|
||||
for(var/device_id in alarm_area.air_vent_names)
|
||||
send_signal(device_id, list("power"= 1, "checks"= 1, "set_external_pressure"= target_pressure) )
|
||||
send_signal(device_id, list("power"= 1, "checks"= "default", "set_external_pressure"= "default") )
|
||||
|
||||
if(AALARM_MODE_OFF)
|
||||
for(var/device_id in alarm_area.air_scrub_names)
|
||||
@@ -434,16 +440,6 @@
|
||||
if (alarm_area.atmosalert(new_danger_level))
|
||||
post_alert(new_danger_level)
|
||||
|
||||
for (var/area/A in alarm_area.related)
|
||||
for (var/obj/machinery/alarm/AA in A)
|
||||
if ( !(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted && AA.danger_level != new_danger_level)
|
||||
AA.update_icon()
|
||||
|
||||
if(danger_level > 1)
|
||||
air_doors_close(0)
|
||||
else
|
||||
air_doors_open(0)
|
||||
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/alarm/proc/post_alert(alert_level)
|
||||
@@ -466,71 +462,6 @@
|
||||
|
||||
frequency.post_signal(src, alert_signal)
|
||||
|
||||
/obj/machinery/alarm/proc/refresh_danger_level()
|
||||
var/level = 0
|
||||
for (var/area/A in alarm_area.related)
|
||||
for (var/obj/machinery/alarm/AA in A)
|
||||
if ( !(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted)
|
||||
if (AA.danger_level > level)
|
||||
level = AA.danger_level
|
||||
apply_danger_level(level)
|
||||
|
||||
/obj/machinery/alarm/proc/air_doors_close(manual)
|
||||
var/area/A = get_area(src)
|
||||
if(!A.master.air_doors_activated)
|
||||
A.master.air_doors_activated = 1
|
||||
for(var/obj/machinery/door/E in A.master.all_doors)
|
||||
if(istype(E,/obj/machinery/door/firedoor))
|
||||
if(!E:blocked)
|
||||
if(E.operating)
|
||||
E:nextstate = CLOSED
|
||||
else if(!E.density)
|
||||
spawn(0)
|
||||
E.close()
|
||||
continue
|
||||
|
||||
/* if(istype(E, /obj/machinery/door/airlock))
|
||||
if((!E:arePowerSystemsOn()) || (E.stat & NOPOWER) || E:air_locked) continue
|
||||
if(!E.density)
|
||||
spawn(0)
|
||||
E.close()
|
||||
spawn(10)
|
||||
if(E.density)
|
||||
E:air_locked = E.req_access
|
||||
E:req_access = list(ACCESS_ENGINE, ACCESS_ATMOSPHERICS)
|
||||
E.update_icon()
|
||||
else if(E.operating)
|
||||
spawn(10)
|
||||
E.close()
|
||||
if(E.density)
|
||||
E:air_locked = E.req_access
|
||||
E:req_access = list(ACCESS_ENGINE, ACCESS_ATMOSPHERICS)
|
||||
E.update_icon()
|
||||
else if(!E:locked) //Don't lock already bolted doors.
|
||||
E:air_locked = E.req_access
|
||||
E:req_access = list(ACCESS_ENGINE, ACCESS_ATMOSPHERICS)
|
||||
E.update_icon()*/
|
||||
|
||||
/obj/machinery/alarm/proc/air_doors_open(manual)
|
||||
var/area/A = get_area(loc)
|
||||
if(A.master.air_doors_activated)
|
||||
A.master.air_doors_activated = 0
|
||||
for(var/obj/machinery/door/E in A.master.all_doors)
|
||||
if(istype(E, /obj/machinery/door/firedoor))
|
||||
if(!E:blocked)
|
||||
if(E.operating)
|
||||
E:nextstate = OPEN
|
||||
else if(E.density)
|
||||
spawn(0)
|
||||
E.open()
|
||||
continue
|
||||
|
||||
/* if(istype(E, /obj/machinery/door/airlock))
|
||||
if((!E:arePowerSystemsOn()) || (E.stat & NOPOWER)) continue
|
||||
if(!isnull(E:air_locked)) //Don't mess with doors locked for other reasons.
|
||||
E:req_access = E:air_locked
|
||||
E:air_locked = null
|
||||
E.update_icon()*/
|
||||
|
||||
///////////
|
||||
//HACKING//
|
||||
@@ -773,19 +704,24 @@ Toxins: <span class='dl[phoron_dangerlevel]'>[phoron_percent]</span>%<br>
|
||||
|
||||
output += "Temperature: <span class='dl[temperature_dangerlevel]'>[environment.temperature]</span>K ([round(environment.temperature - T0C, 0.1)]C)<br>"
|
||||
|
||||
//Overall status
|
||||
//'Local Status' should report the LOCAL status, damnit.
|
||||
output += "Local Status: "
|
||||
switch(max(pressure_dangerlevel,oxygen_dangerlevel,co2_dangerlevel,phoron_dangerlevel,other_dangerlevel,temperature_dangerlevel))
|
||||
if(2)
|
||||
output += "<span class='dl2'>DANGER: Internals Required</span>"
|
||||
output += "<span class='dl2'>DANGER: Internals Required</span><br>"
|
||||
if(1)
|
||||
output += "<span class='dl1'>Caution</span>"
|
||||
output += "<span class='dl1'>Caution</span><br>"
|
||||
if(0)
|
||||
if(alarm_area.atmosalm)
|
||||
output += {"<span class='dl1'>Caution: Atmos alert in area</span>"}
|
||||
else
|
||||
output += {"<span class='dl0'>Optimal</span>"}
|
||||
output += "<span class='dl0'>Optimal</span><br>"
|
||||
|
||||
output += "Area Status: "
|
||||
if(alarm_area.atmosalm)
|
||||
output += "<span class='dl1'>Atmos alert in area</span>"
|
||||
else if (alarm_area.fire)
|
||||
output += "<span class='dl1'>Fire alarm in area</span>"
|
||||
else
|
||||
output += "No alerts"
|
||||
|
||||
return output
|
||||
|
||||
/obj/machinery/alarm/proc/rcon_text()
|
||||
@@ -816,9 +752,9 @@ Toxins: <span class='dl[phoron_dangerlevel]'>[phoron_percent]</span>%<br>
|
||||
switch(screen)
|
||||
if (AALARM_SCREEN_MAIN)
|
||||
if(alarm_area.atmosalm)
|
||||
output += "<a href='?src=\ref[src];atmos_reset=1'>Reset - Atmospheric Alarm</a><hr>"
|
||||
output += "<a href='?src=\ref[src];atmos_reset=1'>Reset - Area Atmospheric Alarm</a><hr>"
|
||||
else
|
||||
output += "<a href='?src=\ref[src];atmos_alarm=1'>Activate - Atmospheric Alarm</a><hr>"
|
||||
output += "<a href='?src=\ref[src];atmos_alarm=1'>Activate - Area Atmospheric Alarm</a><hr>"
|
||||
|
||||
output += {"
|
||||
<a href='?src=\ref[src];screen=[AALARM_SCREEN_SCRUB]'>Scrubbers Control</a><br>
|
||||
@@ -1081,9 +1017,9 @@ table tr:first-child th:first-child { border: none;}
|
||||
if(href_list["atmos_unlock"])
|
||||
switch(href_list["atmos_unlock"])
|
||||
if("0")
|
||||
air_doors_close(1)
|
||||
alarm_area.air_doors_close()
|
||||
if("1")
|
||||
air_doors_open(1)
|
||||
alarm_area.air_doors_open()
|
||||
|
||||
if(href_list["atmos_alarm"])
|
||||
if (alarm_area.atmosalert(2))
|
||||
@@ -1325,7 +1261,7 @@ FIRE ALARM
|
||||
else
|
||||
icon_state = "fire0"
|
||||
|
||||
/obj/machinery/firealarm/temperature_expose(datum/gas_mixture/air, temperature, volume)
|
||||
/obj/machinery/firealarm/fire_act(datum/gas_mixture/air, temperature, volume)
|
||||
if(src.detecting)
|
||||
if(temperature > T0C+200)
|
||||
src.alarm() // added check of detector status here
|
||||
|
||||
@@ -110,7 +110,7 @@ update_flag
|
||||
overlays += "can-o3"
|
||||
return
|
||||
|
||||
/obj/machinery/portable_atmospherics/canister/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
/obj/machinery/portable_atmospherics/canister/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
if(exposed_temperature > temperature_resistance)
|
||||
health -= 5
|
||||
healthcheck()
|
||||
|
||||
@@ -119,6 +119,11 @@
|
||||
return
|
||||
|
||||
if (opened)
|
||||
//Don't eat multitools or wirecutters used on an open lathe.
|
||||
if(istype(O, /obj/item/device/multitool) || istype(O, /obj/item/weapon/wirecutters))
|
||||
attack_hand(user)
|
||||
return
|
||||
|
||||
//Dismantle the frame.
|
||||
if(istype(O, /obj/item/weapon/crowbar))
|
||||
dismantle()
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
icon = 'icons/obj/computer.dmi'
|
||||
icon_state = "ai-fixer"
|
||||
circuit = /obj/item/weapon/circuitboard/aifixer
|
||||
req_access = list(access_captain, access_robotics, access_heads)
|
||||
req_one_access = list(access_robotics, access_heads)
|
||||
var/mob/living/silicon/ai/occupant = null
|
||||
var/active = 0
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
user << "This terminal isn't functioning right now, get it working!"
|
||||
return
|
||||
I:transfer_ai("AIFIXER","AICARD",src,user)
|
||||
|
||||
|
||||
..()
|
||||
return
|
||||
|
||||
|
||||
@@ -30,6 +30,29 @@
|
||||
|
||||
return formatted
|
||||
|
||||
/obj/machinery/computer/card/verb/eject_id()
|
||||
set category = "Object"
|
||||
set name = "Eject ID Card"
|
||||
set src in oview(1)
|
||||
|
||||
if(!usr || usr.stat || usr.lying) return
|
||||
|
||||
if(scan)
|
||||
usr << "You remove \the [scan] from \the [src]."
|
||||
scan.loc = get_turf(src)
|
||||
if(!usr.get_active_hand())
|
||||
usr.put_in_hands(scan)
|
||||
scan = null
|
||||
else if(modify)
|
||||
usr << "You remove \the [modify] from \the [src]."
|
||||
modify.loc = get_turf(src)
|
||||
if(!usr.get_active_hand())
|
||||
usr.put_in_hands(modify)
|
||||
modify = null
|
||||
else
|
||||
usr << "There is nothing to remove from the console."
|
||||
return
|
||||
|
||||
/obj/machinery/computer/card/attackby(obj/item/weapon/card/id/id_card, mob/user)
|
||||
if(!istype(id_card))
|
||||
return ..()
|
||||
|
||||
@@ -309,7 +309,7 @@
|
||||
dat += "<BR>\[ <A HREF='?src=\ref[src];operation=RestoreBackup'>Restore Backup Routing Data</A> \]"
|
||||
|
||||
dat += "<BR>\[ <A HREF='?src=\ref[src];operation=changeseclevel'>Change alert level</A> \]"
|
||||
if(!emergency_shuttle.location())
|
||||
if(emergency_shuttle.location())
|
||||
if (emergency_shuttle.online())
|
||||
dat += "<BR>\[ <A HREF='?src=\ref[src];operation=cancelshuttle'>Cancel Shuttle Call</A> \]"
|
||||
else
|
||||
@@ -377,7 +377,7 @@
|
||||
var/dat = ""
|
||||
switch(src.aistate)
|
||||
if(STATE_DEFAULT)
|
||||
if(!emergency_shuttle.location() && !emergency_shuttle.online())
|
||||
if(emergency_shuttle.location() && !emergency_shuttle.online())
|
||||
dat += "<BR>\[ <A HREF='?src=\ref[src];operation=ai-callshuttle'>Call Emergency Shuttle</A> \]"
|
||||
dat += "<BR>\[ <A HREF='?src=\ref[src];operation=ai-messagelist'>Message List</A> \]"
|
||||
dat += "<BR>\[ <A HREF='?src=\ref[src];operation=ai-status'>Set Status Display</A> \]"
|
||||
|
||||
@@ -108,13 +108,9 @@
|
||||
|
||||
|
||||
/obj/machinery/computer/crew/proc/scan()
|
||||
for(var/obj/item/clothing/under/C in world)
|
||||
if((C.has_sensor) && (istype(C.loc, /mob/living/carbon/human)))
|
||||
var/check = 0
|
||||
for(var/O in src.tracked)
|
||||
if(O == C)
|
||||
check = 1
|
||||
break
|
||||
if(!check)
|
||||
src.tracked.Add(C)
|
||||
for(var/mob/living/carbon/human/H in mob_list)
|
||||
if(istype(H.w_uniform, /obj/item/clothing/under))
|
||||
var/obj/item/clothing/under/C = H.w_uniform
|
||||
if (C.has_sensor)
|
||||
tracked |= C
|
||||
return 1
|
||||
@@ -16,6 +16,23 @@
|
||||
var/temp = null
|
||||
var/printing = null
|
||||
|
||||
/obj/machinery/computer/med_data/verb/eject_id()
|
||||
set category = "Object"
|
||||
set name = "Eject ID Card"
|
||||
set src in oview(1)
|
||||
|
||||
if(!usr || usr.stat || usr.lying) return
|
||||
|
||||
if(scan)
|
||||
usr << "You remove \the [scan] from \the [src]."
|
||||
scan.loc = get_turf(src)
|
||||
if(!usr.get_active_hand())
|
||||
usr.put_in_hands(scan)
|
||||
scan = null
|
||||
else
|
||||
usr << "There is nothing to remove from the console."
|
||||
return
|
||||
|
||||
/obj/machinery/computer/med_data/attackby(obj/item/O as obj, user as mob)
|
||||
if(istype(O, /obj/item/weapon/card/id) && !scan)
|
||||
usr.drop_item()
|
||||
|
||||
@@ -22,6 +22,22 @@
|
||||
var/sortBy = "name"
|
||||
var/order = 1 // -1 = Descending - 1 = Ascending
|
||||
|
||||
/obj/machinery/computer/secure_data/verb/eject_id()
|
||||
set category = "Object"
|
||||
set name = "Eject ID Card"
|
||||
set src in oview(1)
|
||||
|
||||
if(!usr || usr.stat || usr.lying) return
|
||||
|
||||
if(scan)
|
||||
usr << "You remove \the [scan] from \the [src]."
|
||||
scan.loc = get_turf(src)
|
||||
if(!usr.get_active_hand())
|
||||
usr.put_in_hands(scan)
|
||||
scan = null
|
||||
else
|
||||
usr << "There is nothing to remove from the console."
|
||||
return
|
||||
|
||||
/obj/machinery/computer/secure_data/attackby(obj/item/O as obj, user as mob)
|
||||
if(istype(O, /obj/item/weapon/card/id) && !scan)
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user