Merge branch 'master' of https://github.com/tgstation/-tg-station into LizardHunting

This commit is contained in:
KazeEspada
2016-01-24 15:14:00 -07:00
682 changed files with 17967 additions and 17402 deletions
+17
View File
@@ -279,3 +279,20 @@ Pipelines + Other Objects -> Pipe network
/obj/machinery/atmospherics/proc/returnPipenets()
return list()
/obj/machinery/atmospherics/onShuttleMove()
. = ..()
if(!.)
return
for(DEVICE_TYPE_LOOP)
dealWithShuttleStuff(I)
atmosinit() //we've moved, so what once was next to us may not be
build_network()
/obj/machinery/atmospherics/proc/dealWithShuttleStuff(I)
var/obj/machinery/atmospherics/node = NODE_I
var/turf/node_turf = get_turf(node)
var/turf/self_turf = get_turf(src)
if(node_turf.loc != self_turf.loc) //shuttles are area based, so this means the node is not on the shuttle with us
node.disconnect(src)
NODE_I = null
@@ -7,7 +7,7 @@
desc = "A gas circulator pump and heat exchanger."
icon_state = "circ1-off"
var/side = 1 // 1=left 2=right
var/side = CIRC_LEFT
var/status = 0
var/last_pressure_delta = 0
@@ -15,6 +15,9 @@
anchored = 1
density = 1
var/global/const/CIRC_LEFT = 1
var/global/const/CIRC_RIGHT = 2
/obj/machinery/atmospherics/components/binary/circulator/proc/return_transfer_air()
@@ -1,4 +1,3 @@
/*
Passive gate is similar to the regular pump except:
@@ -11,7 +10,7 @@ Passive gate is similar to the regular pump except:
icon_state = "passgate_map"
name = "passive gate"
desc = "A one-way air valve that does not require power"
desc = "A one-way air valve that does not require power."
can_unwrench = 1
@@ -93,23 +92,43 @@ Passive gate is similar to the regular pump except:
return 1
/obj/machinery/atmospherics/components/binary/passive_gate/interact(mob/user)
if(stat & (BROKEN|NOPOWER)) return
ui_interact(user)
/obj/machinery/atmospherics/components/binary/passive_gate/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 0)
ui = SSnano.try_update_ui(user, src, ui_key, ui, force_open = force_open)
if (!ui)
ui = new(user, src, ui_key, "atmos_pump", name, 400, 115)
/obj/machinery/atmospherics/components/binary/passive_gate/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, \
datum/tgui/master_ui = null, datum/ui_state/state = default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "atmos_pump", name, 335, 115, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/binary/passive_gate/get_ui_data()
var/data = list()
data["on"] = on
data["set_pressure"] = round(target_pressure)
data["pressure"] = round(target_pressure)
data["max_pressure"] = round(MAX_OUTPUT_PRESSURE)
return data
/obj/machinery/atmospherics/components/binary/passive_gate/ui_act(action, params)
if(..())
return
switch(action)
if("power")
on = !on
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
. = TRUE
if("pressure")
var/pressure = params["pressure"]
if(pressure == "max")
target_pressure = MAX_OUTPUT_PRESSURE
. = TRUE
else if(pressure == "input")
pressure = input("New output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", name, target_pressure) as num|null
. = .(action, list("pressure" = pressure))
else if(text2num(pressure) != null)
target_pressure = Clamp(text2num(pressure), 0, MAX_OUTPUT_PRESSURE)
. = TRUE
if(.)
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
update_icon()
/obj/machinery/atmospherics/components/binary/passive_gate/atmosinit()
..()
if(frequency)
@@ -134,47 +153,21 @@ Passive gate is similar to the regular pump except:
investigate_log("was turned [on ? "on" : "off"] by a remote signal", "atmos")
if("status" in signal.data)
spawn(2)
broadcast_status()
return //do not update_icon
spawn(2)
broadcast_status()
return
broadcast_status()
update_icon()
return
/obj/machinery/atmospherics/components/binary/passive_gate/attack_hand(mob/user)
if(..() || !user)
return
interact(user)
/obj/machinery/atmospherics/components/binary/passive_gate/ui_act(action, params)
if(..())
return
switch(action)
if("power")
on = !on
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
if("pressure")
switch(params["set"])
if ("max")
target_pressure = MAX_OUTPUT_PRESSURE
if ("custom")
target_pressure = max(0, min(MAX_OUTPUT_PRESSURE, safe_input("Pressure control", "Enter new output pressure (0-[MAX_OUTPUT_PRESSURE] kPa)", target_pressure)))
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
update_icon()
return 1
/obj/machinery/atmospherics/components/binary/passive_gate/power_change()
..()
update_icon()
/obj/machinery/atmospherics/components/binary/passive_gate/attackby(obj/item/weapon/W, mob/user, params)
if (!istype(W, /obj/item/weapon/wrench))
if(!istype(W, /obj/item/weapon/wrench))
return ..()
if (on)
if(on)
user << "<span class='warning'>You cannot unwrench this [src], turn it off first!</span>"
return 1
return ..()
@@ -15,7 +15,7 @@ Thus, the two variables affect pump operation are set in New():
/obj/machinery/atmospherics/components/binary/pump
icon_state = "pump_map"
name = "gas pump"
desc = "A pump"
desc = "A pump that moves gas by pressure."
can_unwrench = 1
@@ -98,26 +98,49 @@ Thus, the two variables affect pump operation are set in New():
return 1
/obj/machinery/atmospherics/components/binary/pump/interact(mob/user)
if(stat & (BROKEN|NOPOWER)) return
/obj/machinery/atmospherics/components/binary/pump/attack_hand(mob/user)
if(!src.allowed(usr))
usr << "<span class='danger'>Access denied.</span>"
return
ui_interact(user)
..()
/obj/machinery/atmospherics/components/binary/pump/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 0)
ui = SSnano.try_update_ui(user, src, ui_key, ui, force_open = force_open)
if (!ui)
ui = new(user, src, ui_key, "atmos_pump", name, 400, 115)
/obj/machinery/atmospherics/components/binary/pump/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, \
datum/tgui/master_ui = null, datum/ui_state/state = default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "atmos_pump", name, 335, 115, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/binary/pump/get_ui_data()
var/data = list()
data["on"] = on
data["set_pressure"] = round(target_pressure)
data["pressure"] = round(target_pressure)
data["max_pressure"] = round(MAX_OUTPUT_PRESSURE)
return data
/obj/machinery/atmospherics/components/binary/pump/ui_act(action, params)
if(..())
return
switch(action)
if("power")
on = !on
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
. = TRUE
if("pressure")
var/pressure = params["pressure"]
if(pressure == "max")
target_pressure = MAX_OUTPUT_PRESSURE
. = TRUE
else if(pressure == "input")
pressure = input("New output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", name, target_pressure) as num|null
. = .(action, list("pressure" = pressure))
else if(text2num(pressure) != null)
target_pressure = Clamp(text2num(pressure), 0, MAX_OUTPUT_PRESSURE)
. = TRUE
if(.)
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
update_icon()
/obj/machinery/atmospherics/components/binary/pump/atmosinit()
..()
if(frequency)
@@ -142,39 +165,13 @@ Thus, the two variables affect pump operation are set in New():
investigate_log("was turned [on ? "on" : "off"] by a remote signal", "atmos")
if("status" in signal.data)
spawn(2)
broadcast_status()
return //do not update_icon
spawn(2)
broadcast_status()
return
broadcast_status()
update_icon()
return
/obj/machinery/atmospherics/components/binary/pump/attack_hand(mob/user)
if(..() || !user)
return
interact(user)
/obj/machinery/atmospherics/components/binary/pump/ui_act(action, params)
if(..())
return
switch(action)
if("power")
on = !on
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
if("pressure")
switch(params["set"])
if ("max")
target_pressure = MAX_OUTPUT_PRESSURE
if ("custom")
target_pressure = max(0, min(MAX_OUTPUT_PRESSURE, safe_input("Pressure control", "Enter new output pressure (0-[MAX_OUTPUT_PRESSURE] kPa)", target_pressure)))
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
update_icon()
return 1
/obj/machinery/atmospherics/components/binary/pump/power_change()
..()
update_icon()
@@ -15,7 +15,7 @@ Thus, the two variables affect pump operation are set in New():
/obj/machinery/atmospherics/components/binary/volume_pump
icon_state = "volpump_map"
name = "volumetric gas pump"
desc = "A volumetric pump"
desc = "A pump that moves gas by volume."
can_unwrench = 1
@@ -59,7 +59,7 @@ Thus, the two variables affect pump operation are set in New():
if((input_starting_pressure < 0.01) || (output_starting_pressure > 9000))
return 1
var/transfer_ratio = max(1, transfer_rate/air1.volume)
var/transfer_ratio = min(1, transfer_rate/air1.volume)
var/datum/gas_mixture/removed = air1.remove_ratio(transfer_ratio)
@@ -94,24 +94,23 @@ Thus, the two variables affect pump operation are set in New():
return 1
/obj/machinery/atmospherics/components/binary/volume_pump/interact(mob/user)
if(stat & (BROKEN|NOPOWER))
return
/obj/machinery/atmospherics/components/binary/volume_pump/attack_hand(mob/user)
if(!src.allowed(usr))
usr << "<span class='danger'>Access denied.</span>"
return
ui_interact(user)
..()
/obj/machinery/atmospherics/components/binary/volume_pump/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 0)
ui = SSnano.try_update_ui(user, src, ui_key, ui, force_open = force_open)
if (!ui)
ui = new(user, src, ui_key, "atmos_pump", name, 400, 115)
/obj/machinery/atmospherics/components/binary/volume_pump/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, \
datum/tgui/master_ui = null, datum/ui_state/state = default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "atmos_pump", name, 310, 115, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/binary/volume_pump/get_ui_data()
var/data = list()
data["on"] = on
data["transfer_rate"] = round(transfer_rate)
data["rate"] = round(transfer_rate)
data["max_rate"] = round(MAX_TRANSFER_RATE)
return data
@@ -120,6 +119,29 @@ Thus, the two variables affect pump operation are set in New():
set_frequency(frequency)
/obj/machinery/atmospherics/components/binary/volume_pump/ui_act(action, params)
if(..())
return
switch(action)
if("power")
on = !on
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
. = TRUE
if("rate")
var/rate = params["rate"]
if(rate == "max")
transfer_rate = MAX_TRANSFER_RATE
. = TRUE
else if(rate == "input")
rate = input("New transfer rate (0-[MAX_TRANSFER_RATE] L/s):", name, transfer_rate) as num|null
. = .(action, list("rate" = rate))
else if(text2num(rate) != null)
transfer_rate = Clamp(text2num(rate), 0, MAX_TRANSFER_RATE)
. = TRUE
if(.)
investigate_log("was set to [transfer_rate] L/s by [key_name(usr)]", "atmos")
update_icon()
/obj/machinery/atmospherics/components/binary/volume_pump/receive_signal(datum/signal/signal)
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
return 0
@@ -149,30 +171,6 @@ Thus, the two variables affect pump operation are set in New():
update_icon()
return
/obj/machinery/atmospherics/components/binary/volume_pump/attack_hand(mob/user)
if(..() || !user)
return
interact(user)
/obj/machinery/atmospherics/components/binary/volume_pump/ui_act(action, params)
if(..())
return
switch(action)
if("power")
on = !on
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
if("transfer")
switch(params)
if ("max")
transfer_rate = MAX_TRANSFER_RATE
if ("custom")
transfer_rate = max(0, min(MAX_TRANSFER_RATE, safe_input("Pressure control", "Enter new transfer rate (0-[MAX_TRANSFER_RATE] L/s)", transfer_rate)))
investigate_log("was set to [transfer_rate] L/s by [key_name(usr)]", "atmos")
update_icon()
return 1
/obj/machinery/atmospherics/components/binary/volume_pump/power_change()
..()
update_icon()
@@ -3,7 +3,7 @@ So much of atmospherics.dm was used solely by components, so separating this mak
On top of that, now people can add component-speciic procs/vars if they want!
*/
/obj/machinery/atmospherics/components/
/obj/machinery/atmospherics/components
var/welded = 0 //Used on pumps and scrubbers
var/showpipe = 0
@@ -150,9 +150,16 @@ Helpers
/obj/machinery/atmospherics/components/proc/update_parents()
for(DEVICE_TYPE_LOOP)
var/datum/pipeline/parent = PARENT_I
if(!parent)
throw EXCEPTION("Component is missing a pipenet! Rebuilding...")
build_network()
parent.update = 1
/obj/machinery/atmospherics/components/returnPipenets()
. = list()
for(DEVICE_TYPE_LOOP)
. += returnPipenet(NODE_I)
. += returnPipenet(NODE_I)
/obj/machinery/atmospherics/components/dealWithShuttleStuff(I)
..()
nullifyPipenet(PARENT_I)
@@ -1,33 +1,11 @@
#define FILTER_NOTHING -1
#define FILTER_PLASMA 0
#define FILTER_OXYGEN 1
#define FILTER_NITROGEN 2
#define FILTER_CARBONDIOXIDE 3
#define FILTER_NITROUSOXIDE 4
/obj/machinery/atmospherics/components/trinary/filter
name = "gas filter"
icon_state = "filter_off"
density = 0
name = "gas filter"
can_unwrench = 1
var/on = 0
var/target_pressure = ONE_ATMOSPHERE
var/filter_type = 0
/*
Filter types:
-1: Nothing
0: Plasma: Plasma Toxin, Oxygen Agent B
1: Oxygen: Oxygen ONLY
2: Nitrogen: Nitrogen ONLY
3: Carbon Dioxide: Carbon Dioxide ONLY
4: Sleeping Agent (N2O)
*/
var/filter_type = ""
var/frequency = 0
var/datum/radio_frequency/radio_connection
@@ -108,39 +86,13 @@ Filter types:
var/datum/gas_mixture/filtered_out = new
filtered_out.temperature = removed.temperature
switch(filter_type)
if(FILTER_PLASMA)
filtered_out.toxins = removed.toxins
removed.toxins = 0
if(removed.trace_gases.len>0)
for(var/datum/gas/trace_gas in removed.trace_gases)
if(istype(trace_gas, /datum/gas/oxygen_agent_b))
removed.trace_gases -= trace_gas
filtered_out.trace_gases += trace_gas
if(FILTER_OXYGEN)
filtered_out.oxygen = removed.oxygen
removed.oxygen = 0
if(FILTER_NITROGEN)
filtered_out.nitrogen = removed.nitrogen
removed.nitrogen = 0
if(FILTER_CARBONDIOXIDE)
filtered_out.carbon_dioxide = removed.carbon_dioxide
removed.carbon_dioxide = 0
if(FILTER_NITROUSOXIDE)
if(removed.trace_gases.len>0)
for(var/datum/gas/trace_gas in removed.trace_gases)
if(istype(trace_gas, /datum/gas/sleeping_agent))
removed.trace_gases -= trace_gas
filtered_out.trace_gases += trace_gas
else
filtered_out = null
if(filter_type && removed.gases[filter_type])
filtered_out.assert_gas(filter_type)
filtered_out.gases[filter_type][MOLES] = removed.gases[filter_type][MOLES]
removed.gases[filter_type][MOLES] = 0
removed.garbage_collect()
else
filtered_out = null
air2.merge(filtered_out)
air3.merge(removed)
@@ -154,28 +106,22 @@ Filter types:
return ..()
/obj/machinery/atmospherics/components/trinary/filter/attack_hand(mob/user)
if(..() | !user)
return
interact(user)
/obj/machinery/atmospherics/components/trinary/filter/interact(mob/user)
if(stat & (BROKEN|NOPOWER))
return
if(!src.allowed(usr))
usr << "<span class='danger'>Access denied.</span>"
return
ui_interact(user)
..()
/obj/machinery/atmospherics/components/trinary/filter/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 0)
ui = SSnano.try_update_ui(user, src, ui_key, ui, force_open = force_open)
if (!ui)
ui = new(user, src, ui_key, "atmos_filter", name, 450, 145)
/obj/machinery/atmospherics/components/trinary/filter/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, \
datum/tgui/master_ui = null, datum/ui_state/state = default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "atmos_filter", name, 470, 140, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/trinary/filter/get_ui_data()
var/data = list()
data["on"] = on
data["set_pressure"] = round(target_pressure)
data["pressure"] = round(target_pressure)
data["max_pressure"] = round(MAX_OUTPUT_PRESSURE)
data["filter_type"] = filter_type
return data
@@ -183,32 +129,31 @@ Filter types:
/obj/machinery/atmospherics/components/trinary/filter/ui_act(action, params)
if(..())
return
switch(action)
if("power")
on=!on
on = !on
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
. = TRUE
if("pressure")
switch(params["set"])
if("max")
target_pressure = MAX_OUTPUT_PRESSURE
if("custom")
target_pressure = max(0, min(MAX_OUTPUT_PRESSURE, safe_input("Pressure control", "Enter new output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", target_pressure)))
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
var/pressure = params["pressure"]
if(pressure == "max")
target_pressure = MAX_OUTPUT_PRESSURE
. = TRUE
else if(pressure == "input")
pressure = input("New output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", name, target_pressure) as num|null
. = .(action, list("pressure" = pressure))
else if(text2num(pressure) != null)
target_pressure = Clamp(text2num(pressure), 0, MAX_OUTPUT_PRESSURE)
. = TRUE
if(.)
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
if("filter")
src.filter_type = text2num(params["mode"])
var/filtering_name = "nothing"
switch(filter_type)
if(FILTER_PLASMA)
filtering_name = "plasma"
if(FILTER_OXYGEN)
filtering_name = "oxygen"
if(FILTER_NITROGEN)
filtering_name = "nitrogen"
if(FILTER_CARBONDIOXIDE)
filtering_name = "carbon dioxide"
if(FILTER_NITROUSOXIDE)
filtering_name = "nitrous oxide"
investigate_log("was set to filter [filtering_name] by [key_name(usr)]", "atmos")
filter_type = ""
var/filter_name = "nothing"
var/mode = params["mode"]
if(mode in meta_gas_info)
filter_type = mode
filter_name = meta_gas_info[mode][META_GAS_NAME]
investigate_log("was set to filter [filter_name] by [key_name(usr)]", "atmos")
. = TRUE
update_icon()
return 1
@@ -117,22 +117,16 @@
return 1
/obj/machinery/atmospherics/components/trinary/mixer/attack_hand(mob/user)
if(..() | !user)
return
interact(user)
/obj/machinery/atmospherics/components/trinary/mixer/interact(mob/user)
if(stat & (BROKEN|NOPOWER))
return
if(!src.allowed(usr))
usr << "<span class='danger'>Access denied.</span>"
return
ui_interact(user)
..()
/obj/machinery/atmospherics/components/trinary/mixer/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 0)
ui = SSnano.try_update_ui(user, src, ui_key, ui, force_open = force_open)
if (!ui)
ui = new(user, src, ui_key, "atmos_mixer", name, 450, 175)
/obj/machinery/atmospherics/components/trinary/mixer/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, \
datum/tgui/master_ui = null, datum/ui_state/state = default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "atmos_mixer", name, 370, 165, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/trinary/mixer/get_ui_data()
@@ -147,27 +141,34 @@
/obj/machinery/atmospherics/components/trinary/mixer/ui_act(action, params)
if(..())
return
switch(action)
if("power")
on = !on
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
. = TRUE
if("pressure")
switch(params["set"])
if("max")
target_pressure = MAX_OUTPUT_PRESSURE
if("custom")
target_pressure = max(0, min(MAX_OUTPUT_PRESSURE, safe_input("Pressure control", "Enter new output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", target_pressure)))
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
var/pressure = params["pressure"]
if(pressure == "max")
target_pressure = MAX_OUTPUT_PRESSURE
. = TRUE
else if(pressure == "input")
pressure = input("New output pressure (0-[MAX_OUTPUT_PRESSURE] kPa):", name, target_pressure) as num|null
. = .(action, list("pressure" = pressure))
else if(text2num(pressure) != null)
target_pressure = Clamp(text2num(pressure), 0, MAX_OUTPUT_PRESSURE)
. = TRUE
if(.)
investigate_log("was set to [target_pressure] kPa by [key_name(usr)]", "atmos")
if("node1")
var/value = text2num(params["concentration"])
src.node1_concentration = max(0, min(1, src.node1_concentration + value))
src.node2_concentration = max(0, min(1, src.node2_concentration - value))
node1_concentration = max(0, min(1, node1_concentration + value))
node2_concentration = max(0, min(1, node2_concentration - value))
investigate_log("was set to [node1_concentration] % on node 1 by [key_name(usr)]", "atmos")
. = TRUE
if("node2")
var/value = text2num(params["concentration"])
src.node2_concentration = max(0, min(1, src.node2_concentration + value))
src.node1_concentration = max(0, min(1, src.node1_concentration - value))
node2_concentration = max(0, min(1, node2_concentration + value))
node1_concentration = max(0, min(1, node1_concentration - value))
investigate_log("was set to [node2_concentration] % on node 2 by [key_name(usr)]", "atmos")
update_icon()
return 1
. = TRUE
update_icon()
@@ -1,252 +0,0 @@
/obj/machinery/atmospherics/components/unary/cold_sink/freezer
name = "freezer"
icon = 'icons/obj/Cryogenic2.dmi'
icon_state = "freezer"
density = 1
var/min_temperature = 0
anchored = 1
use_power = 1
current_heat_capacity = 1000
/obj/machinery/atmospherics/components/unary/cold_sink/freezer/New()
..()
initialize_directions = dir
component_parts = list()
component_parts += new /obj/item/weapon/circuitboard/thermomachine(null)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(null)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(null)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(null)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(null)
component_parts += new /obj/item/weapon/stock_parts/console_screen(null)
component_parts += new /obj/item/stack/cable_coil(null, 1)
RefreshParts()
/obj/machinery/atmospherics/components/unary/cold_sink/freezer/construction()
..(dir,dir)
/obj/machinery/atmospherics/components/unary/cold_sink/freezer/RefreshParts()
var/H
var/T
for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts)
H += M.rating
for(var/obj/item/weapon/stock_parts/micro_laser/M in component_parts)
T += M.rating
min_temperature = max(T0C - (170 + T*15), TCMB)
current_heat_capacity = 1000 * ((H - 1) ** 2)
/obj/machinery/atmospherics/components/unary/cold_sink/freezer/attackby(obj/item/I, mob/user, params)
if(default_deconstruction_screwdriver(user, "freezer-o", "freezer", I))
on = 0
update_icon()
return
if(exchange_parts(user, I))
return
default_deconstruction_crowbar(I)
if(default_change_direction_wrench(user, I))
return
/obj/machinery/atmospherics/components/unary/cold_sink/freezer/update_icon()
if(panel_open)
icon_state = "freezer-o"
else if(src.on)
icon_state = "freezer_1"
else
icon_state = "freezer"
return
/obj/machinery/atmospherics/components/unary/cold_sink/freezer/attack_ai(mob/user)
return interact(user)
/obj/machinery/atmospherics/components/unary/cold_sink/freezer/attack_paw(mob/user)
return interact(user)
/obj/machinery/atmospherics/components/unary/cold_sink/freezer/attack_hand(mob/user)
return interact(user)
/obj/machinery/atmospherics/components/unary/cold_sink/freezer/interact(mob/user)
if(stat & (NOPOWER|BROKEN))
return
var/datum/gas_mixture/air_contents = AIR1
user.set_machine(src)
var/temp_text = ""
if(air_contents.temperature > (T0C - 20))
temp_text = "<span class='bad'>[air_contents.temperature]</span>"
else if(air_contents.temperature < (T0C - 20) && air_contents.temperature > (T0C - 100))
temp_text = "<span class='average'>[air_contents.temperature]</span>"
else
temp_text = "<span class='good'>[air_contents.temperature]</span>"
var/dat = {"
Current Status: [ on ? "<A href='?src=\ref[src];start=1'>Off</A> <span class='linkOn'>On</span>" : "<span class='linkOn'>Off</span> <A href='?src=\ref[src];start=1'>On</A>"]<BR>
Current Gas Temperature: [temp_text]<BR>
Current Air Pressure: [air_contents.return_pressure()]<BR>
Target Gas Temperature: <A href='?src=\ref[src];temp=-100'>-</A> <A href='?src=\ref[src];temp=-10'>-</A> <A href='?src=\ref[src];temp=-1'>-</A> [current_temperature] <A href='?src=\ref[src];temp=1'>+</A> <A href='?src=\ref[src];temp=10'>+</A> <A href='?src=\ref[src];temp=100'>+</A><BR>
"}
//user << browse(dat, "window=freezer;size=400x500")
//onclose(user, "freezer")
var/datum/browser/popup = new(user, "freezer", "Cryo Gas Cooling System", 400, 240) // Set up the popup browser window
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
popup.set_content(dat)
popup.open()
/obj/machinery/atmospherics/components/unary/cold_sink/freezer/Topic(href, href_list)
if(..())
return
usr.set_machine(src)
if (href_list["start"])
src.on = !src.on
use_power = 1 + src.on
update_icon()
if(href_list["temp"])
var/amount = text2num(href_list["temp"])
if(amount > 0)
src.current_temperature = min(T20C, src.current_temperature+amount)
else
src.current_temperature = max(min_temperature, src.current_temperature+amount)
active_power_usage = (current_heat_capacity * (T20C - current_temperature) / 100) + idle_power_usage
src.updateUsrDialog()
/obj/machinery/atmospherics/components/unary/cold_sink/freezer/process()
..()
src.updateUsrDialog()
/obj/machinery/atmospherics/components/unary/cold_sink/freezer/power_change()
..()
if(stat & NOPOWER)
on = 0
update_icon()
/obj/machinery/atmospherics/components/unary/heat_reservoir/heater/
name = "heater"
icon = 'icons/obj/Cryogenic2.dmi'
icon_state = "heater"
density = 1
var/max_temperature = 0
anchored = 1
current_heat_capacity = 1000
/obj/machinery/atmospherics/components/unary/heat_reservoir/heater/New()
..()
initialize_directions = dir
var/obj/item/weapon/circuitboard/thermomachine/H = new /obj/item/weapon/circuitboard/thermomachine(null)
H.build_path = /obj/machinery/atmospherics/components/unary/heat_reservoir/heater
H.name = "circuit board (Heater)"
component_parts = list()
component_parts += H
component_parts += new /obj/item/weapon/stock_parts/matter_bin(null)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(null)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(null)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(null)
component_parts += new /obj/item/weapon/stock_parts/console_screen(null)
component_parts += new /obj/item/stack/cable_coil(null, 1)
RefreshParts()
/obj/machinery/atmospherics/components/unary/heat_reservoir/heater/construction()
..(dir,dir)
/obj/machinery/atmospherics/components/unary/heat_reservoir/heater/RefreshParts()
var/H
var/T
for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts)
H += M.rating
for(var/obj/item/weapon/stock_parts/micro_laser/M in component_parts)
T += M.rating
max_temperature = T20C + (140 * T)
current_heat_capacity = 1000 * ((H - 1) ** 2)
/obj/machinery/atmospherics/components/unary/heat_reservoir/heater/attackby(obj/item/I, mob/user, params)
if(default_deconstruction_screwdriver(user, "heater-o", "heater", I))
on = 0
update_icon()
return
if(exchange_parts(user, I))
return
default_deconstruction_crowbar(I)
if(default_change_direction_wrench(user, I))
return
/obj/machinery/atmospherics/components/unary/heat_reservoir/heater/update_icon()
if(panel_open)
icon_state = "heater-o"
else if(src.on)
icon_state = "heater_1"
else
icon_state = "heater"
return
/obj/machinery/atmospherics/components/unary/heat_reservoir/heater/attack_ai(mob/user)
return src.attack_hand(user)
/obj/machinery/atmospherics/components/unary/heat_reservoir/heater/attack_paw(mob/user)
return src.attack_hand(user)
/obj/machinery/atmospherics/components/unary/heat_reservoir/heater/attack_hand(mob/user)
return interact(user)
/obj/machinery/atmospherics/components/unary/heat_reservoir/heater/interact(mob/user)
var/datum/gas_mixture/air_contents = AIR1
if(stat & (NOPOWER|BROKEN))
return
user.set_machine(src)
var/temp_text = ""
if(air_contents.temperature < (T20C + 80))
temp_text = "<span class='good'>[air_contents.temperature]</span>"
else if(air_contents.temperature > (T20C + 80) && air_contents.temperature < (T20C + 180))
temp_text = "<span class='average'>[air_contents.temperature]</span>"
else
temp_text = "<span class='bad'>[air_contents.temperature]</span>"
var/dat = {"
Current Status: [ on ? "<A href='?src=\ref[src];start=1'>Off</A> <span class='linkOn'>On</span>" : "<span class='linkOn'>Off</span> <A href='?src=\ref[src];start=1'>On</A>"]<BR>
Current Gas Temperature: [temp_text]<BR>
Current Air Pressure: [air_contents.return_pressure()]<BR>
Target Gas Temperature: <A href='?src=\ref[src];temp=-100'>-</A> <A href='?src=\ref[src];temp=-10'>-</A> <A href='?src=\ref[src];temp=-1'>-</A> [current_temperature] <A href='?src=\ref[src];temp=1'>+</A> <A href='?src=\ref[src];temp=10'>+</A> <A href='?src=\ref[src];temp=100'>+</A><BR>
"}
//user << browse(dat, "window=freezer;size=400x500")
//onclose(user, "freezer")
var/datum/browser/popup = new(user, "freezer", "Pyro Gas Heating System", 400, 240) // Set up the popup browser window
popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
popup.set_content(dat)
popup.open()
/obj/machinery/atmospherics/components/unary/heat_reservoir/heater/Topic(href, href_list)
if(..())
return
usr.set_machine(src)
if (href_list["start"])
src.on = !src.on
use_power = 1 + src.on
update_icon()
if(href_list["temp"])
var/amount = text2num(href_list["temp"])
if(amount > 0)
src.current_temperature = min((max_temperature), src.current_temperature+amount)
else
src.current_temperature = max(T20C, src.current_temperature+amount)
active_power_usage = (current_heat_capacity * (current_temperature - T20C) / 100) + idle_power_usage
src.updateUsrDialog()
src.add_fingerprint(usr)
return
/obj/machinery/atmospherics/components/unary/heat_reservoir/heater/process()
..()
src.updateUsrDialog()
/obj/machinery/atmospherics/components/unary/heat_reservoir/heater/power_change()
..()
if(stat & NOPOWER)
on = 0
update_icon()
@@ -1,43 +0,0 @@
/obj/machinery/atmospherics/components/unary/cold_sink
icon_state = "cold_map"
use_power = 1
name = "cold sink"
desc = "Cools gas when connected to pipe network"
var/on = 0
var/current_temperature = T20C
var/current_heat_capacity = 50000 //totally random
/obj/machinery/atmospherics/components/unary/cold_sink/update_icon_nopipes()
overlays.Cut()
if(showpipe)
overlays += getpipeimage('icons/obj/atmospherics/components/unary_devices.dmi', "scrub_cap", initialize_directions) //scrub_cap works for now
if(!NODE1 || !on || stat & (NOPOWER|BROKEN))
icon_state = "cold_off"
return
else
icon_state = "cold_on"
/obj/machinery/atmospherics/components/unary/cold_sink/process_atmos()
..()
if(!on)
return 0
var/datum/gas_mixture/air_contents = AIR1
var/air_heat_capacity = air_contents.heat_capacity()
var/combined_heat_capacity = current_heat_capacity + air_heat_capacity
var/old_temperature = air_contents.temperature
if(combined_heat_capacity > 0)
var/combined_energy = current_temperature*current_heat_capacity + air_heat_capacity*air_contents.temperature
air_contents.temperature = combined_energy/combined_heat_capacity
//todo: have current temperature affected. require power to bring down current temperature again
if(abs(old_temperature-air_contents.temperature) > 1)
update_parents()
return 1
+165 -223
View File
@@ -4,16 +4,20 @@
icon_state = "cell-off"
density = 1
anchored = 1
layer = 4
var/on = 0
var/temperature_archived
var/obj/item/weapon/reagent_containers/glass/beaker = null
var/next_trans = 0
var/current_heat_capacity = 50
state_open = 0
var/on = FALSE
state_open = FALSE
var/autoeject = FALSE
var/volume = 100
var/efficiency = 1
var/autoEject = 0
var/sleep_factor = 750
var/paralyze_factor = 1000
var/heat_capacity = 100000
var/conduction_coefficient = 0.01
var/obj/item/weapon/reagent_containers/glass/beaker = null
var/reagent_transfer = 0
/obj/machinery/atmospherics/components/unary/cryo_cell/New()
..()
@@ -27,117 +31,178 @@
component_parts += new /obj/item/weapon/stock_parts/console_screen(null)
component_parts += new /obj/item/stack/cable_coil(null, 1)
/obj/machinery/atmospherics/components/unary/cryo_cell/construction()
..(dir,dir)
..(dir, dir)
/obj/machinery/atmospherics/components/unary/cryo_cell/RefreshParts()
var/C
for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts)
C += M.rating
current_heat_capacity = 50 * C
efficiency = C
efficiency = initial(efficiency) * C
sleep_factor = initial(sleep_factor) * C
paralyze_factor = initial(paralyze_factor) * C
heat_capacity = initial(heat_capacity) / C
conduction_coefficient = initial(conduction_coefficient) * C
/obj/machinery/atmospherics/components/unary/cryo_cell/Destroy()
var/turf/T = loc
T.contents += contents
if(beaker)
beaker.loc = get_step(loc, SOUTH) // Beaker is carefully ejected from the wreckage of the cryotube.
beaker = null
return ..()
/obj/machinery/atmospherics/components/unary/cryo_cell/process_atmos()
..()
var/datum/gas_mixture/air_contents = AIR1
if(air_contents)
temperature_archived = air_contents.temperature
heat_gas_contents()
if(abs(temperature_archived-air_contents.temperature) > 1)
update_parents()
/obj/machinery/atmospherics/components/unary/cryo_cell/update_icon()
if(panel_open)
icon_state = "cell-o"
else if(state_open)
icon_state = "cell-open"
else if(on && is_operational())
if(occupant)
icon_state = "cell-occupied"
else
icon_state = "cell-on"
else
icon_state = "cell-off"
/obj/machinery/atmospherics/components/unary/cryo_cell/process()
..()
if(occupant && occupant.health >= 100)
on = 0
playsound(src.loc, 'sound/machines/ding.ogg', 50, 1)
if(autoEject)
open_machine()
if(!NODE1 || !is_operational())
if(!on)
return
if(AIR1)
if(on && occupant)
process_occupant()
expel_gas()
var/datum/gas_mixture/air1 = AIR1
if(occupant)
if(occupant.health >= 100) // Don't bother with fully healed people.
on = FALSE
update_icon()
playsound(src.loc, 'sound/machines/ding.ogg', volume, 1) // Bug the doctors.
if(autoeject) // Eject if configured.
open_machine()
return
else if(occupant.stat == DEAD) // We don't bother with dead people.
return
if(occupant.bodytemperature < T0C) // Sleepytime. Why? More cryo magic.
occupant.sleeping = (occupant.bodytemperature / sleep_factor) * 100
occupant.paralysis = (occupant.bodytemperature / paralyze_factor) * 100
if(beaker)
if(reagent_transfer == 0) // Magically transfer reagents. Because cryo magic.
beaker.reagents.trans_to(occupant, 1, 10 * efficiency) // Transfer reagents, multiplied because cryo magic.
beaker.reagents.reaction(occupant, VAPOR)
air1.gases["o2"][MOLES] -= 2 / efficiency // Lets use gas for this.
if(++reagent_transfer >= 10 * efficiency) // Throttle reagent transfer (higher efficiency will transfer the same amount but consume less from the beaker).
reagent_transfer = 0
return 1
/obj/machinery/atmospherics/components/unary/cryo_cell/MouseDrop_T(mob/target, mob/user)
if(user.stat || user.lying || !Adjacent(user) || !target.Adjacent(user) || !iscarbon(target))
/obj/machinery/atmospherics/components/unary/cryo_cell/process_atmos()
..()
if(!on)
return
close_machine(target)
var/datum/gas_mixture/air1 = AIR1
if(!NODE1 || !AIR1 || air1.gases["o2"][MOLES] < 5) // Turn off if the machine won't work.
on = FALSE
update_icon()
return
if(occupant)
var/cold_protection = 0
var/mob/living/carbon/human/H = occupant
if(istype(H))
cold_protection = H.get_cold_protection(air1.temperature)
/obj/machinery/atmospherics/components/unary/cryo_cell/relaymove(mob/user)
var/temperature_delta = air1.temperature - occupant.bodytemperature // The only semi-realistic thing here: share temperature between the cell and the occupant.
if(abs(temperature_delta) > 1)
var/air_heat_capacity = air1.heat_capacity()
var/heat = ((1 - cold_protection) / 10 + conduction_coefficient) \
* temperature_delta * \
(air_heat_capacity * heat_capacity / (air_heat_capacity + heat_capacity))
air1.temperature = max(air1.temperature - heat / air_heat_capacity, TCMB)
occupant.bodytemperature = max(occupant.bodytemperature + heat / heat_capacity, TCMB)
air1.gases["o2"][MOLES] -= 0.5 / efficiency // Magically consume gas? Why not, we run on cryo magic.
/obj/machinery/atmospherics/components/unary/cryo_cell/power_change()
..()
update_icon()
/obj/machinery/atmospherics/components/unary/cryo_cell/relaymove(mob/user) // Prevent ventcrawl in this machine.
return
/obj/machinery/atmospherics/components/unary/cryo_cell/container_resist()
/obj/machinery/atmospherics/components/unary/cryo_cell/open_machine()
if(!state_open && !panel_open)
on = FALSE
..()
if(beaker)
beaker.loc = src
/obj/machinery/atmospherics/components/unary/cryo_cell/close_machine(mob/living/carbon/user)
if((isnull(user) || istype(user)) && state_open && !panel_open)
..(user)
return occupant
/obj/machinery/atmospherics/components/unary/cryo_cell/container_resist(mob/user)
usr << "<span class='notice'>You struggle inside the cryotube, kicking the release with your foot.</span>"
sleep(150)
if(!src || !usr || (!occupant && !contents.Find(usr))) // Make sure they didn't disappear.
return
open_machine()
audible_message("<span class='notice'>You hear a thump from [src].</span>")
addtimer(src, "resist_open", 300, FALSE, user)
/obj/machinery/atmospherics/components/unary/cryo_cell/proc/resist_open(mob/user)
if(occupant && (user in src)) // Check they're still here.
open_machine()
/obj/machinery/atmospherics/components/unary/cryo_cell/examine(mob/user)
..()
var/list/otherstuff = contents - beaker
if(otherstuff.len > 0)
user << "You can just about make out some loose objects floating in the murk:"
for(var/atom/movable/floater in otherstuff)
user << "\icon[floater] [floater.name]"
if(occupant)
if(on)
user << "Someone's inside [src]!"
else
user << "You can barely make out a form floating in [src]."
else
user << "Seems empty."
user << "[src] seems empty."
/obj/machinery/atmospherics/components/unary/cryo_cell/attack_hand(mob/user)
if(..() | !user)
/obj/machinery/atmospherics/components/unary/cryo_cell/MouseDrop_T(mob/target, mob/user)
if(user.stat || user.lying || !Adjacent(user) || !Adjacent(target))
return
interact(user)
close_machine(target)
/obj/machinery/atmospherics/components/unary/cryo_cell/interact(mob/user)
if(panel_open)
/obj/machinery/atmospherics/components/unary/cryo_cell/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/reagent_containers/glass))
if(isrobot(user))
return
if(beaker)
user << "<span class='warning'>A beaker is already loaded into [src]!</span>"
return
if(!user.drop_item())
return
beaker = I
I.loc = src
user.visible_message("[user] places [I] in [src].", \
"<span class='notice'>You place [I] in [src].</span>")
if(!(on || occupant || state_open))
if(default_deconstruction_screwdriver(user, "cell-o", "cell-off", I))
return
if(exchange_parts(user, I))
return
if(default_change_direction_wrench(user, I))
return
if(default_pry_open(I))
return
if(default_deconstruction_crowbar(I))
return
ui_interact(user)
/obj/machinery/atmospherics/components/unary/cryo_cell/ui_interact(mob/user, ui_key = "main", datum/nanoui/ui = null, force_open = 0)
ui = SSnano.try_update_ui(user, src, ui_key, ui, force_open = force_open)
if (!ui)
ui = new(user, src, ui_key, "cryo", name, 410, 550, state = notcontained_state)
/obj/machinery/atmospherics/components/unary/cryo_cell/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, \
datum/tgui/master_ui = null, datum/ui_state/state = notcontained_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "cryo", name, 400, 550, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/unary/cryo_cell/get_ui_data()
// this is the data which will be sent to the ui
var/datum/gas_mixture/air_contents = AIR1
var/data = list()
var/list/data = list()
data["isOperating"] = on
data["hasOccupant"] = occupant ? 1 : 0
data["autoEject"] = autoEject
data["isOpen"] = state_open
data["autoEject"] = autoeject
var/occupantData = list()
if (!occupant)
occupantData["name"] = null
occupantData["stat"] = null
occupantData["health"] = null
occupantData["maxHealth"] = null
occupantData["minHealth"] = null
occupantData["bruteLoss"] = null
occupantData["oxyLoss"] = null
occupantData["toxLoss"] = null
occupantData["fireLoss"] = null
occupantData["bodyTemperature"] = null
else
var/list/occupantData = list()
if(occupant)
occupantData["name"] = occupant.name
occupantData["stat"] = occupant.stat
occupantData["health"] = occupant.health
@@ -150,163 +215,40 @@
occupantData["bodyTemperature"] = occupant.bodytemperature
data["occupant"] = occupantData
data["isOpen"] = state_open
data["cellTemperature"] = round(air_contents.temperature)
data["cellTemperatureStatus"] = "good"
if(air_contents.temperature > T0C) // if greater than 273.15 kelvin (0 celcius)
data["cellTemperatureStatus"] = "bad"
else if(air_contents.temperature > 225)
data["cellTemperatureStatus"] = "average"
var/datum/gas_mixture/air1 = AIR1
data["cellTemperature"] = round(air1.temperature)
data["isBeakerLoaded"] = beaker ? 1 : 0
var beakerContents[0]
var beakerContents = list()
if(beaker && beaker.reagents && beaker.reagents.reagent_list.len)
for(var/datum/reagent/R in beaker.reagents.reagent_list)
beakerContents.Add(list(list("name" = R.name, "volume" = R.volume))) // list in a list because Byond merges the first list...
beakerContents += list(list("name" = R.name, "volume" = R.volume))
data["beakerContents"] = beakerContents
return data
/obj/machinery/atmospherics/components/unary/cryo_cell/ui_act(action, params)
if(..())
return
switch(action)
if("open")
open_machine()
if("close")
close_machine()
if("power")
if(on)
on = FALSE
else if(!state_open)
on = TRUE
. = TRUE
if("door")
if(state_open)
close_machine()
else
open_machine()
. = TRUE
if("autoeject")
autoEject = !autoEject
if("on")
if(!state_open)
on = 1
if("off")
on = 0
autoeject = !autoeject
. = TRUE
if("ejectbeaker")
if(beaker)
beaker.loc = get_step(loc, SOUTH)
beaker.loc = loc
beaker = null
. = TRUE
update_icon()
return 1
/obj/machinery/atmospherics/components/unary/cryo_cell/attackby(obj/item/I, mob/user, params)
if(istype(I, /obj/item/weapon/reagent_containers/glass))
if(isrobot(user))
return
if(beaker)
user << "<span class='warning'>A beaker is already loaded into [src]!</span>"
return
if(!user.drop_item())
return
beaker = I
I.loc = src
user.visible_message("[user] places [I] in [src].", \
"<span class='notice'>You place [I] in [src].</span>")
if(!(on || occupant || state_open))
if(default_deconstruction_screwdriver(user, "cell-o", "cell-off", I))
return
if(default_change_direction_wrench(user, I))
return
if(exchange_parts(user, I))
return
if(default_pry_open(I))
return
default_deconstruction_crowbar(I)
/obj/machinery/atmospherics/components/unary/cryo_cell/open_machine()
if(!state_open && !panel_open)
on = 0
layer = 3
if(occupant)
occupant.bodytemperature = Clamp(occupant.bodytemperature, 261, 360)
..()
if(beaker)
beaker.loc = src
/obj/machinery/atmospherics/components/unary/cryo_cell/close_machine(mob/living/carbon/M)
if(state_open && !panel_open)
layer = 4
..(M)
return occupant
/obj/machinery/atmospherics/components/unary/cryo_cell/update_icon()
if(panel_open)
icon_state = "cell-o"
return
if(state_open)
icon_state = "cell-open"
return
if(on && is_operational())
if(occupant)
icon_state = "cell-occupied"
else
icon_state = "cell-on"
else
icon_state = "cell-off"
/obj/machinery/atmospherics/components/unary/cryo_cell/power_change()
..()
update_icon()
/obj/machinery/atmospherics/components/unary/cryo_cell/proc/process_occupant()
var/datum/gas_mixture/air_contents = AIR1
if(!on)
return
if(air_contents.total_moles() < 10)
return
if(occupant)
if(occupant.stat == 2 || occupant.health >= 100) //Why waste energy on dead or healthy people
occupant.bodytemperature = T0C
return
occupant.bodytemperature += 2*(air_contents.temperature - occupant.bodytemperature) * current_heat_capacity / (current_heat_capacity + air_contents.heat_capacity())
occupant.bodytemperature = max(occupant.bodytemperature, air_contents.temperature) // this is so ugly i'm sorry for doing it i'll fix it later i promise //TODO: fix someone else's broken promise - duncathan
if(occupant.bodytemperature < T0C)
occupant.sleeping = max(5 / efficiency, (1 / occupant.bodytemperature) * 2000 / efficiency)
occupant.Paralyse(max(5 / efficiency, (1 / occupant.bodytemperature) * 3000 / efficiency))
if(air_contents.oxygen > 2)
if(occupant.getOxyLoss()) occupant.adjustOxyLoss(-1)
else
occupant.adjustOxyLoss(-1)
// Severe damage should heal waaay slower without proper chemicals...
if(occupant.bodytemperature < 225)
if(occupant.getToxLoss())
occupant.adjustToxLoss(max(-efficiency, (-20*(efficiency ** 2)) / occupant.getToxLoss()))
var/heal_brute = occupant.getBruteLoss() ? min(efficiency, 20*(efficiency**2) / occupant.getBruteLoss()) : 0
var/heal_fire = occupant.getFireLoss() ? min(efficiency, 20*(efficiency**2) / occupant.getFireLoss()) : 0
occupant.heal_organ_damage(heal_brute, heal_fire)
if(beaker && next_trans == 0)
beaker.reagents.trans_to(occupant, 1, 10)
beaker.reagents.reaction(occupant, VAPOR)
next_trans++
if(next_trans == 10)
next_trans = 0
/obj/machinery/atmospherics/components/unary/cryo_cell/proc/heat_gas_contents()
var/datum/gas_mixture/air_contents = AIR1
if(air_contents.total_moles() < 1)
return
var/air_heat_capacity = air_contents.heat_capacity()
var/combined_heat_capacity = current_heat_capacity + air_heat_capacity
if(combined_heat_capacity > 0)
var/combined_energy = T20C * current_heat_capacity + air_heat_capacity * air_contents.temperature
air_contents.temperature = combined_energy/combined_heat_capacity
/obj/machinery/atmospherics/components/unary/cryo_cell/proc/expel_gas()
var/datum/gas_mixture/air_contents = AIR1
if(air_contents.total_moles() < 1)
return
var/datum/gas_mixture/expel_gas = new
var/remove_amount = air_contents.total_moles() / 100
expel_gas = air_contents.remove(remove_amount)
expel_gas.temperature = T20C //Lets expel hot gas and see if that helps people not die as they are removed
loc.assume_air(expel_gas)
air_update_turf()
@@ -1,46 +0,0 @@
/obj/machinery/atmospherics/components/unary/heat_reservoir
//currently the same code as cold_sink but anticipating process() changes
icon_state = "cold_map"
use_power = 1
name = "heat reservoir"
desc = "Heats gas when connected to pipe network"
var/on = 0
var/current_temperature = T20C
var/current_heat_capacity = 50000 //totally random
/obj/machinery/atmospherics/components/unary/heat_reservoir/update_icon_nopipes()
overlays.Cut()
if(showpipe)
overlays += getpipeimage('icons/obj/atmospherics/components/unary_devices.dmi', "scrub_cap", initialize_directions) //scrub_cap works for now
if(!NODE1 || !on || stat & (NOPOWER|BROKEN))
icon_state = "cold_off"
return
else
icon_state = "cold_on"
/obj/machinery/atmospherics/components/unary/heat_reservoir/process_atmos()
..()
if(!on)
return 0
var/datum/gas_mixture/air_contents = AIR1
var/air_heat_capacity = air_contents.heat_capacity()
var/combined_heat_capacity = current_heat_capacity + air_heat_capacity
var/old_temperature = air_contents.temperature
if(combined_heat_capacity > 0)
var/combined_energy = current_temperature*current_heat_capacity + air_heat_capacity*air_contents.temperature
air_contents.temperature = combined_energy/combined_heat_capacity
//todo: have current temperature affected. require power to bring up current temperature again
if(abs(old_temperature-air_contents.temperature) > 1)
update_parents()
return 1
@@ -46,7 +46,8 @@
var/added_oxygen = oxygen_content - total_moles
air_contents.temperature = (current_heat_capacity*air_contents.temperature + 20*added_oxygen*T0C)/(current_heat_capacity+20*added_oxygen)
air_contents.oxygen += added_oxygen
air_contents.assert_gas("o2")
air_contents.gases["o2"][MOLES] += added_oxygen
update_parents()
@@ -8,6 +8,12 @@
use_power = 0
level = 0
/obj/machinery/atmospherics/components/unary/portables_connector/New()
..()
var/datum/gas_mixture/air_contents = AIR1
air_contents.volume = 0
/obj/machinery/atmospherics/components/unary/portables_connector/visible
level = 2
@@ -6,58 +6,36 @@
desc = "A large vessel containing pressurized gas."
var/volume = 10000 //in liters, 1 meters by 1 meters by 2 meters
density = 1
var/gas_type = 0
/obj/machinery/atmospherics/components/unary/tank/New()
..()
var/datum/gas_mixture/air_contents = AIR1
air_contents.volume = volume
air_contents.temperature = T20C
if(gas_type)
air_contents.assert_gas(gas_type)
air_contents.gases[gas_type][MOLES] = AIR_CONTENTS
name = "[name] ([air_contents.gases[gas_type][GAS_NAME]])"
/obj/machinery/atmospherics/components/unary/tank/carbon_dioxide
name = "pressure tank (Carbon Dioxide)"
/obj/machinery/atmospherics/components/unary/tank/carbon_dioxide/New()
..()
var/datum/gas_mixture/air_contents = AIR1
air_contents.carbon_dioxide = AIR_CONTENTS
gas_type = "co2"
/obj/machinery/atmospherics/components/unary/tank/toxins
icon_state = "orange"
name = "pressure tank (Plasma)"
/obj/machinery/atmospherics/components/unary/tank/toxins/New()
..()
var/datum/gas_mixture/air_contents = AIR1
air_contents.toxins = AIR_CONTENTS
gas_type = "plasma"
/obj/machinery/atmospherics/components/unary/tank/oxygen_agent_b
icon_state = "orange_2"
name = "pressure tank (Oxygen + Plasma)"
/obj/machinery/atmospherics/components/unary/tank/oxygen_agent_b/New()
..()
var/datum/gas_mixture/air_contents = AIR1
var/datum/gas/oxygen_agent_b/trace_gas = new
trace_gas.moles = AIR_CONTENTS
air_contents.trace_gases += trace_gas
gas_type = "agent_b"
/obj/machinery/atmospherics/components/unary/tank/oxygen
icon_state = "blue"
name = "pressure tank (Oxygen)"
/obj/machinery/atmospherics/components/unary/tank/oxygen/New()
..()
var/datum/gas_mixture/air_contents = AIR1
air_contents.oxygen = AIR_CONTENTS
gas_type = "o2"
/obj/machinery/atmospherics/components/unary/tank/nitrogen
icon_state = "red"
name = "pressure tank (Nitrogen)"
/obj/machinery/atmospherics/components/unary/tank/nitrogen/New()
..()
var/datum/gas_mixture/air_contents = AIR1
air_contents.nitrogen = AIR_CONTENTS
gas_type = "n2"
/obj/machinery/atmospherics/components/unary/tank/air
icon_state = "grey"
@@ -66,5 +44,6 @@
/obj/machinery/atmospherics/components/unary/tank/air/New()
..()
var/datum/gas_mixture/air_contents = AIR1
air_contents.oxygen = AIR_CONTENTS * 0.2
air_contents.nitrogen = AIR_CONTENTS * 0.8
air_contents.assert_gases("o2", "n2")
air_contents.gases["o2"][MOLES] = AIR_CONTENTS * 0.2
air_contents.gases["n2"][MOLES] = AIR_CONTENTS * 0.8
@@ -0,0 +1,174 @@
/obj/machinery/atmospherics/components/unary/thermomachine
name = "thermomachine"
desc = "Heats or cools gas in connected pipes."
icon_state = "cold_map"
var/icon_state_on = "cold_on"
var/icon_state_open = "cold_off"
density = TRUE
anchored = TRUE
var/on = FALSE
var/min_temperature = 0
var/max_temperature = 0
var/target_temperature = T20C
var/heat_capacity = 0
var/interactive = TRUE // So mapmakers can disable interaction.
/obj/machinery/atmospherics/components/unary/thermomachine/New()
..()
initialize_directions = dir
component_parts = list()
component_parts += new /obj/item/weapon/stock_parts/matter_bin(null)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(null)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(null)
component_parts += new /obj/item/weapon/stock_parts/micro_laser(null)
component_parts += new /obj/item/weapon/stock_parts/console_screen(null)
component_parts += new /obj/item/stack/cable_coil(null, 1)
RefreshParts()
/obj/machinery/atmospherics/components/unary/thermomachine/construction()
..(dir,dir)
/obj/machinery/atmospherics/components/unary/thermomachine/RefreshParts()
var/B
for(var/obj/item/weapon/stock_parts/matter_bin/M in component_parts)
B += M.rating
heat_capacity = 1000 * ((B - 1) ** 2)
/obj/machinery/atmospherics/components/unary/thermomachine/update_icon()
if(panel_open)
icon_state = icon_state_open
else if(on && is_operational())
icon_state = icon_state_on
else
icon_state = initial(icon_state)
return
/obj/machinery/atmospherics/components/unary/thermomachine/update_icon_nopipes()
overlays.Cut()
if(showpipe)
overlays += getpipeimage(icon, "scrub_cap", initialize_directions)
/obj/machinery/atmospherics/components/unary/thermomachine/process_atmos()
..()
if(!on || !NODE1)
return
var/datum/gas_mixture/air_contents = AIR1
var/air_heat_capacity = air_contents.heat_capacity()
var/combined_heat_capacity = heat_capacity + air_heat_capacity
var/old_temperature = air_contents.temperature
if(combined_heat_capacity > 0)
var/combined_energy = heat_capacity * target_temperature + air_heat_capacity * air_contents.temperature
air_contents.temperature = combined_energy/combined_heat_capacity
var/temperature_delta= abs(old_temperature - air_contents.temperature)
if(temperature_delta > 1)
active_power_usage = (heat_capacity * temperature_delta) / 10 + idle_power_usage
update_parents()
else
active_power_usage = idle_power_usage
return 1
/obj/machinery/atmospherics/components/unary/thermomachine/power_change()
..()
update_icon()
/obj/machinery/atmospherics/components/unary/thermomachine/attackby(obj/item/I, mob/user, params)
if(!(on || state_open))
if(default_deconstruction_screwdriver(user, icon_state_open, initial(icon_state), I))
return
if(exchange_parts(user, I))
return
if(default_change_direction_wrench(user, I))
return
if(default_deconstruction_crowbar(I))
return
/obj/machinery/atmospherics/components/unary/thermomachine/ui_interact(mob/user, ui_key = "main", datum/tgui/ui = null, force_open = 0, \
datum/tgui/master_ui = null, datum/ui_state/state = default_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if(!ui)
ui = new(user, src, ui_key, "thermomachine", name, 400, 240, master_ui, state)
ui.open()
/obj/machinery/atmospherics/components/unary/thermomachine/get_ui_data(mob/user)
var/list/data = list()
data["on"] = on
data["min"] = min_temperature
data["max"] = max_temperature
data["target"] = target_temperature
data["initial"] = initial(target_temperature)
var/datum/gas_mixture/air1 = AIR1
data["temperature"] = air1.temperature
data["pressure"] = air1.return_pressure()
return data
/obj/machinery/atmospherics/components/unary/thermomachine/ui_act(action, params)
if(..() || !interactive)
return
switch(action)
if("power")
on = !on
use_power = 1 + on
investigate_log("was turned [on ? "on" : "off"] by [key_name(usr)]", "atmos")
. = TRUE
if("target")
var/target = params["target"]
var/adjust = text2num(params["adjust"])
if(target == "input")
target = input("Set new target ([min_temperature]-[max_temperature] K):", name, target_temperature) as num|null
. = .(action, list("target" = target))
else if(text2num(target) != null)
target_temperature = text2num(target)
. = TRUE
else if(adjust)
target_temperature += adjust
. = TRUE
if(.)
target_temperature = Clamp(target_temperature, min_temperature, max_temperature)
investigate_log("was set to [target_temperature] K by [key_name(usr)]", "atmos")
update_icon()
/obj/machinery/atmospherics/components/unary/thermomachine/freezer
name = "freezer"
icon = 'icons/obj/Cryogenic2.dmi'
icon_state = "freezer"
icon_state_on = "freezer_1"
icon_state_open = "freezer-o"
max_temperature = T20C
min_temperature = 170
/obj/machinery/atmospherics/components/unary/thermomachine/freezer/New()
..()
component_parts += new /obj/item/weapon/circuitboard/thermomachine/freezer(null)
/obj/machinery/atmospherics/components/unary/thermomachine/freezer/RefreshParts()
..()
var/L
for(var/obj/item/weapon/stock_parts/micro_laser/M in component_parts)
L += M.rating
min_temperature = max(T0C - (initial(min_temperature) + L * 15), TCMB)
/obj/machinery/atmospherics/components/unary/thermomachine/heater
name = "heater"
icon = 'icons/obj/Cryogenic2.dmi'
icon_state = "heater"
icon_state_on = "heater_1"
icon_state_open = "heater-o"
max_temperature = 140
min_temperature = T20C
/obj/machinery/atmospherics/components/unary/thermomachine/heater/New()
..()
component_parts += new /obj/item/weapon/circuitboard/thermomachine/heater(null)
/obj/machinery/atmospherics/components/unary/thermomachine/heater/RefreshParts()
..()
var/L
for(var/obj/item/weapon/stock_parts/micro_laser/M in component_parts)
L += M.rating
max_temperature = T20C + (initial(max_temperature) * L)
@@ -102,11 +102,7 @@
return
if (!NODE1)
on = 0
//broadcast_status() // from now air alarm/control computer should request update purposely --rastaf0
if(!on)
return 0
if(welded)
if(!on || welded)
return 0
var/datum/gas_mixture/air_contents = AIR1
@@ -170,7 +166,8 @@
signal.data = list(
"area" = src.area_uid,
"tag" = src.id_tag,
"device" = "AVP",
"frequency" = frequency,
"device" = "VP",
"power" = on,
"direction" = pump_direction?("release"):("siphon"),
"checks" = pressure_checks,
@@ -236,6 +233,9 @@
if("set_external_pressure" in signal.data)
external_pressure_bound = Clamp(text2num(signal.data["set_external_pressure"]),0,ONE_ATMOSPHERE*50)
if("reset_external_pressure" in signal.data)
external_pressure_bound = ONE_ATMOSPHERE
if("adjust_internal_pressure" in signal.data)
internal_pressure_bound = Clamp(internal_pressure_bound + text2num(signal.data["adjust_internal_pressure"]),0,ONE_ATMOSPHERE*50)
@@ -247,13 +247,11 @@
return
if("status" in signal.data)
spawn(2)
broadcast_status()
broadcast_status()
return //do not update_icon
//log_admin("DEBUG \[[world.timeofday]\]: vent_pump/receive_signal: unknown command \"[signal.data["command"]]\"\n[signal.debug_print()]")
spawn(2)
broadcast_status()
broadcast_status()
update_icon()
return
@@ -277,7 +275,7 @@
welded = 0
update_icon()
pipe_vision_img = image(src, loc, layer = 20, dir = dir)
return 1
return 0
else
return ..()
@@ -117,7 +117,8 @@
signal.data = list(
"area" = area_uid,
"tag" = id_tag,
"device" = "AScr",
"frequency" = frequency,
"device" = "VS",
"timestamp" = world.time,
"power" = on,
"scrubbing" = scrubbing,
@@ -151,51 +152,66 @@
return
if (!NODE1)
on = 0
//broadcast_status()
if(!on || welded)
return 0
scrub(loc)
if (widenet)
if(widenet)
for (var/turf/simulated/tile in adjacent_turfs)
scrub(tile)
/obj/machinery/atmospherics/components/unary/vent_scrubber/proc/scrub(var/turf/simulated/tile)
if (!tile || !istype(tile))
if (!istype(tile))
return 0
var/datum/gas_mixture/environment = tile.return_air()
var/datum/gas_mixture/air_contents = AIR1
var/list/env_gases = environment.gases
if(scrubbing & SCRUBBING)
if((environment.toxins>0) || (environment.carbon_dioxide>0) || (environment.trace_gases.len>0))
var/should_we_scrub = FALSE
for(var/id in env_gases)
if(id == "n2" || id == "o2")
continue
if(env_gases[id][MOLES])
should_we_scrub = TRUE
break
if(should_we_scrub)
var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles()
//Take a gas sample
var/datum/gas_mixture/removed = tile.remove_air(transfer_moles)
var/list/removed_gases = removed.gases
if (isnull(removed)) //in space
return
//Filter it
var/datum/gas_mixture/filtered_out = new
var/list/filtered_gases = filtered_out.gases
filtered_out.temperature = removed.temperature
if(scrub_Toxins)
filtered_out.toxins = removed.toxins
removed.toxins = 0
if(scrub_CO2)
filtered_out.carbon_dioxide = removed.carbon_dioxide
removed.carbon_dioxide = 0
if(removed.trace_gases.len>0)
for(var/datum/gas/trace_gas in removed.trace_gases)
if(istype(trace_gas, /datum/gas/oxygen_agent_b))
removed.trace_gases -= trace_gas
filtered_out.trace_gases += trace_gas
else if(istype(trace_gas, /datum/gas/sleeping_agent) && scrub_N2O)
removed.trace_gases -= trace_gas
filtered_out.trace_gases += trace_gas
if(scrub_Toxins && removed_gases["plasma"])
filtered_out.assert_gas("plasma")
filtered_gases["plasma"][MOLES] = removed_gases["plasma"][MOLES]
removed.gases["plasma"][MOLES] = 0
if(scrub_CO2 && removed_gases["co2"])
filtered_out.assert_gas("co2")
filtered_out.gases["co2"][MOLES] = removed_gases["co2"][MOLES]
removed.gases["co2"][MOLES] = 0
if(removed_gases["agent_b"])
filtered_out.assert_gas("agent_b")
filtered_out.gases["agent_b"][MOLES] = removed_gases["agent_b"][MOLES]
removed.gases["agent_b"][MOLES] = 0
if(scrub_N2O && removed_gases["n2o"])
filtered_out.assert_gas("n2o")
filtered_out.gases["n2o"][MOLES] = removed_gases["n2o"][MOLES]
removed.gases["n2o"][MOLES] = 0
removed.garbage_collect()
//Remix the resulting gases
air_contents.merge(filtered_out)
@@ -275,12 +291,10 @@
return
if("status" in signal.data)
spawn(2)
broadcast_status()
broadcast_status()
return //do not update_icon
spawn(2)
broadcast_status()
broadcast_status()
update_icon()
return
@@ -309,7 +323,7 @@
welded = 0
update_icon()
pipe_vision_img = image(src, loc, layer = 20, dir = dir)
return 1
return 0
if (!istype(W, /obj/item/weapon/wrench))
return ..()
if (!(stat & NOPOWER) && on)
@@ -321,4 +335,4 @@
return !welded
#undef SIPHONING
#undef SCRUBBING
#undef SCRUBBING
+19 -57
View File
@@ -24,8 +24,7 @@
if(update)
update = 0
reconcile_air()
return
update = air.react()
var/pipenetwarnings = 10
@@ -130,21 +129,14 @@ var/pipenetwarnings = 10
for(var/obj/machinery/atmospherics/pipe/member in members)
member.air_temporary = new
member.air_temporary.volume = member.volume
member.air_temporary.copy_from(air)
var/member_gases = member.air_temporary.gases
member.air_temporary.oxygen = air.oxygen*member.volume/air.volume
member.air_temporary.nitrogen = air.nitrogen*member.volume/air.volume
member.air_temporary.toxins = air.toxins*member.volume/air.volume
member.air_temporary.carbon_dioxide = air.carbon_dioxide*member.volume/air.volume
for(var/id in member_gases)
member_gases[id][MOLES] *= member.volume/air.volume
member.air_temporary.temperature = air.temperature
if(air.trace_gases.len)
for(var/datum/gas/trace_gas in air.trace_gases)
var/datum/gas/corresponding = new trace_gas.type()
member.air_temporary.trace_gases += corresponding
corresponding.moles = trace_gas.moles*member.volume/air.volume
/datum/pipeline/proc/temperature_interact(turf/target, share_volume, thermal_conductivity)
var/total_heat_capacity = air.heat_capacity()
var/partial_heat_capacity = total_heat_capacity*(share_volume/air.volume)
@@ -203,7 +195,7 @@ var/pipenetwarnings = 10
var/list/datum/pipeline/PL = list()
PL += src
for(var/i=1;i<=PL.len;i++)
for(var/i = 1; i <= PL.len; i++) //can't do a for-each here because we may add to the list within the loop
var/datum/pipeline/P = PL[i]
GL += P.air
GL += P.other_airs
@@ -215,56 +207,26 @@ var/pipenetwarnings = 10
if(C.connected_device)
GL += C.portableConnectorReturnAir()
var/total_volume = 0
var/total_thermal_energy = 0
var/total_heat_capacity = 0
var/total_oxygen = 0
var/total_nitrogen = 0
var/total_toxins = 0
var/total_carbon_dioxide = 0
var/list/total_trace_gases = list()
var/datum/gas_mixture/total_gas_mixture = new(0)
for(var/i in GL)
var/datum/gas_mixture/G = i
total_gas_mixture.volume += G.volume
total_gas_mixture.merge(G)
for(var/datum/gas_mixture/G in GL)
total_volume += G.volume
total_thermal_energy += G.thermal_energy()
total_heat_capacity += G.heat_capacity()
total_oxygen += G.oxygen
total_nitrogen += G.nitrogen
total_toxins += G.toxins
total_carbon_dioxide += G.carbon_dioxide
if(G.trace_gases.len)
for(var/datum/gas/trace_gas in G.trace_gases)
var/datum/gas/corresponding = locate(trace_gas.type) in total_trace_gases
if(!corresponding)
corresponding = new trace_gas.type()
total_trace_gases += corresponding
corresponding.moles += trace_gas.moles
if(total_volume > 0)
//Calculate temperature
var/temperature = 0
if(total_heat_capacity > 0)
temperature = total_thermal_energy/total_heat_capacity
total_gas_mixture.temperature = total_heat_capacity ? total_thermal_energy/total_heat_capacity : 0
if(total_gas_mixture.volume > 0)
//Update individual gas_mixtures by volume ratio
for(var/datum/gas_mixture/G in GL)
G.oxygen = total_oxygen*G.volume/total_volume
G.nitrogen = total_nitrogen*G.volume/total_volume
G.toxins = total_toxins*G.volume/total_volume
G.carbon_dioxide = total_carbon_dioxide*G.volume/total_volume
G.copy_from(total_gas_mixture)
var/list/G_gases = G.gases
for(var/id in G_gases)
G_gases[id][MOLES] *= G.volume/total_gas_mixture.volume
G.temperature = temperature
if(total_trace_gases.len)
for(var/datum/gas/trace_gas in total_trace_gases)
var/datum/gas/corresponding = locate(trace_gas.type) in G.trace_gases
if(!corresponding)
corresponding = new trace_gas.type()
G.trace_gases += corresponding
corresponding.moles = trace_gas.moles*G.volume/total_volume
+81
View File
@@ -0,0 +1,81 @@
var/list/hardcoded_gases = list("o2","n2","co2","plasma") //the main four gases, which were at one time hardcoded
/proc/meta_gas_list()
var/meta_list = new /list
for(var/gas_path in subtypesof(/datum/gas))
var/list/gas_info = new(4)
var/datum/gas/g = gas_path
gas_info[META_GAS_SPECIFIC_HEAT] = initial(g.specific_heat)
gas_info[META_GAS_NAME] = initial(g.name)
gas_info[META_GAS_MOLES_VISIBLE] = initial(g.moles_visible)
if(gas_info[META_GAS_MOLES_VISIBLE] != null)
gas_info[META_GAS_OVERLAY] = new /obj/effect/overlay/gas(initial(g.gas_overlay))
meta_list[initial(g.id)] = gas_info
. = meta_list
/*||||||||||||||/----------\||||||||||||||*\
||||||||||||||||[GAS DATUMS]||||||||||||||||
||||||||||||||||\__________/||||||||||||||||
||||These should never be instantiated. ||||
||||They exist only to make it easier ||||
||||to add a new gas. They are accessed ||||
||||only by meta_gas_list(). ||||
\*||||||||||||||||||||||||||||||||||||||||*/
/datum/gas
var/id = ""
var/specific_heat = 0
var/name = ""
var/gas_overlay = "" //icon_state in icons/effects/tile_effects.dmi
var/moles_visible = null
/datum/gas/oxygen
id = "o2"
specific_heat = 20
name = "Oxygen"
/datum/gas/nitrogen
id = "n2"
specific_heat = 20
name = "Nitrogen"
/datum/gas/carbon_dioxide //what the fuck is this?
id = "co2"
specific_heat = 30
name = "Carbon Dioxide"
/datum/gas/plasma
id = "plasma"
specific_heat = 200
name = "Plasma"
gas_overlay = "plasma"
moles_visible = MOLES_PLASMA_VISIBLE
/datum/gas/nitrous_oxide
id = "n2o"
specific_heat = 40
name = "Nitrous Oxide"
gas_overlay = "nitrous_oxide"
moles_visible = 1
/datum/gas/oxygen_agent_b
id = "agent_b"
specific_heat = 300
name = "Oxygen Agent B"
/datum/gas/volatile_fuel
id = "v_fuel"
specific_heat = 30
name = "Volatile Fuel"
/obj/effect/overlay/gas/
icon = 'icons/effects/tile_effects.dmi'
mouse_opacity = 0
layer = 5
appearance_flags = RESET_COLOR
/obj/effect/overlay/gas/New(state)
. = ..()
icon_state = state
@@ -51,10 +51,11 @@
/obj/machinery/atmospherics/pipe/heat_exchanging/process()
var/datum/gas_mixture/pipe_air = return_air()
if(!pipe_air)
if(!parent)
return //machines subsystem fires before atmos is initialized so this prevents race condition runtimes
var/datum/gas_mixture/pipe_air = return_air()
//Heat causes pipe to glow
if(pipe_air.temperature && (icon_temperature > 500 || pipe_air.temperature > 500)) //glow starts at 500K
if(abs(pipe_air.temperature - icon_temperature) > 10)
+8 -4
View File
@@ -11,9 +11,13 @@
var/datum/gas_mixture/air_contents = return_air()
if(!air_contents)
return 0
var/oxy = air_contents.gases["o2"] ? air_contents.gases["o2"][MOLES] : 0
var/tox = air_contents.gases["plasma"] ? air_contents.gases["plasma"][MOLES] : 0
if(active_hotspot)
if(soh)
if(air_contents.toxins > 0.5 && air_contents.oxygen > 0.5)
if(tox > 0.5 && oxy > 0.5)
if(active_hotspot.temperature < exposed_temperature)
active_hotspot.temperature = exposed_temperature
if(active_hotspot.volume < exposed_volume)
@@ -22,11 +26,11 @@
var/igniting = 0
if((exposed_temperature > PLASMA_MINIMUM_BURN_TEMPERATURE) && air_contents.toxins > 0.5)
if((exposed_temperature > PLASMA_MINIMUM_BURN_TEMPERATURE) && tox > 0.5)
igniting = 1
if(igniting)
if(air_contents.oxygen < 0.5 || air_contents.toxins < 0.5)
if(oxy < 0.5 || tox < 0.5)
return 0
active_hotspot = PoolOrNew(/obj/effect/hotspot, src)
@@ -104,7 +108,7 @@
qdel(src)
return
if(!(location.air) || location.air.toxins < 0.5 || location.air.oxygen < 0.5)
if(!(location.air) || !location.air.gases["plasma"] || !location.air.gases["o2"] || location.air.gases["plasma"][MOLES] < 0.5 || location.air.gases["o2"][MOLES] < 0.5)
qdel(src)
return
+17 -9
View File
@@ -155,6 +155,7 @@ var/const/SPAWN_AIR = 256
return
var/datum/gas_mixture/G = new
var/list/new_gases = G.gases
if(flag & SPAWN_20C)
G.temperature = T20C
@@ -163,22 +164,29 @@ var/const/SPAWN_AIR = 256
G.temperature += 1000
if(flag & SPAWN_TOXINS)
G.toxins += amount
G.assert_gas("plasma")
new_gases["plasma"][MOLES] += amount
if(flag & SPAWN_OXYGEN)
G.oxygen += amount
G.assert_gas("o2")
new_gases["o2"][MOLES] += amount
if(flag & SPAWN_CO2)
G.carbon_dioxide += amount
G.assert_gas("co2")
new_gases["co2"][MOLES] += amount
if(flag & SPAWN_NITROGEN)
G.nitrogen += amount
G.assert_gas("n2")
new_gases["n2"][MOLES] += amount
if(flag & SPAWN_N2O)
var/datum/gas/sleeping_agent/T = new
T.moles += amount
G.trace_gases += T
G.assert_gas("n2o")
new_gases["n2o"][MOLES] += amount
if(flag & SPAWN_AIR)
G.oxygen += MOLES_O2STANDARD * amount
G.nitrogen += MOLES_N2STANDARD * amount
G.assert_gases("o2","n2")
new_gases["o2"][MOLES] += MOLES_O2STANDARD * amount
new_gases["n2"][MOLES] += MOLES_N2STANDARD * amount
air.merge(G)
SSair.add_to_active(src, 0)
+44 -83
View File
@@ -15,26 +15,14 @@
//Create gas mixture to hold data for passing
var/datum/gas_mixture/GM = new
GM.oxygen = oxygen
GM.carbon_dioxide = carbon_dioxide
GM.nitrogen = nitrogen
GM.toxins = toxins
GM.temperature = temperature
GM.copy_from_turf(src)
return GM
/turf/remove_air(amount as num)
var/datum/gas_mixture/GM = new
/turf/remove_air(amount)
var/datum/gas_mixture/GM = return_air()
var/sum = oxygen + carbon_dioxide + nitrogen + toxins
if(sum>0)
GM.oxygen = (oxygen/sum)*amount
GM.carbon_dioxide = (carbon_dioxide/sum)*amount
GM.nitrogen = (nitrogen/sum)*amount
GM.toxins = (toxins/sum)*amount
GM.temperature = temperature
GM.remove(amount)
return GM
@@ -51,7 +39,7 @@
var/temperature_archived //USED ONLY FOR SOLIDS
var/atmos_overlay_type = "" //current active overlay
var/atmos_overlay_types = list() //gas IDs of current active overlays
/turf/simulated/New()
..()
@@ -61,11 +49,7 @@
visibilityChanged()
if(!blocks_air)
air = new
air.oxygen = oxygen
air.carbon_dioxide = carbon_dioxide
air.nitrogen = nitrogen
air.toxins = toxins
air.temperature = temperature
air.copy_from_turf(src)
/turf/simulated/Destroy()
visibilityChanged()
@@ -168,22 +152,22 @@
excited_group.merge_groups(enemy_simulated.excited_group) //combine groups
share_air(enemy_simulated) //share
else
if((recently_active == 1 && enemy_simulated.recently_active == 1) || !air.compare(enemy_simulated.air))
if((recently_active == 1 && enemy_simulated.recently_active == 1) || air.compare(enemy_simulated.air))
excited_group.add_turf(enemy_simulated) //add enemy to our group
share_air(enemy_simulated) //share
else
if(enemy_simulated.excited_group)
if((recently_active == 1 && enemy_simulated.recently_active == 1) || !air.compare(enemy_simulated.air))
if((recently_active == 1 && enemy_simulated.recently_active == 1) || air.compare(enemy_simulated.air))
enemy_simulated.excited_group.add_turf(src) //join self to enemy group
share_air(enemy_simulated) //share
else
if((recently_active == 1 && enemy_simulated.recently_active == 1) || !air.compare(enemy_simulated.air))
if((recently_active == 1 && enemy_simulated.recently_active == 1) || air.compare(enemy_simulated.air))
var/datum/excited_group/EG = new //generate new group
EG.add_turf(src)
EG.add_turf(enemy_simulated)
share_air(enemy_simulated) //share
else
if(!air.compare(enemy_simulated.air)) //compare if
if(air.compare(enemy_simulated.air)) //compare if
SSair.add_to_active(enemy_simulated) //excite enemy
if(excited_group)
excited_group.add_turf(enemy_simulated) //add enemy to group
@@ -196,13 +180,13 @@
/******************* GROUP HANDLING FINISH *********************************************************************/
else
if(!air.check_turf(enemy_tile, atmos_adjacent_turfs_amount))
if(air.check_turf(enemy_tile, atmos_adjacent_turfs_amount))
var/difference = air.mimic(enemy_tile,atmos_adjacent_turfs_amount)
if(difference)
if(difference > 0)
consider_pressure_difference(enemy_tile, difference)
else
enemy_tile.consider_pressure_difference(src, difference)
enemy_tile.consider_pressure_difference(src, -difference)
remove = 0
if(excited_group)
last_share_check()
@@ -224,7 +208,9 @@
if(!excited_group && remove == 1)
SSair.remove_from_active(src)
/turf/simulated/temperature_expose()
if(temperature > heat_capacity)
to_be_destroyed = 1
/turf/simulated/proc/archive()
if(air) //For open space like floors
@@ -233,34 +219,24 @@
archived_cycle = SSair.times_fired
/turf/simulated/proc/update_visuals()
var/new_overlay_type = tile_graphic()
if (new_overlay_type == atmos_overlay_type)
return
var/atmos_overlay = get_atmos_overlay_by_name(atmos_overlay_type)
if (atmos_overlay)
overlays -= atmos_overlay
var/list/new_overlay_types = tile_graphic()
atmos_overlay = get_atmos_overlay_by_name(new_overlay_type)
if (atmos_overlay)
overlays += atmos_overlay
atmos_overlay_type = new_overlay_type
for(var/overlay in atmos_overlay_types-new_overlay_types) //doesn't remove overlays that would only be added
overlays -= overlay
atmos_overlay_types -= overlay
/turf/simulated/proc/get_atmos_overlay_by_name(var/name)
switch(name)
if("plasma")
return SSair.plasma_overlay
if("sleeping_agent")
return SSair.sleeptoxin_overlay
return null
for(var/overlay in new_overlay_types-atmos_overlay_types) //doesn't add overlays that already exist
overlays += overlay
atmos_overlay_types = new_overlay_types
/turf/simulated/proc/tile_graphic()
if(air.toxins > MOLES_PLASMA_VISIBLE)
return "plasma"
var/datum/gas/sleeping_agent = locate(/datum/gas/sleeping_agent) in air.trace_gases
if(sleeping_agent && (sleeping_agent.moles > 1))
return "sleeping_agent"
return null
. = new /list
var/list/gases = air.gases
for(var/id in gases)
var/gas = gases[id]
if(gas[GAS_OVERLAY] && gas[MOLES] > gas[MOLES_VISIBLE])
. += gas[GAS_OVERLAY]
/turf/simulated/proc/share_air(turf/simulated/T)
if(T.current_cycle < current_cycle)
@@ -270,7 +246,7 @@
if(difference > 0)
consider_pressure_difference(T, difference)
else
T.consider_pressure_difference(src, difference)
T.consider_pressure_difference(src, -difference)
last_share_check()
/turf/proc/consider_pressure_difference(turf/simulated/T, difference)
@@ -290,12 +266,16 @@
/atom/movable/var/pressure_resistance = 5
/atom/movable/var/last_high_pressure_movement_air_cycle = 0
/atom/movable/proc/experience_pressure_difference(pressure_difference, direction)
set waitfor = 0
. = 0
if(!anchored && !pulledby)
if(pressure_difference > pressure_resistance)
spawn step(src, direction)
return 1
. = 1
if(pressure_difference > pressure_resistance && last_high_pressure_movement_air_cycle < SSair.times_fired)
last_high_pressure_movement_air_cycle = SSair.times_fired
step(src, direction)
@@ -331,36 +311,17 @@
/datum/excited_group/proc/self_breakdown()
var/datum/gas_mixture/A = new
var/datum/gas/sleeping_agent/S = new
A.trace_gases += S
var/list/A_gases = A.gases
for(var/turf/simulated/T in turf_list)
A.oxygen += T.air.oxygen
A.carbon_dioxide+= T.air.carbon_dioxide
A.nitrogen += T.air.nitrogen
A.toxins += T.air.toxins
if(T.air.trace_gases.len)
for(var/datum/gas/N in T.air.trace_gases)
S.moles += N.moles
A.merge(T.air)
for(var/turf/simulated/T in turf_list)
T.air.oxygen = A.oxygen/turf_list.len
T.air.carbon_dioxide= A.carbon_dioxide/turf_list.len
T.air.nitrogen = A.nitrogen/turf_list.len
T.air.toxins = A.toxins/turf_list.len
if(S.moles > 0)
if(T.air.trace_gases.len)
for(var/datum/gas/G in T.air.trace_gases)
G.moles = S.moles/turf_list.len
else
var/datum/gas/sleeping_agent/G = new
G.moles = S.moles/turf_list.len
T.air.trace_gases += G
var/T_gases = T.air.gases
for(var/id in T_gases)
T_gases[id][MOLES] = A_gases[id][MOLES]/turf_list.len
T.update_visuals()
/datum/excited_group/proc/dismantle()
for(var/turf/simulated/T in turf_list)
T.excited = 0
@@ -473,4 +434,4 @@
var/heat = thermal_conductivity*delta_temperature* \
(heat_capacity*700000/(heat_capacity+700000)) //700000 is the heat_capacity from a space turf, hardcoded here
temperature -= heat/heat_capacity
temperature -= heat/heat_capacity
+18 -5
View File
@@ -8,11 +8,19 @@
#define MOLES_O2STANDARD (MOLES_CELLSTANDARD*O2STANDARD) // O2 standard value (21%)
#define MOLES_N2STANDARD (MOLES_CELLSTANDARD*N2STANDARD) // N2 standard value (79%)
#define GAS_O2 (1 << 0)
#define GAS_N2 (1 << 1)
#define GAS_PL (1 << 2)
#define GAS_CO2 (1 << 3)
#define GAS_N2O (1 << 4)
//indices of values in gas lists. used by listmos.
#define MOLES 1
#define ARCHIVE 2
#define GAS_META 3
//this is kinda hacky... but it means I don't have to change every single time they're called.
#define META_GAS_SPECIFIC_HEAT 1
#define META_GAS_NAME 2
#define META_GAS_OVERLAY 4
#define META_GAS_MOLES_VISIBLE 3
#define SPECIFIC_HEAT GAS_META][META_GAS_SPECIFIC_HEAT
#define GAS_NAME GAS_META][META_GAS_NAME
#define GAS_OVERLAY GAS_META][META_GAS_OVERLAY
#define MOLES_VISIBLE GAS_META][META_GAS_MOLES_VISIBLE
//stuff you should probably leave well alone!
//ATMOS
@@ -152,3 +160,8 @@
#define PARENT2 parents[2]
#define PARENT3 parents[3]
#define PARENT_I parents[I]
//Tanks
#define TANK_MAX_RELEASE_PRESSURE (ONE_ATMOSPHERE*3)
#define TANK_MIN_RELEASE_PRESSURE 0
#define TANK_DEFAULT_RELEASE_PRESSURE 16
+3
View File
@@ -324,3 +324,6 @@ var/list/bloody_footprints_cache = list()
//Bloodcrawling
#define BLOODCRAWL 1
#define BLOODCRAWL_EAT 2
//Color Defines
#define OOC_COLOR "#002eb8"
-15
View File
@@ -1,15 +0,0 @@
/**
* NanoUI Defines
*
* Contains all NanoUI state definitions.
*
* /tg/station user interface library
* thanks to baystation12
*
* modified by neersighted
**/
#define NANO_INTERACTIVE 2 // Green/Interactive
#define NANO_UPDATE 1 // Orange/Updates Only
#define NANO_DISABLED 0 // Red/Disabled
#define NANO_CLOSE -1 // Closed
+5
View File
@@ -0,0 +1,5 @@
#define MIN_FREE_FREQ 1201
#define MAX_FREE_FREQ 1599
#define MIN_FREQ 1441
#define MAX_FREQ 1489
+4
View File
@@ -0,0 +1,4 @@
#define UI_INTERACTIVE 2 // Green/Interactive
#define UI_UPDATE 1 // Orange/Updates Only
#define UI_DISABLED 0 // Red/Disabled
#define UI_CLOSE -1 // Closed
+44
View File
@@ -0,0 +1,44 @@
#define WIRE_ACTIVATE "activate"
#define WIRE_AI "ai"
#define WIRE_ALARM "alarm"
#define WIRE_AVOIDANCE "avoidance"
#define WIRE_BACKUP1 "backup1"
#define WIRE_BACKUP2 "backup2"
#define WIRE_BEACON "beacon"
#define WIRE_BOLTS "bolts"
#define WIRE_BOOM "boom"
#define WIRE_CAMERA "camera"
#define WIRE_CONTRABAND "contraband"
#define WIRE_DELAY "delay"
#define WIRE_DISABLE "disable"
#define WIRE_DISARM "disarm"
#define WIRE_ELECTRIFY "electrify"
#define WIRE_HACK "hack"
#define WIRE_IDSCAN "idscan"
#define WIRE_INTERFACE "interface"
#define WIRE_LAWSYNC "lawsync"
#define WIRE_LIGHT "light"
#define WIRE_LIMIT "limit"
#define WIRE_LOADCHECK "loadcheck"
#define WIRE_LOCKDOWN "lockdown"
#define WIRE_MOTOR1 "motor1"
#define WIRE_MOTOR2 "motor2"
#define WIRE_OPEN "open"
#define WIRE_PANIC "panic"
#define WIRE_POWER "power"
#define WIRE_POWER1 "power1"
#define WIRE_POWER2 "power2"
#define WIRE_PROCEED "proceed"
#define WIRE_RX "recieve"
#define WIRE_SAFETY "safety"
#define WIRE_SHOCK "shock"
#define WIRE_SIGNAL "signal"
#define WIRE_SPEAKER "speaker"
#define WIRE_STRENGTH "strength"
#define WIRE_THROW "throw"
#define WIRE_TIMING "timing"
#define WIRE_TX "transmit"
#define WIRE_UNBOLT "unbolt"
#define WIRE_ZAP "zap"
#define WIRE_ZAP1 "zap1"
#define WIRE_ZAP2 "zap2"
+30 -17
View File
@@ -17,9 +17,8 @@
/atom/var/top_right_corner
/atom/var/bottom_left_corner
/atom/var/bottom_right_corner
/atom/var/can_be_unanchored = 0
/atom/var/list/canSmoothWith = null // TYPE PATHS I CAN SMOOTH WITH~~~~~ If this is null and atom is smooth, it smooths only with itself
/atom/movable/var/can_be_unanchored = 0
//generic (by snowflake) tile smoothing code; smooth your icons with this!
/*
Each tile is divided in 4 corners, each corner has an image associated to it; the tile is then overlayed by these 4 images
@@ -36,23 +35,37 @@
var/adjacencies = 0
if(A.can_be_unanchored)
var/atom/movable/AM = A
if(!AM.anchored)
var/atom/movable/AM
if(istype(A, /atom/movable))
AM = A
if(AM.can_be_unanchored && !AM.anchored)
return 0
for(var/direction in alldirs)
AM = find_type_in_direction(A, direction)
if(istype(AM))
if(AM.anchored)
adjacencies |= 1 << direction
else
if(AM)
adjacencies |= 1 << direction
else
for(var/direction in alldirs)
if(find_type_in_direction(A, direction))
adjacencies |= 1 << direction
for(var/direction in cardinal)
AM = find_type_in_direction(A, direction)
if( (AM && !istype(AM)) || (istype(AM) && AM.anchored) )
adjacencies |= 1 << direction
if(adjacencies & N_NORTH)
if(adjacencies & N_WEST)
AM = find_type_in_direction(A, NORTHWEST)
if( (AM && !istype(AM)) || (istype(AM) && AM.anchored) )
adjacencies |= N_NORTHWEST
if(adjacencies & N_EAST)
AM = find_type_in_direction(A, NORTHEAST)
if( (AM && !istype(AM)) || (istype(AM) && AM.anchored) )
adjacencies |= N_NORTHEAST
if(adjacencies & N_SOUTH)
if(adjacencies & N_WEST)
AM = find_type_in_direction(A, SOUTHWEST)
if( (AM && !istype(AM)) || (istype(AM) && AM.anchored) )
adjacencies |= N_SOUTHWEST
if(adjacencies & N_EAST)
AM = find_type_in_direction(A, SOUTHEAST)
if( (AM && !istype(AM)) || (istype(AM) && AM.anchored) )
adjacencies |= N_SOUTHEAST
return adjacencies
/proc/smooth_icon(atom/A)
+17 -11
View File
@@ -127,15 +127,21 @@ Proc for attack log creation, because really why not
/proc/add_logs(mob/user, mob/target, what_done, object=null, addition=null)
var/newhealthtxt = ""
var/coordinates = ""
var/turf/attack_location = get_turf(target)
var/coordinates = "([attack_location.x],[attack_location.y],[attack_location.z])"
if (target && isliving(target))
if(attack_location)
coordinates = "([attack_location.x],[attack_location.y],[attack_location.z])"
if(target && isliving(target))
var/mob/living/L = target
newhealthtxt = " (NEWHP: [L.health])"
if(user && ismob(user))
user.attack_log += text("\[[time_stamp()]\] <font color='red'>Has [what_done] [target ? "[target.name][(ismob(target) && target.ckey) ? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition][newhealthtxt][coordinates]</font>")
if(user.mind)
user.mind.attack_log += text("\[[time_stamp()]\] <font color='red'>[user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"] has [what_done] [target ? "[target.name][(ismob(target) && target.ckey) ? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition][newhealthtxt][coordinates]</font>")
if(target && ismob(target))
target.attack_log += text("\[[time_stamp()]\] <font color='orange'>Has been [what_done] by [user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition][newhealthtxt][coordinates]</font>")
if(target.mind)
target.mind.attack_log += text("\[[time_stamp()]\] <font color='orange'>[target ? "[target.name][(ismob(target) && target.ckey) ? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"] has been [what_done] by [user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition][newhealthtxt][coordinates]</font>")
log_attack("[user ? "[user.name][(ismob(user) && user.ckey) ? "([user.ckey])" : ""]" : "NON-EXISTANT SUBJECT"] [what_done] [target ? "[target.name][(ismob(target) && target.ckey)? "([target.ckey])" : ""]" : "NON-EXISTANT SUBJECT"][object ? " with [object]" : " "][addition][newhealthtxt][coordinates]")
@@ -144,10 +150,10 @@ Proc for attack log creation, because really why not
if(!user || !target)
return 0
var/user_loc = user.loc
var/drifting = 0
if(!user.Process_Spacemove(0) && user.inertia_dir)
drifting = 1
drifting = 1
var/target_loc = target.loc
@@ -168,11 +174,11 @@ Proc for attack log creation, because really why not
break
if(uninterruptible)
continue
if(drifting && !user.inertia_dir)
drifting = 0
user_loc = user.loc
if((!drifting && user.loc != user_loc) || target.loc != target_loc || user.get_active_hand() != holding || user.incapacitated() || user.lying )
. = 0
break
@@ -188,11 +194,11 @@ Proc for attack log creation, because really why not
Tloc = target.loc
var/atom/Uloc = user.loc
var/drifting = 0
if(!user.Process_Spacemove(0) && user.inertia_dir)
drifting = 1
drifting = 1
var/holding = user.get_active_hand()
var/holdingnull = 1 //User's hand started out empty, check for an empty hand
@@ -210,11 +216,11 @@ Proc for attack log creation, because really why not
sleep(1)
if (progress)
progbar.update(world.time - starttime)
if(drifting && !user.inertia_dir)
drifting = 0
Uloc = user.loc
if(!user || user.stat || user.weakened || user.stunned || (!drifting && user.loc != Uloc))
. = 0
break
+14
View File
@@ -0,0 +1,14 @@
// Ensure the frequency is within bounds of what it should be sending/recieving at
/proc/sanitize_frequency(frequency, free = FALSE)
. = round(frequency)
if(free)
. = Clamp(frequency, MIN_FREE_FREQ, MAX_FREE_FREQ)
else
. = Clamp(frequency, MIN_FREQ, MAX_FREQ)
if(!(. % 2)) // Ensure the last digit is an odd number
. += 1
// Format frequency by moving the decimal.
/proc/format_frequency(frequency)
frequency = text2num(frequency)
return "[round(frequency / 10)].[frequency % 10]"
+2
View File
@@ -304,6 +304,8 @@
switch(ui_style)
if("Retro") return 'icons/mob/screen_retro.dmi'
if("Plasmafire") return 'icons/mob/screen_plasmafire.dmi'
if("Slimecore") return 'icons/mob/screen_slimecore.dmi'
if("Operative") return 'icons/mob/screen_operative.dmi'
else return 'icons/mob/screen_midnight.dmi'
//colour formats
+41 -134
View File
@@ -26,11 +26,6 @@
return text("#[][][]", textr, textg, textb)
return
//Returns the middle-most value
/proc/dd_range(low, high, num)
return max(low,min(high,num))
/proc/Get_Angle(atom/movable/start,atom/movable/end)//For beams.
if(!start || !end) return 0
var/dy
@@ -182,98 +177,8 @@ Turf and target are seperate in case you want to teleport some distance from a t
return 0
return 1
//Ensure the frequency is within bounds of what it should be sending/recieving at
/proc/sanitize_frequency(f)
f = round(f)
f = max(1441, f) // 144.1
f = min(1489, f) // 148.9
if ((f % 2) == 0) //Ensure the last digit is an odd number
f += 1
return f
//Turns 1479 into 147.9
/proc/format_frequency(f)
f = text2num(f)
return "[round(f / 10)].[f % 10]"
//This will update a mob's name, real_name, mind.name, data_core records, pda, id and traitor text
//Calling this proc without an oldname will only update the mob and skip updating the pda, id and records ~Carn
/mob/proc/fully_replace_character_name(oldname,newname)
if(!newname) return 0
real_name = newname
name = newname
if(mind)
mind.name = newname
if(istype(src, /mob/living/carbon))
var/mob/living/carbon/C = src
if(C.dna)
C.dna.real_name = real_name
if(isAI(src))
var/mob/living/silicon/ai/AI = src
if(oldname != real_name)
if(AI.eyeobj)
AI.eyeobj.name = "[newname] (AI Eye)"
// Set ai pda name
if(AI.aiPDA)
AI.aiPDA.owner = newname
AI.aiPDA.name = newname + " (" + AI.aiPDA.ownjob + ")"
// Notify Cyborgs
for(var/mob/living/silicon/robot/Slave in AI.connected_robots)
Slave.show_laws()
if(isrobot(src))
var/mob/living/silicon/robot/R = src
if(oldname != real_name)
R.notify_ai(3, oldname, newname)
if(R.camera)
R.camera.c_tag = real_name
if(oldname)
//update the datacore records! This is goig to be a bit costly.
for(var/list/L in list(data_core.general,data_core.medical,data_core.security,data_core.locked))
var/datum/data/record/R = find_record("name", oldname, L)
if(R) R.fields["name"] = newname
//update our pda and id if we have them on our person
var/list/searching = GetAllContents()
var/search_id = 1
var/search_pda = 1
for(var/A in searching)
if( search_id && istype(A,/obj/item/weapon/card/id) )
var/obj/item/weapon/card/id/ID = A
if(ID.registered_name == oldname)
ID.registered_name = newname
ID.update_label()
if(!search_pda) break
search_id = 0
else if( search_pda && istype(A,/obj/item/device/pda) )
var/obj/item/device/pda/PDA = A
if(PDA.owner == oldname)
PDA.owner = newname
PDA.update_label()
if(!search_id) break
search_pda = 0
for(var/datum/mind/T in ticker.minds)
for(var/datum/objective/obj in T.objectives)
// Only update if this player is a target
if(obj.target && obj.target.current && obj.target.current.real_name == name)
obj.update_explanation_text()
return 1
//Generalised helper proc for letting mobs rename themselves. Used to be clname() and ainame()
/mob/proc/rename_self(role, allow_numbers=0)
/mob/proc/rename_self(role)
var/oldname = real_name
var/newname
var/loop = 1
@@ -305,13 +210,8 @@ Turf and target are seperate in case you want to teleport some distance from a t
loop--
safety++
if(isAI(src))
oldname = null//don't bother with the records update crap
if(newname)
fully_replace_character_name(oldname,newname)
if(isrobot(src))
var/mob/living/silicon/robot/A = src
A.custom_name = newname
//Picks a string of symbols to display as the law number for hacked or ion laws
@@ -620,25 +520,36 @@ Turf and target are seperate in case you want to teleport some distance from a t
/proc/can_see(atom/source, atom/target, length=5) // I couldnt be arsed to do actual raycasting :I This is horribly inaccurate.
var/turf/current = get_turf(source)
var/turf/target_turf = get_turf(target)
var/steps = 0
while(current != target_turf)
if(steps > length) return 0
if(current.opacity) return 0
for(var/atom/A in current)
if(A.opacity) return 0
var/steps = 1
if(current != target_turf)
current = get_step_towards(current, target_turf)
steps++
while(current != target_turf)
if(steps > length) return 0
if(current.opacity) return 0
for(var/atom/A in current)
if(A.opacity) return 0
current = get_step_towards(current, target_turf)
steps++
return 1
/proc/is_blocked_turf(turf/T)
var/cant_pass = 0
if(T.density) cant_pass = 1
for(var/atom/A in T)
if(A.density)//&&A.anchored
cant_pass = 1
return cant_pass
if(T.density)
return 1
for(var/i in T)
var/atom/A = i
if(A.density)
return 1
return 0
/proc/is_anchored_dense_turf(turf/T) //like the older version of the above, fails only if also anchored
if(T.density)
return 1
for(var/i in T)
var/atom/movable/A = i
if(A.density && A.anchored)
return 1
return 0
/proc/get_step_towards2(atom/ref , atom/trg)
var/base_dir = get_dir(ref, get_step_towards(ref,trg))
@@ -674,9 +585,10 @@ Turf and target are seperate in case you want to teleport some distance from a t
if(A.vars.Find(lowertext(varname))) return 1
else return 0
//Returns sortedAreas list if populated
//else populates the list first before returning it
//Repopulates sortedAreas list
/proc/SortAreas()
sortedAreas = list()
for(var/area/A in world)
sortedAreas.Add(A)
@@ -947,20 +859,15 @@ var/list/WALLITEMS_INVERSE = list(
user << "<span class='notice'>Results of analysis of \icon[icon] [target].</span>"
if(total_moles>0)
var/o2_concentration = air_contents.oxygen/total_moles
var/n2_concentration = air_contents.nitrogen/total_moles
var/co2_concentration = air_contents.carbon_dioxide/total_moles
var/plasma_concentration = air_contents.toxins/total_moles
var/unknown_concentration = 1-(o2_concentration+n2_concentration+co2_concentration+plasma_concentration)
user << "<span class='notice'>Pressure: [round(pressure,0.1)] kPa</span>"
user << "<span class='notice'>Nitrogen: [round(n2_concentration*100)] %</span>"
user << "<span class='notice'>Oxygen: [round(o2_concentration*100)] %</span>"
user << "<span class='notice'>CO2: [round(co2_concentration*100)] %</span>"
user << "<span class='notice'>Plasma: [round(plasma_concentration*100)] %</span>"
if(unknown_concentration>0.01)
user << "<span class='danger'>Unknown: [round(unknown_concentration*100)] %</span>"
var/list/cached_gases = air_contents.gases
for(var/id in cached_gases)
var/gas_concentration = cached_gases[id][MOLES]/total_moles
if(id in hardcoded_gases || gas_concentration > 0.01) //ensures the four primary gases are always shown.
user << "<span class='notice'>[cached_gases[id][GAS_NAME]]: [round(gas_concentration*100)] %</span>"
user << "<span class='notice'>Temperature: [round(air_contents.temperature-T0C)] &deg;C</span>"
else
user << "<span class='notice'>[target] is empty!</span>"
@@ -1232,10 +1139,10 @@ B --><-- A
return L
/atom/proc/contains(var/atom/location)
if(!location)
/atom/proc/contains(var/atom/A)
if(!A)
return 0
for(location, location && location != src, location=location.loc); //semicolon is for the empty statement
for(var/atom/location = A.loc, location, location = location.loc)
if(location == src)
return 1
return 0
+2 -1
View File
@@ -1,5 +1,6 @@
#define DEBUG //Enables byond profiling and full runtime logs - note, this may also be defined in your .dme file
//#define TESTING //Enables in-depth debug messages to runtime log (used for debugging) //By using the testing("message") proc you can create debug-feedback for people with this
//Enables in-depth debug messages to runtime log (used for debugging)
//#define TESTING //By using the testing("message") proc you can create debug-feedback for people with this
//uncommented, but not visible in the release version)
#define PRELOAD_RSC 1 /*set to:
+2 -1
View File
@@ -16,4 +16,5 @@ var/global/list/table_recipes = list() //list of all table craft recipes
var/global/list/rcd_list = list() //list of Rapid Construction Devices.
var/global/list/apcs_list = list() //list of all Area Power Controller machines, seperate from machines for powernet speeeeeeed.
var/global/list/tracked_implants = list() //list of all current implants that are tracked to work out what sort of trek everyone is on. Sadly not on lavaworld not implemented...
var/global/list/poi_list = list() //list of points of interest for observe/follow
var/global/list/poi_list = list() //list of points of interest for observe/follow
var/global/list/pinpointer_list = list() //list of all pinpointers. Used to change stuff they are pointing to all at once.
-4
View File
@@ -7,8 +7,4 @@ var/CHARGELEVEL = 0.001 // Cap for how fast cells charge, as a percentage-per-ti
var/list/powernets = list()
// this is not strictly unused although the whole modules datum thing is unused
// To remove this you need to remove that
var/datum/moduletypes/mods = new()
var/map_name = "Unknown" //The name of the map that is loaded. Assigned in world/New()
+2 -4
View File
@@ -73,7 +73,7 @@
CtrlClickOn(A)
return
if(stat || paralysis || stunned || weakened)
if(stat || paralysis || stunned || weakened || sleeping)
return
face_atom(A)
@@ -221,10 +221,8 @@
/mob/proc/CtrlClickOn(atom/A)
A.CtrlClick(src)
return
/atom/proc/CtrlClick(mob/user)
return
/atom/movable/CtrlClick(mob/living/user)
/atom/proc/CtrlClick(mob/user)
var/mob/living/ML = user
if(istype(ML))
ML.pulled(src)
+5 -5
View File
@@ -27,17 +27,17 @@
WARNING("[src] threw alert [category] with new_master [new_master] while already having that alert with master [alert.master]")
clear_alert(category)
return .()
else if(alert.type == type && (!severity || severity == alert.severity))
else if(alert.type != type)
clear_alert(category)
return .()
else if(!severity || severity == alert.severity)
if(alert.timeout)
clear_alert(category)
return .()
else
// src << "threw alert not in need of update [category] [type] [severity]"
else //no need to update
return 0
// src << "updating alert [category] [type] [severity]"
else
alert = PoolOrNew(type)
// src << "throwing new alert [category] [type] [severity]"
if(new_master)
var/old_layer = new_master.layer
+4 -3
View File
@@ -81,9 +81,10 @@
action_intent = using
if(istype(mymob, /mob/living/carbon/alien/humanoid/hunter))
mymob.leap_icon = new /obj/screen/alien/leap()
mymob.leap_icon.screen_loc = ui_alien_storage_r
adding += mymob.leap_icon
var/mob/living/carbon/alien/humanoid/hunter/H = mymob
H.leap_icon = new /obj/screen/alien/leap()
H.leap_icon.screen_loc = ui_alien_storage_r
adding += H.leap_icon
using = new /obj/screen/drop()
using.icon = 'icons/mob/screen_alien.dmi'
+3
View File
@@ -25,6 +25,9 @@
/atom/proc/attack_hand(mob/user)
return
/atom/proc/interact(mob/user)
return
/*
/mob/living/carbon/human/RestrainedClickOn(var/atom/A) ---carbons will handle this
return
+1 -2
View File
@@ -127,12 +127,11 @@ var/const/tk_maxrange = 15
var/resolved = target.attackby(I, user, params)
if(!resolved && target && I)
I.afterattack(target,user,1) // for splashing with beakers
else
apply_focus_overlay()
focus.throw_at(target, 10, 1,user)
last_throw = world.time
user.changeNext_move(CLICK_CD_MELEE)
return
/proc/tkMaxRangeCheck(mob/user, atom/target, atom/focus)
+26 -6
View File
@@ -21,7 +21,8 @@ var/global/datum/controller/master/Master = new()
var/iteration = 0
// The cost (in deciseconds) of the MC loop.
var/cost = 0
// The old fps when we slow it down to prevent lag.
var/old_fps
// A list of subsystems to process().
var/list/subsystems = list()
// The cost of running the subsystems (in deciseconds).
@@ -127,8 +128,14 @@ var/global/datum/controller/master/Master = new()
var/ran_subsystems = 0
for(var/datum/subsystem/SS in subsystems)
if(world.cpu >= 100)
//if world.cpu gets above 120,
//byond will pause most client updates for (about) 1.6 seconds.
//(1.6 seconds worth of ticks)
//We just stop running subsystems to avoid that.
break
if(SS.can_fire > 0)
if(SS.next_fire <= world.time && SS.last_fire + (SS.wait * 0.5) <= world.time) // Check if it's time.
if(SS.next_fire <= world.time && SS.last_fire + (SS.wait * 0.75) <= world.time) // Check if it's time.
ran_subsystems = 1
timer = world.timeofday
last_type_processed = SS.type
@@ -144,12 +151,14 @@ var/global/datum/controller/master/Master = new()
SS.wait = Clamp(newwait, SS.dwait_lower, SS.dwait_upper)
if(oldwait != SS.wait)
processing_interval = calculate_gcd()
SS.next_fire += SS.wait
SS.next_fire = world.time + SS.wait
else
SS.next_fire += SS.wait
++SS.times_fired
// If we caused BYOND to miss a tick, stop processing for a bit...
if(startingtick < world.time || start_time + 1 < world.timeofday)
break
sleep(-1)
sleep(0)
cost = MC_AVERAGE(cost, world.timeofday - start_time)
if(ran_subsystems)
@@ -166,9 +175,20 @@ var/global/datum/controller/master/Master = new()
if(startingtick < world.time || start_time + 1 < world.timeofday)
extrasleep += world.tick_lag * 2
// If we are loading the server too much, sleep a bit extra...
if(world.cpu > 80)
extrasleep += extrasleep + processing_interval
if(world.cpu >= 75)
extrasleep += (extrasleep + processing_interval) * ((world.cpu-50)/10)
if(world.cpu >= 100)
if(!old_fps)
old_fps = world.fps
//byond bug, if we go over 120 fps and world.fps is higher then 10, the bad things that happen are made worst.
world.fps = 10
else if(old_fps && world.cpu < 50)
world.fps = old_fps
old_fps = null
sleep(processing_interval + extrasleep)
else
sleep(50)
#undef MC_AVERAGE
+24 -23
View File
@@ -18,9 +18,6 @@ var/datum/subsystem/air/SSair
var/cost_pipenets = 0
var/cost_atmos_machinery = 0
var/obj/effect/overlay/plasma_overlay //overlay for plasma
var/obj/effect/overlay/sleeptoxin_overlay //overlay for sleeptoxin
var/list/excited_groups = list()
var/list/active_turfs = list()
var/list/hotspots = list()
@@ -36,9 +33,6 @@ var/datum/subsystem/air/SSair
/datum/subsystem/air/New()
NEW_SS_GLOBAL(SSair)
plasma_overlay = new /obj/effect/overlay{icon='icons/effects/tile_effects.dmi';mouse_opacity=0;layer=5;icon_state="plasma"}()
sleeptoxin_overlay = new /obj/effect/overlay{icon='icons/effects/tile_effects.dmi';mouse_opacity=0;layer=5;icon_state="sleeping_agent"}()
/datum/subsystem/air/stat_entry(msg)
msg += "C:{"
msg += "AT:[round(cost_turfs,0.01)]|"
@@ -169,32 +163,39 @@ var/datum/subsystem/air/SSair
/datum/subsystem/air/proc/setup_allturfs(z_level)
var/z_start = 1
var/z_finish = world.maxz
if(1 <= z_level && z_level <= world.maxz)
z_level = round(z_level)
z_start = z_level
z_finish = z_level
var/list/turfs_to_init = block(locate(1, 1, z_start), locate(world.maxx, world.maxy, z_finish))
for(var/turf/simulated/T in turfs_to_init)
T.CalculateAdjacentTurfs()
T.excited = 0
active_turfs -= T
if(!T.blocks_air)
T.update_visuals()
for(var/direction in cardinal)
if(!(T.atmos_adjacent_turfs & direction))
continue
var/turf/enemy_tile = get_step(T, direction)
if(istype(enemy_tile,/turf/simulated/))
var/turf/simulated/enemy_simulated = enemy_tile
if(!T.air.compare(enemy_simulated.air))
T.excited = 1
active_turfs |= T
break
else
if(!T.air.check_turf_total(enemy_tile))
T.excited = 1
active_turfs |= T
break
if(T.blocks_air)
continue
T.update_visuals()
for(var/direction in cardinal)
if(!(T.atmos_adjacent_turfs & direction))
continue
var/turf/enemy_tile = get_step(T, direction)
var/datum/gas_mixture/enemy_air = enemy_tile.return_air()
var/is_active = T.air.compare(enemy_air)
if(is_active)
testing("Active turf found. Return value of compare(): [is_active]")
T.excited = 1
active_turfs |= T
break
if(active_turfs.len)
warning("There are [active_turfs.len] active turfs at roundstart, this is a mapping error caused by a difference of the air between the adjacent turfs. You can see its coordinates using \"Mapping -> Show roundstart AT list\" verb (debug verbs required)")
for(var/turf/simulated/T in active_turfs)
+23 -24
View File
@@ -103,50 +103,49 @@ var/datum/subsystem/garbage_collector/SSgarbage
// Should be treated as a replacement for the 'del' keyword.
// Datums passed to this will be given a chance to clean up references to allow the GC to collect them.
/proc/qdel(var/datum/A)
if (!A)
/proc/qdel(datum/D)
if(!D)
return
#ifdef TESTING
SSgarbage.qdel_list += "[A.type]"
#endif
if (!istype(A))
del(A)
else if (isnull(A.gc_destroyed))
// Let our friend know they're about to get fucked up.
var/hint = A.Destroy()
if (!A)
if(!istype(D))
del(D)
else if(isnull(D.gc_destroyed))
var/hint = D.Destroy() // Let our friend know they're about to get fucked up.
if(!D)
return
switch (hint)
switch(hint)
if (QDEL_HINT_QUEUE) //qdel should queue the object for deletion.
SSgarbage.Queue(A)
SSgarbage.Queue(D)
if (QDEL_HINT_LETMELIVE) //qdel should let the object live after calling destory.
return
if (QDEL_HINT_IWILLGC) //functionally the same as the above. qdel should assume the object will gc on its own, and not check it.
return
if (QDEL_HINT_HARDDEL) //qdel should assume this object won't gc, and queue a hard delete using a hard reference to save time from the locate()
SSgarbage.HardQueue(A)
SSgarbage.HardQueue(D)
if (QDEL_HINT_HARDDEL_NOW) //qdel should assume this object won't gc, and hard del it post haste.
del(A)
del(D)
if (QDEL_HINT_PUTINPOOL) //qdel will put this object in the pool.
PlaceInPool(A,0)
PlaceInPool(D, 0)
if (QDEL_HINT_FINDREFERENCE)//qdel will, if TESTING is enabled, display all references to this object, then queue the object for deletion.
SSgarbage.Queue(A)
SSgarbage.Queue(D)
#ifdef TESTING
A.find_references()
#endif
else
if(!("[A.type]" in SSgarbage.noqdelhint))
SSgarbage.noqdelhint += "[A.type]"
testing("WARNING: [A.type] is not returning a qdel hint. It is being placed in the queue. Further instances of this type will also be queued.")
SSgarbage.Queue(A)
if(!("[D.type]" in SSgarbage.noqdelhint))
SSgarbage.noqdelhint += "[D.type]"
testing("WARNING: [D.type] is not returning a qdel hint. It is being placed in the queue. Further instances of this type will also be queued.")
SSgarbage.Queue(D)
// Returns 1 if the object has been queued for deletion.
/proc/qdeleted(var/datum/A)
if (!istype(A))
return 0
if (A.gc_destroyed)
return 1
return 0
/proc/qdeleted(datum/D)
if(!istype(D))
return FALSE
if(D.gc_destroyed)
return TRUE
return FALSE
// Default implementation of clean-up code.
// This should be overridden to remove all references pointing to the object being destroyed.
+6 -4
View File
@@ -13,16 +13,18 @@ var/datum/subsystem/minimap/SSminimap
var/const/MAX_ICON_DIMENSION = 1024
var/const/ICON_SIZE = 4
var/max_initalized_zlevel = 0
/datum/subsystem/minimap/New()
NEW_SS_GLOBAL(SSminimap)
/datum/subsystem/minimap/Initialize(timeofday, zlevel)
if (zlevel)
if(zlevel)
return ..()
for(var/z = 1 to ZLEVEL_SPACEMAX)
generate(z)
for (var/z = 1 to ZLEVEL_SPACEMAX)
register_asset("minimap_[z].png", file("[getMinimapFile(z)].png"))
max_initalized_zlevel = ZLEVEL_SPACEMAX
..()
/datum/subsystem/minimap/proc/generate(z, x1 = 1, y1 = 1, x2 = world.maxx, y2 = world.maxy)
@@ -173,9 +175,9 @@ var/datum/subsystem/minimap/SSminimap
return "data/minimaps/[MAP_NAME]_[zlevel]"
/datum/subsystem/minimap/proc/sendMinimaps(client/client)
for (var/z = 1 to world.maxz)
for(var/z = 1 to max_initalized_zlevel)
send_asset(client, "minimap_[z].png")
#ifdef MINIMAP_DEBUG
#undef MINIMAP_DEBUG
#endif
#endif
-30
View File
@@ -1,30 +0,0 @@
var/datum/subsystem/nano/SSnano
/datum/subsystem/nano
name = "NanoUI"
wait = 10
priority = 16
display = 6
can_fire = 1 // This needs to fire before round start.
var/list/open_uis = list() // A list of open NanoUIs, grouped by src_object and ui_key.
var/list/processing_uis = list() // A list of processing NanoUIs, not grouped.
var/html // The HTML template used by new UIs; minus initial data.
/datum/subsystem/nano/New()
html = file2text('nano/assets/nanoui.html') // Read the HTML from disk.
NEW_SS_GLOBAL(SSnano)
/datum/subsystem/nano/stat_entry()
..("O:[open_uis.len]|P:[processing_uis.len]") // Show how many interfaces we have open/are processing.
/datum/subsystem/nano/fire() // Process UIs.
for(var/thing in processing_uis)
var/datum/nanoui/ui = thing
if(ui && ui.user && ui.src_object)
ui.process()
continue
processing_uis.Remove(ui)
@@ -37,8 +37,9 @@
if(!src || qdeleted(src))
return
var/turf/T = pick(get_area_turfs(picked_area))
var/turf/T = safepick(get_area_turfs(picked_area))
if(!T)
return
var/obj/docking_port/stationary/landing_zone = new /obj/docking_port/stationary(T)
landing_zone.id = "assault_pod(\ref[src])"
landing_zone.name = "Landing Zone"
@@ -1,3 +1,7 @@
#define UNLAUNCHED 0
#define ENDGAME_LAUNCHED 1
#define EARLY_LAUNCHED 2
/obj/docking_port/mobile/emergency
name = "emergency shuttle"
id = "emergency"
@@ -102,18 +106,22 @@
G.dom_attempts = min(1,G.dom_attempts)
if(SHUTTLE_DOCKED)
if(time_left <= 0 && SSshuttle.emergencyNoEscape)
priority_announce("Hostile environment detected. Departure has been postponed indefinitely pending conflict resolution.", null, 'sound/misc/notice1.ogg', "Priority")
sound_played = 0
mode = SHUTTLE_STRANDED
if(time_left <= 50 && !sound_played) //4 seconds left - should sync up with the launch
sound_played = 1
if(time_left <= 50 && !sound_played) //4 seconds left:REV UP THOSE ENGINES BOYS. - should sync up with the launch
sound_played = 1 //Only rev them up once.
for(var/area/shuttle/escape/E in world)
E << 'sound/effects/hyperspace_begin.ogg'
if(time_left <= 0 && SSshuttle.emergencyNoEscape)
priority_announce("Hostile environment detected. Departure has been postponed indefinitely pending conflict resolution.", null, 'sound/misc/notice1.ogg', "Priority")
sound_played = 0 //Since we didn't launch, we will need to rev up the engines again next pass.
mode = SHUTTLE_STRANDED
if(time_left <= 0 && !SSshuttle.emergencyNoEscape)
//move each escape pod to its corresponding transit dock
for(var/obj/docking_port/mobile/pod/M in SSshuttle.mobile)
if(M.z == ZLEVEL_STATION) //Will not launch from the mine/planet
if(M.launch_status == UNLAUNCHED) //Will not launch from the mine/planet
M.launch_status = ENDGAME_LAUNCHED
M.enterTransit()
//now move the actual emergency shuttle to its transit dock
for(var/area/shuttle/escape/E in world)
@@ -126,7 +134,8 @@
if(time_left <= 0)
//move each escape pod to its corresponding escape dock
for(var/obj/docking_port/mobile/pod/M in SSshuttle.mobile)
M.dock(SSshuttle.getDock("[M.id]_away"))
if(M.launch_status == ENDGAME_LAUNCHED)
M.dock(SSshuttle.getDock("[M.id]_away"))
//now move the actual emergency shuttle to centcomm
for(var/area/shuttle/escape/E in world)
E << 'sound/effects/hyperspace_end.ogg'
@@ -148,9 +157,11 @@
dwidth = 1
width = 3
height = 4
var/launch_status = UNLAUNCHED
/obj/docking_port/mobile/pod/request()
if(security_level == SEC_LEVEL_RED || security_level == SEC_LEVEL_DELTA && z == ZLEVEL_STATION)
if((security_level == SEC_LEVEL_RED || security_level == SEC_LEVEL_DELTA) && launch_status == UNLAUNCHED)
launch_status = EARLY_LAUNCHED
return ..()
/obj/docking_port/mobile/pod/New()
@@ -221,8 +232,8 @@
new /obj/item/clothing/suit/space/orange(src)
new /obj/item/clothing/mask/gas(src)
new /obj/item/clothing/mask/gas(src)
new /obj/item/weapon/tank/internals/air(src)
new /obj/item/weapon/tank/internals/air(src)
new /obj/item/weapon/tank/internals/oxygen/red(src)
new /obj/item/weapon/tank/internals/oxygen/red(src)
new /obj/item/weapon/pickaxe/emergency(src)
new /obj/item/weapon/pickaxe/emergency(src)
new /obj/item/weapon/survivalcapsule(src)
@@ -238,3 +249,9 @@
/obj/item/weapon/storage/pod/attack_hand(mob/user)
return
#undef UNLAUNCHED
#undef LAUNCHED
#undef EARLY_LAUNCHED
@@ -211,6 +211,7 @@
var/list/blacklist = list(
/mob/living,
/obj/effect/blob,
/obj/effect/rune,
/obj/effect/spider/spiderling,
/obj/item/weapon/disk/nuclear,
/obj/machinery/nuclearbomb,
+30
View File
@@ -0,0 +1,30 @@
var/datum/subsystem/tgui/SStgui
/datum/subsystem/tgui
name = "tgui"
wait = 10
priority = 16
display = 6
can_fire = 1 // This needs to fire before round start.
var/list/open_uis = list() // A list of open UIs, grouped by src_object and ui_key.
var/list/processing_uis = list() // A list of processing UIs, ungrouped.
var/basehtml // The HTML base used for all UIs.
/datum/subsystem/tgui/New()
basehtml = file2text('tgui/tgui.html') // Read the HTML from disk.
NEW_SS_GLOBAL(SStgui)
/datum/subsystem/tgui/stat_entry()
..("P:[processing_uis.len]")
/datum/subsystem/tgui/fire()
for(var/thing in processing_uis)
var/datum/tgui/ui = thing
if(ui && ui.user && ui.src_object)
ui.process()
continue
processing_uis.Remove(ui)
+1 -1
View File
@@ -485,5 +485,5 @@ var/datum/subsystem/ticker/ticker
//map rotate chance defaults to 75% of the length of the round (in minutes)
if (!prob((world.time/600)*config.maprotatechancedelta))
return
spawn(-1) //compiling a map can lock up the mc for 30 to 60 seconds if we don't spawn
spawn(0) //compiling a map can lock up the mc for 30 to 60 seconds if we don't spawn
maprotate()
+7 -3
View File
@@ -26,10 +26,13 @@ var/datum/subsystem/timer/SStimer
if (!event.thingToCall || qdeleted(event.thingToCall))
qdel(event)
if (event.timeToRun <= world.time)
spawn(-1)
call(event.thingToCall, event.procToCall)(arglist(event.argList))
runevent(event)
qdel(event)
/datum/subsystem/timer/proc/runevent(datum/timedevent/event)
set waitfor = 0
call(event.thingToCall, event.procToCall)(arglist(event.argList))
/datum/timedevent
var/thingToCall
var/procToCall
@@ -46,7 +49,8 @@ var/datum/subsystem/timer/SStimer
/datum/timedevent/Destroy()
SStimer.processing -= src
SStimer.hashes -= src.hash
return ..()
return QDEL_HINT_IWILLGC
/proc/addtimer(thingToCall, procToCall, wait, unique = FALSE, ...)
if (!SStimer) //can't run timers before the mc has been created
+24 -1
View File
@@ -188,4 +188,27 @@
/datum/ai_laws/proc/associate(mob/living/silicon/M)
if(!owner)
owner = M
owner = M
/datum/ai_laws/proc/get_law_list(include_zeroth = 0, show_numbers = 1)
var/list/data = list()
if (include_zeroth && zeroth)
data += "[show_numbers ? "0:" : ""] [zeroth]"
for(var/law in ion)
if (length(law) > 0)
var/num = ionnum()
data += "[show_numbers ? "[num]:" : ""] [law]"
var/number = 1
for(var/law in inherent)
if (length(law) > 0)
data += "[show_numbers ? "[number]:" : ""] [law]"
number++
for(var/law in supplied)
if (length(law) > 0)
data += "[show_numbers ? "[number]:" : ""] [law]"
number++
return data
+7 -9
View File
@@ -19,13 +19,9 @@
/datum/beam/New(beam_origin,beam_target,beam_icon='icons/effects/beam.dmi',beam_icon_state="b_beam",time=50,maxdistance=10,btype = /obj/effect/ebeam)
endtime = world.time+time
origin = beam_origin
origin_oldloc = origin.loc
if(isarea(origin_oldloc))
origin_oldloc = origin
origin_oldloc = get_turf(origin)
target = beam_target
target_oldloc = target.loc
if(isarea(target_oldloc))
target_oldloc = target
target_oldloc = get_turf(target)
if(origin_oldloc == origin && target_oldloc == target)
static_beam = 1
max_distance = maxdistance
@@ -38,9 +34,11 @@
/datum/beam/proc/Start()
Draw()
while(!finished && origin && target && world.time < endtime && get_dist(origin,target)<max_distance && origin.z == target.z)
if(!static_beam && (origin.loc != origin_oldloc || target.loc != target_oldloc))
origin_oldloc = origin.loc //so we don't keep checking against their initial positions, leading to endless Reset()+Draw() calls
target_oldloc = target.loc
var/origin_turf = get_turf(origin)
var/target_turf = get_turf(target)
if(!static_beam && (origin_turf != origin_oldloc || target_turf != target_oldloc))
origin_oldloc = origin_turf //so we don't keep checking against their initial positions, leading to endless Reset()+Draw() calls
target_oldloc = target_turf
Reset()
Draw()
sleep(sleep_time)
+2 -2
View File
@@ -348,7 +348,7 @@ body
html += "[name] = <span class='value'>null</span>"
else if (istext(value))
html += "[name] = <span class='value'>\"[value]\"</span>"
html += "[name] = <span class='value'>\"[html_encode(value)]\"</span>"
else if (isicon(value))
#ifdef VARSICON
@@ -405,7 +405,7 @@ body
html += "</ul>"
else
html += "[name] = <span class='value'>[value]</span>"
html += "[name] = <span class='value'>[html_encode(value)]</span>"
html += "</li>"
+1 -1
View File
@@ -122,7 +122,7 @@ var/list/diseases = subtypesof(/datum/disease)
if(isturf(source.loc))
for(var/mob/living/carbon/C in oview(spread_range, source))
if(isturf(C.loc))
if(AStar(source.loc, C.loc, null, /turf/proc/Distance, spread_range, adjacent = (spread_flags & AIRBORNE) ? /turf/proc/reachableAdjacentAtmosTurfs : /turf/proc/reachableAdjacentTurfs))
if(AStar(source, C.loc,/turf/proc/Distance, spread_range, adjacent = (spread_flags & AIRBORNE) ? /turf/proc/reachableAdjacentAtmosTurfs : /turf/proc/reachableAdjacentTurfs))
C.ContractDisease(src)
+1 -1
View File
@@ -5,7 +5,7 @@
spread_flags = CONTACT_GENERAL
cure_text = "Mutadone"
cures = list("mutadone")
disease_flags = CAN_CARRY|CAN_RESIST
disease_flags = CAN_CARRY|CAN_RESIST|CURABLE
agent = "S4E1 retrovirus"
viable_mobtypes = list(/mob/living/carbon/human)
var/datum/dna/original_dna = null
+1 -1
View File
@@ -8,7 +8,7 @@
cure_chance = 15//higher chance to cure, since two reagents are required
agent = "Gravitokinetic Bipotential SADS+"
viable_mobtypes = list(/mob/living/carbon/human)
disease_flags = CAN_CARRY|CAN_RESIST
disease_flags = CAN_CARRY|CAN_RESIST|CURABLE
permeability_mod = 1
severity = BIOHAZARD
+1 -31
View File
@@ -6,7 +6,7 @@
cures = list("iron")
agent = "Fukkos Miracos"
viable_mobtypes = list(/mob/living/carbon/human)
disease_flags = CAN_CARRY|CAN_RESIST
disease_flags = CAN_CARRY|CAN_RESIST|CURABLE
permeability_mod = 0.75
desc = "This disease disrupts the magnetic field of your body, making it act as if a powerful magnet. Injections of iron help stabilize the field."
severity = MEDIUM
@@ -24,16 +24,6 @@
for(var/mob/living/silicon/S in orange(2,affected_mob))
if(istype(S, /mob/living/silicon/ai)) continue
step_towards(S,affected_mob)
/*
if(M.x > affected_mob.x)
M.x--
else if(M.x < affected_mob.x)
M.x++
if(M.y > affected_mob.y)
M.y--
else if(M.y < affected_mob.y)
M.y++
*/
if(3)
if(prob(2))
affected_mob << "<span class='danger'>You feel a strong shock course through your body.</span>"
@@ -52,16 +42,6 @@
var/iter = rand(1,2)
for(i=0,i<iter,i++)
step_towards(S,affected_mob)
/*
if(M.x > affected_mob.x)
M.x-=rand(1,min(3,M.x-affected_mob.x))
else if(M.x < affected_mob.x)
M.x+=rand(1,min(3,affected_mob.x-M.x))
if(M.y > affected_mob.y)
M.y-=rand(1,min(3,M.y-affected_mob.y))
else if(M.y < affected_mob.y)
M.y+=rand(1,min(3,affected_mob.y-M.y))
*/
if(4)
if(prob(2))
affected_mob << "<span class='danger'>You feel a powerful shock course through your body.</span>"
@@ -80,14 +60,4 @@
var/iter = rand(1,3)
for(i=0,i<iter,i++)
step_towards(S,affected_mob)
/*
if(M.x > affected_mob.x)
M.x-=rand(1,min(5,M.x-affected_mob.x))
else if(M.x < affected_mob.x)
M.x+=rand(1,min(5,affected_mob.x-M.x))
if(M.y > affected_mob.y)
M.y-=rand(1,min(5,M.y-affected_mob.y))
else if(M.y < affected_mob.y)
M.y+=rand(1,min(5,affected_mob.y-M.y))
*/
return
+1 -1
View File
@@ -7,7 +7,7 @@
cure_chance = 100
agent = "Rincewindus Vulgaris"
viable_mobtypes = list(/mob/living/carbon/human)
disease_flags = CAN_CARRY|CAN_RESIST
disease_flags = CAN_CARRY|CAN_RESIST|CURABLE
permeability_mod = 0.75
desc = "Some speculate, that this virus is the cause of Wizard Federation existance. Subjects affected show the signs of mental retardation, yelling obscure sentences or total gibberish. On late stages subjects sometime express the feelings of inner power, and, cite, 'the ability to control the forces of cosmos themselves!' A gulp of strong, manly spirits usually reverts them to normal, humanlike, condition."
severity = HARMFUL
+275 -426
View File
@@ -3,90 +3,108 @@ What are the archived variables for?
Calculations are done using the archived variables with the results merged into the regular variables.
This prevents race conditions that arise based on the order of tile processing.
*/
#define SPECIFIC_HEAT_TOXIN 200
#define SPECIFIC_HEAT_AIR 20
#define SPECIFIC_HEAT_CDO 30
#define HEAT_CAPACITY_CALCULATION(oxygen,carbon_dioxide,nitrogen,toxins) \
(carbon_dioxide*SPECIFIC_HEAT_CDO + (oxygen+nitrogen)*SPECIFIC_HEAT_AIR + toxins*SPECIFIC_HEAT_TOXIN)
#define MINIMUM_HEAT_CAPACITY 0.0003
#define QUANTIZE(variable) (round(variable,0.0000001))/*I feel the need to document what happens here. Basically this is used to catch most rounding errors, however it's previous value made it so that
once gases got hot enough, most procedures wouldnt occur due to the fact that the mole counts would get rounded away. Thus, we lowered it a few orders of magnititude */
/datum/gas
var/moles = 0
var/specific_heat = 0
var/moles_archived = 0
var/list/meta_gas_info = meta_gas_list() //see ATMOSPHERICS/gas_types.dm
var/list/cached_gases_list = null
/datum/gas/sleeping_agent
specific_heat = 40
/proc/gaslist(gasid)
if(!cached_gases_list)
cached_gases_list = new /list(meta_gas_info.len)
/datum/gas/oxygen_agent_b
specific_heat = 300
if(!cached_gases_list[gasid])
if(!meta_gas_info[gasid])
CRASH("Error: no such gas type! Type : [gasid]")
/datum/gas/volatile_fuel
specific_heat = 30
var/list/new_gas_list = new(3)
new_gas_list[MOLES] = 0
new_gas_list[ARCHIVE] = 0
new_gas_list[GAS_META] = meta_gas_info[gasid]
cached_gases_list[gasid] = new_gas_list
var/list/gas = cached_gases_list[gasid]
. = gas.Copy()
/datum/gas_mixture
var/oxygen = 0
var/carbon_dioxide = 0
var/nitrogen = 0
var/toxins = 0
var/volume = CELL_VOLUME
var/temperature = 0 //in Kelvin
var/last_share
var/list/datum/gas/trace_gases = list()
var/tmp/oxygen_archived
var/tmp/carbon_dioxide_archived
var/tmp/nitrogen_archived
var/tmp/toxins_archived
var/list/gases
var/temperature //in Kelvin
var/tmp/temperature_archived
var/volume
var/last_share
var/tmp/fuel_burnt
var/tmp/fuel_burnt = 0
/datum/gas_mixture/New(Volume = CELL_VOLUME)
. = ..()
gases = new
temperature = 0
temperature_archived = 0
volume = Volume
last_share = 0
fuel_burnt = 0
//listmos procs
//assert_gas(gas_id) - used to guarantee that the gas list for this id exists.
//Must be used before adding to a gas. May be used before reading from a gas.
/datum/gas_mixture/proc/assert_gas(gas_id)
var/cached_gases = gases
if(cached_gases[gas_id])
return
cached_gases[gas_id] = gaslist(gas_id) //see ATMOSPHERICS/gas_types.dm
//assert_gases(args) - shorthand for calling assert_gas() once for each gas type.
/datum/gas_mixture/proc/assert_gases()
for(var/id in args)
assert_gas(id)
//add_gas(gas_id) - similar to assert_gas(), but does not check for an existing
//gas list for this id.
//Used instead of assert_gas() when you know the gas does not exist. Faster than assert_gas().
/datum/gas_mixture/proc/add_gas(gas_id)
gases[gas_id] = gaslist(gas_id)
//add_gases(args) - shorthand for calling add_gas() once for each gas_type.
/datum/gas_mixture/proc/add_gases()
for(var/id in args)
add_gas(id)
//garbage_collect() - removes any gas list which is empty.
//Must be used after subtracting from a gas. Must be used after assert_gas()
//if assert_gas() was called only to read from the gas.
//By removing empty gases, processing speed is increased.
/datum/gas_mixture/proc/garbage_collect()
var/list/cached_gases = gases
for(var/id in cached_gases)
var/gas = cached_gases[id]
if(QUANTIZE(gas[MOLES]) <= 0 && QUANTIZE(gas[ARCHIVE]) <= 0)
cached_gases -= id
//PV=nRT - related procedures
/datum/gas_mixture/proc/heat_capacity()
var/heat_capacity = HEAT_CAPACITY_CALCULATION(oxygen,carbon_dioxide,nitrogen,toxins)
for(var/gas in trace_gases)
var/datum/gas/trace_gas = gas
heat_capacity += trace_gas.moles*trace_gas.specific_heat
return heat_capacity
var/list/cached_gases = gases
. = 0
for(var/id in cached_gases)
. += cached_gases[id][MOLES]*cached_gases[id][SPECIFIC_HEAT]
/datum/gas_mixture/proc/heat_capacity_archived()
var/heat_capacity_archived = HEAT_CAPACITY_CALCULATION(oxygen_archived,carbon_dioxide_archived,nitrogen_archived,toxins_archived)
for(var/gas in trace_gases)
var/datum/gas/trace_gas = gas
heat_capacity_archived += trace_gas.moles_archived*trace_gas.specific_heat
return heat_capacity_archived
var/list/cached_gases = gases
. = 0
for(var/id in cached_gases)
. += cached_gases[id][ARCHIVE]*cached_gases[id][SPECIFIC_HEAT]
/datum/gas_mixture/proc/total_moles()
var/moles = oxygen + carbon_dioxide + nitrogen + toxins
for(var/gas in trace_gases)
var/datum/gas/trace_gas = gas
moles += trace_gas.moles
return moles
var/list/cached_gases = gases
. = 0
for(var/id in cached_gases)
. += cached_gases[id][MOLES]
/datum/gas_mixture/proc/return_pressure()
if(volume>0)
return total_moles()*R_IDEAL_GAS_EQUATION*temperature/volume
return 0
/datum/gas_mixture/proc/return_temperature()
return temperature
@@ -103,84 +121,96 @@ What are the archived variables for?
/datum/gas_mixture/proc/react(atom/dump_location)
var/list/procgases = gases //this speeds things up because >byond
var/reacting = 0 //set to 1 if a notable reaction occured (used by pipe_network)
if(temperature < TCMB)
temperature = TCMB
if(trace_gases.len > 0)
if(temperature > 900)
if(toxins > MINIMUM_HEAT_CAPACITY && carbon_dioxide > MINIMUM_HEAT_CAPACITY)
var/datum/gas/oxygen_agent_b/trace_gas = locate(/datum/gas/oxygen_agent_b/) in trace_gases
if(trace_gas)
var/reaction_rate = min(carbon_dioxide*0.75, toxins*0.25, trace_gas.moles*0.05)
if(procgases["agent_b"] && temperature > 900 && procgases["plasma"] && procgases["co2"])
if(procgases["plasma"][MOLES] > MINIMUM_HEAT_CAPACITY && procgases["co2"][MOLES] > MINIMUM_HEAT_CAPACITY)
var/reaction_rate = min(procgases["co2"][MOLES]*0.75, procgases["plasma"][MOLES]*0.25, procgases["agent_b"][MOLES]*0.05)
carbon_dioxide -= reaction_rate
oxygen += reaction_rate
procgases["co2"][MOLES] -= reaction_rate
trace_gas.moles -= reaction_rate*0.05
assert_gas("o2") //only need to assert oxygen, as this reaction doesn't occur without the other gases existing
procgases["o2"][MOLES] += reaction_rate
temperature -= (reaction_rate*20000)/heat_capacity()
procgases["agent_b"][MOLES] -= reaction_rate*0.05
reacting = 1
temperature -= (reaction_rate*20000)/heat_capacity()
garbage_collect()
reacting = 1
/*
if(thermal_energy() > (PLASMA_BINDING_ENERGY*10))
if(toxins > MINIMUM_HEAT_CAPACITY && carbon_dioxide > MINIMUM_HEAT_CAPACITY && (toxins+carbon_dioxide)/total_moles() >= FUSION_PURITY_THRESHOLD)//Fusion wont occur if the level of impurities is too high.
//world << "pre [temperature, [toxins], [carbon_dioxide]
if(procgases["plasma"] && procgases["co2"] && procgases["plasma"][MOLES] > MINIMUM_HEAT_CAPACITY && procgases["co2"][MOLES] > MINIMUM_HEAT_CAPACITY && (procgases["plasma"][MOLES]+procgases["co2"][MOLES])/total_moles() >= FUSION_PURITY_THRESHOLD)//Fusion wont occur if the level of impurities is too high.
//world << "pre [temperature, [procgases["plasma"][MOLES]], [procgases["co2"][MOLES]]
var/old_heat_capacity = heat_capacity()
var/carbon_efficency = min(toxins/carbon_dioxide,MAX_CARBON_EFFICENCY)
var/carbon_efficency = min(procgases["plasma"][MOLES]/procgases["co2"][MOLES],MAX_CARBON_EFFICENCY)
var/reaction_energy = thermal_energy()
var/moles_impurities = total_moles()-(toxins+carbon_dioxide)
var/moles_impurities = total_moles()-(procgases["plasma"][MOLES]+procgases["co2"][MOLES])
var/plasma_fused = (PLASMA_FUSED_COEFFICENT*carbon_efficency)*(temperature/PLASMA_BINDING_ENERGY)
var/carbon_catalyzed = (CARBON_CATALYST_COEFFICENT*carbon_efficency)*(temperature/PLASMA_BINDING_ENERGY)
var/oxygen_added = carbon_catalyzed
var/nitrogen_added = (plasma_fused-oxygen_added)-(thermal_energy()/PLASMA_BINDING_ENERGY)
reaction_energy = max(reaction_energy+((carbon_efficency*toxins)/((moles_impurities/carbon_efficency)+2)*10)+((plasma_fused/(moles_impurities/carbon_efficency))*PLASMA_BINDING_ENERGY),0)
toxins = max(toxins-plasma_fused,0)
carbon_dioxide = max(carbon_dioxide-carbon_catalyzed,0)
oxygen = max(oxygen+oxygen_added,0)
nitrogen = max(nitrogen+nitrogen_added,0)
reaction_energy = max(reaction_energy+((carbon_efficency*procgases["plasma"][MOLES])/((moles_impurities/carbon_efficency)+2)*10)+((plasma_fused/(moles_impurities/carbon_efficency))*PLASMA_BINDING_ENERGY),0)
assert_gases("o2", "n2")
procgases["plasma"][MOLES] -= plasma_fused
procgases["co2"][MOLES] -= carbon_catalyzed
procgases["o2"][MOLES] += oxygen_added
procgases["n2"][MOLES] += nitrogen_added
garbage_collect()
if(reaction_energy > 0)
reacting = 1
var/new_heat_capacity = heat_capacity()
if(new_heat_capacity > MINIMUM_HEAT_CAPACITY)
temperature = max(((temperature*old_heat_capacity + reaction_energy)/new_heat_capacity),TCMB)
//Prevents whatever mechanism is causing it to hit negative temperatures.
//world << "post [temperature], [toxins], [carbon_dioxide]
//world << "post [temperature], [procgases["plasma"][MOLES]], [procgases["co2"][MOLES]]
*/
fuel_burnt = 0
if(temperature > FIRE_MINIMUM_TEMPERATURE_TO_EXIST)
//world << "pre [temperature], [oxygen], [toxins]"
if(fire() > 0)
//world << "pre [temperature], [procgases["o2"][MOLES]], [procgases["plasma"][MOLES]]"
if(fire())
reacting = 1
//world << "post [temperature], [oxygen], [toxins]"
//world << "post [temperature], [procgases["o2"][MOLES]], [procgases["plasma"][MOLES]]"
return reacting
/datum/gas_mixture/proc/fire()
var/energy_released = 0
var/old_heat_capacity = heat_capacity()
var/list/procgases = gases //this speeds things up because accessing datum vars is slow
var/datum/gas/volatile_fuel/fuel_store = locate(/datum/gas/volatile_fuel/) in trace_gases
if(fuel_store) //General volatile gas burn
var/burned_fuel = 0
if(procgases["v_fuel"] && procgases["v_fuel"][MOLES]) //General volatile gas burn
var/burned_fuel
if(oxygen < fuel_store.moles)
burned_fuel = oxygen
fuel_store.moles -= burned_fuel
oxygen = 0
if(!procgases["o2"])
burned_fuel = 0
else if(procgases["o2"][MOLES] < procgases["v_fuel"][MOLES])
burned_fuel = procgases["o2"][MOLES]
procgases["v_fuel"][MOLES] -= burned_fuel
procgases["o2"][MOLES] = 0
else
burned_fuel = fuel_store.moles
oxygen -= fuel_store.moles
trace_gases -= fuel_store
fuel_store = null
burned_fuel = procgases["v_fuel"][MOLES]
procgases["o2"][MOLES] -= procgases["v_fuel"][MOLES]
energy_released += FIRE_CARBON_ENERGY_RELEASED * burned_fuel
carbon_dioxide += burned_fuel
fuel_burnt += burned_fuel
if(burned_fuel)
energy_released += FIRE_CARBON_ENERGY_RELEASED * burned_fuel
assert_gas("co2")
procgases["co2"][MOLES] += burned_fuel
fuel_burnt += burned_fuel
//Handle plasma burning
if(toxins > MINIMUM_HEAT_CAPACITY)
if(procgases["plasma"] && procgases["plasma"][MOLES] > MINIMUM_HEAT_CAPACITY)
var/plasma_burn_rate = 0
var/oxygen_burn_rate = 0
//more plasma released at higher temperatures
@@ -190,19 +220,22 @@ What are the archived variables for?
else
temperature_scale = (temperature-PLASMA_MINIMUM_BURN_TEMPERATURE)/(PLASMA_UPPER_TEMPERATURE-PLASMA_MINIMUM_BURN_TEMPERATURE)
if(temperature_scale > 0)
assert_gas("o2")
assert_gas("co2")
oxygen_burn_rate = OXYGEN_BURN_RATE_BASE - temperature_scale
if(oxygen > toxins*PLASMA_OXYGEN_FULLBURN)
plasma_burn_rate = (toxins*temperature_scale)/PLASMA_BURN_RATE_DELTA
if(procgases["o2"][MOLES] > procgases["plasma"][MOLES]*PLASMA_OXYGEN_FULLBURN)
plasma_burn_rate = (procgases["plasma"][MOLES]*temperature_scale)/PLASMA_BURN_RATE_DELTA
else
plasma_burn_rate = (temperature_scale*(oxygen/PLASMA_OXYGEN_FULLBURN))/PLASMA_BURN_RATE_DELTA
plasma_burn_rate = (temperature_scale*(procgases["o2"][MOLES]/PLASMA_OXYGEN_FULLBURN))/PLASMA_BURN_RATE_DELTA
if(plasma_burn_rate > MINIMUM_HEAT_CAPACITY)
toxins -= plasma_burn_rate
oxygen -= plasma_burn_rate*oxygen_burn_rate
carbon_dioxide += plasma_burn_rate
procgases["plasma"][MOLES] -= plasma_burn_rate
procgases["o2"][MOLES] -= plasma_burn_rate*oxygen_burn_rate
procgases["co2"][MOLES] += plasma_burn_rate
energy_released += FIRE_PLASMA_ENERGY_RELEASED * (plasma_burn_rate)
fuel_burnt += (plasma_burn_rate)*(1+oxygen_burn_rate)
garbage_collect()
if(energy_released > 0)
var/new_heat_capacity = heat_capacity()
@@ -217,7 +250,7 @@ What are the archived variables for?
/datum/gas_mixture/proc/merge(datum/gas_mixture/giver)
//Merges all air from giver into self. Deletes giver.
//Returns: 1 on success (no failure cases yet)
//Returns: 1 in all cases
/datum/gas_mixture/proc/remove(amount)
//Proportionally removes amount of gas from the gas_mixture
@@ -233,11 +266,11 @@ What are the archived variables for?
/datum/gas_mixture/proc/share(datum/gas_mixture/sharer)
//Performs air sharing calculations between two gas_mixtures assuming only 1 boundary length
//Return: amount of gas exchanged (+ if sharer received)
/datum/gas_mixture/proc/mimic(turf/model) //I want this proc to die a painful death
/datum/gas_mixture/proc/mimic(turf/model)
//Similar to share(...), except the model is not modified
//Return: amount of gas exchanged
/datum/gas_mixture/proc/check_turf(turf/model) //I want this proc to die a painful death
/datum/gas_mixture/proc/check_turf(turf/model)
//Returns: 0 if self-check failed or 1 if check passes
/datum/gas_mixture/proc/temperature_mimic(turf/model, conduction_coefficient) //I want this proc to die a painful death
@@ -248,20 +281,17 @@ What are the archived variables for?
/datum/gas_mixture/proc/compare(datum/gas_mixture/sample)
//Compares sample to self to see if within acceptable ranges that group processing may be enabled
//returns: a string indicating what check failed, or "" if check passes
/datum/gas_mixture/proc/copy_from_turf(turf/model)
//Copies all gas info from the turf into the gas list along with copying temperature, then archives
/datum/gas_mixture/archive()
oxygen_archived = oxygen
carbon_dioxide_archived = carbon_dioxide
nitrogen_archived = nitrogen
toxins_archived = toxins
for(var/gas in trace_gases)
var/datum/gas/trace_gas = gas
trace_gas.moles_archived = trace_gas.moles
var/list/cached_gases = gases
for(var/id in cached_gases)
cached_gases[id][ARCHIVE] = cached_gases[id][MOLES]
temperature_archived = temperature
return 1
. = 1
/datum/gas_mixture/merge(datum/gas_mixture/giver)
if(!giver)
@@ -271,268 +301,145 @@ What are the archived variables for?
var/self_heat_capacity = heat_capacity()
var/giver_heat_capacity = giver.heat_capacity()
var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity
if(combined_heat_capacity != 0)
if(combined_heat_capacity)
temperature = (giver.temperature*giver_heat_capacity + temperature*self_heat_capacity)/combined_heat_capacity
var/list/cached_gases = gases //accessing datum vars is slower than proc vars
var/list/giver_gases = giver.gases
for(var/giver_id in giver_gases)
assert_gas(giver_id)
cached_gases[giver_id][MOLES] += giver_gases[giver_id][MOLES]
oxygen += giver.oxygen
carbon_dioxide += giver.carbon_dioxide
nitrogen += giver.nitrogen
toxins += giver.toxins
for(var/gas in giver.trace_gases)
var/datum/gas/trace_gas = gas
var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases
if(!corresponding)
corresponding = new trace_gas.type()
trace_gases += corresponding
corresponding.moles += trace_gas.moles
return 1
. = 1
/datum/gas_mixture/remove(amount)
var/sum = total_moles()
amount = min(amount,sum) //Can not take more air than tile has!
if(amount <= 0)
return null
var/datum/gas_mixture/removed = new
var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars
var/list/cached_gases = gases
removed.oxygen = QUANTIZE((oxygen/sum)*amount)
removed.nitrogen = QUANTIZE((nitrogen/sum)*amount)
removed.carbon_dioxide = QUANTIZE((carbon_dioxide/sum)*amount)
removed.toxins = QUANTIZE((toxins/sum)*amount)
oxygen -= removed.oxygen
nitrogen -= removed.nitrogen
carbon_dioxide -= removed.carbon_dioxide
toxins -= removed.toxins
for(var/gas in trace_gases)
var/datum/gas/trace_gas = gas
var/datum/gas/corresponding = new trace_gas.type()
removed.trace_gases += corresponding
corresponding.moles = (trace_gas.moles/sum)*amount
trace_gas.moles -= corresponding.moles
for(var/id in cached_gases)
removed.assert_gas(id)
removed_gases[id][MOLES] = QUANTIZE((cached_gases[id][MOLES]/sum)*amount)
cached_gases[id][MOLES] -= removed_gases[id][MOLES]
removed.temperature = temperature
return removed
garbage_collect()
. = removed
/datum/gas_mixture/remove_ratio(ratio)
if(ratio <= 0)
return null
ratio = min(ratio, 1)
var/datum/gas_mixture/removed = new
var/list/removed_gases = removed.gases //accessing datum vars is slower than proc vars
var/list/cached_gases = gases
removed.oxygen = QUANTIZE(oxygen*ratio)
removed.nitrogen = QUANTIZE(nitrogen*ratio)
removed.carbon_dioxide = QUANTIZE(carbon_dioxide*ratio)
removed.toxins = QUANTIZE(toxins*ratio)
oxygen -= removed.oxygen
nitrogen -= removed.nitrogen
carbon_dioxide -= removed.carbon_dioxide
toxins -= removed.toxins
for(var/gas in trace_gases)
var/datum/gas/trace_gas = gas
var/datum/gas/corresponding = new trace_gas.type()
removed.trace_gases += corresponding
corresponding.moles = trace_gas.moles*ratio
trace_gas.moles -= corresponding.moles
for(var/id in cached_gases)
removed.assert_gas(id)
removed_gases[id][MOLES] = QUANTIZE(cached_gases[id][MOLES]*ratio)
cached_gases[id][MOLES] -= removed_gases[id][MOLES]
removed.temperature = temperature
return removed
garbage_collect()
. = removed
/datum/gas_mixture/copy_from(datum/gas_mixture/sample)
oxygen = sample.oxygen
carbon_dioxide = sample.carbon_dioxide
nitrogen = sample.nitrogen
toxins = sample.toxins
var/list/cached_gases = gases //accessing datum vars is slower than proc vars
var/list/sample_gases = sample.gases
var/list/copied_gases = list()
for(var/sample_id in sample_gases)
assert_gas(sample_id)
cached_gases[sample_id][MOLES] = sample_gases[sample_id][MOLES]
copied_gases += sample_id
for(var/id in cached_gases-copied_gases)
assert_gas(id)
cached_gases[id][MOLES] = 0
trace_gases.len=null
for(var/gas in sample.trace_gases)
var/datum/gas/trace_gas = gas
var/datum/gas/corresponding = new trace_gas.type()
trace_gases += corresponding
corresponding.moles = trace_gas.moles
garbage_collect()
temperature = sample.temperature
return 1
/datum/gas_mixture/check_turf(turf/model, atmos_adjacent_turfs = 4)
var/delta_oxygen = (oxygen_archived - model.oxygen)/(atmos_adjacent_turfs+1)
var/delta_carbon_dioxide = (carbon_dioxide_archived - model.carbon_dioxide)/(atmos_adjacent_turfs+1)
var/delta_nitrogen = (nitrogen_archived - model.nitrogen)/(atmos_adjacent_turfs+1)
var/delta_toxins = (toxins_archived - model.toxins)/(atmos_adjacent_turfs+1)
var/delta_temperature = (temperature_archived - model.temperature)
if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins_archived*MINIMUM_AIR_RATIO_TO_SUSPEND)))
return 0
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
return 0
for(var/gas in trace_gases)
var/datum/gas/trace_gas = gas
if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND*4)
return 0
return 1
/datum/gas_mixture/proc/check_turf_total(turf/model) //I want this proc to die a painful death
var/delta_oxygen = (oxygen - model.oxygen)
var/delta_carbon_dioxide = (carbon_dioxide - model.carbon_dioxide)
var/delta_nitrogen = (nitrogen - model.nitrogen)
var/delta_toxins = (toxins - model.toxins)
var/delta_temperature = (temperature - model.temperature)
if(((abs(delta_oxygen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_oxygen) >= oxygen*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_carbon_dioxide) >= carbon_dioxide*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_nitrogen) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_nitrogen) >= nitrogen*MINIMUM_AIR_RATIO_TO_SUSPEND)) \
|| ((abs(delta_toxins) > MINIMUM_AIR_TO_SUSPEND) && (abs(delta_toxins) >= toxins*MINIMUM_AIR_RATIO_TO_SUSPEND)))
return 0
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND)
return 0
for(var/gas in trace_gases)
var/datum/gas/trace_gas = gas
if(trace_gas.moles > MINIMUM_AIR_TO_SUSPEND*4)
return 0
return 1
var/datum/gas_mixture/copied = new
copied.copy_from_turf(model)
. = compare(copied, datatype = ARCHIVE, adjacents = atmos_adjacent_turfs)
/datum/gas_mixture/share(datum/gas_mixture/sharer, atmos_adjacent_turfs = 4)
if(!sharer) return 0
var/delta_oxygen = QUANTIZE(oxygen_archived - sharer.oxygen_archived)/(atmos_adjacent_turfs+1)
var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - sharer.carbon_dioxide_archived)/(atmos_adjacent_turfs+1)
var/delta_nitrogen = QUANTIZE(nitrogen_archived - sharer.nitrogen_archived)/(atmos_adjacent_turfs+1)
var/delta_toxins = QUANTIZE(toxins_archived - sharer.toxins_archived)/(atmos_adjacent_turfs+1)
. = 0
if(!sharer)
return
var/moved_moles = 0
var/abs_moved_moles = 0
//make this local to the proc for sanic speed
var/list/sharercache = sharer.gases
var/list/selfcache = gases
var/delta_temperature = (temperature_archived - sharer.temperature_archived)
var/old_self_heat_capacity = 0
var/old_sharer_heat_capacity = 0
var/heat_capacity_self_to_sharer = 0
var/heat_capacity_sharer_to_self = 0
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/delta_air = delta_oxygen+delta_nitrogen
if(delta_air)
var/air_heat_capacity = SPECIFIC_HEAT_AIR*delta_air
if(delta_air > 0)
heat_capacity_self_to_sharer += air_heat_capacity
else
heat_capacity_sharer_to_self -= air_heat_capacity
if(delta_carbon_dioxide)
var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO*delta_carbon_dioxide
if(delta_carbon_dioxide > 0)
heat_capacity_self_to_sharer += carbon_dioxide_heat_capacity
else
heat_capacity_sharer_to_self -= carbon_dioxide_heat_capacity
if(delta_toxins)
var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN*delta_toxins
if(delta_toxins > 0)
heat_capacity_self_to_sharer += toxins_heat_capacity
else
heat_capacity_sharer_to_self -= toxins_heat_capacity
old_self_heat_capacity = heat_capacity()
old_sharer_heat_capacity = sharer.heat_capacity()
oxygen -= delta_oxygen
sharer.oxygen += delta_oxygen
var/heat_capacity_self_to_sharer = 0 //heat capacity of the moles transferred from us to the sharer
var/heat_capacity_sharer_to_self = 0 //heat capacity of the moles transferred from the sharer to us
carbon_dioxide -= delta_carbon_dioxide
sharer.carbon_dioxide += delta_carbon_dioxide
for(var/sharer_id in sharercache-selfcache)
add_gas(sharer_id) //we can use add_gas() because we're looping only through the IDs not in our cache
nitrogen -= delta_nitrogen
sharer.nitrogen += delta_nitrogen
//GAS TRANSFER
for(var/id in selfcache)
if(!sharercache[id]) //checking here prevents an uneeded proc call if the check fails.
sharer.add_gas(id)
toxins -= delta_toxins
sharer.toxins += delta_toxins
var/gas = selfcache[id]
var/sharergas = sharercache[id]
var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins)
last_share = abs(delta_oxygen) + abs(delta_carbon_dioxide) + abs(delta_nitrogen) + abs(delta_toxins)
var/delta = QUANTIZE(gas[ARCHIVE] - sharergas[ARCHIVE])/(atmos_adjacent_turfs+1) //the amount of gas that gets moved between the mixtures
var/list/trace_types_considered = list()
for(var/gas in trace_gases)
var/datum/gas/trace_gas = gas
var/datum/gas/corresponding = locate(trace_gas.type) in sharer.trace_gases
var/delta = 0
if(corresponding)
delta = QUANTIZE(trace_gas.moles_archived - corresponding.moles_archived)/(atmos_adjacent_turfs+1)
else
corresponding = new trace_gas.type()
sharer.trace_gases += corresponding
delta = trace_gas.moles_archived/(atmos_adjacent_turfs+1)
trace_gas.moles -= delta
corresponding.moles += delta
if(delta)
var/individual_heat_capacity = trace_gas.specific_heat*delta
if(delta && abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/gas_heat_capacity = delta * gas[SPECIFIC_HEAT]
if(delta > 0)
heat_capacity_self_to_sharer += individual_heat_capacity
heat_capacity_self_to_sharer += gas_heat_capacity
else
heat_capacity_sharer_to_self -= individual_heat_capacity
heat_capacity_sharer_to_self -= gas_heat_capacity //subtract here instead of adding the absolute value because we know that delta is negative. saves a proc call.
moved_moles += delta
last_share += abs(delta)
gas[MOLES] -= delta
sharergas[MOLES] += delta
moved_moles += delta
abs_moved_moles += abs(delta)
trace_types_considered += trace_gas.type
for(var/gas in sharer.trace_gases)
var/datum/gas/trace_gas = gas
if(trace_gas.type in trace_types_considered)
continue
var/datum/gas/corresponding
var/delta = 0
corresponding = new trace_gas.type()
trace_gases += corresponding
delta = trace_gas.moles_archived/5
trace_gas.moles -= delta
corresponding.moles += delta
//Guaranteed transfer from sharer to self
var/individual_heat_capacity = trace_gas.specific_heat*delta
heat_capacity_sharer_to_self += individual_heat_capacity
moved_moles += -delta
last_share += abs(delta)
last_share = abs_moved_moles
//THERMAL ENERGY TRANSFER
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/new_self_heat_capacity = old_self_heat_capacity + heat_capacity_sharer_to_self - heat_capacity_self_to_sharer
var/new_sharer_heat_capacity = old_sharer_heat_capacity + heat_capacity_self_to_sharer - heat_capacity_sharer_to_self
//transfer of thermal energy (via changed heat capacity) between self and sharer
if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY)
temperature = (old_self_heat_capacity*temperature - heat_capacity_self_to_sharer*temperature_archived + heat_capacity_sharer_to_self*sharer.temperature_archived)/new_self_heat_capacity
if(new_sharer_heat_capacity > MINIMUM_HEAT_CAPACITY)
sharer.temperature = (old_sharer_heat_capacity*sharer.temperature-heat_capacity_sharer_to_self*sharer.temperature_archived + heat_capacity_self_to_sharer*temperature_archived)/new_sharer_heat_capacity
//thermal energy of the system (self and sharer) is unchanged
if(abs(old_sharer_heat_capacity) > MINIMUM_HEAT_CAPACITY)
if(abs(new_sharer_heat_capacity/old_sharer_heat_capacity - 1) < 0.10) // <10% change in sharer heat capacity
@@ -540,78 +447,18 @@ What are the archived variables for?
if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE) || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
var/delta_pressure = temperature_archived*(total_moles() + moved_moles) - sharer.temperature_archived*(sharer.total_moles() - moved_moles)
return delta_pressure*R_IDEAL_GAS_EQUATION/volume
. = delta_pressure*R_IDEAL_GAS_EQUATION/volume
garbage_collect()
sharer.garbage_collect()
/datum/gas_mixture/mimic(turf/model, atmos_adjacent_turfs = 4)
var/delta_oxygen = QUANTIZE(oxygen_archived - model.oxygen)/(atmos_adjacent_turfs+1)
var/delta_carbon_dioxide = QUANTIZE(carbon_dioxide_archived - model.carbon_dioxide)/(atmos_adjacent_turfs+1)
var/delta_nitrogen = QUANTIZE(nitrogen_archived - model.nitrogen)/(atmos_adjacent_turfs+1)
var/delta_toxins = QUANTIZE(toxins_archived - model.toxins)/(atmos_adjacent_turfs+1)
var/delta_temperature = (temperature_archived - model.temperature)
var/heat_transferred = 0
var/old_self_heat_capacity = 0
var/heat_capacity_transferred = 0
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/delta_air = delta_oxygen+delta_nitrogen
if(delta_air)
var/air_heat_capacity = SPECIFIC_HEAT_AIR*delta_air
heat_transferred -= air_heat_capacity*model.temperature
heat_capacity_transferred -= air_heat_capacity
if(delta_carbon_dioxide)
var/carbon_dioxide_heat_capacity = SPECIFIC_HEAT_CDO*delta_carbon_dioxide
heat_transferred -= carbon_dioxide_heat_capacity*model.temperature
heat_capacity_transferred -= carbon_dioxide_heat_capacity
if(delta_toxins)
var/toxins_heat_capacity = SPECIFIC_HEAT_TOXIN*delta_toxins
heat_transferred -= toxins_heat_capacity*model.temperature
heat_capacity_transferred -= toxins_heat_capacity
old_self_heat_capacity = heat_capacity()
oxygen -= delta_oxygen
carbon_dioxide -= delta_carbon_dioxide
nitrogen -= delta_nitrogen
toxins -= delta_toxins
var/moved_moles = (delta_oxygen + delta_carbon_dioxide + delta_nitrogen + delta_toxins)
last_share = abs(delta_oxygen) + abs(delta_carbon_dioxide) + abs(delta_nitrogen) + abs(delta_toxins)
if(trace_gases.len)
for(var/gas in trace_gases)
var/datum/gas/trace_gas = gas
var/delta = 0
delta = trace_gas.moles_archived/(atmos_adjacent_turfs+1)
trace_gas.moles -= delta
var/heat_cap_transferred = delta*trace_gas.specific_heat
heat_transferred += heat_cap_transferred*temperature_archived
heat_capacity_transferred += heat_cap_transferred
moved_moles += delta
moved_moles += abs(delta)
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/new_self_heat_capacity = old_self_heat_capacity - heat_capacity_transferred
if(new_self_heat_capacity > MINIMUM_HEAT_CAPACITY)
temperature = (old_self_heat_capacity*temperature - heat_capacity_transferred*temperature_archived)/new_self_heat_capacity
temperature_mimic(model, model.thermal_conductivity)
if((delta_temperature > MINIMUM_TEMPERATURE_TO_MOVE) || abs(moved_moles) > MINIMUM_MOLES_DELTA_TO_MOVE)
var/delta_pressure = temperature_archived*(total_moles() + moved_moles) - model.temperature*(model.oxygen+model.carbon_dioxide+model.nitrogen+model.toxins)
return delta_pressure*R_IDEAL_GAS_EQUATION/volume
else
return 0
var/datum/gas_mixture/copied = new
copied.copy_from_turf(model)
. = share(copied, atmos_adjacent_turfs)
/datum/gas_mixture/temperature_share(datum/gas_mixture/sharer, conduction_coefficient)
//transfer of thermal energy (via conduction) between self and sharer
var/delta_temperature = (temperature_archived - sharer.temperature_archived)
if(abs(delta_temperature) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
var/self_heat_capacity = heat_capacity_archived()
@@ -621,8 +468,9 @@ What are the archived variables for?
var/heat = conduction_coefficient*delta_temperature* \
(self_heat_capacity*sharer_heat_capacity/(self_heat_capacity+sharer_heat_capacity))
temperature -= heat/self_heat_capacity
sharer.temperature += heat/sharer_heat_capacity
temperature = max(temperature - heat/self_heat_capacity, TCMB)
sharer.temperature = max(sharer.temperature + heat/sharer_heat_capacity, TCMB)
//thermal energy of the system (self and sharer) is unchanged
/datum/gas_mixture/temperature_mimic(turf/model, conduction_coefficient)
var/delta_temperature = (temperature - model.temperature)
@@ -633,7 +481,7 @@ What are the archived variables for?
var/heat = conduction_coefficient*delta_temperature* \
(self_heat_capacity*model.heat_capacity/(self_heat_capacity+model.heat_capacity))
temperature -= heat/self_heat_capacity
temperature = max(temperature - heat/self_heat_capacity, TCMB)
/datum/gas_mixture/temperature_turf_share(turf/simulated/sharer, conduction_coefficient)
var/delta_temperature = (temperature_archived - sharer.temperature)
@@ -644,53 +492,54 @@ What are the archived variables for?
var/heat = conduction_coefficient*delta_temperature* \
(self_heat_capacity*sharer.heat_capacity/(self_heat_capacity+sharer.heat_capacity))
temperature -= heat/self_heat_capacity
sharer.temperature += heat/sharer.heat_capacity
temperature = max(temperature - heat/self_heat_capacity, TCMB)
sharer.temperature = max(sharer.temperature + heat/sharer.heat_capacity, TCMB)
/datum/gas_mixture/compare(datum/gas_mixture/sample)
if((abs(oxygen-sample.oxygen) > MINIMUM_AIR_TO_SUSPEND) && \
((oxygen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.oxygen)))
return 0
if((abs(nitrogen-sample.nitrogen) > MINIMUM_AIR_TO_SUSPEND) && \
((nitrogen < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen) || (nitrogen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.nitrogen)))
return 0
if((abs(carbon_dioxide-sample.carbon_dioxide) > MINIMUM_AIR_TO_SUSPEND) && \
((carbon_dioxide < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide) || (oxygen > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.carbon_dioxide)))
return 0
if((abs(toxins-sample.toxins) > MINIMUM_AIR_TO_SUSPEND) && \
((toxins < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins) || (toxins > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*sample.toxins)))
return 0
/datum/gas_mixture/compare(datum/gas_mixture/sample, datatype = MOLES, adjacents = 0)
. = ""
var/list/sample_gases = sample.gases //accessing datum vars is slower than proc vars
var/list/cached_gases = gases
for(var/id in cached_gases|sample_gases)
var/gas_moles = cached_gases[id] ? cached_gases[id][datatype] : 0
var/sample_moles = sample_gases[id] ? sample_gases[id][datatype] : 0
var/delta = abs(gas_moles - sample_moles)/(adjacents+1)
if(delta > MINIMUM_AIR_TO_SUSPEND && \
delta > gas_moles*MINIMUM_AIR_RATIO_TO_SUSPEND)
return id
if(total_moles() > MINIMUM_AIR_TO_SUSPEND)
if((abs(temperature-sample.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) && \
((temperature < (1-MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature) || (temperature > (1+MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature)))
return 0
var/temp
var/sample_temp
for(var/gas in sample.trace_gases)
var/datum/gas/trace_gas = gas
if(trace_gas.moles_archived > MINIMUM_AIR_TO_SUSPEND)
var/datum/gas/corresponding = locate(trace_gas.type) in trace_gases
if(corresponding)
if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \
((corresponding.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles) || (corresponding.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*trace_gas.moles)))
return 0
else
return 0
switch(datatype)
if(MOLES)
temp = temperature
sample_temp = sample.temperature
if(ARCHIVE)
temp = temperature_archived
sample_temp = sample.temperature_archived
for(var/gas in trace_gases)
var/datum/gas/trace_gas = gas
if(trace_gas.moles > MINIMUM_AIR_TO_SUSPEND)
var/datum/gas/corresponding = locate(trace_gas.type) in sample.trace_gases
if(corresponding)
if((abs(trace_gas.moles - corresponding.moles) > MINIMUM_AIR_TO_SUSPEND) && \
((trace_gas.moles < (1-MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles) || (trace_gas.moles > (1+MINIMUM_AIR_RATIO_TO_SUSPEND)*corresponding.moles)))
return 0
else
return 0
return 1
var/delta_temperature = abs(temp-sample_temp)
if((delta_temperature > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) && \
delta_temperature > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND*temp)
return "temp"
/datum/gas_mixture/copy_from_turf(turf/model)
assert_gases(arglist(hardcoded_gases))
var/list/cached_gases = gases
cached_gases["o2"][MOLES] = model.oxygen
cached_gases["n2"][MOLES] = model.nitrogen
cached_gases["plasma"][MOLES] = model.toxins
cached_gases["co2"][MOLES] = model.carbon_dioxide
for(var/id in cached_gases-hardcoded_gases)
cached_gases[id][MOLES] = 0 //turfs don't account for anything other than the four old hardcoded gases
temperature = model.temperature
garbage_collect()
//Takes the amount of the gas you want to PP as an argument
//So I don't have to do some hacky switches/defines/magic strings
+1 -1
View File
@@ -34,7 +34,7 @@
//world << "Events in [args[1]] called"
var/list/event = listgetindex(events,args[1])
if(istype(event))
spawn(-1)
spawn(0)
for(var/datum/event/E in event)
if(!E.Fire(arglist(args.Copy(2))))
clearEvent(args[1],E)
+2 -2
View File
@@ -82,12 +82,12 @@
/datum/teleport/proc/playSpecials(atom/location,datum/effect_system/effect,sound)
if(location)
if(effect)
spawn(-1)
spawn(0)
src = null
effect.attach(location)
effect.start()
if(sound)
spawn(-1)
spawn(0)
src = null
playsound(location,sound,60,1)
return
+1680 -1580
View File
File diff suppressed because it is too large Load Diff
-62
View File
@@ -1,62 +0,0 @@
// module datum.
// this is per-object instance, and shows the condition of the modules in the object
// actual modules needed is referenced through modulestypes and the object type
/datum/module
var/status // bits set if working, 0 if broken
var/installed // bits set if installed, 0 if missing
// moduletypes datum
// this is per-object type, and shows the modules needed for a type of object
/datum/moduletypes
var/list/modcount = list() // assoc list of the count of modules for a type
var/list/modules = list( // global associative list
"/obj/machinery/power/apc" = "card_reader,power_control,id_auth,cell_power,cell_charge")
/datum/module/New(var/obj/O)
var/type = O.type // the type of the creating object
var/mneed = mods.inmodlist(type) // find if this type has modules defined
if(!mneed) // not found in module list?
qdel(src) // delete self, thus ending proc
var/needed = mods.getbitmask(type) // get a bitmask for the number of modules in this object
status = needed
installed = needed
/datum/moduletypes/proc/addmod(type, modtextlist)
modules += type // index by type text
modules[type] = modtextlist
/datum/moduletypes/proc/inmodlist(type)
return ("[type]" in modules)
/datum/moduletypes/proc/getbitmask(type)
var/count = modcount["[type]"]
if(count)
return 2**count-1
var/modtext = modules["[type]"]
var/num = 1
var/pos = 1
while(1)
pos = findtext(modtext, ",", pos, 0)
if(!pos)
break
else
pos++
num++
modcount += "[type]"
modcount["[type]"] = num
return 2**num-1
+4
View File
@@ -70,6 +70,10 @@
cult_req = 1
charge_max = 4000
/obj/effect/proc_holder/spell/aoe_turf/conjure/soulstone/noncult
summon_type = list(/obj/item/device/soulstone/anybody)
/obj/effect/proc_holder/spell/aoe_turf/conjure/lesserforcewall
name = "Shield"
+1 -1
View File
@@ -6,7 +6,7 @@
range = -1
school = "conjuration"
charge_max = 300
charge_max = 750
clothes_req = 1
cooldown_min = 10 //Gun wizard
action_icon_state = "bolt_action"
+2 -1
View File
@@ -43,7 +43,7 @@ Also, you never added distance checking after target is selected. I've went ahea
user << "<span class='warning'>They appear to be catatonic! Not even magic can affect their vacant mind.</span>"
return
if(target.mind.special_role in protected_roles)
if((target.mind.special_role in protected_roles) || cmptext(copytext(target.key,1,2),"@"))
user << "<span class='warning'>Their mind is resisting your spell!</span>"
return
@@ -69,6 +69,7 @@ Also, you never added distance checking after target is selected. I've went ahea
ghost.mind.transfer_to(caster)
if(ghost.key)
caster.key = ghost.key //have to transfer the key since the mind was not active
qdel(ghost)
if(caster.mind.special_verbs.len)//If they had any special verbs, we add them here.
for(var/V in caster.mind.special_verbs)
File diff suppressed because it is too large Load Diff
+112 -157
View File
@@ -1,195 +1,150 @@
// Wires for airlocks
/datum/wires/airlock/secure
random = 1
/datum/wires/airlock
holder_type = /obj/machinery/door/airlock
wire_count = 12
window_y = 570
var/const/AIRLOCK_WIRE_IDSCAN = 1
var/const/AIRLOCK_WIRE_MAIN_POWER1 = 2
var/const/AIRLOCK_WIRE_MAIN_POWER2 = 4
var/const/AIRLOCK_WIRE_DOOR_BOLTS = 8
var/const/AIRLOCK_WIRE_BACKUP_POWER1 = 16
var/const/AIRLOCK_WIRE_BACKUP_POWER2 = 32
var/const/AIRLOCK_WIRE_OPEN_DOOR = 64
var/const/AIRLOCK_WIRE_AI_CONTROL = 128
var/const/AIRLOCK_WIRE_ELECTRIFY = 256
var/const/AIRLOCK_WIRE_SAFETY = 512
var/const/AIRLOCK_WIRE_SPEED = 1024
var/const/AIRLOCK_WIRE_LIGHT = 2048
/datum/wires/airlock/secure
randomize = TRUE
/datum/wires/airlock/CanUse(var/mob/living/L)
/datum/wires/airlock/New(atom/holder)
wires = list(
WIRE_POWER1, WIRE_POWER2,
WIRE_BACKUP1, WIRE_BACKUP2,
WIRE_OPEN, WIRE_BOLTS, WIRE_IDSCAN, WIRE_AI,
WIRE_SHOCK, WIRE_SAFETY, WIRE_TIMING, WIRE_LIGHT,
WIRE_ZAP1, WIRE_ZAP2
)
add_duds(2)
..()
/datum/wires/airlock/interactable(mob/user)
var/obj/machinery/door/airlock/A = holder
if(!istype(L, /mob/living/silicon))
if(A.isElectrified())
if(A.shock(L, 100))
return 0
if(!istype(user, /mob/living/silicon) && A.isElectrified() && A.shock(user, 100))
return FALSE
if(A.p_open)
return 1
return 0
return TRUE
/datum/wires/airlock/GetInteractWindow()
/datum/wires/airlock/get_status()
var/obj/machinery/door/airlock/A = holder
. += ..()
. += text("<br>\n[]<br>\n[]<br>\n[]<br>\n[]<br>\n[]<br>\n[]<br>\n[]", (A.locked ? "The door bolts have fallen!" : "The door bolts look up."),
(A.lights ? "The door bolt lights are on." : "The door bolt lights are off!"),
((A.hasPower()) ? "The test light is on." : "The test light is off!"),
((A.aiControlDisabled==0 && !A.emagged) ? "The 'AI control allowed' light is on." : "The 'AI control allowed' light is off."),
(A.safe==0 ? "The 'Check Wiring' light is on." : "The 'Check Wiring' light is off."),
(A.normalspeed==0 ? "The 'Check Timing Mechanism' light is on." : "The 'Check Timing Mechanism' light is off."),
(A.emergency==0 ? "The emergency lights are off." : "The emergency lights are on."))
/datum/wires/airlock/UpdateCut(var/index, var/mended)
var/list/status = list()
status += "The door bolts [A.locked ? "have fallen!" : "look up."]"
status += "The test light is [A.hasPower() ? "on" : "off"]."
status += "The AI connection light is [A.aiControlDisabled || A.emagged ? "off" : "on"]."
status += "The check wiring light is [A.safe ? "off" : "on"]."
status += "The timer is powered [A.autoclose ? "on" : "off"]."
status += "The speed light is [A.normalspeed ? "on" : "off"]."
status += "The emergency light is [A.emergency ? "on" : "off"]."
return status
/datum/wires/airlock/on_pulse(wire)
var/obj/machinery/door/airlock/A = holder
switch(index)
if(AIRLOCK_WIRE_MAIN_POWER1, AIRLOCK_WIRE_MAIN_POWER2)
if(!mended)
//Cutting either one disables the main door power, but unless backup power is also cut, the backup power re-powers the door in 10 seconds. While unpowered, the door may be crowbarred open, but bolts-raising will not work. Cutting these wires may electocute the user.
A.loseMainPower()
A.shock(usr, 50)
else
if((!IsIndexCut(AIRLOCK_WIRE_MAIN_POWER1)) && (!IsIndexCut(AIRLOCK_WIRE_MAIN_POWER2)))
A.regainMainPower()
A.shock(usr, 50)
if(AIRLOCK_WIRE_BACKUP_POWER1, AIRLOCK_WIRE_BACKUP_POWER2)
if(!mended)
//Cutting either one disables the backup door power (allowing it to be crowbarred open, but disabling bolts-raising), but may electocute the user.
A.loseBackupPower()
A.shock(usr, 50)
else
if((!IsIndexCut(AIRLOCK_WIRE_BACKUP_POWER1)) && (!IsIndexCut(AIRLOCK_WIRE_BACKUP_POWER2)))
A.regainBackupPower()
A.shock(usr, 50)
if(AIRLOCK_WIRE_DOOR_BOLTS)
if(!mended)
//Cutting this wire also drops the door bolts, and mending it does not raise them. (This is what happens now, except there are a lot more wires going to door bolts at present)
if(A.locked!=1)
A.locked = 1
A.update_icon()
if(AIRLOCK_WIRE_AI_CONTROL)
if(!mended)
//one wire for AI control. Cutting this prevents the AI from controlling the door unless it has hacked the door through the power connection (which takes about a minute). If both main and backup power are cut, as well as this wire, then the AI cannot operate or hack the door at all.
//aiControlDisabled: If 1, AI control is disabled until the AI hacks back in and disables the lock. If 2, the AI has bypassed the lock. If -1, the control is enabled but the AI had bypassed it earlier, so if it is disabled again the AI would have no trouble getting back in.
if(A.aiControlDisabled == 0)
A.aiControlDisabled = 1
else if(A.aiControlDisabled == -1)
A.aiControlDisabled = 2
else
if(A.aiControlDisabled == 1)
A.aiControlDisabled = 0
else if(A.aiControlDisabled == 2)
A.aiControlDisabled = -1
if(AIRLOCK_WIRE_ELECTRIFY)
if(!mended)
//Cutting this wire electrifies the door, so that the next person to touch the door without insulated gloves gets electrocuted.
if(A.secondsElectrified != -1)
A.shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])")
add_logs(usr, A, "electrified", addition="at [A.x],[A.y],[A.z]")
A.secondsElectrified = -1
else
if(A.secondsElectrified == -1)
A.secondsElectrified = 0
return // Don't update the dialog.
if (AIRLOCK_WIRE_SAFETY)
A.safe = mended
if(AIRLOCK_WIRE_SPEED)
A.autoclose = mended
if(mended)
if(!A.density)
switch(wire)
if(WIRE_POWER1, WIRE_POWER2) // Pulse to loose power.
A.loseMainPower()
if(WIRE_BACKUP1, WIRE_BACKUP2) // Pulse to loose backup power.
A.loseBackupPower()
if(WIRE_OPEN) // Pulse to open door (only works not emagged and ID wire is cut or no access is required).
if(A.emagged)
return
if(!A.requiresID() || A.check_access(null))
if(A.density)
A.open()
else
A.close()
if(AIRLOCK_WIRE_LIGHT)
A.lights = mended
if(WIRE_BOLTS) // Pulse to toggle bolts (but only raise if power is on).
if(!A.locked)
A.bolt()
A.audible_message("<span class='italics'>You hear a click from the bottom of the door.</span>", null, 1)
else
if(A.hasPower())
A.unbolt()
A.audible_message("<span class='italics'>You hear a click from the bottom of the door.</span>", null, 1)
A.update_icon()
/datum/wires/airlock/UpdatePulsed(index)
var/obj/machinery/door/airlock/A = holder
switch(index)
if(AIRLOCK_WIRE_IDSCAN)
//Sending a pulse through this disables emergency access and flashes the red light on the door (if the door has power).
if(WIRE_IDSCAN) // Pulse to disable emergency access and flash red lights.
if(A.hasPower() && A.density)
A.do_animate("deny")
if(A.emergency)
A.emergency = 0
A.emergency = FALSE
A.update_icon()
if(AIRLOCK_WIRE_MAIN_POWER1 || AIRLOCK_WIRE_MAIN_POWER2)
//Sending a pulse through either one causes a breaker to trip, disabling the door for 10 seconds if backup power is connected, or 1 minute if not (or until backup power comes back on, whichever is shorter).
A.loseMainPower()
if(AIRLOCK_WIRE_DOOR_BOLTS)
//one wire for door bolts. Sending a pulse through this drops door bolts if they're not down (whether power's on or not),
//raises them if they are down (only if power's on)
if(!A.locked)
A.locked = 1
A.audible_message("<span class='italics'>You hear a click from the bottom of the door.</span>", null, 1)
else
if(A.hasPower()) //only can raise bolts if power's on
A.locked = 0
A.audible_message("<span class='italics'>You hear a click from the bottom of the door.</span>", null, 1)
A.update_icon()
if(AIRLOCK_WIRE_BACKUP_POWER1 || AIRLOCK_WIRE_BACKUP_POWER2)
//two wires for backup power. Sending a pulse through either one causes a breaker to trip, but this does not disable it unless main power is down too (in which case it is disabled for 1 minute or however long it takes main power to come back, whichever is shorter).
A.loseBackupPower()
if(AIRLOCK_WIRE_AI_CONTROL)
if(WIRE_AI) // Pulse to disable WIRE_AI control for 10 ticks (follows same rules as cutting).
if(A.aiControlDisabled == 0)
A.aiControlDisabled = 1
else if(A.aiControlDisabled == -1)
A.aiControlDisabled = 2
spawn(10)
if(A)
if(A.aiControlDisabled == 1)
A.aiControlDisabled = 0
else if(A.aiControlDisabled == 2)
A.aiControlDisabled = -1
if(AIRLOCK_WIRE_ELECTRIFY)
//one wire for electrifying the door. Sending a pulse through this electrifies the door for 30 seconds.
if(A.secondsElectrified==0)
if(WIRE_SHOCK) // Pulse to shock the door for 10 ticks.
if(!A.secondsElectrified)
A.secondsElectrified = 30
A.shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])")
add_logs(usr, A, "electrified", addition="at [A.x],[A.y],[A.z]")
A.secondsElectrified = 30
spawn(10)
if(A)
//TODO: Move this into process() and make pulsing reset secondsElectrified to 30
while (A.secondsElectrified>0)
A.secondsElectrified-=1
if(A.secondsElectrified<0)
while (A.secondsElectrified > 0)
A.secondsElectrified -= 1
if(A.secondsElectrified < 0)
A.secondsElectrified = 0
sleep(10)
return
if(AIRLOCK_WIRE_OPEN_DOOR)
//tries to open the door without ID
//will succeed only if the ID wire is cut or the door requires no access and it's not emagged
if(A.emagged) return
if(!A.requiresID() || A.check_access(null))
if(A.density) A.open()
else A.close()
if(AIRLOCK_WIRE_SAFETY)
if(WIRE_SAFETY)
A.safe = !A.safe
if(!A.density)
A.close()
if(AIRLOCK_WIRE_SPEED)
if(WIRE_TIMING)
A.normalspeed = !A.normalspeed
if(AIRLOCK_WIRE_LIGHT)
if(WIRE_LIGHT)
A.lights = !A.lights
A.update_icon()
/datum/wires/airlock/on_cut(wire, mend)
var/obj/machinery/door/airlock/A = holder
switch(wire)
if(WIRE_POWER1, WIRE_POWER2) // Cut to loose power, repair all to gain power.
if(mend && !is_cut(WIRE_POWER1) && !is_cut(WIRE_POWER2))
A.regainMainPower()
A.shock(usr, 50)
else
A.loseMainPower()
A.shock(usr, 50)
if(WIRE_BACKUP1, WIRE_BACKUP2) // Cut to loose backup power, repair all to gain backup power.
if(mend && !is_cut(WIRE_BACKUP1) && !is_cut(WIRE_BACKUP2))
A.regainBackupPower()
A.shock(usr, 50)
else
A.loseBackupPower()
A.shock(usr, 50)
if(WIRE_BOLTS) // Cut to drop bolts, mend does nothing.
if(!mend)
A.bolt()
if(WIRE_AI) // Cut to disable WIRE_AI control, mend to re-enable.
if(mend)
if(A.aiControlDisabled == 1) // 0 = normal, 1 = locked out, 2 = overridden by WIRE_AI, -1 = previously overridden by WIRE_AI
A.aiControlDisabled = 0
else if(A.aiControlDisabled == 2)
A.aiControlDisabled = -1
else
if(A.aiControlDisabled == 0)
A.aiControlDisabled = 1
else if(A.aiControlDisabled == -1)
A.aiControlDisabled = 2
if(WIRE_SHOCK) // Cut to shock the door, mend to unshock.
if(mend)
if(A.secondsElectrified)
A.secondsElectrified = 0
else
if(A.secondsElectrified != -1)
A.secondsElectrified = -1
A.shockedby += text("\[[time_stamp()]\][usr](ckey:[usr.ckey])")
add_logs(usr, A, "electrified", addition="at [A.x],[A.y],[A.z]")
if(WIRE_SAFETY) // Cut to disable safeties, mend to re-enable.
A.safe = mend
if(WIRE_TIMING) // Cut to disable auto-close, mend to re-enable.
A.autoclose = mend
if(A.autoclose && !A.density)
A.close()
if(WIRE_LIGHT) // Cut to disable lights, mend to re-enable.
A.lights = mend
A.update_icon()
if(WIRE_ZAP1, WIRE_ZAP2) // Ouch.
A.shock(usr, 50)
+54 -72
View File
@@ -1,93 +1,75 @@
/datum/wires/alarm
holder_type = /obj/machinery/alarm
wire_count = 5
var/const/AALARM_WIRE_IDSCAN = 1
var/const/AALARM_WIRE_POWER = 2
var/const/AALARM_WIRE_SYPHON = 4
var/const/AALARM_WIRE_AI_CONTROL = 8
var/const/AALARM_WIRE_AALARM = 16
/datum/wires/alarm/New(atom/holder)
wires = list(
WIRE_POWER,
WIRE_IDSCAN, WIRE_AI,
WIRE_PANIC, WIRE_ALARM
)
add_duds(3)
..()
/datum/wires/alarm/CanUse(mob/living/L)
/datum/wires/alarm/interactable(mob/user)
var/obj/machinery/alarm/A = holder
if(A.panel_open && A.buildstage == 2)
return 1
return 0
return TRUE
/datum/wires/alarm/GetInteractWindow()
/datum/wires/alarm/get_status()
var/obj/machinery/alarm/A = holder
. += ..()
. += text("<br>\n[(A.locked ? "The Air Alarm is locked." : "The Air Alarm is unlocked.")]<br>\n[((A.shorted || (A.stat & (NOPOWER|BROKEN))) ? "The Air Alarm is offline." : "The Air Alarm is working properly!")]<br>\n[(A.aidisabled ? "The 'AI control allowed' light is off." : "The 'AI control allowed' light is on.")]")
var/list/status = list()
status += "The interface light is [A.locked ? "red" : "green"]."
status += "The short indicator is [A.shorted ? "lit" : "off"]."
status += "The AI connection light is [!A.aidisabled ? "on" : "off"]."
return status
/datum/wires/alarm/UpdateCut(index, mended)
/datum/wires/alarm/on_pulse(wire)
var/obj/machinery/alarm/A = holder
switch(index)
if(AALARM_WIRE_IDSCAN)
if(!mended)
A.locked = 1
//world << "Idscan wire cut"
if(AALARM_WIRE_POWER)
A.shock(usr, 50)
A.shorted = !mended
A.update_icon()
//world << "Power wire cut"
if (AALARM_WIRE_AI_CONTROL)
if (A.aidisabled == !mended)
A.aidisabled = mended
//world << "AI Control Wire Cut"
if(AALARM_WIRE_SYPHON)
if(!mended)
A.mode = 3 // AALARM_MODE_PANIC
A.apply_mode()
//world << "Syphon Wire Cut"
if(AALARM_WIRE_AALARM)
if (A.alarm_area.atmosalert(2,holder))
A.post_alert(2)
A.update_icon()
/datum/wires/alarm/UpdatePulsed(index)
var/obj/machinery/alarm/A = holder
switch(index)
if(AALARM_WIRE_IDSCAN)
A.locked = !A.locked
// world << "Idscan wire pulsed"
if (AALARM_WIRE_POWER)
// world << "Power wire pulsed"
if(A.shorted == 0)
A.shorted = 1
switch(wire)
if(WIRE_POWER) // Short out for a long time.
if(!A.shorted)
A.shorted = TRUE
A.update_icon()
spawn(12000)
if(A.shorted == 1)
A.shorted = 0
if(A.shorted)
A.shorted = FALSE
A.update_icon()
if (AALARM_WIRE_AI_CONTROL)
// world << "AI Control wire pulsed"
if (A.aidisabled == 0)
A.aidisabled = 1
A.updateDialog()
if(WIRE_IDSCAN) // Toggle lock.
A.locked = !A.locked
if(WIRE_AI) // Disable AI control for a while.
if(!A.aidisabled)
A.aidisabled = TRUE
spawn(100)
if (A.aidisabled == 1)
A.aidisabled = 0
if(AALARM_WIRE_SYPHON)
// world << "Syphon wire pulsed"
if(A.aidisabled)
A.aidisabled = FALSE
if(WIRE_PANIC) // Toggle panic siphon.
if(A.mode == 1) // AALARM_MODE_SCRUB
A.mode = 3 // AALARM_MODE_PANIC
else
A.mode = 1 // AALARM_MODE_SCRUB
A.apply_mode()
if(AALARM_WIRE_AALARM)
// world << "Aalarm wire pulsed"
if (A.alarm_area.atmosalert(0,holder))
if(WIRE_ALARM) // Clear alarms.
if(A.alarm_area.atmosalert(0, holder))
A.post_alert(0)
A.update_icon()
/datum/wires/alarm/on_cut(wire, mend)
var/obj/machinery/alarm/A = holder
switch(wire)
if(WIRE_POWER) // Short out forever.
A.shock(usr, 50)
A.shorted = !mend
A.update_icon()
if(WIRE_IDSCAN)
if(!mend)
A.locked = TRUE
if(WIRE_AI)
A.aidisabled = mend // Enable/disable AI control.
if(WIRE_PANIC) // Force panic syphon on.
if(!mend)
A.mode = 3 // AALARM_MODE_PANIC
A.apply_mode()
if(WIRE_ALARM) // Post alarm.
if(A.alarm_area.atmosalert(2, holder))
A.post_alert(2)
A.update_icon()
+40 -64
View File
@@ -1,78 +1,54 @@
/datum/wires/apc
holder_type = /obj/machinery/power/apc
wire_count = 4
var/const/APC_WIRE_IDSCAN = 1
var/const/APC_WIRE_MAIN_POWER1 = 2
var/const/APC_WIRE_MAIN_POWER2 = 4
var/const/APC_WIRE_AI_CONTROL = 8
/datum/wires/apc/New(atom/holder)
wires = list(
WIRE_POWER1, WIRE_POWER2,
WIRE_IDSCAN, WIRE_AI
)
add_duds(6)
..()
/datum/wires/apc/GetInteractWindow()
var/obj/machinery/power/apc/A = holder
. += ..()
. += text("<br>\n[(A.locked ? "The APC is locked." : "The APC is unlocked.")]<br>\n[(A.shorted ? "The APCs power has been shorted." : "The APC is working properly!")]<br>\n[(A.aidisabled ? "The 'AI control allowed' light is off." : "The 'AI control allowed' light is on.")]")
/datum/wires/apc/CanUse(mob/living/L)
/datum/wires/apc/interactable(mob/user)
var/obj/machinery/power/apc/A = holder
if(A.wiresexposed)
return 1
return 0
/datum/wires/apc/UpdatePulsed(index)
return TRUE
/datum/wires/apc/get_status()
var/obj/machinery/power/apc/A = holder
var/list/status = list()
status += "The interface light is [A.locked ? "red" : "green"]."
status += "The short indicator is [A.shorted ? "lit" : "off"]."
status += "The AI connection light is [!A.aidisabled ? "on" : "off"]."
return status
switch(index)
if(APC_WIRE_IDSCAN)
A.locked = 0
spawn(300)
if(A)
A.locked = 1
A.updateDialog()
if (APC_WIRE_MAIN_POWER1, APC_WIRE_MAIN_POWER2)
if(A.shorted == 0)
A.shorted = 1
spawn(1200)
if(A && !IsIndexCut(APC_WIRE_MAIN_POWER1) && !IsIndexCut(APC_WIRE_MAIN_POWER2))
A.shorted = 0
A.updateDialog()
if (APC_WIRE_AI_CONTROL)
if (A.aidisabled == 0)
A.aidisabled = 1
spawn(10)
if(A && !IsIndexCut(APC_WIRE_AI_CONTROL))
A.aidisabled = 0
A.updateDialog()
A.updateDialog()
/datum/wires/apc/UpdateCut(index, mended)
/datum/wires/apc/on_pulse(wire)
var/obj/machinery/power/apc/A = holder
switch(wire)
if(WIRE_POWER1, WIRE_POWER2) // Short for a long while.
if(!A.shorted)
A.shorted = TRUE
addtimer(A, "reset", 1200, FALSE, wire)
if(WIRE_IDSCAN) // Unlock for a little while.
A.locked = FALSE
addtimer(A, "reset", 300, FALSE, wire)
if(WIRE_AI) // Disable AI control for a very short time.
if(!A.aidisabled)
A.aidisabled = TRUE
addtimer(A, "reset", 10, FALSE, wire)
/datum/wires/apc/on_cut(index, mend)
var/obj/machinery/power/apc/A = holder
switch(index)
if(APC_WIRE_MAIN_POWER1, APC_WIRE_MAIN_POWER2)
if(!mended)
if(WIRE_POWER1, WIRE_POWER2) // Short out.
if(mend && !is_cut(WIRE_POWER1) && !is_cut(WIRE_POWER2))
A.shorted = FALSE
A.shock(usr, 50)
A.shorted = 1
else if(!IsIndexCut(APC_WIRE_MAIN_POWER1) && !IsIndexCut(APC_WIRE_MAIN_POWER2))
A.shorted = 0
A.shock(usr, 50)
if(APC_WIRE_AI_CONTROL)
if(!mended)
if (A.aidisabled == 0)
A.aidisabled = 1
else
if (A.aidisabled == 1)
A.aidisabled = 0
A.updateDialog()
A.shorted = TRUE
A.shock(usr, 50)
if(WIRE_AI) // Disable AI control.
if(mend)
A.aidisabled = FALSE
else
A.aidisabled = TRUE
+34 -46
View File
@@ -1,59 +1,47 @@
/datum/wires/autolathe
holder_type = /obj/machinery/autolathe
wire_count = 10
var/const/AUTOLATHE_HACK_WIRE = 1
var/const/AUTOLATHE_SHOCK_WIRE = 2
var/const/AUTOLATHE_DISABLE_WIRE = 4
/datum/wires/autolathe/New(atom/holder)
wires = list(
WIRE_HACK, WIRE_DISABLE,
WIRE_SHOCK, WIRE_ZAP
)
add_duds(6)
..()
/datum/wires/autolathe/GetInteractWindow()
var/obj/machinery/autolathe/A = holder
. += ..()
. += text("<BR>The red light is [A.disabled ? "off" : "on"].<BR>The green light is [A.shocked ? "off" : "on"].<BR>The blue light is [A.hacked ? "off" : "on"].<BR>")
/datum/wires/autolathe/CanUse()
/datum/wires/autolathe/interactable(mob/user)
var/obj/machinery/autolathe/A = holder
if(A.panel_open)
return 1
return 0
return TRUE
/datum/wires/autolathe/Interact(mob/living/user)
if(CanUse(user))
var/obj/machinery/autolathe/V = holder
V.attack_hand(user)
/datum/wires/autolathe/UpdateCut(index, mended)
/datum/wires/autolathe/get_status()
var/obj/machinery/autolathe/A = holder
switch(index)
if(AUTOLATHE_HACK_WIRE)
if(!A.hacked)
A.adjust_hacked(1)
if(AUTOLATHE_SHOCK_WIRE)
A.shocked = !mended
if(AUTOLATHE_DISABLE_WIRE)
A.disabled = !mended
var/list/status = list()
status += "The red light is [A.disabled ? "on" : "off"]."
status += "The blue light is [A.hacked ? "on" : "off"]."
return status
/datum/wires/autolathe/UpdatePulsed(index)
if(IsIndexCut(index))
return
/datum/wires/autolathe/on_pulse(wire)
var/obj/machinery/autolathe/A = holder
switch(index)
if(AUTOLATHE_HACK_WIRE)
switch(wire)
if(WIRE_HACK)
A.adjust_hacked(!A.hacked)
spawn(50)
if(A && !IsIndexCut(index))
A.adjust_hacked(0)
Interact(usr)
if(AUTOLATHE_SHOCK_WIRE)
addtimer(A, "reset", 60, FALSE, wire)
if(WIRE_SHOCK)
A.shocked = !A.shocked
spawn(50)
if(A && !IsIndexCut(index))
A.shocked = 0
Interact(usr)
if(AUTOLATHE_DISABLE_WIRE)
addtimer(A, "reset", 60, FALSE, wire)
if(WIRE_DISABLE)
A.disabled = !A.disabled
spawn(50)
if(A && !IsIndexCut(index))
A.disabled = 0
Interact(usr)
addtimer(A, "reset", 60, FALSE, wire)
/datum/wires/autolathe/on_cut(wire, mend)
var/obj/machinery/autolathe/A = holder
switch(wire)
if(WIRE_HACK)
A.adjust_hacked(!mend)
if(WIRE_HACK)
A.shocked = !mend
if(WIRE_DISABLE)
A.disabled = !mend
if(WIRE_ZAP)
A.shock(usr, 50)
+55 -22
View File
@@ -1,46 +1,79 @@
/datum/wires/explosive
wire_count = 1
/datum/wires/explosive/New(atom/holder)
add_duds(2) // In this case duds actually explode.
..()
var/const/WIRE_EXPLODE = 1
/datum/wires/explosive/on_pulse(index)
explode()
/datum/wires/explosive/on_cut(index, mend)
explode()
/datum/wires/explosive/proc/explode()
return
/datum/wires/explosive/UpdatePulsed(index)
switch(index)
if(WIRE_EXPLODE)
explode()
/datum/wires/explosive/UpdateCut(index, mended)
switch(index)
if(WIRE_EXPLODE)
if(!mended)
explode()
/datum/wires/explosive/c4
holder_type = /obj/item/weapon/c4
/datum/wires/explosive/c4/CanUse(mob/living/L)
/datum/wires/explosive/c4/interactable(mob/user)
var/obj/item/weapon/c4/P = holder
if(P.open_panel)
return 1
return 0
return TRUE
/datum/wires/explosive/c4/explode()
var/obj/item/weapon/c4/P = holder
P.explode()
/datum/wires/explosive/pizza
holder_type = /obj/item/pizzabox
randomize = TRUE
/datum/wires/explosive/pizza/New(atom/holder)
wires = list(
WIRE_DISARM
)
add_duds(3) // Duds also explode here.
..()
/datum/wires/explosive/pizza/interactable(mob/user)
var/obj/item/pizzabox/P = holder
if(P.open && P.bomb)
return TRUE
/datum/wires/explosive/pizza/get_status()
var/obj/item/pizzabox/P = holder
var/list/status = list()
status += "The red light is [P.bomb_active ? "on" : "off"]."
status += "The green light is [P.bomb_defused ? "on": "off"]."
return status
/datum/wires/explosive/pizza/on_pulse(wire)
var/obj/item/pizzabox/P = holder
switch(wire)
if(WIRE_DISARM) // Pulse to toggle
P.bomb_defused = !P.bomb_defused
else // Boom
explode()
/datum/wires/explosive/pizza/on_cut(wire, mend)
var/obj/item/pizzabox/P = holder
switch(wire)
if(WIRE_DISARM) // Disarm and untrap the box.
if(!mend)
P.bomb_defused = TRUE
else
if(!mend && !P.bomb_defused)
explode()
/datum/wires/explosive/pizza/explode()
var/obj/item/pizzabox/P = holder
P.bomb.detonate()
/datum/wires/explosive/gibtonite
holder_type = /obj/item/weapon/twohanded/required/gibtonite
/datum/wires/explosive/gibtonite/CanUse(mob/living/L)
return 1
/datum/wires/explosive/gibtonite/UpdateCut(index, mended)
return
/datum/wires/explosive/gibtonite/explode()
var/obj/item/weapon/twohanded/required/gibtonite/P = holder
P.GibtoniteReaction(null, 2)
+19 -53
View File
@@ -1,65 +1,31 @@
/datum/wires/mulebot
random = 1
holder_type = /mob/living/simple_animal/bot/mulebot
wire_count = 10
randomize = TRUE
var/const/WIRE_POWER1 = 1 // power connections
var/const/WIRE_POWER2 = 2
var/const/WIRE_AVOIDANCE = 4 // mob avoidance
var/const/WIRE_LOADCHECK = 8 // load checking (non-crate)
var/const/WIRE_MOTOR1 = 16 // motor wires
var/const/WIRE_MOTOR2 = 32 //
var/const/WIRE_REMOTE_RX = 64 // remote recv functions
var/const/WIRE_REMOTE_TX = 128 // remote trans status
var/const/WIRE_BEACON_RX = 256 // beacon ping recv
/datum/wires/mulebot/New(atom/holder)
wires = list(
WIRE_POWER1, WIRE_POWER2,
WIRE_AVOIDANCE, WIRE_LOADCHECK,
WIRE_MOTOR1, WIRE_MOTOR2,
WIRE_RX, WIRE_TX, WIRE_BEACON
)
..()
/datum/wires/mulebot/CanUse(mob/living/L)
/datum/wires/mulebot/interactable(mob/user)
var/mob/living/simple_animal/bot/mulebot/M = holder
if(M.open)
return 1
return 0
return TRUE
// So the wires do not open a new window, handle the interaction ourselves.
/datum/wires/mulebot/Interact(mob/living/user)
if(CanUse(user))
var/mob/living/simple_animal/bot/mulebot/M = holder
M.update_controls()
/datum/wires/mulebot/UpdatePulsed(index)
switch(index)
/datum/wires/mulebot/on_pulse(wire)
var/mob/living/simple_animal/bot/mulebot/M = holder
switch(wire)
if(WIRE_POWER1, WIRE_POWER2)
holder.visible_message("<span class='notice'>\icon[holder] The charge light flickers.</span>")
holder.visible_message("<span class='notice'>\icon[M] The charge light flickers.</span>")
if(WIRE_AVOIDANCE)
holder.visible_message("<span class='notice'>\icon[holder] The external warning lights flash briefly.</span>")
holder.visible_message("<span class='notice'>\icon[M] The external warning lights flash briefly.</span>")
if(WIRE_LOADCHECK)
holder.visible_message("<span class='notice'>\icon[holder] The load platform clunks.</span>")
holder.visible_message("<span class='notice'>\icon[M] The load platform clunks.</span>")
if(WIRE_MOTOR1, WIRE_MOTOR2)
holder.visible_message("<span class='notice'>\icon[holder] The drive motor whines briefly.</span>")
holder.visible_message("<span class='notice'>\icon[M] The drive motor whines briefly.</span>")
else
holder.visible_message("<span class='notice'>\icon[holder] You hear a radio crackle.</span>")
// HELPER PROCS
/datum/wires/mulebot/proc/Motor1()
return !(wires_status & WIRE_MOTOR1)
/datum/wires/mulebot/proc/Motor2()
return !(wires_status & WIRE_MOTOR2)
/datum/wires/mulebot/proc/HasPower()
return !(wires_status & WIRE_POWER1) && !(wires_status & WIRE_POWER2)
/datum/wires/mulebot/proc/LoadCheck()
return !(wires_status & WIRE_LOADCHECK)
/datum/wires/mulebot/proc/MobAvoid()
return !(wires_status & WIRE_AVOIDANCE)
/datum/wires/mulebot/proc/RemoteTX()
return !(wires_status & WIRE_REMOTE_TX)
/datum/wires/mulebot/proc/RemoteRX()
return !(wires_status & WIRE_REMOTE_RX)
/datum/wires/mulebot/proc/BeaconRX()
return !(wires_status & WIRE_BEACON_RX)
holder.visible_message("<span class='notice'>\icon[M] You hear a radio crackle.</span>")
+26 -34
View File
@@ -1,52 +1,44 @@
/datum/wires/particle_acc/control_box
wire_count = 5
/datum/wires/particle_accelerator/control_box
holder_type = /obj/machinery/particle_accelerator/control_box
var/const/PARTICLE_TOGGLE_WIRE = 1 // Toggles whether the PA is on or not.
var/const/PARTICLE_STRENGTH_WIRE = 2 // Determines the strength of the PA.
var/const/PARTICLE_INTERFACE_WIRE = 4 // Determines the interface showing up.
var/const/PARTICLE_LIMIT_POWER_WIRE = 8 // Determines how strong the PA can be.
//var/const/PARTICLE_NOTHING_WIRE = 16 // Blank wire
/datum/wires/particle_accelerator/control_box/New(atom/holder)
wires = list(
WIRE_POWER, WIRE_STRENGTH, WIRE_LIMIT,
WIRE_INTERFACE
)
add_duds(2)
..()
/datum/wires/particle_acc/control_box/CanUse(mob/living/L)
/datum/wires/particle_accelerator/control_box/interactable(mob/user)
var/obj/machinery/particle_accelerator/control_box/C = holder
if(C.construction_state == 2)
return 1
return 0
return TRUE
/datum/wires/particle_acc/control_box/UpdatePulsed(index)
/datum/wires/particle_accelerator/control_box/on_pulse(wire)
var/obj/machinery/particle_accelerator/control_box/C = holder
switch(index)
if(PARTICLE_TOGGLE_WIRE)
switch(wire)
if(WIRE_POWER)
C.toggle_power()
if(PARTICLE_STRENGTH_WIRE)
if(WIRE_STRENGTH)
C.add_strength()
if(PARTICLE_INTERFACE_WIRE)
if(WIRE_INTERFACE)
C.interface_control = !C.interface_control
if(PARTICLE_LIMIT_POWER_WIRE)
if(WIRE_LIMIT)
C.visible_message("\icon[C]<b>[C]</b> makes a large whirring noise.")
/datum/wires/particle_acc/control_box/UpdateCut(index, mended)
/datum/wires/particle_accelerator/control_box/on_cut(wire, mend)
var/obj/machinery/particle_accelerator/control_box/C = holder
switch(index)
if(PARTICLE_TOGGLE_WIRE)
if(C.active == !mended)
switch(wire)
if(WIRE_POWER)
if(C.active == !mend)
C.toggle_power()
if(PARTICLE_STRENGTH_WIRE)
if(WIRE_STRENGTH)
for(var/i = 1; i < 3; i++)
C.remove_strength()
if(PARTICLE_INTERFACE_WIRE)
C.interface_control = mended
if(PARTICLE_LIMIT_POWER_WIRE)
C.strength_upper_limit = (mended ? 2 : 3)
if(WIRE_INTERFACE)
if(!mend)
C.interface_control = FALSE
if(WIRE_LIMIT)
C.strength_upper_limit = (mend ? 2 : 3)
if(C.strength_upper_limit < C.strength)
C.remove_strength()
-46
View File
@@ -1,46 +0,0 @@
/datum/wires/pizza_bomb
random = 1
holder_type = /obj/item/device/pizza_bomb
wire_count = 4
var/const/PIZZA_WIRE_DISARM = 1 // No boom
/datum/wires/pizza_bomb/UpdatePulsed(index)
var/obj/item/device/pizza_bomb/P = holder
switch(index)
if(PIZZA_WIRE_DISARM)
var/was_primed = P.primed
P.disarm()
if(was_primed)
spawn(100) //Rearm after a short time
if(P)
P.arm()
else
if(!P.disarmed)
message_admins("a pizza bomb at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[P.loc.x];Y=[P.loc.y];Z=[P.loc.z]'>(JMP)</a> armed by [key_name_admin(P.armer)] has exploded via wire pulsing.")
log_game("a pizza bomb ([P.loc.x],[P.loc.y],[P.loc.z]) armed by [key_name(P.armer)] has exploded via wire pulsing.")
P.go_boom()
/datum/wires/pizza_bomb/UpdateCut(index,mended)
var/obj/item/device/pizza_bomb/P = holder
switch(index)
if(PIZZA_WIRE_DISARM)
if(mended)
P.disarmed = 0
else
P.disarm()
else
if(!mended && !P.disarmed)
message_admins("a pizza bomb at <A HREF='?_src_=holder;adminplayerobservecoodjump=1;X=[P.loc.x];Y=[P.loc.y];Z=[P.loc.z]'>(JMP)</a> armed by [key_name_admin(P.armer)] has exploded via wire pulsing.")
log_game("a pizza bomb ([P.loc.x],[P.loc.y],[P.loc.z]) armed by [key_name(P.armer)] has exploded via wire pulsing.")
P.go_boom()
/datum/wires/pizza_bomb/GetInteractWindow()
. = ..()
var/obj/item/device/pizza_bomb/P = holder
. += text("<br>The red light is [P.primed ? "on" : "off"].<br>")
. += text("The green light is [P.disarmed ? "on": "off"].<br>")
+33 -37
View File
@@ -1,51 +1,47 @@
/datum/wires/r_n_d
random = 1
holder_type = /obj/machinery/r_n_d
wire_count = 6
randomize = TRUE
var/const/RD_WIRE_HACK = 1 // Hacks the r_n_d machine
var/const/RD_WIRE_SHOCK = 2 // Shocks the user, 50% chance
var/const/RD_WIRE_DISABLE = 4 // Disables the machine
/datum/wires/r_n_d/New(atom/holder)
wires = list(
WIRE_HACK, WIRE_DISABLE,
WIRE_SHOCK
)
add_duds(5)
..()
/datum/wires/r_n_d/CanUse(mob/living/L)
/datum/wires/r_n_d/interactable(mob/user)
var/obj/machinery/r_n_d/R = holder
if(R.panel_open)
return 1
return 0
return TRUE
/datum/wires/r_n_d/UpdatePulsed(index)
/datum/wires/r_n_d/get_status()
var/obj/machinery/r_n_d/R = holder
switch(index)
if(RD_WIRE_HACK)
var/list/status = list()
status += "The red light is [R.disabled ? "off" : "on"]."
status += "The green light is [R.shocked ? "off" : "on"]."
status += "The blue light is [R.hacked ? "off" : "on"]."
return status
/datum/wires/r_n_d/on_pulse(wire)
var/obj/machinery/r_n_d/R = holder
switch(wire)
if(WIRE_HACK)
R.hacked = !R.hacked
if(RD_WIRE_DISABLE)
if(WIRE_DISABLE)
R.disabled = !R.disabled
if(RD_WIRE_SHOCK)
var/Rshock = R.shocked
R.shocked = !R.shocked
if(WIRE_SHOCK)
R.shocked = TRUE
spawn(100)
if(R)
R.shocked = Rshock
R.shocked = FALSE
/datum/wires/r_n_d/UpdateCut(index,mended)
/datum/wires/r_n_d/on_cut(wire, mend)
var/obj/machinery/r_n_d/R = holder
switch(index)
if(RD_WIRE_HACK)
R.hacked = !mended
if(RD_WIRE_DISABLE)
R.disabled = !mended
if(RD_WIRE_SHOCK)
R.shocked = !mended
/datum/wires/r_n_d/GetInteractWindow()
. = ..()
var/obj/machinery/r_n_d/R = holder
. += text("<br>The red light is [R.disabled ? "off" : "on"].<br>")
. += text("The green light is [R.shocked ? "off" : "on"].<br>")
. += text("The blue light is [R.hacked ? "off" : "on"].<br>")
switch(wire)
if(WIRE_HACK)
R.hacked = !mend
if(WIRE_DISABLE)
R.disabled = !mend
if(WIRE_SHOCK)
R.shocked = !mend
+12 -18
View File
@@ -1,31 +1,25 @@
/datum/wires/radio
holder_type = /obj/item/device/radio
wire_count = 3
var/const/WIRE_SIGNAL = 1
var/const/WIRE_RECEIVE = 2
var/const/WIRE_TRANSMIT = 4
/datum/wires/radio/New(atom/holder)
wires = list(
WIRE_SIGNAL,
WIRE_RX, WIRE_TX
)
..()
/datum/wires/radio/CanUse(mob/living/L)
/datum/wires/radio/interactable(mob/user)
var/obj/item/device/radio/R = holder
if(R.b_stat)
return 1
return 0
return TRUE
/datum/wires/radio/Interact(mob/living/user)
if(CanUse(user))
var/obj/item/device/radio/R = holder
R.interact(user)
/datum/wires/radio/UpdatePulsed(index)
/datum/wires/radio/on_pulse(index)
var/obj/item/device/radio/R = holder
switch(index)
if(WIRE_SIGNAL)
R.listening = !R.listening
R.broadcasting = R.listening
if(WIRE_RECEIVE)
if(WIRE_RX)
R.listening = !R.listening
if(WIRE_TRANSMIT)
R.broadcasting = !R.broadcasting
if(WIRE_TX)
R.broadcasting = !R.broadcasting
+50 -86
View File
@@ -1,102 +1,66 @@
/datum/wires/robot
random = 1
holder_type = /mob/living/silicon/robot
wire_count = 5
randomize = TRUE
var/const/BORG_WIRE_LAWCHECK = 1
var/const/BORG_WIRE_MAIN_POWER = 2 // The power wires do nothing whyyyyyyyyyyyyy
var/const/BORG_WIRE_LOCKED_DOWN = 4
var/const/BORG_WIRE_AI_CONTROL = 8
var/const/BORG_WIRE_CAMERA = 16
/datum/wires/robot/New(atom/holder)
wires = list(
WIRE_AI, WIRE_CAMERA,
WIRE_LAWSYNC, WIRE_LOCKDOWN
)
add_duds(2)
..()
/datum/wires/robot/GetInteractWindow()
. = ..()
/datum/wires/robot/interactable(mob/user)
var/mob/living/silicon/robot/R = holder
. += text("<br>\n[(R.lawupdate ? "The LawSync light is on." : "The LawSync light is off.")]<br>\n[(R.connected_ai ? "The AI link light is on." : "The AI link light is off.")]")
. += text("<br>\n[((!isnull(R.camera) && R.camera.status == 1) ? "The Camera light is on." : "The Camera light is off.")]<br>\n")
. += text("<br>\n[(R.lockcharge ? "The lockdown light is on." : "The lockdown light is off.")]")
return .
/datum/wires/robot/UpdateCut(index, mended)
if(R.wiresexposed)
return TRUE
/datum/wires/robot/get_status()
var/mob/living/silicon/robot/R = holder
switch(index)
if(BORG_WIRE_LAWCHECK) //Cut the law wire, and the borg will no longer receive law updates from its AI
if(!mended)
if (R.lawupdate == 1)
R << "LawSync protocol engaged."
R.show_laws()
else
if (R.lawupdate == 0 && !R.emagged)
R.lawupdate = 1
if (BORG_WIRE_AI_CONTROL) //Cut the AI wire to reset AI control
if(!mended)
if (R.connected_ai)
R.connected_ai = null
if (BORG_WIRE_CAMERA)
if(!isnull(R.camera) && !R.scrambledcodes)
R.camera.status = mended
R.camera.deactivate(usr, 0) // Will kick anyone who is watching the Cyborg's camera.
if(BORG_WIRE_LAWCHECK) //Forces a law update if the borg is set to receive them. Since an update would happen when the borg checks its laws anyway, not much use, but eh
if (R.lawupdate)
R.lawsync()
if(BORG_WIRE_LOCKED_DOWN)
R.SetLockdown(!mended)
/datum/wires/robot/UpdatePulsed(index)
var/list/status = list()
status += "The law sync module is [R.lawupdate ? "on" : "off"]."
status += "The intelligence link display shows [R.connected_ai ? R.connected_ai.name : "NULL"]."
status += "The camera light is [!isnull(R.camera) && R.camera.status ? "on" : "off"]."
status += "The lockdown indicator is [R.lockcharge ? "on" : "off"]."
return status
/datum/wires/robot/on_pulse(wire)
var/mob/living/silicon/robot/R = holder
switch(index)
if (BORG_WIRE_AI_CONTROL) //pulse the AI wire to make the borg reselect an AI
switch(wire)
if(WIRE_AI) // Pulse to pick a new AI.
if(!R.emagged)
var/new_ai = select_active_ai(R)
if(new_ai && (new_ai != R.connected_ai))
R.connected_ai = new_ai
R.notify_ai(1)
var/numberer = 1 // Send images the Cyborg has taken to the AI's album upon sync.
for(var/datum/picture/z in R.aicamera.aipictures)
if(R.connected_ai.aicamera.aipictures.len == 0)
var/datum/picture/p = new/datum/picture()
p = z
p.fields["name"] = "Uploaded Image [numberer] (synced from [R.name])"
R.connected_ai.aicamera.aipictures += p
numberer++
continue
for(var/datum/picture/t in R.connected_ai.aicamera.aipictures) //Hopefully to prevent someone spamming images to silicons, by spamming this wire
if((z.fields["pixel_y"] != t.fields["pixel_y"]) && (z.fields["pixel_x"] != t.fields["pixel_x"])) //~2.26 out of 1000 chance this will stop something it shouldn't
var/datum/picture/p = new/datum/picture()
p = z
p.fields["name"] = "Uploaded Image [numberer] (synced from [R.name])"
R.connected_ai.aicamera.aipictures += p
else
continue
numberer++
if(R.aicamera.aipictures.len > 0)
R << "<span class='notice'>Locally saved images synced with AI. Images were retained in local database in case of loss of connection with the AI.</span>"
if (BORG_WIRE_CAMERA)
if(!isnull(R.camera) && R.camera.can_use() && !R.scrambledcodes)
R.camera.deactivate(usr, 0) // Kick anyone watching the Cyborg's camera, doesn't display you disconnecting the camera.
R.visible_message("[R]'s camera lense focuses loudly.")
R << "Your camera lense focuses loudly."
if(BORG_WIRE_LOCKED_DOWN)
R.notify_ai(TRUE)
if(WIRE_CAMERA) // Pulse to disable the camera.
if(!isnull(R.camera) && !R.scrambledcodes)
R.camera.deactivate(usr, 0)
R.visible_message("[R]'s camera lense focuses loudly.", "Your camera lense focuses loudly.")
if(WIRE_LAWSYNC) // Forces a law update if possible.
if(R.lawupdate)
R.visible_message("[R] gently chimes.", "LawSync protocol engaged.")
R.lawsync()
R.show_laws()
if(WIRE_LOCKDOWN)
R.SetLockdown(!R.lockcharge) // Toggle
/datum/wires/robot/CanUse(mob/living/L)
/datum/wires/robot/on_cut(wire, mend)
var/mob/living/silicon/robot/R = holder
if(R.wiresexposed)
return 1
return 0
/datum/wires/robot/proc/IsCameraCut()
return wires_status & BORG_WIRE_CAMERA
/datum/wires/robot/proc/LockedCut()
return wires_status & BORG_WIRE_LOCKED_DOWN
switch(wire)
if(WIRE_AI) // Cut the AI wire to reset AI control.
if(!mend)
R.connected_ai = null
if(WIRE_LAWSYNC) // Cut the law wire, and the borg will no longer receive law updates from its AI. Repair and it will re-sync.
if(mend)
if(!R.emagged)
R.lawupdate = TRUE
else
R.lawupdate = FALSE
if (WIRE_CAMERA) // Disable the camera.
if(!isnull(R.camera) && !R.scrambledcodes)
R.camera.status = mend
R.camera.deactivate(usr, 0)
R.visible_message("[R]'s camera lense focuses loudly.", "Your camera lense focuses loudly.")
if(WIRE_LOCKDOWN) // Simple lockdown.
R.SetLockdown(!mend)
+57 -59
View File
@@ -1,77 +1,75 @@
/datum/wires/syndicatebomb
random = 1
holder_type = /obj/machinery/syndicatebomb
wire_count = 5
randomize = TRUE
var/const/WIRE_BOOM = 1 // Explodes if pulsed or cut while active, defuses a bomb that isn't active on cut
var/const/WIRE_UNBOLT = 2 // Unbolts the bomb if cut, hint on pulsed
var/const/WIRE_DELAY = 4 // Raises the timer on pulse, does nothing on cut
var/const/WIRE_PROCEED = 8 // Lowers the timer, explodes if cut while the bomb is active
var/const/WIRE_ACTIVATE = 16 // Will start a bombs timer if pulsed, will hint if pulsed while already active, will stop a timer a bomb on cut
/datum/wires/syndicatebomb/New(atom/holder)
wires = list(
WIRE_BOOM, WIRE_UNBOLT,
WIRE_ACTIVATE, WIRE_DELAY, WIRE_PROCEED
)
..()
/datum/wires/syndicatebomb/CanUse(mob/living/L)
/datum/wires/syndicatebomb/interactable(mob/user)
var/obj/machinery/syndicatebomb/P = holder
if(P.open_panel)
return 1
return 0
return TRUE
/datum/wires/syndicatebomb/UpdatePulsed(index)
var/obj/machinery/syndicatebomb/P = holder
switch(index)
/datum/wires/syndicatebomb/on_pulse(wire)
var/obj/machinery/syndicatebomb/B = holder
switch(wire)
if(WIRE_BOOM)
if (P.active)
P.loc.visible_message("<span class='danger'>\icon[holder] An alarm sounds! It's go-</span>")
P.timer = 0
if(B.active)
B.loc.visible_message("<span class='danger'>\icon[B] An alarm sounds! It's go-</span>")
B.timer = 0
if(WIRE_UNBOLT)
P.loc.visible_message("<span class='notice'>\icon[holder] The bolts spin in place for a moment.</span>")
B.loc.visible_message("<span class='notice'>\icon[B] The bolts spin in place for a moment.</span>")
if(WIRE_DELAY)
playsound(P.loc, 'sound/machines/chime.ogg', 30, 1)
P.loc.visible_message("<span class='notice'>\icon[holder] The bomb chirps.</span>")
P.timer += 10
B.loc.visible_message("<span class='notice'>\icon[B] The bomb chirps.</span>")
playsound(B.loc, 'sound/machines/chime.ogg', 30, 1)
B.timer += 10
if(WIRE_PROCEED)
playsound(P.loc, 'sound/machines/buzz-sigh.ogg', 30, 1)
P.loc.visible_message("<span class='danger'>\icon[holder] The bomb buzzes ominously!</span>")
if (P.timer >= 61) //Long fuse bombs can suddenly become more dangerous if you tinker with them
P.timer = 60
if (P.timer >= 21)
P.timer -= 10
else if (P.timer >= 11) //both to prevent negative timers and to have a little mercy
P.timer = 10
B.loc.visible_message("<span class='danger'>\icon[B] The bomb buzzes ominously!</span>")
playsound(B.loc, 'sound/machines/buzz-sigh.ogg', 30, 1)
if(B.timer >= 61) // Long fuse bombs can suddenly become more dangerous if you tinker with them.
B.timer = 60
else if(B.timer >= 21)
B.timer -= 10
else if(B.timer >= 11) // Both to prevent negative timers and to have a little mercy.
B.timer = 10
if(WIRE_ACTIVATE)
if(!P.active && !P.defused)
playsound(P.loc, 'sound/machines/click.ogg', 30, 1)
P.loc.visible_message("<span class='danger'>\icon[holder] You hear the bomb start ticking!</span>")
P.active = 1
P.icon_state = "[initial(P.icon_state)]-active[P.open_panel ? "-wires" : ""]"
if(!B.active && !B.defused)
B.loc.visible_message("<span class='danger'>\icon[B] You hear the bomb start ticking!</span>")
playsound(B.loc, 'sound/machines/click.ogg', 30, 1)
B.active = 1
B.update_icon()
else
P.loc.visible_message("<span class='notice'>\icon[holder] The bomb seems to hesitate for a moment.</span>")
P.timer += 5
B.loc.visible_message("<span class='notice'>\icon[B] The bomb seems to hesitate for a moment.</span>")
B.timer += 5
/datum/wires/syndicatebomb/UpdateCut(index, mended)
var/obj/machinery/syndicatebomb/P = holder
switch(index)
if(WIRE_EXPLODE)
if(!mended)
if(P.active)
P.loc.visible_message("<span class='danger'>\icon[holder] An alarm sounds! It's go-</span>")
P.timer = 0
/datum/wires/syndicatebomb/on_cut(wire, mend)
var/obj/machinery/syndicatebomb/B = holder
switch(wire)
if(WIRE_BOOM)
if(mend)
B.defused = 0 // Cutting and mending all the wires of an inactive bomb will thus cure any sabotage.
else
if(B.active)
B.loc.visible_message("<span class='danger'>\icon[B] An alarm sounds! It's go-</span>")
B.timer = 0
else
P.defused = 1
if(mended)
P.defused = 0 //cutting and mending all the wires of an inactive bomb will thus cure any sabotage
B.defused = 1
if(WIRE_UNBOLT)
if (!mended && P.anchored)
playsound(P.loc, 'sound/effects/stealthoff.ogg', 30, 1)
P.loc.visible_message("<span class='notice'>\icon[holder] The bolts lift out of the ground!</span>")
P.anchored = 0
if(!mend && B.anchored)
B.loc.visible_message("<span class='notice'>\icon[B] The bolts lift out of the ground!</span>")
playsound(B.loc, 'sound/effects/stealthoff.ogg', 30, 1)
B.anchored = 0
if(WIRE_PROCEED)
if(!mended && P.active)
P.loc.visible_message("<span class='danger'>\icon[holder] An alarm sounds! It's go-</span>")
P.timer = 0
if(!mend && B.active)
B.loc.visible_message("<span class='danger'>\icon[B] An alarm sounds! It's go-</span>")
B.timer = 0
if(WIRE_ACTIVATE)
if (!mended && P.active)
P.loc.visible_message("<span class='notice'>\icon[holder] The timer stops! The bomb has been defused!</span>")
P.icon_state = "[initial(P.icon_state)]-inactive[P.open_panel ? "-wires" : ""]"
P.active = 0
P.defused = 1
if (!mend && B.active)
B.loc.visible_message("<span class='notice'>\icon[B] The timer stops! The bomb has been defused!</span>")
B.active = 0
B.defused = 1
B.update_icon()
+40 -40
View File
@@ -1,58 +1,58 @@
/datum/wires/vending
holder_type = /obj/machinery/vending
wire_count = 4
var/const/VENDING_WIRE_THROW = 1
var/const/VENDING_WIRE_CONTRABAND = 2
var/const/VENDING_WIRE_ELECTRIFY = 4
var/const/VENDING_WIRE_IDSCAN = 8
/datum/wires/vending/New(atom/holder)
wires = list(
WIRE_THROW, WIRE_ELECTRIFY, WIRE_SPEAKER,
WIRE_CONTRABAND, WIRE_IDSCAN
)
add_duds(1)
..()
/datum/wires/vending/CanUse(mob/living/L)
/datum/wires/vending/interactable(mob/user)
var/obj/machinery/vending/V = holder
if(!istype(L, /mob/living/silicon))
if(V.seconds_electrified)
if(V.shock(L, 100))
return 0
if(!istype(user, /mob/living/silicon) && V.seconds_electrified && V.shock(user, 100))
return FALSE
if(V.panel_open)
return 1
return 0
return TRUE
/datum/wires/vending/Interact(mob/living/user)
if(CanUse(user))
var/obj/machinery/vending/V = holder
V.attack_hand(user)
/datum/wires/vending/GetInteractWindow()
/datum/wires/vending/get_status()
var/obj/machinery/vending/V = holder
. += ..()
. += "<BR>The orange light is [V.seconds_electrified ? "on" : "off"].<BR>"
. += "The red light is [V.shoot_inventory ? "off" : "blinking"].<BR>"
. += "The green light is [V.extended_inventory ? "on" : "off"].<BR>"
. += "A [V.scan_id ? "purple" : "yellow"] light is on.<BR>"
var/list/status = list()
status += "The orange light is [V.seconds_electrified ? "on" : "off"]."
status += "The red light is [V.shoot_inventory ? "off" : "blinking"]."
status += "The green light is [V.extended_inventory ? "on" : "off"]."
status += "A [V.scan_id ? "purple" : "yellow"] light is on."
status += "The speaker light is [V.shut_up ? "off" : "on"]."
return status
/datum/wires/vending/UpdatePulsed(index)
/datum/wires/vending/on_pulse(wire)
var/obj/machinery/vending/V = holder
switch(index)
if(VENDING_WIRE_THROW)
switch(wire)
if(WIRE_THROW)
V.shoot_inventory = !V.shoot_inventory
if(VENDING_WIRE_CONTRABAND)
if(WIRE_CONTRABAND)
V.extended_inventory = !V.extended_inventory
if(VENDING_WIRE_ELECTRIFY)
if(WIRE_ELECTRIFY)
V.seconds_electrified = 30
if(VENDING_WIRE_IDSCAN)
if(WIRE_IDSCAN)
V.scan_id = !V.scan_id
if(WIRE_SPEAKER)
V.shut_up = !V.shut_up
/datum/wires/vending/UpdateCut(index, mended)
/datum/wires/vending/on_cut(wire, mend)
var/obj/machinery/vending/V = holder
switch(index)
if(VENDING_WIRE_THROW)
V.shoot_inventory = !mended
if(VENDING_WIRE_CONTRABAND)
V.extended_inventory = 0
if(VENDING_WIRE_ELECTRIFY)
if(mended)
V.seconds_electrified = 0
switch(wire)
if(WIRE_THROW)
V.shoot_inventory = !mend
if(WIRE_CONTRABAND)
V.extended_inventory = FALSE
if(WIRE_ELECTRIFY)
if(mend)
V.seconds_electrified = FALSE
else
V.seconds_electrified = -1
if(VENDING_WIRE_IDSCAN)
V.scan_id = 1
if(WIRE_IDSCAN)
V.scan_id = mend
if(WIRE_SPEAKER)
V.shut_up = mend
+329 -289
View File
@@ -1,324 +1,364 @@
// Wire datums. Created by Giacomand.
// Was created to replace a horrible case of copy and pasted code with no care for maintability.
// Goodbye Door wires, Cyborg wires, Vending Machine wires, Autolathe wires
// Protolathe wires, APC wires and Camera wires!
#define MAX_FLAG 65535
var/list/same_wires = list()
// 12 colours, if you're adding more than 12 wires then add more colours here
var/list/wireColours = list("red", "blue", "green", "black", "orange", "brown", "gold", "gray", "cyan", "navy", "purple", "pink")
var/list/wire_colors = list( // http://www.crockford.com/wrrrld/color.html
"#dedbef",
"aliceblue",
"antiquewhite",
"aqua",
"aquamarine",
"beige",
"black",
"blanchedalmond",
"blue",
"blueviolet",
"brown",
"burlywood",
"cadetblue",
"chartreuse",
"chocolate",
"coral",
"cornflowerblue",
"cornsilk",
"crimson",
"cyan",
"darkblue",
"darkcyan",
"darkgoldenrod",
"darkgray",
"darkgrey",
"darkgreen",
"darkkhaki",
"darkmagenta",
"darkolivegreen",
"darkorange",
"darkorchid",
"darkred",
"darksalmon",
"darkseagreen",
"darkslateblue",
"darkslategray",
"darkturquoise",
"darkviolet",
"deeppink",
"deepskyblue",
"dimgray",
"dodgerblue",
"firebrick",
"floralwhite",
"forestgreen",
"fuchsia",
"gainsboro",
"ghostwhite",
"gold",
"goldenrod",
"gray",
"grey",
"green",
"greenyellow",
"honeydew",
"hotpink",
"indianred",
"indigo",
"ivory",
"khaki",
"lavender",
"lavenderblush",
"lawngreen",
"lemonchiffon",
"lightblue",
"lightcoral",
"lightcyan",
"lightgoldenrodyellow",
"lightgray",
"lightgrey",
"lightgreen",
"lightpink",
"lightsalmon",
"lightseagreen",
"lightskyblue",
"lightslategray",
"lightslategrey",
"lightsteelblue",
"lightyellow",
"lime",
"limegreen",
"linen",
"magenta",
"maroon",
"mediumaquamarine",
"mediumblue",
"mediumorchid",
"mediumpurple",
"mediumseagreen",
"mediumslateblue",
"mediumspringgreen",
"mediumturquoise",
"mediumvioletred",
"midnightblue",
"mintcream",
"mistyrose",
"moccasin",
"navajowhite",
"navy",
"oldlace",
"olive",
"olivedrab",
"orange",
"orangered",
"orchid",
"palegoldenrod",
"palegreen",
"paleturquoise",
"palevioletred",
"papayawhip",
"peachpuff",
"peru",
"pink",
"plum",
"powderblue",
"purple",
"red",
"rosybrown",
"royalblue",
"saddlebrown",
"salmon",
"sandybrown",
"seagreen",
"seashell",
"sienna",
"silver",
"skyblue",
"slateblue",
"slategray",
"slategrey",
"snow",
"springgreen",
"steelblue",
"tan",
"teal",
"thistle",
"tomato",
"turquoise",
"violet",
"wheat",
"white",
"whitesmoke",
"yellow",
"yellowgreen",
)
var/list/wire_color_directory = list()
/datum/wires
var/random = 0 // Will the wires be different for every single instance.
var/atom/holder = null // The holder
var/holder_type = null // The holder type; used to make sure that the holder is the correct type.
var/wire_count = 0 // Max is 16
var/wires_status = 0 // BITFLAG OF WIRES
var/list/wires = list()
var/list/signallers = list()
var/table_options = " align='center'"
var/row_options1 = " width='80px'"
var/row_options2 = " width='260px'"
var/window_x = 370
var/window_y = 470
/datum/wires/New(var/atom/holder)
..()
src.holder = holder
if(!istype(holder, holder_type))
CRASH("Our holder is null/the wrong type!")
return
// Generate new wires
if(random)
GenerateWires()
// Get the same wires
else
// We don't have any wires to copy yet, generate some and then copy it.
if(!same_wires[holder_type])
GenerateWires()
same_wires[holder_type] = src.wires.Copy()
else
var/list/wires = same_wires[holder_type]
src.wires = wires // Reference the wires list.
/datum/wires/Destroy()
holder = null
signallers = list()
return ..()
/datum/wires/proc/GenerateWires()
var/list/colours_to_pick = wireColours.Copy() // Get a copy, not a reference.
var/list/indexes_to_pick = list()
//Generate our indexes
for(var/i = 1; i < MAX_FLAG && i < (1 << wire_count); i += i)
indexes_to_pick += i
colours_to_pick.len = wire_count // Downsize it to our specifications.
while(colours_to_pick.len && indexes_to_pick.len)
// Pick and remove a colour
var/colour = pick_n_take(colours_to_pick)
// Pick and remove an index
var/index = pick_n_take(indexes_to_pick)
src.wires[colour] = index
//wires = shuffle(wires)
/datum/wires/proc/IsInteractionTool(obj/item/I)
/proc/is_wire_tool(obj/item/I)
if(istype(I, /obj/item/device/multitool))
return 1
return TRUE
if(istype(I, /obj/item/weapon/wirecutters))
return 1
return TRUE
if(istype(I, /obj/item/device/assembly))
var/obj/item/device/assembly/A = I
if(A.attachable)
return 1
return TRUE
return
return 0
/atom
var/datum/wires/wires = null
/datum/wires
var/atom/holder = null // The holder (atom that contains these wires).
var/holder_type = null // The holder's typepath (used to make wire colors common to all holders).
/datum/wires/proc/Interact(mob/living/user)
var/html = null
if(holder && CanUse(user))
html = GetInteractWindow()
if(html)
if(user.machine != holder)
for(var/A in signallers)
if(istype(signallers[A], /obj/item))
var/obj/item/I = signallers[A]
if(I.on_found(user))
return
var/list/wires = list() // List of wires.
var/list/cut_wires = list() // List of wires that have been cut.
var/list/colors = list() // Dictionary of colors to wire.
var/list/assemblies = list() // List of attached assemblies.
var/randomize = 0 // If every instance of these wires should be random.
user.set_machine(holder)
else
user.unset_machine()
// No content means no window.
user << browse(null, "window=wires")
return
var/datum/browser/popup = new(user, "wires", holder.name, window_x, window_y)
popup.set_content(html)
popup.set_title_image(user.browse_rsc_icon(holder.icon, holder.icon_state))
popup.open()
/datum/wires/proc/GetInteractWindow()
var/html = "<div class='block'>"
html += "<h3>Exposed Wires</h3>"
html += "<table[table_options]>"
for(var/colour in wires)
html += "<tr>"
html += "<td[row_options1]><font color='[colour]'>[capitalize(colour)]</font></td>"
html += "<td[row_options2]>"
html += "<A href='?src=\ref[src];action=1;cut=[colour]'>[IsColourCut(colour) ? "Mend" : "Cut"]</A>"
html += " <A href='?src=\ref[src];action=1;pulse=[colour]'>Pulse</A>"
html += " <A href='?src=\ref[src];action=1;attach=[colour]'>[IsAttached(colour) ? "Detach" : "Attach"] Signaller</A></td></tr>"
html += "</table>"
html += "</div>"
return html
/datum/wires/Topic(href, href_list)
/datum/wires/New(atom/holder)
..()
if(usr.Adjacent(holder) && isliving(usr))
var/mob/living/L = usr
if(CanUse(L) && href_list["action"])
var/obj/item/I = L.get_active_hand()
holder.add_hiddenprint(L)
if(href_list["cut"]) // Toggles the cut/mend status
if(istype(I, /obj/item/weapon/wirecutters))
var/colour = href_list["cut"]
CutWireColour(colour)
else
L << "<span class='warning'>You need wirecutters!</span>"
else if(href_list["pulse"])
if(istype(I, /obj/item/device/multitool))
var/colour = href_list["pulse"]
PulseColour(colour)
else
L << "<span class='warning'>You need a multitool!</span>"
else if(href_list["attach"])
var/colour = href_list["attach"]
// Detach
if(IsAttached(colour))
var/obj/item/O = Detach(colour)
if(O)
L.put_in_hands(O)
// Attach
else
if(istype(I, /obj/item/device/assembly))
var/obj/item/device/assembly/A = I;
if(A.attachable)
if(!L.drop_item())
return
Attach(colour, A)
else
L << "<span class='warning'>You need a attachable assembly!</span>"
// Update Window
Interact(usr)
if(href_list["close"])
usr << browse(null, "window=wires")
usr.unset_machine(holder)
//
// Overridable Procs
//
// Called when wires cut/mended.
/datum/wires/proc/UpdateCut(index, mended)
return
// Called when wire pulsed. Add code here.
/datum/wires/proc/UpdatePulsed(index)
return
/datum/wires/proc/CanUse(mob/living/L)
return 1
// Example of use:
/*
var/const/BOLTED= 1
var/const/SHOCKED = 2
var/const/SAFETY = 4
var/const/POWER = 8
/datum/wires/door/UpdateCut(var/index, var/mended)
var/obj/machinery/door/airlock/A = holder
switch(index)
if(BOLTED)
if(!mended)
A.bolt()
if(SHOCKED)
A.shock()
if(SAFETY )
A.safety()
*/
//
// Helper Procs
//
/datum/wires/proc/PulseColour(colour)
PulseIndex(GetIndex(colour))
/datum/wires/proc/PulseIndex(index)
if(IsIndexCut(index))
if(!istype(holder, holder_type))
CRASH("Wire holder is not of the expected type!")
return
UpdatePulsed(index)
/datum/wires/proc/GetIndex(colour)
if(wires[colour])
var/index = wires[colour]
return index
src.holder = holder
if(randomize)
randomize()
else
CRASH("[colour] is not a key in wires.")
if(!wire_color_directory[holder_type])
randomize()
wire_color_directory[holder_type] = colors
else
colors = shuffle(wire_color_directory[holder_type])
/datum/wires/proc/GetColour(index)
for(var/colour in wires)
if(wires[colour] == index)
return colour
/datum/wires/Destroy()
holder = null
assemblies = list()
return ..()
//
// Is Index/Colour Cut procs
//
/datum/wires/proc/add_duds(duds)
while(duds)
var/dud = "dud[--duds]"
if(dud in wires)
continue
wires += dud
/datum/wires/proc/IsColourCut(colour)
var/index = GetIndex(colour)
return IsIndexCut(index)
/datum/wires/proc/randomize()
var/list/possible_colors = shuffle(wire_colors.Copy())
/datum/wires/proc/IsIndexCut(index)
return (index & wires_status)
for(var/wire in shuffle(wires))
colors[pick_n_take(possible_colors)] = wire
//
// Signaller Procs
//
/datum/wires/proc/repair()
cut_wires = list()
/datum/wires/proc/IsAttached(colour)
if(signallers[colour])
return 1
return 0
/datum/wires/proc/get_wire(color)
return colors[color]
/datum/wires/proc/GetAttached(colour)
if(signallers[colour])
return signallers[colour]
/datum/wires/proc/get_attached(color)
if(assemblies[color])
return assemblies[color]
return null
/datum/wires/proc/Attach(colour, obj/item/device/assembly/S)
if(colour && S && S.attachable)
if(!IsAttached(colour))
signallers[colour] = S
S.loc = holder
S.connected = src
return S
/datum/wires/proc/is_attached(color)
if(assemblies[color])
return TRUE
/datum/wires/proc/Detach(colour)
if(colour)
var/obj/item/device/assembly/S = GetAttached(colour)
if(S)
signallers -= colour
S.connected = null
S.loc = holder.loc
return S
/datum/wires/proc/is_cut(wire)
return (wire in cut_wires)
/datum/wires/proc/is_color_cut(color)
return is_cut(get_wire(color))
/datum/wires/proc/Pulse(obj/item/device/assembly/S)
/datum/wires/proc/is_all_cut()
if(cut_wires.len == wires.len)
return TRUE
for(var/colour in signallers)
if(S == signallers[colour])
PulseColour(colour)
break
//
// Cut Wire Colour/Index procs
//
/datum/wires/proc/CutWireColour(colour)
var/index = GetIndex(colour)
CutWireIndex(index)
/datum/wires/proc/CutWireIndex(index)
if(IsIndexCut(index))
wires_status &= ~index
UpdateCut(index, 1)
/datum/wires/proc/cut(wire)
if(is_cut(wire))
cut_wires -= wire
on_cut(wire, mend = TRUE)
else
wires_status |= index
UpdateCut(index, 0)
cut_wires += wire
on_cut(wire, mend = FALSE)
/datum/wires/proc/RandomCut()
var/r = rand(1, wires.len)
CutWireIndex(r)
/datum/wires/proc/cut_color(color)
cut(get_wire(color))
/datum/wires/proc/CutAll()
for(var/i = 1; i < MAX_FLAG && i < (1 << wire_count); i += i)
CutWireIndex(i)
/datum/wires/proc/cut_random()
cut(wires[rand(1, wires.len)])
/datum/wires/proc/IsAllCut()
if(wires_status == (1 << wire_count) - 1)
return 1
return 0
/datum/wires/proc/cut_all()
for(var/wire in wires)
cut(wire)
//
//Shuffle and Mend
//
/datum/wires/proc/pulse(wire)
if(is_cut(wire))
return
on_pulse(wire)
/datum/wires/proc/Shuffle()
wires_status = 0
GenerateWires()
/datum/wires/proc/pulse_color(color)
pulse(get_wire(color))
/datum/wires/proc/pulse_assembly(obj/item/device/assembly/S)
for(var/color in assemblies)
if(S == assemblies[color])
pulse_color(color)
return TRUE
/datum/wires/proc/attach_assembly(color, obj/item/device/assembly/S)
if(S && istype(S) && S.attachable && !is_attached(color))
assemblies[color] = S
S.loc = holder
S.connected = src
return S
/datum/wires/proc/detach_assembly(color)
var/obj/item/device/assembly/S = get_attached(color)
if(S && istype(S))
assemblies -= color
S.connected = null
S.loc = holder.loc
return S
// Overridable Procs
/datum/wires/proc/interactable(mob/user)
return TRUE
/datum/wires/proc/get_status()
return list()
/datum/wires/proc/on_cut(wire, mend = FALSE)
return
/datum/wires/proc/on_pulse(wire)
return
// End Overridable Procs
/datum/wires/proc/interact(mob/user)
if(!interactable(user))
return
ui_interact(user)
for(var/A in assemblies)
var/obj/item/I = assemblies[A]
if(istype(I) && I.on_found(user))
return
/datum/wires/ui_host()
return holder
/datum/wires/ui_interact(mob/user, ui_key = "wires", datum/tgui/ui = null, force_open = 0, \
datum/tgui/master_ui = null, datum/ui_state/state = wire_state)
ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open)
if (!ui)
ui = new(user, src, ui_key, "wires", "[holder.name] wires", 350, 150 + wires.len * 30, master_ui, state)
ui.open()
/datum/wires/get_ui_data(mob/user)
var/list/data = list()
var/list/payload = list()
for(var/color in colors)
payload.Add(list(list(
"color" = color,
"wire" = (IsAdminGhost(user) ? get_wire(color) : null),
"cut" = is_color_cut(color),
"attached" = is_attached(color)
)))
data["wires"] = payload
data["status"] = get_status()
return data
/datum/wires/ui_act(action, params)
if(..() || !interactable(usr))
return
var/target_wire = params["wire"]
var/mob/living/L = usr
var/obj/item/I = L.get_active_hand()
switch(action)
if("cut")
if(istype(I, /obj/item/weapon/wirecutters) || IsAdminGhost(usr))
playsound(holder, 'sound/items/Wirecutter.ogg', 20, 1)
cut_color(target_wire)
. = TRUE
else
L << "<span class='warning'>You need wirecutters!</span>"
if("pulse")
if(istype(I, /obj/item/device/multitool) || IsAdminGhost(usr))
playsound(holder, 'sound/weapons/empty.ogg', 20, 1)
pulse_color(target_wire)
. = TRUE
else
L << "<span class='warning'>You need a multitool!</span>"
if("attach")
if(is_attached(target_wire))
var/obj/item/O = detach_assembly(target_wire)
if(O)
L.put_in_hands(O)
. = TRUE
else
if(istype(I, /obj/item/device/assembly))
var/obj/item/device/assembly/A = I
if(A.attachable)
if(!L.drop_item())
return
attach_assembly(target_wire, A)
. = TRUE
else
L << "<span class='warning'>You need an attachable assembly!</span>"
+4 -4
View File
@@ -67,8 +67,8 @@ var/list/teleportlocs = list()
for(var/area/AR in world)
if(istype(AR, /area/shuttle) || istype(AR, /area/wizard_station)) continue
if(teleportlocs.Find(AR.name)) continue
var/turf/picked = pick(get_area_turfs(AR.type))
if (picked.z == ZLEVEL_STATION)
var/turf/picked = safepick(get_area_turfs(AR.type))
if (picked && (picked.z == ZLEVEL_STATION))
teleportlocs += AR.name
teleportlocs[AR.name] = AR
@@ -740,7 +740,7 @@ var/list/teleportlocs = list()
music = 'sound/ambience/signal.ogg'
/area/medical/patients_rooms
name = "Patient's Rooms"
name = "Patients' Rooms"
icon_state = "patients"
/area/medical/cmo
@@ -1142,7 +1142,7 @@ var/list/teleportlocs = list()
icon_state = "yellow"
/area/construction/quarters
name = "Engineer's Quarters"
name = "Engineers' Quarters"
icon_state = "yellow"
/area/construction/qmaint
+1 -1
View File
@@ -37,7 +37,7 @@ var/global/max_secret_rooms = 6
//////////////
/proc/make_mining_asteroid_secrets()
for(1 to max_secret_rooms)
for(var/i in 1 to max_secret_rooms)
make_mining_asteroid_secret()
/proc/make_mining_asteroid_secret()
+20
View File
@@ -295,3 +295,23 @@
if(buckled_mob == mover)
return 1
return ..()
/atom/movable/proc/get_spacemove_backup()
var/atom/movable/dense_object_backup
for(var/A in orange(1, get_turf(src)))
if(isarea(A))
continue
else if(isturf(A))
var/turf/turf = A
if(!turf.density)
continue
return turf
else
var/atom/movable/AM = A
if(!AM.CanPass(src) || AM.density)
if(AM.anchored)
return AM
dense_object_backup = AM
break
. = dense_object_backup
+1 -1
View File
@@ -40,7 +40,7 @@
obj/proc/receive_signal(datum/signal/signal, var/receive_method as num, var/receive_param)
Handler from received signals. By default does nothing. Define your own for your object.
Avoid of sending signals directly from this proc, use spawn(-1). Do not use sleep() here please.
Avoid of sending signals directly from this proc, use spawn(0). Do not use sleep() here please.
parameters:
signal - see description below. Extract all needed data from the signal before doing sleep(), spawn() or return!
receive_method - may be TRANSMISSION_WIRE or TRANSMISSION_RADIO.
+1 -1
View File
@@ -160,7 +160,7 @@
unique_enzymes = generate_unique_enzymes()
uni_identity = generate_uni_identity()
struc_enzymes = generate_struc_enzymes()
features = list("mcolor" = "FFF", "tail" = "Smooth", "snout" = "Round", "horns" = "None", "frills" = "None", "spines" = "None", "body_markings" = "None")
features = random_features()
+10 -7
View File
@@ -92,13 +92,14 @@
M << "<B>Your service has not gone unrewarded, however. Studying under [usr.real_name], you have learned stealthy, robeless spells. You are able to cast knock and mindswap."
equip_antag(M)
var/mob/living/carbon/human/H = usr
var/wizard_name_first = pick(wizard_first)
var/wizard_name_second = pick(wizard_second)
var/randomname = "[wizard_name_first] [wizard_name_second]"
var/datum/objective/default/protect/new_objective = add_objective(M.mind, /datum/objective/default/protect)
new_objective.target = H.mind
new_objective.explanation_text = "Protect [H.real_name], the wizard."
var/datum/objective/protect/new_objective = new /datum/objective/protect
new_objective.owner = M:mind
new_objective:target = usr:mind
new_objective.explanation_text = "Protect [usr.real_name], the wizard."
M.mind.objectives += new_objective
ticker.mode.apprentices += M.mind
M.mind.special_role = "apprentice"
ticker.mode.update_wiz_icons_added(M.mind)
@@ -134,7 +135,6 @@
desc = "A single-use teleporter designed to quickly reinforce operatives in the field."
icon = 'icons/obj/device.dmi'
icon_state = "locator"
var/TC_cost = 0
var/borg_to_spawn
var/list/possible_types = list("Assault", "Medical")
@@ -163,6 +163,7 @@
var/datum/effect_system/spark_spread/S = new /datum/effect_system/spark_spread
S.set_up(4, 1, src)
S.start()
qdel(src)
else
user << "<span class='warning'>Unable to connect to Syndicate command. Please wait and try again later or use the teleporter on your uplink to get your points refunded.</span>"
@@ -251,9 +252,11 @@
S.mind.assigned_role = "Slaughter Demon"
S.mind.special_role = "Slaughter Demon"
ticker.mode.traitors += S.mind
var/datum/objective/default/assassinate/new_objective = add_objective(S.mind, /datum/objective/default/assassinate)
var/datum/objective/assassinate/new_objective = new /datum/objective/assassinate
new_objective.owner = S.mind
new_objective.target = usr.mind
new_objective.explanation_text = "Kill [usr.real_name], the one who summoned you."
S.mind.objectives += new_objective
var/datum/objective/new_objective2 = new /datum/objective
new_objective2.owner = S.mind
new_objective2.explanation_text = "Kill everyone else while you're at it."
@@ -261,4 +264,4 @@
S << S.playstyle_string
S << "<B>You are currently not currently in the same plane of existence as the station. Ctrl+Click a blood pool to manifest.</B>"
S << "<B>Objective #[1]</B>: [new_objective.explanation_text]"
S << "<B>Objective #[2]</B>: [new_objective2.explanation_text]"
S << "<B>Objective #[2]</B>: [new_objective2.explanation_text]"
@@ -8,6 +8,7 @@
icon = 'icons/mob/blob.dmi'
pass_flags = PASSBLOB
faction = list("blob")
bubble_icon = "blob"
atmos_requirements = list("min_oxy" = 0, "max_oxy" = 0, "min_tox" = 0, "max_tox" = 0, "min_co2" = 0, "max_co2" = 0, "min_n2" = 0, "max_n2" = 0)
minbodytemp = 0
maxbodytemp = 360
@@ -159,6 +160,8 @@
force_threshold = 10
mob_size = MOB_SIZE_LARGE
gold_core_spawnable = 1
see_invisible = SEE_INVISIBLE_MINIMUM
see_in_dark = 8
/mob/living/simple_animal/hostile/blob/blobbernaut/AttackingTarget()
if(isliving(target))
+3 -7
View File
@@ -8,6 +8,8 @@
explosion_block = 6
point_return = -1
atmosblock = 1
health_regen = 0 //we regen in Life() instead of when pulsed
var/core_regen = 2
var/overmind_get_delay = 0 //we don't want to constantly try to find an overmind, this var tracks when we'll try to get an overmind again
var/resource_delay = 0
var/point_rate = 2
@@ -34,9 +36,6 @@
var/image/C = new('icons/mob/blob.dmi', "blob_core_overlay")
overlays += C
/obj/effect/blob/core/PulseAnimation()
return
/obj/effect/blob/core/Destroy()
blob_cores -= src
if(overmind)
@@ -56,9 +55,6 @@
if(overmind) //we should have an overmind, but...
overmind.update_health()
/obj/effect/blob/core/RegenHealth()
return // Don't regen, we handle it in Life()
/obj/effect/blob/core/Life()
if(!overmind)
create_overmind()
@@ -66,7 +62,7 @@
if(resource_delay <= world.time)
resource_delay = world.time + 10 // 1 second
overmind.add_points(point_rate)
health = min(maxhealth, health+health_regen)
health = min(maxhealth, health+core_regen)
if(overmind)
overmind.update_health()
Pulse_Area(overmind, 12, 4, 3)
+5 -11
View File
@@ -18,22 +18,16 @@
spores = null
return ..()
/obj/effect/blob/factory/PulseAnimation(activate = 0)
if(activate)
..()
return
/obj/effect/blob/factory/run_action()
/obj/effect/blob/factory/Be_Pulsed()
. = ..()
if(spores.len >= max_spores)
return 0
return
if(spore_delay > world.time)
return 0
return
flick("factory_glow", src)
spore_delay = world.time + 100 // 10 seconds
PulseAnimation(1)
var/mob/living/simple_animal/hostile/blob/blobspore/BS = new/mob/living/simple_animal/hostile/blob/blobspore(src.loc, src)
if(overmind) //if we don't have an overmind, we don't need to do anything but make a spore
BS.overmind = overmind
BS.update_icons()
overmind.blob_mobs.Add(BS)
return 0
-3
View File
@@ -25,9 +25,6 @@
var/image/C = new('icons/mob/blob.dmi', "blob_node_overlay")
src.overlays += C
/obj/effect/blob/node/PulseAnimation()
return
/obj/effect/blob/node/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume)
return
+4 -15
View File
@@ -8,22 +8,11 @@
point_return = 15
var/resource_delay = 0
/obj/effect/blob/resource/PulseAnimation(activate = 0)
if(activate)
..()
return
/obj/effect/blob/resource/run_action()
/obj/effect/blob/resource/Be_Pulsed()
. = ..()
if(resource_delay > world.time)
return 0
PulseAnimation(1)
return
flick("factory_glow", src)
resource_delay = world.time + 45 // 4 and a half seconds
if(overmind)
overmind.add_points(1)
return 0
+5 -3
View File
@@ -90,11 +90,13 @@
return
var/message_a = say_quote(message, get_spans())
var/rendered = "<span class='big'><font color=\"#EE4000\">Blob Telepathy, <b>[name](<font color=\"[blob_reagent_datum.color]\">[blob_reagent_datum.name]</font>)</b> [message_a]</font></span>"
var/rendered = "<span class='big'><font color=\"#EE4000\"><b>\[Blob Telepathy\] [name](<font color=\"[blob_reagent_datum.color]\">[blob_reagent_datum.name]</font>)</b> [message_a]</font></span>"
for(var/mob/M in mob_list)
if(isovermind(M) || isobserver(M) || istype(M, /mob/living/simple_animal/hostile/blob))
M.show_message(rendered, 2)
if(isovermind(M) || istype(M, /mob/living/simple_animal/hostile/blob))
M << rendered
if(isobserver(M))
M << "<a href='?src=\ref[M];follow=\ref[src]'>(F)</a> [rendered]"
/mob/camera/blob/emote(act,m_type=1,message = null)
return
+3 -21
View File
@@ -12,8 +12,7 @@
var/health = 30
var/maxhealth = 30
var/health_regen = 2 //how much health this blob regens when pulsed
var/health_timestamp = 0 //we got healed when?
var/pulse_timestamp = 0 //we got pulsed when?
var/pulse_timestamp = 0 //we got pulsed/healed when?
var/brute_resist = 0.5 //multiplies brute damage by this
var/fire_resist = 1 //multiplies burn damage by this
var/atmosblock = 0 //if the blob blocks atmos and heat spread
@@ -90,7 +89,6 @@
src.Be_Pulsed()
if(claim_range)
for(var/obj/effect/blob/B in ultra_range(claim_range, src, 1))
B.update_icon()
if(!B.overmind && !istype(B, /obj/effect/blob/core) && prob(30))
B.overmind = pulsing_overmind //reclaim unclaimed, non-core blobs.
B.update_icon()
@@ -106,10 +104,9 @@
/obj/effect/blob/proc/Be_Pulsed()
if(pulse_timestamp <= world.time)
PulseAnimation()
ConsumeTile()
RegenHealth()
run_action()
health = min(maxhealth, health+health_regen)
update_icon()
pulse_timestamp = world.time + 10
return 1 //we did it, we were pulsed!
return 0 //oh no we failed
@@ -118,21 +115,6 @@
for(var/atom/A in loc)
A.blob_act()
/obj/effect/blob/proc/PulseAnimation()
flick("[icon_state]_glow", src)
return
/obj/effect/blob/proc/RegenHealth() //when pulsed, heal!
if(health_timestamp <= world.time)
health = min(maxhealth, health+health_regen)
update_icon()
health_timestamp = world.time + 10 //1 second between heals
return 1
return 0
/obj/effect/blob/proc/run_action()
return 0
/obj/effect/blob/proc/expand(turf/T = null, prob = 1, controller = null)
if(prob && !prob(health))
+60 -1
View File
@@ -113,6 +113,9 @@ var/list/slot2type = list("head" = /obj/item/clothing/head/changeling, "wear_mas
/datum/game_mode/proc/forge_changeling_objectives(datum/mind/changeling, var/team_mode = 0)
//OBJECTIVES - random traitor objectives. Unique objectives "steal brain" and "identity theft".
//No escape alone because changelings aren't suited for it and it'd probably just lead to rampant robusting
//If it seems like they'd be able to do it in play, add a 10% chance to have to escape alone
var/escape_objective_possible = TRUE
//if there's a team objective, check if it's compatible with escape objectives
@@ -121,7 +124,63 @@ var/list/slot2type = list("head" = /obj/item/clothing/head/changeling, "wear_mas
escape_objective_possible = FALSE
break
generate_objectives(changeling, 4, escape_objective_possible)
var/datum/objective/absorb/absorb_objective = new
absorb_objective.owner = changeling
absorb_objective.gen_amount_goal(6, 8)
changeling.objectives += absorb_objective
if(prob(60))
var/datum/objective/steal/steal_objective = new
steal_objective.owner = changeling
steal_objective.find_target()
changeling.objectives += steal_objective
var/list/active_ais = active_ais()
if(active_ais.len && prob(100/joined_player_list.len))
var/datum/objective/destroy/destroy_objective = new
destroy_objective.owner = changeling
destroy_objective.find_target()
changeling.objectives += destroy_objective
else
if(prob(70))
var/datum/objective/assassinate/kill_objective = new
kill_objective.owner = changeling
if(team_mode) //No backstabbing while in a team
kill_objective.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
else
kill_objective.find_target()
changeling.objectives += kill_objective
else
var/datum/objective/maroon/maroon_objective = new
maroon_objective.owner = changeling
if(team_mode)
maroon_objective.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
else
maroon_objective.find_target()
changeling.objectives += maroon_objective
if (!(locate(/datum/objective/escape) in changeling.objectives) && escape_objective_possible)
var/datum/objective/escape/escape_with_identity/identity_theft = new
identity_theft.owner = changeling
identity_theft.target = maroon_objective.target
identity_theft.update_explanation_text()
changeling.objectives += identity_theft
escape_objective_possible = FALSE
if (!(locate(/datum/objective/escape) in changeling.objectives) && escape_objective_possible)
if(prob(50))
var/datum/objective/escape/escape_objective = new
escape_objective.owner = changeling
changeling.objectives += escape_objective
else
var/datum/objective/escape/escape_with_identity/identity_theft = new
identity_theft.owner = changeling
if(team_mode)
identity_theft.find_target_by_role(role = "Changeling", role_type = 1, invert = 1)
else
identity_theft.find_target()
changeling.objectives += identity_theft
escape_objective_possible = FALSE
@@ -157,10 +157,10 @@
var/mob/dead/observer/ghost = target.ghostize(0)
user.mind.transfer_to(target)
if(ghost && ghost.mind)
if(ghost)
ghost.mind.transfer_to(user)
else
user.key = ghost.key
if(ghost.key)
user.key = ghost.key
user.Paralyse(2)
target << "<span class='warning'>Our genes cry out as we swap our [user] form for [target].</span>"

Some files were not shown because too many files have changed in this diff Show More