Merge branch 'master' of https://github.com/tgstation/-tg-station into LizardHunting
This commit is contained in:
@@ -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
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -324,3 +324,6 @@ var/list/bloody_footprints_cache = list()
|
||||
//Bloodcrawling
|
||||
#define BLOODCRAWL 1
|
||||
#define BLOODCRAWL_EAT 2
|
||||
|
||||
//Color Defines
|
||||
#define OOC_COLOR "#002eb8"
|
||||
@@ -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
|
||||
@@ -0,0 +1,5 @@
|
||||
#define MIN_FREE_FREQ 1201
|
||||
#define MAX_FREE_FREQ 1599
|
||||
|
||||
#define MIN_FREQ 1441
|
||||
#define MAX_FREQ 1489
|
||||
@@ -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
|
||||
@@ -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"
|
||||
@@ -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
@@ -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
|
||||
|
||||
@@ -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]"
|
||||
@@ -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
@@ -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)] °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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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.
|
||||
@@ -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()
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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'
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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.
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
@@ -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)
|
||||
@@ -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()
|
||||
|
||||
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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>"
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
File diff suppressed because it is too large
Load Diff
@@ -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
|
||||
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -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
@@ -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
@@ -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
@@ -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
|
||||
@@ -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)
|
||||
@@ -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)
|
||||
@@ -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>")
|
||||
@@ -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()
|
||||
@@ -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
@@ -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
@@ -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
@@ -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)
|
||||
|
||||
@@ -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()
|
||||
@@ -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
@@ -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>"
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
|
||||
@@ -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
|
||||
@@ -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
@@ -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()
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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))
|
||||
|
||||
@@ -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
Reference in New Issue
Block a user