diff --git a/baystation12.dme b/baystation12.dme
index 8d90f2ba4e8..1d8b91b8bd6 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -764,7 +764,6 @@
#include "code\modules\clothing\gloves\color.dm"
#include "code\modules\clothing\gloves\miscellaneous.dm"
#include "code\modules\clothing\gloves\ninja.dm"
-#include "code\modules\clothing\gloves\stungloves.dm"
#include "code\modules\clothing\head\collectable.dm"
#include "code\modules\clothing\head\hardhat.dm"
#include "code\modules\clothing\head\helmet.dm"
@@ -1141,6 +1140,7 @@
#include "code\modules\power\port_gen.dm"
#include "code\modules\power\power.dm"
#include "code\modules\power\power_monitor.dm"
+#include "code\modules\power\powernet.dm"
#include "code\modules\power\profiling.dm"
#include "code\modules\power\smes.dm"
#include "code\modules\power\smes_construction.dm"
diff --git a/code/ATMOSPHERICS/_atmos_setup.dm b/code/ATMOSPHERICS/_atmos_setup.dm
index c11b51dbc3d..01a8eb003ee 100644
--- a/code/ATMOSPHERICS/_atmos_setup.dm
+++ b/code/ATMOSPHERICS/_atmos_setup.dm
@@ -110,6 +110,19 @@ var/global/list/pipe_colors = list("grey" = PIPE_COLOR_GREY, "red" = PIPE_COLOR_
I.color = pipe_colors[pipe_color]
pipe_icons[state + "[pipe_colors[pipe_color]]"] = I
+ pipe = new ('icons/atmos/heat.dmi')
+ for(var/state in pipe.IconStates())
+ if(!state || findtext(state, "map"))
+ continue
+ pipe_icons["hepipe" + state] = image('icons/atmos/heat.dmi', icon_state = state)
+
+ pipe = new ('icons/atmos/junction.dmi')
+ for(var/state in pipe.IconStates())
+ if(!state || findtext(state, "map"))
+ continue
+ pipe_icons["hejunction" + state] = image('icons/atmos/junction.dmi', icon_state = state)
+
+
/datum/pipe_icon_manager/proc/gen_manifold_icons()
if(!manifold_icons)
manifold_icons = new()
@@ -268,4 +281,4 @@ var/global/list/pipe_colors = list("grey" = PIPE_COLOR_GREY, "red" = PIPE_COLOR_
if("pipe_intact-scrubbers")
pipe_underlays_intact["[D]" + pipe_colors[pipe_color]] = I
-*/
\ No newline at end of file
+*/
diff --git a/code/ATMOSPHERICS/_atmospherics_helpers.dm b/code/ATMOSPHERICS/_atmospherics_helpers.dm
index aeeb11d77c8..8e3a2b0dd76 100644
--- a/code/ATMOSPHERICS/_atmospherics_helpers.dm
+++ b/code/ATMOSPHERICS/_atmospherics_helpers.dm
@@ -1,6 +1,6 @@
/*
Atmos processes
-
+
These procs generalize various processes used by atmos machinery, such as pumping, filtering, or scrubbing gas, allowing them to be reused elsewhere.
If no gas was moved/pumped/filtered/whatever, they return a negative number.
Otherwise they return the amount of energy needed to do whatever it is they do (equivalently power if done over 1 second).
@@ -11,6 +11,15 @@
/obj/machinery/atmospherics/var/last_flow_rate = 0
/obj/machinery/portable_atmospherics/var/last_flow_rate = 0
+
+/obj/machinery/atmospherics/var/debug = 0
+
+/client/proc/atmos_toggle_debug(var/obj/machinery/atmospherics/M in view())
+ set name = "Toggle Debug Messages"
+ set category = "Debug"
+ M.debug = !M.debug
+ usr << "[M]: Debug messages toggled [M.debug? "on" : "off"]."
+
//Generalized gas pumping proc.
//Moves gas from one gas_mixture to another and returns the amount of power needed (assuming 1 second), or -1 if no gas was pumped.
//transfer_moles - Limits the amount of moles to transfer. The actual amount of gas moved may also be limited by available_power, if given.
@@ -18,38 +27,45 @@
/proc/pump_gas(var/obj/machinery/M, var/datum/gas_mixture/source, var/datum/gas_mixture/sink, var/transfer_moles = null, var/available_power = null)
if (source.total_moles < MINUMUM_MOLES_TO_PUMP) //if we cant transfer enough gas just stop to avoid further processing
return -1
-
- if (!transfer_moles)
+
+ //var/source_moles_initial = source.total_moles
+
+ if (isnull(transfer_moles))
transfer_moles = source.total_moles
else
transfer_moles = min(source.total_moles, transfer_moles)
-
+
//Calculate the amount of energy required and limit transfer_moles based on available power
var/specific_power = calculate_specific_power(source, sink)/ATMOS_PUMP_EFFICIENCY //this has to be calculated before we modify any gas mixtures
if (!isnull(available_power) && specific_power > 0)
transfer_moles = min(transfer_moles, available_power / specific_power)
-
+
if (transfer_moles < MINUMUM_MOLES_TO_PUMP) //if we cant transfer enough gas just stop to avoid further processing
return -1
-
+
//Update flow rate meter
if (istype(M, /obj/machinery/atmospherics))
var/obj/machinery/atmospherics/A = M
A.last_flow_rate = (transfer_moles/source.total_moles)*source.volume //group_multiplier gets divided out here
+
+ if (A.debug)
+ A.visible_message("[A]: source entropy: [round(source.specific_entropy(), 0.01)] J/Kmol --> sink entropy: [round(sink.specific_entropy(), 0.01)] J/Kmol")
+ A.visible_message("[A]: specific entropy change = [round(sink.specific_entropy() - source.specific_entropy(), 0.01)] J/Kmol")
+ A.visible_message("[A]: specific power = [round(specific_power, 0.1)] W/mol")
+ A.visible_message("[A]: moles transferred = [transfer_moles] mol")
+
if (istype(M, /obj/machinery/portable_atmospherics))
var/obj/machinery/portable_atmospherics/P = M
P.last_flow_rate = (transfer_moles/source.total_moles)*source.volume //group_multiplier gets divided out here
-
+
var/datum/gas_mixture/removed = source.remove(transfer_moles)
if (!removed) //Just in case
return -1
-
+
var/power_draw = specific_power*transfer_moles
- if (power_draw > 0)
- removed.add_thermal_energy(power_draw) //1st law - energy is conserved
-
+
sink.merge(removed)
-
+
return power_draw
//Generalized gas scrubbing proc.
@@ -62,40 +78,40 @@
return -1
filtering = filtering & source.gas //only filter gasses that are actually there. DO NOT USE &=
-
+
//Determine the specific power of each filterable gas type, and the total amount of filterable gas (gasses selected to be scrubbed)
var/total_filterable_moles = 0 //the total amount of filterable gas
var/list/specific_power_gas = list() //the power required to remove one mole of pure gas, for each gas type
for (var/g in filtering)
if (source.gas[g] < MINUMUM_MOLES_TO_FILTER)
continue
-
+
var/specific_power = calculate_specific_power_gas(g, source, sink)/ATMOS_FILTER_EFFICIENCY
specific_power_gas[g] = specific_power
total_filterable_moles += source.gas[g]
-
+
if (total_filterable_moles < MINUMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing
return -1
-
+
//now that we know the total amount of filterable gas, we can calculate the amount of power needed to scrub one mole of gas
var/total_specific_power = 0 //the power required to remove one mole of filterable gas
for (var/g in filtering)
var/ratio = source.gas[g]/total_filterable_moles //this converts the specific power per mole of pure gas to specific power per mole of scrubbed gas
total_specific_power = specific_power_gas[g]*ratio
-
+
//Figure out how much of each gas to filter
- if (!total_transfer_moles)
+ if (isnull(total_transfer_moles))
total_transfer_moles = total_filterable_moles
else
total_transfer_moles = min(total_transfer_moles, total_filterable_moles)
-
+
//limit transfer_moles based on available power
if (!isnull(available_power) && total_specific_power > 0)
total_transfer_moles = min(total_transfer_moles, available_power/total_specific_power)
-
+
if (total_transfer_moles < MINUMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing
return -1
-
+
//Update flow rate var
if (istype(M, /obj/machinery/atmospherics))
var/obj/machinery/atmospherics/A = M
@@ -103,30 +119,27 @@
if (istype(M, /obj/machinery/portable_atmospherics))
var/obj/machinery/portable_atmospherics/P = M
P.last_flow_rate = (total_transfer_moles/source.total_moles)*source.volume //group_multiplier gets divided out here
-
+
var/power_draw = 0
for (var/g in filtering)
var/transfer_moles = source.gas[g]
//filter gas in proportion to the mole ratio
transfer_moles = min(transfer_moles, total_transfer_moles*(source.gas[g]/total_filterable_moles))
-
+
//use update=0. All the filtered gasses are supposed to be added simultaneously, so we update after the for loop.
source.adjust_gas(g, -transfer_moles, update=0)
sink.adjust_gas_temp(g, transfer_moles, source.temperature, update=0)
-
+
power_draw += specific_power_gas[g]*transfer_moles
-
+
//Remix the resulting gases
sink.update_values()
source.update_values()
-
- if (power_draw > 0)
- sink.add_thermal_energy(power_draw) //gotta conserve that energy
-
+
return power_draw
//Generalized gas filtering proc.
-//Filtering is a bit different from scrubbing. Instead of selectively moving the targeted gas types from one gas mix to another, filtering splits
+//Filtering is a bit different from scrubbing. Instead of selectively moving the targeted gas types from one gas mix to another, filtering splits
//the input gas into two outputs: one that contains /only/ the targeted gas types, and another that completely clean of the targeted gas types.
//filtering - A list of gasids to be filtered. These gasses get moved to sink_filtered, while the other gasses get moved to sink_clean.
//total_transfer_moles - Limits the amount of moles to input. The actual amount of gas filtered may also be limited by available_power, if given.
@@ -136,7 +149,7 @@
return -1
filtering = filtering & source.gas //only filter gasses that are actually there. DO NOT USE &=
-
+
var/total_specific_power = 0 //the power required to remove one mole of input gas
var/total_filterable_moles = 0 //the total amount of filterable gas
var/total_unfilterable_moles = 0 //the total amount of non-filterable gas
@@ -144,30 +157,30 @@
for (var/g in source.gas)
if (source.gas[g] < MINUMUM_MOLES_TO_FILTER)
continue
-
+
if (g in filtering)
specific_power_gas[g] = calculate_specific_power_gas(g, source, sink_filtered)/ATMOS_FILTER_EFFICIENCY
total_filterable_moles += source.gas[g]
else
specific_power_gas[g] = calculate_specific_power_gas(g, source, sink_clean)/ATMOS_FILTER_EFFICIENCY
total_unfilterable_moles += source.gas[g]
-
+
var/ratio = source.gas[g]/source.total_moles //converts the specific power per mole of pure gas to specific power per mole of input gas mix
total_specific_power = specific_power_gas[g]*ratio
-
+
//Figure out how much of each gas to filter
- if (!total_transfer_moles)
+ if (isnull(total_transfer_moles))
total_transfer_moles = source.total_moles
else
total_transfer_moles = min(total_transfer_moles, source.total_moles)
-
+
//limit transfer_moles based on available power
if (!isnull(available_power) && total_specific_power > 0)
total_transfer_moles = min(total_transfer_moles, available_power/total_specific_power)
-
+
if (total_transfer_moles < MINUMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing
return -1
-
+
//Update flow rate var
if (istype(M, /obj/machinery/atmospherics))
var/obj/machinery/atmospherics/A = M
@@ -175,16 +188,16 @@
if (istype(M, /obj/machinery/portable_atmospherics))
var/obj/machinery/portable_atmospherics/P = M
P.last_flow_rate = (total_transfer_moles/source.total_moles)*source.volume //group_multiplier gets divided out here
-
+
var/datum/gas_mixture/removed = source.remove(total_transfer_moles)
if (!removed) //Just in case
return -1
-
+
var/filtered_power_used = 0 //power used to move filterable gas to sink_filtered
var/unfiltered_power_used = 0 //power used to move unfilterable gas to sink_clean
for (var/g in removed.gas)
var/power_used = specific_power_gas[g]*removed.gas[g]
-
+
if (g in filtering)
//use update=0. All the filtered gasses are supposed to be added simultaneously, so we update after the for loop.
sink_filtered.adjust_gas_temp(g, removed.gas[g], removed.temperature, update=0)
@@ -192,17 +205,12 @@
filtered_power_used += power_used
else
unfiltered_power_used += power_used
-
+
sink_filtered.update_values()
removed.update_values()
+
sink_clean.merge(removed)
-
- //1LTD energy is conserved
- if (filtered_power_used > 0)
- sink_filtered.add_thermal_energy(filtered_power_used)
- if (unfiltered_power_used > 0)
- sink_clean.add_thermal_energy(unfiltered_power_used)
-
+
return filtered_power_used + unfiltered_power_used
//For omni devices. Instead filtering is an associative list mapping gasids to gas mixtures.
@@ -213,7 +221,7 @@
return -1
filtering = filtering & source.gas //only filter gasses that are actually there. DO NOT USE &=
-
+
var/total_specific_power = 0 //the power required to remove one mole of input gas
var/total_filterable_moles = 0 //the total amount of filterable gas
var/total_unfilterable_moles = 0 //the total amount of non-filterable gas
@@ -221,7 +229,7 @@
for (var/g in source.gas)
if (source.gas[g] < MINUMUM_MOLES_TO_FILTER)
continue
-
+
if (g in filtering)
var/datum/gas_mixture/sink_filtered = filtering[g]
specific_power_gas[g] = calculate_specific_power_gas(g, source, sink_filtered)/ATMOS_FILTER_EFFICIENCY
@@ -229,23 +237,23 @@
else
specific_power_gas[g] = calculate_specific_power_gas(g, source, sink_clean)/ATMOS_FILTER_EFFICIENCY
total_unfilterable_moles += source.gas[g]
-
+
var/ratio = source.gas[g]/source.total_moles //converts the specific power per mole of pure gas to specific power per mole of input gas mix
total_specific_power = specific_power_gas[g]*ratio
-
+
//Figure out how much of each gas to filter
- if (!total_transfer_moles)
+ if (isnull(total_transfer_moles))
total_transfer_moles = source.total_moles
else
total_transfer_moles = min(total_transfer_moles, source.total_moles)
-
+
//limit transfer_moles based on available power
if (!isnull(available_power) && total_specific_power > 0)
total_transfer_moles = min(total_transfer_moles, available_power/total_specific_power)
-
+
if (total_transfer_moles < MINUMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing
return -1
-
+
//Update Flow Rate var
if (istype(M, /obj/machinery/atmospherics))
var/obj/machinery/atmospherics/A = M
@@ -253,16 +261,16 @@
if (istype(M, /obj/machinery/portable_atmospherics))
var/obj/machinery/portable_atmospherics/P = M
P.last_flow_rate = (total_transfer_moles/source.total_moles)*source.volume //group_multiplier gets divided out here
-
+
var/datum/gas_mixture/removed = source.remove(total_transfer_moles)
if (!removed) //Just in case
return -1
-
+
var/list/filtered_power_used = list() //power used to move filterable gas to the filtered gas mixes
var/unfiltered_power_used = 0 //power used to move unfilterable gas to sink_clean
for (var/g in removed.gas)
var/power_used = specific_power_gas[g]*removed.gas[g]
-
+
if (g in filtering)
var/datum/gas_mixture/sink_filtered = filtering[g]
//use update=0. All the filtered gasses are supposed to be added simultaneously, so we update after the for loop.
@@ -272,18 +280,15 @@
filtered_power_used[sink_filtered] = power_used
else
unfiltered_power_used += power_used
-
+
removed.update_values()
- sink_clean.merge(removed)
-
- //1st LTD energy is conserved
+
var/power_draw = unfiltered_power_used
for (var/datum/gas_mixture/sink_filtered in filtered_power_used)
power_draw += filtered_power_used[sink_filtered]
- sink_filtered.add_thermal_energy(filtered_power_used[sink_filtered])
- if (unfiltered_power_used > 0)
- sink_clean.add_thermal_energy(unfiltered_power_used)
-
+
+ sink_clean.merge(removed)
+
return power_draw
//Similar deal as the other atmos process procs.
@@ -291,7 +296,7 @@
/proc/mix_gas(var/obj/machinery/M, var/list/mix_sources, var/datum/gas_mixture/sink, var/total_transfer_moles = null, var/available_power = null)
if (!mix_sources.len)
return -1
-
+
var/total_specific_power = 0 //the power needed to mix one mole of gas
var/total_mixing_moles = null //the total amount of gas that can be mixed, given our mix ratios
var/total_input_volume = 0 //for flow rate calculation
@@ -300,36 +305,36 @@
for (var/datum/gas_mixture/source in mix_sources)
if (source.total_moles < MINUMUM_MOLES_TO_FILTER)
return -1 //either mix at the set ratios or mix no gas at all
-
+
var/mix_ratio = mix_sources[source]
if (!mix_ratio)
continue //this gas is not being mixed in
-
+
//mixing rate is limited by the source with the least amount of available gas
var/this_mixing_moles = source.total_moles/mix_ratio
if (isnull(total_mixing_moles) || total_mixing_moles > this_mixing_moles)
total_mixing_moles = this_mixing_moles
-
+
source_specific_power[source] = calculate_specific_power(source, sink)*mix_ratio/ATMOS_FILTER_EFFICIENCY
total_specific_power += source_specific_power[source]
total_input_volume += source.volume
total_input_moles += source.total_moles
-
+
if (total_mixing_moles < MINUMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing
return -1
-
- if (!total_transfer_moles)
+
+ if (isnull(total_transfer_moles))
total_transfer_moles = total_mixing_moles
else
total_transfer_moles = min(total_mixing_moles, total_transfer_moles)
-
+
//limit transfer_moles based on available power
if (!isnull(available_power) && total_specific_power > 0)
total_transfer_moles = min(total_transfer_moles, available_power / total_specific_power)
-
+
if (total_transfer_moles < MINUMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing
return -1
-
+
//Update flow rate var
if (istype(M, /obj/machinery/atmospherics))
var/obj/machinery/atmospherics/A = M
@@ -337,23 +342,22 @@
if (istype(M, /obj/machinery/portable_atmospherics))
var/obj/machinery/portable_atmospherics/P = M
P.last_flow_rate = (total_transfer_moles/total_input_moles)*total_input_volume //group_multiplier gets divided out here
-
+
var/total_power_draw = 0
for (var/datum/gas_mixture/source in mix_sources)
var/mix_ratio = mix_sources[source]
if (!mix_ratio)
continue
-
+
var/transfer_moles = total_transfer_moles * mix_ratio
-
+
var/datum/gas_mixture/removed = source.remove(transfer_moles)
-
+
var/power_draw = transfer_moles * source_specific_power[source]
- removed.add_thermal_energy(power_draw) //conservation of energy
total_power_draw += power_draw
-
+
sink.merge(removed)
-
+
return total_power_draw
/*
@@ -366,11 +370,11 @@
var/air_temperature = (sink.temperature > 0)? sink.temperature : source.temperature
var/specific_entropy = sink.specific_entropy() - source.specific_entropy() //sink is gaining moles, source is loosing
var/specific_power = 0 // W/mol
-
+
//If specific_entropy is < 0 then power is required to move gas
if (specific_entropy < 0)
specific_power = -specific_entropy*air_temperature //how much power we need per mole
-
+
return specific_power
//Calculates the amount of power needed to move one mole of a certain gas from source to sink.
@@ -379,11 +383,11 @@
var/air_temperature = (sink.temperature > 0)? sink.temperature : source.temperature
var/specific_entropy = sink.specific_entropy_gas(gasid) - source.specific_entropy_gas(gasid) //sink is gaining moles, source is loosing
var/specific_power = 0 // W/mol
-
+
//If specific_entropy is < 0 then power is required to move gas
if (specific_entropy < 0)
specific_power = -specific_entropy*air_temperature //how much power we need per mole
-
+
return specific_power
//This proc handles power usages.
@@ -399,7 +403,7 @@
use_power = 1 //Don't update here. We will use more power than we are supposed to, but trigger less area power updates.
else
update_use_power(1)
-
+
switch (use_power)
if (0) return 0
if (1) return idle_power_usage
diff --git a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
index 1da0a6eb711..c31f6f92b78 100644
--- a/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/dp_vent_pump.dm
@@ -129,7 +129,7 @@
var/transfer_moles = pressure_delta*output_volume/(air_temperature * R_IDEAL_GAS_EQUATION)
//limit flow rate from turfs
- transfer_moles = min(transfer_moles, environment.total_moles*MAX_SIPHON_FLOWRATE/environment.volume) //group_multiplier gets divided out here
+ transfer_moles = min(transfer_moles, environment.total_moles*air2.volume/environment.volume) //group_multiplier gets divided out here
power_draw = pump_gas(src, environment, air2, transfer_moles, active_power_usage)
diff --git a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
index e70b478b140..d714d7ce1f9 100644
--- a/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
+++ b/code/ATMOSPHERICS/components/binary_devices/passive_gate.dm
@@ -63,7 +63,7 @@
pressure_delta = target_pressure - output_starting_pressure
var/flowing_old = flowing
- if((REGULATE_NONE || pressure_delta > 0.01) && (air1.temperature > 0 || air2.temperature > 0)) //since it's basically a valve, it makes sense to check both temperatures
+ if((regulate_mode == REGULATE_NONE || pressure_delta > 0.01) && (air1.temperature > 0 || air2.temperature > 0)) //since it's basically a valve, it makes sense to check both temperatures
flowing = 1
//flow rate limit
diff --git a/code/ATMOSPHERICS/components/omni_devices/filter.dm b/code/ATMOSPHERICS/components/omni_devices/filter.dm
index e5188b7da49..0bb821e9eba 100644
--- a/code/ATMOSPHERICS/components/omni_devices/filter.dm
+++ b/code/ATMOSPHERICS/components/omni_devices/filter.dm
@@ -8,14 +8,14 @@
var/list/filters = new()
var/datum/omni_port/input
var/datum/omni_port/output
-
+
use_power = 1
idle_power_usage = 150 //internal circuitry, friction losses and stuff
active_power_usage = 7500 //This also doubles as a measure of how powerful the filter is, in Watts. 7500 W ~ 10 HP
-
+
var/max_flow_rate = 200
var/set_flow_rate = 200
-
+
var/list/filtering_outputs = list() //maps gasids to gas_mixtures
/obj/machinery/atmospherics/omni/filter/New()
@@ -58,32 +58,26 @@
return 0
/obj/machinery/atmospherics/omni/filter/process()
- ..()
- if(error_check())
- on = 0
-
- if((stat & (NOPOWER|BROKEN)) || !on)
- update_use_power(0) //usually we get here because a player turned a pump off - definitely want to update.
- last_flow_rate = 0
- return
-
+ if(!..())
+ return 0
+
var/datum/gas_mixture/output_air = output.air //BYOND doesn't like referencing "output.air.return_pressure()" so we need to make a direct reference
var/datum/gas_mixture/input_air = input.air // it's completely happy with them if they're in a loop though i.e. "P.air.return_pressure()"... *shrug*
-
+
//Figure out the amount of moles to transfer
var/transfer_moles = (set_flow_rate/input_air.volume)*input_air.total_moles
-
+
var/power_draw = -1
if (transfer_moles > MINUMUM_MOLES_TO_FILTER)
power_draw = filter_gas_multi(src, filtering_outputs, input_air, output_air, transfer_moles, active_power_usage)
-
+
if (power_draw < 0)
//update_use_power(0)
use_power = 0 //don't force update - easier on CPU
last_flow_rate = 0
else
handle_power_draw(power_draw)
-
+
if(input.network)
input.network.update = 1
if(output.network)
@@ -91,7 +85,7 @@
for(var/datum/omni_port/P in filters)
if(P.network)
P.network.update = 1
-
+
return 1
/obj/machinery/atmospherics/omni/filter/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
@@ -252,7 +246,7 @@
P.mode = previous_mode
if(P.mode != old_mode)
handle_port_change(P)
-
+
update_ports()
/obj/machinery/atmospherics/omni/filter/proc/rebuild_filtering_list()
diff --git a/code/ATMOSPHERICS/components/omni_devices/mixer.dm b/code/ATMOSPHERICS/components/omni_devices/mixer.dm
index 89c148a943c..b59c0281c19 100644
--- a/code/ATMOSPHERICS/components/omni_devices/mixer.dm
+++ b/code/ATMOSPHERICS/components/omni_devices/mixer.dm
@@ -17,10 +17,10 @@
var/tag_south_con
var/tag_east_con
var/tag_west_con
-
+
var/max_flow_rate = 200
var/set_flow_rate = 200
-
+
var/list/mixing_inputs = list()
/obj/machinery/atmospherics/omni/mixer/New()
@@ -45,7 +45,7 @@
if(tag_west_con && tag_west == 1)
P.concentration = tag_west_con
con += max(0, tag_west_con)
-
+
for(var/datum/omni_port/P in ports)
P.air.volume = ATMOS_DEFAULT_VOLUME_MIXER
@@ -86,32 +86,26 @@
return 1
if(inputs.len < 2) //requires at least 2 inputs ~otherwise why are you using a mixer?
return 1
-
+
//concentration must add to 1
var/total = 0
for (var/datum/omni_port/P in inputs)
total += P.concentration
-
+
if (total != 1)
return 1
return 0
/obj/machinery/atmospherics/omni/mixer/process()
- ..()
- if(error_check())
- on = 0
-
- if((stat & (NOPOWER|BROKEN)) || !on)
- update_use_power(0) //usually we get here because a player turned a pump off - definitely want to update.
- last_flow_rate = 0
- return
-
+ if(!..())
+ return 0
+
//Figure out the amount of moles to transfer
var/transfer_moles = 0
for (var/datum/omni_port/P in inputs)
transfer_moles += (set_flow_rate*P.concentration/P.air.volume)*P.air.total_moles
-
+
var/power_draw = -1
if (transfer_moles > MINUMUM_MOLES_TO_FILTER)
power_draw = mix_gas(src, mixing_inputs, output, transfer_moles, active_power_usage)
@@ -122,14 +116,14 @@
last_flow_rate = 0
else
handle_power_draw(power_draw)
-
+
for(var/datum/omni_port/P in inputs)
if(P.concentration && P.network)
P.network.update = 1
if(output.network)
output.network.update = 1
-
+
return 1
/obj/machinery/atmospherics/omni/mixer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
@@ -291,7 +285,7 @@
P.concentration = new_con
else if(!P.con_lock)
P.concentration = remain_con
-
+
rebuild_mixing_inputs()
/obj/machinery/atmospherics/omni/mixer/proc/rebuild_mixing_inputs()
diff --git a/code/ATMOSPHERICS/components/omni_devices/omni_base.dm b/code/ATMOSPHERICS/components/omni_devices/omni_base.dm
index eb5fbe7abee..7a24bf2fbb5 100644
--- a/code/ATMOSPHERICS/components/omni_devices/omni_base.dm
+++ b/code/ATMOSPHERICS/components/omni_devices/omni_base.dm
@@ -50,10 +50,8 @@
/obj/machinery/atmospherics/omni/update_icon()
if(stat & NOPOWER)
overlays = overlays_off
- on = 0
else if(error_check())
overlays = overlays_error
- on = 0
else
overlays = on ? (overlays_on) : (overlays_off)
@@ -64,6 +62,16 @@
/obj/machinery/atmospherics/omni/proc/error_check()
return
+/obj/machinery/atmospherics/omni/process()
+ if(error_check())
+ on = 0
+
+ if((stat & (NOPOWER|BROKEN)) || !on)
+ update_use_power(0) //usually we get here because a player turned a pump off - definitely want to update.
+ last_flow_rate = 0
+ return 0
+ return 1
+
/obj/machinery/atmospherics/omni/power_change()
var/old_stat = stat
..()
diff --git a/code/ATMOSPHERICS/components/trinary_devices/filter.dm b/code/ATMOSPHERICS/components/trinary_devices/filter.dm
index 7590c453e44..5649b25e012 100755
--- a/code/ATMOSPHERICS/components/trinary_devices/filter.dm
+++ b/code/ATMOSPHERICS/components/trinary_devices/filter.dm
@@ -23,7 +23,7 @@
3: Carbon Dioxide: Carbon Dioxide ONLY
4: Sleeping Agent (N2O)
*/
- var/filter_type = 0
+ var/filter_type = -1
var/list/filtered_out = list()
@@ -38,6 +38,18 @@
/obj/machinery/atmospherics/trinary/filter/New()
..()
+ switch(filter_type)
+ if(0) //removing hydrocarbons
+ filtered_out = list("phoron", "oxygen_agent_b")
+ if(1) //removing O2
+ filtered_out = list("oxygen")
+ if(2) //removing N2
+ filtered_out = list("nitrogen")
+ if(3) //removing CO2
+ filtered_out = list("carbon_dioxide")
+ if(4)//removing N2O
+ filtered_out = list("sleeping_agent")
+
air1.volume = ATMOS_DEFAULT_VOLUME_FILTER
air2.volume = ATMOS_DEFAULT_VOLUME_FILTER
air3.volume = ATMOS_DEFAULT_VOLUME_FILTER
diff --git a/code/ATMOSPHERICS/components/unary/cold_sink.dm b/code/ATMOSPHERICS/components/unary/cold_sink.dm
index d49de4adf25..bd3c3b17965 100644
--- a/code/ATMOSPHERICS/components/unary/cold_sink.dm
+++ b/code/ATMOSPHERICS/components/unary/cold_sink.dm
@@ -1,3 +1,6 @@
+//TODO: Put this under a common parent type with heaters to cut down on the copypasta
+#define FREEZER_PERF_MULT 2.5
+
/obj/machinery/atmospherics/unary/freezer
name = "gas cooling system"
desc = "Cools gas when connected to pipe network"
@@ -7,14 +10,17 @@
anchored = 1.0
- var/heatsink_temperature = T20C //the constant temperature resevoir into which the freezer pumps heat. Probably the hull of the station or something.
+ var/heatsink_temperature = T20C //the constant temperature resevoir into which the freezer pumps heat. Probably the hull of the station or something.
var/internal_volume = 600 //L
-
+
var/on = 0
use_power = 0
- idle_power_usage = 5 //5 Watts for thermostat related circuitry
- active_power_usage = 50000 //50 kW. The power rating of the freezer
-
+ idle_power_usage = 5 //5 Watts for thermostat related circuitry
+ active_power_usage //50 kW. The power rating of the freezer
+
+ var/max_power_usage = 20000 //power rating when the usage is turned up to 100
+ var/power_setting = 100
+
var/set_temperature = T20C //thermostat
var/cooling = 0
var/opened = 0 //for deconstruction
@@ -23,14 +29,16 @@
..()
air_contents.volume = internal_volume
initialize_directions = dir
-
+
component_parts = list()
- component_parts += new /obj/item/weapon/circuitboard/gas_cooler(src)
+ component_parts += new /obj/item/weapon/circuitboard/unary_atmos/cooler(src)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/weapon/stock_parts/manipulator(src)
+ active_power_usage = max_power_usage * (power_setting/100)
+
/obj/machinery/atmospherics/unary/freezer/initialize()
if(node) return
@@ -72,7 +80,8 @@
data["minGasTemperature"] = 0
data["maxGasTemperature"] = round(T20C+500)
data["targetGasTemperature"] = round(set_temperature)
-
+ data["powerSetting"] = power_setting
+
var/temp_class = "good"
if (air_contents.temperature > (T0C - 20))
temp_class = "bad"
@@ -104,6 +113,9 @@
src.set_temperature = min(src.set_temperature+amount, 1000)
else
src.set_temperature = max(src.set_temperature+amount, 0)
+ if(href_list["setPower"]) //setting power to 0 is redundant anyways
+ var/new_setting = between(0, text2num(href_list["setPower"]), 100)
+ set_power_level(new_setting)
src.add_fingerprint(usr)
return 1
@@ -113,30 +125,33 @@
if(stat & (NOPOWER|BROKEN) || !on)
cooling = 0
update_use_power(0)
+ update_icon()
return
-
+
if (network && air_contents.temperature > set_temperature)
cooling = 1
update_use_power(2)
-
- var/heat_transfer = min(abs(air_contents.get_thermal_energy_change(set_temperature)), active_power_usage)
+
+ var/heat_transfer = max( -air_contents.get_thermal_energy_change(set_temperature - 5), 0 )
//Assume the heat is being pumped into the hull which is fixed at heatsink_temperature
//not /really/ proper thermodynamics but whatever
- var/cop = air_contents.temperature/heatsink_temperature //heatpump coefficient of performance from thermodynamics -> power used = heat_transfer/cop
+ var/cop = FREEZER_PERF_MULT * air_contents.temperature/heatsink_temperature //heatpump coefficient of performance from thermodynamics -> power used = heat_transfer/cop
heat_transfer = min(heat_transfer, cop * active_power_usage) //limit heat transfer by available power
- air_contents.add_thermal_energy(-heat_transfer) //remove the heat
-
+ var/removed = -air_contents.add_thermal_energy(-heat_transfer) //remove the heat
+ if (debug)
+ visible_message("[src]: Removing [removed] W.")
+
network.update = 1
else
cooling = 0
update_use_power(1)
-
+
update_icon()
//upgrading parts
-/obj/machinery/atmospherics/unary/freezer/RefreshParts()
+/obj/machinery/atmospherics/unary/freezer/RefreshParts()
..()
var/cap_rating = 0
var/cap_count = 0
@@ -144,7 +159,7 @@
var/manip_count = 0
var/bin_rating = 0
var/bin_count = 0
-
+
for(var/obj/item/weapon/stock_parts/P in component_parts)
if(istype(P, /obj/item/weapon/stock_parts/capacitor))
cap_rating += P.rating
@@ -158,10 +173,20 @@
cap_rating /= cap_count
bin_rating /= bin_count
manip_rating /= manip_count
-
+
active_power_usage = initial(active_power_usage)*cap_rating //more powerful
heatsink_temperature = initial(heatsink_temperature)/((manip_rating+bin_rating)/2) //more efficient
air_contents.volume = max(initial(internal_volume) - 200, 0) + 200*bin_rating
+ set_power_level(power_setting)
+
+/obj/machinery/atmospherics/unary/freezer/proc/set_power_level(var/new_power_setting)
+ power_setting = new_power_setting
+
+ var/old_power_usage = active_power_usage
+ active_power_usage = max_power_usage * (power_setting/100)
+
+ if (use_power >= 2 && old_power_usage != active_power_usage)
+ force_power_update()
//dismantling code. copied from autolathe
/obj/machinery/atmospherics/unary/freezer/attackby(var/obj/item/O as obj, var/mob/user as mob)
@@ -173,7 +198,7 @@
if (opened && istype(O, /obj/item/weapon/crowbar))
dismantle()
return
-
+
..()
/obj/machinery/atmospherics/unary/freezer/examine()
diff --git a/code/ATMOSPHERICS/components/unary/heat_source.dm b/code/ATMOSPHERICS/components/unary/heat_source.dm
index f65de389458..707e740f66e 100644
--- a/code/ATMOSPHERICS/components/unary/heat_source.dm
+++ b/code/ATMOSPHERICS/components/unary/heat_source.dm
@@ -1,3 +1,5 @@
+//TODO: Put this under a common parent type with freezers to cut down on the copypasta
+
/obj/machinery/atmospherics/unary/heater
name = "gas heating system"
desc = "Heats gas when connected to a pipe network"
@@ -13,9 +15,12 @@
var/on = 0
use_power = 0
- idle_power_usage = 5 //5 Watts for thermostat related circuitry
- active_power_usage = 50000 //50 kW. The power rating of the heater
+ idle_power_usage = 5 //5 Watts for thermostat related circuitry
+ active_power_usage //50 kW. The power rating of the heater
+ var/max_power_usage = 20000 //power rating when the usage is turned up to 100
+ var/power_setting = 100
+
var/heating = 0 //mainly for icon updates
var/opened = 0 //for deconstruction
@@ -23,12 +28,14 @@
..()
air_contents.volume = internal_volume
initialize_directions = dir
-
+
component_parts = list()
- component_parts += new /obj/item/weapon/circuitboard/gas_heater(src)
+ component_parts += new /obj/item/weapon/circuitboard/unary_atmos/heater(src)
component_parts += new /obj/item/weapon/stock_parts/matter_bin(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
component_parts += new /obj/item/weapon/stock_parts/capacitor(src)
+
+ active_power_usage = max_power_usage * (power_setting/100)
/obj/machinery/atmospherics/unary/heater/initialize()
if(node) return
@@ -52,26 +59,27 @@
else
icon_state = "heater_0"
return
-
+
/obj/machinery/atmospherics/unary/heater/process()
..()
-
+
if(stat & (NOPOWER|BROKEN) || !on)
heating = 0
update_use_power(0)
+ update_icon()
return
-
- if (network && air_contents.temperature < set_temperature)
+
+ if (network && air_contents.total_moles && air_contents.temperature < set_temperature)
update_use_power(2)
air_contents.add_thermal_energy(active_power_usage)
-
+
heating = 1
network.update = 1
else
heating = 0
update_use_power(1)
-
+
update_icon()
/obj/machinery/atmospherics/unary/heater/attack_ai(mob/user as mob)
@@ -82,7 +90,7 @@
/obj/machinery/atmospherics/unary/heater/attack_hand(mob/user as mob)
src.ui_interact(user)
-
+
/obj/machinery/atmospherics/unary/heater/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
// this is the data which will be sent to the ui
var/data[0]
@@ -92,7 +100,8 @@
data["minGasTemperature"] = 0
data["maxGasTemperature"] = round(max_temperature)
data["targetGasTemperature"] = round(set_temperature)
-
+ data["powerSetting"] = power_setting
+
var/temp_class = "normal"
if (air_contents.temperature > (T20C+40))
temp_class = "bad"
@@ -122,14 +131,17 @@
src.set_temperature = min(src.set_temperature+amount, max_temperature)
else
src.set_temperature = max(src.set_temperature+amount, 0)
-
+ if(href_list["setPower"]) //setting power to 0 is redundant anyways
+ var/new_setting = between(0, text2num(href_list["setPower"]), 100)
+ set_power_level(new_setting)
+
src.add_fingerprint(usr)
return 1
//upgrading parts
-/obj/machinery/atmospherics/unary/heater/RefreshParts()
+/obj/machinery/atmospherics/unary/heater/RefreshParts()
..()
-
+
var/cap_rating = 0
var/cap_count = 0
var/bin_rating = 0
@@ -143,10 +155,20 @@
bin_count++
cap_rating /= cap_count
bin_rating /= bin_count
-
- active_power_usage = initial(active_power_usage)*cap_rating
+
+ max_power_usage = initial(max_power_usage)*cap_rating
max_temperature = max(initial(max_temperature) - T20C, 0)*((bin_rating*2 + cap_rating)/3) + T20C
air_contents.volume = max(initial(internal_volume) - 200, 0) + 200*bin_rating
+ set_power_level(power_setting)
+
+/obj/machinery/atmospherics/unary/heater/proc/set_power_level(var/new_power_setting)
+ power_setting = new_power_setting
+
+ var/old_power_usage = active_power_usage
+ active_power_usage = max_power_usage * (power_setting/100)
+
+ if (use_power >= 2 && old_power_usage != active_power_usage)
+ force_power_update()
//dismantling code. copied from autolathe
/obj/machinery/atmospherics/unary/heater/attackby(var/obj/item/O as obj, var/mob/user as mob)
@@ -158,7 +180,7 @@
if (opened && istype(O, /obj/item/weapon/crowbar))
dismantle()
return
-
+
..()
/obj/machinery/atmospherics/unary/heater/examine()
diff --git a/code/ATMOSPHERICS/components/unary/outlet_injector.dm b/code/ATMOSPHERICS/components/unary/outlet_injector.dm
index fb32ade3d28..d603da8cd14 100644
--- a/code/ATMOSPHERICS/components/unary/outlet_injector.dm
+++ b/code/ATMOSPHERICS/components/unary/outlet_injector.dm
@@ -1,6 +1,6 @@
//Basically a one way passive valve. If the pressure inside is greater than the environment then gas will flow passively,
//but it does not permit gas to flow back from the environment into the injector. Can be turned off to prevent any gas flow.
-//When it recieves the "inject" signal, it will try to pump it's entire contents into the environment regardless of pressure, using power.
+//When it receives the "inject" signal, it will try to pump it's entire contents into the environment regardless of pressure, using power.
/obj/machinery/atmospherics/unary/outlet_injector
icon = 'icons/atmos/injector.dmi'
@@ -12,8 +12,8 @@
desc = "Passively injects air into its surroundings. Has a valve attached to it that can control flow rate."
use_power = 1
- idle_power_usage = 5 //internal circuitry
- var/inject_power = 15000 //15000 kW ~ 20 HP
+ idle_power_usage = 150 //internal circuitry, friction losses and stuff
+ active_power_usage = 15000 //This also doubles as a measure of how powerful the pump is, in Watts. 15000 W ~ 20 HP
var/on = 0
var/injecting = 0
@@ -54,26 +54,28 @@
..()
injecting = 0
- if(!on) //only uses power when injecting
- return 0
+ if((stat & (NOPOWER|BROKEN)) || !on)
+ update_use_power(0) //usually we get here because a player turned a pump off - definitely want to update.
+ last_flow_rate = 0
+ return
+ var/power_draw = -1
var/datum/gas_mixture/environment = loc.return_air()
-
+
if(environment && air_contents.temperature > 0)
- var/air_temperature = environment.temperature? environment.temperature : air_contents.temperature
- var/pressure_delta = air_contents.return_pressure() - environment.return_pressure()
- var/output_volume = environment.volume * environment.group_multiplier
-
- if (pressure_delta > 0.01)
- var/transfer_moles = pressure_delta*output_volume/(air_temperature * R_IDEAL_GAS_EQUATION)
- transfer_moles = min(transfer_moles, (volume_rate/air_contents.volume)*air_contents.total_moles) //apply flow rate limit
-
- var/datum/gas_mixture/removed = air_contents.remove(transfer_moles)
- loc.assume_air(removed)
-
- if(network)
- network.update = 1
-
+ var/transfer_moles = (volume_rate/air_contents.volume)*air_contents.total_moles //apply flow rate limit
+ power_draw = pump_gas(src, air_contents, environment, transfer_moles, active_power_usage)
+
+ if (power_draw < 0)
+ //update_use_power(0)
+ use_power = 0 //don't force update - easier on CPU
+ last_flow_rate = 0
+ else
+ handle_power_draw(power_draw)
+
+ if(network)
+ network.update = 1
+
return 1
/obj/machinery/atmospherics/unary/outlet_injector/proc/inject()
@@ -87,7 +89,7 @@
injecting = 1
if(air_contents.temperature > 0)
- var/power_used = pump_gas(src, air_contents, environment, air_contents.total_moles, inject_power)
+ var/power_used = pump_gas(src, air_contents, environment, air_contents.total_moles, active_power_usage)
use_power(power_used)
if(network)
diff --git a/code/ATMOSPHERICS/components/unary/vent_pump.dm b/code/ATMOSPHERICS/components/unary/vent_pump.dm
index 0a9eb3ce800..80b168aabd1 100644
--- a/code/ATMOSPHERICS/components/unary/vent_pump.dm
+++ b/code/ATMOSPHERICS/components/unary/vent_pump.dm
@@ -88,6 +88,15 @@
..()
air_contents.volume = ATMOS_DEFAULT_VOLUME_PUMP + 800
+/obj/machinery/atmospherics/unary/vent_pump/engine
+ name = "Engine Core Vent"
+ power_channel = ENVIRON
+ active_power_usage = 15000 //15 kW ~ 20 HP
+
+/obj/machinery/atmospherics/unary/vent_pump/engine/New()
+ ..()
+ air_contents.volume = ATMOS_DEFAULT_VOLUME_PUMP + 500 //meant to match air injector
+
/obj/machinery/atmospherics/unary/vent_pump/update_icon(var/safety = 0)
if(!check_icon_cache())
return
@@ -174,7 +183,7 @@
var/transfer_moles = pressure_delta*output_volume/(air_temperature * R_IDEAL_GAS_EQUATION)
//limit flow rate from turfs
- transfer_moles = min(transfer_moles, environment.total_moles*MAX_SIPHON_FLOWRATE/environment.volume) //group_multiplier gets divided out here
+ transfer_moles = min(transfer_moles, environment.total_moles*air_contents.volume/environment.volume) //group_multiplier gets divided out here
power_draw = pump_gas(src, environment, air_contents, transfer_moles, active_power_usage)
diff --git a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
index 0e719addc97..dcd052dd99f 100644
--- a/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
+++ b/code/ATMOSPHERICS/components/unary/vent_scrubber.dm
@@ -20,7 +20,7 @@
var/on = 0
var/scrubbing = 1 //0 = siphoning, 1 = scrubbing
- var/list/scrubbing_gas = list()
+ var/list/scrubbing_gas = list("carbon_dioxide")
var/panic = 0 //is this scrubber panicked?
diff --git a/code/ATMOSPHERICS/datum_pipeline.dm b/code/ATMOSPHERICS/datum_pipeline.dm
index ca062775513..aa4473babd5 100644
--- a/code/ATMOSPHERICS/datum_pipeline.dm
+++ b/code/ATMOSPHERICS/datum_pipeline.dm
@@ -202,6 +202,9 @@ datum/pipeline
//surface must be the surface area in m^2
proc/radiate_heat_to_space(surface, thermal_conductivity)
+ var/gas_density = air.total_moles/air.volume
+ thermal_conductivity *= min(gas_density / ( RADIATOR_OPTIMUM_PRESSURE/(R_IDEAL_GAS_EQUATION*T20C) ), 1)
+
//if the h/e pipes radiate less than the AVERAGE_SOLAR_RADIATION, then they will heat up, otherwise they will cool down. It turns out the critical temperature is -26 C
var/heat_gain = surface*(AVERAGE_SOLAR_RADIATION - STEFAN_BOLTZMANN_CONSTANT*thermal_conductivity*(air.temperature - COSMIC_RADIATION_TEMPERATURE) ** 4)
diff --git a/code/ATMOSPHERICS/he_pipes.dm b/code/ATMOSPHERICS/he_pipes.dm
index 607e974ee44..c22c483e8c4 100644
--- a/code/ATMOSPHERICS/he_pipes.dm
+++ b/code/ATMOSPHERICS/he_pipes.dm
@@ -1,7 +1,8 @@
obj/machinery/atmospherics/pipe/simple/heat_exchanging
- icon = 'icons/obj/pipes/heat.dmi'
+ icon = 'icons/atmos/heat.dmi'
icon_state = "intact"
+ pipe_icon = "hepipe"
level = 2
var/initialize_directions_he
var/surface = 2 //surface area in m^2
@@ -35,6 +36,10 @@ obj/machinery/atmospherics/pipe/simple/heat_exchanging
if(target.initialize_directions_he & get_dir(target,src))
node2 = target
break
+ if(!node1 && !node2)
+ del(src)
+ return
+
update_icon()
return
@@ -58,8 +63,9 @@ obj/machinery/atmospherics/pipe/simple/heat_exchanging
obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction
- icon = 'icons/obj/pipes/junction.dmi'
+ icon = 'icons/atmos/junction.dmi'
icon_state = "intact"
+ pipe_icon = "hejunction"
level = 2
minimum_temperature_difference = 300
thermal_conductivity = WALL_HEAT_TRANSFER_COEFFICIENT
@@ -82,16 +88,6 @@ obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction
initialize_directions_he = WEST
// BubbleWrap END
- update_icon()
- if(node1&&node2)
- icon_state = "intact"
- else
- var/have_node1 = node1?1:0
- var/have_node2 = node2?1:0
- icon_state = "exposed[have_node1][have_node2]"
- if(!node1&&!node2)
- del(src)
-
initialize()
for(var/obj/machinery/atmospherics/target in get_step(src,initialize_directions))
if(target.initialize_directions & get_dir(target,src))
@@ -102,5 +98,9 @@ obj/machinery/atmospherics/pipe/simple/heat_exchanging/junction
node2 = target
break
+ if(!node1&&!node2)
+ del(src)
+ return
+
update_icon()
return
diff --git a/code/ATMOSPHERICS/pipes.dm b/code/ATMOSPHERICS/pipes.dm
index 72598779394..77249a4e7e9 100644
--- a/code/ATMOSPHERICS/pipes.dm
+++ b/code/ATMOSPHERICS/pipes.dm
@@ -15,7 +15,7 @@
/obj/machinery/atmospherics/pipe/New()
..()
//so pipes under walls are hidden
- if(!istype(get_turf(src), /turf/simulated/floor))
+ if(istype(get_turf(src), /turf/simulated/wall) || istype(get_turf(src), /turf/simulated/shuttle/wall) || istype(get_turf(src), /turf/unsimulated/wall))
level = 1
/obj/machinery/atmospherics/pipe/proc/pipeline_expansion()
@@ -137,6 +137,7 @@
/obj/machinery/atmospherics/pipe/simple
icon = 'icons/atmos/pipes.dmi'
icon_state = ""
+ var/pipe_icon = "" //what kind of pipe it is and from which dmi is the icon manager getting its icons, "" for simple pipes, "hepipe" for HE pipes, "hejunction" for HE junctions
name = "pipe"
desc = "A one meter section of regular pipe"
@@ -571,6 +572,10 @@
if (node3)
break
+ if(!node1 && !node2 && !node3)
+ del(src)
+ return
+
var/turf/T = get_turf(src)
if(istype(T))
hide(T.intact)
@@ -825,6 +830,10 @@
node4 = target
break
+ if(!node1 && !node2 && !node3 && !node4)
+ del(src)
+ return
+
var/turf/T = get_turf(src)
if(istype(T))
hide(T.intact)
@@ -1028,6 +1037,7 @@
desc = "A large vessel containing pressurized gas."
volume = 10000 //in liters, 1 meters by 1 meters by 2 meters ~tweaked it a little to simulate a pressure tank without needing to recode them yet
+ var/start_pressure = 25*ONE_ATMOSPHERE
level = 1
dir = SOUTH
@@ -1120,8 +1130,8 @@
air_temporary.volume = volume
air_temporary.temperature = T20C
- air_temporary.adjust_multi("oxygen", (25*ONE_ATMOSPHERE*O2STANDARD)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature), \
- "nitrogen",(25*ONE_ATMOSPHERE*N2STANDARD)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+ air_temporary.adjust_multi("oxygen", (start_pressure*O2STANDARD)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature), \
+ "nitrogen",(start_pressure*N2STANDARD)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
..()
@@ -1136,7 +1146,7 @@
air_temporary.volume = volume
air_temporary.temperature = T20C
- air_temporary.adjust_gas("oxygen", (25*ONE_ATMOSPHERE)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+ air_temporary.adjust_gas("oxygen", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
..()
icon_state = "o2"
@@ -1150,7 +1160,7 @@
air_temporary.volume = volume
air_temporary.temperature = T20C
- air_temporary.adjust_gas("nitrogen", (25*ONE_ATMOSPHERE)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+ air_temporary.adjust_gas("nitrogen", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
..()
icon_state = "n2"
@@ -1164,7 +1174,7 @@
air_temporary.volume = volume
air_temporary.temperature = T20C
- air_temporary.adjust_gas("carbon_dioxide", (25*ONE_ATMOSPHERE)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+ air_temporary.adjust_gas("carbon_dioxide", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
..()
icon_state = "co2"
@@ -1178,7 +1188,7 @@
air_temporary.volume = volume
air_temporary.temperature = T20C
- air_temporary.adjust_gas("phoron", (25*ONE_ATMOSPHERE)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+ air_temporary.adjust_gas("phoron", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
..()
icon_state = "phoron"
@@ -1192,7 +1202,7 @@
air_temporary.volume = volume
air_temporary.temperature = T0C
- air_temporary.adjust_gas("sleeping_agent", (25*ONE_ATMOSPHERE)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
+ air_temporary.adjust_gas("sleeping_agent", (start_pressure)*(air_temporary.volume)/(R_IDEAL_GAS_EQUATION*air_temporary.temperature))
..()
icon_state = "n2o"
diff --git a/code/WorkInProgress/kilakk/fax.dm b/code/WorkInProgress/kilakk/fax.dm
index 2934d2ed746..2c342296207 100644
--- a/code/WorkInProgress/kilakk/fax.dm
+++ b/code/WorkInProgress/kilakk/fax.dm
@@ -5,7 +5,7 @@ var/list/alldepartments = list("Central Command")
name = "fax machine"
icon = 'icons/obj/library.dmi'
icon_state = "fax"
- req_one_access = list(access_lawyer, access_heads)
+ req_one_access = list(access_lawyer, access_heads, access_armory) //Warden needs to be able to Fax solgov too.
anchored = 1
density = 1
use_power = 1
@@ -23,12 +23,14 @@ var/list/alldepartments = list("Central Command")
var/dpt = "Central Command" // the department we're sending to
+
/obj/machinery/faxmachine/New()
..()
allfaxes += src
if( !("[department]" in alldepartments) )
alldepartments += department
+ alldepartments += "Sol Government"
/obj/machinery/faxmachine/process()
return 0
@@ -95,9 +97,12 @@ var/list/alldepartments = list("Central Command")
if(tofax)
if(dpt == "Central Command")
- Centcomm_fax(tofax.info, tofax.name, usr)
+ Centcomm_fax(src, tofax.info, tofax.name, usr)
sendcooldown = 1800
+ else if(dpt == "Sol Government")
+ Solgov_fax(src, tofax.info, tofax.name, usr)
+ sendcooldown = 1800
else
SendFax(tofax.info, tofax.name, usr, dpt)
sendcooldown = 600
@@ -177,11 +182,18 @@ var/list/alldepartments = list("Central Command")
user << "You [anchored ? "wrench" : "unwrench"] \the [src]."
return
-/proc/Centcomm_fax(var/sent, var/sentname, var/mob/Sender)
+/proc/Centcomm_fax(var/originfax, var/sent, var/sentname, var/mob/Sender)
+
+ var/msg = "\blue CENTCOMM FAX: [key_name(Sender, 1)] (PP) (VV) (SM) (JMP) (CA) (RPLY): Receiving '[sentname]' via secure connection ... view message"
- var/msg = "\blue CENTCOMM FAX: [key_name(Sender, 1)] (PP) (VV) (SM) (JMP) (CA) (RPLY): Receiving '[sentname]' via secure connection ... view message"
admins << msg
+/proc/Solgov_fax(var/originfax, var/sent, var/sentname, var/mob/Sender)
+ var/msg = "\blue SOL GOVERNMENT FAX: [key_name(Sender, 1)] (PP) (VV) (SM) (JMP) (CA) (RPLY): Receiving '[sentname]' via secure connection ... view message"
+
+ admins << msg
+
+
proc/SendFax(var/sent, var/sentname, var/mob/Sender, var/dpt)
for(var/obj/machinery/faxmachine/F in allfaxes)
diff --git a/code/ZAS/Turf.dm b/code/ZAS/Turf.dm
index 4e70e3b627f..e3a28fe3d47 100644
--- a/code/ZAS/Turf.dm
+++ b/code/ZAS/Turf.dm
@@ -1,15 +1,14 @@
/turf/simulated/var/zone/zone
/turf/simulated/var/open_directions
-/turf/simulated/var/gas_graphic
/turf/var/needs_air_update = 0
/turf/var/datum/gas_mixture/air
-/turf/simulated/proc/set_graphic(new_graphic)
- gas_graphic = new_graphic
- overlays.Cut()
- for(var/i in gas_graphic)
- overlays += i
+/turf/simulated/proc/update_graphic(list/graphic_add = null, list/graphic_remove = null)
+ if(graphic_add)
+ overlays += graphic_add
+ if(graphic_remove)
+ overlays -= graphic_remove
/turf/proc/update_air_properties()
var/block = c_airblock(src)
diff --git a/code/ZAS/Zone.dm b/code/ZAS/Zone.dm
index 40c509bbd90..e794c36b02a 100644
--- a/code/ZAS/Zone.dm
+++ b/code/ZAS/Zone.dm
@@ -51,6 +51,9 @@ Class Procs:
/zone/var/datum/gas_mixture/air = new
+/zone/var/list/graphic_add = list()
+/zone/var/list/graphic_remove = list()
+
/zone/New()
air_master.add_zone(src)
air.temperature = TCMB
@@ -71,7 +74,7 @@ Class Procs:
if(T.fire)
fire_tiles.Add(T)
air_master.active_fire_zones.Add(src)
- T.set_graphic(air.graphic)
+ T.update_graphic(air.graphic)
/zone/proc/remove(turf/simulated/T)
#ifdef ZASDBG
@@ -83,7 +86,7 @@ Class Procs:
contents.Remove(T)
fire_tiles.Remove(T)
T.zone = null
- T.set_graphic(0)
+ T.update_graphic(graphic_remove = air.graphic)
if(contents.len)
air.group_multiplier = contents.len
else
@@ -128,9 +131,11 @@ Class Procs:
air.group_multiplier = contents.len+1
/zone/proc/tick()
- if(air.check_tile_graphic())
+ if(air.check_tile_graphic(graphic_add, graphic_remove))
for(var/turf/simulated/T in contents)
- T.set_graphic(air.graphic)
+ T.update_graphic(graphic_add, graphic_remove)
+ graphic_add.len = 0
+ graphic_remove.len = 0
/zone/proc/dbg_data(mob/M)
M << name
diff --git a/code/ZAS/_gas_mixture_xgm.dm b/code/ZAS/_gas_mixture_xgm.dm
index 1f31cc6e96e..01f95ee9a58 100644
--- a/code/ZAS/_gas_mixture_xgm.dm
+++ b/code/ZAS/_gas_mixture_xgm.dm
@@ -112,7 +112,7 @@
//Returns the thermal energy change required to get to a new temperature
/datum/gas_mixture/proc/get_thermal_energy_change(var/new_temperature)
- return heat_capacity()*(new_temperature - temperature)
+ return heat_capacity()*(max(new_temperature, 0) - temperature)
//Technically vacuum doesn't have a specific entropy. Just use a really big number (infinity would be ideal) here so that it's easy to add gas to vacuum and hard to take gas out.
#define SPECIFIC_ENTROPY_VACUUM 150000
@@ -124,19 +124,32 @@
. = 0
for(var/g in gas)
- var/ratio = gas[g] / total_moles
- . += ratio * specific_entropy_gas(g)
+ . += gas[g] * specific_entropy_gas(g)
. /= total_moles
-//Returns the ideal gas specific entropy of a specific gas in the mix. This is the entropy due to that gas per mole of /that/ gas in the mixture, not the entropy due to that gas per mole of gas mixture.
+/*
+ It's arguable whether this should even be called entropy anymore. It's more "based on" entropy than actually entropy now.
+
+ Returns the ideal gas specific entropy of a specific gas in the mix. This is the entropy due to that gas per mole of /that/ gas in the mixture, not the entropy due to that gas per mole of gas mixture.
+
+ For the purposes of SS13, the specific entropy is just a number that tells you how hard it is to move gas. You can replace this with whatever you want.
+ Just remember that returning a SMALL number == adding gas to this gas mix is HARD, taking gas away is EASY, and that returning a LARGE number means the opposite (so a vacuum should approach infinity).
+
+ So returning a constant/(partial pressure) would probably do what most players expect. Although the version I have implemented below is a bit more nuanced than simply 1/P in that it scales in a way
+ which is bit more realistic (natural log), and returns a fairly accurate entropy around room temperatures and pressures.
+*/
/datum/gas_mixture/proc/specific_entropy_gas(var/gasid)
if (!(gasid in gas) || gas[gasid] == 0)
return SPECIFIC_ENTROPY_VACUUM //that gas isn't here
+ //group_multiplier gets divided out in volume/gas[gasid] - also, V/(m*T) = R/(partial pressure)
var/molar_mass = gas_data.molar_mass[gasid]
var/specific_heat = gas_data.specific_heat[gasid]
- //group_multiplier gets divided out in volume/gas[gasid]
- return R_IDEAL_GAS_EQUATION * ( log( (IDEAL_GAS_ENTROPY_CONSTANT*volume/gas[gasid]) * sqrt((molar_mass*specific_heat*temperature)**3) + 1 ) + 5/2 )
+ return R_IDEAL_GAS_EQUATION * ( log( (IDEAL_GAS_ENTROPY_CONSTANT*volume/(gas[gasid] * temperature)) * (molar_mass*specific_heat*temperature)**(2/3) + 1 ) + 15 )
+
+ //alternative, simpler equation
+ //var/partial_pressure = gas[gasid] * R_IDEAL_GAS_EQUATION * temperature / volume
+ //return R_IDEAL_GAS_EQUATION * ( log (1 + IDEAL_GAS_ENTROPY_CONSTANT/partial_pressure) + 20 )
//Updates the total_moles count and trims any empty gases.
/datum/gas_mixture/proc/update_values()
@@ -255,12 +268,8 @@
zburn(null)
//Rechecks the gas_mixture and adjusts the graphic list if needed.
-/datum/gas_mixture/proc/check_tile_graphic()
- //List of new overlays that weren't valid before.
- var/list/graphic_add = null
- //List of overlays that need to be removed now that they're not valid.
- var/list/graphic_remove = null
-
+//Two lists can be passed by reference if you need know specifically which graphics were added and removed.
+/datum/gas_mixture/proc/check_tile_graphic(list/graphic_add = null, list/graphic_remove = null)
for(var/g in gas_data.overlay_limit)
if(graphic.Find(gas_data.tile_overlay[g]))
//Overlay is already applied for this gas, check if it's still valid.
diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm
index 77ed7f308e6..8c6befa38f8 100644
--- a/code/__HELPERS/game.dm
+++ b/code/__HELPERS/game.dm
@@ -398,4 +398,65 @@ datum/projectile_data
var/r = mixOneColor(weights, reds)
var/g = mixOneColor(weights, greens)
var/b = mixOneColor(weights, blues)
- return rgb(r,g,b)
\ No newline at end of file
+ return rgb(r,g,b)
+
+/**
+* Gets the highest and lowest pressures from the tiles in cardinal directions
+* around us, then checks the difference.
+*/
+/proc/getOPressureDifferential(var/turf/loc)
+ var/minp=16777216;
+ var/maxp=0;
+ for(var/dir in cardinal)
+ var/turf/simulated/T=get_turf(get_step(loc,dir))
+ var/cp=0
+ if(T && istype(T) && T.zone)
+ var/datum/gas_mixture/environment = T.return_air()
+ cp = environment.return_pressure()
+ else
+ if(istype(T,/turf/simulated))
+ continue
+ if(cpmaxp)maxp=cp
+ return abs(minp-maxp)
+
+/proc/convert_k2c(var/temp)
+ return ((temp - T0C))
+
+/proc/convert_c2k(var/temp)
+ return ((temp + T0C))
+
+/proc/getCardinalAirInfo(var/turf/loc, var/list/stats=list("temperature"))
+ var/list/temps = new/list(4)
+ for(var/dir in cardinal)
+ var/direction
+ switch(dir)
+ if(NORTH)
+ direction = 1
+ if(SOUTH)
+ direction = 2
+ if(EAST)
+ direction = 3
+ if(WEST)
+ direction = 4
+ var/turf/simulated/T=get_turf(get_step(loc,dir))
+ var/list/rstats = new /list(stats.len)
+ if(T && istype(T) && T.zone)
+ var/datum/gas_mixture/environment = T.return_air()
+ for(var/i=1;i<=stats.len;i++)
+ if(stats[i] == "pressure")
+ rstats[i] = environment.return_pressure()
+ else
+ rstats[i] = environment.vars[stats[i]]
+ else if(istype(T, /turf/simulated))
+ rstats = null // Exclude zone (wall, door, etc).
+ else if(istype(T, /turf))
+ // Should still work. (/turf/return_air())
+ var/datum/gas_mixture/environment = T.return_air()
+ for(var/i=1;i<=stats.len;i++)
+ if(stats[i] == "pressure")
+ rstats[i] = environment.return_pressure()
+ else
+ rstats[i] = environment.vars[stats[i]]
+ temps[direction] = rstats
+ return temps
diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm
index c733d1ad35e..079c551ebf4 100644
--- a/code/_onclick/hud/screen_objects.dm
+++ b/code/_onclick/hud/screen_objects.dm
@@ -91,7 +91,7 @@
if(master)
var/obj/item/I = usr.get_active_hand()
if(I)
- master.attackby(I, usr)
+ usr.ClickOn(master)
usr.next_move = world.time+2
return 1
diff --git a/code/controllers/_DynamicAreaLighting_TG.dm b/code/controllers/_DynamicAreaLighting_TG.dm
index 03ea77affcb..a93a7b64401 100644
--- a/code/controllers/_DynamicAreaLighting_TG.dm
+++ b/code/controllers/_DynamicAreaLighting_TG.dm
@@ -74,6 +74,7 @@ datum/light_source
changed = 1
if (owner.l_color != _l_color)
+ readrgb(owner.l_color)
changed = 1
if(changed)
diff --git a/code/controllers/communications.dm b/code/controllers/communications.dm
index 614768a0fe8..e7683de03b8 100644
--- a/code/controllers/communications.dm
+++ b/code/controllers/communications.dm
@@ -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(-1). DO NOT use sleep() here or call procs that sleep please. If you must, use spawn()
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.
@@ -84,7 +84,7 @@ On the map:
1311 for prison shuttle console (in fact, it is not used)
1435 for status displays
1437 for atmospherics/fire alerts
-1439 for engine components
+1438 for engine components
1439 for air pumps, air scrubbers, atmo control
1441 for atmospherics - supply tanks
1443 for atmospherics - distribution loop/mixed air tank
@@ -237,13 +237,7 @@ var/global/datum/controller/radio/radio_controller
if(start_point.z!=end_point.z || get_dist(start_point, end_point) > range)
continue
- //allow sequential signals before round start, so that every air alarm sounding off at once doesn't cause trouble.
- if(!ticker || ticker.current_state < 3)
- device.receive_signal(signal, TRANSMISSION_RADIO, frequency)
- else
- spawn(0)
- if(device) //in case the device got destroyed somehow
- device.receive_signal(signal, TRANSMISSION_RADIO, frequency)
+ device.receive_signal(signal, TRANSMISSION_RADIO, frequency)
/datum/radio_frequency/proc/add_listener(obj/device as obj, var/filter as text|null)
if (!filter)
diff --git a/code/controllers/configuration.dm b/code/controllers/configuration.dm
index f85391b7675..284caa23ac7 100644
--- a/code/controllers/configuration.dm
+++ b/code/controllers/configuration.dm
@@ -536,7 +536,6 @@
if("limbs_can_break")
config.limbs_can_break = value
-
if("run_speed")
config.run_speed = value
if("walk_speed")
diff --git a/code/controllers/lighting_controller.dm b/code/controllers/lighting_controller.dm
index a938586e241..08c29e1a076 100644
--- a/code/controllers/lighting_controller.dm
+++ b/code/controllers/lighting_controller.dm
@@ -16,7 +16,6 @@ datum/controller/lighting
var/list/changed_turfs = list()
var/changed_turfs_workload_max = 0
- var/list/changed_areas = list()
datum/controller/lighting/New()
lighting_states = max( 0, length(icon_states(LIGHTING_ICON))-1 )
@@ -55,18 +54,9 @@ datum/controller/lighting/proc/process()
for(var/i=1, i<=changed_turfs.len, i++)
var/turf/T = changed_turfs[i]
if(T && T.lighting_changed)
- changed_areas |= T.loc
T.shift_to_subarea()
changed_turfs.Cut() // reset the changed list
- for(var/i = 1; i <= changed_areas.len, i++)
- var/area/A = changed_areas[i]
- if(A.master != A && !A.contents.len)
- A.related -= A
- active_areas -= A
- all_areas -= A
- changed_areas.Cut()
-
process_cost = (world.timeofday - started)
sleep(processing_interval)
diff --git a/code/controllers/master_controller.dm b/code/controllers/master_controller.dm
index 204081716c7..8654fb89a12 100644
--- a/code/controllers/master_controller.dm
+++ b/code/controllers/master_controller.dm
@@ -307,6 +307,7 @@ datum/controller/game_controller/proc/process_machines_power()
var/area/A = active_areas[i]
if(A.powerupdate && A.master == A)
A.powerupdate -= 1
+ A.clear_usage()
for(var/j = 1; j <= A.related.len; j++)
var/area/SubArea = A.related[j]
for(var/obj/machinery/M in SubArea)
@@ -362,7 +363,7 @@ datum/controller/game_controller/proc/process_powernets()
while(i<=powernets.len)
var/datum/powernet/Powernet = powernets[i]
if(Powernet)
- Powernet.reset()
+ Powernet.process()
i++
continue
powernets.Cut(i,i+1)
diff --git a/code/datums/mixed.dm b/code/datums/mixed.dm
index 6732e2a8b94..f0f0c70abda 100644
--- a/code/datums/mixed.dm
+++ b/code/datums/mixed.dm
@@ -30,20 +30,5 @@
-/datum/powernet
- var/list/cables = list() // all cables & junctions
- var/list/nodes = list() // all APCs & sources
-
- var/newload = 0
- var/load = 0
- var/newavail = 0
- var/avail = 0
- var/viewload = 0
- var/number = 0
- var/perapc = 0 // per-apc avilability
- var/netexcess = 0
-
-
-
/datum/debug
var/list/debuglist
diff --git a/code/datums/supplypacks.dm b/code/datums/supplypacks.dm
index cf08713f1f5..c250a757bf8 100755
--- a/code/datums/supplypacks.dm
+++ b/code/datums/supplypacks.dm
@@ -22,11 +22,9 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/datum/supply_packs/New()
manifest += ""
- for(var/path in contains)
+ for(var/atom/movable/path in contains)
if(!path) continue
- var/atom/movable/AM = new path()
- manifest += "- [AM.name]
"
- AM.loc = null //just to make sure they're deleted by the garbage collector
+ manifest += "- [initial(path.name)]
"
manifest += "
"
/datum/supply_packs/specialops
@@ -348,20 +346,17 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
/datum/supply_packs/exoticseeds
name = "Exotic seeds crate"
- contains = list(/obj/item/seeds/nettleseed,
+ contains = list(/obj/item/seeds/replicapod,
/obj/item/seeds/replicapod,
- /obj/item/seeds/replicapod,
- /obj/item/seeds/replicapod,
- /obj/item/seeds/plumpmycelium,
/obj/item/seeds/libertymycelium,
- /obj/item/seeds/amanitamycelium,
/obj/item/seeds/reishimycelium,
- /obj/item/seeds/bananaseed,
- /obj/item/seeds/riceseed,
- /obj/item/seeds/eggplantseed,
- /obj/item/seeds/limeseed,
- /obj/item/seeds/grapeseed,
- /obj/item/seeds/eggyseed)
+ /obj/item/seeds/random,
+ /obj/item/seeds/random,
+ /obj/item/seeds/random,
+ /obj/item/seeds/random,
+ /obj/item/seeds/random,
+ /obj/item/seeds/random,
+ /obj/item/seeds/kudzuseed)
cost = 15
containertype = /obj/structure/closet/crate/hydroponics
containername = "Exotic Seeds crate"
diff --git a/code/game/area/Space Station 13 areas.dm b/code/game/area/Space Station 13 areas.dm
index 98e9a1af800..183568ad184 100755
--- a/code/game/area/Space Station 13 areas.dm
+++ b/code/game/area/Space Station 13 areas.dm
@@ -380,7 +380,7 @@ var/list/ghostteleportlocs = list()
//SYNDICATES
/area/syndicate_mothership
- name = "\improper Syndicate Mothership"
+ name = "\improper Syndicate Base"
icon_state = "syndie-ship"
requires_power = 0
unlimited_power = 1
@@ -1103,7 +1103,8 @@ var/list/ghostteleportlocs = list()
//Solars
/area/solar
- requires_power = 0
+ requires_power = 1
+ always_unpowered = 1
luminosity = 1
lighting_use_dynamic = 0
@@ -1133,7 +1134,7 @@ var/list/ghostteleportlocs = list()
/area/maintenance/auxsolarport
name = "Fore Port Solar Maintenance"
- icon_state = "SolarcontrolA"
+ icon_state = "SolarcontrolP"
/area/maintenance/starboardsolar
name = "Aft Starboard Solar Maintenance"
@@ -1145,7 +1146,7 @@ var/list/ghostteleportlocs = list()
/area/maintenance/auxsolarstarboard
name = "Fore Starboard Solar Maintenance"
- icon_state = "SolarcontrolA"
+ icon_state = "SolarcontrolS"
/area/maintenance/foresolar
name = "Fore Solar Maintenance"
@@ -1460,6 +1461,10 @@ var/list/ghostteleportlocs = list()
name = "\improper Research and Development"
icon_state = "research"
+/area/rnd/docking
+ name = "\improper Research Dock"
+ icon_state = "research"
+
/area/rnd/lab
name = "\improper Research Lab"
icon_state = "toxlab"
diff --git a/code/game/gamemodes/calamity/calamity.dm b/code/game/gamemodes/calamity/calamity.dm
index c2ab3202f4f..4645fd2d3be 100644
--- a/code/game/gamemodes/calamity/calamity.dm
+++ b/code/game/gamemodes/calamity/calamity.dm
@@ -17,14 +17,14 @@
uplink_uses = 10
//Possible roundstart antag types.
- var/list/atypes = list("syndi","ling","tater","wiz","ninja","vox","slug","cult")
+ var/list/atypes = list("syndi","ling","tater","wiz","ninja","vox","cult") //Readd slug when borer spawn is fixed.
var/list/chosen_atypes = list()
var/list/chosen_candidates = list()
var/list/already_assigned_candidates = list()
//At one antagonist group per 10 players we are just going to go with tiny groups.
- var/max_antags = 3 // Antag groups spawn with this many members.
- var/antag_type_ratio = 10 // 1 antag type per this many players.
+ var/max_antags = 5 // Antag groups spawn with this many members.
+ var/antag_type_ratio = 8 // 1 antag type per this many players.
var/const/waittime_l = 600
var/const/waittime_h = 1800
@@ -48,26 +48,37 @@
var/atype
var/list/candidates = list()
- while(atypes.len && candidates.len == 0) //While there are untested antag mode types and we don't have any candidates selected, loop.
+ // Go through antag types at random until we find one that has candidates.
+ while(atypes.len && !candidates.len)
atype = pick(atypes)
log_debug("Calamity: checking [atype].")
atypes -= atype
candidates = get_role_candidates(atype)
- if(!candidates.len)
- log_debug("Calamity mode setup failed, no antag types or candidates left.")
- return 0
+ //Prune out candidates who are already antagonists.
+ var/list/remove_players = list()
+ for(var/datum/mind/player in candidates)
+ if(player.special_role || player.assigned_role == "MODE")
+ remove_players += player
+ candidates -= remove_players
log_debug("Calamity: selected [atype] (possible candidates: [candidates.len])")
chosen_atypes += atype
for(var/j=0;j synd_spawn.len)
spawnpos = 1
@@ -254,8 +276,9 @@
update_all_synd_icons()
- if(uplinklocker)
- new /obj/structure/closet/syndicate/nuclear(uplinklocker.loc)
+ if(uplinkdevice)
+ var/obj/item/device/radio/uplink/U = new(uplinkdevice.loc)
+ U.hidden_uplink.uses = 40
if(nuke_spawn && synd_spawn.len > 0)
var/obj/machinery/nuclearbomb/the_bomb = new /obj/machinery/nuclearbomb(nuke_spawn.loc)
the_bomb.r_code = nuke_code
@@ -264,7 +287,7 @@
for(var/datum/mind/player in candidates)
- changelings += player
+ changelings |= player
grant_changeling_powers(player.current)
player.special_role = "Changeling"
@@ -278,7 +301,7 @@
/datum/game_mode/calamity/proc/spawn_traitors(var/list/candidates)
for(var/datum/mind/player in candidates)
- traitors += player
+ traitors |= player
if(!config.objectives_disabled)
player.objectives += new /datum/objective/escape()
@@ -292,7 +315,7 @@
/datum/game_mode/calamity/proc/spawn_cabal(var/list/candidates)
for(var/datum/mind/player in candidates)
- wizards += player
+ wizards |= player
if(!config.objectives_disabled)
player.objectives += new /datum/objective/escape()
@@ -314,7 +337,7 @@
ninjastart.Add(L)
for(var/datum/mind/player in candidates)
- ninjas += player
+ ninjas |= player
player.current << browse(null, "window=playersetup")
player.current = create_space_ninja(pick(ninjastart))
@@ -347,7 +370,7 @@
//Create raiders.
for(var/datum/mind/player in candidates)
- raiders += player
+ raiders |= player
//Place them on the shuttle.
var/index = 1
@@ -375,42 +398,43 @@
var/list/possible_hosts = list()
for(var/mob/living/carbon/human/H in mob_list)
if(!(H.species.flags & IS_SYNTHETIC))
- possible_hosts += H
+ possible_hosts |= H
- for(var/datum/mind/player in candidates)
+ spawn(10)
+ for(var/datum/mind/player in candidates)
- if(!possible_hosts || possible_hosts.len)
- break
+ if(!possible_hosts || possible_hosts.len)
+ break
- borers += player
- var/mob/living/carbon/human/target_host = pick(possible_hosts)
- possible_hosts -= target_host
+ borers |= player
+ var/mob/living/carbon/human/target_host = pick(possible_hosts)
+ possible_hosts -= target_host
- var/mob/living/simple_animal/borer/roundstart/B = new(target_host)
+ var/mob/living/simple_animal/borer/roundstart/B = new(target_host)
- player.current = B
- B.mind = player
- B.key = player.key
- player.assigned_role = "Cortical Borer"
- player.special_role = "Cortical Borer"
+ player.current = B
+ B.mind = player
+ B.key = player.key
+ player.assigned_role = "Cortical Borer"
+ player.special_role = "Cortical Borer"
- B.host = target_host
- B.host_brain.name = target_host.name
- B.host_brain.real_name = target_host.real_name
+ B.host = target_host
+ B.host_brain.name = target_host.name
+ B.host_brain.real_name = target_host.real_name
- var/datum/organ/external/head = target_host.get_organ("head")
- head.implants += B
+ var/datum/organ/external/head = target_host.get_organ("head")
+ head.implants += B
- player.current << "\blue You are a cortical borer! You are a brain slug that worms its way \
- into the head of its victim, lurking out of sight until it needs to take control."
- player.current << "You can speak to your victim with say, to other borers with say ;, and use your Alien tab for abilities."
+ player.current << "\blue You are a cortical borer! You are a brain slug that worms its way \
+ into the head of its victim, lurking out of sight until it needs to take control."
+ player.current << "You can speak to your victim with say, to other borers with say ;, and use your Alien tab for abilities."
- if(!config.objectives_disabled)
- player.objectives += new /datum/objective/borer_survive()
- player.objectives += new /datum/objective/borer_reproduce()
- player.objectives += new /datum/objective/escape()
+ if(!config.objectives_disabled)
+ player.objectives += new /datum/objective/borer_survive()
+ player.objectives += new /datum/objective/borer_reproduce()
+ player.objectives += new /datum/objective/escape()
- show_objectives(player)
+ show_objectives(player)
/datum/game_mode/calamity/proc/spawn_cultists(var/list/candidates)
@@ -430,7 +454,7 @@
if(player.assigned_role == job)
continue
- cult += player
+ cult |= player
equip_cultist(player.current)
grant_runeword(player.current)
update_cult_icons_added(player)
diff --git a/code/game/gamemodes/cult/runes.dm b/code/game/gamemodes/cult/runes.dm
index 14b253f4159..6750f7c83eb 100644
--- a/code/game/gamemodes/cult/runes.dm
+++ b/code/game/gamemodes/cult/runes.dm
@@ -104,7 +104,7 @@ var/list/sacrificed = list()
if(M.stat==2)
continue
usr.say("Mah[pick("'","`")]weyh pleggh at e'ntrath!")
- M.visible_message("\red [M] writhes in pain as the markings below him glow a bloody red.", \
+ M.visible_message("\red [M] writhes in pain as the markings below \him glow a bloody red.", \
"\red AAAAAAHHHH!.", \
"\red You hear an anguished scream.")
if(is_convertable_to_cult(M.mind) && !jobban_isbanned(M, "cultist"))//putting jobban check here because is_convertable uses mind as argument
diff --git a/code/game/gamemodes/events/space_ninja.dm b/code/game/gamemodes/events/space_ninja.dm
index 2421a354660..c1fd9b219f9 100644
--- a/code/game/gamemodes/events/space_ninja.dm
+++ b/code/game/gamemodes/events/space_ninja.dm
@@ -142,7 +142,7 @@ Malf AIs/silicons aren't added. Monkeys aren't added. Messes with objective comp
//Here we pick a location and spawn the ninja.
if(ninjastart.len == 0)
for(var/obj/effect/landmark/L in landmarks_list)
- if(L.name == "carpspawn")
+ if(L.name == "carpspawn" && locate(/turf/simulated) in range(7, L))
ninjastart.Add(L)
var/ninja_key = null
diff --git a/code/game/gamemodes/gameticker.dm b/code/game/gamemodes/gameticker.dm
index 723d8102d02..fa7b55c7f8d 100644
--- a/code/game/gamemodes/gameticker.dm
+++ b/code/game/gamemodes/gameticker.dm
@@ -37,6 +37,8 @@ var/global/datum/controller/gameticker/ticker
var/triai = 0//Global holder for Triumvirate
+ var/round_end_announced = 0 // Spam Prevention. Announce round end only once.
+
/datum/controller/gameticker/proc/pregame()
login_music = pick(\
/*'sound/music/halloween/skeletons.ogg',\
@@ -360,7 +362,9 @@ var/global/datum/controller/gameticker/ticker
//call a transfer shuttle vote
spawn(50)
- world << "\red The round has ended!"
+ if(!round_end_announced) // Spam Prevention. Now it should announce only once.
+ world << "\red The round has ended!"
+ round_end_announced = 1
vote.autotransfer()
return 1
diff --git a/code/game/gamemodes/malfunction/malfunction.dm b/code/game/gamemodes/malfunction/malfunction.dm
index 1f6f40176c0..2fb432d119a 100644
--- a/code/game/gamemodes/malfunction/malfunction.dm
+++ b/code/game/gamemodes/malfunction/malfunction.dm
@@ -53,6 +53,7 @@
AI_mind.current.verbs += /mob/living/silicon/ai/proc/choose_modules
AI_mind.current:laws = new /datum/ai_laws/malfunction
AI_mind.current:malf_picker = new /datum/AI_Module/module_picker
+ AI_mind.current.verbs += /datum/game_mode/malfunction/proc/ai_win // We run checks if AI overtaken the station in the proc itself. This guarantees you won't have to relog when it refuses to appear on takeover completion.
AI_mind.current:show_laws()
greet_malf(AI_mind)
@@ -113,11 +114,8 @@
for(var/datum/mind/AI_mind in malf_ai)
AI_mind.current << "Congratulations you have taken control of the station."
AI_mind.current << "You may decide to blow up the station. You have 60 seconds to choose."
- AI_mind.current << "You should have a new verb in the Malfunction tab. If you dont - rejoin the game."
- AI_mind.current.verbs += /datum/game_mode/malfunction/proc/ai_win
+ AI_mind.current << "You can use the \"Explode\" verb to activate the self-destruct"
spawn (600)
- for(var/datum/mind/AI_mind in malf_ai)
- AI_mind.current.verbs -= /datum/game_mode/malfunction/proc/ai_win
to_nuke_or_not_to_nuke = 0
return
@@ -182,19 +180,69 @@
set category = "Malfunction"
set name = "Explode"
set desc = "Station go boom"
- if (!ticker.mode:to_nuke_or_not_to_nuke)
+
+ if(!ticker.mode:station_captured)
+ usr << "You are unable to access the self-destruct system as you don't control the station yet."
return
+
+ if(ticker.mode:explosion_in_progress || ticker.mode:station_was_nuked)
+ usr << "The self-destruct countdown is already triggered!"
+ return
+
+ if(!ticker.mode:to_nuke_or_not_to_nuke) //Takeover IS completed, but 60s timer passed.
+ usr << "You lost control over self-destruct system. It seems to be behind firewall. Unable to hack"
+ return
+
+ usr << "\red Self-Destruct sequence initialised!"
+
ticker.mode:to_nuke_or_not_to_nuke = 0
- for(var/datum/mind/AI_mind in ticker.mode:malf_ai)
- AI_mind.current.verbs -= /datum/game_mode/malfunction/proc/ai_win
ticker.mode:explosion_in_progress = 1
for(var/mob/M in player_list)
M << 'sound/machines/Alarm.ogg'
- world << "Self-destructing in 10"
+
+ var/obj/item/device/radio/R = new (src)
+ var/AN = "Self-Destruct System"
+
+ R.autosay("Caution. Self-Destruct sequence has been actived. Self-destructing in Ten..", AN)
for (var/i=9 to 1 step -1)
sleep(10)
- world << i
+ var/msg = ""
+ switch(i)
+ if(9)
+ msg = "Nine.."
+ if(8)
+ msg = "Eight.."
+ if(7)
+ msg = "Seven.."
+ if(6)
+ msg = "Six.."
+ if(5)
+ msg = "Five.."
+ if(4)
+ msg = "Four.."
+ if(3)
+ msg = "Three.."
+ if(2)
+ msg = "Two.."
+ if(1)
+ msg = "One.."
+
+ R.autosay(msg, AN)
sleep(10)
+ var/msg = ""
+ var/abort = 0
+ if(ticker.mode:is_malf_ai_dead()) // That. Was. CLOSE.
+ msg = "Self-destruct sequence has been cancelled."
+ abort = 1
+ else
+ msg = "Zero. Have a nice day."
+ R.autosay(msg, AN)
+
+ if(abort)
+ ticker.mode:explosion_in_progress = 0
+ set_security_level("red") //Delta's over
+ return
+
enter_allowed = 0
if(ticker)
ticker.station_explosion_cinematic(0,null)
diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm
index 6f89c015aad..911dc58d846 100644
--- a/code/game/gamemodes/nuclear/nuclear.dm
+++ b/code/game/gamemodes/nuclear/nuclear.dm
@@ -208,6 +208,7 @@ var/global/list/turf/synd_spawn = list()
/datum/game_mode/proc/equip_syndicate(mob/living/carbon/human/synd_mob)
var/obj/item/device/radio/R = new /obj/item/device/radio/headset/syndicate(synd_mob)
R.set_frequency(SYND_FREQ)
+ R.freerange = 1
synd_mob.equip_to_slot_or_del(R, slot_l_ear)
synd_mob.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(synd_mob), slot_w_uniform)
@@ -217,11 +218,8 @@ var/global/list/turf/synd_spawn = list()
if(synd_mob.backbag == 2) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(synd_mob), slot_back)
if(synd_mob.backbag == 3) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_norm(synd_mob), slot_back)
if(synd_mob.backbag == 4) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(synd_mob), slot_back)
- synd_mob.equip_to_slot_or_del(new /obj/item/ammo_magazine/a12mm(synd_mob), slot_in_backpack)
- synd_mob.equip_to_slot_or_del(new /obj/item/ammo_magazine/a12mm(synd_mob), slot_in_backpack)
- synd_mob.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/pill/cyanide(synd_mob), slot_in_backpack)
- synd_mob.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/automatic/c20r(synd_mob), slot_belt)
synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(synd_mob.back), slot_in_backpack)
+ synd_mob.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/pill/cyanide(synd_mob), slot_in_backpack)
/* Commented; nukes now have a suit cycler for changing rig-suits, they don't need to spawn with them
var/obj/item/clothing/suit/space/rig/syndi/new_suit = new(synd_mob)
diff --git a/code/game/machinery/OpTable.dm b/code/game/machinery/OpTable.dm
index aa582281048..641e9473add 100644
--- a/code/game/machinery/OpTable.dm
+++ b/code/game/machinery/OpTable.dm
@@ -123,18 +123,26 @@
set category = "Object"
set src in oview(1)
- if(usr.stat || !ishuman(usr) || usr.buckled || usr.restrained())
- return
-
- if(src.victim)
- usr << "\blue The table is already occupied!"
+ if(usr.stat || !ishuman(usr) || usr.restrained() || !check_table(usr))
return
take_victim(usr,usr)
/obj/machinery/optable/attackby(obj/item/weapon/W as obj, mob/living/carbon/user as mob)
if (istype(W, /obj/item/weapon/grab))
- if(iscarbon(W:affecting))
- take_victim(W:affecting,usr)
+ var/obj/item/weapon/grab/G = W
+ if(iscarbon(G.affecting) && check_table(G.affecting))
+ take_victim(G.affecting,usr)
del(W)
- return
\ No newline at end of file
+ return
+
+/obj/machinery/optable/proc/check_table(mob/living/carbon/patient as mob)
+ if(src.victim)
+ usr << "\blue The table is already occupied!"
+ return 0
+
+ if(patient.buckled)
+ usr << "\blue Unbuckle first!"
+ return 0
+
+ return 1
diff --git a/code/game/machinery/atmo_control.dm b/code/game/machinery/atmo_control.dm
index b5d5af6183e..a62da66d770 100644
--- a/code/game/machinery/atmo_control.dm
+++ b/code/game/machinery/atmo_control.dm
@@ -1,4 +1,4 @@
-obj/machinery/air_sensor
+/obj/machinery/air_sensor
icon = 'icons/obj/stationobjs.dmi'
icon_state = "gsensor1"
name = "Gas Sensor"
@@ -22,59 +22,58 @@ obj/machinery/air_sensor
var/datum/radio_frequency/radio_connection
- update_icon()
- icon_state = "gsensor[on]"
+/obj/machinery/air_sensor/update_icon()
+ icon_state = "gsensor[on]"
- process()
- if(on)
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.data["tag"] = id_tag
- signal.data["timestamp"] = world.time
+/obj/machinery/air_sensor/process()
+ if(on)
+ var/datum/signal/signal = new
+ signal.transmission_method = 1 //radio signal
+ signal.data["tag"] = id_tag
+ signal.data["timestamp"] = world.time
- var/datum/gas_mixture/air_sample = return_air()
+ var/datum/gas_mixture/air_sample = return_air()
- if(output&1)
- signal.data["pressure"] = num2text(round(air_sample.return_pressure(),0.1),)
- if(output&2)
- signal.data["temperature"] = round(air_sample.temperature,0.1)
+ if(output&1)
+ signal.data["pressure"] = num2text(round(air_sample.return_pressure(),0.1),)
+ if(output&2)
+ signal.data["temperature"] = round(air_sample.temperature,0.1)
- if(output>4)
- var/total_moles = air_sample.total_moles
- if(total_moles > 0)
- if(output&4)
- signal.data["oxygen"] = round(100*air_sample.gas["oxygen"]/total_moles,0.1)
- if(output&8)
- signal.data["phoron"] = round(100*air_sample.gas["phoron"]/total_moles,0.1)
- if(output&16)
- signal.data["nitrogen"] = round(100*air_sample.gas["nitrogen"]/total_moles,0.1)
- if(output&32)
- signal.data["carbon_dioxide"] = round(100*air_sample.gas["carbon_dioxide"]/total_moles,0.1)
- else
- signal.data["oxygen"] = 0
- signal.data["phoron"] = 0
- signal.data["nitrogen"] = 0
- signal.data["carbon_dioxide"] = 0
- signal.data["sigtype"]="status"
- radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
+ if(output>4)
+ var/total_moles = air_sample.total_moles
+ if(total_moles > 0)
+ if(output&4)
+ signal.data["oxygen"] = round(100*air_sample.gas["oxygen"]/total_moles,0.1)
+ if(output&8)
+ signal.data["phoron"] = round(100*air_sample.gas["phoron"]/total_moles,0.1)
+ if(output&16)
+ signal.data["nitrogen"] = round(100*air_sample.gas["nitrogen"]/total_moles,0.1)
+ if(output&32)
+ signal.data["carbon_dioxide"] = round(100*air_sample.gas["carbon_dioxide"]/total_moles,0.1)
+ else
+ signal.data["oxygen"] = 0
+ signal.data["phoron"] = 0
+ signal.data["nitrogen"] = 0
+ signal.data["carbon_dioxide"] = 0
+ signal.data["sigtype"]="status"
+ radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
- proc
- set_frequency(new_frequency)
- radio_controller.remove_object(src, frequency)
- frequency = new_frequency
- radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA)
+/obj/machinery/air_sensor/proc/set_frequency(new_frequency)
+ radio_controller.remove_object(src, frequency)
+ frequency = new_frequency
+ radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA)
- initialize()
+/obj/machinery/air_sensor/initialize()
+ set_frequency(frequency)
+
+/obj/machinery/air_sensor/New()
+ ..()
+
+ if(radio_controller)
set_frequency(frequency)
- New()
- ..()
-
- if(radio_controller)
- set_frequency(frequency)
-
-obj/machinery/computer/general_air_control
+/obj/machinery/computer/general_air_control
icon = 'icons/obj/computer.dmi'
icon_state = "tank"
@@ -87,298 +86,426 @@ obj/machinery/computer/general_air_control
var/datum/radio_frequency/radio_connection
circuit = /obj/item/weapon/circuitboard/air_management
- attack_hand(mob/user)
- if(..(user))
- return
- user << browse(return_text(),"window=computer")
- user.set_machine(src)
- onclose(user, "computer")
+/obj/machinery/computer/general_air_control/attack_hand(mob/user)
+ if(..(user))
+ return
+ user << browse(return_text(),"window=computer")
+ user.set_machine(src)
+ onclose(user, "computer")
- process()
- ..()
- src.updateUsrDialog()
+/obj/machinery/computer/general_air_control/process()
+ ..()
+ src.updateUsrDialog()
- receive_signal(datum/signal/signal)
- if(!signal || signal.encryption) return
+/obj/machinery/computer/general_air_control/receive_signal(datum/signal/signal)
+ if(!signal || signal.encryption) return
- var/id_tag = signal.data["tag"]
- if(!id_tag || !sensors.Find(id_tag)) return
+ var/id_tag = signal.data["tag"]
+ if(!id_tag || !sensors.Find(id_tag)) return
- sensor_information[id_tag] = signal.data
+ sensor_information[id_tag] = signal.data
- proc/return_text()
- var/sensor_data
- if(sensors.len)
- for(var/id_tag in sensors)
- var/long_name = sensors[id_tag]
- var/list/data = sensor_information[id_tag]
- var/sensor_part = "[long_name]:
"
+/obj/machinery/computer/general_air_control/proc/return_text()
+ var/sensor_data
+ if(sensors.len)
+ for(var/id_tag in sensors)
+ var/long_name = sensors[id_tag]
+ var/list/data = sensor_information[id_tag]
+ var/sensor_part = "[long_name]:
"
- if(data)
- if(data["pressure"])
- sensor_part += " Pressure: [data["pressure"]] kPa
"
- if(data["temperature"])
- sensor_part += " Temperature: [data["temperature"]] K
"
- if(data["oxygen"]||data["phoron"]||data["nitrogen"]||data["carbon_dioxide"])
- sensor_part += " Gas Composition :"
- if(data["oxygen"])
- sensor_part += "[data["oxygen"]]% O2; "
- if(data["nitrogen"])
- sensor_part += "[data["nitrogen"]]% N; "
- if(data["carbon_dioxide"])
- sensor_part += "[data["carbon_dioxide"]]% CO2; "
- if(data["phoron"])
- sensor_part += "[data["phoron"]]% TX; "
- sensor_part += "
"
+ if(data)
+ if(data["pressure"])
+ sensor_part += " Pressure: [data["pressure"]] kPa
"
+ if(data["temperature"])
+ sensor_part += " Temperature: [data["temperature"]] K
"
+ if(data["oxygen"]||data["phoron"]||data["nitrogen"]||data["carbon_dioxide"])
+ sensor_part += " Gas Composition :"
+ if(data["oxygen"])
+ sensor_part += "[data["oxygen"]]% O2; "
+ if(data["nitrogen"])
+ sensor_part += "[data["nitrogen"]]% N; "
+ if(data["carbon_dioxide"])
+ sensor_part += "[data["carbon_dioxide"]]% CO2; "
+ if(data["phoron"])
+ sensor_part += "[data["phoron"]]% TX; "
+ sensor_part += "
"
- else
- sensor_part = "[long_name] can not be found!
"
+ else
+ sensor_part = "[long_name] can not be found!
"
- sensor_data += sensor_part
+ sensor_data += sensor_part
- else
- sensor_data = "No sensors connected."
+ else
+ sensor_data = "No sensors connected."
- var/output = {"[name]
+ var/output = {"[name]
Sensor Data:
[sensor_data]"}
- return output
+ return output
- proc
- set_frequency(new_frequency)
- radio_controller.remove_object(src, frequency)
- frequency = new_frequency
- radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA)
+/obj/machinery/computer/general_air_control/proc/set_frequency(new_frequency)
+ radio_controller.remove_object(src, frequency)
+ frequency = new_frequency
+ radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA)
- initialize()
- set_frequency(frequency)
-
- large_tank_control
- icon = 'icons/obj/computer.dmi'
- icon_state = "tank"
-
- var/input_tag
- var/output_tag
-
- var/list/input_info
- var/list/output_info
-
- var/pressure_setting = ONE_ATMOSPHERE * 45
- circuit = /obj/item/weapon/circuitboard/air_management/tank_control
+/obj/machinery/computer/general_air_control/initialize()
+ set_frequency(frequency)
- return_text()
- var/output = ..()
- //if(signal.data)
- // input_info = signal.data // Attempting to fix intake control -- TLE
+/obj/machinery/computer/general_air_control/large_tank_control
+ icon = 'icons/obj/computer.dmi'
+ icon_state = "tank"
- output += "Tank Control System
"
- if(input_info)
- var/power = (input_info["power"])
- var/volume_rate = input_info["volume_rate"]
- output += {"Input: [power?("Injecting"):("On Hold")] Refresh
-Rate: [volume_rate] L/sec
"}
- output += "Command: Toggle Power
"
+ frequency = 1441
+ var/input_tag
+ var/output_tag
- else
- output += "ERROR: Can not find input port Search
"
+ var/list/input_info
+ var/list/output_info
- output += "
"
+ var/input_flow_setting = 200
+ var/pressure_setting = ONE_ATMOSPHERE * 45
+ circuit = /obj/item/weapon/circuitboard/air_management/tank_control
- if(output_info)
- var/power = (output_info["power"])
- var/output_pressure = output_info["internal"]
- output += {"Output: [power?("Open"):("On Hold")] Refresh
+
+/obj/machinery/computer/general_air_control/large_tank_control/return_text()
+ var/output = ..()
+ //if(signal.data)
+ // input_info = signal.data // Attempting to fix intake control -- TLE
+
+ output += "Tank Control System
"
+ if(input_info)
+ var/power = (input_info["power"])
+ var/volume_rate = round(input_info["volume_rate"], 0.1)
+ output += "Input: [power?("Injecting"):("On Hold")] Refresh
Flow Rate Limit: [volume_rate] L/s
"
+ output += "Command: Toggle Power Set Flow Rate
"
+
+ else
+ output += "ERROR: Can not find input port Search
"
+
+ output += "Flow Rate Limit: - - - - [round(input_flow_setting, 0.1)] L/s + + + +
"
+
+ output += "
"
+
+ if(output_info)
+ var/power = (output_info["power"])
+ var/output_pressure = output_info["internal"]
+ output += {"Output: [power?("Open"):("On Hold")] Refresh
Max Output Pressure: [output_pressure] kPa
"}
- output += "Command: Toggle Power Set Pressure
"
+ output += "Command: Toggle Power Set Pressure
"
- else
- output += "ERROR: Can not find output port Search
"
+ else
+ output += "ERROR: Can not find output port Search
"
- output += "Max Output Pressure Set: - - - - [pressure_setting] kPa + + + +
"
+ output += "Max Output Pressure Set: - - - - [pressure_setting] kPa + + + +
"
- return output
+ return output
- receive_signal(datum/signal/signal)
- if(!signal || signal.encryption) return
+/obj/machinery/computer/general_air_control/large_tank_control/receive_signal(datum/signal/signal)
+ if(!signal || signal.encryption) return
- var/id_tag = signal.data["tag"]
+ var/id_tag = signal.data["tag"]
- if(input_tag == id_tag)
- input_info = signal.data
- else if(output_tag == id_tag)
- output_info = signal.data
- else
- ..(signal)
+ if(input_tag == id_tag)
+ input_info = signal.data
+ else if(output_tag == id_tag)
+ output_info = signal.data
+ else
+ ..(signal)
- Topic(href, href_list)
- if(..())
- return
+/obj/machinery/computer/general_air_control/large_tank_control/Topic(href, href_list)
+ if(..())
+ return
- if(href_list["adj_pressure"])
- var/change = text2num(href_list["adj_pressure"])
- pressure_setting = between(0, pressure_setting + change, 50*ONE_ATMOSPHERE)
- spawn(1)
- src.updateUsrDialog()
- return
+ if(href_list["adj_pressure"])
+ var/change = text2num(href_list["adj_pressure"])
+ pressure_setting = between(0, pressure_setting + change, 50*ONE_ATMOSPHERE)
+ spawn(1)
+ src.updateUsrDialog()
+ return
- if(!radio_connection)
- return 0
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
- if(href_list["in_refresh_status"])
- input_info = null
- signal.data = list ("tag" = input_tag, "status")
+ if(href_list["adj_input_flow_rate"])
+ var/change = text2num(href_list["adj_input_flow_rate"])
+ input_flow_setting = between(0, input_flow_setting + change, ATMOS_DEFAULT_VOLUME_PUMP + 500) //default flow rate limit for air injectors
+ spawn(1)
+ src.updateUsrDialog()
+ return
+
+ if(!radio_connection)
+ return 0
+ var/datum/signal/signal = new
+ signal.transmission_method = 1 //radio signal
+ signal.source = src
+ if(href_list["in_refresh_status"])
+ input_info = null
+ signal.data = list ("tag" = input_tag, "status" = 1)
- if(href_list["in_toggle_injector"])
- input_info = null
- signal.data = list ("tag" = input_tag, "power_toggle")
+ if(href_list["in_toggle_injector"])
+ input_info = null
+ signal.data = list ("tag" = input_tag, "power_toggle" = 1)
- if(href_list["out_refresh_status"])
- output_info = null
- signal.data = list ("tag" = output_tag, "status")
+ if(href_list["in_set_flowrate"])
+ input_info = null
+ signal.data = list ("tag" = input_tag, "set_volume_rate" = "[input_flow_setting]")
- if(href_list["out_toggle_power"])
- output_info = null
- signal.data = list ("tag" = output_tag, "power_toggle")
+ if(href_list["out_refresh_status"])
+ output_info = null
+ signal.data = list ("tag" = output_tag, "status" = 1)
- if(href_list["out_set_pressure"])
- output_info = null
- signal.data = list ("tag" = output_tag, "set_internal_pressure" = "[pressure_setting]")
+ if(href_list["out_toggle_power"])
+ output_info = null
+ signal.data = list ("tag" = output_tag, "power_toggle" = 1)
- signal.data["sigtype"]="command"
- radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
+ if(href_list["out_set_pressure"])
+ output_info = null
+ signal.data = list ("tag" = output_tag, "set_internal_pressure" = "[pressure_setting]")
- spawn(5)
- src.updateUsrDialog()
+ signal.data["sigtype"]="command"
+ radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
- fuel_injection
- icon = 'icons/obj/computer.dmi'
- icon_state = "atmos"
+ spawn(5)
+ src.updateUsrDialog()
- var/device_tag
- var/list/device_info
+/obj/machinery/computer/general_air_control/supermatter_core
+ icon = 'icons/obj/computer.dmi'
+ icon_state = "tank"
- var/automation = 0
+ frequency = 1438
+ var/input_tag
+ var/output_tag
- var/cutoff_temperature = 2000
- var/on_temperature = 1200
- circuit = /obj/item/weapon/circuitboard/air_management/injector_control
+ var/list/input_info
+ var/list/output_info
- process()
- if(automation)
- if(!radio_connection)
- return 0
+ var/input_flow_setting = 700
+ var/pressure_setting = 100
+ circuit = /obj/item/weapon/circuitboard/air_management/supermatter_core
- var/injecting = 0
- for(var/id_tag in sensor_information)
- var/list/data = sensor_information[id_tag]
- if(data["temperature"])
- if(data["temperature"] >= cutoff_temperature)
- injecting = 0
- break
- if(data["temperature"] <= on_temperature)
- injecting = 1
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
+/obj/machinery/computer/general_air_control/supermatter_core/return_text()
+ var/output = ..()
+ //if(signal.data)
+ // input_info = signal.data // Attempting to fix intake control -- TLE
- signal.data = list(
- "tag" = device_tag,
- "power" = injecting,
- "sigtype"="command"
- )
+ output += "Core Cooling Control System
"
+ if(input_info)
+ var/power = (input_info["power"])
+ var/volume_rate = round(input_info["volume_rate"], 0.1)
+ output += "Coolant Input: [power?("Injecting"):("On Hold")] Refresh
Flow Rate Limit: [volume_rate] L/s
"
+ output += "Command: Toggle Power Set Flow Rate
"
- radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
+ else
+ output += "ERROR: Can not find input port Search
"
+
+ output += "Flow Rate Limit: - - - - [round(input_flow_setting, 0.1)] L/s + + + +
"
- ..()
+ output += "
"
- return_text()
- var/output = ..()
+ if(output_info)
+ var/power = (output_info["power"])
+ var/pressure_limit = output_info["external"]
+ output += {"Core Outpump: [power?("Open"):("On Hold")] Refresh
+Min Core Pressure: [pressure_limit] kPa
"}
+ output += "Command: Toggle Power Set Pressure
"
- output += "Fuel Injection System
"
- if(device_info)
- var/power = device_info["power"]
- var/volume_rate = device_info["volume_rate"]
- output += {"Status: [power?("Injecting"):("On Hold")] Refresh
+ else
+ output += "ERROR: Can not find output port Search
"
+
+ output += "Min Core Pressure Set: - - - - [pressure_setting] kPa + + + +
"
+
+ return output
+
+/obj/machinery/computer/general_air_control/supermatter_core/receive_signal(datum/signal/signal)
+ if(!signal || signal.encryption) return
+
+ var/id_tag = signal.data["tag"]
+
+ if(input_tag == id_tag)
+ input_info = signal.data
+ else if(output_tag == id_tag)
+ output_info = signal.data
+ else
+ ..(signal)
+
+/obj/machinery/computer/general_air_control/supermatter_core/Topic(href, href_list)
+ if(..())
+ return
+
+ if(href_list["adj_pressure"])
+ var/change = text2num(href_list["adj_pressure"])
+ pressure_setting = between(0, pressure_setting + change, 10*ONE_ATMOSPHERE)
+ spawn(1)
+ src.updateUsrDialog()
+ return
+
+ if(href_list["adj_input_flow_rate"])
+ var/change = text2num(href_list["adj_input_flow_rate"])
+ input_flow_setting = between(0, input_flow_setting + change, ATMOS_DEFAULT_VOLUME_PUMP + 500) //default flow rate limit for air injectors
+ spawn(1)
+ src.updateUsrDialog()
+ return
+
+ if(!radio_connection)
+ return 0
+ var/datum/signal/signal = new
+ signal.transmission_method = 1 //radio signal
+ signal.source = src
+ if(href_list["in_refresh_status"])
+ input_info = null
+ signal.data = list ("tag" = input_tag, "status" = 1)
+
+ if(href_list["in_toggle_injector"])
+ input_info = null
+ signal.data = list ("tag" = input_tag, "power_toggle" = 1)
+
+ if(href_list["in_set_flowrate"])
+ input_info = null
+ signal.data = list ("tag" = input_tag, "set_volume_rate" = "[input_flow_setting]")
+
+ if(href_list["out_refresh_status"])
+ output_info = null
+ signal.data = list ("tag" = output_tag, "status" = 1)
+
+ if(href_list["out_toggle_power"])
+ output_info = null
+ signal.data = list ("tag" = output_tag, "power_toggle" = 1)
+
+ if(href_list["out_set_pressure"])
+ output_info = null
+ signal.data = list ("tag" = output_tag, "set_external_pressure" = "[pressure_setting]", "checks" = 1)
+
+ signal.data["sigtype"]="command"
+ radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
+
+ spawn(5)
+ src.updateUsrDialog()
+
+/obj/machinery/computer/general_air_control/fuel_injection
+ icon = 'icons/obj/computer.dmi'
+ icon_state = "atmos"
+
+ var/device_tag
+ var/list/device_info
+
+ var/automation = 0
+
+ var/cutoff_temperature = 2000
+ var/on_temperature = 1200
+ circuit = /obj/item/weapon/circuitboard/air_management/injector_control
+
+/obj/machinery/computer/general_air_control/fuel_injection/process()
+ if(automation)
+ if(!radio_connection)
+ return 0
+
+ var/injecting = 0
+ for(var/id_tag in sensor_information)
+ var/list/data = sensor_information[id_tag]
+ if(data["temperature"])
+ if(data["temperature"] >= cutoff_temperature)
+ injecting = 0
+ break
+ if(data["temperature"] <= on_temperature)
+ injecting = 1
+
+ var/datum/signal/signal = new
+ signal.transmission_method = 1 //radio signal
+ signal.source = src
+
+ signal.data = list(
+ "tag" = device_tag,
+ "power" = injecting,
+ "sigtype"="command"
+ )
+
+ radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
+
+ ..()
+
+/obj/machinery/computer/general_air_control/fuel_injection/return_text()
+ var/output = ..()
+
+ output += "Fuel Injection System
"
+ if(device_info)
+ var/power = device_info["power"]
+ var/volume_rate = device_info["volume_rate"]
+ output += {"Status: [power?("Injecting"):("On Hold")] Refresh
Rate: [volume_rate] L/sec
"}
- if(automation)
- output += "Automated Fuel Injection: Engaged
"
- output += "Injector Controls Locked Out
"
- else
- output += "Automated Fuel Injection: Disengaged
"
- output += "Injector: Toggle Power Inject (1 Cycle)
"
+ if(automation)
+ output += "Automated Fuel Injection: Engaged
"
+ output += "Injector Controls Locked Out
"
+ else
+ output += "Automated Fuel Injection: Disengaged
"
+ output += "Injector: Toggle Power Inject (1 Cycle)
"
- else
- output += "ERROR: Can not find device Search
"
+ else
+ output += "ERROR: Can not find device Search
"
- return output
+ return output
- receive_signal(datum/signal/signal)
- if(!signal || signal.encryption) return
+/obj/machinery/computer/general_air_control/fuel_injection/receive_signal(datum/signal/signal)
+ if(!signal || signal.encryption) return
- var/id_tag = signal.data["tag"]
+ var/id_tag = signal.data["tag"]
- if(device_tag == id_tag)
- device_info = signal.data
- else
- ..(signal)
+ if(device_tag == id_tag)
+ device_info = signal.data
+ else
+ ..(signal)
- Topic(href, href_list)
- if(..())
- return
+/obj/machinery/computer/general_air_control/fuel_injection/Topic(href, href_list)
+ if(..())
+ return
- if(href_list["refresh_status"])
- device_info = null
- if(!radio_connection)
- return 0
+ if(href_list["refresh_status"])
+ device_info = null
+ if(!radio_connection)
+ return 0
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
- signal.data = list(
- "tag" = device_tag,
- "status",
- "sigtype"="command"
- )
- radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
+ var/datum/signal/signal = new
+ signal.transmission_method = 1 //radio signal
+ signal.source = src
+ signal.data = list(
+ "tag" = device_tag,
+ "status" = 1,
+ "sigtype"="command"
+ )
+ radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
- if(href_list["toggle_automation"])
- automation = !automation
+ if(href_list["toggle_automation"])
+ automation = !automation
- if(href_list["toggle_injector"])
- device_info = null
- if(!radio_connection)
- return 0
+ if(href_list["toggle_injector"])
+ device_info = null
+ if(!radio_connection)
+ return 0
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
- signal.data = list(
- "tag" = device_tag,
- "power_toggle",
- "sigtype"="command"
- )
+ var/datum/signal/signal = new
+ signal.transmission_method = 1 //radio signal
+ signal.source = src
+ signal.data = list(
+ "tag" = device_tag,
+ "power_toggle" = 1,
+ "sigtype"="command"
+ )
- radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
+ radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
- if(href_list["injection"])
- if(!radio_connection)
- return 0
+ if(href_list["injection"])
+ if(!radio_connection)
+ return 0
- var/datum/signal/signal = new
- signal.transmission_method = 1 //radio signal
- signal.source = src
- signal.data = list(
- "tag" = device_tag,
- "inject",
- "sigtype"="command"
- )
+ var/datum/signal/signal = new
+ signal.transmission_method = 1 //radio signal
+ signal.source = src
+ signal.data = list(
+ "tag" = device_tag,
+ "inject" = 1,
+ "sigtype"="command"
+ )
- radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
+ radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
diff --git a/code/game/machinery/atmoalter/canister.dm b/code/game/machinery/atmoalter/canister.dm
index 9e85bccfda0..ff7821fa0af 100644
--- a/code/game/machinery/atmoalter/canister.dm
+++ b/code/game/machinery/atmoalter/canister.dm
@@ -49,7 +49,8 @@
icon_state = "grey"
canister_color = "grey"
can_label = 0
-
+/obj/machinery/portable_atmospherics/canister/air/airlock
+ filled = 0.05
/obj/machinery/portable_atmospherics/canister/empty/oxygen
name = "Canister: \[O2\]"
icon_state = "blue"
diff --git a/code/game/machinery/atmoalter/meter.dm b/code/game/machinery/atmoalter/meter.dm
index 9c26fa4a4e5..1c99ff73448 100644
--- a/code/game/machinery/atmoalter/meter.dm
+++ b/code/game/machinery/atmoalter/meter.dm
@@ -77,7 +77,7 @@
else if(src.target)
var/datum/gas_mixture/environment = target.return_air()
if(environment)
- t += "The pressure gauge reads [round(environment.return_pressure(), 0.01)] kPa; [round(environment.temperature,0.01)]°K ([round(environment.temperature-T0C,0.01)]°C)"
+ t += "The pressure gauge reads [round(environment.return_pressure(), 0.01)] kPa; [round(environment.temperature,0.01)]K ([round(environment.temperature-T0C,0.01)]°C)"
else
t += "The sensor error light is blinking."
else
diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm
index c24d07a2eda..1261d0fc146 100644
--- a/code/game/machinery/autolathe.dm
+++ b/code/game/machinery/autolathe.dm
@@ -373,4 +373,15 @@
tot_rating += MB.rating
storage_capacity["metal"] = tot_rating * 25000
- storage_capacity["glass"] = tot_rating * 12500
\ No newline at end of file
+ storage_capacity["glass"] = tot_rating * 12500
+
+/obj/machinery/autolathe/dismantle()
+ ..()
+ var/list/sheets = list("metal" = /obj/item/stack/sheet/metal, "glass" = /obj/item/stack/sheet/glass)
+
+ for(var/mat in stored_material)
+ var/T = sheets[mat]
+ var/obj/item/stack/sheet/S = new T
+ if(stored_material[mat] > S.perunit)
+ S.amount = round(stored_material[mat] / S.perunit)
+ S.loc = loc
diff --git a/code/game/machinery/bots/floorbot.dm b/code/game/machinery/bots/floorbot.dm
index 0691a74e541..2502277226b 100644
--- a/code/game/machinery/bots/floorbot.dm
+++ b/code/game/machinery/bots/floorbot.dm
@@ -79,7 +79,7 @@
var/dat
dat += "Automatic Station Floor Repairer v1.0
"
dat += "Status: [src.on ? "On" : "Off"]
"
- dat += "Maintenance panel panel is [src.open ? "opened" : "closed"]
"
+ dat += "Maintenance panel is [src.open ? "opened" : "closed"]
"
dat += "Tiles left: [src.amount]
"
dat += "Behvaiour controls are [src.locked ? "locked" : "unlocked"]
"
if(!src.locked || issilicon(user))
@@ -448,4 +448,4 @@
if (!in_range(src, usr) && src.loc != usr)
return
- src.created_name = t
\ No newline at end of file
+ src.created_name = t
diff --git a/code/game/machinery/bots/medbot.dm b/code/game/machinery/bots/medbot.dm
index c5008e1dc74..f55501c3fb4 100644
--- a/code/game/machinery/bots/medbot.dm
+++ b/code/game/machinery/bots/medbot.dm
@@ -106,7 +106,7 @@
var/dat
dat += "Automatic Medical Unit v1.0
"
dat += "Status: [src.on ? "On" : "Off"]
"
- dat += "Maintenance panel panel is [src.open ? "opened" : "closed"]
"
+ dat += "Maintenance panel is [src.open ? "opened" : "closed"]
"
dat += "Beaker: "
if (src.reagent_glass)
dat += "Loaded \[[src.reagent_glass.reagents.total_volume]/[src.reagent_glass.reagents.maximum_volume]\]"
diff --git a/code/game/machinery/bots/secbot.dm b/code/game/machinery/bots/secbot.dm
index 6358c1466c2..094f3ff7006 100644
--- a/code/game/machinery/bots/secbot.dm
+++ b/code/game/machinery/bots/secbot.dm
@@ -141,7 +141,7 @@
Automatic Security Unit v[bot_version]
Status: []
Behaviour controls are [src.locked ? "locked" : "unlocked"]
-Maintenance panel panel is [src.open ? "opened" : "closed"]"},
+Maintenance panel is [src.open ? "opened" : "closed"]"},
"[src.on ? "On" : "Off"]" )
diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm
index b50d38dcb6a..14f8f93e56f 100644
--- a/code/game/machinery/camera/camera.dm
+++ b/code/game/machinery/camera/camera.dm
@@ -70,13 +70,7 @@
cancelCameraAlarm()
if(can_use())
cameranet.addCamera(src)
- for(var/mob/O in mob_list)
- if (istype(O.machine, /obj/machinery/computer/security))
- var/obj/machinery/computer/security/S = O.machine
- if (S.current == src)
- O.unset_machine()
- O.reset_view(null)
- O << "The screen bursts into static."
+ kick_viewers()
..()
@@ -193,6 +187,10 @@
// now disconnect anyone using the camera
//Apparently, this will disconnect anyone even if the camera was re-activated.
//I guess that doesn't matter since they can't use it anyway?
+ kick_viewers()
+
+//This might be redundant, because of check_eye()
+/obj/machinery/camera/proc/kick_viewers()
for(var/mob/O in player_list)
if (istype(O.machine, /obj/machinery/computer/security))
var/obj/machinery/computer/security/S = O.machine
diff --git a/code/game/machinery/camera/camera_assembly.dm b/code/game/machinery/camera/camera_assembly.dm
index 097c4f9a27e..0017b260c29 100644
--- a/code/game/machinery/camera/camera_assembly.dm
+++ b/code/game/machinery/camera/camera_assembly.dm
@@ -9,7 +9,7 @@
matter = list("metal" = 700,"glass" = 300)
// Motion, EMP-Proof, X-Ray
- var/list/obj/item/possible_upgrades = list(/obj/item/device/assembly/prox_sensor, /obj/item/stack/sheet/mineral/phoron, /obj/item/weapon/reagent_containers/food/snacks/grown/carrot)
+ var/list/obj/item/possible_upgrades = list(/obj/item/device/assembly/prox_sensor, /obj/item/stack/sheet/mineral/osmium, /obj/item/weapon/stock_parts/scanning_module)
var/list/upgrades = list()
var/state = 0
var/busy = 0
@@ -88,7 +88,8 @@
usr << "No network found please hang up and try your call again."
return
- var/temptag = "[get_area(src)] ([rand(1, 999)])"
+ var/area/camera_area = get_area(src)
+ var/temptag = "[sanitize(camera_area.name)] ([rand(1, 999)])"
input = strip_html(input(usr, "How would you like to name the camera?", "Set Camera Name", temptag))
state = 4
@@ -125,7 +126,7 @@
// Upgrades!
if(is_type_in_list(W, possible_upgrades) && !is_type_in_list(W, upgrades)) // Is a possible upgrade and isn't in the camera already.
- user << "You attach the [W] into the assembly inner circuits."
+ user << "You attach \the [W] into the assembly inner circuits."
upgrades += W
user.drop_item(W)
W.loc = src
diff --git a/code/game/machinery/camera/motion.dm b/code/game/machinery/camera/motion.dm
index 19f2620630e..0c6f7d95a7f 100644
--- a/code/game/machinery/camera/motion.dm
+++ b/code/game/machinery/camera/motion.dm
@@ -8,6 +8,8 @@
/obj/machinery/camera/process()
// motion camera event loop
+ if (stat & (EMPED|NOPOWER))
+ return
if(!isMotion())
. = PROCESS_KILL
return
@@ -40,16 +42,20 @@
cancelAlarm()
/obj/machinery/camera/proc/cancelAlarm()
+ if (!status || (stat & NOPOWER))
+ return 0
if (detectTime == -1)
for (var/mob/living/silicon/aiPlayer in player_list)
- if (status) aiPlayer.cancelAlarm("Motion", get_area(src), src)
+ aiPlayer.cancelAlarm("Motion", get_area(src), src)
detectTime = 0
return 1
/obj/machinery/camera/proc/triggerAlarm()
+ if (!status || (stat & NOPOWER))
+ return 0
if (!detectTime) return 0
for (var/mob/living/silicon/aiPlayer in player_list)
- if (status) aiPlayer.triggerAlarm("Motion", get_area(src), list(src), src)
+ aiPlayer.triggerAlarm("Motion", get_area(src), list(src), src)
detectTime = -1
return 1
diff --git a/code/game/machinery/camera/presets.dm b/code/game/machinery/camera/presets.dm
index 0c0c8457003..21a9dc10616 100644
--- a/code/game/machinery/camera/presets.dm
+++ b/code/game/machinery/camera/presets.dm
@@ -53,12 +53,14 @@
// CHECKS
/obj/machinery/camera/proc/isEmpProof()
- var/O = locate(/obj/item/stack/sheet/mineral/phoron) in assembly.upgrades
+ var/O = locate(/obj/item/stack/sheet/mineral/osmium) in assembly.upgrades
return O
/obj/machinery/camera/proc/isXRay()
- var/O = locate(/obj/item/weapon/reagent_containers/food/snacks/grown/carrot) in assembly.upgrades
- return O
+ var/obj/item/weapon/stock_parts/scanning_module/O = locate(/obj/item/weapon/stock_parts/scanning_module) in assembly.upgrades
+ if (O && O.rating >= 2)
+ return O
+ return null
/obj/machinery/camera/proc/isMotion()
var/O = locate(/obj/item/device/assembly/prox_sensor) in assembly.upgrades
@@ -67,11 +69,22 @@
// UPGRADE PROCS
/obj/machinery/camera/proc/upgradeEmpProof()
- assembly.upgrades.Add(new /obj/item/stack/sheet/mineral/phoron(assembly))
+ assembly.upgrades.Add(new /obj/item/stack/sheet/mineral/osmium(assembly))
+ setPowerUsage()
/obj/machinery/camera/proc/upgradeXRay()
- assembly.upgrades.Add(new /obj/item/weapon/reagent_containers/food/snacks/grown/carrot(assembly))
+ assembly.upgrades.Add(new /obj/item/weapon/stock_parts/scanning_module/adv(assembly))
+ setPowerUsage()
// If you are upgrading Motion, and it isn't in the camera's New(), add it to the machines list.
/obj/machinery/camera/proc/upgradeMotion()
- assembly.upgrades.Add(new /obj/item/device/assembly/prox_sensor(assembly))
\ No newline at end of file
+ assembly.upgrades.Add(new /obj/item/device/assembly/prox_sensor(assembly))
+ setPowerUsage()
+
+/obj/machinery/camera/proc/setPowerUsage()
+ var/mult = 1
+ if (isXRay())
+ mult++
+ if (isMotion())
+ mult++
+ active_power_usage = mult*initial(active_power_usage)
diff --git a/code/game/machinery/computer/buildandrepair.dm b/code/game/machinery/computer/buildandrepair.dm
index 50eb026b933..06527e3f97f 100644
--- a/code/game/machinery/computer/buildandrepair.dm
+++ b/code/game/machinery/computer/buildandrepair.dm
@@ -25,15 +25,16 @@
var/frame_desc = null
var/contain_parts = 1
-//Called when the circuitboard is used to contruct a new computer.
-/obj/item/weapon/circuitboard/proc/construct_computer(var/obj/machinery/computer/C)
- if (istype(C, build_path))
+//Called when the circuitboard is used to contruct a new machine.
+/obj/item/weapon/circuitboard/proc/construct(var/obj/machinery/M)
+ if (istype(M, build_path))
return 1
return 0
-//Called when a computer is deconstructed to produce a circuitboard
-/obj/item/weapon/circuitboard/proc/deconstruct_computer(var/obj/machinery/computer/C)
- if (istype(C, build_path))
+//Called when a computer is deconstructed to produce a circuitboard.
+//Only used by computers, as other machines store their circuitboard instance.
+/obj/item/weapon/circuitboard/proc/deconstruct(var/obj/machinery/M)
+ if (istype(M, build_path))
return 1
return 0
@@ -55,11 +56,11 @@
var/locked = 1
var/emagged = 0
-/obj/item/weapon/circuitboard/security/construct_computer(var/obj/machinery/computer/security/C)
+/obj/item/weapon/circuitboard/security/construct(var/obj/machinery/computer/security/C)
if (..(C))
C.network = network
-/obj/item/weapon/circuitboard/security/deconstruct_computer(var/obj/machinery/computer/security/C)
+/obj/item/weapon/circuitboard/security/deconstruct(var/obj/machinery/computer/security/C)
if (..(C))
network = C.network
@@ -132,15 +133,20 @@
/obj/item/weapon/circuitboard/air_management/tank_control
name = "Circuit board (Tank Control)"
build_path = "/obj/machinery/computer/general_air_control/large_tank_control"
+ frequency = 1441
+/obj/item/weapon/circuitboard/air_management/supermatter_core
+ name = "Circuit board (Core Control)"
+ build_path = "/obj/machinery/computer/general_air_control/supermatter_core"
+ frequency = 1438
/obj/item/weapon/circuitboard/air_management/injector_control
name = "Circuit board (Injector Control)"
build_path = "/obj/machinery/computer/general_air_control/fuel_injection"
-/obj/item/weapon/circuitboard/air_management/construct_computer(var/obj/machinery/computer/general_air_control/C)
+/obj/item/weapon/circuitboard/air_management/construct(var/obj/machinery/computer/general_air_control/C)
if (..(C))
C.frequency = frequency
-/obj/item/weapon/circuitboard/air_management/deconstruct_computer(var/obj/machinery/computer/general_air_control/C)
+/obj/item/weapon/circuitboard/air_management/deconstruct(var/obj/machinery/computer/general_air_control/C)
if (..(C))
frequency = C.frequency
@@ -216,11 +222,11 @@
origin_tech = "programming=3"
var/contraband_enabled = 0
-/obj/item/weapon/circuitboard/supplycomp/construct_computer(var/obj/machinery/computer/supplycomp/SC)
+/obj/item/weapon/circuitboard/supplycomp/construct(var/obj/machinery/computer/supplycomp/SC)
if (..(SC))
SC.can_order_contraband = contraband_enabled
-/obj/item/weapon/circuitboard/supplycomp/deconstruct_computer(var/obj/machinery/computer/supplycomp/SC)
+/obj/item/weapon/circuitboard/supplycomp/deconstruct(var/obj/machinery/computer/supplycomp/SC)
if (..(SC))
contraband_enabled = SC.can_order_contraband
@@ -446,5 +452,5 @@
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
user << "\blue You connect the monitor."
var/B = new src.circuit.build_path ( src.loc )
- src.circuit.construct_computer(B)
+ src.circuit.construct(B)
del(src)
\ No newline at end of file
diff --git a/code/game/machinery/computer/camera.dm b/code/game/machinery/computer/camera.dm
index 13dd68d584c..ef434955a1a 100644
--- a/code/game/machinery/computer/camera.dm
+++ b/code/game/machinery/computer/camera.dm
@@ -21,8 +21,10 @@
check_eye(var/mob/user as mob)
- if ((get_dist(user, src) > 1 || !( user.canmove ) || user.blinded || !( current ) || !( current.status )) && (!istype(user, /mob/living/silicon)))
+ if (user.stat || ((get_dist(user, src) > 1 || !( user.canmove ) || user.blinded) && !istype(user, /mob/living/silicon))) //user can't see - not sure why canmove is here.
return null
+ if ( !current || !current.can_use() ) //camera doesn't work
+ current = null
user.reset_view(current)
return 1
@@ -46,7 +48,7 @@
D["Cancel"] = "Cancel"
for(var/obj/machinery/camera/C in L)
if(can_access_camera(C))
- D[text("[][]", C.c_tag, (C.status ? null : " (Deactivated)"))] = C
+ D[text("[][]", C.c_tag, (C.can_use() ? null : " (Deactivated)"))] = C
var/t = input(user, "Which camera should you change to?") as null|anything in D
if(!t)
@@ -72,19 +74,18 @@
return 0
proc/switch_to_camera(var/mob/user, var/obj/machinery/camera/C)
- if ((get_dist(user, src) > 1 || user.machine != src || user.blinded || !( user.canmove ) || !( C.can_use() )) && (!istype(user, /mob/living/silicon/ai)))
- if(!C.can_use() && !isAI(user))
- src.current = null
- return 0
- else
- if(isAI(user))
- var/mob/living/silicon/ai/A = user
- A.eyeobj.setLoc(get_turf(C))
- A.client.eye = A.eyeobj
- else
- src.current = C
- use_power(50)
+ //don't need to check if the camera works for AI because the AI jumps to the camera location and doesn't actually look through cameras.
+ if(isAI(user))
+ var/mob/living/silicon/ai/A = user
+ A.eyeobj.setLoc(get_turf(C))
+ A.client.eye = A.eyeobj
return 1
+
+ if (!C.can_use() || user.stat || (get_dist(user, src) > 1 || user.machine != src || user.blinded || !( user.canmove ) && !istype(user, /mob/living/silicon)))
+ return 0
+ src.current = C
+ use_power(50)
+ return 1
//Camera control: moving.
proc/jump_on_click(var/mob/user,var/A)
diff --git a/code/game/machinery/computer/camera_monitor.dm b/code/game/machinery/computer/camera_monitor.dm
index c8f3b7b3481..11e8ddd43c6 100644
--- a/code/game/machinery/computer/camera_monitor.dm
+++ b/code/game/machinery/computer/camera_monitor.dm
@@ -40,7 +40,7 @@
D["Cancel"] = "Cancel"
for (var/obj/machinery/camera/C in L)
if ( C.network in src.networks )
- D[text("[]: [][]", C.network, C.c_tag, (C.status ? null : " (Deactivated)"))] = C
+ D[text("[]: [][]", C.network, C.c_tag, (C.can_use() ? null : " (Deactivated)"))] = C
var/t = input(user, "Which camera should you change to?") as null|anything in D
diff --git a/code/game/machinery/computer/computer.dm b/code/game/machinery/computer/computer.dm
index 23e764efe4f..ff88f89c5a2 100644
--- a/code/game/machinery/computer/computer.dm
+++ b/code/game/machinery/computer/computer.dm
@@ -120,7 +120,7 @@
user << "\blue You disconnect the monitor."
A.state = 4
A.icon_state = "4"
- M.deconstruct_computer(src)
+ M.deconstruct(src)
del(src)
else
src.attack_hand(user)
diff --git a/code/game/machinery/computer/crew.dm b/code/game/machinery/computer/crew.dm
index 4796afff998..d9b0bbc433f 100644
--- a/code/game/machinery/computer/crew.dm
+++ b/code/game/machinery/computer/crew.dm
@@ -117,10 +117,7 @@
ui.add_template("mapContent", "crew_monitor_map_content.tmpl")
// adding a template with the key "mapHeader" replaces the map header content
ui.add_template("mapHeader", "crew_monitor_map_header.tmpl")
-
- // we want to show the map by default
- ui.set_show_map(1)
-
+
ui.set_initial_data(data)
ui.open()
diff --git a/code/game/machinery/constructable_frame.dm b/code/game/machinery/constructable_frame.dm
index 8a7060ac7ea..106cd2bbad2 100644
--- a/code/game/machinery/constructable_frame.dm
+++ b/code/game/machinery/constructable_frame.dm
@@ -115,6 +115,7 @@
playsound(src.loc, 'sound/items/Screwdriver.ogg', 50, 1)
var/obj/machinery/new_machine = new src.circuit.build_path(src.loc)
new_machine.component_parts.Cut()
+ src.circuit.construct(new_machine)
for(var/obj/O in src)
if(circuit.contain_parts) // things like disposal don't want their parts in them
O.loc = new_machine
@@ -275,10 +276,35 @@ obj/item/weapon/circuitboard/rdserver
"/obj/item/weapon/stock_parts/console_screen" = 1,
"/obj/item/stack/cable_coil" = 2,)
-/obj/item/weapon/circuitboard/gas_heater
+/obj/item/weapon/circuitboard/unary_atmos
+ board_type = "machine"
+ var/machine_dir = SOUTH
+ var/init_dirs = SOUTH
+
+/obj/item/weapon/circuitboard/unary_atmos/attackby(obj/item/I as obj, mob/user as mob)
+ if(istype(I,/obj/item/weapon/screwdriver))
+ machine_dir = turn(machine_dir, 90)
+ init_dirs = machine_dir
+ user.visible_message("\blue \The [user] adjusts the jumper on the [src]'s port configuration pins.", "\blue You adjust the jumper on the port configuration pins. Now set to [dir2text(machine_dir)].")
+ return
+
+/obj/item/weapon/circuitboard/unary_atmos/examine()
+ ..()
+ usr << "The jumper is connecting the [dir2text(machine_dir)] pins."
+
+/obj/item/weapon/circuitboard/unary_atmos/construct(var/obj/machinery/atmospherics/unary/U)
+ //TODO: Move this stuff into the relevant constructor when pipe/construction.dm is cleaned up.
+ U.dir = src.machine_dir
+ U.initialize_directions = src.init_dirs
+ U.initialize()
+ U.build_network()
+ if (U.node)
+ U.node.initialize()
+ U.node.build_network()
+
+/obj/item/weapon/circuitboard/unary_atmos/heater
name = "Circuit Board (Gas Heating System)"
build_path = "/obj/machinery/atmospherics/unary/heater"
- board_type = "machine"
origin_tech = "powerstorage=2;engineering=1"
frame_desc = "Requires 5 Pieces of Cable, 1 Matter Bin, and 2 Capacitors."
req_components = list(
@@ -286,10 +312,9 @@ obj/item/weapon/circuitboard/rdserver
"/obj/item/weapon/stock_parts/matter_bin" = 1,
"/obj/item/weapon/stock_parts/capacitor" = 2)
-/obj/item/weapon/circuitboard/gas_cooler
+/obj/item/weapon/circuitboard/unary_atmos/cooler
name = "Circuit Board (Gas Cooling System)"
build_path = "/obj/machinery/atmospherics/unary/freezer"
- board_type = "machine"
origin_tech = "magnets=2;engineering=2"
frame_desc = "Requires 2 Pieces of Cable, 1 Matter Bin, 1 Micro Manipulator, and 2 Capacitors."
req_components = list(
diff --git a/code/game/machinery/cryo.dm b/code/game/machinery/cryo.dm
index 29451066847..3974ebdd503 100644
--- a/code/game/machinery/cryo.dm
+++ b/code/game/machinery/cryo.dm
@@ -1,3 +1,5 @@
+#define HEAT_CAPACITY_HUMAN 100 //249840 J/K, for a 72 kg person.
+
/obj/machinery/atmospherics/unary/cryo_cell
name = "cryo cell"
icon = 'icons/obj/cryogenics.dmi'
@@ -10,7 +12,7 @@
use_power = 1
idle_power_usage = 20
active_power_usage = 200
-
+
var/temperature_archived
var/mob/living/carbon/occupant = null
var/obj/item/weapon/reagent_containers/glass/beaker = null
diff --git a/code/game/machinery/cryopod.dm b/code/game/machinery/cryopod.dm
index fe569e23647..48321f9fc80 100644
--- a/code/game/machinery/cryopod.dm
+++ b/code/game/machinery/cryopod.dm
@@ -41,6 +41,7 @@ var/global/list/frozen_items = list()
dat += "
Cryogenic Oversight Control
"
dat += "Welcome, [user.real_name].
"
dat += "View storage log.
"
+ dat += "View objects.
"
dat += "Recover object.
"
dat += "Recover all objects.
"
@@ -65,16 +66,27 @@ var/global/list/frozen_items = list()
user << browse(dat, "window=cryolog")
+ if(href_list["view"])
+
+ var/dat = "Recently stored objects
"
+ for(var/obj/item/I in frozen_items)
+ dat += "[I.name]
"
+ dat += "
"
+
+ user << browse(dat, "window=cryoitems")
+
else if(href_list["item"])
if(frozen_items.len == 0)
user << "\blue There is nothing to recover from storage."
return
- var/obj/item/I = input(usr, "Please choose which object to retrieve.","Object recovery",null) as obj in frozen_items
+ var/obj/item/I = input(usr, "Please choose which object to retrieve.","Object recovery",null) as null|anything in frozen_items
+ if(!I)
+ return
- if(!I || frozen_items.len == 0)
- user << "\blue There is nothing to recover from storage."
+ if(!(I in frozen_items))
+ user << "\blue \The [I] is no longer in storage."
return
visible_message("\blue The console beeps happily as it disgorges \the [I].", 3)
@@ -134,10 +146,10 @@ var/global/list/frozen_items = list()
density = 1
anchored = 1
- var/mob/occupant = null // Person waiting to be despawned.
- var/orient_right = null // Flips the sprite.
- var/time_till_despawn = 9000 // 15 minutes-ish safe period before being despawned.
- var/time_entered = 0 // Used to keep track of the safe period.
+ var/mob/occupant = null // Person waiting to be despawned.
+ var/orient_right = null // Flips the sprite.
+ var/time_till_despawn = 18000 // 30 minutes-ish safe period before being despawned.
+ var/time_entered = 0 // Used to keep track of the safe period.
var/obj/item/device/radio/intercom/announce //
// These items are preserved when the process() despawn proc occurs.
@@ -173,7 +185,6 @@ var/global/list/frozen_items = list()
//Lifted from Unity stasis.dm and refactored. ~Zuhayr
/obj/machinery/cryopod/process()
if(occupant)
-
//Allow a ten minute gap between entering the pod and actually despawning.
if(world.time - time_entered < time_till_despawn)
return
@@ -187,7 +198,7 @@ var/global/list/frozen_items = list()
if(W.contents.len) //Make sure we catch anything not handled by del() on the items.
for(var/obj/item/O in W.contents)
- if(istype(O,/obj/item/weapon/storage/internal)) //Stop eating pockets you fuck!
+ if(istype(O,/obj/item/weapon/storage/internal)) //Stop eating pockets, you fuck!
continue
O.loc = src
@@ -333,6 +344,7 @@ var/global/list/frozen_items = list()
src.add_fingerprint(M)
/obj/machinery/cryopod/verb/eject()
+
set name = "Eject Pod"
set category = "Object"
set src in oview(1)
@@ -344,6 +356,14 @@ var/global/list/frozen_items = list()
else
icon_state = "body_scanner_0"
+ //Eject any items that aren't meant to be in the pod.
+ var/list/items = src.contents
+ if(occupant) items -= occupant
+ if(announce) items -= announce
+
+ for(var/obj/item/W in items)
+ W.loc = get_turf(src)
+
src.go_out()
add_fingerprint(usr)
return
diff --git a/code/game/machinery/doors/airlock_control.dm b/code/game/machinery/doors/airlock_control.dm
index 3b1700df784..7ad909c8eb4 100644
--- a/code/game/machinery/doors/airlock_control.dm
+++ b/code/game/machinery/doors/airlock_control.dm
@@ -28,7 +28,8 @@ obj/machinery/door/airlock/receive_signal(datum/signal/signal)
if(id_tag != signal.data["tag"] || !signal.data["command"]) return
cur_command = signal.data["command"]
- execute_current_command()
+ spawn()
+ execute_current_command()
obj/machinery/door/airlock/proc/execute_current_command()
if(operating)
diff --git a/code/game/machinery/doors/door.dm b/code/game/machinery/doors/door.dm
index 12f224ac527..ceb04ad56b2 100644
--- a/code/game/machinery/doors/door.dm
+++ b/code/game/machinery/doors/door.dm
@@ -1,4 +1,6 @@
//This file was auto-corrected by findeclaration.exe on 25.5.2012 20:42:31
+#define DOOR_OPEN_LAYER 2.7 //Under all objects if opened. 2.7 due to tables being at 2.6
+#define DOOR_CLOSED_LAYER 3.1 //Above most items if closed
/obj/machinery/door
name = "Door"
@@ -8,7 +10,9 @@
anchored = 1
opacity = 1
density = 1
- layer = 2.7
+ layer = DOOR_OPEN_LAYER
+ var/open_layer = DOOR_OPEN_LAYER
+ var/closed_layer = DOOR_CLOSED_LAYER
var/secondsElectrified = 0
var/visible = 1
@@ -27,11 +31,11 @@
/obj/machinery/door/New()
. = ..()
if(density)
- layer = 3.1 //Above most items if closed
+ layer = closed_layer
explosion_resistance = initial(explosion_resistance)
update_heat_protection(get_turf(src))
else
- layer = 2.7 //Under all objects if opened. 2.7 due to tables being at 2.6
+ layer = open_layer
explosion_resistance = 0
@@ -142,7 +146,7 @@
user = null
if(!src.requiresID())
user = null
- if(src.density && (istype(I, /obj/item/weapon/card/emag)||istype(I, /obj/item/weapon/melee/energy/blade)))
+ if(src.density && ((operable() && istype(I, /obj/item/weapon/card/emag)) || istype(I, /obj/item/weapon/melee/energy/blade)))
flick("door_spark", src)
sleep(6)
open()
@@ -226,7 +230,7 @@
icon_state = "door0"
src.SetOpacity(0)
sleep(10)
- src.layer = 2.7
+ src.layer = open_layer
src.density = 0
explosion_resistance = 0
update_icon()
@@ -250,10 +254,10 @@
if(operating > 0) return
operating = 1
- do_animate("closing")
src.density = 1
explosion_resistance = initial(explosion_resistance)
- src.layer = 3.1
+ src.layer = closed_layer
+ do_animate("closing")
sleep(10)
update_icon()
if(visible && !glass)
diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm
index 40bc8d7e51d..a814ba1718b 100644
--- a/code/game/machinery/doors/firedoor.dm
+++ b/code/game/machinery/doors/firedoor.dm
@@ -1,5 +1,15 @@
/var/const/OPEN = 1
/var/const/CLOSED = 2
+
+#define FIREDOOR_MAX_PRESSURE_DIFF 25 // kPa
+#define FIREDOOR_MAX_TEMP 50 // °C
+#define FIREDOOR_MIN_TEMP 0
+
+// Bitflags
+#define FIREDOOR_ALERT_HOT 1
+#define FIREDOOR_ALERT_COLD 2
+// Not used #define FIREDOOR_ALERT_LOWPRESS 4
+
/obj/machinery/door/firedoor
name = "\improper Emergency Shutter"
desc = "Emergency air-tight shutter, capable of sealing off breached areas."
@@ -8,17 +18,33 @@
req_one_access = list(access_atmospherics, access_engine_equip)
opacity = 0
density = 0
+ layer = DOOR_OPEN_LAYER - 0.01
+ open_layer = DOOR_OPEN_LAYER - 0.01 // Just below doors when open
+ closed_layer = DOOR_CLOSED_LAYER + 0.01 // Just above doors when closed
var/blocked = 0
+ var/lockdown = 0 // When the door has detected a problem, it locks.
+ var/pdiff_alert = 0
+ var/pdiff = 0
var/nextstate = null
var/net_id
var/list/areas_added
- var/list/users_to_open
-
+ var/list/users_to_open = new
+ var/next_process_time = 0
+
power_channel = ENVIRON
use_power = 1
idle_power_usage = 5
+ var/list/tile_info[4]
+ var/list/dir_alerts[4] // 4 dirs, bitflags
+
+ // MUST be in same order as FIREDOOR_ALERT_*
+ var/list/ALERT_STATES=list(
+ "hot",
+ "cold"
+ )
+
/obj/machinery/door/firedoor/New()
. = ..()
for(var/obj/machinery/door/firedoor/F in loc)
@@ -38,7 +64,6 @@
A.all_doors.Add(src)
areas_added += A
-
/obj/machinery/door/firedoor/Del()
for(var/area/A in areas_added)
A.all_doors.Remove(src)
@@ -48,14 +73,47 @@
/obj/machinery/door/firedoor/examine()
set src in view()
. = ..()
- if( islist(users_to_open) && users_to_open.len)
+
+ if(get_dist(src, usr) > 1 && !isAI(usr))
+ return
+
+ if(pdiff >= FIREDOOR_MAX_PRESSURE_DIFF)
+ usr << "WARNING: Current pressure differential is [pdiff]kPa! Opening door may result in injury!"
+
+ usr << "Sensor readings:"
+ for(var/index = 1; index <= tile_info.len; index++)
+ var/o = " "
+ switch(index)
+ if(1)
+ o += "NORTH: "
+ if(2)
+ o += "SOUTH: "
+ if(3)
+ o += "EAST: "
+ if(4)
+ o += "WEST: "
+ if(tile_info[index] == null)
+ o += "DATA UNAVAILABLE"
+ usr << o
+ continue
+ var/celsius = convert_k2c(tile_info[index][1])
+ var/pressure = tile_info[index][2]
+ if(dir_alerts[index] & (FIREDOOR_ALERT_HOT|FIREDOOR_ALERT_COLD))
+ o += ""
+ else
+ o += ""
+ o += "[celsius]°C "
+ o += ""
+ o += "[pressure]kPa"
+ usr << o
+
+ if(islist(users_to_open) && users_to_open.len)
var/users_to_open_string = users_to_open[1]
if(users_to_open.len >= 2)
for(var/i = 2 to users_to_open.len)
users_to_open_string += ", [users_to_open[i]]"
usr << "These people have opened \the [src] during an alert: [users_to_open_string]."
-
/obj/machinery/door/firedoor/Bumped(atom/AM)
if(p_open || operating)
return
@@ -63,7 +121,7 @@
return ..()
if(istype(AM, /obj/mecha))
var/obj/mecha/mecha = AM
- if (mecha.occupant)
+ if(mecha.occupant)
var/mob/M = mecha.occupant
if(world.time - M.last_bumped <= 10) return //Can bump-open one airlock per second. This is to prevent popup message spam.
M.last_bumped = world.time
@@ -79,12 +137,7 @@
user << "\The [src] is welded solid!"
return
- if(!allowed(user))
- user << "Access denied."
- return
-
- var/alarmed = 0
-
+ var/alarmed = lockdown
for(var/area/A in areas_added) //Checks if there are fire alarms in any areas associated with that firedoor
if(A.fire || A.air_doors_activated)
alarmed = 1
@@ -100,9 +153,21 @@
user << "\The [src] is not functioning, you'll have to force it open manually."
return
+ if(alarmed && density && lockdown && !allowed(user))
+ user << "Access denied. Please wait for authorities to arrive, or for the alert to clear."
+ return
+ else
+ user.visible_message("\The [src] [density ? "open" : "close"]s for \the [user].",\
+ "\The [src] [density ? "open" : "close"]s.",\
+ "You hear a beep, and a door opening.")
+
var/needs_to_close = 0
if(density)
if(alarmed)
+ // Accountability!
+ users_to_open |= user.name
+ log_admin("[user]([user.ckey]) has opened an alarming emergency shutter.")
+ message_admins("[user]([user.ckey]) has opened an alarming emergency shutter.")
needs_to_close = 1
spawn()
open()
@@ -128,38 +193,42 @@
var/obj/item/weapon/weldingtool/W = C
if(W.remove_fuel(0, user))
blocked = !blocked
- user.visible_message("\red \The [user] [blocked ? "welds" : "unwelds"] \the [src] with \a [W].",\
+ user.visible_message("\The [user] [blocked ? "welds" : "unwelds"] \the [src] with \a [W].",\
"You [blocked ? "weld" : "unweld"] \the [src] with \the [W].",\
"You hear something being welded.")
update_icon()
return
if(blocked)
- user << "\red \The [src] is welded solid!"
+ user << "\The [src] is welded solid!"
return
-
- if( istype(C, /obj/item/weapon/crowbar) || ( istype(C,/obj/item/weapon/twohanded/fireaxe) && C:wielded == 1 ) )
+ if(istype(C, /obj/item/weapon/crowbar) || istype(C,/obj/item/weapon/melee/energy/blade) || istype(C,/obj/item/weapon/twohanded/fireaxe))
if(operating)
return
- if( blocked && istype(C, /obj/item/weapon/crowbar) )
- user.visible_message("\red \The [user] pries at \the [src] with \a [C], but \the [src] is welded in place!",\
+ if(blocked && istype(C, /obj/item/weapon/crowbar))
+ user.visible_message("\The [user] pries at \the [src] with \a [C], but \the [src] is welded in place!",\
"You try to pry \the [src] [density ? "open" : "closed"], but it is welded in place!",\
"You hear someone struggle and metal straining.")
return
- user.visible_message("\red \The [user] starts to force \the [src] [density ? "open" : "closed"] with \a [C]!",\
+ if(istype(C,/obj/item/weapon/twohanded/fireaxe))
+ var/obj/item/weapon/twohanded/fireaxe/F = C
+ if(!F.wielded)
+ return
+
+ user.visible_message("\The [user] starts to force \the [src] [density ? "open" : "closed"] with \a [C]!",\
"You start forcing \the [src] [density ? "open" : "closed"] with \the [C]!",\
"You hear metal strain.")
if(do_after(user,30))
- if( istype(C, /obj/item/weapon/crowbar) )
- if( stat & (BROKEN|NOPOWER) || !density)
- user.visible_message("\red \The [user] forces \the [src] [density ? "open" : "closed"] with \a [C]!",\
+ if(istype(C, /obj/item/weapon/crowbar))
+ if(stat & (BROKEN|NOPOWER) || !density)
+ user.visible_message("\The [user] forces \the [src] [density ? "open" : "closed"] with \a [C]!",\
"You force \the [src] [density ? "open" : "closed"] with \the [C]!",\
"You hear metal strain, and a door [density ? "open" : "close"].")
else
- user.visible_message("\red \The [user] forces \the [ blocked ? "welded" : "" ] [src] [density ? "open" : "closed"] with \a [C]!",\
+ user.visible_message("\The [user] forces \the [ blocked ? "welded" : "" ] [src] [density ? "open" : "closed"] with \a [C]!",\
"You force \the [ blocked ? "welded" : "" ] [src] [density ? "open" : "closed"] with \the [C]!",\
"You hear metal strain and groan, and a door [density ? "opening" : "closing"].")
if(density)
@@ -170,7 +239,50 @@
close()
return
+// CHECK PRESSURE
+/obj/machinery/door/firedoor/process()
+ ..()
+ if(density && next_process_time <= world.time)
+ next_process_time = world.time + 100 // 10 second delays between process updates
+ var/changed = 0
+ lockdown=0
+ // Pressure alerts
+ pdiff = getOPressureDifferential(src.loc)
+ if(pdiff >= FIREDOOR_MAX_PRESSURE_DIFF)
+ lockdown = 1
+ if(!pdiff_alert)
+ pdiff_alert = 1
+ changed = 1 // update_icon()
+ else
+ if(pdiff_alert)
+ pdiff_alert = 0
+ changed = 1 // update_icon()
+
+ tile_info = getCardinalAirInfo(src.loc,list("temperature","pressure"))
+ var/old_alerts = dir_alerts
+ for(var/index = 1; index <= 4; index++)
+ var/list/tileinfo=tile_info[index]
+ if(tileinfo==null)
+ continue // Bad data.
+ var/celsius = convert_k2c(tileinfo[1])
+
+ var/alerts=0
+
+ // Temperatures
+ if(celsius >= FIREDOOR_MAX_TEMP)
+ alerts |= FIREDOOR_ALERT_HOT
+ lockdown = 1
+ else if(celsius <= FIREDOOR_MIN_TEMP)
+ alerts |= FIREDOOR_ALERT_COLD
+ lockdown = 1
+
+ dir_alerts[index]=alerts
+
+ if(dir_alerts != old_alerts)
+ changed = 1
+ if(changed)
+ update_icon()
/obj/machinery/door/firedoor/proc/latetoggle()
if(operating || !nextstate)
@@ -178,6 +290,7 @@
switch(nextstate)
if(OPEN)
nextstate = null
+
open()
if(CLOSED)
nextstate = null
@@ -189,15 +302,17 @@
return ..()
/obj/machinery/door/firedoor/open(var/forced = 0)
- if (!forced)
- if (stat & (BROKEN|NOPOWER))
+ if(!forced)
+ if(stat & (BROKEN|NOPOWER))
return //needs power to open unless it was forced
else
use_power(360)
+ else
+ log_admin("[usr]([usr.ckey]) has forced open an emergency shutter.")
+ message_admins("[usr]([usr.ckey]) has forced open an emergency shutter.")
latetoggle()
return ..()
-
/obj/machinery/door/firedoor/do_animate(animation)
switch(animation)
if("opening")
@@ -213,6 +328,14 @@
icon_state = "door_closed"
if(blocked)
overlays += "welded"
+ if(pdiff_alert)
+ overlays += "palert"
+ if(dir_alerts)
+ for(var/d=1;d<=4;d++)
+ var/cdir = cardinal[d]
+ for(var/i=1;i<=ALERT_STATES.len;i++)
+ if(dir_alerts[d] & (1<<(i-1)))
+ overlays += new/icon(icon,"alert_[ALERT_STATES[i]]", dir=cdir)
else
icon_state = "door_open"
if(blocked)
@@ -220,7 +343,6 @@
return
-
/obj/machinery/door/firedoor/border_only
//These are playing merry hell on ZAS. Sorry fellas :(
/*
diff --git a/code/game/machinery/embedded_controller/airlock_controllers.dm b/code/game/machinery/embedded_controller/airlock_controllers.dm
index c7891ef69bf..fb909dee555 100644
--- a/code/game/machinery/embedded_controller/airlock_controllers.dm
+++ b/code/game/machinery/embedded_controller/airlock_controllers.dm
@@ -8,7 +8,8 @@
var/tag_chamber_sensor
var/tag_exterior_sensor
var/tag_interior_sensor
- var/tag_mech_sensor
+ var/tag_airlock_mech_sensor
+ var/tag_shuttle_mech_sensor
var/tag_secure = 0
/obj/machinery/embedded_controller/radio/airlock/initialize()
diff --git a/code/game/machinery/embedded_controller/airlock_program.dm b/code/game/machinery/embedded_controller/airlock_program.dm
index ed93dca9584..8cb3abb9980 100644
--- a/code/game/machinery/embedded_controller/airlock_program.dm
+++ b/code/game/machinery/embedded_controller/airlock_program.dm
@@ -17,7 +17,8 @@
var/tag_chamber_sensor
var/tag_exterior_sensor
var/tag_interior_sensor
- var/tag_mech_sensor
+ var/tag_airlock_mech_sensor
+ var/tag_shuttle_mech_sensor
var/state = STATE_IDLE
var/target_state = TARGET_NONE
@@ -43,7 +44,8 @@
tag_chamber_sensor = controller.tag_chamber_sensor? controller.tag_chamber_sensor : "[id_tag]_sensor"
tag_exterior_sensor = controller.tag_exterior_sensor
tag_interior_sensor = controller.tag_interior_sensor
- tag_mech_sensor = controller.tag_mech_sensor? controller.tag_mech_sensor : "[id_tag]_mech"
+ tag_airlock_mech_sensor = controller.tag_airlock_mech_sensor? controller.tag_airlock_mech_sensor : "[id_tag]_airlock_mech"
+ tag_shuttle_mech_sensor = controller.tag_shuttle_mech_sensor? controller.tag_shuttle_mech_sensor : "[id_tag]_shuttle_mech"
memory["secure"] = controller.tag_secure
spawn(10)
@@ -187,7 +189,7 @@
if(memory["purge"])
target_pressure = 0
-
+
if(memory["purge"])
target_pressure = 0
@@ -202,7 +204,7 @@
//Check for vacuum - this is set after the pumps so the pumps are aiming for 0
if(!memory["target_pressure"])
memory["target_pressure"] = ONE_ATMOSPHERE * 0.05
-
+
if(STATE_PRESSURIZE)
if(memory["chamber_sensor_pressure"] >= memory["target_pressure"] * 0.95)
cycleDoors(target_state)
@@ -303,11 +305,19 @@
signalDoor(tag_exterior_door, command)
signalDoor(tag_interior_door, command)
+datum/computer/file/embedded_program/airlock/proc/signal_mech_sensor(var/command, var/sensor)
+ var/datum/signal/signal = new
+ signal.data["tag"] = sensor
+ signal.data["command"] = command
+ post_signal(signal)
+
/datum/computer/file/embedded_program/airlock/proc/enable_mech_regulation()
- signalDoor(tag_mech_sensor, "enable")
+ signal_mech_sensor("enable", tag_shuttle_mech_sensor)
+ signal_mech_sensor("enable", tag_airlock_mech_sensor)
/datum/computer/file/embedded_program/airlock/proc/disable_mech_regulation()
- signalDoor(tag_mech_sensor, "disable")
+ signal_mech_sensor("disable", tag_shuttle_mech_sensor)
+ signal_mech_sensor("disable", tag_airlock_mech_sensor)
/*----------------------------------------------------------
toggleDoor()
diff --git a/code/game/machinery/embedded_controller/simple_docking_controller.dm b/code/game/machinery/embedded_controller/simple_docking_controller.dm
index 83361c3af34..f1001ada553 100644
--- a/code/game/machinery/embedded_controller/simple_docking_controller.dm
+++ b/code/game/machinery/embedded_controller/simple_docking_controller.dm
@@ -96,12 +96,13 @@
signal.data["command"] = command
post_signal(signal)
-/datum/computer/file/embedded_program/docking/simple/proc/signal_mech_sensor(var/command)
- signal_door(command)
+///datum/computer/file/embedded_program/docking/simple/proc/signal_mech_sensor(var/command)
+// signal_door(command)
+// return
/datum/computer/file/embedded_program/docking/simple/proc/open_door()
if(memory["door_status"]["state"] == "closed")
- signal_mech_sensor("enable")
+ //signal_mech_sensor("enable")
signal_door("secure_open")
else if(memory["door_status"]["lock"] == "unlocked")
signal_door("lock")
@@ -109,7 +110,7 @@
/datum/computer/file/embedded_program/docking/simple/proc/close_door()
if(memory["door_status"]["state"] == "open")
signal_door("secure_close")
- signal_mech_sensor("disable")
+ //signal_mech_sensor("disable")
else if(memory["door_status"]["lock"] == "unlocked")
signal_door("lock")
diff --git a/code/game/machinery/machinery.dm b/code/game/machinery/machinery.dm
index b4ec54d6155..cc2c770a7f1 100644
--- a/code/game/machinery/machinery.dm
+++ b/code/game/machinery/machinery.dm
@@ -106,7 +106,7 @@ Class Procs:
var/active_power_usage = 0
var/power_channel = EQUIP
//EQUIP,ENVIRON or LIGHT
- var/list/component_parts = null //list of all the parts used to build it, if made from certain kinds of frames.
+ var/list/component_parts = list() //list of all the parts used to build it, if made from certain kinds of frames.
var/uid
var/manual = 0
var/global/gl_uid = 1
@@ -166,13 +166,12 @@ Class Procs:
use_power = new_use_power
//force area power update
- //use_power() forces an area power update on the next tick so have to pass the correct power amount for this tick
- if (use_power >= 2)
- use_power(active_power_usage)
- else if (use_power == 1)
- use_power(idle_power_usage)
- else
- use_power(0)
+ force_power_update()
+
+/obj/machinery/proc/force_power_update()
+ var/area/A = get_area(src)
+ if(A && A.master)
+ A.master.powerupdate = 1
/obj/machinery/proc/auto_use_power()
if(!powered(power_channel))
@@ -183,9 +182,15 @@ Class Procs:
use_power(active_power_usage,power_channel, 1)
return 1
+/obj/machinery/proc/operable(var/additional_flags = 0)
+ return !inoperable(additional_flags)
+
+/obj/machinery/proc/inoperable(var/additional_flags = 0)
+ return (stat & (NOPOWER|BROKEN|additional_flags))
+
/obj/machinery/Topic(href, href_list)
..()
- if(stat & (NOPOWER|BROKEN))
+ if(inoperable())
return 1
if(usr.restrained() || usr.lying || usr.stat)
return 1
@@ -227,7 +232,7 @@ Class Procs:
return src.attack_hand(user)
/obj/machinery/attack_hand(mob/user as mob)
- if(stat & (NOPOWER|BROKEN|MAINT))
+ if(inoperable(MAINT))
return 1
if(user.lying || user.stat)
return 1
@@ -277,7 +282,7 @@ Class Procs:
playsound(src.loc, 'sound/machines/ping.ogg', 50, 0)
/obj/machinery/proc/shock(mob/user, prb)
- if(stat & (BROKEN|NOPOWER))
+ if(inoperable())
return 0
if(!prob(prb))
return 0
diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm
index 7d65abb6d78..a1a56bb9768 100644
--- a/code/game/machinery/pipe/construction.dm
+++ b/code/game/machinery/pipe/construction.dm
@@ -442,6 +442,7 @@ Buildable meters
var/pipefailtext = "\red There's nothing to connect this pipe section to!" //(with how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment)"
+ //TODO: Move all of this stuff into the various pipe constructors.
switch(pipe_type)
if(PIPE_SIMPLE_STRAIGHT, PIPE_SIMPLE_BENT)
var/obj/machinery/atmospherics/pipe/simple/P = new( src.loc )
@@ -522,7 +523,7 @@ Buildable meters
if(PIPE_HE_STRAIGHT, PIPE_HE_BENT)
var/obj/machinery/atmospherics/pipe/simple/heat_exchanging/P = new ( src.loc )
P.dir = src.dir
- P.initialize_directions = 0
+ P.initialize_directions = pipe_dir //this var it's used to know if the pipe is bent or not
P.initialize_directions_he = pipe_dir
//var/turf/T = P.loc
//P.level = T.intact ? 2 : 1
@@ -563,7 +564,7 @@ Buildable meters
M.level = T.intact ? 2 : 1
M.initialize()
if (!M)
- usr << "There's nothing to connect this manifold to!" //(with how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment)"
+ usr << pipefailtext
return 1
M.build_network()
if (M.node1)
@@ -632,7 +633,7 @@ Buildable meters
M.level = T.intact ? 2 : 1
M.initialize()
if (!M)
- usr << "There's nothing to connect this manifold to!" //(with how the pipe code works, at least one end needs to be connected to something, otherwise the game deletes the segment)"
+ usr << pipefailtext
return 1
M.build_network()
if (M.node1)
diff --git a/code/game/machinery/spaceheater.dm b/code/game/machinery/spaceheater.dm
index ffa69f8b412..f6a1455e78c 100644
--- a/code/game/machinery/spaceheater.dm
+++ b/code/game/machinery/spaceheater.dm
@@ -98,7 +98,7 @@
dat += "-"
- dat += " [set_temperature]°C "
+ dat += " [set_temperature]K ([set_temperature-T0C]°C)"
dat += "+
"
user.set_machine(src)
@@ -176,7 +176,7 @@
heat_transfer = min(heat_transfer, cop * heating_power) //limit heat transfer by available power
heat_transfer = removed.add_thermal_energy(-heat_transfer) //get the actual heat transfer
-
+
var/power_used = abs(heat_transfer)/cop
cell.use(power_used*CELLRATE)
diff --git a/code/game/machinery/suit_storage_unit.dm b/code/game/machinery/suit_storage_unit.dm
index c21616811e4..3f0b7448895 100644
--- a/code/game/machinery/suit_storage_unit.dm
+++ b/code/game/machinery/suit_storage_unit.dm
@@ -622,35 +622,35 @@
model_text = "Engineering"
req_access = list(access_construction)
departments = list("Engineering","Atmos")
- species = list("Human","Tajaran") //Add Unathi when sprites exist for their suits.
+ species = list("Human","Tajaran","Skrell","Unathi") //Add Unathi when sprites exist for their suits.
/obj/machinery/suit_cycler/mining
name = "Mining suit cycler"
model_text = "Mining"
req_access = list(access_mining)
departments = list("Mining")
- species = list("Human","Tajaran")
+ species = list("Human","Tajaran","Skrell","Unathi")
/obj/machinery/suit_cycler/security
name = "Security suit cycler"
model_text = "Security"
req_access = list(access_security)
departments = list("Security")
- species = list("Human","Tajaran")
+ species = list("Human","Tajaran","Skrell","Unathi")
/obj/machinery/suit_cycler/medical
name = "Medical suit cycler"
model_text = "Medical"
req_access = list(access_medical)
departments = list("Medical")
- species = list("Human","Tajaran")
+ species = list("Human","Tajaran","Skrell","Unathi")
/obj/machinery/suit_cycler/syndicate
name = "Nonstandard suit cycler"
model_text = "Nonstandard"
req_access = list(access_syndicate)
departments = list("Mercenary")
- species = list("Human","Tajaran","Unathi","Skrell")
+ species = list("Human","Tajaran","Skrell","Unathi")
can_repair = 1
/obj/machinery/suit_cycler/attack_ai(mob/user as mob)
diff --git a/code/game/mecha/mecha.dm b/code/game/mecha/mecha.dm
index 43592ae2cb9..78ee794b532 100644
--- a/code/game/mecha/mecha.dm
+++ b/code/game/mecha/mecha.dm
@@ -1298,9 +1298,9 @@
Powercell charge: [isnull(cell_charge)?"No powercell installed":"[cell.percent()]%"]
Air source: [use_internal_tank?"Internal Airtank":"Environment"]
Airtank pressure: [tank_pressure]kPa
- Airtank temperature: [tank_temperature]°K|[tank_temperature - T0C]°C
+ Airtank temperature: [tank_temperature]K|[tank_temperature - T0C]°C
Cabin pressure: [cabin_pressure>WARNING_HIGH_PRESSURE ? "[cabin_pressure]": cabin_pressure]kPa
- Cabin temperature: [return_temperature()]°K|[return_temperature() - T0C]°C
+ Cabin temperature: [return_temperature()]K|[return_temperature() - T0C]°C
Lights: [lights?"on":"off"]
[src.dna?"DNA-locked:
[src.dna] \[Reset\]
":null]
"}
diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm
index 5a78b702d04..6e1cc86633c 100644
--- a/code/game/objects/items.dm
+++ b/code/game/objects/items.dm
@@ -49,18 +49,11 @@
var/list/sprite_sheets = null
var/icon_override = null //Used to override hardcoded clothing dmis in human clothing proc.
- /* Species-specific sprite sheets for object and inhand sprites
+ /* Species-specific sprite sheets for inventory sprites
Works similarly to worn sprite_sheets, except the alternate sprites are used when the clothing/refit_for_species() proc is called.
*/
var/list/sprite_sheets_obj = null
- //Inhand is not as big a deal as the object sprites, so I'm not sure if these are worth the extra vars.
- //Maybe in the future:
- //var/list/sprite_sheets_inhand_l = null
- //var/list/sprite_sheets_inhand_r = null
- //var/icon_l_hand = 'icons/mob/items_lefthand.dmi'
- //var/icon_r_hand = 'icons/mob/items_righthand.dmi'
-
/obj/item/device
icon = 'icons/obj/device.dmi'
diff --git a/code/game/objects/items/robot/robot_upgrades.dm b/code/game/objects/items/robot/robot_upgrades.dm
index c2aca6807ea..ce8056d46a7 100644
--- a/code/game/objects/items/robot/robot_upgrades.dm
+++ b/code/game/objects/items/robot/robot_upgrades.dm
@@ -30,6 +30,11 @@
R.uneq_all()
R.hands.icon_state = "nomod"
R.icon_state = "robot"
+ //world << R.custom_sprite
+ if(R.custom_sprite == 1)
+ //world << R.icon_state
+ icon = 'icons/mob/custom-synthetic.dmi'
+ R.icon_state = "[R.ckey]-Standard"
del(R.module)
R.module = null
R.camera.network.Remove(list("Engineering","Medical","MINE"))
diff --git a/code/game/objects/items/stacks/sheets/glass.dm b/code/game/objects/items/stacks/sheets/glass.dm
index 88a0decc2b3..c1126464f56 100644
--- a/code/game/objects/items/stacks/sheets/glass.dm
+++ b/code/game/objects/items/stacks/sheets/glass.dm
@@ -251,7 +251,7 @@
singular_name = "phoron glass sheet"
icon_state = "sheet-phoronglass"
matter = list("glass" = 7500)
- origin_tech = "materials=3;phoron=2"
+ origin_tech = "materials=3;phorontech=2"
created_window = /obj/structure/window/phoronbasic
/obj/item/stack/sheet/glass/phoronglass/attack_self(mob/user as mob)
@@ -284,7 +284,7 @@
icon_state = "sheet-phoronrglass"
matter = list("glass" = 7500,"metal" = 1875)
- origin_tech = "materials=4;phoron=2"
+ origin_tech = "materials=4;phorontech=2"
created_window = /obj/structure/window/phoronreinforced
/obj/item/stack/sheet/glass/phoronrglass/attack_self(mob/user as mob)
diff --git a/code/game/objects/items/weapons/RSF.dm b/code/game/objects/items/weapons/RSF.dm
index 9d86411b1a5..d6a707237c3 100644
--- a/code/game/objects/items/weapons/RSF.dm
+++ b/code/game/objects/items/weapons/RSF.dm
@@ -4,7 +4,6 @@ RSF
*/
-//TODO: WHAT THE FUCK, FIX THIS GARBAGE.
/obj/item/weapon/rsf
name = "\improper Rapid-Service-Fabricator"
desc = "A device used to rapidly deploy service items."
@@ -13,26 +12,29 @@ RSF
opacity = 0
density = 0
anchored = 0.0
- var/stored_matter = 0
+ var/stored_matter = 30
var/mode = 1
flags = TABLEPASS
w_class = 3.0
-/obj/item/weapon/rsf/New()
- desc = "A RSF. It currently holds [stored_matter]/30 fabrication-units."
- return
+/obj/item/weapon/rsf/examine()
+ set src in view(1)
+ ..()
+ usr << "It currently holds [stored_matter]/30 fabrication-units."
/obj/item/weapon/rsf/attackby(obj/item/weapon/W as obj, mob/user as mob)
..()
if (istype(W, /obj/item/weapon/rcd_ammo))
+
if ((stored_matter + 10) > 30)
- user << "The RSF cant hold any more matter."
+ user << "The RSF can't hold any more matter."
return
+
del(W)
+
stored_matter += 10
playsound(src.loc, 'sound/machines/click.ogg', 10, 1)
user << "The RSF now holds [stored_matter]/30 fabrication-units."
- desc = "A RSF. It currently holds [stored_matter]/30 fabrication-units."
return
/obj/item/weapon/rsf/attack_self(mob/user as mob)
@@ -64,174 +66,51 @@ RSF
// Change mode
/obj/item/weapon/rsf/afterattack(atom/A, mob/user as mob, proximity)
+
if(!proximity) return
- if (!(istype(A, /obj/structure/table) || istype(A, /turf/simulated/floor)))
+
+ if(istype(user,/mob/living/silicon/robot))
+ var/mob/living/silicon/robot/R = user
+ if(R.stat || !R.cell || R.cell.charge <= 0)
+ return
+ else
+ if(stored_matter <= 0)
+ return
+
+ if(!istype(A, /obj/structure/table) && !istype(A, /turf/simulated/floor))
return
- if (istype(A, /obj/structure/table) && mode == 1)
- if (istype(A, /obj/structure/table) && stored_matter >= 1)
- user << "Dispensing Dosh..."
- playsound(src.loc, 'sound/machines/click.ogg', 10, 1)
- new /obj/item/weapon/spacecash/c10( A.loc )
- if (isrobot(user))
- var/mob/living/silicon/robot/engy = user
- engy.cell.charge -= 200 //once money becomes useful, I guess changing this to a high ammount, like 500 units a kick, till then, enjoy dosh!
- else
- stored_matter--
- user << "The RSF now holds [stored_matter]/30 fabrication-units."
- desc = "A RSF. It currently holds [stored_matter]/30 fabrication-units."
- return
+ playsound(src.loc, 'sound/machines/click.ogg', 10, 1)
+ var/used_energy = 0
+ var/obj/product
- else if (istype(A, /turf/simulated/floor) && mode == 1)
- if (istype(A, /turf/simulated/floor) && stored_matter >= 1)
- user << "Dispensing Dosh..."
- playsound(src.loc, 'sound/machines/click.ogg', 10, 1)
- new /obj/item/weapon/spacecash/c10( A )
- if (isrobot(user))
- var/mob/living/silicon/robot/engy = user
- engy.cell.charge -= 200 //once money becomes useful, I guess changing this to a high ammount, like 500 units a kick, till then, enjoy dosh!
- else
- stored_matter--
- user << "The RSF now holds [stored_matter]/30 fabrication-units."
- desc = "A RSF. It currently holds [stored_matter]/30 fabrication-units."
- return
+ switch(mode)
+ if(1)
+ product = new /obj/item/weapon/spacecash/c10()
+ used_energy = 200
+ if(2)
+ product = new /obj/item/weapon/reagent_containers/food/drinks/drinkingglass()
+ used_energy = 50
+ if(3)
+ product = new /obj/item/weapon/paper()
+ used_energy = 10
+ if(4)
+ product = new /obj/item/weapon/pen()
+ used_energy = 50
+ if(5)
+ product = new /obj/item/weapon/storage/pill_bottle/dice()
+ used_energy = 200
+ if(6)
+ product = new /obj/item/clothing/mask/cigarette()
+ used_energy = 10
- else if (istype(A, /obj/structure/table) && mode == 2)
- if (istype(A, /obj/structure/table) && stored_matter >= 1)
- user << "Dispensing Drinking Glass..."
- playsound(src.loc, 'sound/machines/click.ogg', 10, 1)
- new /obj/item/weapon/reagent_containers/food/drinks/drinkingglass( A.loc )
- if (isrobot(user))
- var/mob/living/silicon/robot/engy = user
- engy.cell.charge -= 50
- else
- stored_matter--
- user << "The RSF now holds [stored_matter]/30 fabrication-units."
- desc = "A RSF. It currently holds [stored_matter]/30 fabrication-units."
- return
+ user << "Dispensing [product ? product : "product"]..."
+ product.loc = get_turf(A)
- else if (istype(A, /turf/simulated/floor) && mode == 2)
- if (istype(A, /turf/simulated/floor) && stored_matter >= 1)
- user << "Dispensing Drinking Glass..."
- playsound(src.loc, 'sound/machines/click.ogg', 10, 1)
- new /obj/item/weapon/reagent_containers/food/drinks/drinkingglass( A )
- if (isrobot(user))
- var/mob/living/silicon/robot/engy = user
- engy.cell.charge -= 50
- else
- stored_matter--
- user << "The RSF now holds [stored_matter]/30 fabrication-units."
- desc = "A RSF. It currently holds [stored_matter]/30 fabrication-units."
- return
-
- else if (istype(A, /obj/structure/table) && mode == 3)
- if (istype(A, /obj/structure/table) && stored_matter >= 1)
- user << "Dispensing Paper Sheet..."
- playsound(src.loc, 'sound/machines/click.ogg', 10, 1)
- new /obj/item/weapon/paper( A.loc )
- if (isrobot(user))
- var/mob/living/silicon/robot/engy = user
- engy.cell.charge -= 10
- else
- stored_matter--
- user << "The RSF now holds [stored_matter]/30 fabrication-units."
- desc = "A RSF. It currently holds [stored_matter]/30 fabrication-units."
- return
-
- else if (istype(A, /turf/simulated/floor) && mode == 3)
- if (istype(A, /turf/simulated/floor) && stored_matter >= 1)
- user << "Dispensing Paper Sheet..."
- playsound(src.loc, 'sound/machines/click.ogg', 10, 1)
- new /obj/item/weapon/paper( A )
- if (isrobot(user))
- var/mob/living/silicon/robot/engy = user
- engy.cell.charge -= 10
- else
- stored_matter--
- user << "The RSF now holds [stored_matter]/30 fabrication-units."
- desc = "A RSF. It currently holds [stored_matter]/30 fabrication-units."
- return
-
- else if (istype(A, /obj/structure/table) && mode == 4)
- if (istype(A, /obj/structure/table) && stored_matter >= 1)
- user << "Dispensing Pen..."
- playsound(src.loc, 'sound/machines/click.ogg', 10, 1)
- new /obj/item/weapon/pen( A.loc )
- if (isrobot(user))
- var/mob/living/silicon/robot/engy = user
- engy.cell.charge -= 50
- else
- stored_matter--
- user << "The RSF now holds [stored_matter]/30 fabrication-units."
- desc = "A RSF. It currently holds [stored_matter]/30 fabrication-units."
- return
-
- else if (istype(A, /turf/simulated/floor) && mode == 4)
- if (istype(A, /turf/simulated/floor) && stored_matter >= 1)
- user << "Dispensing Pen..."
- playsound(src.loc, 'sound/machines/click.ogg', 10, 1)
- new /obj/item/weapon/pen( A )
- if (isrobot(user))
- var/mob/living/silicon/robot/engy = user
- engy.cell.charge -= 50
- else
- stored_matter--
- user << "The RSF now holds [stored_matter]/30 fabrication-units."
- desc = "A RSF. It currently holds [stored_matter]/30 fabrication-units."
- return
-
- else if (istype(A, /obj/structure/table) && mode == 5)
- if (istype(A, /obj/structure/table) && stored_matter >= 1)
- user << "Dispensing Dice Pack..."
- playsound(src.loc, 'sound/machines/click.ogg', 10, 1)
- new /obj/item/weapon/storage/pill_bottle/dice( A.loc )
- if (isrobot(user))
- var/mob/living/silicon/robot/engy = user
- engy.cell.charge -= 200
- else
- stored_matter--
- user << "The RSF now holds [stored_matter]/30 fabrication-units."
- desc = "A RSF. It currently holds [stored_matter]/30 fabrication-units."
- return
-
- else if (istype(A, /turf/simulated/floor) && mode == 5)
- if (istype(A, /turf/simulated/floor) && stored_matter >= 1)
- user << "Dispensing Dice Pack..."
- playsound(src.loc, 'sound/machines/click.ogg', 10, 1)
- new /obj/item/weapon/storage/pill_bottle/dice( A )
- if (isrobot(user))
- var/mob/living/silicon/robot/engy = user
- engy.cell.charge -= 200
- else
- stored_matter--
- user << "The RSF now holds [stored_matter]/30 fabrication-units."
- desc = "A RSF. It currently holds [stored_matter]/30 fabrication-units."
- return
-
- else if (istype(A, /obj/structure/table) && mode == 6)
- if (istype(A, /obj/structure/table) && stored_matter >= 1)
- user << "Dispensing Cigarette..."
- playsound(src.loc, 'sound/machines/click.ogg', 10, 1)
- new /obj/item/clothing/mask/cigarette( A.loc )
- if (isrobot(user))
- var/mob/living/silicon/robot/engy = user
- engy.cell.charge -= 10
- else
- stored_matter--
- user << "The RSF now holds [stored_matter]/30 fabrication-units."
- desc = "A RSF. It currently holds [stored_matter]/30 fabrication-units."
- return
-
- else if (istype(A, /turf/simulated/floor) && mode == 6)
- if (istype(A, /turf/simulated/floor) && stored_matter >= 1)
- user << "Dispensing Cigarette..."
- playsound(src.loc, 'sound/machines/click.ogg', 10, 1)
- new /obj/item/clothing/mask/cigarette( A )
- if (isrobot(user))
- var/mob/living/silicon/robot/engy = user
- engy.cell.charge -= 10
- else
- stored_matter--
- user << "The RSF now holds [stored_matter]/30 fabrication-units."
- desc = "A RSF. It currently holds [stored_matter]/30 fabrication-units."
- return
\ No newline at end of file
+ if(isrobot(user))
+ var/mob/living/silicon/robot/R = user
+ if(R.cell)
+ R.cell.use(used_energy)
+ else
+ stored_matter--
+ user << "The RSF now holds [stored_matter]/30 fabrication-units."
\ No newline at end of file
diff --git a/code/game/objects/items/weapons/power_cells.dm b/code/game/objects/items/weapons/power_cells.dm
index 5636681f5e8..ba75d32990a 100644
--- a/code/game/objects/items/weapons/power_cells.dm
+++ b/code/game/objects/items/weapons/power_cells.dm
@@ -28,7 +28,7 @@
desc = "You can't top the plasma top." //TOTALLY TRADEMARK INFRINGEMENT
origin_tech = "powerstorage=0"
maxcharge = 500
- matter = list("glass" = 40)
+ matter = list("metal" = 700, "glass" = 40)
/obj/item/weapon/cell/crap/empty/New()
..()
@@ -38,18 +38,24 @@
name = "security borg rechargable D battery"
origin_tech = "powerstorage=0"
maxcharge = 600 //600 max charge / 100 charge per shot = six shots
- matter = list("glass" = 40)
+ matter = list("metal" = 700, "glass" = 40)
/obj/item/weapon/cell/secborg/empty/New()
..()
charge = 0
+/obj/item/weapon/cell/apc
+ name = "heavy-duty power cell"
+ origin_tech = "powerstorage=1"
+ maxcharge = 5000
+ matter = list("metal" = 700, "glass" = 50)
+
/obj/item/weapon/cell/high
name = "high-capacity power cell"
origin_tech = "powerstorage=2"
icon_state = "hcell"
maxcharge = 10000
- matter = list("glass" = 60)
+ matter = list("metal" = 700, "glass" = 60)
/obj/item/weapon/cell/high/empty/New()
..()
@@ -60,7 +66,7 @@
origin_tech = "powerstorage=5"
icon_state = "scell"
maxcharge = 20000
- matter = list("glass" = 70)
+ matter = list("metal" = 700, "glass" = 70)
construction_cost = list("metal"=750,"glass"=100)
/obj/item/weapon/cell/super/empty/New()
@@ -72,7 +78,7 @@
origin_tech = "powerstorage=6"
icon_state = "hpcell"
maxcharge = 30000
- matter = list("glass" = 80)
+ matter = list("metal" = 700, "glass" = 80)
construction_cost = list("metal"=500,"glass"=150,"gold"=200,"silver"=200)
/obj/item/weapon/cell/hyper/empty/New()
@@ -84,7 +90,7 @@
icon_state = "icell"
origin_tech = null
maxcharge = 30000
- matter = list("glass"= 80)
+ matter = list("metal" = 700, "glass" = 80)
use()
return 1
diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm
index af50cd10882..f4400132e80 100644
--- a/code/game/objects/items/weapons/tools.dm
+++ b/code/game/objects/items/weapons/tools.dm
@@ -410,7 +410,7 @@
max_fuel = 40
w_class = 3.0
matter = list("metal" = 70, "glass" = 120)
- origin_tech = "engineering=4;phoron=3"
+ origin_tech = "engineering=4;phorontech=3"
var/last_gen = 0
diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
index 8252934c1e0..1fd6bdff5fc 100644
--- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm
+++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm
@@ -115,7 +115,6 @@
new /obj/item/clothing/glasses/sunglasses/sechud(src)
new /obj/item/taperoll/police(src)
new /obj/item/weapon/shield/riot(src)
- new /obj/item/weapon/storage/lockbox/loyalty(src)
new /obj/item/weapon/storage/box/flashbangs(src)
new /obj/item/weapon/storage/belt/security(src)
new /obj/item/device/flash(src)
diff --git a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
index 31a1681eace..f7eafdda9db 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/chairs.dm
@@ -153,17 +153,23 @@
if(propelled)
var/mob/living/occupant = buckled_mob
unbuckle()
+
+ var/def_zone = ran_zone()
+ var/blocked = occupant.run_armor_check(def_zone, "melee")
occupant.throw_at(A, 3, propelled)
- occupant.apply_effect(6, STUN, 0)
- occupant.apply_effect(6, WEAKEN, 0)
- occupant.apply_effect(6, STUTTER, 0)
+ occupant.apply_effect(6, STUN, blocked)
+ occupant.apply_effect(6, WEAKEN, blocked)
+ occupant.apply_effect(6, STUTTER, blocked)
+ occupant.apply_damage(10, BRUTE, def_zone, blocked)
playsound(src.loc, 'sound/weapons/punch1.ogg', 50, 1, -1)
if(istype(A, /mob/living))
var/mob/living/victim = A
- victim.apply_effect(6, STUN, 0)
- victim.apply_effect(6, WEAKEN, 0)
- victim.apply_effect(6, STUTTER, 0)
- victim.take_organ_damage(10)
+ def_zone = ran_zone()
+ blocked = victim.run_armor_check(def_zone, "melee")
+ victim.apply_effect(6, STUN, blocked)
+ victim.apply_effect(6, WEAKEN, blocked)
+ victim.apply_effect(6, STUTTER, blocked)
+ victim.apply_damage(10, BRUTE, def_zone, blocked)
occupant.visible_message("[occupant] crashed into \the [A]!")
/obj/structure/stool/bed/chair/office/light
diff --git a/code/game/objects/structures/stool_bed_chair_nest/stools.dm b/code/game/objects/structures/stool_bed_chair_nest/stools.dm
index a068af11938..ba27d070d71 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/stools.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/stools.dm
@@ -54,12 +54,27 @@
w_class = 5.0
var/obj/structure/stool/origin = null
+/obj/item/weapon/stool/proc/deploy(var/mob/user)
+
+ if(!origin)
+ del src
+
+ origin.loc = get_turf(src)
+
+ if(user)
+ user.u_equip(src)
+ user.visible_message("\blue [user] puts [src] down.", "\blue You put [src] down.")
+
+ del src
+
+/obj/item/weapon/stool/dropped(mob/user as mob)
+ ..()
+ if(istype(loc,/turf/))
+ deploy(user)
+
/obj/item/weapon/stool/attack_self(mob/user as mob)
..()
- origin.loc = get_turf(src)
- user.u_equip(src)
- user.visible_message("\blue [user] puts [src] down.", "\blue You put [src] down.")
- del src
+ deploy(user)
/obj/item/weapon/stool/attack(mob/M as mob, mob/user as mob)
if (prob(5) && istype(M,/mob/living))
diff --git a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
index 9c00ee38963..8e801de6e2d 100644
--- a/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
+++ b/code/game/objects/structures/stool_bed_chair_nest/wheelchair.dm
@@ -147,16 +147,22 @@
else if (propelled)
occupant.throw_at(A, 3, propelled)
- occupant.apply_effect(6, STUN, 0)
- occupant.apply_effect(6, WEAKEN, 0)
- occupant.apply_effect(6, STUTTER, 0)
+ var/def_zone = ran_zone()
+ var/blocked = occupant.run_armor_check(def_zone, "melee")
+ occupant.throw_at(A, 3, propelled)
+ occupant.apply_effect(6, STUN, blocked)
+ occupant.apply_effect(6, WEAKEN, blocked)
+ occupant.apply_effect(6, STUTTER, blocked)
+ occupant.apply_damage(10, BRUTE, def_zone)
playsound(src.loc, 'sound/weapons/punch1.ogg', 50, 1, -1)
if(istype(A, /mob/living))
var/mob/living/victim = A
- victim.apply_effect(6, STUN, 0)
- victim.apply_effect(6, WEAKEN, 0)
- victim.apply_effect(6, STUTTER, 0)
- victim.take_organ_damage(10)
+ def_zone = ran_zone()
+ blocked = victim.run_armor_check(def_zone, "melee")
+ victim.apply_effect(6, STUN, blocked)
+ victim.apply_effect(6, WEAKEN, blocked)
+ victim.apply_effect(6, STUTTER, blocked)
+ victim.apply_damage(10, BRUTE, def_zone)
if(pulling)
occupant.visible_message("[pulling] has thrusted \the [name] into \the [A], throwing \the [occupant] out of it!")
diff --git a/code/game/turfs/simulated/floor_types.dm b/code/game/turfs/simulated/floor_types.dm
index 98e0f660350..adf6fe4bcea 100644
--- a/code/game/turfs/simulated/floor_types.dm
+++ b/code/game/turfs/simulated/floor_types.dm
@@ -55,6 +55,9 @@
heat_capacity = 325000
intact = 0
+/turf/simulated/floor/engine/nitrogen
+ oxygen = 0
+
/turf/simulated/floor/engine/attackby(obj/item/weapon/C as obj, mob/user as mob)
if(!C)
return
diff --git a/code/modules/admin/topic.dm b/code/modules/admin/topic.dm
index 6b1e1d2b018..1493751ab10 100644
--- a/code/modules/admin/topic.dm
+++ b/code/modules/admin/topic.dm
@@ -1492,6 +1492,7 @@
else if(href_list["CentcommFaxReply"])
var/mob/living/carbon/human/H = locate(href_list["CentcommFaxReply"])
+ var/obj/machinery/faxmachine/fax = locate(href_list["originfax"])
var/input = input(src.owner, "Please enter a message to reply to [key_name(H)] via secure connection. NOTE: BBCode does not work, but HTML tags do! Use
for line breaks.", "Outgoing message from Centcomm", "") as message|null
if(!input) return
@@ -1499,32 +1500,76 @@
var/customname = input(src.owner, "Pick a title for the report", "Title") as text|null
for(var/obj/machinery/faxmachine/F in machines)
- if(! (F.stat & (BROKEN|NOPOWER) ) )
+ if(F == fax)
+ if(! (F.stat & (BROKEN|NOPOWER) ) )
- // animate! it's alive!
- flick("faxreceive", F)
+ // animate! it's alive!
+ flick("faxreceive", F)
- // give the sprite some time to flick
- spawn(20)
- var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( F.loc )
- P.name = "[command_name()]- [customname]"
- P.info = input
- P.update_icon()
+ // give the sprite some time to flick
+ spawn(20)
+ var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( F.loc )
+ P.name = "[command_name()]- [customname]"
+ P.info = input
+ P.update_icon()
- playsound(F.loc, "sound/items/polaroid1.ogg", 50, 1)
+ playsound(F.loc, "sound/items/polaroid1.ogg", 50, 1)
- // Stamps
- var/image/stampoverlay = image('icons/obj/bureaucracy.dmi')
- stampoverlay.icon_state = "paper_stamp-cent"
- if(!P.stamped)
- P.stamped = new
- P.stamped += /obj/item/weapon/stamp
- P.overlays += stampoverlay
- P.stamps += "
This paper has been stamped by the Central Command Quantum Relay."
+ // Stamps
+ var/image/stampoverlay = image('icons/obj/bureaucracy.dmi')
+ stampoverlay.icon_state = "paper_stamp-cent"
+ if(!P.stamped)
+ P.stamped = new
+ P.stamped += /obj/item/weapon/stamp
+ P.overlays += stampoverlay
+ P.stamps += "
This paper has been stamped by the Central Command Quantum Relay."
+
+ src.owner << "Message reply to transmitted successfully."
+ log_admin("[key_name(src.owner)] replied to a fax message from [key_name(H)]: [input]")
+ message_admins("[key_name_admin(src.owner)] replied to a fax message from [key_name_admin(H)]", 1)
+ return
+ src.owner << "/red Unable to locate fax!"
+
+ else if(href_list["SolGovFaxReply"])
+ var/mob/living/carbon/human/H = locate(href_list["SolGovFaxReply"])
+ var/obj/machinery/faxmachine/fax = locate(href_list["originfax"])
+
+ var/input = input(src.owner, "Please enter a message to reply to [key_name(H)] via secure connection. NOTE: BBCode does not work, but HTML tags do! Use
for line breaks.", "Outgoing message from Centcomm", "") as message|null
+ if(!input) return
+
+ var/customname = input(src.owner, "Pick a title for the report", "Title") as text|null
+
+ for(var/obj/machinery/faxmachine/F in machines)
+ if(F == fax)
+ if(! (F.stat & (BROKEN|NOPOWER) ) )
+
+ // animate! it's alive!
+ flick("faxreceive", F)
+
+ // give the sprite some time to flick
+ spawn(20)
+ var/obj/item/weapon/paper/P = new /obj/item/weapon/paper( F.loc )
+ P.name = "Sol Government- [customname]"
+ P.info = input
+ P.update_icon()
+
+ playsound(F.loc, "sound/items/polaroid1.ogg", 50, 1)
+
+ // Stamps
+ var/image/stampoverlay = image('icons/obj/bureaucracy.dmi')
+ stampoverlay.icon_state = "paper_stamp-cap"
+ if(!P.stamped)
+ P.stamped = new
+ P.stamped += /obj/item/weapon/stamp
+ P.overlays += stampoverlay
+ P.stamps += "
This paper has been stamped and encrypted by the Sol Government Quantum Relay."
+
+ src.owner << "Message reply to transmitted successfully."
+ log_admin("[key_name(src.owner)] replied to a fax message from [key_name(H)]: [input]")
+ message_admins("[key_name_admin(src.owner)] replied to a fax message from [key_name_admin(H)]", 1)
+ return
+ src.owner << "/red Unable to locate fax!"
- src.owner << "Message reply to transmitted successfully."
- log_admin("[key_name(src.owner)] replied to a fax message from [key_name(H)]: [input]")
- message_admins("[key_name_admin(src.owner)] replied to a fax message from [key_name_admin(H)]", 1)
else if(href_list["jumpto"])
diff --git a/code/modules/admin/verbs/mapping.dm b/code/modules/admin/verbs/mapping.dm
index 6e2bd20e322..fa5fba4ba05 100644
--- a/code/modules/admin/verbs/mapping.dm
+++ b/code/modules/admin/verbs/mapping.dm
@@ -125,7 +125,7 @@ var/intercom_range_display_status = 0
feedback_add_details("admin_verb","mIRD") //If you are copy-pasting this, ensure the 2nd parameter is unique to the new proc!
var/list/debug_verbs = list (
- /client/proc/do_not_use_these
+ /client/proc/do_not_use_these
,/client/proc/camera_view
,/client/proc/sec_camera_report
,/client/proc/intercom_view
@@ -158,9 +158,13 @@ var/list/debug_verbs = list (
,/client/proc/ZoneTick
,/client/proc/rebootAirMaster
,/client/proc/hide_debug_verbs
- ,/client/proc/testZAScolors
- ,/client/proc/testZAScolors_remove
- ,/client/proc/setup_supermatter_engine
+ ,/client/proc/testZAScolors
+ ,/client/proc/testZAScolors_remove
+ ,/client/proc/setup_supermatter_engine
+ ,/client/proc/view_power_update_stats_area
+ ,/client/proc/view_power_update_stats_machines
+ ,/client/proc/toggle_power_update_profiling
+ ,/client/proc/atmos_toggle_debug
)
diff --git a/code/modules/admin/verbs/modifyvariables.dm b/code/modules/admin/verbs/modifyvariables.dm
index e5b1555b0d9..b89b4a67eb5 100644
--- a/code/modules/admin/verbs/modifyvariables.dm
+++ b/code/modules/admin/verbs/modifyvariables.dm
@@ -215,7 +215,7 @@ var/list/forbidden_varedit_object_types = list(
var/list/choices = list("text","num","type","reference","mob reference", "icon","file","list","edit referenced object","restore to default")
if(src.holder && src.holder.marked_datum)
choices += "marked datum ([holder.marked_datum.type])"
- if(!isnull(default) && default != "num" && !isnull(L[variable]))
+ if(!isnull(default) && default != "num")
choices += "edit associated variable"
choices += "DELETE FROM LIST"
diff --git a/code/modules/client/preferences.dm b/code/modules/client/preferences.dm
old mode 100644
new mode 100755
index 39213f436da..193d63f96c5
--- a/code/modules/client/preferences.dm
+++ b/code/modules/client/preferences.dm
@@ -1347,7 +1347,8 @@ datum/preferences
organ_data[limb] = "cyborg"
if(second_limb)
organ_data[second_limb] = "cyborg"
-
+ if(third_limb && organ_data[third_limb] == "amputated")
+ organ_data[third_limb] = null
if("organs")
var/organ_name = input(user, "Which internal function do you want to change?") as null|anything in list("Heart", "Eyes")
if(!organ_name) return
diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm
index fa519d6f0be..9bd9e779c3c 100644
--- a/code/modules/clothing/clothing.dm
+++ b/code/modules/clothing/clothing.dm
@@ -1,6 +1,14 @@
/obj/item/clothing
name = "clothing"
var/list/species_restricted = null //Only these species can wear this kit.
+
+ /*
+ Sprites used when the clothing item is refit. This is done by setting icon_override.
+ For best results, if this is set then sprite_sheets should be null and vice versa, but that is by no means necessary.
+ Ideally, sprite_sheets_refit should be used for "hard" clothing items that can't change shape very well to fit the wearer (e.g. helmets, hardsuits),
+ while sprite_sheets should be used for "flexible" clothing items that do not need to be refitted (e.g. vox wearing jumpsuits).
+ */
+ var/list/sprite_sheets_refit = null
//BS12: Species-restricted clothing check.
/obj/item/clothing/mob_can_equip(M as mob, slot)
@@ -41,6 +49,11 @@
species_restricted = list(target_species)
//Set icon
+ if (sprite_sheets_refit && (target_species in sprite_sheets_refit))
+ icon_override = sprite_sheets_refit[target_species]
+ else
+ icon_override = initial(icon_override)
+
if (sprite_sheets_obj && (target_species in sprite_sheets_obj))
icon = sprite_sheets_obj[target_species]
else
@@ -57,12 +70,16 @@
species_restricted = list(target_species)
//Set icon
+ if (sprite_sheets_refit && (target_species in sprite_sheets_refit))
+ icon_override = sprite_sheets_refit[target_species]
+ else
+ icon_override = initial(icon_override)
+
if (sprite_sheets_obj && (target_species in sprite_sheets_obj))
icon = sprite_sheets_obj[target_species]
else
icon = initial(icon)
-
//Ears: headsets, earmuffs and tiny objects
/obj/item/clothing/ears
name = "ears"
@@ -182,6 +199,24 @@ BLIND // can't see anything
/obj/item/clothing/gloves/proc/Touch(var/atom/A, var/proximity)
return 0 // return 1 to cancel attack_hand()
+/obj/item/clothing/gloves/attackby(obj/item/weapon/W, mob/user)
+ if(istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/weapon/scalpel))
+ if (clipped)
+ user << "The [src] have already been clipped!"
+ update_icon()
+ return
+
+ playsound(src.loc, 'sound/items/Wirecutter.ogg', 100, 1)
+ user.visible_message("\red [user] cuts the fingertips off of the [src].","\red You cut the fingertips off of the [src].")
+
+ clipped = 1
+ name = "mangled [name]"
+ desc = "[desc]
They have had the fingertips cut off of them."
+ if("exclude" in species_restricted)
+ species_restricted -= "Unathi"
+ species_restricted -= "Tajaran"
+ return
+
//Head
/obj/item/clothing/head
name = "head"
diff --git a/code/modules/clothing/gloves/boxing.dm b/code/modules/clothing/gloves/boxing.dm
index 0865c31e942..02a34b41928 100644
--- a/code/modules/clothing/gloves/boxing.dm
+++ b/code/modules/clothing/gloves/boxing.dm
@@ -4,6 +4,12 @@
icon_state = "boxing"
item_state = "boxing"
+/obj/item/clothing/gloves/boxing/attackby(obj/item/weapon/W, mob/user)
+ if(istype(W, /obj/item/weapon/wirecutters) || istype(W, /obj/item/weapon/scalpel))
+ user << "That won't work." //Nope
+ return
+ ..()
+
/obj/item/clothing/gloves/boxing/green
icon_state = "boxinggreen"
item_state = "boxinggreen"
diff --git a/code/modules/clothing/shoes/colour.dm b/code/modules/clothing/shoes/colour.dm
index 55d0591a375..e20bea4cc73 100644
--- a/code/modules/clothing/shoes/colour.dm
+++ b/code/modules/clothing/shoes/colour.dm
@@ -86,29 +86,32 @@
item_color = "orange"
var/obj/item/weapon/handcuffs/chained = null
-/obj/item/clothing/shoes/orange/proc/attach_cuffs(var/obj/item/weapon/handcuffs/cuffs)
+/obj/item/clothing/shoes/orange/proc/attach_cuffs(var/obj/item/weapon/handcuffs/cuffs, mob/user as mob)
if (src.chained) return
+ user.drop_item()
cuffs.loc = src
src.chained = cuffs
src.slowdown = 15
src.icon_state = "orange1"
-/obj/item/clothing/shoes/orange/proc/remove_cuffs()
+/obj/item/clothing/shoes/orange/proc/remove_cuffs(mob/user as mob)
if (!src.chained) return
- src.chained.loc = get_turf(src)
+ user.put_in_hands(src.chained)
+ src.chained.add_fingerprint(user)
+
src.slowdown = initial(slowdown)
src.icon_state = "orange"
src.chained = null
/obj/item/clothing/shoes/orange/attack_self(mob/user as mob)
..()
- remove_cuffs()
+ remove_cuffs(user)
/obj/item/clothing/shoes/orange/attackby(H as obj, mob/user as mob)
..()
if (istype(H, /obj/item/weapon/handcuffs))
- attach_cuffs(H)
+ attach_cuffs(H, user)
diff --git a/code/modules/clothing/spacesuits/ert.dm b/code/modules/clothing/spacesuits/ert.dm
index 91bfd9dd059..33d8b19af61 100644
--- a/code/modules/clothing/spacesuits/ert.dm
+++ b/code/modules/clothing/spacesuits/ert.dm
@@ -30,7 +30,7 @@
w_class = 3
allowed = list(/obj/item/weapon/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/handcuffs,/obj/item/weapon/tank/emergency_oxygen)
slowdown = 1
- armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 100, rad = 60)
+ armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 100, rad = 100)
allowed = list(/obj/item/device/flashlight, /obj/item/weapon/tank, /obj/item/device/t_scanner, /obj/item/weapon/rcd, /obj/item/weapon/crowbar, \
/obj/item/weapon/screwdriver, /obj/item/weapon/weldingtool, /obj/item/weapon/wirecutters, /obj/item/weapon/wrench, /obj/item/device/multitool, \
/obj/item/device/radio, /obj/item/device/analyzer, /obj/item/weapon/gun/energy/laser, /obj/item/weapon/gun/energy/pulse_rifle, \
diff --git a/code/modules/clothing/spacesuits/rig.dm b/code/modules/clothing/spacesuits/rig.dm
index 6a0ecc49331..a8017a95da0 100644
--- a/code/modules/clothing/spacesuits/rig.dm
+++ b/code/modules/clothing/spacesuits/rig.dm
@@ -15,13 +15,15 @@
//Species-specific stuff.
species_restricted = list("exclude","Unathi","Tajaran","Skrell","Diona","Vox")
- sprite_sheets = list(
+ sprite_sheets_refit = list(
"Unathi" = 'icons/mob/species/unathi/helmet.dmi',
"Tajaran" = 'icons/mob/species/tajaran/helmet.dmi',
- "Skrell" = 'icons/mob/species/skrell/helmet.dmi'
+ "Skrell" = 'icons/mob/species/skrell/helmet.dmi',
)
sprite_sheets_obj = list(
+ "Unathi" = 'icons/obj/clothing/species/unathi/hats.dmi',
"Tajaran" = 'icons/obj/clothing/species/tajaran/hats.dmi',
+ "Skrell" = 'icons/obj/clothing/species/skrell/hats.dmi',
)
attack_self(mob/user)
@@ -63,13 +65,15 @@
max_heat_protection_temperature = SPACE_SUIT_MAX_HEAT_PROTECTION_TEMPERATURE
species_restricted = list("exclude","Unathi","Tajaran","Diona","Vox")
- sprite_sheets = list(
+ sprite_sheets_refit = list(
"Unathi" = 'icons/mob/species/unathi/suit.dmi',
"Tajaran" = 'icons/mob/species/tajaran/suit.dmi',
- "Skrell" = 'icons/mob/species/skrell/suit.dmi'
+ "Skrell" = 'icons/mob/species/skrell/suit.dmi',
)
sprite_sheets_obj = list(
+ "Unathi" = 'icons/obj/clothing/species/unathi/suits.dmi',
"Tajaran" = 'icons/obj/clothing/species/tajaran/suits.dmi',
+ "Skrell" = 'icons/obj/clothing/species/skrell/suits.dmi',
)
//Breach thresholds, should ideally be inherited by most (if not all) hardsuits.
@@ -322,14 +326,16 @@
icon_state = "rig0-white"
item_state = "ce_helm"
item_color = "white"
- sprite_sheets = null
+ sprite_sheets_refit = null
+ sprite_sheets_obj = null
/obj/item/clothing/suit/space/rig/engineering/chief
icon_state = "rig-white"
name = "advanced hardsuit"
desc = "An advanced suit that protects against hazardous, low pressure environments. Shines with a high polish."
item_state = "ce_hardsuit"
- sprite_sheets = null
+ sprite_sheets_refit = null
+ sprite_sheets_obj = null
//Mining rig
/obj/item/clothing/head/helmet/space/rig/mining
@@ -359,11 +365,6 @@
siemens_coefficient = 0.6
var/obj/machinery/camera/camera
species_restricted = list("exclude","Unathi","Tajaran","Skrell","Vox")
- sprite_sheets_obj = list(
- "Tajaran" = 'icons/obj/clothing/species/tajaran/hats.dmi',
- "Unathi" = 'icons/obj/clothing/species/unathi/hats.dmi',
- "Skrell" = 'icons/obj/clothing/species/skrell/hats.dmi',
- )
/obj/item/clothing/head/helmet/space/rig/syndi/attack_self(mob/user)
@@ -392,11 +393,6 @@
allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank,/obj/item/device/suit_cooling_unit,/obj/item/weapon/gun,/obj/item/ammo_magazine,/obj/item/ammo_casing,/obj/item/weapon/melee/baton,/obj/item/weapon/melee/energy/sword,/obj/item/weapon/handcuffs)
siemens_coefficient = 0.6
species_restricted = list("exclude","Unathi","Tajaran","Skrell","Vox")
- sprite_sheets_obj = list(
- "Tajaran" = 'icons/obj/clothing/species/tajaran/suits.dmi',
- "Unathi" = 'icons/obj/clothing/species/unathi/suits.dmi',
- "Skrell" = 'icons/obj/clothing/species/skrell/suits.dmi',
- )
//Wizard Rig
@@ -409,7 +405,7 @@
unacidable = 1 //No longer shall our kind be foiled by lone chemists with spray bottles!
armor = list(melee = 40, bullet = 20, laser = 20,energy = 20, bomb = 35, bio = 100, rad = 60)
siemens_coefficient = 0.7
- sprite_sheets = null
+ sprite_sheets_refit = null
sprite_sheets_obj = null
/obj/item/clothing/suit/space/rig/wizard
@@ -422,7 +418,7 @@
unacidable = 1
armor = list(melee = 40, bullet = 20, laser = 20,energy = 20, bomb = 35, bio = 100, rad = 60)
siemens_coefficient = 0.7
- sprite_sheets = null
+ sprite_sheets_refit = null
sprite_sheets_obj = null
//Medical Rig
diff --git a/code/modules/clothing/suits/utility.dm b/code/modules/clothing/suits/utility.dm
index 91153fee0fa..e75b3126902 100644
--- a/code/modules/clothing/suits/utility.dm
+++ b/code/modules/clothing/suits/utility.dm
@@ -102,7 +102,7 @@
w_class = 4//bulky item
gas_transfer_coefficient = 0.90
permeability_coefficient = 0.50
- body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
+ body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS|FEET
allowed = list(/obj/item/device/flashlight,/obj/item/weapon/tank/emergency_oxygen,/obj/item/clothing/head/radiation,/obj/item/clothing/mask/gas)
slowdown = 1.5
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 60, rad = 100)
diff --git a/code/modules/detectivework/evidence.dm b/code/modules/detectivework/evidence.dm
index 7148a5afed6..b5f6dfa2330 100644
--- a/code/modules/detectivework/evidence.dm
+++ b/code/modules/detectivework/evidence.dm
@@ -7,14 +7,39 @@
icon_state = "evidenceobj"
item_state = ""
w_class = 2
+ var/obj/item/stored_item = null
-/obj/item/weapon/evidencebag/afterattack(obj/item/I, mob/user as mob, proximity)
- if(!proximity) return
- if(!in_range(I, user))
+/obj/item/weapon/evidencebag/MouseDrop(var/obj/item/I as obj)
+ if (!ishuman(usr))
return
- if(!istype(I) || I.anchored == 1)
- return ..()
+ var/mob/living/carbon/human/user = usr
+
+ if (!(user.l_hand == src || user.r_hand == src))
+ return //bag must be in your hands to use
+
+ if (isturf(I.loc))
+ if (!user.Adjacent(I))
+ return
+ else
+ //If it isn't on the floor. Do some checks to see if it's in our hands or a box. Otherwise give up.
+ if(istype(I.loc,/obj/item/weapon/storage)) //in a container.
+ var/sdepth = I.storage_depth(user)
+ if (sdepth == -1 || sdepth > 1)
+ return //too deeply nested to access
+
+ var/obj/item/weapon/storage/U = I.loc
+ user.client.screen -= I
+ U.contents.Remove(I)
+ else if(user.l_hand == I) //in a hand
+ user.drop_l_hand()
+ else if(user.r_hand == I) //in a hand
+ user.drop_r_hand()
+ else
+ return
+
+ if(!istype(I) || I.anchored)
+ return
if(istype(I, /obj/item/weapon/evidencebag))
user << "You find putting an evidence bag in another evidence bag to be slightly absurd."
@@ -26,19 +51,7 @@
if(contents.len)
user << "[src] already has something inside it."
- return ..()
-
- if(!isturf(I.loc)) //If it isn't on the floor. Do some checks to see if it's in our hands or a box. Otherwise give up.
- if(istype(I.loc,/obj/item/weapon/storage)) //in a container.
- var/obj/item/weapon/storage/U = I.loc
- user.client.screen -= I
- U.contents.Remove(I)
- else if(user.l_hand == I) //in a hand
- user.drop_l_hand()
- else if(user.r_hand == I) //in a hand
- user.drop_r_hand()
- else
- return
+ return
user.visible_message("[user] puts [I] into [src]", "You put [I] inside [src].",\
"You hear a rustle as someone puts something into a plastic bag.")
@@ -55,28 +68,35 @@
overlays += img
overlays += "evidence" //should look nicer for transparent stuff. not really that important, but hey.
- desc = "An evidence bag containing [I]. [I.desc]"
+ desc = "An evidence bag containing [I]."
I.loc = src
+ stored_item = I
w_class = I.w_class
return
/obj/item/weapon/evidencebag/attack_self(mob/user as mob)
if(contents.len)
- var/obj/item/I = contents[1]
+ var/obj/item/I = stored_item
user.visible_message("[user] takes [I] out of [src]", "You take [I] out of [src].",\
"You hear someone rustle around in a plastic bag, and remove something.")
overlays.Cut() //remove the overlays
+
user.put_in_hands(I)
- w_class = 1
+ stored_item = null
+
+ w_class = initial(w_class)
icon_state = "evidenceobj"
desc = "An empty evidence bag."
-
else
user << "[src] is empty."
icon_state = "evidenceobj"
return
+/obj/item/weapon/evidencebag/examine()
+ ..()
+ if (stored_item) stored_item.examine()
+
/obj/item/weapon/storage/box/evidence
name = "evidence bag box"
desc = "A box claiming to contain evidence bags."
diff --git a/code/modules/events/borers.dm b/code/modules/events/borers.dm
index 2c6a2820fbb..75e1f8b577c 100644
--- a/code/modules/events/borers.dm
+++ b/code/modules/events/borers.dm
@@ -6,7 +6,7 @@
/datum/event/borer_infestation
announceWhen = 400
- var/spawncount = 1
+ var/spawncount = 5
var/successSpawn = 0 //So we don't make a command report if nothing gets spawned.
/datum/event/borer_infestation/setup()
diff --git a/code/modules/events/event_dynamic.dm b/code/modules/events/event_dynamic.dm
index 7ca50ad9ebe..fc96c21821f 100644
--- a/code/modules/events/event_dynamic.dm
+++ b/code/modules/events/event_dynamic.dm
@@ -44,15 +44,23 @@ var/list/event_last_fired = list()
//see:
// Code/WorkInProgress/Cael_Aislinn/Economy/Economy_Events.dm
// Code/WorkInProgress/Cael_Aislinn/Economy/Economy_Events_Mundane.dm
- possibleEvents[/datum/event/economic_event] = 300
- possibleEvents[/datum/event/trivial_news] = 400
- possibleEvents[/datum/event/mundane_news] = 300
+
+ if(ticker.mode && ticker.mode.name == "calamity") //Calamity mode messes with some events.
+ possibleEvents[/datum/event/borer_infestation] = 400
+ possibleEvents[/datum/event/economic_event] = 25
+ possibleEvents[/datum/event/trivial_news] = 25
+ possibleEvents[/datum/event/mundane_news] = 25
+ else
+ possibleEvents[/datum/event/economic_event] = 300
+ possibleEvents[/datum/event/trivial_news] = 400
+ possibleEvents[/datum/event/mundane_news] = 300
possibleEvents[/datum/event/pda_spam] = max(min(25, player_list.len) * 4, 200)
possibleEvents[/datum/event/money_lotto] = max(min(5, player_list.len), 50)
if(account_hack_attempted)
possibleEvents[/datum/event/money_hacker] = max(min(25, player_list.len) * 4, 200)
+
possibleEvents[/datum/event/carp_migration] = 20 + 10 * active_with_role["Engineer"]
possibleEvents[/datum/event/brand_intelligence] = 20 + 25 * active_with_role["Janitor"]
diff --git a/code/modules/events/event_manager.dm b/code/modules/events/event_manager.dm
index 1311e1c71bb..12efae2facc 100644
--- a/code/modules/events/event_manager.dm
+++ b/code/modules/events/event_manager.dm
@@ -32,7 +32,7 @@ var/scheduledEvent = null
playercount_modifier = 0.8
if(ticker.mode && ticker.mode.name == "calamity") //Calamity mode lowers the time required between events drastically.
- playercount_modifier = playercount_modifier * 0.3
+ playercount_modifier = playercount_modifier * 0.5
var/next_event_delay = rand(eventTimeLower, eventTimeUpper) * playercount_modifier
scheduledEvent = world.timeofday + next_event_delay
diff --git a/code/modules/hydroponics/hydro_tools.dm b/code/modules/hydroponics/hydro_tools.dm
index a0276e37b73..87cd6079fc2 100644
--- a/code/modules/hydroponics/hydro_tools.dm
+++ b/code/modules/hydroponics/hydro_tools.dm
@@ -18,7 +18,9 @@
var/datum/seed/grown_seed
var/datum/reagents/grown_reagents
- if(istype(target,/obj/item/weapon/reagent_containers/food/snacks/grown))
+ if(istype(target,/obj/structure/rack) || istype(target,/obj/structure/table))
+ return ..()
+ else if(istype(target,/obj/item/weapon/reagent_containers/food/snacks/grown))
var/obj/item/weapon/reagent_containers/food/snacks/grown/G = target
grown_seed = seed_types[G.plantname]
@@ -166,7 +168,7 @@
/obj/item/weapon/plantspray
icon = 'icons/obj/hydroponics.dmi'
item_state = "spray"
- flags = TABLEPASS | OPENCONTAINER | FPRINT | NOBLUDGEON
+ flags = TABLEPASS | FPRINT | NOBLUDGEON
slot_flags = SLOT_BELT
throwforce = 4
w_class = 2.0
@@ -181,13 +183,13 @@
name = "weed-spray"
desc = "It's a toxic mixture, in spray form, to kill small weeds."
icon_state = "weedspray"
- weed_kill_str = 2
+ weed_kill_str = 6
/obj/item/weapon/plantspray/pests
name = "pest-spray"
desc = "It's some pest eliminator spray! Do not inhale!"
icon_state = "pestspray"
- pest_kill_str = 2
+ pest_kill_str = 6
/obj/item/weapon/plantspray/pests/old
name = "bottle of pestkiller"
diff --git a/code/modules/hydroponics/hydro_tray.dm b/code/modules/hydroponics/hydro_tray.dm
index dc0dda59e45..a7aeba259c8 100644
--- a/code/modules/hydroponics/hydro_tray.dm
+++ b/code/modules/hydroponics/hydro_tray.dm
@@ -7,14 +7,15 @@
density = 1
anchored = 1
flags = OPENCONTAINER
+ volume = 100
var/draw_warnings = 1 //Set to 0 to stop it from drawing the alert lights.
// Plant maintenance vars.
- var/waterlevel = 100 // Water level (max 100)
- var/nutrilevel = 10 // Nutrient level (max 10)
+ var/waterlevel = 100 // Water (max 100)
+ var/nutrilevel = 100 // Nutrient (max 100)
var/pestlevel = 0 // Pests (max 10)
- var/weedlevel = 0 // Weeds (max 10)s
+ var/weedlevel = 0 // Weeds (max 10)
// Tray state vars.
var/dead = 0 // Is it dead?
@@ -25,6 +26,7 @@
var/yield_mod = 0 // Modifier to yield
var/mutation_mod = 0 // Modifier to mutation chance
var/toxins = 0 // Toxicity in the tray?
+ var/mutation_level = 0 // When it hits 100, the plant mutates.
// Mechanical concerns.
var/health = 0 // Plant health.
@@ -33,6 +35,7 @@
var/cycledelay = 150 // Delay per cycle.
var/closed_system // If set, the tray will attempt to take atmos from a pipe.
var/force_update // Set this to bypass the cycle time check.
+ var/obj/temp_chem_holder // Something to hold reagents during process_reagents()
// Seed details/line data.
var/datum/seed/seed = null // The currently planted seed
@@ -104,7 +107,7 @@
"cryoxadone" = list( 3, 0, 0 ),
"ammonia" = list( 0.5, 0, 0 ),
"diethylamine" = list( 1, 0, 0 ),
- "nutriment" = list( 0.5, 1, 0 ),
+ "nutriment" = list( 0.5, 0.1, 0 ),
"radium" = list( -1.5, 0, 0.2 ),
"adminordrazine" = list( 1, 1, 1 ),
"robustharvest" = list( 0, 0.2, 0 ),
@@ -114,12 +117,14 @@
// Mutagen list specifies minimum value for the mutation to take place, rather
// than a bound as the lists above specify.
var/global/list/mutagenic_reagents = list(
- "radium" = list(8,3),
- "mutagen" = list(3,8)
+ "radium" = 3,
+ "mutagen" = 8
)
/obj/machinery/portable_atmospherics/hydroponics/New()
..()
+ temp_chem_holder = new()
+ temp_chem_holder.create_reagents(10)
create_reagents(200)
connect()
update_icon()
@@ -162,9 +167,12 @@
return
lastcycle = world.time
+ // Mutation level drops each main tick.
+ mutation_level -= rand(2,4)
+
// Weeds like water and nutrients, there's a chance the weed population will increase.
// Bonus chance if the tray is unoccupied.
- if(waterlevel > 10 && nutrilevel > 2 && prob(isnull(seed) ? 6 : 3))
+ if(waterlevel > 10 && nutrilevel > 2 && prob(isnull(seed) ? 5 : 2))
weedlevel += 1 * HYDRO_SPEED_MULTIPLIER
// There's a chance for a weed explosion to happen if the weeds take over.
@@ -179,13 +187,19 @@
return
// Advance plant age.
- if(prob(25)) age += 1 * HYDRO_SPEED_MULTIPLIER
+ if(prob(30)) age += 1 * HYDRO_SPEED_MULTIPLIER
//Highly mutable plants have a chance of mutating every tick.
if(seed.immutable == -1)
var/mut_prob = rand(1,100)
if(mut_prob <= 5) mutate(mut_prob == 1 ? 2 : 1)
+ // Other plants also mutate if enough mutagenic compounds have been added.
+ if(!seed.immutable)
+ if(prob(min(mutation_level,100)))
+ mutate((rand(100) < 25) ? 2 : 1)
+ mutation_level = 0
+
// Maintain tray nutrient and water levels.
if(seed.nutrient_consumption > 0 && nutrilevel > 0 && prob(25))
nutrilevel -= max(0,seed.nutrient_consumption * HYDRO_SPEED_MULTIPLIER)
@@ -242,7 +256,7 @@
if(seed.exude_gasses && seed.exude_gasses.len)
for(var/gas in seed.exude_gasses)
environment.adjust_gas(gas, max(1,round((seed.exude_gasses[gas]*seed.potency)/seed.exude_gasses.len)))
-
+
// If we're attached to a pipenet, then we should let the pipenet know we might have modified some gasses
if (closed_system && connected_port)
update_connected_network()
@@ -291,6 +305,7 @@
// When the plant dies, weeds thrive and pests die off.
if(health <= 0)
dead = 1
+ mutation_level = 0
harvest = 0
weedlevel += 1 * HYDRO_SPEED_MULTIPLIER
pestlevel = 0
@@ -302,7 +317,7 @@
lastproduce = age
if(prob(3)) // On each tick, there's a chance the pest population will increase
- pestlevel += 1 * HYDRO_SPEED_MULTIPLIER
+ pestlevel += 0.1 * HYDRO_SPEED_MULTIPLIER
check_level_sanity()
update_icon()
@@ -316,19 +331,20 @@
if(reagents.total_volume <= 0)
return
- for(var/datum/reagent/R in reagents.reagent_list)
+ reagents.trans_to(temp_chem_holder, min(reagents.total_volume,rand(1,3)))
+ for(var/datum/reagent/R in temp_chem_holder.reagents.reagent_list)
- var/reagent_total = reagents.get_reagent_amount(R.id)
+ var/reagent_total = temp_chem_holder.reagents.get_reagent_amount(R.id)
if(seed && !dead)
//Handle some general level adjustments.
if(toxic_reagents[R.id])
toxins += toxic_reagents[R.id] * reagent_total
if(weedkiller_reagents[R.id])
- weedlevel += weedkiller_reagents[R.id] * reagent_total
+ weedlevel -= weedkiller_reagents[R.id] * reagent_total
if(pestkiller_reagents[R.id])
- pestlevel += pestkiller_reagents[R.id] * reagent_total
+ pestlevel -= pestkiller_reagents[R.id] * reagent_total
// Beneficial reagents have a few impacts along with health buffs.
if(beneficial_reagents[R.id])
@@ -338,12 +354,7 @@
// Mutagen is distinct from the previous types and mostly has a chance of proccing a mutation.
if(mutagenic_reagents[R.id])
- var/reagent_min_value = mutagenic_reagents[R.id][1]
- var/reagent_value = mutagenic_reagents[R.id][2]+mutation_mod
-
- if(reagent_total >= reagent_min_value)
- if(prob(min(reagent_total*reagent_value,100)))
- mutate(reagent_total > 10 ? 2 : 1)
+ mutation_level += reagent_total*mutagenic_reagents[R.id]+mutation_mod
// Handle nutrient refilling.
if(nutrient_reagents[R.id])
@@ -356,10 +367,11 @@
water_added += water_input
waterlevel += water_input
+ // Water dilutes toxin level.
if(water_added > 0)
toxins -= round(water_added/4)
- reagents.clear_reagents()
+ temp_chem_holder.reagents.clear_reagents()
check_level_sanity()
update_icon()
@@ -509,11 +521,12 @@
health = 0
dead = 0
- nutrilevel = max(0,min(nutrilevel,10))
- waterlevel = max(0,min(waterlevel,100))
- pestlevel = max(0,min(pestlevel,10))
- weedlevel = max(0,min(weedlevel,10))
- toxins = max(0,min(toxins,10))
+ mutation_level = max(0,min(mutation_level,100))
+ nutrilevel = max(0,min(nutrilevel,10))
+ waterlevel = max(0,min(waterlevel,100))
+ pestlevel = max(0,min(pestlevel,10))
+ weedlevel = max(0,min(weedlevel,10))
+ toxins = max(0,min(toxins,10))
/obj/machinery/portable_atmospherics/hydroponics/proc/mutate_species()
@@ -548,10 +561,16 @@
user << "There is nothing to take a sample from in \the [src]."
return
- seed.harvest(user,yield_mod,1)
- health -= (rand(1,5)*10)
- check_level_sanity()
+ if(dead)
+ user << "\The plant is dead."
+ return
+ // Create a sample.
+ seed.harvest(user,yield_mod,1)
+ health -= (rand(3,5)*10)
+
+ // Bookkeeping.
+ check_level_sanity()
force_update = 1
process()
@@ -565,14 +584,14 @@
if(seed)
return ..()
else
- user << "There's no plant in the tray to inject."
+ user << "There's no plant to inject."
return 1
else
if(seed)
//Leaving this in in case we want to extract from plants later.
user << "You can't get any extract out of this plant."
else
- user << "There's nothing in the tray to draw something from."
+ user << "There's nothing to draw something from."
return 1
else if (istype(O, /obj/item/seeds))
@@ -637,7 +656,7 @@
user << "There's nothing in [src] to spray!"
else if (istype(O, /obj/item/weapon/minihoe)) // The minihoe
- //var/deweeding
+
if(weedlevel > 0)
user.visible_message("\red [user] starts uprooting the weeds.", "\red You remove the weeds from the [src].")
weedlevel = 0
diff --git a/code/modules/hydroponics/seed_datums.dm b/code/modules/hydroponics/seed_datums.dm
index f1d12a1a6a5..206cb535f45 100644
--- a/code/modules/hydroponics/seed_datums.dm
+++ b/code/modules/hydroponics/seed_datums.dm
@@ -97,6 +97,136 @@ proc/populate_seed_list()
var/flower_icon = "vine_fruit" // Which overlay to use.
var/flower_colour // Which colour to use.
+//Creates a random seed. MAKE SURE THE LINE HAS DIVERGED BEFORE THIS IS CALLED.
+/datum/seed/proc/randomize()
+
+ roundstart = 0
+ seed_name = "strange plant" // TODO: name generator.
+ display_name = "strange plants" // TODO: name generator.
+
+ seed_noun = pick("spores","nodes","cuttings","seeds")
+ products = list(/obj/item/weapon/reagent_containers/food/snacks/grown/generic_fruit)
+ potency = rand(5,30)
+
+ //TODO: Finish generalizing the product icons so this can be randomized.
+ packet_icon = "seed-berry"
+ plant_icon = "berry"
+ if(prob(20))
+ harvest_repeat = 1
+
+ if(prob(5))
+ consume_gasses = list()
+ var/gas = pick("oxygen","nitrogen","phoron","carbon_dioxide")
+ consume_gasses[gas] = rand(3,9)
+
+ if(prob(5))
+ exude_gasses = list()
+ var/gas = pick("oxygen","nitrogen","phoron","carbon_dioxide")
+ exude_gasses[gas] = rand(3,9)
+
+ chems = list()
+ if(prob(80))
+ chems["nutriment"] = list(rand(1,10),rand(10,20))
+
+ var/additional_chems = rand(0,5)
+
+ var/list/possible_chems = list(
+ "bicaridine",
+ "hyperzine",
+ "cryoxadone",
+ "blood",
+ "water",
+ "potassium",
+ "plasticide",
+ "slimetoxin",
+ "aslimetoxin",
+ "inaprovaline",
+ "space_drugs",
+ "paroxetine",
+ "mercury",
+ "sugar",
+ "radium",
+ "ryetalyn",
+ "alkysine",
+ "thermite",
+ "tramadol",
+ "cryptobiolin",
+ "dermaline",
+ "dexalin",
+ "phoron",
+ "synaptizine",
+ "impedrezene",
+ "hyronalin",
+ "peridaxon",
+ "toxin",
+ "rezadone",
+ "ethylredoxrazine",
+ "slimejelly",
+ "cyanide",
+ "mindbreaker",
+ "stoxin"
+ )
+
+ for(var/x=1;x<=additional_chems;x++)
+ if(!possible_chems.len)
+ break
+ var/new_chem = pick(possible_chems)
+ possible_chems -= new_chem
+ chems[new_chem] = list(rand(1,10),rand(10,20))
+
+ if(prob(90))
+ requires_nutrients = 1
+ nutrient_consumption = rand(100)*0.1
+ else
+ requires_nutrients = 0
+
+ if(prob(90))
+ requires_water = 1
+ water_consumption = rand(10)
+ else
+ requires_water = 0
+
+ ideal_heat = rand(100,400)
+ heat_tolerance = rand(10,30)
+ ideal_light = rand(2,10)
+ light_tolerance = rand(2,7)
+ toxins_tolerance = rand(2,7)
+ pest_tolerance = rand(2,7)
+ weed_tolerance = rand(2,7)
+ lowkpa_tolerance = rand(10,50)
+ highkpa_tolerance = rand(100,300)
+
+ if(prob(5))
+ alter_temp = rand(-5,5)
+
+ if(prob(1))
+ immutable = -1
+
+ var/carnivore_prob = rand(100)
+ if(carnivore_prob < 5)
+ carnivorous = 2
+ else if(carnivore_prob < 10)
+ carnivorous = 1
+
+ if(prob(10))
+ parasite = 1
+
+ var/vine_prob = rand(100)
+ if(vine_prob < 5)
+ spread = 2
+ else if(vine_prob < 10)
+ spread = 1
+
+ if(prob(5))
+ biolum = 1
+ biolum_colour = "#[pick(list("FF0000","FF7F00","FFFF00","00FF00","0000FF","4B0082","8F00FF"))]"
+
+ endurance = rand(60,100)
+ yield = rand(3,15)
+ maturation = rand(5,15)
+ production = maturation + rand(2,5)
+ lifespan = production + rand(5,10)
+
//Returns a key corresponding to an entry in the global seed list.
/datum/seed/proc/get_mutant_variant()
if(!mutants || !mutants.len || immutable > 0) return 0
@@ -188,26 +318,35 @@ proc/populate_seed_list()
if(gene.values.len < 6) return
- yield = round(yield*0.5)
- endurance = round(endurance*0.5)
- lifespan = round(lifespan*0.8)
+ if(yield > 0) yield = max(1,round(yield*0.85))
+ if(endurance > 0) endurance = max(1,round(endurance*0.85))
+ if(lifespan > 0) lifespan = max(1,round(lifespan*0.85))
if(!products) products = list()
products |= gene.values[1]
if(!chems) chems = list()
- for(var/rid in gene.values[2])
- var/existing_chem
- for(var/chem in chems)
- if(rid == chem)
- existing_chem = 1
- break
- if(existing_chem)
- chems[rid][1] = max(1,round((chems[rid][1]+gene.values[2][rid][1])/2))
- chems[rid][2] = max(1,round((chems[rid][2]+gene.values[2][rid][2])/2))
+ var/list/gene_value = gene.values[2]
+ for(var/rid in gene_value)
+
+ var/list/gene_chem = gene_value[rid]
+
+ if(chems[rid])
+
+ var/list/chem_value = chems[rid]
+
+ chems[rid][1] = max(1,round((gene_chem[1] + chem_value[1])/2))
+
+ if(gene_chem.len > 1)
+ if(chem_value > 1)
+ chems[rid][2] = max(1,round((gene_chem[2] + chem_value[2])/2))
+ else
+ chems[rid][2] = gene_chem[2]
+
else
- chems[rid] = gene.values[2][rid]
+ var/list/new_chem = gene_chem[rid]
+ chems[rid] = new_chem.Copy()
var/list/new_gasses = gene.values[3]
if(istype(new_gasses))
@@ -353,7 +492,7 @@ proc/populate_seed_list()
if(!isnull(products) && products.len && yield > 0)
got_product = 1
- if(!got_product)
+ if(!got_product && !harvest_sample)
user << "\red You fail to harvest anything useful."
else
user << "You [harvest_sample ? "take a sample" : "harvest"] from the [display_name]."
@@ -370,12 +509,14 @@ proc/populate_seed_list()
seeds.update_seed()
return
- var/total_yield
- if(isnull(yield_mod) || yield_mod < 1)
- yield_mod = 0
- total_yield = yield
- else
- total_yield = max(1,rand(yield_mod,yield_mod+yield))
+ var/total_yield = 0
+ if(yield > -1)
+ if(isnull(yield_mod) || yield_mod < 1)
+ yield_mod = 0
+ total_yield = yield
+ else
+ total_yield = yield + rand(yield_mod)
+ total_yield = max(1,total_yield)
currently_querying = list()
for(var/i = 0;i 0)
user << "That seed is not compatible with our genetics technology."
diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm
index d0afda2e6fb..77a220792bc 100644
--- a/code/modules/hydroponics/seeds.dm
+++ b/code/modules/hydroponics/seeds.dm
@@ -40,6 +40,19 @@
..()
src.name = "packet of [seed.seed_name] cuttings"
+/obj/item/seeds/random
+ seed_type = null
+
+/obj/item/seeds/random/New()
+ seed = new()
+ seed.randomize()
+
+ seed.uid = seed_types.len + 1
+ seed.name = "[seed.uid]"
+ seed_types[seed.name] = seed
+
+ update_seed()
+
/obj/item/seeds/replicapod
seed_type = "diona"
diff --git a/code/modules/hydroponics/vines.dm b/code/modules/hydroponics/vines.dm
index 085229d417c..70265984f30 100644
--- a/code/modules/hydroponics/vines.dm
+++ b/code/modules/hydroponics/vines.dm
@@ -240,7 +240,7 @@
del src
/obj/effect/plantsegment/proc/die()
- if(seed && harvest)
+ if(seed && harvest && rand(5))
seed.harvest(src,1)
del(src)
diff --git a/code/modules/library/lib_items.dm b/code/modules/library/lib_items.dm
index ffb4915d788..e8374d56522 100644
--- a/code/modules/library/lib_items.dm
+++ b/code/modules/library/lib_items.dm
@@ -41,7 +41,7 @@
/obj/structure/bookcase/attack_hand(var/mob/user as mob)
if(contents.len)
- var/obj/item/weapon/book/choice = input("Which book would you like to remove from the shelf?") in contents as obj|null
+ var/obj/item/weapon/book/choice = input("Which book would you like to remove from the shelf?") as null|obj in contents
if(choice)
if(!usr.canmove || usr.stat || usr.restrained() || !in_range(loc, usr))
return
diff --git a/code/modules/mining/machine_processing.dm b/code/modules/mining/machine_processing.dm
index d8b671af252..2a029b42eeb 100644
--- a/code/modules/mining/machine_processing.dm
+++ b/code/modules/mining/machine_processing.dm
@@ -62,7 +62,7 @@
dat += "Currently displaying [show_all_ores ? "all ore types" : "only available ore types"]. \[[show_all_ores ? "show less" : "show more"]\]"
dat += "The ore processor is currently [(machine.active ? "processing" : "disabled")]."
user << browse(dat, "window=processor_console;size=400x500")
- onclose(user, "computer")
+ onclose(user, "processor_console")
return
/obj/machinery/mineral/processing_unit_console/Topic(href, href_list)
diff --git a/code/modules/mining/mine_turfs.dm b/code/modules/mining/mine_turfs.dm
index bf70bb5c767..c556990e815 100644
--- a/code/modules/mining/mine_turfs.dm
+++ b/code/modules/mining/mine_turfs.dm
@@ -28,8 +28,6 @@
/turf/simulated/mineral/New()
- . = ..()
-
MineralSpread()
spawn(2)
@@ -260,8 +258,23 @@
M.Stun(5)
M.apply_effect(25, IRRADIATE)
+
+ var/list/step_overlays = list("n" = NORTH, "s" = SOUTH, "e" = EAST, "w" = WEST)
+
+ //Add some rubble, you did just clear out a big chunk of rock.
var/turf/simulated/floor/plating/airless/asteroid/N = ChangeTurf(/turf/simulated/floor/plating/airless/asteroid)
- for(var/i=0;i last_update + 10)
- update_orecount()
+ update_ore_count()
last_update = world.time
- var/dat = text("The contents of the ore box reveal...")
- if (amt_iron)
- dat += text("
Metal ore: [amt_iron]")
- if (amt_glass)
- dat += text("
Sand: [amt_glass]")
- if (amt_phoron)
- dat += text("
Phoron ore: [amt_phoron]")
- if (amt_uranium)
- dat += text("
Uranium ore: [amt_uranium]")
- if (amt_silver)
- dat += text("
Silver ore: [amt_silver]")
- if (amt_gold)
- dat += text("
Gold ore: [amt_gold]")
- if (amt_diamond)
- dat += text("
Diamond ore: [amt_diamond]")
- if (amt_strange)
- dat += text("
Strange rocks: [amt_strange]")
-
- usr << dat
-
+ usr << "It holds:"
+ for(var/ore in stored_ore)
+ usr << "- [stored_ore[ore]] [ore]"
return
@@ -106,47 +95,4 @@
O.loc = src.loc
usr << "\blue You empty the ore box"
- return
-
-
-// Updates ore tally
-/obj/structure/ore_box/proc/update_orecount()
- amt_iron = 0
- amt_glass = 0
- amt_phoron = 0
- amt_uranium = 0
- amt_silver = 0
- amt_gold = 0
- amt_diamond = 0
- amt_strange = 0
- amt_clown = 0
-
- for(var/obj/item/weapon/ore/O in contents)
- if(!istype(O))
- continue
-
- if (istype(O, /obj/item/weapon/ore/iron))
- amt_iron++
- continue
- if (istype(O, /obj/item/weapon/ore/glass))
- amt_glass++
- continue
- if (istype(O, /obj/item/weapon/ore/phoron))
- amt_phoron++
- continue
- if (istype(O, /obj/item/weapon/ore/uranium))
- amt_uranium++
- continue
- if (istype(O, /obj/item/weapon/ore/silver))
- amt_silver++
- continue
- if (istype(O, /obj/item/weapon/ore/gold))
- amt_gold++
- continue
- if (istype(O, /obj/item/weapon/ore/diamond))
- amt_diamond++
- continue
- if (istype(O, /obj/item/weapon/ore/strangerock))
- amt_strange++
- continue
return
\ No newline at end of file
diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm
index 575996a84f7..f0c22c9f596 100644
--- a/code/modules/mob/living/carbon/carbon.dm
+++ b/code/modules/mob/living/carbon/carbon.dm
@@ -122,11 +122,11 @@
"\red You feel a mild shock course through your body.", \
"\red You hear a light zapping." \
)
-
+
var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread
s.set_up(5, 1, loc)
s.start()
-
+
return shock_damage
diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm
index bc6d2832e6a..01caff57e5a 100644
--- a/code/modules/mob/living/carbon/human/human_damage.dm
+++ b/code/modules/mob/living/carbon/human/human_damage.dm
@@ -165,6 +165,10 @@
hud_updateflag |= 1 << HEALTH_HUD
updatehealth()
+
+/*
+In most cases it makes more sense to use apply_damage() instead! And make sure to check armour if applicable.
+*/
//Damages ONE external organ, organ gets randomly selected from damagable ones.
//It automatically updates damage overlays if necesary
//It automatically updates health status
diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm
index d8d97dee787..5659f44a617 100644
--- a/code/modules/mob/living/carbon/human/human_defense.dm
+++ b/code/modules/mob/living/carbon/human/human_defense.dm
@@ -84,7 +84,7 @@ emp_act
/mob/living/carbon/human/getarmor(var/def_zone, var/type)
var/armorval = 0
- var/organnum = 0
+ var/total = 0
if(def_zone)
if(isorgan(def_zone))
@@ -94,10 +94,13 @@ emp_act
//If a specific bodypart is targetted, check how that bodypart is protected and return the value.
//If you don't specify a bodypart, it checks ALL your bodyparts for protection, and averages out the values
- for(var/datum/organ/external/organ in organs)
- armorval += getarmor_organ(organ, type)
- organnum++
- return (armorval/max(organnum, 1))
+ for(var/organ_name in organs_by_name)
+ if (organ_name in organ_rel_size)
+ var/datum/organ/external/organ = organs_by_name[organ_name]
+ var/weight = organ_rel_size[organ_name]
+ armorval += getarmor_organ(organ, type) * weight
+ total += weight
+ return (armorval/max(total, 1))
//this proc returns the Siemens coefficient of electrical resistivity for a particular external organ.
/mob/living/carbon/human/proc/get_siemens_coefficient_organ(var/datum/organ/external/def_zone)
@@ -117,11 +120,10 @@ emp_act
/mob/living/carbon/human/proc/getarmor_organ(var/datum/organ/external/def_zone, var/type)
if(!type) return 0
var/protection = 0
- var/list/body_parts = list(head, wear_mask, wear_suit, w_uniform)
- for(var/bp in body_parts)
- if(!bp) continue
- if(bp && istype(bp ,/obj/item/clothing))
- var/obj/item/clothing/C = bp
+ var/list/protective_gear = list(head, wear_mask, wear_suit, w_uniform)
+ for(var/gear in protective_gear)
+ if(gear && istype(gear ,/obj/item/clothing))
+ var/obj/item/clothing/C = gear
if(C.body_parts_covered & def_zone.body_part)
protection += C.armor[type]
return protection
diff --git a/code/modules/mob/living/carbon/human/life.dm b/code/modules/mob/living/carbon/human/life.dm
index 1119225ec17..c5fb663116a 100644
--- a/code/modules/mob/living/carbon/human/life.dm
+++ b/code/modules/mob/living/carbon/human/life.dm
@@ -642,6 +642,12 @@
var/pressure = environment.return_pressure()
var/adjusted_pressure = calculate_affecting_pressure(pressure)
+ //Check for contaminants before anything else because we don't want to skip it.
+ for(var/g in environment.gas)
+ if(gas_data.flags[g] & XGM_GAS_CONTAMINANT && environment.gas[g] > gas_data.overlay_limit[g] + 1)
+ pl_effects()
+ break
+
if(!istype(get_turf(src), /turf/space)) //space is not meant to change your body temperature.
var/loc_temp = T0C
if(istype(loc, /obj/mecha))
@@ -730,10 +736,6 @@
else
pressure_alert = -1
- for(var/g in environment.gas)
- if(gas_data.flags[g] & XGM_GAS_CONTAMINANT && environment.gas[g] > gas_data.overlay_limit[g] + 1)
- pl_effects()
- break
return
/*
diff --git a/code/modules/mob/living/damage_procs.dm b/code/modules/mob/living/damage_procs.dm
index 5431a2775ad..cc76d40c654 100644
--- a/code/modules/mob/living/damage_procs.dm
+++ b/code/modules/mob/living/damage_procs.dm
@@ -52,7 +52,8 @@
if(AGONY)
halloss += effect // Useful for objects that cause "subdual" damage. PAIN!
if(IRRADIATE)
- radiation += max((((effect - (effect*(getarmor(null, "rad")/100))))/(blocked+1)),0)//Rads auto check armor
+ var/rad_protection = getarmor(null, "rad")/100
+ radiation += max((1-rad_protection)*effect/(blocked+1),0)//Rads auto check armor
if(STUTTER)
if(status_flags & CANSTUN) // stun is usually associated with stutter
stuttering = max(stuttering,(effect/(blocked+1)))
diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm
index 2c0b3bbdb62..daf0e370049 100644
--- a/code/modules/mob/living/living.dm
+++ b/code/modules/mob/living/living.dm
@@ -470,7 +470,7 @@
H << "\red You begin doggedly resisting the parasite's control (this will take approximately sixty seconds)."
B.host << "\red You feel the captive mind of [src] begin to resist your control."
- spawn(rand(350,450)+B.host.brainloss)
+ spawn(rand(400,500)+B.host.brainloss)
if(!B || !B.controlling)
return
diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm
index 6f308e6add4..3e895c73c2c 100644
--- a/code/modules/mob/living/living_defense.dm
+++ b/code/modules/mob/living/living_defense.dm
@@ -61,7 +61,7 @@
src <<"\red You have been hit by [P]!"
del P
return
-
+
//Armor
var/absorb = run_armor_check(def_zone, P.flag)
var/proj_sharp = is_sharp(P)
@@ -78,13 +78,13 @@
//Handles the effects of "stun" weapons
/mob/living/proc/stun_effect_act(var/stun_amount, var/agony_amount, var/def_zone, var/used_weapon=null)
flash_pain()
-
+
if (stun_amount)
Stun(stun_amount)
Weaken(stun_amount)
apply_effect(STUTTER, stun_amount)
apply_effect(EYE_BLUR, stun_amount)
-
+
if (agony_amount)
apply_damage(agony_amount, HALLOSS, def_zone, 0, used_weapon)
apply_effect(STUTTER, agony_amount/10)
@@ -108,16 +108,16 @@
var/obj/item/weapon/W = O
dtype = W.damtype
var/throw_damage = O.throwforce*(speed/5)
-
+
var/miss_chance = 15
if (O.throw_source)
var/distance = get_dist(O.throw_source, loc)
miss_chance = min(15*(distance-2), 0)
-
+
if (prob(miss_chance))
visible_message("\blue \The [O] misses [src] narrowly!")
return
-
+
src.visible_message("\red [src] has been hit by [O].")
var/armor = run_armor_check(null, "melee")
@@ -125,7 +125,7 @@
apply_damage(throw_damage, dtype, null, armor, is_sharp(O), has_edge(O), O)
O.throwing = 0 //it hit, so stop moving
-
+
if(ismob(O.thrower))
var/mob/M = O.thrower
var/client/assailant = M.client
@@ -145,7 +145,7 @@
src.throw_at(get_edge_target_turf(src,dir),1,momentum)
if(!W || !src) return
-
+
if(W.sharp) //Projectile is suitable for pinning.
//Handles embedding for non-humans and simple_animals.
O.loc = src
@@ -158,6 +158,7 @@
visible_message("[src] is pinned to the wall by [O]!","You are pinned to the wall by [O]!")
src.anchored = 1
src.pinned += O
+ src.verbs += /mob/proc/yank_out_object
//This is called when the mob is thrown into a dense turf
/mob/living/proc/turf_collision(var/turf/T, var/speed)
diff --git a/code/modules/mob/living/silicon/ai/ai.dm b/code/modules/mob/living/silicon/ai/ai.dm
index 36a8df5cc15..7a187d2573e 100644
--- a/code/modules/mob/living/silicon/ai/ai.dm
+++ b/code/modules/mob/living/silicon/ai/ai.dm
@@ -3,6 +3,7 @@
var/list/ai_list = list()
var/list/ai_verbs_default = list(
+ /mob/living/silicon/ai/proc/ai_alerts,
/mob/living/silicon/ai/proc/ai_announcement,
/mob/living/silicon/ai/proc/ai_call_shuttle,
// /mob/living/silicon/ai/proc/ai_recall_shuttle,
diff --git a/code/modules/mob/living/silicon/pai/pai.dm b/code/modules/mob/living/silicon/pai/pai.dm
index dd3e2e6b3cf..efdf6669ac2 100755
--- a/code/modules/mob/living/silicon/pai/pai.dm
+++ b/code/modules/mob/living/silicon/pai/pai.dm
@@ -32,7 +32,7 @@
"Chirp" = list("chirps","chirrups","cheeps"),
"Feline" = list("purrs","yowls","meows")
)
-
+
var/obj/item/weapon/pai_cable/cable // The cable we produce and use when door or camera jacking
var/master // Name of the one who commands us
@@ -84,7 +84,6 @@
add_language("Tradeband", 1)
add_language("Gutter", 1)
- verbs += /mob/living/silicon/pai/proc/fold_out
verbs += /mob/living/silicon/pai/proc/choose_chassis
verbs += /mob/living/silicon/pai/proc/choose_verbs
@@ -301,7 +300,7 @@
// mobile pai mob. This also includes handling some of the general shit that can occur
// to it. Really this deserves its own file, but for the moment it can sit here. ~ Z
-/mob/living/silicon/pai/proc/fold_out()
+/mob/living/silicon/pai/verb/fold_out()
set category = "pAI Commands"
set name = "Unfold Chassis"
@@ -315,8 +314,6 @@
return
last_special = world.time + 100
- verbs -= /mob/living/silicon/pai/proc/fold_out
- verbs += /mob/living/silicon/pai/proc/fold_up
var/turf/T = get_turf(src)
if(istype(T)) T.visible_message("[src] folds outwards, expanding into a mobile form.")
@@ -333,7 +330,7 @@
src.forceMove(get_turf(card))
card.forceMove(src)
-/mob/living/silicon/pai/proc/fold_up()
+/mob/living/silicon/pai/verb/fold_up()
set category = "pAI Commands"
set name = "Collapse Chassis"
@@ -412,8 +409,8 @@
last_special = world.time + 100
- verbs -= /mob/living/silicon/pai/proc/fold_up
- verbs += /mob/living/silicon/pai/proc/fold_out
+ if(src.loc == card)
+ return
var/turf/T = get_turf(src)
if(istype(T)) T.visible_message("[src] neatly folds inwards, compacting down to a rectangular card.")
diff --git a/code/modules/mob/living/silicon/pai/recruit.dm b/code/modules/mob/living/silicon/pai/recruit.dm
index 73a6d59c158..623b2b5638e 100644
--- a/code/modules/mob/living/silicon/pai/recruit.dm
+++ b/code/modules/mob/living/silicon/pai/recruit.dm
@@ -108,7 +108,6 @@ var/datum/paiController/paiController // Global handler for pAI candidates
candidate.key = M.key
pai_candidates.Add(candidate)
-
var/dat = ""
dat += {"