mirror of
https://github.com/VOREStation/VOREStation.git
synced 2026-08-22 11:38:12 +01:00
Merge pull request #6336 from Baystation12/dev-freeze
[DNM] Dev freeze > Master
This commit is contained in:
+30
-13
@@ -48,6 +48,8 @@
|
||||
#include "code\_onclick\hud\other_mobs.dm"
|
||||
#include "code\_onclick\hud\robot.dm"
|
||||
#include "code\_onclick\hud\screen_objects.dm"
|
||||
#include "code\ATMOSPHERICS\_atmos_setup.dm"
|
||||
#include "code\ATMOSPHERICS\_atmospherics_helpers.dm"
|
||||
#include "code\ATMOSPHERICS\atmospherics.dm"
|
||||
#include "code\ATMOSPHERICS\datum_pipe_network.dm"
|
||||
#include "code\ATMOSPHERICS\datum_pipeline.dm"
|
||||
@@ -82,6 +84,7 @@
|
||||
#include "code\ATMOSPHERICS\components\unary\vent_scrubber.dm"
|
||||
#include "code\controllers\_DynamicAreaLighting_TG.dm"
|
||||
#include "code\controllers\autotransfer.dm"
|
||||
#include "code\controllers\communications.dm"
|
||||
#include "code\controllers\configuration.dm"
|
||||
#include "code\controllers\emergency_shuttle_controller.dm"
|
||||
#include "code\controllers\failsafe.dm"
|
||||
@@ -173,7 +176,6 @@
|
||||
#include "code\game\asteroid.dm"
|
||||
#include "code\game\atoms.dm"
|
||||
#include "code\game\atoms_movable.dm"
|
||||
#include "code\game\communications.dm"
|
||||
#include "code\game\response_team.dm"
|
||||
#include "code\game\shuttle_engines.dm"
|
||||
#include "code\game\skincmd.dm"
|
||||
@@ -205,6 +207,7 @@
|
||||
#include "code\game\gamemodes\blob\blobs\factory.dm"
|
||||
#include "code\game\gamemodes\blob\blobs\node.dm"
|
||||
#include "code\game\gamemodes\blob\blobs\shield.dm"
|
||||
#include "code\game\gamemodes\calamity\calamity.dm"
|
||||
#include "code\game\gamemodes\changeling\changeling.dm"
|
||||
#include "code\game\gamemodes\changeling\changeling_powers.dm"
|
||||
#include "code\game\gamemodes\changeling\modularchangling.dm"
|
||||
@@ -297,7 +300,6 @@
|
||||
#include "code\game\machinery\doppler_array.dm"
|
||||
#include "code\game\machinery\flasher.dm"
|
||||
#include "code\game\machinery\floodlight.dm"
|
||||
#include "code\game\machinery\Freezer.dm"
|
||||
#include "code\game\machinery\hologram.dm"
|
||||
#include "code\game\machinery\holosign.dm"
|
||||
#include "code\game\machinery\igniter.dm"
|
||||
@@ -310,14 +312,12 @@
|
||||
#include "code\game\machinery\newscaster.dm"
|
||||
#include "code\game\machinery\OpTable.dm"
|
||||
#include "code\game\machinery\overview.dm"
|
||||
#include "code\game\machinery\podmen.dm"
|
||||
#include "code\game\machinery\portable_turret.dm"
|
||||
#include "code\game\machinery\recharger.dm"
|
||||
#include "code\game\machinery\rechargestation.dm"
|
||||
#include "code\game\machinery\requests_console.dm"
|
||||
#include "code\game\machinery\robot_fabricator.dm"
|
||||
#include "code\game\machinery\seed_extractor.dm"
|
||||
#include "code\game\machinery\shieldgen.dm"
|
||||
#include "code\game\machinery\Sleeper.dm"
|
||||
#include "code\game\machinery\spaceheater.dm"
|
||||
#include "code\game\machinery\status_display.dm"
|
||||
@@ -334,7 +334,6 @@
|
||||
#include "code\game\machinery\atmoalter\portable_atmospherics.dm"
|
||||
#include "code\game\machinery\atmoalter\pump.dm"
|
||||
#include "code\game\machinery\atmoalter\scrubber.dm"
|
||||
#include "code\game\machinery\atmoalter\zvent.dm"
|
||||
#include "code\game\machinery\bots\bots.dm"
|
||||
#include "code\game\machinery\bots\cleanbot.dm"
|
||||
#include "code\game\machinery\bots\ed209bot.dm"
|
||||
@@ -366,7 +365,6 @@
|
||||
#include "code\game\machinery\computer\message.dm"
|
||||
#include "code\game\machinery\computer\Operating.dm"
|
||||
#include "code\game\machinery\computer\pod.dm"
|
||||
#include "code\game\machinery\computer\power.dm"
|
||||
#include "code\game\machinery\computer\prisoner.dm"
|
||||
#include "code\game\machinery\computer\prisonshuttle.dm"
|
||||
#include "code\game\machinery\computer\robot.dm"
|
||||
@@ -415,6 +413,7 @@
|
||||
#include "code\game\magic\Uristrunes.dm"
|
||||
#include "code\game\mecha\mech_bay.dm"
|
||||
#include "code\game\mecha\mech_fabricator.dm"
|
||||
#include "code\game\mecha\mech_sensor.dm"
|
||||
#include "code\game\mecha\mecha.dm"
|
||||
#include "code\game\mecha\mecha_construction_paths.dm"
|
||||
#include "code\game\mecha\mecha_control_console.dm"
|
||||
@@ -485,6 +484,7 @@
|
||||
#include "code\game\objects\items\devices\debugger.dm"
|
||||
#include "code\game\objects\items\devices\flash.dm"
|
||||
#include "code\game\objects\items\devices\flashlight.dm"
|
||||
#include "code\game\objects\items\devices\floor_painter.dm"
|
||||
#include "code\game\objects\items\devices\lightreplacer.dm"
|
||||
#include "code\game\objects\items\devices\megaphone.dm"
|
||||
#include "code\game\objects\items\devices\modkit.dm"
|
||||
@@ -746,6 +746,7 @@
|
||||
#include "code\modules\client\client defines.dm"
|
||||
#include "code\modules\client\client procs.dm"
|
||||
#include "code\modules\client\preferences.dm"
|
||||
#include "code\modules\client\preferences_factions.dm"
|
||||
#include "code\modules\client\preferences_gear.dm"
|
||||
#include "code\modules\client\preferences_savefile.dm"
|
||||
#include "code\modules\client\preferences_spawnpoints.dm"
|
||||
@@ -803,10 +804,11 @@
|
||||
#include "code\modules\customitems\item_defines.dm"
|
||||
#include "code\modules\customitems\item_spawning.dm"
|
||||
#include "code\modules\destilery\main.dm"
|
||||
#include "code\modules\detectivework\detective_work.dm"
|
||||
#include "code\modules\detectivework\evidence.dm"
|
||||
#include "code\modules\detectivework\footprints_and_rag.dm"
|
||||
#include "code\modules\detectivework\forensics.dm"
|
||||
#include "code\modules\detectivework\scanner.dm"
|
||||
#include "code\modules\detectivework\scanning_console.dm"
|
||||
#include "code\modules\economy\Accounts.dm"
|
||||
#include "code\modules\economy\Accounts_DB.dm"
|
||||
#include "code\modules\economy\ATM.dm"
|
||||
@@ -857,7 +859,11 @@
|
||||
#include "code\modules\hydroponics\grown_inedible.dm"
|
||||
#include "code\modules\hydroponics\hydro_tools.dm"
|
||||
#include "code\modules\hydroponics\hydro_tray.dm"
|
||||
#include "code\modules\hydroponics\seed_datums.dm"
|
||||
#include "code\modules\hydroponics\seed_machines.dm"
|
||||
#include "code\modules\hydroponics\seed_mobs.dm"
|
||||
#include "code\modules\hydroponics\seeds.dm"
|
||||
#include "code\modules\hydroponics\vines.dm"
|
||||
#include "code\modules\library\lib_items.dm"
|
||||
#include "code\modules\library\lib_machines.dm"
|
||||
#include "code\modules\library\lib_readme.dm"
|
||||
@@ -982,6 +988,7 @@
|
||||
#include "code\modules\mob\living\carbon\metroid\login.dm"
|
||||
#include "code\modules\mob\living\carbon\metroid\metroid.dm"
|
||||
#include "code\modules\mob\living\carbon\metroid\powers.dm"
|
||||
#include "code\modules\mob\living\carbon\metroid\say.dm"
|
||||
#include "code\modules\mob\living\carbon\metroid\subtypes.dm"
|
||||
#include "code\modules\mob\living\carbon\metroid\update_icons.dm"
|
||||
#include "code\modules\mob\living\carbon\monkey\death.dm"
|
||||
@@ -1032,6 +1039,7 @@
|
||||
#include "code\modules\mob\living\silicon\robot\laws.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\life.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\login.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\photos.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\robot.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\robot_damage.dm"
|
||||
#include "code\modules\mob\living\silicon\robot\robot_items.dm"
|
||||
@@ -1090,6 +1098,7 @@
|
||||
#include "code\modules\nano\JSON Writer.dm"
|
||||
#include "code\modules\nano\nanoexternal.dm"
|
||||
#include "code\modules\nano\nanomanager.dm"
|
||||
#include "code\modules\nano\nanomapgen.dm"
|
||||
#include "code\modules\nano\nanoui.dm"
|
||||
#include "code\modules\organs\blood.dm"
|
||||
#include "code\modules\organs\organ.dm"
|
||||
@@ -1108,6 +1117,7 @@
|
||||
#include "code\modules\paperwork\pen.dm"
|
||||
#include "code\modules\paperwork\photocopier.dm"
|
||||
#include "code\modules\paperwork\photography.dm"
|
||||
#include "code\modules\paperwork\silicon_photography.dm"
|
||||
#include "code\modules\paperwork\stamps.dm"
|
||||
#include "code\modules\power\apc.dm"
|
||||
#include "code\modules\power\batteryrack.dm"
|
||||
@@ -1122,6 +1132,9 @@
|
||||
#include "code\modules\power\lighting.dm"
|
||||
#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\solar.dm"
|
||||
#include "code\modules\power\switch.dm"
|
||||
@@ -1306,6 +1319,13 @@
|
||||
#include "code\modules\scripting\Scanner\Tokens.dm"
|
||||
#include "code\modules\security levels\keycard authentication.dm"
|
||||
#include "code\modules\security levels\security levels.dm"
|
||||
#include "code\modules\shieldgen\circuits_and_designs.dm"
|
||||
#include "code\modules\shieldgen\emergency_shield.dm"
|
||||
#include "code\modules\shieldgen\energy_field.dm"
|
||||
#include "code\modules\shieldgen\sheldwallgen.dm"
|
||||
#include "code\modules\shieldgen\shield_capacitor.dm"
|
||||
#include "code\modules\shieldgen\shield_gen.dm"
|
||||
#include "code\modules\shieldgen\shield_gen_external.dm"
|
||||
#include "code\modules\shuttles\antagonist.dm"
|
||||
#include "code\modules\shuttles\departmental.dm"
|
||||
#include "code\modules\shuttles\escape_pods.dm"
|
||||
@@ -1379,11 +1399,6 @@
|
||||
#include "code\WorkInProgress\Cael_Aislinn\Rust\gyrotron_controller.dm"
|
||||
#include "code\WorkInProgress\Cael_Aislinn\Rust\radiation.dm"
|
||||
#include "code\WorkInProgress\Cael_Aislinn\Rust\virtual_particle_catcher.dm"
|
||||
#include "code\WorkInProgress\Cael_Aislinn\ShieldGen\circuits_and_designs.dm"
|
||||
#include "code\WorkInProgress\Cael_Aislinn\ShieldGen\energy_field.dm"
|
||||
#include "code\WorkInProgress\Cael_Aislinn\ShieldGen\shield_capacitor.dm"
|
||||
#include "code\WorkInProgress\Cael_Aislinn\ShieldGen\shield_gen.dm"
|
||||
#include "code\WorkInProgress\Cael_Aislinn\ShieldGen\shield_gen_external.dm"
|
||||
#include "code\WorkInProgress\Cael_Aislinn\Supermatter\LaserComputer.dm"
|
||||
#include "code\WorkInProgress\Cael_Aislinn\Supermatter\ZeroPointLaser.dm"
|
||||
#include "code\WorkInProgress\Chinsky\ashtray.dm"
|
||||
@@ -1426,7 +1441,8 @@
|
||||
#include "code\WorkInProgress\SkyMarshal\Ultralight_procs.dm"
|
||||
#include "code\WorkInProgress\Wrongnumber\weldbackpack.dm"
|
||||
#include "code\ZAS\_docs.dm"
|
||||
#include "code\ZAS\_gas_mixture.dm"
|
||||
#include "code\ZAS\_gas_mixture_xgm.dm"
|
||||
#include "code\ZAS\_xgm_gas_data.dm"
|
||||
#include "code\ZAS\Airflow.dm"
|
||||
#include "code\ZAS\Atom.dm"
|
||||
#include "code\ZAS\Connection.dm"
|
||||
@@ -1436,6 +1452,7 @@
|
||||
#include "code\ZAS\Debug.dm"
|
||||
#include "code\ZAS\Diagnostic.dm"
|
||||
#include "code\ZAS\Fire.dm"
|
||||
#include "code\ZAS\Gas.dm"
|
||||
#include "code\ZAS\Phoron.dm"
|
||||
#include "code\ZAS\Turf.dm"
|
||||
#include "code\ZAS\Variable Settings.dm"
|
||||
|
||||
@@ -0,0 +1,215 @@
|
||||
//--------------------------------------------
|
||||
// Pipe colors
|
||||
//
|
||||
// Add them here and to the pipe_colors list
|
||||
// to automatically add them to all relevant
|
||||
// atmospherics devices.
|
||||
//--------------------------------------------
|
||||
|
||||
#define PIPE_COLOR_GREY "#ffffff" //yes white is grey
|
||||
#define PIPE_COLOR_RED "#ff0000"
|
||||
#define PIPE_COLOR_BLUE "#0000ff"
|
||||
#define PIPE_COLOR_CYAN "#00ffff"
|
||||
#define PIPE_COLOR_GREEN "#00ff00"
|
||||
#define PIPE_COLOR_YELLOW "#ffcc00"
|
||||
#define PIPE_COLOR_PURPLE "#5c1ec0"
|
||||
|
||||
var/global/list/pipe_colors = list("grey" = PIPE_COLOR_GREY, "red" = PIPE_COLOR_RED, "blue" = PIPE_COLOR_BLUE, "cyan" = PIPE_COLOR_CYAN, "green" = PIPE_COLOR_GREEN, "yellow" = PIPE_COLOR_YELLOW, "purple" = PIPE_COLOR_PURPLE)
|
||||
|
||||
/proc/pipe_color_lookup(var/color)
|
||||
for(var/C in pipe_colors)
|
||||
if(color == pipe_colors[C])
|
||||
return "[C]"
|
||||
|
||||
/proc/pipe_color_check(var/color)
|
||||
if(!color)
|
||||
return 1
|
||||
for(var/C in pipe_colors)
|
||||
if(color == pipe_colors[C])
|
||||
return 1
|
||||
return 0
|
||||
|
||||
//--------------------------------------------
|
||||
// Icon cache generation
|
||||
//--------------------------------------------
|
||||
|
||||
/datum/pipe_icon_manager
|
||||
var/list/pipe_icons[]
|
||||
var/list/manifold_icons[]
|
||||
var/list/device_icons[]
|
||||
var/list/underlays_down[]
|
||||
var/list/underlays_exposed[]
|
||||
var/list/underlays_intact[]
|
||||
var/list/pipe_underlays_exposed[]
|
||||
var/list/pipe_underlays_intact[]
|
||||
var/list/omni_icons[]
|
||||
|
||||
/datum/pipe_icon_manager/New()
|
||||
check_icons()
|
||||
|
||||
/datum/pipe_icon_manager/proc/get_atmos_icon(var/device, var/dir, var/color, var/state)
|
||||
check_icons()
|
||||
|
||||
device = "[device]"
|
||||
state = "[state]"
|
||||
color = "[color]"
|
||||
dir = "[dir]"
|
||||
|
||||
switch(device)
|
||||
if("pipe")
|
||||
return pipe_icons[state + color]
|
||||
if("manifold")
|
||||
return manifold_icons[state + color]
|
||||
if("device")
|
||||
return device_icons[state]
|
||||
if("omni")
|
||||
return omni_icons[state]
|
||||
if("underlay_intact")
|
||||
return underlays_intact[dir + color]
|
||||
if("underlay_exposed")
|
||||
return underlays_exposed[dir + color]
|
||||
if("underlay_down")
|
||||
return underlays_down[dir + color]
|
||||
if("pipe_underlay_exposed")
|
||||
return pipe_underlays_exposed[dir + color]
|
||||
if("pipe_underlay_intact")
|
||||
return pipe_underlays_intact[dir + color]
|
||||
|
||||
/datum/pipe_icon_manager/proc/check_icons()
|
||||
if(!pipe_icons)
|
||||
gen_pipe_icons()
|
||||
if(!manifold_icons)
|
||||
gen_manifold_icons()
|
||||
if(!device_icons)
|
||||
gen_device_icons()
|
||||
if(!omni_icons)
|
||||
gen_omni_icons()
|
||||
if(!underlays_intact || !underlays_down || !underlays_exposed || !pipe_underlays_exposed || !pipe_underlays_intact)
|
||||
gen_underlay_icons()
|
||||
|
||||
/datum/pipe_icon_manager/proc/gen_pipe_icons()
|
||||
if(!pipe_icons)
|
||||
pipe_icons = new()
|
||||
|
||||
var/icon/pipe = new('icons/atmos/pipes.dmi')
|
||||
|
||||
for(var/state in pipe.IconStates())
|
||||
if(!state || findtext(state, "map"))
|
||||
continue
|
||||
|
||||
var/cache_name = state
|
||||
var/image/I = image('icons/atmos/pipes.dmi', icon_state = state)
|
||||
pipe_icons[cache_name] = I
|
||||
|
||||
for(var/pipe_color in pipe_colors)
|
||||
I = image('icons/atmos/pipes.dmi', icon_state = state)
|
||||
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()
|
||||
|
||||
var/icon/pipe = new('icons/atmos/manifold.dmi')
|
||||
|
||||
for(var/state in pipe.IconStates())
|
||||
if(findtext(state, "clamps"))
|
||||
var/image/I = image('icons/atmos/manifold.dmi', icon_state = state)
|
||||
manifold_icons[state] = I
|
||||
continue
|
||||
|
||||
if(state == "core" || state == "4way")
|
||||
var/image/I = image('icons/atmos/manifold.dmi', icon_state = state)
|
||||
manifold_icons[state] = I
|
||||
for(var/pipe_color in pipe_colors)
|
||||
I = image('icons/atmos/manifold.dmi', icon_state = state)
|
||||
I.color = pipe_colors[pipe_color]
|
||||
manifold_icons[state + pipe_colors[pipe_color]] = I
|
||||
|
||||
/datum/pipe_icon_manager/proc/gen_device_icons()
|
||||
if(!device_icons)
|
||||
device_icons = new()
|
||||
|
||||
var/icon/device
|
||||
|
||||
device = new('icons/atmos/vent_pump.dmi')
|
||||
for(var/state in device.IconStates())
|
||||
if(!state || findtext(state, "map"))
|
||||
continue
|
||||
device_icons["vent" + state] = image('icons/atmos/vent_pump.dmi', icon_state = state)
|
||||
|
||||
device = new('icons/atmos/vent_scrubber.dmi')
|
||||
for(var/state in device.IconStates())
|
||||
if(!state || findtext(state, "map"))
|
||||
continue
|
||||
device_icons["scrubber" + state] = image('icons/atmos/vent_scrubber.dmi', icon_state = state)
|
||||
|
||||
/datum/pipe_icon_manager/proc/gen_omni_icons()
|
||||
if(!omni_icons)
|
||||
omni_icons = new()
|
||||
|
||||
var/icon/omni = new('icons/atmos/omni_devices.dmi')
|
||||
|
||||
for(var/state in omni.IconStates())
|
||||
if(!state || findtext(state, "map"))
|
||||
continue
|
||||
omni_icons[state] = image('icons/atmos/omni_devices.dmi', icon_state = state)
|
||||
|
||||
/datum/pipe_icon_manager/proc/gen_underlay_icons()
|
||||
if(!underlays_intact)
|
||||
underlays_intact = new()
|
||||
if(!underlays_exposed)
|
||||
underlays_exposed = new()
|
||||
if(!underlays_down)
|
||||
underlays_down = new()
|
||||
if(!pipe_underlays_exposed)
|
||||
pipe_underlays_exposed = new()
|
||||
if(!pipe_underlays_intact)
|
||||
pipe_underlays_intact = new()
|
||||
|
||||
var/icon/pipe = new('icons/atmos/pipe_underlays.dmi')
|
||||
|
||||
for(var/state in pipe.IconStates())
|
||||
if(state == "")
|
||||
continue
|
||||
|
||||
for(var/D in cardinal)
|
||||
var/image/I = image('icons/atmos/pipe_underlays.dmi', icon_state = state, dir = D)
|
||||
switch(state)
|
||||
if("intact")
|
||||
underlays_intact["[D]"] = I
|
||||
if("exposed")
|
||||
underlays_exposed["[D]"] = I
|
||||
if("down")
|
||||
underlays_down["[D]"] = I
|
||||
if("pipe_exposed")
|
||||
pipe_underlays_exposed["[D]"] = I
|
||||
if("pipe_intact")
|
||||
pipe_underlays_intact["[D]"] = I
|
||||
for(var/pipe_color in pipe_colors)
|
||||
I = image('icons/atmos/pipe_underlays.dmi', icon_state = state, dir = D)
|
||||
I.color = pipe_colors[pipe_color]
|
||||
switch(state)
|
||||
if("intact")
|
||||
underlays_intact["[D]" + pipe_colors[pipe_color]] = I
|
||||
if("exposed")
|
||||
underlays_exposed["[D]" + pipe_colors[pipe_color]] = I
|
||||
if("down")
|
||||
underlays_down["[D]" + pipe_colors[pipe_color]] = I
|
||||
if("pipe_exposed")
|
||||
pipe_underlays_exposed["[D]" + pipe_colors[pipe_color]] = I
|
||||
if("pipe_intact")
|
||||
pipe_underlays_intact["[D]" + pipe_colors[pipe_color]] = I
|
||||
@@ -0,0 +1,423 @@
|
||||
/*
|
||||
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).
|
||||
In the case of free-flowing gas you can do things with gas and still use 0 power, hence the distinction between negative and non-negative return values.
|
||||
*/
|
||||
|
||||
|
||||
/obj/machinery/atmospherics/var/last_flow_rate = 0
|
||||
/obj/machinery/portable_atmospherics/var/last_flow_rate = 0
|
||||
|
||||
|
||||
/obj/machinery/atmospherics/var/debug = 0
|
||||
|
||||
/obj/machinery/atmospherics/verb/toggle_debug()
|
||||
set name = "Toggle Debug Messages"
|
||||
set category = "Debug"
|
||||
set src in view()
|
||||
debug = !debug
|
||||
usr << "[src]: Debug messages toggled [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.
|
||||
//available_power - the maximum amount of power that may be used when moving gas. If null then the transfer is not limited by power.
|
||||
/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)
|
||||
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 * config.atmos_machine_heat) //1st law - energy is conserved
|
||||
|
||||
sink.merge(removed)
|
||||
|
||||
return power_draw
|
||||
|
||||
//Generalized gas scrubbing proc.
|
||||
//Selectively moves specified gasses one gas_mixture to another and returns the amount of power needed (assuming 1 second), or -1 if no gas was filtered.
|
||||
//filtering - A list of gasids to be scrubbed from source
|
||||
//total_transfer_moles - Limits the amount of moles to scrub. The actual amount of gas scrubbed may also be limited by available_power, if given.
|
||||
//available_power - the maximum amount of power that may be used when scrubbing gas. If null then the scrubbing is not limited by power.
|
||||
/proc/scrub_gas(var/obj/machinery/M, var/list/filtering, var/datum/gas_mixture/source, var/datum/gas_mixture/sink, var/total_transfer_moles = null, var/available_power = null)
|
||||
if (source.total_moles < MINUMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing
|
||||
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)
|
||||
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
|
||||
A.last_flow_rate = (total_transfer_moles/source.total_moles)*source.volume //group_multiplier gets divided out here
|
||||
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 * config.atmos_machine_heat) //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
|
||||
//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.
|
||||
//available_power - the maximum amount of power that may be used when filtering gas. If null then the filtering is not limited by power.
|
||||
/proc/filter_gas(var/obj/machinery/M, var/list/filtering, var/datum/gas_mixture/source, var/datum/gas_mixture/sink_filtered, var/datum/gas_mixture/sink_clean, var/total_transfer_moles = null, var/available_power = null)
|
||||
if (source.total_moles < MINUMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing
|
||||
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
|
||||
var/list/specific_power_gas = list() //the power required to remove one mole of pure gas, for each gas type
|
||||
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)
|
||||
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
|
||||
A.last_flow_rate = (total_transfer_moles/source.total_moles)*source.volume //group_multiplier gets divided out here
|
||||
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)
|
||||
removed.adjust_gas(g, -removed.gas[g], update=0)
|
||||
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 * config.atmos_machine_heat)
|
||||
if (unfiltered_power_used > 0)
|
||||
sink_clean.add_thermal_energy(unfiltered_power_used * config.atmos_machine_heat)
|
||||
|
||||
return filtered_power_used + unfiltered_power_used
|
||||
|
||||
//For omni devices. Instead filtering is an associative list mapping gasids to gas mixtures.
|
||||
//I don't like the copypasta, but I decided to keep both versions of gas filtering as filter_gas is slightly faster (doesn't create as many temporary lists, doesn't call update_values() as much)
|
||||
//filter_gas can be removed and replaced with this proc if need be.
|
||||
/proc/filter_gas_multi(var/obj/machinery/M, var/list/filtering, var/datum/gas_mixture/source, var/datum/gas_mixture/sink_clean, var/total_transfer_moles = null, var/available_power = null)
|
||||
if (source.total_moles < MINUMUM_MOLES_TO_FILTER) //if we cant transfer enough gas just stop to avoid further processing
|
||||
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
|
||||
var/list/specific_power_gas = list() //the power required to remove one mole of pure gas, for each gas type
|
||||
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
|
||||
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)
|
||||
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
|
||||
A.last_flow_rate = (total_transfer_moles/source.total_moles)*source.volume //group_multiplier gets divided out here
|
||||
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.
|
||||
sink_filtered.adjust_gas_temp(g, removed.gas[g], removed.temperature, update=1)
|
||||
removed.adjust_gas(g, -removed.gas[g], update=0)
|
||||
if (power_used)
|
||||
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] * config.atmos_machine_heat)
|
||||
if (unfiltered_power_used > 0)
|
||||
sink_clean.add_thermal_energy(unfiltered_power_used * config.atmos_machine_heat)
|
||||
|
||||
return power_draw
|
||||
|
||||
//Similar deal as the other atmos process procs.
|
||||
//mix_sources maps input gas mixtures to mix ratios. The mix ratios MUST add up to 1.
|
||||
/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
|
||||
var/total_input_moles = 0 //for flow rate calculation
|
||||
var/list/source_specific_power = list()
|
||||
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)
|
||||
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
|
||||
A.last_flow_rate = (total_transfer_moles/total_input_moles)*total_input_volume //group_multiplier gets divided out here
|
||||
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 * config.atmos_machine_heat) //conservation of energy
|
||||
total_power_draw += power_draw
|
||||
|
||||
sink.merge(removed)
|
||||
|
||||
return total_power_draw
|
||||
|
||||
/*
|
||||
Helper procs for various things.
|
||||
*/
|
||||
|
||||
//Calculates the amount of power needed to move one mole from source to sink.
|
||||
/proc/calculate_specific_power(datum/gas_mixture/source, datum/gas_mixture/sink)
|
||||
//Calculate the amount of energy required
|
||||
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.
|
||||
/proc/calculate_specific_power_gas(var/gasid, datum/gas_mixture/source, datum/gas_mixture/sink)
|
||||
//Calculate the amount of energy required
|
||||
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.
|
||||
//Calling update_use_power() or use_power() too often will result in lag since updating area power can be costly.
|
||||
//This proc implements an approximation scheme that will cause area power updates to be triggered less often.
|
||||
//By having atmos machinery use this proc it is easy to change the power usage approximation for all atmos machines
|
||||
/obj/machinery/proc/handle_power_draw(var/usage_amount)
|
||||
//This code errs on the side of using more power. Using this will mean that sometimes atmos machines use more power than they need, but won't get power for free.
|
||||
if (usage_amount > idle_power_usage)
|
||||
update_use_power(2)
|
||||
else
|
||||
if (use_power >= 2)
|
||||
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
|
||||
if (2 to INFINITY) return max(idle_power_usage, usage_amount)
|
||||
@@ -9,49 +9,96 @@ Pipes -> Pipelines
|
||||
Pipelines + Other Objects -> Pipe network
|
||||
|
||||
*/
|
||||
|
||||
obj/machinery/atmospherics
|
||||
/obj/machinery/atmospherics
|
||||
anchored = 1
|
||||
idle_power_usage = 0
|
||||
active_power_usage = 0
|
||||
power_channel = ENVIRON
|
||||
var/nodealert = 0
|
||||
|
||||
var/initialize_directions = 0
|
||||
var/pipe_color
|
||||
|
||||
var/global/datum/pipe_icon_manager/icon_manager
|
||||
|
||||
/obj/machinery/atmospherics/New()
|
||||
if(!icon_manager)
|
||||
icon_manager = new()
|
||||
|
||||
if(!pipe_color)
|
||||
pipe_color = color
|
||||
color = null
|
||||
|
||||
if(!pipe_color_check(pipe_color))
|
||||
pipe_color = null
|
||||
..()
|
||||
|
||||
obj/machinery/atmospherics/var/initialize_directions = 0
|
||||
obj/machinery/atmospherics/var/pipe_color
|
||||
/obj/machinery/atmospherics/attackby(atom/A, mob/user as mob)
|
||||
if(istype(A, /obj/item/device/pipe_painter))
|
||||
return
|
||||
..()
|
||||
|
||||
obj/machinery/atmospherics/process()
|
||||
/obj/machinery/atmospherics/proc/add_underlay(var/turf/T, var/obj/machinery/atmospherics/node, var/direction)
|
||||
if(node)
|
||||
if(T.intact && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
|
||||
underlays += icon_manager.get_atmos_icon("underlay_down", direction, color_cache_name(node))
|
||||
else
|
||||
underlays += icon_manager.get_atmos_icon("underlay_intact", direction, color_cache_name(node))
|
||||
else
|
||||
underlays += icon_manager.get_atmos_icon("underlay_exposed", direction, pipe_color)
|
||||
|
||||
/obj/machinery/atmospherics/proc/update_underlays()
|
||||
if(check_icon_cache())
|
||||
return 1
|
||||
else
|
||||
return 0
|
||||
|
||||
/obj/machinery/atmospherics/proc/check_icon_cache(var/safety = 0)
|
||||
if(!istype(icon_manager))
|
||||
if(!safety) //to prevent infinite loops
|
||||
icon_manager = new()
|
||||
check_icon_cache(1)
|
||||
return 0
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/atmospherics/proc/color_cache_name(var/obj/machinery/atmospherics/node)
|
||||
//Don't use this for standard pipes
|
||||
if(!istype(node))
|
||||
return null
|
||||
|
||||
return node.pipe_color
|
||||
|
||||
/obj/machinery/atmospherics/process()
|
||||
build_network()
|
||||
|
||||
obj/machinery/atmospherics/proc/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
|
||||
/obj/machinery/atmospherics/proc/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
|
||||
// Check to see if should be added to network. Add self if so and adjust variables appropriately.
|
||||
// Note don't forget to have neighbors look as well!
|
||||
|
||||
return null
|
||||
|
||||
obj/machinery/atmospherics/proc/build_network()
|
||||
/obj/machinery/atmospherics/proc/build_network()
|
||||
// Called to build a network from this node
|
||||
|
||||
return null
|
||||
|
||||
obj/machinery/atmospherics/proc/return_network(obj/machinery/atmospherics/reference)
|
||||
/obj/machinery/atmospherics/proc/return_network(obj/machinery/atmospherics/reference)
|
||||
// Returns pipe_network associated with connection to reference
|
||||
// Notes: should create network if necessary
|
||||
// Should never return null
|
||||
|
||||
return null
|
||||
|
||||
obj/machinery/atmospherics/proc/reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
|
||||
/obj/machinery/atmospherics/proc/reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
|
||||
// Used when two pipe_networks are combining
|
||||
|
||||
obj/machinery/atmospherics/proc/return_network_air(datum/network/reference)
|
||||
/obj/machinery/atmospherics/proc/return_network_air(datum/network/reference)
|
||||
// Return a list of gas_mixture(s) in the object
|
||||
// associated with reference pipe_network for use in rebuilding the networks gases list
|
||||
// Is permitted to return null
|
||||
|
||||
obj/machinery/atmospherics/proc/disconnect(obj/machinery/atmospherics/reference)
|
||||
/obj/machinery/atmospherics/proc/disconnect(obj/machinery/atmospherics/reference)
|
||||
|
||||
obj/machinery/atmospherics/update_icon()
|
||||
/obj/machinery/atmospherics/update_icon()
|
||||
return null
|
||||
@@ -76,6 +76,7 @@ obj/machinery/atmospherics/binary
|
||||
break
|
||||
|
||||
update_icon()
|
||||
update_underlays()
|
||||
|
||||
build_network()
|
||||
if(!network1 && node1)
|
||||
@@ -127,4 +128,7 @@ obj/machinery/atmospherics/binary
|
||||
del(network2)
|
||||
node2 = null
|
||||
|
||||
update_icon()
|
||||
update_underlays()
|
||||
|
||||
return null
|
||||
@@ -1,6 +1,18 @@
|
||||
#define DEFAULT_PRESSURE_DELTA 10000
|
||||
|
||||
#define EXTERNAL_PRESSURE_BOUND ONE_ATMOSPHERE
|
||||
#define INTERNAL_PRESSURE_BOUND 0
|
||||
#define PRESSURE_CHECKS 1
|
||||
|
||||
#define PRESSURE_CHECK_EXTERNAL 1
|
||||
#define PRESSURE_CHECK_INPUT 2
|
||||
#define PRESSURE_CHECK_OUTPUT 4
|
||||
|
||||
#undefine
|
||||
|
||||
/obj/machinery/atmospherics/binary/dp_vent_pump
|
||||
icon = 'icons/obj/atmospherics/dp_vent_pump.dmi'
|
||||
icon_state = "off"
|
||||
icon = 'icons/atmos/vent_pump.dmi'
|
||||
icon_state = "map_dp_vent"
|
||||
|
||||
//node2 is output port
|
||||
//node1 is input port
|
||||
@@ -10,190 +22,246 @@
|
||||
|
||||
level = 1
|
||||
|
||||
high_volume
|
||||
name = "Large Dual Port Air Vent"
|
||||
|
||||
New()
|
||||
..()
|
||||
|
||||
air1.volume = 1000
|
||||
air2.volume = 1000
|
||||
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 pump is, in Watts. 7500 W ~ 10 HP
|
||||
var/last_power_draw = 0
|
||||
|
||||
var/on = 0
|
||||
var/pump_direction = 1 //0 = siphoning, 1 = releasing
|
||||
|
||||
var/external_pressure_bound = ONE_ATMOSPHERE
|
||||
var/input_pressure_min = 0
|
||||
var/output_pressure_max = 0
|
||||
|
||||
var/pressure_checks = 1
|
||||
//1: Do not pass external_pressure_bound
|
||||
//2: Do not pass input_pressure_min
|
||||
//4: Do not pass output_pressure_max
|
||||
|
||||
update_icon()
|
||||
if(on)
|
||||
if(pump_direction)
|
||||
icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]out"
|
||||
else
|
||||
icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]in"
|
||||
else
|
||||
icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]off"
|
||||
on = 0
|
||||
|
||||
return
|
||||
|
||||
hide(var/i) //to make the little pipe section invisible, the icon changes.
|
||||
if(on)
|
||||
if(pump_direction)
|
||||
icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]out"
|
||||
else
|
||||
icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]in"
|
||||
else
|
||||
icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]off"
|
||||
on = 0
|
||||
return
|
||||
|
||||
process()
|
||||
..()
|
||||
|
||||
if(!on)
|
||||
return 0
|
||||
|
||||
var/datum/gas_mixture/environment = loc.return_air()
|
||||
var/environment_pressure = environment.return_pressure()
|
||||
|
||||
if(pump_direction) //input -> external
|
||||
var/pressure_delta = 10000
|
||||
|
||||
if(pressure_checks&1)
|
||||
pressure_delta = min(pressure_delta, (external_pressure_bound - environment_pressure))
|
||||
if(pressure_checks&2)
|
||||
pressure_delta = min(pressure_delta, (air1.return_pressure() - input_pressure_min))
|
||||
|
||||
if(pressure_delta > 0)
|
||||
if(air1.temperature > 0)
|
||||
var/transfer_moles = pressure_delta*environment.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
var/datum/gas_mixture/removed = air1.remove(transfer_moles)
|
||||
|
||||
loc.assume_air(removed)
|
||||
|
||||
if(network1)
|
||||
network1.update = 1
|
||||
|
||||
else //external -> output
|
||||
var/pressure_delta = 10000
|
||||
|
||||
if(pressure_checks&1)
|
||||
pressure_delta = min(pressure_delta, (environment_pressure - external_pressure_bound))
|
||||
if(pressure_checks&4)
|
||||
pressure_delta = min(pressure_delta, (output_pressure_max - air2.return_pressure()))
|
||||
|
||||
if(pressure_delta > 0)
|
||||
if(environment.temperature > 0)
|
||||
var/transfer_moles = pressure_delta*air2.volume/(environment.temperature * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
var/datum/gas_mixture/removed = loc.remove_air(transfer_moles)
|
||||
|
||||
air2.merge(removed)
|
||||
|
||||
if(network2)
|
||||
network2.update = 1
|
||||
|
||||
return 1
|
||||
|
||||
//Radio remote control
|
||||
|
||||
proc
|
||||
set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
if(frequency)
|
||||
radio_connection = radio_controller.add_object(src, frequency, filter = RADIO_ATMOSIA)
|
||||
|
||||
broadcast_status()
|
||||
if(!radio_connection)
|
||||
return 0
|
||||
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 1 //radio signal
|
||||
signal.source = src
|
||||
|
||||
signal.data = list(
|
||||
"tag" = id,
|
||||
"device" = "ADVP",
|
||||
"power" = on,
|
||||
"direction" = pump_direction?("release"):("siphon"),
|
||||
"checks" = pressure_checks,
|
||||
"input" = input_pressure_min,
|
||||
"output" = output_pressure_max,
|
||||
"external" = external_pressure_bound,
|
||||
"sigtype" = "status"
|
||||
)
|
||||
radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
|
||||
|
||||
return 1
|
||||
var/external_pressure_bound = EXTERNAL_PRESSURE_BOUND
|
||||
var/input_pressure_min = INTERNAL_PRESSURE_BOUND
|
||||
var/output_pressure_max = DEFAULT_PRESSURE_DELTA
|
||||
|
||||
var/frequency = 0
|
||||
var/id = null
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
initialize()
|
||||
..()
|
||||
if(frequency)
|
||||
set_frequency(frequency)
|
||||
var/pressure_checks = PRESSURE_CHECK_EXTERNAL
|
||||
//1: Do not pass external_pressure_bound
|
||||
//2: Do not pass input_pressure_min
|
||||
//4: Do not pass output_pressure_max
|
||||
|
||||
receive_signal(datum/signal/signal)
|
||||
/obj/machinery/atmospherics/binary/dp_vent_pump/New()
|
||||
..()
|
||||
air1.volume = ATMOS_DEFAULT_VOLUME_PUMP
|
||||
air2.volume = ATMOS_DEFAULT_VOLUME_PUMP
|
||||
icon = null
|
||||
|
||||
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
|
||||
return 0
|
||||
if("power" in signal.data)
|
||||
on = text2num(signal.data["power"])
|
||||
/obj/machinery/atmospherics/binary/dp_vent_pump/high_volume
|
||||
name = "Large Dual Port Air Vent"
|
||||
|
||||
if("power_toggle" in signal.data)
|
||||
on = !on
|
||||
/obj/machinery/atmospherics/binary/dp_vent_pump/high_volume/New()
|
||||
..()
|
||||
air1.volume = ATMOS_DEFAULT_VOLUME_PUMP + 800
|
||||
air2.volume = ATMOS_DEFAULT_VOLUME_PUMP + 800
|
||||
|
||||
if("direction" in signal.data)
|
||||
pump_direction = text2num(signal.data["direction"])
|
||||
/obj/machinery/atmospherics/binary/dp_vent_pump/update_icon(var/safety = 0)
|
||||
if(!check_icon_cache())
|
||||
return
|
||||
|
||||
if("checks" in signal.data)
|
||||
pressure_checks = text2num(signal.data["checks"])
|
||||
overlays.Cut()
|
||||
|
||||
var/vent_icon = "vent"
|
||||
|
||||
if("purge" in signal.data)
|
||||
pressure_checks &= ~1
|
||||
pump_direction = 0
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T))
|
||||
return
|
||||
|
||||
if("stabalize" in signal.data)
|
||||
pressure_checks |= 1
|
||||
pump_direction = 1
|
||||
if(T.intact && node1 && node2 && node1.level == 1 && node2.level == 1 && istype(node1, /obj/machinery/atmospherics/pipe) && istype(node2, /obj/machinery/atmospherics/pipe))
|
||||
vent_icon += "h"
|
||||
|
||||
if(!powered())
|
||||
vent_icon += "off"
|
||||
else
|
||||
vent_icon += "[on ? "[pump_direction ? "out" : "in"]" : "off"]"
|
||||
|
||||
if("set_input_pressure" in signal.data)
|
||||
input_pressure_min = between(
|
||||
0,
|
||||
text2num(signal.data["set_input_pressure"]),
|
||||
ONE_ATMOSPHERE*50
|
||||
)
|
||||
overlays += icon_manager.get_atmos_icon("device", , , vent_icon)
|
||||
|
||||
if("set_output_pressure" in signal.data)
|
||||
output_pressure_max = between(
|
||||
0,
|
||||
text2num(signal.data["set_output_pressure"]),
|
||||
ONE_ATMOSPHERE*50
|
||||
)
|
||||
/obj/machinery/atmospherics/binary/dp_vent_pump/update_underlays()
|
||||
if(..())
|
||||
underlays.Cut()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T))
|
||||
return
|
||||
if(T.intact && node1 && node2 && node1.level == 1 && node2.level == 1 && istype(node1, /obj/machinery/atmospherics/pipe) && istype(node2, /obj/machinery/atmospherics/pipe))
|
||||
return
|
||||
else
|
||||
add_underlay(T, node1, turn(dir, -180))
|
||||
add_underlay(T, node2, dir)
|
||||
|
||||
if("set_external_pressure" in signal.data)
|
||||
external_pressure_bound = between(
|
||||
0,
|
||||
text2num(signal.data["set_external_pressure"]),
|
||||
ONE_ATMOSPHERE*50
|
||||
)
|
||||
/obj/machinery/atmospherics/binary/dp_vent_pump/hide(var/i)
|
||||
update_icon()
|
||||
update_underlays()
|
||||
|
||||
if("status" in signal.data)
|
||||
spawn(2)
|
||||
broadcast_status()
|
||||
return //do not update_icon
|
||||
//if(signal.data["tag"])
|
||||
/obj/machinery/atmospherics/binary/dp_vent_pump/process()
|
||||
..()
|
||||
|
||||
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_power_draw = 0
|
||||
last_flow_rate = 0
|
||||
return 0
|
||||
|
||||
var/datum/gas_mixture/environment = loc.return_air()
|
||||
|
||||
var/power_draw = -1
|
||||
|
||||
//Figure out the target pressure difference
|
||||
var/pressure_delta = get_pressure_delta(environment)
|
||||
|
||||
if(pressure_delta > 0.5)
|
||||
if(pump_direction) //internal -> external
|
||||
if (node1 && (environment.temperature || air1.temperature))
|
||||
var/output_volume = environment.volume * environment.group_multiplier
|
||||
var/air_temperature = environment.temperature? environment.temperature : air1.temperature
|
||||
var/transfer_moles = pressure_delta*output_volume/(air_temperature * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
power_draw = pump_gas(src, air1, environment, transfer_moles, active_power_usage)
|
||||
|
||||
if(power_draw >= 0 && network1)
|
||||
network1.update = 1
|
||||
else //external -> internal
|
||||
if (node2 && (environment.temperature || air2.temperature))
|
||||
var/output_volume = air2.volume + (network2? network2.volume : 0)
|
||||
var/air_temperature = air2.temperature? air2.temperature : environment.temperature
|
||||
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*air2.volume/environment.volume) //group_multiplier gets divided out here
|
||||
|
||||
power_draw = pump_gas(src, environment, air2, transfer_moles, active_power_usage)
|
||||
|
||||
if(power_draw >= 0 && network2)
|
||||
network2.update = 1
|
||||
|
||||
if (power_draw < 0)
|
||||
last_power_draw = 0
|
||||
last_flow_rate = 0
|
||||
//update_use_power(0)
|
||||
use_power = 0 //don't force update - easier on CPU
|
||||
else
|
||||
last_power_draw = handle_power_draw(power_draw)
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/atmospherics/binary/dp_vent_pump/proc/get_pressure_delta(datum/gas_mixture/environment)
|
||||
var/pressure_delta = DEFAULT_PRESSURE_DELTA
|
||||
var/environment_pressure = environment.return_pressure()
|
||||
|
||||
if(pump_direction) //internal -> external
|
||||
if(pressure_checks & PRESSURE_CHECK_EXTERNAL)
|
||||
pressure_delta = min(pressure_delta, external_pressure_bound - environment_pressure) //increasing the pressure here
|
||||
if(pressure_checks & PRESSURE_CHECK_INPUT)
|
||||
pressure_delta = min(pressure_delta, air1.return_pressure() - input_pressure_min) //decreasing the pressure here
|
||||
else //external -> internal
|
||||
if(pressure_checks & PRESSURE_CHECK_EXTERNAL)
|
||||
pressure_delta = min(pressure_delta, environment_pressure - external_pressure_bound) //decreasing the pressure here
|
||||
if(pressure_checks & PRESSURE_CHECK_OUTPUT)
|
||||
pressure_delta = min(pressure_delta, output_pressure_max - air2.return_pressure()) //increasing the pressure here
|
||||
|
||||
return pressure_delta
|
||||
|
||||
|
||||
//Radio remote control
|
||||
|
||||
/obj/machinery/atmospherics/binary/dp_vent_pump/proc/set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
if(frequency)
|
||||
radio_connection = radio_controller.add_object(src, frequency, filter = RADIO_ATMOSIA)
|
||||
|
||||
/obj/machinery/atmospherics/binary/dp_vent_pump/proc/broadcast_status()
|
||||
if(!radio_connection)
|
||||
return 0
|
||||
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 1 //radio signal
|
||||
signal.source = src
|
||||
|
||||
signal.data = list(
|
||||
"tag" = id,
|
||||
"device" = "ADVP",
|
||||
"power" = on,
|
||||
"direction" = pump_direction?("release"):("siphon"),
|
||||
"checks" = pressure_checks,
|
||||
"input" = input_pressure_min,
|
||||
"output" = output_pressure_max,
|
||||
"external" = external_pressure_bound,
|
||||
"sigtype" = "status"
|
||||
)
|
||||
radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/atmospherics/binary/dp_vent_pump/initialize()
|
||||
..()
|
||||
if(frequency)
|
||||
set_frequency(frequency)
|
||||
|
||||
/obj/machinery/atmospherics/binary/dp_vent_pump/examine()
|
||||
set src in oview(1)
|
||||
..()
|
||||
|
||||
if (get_dist(usr, src) <= 1)
|
||||
usr << "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W"
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_pump/power_change()
|
||||
var/old_stat = stat
|
||||
..()
|
||||
if(old_stat != stat)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/binary/dp_vent_pump/receive_signal(datum/signal/signal)
|
||||
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
|
||||
return 0
|
||||
if(signal.data["power"])
|
||||
on = text2num(signal.data["power"])
|
||||
|
||||
if(signal.data["power_toggle"])
|
||||
on = !on
|
||||
|
||||
if(signal.data["direction"])
|
||||
pump_direction = text2num(signal.data["direction"])
|
||||
|
||||
if(signal.data["checks"])
|
||||
pressure_checks = text2num(signal.data["checks"])
|
||||
|
||||
if(signal.data["purge"])
|
||||
pressure_checks &= ~1
|
||||
pump_direction = 0
|
||||
|
||||
if(signal.data["stabalize"])
|
||||
pressure_checks |= 1
|
||||
pump_direction = 1
|
||||
|
||||
if(signal.data["set_input_pressure"])
|
||||
input_pressure_min = between(
|
||||
0,
|
||||
text2num(signal.data["set_input_pressure"]),
|
||||
ONE_ATMOSPHERE*50
|
||||
)
|
||||
|
||||
if(signal.data["set_output_pressure"])
|
||||
output_pressure_max = between(
|
||||
0,
|
||||
text2num(signal.data["set_output_pressure"]),
|
||||
ONE_ATMOSPHERE*50
|
||||
)
|
||||
|
||||
if(signal.data["set_external_pressure"])
|
||||
external_pressure_bound = between(
|
||||
0,
|
||||
text2num(signal.data["set_external_pressure"]),
|
||||
ONE_ATMOSPHERE*50
|
||||
)
|
||||
|
||||
if(signal.data["status"])
|
||||
spawn(2)
|
||||
broadcast_status()
|
||||
update_icon()
|
||||
return //do not update_icon
|
||||
|
||||
spawn(2)
|
||||
broadcast_status()
|
||||
update_icon()
|
||||
@@ -1,188 +1,264 @@
|
||||
obj/machinery/atmospherics/binary/passive_gate
|
||||
//Tries to achieve target pressure at output (like a normal pump) except
|
||||
// Uses no power but can not transfer gases from a low pressure area to a high pressure area
|
||||
icon = 'icons/obj/atmospherics/passive_gate.dmi'
|
||||
icon_state = "intact_off"
|
||||
#define REGULATE_NONE 0
|
||||
#define REGULATE_INPUT 1 //shuts off when input side is below the target pressure
|
||||
#define REGULATE_OUTPUT 2 //shuts off when output side is above the target pressure
|
||||
|
||||
name = "Passive gate"
|
||||
desc = "A one-way air valve that does not require power"
|
||||
#undefine
|
||||
|
||||
var/on = 0
|
||||
/obj/machinery/atmospherics/binary/passive_gate
|
||||
icon = 'icons/atmos/passive_gate.dmi'
|
||||
icon_state = "map"
|
||||
level = 1
|
||||
|
||||
name = "pressure regulator"
|
||||
desc = "A one-way air valve that can be used to regulate input or output pressure, and flow rate. Does not require power."
|
||||
|
||||
use_power = 0
|
||||
|
||||
var/on = 0 //doesn't actually use power. this is just whether the valve is open or not
|
||||
var/target_pressure = ONE_ATMOSPHERE
|
||||
|
||||
var/max_pressure_setting = 15000 //kPa
|
||||
var/set_flow_rate = ATMOS_DEFAULT_VOLUME_PUMP * 2.5
|
||||
var/regulate_mode = REGULATE_OUTPUT
|
||||
|
||||
var/flowing = 0 //for icons - becomes zero if the valve closes itself due to regulation mode
|
||||
|
||||
var/frequency = 0
|
||||
var/id = null
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
update_icon()
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "intact_off"
|
||||
else if(node1 && node2)
|
||||
icon_state = "intact_[on?("on"):("off")]"
|
||||
else
|
||||
if(node1)
|
||||
icon_state = "exposed_1_off"
|
||||
else if(node2)
|
||||
icon_state = "exposed_2_off"
|
||||
else
|
||||
icon_state = "exposed_3_off"
|
||||
return
|
||||
/obj/machinery/atmospherics/binary/passive_gate/New()
|
||||
..()
|
||||
air1.volume = ATMOS_DEFAULT_VOLUME_PUMP * 2.5
|
||||
air2.volume = ATMOS_DEFAULT_VOLUME_PUMP * 2.5
|
||||
|
||||
process()
|
||||
..()
|
||||
if(!on)
|
||||
return 0
|
||||
/obj/machinery/atmospherics/binary/passive_gate/update_icon()
|
||||
icon_state = (on && flowing)? "on" : "off"
|
||||
|
||||
var/output_starting_pressure = air2.return_pressure()
|
||||
var/input_starting_pressure = air1.return_pressure()
|
||||
/obj/machinery/atmospherics/binary/passive_gate/update_underlays()
|
||||
if(..())
|
||||
underlays.Cut()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T))
|
||||
return
|
||||
add_underlay(T, node1, turn(dir, 180))
|
||||
add_underlay(T, node2, dir)
|
||||
|
||||
if(output_starting_pressure >= min(target_pressure,input_starting_pressure-10))
|
||||
//No need to pump gas if target is already reached or input pressure is too low
|
||||
//Need at least 10 KPa difference to overcome friction in the mechanism
|
||||
return 1
|
||||
/obj/machinery/atmospherics/binary/passive_gate/hide(var/i)
|
||||
update_underlays()
|
||||
|
||||
//Calculate necessary moles to transfer using PV = nRT
|
||||
if((air1.total_moles() > 0) && (air1.temperature>0))
|
||||
var/pressure_delta = min(target_pressure - output_starting_pressure, (input_starting_pressure - output_starting_pressure)/2)
|
||||
//Can not have a pressure delta that would cause output_pressure > input_pressure
|
||||
/obj/machinery/atmospherics/binary/passive_gate/process()
|
||||
..()
|
||||
if(!on)
|
||||
last_flow_rate = 0
|
||||
return 0
|
||||
|
||||
var/transfer_moles = pressure_delta*air2.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
//Actually transfer the gas
|
||||
var/datum/gas_mixture/removed = air1.remove(transfer_moles)
|
||||
air2.merge(removed)
|
||||
var/output_starting_pressure = air2.return_pressure()
|
||||
var/input_starting_pressure = air1.return_pressure()
|
||||
|
||||
var/pressure_delta
|
||||
switch (regulate_mode)
|
||||
if (REGULATE_INPUT)
|
||||
pressure_delta = input_starting_pressure - target_pressure
|
||||
if (REGULATE_OUTPUT)
|
||||
pressure_delta = target_pressure - output_starting_pressure
|
||||
|
||||
var/flowing_old = flowing
|
||||
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
|
||||
var/transfer_moles = (set_flow_rate/air1.volume)*air1.total_moles
|
||||
|
||||
//Figure out how much gas to transfer to meet the target pressure.
|
||||
switch (regulate_mode)
|
||||
if (REGULATE_INPUT)
|
||||
var/air_temperature = (air1.temperature > 0)? air1.temperature : air2.temperature
|
||||
var/input_volume = air1.volume + (network1? network1.volume : 0)
|
||||
transfer_moles = min(transfer_moles, pressure_delta*input_volume/(air_temperature * R_IDEAL_GAS_EQUATION))
|
||||
if (REGULATE_OUTPUT)
|
||||
var/air_temperature = (air2.temperature > 0)? air2.temperature : air1.temperature
|
||||
var/output_volume = air2.volume + (network2? network2.volume : 0)
|
||||
|
||||
transfer_moles = min(transfer_moles, pressure_delta*output_volume/(air_temperature * R_IDEAL_GAS_EQUATION))
|
||||
|
||||
//pump_gas() will return a negative number if no flow occurred
|
||||
var/flow = pump_gas(src, air1, air2, transfer_moles, available_power=0) //available_power=0 means we only move gas if it would flow naturally
|
||||
|
||||
if (flow >= 0)
|
||||
if(network1)
|
||||
network1.update = 1
|
||||
|
||||
if(network2)
|
||||
network2.update = 1
|
||||
else
|
||||
flowing = 0
|
||||
last_flow_rate = 0
|
||||
|
||||
if (flowing != flowing_old)
|
||||
update_icon()
|
||||
|
||||
|
||||
//Radio remote control
|
||||
//Radio remote control
|
||||
|
||||
proc
|
||||
set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
if(frequency)
|
||||
radio_connection = radio_controller.add_object(src, frequency, filter = RADIO_ATMOSIA)
|
||||
/obj/machinery/atmospherics/binary/passive_gate/proc/set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
if(frequency)
|
||||
radio_connection = radio_controller.add_object(src, frequency, filter = RADIO_ATMOSIA)
|
||||
|
||||
broadcast_status()
|
||||
if(!radio_connection)
|
||||
return 0
|
||||
/obj/machinery/atmospherics/binary/passive_gate/proc/broadcast_status()
|
||||
if(!radio_connection)
|
||||
return 0
|
||||
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 1 //radio signal
|
||||
signal.source = src
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 1 //radio signal
|
||||
signal.source = src
|
||||
|
||||
signal.data = list(
|
||||
"tag" = id,
|
||||
"device" = "AGP",
|
||||
"power" = on,
|
||||
"target_output" = target_pressure,
|
||||
"sigtype" = "status"
|
||||
)
|
||||
signal.data = list(
|
||||
"tag" = id,
|
||||
"device" = "AGP",
|
||||
"power" = on,
|
||||
"target_output" = target_pressure,
|
||||
"regulate_mode" = regulate_mode,
|
||||
"set_flow_rate" = set_flow_rate,
|
||||
"sigtype" = "status"
|
||||
)
|
||||
|
||||
radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
|
||||
radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
|
||||
|
||||
return 1
|
||||
return 1
|
||||
|
||||
interact(mob/user as mob)
|
||||
var/dat = {"<b>Power: </b><a href='?src=\ref[src];power=1'>[on?"On":"Off"]</a><br>
|
||||
<b>Desirable output pressure: </b>
|
||||
[round(target_pressure,0.1)]kPa | <a href='?src=\ref[src];set_press=1'>Change</a>
|
||||
"}
|
||||
/obj/machinery/atmospherics/binary/passive_gate/initialize()
|
||||
..()
|
||||
if(frequency)
|
||||
set_frequency(frequency)
|
||||
|
||||
user << browse("<HEAD><TITLE>[src.name] control</TITLE></HEAD><TT>[dat]</TT>", "window=atmo_pump")
|
||||
onclose(user, "atmo_pump")
|
||||
/obj/machinery/atmospherics/binary/passive_gate/receive_signal(datum/signal/signal)
|
||||
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
|
||||
return 0
|
||||
|
||||
initialize()
|
||||
..()
|
||||
if(frequency)
|
||||
set_frequency(frequency)
|
||||
if("power" in signal.data)
|
||||
on = text2num(signal.data["power"])
|
||||
|
||||
receive_signal(datum/signal/signal)
|
||||
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
|
||||
return 0
|
||||
if("power_toggle" in signal.data)
|
||||
on = !on
|
||||
|
||||
if("power" in signal.data)
|
||||
on = text2num(signal.data["power"])
|
||||
if("set_target_pressure" in signal.data)
|
||||
target_pressure = between(
|
||||
0,
|
||||
text2num(signal.data["set_target_pressure"]),
|
||||
max_pressure_setting
|
||||
)
|
||||
|
||||
if("power_toggle" in signal.data)
|
||||
on = !on
|
||||
if("set_regulate_mode" in signal.data)
|
||||
regulate_mode = text2num(signal.data["set_regulate_mode"])
|
||||
|
||||
if("set_output_pressure" in signal.data)
|
||||
target_pressure = between(
|
||||
0,
|
||||
text2num(signal.data["set_output_pressure"]),
|
||||
ONE_ATMOSPHERE*50
|
||||
)
|
||||
|
||||
if("status" in signal.data)
|
||||
spawn(2)
|
||||
broadcast_status()
|
||||
return //do not update_icon
|
||||
if("set_flow_rate" in signal.data)
|
||||
regulate_mode = text2num(signal.data["set_flow_rate"])
|
||||
|
||||
if("status" in signal.data)
|
||||
spawn(2)
|
||||
broadcast_status()
|
||||
update_icon()
|
||||
return //do not update_icon
|
||||
|
||||
spawn(2)
|
||||
broadcast_status()
|
||||
update_icon()
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/binary/passive_gate/attack_hand(user as mob)
|
||||
if(..())
|
||||
return
|
||||
src.add_fingerprint(usr)
|
||||
if(!src.allowed(user))
|
||||
user << "\red Access denied."
|
||||
return
|
||||
usr.set_machine(src)
|
||||
ui_interact(user)
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/binary/passive_gate/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
|
||||
// this is the data which will be sent to the ui
|
||||
var/data[0]
|
||||
|
||||
data = list(
|
||||
"on" = on,
|
||||
"pressure_set" = round(target_pressure*100), //Nano UI can't handle rounded non-integers, apparently.
|
||||
"max_pressure" = max_pressure_setting,
|
||||
"input_pressure" = round(air1.return_pressure()*100),
|
||||
"output_pressure" = round(air2.return_pressure()*100),
|
||||
"regulate_mode" = regulate_mode,
|
||||
"set_flow_rate" = round(set_flow_rate*10),
|
||||
"last_flow_rate" = round(last_flow_rate*10),
|
||||
)
|
||||
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "pressure_regulator.tmpl", name, 470, 370)
|
||||
ui.set_initial_data(data) // when the ui is first opened this is the data it will use
|
||||
ui.open() // open the new ui window
|
||||
ui.set_auto_update(1) // auto update every Master Controller tick
|
||||
|
||||
|
||||
attack_hand(user as mob)
|
||||
if(..())
|
||||
return
|
||||
src.add_fingerprint(usr)
|
||||
if(!src.allowed(user))
|
||||
user << "\red Access denied."
|
||||
return
|
||||
usr.set_machine(src)
|
||||
interact(user)
|
||||
return
|
||||
|
||||
Topic(href,href_list)
|
||||
if(..()) return
|
||||
if(href_list["power"])
|
||||
on = !on
|
||||
if(href_list["set_press"])
|
||||
var/new_pressure = input(usr,"Enter new output pressure (0-4500kPa)","Pressure control",src.target_pressure) as num
|
||||
src.target_pressure = max(0, min(4500, new_pressure))
|
||||
usr.set_machine(src)
|
||||
src.update_icon()
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
|
||||
|
||||
attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if (!istype(W, /obj/item/weapon/wrench))
|
||||
return ..()
|
||||
if (on)
|
||||
user << "\red You cannot unwrench this [src], turn it off first."
|
||||
return 1
|
||||
var/turf/T = src.loc
|
||||
if (level==1 && isturf(T) && T.intact)
|
||||
user << "\red You must remove the plating first."
|
||||
return 1
|
||||
var/datum/gas_mixture/int_air = return_air()
|
||||
var/datum/gas_mixture/env_air = loc.return_air()
|
||||
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
|
||||
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
|
||||
add_fingerprint(user)
|
||||
return 1
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
user << "\blue You begin to unfasten \the [src]..."
|
||||
if (do_after(user, 40))
|
||||
user.visible_message( \
|
||||
"[user] unfastens \the [src].", \
|
||||
"\blue You have unfastened \the [src].", \
|
||||
"You hear ratchet.")
|
||||
new /obj/item/pipe(loc, make_from=src)
|
||||
del(src)
|
||||
/obj/machinery/atmospherics/binary/passive_gate/Topic(href,href_list)
|
||||
if(..()) return
|
||||
|
||||
if(href_list["toggle_valve"])
|
||||
on = !on
|
||||
|
||||
if(href_list["regulate_mode"])
|
||||
switch(href_list["regulate_mode"])
|
||||
if ("off") regulate_mode = REGULATE_NONE
|
||||
if ("input") regulate_mode = REGULATE_INPUT
|
||||
if ("output") regulate_mode = REGULATE_OUTPUT
|
||||
|
||||
switch(href_list["set_press"])
|
||||
if ("min")
|
||||
target_pressure = 0
|
||||
if ("max")
|
||||
target_pressure = max_pressure_setting
|
||||
if ("set")
|
||||
var/new_pressure = input(usr,"Enter new output pressure (0-[max_pressure_setting]kPa)","Pressure Control",src.target_pressure) as num
|
||||
src.target_pressure = between(0, new_pressure, max_pressure_setting)
|
||||
|
||||
switch(href_list["set_flow_rate"])
|
||||
if ("min")
|
||||
set_flow_rate = 0
|
||||
if ("max")
|
||||
set_flow_rate = air1.volume
|
||||
if ("set")
|
||||
var/new_flow_rate = input(usr,"Enter new flow rate limit (0-[air1.volume]kPa)","Flow Rate Control",src.set_flow_rate) as num
|
||||
src.set_flow_rate = between(0, new_flow_rate, air1.volume)
|
||||
|
||||
usr.set_machine(src) //Is this even needed with NanoUI?
|
||||
src.update_icon()
|
||||
src.add_fingerprint(usr)
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/binary/passive_gate/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if (!istype(W, /obj/item/weapon/wrench))
|
||||
return ..()
|
||||
if (on)
|
||||
user << "\red You cannot unwrench this [src], turn it off first."
|
||||
return 1
|
||||
var/datum/gas_mixture/int_air = return_air()
|
||||
var/datum/gas_mixture/env_air = loc.return_air()
|
||||
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
|
||||
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
|
||||
add_fingerprint(user)
|
||||
return 1
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
user << "\blue You begin to unfasten \the [src]..."
|
||||
if (do_after(user, 40))
|
||||
user.visible_message( \
|
||||
"[user] unfastens \the [src].", \
|
||||
"\blue You have unfastened \the [src].", \
|
||||
"You hear ratchet.")
|
||||
new /obj/item/pipe(loc, make_from=src)
|
||||
del(src)
|
||||
|
||||
@@ -12,194 +12,238 @@ Thus, the two variables affect pump operation are set in New():
|
||||
but overall network volume is also increased as this increases...
|
||||
*/
|
||||
|
||||
obj/machinery/atmospherics/binary/pump
|
||||
icon = 'icons/obj/atmospherics/pump.dmi'
|
||||
icon_state = "intact_off"
|
||||
/obj/machinery/atmospherics/binary/pump
|
||||
icon = 'icons/atmos/pump.dmi'
|
||||
icon_state = "map_off"
|
||||
level = 1
|
||||
|
||||
name = "Gas pump"
|
||||
name = "gas pump"
|
||||
desc = "A pump"
|
||||
|
||||
var/on = 0
|
||||
var/target_pressure = ONE_ATMOSPHERE
|
||||
|
||||
//var/max_volume_transfer = 10000
|
||||
|
||||
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 pump is, in Watts. 7500 W ~ 10 HP
|
||||
|
||||
var/last_power_draw = 0 //for UI
|
||||
var/max_pressure_setting = 15000 //kPa
|
||||
|
||||
var/frequency = 0
|
||||
var/id = null
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
highcap
|
||||
name = "High capacity gas pump"
|
||||
desc = "A high capacity pump"
|
||||
/obj/machinery/atmospherics/binary/pump/New()
|
||||
..()
|
||||
air1.volume = ATMOS_DEFAULT_VOLUME_PUMP
|
||||
air2.volume = ATMOS_DEFAULT_VOLUME_PUMP
|
||||
|
||||
target_pressure = 15000000
|
||||
/obj/machinery/atmospherics/binary/pump/on
|
||||
icon_state = "map_on"
|
||||
on = 1
|
||||
|
||||
on
|
||||
on = 1
|
||||
icon_state = "intact_on"
|
||||
|
||||
update_icon()
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "intact_off"
|
||||
else if(node1 && node2)
|
||||
icon_state = "intact_[on?("on"):("off")]"
|
||||
else
|
||||
if(node1)
|
||||
icon_state = "exposed_1_off"
|
||||
else if(node2)
|
||||
icon_state = "exposed_2_off"
|
||||
else
|
||||
icon_state = "exposed_3_off"
|
||||
/obj/machinery/atmospherics/binary/pump/update_icon()
|
||||
if(!powered())
|
||||
icon_state = "off"
|
||||
else
|
||||
icon_state = "[on ? "on" : "off"]"
|
||||
|
||||
/obj/machinery/atmospherics/binary/pump/update_underlays()
|
||||
if(..())
|
||||
underlays.Cut()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T))
|
||||
return
|
||||
add_underlay(T, node1, turn(dir, -180))
|
||||
add_underlay(T, node2, dir)
|
||||
|
||||
/obj/machinery/atmospherics/binary/pump/hide(var/i)
|
||||
update_underlays()
|
||||
|
||||
/obj/machinery/atmospherics/binary/pump/process()
|
||||
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_power_draw = 0
|
||||
last_flow_rate = 0
|
||||
return
|
||||
|
||||
process()
|
||||
// ..()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
if(!on)
|
||||
return 0
|
||||
var/power_draw = -1
|
||||
var/pressure_delta = target_pressure - air2.return_pressure()
|
||||
|
||||
var/output_starting_pressure = air2.return_pressure()
|
||||
if(pressure_delta > 0.01 && air1.temperature > 0)
|
||||
//Figure out how much gas to transfer to meet the target pressure.
|
||||
var/air_temperature = (air2.temperature > 0)? air2.temperature : air1.temperature
|
||||
var/output_volume = air2.volume + (network2? network2.volume : 0)
|
||||
|
||||
//get the number of moles that would have to be transfered to bring sink to the target pressure
|
||||
var/transfer_moles = pressure_delta*output_volume/(air_temperature * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
power_draw = pump_gas(src, air1, air2, transfer_moles, active_power_usage)
|
||||
|
||||
if (power_draw < 0)
|
||||
//update_use_power(0)
|
||||
use_power = 0 //don't force update - easier on CPU
|
||||
last_power_draw = 0
|
||||
last_flow_rate = 0
|
||||
else
|
||||
last_power_draw = handle_power_draw(power_draw)
|
||||
|
||||
if(network1)
|
||||
network1.update = 1
|
||||
|
||||
if( (target_pressure - output_starting_pressure) < 0.01)
|
||||
//No need to pump gas if target is already reached!
|
||||
return 1
|
||||
if(network2)
|
||||
network2.update = 1
|
||||
|
||||
//Calculate necessary moles to transfer using PV=nRT
|
||||
if((air1.total_moles() > 0) && (air1.temperature>0))
|
||||
var/pressure_delta = target_pressure - output_starting_pressure
|
||||
var/transfer_moles = pressure_delta*air2.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
|
||||
return 1
|
||||
|
||||
//Actually transfer the gas
|
||||
var/datum/gas_mixture/removed = air1.remove(transfer_moles)
|
||||
air2.merge(removed)
|
||||
//Radio remote control
|
||||
|
||||
if(network1)
|
||||
network1.update = 1
|
||||
/obj/machinery/atmospherics/binary/pump/proc/set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
if(frequency)
|
||||
radio_connection = radio_controller.add_object(src, frequency, filter = RADIO_ATMOSIA)
|
||||
|
||||
if(network2)
|
||||
network2.update = 1
|
||||
/obj/machinery/atmospherics/binary/pump/proc/broadcast_status()
|
||||
if(!radio_connection)
|
||||
return 0
|
||||
|
||||
return 1
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 1 //radio signal
|
||||
signal.source = src
|
||||
|
||||
//Radio remote control
|
||||
signal.data = list(
|
||||
"tag" = id,
|
||||
"device" = "AGP",
|
||||
"power" = on,
|
||||
"target_output" = target_pressure,
|
||||
"sigtype" = "status"
|
||||
)
|
||||
|
||||
proc
|
||||
set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
if(frequency)
|
||||
radio_connection = radio_controller.add_object(src, frequency, filter = RADIO_ATMOSIA)
|
||||
radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
|
||||
|
||||
broadcast_status()
|
||||
if(!radio_connection)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 1 //radio signal
|
||||
signal.source = src
|
||||
/obj/machinery/atmospherics/binary/pump/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
if(stat & (BROKEN|NOPOWER))
|
||||
return
|
||||
|
||||
signal.data = list(
|
||||
"tag" = id,
|
||||
"device" = "AGP",
|
||||
"power" = on,
|
||||
"target_output" = target_pressure,
|
||||
"sigtype" = "status"
|
||||
)
|
||||
// this is the data which will be sent to the ui
|
||||
var/data[0]
|
||||
|
||||
data = list(
|
||||
"on" = on,
|
||||
"pressure_set" = round(target_pressure*100), //Nano UI can't handle rounded non-integers, apparently.
|
||||
"max_pressure" = max_pressure_setting,
|
||||
"last_flow_rate" = round(last_flow_rate*10),
|
||||
"last_power_draw" = round(last_power_draw),
|
||||
"max_power_draw" = active_power_usage,
|
||||
)
|
||||
|
||||
radio_connection.post_signal(src, signal, filter = RADIO_ATMOSIA)
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "gas_pump.tmpl", name, 470, 290)
|
||||
ui.set_initial_data(data) // when the ui is first opened this is the data it will use
|
||||
ui.open() // open the new ui window
|
||||
ui.set_auto_update(1) // auto update every Master Controller tick
|
||||
|
||||
return 1
|
||||
/obj/machinery/atmospherics/binary/pump/initialize()
|
||||
..()
|
||||
if(frequency)
|
||||
set_frequency(frequency)
|
||||
|
||||
interact(mob/user as mob)
|
||||
var/dat = {"<b>Power: </b><a href='?src=\ref[src];power=1'>[on?"On":"Off"]</a><br>
|
||||
<b>Desirable output pressure: </b>
|
||||
[round(target_pressure,0.1)]kPa | <a href='?src=\ref[src];set_press=1'>Change</a>
|
||||
"}
|
||||
/obj/machinery/atmospherics/binary/pump/receive_signal(datum/signal/signal)
|
||||
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
|
||||
return 0
|
||||
|
||||
user << browse("<HEAD><TITLE>[src.name] control</TITLE></HEAD><TT>[dat]</TT>", "window=atmo_pump")
|
||||
onclose(user, "atmo_pump")
|
||||
if(signal.data["power"])
|
||||
if(text2num(signal.data["power"]))
|
||||
on = 1
|
||||
else
|
||||
on = 0
|
||||
|
||||
initialize()
|
||||
..()
|
||||
if(frequency)
|
||||
set_frequency(frequency)
|
||||
if("power_toggle" in signal.data)
|
||||
on = !on
|
||||
|
||||
receive_signal(datum/signal/signal)
|
||||
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
|
||||
return 0
|
||||
|
||||
if("power" in signal.data)
|
||||
on = text2num(signal.data["power"])
|
||||
|
||||
if("power_toggle" in signal.data)
|
||||
on = !on
|
||||
|
||||
if("set_output_pressure" in signal.data)
|
||||
target_pressure = between(
|
||||
0,
|
||||
text2num(signal.data["set_output_pressure"]),
|
||||
ONE_ATMOSPHERE*50
|
||||
)
|
||||
|
||||
if("status" in signal.data)
|
||||
spawn(2)
|
||||
broadcast_status()
|
||||
return //do not update_icon
|
||||
if(signal.data["set_output_pressure"])
|
||||
target_pressure = between(
|
||||
0,
|
||||
text2num(signal.data["set_output_pressure"]),
|
||||
ONE_ATMOSPHERE*50
|
||||
)
|
||||
|
||||
if(signal.data["status"])
|
||||
spawn(2)
|
||||
broadcast_status()
|
||||
update_icon()
|
||||
return //do not update_icon
|
||||
|
||||
spawn(2)
|
||||
broadcast_status()
|
||||
update_icon()
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/binary/pump/attack_hand(user as mob)
|
||||
if(..())
|
||||
return
|
||||
|
||||
|
||||
attack_hand(user as mob)
|
||||
if(..())
|
||||
return
|
||||
src.add_fingerprint(usr)
|
||||
if(!src.allowed(user))
|
||||
user << "\red Access denied."
|
||||
return
|
||||
usr.set_machine(src)
|
||||
interact(user)
|
||||
src.add_fingerprint(usr)
|
||||
if(!src.allowed(user))
|
||||
user << "\red Access denied."
|
||||
return
|
||||
usr.set_machine(src)
|
||||
ui_interact(user)
|
||||
return
|
||||
|
||||
Topic(href,href_list)
|
||||
if(..()) return
|
||||
if(href_list["power"])
|
||||
on = !on
|
||||
if(href_list["set_press"])
|
||||
var/new_pressure = input(usr,"Enter new output pressure (0-4500kPa)","Pressure control",src.target_pressure) as num
|
||||
src.target_pressure = max(0, min(4500, new_pressure))
|
||||
usr.set_machine(src)
|
||||
src.update_icon()
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
/obj/machinery/atmospherics/binary/pump/Topic(href,href_list)
|
||||
if(..()) return
|
||||
|
||||
if(href_list["power"])
|
||||
on = !on
|
||||
|
||||
switch(href_list["set_press"])
|
||||
if ("min")
|
||||
target_pressure = 0
|
||||
if ("max")
|
||||
target_pressure = max_pressure_setting
|
||||
if ("set")
|
||||
var/new_pressure = input(usr,"Enter new output pressure (0-[max_pressure_setting]kPa)","Pressure control",src.target_pressure) as num
|
||||
src.target_pressure = between(0, new_pressure, max_pressure_setting)
|
||||
|
||||
usr.set_machine(src)
|
||||
src.add_fingerprint(usr)
|
||||
|
||||
src.update_icon()
|
||||
|
||||
power_change()
|
||||
..()
|
||||
/obj/machinery/atmospherics/binary/pump/power_change()
|
||||
var/old_stat = stat
|
||||
..()
|
||||
if(old_stat != stat)
|
||||
update_icon()
|
||||
|
||||
attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if (!istype(W, /obj/item/weapon/wrench))
|
||||
return ..()
|
||||
if (!(stat & NOPOWER) && on)
|
||||
user << "\red You cannot unwrench this [src], turn it off first."
|
||||
return 1
|
||||
var/turf/T = src.loc
|
||||
if (level==1 && isturf(T) && T.intact)
|
||||
user << "\red You must remove the plating first."
|
||||
return 1
|
||||
var/datum/gas_mixture/int_air = return_air()
|
||||
var/datum/gas_mixture/env_air = loc.return_air()
|
||||
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
|
||||
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
|
||||
add_fingerprint(user)
|
||||
return 1
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
user << "\blue You begin to unfasten \the [src]..."
|
||||
if (do_after(user, 40))
|
||||
user.visible_message( \
|
||||
"[user] unfastens \the [src].", \
|
||||
"\blue You have unfastened \the [src].", \
|
||||
"You hear ratchet.")
|
||||
new /obj/item/pipe(loc, make_from=src)
|
||||
del(src)
|
||||
/obj/machinery/atmospherics/binary/pump/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if (!istype(W, /obj/item/weapon/wrench))
|
||||
return ..()
|
||||
if (!(stat & NOPOWER) && on)
|
||||
user << "\red You cannot unwrench this [src], turn it off first."
|
||||
return 1
|
||||
var/datum/gas_mixture/int_air = return_air()
|
||||
var/datum/gas_mixture/env_air = loc.return_air()
|
||||
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
|
||||
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
|
||||
add_fingerprint(user)
|
||||
return 1
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
user << "\blue You begin to unfasten \the [src]..."
|
||||
if (do_after(user, 40))
|
||||
user.visible_message( \
|
||||
"[user] unfastens \the [src].", \
|
||||
"\blue You have unfastened \the [src].", \
|
||||
"You hear ratchet.")
|
||||
new /obj/item/pipe(loc, make_from=src)
|
||||
del(src)
|
||||
|
||||
@@ -1,199 +1,19 @@
|
||||
/*
|
||||
Every cycle, the pump uses the air in air_in to try and make air_out the perfect pressure.
|
||||
/obj/machinery/atmospherics/binary/pump/high_power
|
||||
icon = 'icons/atmos/volume_pump.dmi'
|
||||
icon_state = "map_off"
|
||||
level = 1
|
||||
|
||||
node1, air1, network1 correspond to input
|
||||
node2, air2, network2 correspond to output
|
||||
name = "high power gas pump"
|
||||
desc = "A pump. Has double the power rating of the standard gas pump."
|
||||
|
||||
Thus, the two variables affect pump operation are set in New():
|
||||
air1.volume
|
||||
This is the volume of gas available to the pump that may be transfered to the output
|
||||
air2.volume
|
||||
Higher quantities of this cause more air to be perfected later
|
||||
but overall network volume is also increased as this increases...
|
||||
*/
|
||||
active_power_usage = 15000 //This also doubles as a measure of how powerful the pump is, in Watts. 15000 W ~ 20 HP
|
||||
|
||||
obj/machinery/atmospherics/binary/volume_pump
|
||||
icon = 'icons/obj/atmospherics/volume_pump.dmi'
|
||||
icon_state = "intact_off"
|
||||
|
||||
name = "Volumetric gas pump"
|
||||
desc = "A volumetric pump"
|
||||
|
||||
var/on = 0
|
||||
var/transfer_rate = 200
|
||||
|
||||
var/frequency = 0
|
||||
var/id = null
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
on
|
||||
on = 1
|
||||
icon_state = "intact_on"
|
||||
|
||||
update_icon()
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "intact_off"
|
||||
else if(node1 && node2)
|
||||
icon_state = "intact_[on?("on"):("off")]"
|
||||
else
|
||||
if(node1)
|
||||
icon_state = "exposed_1_off"
|
||||
else if(node2)
|
||||
icon_state = "exposed_2_off"
|
||||
else
|
||||
icon_state = "exposed_3_off"
|
||||
return
|
||||
|
||||
process()
|
||||
// ..()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
if(!on)
|
||||
return 0
|
||||
|
||||
// Pump mechanism just won't do anything if the pressure is too high/too low
|
||||
|
||||
var/input_starting_pressure = air1.return_pressure()
|
||||
var/output_starting_pressure = air2.return_pressure()
|
||||
|
||||
if((input_starting_pressure < 0.01) || (output_starting_pressure > 9000))
|
||||
return 1
|
||||
|
||||
var/transfer_ratio = max(1, transfer_rate/air1.volume)
|
||||
|
||||
var/datum/gas_mixture/removed = air1.remove_ratio(transfer_ratio)
|
||||
|
||||
air2.merge(removed)
|
||||
|
||||
if(network1)
|
||||
network1.update = 1
|
||||
|
||||
if(network2)
|
||||
network2.update = 1
|
||||
|
||||
return 1
|
||||
|
||||
proc
|
||||
set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
if(frequency)
|
||||
radio_connection = radio_controller.add_object(src, frequency)
|
||||
|
||||
broadcast_status()
|
||||
if(!radio_connection)
|
||||
return 0
|
||||
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 1 //radio signal
|
||||
signal.source = src
|
||||
|
||||
signal.data = list(
|
||||
"tag" = id,
|
||||
"device" = "APV",
|
||||
"power" = on,
|
||||
"transfer_rate" = transfer_rate,
|
||||
"sigtype" = "status"
|
||||
)
|
||||
radio_connection.post_signal(src, signal)
|
||||
|
||||
return 1
|
||||
|
||||
interact(mob/user as mob)
|
||||
var/dat = {"<b>Power: </b><a href='?src=\ref[src];power=1'>[on?"On":"Off"]</a><br>
|
||||
<b>Desirable output flow: </b>
|
||||
[round(transfer_rate,1)]l/s | <a href='?src=\ref[src];set_transfer_rate=1'>Change</a>
|
||||
"}
|
||||
|
||||
user << browse("<HEAD><TITLE>[src.name] control</TITLE></HEAD><TT>[dat]</TT>", "window=atmo_pump")
|
||||
onclose(user, "atmo_pump")
|
||||
|
||||
|
||||
|
||||
initialize()
|
||||
..()
|
||||
|
||||
set_frequency(frequency)
|
||||
|
||||
receive_signal(datum/signal/signal)
|
||||
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
|
||||
return 0
|
||||
|
||||
if("power" in signal.data)
|
||||
on = text2num(signal.data["power"])
|
||||
|
||||
if("power_toggle" in signal.data)
|
||||
on = !on
|
||||
|
||||
if("set_transfer_rate" in signal.data)
|
||||
transfer_rate = between(
|
||||
0,
|
||||
text2num(signal.data["set_transfer_rate"]),
|
||||
air1.volume
|
||||
)
|
||||
|
||||
if("status" in signal.data)
|
||||
spawn(2)
|
||||
broadcast_status()
|
||||
return //do not update_icon
|
||||
|
||||
spawn(2)
|
||||
broadcast_status()
|
||||
update_icon()
|
||||
|
||||
|
||||
attack_hand(user as mob)
|
||||
if(..())
|
||||
return
|
||||
src.add_fingerprint(usr)
|
||||
if(!src.allowed(user))
|
||||
user << "\red Access denied."
|
||||
return
|
||||
usr.set_machine(src)
|
||||
interact(user)
|
||||
return
|
||||
|
||||
Topic(href,href_list)
|
||||
if(..()) return
|
||||
if(href_list["power"])
|
||||
on = !on
|
||||
if(href_list["set_transfer_rate"])
|
||||
var/new_transfer_rate = input(usr,"Enter new output volume (0-200l/s)","Flow control",src.transfer_rate) as num
|
||||
src.transfer_rate = max(0, min(200, new_transfer_rate))
|
||||
usr.set_machine(src)
|
||||
src.update_icon()
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
power_change()
|
||||
..()
|
||||
update_icon()
|
||||
|
||||
|
||||
|
||||
attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if (!istype(W, /obj/item/weapon/wrench))
|
||||
return ..()
|
||||
if (!(stat & NOPOWER) && on)
|
||||
user << "\red You cannot unwrench this [src], turn it off first."
|
||||
return 1
|
||||
var/turf/T = src.loc
|
||||
if (level==1 && isturf(T) && T.intact)
|
||||
user << "\red You must remove the plating first."
|
||||
return 1
|
||||
var/datum/gas_mixture/int_air = return_air()
|
||||
var/datum/gas_mixture/env_air = loc.return_air()
|
||||
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
|
||||
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
|
||||
add_fingerprint(user)
|
||||
return 1
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
user << "\blue You begin to unfasten \the [src]..."
|
||||
if (do_after(user, 40))
|
||||
user.visible_message( \
|
||||
"[user] unfastens \the [src].", \
|
||||
"\blue You have unfastened \the [src].", \
|
||||
"You hear ratchet.")
|
||||
new /obj/item/pipe(loc, make_from=src)
|
||||
del(src)
|
||||
/obj/machinery/atmospherics/binary/pump/high_power/on
|
||||
on = 1
|
||||
icon_state = "map_on"
|
||||
|
||||
/obj/machinery/atmospherics/binary/pump/high_power/update_icon()
|
||||
if(!powered())
|
||||
icon_state = "off"
|
||||
else
|
||||
icon_state = "[on ? "on" : "off"]"
|
||||
@@ -11,33 +11,6 @@
|
||||
#define ATM_P 6 //Phoron
|
||||
#define ATM_N2O 7
|
||||
|
||||
//--------------------------------------------
|
||||
// Omni device cached icon list
|
||||
//--------------------------------------------
|
||||
var/global/list/omni_icons[]
|
||||
|
||||
/proc/gen_omni_icons()
|
||||
omni_icons = new()
|
||||
var/icon/omni = new('icons/obj/atmospherics/omni_devices.dmi')
|
||||
|
||||
for(var/state in omni.IconStates())
|
||||
if(!state || findtext(state, "map"))
|
||||
continue
|
||||
|
||||
var/image/I = image('icons/obj/atmospherics/omni_devices.dmi', icon_state = state)
|
||||
|
||||
if(findtext(state, "pipe"))
|
||||
for(var/pipe_color in pipe_colors)
|
||||
I = image('icons/obj/atmospherics/omni_devices.dmi', icon_state = state)
|
||||
I.color = pipe_colors[pipe_color]
|
||||
var/cache_name = state
|
||||
if(I.color)
|
||||
cache_name += "_[pipe_colors[pipe_color]]"
|
||||
omni_icons[cache_name] = I
|
||||
else
|
||||
omni_icons[state] = I
|
||||
|
||||
|
||||
//--------------------------------------------
|
||||
// Omni port datum
|
||||
//
|
||||
@@ -83,16 +56,6 @@ var/global/list/omni_icons[]
|
||||
// Need to find somewhere else for these
|
||||
//--------------------------------------------
|
||||
|
||||
#define PIPE_COLOR_RED "#ff0000"
|
||||
#define PIPE_COLOR_BLUE "#0000ff"
|
||||
#define PIPE_COLOR_CYAN "#00ffff"
|
||||
#define PIPE_COLOR_GREEN "#00ff00"
|
||||
#define PIPE_COLOR_YELLOW "#ffcc00"
|
||||
#define PIPE_COLOR_PURPLE "#5c1ec0"
|
||||
|
||||
var/global/list/pipe_colors = list("grey" = null, "red" = PIPE_COLOR_RED, "blue" = PIPE_COLOR_BLUE, "cyan" = PIPE_COLOR_CYAN, "green" = PIPE_COLOR_GREEN, "yellow" = PIPE_COLOR_YELLOW, "purple" = PIPE_COLOR_PURPLE)
|
||||
|
||||
|
||||
//returns a text string based on the direction flag input
|
||||
// if capitalize is true, it will return the string capitalized
|
||||
// otherwise it will return the direction string in lower case
|
||||
@@ -127,4 +90,20 @@ var/global/list/pipe_colors = list("grey" = null, "red" = PIPE_COLOR_RED, "blue"
|
||||
if("west")
|
||||
return WEST
|
||||
else
|
||||
return 0
|
||||
return 0
|
||||
|
||||
/proc/mode_to_gasid(var/mode)
|
||||
switch(mode)
|
||||
if(ATM_O2)
|
||||
return "oxygen"
|
||||
if(ATM_N2)
|
||||
return "nitrogen"
|
||||
if(ATM_CO2)
|
||||
return "carbon_dioxide"
|
||||
if(ATM_P)
|
||||
return "phoron"
|
||||
if(ATM_N2O)
|
||||
return "sleeping_agent"
|
||||
else
|
||||
return null
|
||||
|
||||
@@ -8,6 +8,21 @@
|
||||
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()
|
||||
..()
|
||||
rebuild_filtering_list()
|
||||
for(var/datum/omni_port/P in ports)
|
||||
P.air.volume = ATMOS_DEFAULT_VOLUME_FILTER
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/Del()
|
||||
input = null
|
||||
@@ -37,89 +52,56 @@
|
||||
/obj/machinery/atmospherics/omni/filter/error_check()
|
||||
if(!input || !output || !filters)
|
||||
return 1
|
||||
if(filters.len < 1 || filters.len > 2) //requires 1 or 2 filters ~otherwise why are you using a filter?
|
||||
if(filters.len < 1) //requires at least 1 filter ~otherwise why are you using a filter?
|
||||
return 1
|
||||
|
||||
return 0
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/process()
|
||||
..()
|
||||
if(!on)
|
||||
return 0
|
||||
if(error_check())
|
||||
on = 0
|
||||
|
||||
if(!input || !output)
|
||||
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/datum/gas_mixture/output_air = output.air //BYOND doesn't like referencing "output.air.return_pressure()" so we need to make a direct reference
|
||||
var/datum/gas_mixture/input_air = input.air // it's completely happy with them if they're in a loop though i.e. "P.air.return_pressure()"... *shrug*
|
||||
|
||||
var/output_pressure = output_air.return_pressure()
|
||||
|
||||
if(output_pressure >= target_pressure)
|
||||
return
|
||||
for(var/datum/omni_port/P in filters)
|
||||
if(P.air.return_pressure() >= target_pressure)
|
||||
return
|
||||
|
||||
var/pressure_delta = target_pressure - output_pressure
|
||||
|
||||
if(input_air.return_temperature() > 0)
|
||||
input.transfer_moles = pressure_delta * output_air.volume / (input_air.return_temperature() * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
if(input.transfer_moles > 0)
|
||||
var/datum/gas_mixture/removed = input_air.remove(input.transfer_moles)
|
||||
//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(!removed)
|
||||
return
|
||||
|
||||
for(var/datum/omni_port/P in filters)
|
||||
var/datum/gas_mixture/filtered_out = new
|
||||
filtered_out.temperature = removed.return_temperature()
|
||||
|
||||
switch(P.mode)
|
||||
if(ATM_O2)
|
||||
filtered_out.oxygen = removed.oxygen
|
||||
removed.oxygen = 0
|
||||
if(ATM_N2)
|
||||
filtered_out.nitrogen = removed.nitrogen
|
||||
removed.nitrogen = 0
|
||||
if(ATM_CO2)
|
||||
filtered_out.carbon_dioxide = removed.carbon_dioxide
|
||||
removed.carbon_dioxide = 0
|
||||
if(ATM_P)
|
||||
filtered_out.phoron = removed.phoron
|
||||
removed.phoron = 0
|
||||
if(ATM_N2O)
|
||||
if(removed.trace_gases.len>0)
|
||||
for(var/datum/gas/sleeping_agent/trace_gas in removed.trace_gases)
|
||||
if(istype(trace_gas))
|
||||
removed.trace_gases -= trace_gas
|
||||
filtered_out.trace_gases += trace_gas
|
||||
else
|
||||
filtered_out = null
|
||||
|
||||
P.air.merge(filtered_out)
|
||||
if(P.network)
|
||||
P.network.update = 1
|
||||
|
||||
output_air.merge(removed)
|
||||
if(output.network)
|
||||
output.network.update = 1
|
||||
|
||||
input.transfer_moles = 0
|
||||
if(input.network)
|
||||
input.network.update = 1
|
||||
if(output.network)
|
||||
output.network.update = 1
|
||||
for(var/datum/omni_port/P in filters)
|
||||
if(P.network)
|
||||
P.network.update = 1
|
||||
|
||||
return 1
|
||||
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null)
|
||||
/obj/machinery/atmospherics/omni/filter/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
usr.set_machine(src)
|
||||
|
||||
var/list/data = new()
|
||||
|
||||
data = build_uidata()
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data)
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "omni_filter.tmpl", "Omni Filter Control", 330, 330)
|
||||
@@ -161,7 +143,8 @@
|
||||
if(portData.len)
|
||||
data["ports"] = portData
|
||||
if(output)
|
||||
data["pressure"] = target_pressure
|
||||
data["set_flow_rate"] = round(set_flow_rate*10) //because nanoui can't handle rounded decimals.
|
||||
data["last_flow_rate"] = round(last_flow_rate*10)
|
||||
|
||||
return data
|
||||
|
||||
@@ -196,9 +179,9 @@
|
||||
//only allows config changes when in configuring mode ~otherwise you'll get weird pressure stuff going on
|
||||
if(configuring && !on)
|
||||
switch(href_list["command"])
|
||||
if("set_pressure")
|
||||
var/new_pressure = input(usr,"Enter new output pressure (0-4500kPa)","Pressure control",target_pressure) as num
|
||||
target_pressure = between(0, new_pressure, 4500)
|
||||
if("set_flow_rate")
|
||||
var/new_flow_rate = input(usr,"Enter new flow rate limit (0-[max_flow_rate]L/s)","Flow Rate Control",set_flow_rate) as num
|
||||
set_flow_rate = between(0, new_flow_rate, max_flow_rate)
|
||||
if("switch_mode")
|
||||
switch_mode(dir_flag(href_list["dir"]), mode_return_switch(href_list["mode"]))
|
||||
if("switch_filter")
|
||||
@@ -257,6 +240,7 @@
|
||||
target_port.mode = mode
|
||||
if(target_port.mode != previous_mode)
|
||||
handle_port_change(target_port)
|
||||
rebuild_filtering_list()
|
||||
else
|
||||
return
|
||||
else
|
||||
@@ -268,9 +252,16 @@
|
||||
P.mode = previous_mode
|
||||
if(P.mode != old_mode)
|
||||
handle_port_change(P)
|
||||
|
||||
|
||||
update_ports()
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/proc/rebuild_filtering_list()
|
||||
filtering_outputs.Cut()
|
||||
for(var/datum/omni_port/P in ports)
|
||||
var/gasid = mode_to_gasid(P.mode)
|
||||
if(gasid)
|
||||
filtering_outputs[gasid] = P.air
|
||||
|
||||
/obj/machinery/atmospherics/omni/filter/proc/handle_port_change(var/datum/omni_port/P)
|
||||
switch(P.mode)
|
||||
if(ATM_NONE)
|
||||
|
||||
@@ -5,14 +5,23 @@
|
||||
name = "omni gas mixer"
|
||||
icon_state = "map_mixer"
|
||||
|
||||
use_power = 1
|
||||
idle_power_usage = 150 //internal circuitry, friction losses and stuff
|
||||
active_power_usage = 3700 //This also doubles as a measure of how powerful the mixer is, in Watts. 3700 W ~ 5 HP
|
||||
|
||||
var/list/inputs = new()
|
||||
var/datum/omni_port/output
|
||||
|
||||
//setup tags for initial concentration values (must be decimal)
|
||||
var/tag_north_con
|
||||
var/tag_north_con
|
||||
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()
|
||||
..()
|
||||
@@ -36,13 +45,11 @@
|
||||
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
|
||||
|
||||
//mappers who are bad at maths will be punished (total concentration must be 100%)
|
||||
if(con != 1)
|
||||
tag_north_con = null
|
||||
tag_south_con = null
|
||||
tag_east_con = null
|
||||
tag_west_con = null
|
||||
rebuild_mixing_inputs()
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/Del()
|
||||
inputs.Cut()
|
||||
@@ -57,7 +64,6 @@
|
||||
if(inputs.Find(P))
|
||||
inputs -= P
|
||||
|
||||
P.air.volume = 200
|
||||
switch(P.mode)
|
||||
if(ATM_INPUT)
|
||||
inputs += P
|
||||
@@ -69,7 +75,7 @@
|
||||
P.concentration = 1 / max(1, inputs.len)
|
||||
|
||||
if(output)
|
||||
output.air.volume *= 0.75 * inputs.len
|
||||
output.air.volume = ATMOS_DEFAULT_VOLUME_MIXER * 0.75 * inputs.len
|
||||
output.concentration = 1
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/proc/mapper_set()
|
||||
@@ -78,73 +84,62 @@
|
||||
/obj/machinery/atmospherics/omni/mixer/error_check()
|
||||
if(!output || !inputs)
|
||||
return 1
|
||||
if(inputs.len < 2 || inputs.len > 3) //requires 2 or 3 inputs ~otherwise why are you using a mixer?
|
||||
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(!on)
|
||||
return 0
|
||||
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
|
||||
|
||||
//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)
|
||||
|
||||
var/datum/gas_mixture/output_air = output.air
|
||||
var/output_pressure = output_air.return_pressure()
|
||||
|
||||
|
||||
if(output_pressure >= target_pressure * 0.999)
|
||||
//No need to mix if target is already full! - 0.1% margin of error so we minimize processing minor gas volumes
|
||||
return 1
|
||||
|
||||
//Calculate necessary moles to transfer using PV=nRT
|
||||
|
||||
var/pressure_delta = target_pressure - output_pressure
|
||||
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
if(P.air.return_temperature() > 0)
|
||||
P.transfer_moles = (P.concentration * pressure_delta) * output_air.return_volume() / (P.air.return_temperature() * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
var/ratio_check = null
|
||||
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
if(!P.transfer_moles)
|
||||
return
|
||||
if(P.air.total_moles() < P.transfer_moles)
|
||||
ratio_check = 1
|
||||
continue
|
||||
|
||||
if(ratio_check)
|
||||
var/list/ratio_list = new()
|
||||
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)
|
||||
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
ratio_list.Add(P.air.total_moles() / P.transfer_moles)
|
||||
|
||||
var/ratio = min(ratio_list)
|
||||
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
P.transfer_moles *= ratio
|
||||
|
||||
|
||||
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
if(P.transfer_moles > 0)
|
||||
output_air.merge(P.air.remove(P.transfer_moles))
|
||||
if(P.network)
|
||||
if(P.concentration && P.network)
|
||||
P.network.update = 1
|
||||
P.transfer_moles = 0
|
||||
|
||||
if(output.network)
|
||||
output.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)
|
||||
/obj/machinery/atmospherics/omni/mixer/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
usr.set_machine(src)
|
||||
|
||||
var/list/data = new()
|
||||
|
||||
data = build_uidata()
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data)
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "omni_mixer.tmpl", "Omni Mixer Control", 360, 330)
|
||||
@@ -180,7 +175,8 @@
|
||||
if(portData.len)
|
||||
data["ports"] = portData
|
||||
if(output)
|
||||
data["pressure"] = target_pressure
|
||||
data["set_flow_rate"] = round(set_flow_rate*10) //because nanoui can't handle rounded decimals.
|
||||
data["last_flow_rate"] = round(last_flow_rate*10)
|
||||
|
||||
return data
|
||||
|
||||
@@ -201,9 +197,9 @@
|
||||
//only allows config changes when in configuring mode ~otherwise you'll get weird pressure stuff going on
|
||||
if(configuring && !on)
|
||||
switch(href_list["command"])
|
||||
if("set_pressure")
|
||||
var/new_pressure = input(usr,"Enter new output pressure (0-4500kPa)","Pressure control",target_pressure) as num
|
||||
target_pressure = between(0, new_pressure, 4500)
|
||||
if("set_flow_rate")
|
||||
var/new_flow_rate = input(usr,"Enter new flow rate limit (0-[max_flow_rate]L/s)","Flow Rate Control",set_flow_rate) as num
|
||||
set_flow_rate = between(0, new_flow_rate, max_flow_rate)
|
||||
if("switch_mode")
|
||||
switch_mode(dir_flag(href_list["dir"]), href_list["mode"])
|
||||
if("switch_con")
|
||||
@@ -253,6 +249,7 @@
|
||||
P.update = 1
|
||||
|
||||
update_ports()
|
||||
rebuild_mixing_inputs()
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/proc/change_concentration(var/port = NORTH)
|
||||
tag_north_con = null
|
||||
@@ -294,6 +291,13 @@
|
||||
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()
|
||||
mixing_inputs.Cut()
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
mixing_inputs[P.air] = P.concentration
|
||||
|
||||
/obj/machinery/atmospherics/omni/mixer/proc/con_lock(var/port = NORTH)
|
||||
for(var/datum/omni_port/P in inputs)
|
||||
|
||||
@@ -3,14 +3,15 @@
|
||||
//--------------------------------------------
|
||||
/obj/machinery/atmospherics/omni
|
||||
name = "omni device"
|
||||
icon = 'icons/obj/atmospherics/omni_devices.dmi'
|
||||
icon = 'icons/atmos/omni_devices.dmi'
|
||||
icon_state = "base"
|
||||
use_power = 1
|
||||
initialize_directions = 0
|
||||
level = 1
|
||||
|
||||
var/on = 0
|
||||
var/configuring = 0
|
||||
var/target_pressure = ONE_ATMOSPHERE
|
||||
//var/target_pressure = ONE_ATMOSPHERE //a base type as abstract as this should NOT be making these kinds of assumptions
|
||||
|
||||
var/tag_north = ATM_NONE
|
||||
var/tag_south = ATM_NONE
|
||||
@@ -70,12 +71,6 @@
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/omni/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if(istype(W, /obj/item/device/pipe_painter)) //for updating the color of connected pipe ends
|
||||
for(var/datum/omni_port/P in ports)
|
||||
P.update = 1
|
||||
update_ports()
|
||||
return
|
||||
|
||||
if(!istype(W, /obj/item/weapon/wrench))
|
||||
return ..()
|
||||
|
||||
@@ -106,8 +101,8 @@
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/omni/proc/build_icons()
|
||||
if(!omni_icons)
|
||||
gen_omni_icons()
|
||||
if(!check_icon_cache())
|
||||
return
|
||||
|
||||
var/core_icon = null
|
||||
if(istype(src, /obj/machinery/atmospherics/omni/mixer))
|
||||
@@ -119,13 +114,16 @@
|
||||
|
||||
//directional icons are layers 1-4, with the core icon on layer 5
|
||||
if(core_icon)
|
||||
overlays_off[5] = omni_icons[core_icon]
|
||||
overlays_on[5] = omni_icons[core_icon + "_glow"]
|
||||
overlays_off[5] = icon_manager.get_atmos_icon("omni", , , core_icon)
|
||||
overlays_on[5] = icon_manager.get_atmos_icon("omni", , , core_icon + "_glow")
|
||||
|
||||
overlays_error[1] = omni_icons[core_icon]
|
||||
overlays_error[2] = omni_icons["error"]
|
||||
overlays_error[1] = icon_manager.get_atmos_icon("omni", , , core_icon)
|
||||
overlays_error[2] = icon_manager.get_atmos_icon("omni", , , "error")
|
||||
|
||||
/obj/machinery/atmospherics/omni/proc/update_port_icons()
|
||||
if(!check_icon_cache())
|
||||
return
|
||||
|
||||
for(var/datum/omni_port/P in ports)
|
||||
if(P.update)
|
||||
var/ref_layer = 0
|
||||
@@ -145,11 +143,11 @@
|
||||
var/list/port_icons = select_port_icons(P)
|
||||
if(port_icons)
|
||||
if(P.node)
|
||||
underlays_current[ref_layer] = omni_icons[port_icons["pipe_icon"]]
|
||||
underlays_current[ref_layer] = port_icons["pipe_icon"]
|
||||
else
|
||||
underlays_current[ref_layer] = null
|
||||
overlays_off[ref_layer] = omni_icons[port_icons["off_icon"]]
|
||||
overlays_on[ref_layer] = omni_icons[port_icons["on_icon"]]
|
||||
overlays_off[ref_layer] = port_icons["off_icon"]
|
||||
overlays_on[ref_layer] = port_icons["on_icon"]
|
||||
else
|
||||
underlays_current[ref_layer] = null
|
||||
overlays_off[ref_layer] = null
|
||||
@@ -175,14 +173,29 @@
|
||||
if(ATM_O2 to ATM_N2O)
|
||||
ic_on += "_filter"
|
||||
ic_off += "_out"
|
||||
|
||||
var/pipe_state = ic_dir + "_pipe"
|
||||
if(P.node)
|
||||
if(P.node.color)
|
||||
pipe_state += "_[P.node.color]"
|
||||
|
||||
ic_on = icon_manager.get_atmos_icon("omni", , , ic_on)
|
||||
ic_off = icon_manager.get_atmos_icon("omni", , , ic_off)
|
||||
|
||||
var/pipe_state
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T))
|
||||
return
|
||||
if(T.intact && istype(P.node, /obj/machinery/atmospherics/pipe) && P.node.level == 1 )
|
||||
pipe_state = icon_manager.get_atmos_icon("underlay_down", P.dir, color_cache_name(P.node))
|
||||
else
|
||||
pipe_state = icon_manager.get_atmos_icon("underlay_intact", P.dir, color_cache_name(P.node))
|
||||
|
||||
return list("on_icon" = ic_on, "off_icon" = ic_off, "pipe_icon" = pipe_state)
|
||||
|
||||
/obj/machinery/atmospherics/omni/update_underlays()
|
||||
for(var/datum/omni_port/P in ports)
|
||||
P.update = 1
|
||||
update_ports()
|
||||
|
||||
/obj/machinery/atmospherics/omni/hide(var/i)
|
||||
update_underlays()
|
||||
|
||||
/obj/machinery/atmospherics/omni/proc/update_ports()
|
||||
sort_ports()
|
||||
update_port_icons()
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/obj/machinery/atmospherics/portables_connector
|
||||
icon = 'icons/obj/atmospherics/portables_connector.dmi'
|
||||
icon_state = "intact"
|
||||
icon = 'icons/atmos/connector.dmi'
|
||||
icon_state = "map_connector"
|
||||
|
||||
name = "Connector Port"
|
||||
desc = "For connecting portables devices related to atmospherics control."
|
||||
@@ -16,142 +16,139 @@
|
||||
|
||||
var/on = 0
|
||||
use_power = 0
|
||||
level = 0
|
||||
level = 1
|
||||
|
||||
|
||||
New()
|
||||
initialize_directions = dir
|
||||
..()
|
||||
/obj/machinery/atmospherics/portables_connector/New()
|
||||
initialize_directions = dir
|
||||
..()
|
||||
|
||||
update_icon()
|
||||
if(node)
|
||||
icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]intact"
|
||||
dir = get_dir(src, node)
|
||||
else
|
||||
icon_state = "exposed"
|
||||
/obj/machinery/atmospherics/portables_connector/update_icon()
|
||||
icon_state = "connector"
|
||||
|
||||
/obj/machinery/atmospherics/portables_connector/update_underlays()
|
||||
if(..())
|
||||
underlays.Cut()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T))
|
||||
return
|
||||
add_underlay(T, node, dir)
|
||||
|
||||
/obj/machinery/atmospherics/portables_connector/hide(var/i)
|
||||
update_underlays()
|
||||
|
||||
/obj/machinery/atmospherics/portables_connector/process()
|
||||
..()
|
||||
if(!on)
|
||||
return
|
||||
|
||||
hide(var/i) //to make the little pipe section invisible, the icon changes.
|
||||
if(node)
|
||||
icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]intact"
|
||||
dir = get_dir(src, node)
|
||||
else
|
||||
icon_state = "exposed"
|
||||
|
||||
process()
|
||||
..()
|
||||
if(!on)
|
||||
return
|
||||
if(!connected_device)
|
||||
on = 0
|
||||
return
|
||||
if(network)
|
||||
network.update = 1
|
||||
return 1
|
||||
if(!connected_device)
|
||||
on = 0
|
||||
return
|
||||
if(network)
|
||||
network.update = 1
|
||||
return 1
|
||||
|
||||
// Housekeeping and pipe network stuff below
|
||||
network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
|
||||
if(reference == node)
|
||||
network = new_network
|
||||
/obj/machinery/atmospherics/portables_connector/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
|
||||
if(reference == node)
|
||||
network = new_network
|
||||
|
||||
if(new_network.normal_members.Find(src))
|
||||
return 0
|
||||
if(new_network.normal_members.Find(src))
|
||||
return 0
|
||||
|
||||
new_network.normal_members += src
|
||||
new_network.normal_members += src
|
||||
|
||||
return null
|
||||
return null
|
||||
|
||||
Del()
|
||||
loc = null
|
||||
/obj/machinery/atmospherics/portables_connector/Del()
|
||||
loc = null
|
||||
|
||||
if(connected_device)
|
||||
connected_device.disconnect()
|
||||
if(connected_device)
|
||||
connected_device.disconnect()
|
||||
|
||||
if(node)
|
||||
node.disconnect(src)
|
||||
del(network)
|
||||
if(node)
|
||||
node.disconnect(src)
|
||||
del(network)
|
||||
|
||||
node = null
|
||||
node = null
|
||||
|
||||
..()
|
||||
..()
|
||||
|
||||
initialize()
|
||||
if(node) return
|
||||
/obj/machinery/atmospherics/portables_connector/initialize()
|
||||
if(node) return
|
||||
|
||||
var/node_connect = dir
|
||||
var/node_connect = dir
|
||||
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node_connect))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node = target
|
||||
break
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node_connect))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node = target
|
||||
break
|
||||
|
||||
update_icon()
|
||||
update_icon()
|
||||
update_underlays()
|
||||
|
||||
/obj/machinery/atmospherics/portables_connector/build_network()
|
||||
if(!network && node)
|
||||
network = new /datum/pipe_network()
|
||||
network.normal_members += src
|
||||
network.build_network(node, src)
|
||||
|
||||
|
||||
/obj/machinery/atmospherics/portables_connector/return_network(obj/machinery/atmospherics/reference)
|
||||
build_network()
|
||||
if(!network && node)
|
||||
network = new /datum/pipe_network()
|
||||
network.normal_members += src
|
||||
network.build_network(node, src)
|
||||
|
||||
if(reference==node)
|
||||
return network
|
||||
|
||||
if(reference==connected_device)
|
||||
return network
|
||||
|
||||
return null
|
||||
|
||||
/obj/machinery/atmospherics/portables_connector/reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
|
||||
if(network == old_network)
|
||||
network = new_network
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/atmospherics/portables_connector/return_network_air(datum/pipe_network/reference)
|
||||
var/list/results = list()
|
||||
|
||||
if(connected_device)
|
||||
results += connected_device.air_contents
|
||||
|
||||
return results
|
||||
|
||||
/obj/machinery/atmospherics/portables_connector/disconnect(obj/machinery/atmospherics/reference)
|
||||
if(reference==node)
|
||||
del(network)
|
||||
node = null
|
||||
|
||||
update_underlays()
|
||||
|
||||
return null
|
||||
|
||||
|
||||
return_network(obj/machinery/atmospherics/reference)
|
||||
build_network()
|
||||
|
||||
if(reference==node)
|
||||
return network
|
||||
|
||||
if(reference==connected_device)
|
||||
return network
|
||||
|
||||
return null
|
||||
|
||||
reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
|
||||
if(network == old_network)
|
||||
network = new_network
|
||||
|
||||
/obj/machinery/atmospherics/portables_connector/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if (!istype(W, /obj/item/weapon/wrench))
|
||||
return ..()
|
||||
if (connected_device)
|
||||
user << "\red You cannot unwrench this [src], dettach [connected_device] first."
|
||||
return 1
|
||||
|
||||
return_network_air(datum/pipe_network/reference)
|
||||
var/list/results = list()
|
||||
|
||||
if(connected_device)
|
||||
results += connected_device.air_contents
|
||||
|
||||
return results
|
||||
|
||||
disconnect(obj/machinery/atmospherics/reference)
|
||||
if(reference==node)
|
||||
del(network)
|
||||
node = null
|
||||
|
||||
return null
|
||||
|
||||
|
||||
attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if (!istype(W, /obj/item/weapon/wrench))
|
||||
return ..()
|
||||
if (connected_device)
|
||||
user << "\red You cannot unwrench this [src], dettach [connected_device] first."
|
||||
return 1
|
||||
if (locate(/obj/machinery/portable_atmospherics, src.loc))
|
||||
return 1
|
||||
var/turf/T = src.loc
|
||||
if (level==1 && isturf(T) && T.intact)
|
||||
user << "\red You must remove the plating first."
|
||||
return 1
|
||||
var/datum/gas_mixture/int_air = return_air()
|
||||
var/datum/gas_mixture/env_air = loc.return_air()
|
||||
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
|
||||
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
|
||||
add_fingerprint(user)
|
||||
return 1
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
user << "\blue You begin to unfasten \the [src]..."
|
||||
if (do_after(user, 40))
|
||||
user.visible_message( \
|
||||
"[user] unfastens \the [src].", \
|
||||
"\blue You have unfastened \the [src].", \
|
||||
"You hear ratchet.")
|
||||
new /obj/item/pipe(loc, make_from=src)
|
||||
del(src)
|
||||
if (locate(/obj/machinery/portable_atmospherics, src.loc))
|
||||
return 1
|
||||
var/datum/gas_mixture/int_air = return_air()
|
||||
var/datum/gas_mixture/env_air = loc.return_air()
|
||||
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
|
||||
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
|
||||
add_fingerprint(user)
|
||||
return 1
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
user << "\blue You begin to unfasten \the [src]..."
|
||||
if (do_after(user, 40))
|
||||
user.visible_message( \
|
||||
"[user] unfastens \the [src].", \
|
||||
"\blue You have unfastened \the [src].", \
|
||||
"You hear ratchet.")
|
||||
new /obj/item/pipe(loc, make_from=src)
|
||||
del(src)
|
||||
|
||||
@@ -1,124 +1,103 @@
|
||||
obj/machinery/atmospherics/trinary/filter
|
||||
icon = 'icons/obj/atmospherics/filter.dmi'
|
||||
icon_state = "intact_off"
|
||||
/obj/machinery/atmospherics/trinary/filter
|
||||
icon = 'icons/atmos/filter.dmi'
|
||||
icon_state = "map"
|
||||
density = 0
|
||||
level = 1
|
||||
|
||||
name = "Gas filter"
|
||||
|
||||
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/on = 0
|
||||
var/temp = null // -- TLE
|
||||
|
||||
var/target_pressure = ONE_ATMOSPHERE
|
||||
var/set_flow_rate = ATMOS_DEFAULT_VOLUME_FILTER
|
||||
|
||||
/*
|
||||
Filter types:
|
||||
-1: Nothing
|
||||
0: Phoron: Phoron, Oxygen Agent B
|
||||
1: Oxygen: Oxygen ONLY
|
||||
2: Nitrogen: Nitrogen ONLY
|
||||
3: Carbon Dioxide: Carbon Dioxide ONLY
|
||||
4: Sleeping Agent (N2O)
|
||||
*/
|
||||
var/filter_type = 0
|
||||
/*
|
||||
Filter types:
|
||||
-1: Nothing
|
||||
0: Phoron: Phoron, Oxygen Agent B
|
||||
1: Oxygen: Oxygen ONLY
|
||||
2: Nitrogen: Nitrogen ONLY
|
||||
3: Carbon Dioxide: Carbon Dioxide ONLY
|
||||
4: Sleeping Agent (N2O)
|
||||
*/
|
||||
var/list/filtered_out = list()
|
||||
|
||||
|
||||
var/frequency = 0
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
proc
|
||||
set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
if(frequency)
|
||||
radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA)
|
||||
/obj/machinery/atmospherics/trinary/filter/proc/set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
if(frequency)
|
||||
radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA)
|
||||
|
||||
New()
|
||||
if(radio_controller)
|
||||
initialize()
|
||||
..()
|
||||
/obj/machinery/atmospherics/trinary/filter/New()
|
||||
..()
|
||||
air1.volume = ATMOS_DEFAULT_VOLUME_FILTER
|
||||
air2.volume = ATMOS_DEFAULT_VOLUME_FILTER
|
||||
air3.volume = ATMOS_DEFAULT_VOLUME_FILTER
|
||||
|
||||
if(radio_controller)
|
||||
initialize()
|
||||
|
||||
update_icon()
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "intact_off"
|
||||
else if(node2 && node3 && node1)
|
||||
icon_state = "intact_[on?("on"):("off")]"
|
||||
/obj/machinery/atmospherics/trinary/filter/update_icon()
|
||||
if(istype(src, /obj/machinery/atmospherics/trinary/filter/m_filter))
|
||||
icon_state = "m"
|
||||
else
|
||||
icon_state = ""
|
||||
|
||||
if(!powered())
|
||||
icon_state += "off"
|
||||
else if(node2 && node3 && node1)
|
||||
icon_state += on ? "on" : "off"
|
||||
else
|
||||
icon_state += "off"
|
||||
on = 0
|
||||
|
||||
/obj/machinery/atmospherics/trinary/filter/update_underlays()
|
||||
if(..())
|
||||
underlays.Cut()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T))
|
||||
return
|
||||
|
||||
add_underlay(T, node1, turn(dir, -180))
|
||||
|
||||
if(istype(src, /obj/machinery/atmospherics/trinary/filter/m_filter))
|
||||
add_underlay(T, node2, turn(dir, 90))
|
||||
else
|
||||
icon_state = "intact_off"
|
||||
on = 0
|
||||
add_underlay(T, node2, turn(dir, -90))
|
||||
|
||||
add_underlay(T, node3, dir)
|
||||
|
||||
/obj/machinery/atmospherics/trinary/filter/hide(var/i)
|
||||
update_underlays()
|
||||
|
||||
/obj/machinery/atmospherics/trinary/filter/power_change()
|
||||
var/old_stat = stat
|
||||
..()
|
||||
if(old_stat != stat)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/trinary/filter/process()
|
||||
..()
|
||||
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
|
||||
|
||||
power_change()
|
||||
var/old_stat = stat
|
||||
..()
|
||||
if(old_stat != stat)
|
||||
update_icon()
|
||||
|
||||
process()
|
||||
..()
|
||||
if(!on)
|
||||
return 0
|
||||
|
||||
var/output_starting_pressure = air3.return_pressure()
|
||||
|
||||
if(output_starting_pressure >= target_pressure || air2.return_pressure() >= target_pressure )
|
||||
//No need to mix if target is already full!
|
||||
return 1
|
||||
|
||||
//Calculate necessary moles to transfer using PV=nRT
|
||||
|
||||
var/pressure_delta = target_pressure - output_starting_pressure
|
||||
var/transfer_moles
|
||||
|
||||
if(air1.temperature > 0)
|
||||
transfer_moles = pressure_delta*air3.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
//Actually transfer the gas
|
||||
|
||||
if(transfer_moles > 0)
|
||||
var/datum/gas_mixture/removed = air1.remove(transfer_moles)
|
||||
|
||||
if(!removed)
|
||||
return
|
||||
var/datum/gas_mixture/filtered_out = new
|
||||
filtered_out.temperature = removed.temperature
|
||||
|
||||
switch(filter_type)
|
||||
if(0) //removing hydrocarbons
|
||||
filtered_out.phoron = removed.phoron
|
||||
removed.phoron = 0
|
||||
|
||||
if(removed.trace_gases.len>0)
|
||||
for(var/datum/gas/trace_gas in removed.trace_gases)
|
||||
if(istype(trace_gas, /datum/gas/oxygen_agent_b))
|
||||
removed.trace_gases -= trace_gas
|
||||
filtered_out.trace_gases += trace_gas
|
||||
|
||||
if(1) //removing O2
|
||||
filtered_out.oxygen = removed.oxygen
|
||||
removed.oxygen = 0
|
||||
|
||||
if(2) //removing N2
|
||||
filtered_out.nitrogen = removed.nitrogen
|
||||
removed.nitrogen = 0
|
||||
|
||||
if(3) //removing CO2
|
||||
filtered_out.carbon_dioxide = removed.carbon_dioxide
|
||||
removed.carbon_dioxide = 0
|
||||
|
||||
if(4)//removing N2O
|
||||
if(removed.trace_gases.len>0)
|
||||
for(var/datum/gas/trace_gas in removed.trace_gases)
|
||||
if(istype(trace_gas, /datum/gas/sleeping_agent))
|
||||
removed.trace_gases -= trace_gas
|
||||
filtered_out.trace_gases += trace_gas
|
||||
|
||||
else
|
||||
filtered_out = null
|
||||
|
||||
|
||||
air2.merge(filtered_out)
|
||||
air3.merge(removed)
|
||||
|
||||
|
||||
//Figure out the amount of moles to transfer
|
||||
var/transfer_moles = (set_flow_rate/air1.volume)*air1.total_moles
|
||||
|
||||
var/power_draw = -1
|
||||
if (transfer_moles > MINUMUM_MOLES_TO_FILTER)
|
||||
power_draw = filter_gas(src, filtered_out, air1, air2, air3, transfer_moles, active_power_usage)
|
||||
|
||||
if(network2)
|
||||
network2.update = 1
|
||||
|
||||
@@ -128,37 +107,40 @@ Filter types:
|
||||
if(network1)
|
||||
network1.update = 1
|
||||
|
||||
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)
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/atmospherics/trinary/filter/initialize()
|
||||
set_frequency(frequency)
|
||||
..()
|
||||
|
||||
/obj/machinery/atmospherics/trinary/filter/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if (!istype(W, /obj/item/weapon/wrench))
|
||||
return ..()
|
||||
var/datum/gas_mixture/int_air = return_air()
|
||||
var/datum/gas_mixture/env_air = loc.return_air()
|
||||
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
|
||||
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
|
||||
add_fingerprint(user)
|
||||
return 1
|
||||
|
||||
initialize()
|
||||
set_frequency(frequency)
|
||||
..()
|
||||
|
||||
attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if (!istype(W, /obj/item/weapon/wrench))
|
||||
return ..()
|
||||
var/turf/T = src.loc
|
||||
if (level==1 && isturf(T) && T.intact)
|
||||
user << "\red You must remove the plating first."
|
||||
return 1
|
||||
var/datum/gas_mixture/int_air = return_air()
|
||||
var/datum/gas_mixture/env_air = loc.return_air()
|
||||
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
|
||||
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
|
||||
add_fingerprint(user)
|
||||
return 1
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
user << "\blue You begin to unfasten \the [src]..."
|
||||
if (do_after(user, 40))
|
||||
user.visible_message( \
|
||||
"[user] unfastens \the [src].", \
|
||||
"\blue You have unfastened \the [src].", \
|
||||
"You hear ratchet.")
|
||||
new /obj/item/pipe(loc, make_from=src)
|
||||
del(src)
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
user << "\blue You begin to unfasten \the [src]..."
|
||||
if (do_after(user, 40))
|
||||
user.visible_message( \
|
||||
"[user] unfastens \the [src].", \
|
||||
"\blue You have unfastened \the [src].", \
|
||||
"You hear ratchet.")
|
||||
new /obj/item/pipe(loc, make_from=src)
|
||||
del(src)
|
||||
|
||||
|
||||
obj/machinery/atmospherics/trinary/filter/attack_hand(user as mob) // -- TLE
|
||||
/obj/machinery/atmospherics/trinary/filter/attack_hand(user as mob) // -- TLE
|
||||
if(..())
|
||||
return
|
||||
|
||||
@@ -194,8 +176,10 @@ obj/machinery/atmospherics/trinary/filter/attack_hand(user as mob) // -- TLE
|
||||
<A href='?src=\ref[src];filterset=3'>Carbon Dioxide</A><BR>
|
||||
<A href='?src=\ref[src];filterset=4'>Nitrous Oxide</A><BR>
|
||||
<A href='?src=\ref[src];filterset=-1'>Nothing</A><BR>
|
||||
<HR><B>Desirable output pressure:</B>
|
||||
[src.target_pressure]kPa | <a href='?src=\ref[src];set_press=1'>Change</a>
|
||||
<HR>
|
||||
<B>Set Flow Rate Limit:</B>
|
||||
[src.set_flow_rate]L/s | <a href='?src=\ref[src];set_flow_rate=1'>Change</a><BR>
|
||||
<B>Flow rate: </B>[round(last_flow_rate, 0.1)]L/s
|
||||
"}
|
||||
/*
|
||||
user << browse("<HEAD><TITLE>[src.name] control</TITLE></HEAD>[dat]","window=atmo_filter")
|
||||
@@ -211,18 +195,33 @@ obj/machinery/atmospherics/trinary/filter/attack_hand(user as mob) // -- TLE
|
||||
onclose(user, "atmo_filter")
|
||||
return
|
||||
|
||||
obj/machinery/atmospherics/trinary/filter/Topic(href, href_list) // -- TLE
|
||||
/obj/machinery/atmospherics/trinary/filter/Topic(href, href_list) // -- TLE
|
||||
if(..())
|
||||
return
|
||||
usr.set_machine(src)
|
||||
src.add_fingerprint(usr)
|
||||
if(href_list["filterset"])
|
||||
src.filter_type = text2num(href_list["filterset"])
|
||||
filter_type = text2num(href_list["filterset"])
|
||||
|
||||
filtered_out.Cut() //no need to create new lists unnecessarily
|
||||
switch(filter_type)
|
||||
if(0) //removing hydrocarbons
|
||||
filtered_out += "phoron"
|
||||
filtered_out += "oxygen_agent_b"
|
||||
if(1) //removing O2
|
||||
filtered_out += "oxygen"
|
||||
if(2) //removing N2
|
||||
filtered_out += "nitrogen"
|
||||
if(3) //removing CO2
|
||||
filtered_out += "carbon_dioxide"
|
||||
if(4)//removing N2O
|
||||
filtered_out += "sleeping_agent"
|
||||
|
||||
if (href_list["temp"])
|
||||
src.temp = null
|
||||
if(href_list["set_press"])
|
||||
var/new_pressure = input(usr,"Enter new output pressure (0-4500kPa)","Pressure control",src.target_pressure) as num
|
||||
src.target_pressure = max(0, min(4500, new_pressure))
|
||||
if(href_list["set_flow_rate"])
|
||||
var/new_flow_rate = input(usr,"Enter new flow rate (0-[air1.volume]L/s)","Flow Rate Control",src.set_flow_rate) as num
|
||||
src.set_flow_rate = max(0, min(air1.volume, new_flow_rate))
|
||||
if(href_list["power"])
|
||||
on=!on
|
||||
src.update_icon()
|
||||
@@ -234,9 +233,8 @@ obj/machinery/atmospherics/trinary/filter/Topic(href, href_list) // -- TLE
|
||||
*/
|
||||
return
|
||||
|
||||
obj/machinery/atmospherics/trinary/filter/m_filter
|
||||
icon = 'icons/obj/atmospherics/m_filter.dmi'
|
||||
icon_state = "intact_off"
|
||||
/obj/machinery/atmospherics/trinary/filter/m_filter
|
||||
icon_state = "mmap"
|
||||
|
||||
dir = SOUTH
|
||||
initialize_directions = SOUTH|NORTH|EAST
|
||||
@@ -253,7 +251,9 @@ obj/machinery/atmospherics/trinary/filter/m_filter/New()
|
||||
if(WEST)
|
||||
initialize_directions = WEST|SOUTH|EAST
|
||||
|
||||
obj/machinery/atmospherics/trinary/filter/m_filter/initialize()
|
||||
/obj/machinery/atmospherics/trinary/filter/m_filter/initialize()
|
||||
set_frequency(frequency)
|
||||
|
||||
if(node1 && node2 && node3) return
|
||||
|
||||
var/node1_connect = turn(dir, -180)
|
||||
@@ -276,3 +276,4 @@ obj/machinery/atmospherics/trinary/filter/m_filter/initialize()
|
||||
break
|
||||
|
||||
update_icon()
|
||||
update_underlays()
|
||||
|
||||
@@ -1,169 +1,185 @@
|
||||
obj/machinery/atmospherics/trinary/mixer
|
||||
icon = 'icons/obj/atmospherics/mixer.dmi'
|
||||
icon_state = "intact_off"
|
||||
/obj/machinery/atmospherics/trinary/mixer
|
||||
icon = 'icons/atmos/mixer.dmi'
|
||||
icon_state = "map"
|
||||
density = 0
|
||||
level = 1
|
||||
|
||||
name = "Gas mixer"
|
||||
|
||||
var/on = 0
|
||||
use_power = 1
|
||||
idle_power_usage = 150 //internal circuitry, friction losses and stuff
|
||||
active_power_usage = 3700 //This also doubles as a measure of how powerful the mixer is, in Watts. 3700 W ~ 5 HP
|
||||
|
||||
var/target_pressure = ONE_ATMOSPHERE
|
||||
var/set_flow_rate = ATMOS_DEFAULT_VOLUME_MIXER
|
||||
var/list/mixing_inputs
|
||||
|
||||
//for mapping
|
||||
var/node1_concentration = 0.5
|
||||
var/node2_concentration = 0.5
|
||||
|
||||
//node 3 is the outlet, nodes 1 & 2 are intakes
|
||||
|
||||
update_icon()
|
||||
if(stat & NOPOWER)
|
||||
icon_state = "intact_off"
|
||||
else if(node2 && node3 && node1)
|
||||
icon_state = "intact_[on?("on"):("off")]"
|
||||
/obj/machinery/atmospherics/trinary/mixer/update_icon(var/safety = 0)
|
||||
if(istype(src, /obj/machinery/atmospherics/trinary/mixer/m_mixer))
|
||||
icon_state = "m"
|
||||
else if(istype(src, /obj/machinery/atmospherics/trinary/mixer/t_mixer))
|
||||
icon_state = "t"
|
||||
else
|
||||
icon_state = ""
|
||||
|
||||
if(!powered())
|
||||
icon_state += "off"
|
||||
else if(node2 && node3 && node1)
|
||||
icon_state += on ? "on" : "off"
|
||||
else
|
||||
icon_state += "off"
|
||||
on = 0
|
||||
|
||||
/obj/machinery/atmospherics/trinary/mixer/update_underlays()
|
||||
if(..())
|
||||
underlays.Cut()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T))
|
||||
return
|
||||
|
||||
if(istype(src, /obj/machinery/atmospherics/trinary/mixer/t_mixer))
|
||||
add_underlay(T, node1, turn(dir, -90))
|
||||
else
|
||||
icon_state = "intact_off"
|
||||
on = 0
|
||||
add_underlay(T, node1, turn(dir, -180))
|
||||
|
||||
if(istype(src, /obj/machinery/atmospherics/trinary/mixer/m_mixer) || istype(src, /obj/machinery/atmospherics/trinary/mixer/t_mixer))
|
||||
add_underlay(T, node2, turn(dir, 90))
|
||||
else
|
||||
add_underlay(T, node2, turn(dir, -90))
|
||||
|
||||
add_underlay(T, node3, dir)
|
||||
|
||||
/obj/machinery/atmospherics/trinary/mixer/hide(var/i)
|
||||
update_underlays()
|
||||
|
||||
/obj/machinery/atmospherics/trinary/mixer/power_change()
|
||||
var/old_stat = stat
|
||||
..()
|
||||
if(old_stat != stat)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/trinary/mixer/New()
|
||||
..()
|
||||
air1.volume = ATMOS_DEFAULT_VOLUME_MIXER
|
||||
air2.volume = ATMOS_DEFAULT_VOLUME_MIXER
|
||||
air3.volume = ATMOS_DEFAULT_VOLUME_MIXER * 1.5
|
||||
|
||||
/obj/machinery/atmospherics/trinary/mixer/process()
|
||||
..()
|
||||
|
||||
//For some reason this doesn't work even in initialize(), so it goes here.
|
||||
if (!mixing_inputs)
|
||||
mixing_inputs = list(src.air1 = node1_concentration, src.air2 = node2_concentration)
|
||||
|
||||
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
|
||||
|
||||
power_change()
|
||||
var/old_stat = stat
|
||||
..()
|
||||
if(old_stat != stat)
|
||||
update_icon()
|
||||
|
||||
New()
|
||||
..()
|
||||
air3.volume = 300
|
||||
|
||||
process()
|
||||
..()
|
||||
if(!on)
|
||||
return 0
|
||||
|
||||
var/output_starting_pressure = air3.return_pressure()
|
||||
|
||||
if(output_starting_pressure >= target_pressure)
|
||||
//No need to mix if target is already full!
|
||||
return 1
|
||||
|
||||
//Calculate necessary moles to transfer using PV=nRT
|
||||
|
||||
var/pressure_delta = target_pressure - output_starting_pressure
|
||||
var/transfer_moles1 = 0
|
||||
var/transfer_moles2 = 0
|
||||
|
||||
if(air1.temperature > 0)
|
||||
transfer_moles1 = (node1_concentration*pressure_delta)*air3.volume/(air1.temperature * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
if(air2.temperature > 0)
|
||||
transfer_moles2 = (node2_concentration*pressure_delta)*air3.volume/(air2.temperature * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
var/air1_moles = air1.total_moles()
|
||||
var/air2_moles = air2.total_moles()
|
||||
|
||||
if((air1_moles < transfer_moles1) || (air2_moles < transfer_moles2))
|
||||
if(!transfer_moles1 || !transfer_moles2) return
|
||||
var/ratio = min(air1_moles/transfer_moles1, air2_moles/transfer_moles2)
|
||||
|
||||
transfer_moles1 *= ratio
|
||||
transfer_moles2 *= ratio
|
||||
|
||||
//Actually transfer the gas
|
||||
|
||||
if(transfer_moles1 > 0)
|
||||
var/datum/gas_mixture/removed1 = air1.remove(transfer_moles1)
|
||||
air3.merge(removed1)
|
||||
|
||||
if(transfer_moles2 > 0)
|
||||
var/datum/gas_mixture/removed2 = air2.remove(transfer_moles2)
|
||||
air3.merge(removed2)
|
||||
|
||||
if(network1 && transfer_moles1)
|
||||
|
||||
//Figure out the amount of moles to transfer
|
||||
var/transfer_moles = (set_flow_rate*mixing_inputs[air1]/air1.volume)*air1.total_moles + (set_flow_rate*mixing_inputs[air1]/air2.volume)*air2.total_moles
|
||||
|
||||
var/power_draw = -1
|
||||
if (transfer_moles > MINUMUM_MOLES_TO_FILTER)
|
||||
power_draw = mix_gas(src, mixing_inputs, air3, transfer_moles, active_power_usage)
|
||||
|
||||
if(network1 && mixing_inputs[air1])
|
||||
network1.update = 1
|
||||
|
||||
if(network2 && transfer_moles2)
|
||||
if(network2 && mixing_inputs[air2])
|
||||
network2.update = 1
|
||||
|
||||
if(network3)
|
||||
network3.update = 1
|
||||
|
||||
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)
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/atmospherics/trinary/mixer/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if (!istype(W, /obj/item/weapon/wrench))
|
||||
return ..()
|
||||
var/datum/gas_mixture/int_air = return_air()
|
||||
var/datum/gas_mixture/env_air = loc.return_air()
|
||||
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
|
||||
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
|
||||
add_fingerprint(user)
|
||||
return 1
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
user << "\blue You begin to unfasten \the [src]..."
|
||||
if (do_after(user, 40))
|
||||
user.visible_message( \
|
||||
"[user] unfastens \the [src].", \
|
||||
"\blue You have unfastened \the [src].", \
|
||||
"You hear ratchet.")
|
||||
new /obj/item/pipe(loc, make_from=src)
|
||||
del(src)
|
||||
|
||||
attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if (!istype(W, /obj/item/weapon/wrench))
|
||||
return ..()
|
||||
var/turf/T = src.loc
|
||||
if (level==1 && isturf(T) && T.intact)
|
||||
user << "\red You must remove the plating first."
|
||||
return 1
|
||||
var/datum/gas_mixture/int_air = return_air()
|
||||
var/datum/gas_mixture/env_air = loc.return_air()
|
||||
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
|
||||
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
|
||||
add_fingerprint(user)
|
||||
return 1
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
user << "\blue You begin to unfasten \the [src]..."
|
||||
if (do_after(user, 40))
|
||||
user.visible_message( \
|
||||
"[user] unfastens \the [src].", \
|
||||
"\blue You have unfastened \the [src].", \
|
||||
"You hear ratchet.")
|
||||
new /obj/item/pipe(loc, make_from=src)
|
||||
del(src)
|
||||
|
||||
attack_hand(user as mob)
|
||||
if(..())
|
||||
return
|
||||
src.add_fingerprint(usr)
|
||||
if(!src.allowed(user))
|
||||
user << "\red Access denied."
|
||||
return
|
||||
usr.set_machine(src)
|
||||
var/dat = {"<b>Power: </b><a href='?src=\ref[src];power=1'>[on?"On":"Off"]</a><br>
|
||||
<b>Desirable output pressure: </b>
|
||||
[target_pressure]kPa | <a href='?src=\ref[src];set_press=1'>Change</a>
|
||||
<br>
|
||||
<b>Node 1 Concentration:</b>
|
||||
<a href='?src=\ref[src];node1_c=-0.1'><b>-</b></a>
|
||||
<a href='?src=\ref[src];node1_c=-0.01'>-</a>
|
||||
[node1_concentration]([node1_concentration*100]%)
|
||||
<a href='?src=\ref[src];node1_c=0.01'><b>+</b></a>
|
||||
<a href='?src=\ref[src];node1_c=0.1'>+</a>
|
||||
<br>
|
||||
<b>Node 2 Concentration:</b>
|
||||
<a href='?src=\ref[src];node2_c=-0.1'><b>-</b></a>
|
||||
<a href='?src=\ref[src];node2_c=-0.01'>-</a>
|
||||
[node2_concentration]([node2_concentration*100]%)
|
||||
<a href='?src=\ref[src];node2_c=0.01'><b>+</b></a>
|
||||
<a href='?src=\ref[src];node2_c=0.1'>+</a>
|
||||
"}
|
||||
|
||||
user << browse("<HEAD><TITLE>[src.name] control</TITLE></HEAD><TT>[dat]</TT>", "window=atmo_mixer")
|
||||
onclose(user, "atmo_mixer")
|
||||
/obj/machinery/atmospherics/trinary/mixer/attack_hand(user as mob)
|
||||
if(..())
|
||||
return
|
||||
|
||||
Topic(href,href_list)
|
||||
if(..()) return
|
||||
if(href_list["power"])
|
||||
on = !on
|
||||
if(href_list["set_press"])
|
||||
var/new_pressure = input(usr,"Enter new output pressure (0-4500kPa)","Pressure control",src.target_pressure) as num
|
||||
src.target_pressure = max(0, min(4500, new_pressure))
|
||||
if(href_list["node1_c"])
|
||||
var/value = text2num(href_list["node1_c"])
|
||||
src.node1_concentration = max(0, min(1, src.node1_concentration + value))
|
||||
src.node2_concentration = max(0, min(1, src.node2_concentration - value))
|
||||
if(href_list["node2_c"])
|
||||
var/value = text2num(href_list["node2_c"])
|
||||
src.node2_concentration = max(0, min(1, src.node2_concentration + value))
|
||||
src.node1_concentration = max(0, min(1, src.node1_concentration - value))
|
||||
src.update_icon()
|
||||
src.updateUsrDialog()
|
||||
src.add_fingerprint(usr)
|
||||
if(!src.allowed(user))
|
||||
user << "\red Access denied."
|
||||
return
|
||||
usr.set_machine(src)
|
||||
var/dat = {"<b>Power: </b><a href='?src=\ref[src];power=1'>[on?"On":"Off"]</a><br>
|
||||
<b>Set Flow Rate Limit: </b>
|
||||
[set_flow_rate]L/s | <a href='?src=\ref[src];set_press=1'>Change</a>
|
||||
<br>
|
||||
<b>Flow Rate: </b>[round(last_flow_rate, 0.1)]L/s
|
||||
<br><hr>
|
||||
<b>Node 1 Concentration:</b>
|
||||
<a href='?src=\ref[src];node1_c=-0.1'><b>-</b></a>
|
||||
<a href='?src=\ref[src];node1_c=-0.01'>-</a>
|
||||
[mixing_inputs[air1]]([mixing_inputs[air1]*100]%)
|
||||
<a href='?src=\ref[src];node1_c=0.01'><b>+</b></a>
|
||||
<a href='?src=\ref[src];node1_c=0.1'>+</a>
|
||||
<br>
|
||||
<b>Node 2 Concentration:</b>
|
||||
<a href='?src=\ref[src];node2_c=-0.1'><b>-</b></a>
|
||||
<a href='?src=\ref[src];node2_c=-0.01'>-</a>
|
||||
[mixing_inputs[air2]]([mixing_inputs[air2]*100]%)
|
||||
<a href='?src=\ref[src];node2_c=0.01'><b>+</b></a>
|
||||
<a href='?src=\ref[src];node2_c=0.1'>+</a>
|
||||
"}
|
||||
|
||||
user << browse("<HEAD><TITLE>[src.name] control</TITLE></HEAD><TT>[dat]</TT>", "window=atmo_mixer")
|
||||
onclose(user, "atmo_mixer")
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/trinary/mixer/Topic(href,href_list)
|
||||
if(..()) return
|
||||
if(href_list["power"])
|
||||
on = !on
|
||||
if(href_list["set_press"])
|
||||
var/max_flow_rate = min(air1.volume, air2.volume)
|
||||
var/new_flow_rate = input(usr,"Enter new flow rate limit (0-[max_flow_rate]L/s)","Flow Rate Control",src.set_flow_rate) as num
|
||||
src.set_flow_rate = max(0, min(max_flow_rate, new_flow_rate))
|
||||
if(href_list["node1_c"])
|
||||
var/value = text2num(href_list["node1_c"])
|
||||
src.mixing_inputs[air1] = max(0, min(1, src.mixing_inputs[air1] + value))
|
||||
src.mixing_inputs[air2] = 1.0 - mixing_inputs[air1]
|
||||
if(href_list["node2_c"])
|
||||
var/value = text2num(href_list["node2_c"])
|
||||
src.mixing_inputs[air2] = max(0, min(1, src.mixing_inputs[air2] + value))
|
||||
src.mixing_inputs[air1] = 1.0 - mixing_inputs[air2]
|
||||
src.update_icon()
|
||||
src.updateUsrDialog()
|
||||
return
|
||||
|
||||
obj/machinery/atmospherics/trinary/mixer/t_mixer
|
||||
icon = 'icons/obj/atmospherics/t_mixer.dmi'
|
||||
icon_state = "intact_off"
|
||||
icon_state = "tmap"
|
||||
|
||||
dir = SOUTH
|
||||
initialize_directions = SOUTH|EAST|WEST
|
||||
@@ -183,6 +199,7 @@ obj/machinery/atmospherics/trinary/mixer/t_mixer/New()
|
||||
initialize_directions = WEST|NORTH|SOUTH
|
||||
|
||||
obj/machinery/atmospherics/trinary/mixer/t_mixer/initialize()
|
||||
..()
|
||||
if(node1 && node2 && node3) return
|
||||
|
||||
var/node1_connect = turn(dir, -90)
|
||||
@@ -205,10 +222,10 @@ obj/machinery/atmospherics/trinary/mixer/t_mixer/initialize()
|
||||
break
|
||||
|
||||
update_icon()
|
||||
update_underlays()
|
||||
|
||||
obj/machinery/atmospherics/trinary/mixer/m_mixer
|
||||
icon = 'icons/obj/atmospherics/m_mixer.dmi'
|
||||
icon_state = "intact_off"
|
||||
icon_state = "mmap"
|
||||
|
||||
dir = SOUTH
|
||||
initialize_directions = SOUTH|NORTH|EAST
|
||||
@@ -228,6 +245,7 @@ obj/machinery/atmospherics/trinary/mixer/m_mixer/New()
|
||||
initialize_directions = WEST|SOUTH|EAST
|
||||
|
||||
obj/machinery/atmospherics/trinary/mixer/m_mixer/initialize()
|
||||
..()
|
||||
if(node1 && node2 && node3) return
|
||||
|
||||
var/node1_connect = turn(dir, -180)
|
||||
@@ -249,4 +267,5 @@ obj/machinery/atmospherics/trinary/mixer/m_mixer/initialize()
|
||||
node3 = target
|
||||
break
|
||||
|
||||
update_icon()
|
||||
update_icon()
|
||||
update_underlays()
|
||||
|
||||
@@ -2,6 +2,8 @@ obj/machinery/atmospherics/trinary
|
||||
dir = SOUTH
|
||||
initialize_directions = SOUTH|NORTH|WEST
|
||||
use_power = 1
|
||||
|
||||
var/on = 0
|
||||
|
||||
var/datum/gas_mixture/air1
|
||||
var/datum/gas_mixture/air2
|
||||
@@ -94,6 +96,7 @@ obj/machinery/atmospherics/trinary
|
||||
break
|
||||
|
||||
update_icon()
|
||||
update_underlays()
|
||||
|
||||
build_network()
|
||||
if(!network1 && node1)
|
||||
@@ -160,5 +163,7 @@ obj/machinery/atmospherics/trinary
|
||||
else if(reference==node3)
|
||||
del(network3)
|
||||
node3 = null
|
||||
|
||||
update_underlays()
|
||||
|
||||
return null
|
||||
@@ -1,10 +1,11 @@
|
||||
obj/machinery/atmospherics/tvalve
|
||||
icon = 'icons/obj/atmospherics/valve.dmi'
|
||||
icon_state = "tvalve0"
|
||||
/obj/machinery/atmospherics/tvalve
|
||||
icon = 'icons/atmos/tvalve.dmi'
|
||||
icon_state = "map_tvalve0"
|
||||
|
||||
name = "manual switching valve"
|
||||
desc = "A pipe valve"
|
||||
|
||||
level = 1
|
||||
dir = SOUTH
|
||||
initialize_directions = SOUTH|NORTH|WEST
|
||||
|
||||
@@ -19,415 +20,466 @@ obj/machinery/atmospherics/tvalve
|
||||
var/datum/pipe_network/network_node2
|
||||
var/datum/pipe_network/network_node3
|
||||
|
||||
update_icon(animation)
|
||||
if(animation)
|
||||
flick("tvalve[src.state][!src.state]",src)
|
||||
/obj/machinery/atmospherics/tvalve/bypass
|
||||
icon_state = "map_tvalve1"
|
||||
state = 1
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/update_icon(animation)
|
||||
if(animation)
|
||||
flick("tvalve[src.state][!src.state]",src)
|
||||
else
|
||||
icon_state = "tvalve[state]"
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/update_underlays()
|
||||
if(..())
|
||||
underlays.Cut()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T))
|
||||
return
|
||||
add_underlay(T, node1, turn(dir, -180))
|
||||
|
||||
if(istype(src, /obj/machinery/atmospherics/tvalve/mirrored))
|
||||
add_underlay(T, node2, turn(dir, 90))
|
||||
else
|
||||
icon_state = "tvalve[state]"
|
||||
add_underlay(T, node2, turn(dir, -90))
|
||||
|
||||
add_underlay(T, node3, dir)
|
||||
|
||||
New()
|
||||
initialize_directions()
|
||||
..()
|
||||
|
||||
proc/initialize_directions()
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
initialize_directions = SOUTH|NORTH|EAST
|
||||
if(SOUTH)
|
||||
initialize_directions = NORTH|SOUTH|WEST
|
||||
if(EAST)
|
||||
initialize_directions = WEST|EAST|SOUTH
|
||||
if(WEST)
|
||||
initialize_directions = EAST|WEST|NORTH
|
||||
|
||||
network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
|
||||
if(reference == node1)
|
||||
network_node1 = new_network
|
||||
if(state)
|
||||
network_node2 = new_network
|
||||
else
|
||||
network_node3 = new_network
|
||||
else if(reference == node2)
|
||||
network_node2 = new_network
|
||||
if(state)
|
||||
network_node1 = new_network
|
||||
else if(reference == node3)
|
||||
network_node3 = new_network
|
||||
if(!state)
|
||||
network_node1 = new_network
|
||||
|
||||
if(new_network.normal_members.Find(src))
|
||||
return 0
|
||||
|
||||
new_network.normal_members += src
|
||||
|
||||
if(state)
|
||||
if(reference == node1)
|
||||
if(node2)
|
||||
return node2.network_expand(new_network, src)
|
||||
else if(reference == node2)
|
||||
if(node1)
|
||||
return node1.network_expand(new_network, src)
|
||||
else
|
||||
if(reference == node1)
|
||||
if(node3)
|
||||
return node3.network_expand(new_network, src)
|
||||
else if(reference == node3)
|
||||
if(node1)
|
||||
return node1.network_expand(new_network, src)
|
||||
|
||||
return null
|
||||
|
||||
Del()
|
||||
loc = null
|
||||
|
||||
if(node1)
|
||||
node1.disconnect(src)
|
||||
del(network_node1)
|
||||
if(node2)
|
||||
node2.disconnect(src)
|
||||
del(network_node2)
|
||||
if(node3)
|
||||
node3.disconnect(src)
|
||||
del(network_node3)
|
||||
|
||||
node1 = null
|
||||
node2 = null
|
||||
node3 = null
|
||||
|
||||
..()
|
||||
|
||||
proc/go_to_side()
|
||||
|
||||
if(state) return 0
|
||||
|
||||
state = 1
|
||||
update_icon()
|
||||
|
||||
if(network_node1)
|
||||
del(network_node1)
|
||||
if(network_node3)
|
||||
del(network_node3)
|
||||
build_network()
|
||||
|
||||
if(network_node1&&network_node2)
|
||||
network_node1.merge(network_node2)
|
||||
network_node2 = network_node1
|
||||
|
||||
if(network_node1)
|
||||
network_node1.update = 1
|
||||
else if(network_node2)
|
||||
network_node2.update = 1
|
||||
|
||||
return 1
|
||||
|
||||
proc/go_straight()
|
||||
|
||||
if(!state)
|
||||
return 0
|
||||
|
||||
state = 0
|
||||
update_icon()
|
||||
|
||||
if(network_node1)
|
||||
del(network_node1)
|
||||
if(network_node2)
|
||||
del(network_node2)
|
||||
build_network()
|
||||
|
||||
if(network_node1&&network_node3)
|
||||
network_node1.merge(network_node3)
|
||||
network_node3 = network_node1
|
||||
|
||||
if(network_node1)
|
||||
network_node1.update = 1
|
||||
else if(network_node3)
|
||||
network_node3.update = 1
|
||||
|
||||
return 1
|
||||
|
||||
attack_ai(mob/user as mob)
|
||||
return
|
||||
|
||||
attack_paw(mob/user as mob)
|
||||
return attack_hand(user)
|
||||
|
||||
attack_hand(mob/user as mob)
|
||||
src.add_fingerprint(usr)
|
||||
update_icon(1)
|
||||
sleep(10)
|
||||
if (src.state)
|
||||
src.go_straight()
|
||||
else
|
||||
src.go_to_side()
|
||||
|
||||
process()
|
||||
..()
|
||||
machines.Remove(src)
|
||||
|
||||
/* if(open && (!node1 || !node2))
|
||||
close()
|
||||
if(!node1)
|
||||
if(!nodealert)
|
||||
//world << "Missing node from [src] at [src.x],[src.y],[src.z]"
|
||||
nodealert = 1
|
||||
else if (!node2)
|
||||
if(!nodealert)
|
||||
//world << "Missing node from [src] at [src.x],[src.y],[src.z]"
|
||||
nodealert = 1
|
||||
else if (nodealert)
|
||||
nodealert = 0
|
||||
*/
|
||||
|
||||
return
|
||||
|
||||
initialize()
|
||||
var/node1_dir
|
||||
var/node2_dir
|
||||
var/node3_dir
|
||||
|
||||
node1_dir = turn(dir, 180)
|
||||
node2_dir = turn(dir, -90)
|
||||
node3_dir = dir
|
||||
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node1_dir))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node1 = target
|
||||
break
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node2_dir))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node2 = target
|
||||
break
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node3_dir))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node3 = target
|
||||
break
|
||||
|
||||
build_network()
|
||||
if(!network_node1 && node1)
|
||||
network_node1 = new /datum/pipe_network()
|
||||
network_node1.normal_members += src
|
||||
network_node1.build_network(node1, src)
|
||||
|
||||
if(!network_node2 && node2)
|
||||
network_node2 = new /datum/pipe_network()
|
||||
network_node2.normal_members += src
|
||||
network_node2.build_network(node2, src)
|
||||
|
||||
if(!network_node3 && node3)
|
||||
network_node3 = new /datum/pipe_network()
|
||||
network_node3.normal_members += src
|
||||
network_node3.build_network(node3, src)
|
||||
|
||||
|
||||
return_network(obj/machinery/atmospherics/reference)
|
||||
build_network()
|
||||
|
||||
if(reference==node1)
|
||||
return network_node1
|
||||
|
||||
if(reference==node2)
|
||||
return network_node2
|
||||
|
||||
if(reference==node3)
|
||||
return network_node3
|
||||
|
||||
return null
|
||||
|
||||
reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
|
||||
if(network_node1 == old_network)
|
||||
network_node1 = new_network
|
||||
if(network_node2 == old_network)
|
||||
network_node2 = new_network
|
||||
if(network_node3 == old_network)
|
||||
network_node3 = new_network
|
||||
|
||||
return 1
|
||||
|
||||
return_network_air(datum/network/reference)
|
||||
return null
|
||||
|
||||
disconnect(obj/machinery/atmospherics/reference)
|
||||
if(reference==node1)
|
||||
del(network_node1)
|
||||
node1 = null
|
||||
|
||||
else if(reference==node2)
|
||||
del(network_node2)
|
||||
node2 = null
|
||||
|
||||
else if(reference==node3)
|
||||
del(network_node3)
|
||||
node2 = null
|
||||
|
||||
return null
|
||||
|
||||
digital // can be controlled by AI
|
||||
name = "digital switching valve"
|
||||
desc = "A digitally controlled valve."
|
||||
icon = 'icons/obj/atmospherics/digital_valve.dmi'
|
||||
|
||||
attack_ai(mob/user as mob)
|
||||
return src.attack_hand(user)
|
||||
|
||||
attack_hand(mob/user as mob)
|
||||
if(!src.allowed(user))
|
||||
user << "\red Access denied."
|
||||
return
|
||||
..()
|
||||
|
||||
//Radio remote control
|
||||
|
||||
proc
|
||||
set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
if(frequency)
|
||||
radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA)
|
||||
|
||||
var/frequency = 0
|
||||
var/id = null
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
initialize()
|
||||
..()
|
||||
if(frequency)
|
||||
set_frequency(frequency)
|
||||
|
||||
receive_signal(datum/signal/signal)
|
||||
if(!signal.data["tag"] || (signal.data["tag"] != id))
|
||||
return 0
|
||||
|
||||
switch(signal.data["command"])
|
||||
if("valve_open")
|
||||
if(!state)
|
||||
go_to_side()
|
||||
|
||||
if("valve_close")
|
||||
if(state)
|
||||
go_straight()
|
||||
|
||||
if("valve_toggle")
|
||||
if(state)
|
||||
go_straight()
|
||||
else
|
||||
go_to_side()
|
||||
|
||||
attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if (!istype(W, /obj/item/weapon/wrench))
|
||||
return ..()
|
||||
if (istype(src, /obj/machinery/atmospherics/tvalve/digital))
|
||||
user << "\red You cannot unwrench this [src], it's too complicated."
|
||||
return 1
|
||||
var/turf/T = src.loc
|
||||
if (level==1 && isturf(T) && T.intact)
|
||||
user << "\red You must remove the plating first."
|
||||
return 1
|
||||
var/datum/gas_mixture/int_air = return_air()
|
||||
var/datum/gas_mixture/env_air = loc.return_air()
|
||||
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
|
||||
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
|
||||
add_fingerprint(user)
|
||||
return 1
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
user << "\blue You begin to unfasten \the [src]..."
|
||||
if (do_after(user, 40))
|
||||
user.visible_message( \
|
||||
"[user] unfastens \the [src].", \
|
||||
"\blue You have unfastened \the [src].", \
|
||||
"You hear ratchet.")
|
||||
new /obj/item/pipe(loc, make_from=src)
|
||||
del(src)
|
||||
|
||||
obj/machinery/atmospherics/tvalve/mirrored
|
||||
icon_state = "tvalvem0"
|
||||
/obj/machinery/atmospherics/tvalve/hide(var/i)
|
||||
update_underlays()
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/New()
|
||||
initialize_directions()
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
initialize_directions = SOUTH|NORTH|WEST
|
||||
if(SOUTH)
|
||||
initialize_directions = NORTH|SOUTH|EAST
|
||||
if(EAST)
|
||||
initialize_directions = WEST|EAST|NORTH
|
||||
if(WEST)
|
||||
initialize_directions = EAST|WEST|SOUTH
|
||||
..()
|
||||
|
||||
initialize()
|
||||
var/node1_dir
|
||||
var/node2_dir
|
||||
var/node3_dir
|
||||
/obj/machinery/atmospherics/tvalve/proc/initialize_directions()
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
initialize_directions = SOUTH|NORTH|EAST
|
||||
if(SOUTH)
|
||||
initialize_directions = NORTH|SOUTH|WEST
|
||||
if(EAST)
|
||||
initialize_directions = WEST|EAST|SOUTH
|
||||
if(WEST)
|
||||
initialize_directions = EAST|WEST|NORTH
|
||||
|
||||
node1_dir = turn(dir, 180)
|
||||
node2_dir = turn(dir, 90)
|
||||
node3_dir = dir
|
||||
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node1_dir))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node1 = target
|
||||
break
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node2_dir))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node2 = target
|
||||
break
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node3_dir))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node3 = target
|
||||
break
|
||||
|
||||
update_icon(animation)
|
||||
if(animation)
|
||||
flick("tvalvem[src.state][!src.state]",src)
|
||||
/obj/machinery/atmospherics/tvalve/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
|
||||
if(reference == node1)
|
||||
network_node1 = new_network
|
||||
if(state)
|
||||
network_node2 = new_network
|
||||
else
|
||||
icon_state = "tvalvem[state]"
|
||||
network_node3 = new_network
|
||||
else if(reference == node2)
|
||||
network_node2 = new_network
|
||||
if(state)
|
||||
network_node1 = new_network
|
||||
else if(reference == node3)
|
||||
network_node3 = new_network
|
||||
if(!state)
|
||||
network_node1 = new_network
|
||||
|
||||
digital // can be controlled by AI
|
||||
name = "digital switching valve"
|
||||
desc = "A digitally controlled valve."
|
||||
icon = 'icons/obj/atmospherics/digital_valve.dmi'
|
||||
if(new_network.normal_members.Find(src))
|
||||
return 0
|
||||
|
||||
attack_ai(mob/user as mob)
|
||||
return src.attack_hand(user)
|
||||
new_network.normal_members += src
|
||||
|
||||
attack_hand(mob/user as mob)
|
||||
if(!src.allowed(user))
|
||||
user << "\red Access denied."
|
||||
return
|
||||
..()
|
||||
if(state)
|
||||
if(reference == node1)
|
||||
if(node2)
|
||||
return node2.network_expand(new_network, src)
|
||||
else if(reference == node2)
|
||||
if(node1)
|
||||
return node1.network_expand(new_network, src)
|
||||
else
|
||||
if(reference == node1)
|
||||
if(node3)
|
||||
return node3.network_expand(new_network, src)
|
||||
else if(reference == node3)
|
||||
if(node1)
|
||||
return node1.network_expand(new_network, src)
|
||||
|
||||
//Radio remote control -eh?
|
||||
return null
|
||||
|
||||
proc
|
||||
set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
if(frequency)
|
||||
radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA)
|
||||
/obj/machinery/atmospherics/tvalve/Del()
|
||||
loc = null
|
||||
|
||||
var/frequency = 0
|
||||
var/id = null
|
||||
var/datum/radio_frequency/radio_connection
|
||||
if(node1)
|
||||
node1.disconnect(src)
|
||||
del(network_node1)
|
||||
if(node2)
|
||||
node2.disconnect(src)
|
||||
del(network_node2)
|
||||
if(node3)
|
||||
node3.disconnect(src)
|
||||
del(network_node3)
|
||||
|
||||
initialize()
|
||||
..()
|
||||
if(frequency)
|
||||
set_frequency(frequency)
|
||||
node1 = null
|
||||
node2 = null
|
||||
node3 = null
|
||||
|
||||
receive_signal(datum/signal/signal)
|
||||
if(!signal.data["tag"] || (signal.data["tag"] != id))
|
||||
return 0
|
||||
..()
|
||||
|
||||
switch(signal.data["command"])
|
||||
if("valve_open")
|
||||
if(!state)
|
||||
go_to_side()
|
||||
/obj/machinery/atmospherics/tvalve/proc/go_to_side()
|
||||
|
||||
if("valve_close")
|
||||
if(state)
|
||||
go_straight()
|
||||
if(state) return 0
|
||||
|
||||
if("valve_toggle")
|
||||
if(state)
|
||||
go_straight()
|
||||
else
|
||||
go_to_side()
|
||||
state = 1
|
||||
update_icon()
|
||||
|
||||
if(network_node1)
|
||||
del(network_node1)
|
||||
if(network_node3)
|
||||
del(network_node3)
|
||||
build_network()
|
||||
|
||||
if(network_node1&&network_node2)
|
||||
network_node1.merge(network_node2)
|
||||
network_node2 = network_node1
|
||||
|
||||
if(network_node1)
|
||||
network_node1.update = 1
|
||||
else if(network_node2)
|
||||
network_node2.update = 1
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/proc/go_straight()
|
||||
|
||||
if(!state)
|
||||
return 0
|
||||
|
||||
state = 0
|
||||
update_icon()
|
||||
|
||||
if(network_node1)
|
||||
del(network_node1)
|
||||
if(network_node2)
|
||||
del(network_node2)
|
||||
build_network()
|
||||
|
||||
if(network_node1&&network_node3)
|
||||
network_node1.merge(network_node3)
|
||||
network_node3 = network_node1
|
||||
|
||||
if(network_node1)
|
||||
network_node1.update = 1
|
||||
else if(network_node3)
|
||||
network_node3.update = 1
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/attack_ai(mob/user as mob)
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/attack_paw(mob/user as mob)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/attack_hand(mob/user as mob)
|
||||
src.add_fingerprint(usr)
|
||||
update_icon(1)
|
||||
sleep(10)
|
||||
if (src.state)
|
||||
src.go_straight()
|
||||
else
|
||||
src.go_to_side()
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/process()
|
||||
..()
|
||||
. = PROCESS_KILL
|
||||
//machines.Remove(src)
|
||||
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/initialize()
|
||||
var/node1_dir
|
||||
var/node2_dir
|
||||
var/node3_dir
|
||||
|
||||
node1_dir = turn(dir, 180)
|
||||
node2_dir = turn(dir, -90)
|
||||
node3_dir = dir
|
||||
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node1_dir))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node1 = target
|
||||
break
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node2_dir))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node2 = target
|
||||
break
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node3_dir))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node3 = target
|
||||
break
|
||||
|
||||
update_icon()
|
||||
update_underlays()
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/build_network()
|
||||
if(!network_node1 && node1)
|
||||
network_node1 = new /datum/pipe_network()
|
||||
network_node1.normal_members += src
|
||||
network_node1.build_network(node1, src)
|
||||
|
||||
if(!network_node2 && node2)
|
||||
network_node2 = new /datum/pipe_network()
|
||||
network_node2.normal_members += src
|
||||
network_node2.build_network(node2, src)
|
||||
|
||||
if(!network_node3 && node3)
|
||||
network_node3 = new /datum/pipe_network()
|
||||
network_node3.normal_members += src
|
||||
network_node3.build_network(node3, src)
|
||||
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/return_network(obj/machinery/atmospherics/reference)
|
||||
build_network()
|
||||
|
||||
if(reference==node1)
|
||||
return network_node1
|
||||
|
||||
if(reference==node2)
|
||||
return network_node2
|
||||
|
||||
if(reference==node3)
|
||||
return network_node3
|
||||
|
||||
return null
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
|
||||
if(network_node1 == old_network)
|
||||
network_node1 = new_network
|
||||
if(network_node2 == old_network)
|
||||
network_node2 = new_network
|
||||
if(network_node3 == old_network)
|
||||
network_node3 = new_network
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/return_network_air(datum/network/reference)
|
||||
return null
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/disconnect(obj/machinery/atmospherics/reference)
|
||||
if(reference==node1)
|
||||
del(network_node1)
|
||||
node1 = null
|
||||
|
||||
else if(reference==node2)
|
||||
del(network_node2)
|
||||
node2 = null
|
||||
|
||||
else if(reference==node3)
|
||||
del(network_node3)
|
||||
node2 = null
|
||||
|
||||
update_underlays()
|
||||
|
||||
return null
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/digital // can be controlled by AI
|
||||
name = "digital switching valve"
|
||||
desc = "A digitally controlled valve."
|
||||
icon = 'icons/atmos/digital_tvalve.dmi'
|
||||
|
||||
var/frequency = 0
|
||||
var/id = null
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/digital/bypass
|
||||
icon_state = "map_tvalve1"
|
||||
state = 1
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/digital/power_change()
|
||||
var/old_stat = stat
|
||||
..()
|
||||
if(old_stat != stat)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/digital/update_icon()
|
||||
..()
|
||||
if(!powered())
|
||||
icon_state = "tvalvenopower"
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/digital/attack_ai(mob/user as mob)
|
||||
return src.attack_hand(user)
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/digital/attack_hand(mob/user as mob)
|
||||
if(!powered())
|
||||
return
|
||||
if(!src.allowed(user))
|
||||
user << "\red Access denied."
|
||||
return
|
||||
..()
|
||||
|
||||
//Radio remote control
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/digital/proc/set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
if(frequency)
|
||||
radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA)
|
||||
|
||||
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/digital/initialize()
|
||||
..()
|
||||
if(frequency)
|
||||
set_frequency(frequency)
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/digital/receive_signal(datum/signal/signal)
|
||||
if(!signal.data["tag"] || (signal.data["tag"] != id))
|
||||
return 0
|
||||
|
||||
switch(signal.data["command"])
|
||||
if("valve_open")
|
||||
if(!state)
|
||||
go_to_side()
|
||||
|
||||
if("valve_close")
|
||||
if(state)
|
||||
go_straight()
|
||||
|
||||
if("valve_toggle")
|
||||
if(state)
|
||||
go_straight()
|
||||
else
|
||||
go_to_side()
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if (!istype(W, /obj/item/weapon/wrench))
|
||||
return ..()
|
||||
if (istype(src, /obj/machinery/atmospherics/tvalve/digital))
|
||||
user << "\red You cannot unwrench this [src], it's too complicated."
|
||||
return 1
|
||||
var/datum/gas_mixture/int_air = return_air()
|
||||
var/datum/gas_mixture/env_air = loc.return_air()
|
||||
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
|
||||
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
|
||||
add_fingerprint(user)
|
||||
return 1
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
user << "\blue You begin to unfasten \the [src]..."
|
||||
if (do_after(user, 40))
|
||||
user.visible_message( \
|
||||
"[user] unfastens \the [src].", \
|
||||
"\blue You have unfastened \the [src].", \
|
||||
"You hear ratchet.")
|
||||
new /obj/item/pipe(loc, make_from=src)
|
||||
del(src)
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/mirrored
|
||||
icon_state = "map_tvalvem0"
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/mirrored/bypass
|
||||
icon_state = "map_tvalvem1"
|
||||
state = 1
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/mirrored/initialize_directions()
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
initialize_directions = SOUTH|NORTH|WEST
|
||||
if(SOUTH)
|
||||
initialize_directions = NORTH|SOUTH|EAST
|
||||
if(EAST)
|
||||
initialize_directions = WEST|EAST|NORTH
|
||||
if(WEST)
|
||||
initialize_directions = EAST|WEST|SOUTH
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/mirrored/initialize()
|
||||
var/node1_dir
|
||||
var/node2_dir
|
||||
var/node3_dir
|
||||
|
||||
node1_dir = turn(dir, 180)
|
||||
node2_dir = turn(dir, 90)
|
||||
node3_dir = dir
|
||||
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node1_dir))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node1 = target
|
||||
break
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node2_dir))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node2 = target
|
||||
break
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node3_dir))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node3 = target
|
||||
break
|
||||
|
||||
update_icon()
|
||||
update_underlays()
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/mirrored/update_icon(animation)
|
||||
if(animation)
|
||||
flick("tvalvem[src.state][!src.state]",src)
|
||||
else
|
||||
icon_state = "tvalvem[state]"
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/mirrored/digital // can be controlled by AI
|
||||
name = "digital switching valve"
|
||||
desc = "A digitally controlled valve."
|
||||
icon = 'icons/atmos/digital_tvalve.dmi'
|
||||
|
||||
var/frequency = 0
|
||||
var/id = null
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/mirrored/digital/bypass
|
||||
icon_state = "map_tvalvem1"
|
||||
state = 1
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/mirrored/digital/power_change()
|
||||
var/old_stat = stat
|
||||
..()
|
||||
if(old_stat != stat)
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/mirrored/digital/update_icon()
|
||||
..()
|
||||
if(!powered())
|
||||
icon_state = "tvalvemnopower"
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/mirrored/digital/attack_ai(mob/user as mob)
|
||||
return src.attack_hand(user)
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/mirrored/digital/attack_hand(mob/user as mob)
|
||||
if(!powered())
|
||||
return
|
||||
if(!src.allowed(user))
|
||||
user << "\red Access denied."
|
||||
return
|
||||
..()
|
||||
|
||||
//Radio remote control -eh?
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/mirrored/digital/proc/set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
if(frequency)
|
||||
radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA)
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/mirrored/digital/initialize()
|
||||
..()
|
||||
if(frequency)
|
||||
set_frequency(frequency)
|
||||
|
||||
/obj/machinery/atmospherics/tvalve/mirrored/digital/receive_signal(datum/signal/signal)
|
||||
if(!signal.data["tag"] || (signal.data["tag"] != id))
|
||||
return 0
|
||||
|
||||
switch(signal.data["command"])
|
||||
if("valve_open")
|
||||
if(!state)
|
||||
go_to_side()
|
||||
|
||||
if("valve_close")
|
||||
if(state)
|
||||
go_straight()
|
||||
|
||||
if("valve_toggle")
|
||||
if(state)
|
||||
go_straight()
|
||||
else
|
||||
go_to_side()
|
||||
@@ -1,41 +1,207 @@
|
||||
/obj/machinery/atmospherics/unary/cold_sink
|
||||
icon = 'icons/obj/atmospherics/cold_sink.dmi'
|
||||
icon_state = "intact_off"
|
||||
density = 1
|
||||
use_power = 1
|
||||
//TODO: Put this under a common parent type with heaters to cut down on the copypasta
|
||||
#define FREEZER_PERF_MULT 2.5
|
||||
|
||||
name = "Cold Sink"
|
||||
/obj/machinery/atmospherics/unary/freezer
|
||||
name = "gas cooling system"
|
||||
desc = "Cools gas when connected to pipe network"
|
||||
icon = 'icons/obj/Cryogenic2.dmi'
|
||||
icon_state = "freezer_0"
|
||||
density = 1
|
||||
|
||||
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/internal_volume = 600 //L
|
||||
|
||||
var/on = 0
|
||||
use_power = 0
|
||||
idle_power_usage = 5 //5 Watts for thermostat related circuitry
|
||||
active_power_usage //50 kW. The power rating of the freezer
|
||||
|
||||
var/current_temperature = T20C
|
||||
var/current_heat_capacity = 50000 //totally random
|
||||
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
|
||||
|
||||
/obj/machinery/atmospherics/unary/freezer/New()
|
||||
..()
|
||||
air_contents.volume = internal_volume
|
||||
initialize_directions = dir
|
||||
|
||||
component_parts = list()
|
||||
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
|
||||
|
||||
var/node_connect = dir
|
||||
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node_connect))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node = target
|
||||
break
|
||||
|
||||
update_icon()
|
||||
if(node)
|
||||
icon_state = "intact_[on?("on"):("off")]"
|
||||
|
||||
|
||||
/obj/machinery/atmospherics/unary/freezer/update_icon()
|
||||
if(src.node)
|
||||
if(src.on && cooling)
|
||||
icon_state = "freezer_1"
|
||||
else
|
||||
icon_state = "exposed"
|
||||
icon_state = "freezer"
|
||||
else
|
||||
icon_state = "freezer_0"
|
||||
return
|
||||
|
||||
on = 0
|
||||
/obj/machinery/atmospherics/unary/freezer/attack_ai(mob/user as mob)
|
||||
src.ui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/unary/freezer/attack_paw(mob/user as mob)
|
||||
src.ui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/unary/freezer/attack_hand(mob/user as mob)
|
||||
src.ui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/unary/freezer/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]
|
||||
data["on"] = on ? 1 : 0
|
||||
data["gasPressure"] = round(air_contents.return_pressure())
|
||||
data["gasTemperature"] = round(air_contents.temperature)
|
||||
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"
|
||||
else if (air_contents.temperature < (T0C - 20) && air_contents.temperature > (T0C - 100))
|
||||
temp_class = "average"
|
||||
data["gasTemperatureClass"] = temp_class
|
||||
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "freezer.tmpl", "Gas Cooling System", 440, 300)
|
||||
// when the ui is first opened this is the data it will use
|
||||
ui.set_initial_data(data)
|
||||
// open the new ui window
|
||||
ui.open()
|
||||
// auto update every Master Controller tick
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/atmospherics/unary/freezer/Topic(href, href_list)
|
||||
if (href_list["toggleStatus"])
|
||||
src.on = !src.on
|
||||
update_icon()
|
||||
update_use_power(on)
|
||||
if(href_list["temp"])
|
||||
var/amount = text2num(href_list["temp"])
|
||||
if(amount > 0)
|
||||
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
|
||||
|
||||
/obj/machinery/atmospherics/unary/freezer/process()
|
||||
..()
|
||||
if(stat & (NOPOWER|BROKEN) || !on)
|
||||
cooling = 0
|
||||
update_use_power(0)
|
||||
update_icon()
|
||||
return
|
||||
|
||||
process()
|
||||
..()
|
||||
if(!on || !network)
|
||||
return 0
|
||||
var/air_heat_capacity = air_contents.heat_capacity()
|
||||
var/combined_heat_capacity = current_heat_capacity + air_heat_capacity
|
||||
var/old_temperature = air_contents.temperature
|
||||
if (network && air_contents.temperature > set_temperature)
|
||||
cooling = 1
|
||||
update_use_power(2)
|
||||
|
||||
if(combined_heat_capacity > 0)
|
||||
var/combined_energy = current_temperature*current_heat_capacity + air_heat_capacity*air_contents.temperature
|
||||
air_contents.temperature = combined_energy/combined_heat_capacity
|
||||
var/heat_transfer = max( -air_contents.get_thermal_energy_change(set_temperature - 5), 0 )
|
||||
|
||||
//todo: have current temperature affected. require power to bring down current temperature again
|
||||
//Assume the heat is being pumped into the hull which is fixed at heatsink_temperature
|
||||
//not /really/ proper thermodynamics but whatever
|
||||
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
|
||||
|
||||
if(abs(old_temperature-air_contents.temperature) > 1)
|
||||
network.update = 1
|
||||
return 1
|
||||
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()
|
||||
..()
|
||||
var/cap_rating = 0
|
||||
var/cap_count = 0
|
||||
var/manip_rating = 0
|
||||
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
|
||||
cap_count++
|
||||
if(istype(P, /obj/item/weapon/stock_parts/manipulator))
|
||||
manip_rating += P.rating
|
||||
manip_count++
|
||||
if(istype(P, /obj/item/weapon/stock_parts/matter_bin))
|
||||
bin_rating += P.rating
|
||||
bin_count++
|
||||
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)
|
||||
if(istype(O, /obj/item/weapon/screwdriver))
|
||||
opened = !opened
|
||||
user << "You [opened ? "open" : "close"] the maintenance hatch of [src]."
|
||||
return
|
||||
|
||||
if (opened && istype(O, /obj/item/weapon/crowbar))
|
||||
dismantle()
|
||||
return
|
||||
|
||||
..()
|
||||
|
||||
/obj/machinery/atmospherics/unary/freezer/examine()
|
||||
..()
|
||||
if (opened)
|
||||
usr << "The maintenance hatch is open."
|
||||
@@ -1,43 +1,189 @@
|
||||
/obj/machinery/atmospherics/unary/heat_reservoir
|
||||
//currently the same code as cold_sink but anticipating process() changes
|
||||
//TODO: Put this under a common parent type with freezers to cut down on the copypasta
|
||||
|
||||
icon = 'icons/obj/atmospherics/cold_sink.dmi'
|
||||
icon_state = "intact_off"
|
||||
/obj/machinery/atmospherics/unary/heater
|
||||
name = "gas heating system"
|
||||
desc = "Heats gas when connected to a pipe network"
|
||||
icon = 'icons/obj/Cryogenic2.dmi'
|
||||
icon_state = "heater_0"
|
||||
density = 1
|
||||
use_power = 1
|
||||
|
||||
name = "Heat Reservoir"
|
||||
desc = "Heats gas when connected to pipe network"
|
||||
anchored = 1.0
|
||||
|
||||
var/set_temperature = T20C //thermostat
|
||||
var/max_temperature = T20C + 680
|
||||
var/internal_volume = 600 //L
|
||||
|
||||
var/on = 0
|
||||
use_power = 0
|
||||
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/current_temperature = T20C
|
||||
var/current_heat_capacity = 50000 //totally random
|
||||
var/heating = 0 //mainly for icon updates
|
||||
var/opened = 0 //for deconstruction
|
||||
|
||||
/obj/machinery/atmospherics/unary/heater/New()
|
||||
..()
|
||||
air_contents.volume = internal_volume
|
||||
initialize_directions = dir
|
||||
|
||||
component_parts = list()
|
||||
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
|
||||
|
||||
var/node_connect = dir
|
||||
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node_connect))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node = target
|
||||
break
|
||||
|
||||
update_icon()
|
||||
if(node)
|
||||
icon_state = "intact_[on?("on"):("off")]"
|
||||
|
||||
|
||||
/obj/machinery/atmospherics/unary/heater/update_icon()
|
||||
if(src.node)
|
||||
if(src.on && src.heating)
|
||||
icon_state = "heater_1"
|
||||
else
|
||||
icon_state = "exposed"
|
||||
icon_state = "heater"
|
||||
else
|
||||
icon_state = "heater_0"
|
||||
return
|
||||
|
||||
on = 0
|
||||
|
||||
/obj/machinery/atmospherics/unary/heater/process()
|
||||
..()
|
||||
|
||||
if(stat & (NOPOWER|BROKEN) || !on)
|
||||
heating = 0
|
||||
update_use_power(0)
|
||||
update_icon()
|
||||
return
|
||||
|
||||
process()
|
||||
..()
|
||||
if(!on || !network)
|
||||
return 0
|
||||
var/air_heat_capacity = air_contents.heat_capacity()
|
||||
var/combined_heat_capacity = current_heat_capacity + air_heat_capacity
|
||||
var/old_temperature = air_contents.temperature
|
||||
if (network && air_contents.total_moles && air_contents.temperature < set_temperature)
|
||||
update_use_power(2)
|
||||
air_contents.add_thermal_energy(active_power_usage)
|
||||
|
||||
if(combined_heat_capacity > 0)
|
||||
var/combined_energy = current_temperature*current_heat_capacity + air_heat_capacity*air_contents.temperature
|
||||
air_contents.temperature = combined_energy/combined_heat_capacity
|
||||
heating = 1
|
||||
network.update = 1
|
||||
else
|
||||
heating = 0
|
||||
update_use_power(1)
|
||||
|
||||
//todo: have current temperature affected. require power to bring up current temperature again
|
||||
update_icon()
|
||||
|
||||
if(abs(old_temperature-air_contents.temperature) > 1)
|
||||
network.update = 1
|
||||
return 1
|
||||
/obj/machinery/atmospherics/unary/heater/attack_ai(mob/user as mob)
|
||||
src.ui_interact(user)
|
||||
|
||||
/obj/machinery/atmospherics/unary/heater/attack_paw(mob/user as mob)
|
||||
src.ui_interact(user)
|
||||
|
||||
/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]
|
||||
data["on"] = on ? 1 : 0
|
||||
data["gasPressure"] = round(air_contents.return_pressure())
|
||||
data["gasTemperature"] = round(air_contents.temperature)
|
||||
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"
|
||||
data["gasTemperatureClass"] = temp_class
|
||||
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
ui = new(user, src, ui_key, "freezer.tmpl", "Gas Heating System", 440, 300)
|
||||
// when the ui is first opened this is the data it will use
|
||||
ui.set_initial_data(data)
|
||||
// open the new ui window
|
||||
ui.open()
|
||||
// auto update every Master Controller tick
|
||||
ui.set_auto_update(1)
|
||||
|
||||
/obj/machinery/atmospherics/unary/heater/Topic(href, href_list)
|
||||
if (href_list["toggleStatus"])
|
||||
src.on = !src.on
|
||||
update_use_power(on)
|
||||
update_icon()
|
||||
if(href_list["temp"])
|
||||
var/amount = text2num(href_list["temp"])
|
||||
if(amount > 0)
|
||||
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()
|
||||
..()
|
||||
|
||||
var/cap_rating = 0
|
||||
var/cap_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
|
||||
cap_count++
|
||||
if(istype(P, /obj/item/weapon/stock_parts/matter_bin))
|
||||
bin_rating += P.rating
|
||||
bin_count++
|
||||
cap_rating /= cap_count
|
||||
bin_rating /= bin_count
|
||||
|
||||
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)
|
||||
if(istype(O, /obj/item/weapon/screwdriver))
|
||||
opened = !opened
|
||||
user << "You [opened ? "open" : "close"] the maintenance hatch of [src]."
|
||||
return
|
||||
|
||||
if (opened && istype(O, /obj/item/weapon/crowbar))
|
||||
dismantle()
|
||||
return
|
||||
|
||||
..()
|
||||
|
||||
/obj/machinery/atmospherics/unary/heater/examine()
|
||||
..()
|
||||
if (opened)
|
||||
usr << "The maintenance hatch is open."
|
||||
@@ -1,15 +1,24 @@
|
||||
//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 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/obj/atmospherics/outlet_injector.dmi'
|
||||
icon_state = "off"
|
||||
icon = 'icons/atmos/injector.dmi'
|
||||
icon_state = "map_injector"
|
||||
use_power = 1
|
||||
layer = 3
|
||||
|
||||
name = "Air Injector"
|
||||
desc = "Has a valve and pump attached to it"
|
||||
name = "air injector"
|
||||
desc = "Passively injects air into its surroundings. Has a valve attached to it that can control flow rate."
|
||||
|
||||
use_power = 1
|
||||
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
|
||||
|
||||
var/volume_rate = 50
|
||||
var/volume_rate = 50 //flow rate limit
|
||||
|
||||
var/frequency = 0
|
||||
var/id = null
|
||||
@@ -17,131 +26,136 @@
|
||||
|
||||
level = 1
|
||||
|
||||
update_icon()
|
||||
if(node)
|
||||
if(on && !(stat & NOPOWER))
|
||||
icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]on"
|
||||
else
|
||||
icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]off"
|
||||
else
|
||||
icon_state = "exposed"
|
||||
on = 0
|
||||
/obj/machinery/atmospherics/unary/outlet_injector/New()
|
||||
..()
|
||||
air_contents.volume = ATMOS_DEFAULT_VOLUME_PUMP + 500 //Give it a small reservoir for injecting. Also allows it to have a higher flow rate limit than vent pumps, to differentiate injectors a bit more.
|
||||
|
||||
return
|
||||
/obj/machinery/atmospherics/unary/outlet_injector/update_icon()
|
||||
if(!powered())
|
||||
icon_state = "off"
|
||||
else
|
||||
icon_state = "[on ? "on" : "off"]"
|
||||
|
||||
power_change()
|
||||
var/old_stat = stat
|
||||
..()
|
||||
if(old_stat != stat)
|
||||
update_icon()
|
||||
|
||||
|
||||
process()
|
||||
..()
|
||||
injecting = 0
|
||||
|
||||
if(!on || stat & NOPOWER)
|
||||
return 0
|
||||
|
||||
if(air_contents.temperature > 0)
|
||||
var/transfer_moles = (air_contents.return_pressure())*volume_rate/(air_contents.temperature * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
var/datum/gas_mixture/removed = air_contents.remove(transfer_moles)
|
||||
|
||||
loc.assume_air(removed)
|
||||
|
||||
if(network)
|
||||
network.update = 1
|
||||
|
||||
return 1
|
||||
|
||||
proc/inject()
|
||||
if(on || injecting)
|
||||
return 0
|
||||
|
||||
injecting = 1
|
||||
|
||||
if(air_contents.temperature > 0)
|
||||
var/transfer_moles = (air_contents.return_pressure())*volume_rate/(air_contents.temperature * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
var/datum/gas_mixture/removed = air_contents.remove(transfer_moles)
|
||||
|
||||
loc.assume_air(removed)
|
||||
|
||||
if(network)
|
||||
network.update = 1
|
||||
|
||||
flick("inject", src)
|
||||
|
||||
proc
|
||||
set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
if(frequency)
|
||||
radio_connection = radio_controller.add_object(src, frequency)
|
||||
|
||||
broadcast_status()
|
||||
if(!radio_connection)
|
||||
return 0
|
||||
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 1 //radio signal
|
||||
signal.source = src
|
||||
|
||||
signal.data = list(
|
||||
"tag" = id,
|
||||
"device" = "AO",
|
||||
"power" = on,
|
||||
"volume_rate" = volume_rate,
|
||||
//"timestamp" = world.time,
|
||||
"sigtype" = "status"
|
||||
)
|
||||
|
||||
radio_connection.post_signal(src, signal)
|
||||
|
||||
return 1
|
||||
|
||||
initialize()
|
||||
..()
|
||||
|
||||
set_frequency(frequency)
|
||||
|
||||
receive_signal(datum/signal/signal)
|
||||
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
|
||||
return 0
|
||||
|
||||
if("power" in signal.data)
|
||||
on = text2num(signal.data["power"])
|
||||
|
||||
if("power_toggle" in signal.data)
|
||||
on = !on
|
||||
|
||||
if("inject" in signal.data)
|
||||
spawn inject()
|
||||
/obj/machinery/atmospherics/unary/outlet_injector/update_underlays()
|
||||
if(..())
|
||||
underlays.Cut()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T))
|
||||
return
|
||||
add_underlay(T, node, dir)
|
||||
|
||||
if("set_volume_rate" in signal.data)
|
||||
var/number = text2num(signal.data["set_volume_rate"])
|
||||
volume_rate = between(0, number, air_contents.volume)
|
||||
|
||||
if("status" in signal.data)
|
||||
spawn(2)
|
||||
broadcast_status()
|
||||
return //do not update_icon
|
||||
|
||||
//log_admin("DEBUG \[[world.timeofday]\]: outlet_injector/receive_signal: unknown command \"[signal.data["command"]]\"\n[signal.debug_print()]")
|
||||
//return
|
||||
spawn(2)
|
||||
broadcast_status()
|
||||
/obj/machinery/atmospherics/unary/outlet_injector/power_change()
|
||||
var/old_stat = stat
|
||||
..()
|
||||
if(old_stat != stat)
|
||||
update_icon()
|
||||
|
||||
hide(var/i) //to make the little pipe section invisible, the icon changes.
|
||||
if(node)
|
||||
if(on)
|
||||
icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]on"
|
||||
else
|
||||
icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]off"
|
||||
else
|
||||
icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]exposed"
|
||||
on = 0
|
||||
return
|
||||
/obj/machinery/atmospherics/unary/outlet_injector/process()
|
||||
..()
|
||||
injecting = 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/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()
|
||||
if(on || injecting || (stat & NOPOWER))
|
||||
return 0
|
||||
|
||||
var/datum/gas_mixture/environment = loc.return_air()
|
||||
if (!environment)
|
||||
return 0
|
||||
|
||||
injecting = 1
|
||||
|
||||
if(air_contents.temperature > 0)
|
||||
var/power_used = pump_gas(src, air_contents, environment, air_contents.total_moles, active_power_usage)
|
||||
use_power(power_used)
|
||||
|
||||
if(network)
|
||||
network.update = 1
|
||||
|
||||
flick("inject", src)
|
||||
|
||||
/obj/machinery/atmospherics/unary/outlet_injector/proc/set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
if(frequency)
|
||||
radio_connection = radio_controller.add_object(src, frequency)
|
||||
|
||||
/obj/machinery/atmospherics/unary/outlet_injector/proc/broadcast_status()
|
||||
if(!radio_connection)
|
||||
return 0
|
||||
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 1 //radio signal
|
||||
signal.source = src
|
||||
|
||||
signal.data = list(
|
||||
"tag" = id,
|
||||
"device" = "AO",
|
||||
"power" = on,
|
||||
"volume_rate" = volume_rate,
|
||||
"sigtype" = "status"
|
||||
)
|
||||
|
||||
radio_connection.post_signal(src, signal)
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/atmospherics/unary/outlet_injector/initialize()
|
||||
..()
|
||||
|
||||
set_frequency(frequency)
|
||||
|
||||
/obj/machinery/atmospherics/unary/outlet_injector/receive_signal(datum/signal/signal)
|
||||
if(!signal.data["tag"] || (signal.data["tag"] != id) || (signal.data["sigtype"]!="command"))
|
||||
return 0
|
||||
|
||||
if(signal.data["power"])
|
||||
on = text2num(signal.data["power"])
|
||||
update_use_power(on)
|
||||
|
||||
if(signal.data["power_toggle"])
|
||||
on = !on
|
||||
update_use_power(on)
|
||||
|
||||
if(signal.data["inject"])
|
||||
spawn inject()
|
||||
return
|
||||
|
||||
if(signal.data["set_volume_rate"])
|
||||
var/number = text2num(signal.data["set_volume_rate"])
|
||||
volume_rate = between(0, number, air_contents.volume)
|
||||
|
||||
if(signal.data["status"])
|
||||
spawn(2)
|
||||
broadcast_status()
|
||||
return //do not update_icon
|
||||
|
||||
spawn(2)
|
||||
broadcast_status()
|
||||
update_icon()
|
||||
|
||||
/obj/machinery/atmospherics/unary/outlet_injector/hide(var/i)
|
||||
update_underlays()
|
||||
@@ -33,7 +33,7 @@ obj/machinery/atmospherics/unary/oxygen_generator
|
||||
if(!on)
|
||||
return 0
|
||||
|
||||
var/total_moles = air_contents.total_moles()
|
||||
var/total_moles = air_contents.total_moles
|
||||
|
||||
if(total_moles < oxygen_content)
|
||||
var/current_heat_capacity = air_contents.heat_capacity()
|
||||
@@ -41,7 +41,7 @@ obj/machinery/atmospherics/unary/oxygen_generator
|
||||
var/added_oxygen = oxygen_content - total_moles
|
||||
|
||||
air_contents.temperature = (current_heat_capacity*air_contents.temperature + 20*added_oxygen*T0C)/(current_heat_capacity+20*added_oxygen)
|
||||
air_contents.oxygen += added_oxygen
|
||||
air_contents.adjust_gas("oxygen", added_oxygen)
|
||||
|
||||
if(network)
|
||||
network.update = 1
|
||||
|
||||
@@ -50,6 +50,7 @@
|
||||
break
|
||||
|
||||
update_icon()
|
||||
update_underlays()
|
||||
|
||||
build_network()
|
||||
if(!network && node)
|
||||
@@ -85,4 +86,7 @@
|
||||
del(network)
|
||||
node = null
|
||||
|
||||
update_icon()
|
||||
update_underlays()
|
||||
|
||||
return null
|
||||
@@ -1,16 +1,24 @@
|
||||
#define DEFAULT_PRESSURE_DELTA 10000
|
||||
|
||||
#define EXTERNAL_PRESSURE_BOUND ONE_ATMOSPHERE
|
||||
#define INTERNAL_PRESSURE_BOUND 0
|
||||
#define PRESSURE_CHECKS 1
|
||||
|
||||
#define PRESSURE_CHECK_EXTERNAL 1
|
||||
#define PRESSURE_CHECK_INTERNAL 2
|
||||
|
||||
#undefine
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_pump
|
||||
icon = 'icons/obj/atmospherics/vent_pump.dmi'
|
||||
icon_state = "off"
|
||||
icon = 'icons/atmos/vent_pump.dmi'
|
||||
icon_state = "map_vent"
|
||||
|
||||
name = "Air Vent"
|
||||
desc = "Has a valve and pump attached to it"
|
||||
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 pump is, in Watts. 7500 W ~ 10 HP
|
||||
|
||||
var/area/initial_loc
|
||||
level = 1
|
||||
var/area_uid
|
||||
@@ -19,6 +27,8 @@
|
||||
var/on = 0
|
||||
var/pump_direction = 1 //0 = siphoning, 1 = releasing
|
||||
|
||||
var/last_power_draw = 0
|
||||
|
||||
var/external_pressure_bound = EXTERNAL_PRESSURE_BOUND
|
||||
var/internal_pressure_bound = INTERNAL_PRESSURE_BOUND
|
||||
|
||||
@@ -40,316 +50,367 @@
|
||||
var/radio_filter_out
|
||||
var/radio_filter_in
|
||||
|
||||
on
|
||||
on = 1
|
||||
icon_state = "out"
|
||||
/obj/machinery/atmospherics/unary/vent_pump/on
|
||||
on = 1
|
||||
icon_state = "map_vent_out"
|
||||
|
||||
siphon
|
||||
pump_direction = 0
|
||||
icon_state = "off"
|
||||
/obj/machinery/atmospherics/unary/vent_pump/siphon
|
||||
pump_direction = 0
|
||||
|
||||
on
|
||||
on = 1
|
||||
icon_state = "in"
|
||||
/obj/machinery/atmospherics/unary/vent_pump/siphon/on
|
||||
on = 1
|
||||
icon_state = "map_vent_in"
|
||||
|
||||
New()
|
||||
initial_loc = get_area(loc)
|
||||
if (initial_loc.master)
|
||||
initial_loc = initial_loc.master
|
||||
area_uid = initial_loc.uid
|
||||
if (!id_tag)
|
||||
assign_uid()
|
||||
id_tag = num2text(uid)
|
||||
if(ticker && ticker.current_state == 3)//if the game is running
|
||||
src.initialize()
|
||||
src.broadcast_status()
|
||||
..()
|
||||
/obj/machinery/atmospherics/unary/vent_pump/New()
|
||||
..()
|
||||
air_contents.volume = ATMOS_DEFAULT_VOLUME_PUMP
|
||||
|
||||
icon = null
|
||||
initial_loc = get_area(loc)
|
||||
if (initial_loc.master)
|
||||
initial_loc = initial_loc.master
|
||||
area_uid = initial_loc.uid
|
||||
if (!id_tag)
|
||||
assign_uid()
|
||||
id_tag = num2text(uid)
|
||||
if(ticker && ticker.current_state == 3)//if the game is running
|
||||
src.initialize()
|
||||
src.broadcast_status()
|
||||
|
||||
high_volume
|
||||
name = "Large Air Vent"
|
||||
power_channel = EQUIP
|
||||
New()
|
||||
..()
|
||||
air_contents.volume = 1000
|
||||
/obj/machinery/atmospherics/unary/vent_pump/high_volume
|
||||
name = "Large Air Vent"
|
||||
power_channel = EQUIP
|
||||
active_power_usage = 15000 //15 kW ~ 20 HP
|
||||
|
||||
update_icon()
|
||||
if(welded)
|
||||
icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]weld"
|
||||
return
|
||||
if(on && !(stat & (NOPOWER|BROKEN)))
|
||||
if(pump_direction)
|
||||
icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]out"
|
||||
else
|
||||
icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]in"
|
||||
else
|
||||
icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]off"
|
||||
/obj/machinery/atmospherics/unary/vent_pump/high_volume/New()
|
||||
..()
|
||||
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
|
||||
if (!node)
|
||||
on = 0
|
||||
|
||||
overlays.Cut()
|
||||
|
||||
var/vent_icon = "vent"
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T))
|
||||
return
|
||||
|
||||
process()
|
||||
..()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
if(T.intact && node && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
|
||||
vent_icon += "h"
|
||||
|
||||
if(welded)
|
||||
vent_icon += "weld"
|
||||
else if(!powered())
|
||||
vent_icon += "off"
|
||||
else
|
||||
vent_icon += "[on ? "[pump_direction ? "out" : "in"]" : "off"]"
|
||||
|
||||
overlays += icon_manager.get_atmos_icon("device", , , vent_icon)
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_pump/update_underlays()
|
||||
if(..())
|
||||
underlays.Cut()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T))
|
||||
return
|
||||
if (!node)
|
||||
on = 0
|
||||
//broadcast_status() // from now air alarm/control computer should request update purposely --rastaf0
|
||||
if(!on)
|
||||
return 0
|
||||
if(T.intact && node && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
|
||||
return
|
||||
else
|
||||
add_underlay(T, node, dir)
|
||||
|
||||
if(welded)
|
||||
return 0
|
||||
/obj/machinery/atmospherics/unary/vent_pump/hide()
|
||||
update_icon()
|
||||
update_underlays()
|
||||
|
||||
var/datum/gas_mixture/environment = loc.return_air()
|
||||
var/environment_pressure = environment.return_pressure()
|
||||
/obj/machinery/atmospherics/unary/vent_pump/proc/can_pump()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return 0
|
||||
if(!on)
|
||||
return 0
|
||||
if(welded)
|
||||
return 0
|
||||
return 1
|
||||
|
||||
if(pump_direction) //internal -> external
|
||||
var/pressure_delta = 10000
|
||||
/obj/machinery/atmospherics/unary/vent_pump/process()
|
||||
..()
|
||||
|
||||
if (!node)
|
||||
on = 0
|
||||
if(!can_pump())
|
||||
update_use_power(0) //usually we get here because a player turned a pump off - definitely want to update.
|
||||
last_power_draw = 0
|
||||
last_flow_rate = 0
|
||||
return 0
|
||||
|
||||
if(pressure_checks&1)
|
||||
pressure_delta = min(pressure_delta, (external_pressure_bound - environment_pressure))
|
||||
if(pressure_checks&2)
|
||||
pressure_delta = min(pressure_delta, (air_contents.return_pressure() - internal_pressure_bound))
|
||||
var/datum/gas_mixture/environment = loc.return_air()
|
||||
|
||||
if(pressure_delta > 0.5)
|
||||
if(air_contents.temperature > 0)
|
||||
var/transfer_moles = pressure_delta*environment.volume/(air_contents.temperature * R_IDEAL_GAS_EQUATION)
|
||||
|
||||
var/datum/gas_mixture/removed = air_contents.remove(transfer_moles)
|
||||
|
||||
loc.assume_air(removed)
|
||||
|
||||
if(network)
|
||||
network.update = 1
|
||||
var/power_draw = -1
|
||||
|
||||
//Figure out the target pressure difference
|
||||
var/pressure_delta = get_pressure_delta(environment)
|
||||
//src.visible_message("DEBUG >>> [src]: pressure_delta = [pressure_delta]")
|
||||
|
||||
if((environment.temperature || air_contents.temperature) && pressure_delta > 0.5)
|
||||
if(pump_direction) //internal -> external
|
||||
var/output_volume = environment.volume * environment.group_multiplier
|
||||
var/air_temperature = environment.temperature? environment.temperature : air_contents.temperature
|
||||
var/transfer_moles = pressure_delta*output_volume/(air_temperature * R_IDEAL_GAS_EQUATION)
|
||||
//src.visible_message("DEBUG >>> [src]: output_volume = [output_volume]L; air_temperature = [air_temperature]K; transfer_moles = [transfer_moles] mol")
|
||||
|
||||
power_draw = pump_gas(src, air_contents, environment, transfer_moles, active_power_usage)
|
||||
else //external -> internal
|
||||
var/pressure_delta = 10000
|
||||
if(pressure_checks&1)
|
||||
pressure_delta = min(pressure_delta, (environment_pressure - external_pressure_bound))
|
||||
if(pressure_checks&2)
|
||||
pressure_delta = min(pressure_delta, (internal_pressure_bound - air_contents.return_pressure()))
|
||||
var/output_volume = air_contents.volume + (network? network.volume : 0)
|
||||
var/air_temperature = air_contents.temperature? air_contents.temperature : environment.temperature
|
||||
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*air_contents.volume/environment.volume) //group_multiplier gets divided out here
|
||||
|
||||
power_draw = pump_gas(src, environment, air_contents, transfer_moles, active_power_usage)
|
||||
|
||||
if(pressure_delta > 0.5)
|
||||
if(environment.temperature > 0)
|
||||
var/transfer_moles = pressure_delta*air_contents.volume/(environment.temperature * R_IDEAL_GAS_EQUATION)
|
||||
if (power_draw < 0)
|
||||
last_power_draw = 0
|
||||
last_flow_rate = 0
|
||||
//update_use_power(0)
|
||||
use_power = 0 //don't force update - easier on CPU
|
||||
else
|
||||
last_power_draw = handle_power_draw(power_draw)
|
||||
if(network)
|
||||
network.update = 1
|
||||
|
||||
return 1
|
||||
|
||||
var/datum/gas_mixture/removed = loc.remove_air(transfer_moles)
|
||||
if (isnull(removed)) //in space
|
||||
return
|
||||
/obj/machinery/atmospherics/unary/vent_pump/proc/get_pressure_delta(datum/gas_mixture/environment)
|
||||
var/pressure_delta = DEFAULT_PRESSURE_DELTA
|
||||
var/environment_pressure = environment.return_pressure()
|
||||
|
||||
if(pump_direction) //internal -> external
|
||||
if(pressure_checks & PRESSURE_CHECK_EXTERNAL)
|
||||
pressure_delta = min(pressure_delta, external_pressure_bound - environment_pressure) //increasing the pressure here
|
||||
if(pressure_checks & PRESSURE_CHECK_INTERNAL)
|
||||
pressure_delta = min(pressure_delta, air_contents.return_pressure() - internal_pressure_bound) //decreasing the pressure here
|
||||
else //external -> internal
|
||||
if(pressure_checks & PRESSURE_CHECK_EXTERNAL)
|
||||
pressure_delta = min(pressure_delta, environment_pressure - external_pressure_bound) //decreasing the pressure here
|
||||
if(pressure_checks & PRESSURE_CHECK_INTERNAL)
|
||||
pressure_delta = min(pressure_delta, internal_pressure_bound - air_contents.return_pressure()) //increasing the pressure here
|
||||
|
||||
return pressure_delta
|
||||
|
||||
air_contents.merge(removed)
|
||||
//Radio remote control
|
||||
|
||||
if(network)
|
||||
network.update = 1
|
||||
/obj/machinery/atmospherics/unary/vent_pump/proc/set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
if(frequency)
|
||||
radio_connection = radio_controller.add_object(src, frequency,radio_filter_in)
|
||||
|
||||
return 1
|
||||
/obj/machinery/atmospherics/unary/vent_pump/proc/broadcast_status()
|
||||
if(!radio_connection)
|
||||
return 0
|
||||
|
||||
//Radio remote control
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 1 //radio signal
|
||||
signal.source = src
|
||||
|
||||
proc
|
||||
set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
if(frequency)
|
||||
radio_connection = radio_controller.add_object(src, frequency,radio_filter_in)
|
||||
signal.data = list(
|
||||
"area" = src.area_uid,
|
||||
"tag" = src.id_tag,
|
||||
"device" = "AVP",
|
||||
"power" = on,
|
||||
"direction" = pump_direction?("release"):("siphon"),
|
||||
"checks" = pressure_checks,
|
||||
"internal" = internal_pressure_bound,
|
||||
"external" = external_pressure_bound,
|
||||
"timestamp" = world.time,
|
||||
"sigtype" = "status",
|
||||
"power_draw" = last_power_draw,
|
||||
"flow_rate" = last_flow_rate,
|
||||
)
|
||||
|
||||
broadcast_status()
|
||||
if(!radio_connection)
|
||||
return 0
|
||||
if(!initial_loc.air_vent_names[id_tag])
|
||||
var/new_name = "[initial_loc.name] Vent Pump #[initial_loc.air_vent_names.len+1]"
|
||||
initial_loc.air_vent_names[id_tag] = new_name
|
||||
src.name = new_name
|
||||
initial_loc.air_vent_info[id_tag] = signal.data
|
||||
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 1 //radio signal
|
||||
signal.source = src
|
||||
radio_connection.post_signal(src, signal, radio_filter_out)
|
||||
|
||||
signal.data = list(
|
||||
"area" = src.area_uid,
|
||||
"tag" = src.id_tag,
|
||||
"device" = "AVP",
|
||||
"power" = on,
|
||||
"direction" = pump_direction?("release"):("siphon"),
|
||||
"checks" = pressure_checks,
|
||||
"internal" = internal_pressure_bound,
|
||||
"external" = external_pressure_bound,
|
||||
"timestamp" = world.time,
|
||||
"sigtype" = "status"
|
||||
)
|
||||
|
||||
if(!initial_loc.air_vent_names[id_tag])
|
||||
var/new_name = "[initial_loc.name] Vent Pump #[initial_loc.air_vent_names.len+1]"
|
||||
initial_loc.air_vent_names[id_tag] = new_name
|
||||
src.name = new_name
|
||||
initial_loc.air_vent_info[id_tag] = signal.data
|
||||
|
||||
radio_connection.post_signal(src, signal, radio_filter_out)
|
||||
|
||||
return 1
|
||||
return 1
|
||||
|
||||
|
||||
initialize()
|
||||
..()
|
||||
/obj/machinery/atmospherics/unary/vent_pump/initialize()
|
||||
..()
|
||||
|
||||
//some vents work his own spesial way
|
||||
radio_filter_in = frequency==1439?(RADIO_FROM_AIRALARM):null
|
||||
radio_filter_out = frequency==1439?(RADIO_TO_AIRALARM):null
|
||||
if(frequency)
|
||||
set_frequency(frequency)
|
||||
//some vents work his own spesial way
|
||||
radio_filter_in = frequency==1439?(RADIO_FROM_AIRALARM):null
|
||||
radio_filter_out = frequency==1439?(RADIO_TO_AIRALARM):null
|
||||
if(frequency)
|
||||
set_frequency(frequency)
|
||||
|
||||
receive_signal(datum/signal/signal)
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
//log_admin("DEBUG \[[world.timeofday]\]: /obj/machinery/atmospherics/unary/vent_pump/receive_signal([signal.debug_print()])")
|
||||
if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command"))
|
||||
return 0
|
||||
/obj/machinery/atmospherics/unary/vent_pump/receive_signal(datum/signal/signal)
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
//log_admin("DEBUG \[[world.timeofday]\]: /obj/machinery/atmospherics/unary/vent_pump/receive_signal([signal.debug_print()])")
|
||||
if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command"))
|
||||
return 0
|
||||
|
||||
if(signal.data["purge"] != null)
|
||||
pressure_checks &= ~1
|
||||
pump_direction = 0
|
||||
if(signal.data["purge"] != null)
|
||||
pressure_checks &= ~1
|
||||
pump_direction = 0
|
||||
|
||||
if(signal.data["stabalize"] != null)
|
||||
pressure_checks |= 1
|
||||
pump_direction = 1
|
||||
if(signal.data["stabalize"] != null)
|
||||
pressure_checks |= 1
|
||||
pump_direction = 1
|
||||
|
||||
if(signal.data["power"] != null)
|
||||
on = text2num(signal.data["power"])
|
||||
if(signal.data["power"] != null)
|
||||
on = text2num(signal.data["power"])
|
||||
|
||||
if(signal.data["power_toggle"] != null)
|
||||
on = !on
|
||||
if(signal.data["power_toggle"] != null)
|
||||
on = !on
|
||||
|
||||
if(signal.data["checks"] != null)
|
||||
if (signal.data["checks"] == "default")
|
||||
pressure_checks = pressure_checks_default
|
||||
else
|
||||
pressure_checks = text2num(signal.data["checks"])
|
||||
if(signal.data["checks"] != null)
|
||||
if (signal.data["checks"] == "default")
|
||||
pressure_checks = pressure_checks_default
|
||||
else
|
||||
pressure_checks = text2num(signal.data["checks"])
|
||||
|
||||
if(signal.data["checks_toggle"] != null)
|
||||
pressure_checks = (pressure_checks?0:3)
|
||||
if(signal.data["checks_toggle"] != null)
|
||||
pressure_checks = (pressure_checks?0:3)
|
||||
|
||||
if(signal.data["direction"] != null)
|
||||
pump_direction = text2num(signal.data["direction"])
|
||||
|
||||
if(signal.data["direction"] != null)
|
||||
pump_direction = text2num(signal.data["direction"])
|
||||
|
||||
if(signal.data["set_internal_pressure"] != null)
|
||||
if (signal.data["set_internal_pressure"] == "default")
|
||||
internal_pressure_bound = internal_pressure_bound_default
|
||||
else
|
||||
internal_pressure_bound = between(
|
||||
0,
|
||||
text2num(signal.data["set_internal_pressure"]),
|
||||
ONE_ATMOSPHERE*50
|
||||
)
|
||||
|
||||
if(signal.data["set_external_pressure"] != null)
|
||||
if (signal.data["set_external_pressure"] == "default")
|
||||
external_pressure_bound = external_pressure_bound_default
|
||||
else
|
||||
external_pressure_bound = between(
|
||||
0,
|
||||
text2num(signal.data["set_external_pressure"]),
|
||||
ONE_ATMOSPHERE*50
|
||||
)
|
||||
|
||||
if(signal.data["adjust_internal_pressure"] != null)
|
||||
if(signal.data["set_internal_pressure"] != null)
|
||||
if (signal.data["set_internal_pressure"] == "default")
|
||||
internal_pressure_bound = internal_pressure_bound_default
|
||||
else
|
||||
internal_pressure_bound = between(
|
||||
0,
|
||||
internal_pressure_bound + text2num(signal.data["adjust_internal_pressure"]),
|
||||
text2num(signal.data["set_internal_pressure"]),
|
||||
ONE_ATMOSPHERE*50
|
||||
)
|
||||
|
||||
if(signal.data["adjust_external_pressure"] != null)
|
||||
|
||||
|
||||
if(signal.data["set_external_pressure"] != null)
|
||||
if (signal.data["set_external_pressure"] == "default")
|
||||
external_pressure_bound = external_pressure_bound_default
|
||||
else
|
||||
external_pressure_bound = between(
|
||||
0,
|
||||
external_pressure_bound + text2num(signal.data["adjust_external_pressure"]),
|
||||
text2num(signal.data["set_external_pressure"]),
|
||||
ONE_ATMOSPHERE*50
|
||||
)
|
||||
|
||||
if(signal.data["init"] != null)
|
||||
name = signal.data["init"]
|
||||
return
|
||||
if(signal.data["adjust_internal_pressure"] != null)
|
||||
internal_pressure_bound = between(
|
||||
0,
|
||||
internal_pressure_bound + text2num(signal.data["adjust_internal_pressure"]),
|
||||
ONE_ATMOSPHERE*50
|
||||
)
|
||||
|
||||
if(signal.data["status"] != null)
|
||||
spawn(2)
|
||||
broadcast_status()
|
||||
return //do not update_icon
|
||||
if(signal.data["adjust_external_pressure"] != null)
|
||||
|
||||
//log_admin("DEBUG \[[world.timeofday]\]: vent_pump/receive_signal: unknown command \"[signal.data["command"]]\"\n[signal.debug_print()]")
|
||||
|
||||
external_pressure_bound = between(
|
||||
0,
|
||||
external_pressure_bound + text2num(signal.data["adjust_external_pressure"]),
|
||||
ONE_ATMOSPHERE*50
|
||||
)
|
||||
|
||||
if(signal.data["init"] != null)
|
||||
name = signal.data["init"]
|
||||
return
|
||||
|
||||
if(signal.data["status"] != null)
|
||||
spawn(2)
|
||||
broadcast_status()
|
||||
update_icon()
|
||||
return
|
||||
return //do not update_icon
|
||||
|
||||
hide(var/i) //to make the little pipe section invisible, the icon changes.
|
||||
if(welded)
|
||||
icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]weld"
|
||||
return
|
||||
if(on&&node)
|
||||
if(pump_direction)
|
||||
icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]out"
|
||||
else
|
||||
icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]in"
|
||||
else
|
||||
icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]off"
|
||||
on = 0
|
||||
return
|
||||
//log_admin("DEBUG \[[world.timeofday]\]: vent_pump/receive_signal: unknown command \"[signal.data["command"]]\"\n[signal.debug_print()]")
|
||||
spawn(2)
|
||||
broadcast_status()
|
||||
update_icon()
|
||||
return
|
||||
|
||||
attackby(obj/item/W, mob/user)
|
||||
if(istype(W, /obj/item/weapon/weldingtool))
|
||||
var/obj/item/weapon/weldingtool/WT = W
|
||||
if (WT.remove_fuel(0,user))
|
||||
user << "\blue Now welding the vent."
|
||||
if(do_after(user, 20))
|
||||
if(!src || !WT.isOn()) return
|
||||
playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1)
|
||||
if(!welded)
|
||||
user.visible_message("[user] welds the vent shut.", "You weld the vent shut.", "You hear welding.")
|
||||
welded = 1
|
||||
update_icon()
|
||||
else
|
||||
user.visible_message("[user] unwelds the vent.", "You unweld the vent.", "You hear welding.")
|
||||
welded = 0
|
||||
update_icon()
|
||||
/obj/machinery/atmospherics/unary/vent_pump/attackby(obj/item/W, mob/user)
|
||||
if(istype(W, /obj/item/weapon/weldingtool))
|
||||
var/obj/item/weapon/weldingtool/WT = W
|
||||
if (WT.remove_fuel(0,user))
|
||||
user << "\blue Now welding the vent."
|
||||
if(do_after(user, 20))
|
||||
if(!src || !WT.isOn()) return
|
||||
playsound(src.loc, 'sound/items/Welder2.ogg', 50, 1)
|
||||
if(!welded)
|
||||
user.visible_message("[user] welds the vent shut.", "You weld the vent shut.", "You hear welding.")
|
||||
welded = 1
|
||||
update_icon()
|
||||
else
|
||||
user << "\blue The welding tool needs to be on to start this task."
|
||||
user.visible_message("[user] unwelds the vent.", "You unweld the vent.", "You hear welding.")
|
||||
welded = 0
|
||||
update_icon()
|
||||
else
|
||||
user << "\blue You need more welding fuel to complete this task."
|
||||
return 1
|
||||
examine()
|
||||
set src in oview(1)
|
||||
..()
|
||||
if(welded)
|
||||
usr << "It seems welded shut."
|
||||
|
||||
power_change()
|
||||
if(powered(power_channel))
|
||||
stat &= ~NOPOWER
|
||||
user << "\blue The welding tool needs to be on to start this task."
|
||||
else
|
||||
stat |= NOPOWER
|
||||
user << "\blue You need more welding fuel to complete this task."
|
||||
return 1
|
||||
else
|
||||
..()
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_pump/examine()
|
||||
set src in oview(1)
|
||||
..()
|
||||
if (get_dist(usr, src) <= 1)
|
||||
usr << "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W"
|
||||
else
|
||||
usr << "You are too far away to read the gauge."
|
||||
if(welded)
|
||||
usr << "It seems welded shut."
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_pump/power_change()
|
||||
var/old_stat = stat
|
||||
..()
|
||||
if(old_stat != stat)
|
||||
update_icon()
|
||||
|
||||
attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if (!istype(W, /obj/item/weapon/wrench))
|
||||
return ..()
|
||||
if (!(stat & NOPOWER) && on)
|
||||
user << "\red You cannot unwrench this [src], turn it off first."
|
||||
return 1
|
||||
var/turf/T = src.loc
|
||||
if (level==1 && isturf(T) && T.intact)
|
||||
user << "\red You must remove the plating first."
|
||||
return 1
|
||||
var/datum/gas_mixture/int_air = return_air()
|
||||
var/datum/gas_mixture/env_air = loc.return_air()
|
||||
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
|
||||
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
|
||||
add_fingerprint(user)
|
||||
return 1
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
user << "\blue You begin to unfasten \the [src]..."
|
||||
if (do_after(user, 40))
|
||||
user.visible_message( \
|
||||
"[user] unfastens \the [src].", \
|
||||
"\blue You have unfastened \the [src].", \
|
||||
"You hear ratchet.")
|
||||
new /obj/item/pipe(loc, make_from=src)
|
||||
del(src)
|
||||
/obj/machinery/atmospherics/unary/vent_pump/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if (!istype(W, /obj/item/weapon/wrench))
|
||||
return ..()
|
||||
if (!(stat & NOPOWER) && on)
|
||||
user << "\red You cannot unwrench this [src], turn it off first."
|
||||
return 1
|
||||
var/turf/T = src.loc
|
||||
if (node && node.level==1 && isturf(T) && T.intact)
|
||||
user << "\red You must remove the plating first."
|
||||
return 1
|
||||
var/datum/gas_mixture/int_air = return_air()
|
||||
var/datum/gas_mixture/env_air = loc.return_air()
|
||||
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
|
||||
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
|
||||
add_fingerprint(user)
|
||||
return 1
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
user << "\blue You begin to unfasten \the [src]..."
|
||||
if (do_after(user, 40))
|
||||
user.visible_message( \
|
||||
"[user] unfastens \the [src].", \
|
||||
"\blue You have unfastened \the [src].", \
|
||||
"You hear ratchet.")
|
||||
new /obj/item/pipe(loc, make_from=src)
|
||||
del(src)
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_pump/Del()
|
||||
if(initial_loc)
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
/obj/machinery/atmospherics/unary/vent_scrubber
|
||||
icon = 'icons/obj/atmospherics/vent_scrubber.dmi'
|
||||
icon_state = "off"
|
||||
icon = 'icons/atmos/vent_scrubber.dmi'
|
||||
icon_state = "map_scrubber"
|
||||
|
||||
name = "Air Scrubber"
|
||||
desc = "Has a valve and pump attached to it"
|
||||
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 pump is, in Watts. 7500 W ~ 10 HP
|
||||
var/last_power_draw = 0
|
||||
|
||||
level = 1
|
||||
|
||||
@@ -15,255 +18,246 @@
|
||||
|
||||
var/on = 0
|
||||
var/scrubbing = 1 //0 = siphoning, 1 = scrubbing
|
||||
var/scrub_CO2 = 1
|
||||
var/scrub_Toxins = 0
|
||||
var/scrub_N2O = 0
|
||||
var/list/scrubbing_gas = list()
|
||||
|
||||
var/volume_rate = 120
|
||||
var/panic = 0 //is this scrubber panicked?
|
||||
|
||||
var/area_uid
|
||||
var/radio_filter_out
|
||||
var/radio_filter_in
|
||||
New()
|
||||
initial_loc = get_area(loc)
|
||||
if (initial_loc.master)
|
||||
initial_loc = initial_loc.master
|
||||
area_uid = initial_loc.uid
|
||||
if (!id_tag)
|
||||
assign_uid()
|
||||
id_tag = num2text(uid)
|
||||
if(ticker && ticker.current_state == 3)//if the game is running
|
||||
src.initialize()
|
||||
src.broadcast_status()
|
||||
..()
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_scrubber/New()
|
||||
..()
|
||||
air_contents.volume = ATMOS_DEFAULT_VOLUME_FILTER
|
||||
|
||||
icon = null
|
||||
initial_loc = get_area(loc)
|
||||
if (initial_loc.master)
|
||||
initial_loc = initial_loc.master
|
||||
area_uid = initial_loc.uid
|
||||
if (!id_tag)
|
||||
assign_uid()
|
||||
id_tag = num2text(uid)
|
||||
if(ticker && ticker.current_state == 3)//if the game is running
|
||||
src.initialize()
|
||||
src.broadcast_status()
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_scrubber/update_icon(var/safety = 0)
|
||||
if(!check_icon_cache())
|
||||
return
|
||||
|
||||
overlays.Cut()
|
||||
|
||||
var/scrubber_icon = "scrubber"
|
||||
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T))
|
||||
return
|
||||
|
||||
if(!powered())
|
||||
scrubber_icon += "off"
|
||||
else
|
||||
scrubber_icon += "[on ? "[scrubbing ? "on" : "in"]" : "off"]"
|
||||
|
||||
overlays += icon_manager.get_atmos_icon("device", , , scrubber_icon)
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_scrubber/update_underlays()
|
||||
if(..())
|
||||
underlays.Cut()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T))
|
||||
return
|
||||
if(T.intact && node && node.level == 1 && istype(node, /obj/machinery/atmospherics/pipe))
|
||||
return
|
||||
else
|
||||
add_underlay(T, node, dir)
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_scrubber/proc/set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = radio_controller.add_object(src, frequency, radio_filter_in)
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_scrubber/proc/broadcast_status()
|
||||
if(!radio_connection)
|
||||
return 0
|
||||
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 1 //radio signal
|
||||
signal.source = src
|
||||
signal.data = list(
|
||||
"area" = area_uid,
|
||||
"tag" = id_tag,
|
||||
"device" = "AScr",
|
||||
"timestamp" = world.time,
|
||||
"power" = on,
|
||||
"scrubbing" = scrubbing,
|
||||
"panic" = panic,
|
||||
"filter_co2" = ("carbon_dioxide" in scrubbing_gas),
|
||||
"filter_phoron" = ("phoron" in scrubbing_gas),
|
||||
"filter_n2o" = ("sleeping_agent" in scrubbing_gas),
|
||||
"sigtype" = "status"
|
||||
)
|
||||
if(!initial_loc.air_scrub_names[id_tag])
|
||||
var/new_name = "[initial_loc.name] Air Scrubber #[initial_loc.air_scrub_names.len+1]"
|
||||
initial_loc.air_scrub_names[id_tag] = new_name
|
||||
src.name = new_name
|
||||
initial_loc.air_scrub_info[id_tag] = signal.data
|
||||
radio_connection.post_signal(src, signal, radio_filter_out)
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_scrubber/initialize()
|
||||
..()
|
||||
radio_filter_in = frequency==initial(frequency)?(RADIO_FROM_AIRALARM):null
|
||||
radio_filter_out = frequency==initial(frequency)?(RADIO_TO_AIRALARM):null
|
||||
if (frequency)
|
||||
set_frequency(frequency)
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_scrubber/process()
|
||||
..()
|
||||
if (!node)
|
||||
on = 0
|
||||
//broadcast_status()
|
||||
if(!on || (stat & (NOPOWER|BROKEN)))
|
||||
update_use_power(0) //we got here because a player turned a pump off - definitely want to update.
|
||||
last_flow_rate = 0
|
||||
last_power_draw = 0
|
||||
return 0
|
||||
|
||||
var/datum/gas_mixture/environment = loc.return_air()
|
||||
|
||||
var/power_draw = -1
|
||||
if(scrubbing)
|
||||
//limit flow rate from turfs
|
||||
var/transfer_moles = min(environment.total_moles, environment.total_moles*MAX_SCRUBBER_FLOWRATE/environment.volume) //group_multiplier gets divided out here
|
||||
|
||||
power_draw = scrub_gas(src, scrubbing_gas, environment, air_contents, transfer_moles, active_power_usage)
|
||||
else //Just siphon all air
|
||||
//limit flow rate from turfs
|
||||
var/transfer_moles = min(environment.total_moles, environment.total_moles*MAX_SIPHON_FLOWRATE/environment.volume) //group_multiplier gets divided out here
|
||||
|
||||
power_draw = pump_gas(src, environment, air_contents, transfer_moles, active_power_usage)
|
||||
|
||||
if (power_draw < 0)
|
||||
//update_use_power(0)
|
||||
use_power = 0 //don't force update. Sure, we will continue to use power even though we're not pumping anything, but it is easier on the CPU
|
||||
last_power_draw = 0
|
||||
last_flow_rate = 0
|
||||
else
|
||||
last_power_draw = handle_power_draw(power_draw)
|
||||
|
||||
if(network)
|
||||
network.update = 1
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_scrubber/hide(var/i) //to make the little pipe section invisible, the icon changes.
|
||||
update_icon()
|
||||
if(node && on && !(stat & (NOPOWER|BROKEN)))
|
||||
if(scrubbing)
|
||||
icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]on"
|
||||
else
|
||||
icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]in"
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_scrubber/receive_signal(datum/signal/signal)
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command"))
|
||||
return 0
|
||||
|
||||
if(signal.data["power"] != null)
|
||||
on = text2num(signal.data["power"])
|
||||
if(signal.data["power_toggle"] != null)
|
||||
on = !on
|
||||
|
||||
if(signal.data["panic_siphon"]) //must be before if("scrubbing" thing
|
||||
panic = text2num(signal.data["panic_siphon"] != null)
|
||||
if(panic)
|
||||
on = 1
|
||||
scrubbing = 0
|
||||
else
|
||||
icon_state = "[level == 1 && istype(loc, /turf/simulated) ? "h" : "" ]off"
|
||||
scrubbing = 1
|
||||
if(signal.data["toggle_panic_siphon"] != null)
|
||||
panic = !panic
|
||||
if(panic)
|
||||
on = 1
|
||||
scrubbing = 0
|
||||
else
|
||||
scrubbing = 1
|
||||
|
||||
if(signal.data["scrubbing"] != null)
|
||||
scrubbing = text2num(signal.data["scrubbing"])
|
||||
if(signal.data["toggle_scrubbing"])
|
||||
scrubbing = !scrubbing
|
||||
|
||||
var/list/toggle = list()
|
||||
|
||||
if(!isnull(signal.data["co2_scrub"]) && text2num(signal.data["co2_scrub"]) != ("carbon_dioxide" in scrubbing_gas))
|
||||
toggle += "carbon_dioxide"
|
||||
else if(signal.data["toggle_co2_scrub"])
|
||||
toggle += "carbon_dioxide"
|
||||
|
||||
if(!isnull(signal.data["tox_scrub"]) && text2num(signal.data["tox_scrub"]) != ("phoron" in scrubbing_gas))
|
||||
toggle += "phoron"
|
||||
else if(signal.data["toggle_tox_scrub"])
|
||||
toggle += "phoron"
|
||||
|
||||
if(!isnull(signal.data["n2o_scrub"]) && text2num(signal.data["n2o_scrub"]) != ("sleeping_agent" in scrubbing_gas))
|
||||
toggle += "sleeping_agent"
|
||||
else if(signal.data["toggle_n2o_scrub"])
|
||||
toggle += "sleeping_agent"
|
||||
|
||||
scrubbing_gas ^= toggle
|
||||
|
||||
if(signal.data["init"] != null)
|
||||
name = signal.data["init"]
|
||||
return
|
||||
|
||||
proc
|
||||
set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
radio_connection = radio_controller.add_object(src, frequency, radio_filter_in)
|
||||
|
||||
broadcast_status()
|
||||
if(!radio_connection)
|
||||
return 0
|
||||
|
||||
var/datum/signal/signal = new
|
||||
signal.transmission_method = 1 //radio signal
|
||||
signal.source = src
|
||||
signal.data = list(
|
||||
"area" = area_uid,
|
||||
"tag" = id_tag,
|
||||
"device" = "AScr",
|
||||
"timestamp" = world.time,
|
||||
"power" = on,
|
||||
"scrubbing" = scrubbing,
|
||||
"panic" = panic,
|
||||
"filter_co2" = scrub_CO2,
|
||||
"filter_phoron" = scrub_Toxins,
|
||||
"filter_n2o" = scrub_N2O,
|
||||
"sigtype" = "status"
|
||||
)
|
||||
if(!initial_loc.air_scrub_names[id_tag])
|
||||
var/new_name = "[initial_loc.name] Air Scrubber #[initial_loc.air_scrub_names.len+1]"
|
||||
initial_loc.air_scrub_names[id_tag] = new_name
|
||||
src.name = new_name
|
||||
initial_loc.air_scrub_info[id_tag] = signal.data
|
||||
radio_connection.post_signal(src, signal, radio_filter_out)
|
||||
|
||||
return 1
|
||||
|
||||
initialize()
|
||||
..()
|
||||
radio_filter_in = frequency==initial(frequency)?(RADIO_FROM_AIRALARM):null
|
||||
radio_filter_out = frequency==initial(frequency)?(RADIO_TO_AIRALARM):null
|
||||
if (frequency)
|
||||
set_frequency(frequency)
|
||||
|
||||
process()
|
||||
..()
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
if (!node)
|
||||
on = 0
|
||||
//broadcast_status()
|
||||
if(!on)
|
||||
return 0
|
||||
|
||||
|
||||
var/datum/gas_mixture/environment = loc.return_air()
|
||||
|
||||
if(scrubbing)
|
||||
if((environment.phoron>0.001) || (environment.carbon_dioxide>0.001) || (environment.trace_gases.len>0))
|
||||
var/transfer_moles = min(1, volume_rate/environment.volume)*environment.total_moles()
|
||||
|
||||
//Take a gas sample
|
||||
var/datum/gas_mixture/removed = loc.remove_air(transfer_moles)
|
||||
if (isnull(removed)) //in space
|
||||
return
|
||||
|
||||
//Filter it
|
||||
var/datum/gas_mixture/filtered_out = new
|
||||
filtered_out.temperature = removed.temperature
|
||||
if(scrub_Toxins)
|
||||
filtered_out.phoron = removed.phoron
|
||||
removed.phoron = 0
|
||||
if(scrub_CO2)
|
||||
filtered_out.carbon_dioxide = removed.carbon_dioxide
|
||||
removed.carbon_dioxide = 0
|
||||
|
||||
if(removed.trace_gases.len>0)
|
||||
for(var/datum/gas/trace_gas in removed.trace_gases)
|
||||
if(istype(trace_gas, /datum/gas/oxygen_agent_b))
|
||||
removed.trace_gases -= trace_gas
|
||||
filtered_out.trace_gases += trace_gas
|
||||
else if(istype(trace_gas, /datum/gas/sleeping_agent) && scrub_N2O)
|
||||
removed.trace_gases -= trace_gas
|
||||
filtered_out.trace_gases += trace_gas
|
||||
|
||||
|
||||
//Remix the resulting gases
|
||||
air_contents.merge(filtered_out)
|
||||
|
||||
loc.assume_air(removed)
|
||||
|
||||
if(network)
|
||||
network.update = 1
|
||||
|
||||
else //Just siphoning all air
|
||||
if (air_contents.return_pressure()>=50*ONE_ATMOSPHERE)
|
||||
return
|
||||
|
||||
var/transfer_moles = environment.total_moles()*(volume_rate/environment.volume)
|
||||
|
||||
var/datum/gas_mixture/removed = loc.remove_air(transfer_moles)
|
||||
|
||||
air_contents.merge(removed)
|
||||
|
||||
if(network)
|
||||
network.update = 1
|
||||
|
||||
return 1
|
||||
/* //unused piece of code
|
||||
hide(var/i) //to make the little pipe section invisible, the icon changes.
|
||||
if(on&&node)
|
||||
if(scrubbing)
|
||||
icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]on"
|
||||
else
|
||||
icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]in"
|
||||
else
|
||||
icon_state = "[i == 1 && istype(loc, /turf/simulated) ? "h" : "" ]off"
|
||||
on = 0
|
||||
return
|
||||
*/
|
||||
|
||||
receive_signal(datum/signal/signal)
|
||||
if(stat & (NOPOWER|BROKEN))
|
||||
return
|
||||
if(!signal.data["tag"] || (signal.data["tag"] != id_tag) || (signal.data["sigtype"]!="command"))
|
||||
return 0
|
||||
|
||||
if(signal.data["power"] != null)
|
||||
on = text2num(signal.data["power"])
|
||||
if(signal.data["power_toggle"] != null)
|
||||
on = !on
|
||||
|
||||
if(signal.data["panic_siphon"]) //must be before if("scrubbing" thing
|
||||
panic = text2num(signal.data["panic_siphon"] != null)
|
||||
if(panic)
|
||||
on = 1
|
||||
scrubbing = 0
|
||||
volume_rate = 2000
|
||||
else
|
||||
scrubbing = 1
|
||||
volume_rate = initial(volume_rate)
|
||||
if(signal.data["toggle_panic_siphon"] != null)
|
||||
panic = !panic
|
||||
if(panic)
|
||||
on = 1
|
||||
scrubbing = 0
|
||||
volume_rate = 2000
|
||||
else
|
||||
scrubbing = 1
|
||||
volume_rate = initial(volume_rate)
|
||||
|
||||
if(signal.data["scrubbing"] != null)
|
||||
scrubbing = text2num(signal.data["scrubbing"])
|
||||
if(signal.data["toggle_scrubbing"])
|
||||
scrubbing = !scrubbing
|
||||
|
||||
if(signal.data["co2_scrub"] != null)
|
||||
scrub_CO2 = text2num(signal.data["co2_scrub"])
|
||||
if(signal.data["toggle_co2_scrub"])
|
||||
scrub_CO2 = !scrub_CO2
|
||||
|
||||
if(signal.data["tox_scrub"] != null)
|
||||
scrub_Toxins = text2num(signal.data["tox_scrub"])
|
||||
if(signal.data["toggle_tox_scrub"])
|
||||
scrub_Toxins = !scrub_Toxins
|
||||
|
||||
if(signal.data["n2o_scrub"] != null)
|
||||
scrub_N2O = text2num(signal.data["n2o_scrub"])
|
||||
if(signal.data["toggle_n2o_scrub"])
|
||||
scrub_N2O = !scrub_N2O
|
||||
|
||||
if(signal.data["init"] != null)
|
||||
name = signal.data["init"]
|
||||
return
|
||||
|
||||
if(signal.data["status"] != null)
|
||||
spawn(2)
|
||||
broadcast_status()
|
||||
return //do not update_icon
|
||||
|
||||
// log_admin("DEBUG \[[world.timeofday]\]: vent_scrubber/receive_signal: unknown command \"[signal.data["command"]]\"\n[signal.debug_print()]")
|
||||
if(signal.data["status"] != null)
|
||||
spawn(2)
|
||||
broadcast_status()
|
||||
update_icon()
|
||||
return
|
||||
return //do not update_icon
|
||||
|
||||
power_change()
|
||||
if(powered(power_channel))
|
||||
stat &= ~NOPOWER
|
||||
else
|
||||
stat |= NOPOWER
|
||||
// log_admin("DEBUG \[[world.timeofday]\]: vent_scrubber/receive_signal: unknown command \"[signal.data["command"]]\"\n[signal.debug_print()]")
|
||||
spawn(2)
|
||||
broadcast_status()
|
||||
update_icon()
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_scrubber/power_change()
|
||||
var/old_stat = stat
|
||||
..()
|
||||
if(old_stat != stat)
|
||||
update_icon()
|
||||
|
||||
attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if (!istype(W, /obj/item/weapon/wrench))
|
||||
return ..()
|
||||
if (!(stat & NOPOWER) && on)
|
||||
user << "\red You cannot unwrench this [src], turn it off first."
|
||||
return 1
|
||||
var/turf/T = src.loc
|
||||
if (level==1 && isturf(T) && T.intact)
|
||||
user << "\red You must remove the plating first."
|
||||
return 1
|
||||
var/datum/gas_mixture/int_air = return_air()
|
||||
var/datum/gas_mixture/env_air = loc.return_air()
|
||||
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
|
||||
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
|
||||
add_fingerprint(user)
|
||||
return 1
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
user << "\blue You begin to unfasten \the [src]..."
|
||||
if (do_after(user, 40))
|
||||
user.visible_message( \
|
||||
"[user] unfastens \the [src].", \
|
||||
"\blue You have unfastened \the [src].", \
|
||||
"You hear ratchet.")
|
||||
new /obj/item/pipe(loc, make_from=src)
|
||||
del(src)
|
||||
/obj/machinery/atmospherics/unary/vent_scrubber/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if (!istype(W, /obj/item/weapon/wrench))
|
||||
return ..()
|
||||
if (!(stat & NOPOWER) && on)
|
||||
user << "\red You cannot unwrench this [src], turn it off first."
|
||||
return 1
|
||||
var/turf/T = src.loc
|
||||
if (node && node.level==1 && isturf(T) && T.intact)
|
||||
user << "\red You must remove the plating first."
|
||||
return 1
|
||||
var/datum/gas_mixture/int_air = return_air()
|
||||
var/datum/gas_mixture/env_air = loc.return_air()
|
||||
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
|
||||
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
|
||||
add_fingerprint(user)
|
||||
return 1
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
user << "\blue You begin to unfasten \the [src]..."
|
||||
if (do_after(user, 40))
|
||||
user.visible_message( \
|
||||
"[user] unfastens \the [src].", \
|
||||
"\blue You have unfastened \the [src].", \
|
||||
"You hear ratchet.")
|
||||
new /obj/item/pipe(loc, make_from=src)
|
||||
del(src)
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_scrubber/examine()
|
||||
set src in oview(1)
|
||||
..()
|
||||
if (get_dist(usr, src) <= 1)
|
||||
usr << "A small gauge in the corner reads [round(last_flow_rate, 0.1)] L/s; [round(last_power_draw)] W"
|
||||
else
|
||||
usr << "You are too far away to read the gauge."
|
||||
|
||||
/obj/machinery/atmospherics/unary/vent_scrubber/Del()
|
||||
if(initial_loc)
|
||||
|
||||
@@ -1,10 +1,11 @@
|
||||
obj/machinery/atmospherics/valve
|
||||
icon = 'icons/obj/atmospherics/valve.dmi'
|
||||
icon_state = "valve0"
|
||||
/obj/machinery/atmospherics/valve
|
||||
icon = 'icons/atmos/valve.dmi'
|
||||
icon_state = "map_valve0"
|
||||
|
||||
name = "manual valve"
|
||||
desc = "A pipe valve"
|
||||
|
||||
level = 1
|
||||
dir = SOUTH
|
||||
initialize_directions = SOUTH|NORTH
|
||||
|
||||
@@ -17,322 +18,297 @@ obj/machinery/atmospherics/valve
|
||||
var/datum/pipe_network/network_node1
|
||||
var/datum/pipe_network/network_node2
|
||||
|
||||
open
|
||||
open = 1
|
||||
icon_state = "valve1"
|
||||
/obj/machinery/atmospherics/valve/open
|
||||
open = 1
|
||||
icon_state = "map_valve1"
|
||||
|
||||
update_icon(animation)
|
||||
if(animation)
|
||||
flick("valve[src.open][!src.open]",src)
|
||||
else
|
||||
icon_state = "valve[open]"
|
||||
/obj/machinery/atmospherics/valve/update_icon(animation)
|
||||
if(animation)
|
||||
flick("valve[src.open][!src.open]",src)
|
||||
else
|
||||
icon_state = "valve[open]"
|
||||
|
||||
New()
|
||||
switch(dir)
|
||||
if(NORTH || SOUTH)
|
||||
initialize_directions = NORTH|SOUTH
|
||||
if(EAST || WEST)
|
||||
initialize_directions = EAST|WEST
|
||||
..()
|
||||
/obj/machinery/atmospherics/valve/update_underlays()
|
||||
if(..())
|
||||
underlays.Cut()
|
||||
var/turf/T = get_turf(src)
|
||||
if(!istype(T))
|
||||
return
|
||||
add_underlay(T, node1, get_dir(src, node1))
|
||||
add_underlay(T, node2, get_dir(src, node2))
|
||||
|
||||
network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
|
||||
/obj/machinery/atmospherics/valve/hide(var/i)
|
||||
update_underlays()
|
||||
|
||||
/obj/machinery/atmospherics/valve/New()
|
||||
switch(dir)
|
||||
if(NORTH || SOUTH)
|
||||
initialize_directions = NORTH|SOUTH
|
||||
if(EAST || WEST)
|
||||
initialize_directions = EAST|WEST
|
||||
..()
|
||||
|
||||
if(reference == node1)
|
||||
network_node1 = new_network
|
||||
if(open)
|
||||
network_node2 = new_network
|
||||
else if(reference == node2)
|
||||
network_node2 = new_network
|
||||
if(open)
|
||||
network_node1 = new_network
|
||||
|
||||
if(new_network.normal_members.Find(src))
|
||||
return 0
|
||||
|
||||
new_network.normal_members += src
|
||||
|
||||
/obj/machinery/atmospherics/valve/network_expand(datum/pipe_network/new_network, obj/machinery/atmospherics/pipe/reference)
|
||||
if(reference == node1)
|
||||
network_node1 = new_network
|
||||
if(open)
|
||||
if(reference == node1)
|
||||
if(node2)
|
||||
return node2.network_expand(new_network, src)
|
||||
else if(reference == node2)
|
||||
if(node1)
|
||||
return node1.network_expand(new_network, src)
|
||||
network_node2 = new_network
|
||||
else if(reference == node2)
|
||||
network_node2 = new_network
|
||||
if(open)
|
||||
network_node1 = new_network
|
||||
|
||||
return null
|
||||
if(new_network.normal_members.Find(src))
|
||||
return 0
|
||||
|
||||
Del()
|
||||
loc = null
|
||||
new_network.normal_members += src
|
||||
|
||||
if(node1)
|
||||
node1.disconnect(src)
|
||||
del(network_node1)
|
||||
if(node2)
|
||||
node2.disconnect(src)
|
||||
del(network_node2)
|
||||
if(open)
|
||||
if(reference == node1)
|
||||
if(node2)
|
||||
return node2.network_expand(new_network, src)
|
||||
else if(reference == node2)
|
||||
if(node1)
|
||||
return node1.network_expand(new_network, src)
|
||||
|
||||
return null
|
||||
|
||||
/obj/machinery/atmospherics/valve/Del()
|
||||
loc = null
|
||||
|
||||
if(node1)
|
||||
node1.disconnect(src)
|
||||
del(network_node1)
|
||||
if(node2)
|
||||
node2.disconnect(src)
|
||||
del(network_node2)
|
||||
|
||||
node1 = null
|
||||
node2 = null
|
||||
|
||||
..()
|
||||
|
||||
/obj/machinery/atmospherics/valve/proc/open()
|
||||
if(open) return 0
|
||||
|
||||
open = 1
|
||||
update_icon()
|
||||
|
||||
if(network_node1&&network_node2)
|
||||
network_node1.merge(network_node2)
|
||||
network_node2 = network_node1
|
||||
|
||||
if(network_node1)
|
||||
network_node1.update = 1
|
||||
else if(network_node2)
|
||||
network_node2.update = 1
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/atmospherics/valve/proc/close()
|
||||
if(!open)
|
||||
return 0
|
||||
|
||||
open = 0
|
||||
update_icon()
|
||||
|
||||
if(network_node1)
|
||||
del(network_node1)
|
||||
if(network_node2)
|
||||
del(network_node2)
|
||||
|
||||
build_network()
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/atmospherics/valve/proc/normalize_dir()
|
||||
if(dir==3)
|
||||
dir = 1
|
||||
else if(dir==12)
|
||||
dir = 4
|
||||
|
||||
/obj/machinery/atmospherics/valve/attack_ai(mob/user as mob)
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/valve/attack_paw(mob/user as mob)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/machinery/atmospherics/valve/attack_hand(mob/user as mob)
|
||||
src.add_fingerprint(usr)
|
||||
update_icon(1)
|
||||
sleep(10)
|
||||
if (src.open)
|
||||
src.close()
|
||||
else
|
||||
src.open()
|
||||
|
||||
/obj/machinery/atmospherics/valve/process()
|
||||
..()
|
||||
. = PROCESS_KILL
|
||||
|
||||
return
|
||||
|
||||
/obj/machinery/atmospherics/valve/initialize()
|
||||
normalize_dir()
|
||||
|
||||
var/node1_dir
|
||||
var/node2_dir
|
||||
|
||||
for(var/direction in cardinal)
|
||||
if(direction&initialize_directions)
|
||||
if (!node1_dir)
|
||||
node1_dir = direction
|
||||
else if (!node2_dir)
|
||||
node2_dir = direction
|
||||
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node1_dir))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node1 = target
|
||||
break
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node2_dir))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node2 = target
|
||||
break
|
||||
|
||||
build_network()
|
||||
|
||||
update_icon()
|
||||
update_underlays()
|
||||
|
||||
if(openDuringInit)
|
||||
close()
|
||||
open()
|
||||
openDuringInit = 0
|
||||
|
||||
/obj/machinery/atmospherics/valve/build_network()
|
||||
if(!network_node1 && node1)
|
||||
network_node1 = new /datum/pipe_network()
|
||||
network_node1.normal_members += src
|
||||
network_node1.build_network(node1, src)
|
||||
|
||||
if(!network_node2 && node2)
|
||||
network_node2 = new /datum/pipe_network()
|
||||
network_node2.normal_members += src
|
||||
network_node2.build_network(node2, src)
|
||||
|
||||
/obj/machinery/atmospherics/valve/return_network(obj/machinery/atmospherics/reference)
|
||||
build_network()
|
||||
|
||||
if(reference==node1)
|
||||
return network_node1
|
||||
|
||||
if(reference==node2)
|
||||
return network_node2
|
||||
|
||||
return null
|
||||
|
||||
/obj/machinery/atmospherics/valve/reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
|
||||
if(network_node1 == old_network)
|
||||
network_node1 = new_network
|
||||
if(network_node2 == old_network)
|
||||
network_node2 = new_network
|
||||
|
||||
return 1
|
||||
|
||||
/obj/machinery/atmospherics/valve/return_network_air(datum/network/reference)
|
||||
return null
|
||||
|
||||
/obj/machinery/atmospherics/valve/disconnect(obj/machinery/atmospherics/reference)
|
||||
if(reference==node1)
|
||||
del(network_node1)
|
||||
node1 = null
|
||||
|
||||
else if(reference==node2)
|
||||
del(network_node2)
|
||||
node2 = null
|
||||
|
||||
..()
|
||||
update_underlays()
|
||||
|
||||
proc/open()
|
||||
return null
|
||||
|
||||
if(open) return 0
|
||||
/obj/machinery/atmospherics/valve/digital // can be controlled by AI
|
||||
name = "digital valve"
|
||||
desc = "A digitally controlled valve."
|
||||
icon = 'icons/atmos/digital_valve.dmi'
|
||||
|
||||
var/frequency = 0
|
||||
var/id = null
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
open = 1
|
||||
/obj/machinery/atmospherics/valve/digital/attack_ai(mob/user as mob)
|
||||
return src.attack_hand(user)
|
||||
|
||||
/obj/machinery/atmospherics/valve/digital/attack_hand(mob/user as mob)
|
||||
if(!powered())
|
||||
return
|
||||
if(!src.allowed(user))
|
||||
user << "\red Access denied."
|
||||
return
|
||||
..()
|
||||
|
||||
/obj/machinery/atmospherics/valve/digital/open
|
||||
open = 1
|
||||
icon_state = "map_valve1"
|
||||
|
||||
/obj/machinery/atmospherics/valve/digital/power_change()
|
||||
var/old_stat = stat
|
||||
..()
|
||||
if(old_stat != stat)
|
||||
update_icon()
|
||||
|
||||
if(network_node1&&network_node2)
|
||||
network_node1.merge(network_node2)
|
||||
network_node2 = network_node1
|
||||
/obj/machinery/atmospherics/valve/digital/update_icon()
|
||||
..()
|
||||
if(!powered())
|
||||
icon_state = "valve[open]nopower"
|
||||
|
||||
if(network_node1)
|
||||
network_node1.update = 1
|
||||
else if(network_node2)
|
||||
network_node2.update = 1
|
||||
/obj/machinery/atmospherics/valve/digital/proc/set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
if(frequency)
|
||||
radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA)
|
||||
|
||||
return 1
|
||||
/obj/machinery/atmospherics/valve/digital/initialize()
|
||||
..()
|
||||
if(frequency)
|
||||
set_frequency(frequency)
|
||||
|
||||
proc/close()
|
||||
/obj/machinery/atmospherics/valve/digital/receive_signal(datum/signal/signal)
|
||||
if(!signal.data["tag"] || (signal.data["tag"] != id))
|
||||
return 0
|
||||
|
||||
if(!open)
|
||||
return 0
|
||||
switch(signal.data["command"])
|
||||
if("valve_open")
|
||||
if(!open)
|
||||
open()
|
||||
|
||||
open = 0
|
||||
update_icon()
|
||||
if("valve_close")
|
||||
if(open)
|
||||
close()
|
||||
|
||||
if(network_node1)
|
||||
del(network_node1)
|
||||
if(network_node2)
|
||||
del(network_node2)
|
||||
|
||||
build_network()
|
||||
|
||||
return 1
|
||||
|
||||
proc/normalize_dir()
|
||||
if(dir==3)
|
||||
dir = 1
|
||||
else if(dir==12)
|
||||
dir = 4
|
||||
|
||||
attack_ai(mob/user as mob)
|
||||
return
|
||||
|
||||
attack_paw(mob/user as mob)
|
||||
return attack_hand(user)
|
||||
|
||||
attack_hand(mob/user as mob)
|
||||
src.add_fingerprint(usr)
|
||||
update_icon(1)
|
||||
sleep(10)
|
||||
if (src.open)
|
||||
src.close()
|
||||
else
|
||||
src.open()
|
||||
|
||||
process()
|
||||
..()
|
||||
. = PROCESS_KILL
|
||||
|
||||
/* if(open && (!node1 || !node2))
|
||||
close()
|
||||
if(!node1)
|
||||
if(!nodealert)
|
||||
//world << "Missing node from [src] at [src.x],[src.y],[src.z]"
|
||||
nodealert = 1
|
||||
else if (!node2)
|
||||
if(!nodealert)
|
||||
//world << "Missing node from [src] at [src.x],[src.y],[src.z]"
|
||||
nodealert = 1
|
||||
else if (nodealert)
|
||||
nodealert = 0
|
||||
*/
|
||||
|
||||
return
|
||||
|
||||
initialize()
|
||||
normalize_dir()
|
||||
|
||||
var/node1_dir
|
||||
var/node2_dir
|
||||
|
||||
for(var/direction in cardinal)
|
||||
if(direction&initialize_directions)
|
||||
if (!node1_dir)
|
||||
node1_dir = direction
|
||||
else if (!node2_dir)
|
||||
node2_dir = direction
|
||||
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node1_dir))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node1 = target
|
||||
break
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,node2_dir))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node2 = target
|
||||
break
|
||||
|
||||
build_network()
|
||||
|
||||
if(openDuringInit)
|
||||
close()
|
||||
open()
|
||||
openDuringInit = 0
|
||||
|
||||
/*
|
||||
var/connect_directions
|
||||
switch(dir)
|
||||
if(NORTH)
|
||||
connect_directions = NORTH|SOUTH
|
||||
if(SOUTH)
|
||||
connect_directions = NORTH|SOUTH
|
||||
if(EAST)
|
||||
connect_directions = EAST|WEST
|
||||
if(WEST)
|
||||
connect_directions = EAST|WEST
|
||||
if("valve_toggle")
|
||||
if(open)
|
||||
close()
|
||||
else
|
||||
connect_directions = dir
|
||||
|
||||
for(var/direction in cardinal)
|
||||
if(direction&connect_directions)
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,direction))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
connect_directions &= ~direction
|
||||
node1 = target
|
||||
break
|
||||
if(node1)
|
||||
break
|
||||
|
||||
for(var/direction in cardinal)
|
||||
if(direction&connect_directions)
|
||||
for(var/obj/machinery/atmospherics/target in get_step(src,direction))
|
||||
if(target.initialize_directions & get_dir(target,src))
|
||||
node2 = target
|
||||
break
|
||||
if(node1)
|
||||
break
|
||||
*/
|
||||
build_network()
|
||||
if(!network_node1 && node1)
|
||||
network_node1 = new /datum/pipe_network()
|
||||
network_node1.normal_members += src
|
||||
network_node1.build_network(node1, src)
|
||||
|
||||
if(!network_node2 && node2)
|
||||
network_node2 = new /datum/pipe_network()
|
||||
network_node2.normal_members += src
|
||||
network_node2.build_network(node2, src)
|
||||
|
||||
|
||||
return_network(obj/machinery/atmospherics/reference)
|
||||
build_network()
|
||||
|
||||
if(reference==node1)
|
||||
return network_node1
|
||||
|
||||
if(reference==node2)
|
||||
return network_node2
|
||||
|
||||
return null
|
||||
|
||||
reassign_network(datum/pipe_network/old_network, datum/pipe_network/new_network)
|
||||
if(network_node1 == old_network)
|
||||
network_node1 = new_network
|
||||
if(network_node2 == old_network)
|
||||
network_node2 = new_network
|
||||
open()
|
||||
|
||||
/obj/machinery/atmospherics/valve/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if (!istype(W, /obj/item/weapon/wrench))
|
||||
return ..()
|
||||
if (istype(src, /obj/machinery/atmospherics/valve/digital))
|
||||
user << "\red You cannot unwrench this [src], it's too complicated."
|
||||
return 1
|
||||
|
||||
return_network_air(datum/network/reference)
|
||||
return null
|
||||
|
||||
disconnect(obj/machinery/atmospherics/reference)
|
||||
if(reference==node1)
|
||||
del(network_node1)
|
||||
node1 = null
|
||||
|
||||
else if(reference==node2)
|
||||
del(network_node2)
|
||||
node2 = null
|
||||
|
||||
return null
|
||||
|
||||
digital // can be controlled by AI
|
||||
name = "digital valve"
|
||||
desc = "A digitally controlled valve."
|
||||
icon = 'icons/obj/atmospherics/digital_valve.dmi'
|
||||
|
||||
attack_ai(mob/user as mob)
|
||||
return src.attack_hand(user)
|
||||
|
||||
attack_hand(mob/user as mob)
|
||||
if(!src.allowed(user))
|
||||
user << "\red Access denied."
|
||||
return
|
||||
..()
|
||||
|
||||
//Radio remote control
|
||||
|
||||
proc
|
||||
set_frequency(new_frequency)
|
||||
radio_controller.remove_object(src, frequency)
|
||||
frequency = new_frequency
|
||||
if(frequency)
|
||||
radio_connection = radio_controller.add_object(src, frequency, RADIO_ATMOSIA)
|
||||
|
||||
var/frequency = 0
|
||||
var/id = null
|
||||
var/datum/radio_frequency/radio_connection
|
||||
|
||||
initialize()
|
||||
..()
|
||||
if(frequency)
|
||||
set_frequency(frequency)
|
||||
|
||||
receive_signal(datum/signal/signal)
|
||||
if(!signal.data["tag"] || (signal.data["tag"] != id))
|
||||
return 0
|
||||
|
||||
switch(signal.data["command"])
|
||||
if("valve_open")
|
||||
if(!open)
|
||||
open()
|
||||
|
||||
if("valve_close")
|
||||
if(open)
|
||||
close()
|
||||
|
||||
if("valve_toggle")
|
||||
if(open)
|
||||
close()
|
||||
else
|
||||
open()
|
||||
|
||||
attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
|
||||
if (!istype(W, /obj/item/weapon/wrench))
|
||||
return ..()
|
||||
if (istype(src, /obj/machinery/atmospherics/valve/digital))
|
||||
user << "\red You cannot unwrench this [src], it's too complicated."
|
||||
return 1
|
||||
var/turf/T = src.loc
|
||||
if (level==1 && isturf(T) && T.intact)
|
||||
user << "\red You must remove the plating first."
|
||||
return 1
|
||||
var/datum/gas_mixture/int_air = return_air()
|
||||
var/datum/gas_mixture/env_air = loc.return_air()
|
||||
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
|
||||
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
|
||||
add_fingerprint(user)
|
||||
return 1
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
user << "\blue You begin to unfasten \the [src]..."
|
||||
if (do_after(user, 40))
|
||||
user.visible_message( \
|
||||
"[user] unfastens \the [src].", \
|
||||
"\blue You have unfastened \the [src].", \
|
||||
"You hear ratchet.")
|
||||
new /obj/item/pipe(loc, make_from=src)
|
||||
del(src)
|
||||
var/datum/gas_mixture/int_air = return_air()
|
||||
var/datum/gas_mixture/env_air = loc.return_air()
|
||||
if ((int_air.return_pressure()-env_air.return_pressure()) > 2*ONE_ATMOSPHERE)
|
||||
user << "\red You cannot unwrench this [src], it too exerted due to internal pressure."
|
||||
add_fingerprint(user)
|
||||
return 1
|
||||
playsound(src.loc, 'sound/items/Ratchet.ogg', 50, 1)
|
||||
user << "\blue You begin to unfasten \the [src]..."
|
||||
if (do_after(user, 40))
|
||||
user.visible_message( \
|
||||
"[user] unfastens \the [src].", \
|
||||
"\blue You have unfastened \the [src].", \
|
||||
"You hear ratchet.")
|
||||
new /obj/item/pipe(loc, make_from=src)
|
||||
del(src)
|
||||
@@ -2,16 +2,17 @@ var/global/list/datum/pipe_network/pipe_networks = list()
|
||||
|
||||
datum/pipe_network
|
||||
var/list/datum/gas_mixture/gases = list() //All of the gas_mixtures continuously connected in this network
|
||||
var/volume = 0 //caches the total volume for atmos machines to use in gas calculations
|
||||
|
||||
var/list/obj/machinery/atmospherics/normal_members = list()
|
||||
var/list/datum/pipeline/line_members = list()
|
||||
//membership roster to go through for updates and what not
|
||||
|
||||
var/update = 1
|
||||
var/datum/gas_mixture/air_transient = null
|
||||
//var/datum/gas_mixture/air_transient = null
|
||||
|
||||
New()
|
||||
air_transient = new()
|
||||
//air_transient = new()
|
||||
|
||||
..()
|
||||
|
||||
@@ -61,6 +62,7 @@ datum/pipe_network
|
||||
//Go through membership roster and make sure gases is up to date
|
||||
|
||||
gases = list()
|
||||
volume = 0
|
||||
|
||||
for(var/obj/machinery/atmospherics/normal_member in normal_members)
|
||||
var/result = normal_member.return_network_air(src)
|
||||
@@ -68,137 +70,9 @@ datum/pipe_network
|
||||
|
||||
for(var/datum/pipeline/line_member in line_members)
|
||||
gases += line_member.air
|
||||
|
||||
for(var/datum/gas_mixture/air in gases)
|
||||
volume += air.volume
|
||||
|
||||
proc/reconcile_air()
|
||||
//Perfectly equalize all gases members instantly
|
||||
|
||||
//Calculate totals from individual components
|
||||
var/total_thermal_energy = 0
|
||||
var/total_heat_capacity = 0
|
||||
|
||||
air_transient.volume = 0
|
||||
|
||||
air_transient.oxygen = 0
|
||||
air_transient.nitrogen = 0
|
||||
air_transient.phoron = 0
|
||||
air_transient.carbon_dioxide = 0
|
||||
|
||||
|
||||
air_transient.trace_gases = list()
|
||||
|
||||
for(var/datum/gas_mixture/gas in gases)
|
||||
air_transient.volume += gas.volume
|
||||
var/temp_heatcap = gas.heat_capacity()
|
||||
total_thermal_energy += gas.temperature*temp_heatcap
|
||||
total_heat_capacity += temp_heatcap
|
||||
|
||||
air_transient.oxygen += gas.oxygen
|
||||
air_transient.nitrogen += gas.nitrogen
|
||||
air_transient.phoron += gas.phoron
|
||||
air_transient.carbon_dioxide += gas.carbon_dioxide
|
||||
|
||||
if(gas.trace_gases.len)
|
||||
for(var/datum/gas/trace_gas in gas.trace_gases)
|
||||
var/datum/gas/corresponding = locate(trace_gas.type) in air_transient.trace_gases
|
||||
if(!corresponding)
|
||||
corresponding = new trace_gas.type()
|
||||
air_transient.trace_gases += corresponding
|
||||
|
||||
corresponding.moles += trace_gas.moles
|
||||
|
||||
if(air_transient.volume > 0)
|
||||
|
||||
if(total_heat_capacity > 0)
|
||||
air_transient.temperature = total_thermal_energy/total_heat_capacity
|
||||
|
||||
//Allow air mixture to react
|
||||
if(air_transient.react())
|
||||
update = 1
|
||||
|
||||
else
|
||||
air_transient.temperature = 0
|
||||
|
||||
//Update individual gas_mixtures by volume ratio
|
||||
for(var/datum/gas_mixture/gas in gases)
|
||||
gas.oxygen = air_transient.oxygen*gas.volume/air_transient.volume
|
||||
gas.nitrogen = air_transient.nitrogen*gas.volume/air_transient.volume
|
||||
gas.phoron = air_transient.phoron*gas.volume/air_transient.volume
|
||||
gas.carbon_dioxide = air_transient.carbon_dioxide*gas.volume/air_transient.volume
|
||||
|
||||
gas.temperature = air_transient.temperature
|
||||
|
||||
if(air_transient.trace_gases.len)
|
||||
for(var/datum/gas/trace_gas in air_transient.trace_gases)
|
||||
var/datum/gas/corresponding = locate(trace_gas.type) in gas.trace_gases
|
||||
if(!corresponding)
|
||||
corresponding = new trace_gas.type()
|
||||
gas.trace_gases += corresponding
|
||||
|
||||
corresponding.moles = trace_gas.moles*gas.volume/air_transient.volume
|
||||
gas.update_values()
|
||||
air_transient.update_values()
|
||||
return 1
|
||||
|
||||
proc/equalize_gases(datum/gas_mixture/list/gases)
|
||||
//Perfectly equalize all gases members instantly
|
||||
|
||||
//Calculate totals from individual components
|
||||
var/total_volume = 0
|
||||
var/total_thermal_energy = 0
|
||||
var/total_heat_capacity = 0
|
||||
|
||||
var/total_oxygen = 0
|
||||
var/total_nitrogen = 0
|
||||
var/total_phoron = 0
|
||||
var/total_carbon_dioxide = 0
|
||||
|
||||
var/list/total_trace_gases = list()
|
||||
|
||||
for(var/datum/gas_mixture/gas in gases)
|
||||
total_volume += gas.volume
|
||||
var/temp_heatcap = gas.heat_capacity()
|
||||
total_thermal_energy += gas.temperature*temp_heatcap
|
||||
total_heat_capacity += temp_heatcap
|
||||
|
||||
total_oxygen += gas.oxygen
|
||||
total_nitrogen += gas.nitrogen
|
||||
total_phoron += gas.phoron
|
||||
total_carbon_dioxide += gas.carbon_dioxide
|
||||
|
||||
if(gas.trace_gases.len)
|
||||
for(var/datum/gas/trace_gas in gas.trace_gases)
|
||||
var/datum/gas/corresponding = locate(trace_gas.type) in total_trace_gases
|
||||
if(!corresponding)
|
||||
corresponding = new trace_gas.type()
|
||||
total_trace_gases += corresponding
|
||||
|
||||
corresponding.moles += trace_gas.moles
|
||||
|
||||
if(total_volume > 0)
|
||||
|
||||
//Calculate temperature
|
||||
var/temperature = 0
|
||||
|
||||
if(total_heat_capacity > 0)
|
||||
temperature = total_thermal_energy/total_heat_capacity
|
||||
|
||||
//Update individual gas_mixtures by volume ratio
|
||||
for(var/datum/gas_mixture/gas in gases)
|
||||
gas.oxygen = total_oxygen*gas.volume/total_volume
|
||||
gas.nitrogen = total_nitrogen*gas.volume/total_volume
|
||||
gas.phoron = total_phoron*gas.volume/total_volume
|
||||
gas.carbon_dioxide = total_carbon_dioxide*gas.volume/total_volume
|
||||
|
||||
gas.temperature = temperature
|
||||
|
||||
if(total_trace_gases.len)
|
||||
for(var/datum/gas/trace_gas in total_trace_gases)
|
||||
var/datum/gas/corresponding = locate(trace_gas.type) in gas.trace_gases
|
||||
if(!corresponding)
|
||||
corresponding = new trace_gas.type()
|
||||
gas.trace_gases += corresponding
|
||||
|
||||
corresponding.moles = trace_gas.moles*gas.volume/total_volume
|
||||
gas.update_values()
|
||||
|
||||
return 1
|
||||
equalize_gases(gases)
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
#define STEFAN_BOLTZMANN_CONSTANT 0.0000000567
|
||||
|
||||
datum/pipeline
|
||||
var/datum/gas_mixture/air
|
||||
@@ -37,22 +36,9 @@ datum/pipeline
|
||||
|
||||
for(var/obj/machinery/atmospherics/pipe/member in members)
|
||||
member.air_temporary = new
|
||||
member.air_temporary.copy_from(air)
|
||||
member.air_temporary.volume = member.volume
|
||||
|
||||
member.air_temporary.oxygen = air.oxygen*member.volume/air.volume
|
||||
member.air_temporary.nitrogen = air.nitrogen*member.volume/air.volume
|
||||
member.air_temporary.phoron = air.phoron*member.volume/air.volume
|
||||
member.air_temporary.carbon_dioxide = air.carbon_dioxide*member.volume/air.volume
|
||||
|
||||
member.air_temporary.temperature = air.temperature
|
||||
|
||||
if(air.trace_gases.len)
|
||||
for(var/datum/gas/trace_gas in air.trace_gases)
|
||||
var/datum/gas/corresponding = new trace_gas.type()
|
||||
member.air_temporary.trace_gases += corresponding
|
||||
|
||||
corresponding.moles = trace_gas.moles*member.volume/air.volume
|
||||
member.air_temporary.update_values()
|
||||
member.air_temporary.multiply(member.volume / air.volume)
|
||||
|
||||
proc/build_pipeline(obj/machinery/atmospherics/pipe/base)
|
||||
air = new
|
||||
@@ -213,10 +199,15 @@ datum/pipeline
|
||||
air.temperature -= heat/total_heat_capacity
|
||||
if(network)
|
||||
network.update = 1
|
||||
|
||||
proc/radiate_heat(surface, thermal_conductivity)
|
||||
var/total_heat_capacity = air.heat_capacity()
|
||||
var/heat = STEFAN_BOLTZMANN_CONSTANT * surface * air.temperature ** 4 * thermal_conductivity
|
||||
air.temperature = max(0, air.temperature - heat / total_heat_capacity)
|
||||
|
||||
//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)
|
||||
|
||||
air.add_thermal_energy(heat_gain)
|
||||
if(network)
|
||||
network.update = 1
|
||||
@@ -1,10 +1,11 @@
|
||||
|
||||
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
|
||||
var/surface = 2 //surface area in m^2
|
||||
|
||||
minimum_temperature_difference = 20
|
||||
thermal_conductivity = OPEN_HEAT_TRANSFER_COEFFICIENT
|
||||
@@ -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
|
||||
|
||||
@@ -53,13 +58,14 @@ obj/machinery/atmospherics/pipe/simple/heat_exchanging
|
||||
var/datum/gas_mixture/pipe_air = return_air()
|
||||
if(abs(environment_temperature-pipe_air.temperature) > minimum_temperature_difference)
|
||||
parent.temperature_interact(loc, volume, thermal_conductivity)
|
||||
else
|
||||
parent.radiate_heat(surface, 1)
|
||||
else if(istype(loc, /turf/space/))
|
||||
parent.radiate_heat_to_space(surface, 1)
|
||||
|
||||
|
||||
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
|
||||
|
||||
@@ -1,16 +0,0 @@
|
||||
client/verb/discon_pipes()
|
||||
set name = "Show Disconnected Pipes"
|
||||
set category = "Debug"
|
||||
|
||||
for(var/obj/machinery/atmospherics/pipe/simple/P in world)
|
||||
if(!P.node1 || !P.node2)
|
||||
usr << "[P], [P.x], [P.y], [P.z], [P.loc.loc]"
|
||||
|
||||
for(var/obj/machinery/atmospherics/pipe/manifold/P in world)
|
||||
if(!P.node1 || !P.node2 || !P.node3)
|
||||
usr << "[P], [P.x], [P.y], [P.z], [P.loc.loc]"
|
||||
|
||||
for(var/obj/machinery/atmospherics/pipe/manifold4w/P in world)
|
||||
if(!P.node1 || !P.node2 || !P.node3 || !P.node4)
|
||||
usr << "[P], [P.x], [P.y], [P.z], [P.loc.loc]"
|
||||
//With thanks to mini. Check before use, uncheck after. Do Not Use on a live server.
|
||||
+460
-459
File diff suppressed because it is too large
Load Diff
@@ -65,7 +65,6 @@ var/jungle_plants_init = 0
|
||||
reagent_effects = shuffle(reagent_effects)
|
||||
|
||||
/obj/item/weapon/reagent_containers/food/snacks/grown/jungle_fruit
|
||||
seed = ""
|
||||
name = "jungle fruit"
|
||||
desc = "It smells weird and looks off."
|
||||
icon = 'code/WorkInProgress/Cael_Aislinn/Jungle/jungle.dmi'
|
||||
|
||||
@@ -140,20 +140,19 @@ Deuterium-tritium fusion: 4.5 x 10^7 K
|
||||
//the amount of phoron pulled in each update is relative to the field strength, with 50T (max field strength) = 100% of area covered by the field
|
||||
//at minimum strength, 0.25% of the field volume is pulled in per update (?)
|
||||
//have a max of 1000 moles suspended
|
||||
if(held_phoron.phoron < transfer_ratio * 1000)
|
||||
if(held_phoron.gas["phoron"] < transfer_ratio * 1000)
|
||||
var/moles_covered = environment.return_pressure()*volume_covered/(environment.temperature * R_IDEAL_GAS_EQUATION)
|
||||
//world << "\blue moles_covered: [moles_covered]"
|
||||
//
|
||||
var/datum/gas_mixture/gas_covered = environment.remove(moles_covered)
|
||||
var/datum/gas_mixture/phoron_captured = new /datum/gas_mixture()
|
||||
//
|
||||
phoron_captured.phoron = round(gas_covered.phoron * transfer_ratio)
|
||||
phoron_captured.gas["phoron"] = round(gas_covered.gas["phoron"] * transfer_ratio)
|
||||
//world << "\blue[phoron_captured.phoron] moles of phoron captured"
|
||||
phoron_captured.temperature = gas_covered.temperature
|
||||
phoron_captured.update_values()
|
||||
//
|
||||
gas_covered.phoron -= phoron_captured.phoron
|
||||
gas_covered.update_values()
|
||||
gas_covered.adjust_gas("phoron", -phoron_captured.gas["phoron"])
|
||||
//
|
||||
held_phoron.merge(phoron_captured)
|
||||
//
|
||||
@@ -171,7 +170,7 @@ Deuterium-tritium fusion: 4.5 x 10^7 K
|
||||
|
||||
//change held phoron temp according to energy levels
|
||||
//SPECIFIC_HEAT_TOXIN
|
||||
if(mega_energy > 0 && held_phoron.phoron)
|
||||
if(mega_energy > 0 && held_phoron.gas["phoron"])
|
||||
var/heat_capacity = held_phoron.heat_capacity()//200 * number of phoron moles
|
||||
if(heat_capacity > 0.0003) //formerly MINIMUM_HEAT_CAPACITY
|
||||
held_phoron.temperature = (heat_capacity + mega_energy * 35000)/heat_capacity
|
||||
@@ -179,7 +178,7 @@ Deuterium-tritium fusion: 4.5 x 10^7 K
|
||||
//if there is too much phoron in the field, lose some
|
||||
/*if( held_phoron.phoron > (MOLES_CELLSTANDARD * 7) * (50 / field_strength) )
|
||||
LosePhoron()*/
|
||||
if(held_phoron.phoron > 1)
|
||||
if(held_phoron.gas["phoron"] > 1)
|
||||
//lose a random amount of phoron back into the air, increased by the field strength (want to switch this over to frequency eventually)
|
||||
var/loss_ratio = rand() * (0.05 + (0.05 * 50 / field_strength))
|
||||
//world << "lost [loss_ratio*100]% of held phoron"
|
||||
@@ -187,16 +186,16 @@ Deuterium-tritium fusion: 4.5 x 10^7 K
|
||||
var/datum/gas_mixture/phoron_lost = new
|
||||
phoron_lost.temperature = held_phoron.temperature
|
||||
//
|
||||
phoron_lost.phoron = held_phoron.phoron * loss_ratio
|
||||
phoron_lost.gas["phoron"] = held_phoron.gas["phoron"] * loss_ratio
|
||||
//phoron_lost.update_values()
|
||||
held_phoron.phoron -= held_phoron.phoron * loss_ratio
|
||||
held_phoron.gas["phoron"] -= held_phoron.gas["phoron"] * loss_ratio
|
||||
//held_phoron.update_values()
|
||||
//
|
||||
environment.merge(phoron_lost)
|
||||
radiation += loss_ratio * mega_energy * 0.1
|
||||
mega_energy -= loss_ratio * mega_energy * 0.1
|
||||
else
|
||||
held_phoron.phoron = 0
|
||||
held_phoron.gas["phoron"] = null
|
||||
//held_phoron.update_values()
|
||||
|
||||
//handle some reactants formatting
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
//---------- external shield generator
|
||||
//generates an energy field that loops around any built up area in space (is useless inside) halts movement and airflow, is blocked by walls, windows, airlocks etc
|
||||
|
||||
/obj/machinery/shield_gen/external
|
||||
name = "hull shield generator"
|
||||
|
||||
/obj/machinery/shield_gen/external/New()
|
||||
..()
|
||||
|
||||
/obj/machinery/shield_gen/external/get_shielded_turfs()
|
||||
var
|
||||
list
|
||||
open = list(get_turf(src))
|
||||
closed = list()
|
||||
|
||||
while(open.len)
|
||||
for(var/turf/T in open)
|
||||
for(var/turf/O in orange(1, T))
|
||||
if(get_dist(O,src) > field_radius)
|
||||
continue
|
||||
var/add_this_turf = 0
|
||||
if(istype(O,/turf/space))
|
||||
for(var/turf/simulated/G in orange(1, O))
|
||||
add_this_turf = 1
|
||||
break
|
||||
|
||||
//uncomment this for structures (but not lattices) to be surrounded by shield as well
|
||||
/*if(!add_this_turf)
|
||||
for(var/obj/structure/S in orange(1, O))
|
||||
if(!istype(S, /obj/structure/lattice))
|
||||
add_this_turf = 1
|
||||
break
|
||||
if(add_this_turf)
|
||||
for(var/obj/structure/S in O)
|
||||
if(!istype(S, /obj/structure/lattice))
|
||||
add_this_turf = 0
|
||||
break*/
|
||||
|
||||
if(add_this_turf && !(O in open) && !(O in closed))
|
||||
open += O
|
||||
open -= T
|
||||
closed += T
|
||||
|
||||
return closed
|
||||
@@ -30,7 +30,7 @@
|
||||
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/computer/engines/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null)
|
||||
/obj/machinery/computer/engines/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
if(!linked)
|
||||
return
|
||||
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
data["engines_info"] = enginfo
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data)
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "engines_control.tmpl", "[linked.name] Engines Control", 380, 530)
|
||||
ui.set_initial_data(data)
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
|
||||
ui_interact(user)
|
||||
|
||||
/obj/machinery/computer/helm/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null)
|
||||
/obj/machinery/computer/helm/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
if(!linked)
|
||||
return
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
|
||||
data["locations"] = locations
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data)
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "helm.tmpl", "[linked.name] Helm Control", 380, 530)
|
||||
ui.set_initial_data(data)
|
||||
|
||||
@@ -44,7 +44,7 @@
|
||||
var/datum/shuttle/ferry/shuttle = shuttle_controller.shuttles[shuttle_tag]
|
||||
return shuttle && destination && get_dist(home, destination) <= shuttle.range
|
||||
|
||||
/obj/machinery/computer/shuttle_control/explore/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null)
|
||||
/obj/machinery/computer/shuttle_control/explore/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
var/data[0]
|
||||
var/datum/shuttle/ferry/shuttle = shuttle_controller.shuttles[shuttle_tag]
|
||||
if (!istype(shuttle))
|
||||
@@ -103,7 +103,7 @@
|
||||
"can_force" = can_go && shuttle.can_force(),
|
||||
)
|
||||
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data)
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
|
||||
if (!ui)
|
||||
ui = new(user, src, ui_key, "shuttle_control_console_exploration.tmpl", "[shuttle_tag] Shuttle Control", 470, 310)
|
||||
|
||||
@@ -97,8 +97,8 @@
|
||||
//is_blocked_turf(var/turf/T)
|
||||
usr << "\blue You finish placing the [src]." //Git Test
|
||||
|
||||
/obj/item/taperoll/afterattack(var/atom/A, mob/user as mob)
|
||||
if (istype(A, /obj/machinery/door/airlock))
|
||||
/obj/item/taperoll/afterattack(var/atom/A, mob/user as mob, proximity)
|
||||
if (proximity && istype(A, /obj/machinery/door/airlock))
|
||||
var/turf/T = get_turf(A)
|
||||
var/obj/item/tape/P = new tape_type(T.x,T.y,T.z)
|
||||
P.loc = locate(T.x,T.y,T.z)
|
||||
|
||||
@@ -83,9 +83,9 @@ proc/assign_sec_to_department(var/mob/living/carbon/human/H)
|
||||
else
|
||||
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack)
|
||||
H.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(H), slot_in_backpack)
|
||||
var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H)
|
||||
L.imp_in = H
|
||||
L.implanted = 1
|
||||
|
||||
implant_loyalty(H)
|
||||
|
||||
return 1
|
||||
|
||||
/obj/item/device/radio/headset/headset_sec/department/New()
|
||||
|
||||
@@ -23,9 +23,9 @@
|
||||
H.equip_to_slot_or_del(new /obj/item/weapon/gun/energy/taser(H), slot_s_store)
|
||||
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack)
|
||||
H.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(H), slot_in_backpack)
|
||||
var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H)
|
||||
L.imp_in = H
|
||||
L.implanted = 1
|
||||
|
||||
H.implant_loyalty(src) // Will not do so if config is set to disallow.
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
@@ -52,9 +52,9 @@
|
||||
H.equip_to_slot_or_del(new /obj/item/device/flash(H), slot_l_store)
|
||||
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack)
|
||||
H.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(H), slot_in_backpack)
|
||||
var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H)
|
||||
L.imp_in = H
|
||||
L.implanted = 1
|
||||
|
||||
H.implant_loyalty(src) // // Will not do so if config is set to disallow.
|
||||
|
||||
return 1
|
||||
|
||||
|
||||
@@ -89,9 +89,7 @@
|
||||
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/evidence(H), slot_in_backpack)
|
||||
H.equip_to_slot_or_del(new /obj/item/device/detective_scanner(H), slot_in_backpack)
|
||||
|
||||
var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H)
|
||||
L.imp_in = H
|
||||
L.implanted = 1
|
||||
H.implant_loyalty(src) // Will not do so if config is set to disallow.
|
||||
return 1
|
||||
|
||||
|
||||
@@ -118,9 +116,9 @@
|
||||
H.equip_to_slot_or_del(new /obj/item/device/flash(H), slot_l_store)
|
||||
H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack)
|
||||
H.equip_to_slot_or_del(new /obj/item/weapon/handcuffs(H), slot_in_backpack)
|
||||
var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H)
|
||||
L.imp_in = H
|
||||
L.implanted = 1
|
||||
|
||||
H.implant_loyalty(src) // Will not do so if config is set to disallow.
|
||||
|
||||
return 1
|
||||
|
||||
/datum/job/hop
|
||||
|
||||
@@ -70,7 +70,7 @@
|
||||
new /obj/item/weapon/storage/backpack/satchel_sec(src)
|
||||
new /obj/item/weapon/cartridge/hos(src)
|
||||
new /obj/item/device/radio/headset/heads/hos(src)
|
||||
new /obj/item/weapon/storage/lockbox/loyalty(src)
|
||||
if (config.use_loyalty_implants) new /obj/item/weapon/storage/lockbox/loyalty(src)
|
||||
new /obj/item/weapon/storage/flashbang_kit(src)
|
||||
new /obj/item/weapon/storage/belt/security(src)
|
||||
new /obj/item/device/flash(src)
|
||||
|
||||
@@ -164,15 +164,15 @@
|
||||
return
|
||||
if(use_power && istype(battery) && battery.charge > 0)
|
||||
if(use_power == 1)
|
||||
battery.use(idle_power_usage)
|
||||
battery.use(idle_power_usage*CELLRATE) //idle and active_power_usage are in WATTS. battery.use() expects CHARGE.
|
||||
else
|
||||
battery.use(active_power_usage)
|
||||
battery.use(active_power_usage*CELLRATE)
|
||||
return 1
|
||||
return 0
|
||||
|
||||
use_power(var/amount, var/chan = -1)
|
||||
if(battery && battery.charge > 0)
|
||||
battery.use(amount)
|
||||
battery.use(amount*CELLRATE)
|
||||
|
||||
power_change()
|
||||
if( !battery || battery.charge <= 0 )
|
||||
|
||||
@@ -231,9 +231,7 @@ var/global/admin_emergency_team = 0 // Used for admin-spawned response teams
|
||||
// equip_to_slot_or_del(new /obj/item/weapon/storage/firstaid/regular(src), slot_in_backpack) // Regular medkit
|
||||
|
||||
// Loyalty implants
|
||||
var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(src)
|
||||
L.imp_in = src
|
||||
L.implanted = 1
|
||||
implant_loyalty(src)
|
||||
|
||||
// ID cards
|
||||
var/obj/item/weapon/card/id/E = new(src)
|
||||
|
||||
+4
-193
@@ -86,7 +86,8 @@ Class Procs:
|
||||
/connection_edge/proc/tick()
|
||||
|
||||
/connection_edge/proc/flow(list/movable, differential, repelled)
|
||||
for(var/atom/movable/M in movable)
|
||||
for(var/i = 1; i <= movable.len; i++)
|
||||
var/atom/movable/M = movable[i]
|
||||
|
||||
//If they're already being tossed, don't do it again.
|
||||
if(M.last_airflow > world.time - vsc.airflow_delay) continue
|
||||
@@ -156,7 +157,7 @@ Class Procs:
|
||||
return
|
||||
|
||||
//air_master.equalize(A, B)
|
||||
ShareRatio(A.air,B.air,coefficient)
|
||||
A.air.share_ratio(B.air, coefficient)
|
||||
air_master.mark_zone_update(A)
|
||||
air_master.mark_zone_update(B)
|
||||
//world << "equalized."
|
||||
@@ -215,7 +216,7 @@ Class Procs:
|
||||
return
|
||||
//world << "[id]: Tick [air_master.current_cycle]: To [B]!"
|
||||
//A.air.mimic(B, coefficient)
|
||||
ShareSpace(A.air,air,dbg_out)
|
||||
A.air.share_space(air, dbg_out)
|
||||
air_master.mark_zone_update(A)
|
||||
|
||||
var/differential = A.air.return_pressure() - air.return_pressure()
|
||||
@@ -224,196 +225,6 @@ Class Procs:
|
||||
var/list/attracted = A.movables()
|
||||
flow(attracted, abs(differential), differential < 0)
|
||||
|
||||
var/list/sharing_lookup_table = list(0.30, 0.40, 0.48, 0.54, 0.60, 0.66)
|
||||
|
||||
proc/ShareRatio(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles)
|
||||
//Shares a specific ratio of gas between mixtures using simple weighted averages.
|
||||
var
|
||||
//WOOT WOOT TOUCH THIS AND YOU ARE A RETARD
|
||||
ratio = sharing_lookup_table[6]
|
||||
//WOOT WOOT TOUCH THIS AND YOU ARE A RETARD
|
||||
|
||||
size = max(1,A.group_multiplier)
|
||||
share_size = max(1,B.group_multiplier)
|
||||
|
||||
full_oxy = A.oxygen * size
|
||||
full_nitro = A.nitrogen * size
|
||||
full_co2 = A.carbon_dioxide * size
|
||||
full_phoron = A.phoron * size
|
||||
|
||||
full_heat_capacity = A.heat_capacity() * size
|
||||
|
||||
s_full_oxy = B.oxygen * share_size
|
||||
s_full_nitro = B.nitrogen * share_size
|
||||
s_full_co2 = B.carbon_dioxide * share_size
|
||||
s_full_phoron = B.phoron * share_size
|
||||
|
||||
s_full_heat_capacity = B.heat_capacity() * share_size
|
||||
|
||||
oxy_avg = (full_oxy + s_full_oxy) / (size + share_size)
|
||||
nit_avg = (full_nitro + s_full_nitro) / (size + share_size)
|
||||
co2_avg = (full_co2 + s_full_co2) / (size + share_size)
|
||||
phoron_avg = (full_phoron + s_full_phoron) / (size + share_size)
|
||||
|
||||
temp_avg = (A.temperature * full_heat_capacity + B.temperature * s_full_heat_capacity) / (full_heat_capacity + s_full_heat_capacity)
|
||||
|
||||
//WOOT WOOT TOUCH THIS AND YOU ARE A RETARD
|
||||
if(sharing_lookup_table.len >= connecting_tiles) //6 or more interconnecting tiles will max at 42% of air moved per tick.
|
||||
ratio = sharing_lookup_table[connecting_tiles]
|
||||
//WOOT WOOT TOUCH THIS AND YOU ARE A RETARD
|
||||
|
||||
A.oxygen = max(0, (A.oxygen - oxy_avg) * (1-ratio) + oxy_avg )
|
||||
A.nitrogen = max(0, (A.nitrogen - nit_avg) * (1-ratio) + nit_avg )
|
||||
A.carbon_dioxide = max(0, (A.carbon_dioxide - co2_avg) * (1-ratio) + co2_avg )
|
||||
A.phoron = max(0, (A.phoron - phoron_avg) * (1-ratio) + phoron_avg )
|
||||
|
||||
A.temperature = max(0, (A.temperature - temp_avg) * (1-ratio) + temp_avg )
|
||||
|
||||
B.oxygen = max(0, (B.oxygen - oxy_avg) * (1-ratio) + oxy_avg )
|
||||
B.nitrogen = max(0, (B.nitrogen - nit_avg) * (1-ratio) + nit_avg )
|
||||
B.carbon_dioxide = max(0, (B.carbon_dioxide - co2_avg) * (1-ratio) + co2_avg )
|
||||
B.phoron = max(0, (B.phoron - phoron_avg) * (1-ratio) + phoron_avg )
|
||||
|
||||
B.temperature = max(0, (B.temperature - temp_avg) * (1-ratio) + temp_avg )
|
||||
|
||||
for(var/datum/gas/G in A.trace_gases)
|
||||
var/datum/gas/H = locate(G.type) in B.trace_gases
|
||||
if(H)
|
||||
var/G_avg = (G.moles*size + H.moles*share_size) / (size+share_size)
|
||||
G.moles = (G.moles - G_avg) * (1-ratio) + G_avg
|
||||
|
||||
H.moles = (H.moles - G_avg) * (1-ratio) + G_avg
|
||||
else
|
||||
H = new G.type
|
||||
B.trace_gases += H
|
||||
var/G_avg = (G.moles*size) / (size+share_size)
|
||||
G.moles = (G.moles - G_avg) * (1-ratio) + G_avg
|
||||
H.moles = (H.moles - G_avg) * (1-ratio) + G_avg
|
||||
|
||||
for(var/datum/gas/G in B.trace_gases)
|
||||
var/datum/gas/H = locate(G.type) in A.trace_gases
|
||||
if(!H)
|
||||
H = new G.type
|
||||
A.trace_gases += H
|
||||
var/G_avg = (G.moles*size) / (size+share_size)
|
||||
G.moles = (G.moles - G_avg) * (1-ratio) + G_avg
|
||||
H.moles = (H.moles - G_avg) * (1-ratio) + G_avg
|
||||
|
||||
A.update_values()
|
||||
B.update_values()
|
||||
|
||||
if(A.compare(B)) return 1
|
||||
else return 0
|
||||
|
||||
proc/ShareSpace(datum/gas_mixture/A, list/unsimulated_tiles, dbg_output)
|
||||
//A modified version of ShareRatio for spacing gas at the same rate as if it were going into a large airless room.
|
||||
if(!unsimulated_tiles)
|
||||
return 0
|
||||
|
||||
var
|
||||
unsim_oxygen = 0
|
||||
unsim_nitrogen = 0
|
||||
unsim_co2 = 0
|
||||
unsim_phoron = 0
|
||||
unsim_heat_capacity = 0
|
||||
unsim_temperature = 0
|
||||
|
||||
size = max(1,A.group_multiplier)
|
||||
|
||||
var/tileslen
|
||||
var/share_size
|
||||
|
||||
if(istype(unsimulated_tiles, /datum/gas_mixture))
|
||||
var/datum/gas_mixture/avg_unsim = unsimulated_tiles
|
||||
unsim_oxygen = avg_unsim.oxygen
|
||||
unsim_co2 = avg_unsim.carbon_dioxide
|
||||
unsim_nitrogen = avg_unsim.nitrogen
|
||||
unsim_phoron = avg_unsim.phoron
|
||||
unsim_temperature = avg_unsim.temperature
|
||||
share_size = max(1, max(size + 3, 1) + avg_unsim.group_multiplier)
|
||||
tileslen = avg_unsim.group_multiplier
|
||||
|
||||
if(dbg_output)
|
||||
world << "O2: [unsim_oxygen] N2: [unsim_nitrogen] Size: [share_size] Tiles: [tileslen]"
|
||||
|
||||
else if(istype(unsimulated_tiles, /list))
|
||||
if(!unsimulated_tiles.len)
|
||||
return 0
|
||||
// We use the same size for the potentially single space tile
|
||||
// as we use for the entire room. Why is this?
|
||||
// Short answer: We do not want larger rooms to depressurize more
|
||||
// slowly than small rooms, preserving our good old "hollywood-style"
|
||||
// oh-shit effect when large rooms get breached, but still having small
|
||||
// rooms remain pressurized for long enough to make escape possible.
|
||||
share_size = max(1, max(size + 3, 1) + unsimulated_tiles.len)
|
||||
var/correction_ratio = share_size / unsimulated_tiles.len
|
||||
|
||||
for(var/turf/T in unsimulated_tiles)
|
||||
unsim_oxygen += T.oxygen
|
||||
unsim_co2 += T.carbon_dioxide
|
||||
unsim_nitrogen += T.nitrogen
|
||||
unsim_phoron += T.phoron
|
||||
unsim_temperature += T.temperature/unsimulated_tiles.len
|
||||
|
||||
//These values require adjustment in order to properly represent a room of the specified size.
|
||||
unsim_oxygen *= correction_ratio
|
||||
unsim_co2 *= correction_ratio
|
||||
unsim_nitrogen *= correction_ratio
|
||||
unsim_phoron *= correction_ratio
|
||||
tileslen = unsimulated_tiles.len
|
||||
|
||||
else //invalid input type
|
||||
return 0
|
||||
|
||||
unsim_heat_capacity = HEAT_CAPACITY_CALCULATION(unsim_oxygen, unsim_co2, unsim_nitrogen, unsim_phoron)
|
||||
|
||||
var
|
||||
ratio = sharing_lookup_table[6]
|
||||
|
||||
old_pressure = A.return_pressure()
|
||||
|
||||
full_oxy = A.oxygen * size
|
||||
full_nitro = A.nitrogen * size
|
||||
full_co2 = A.carbon_dioxide * size
|
||||
full_phoron = A.phoron * size
|
||||
|
||||
full_heat_capacity = A.heat_capacity() * size
|
||||
|
||||
oxy_avg = (full_oxy + unsim_oxygen*share_size) / (size + share_size)
|
||||
nit_avg = (full_nitro + unsim_nitrogen*share_size) / (size + share_size)
|
||||
co2_avg = (full_co2 + unsim_co2*share_size) / (size + share_size)
|
||||
phoron_avg = (full_phoron + unsim_phoron*share_size) / (size + share_size)
|
||||
|
||||
temp_avg = 0
|
||||
|
||||
if((full_heat_capacity + unsim_heat_capacity) > 0)
|
||||
temp_avg = (A.temperature * full_heat_capacity + unsim_temperature * unsim_heat_capacity) / (full_heat_capacity + unsim_heat_capacity)
|
||||
|
||||
if(sharing_lookup_table.len >= tileslen) //6 or more interconnecting tiles will max at 42% of air moved per tick.
|
||||
ratio = sharing_lookup_table[tileslen]
|
||||
|
||||
if(dbg_output)
|
||||
world << "Ratio: [ratio]"
|
||||
world << "Avg O2: [oxy_avg] N2: [nit_avg]"
|
||||
|
||||
A.oxygen = max(0, (A.oxygen - oxy_avg) * (1 - ratio) + oxy_avg )
|
||||
A.nitrogen = max(0, (A.nitrogen - nit_avg) * (1 - ratio) + nit_avg )
|
||||
A.carbon_dioxide = max(0, (A.carbon_dioxide - co2_avg) * (1 - ratio) + co2_avg )
|
||||
A.phoron = max(0, (A.phoron - phoron_avg) * (1 - ratio) + phoron_avg )
|
||||
|
||||
A.temperature = max(TCMB, (A.temperature - temp_avg) * (1 - ratio) + temp_avg )
|
||||
|
||||
for(var/datum/gas/G in A.trace_gases)
|
||||
var/G_avg = (G.moles * size) / (size + share_size)
|
||||
G.moles = (G.moles - G_avg) * (1 - ratio) + G_avg
|
||||
|
||||
A.update_values()
|
||||
|
||||
if(dbg_output) world << "Result: [abs(old_pressure - A.return_pressure())] kPa"
|
||||
|
||||
return abs(old_pressure - A.return_pressure())
|
||||
|
||||
|
||||
proc/ShareHeat(datum/gas_mixture/A, datum/gas_mixture/B, connecting_tiles)
|
||||
//This implements a simplistic version of the Stefan-Boltzmann law.
|
||||
var/energy_delta = ((A.temperature - B.temperature) ** 4) * 5.6704e-8 * connecting_tiles * 2.5
|
||||
|
||||
+10
-2
@@ -73,6 +73,7 @@ Class Procs:
|
||||
//Geometry updates lists
|
||||
/datum/controller/air_system/var/list/tiles_to_update = list()
|
||||
/datum/controller/air_system/var/list/zones_to_update = list()
|
||||
/datum/controller/air_system/var/list/active_fire_zones = list()
|
||||
/datum/controller/air_system/var/list/active_hotspots = list()
|
||||
|
||||
/datum/controller/air_system/var/active_zones = 0
|
||||
@@ -171,9 +172,16 @@ Total Unsimulated Turfs: [world.maxx*world.maxy*world.maxz - simulated_turf_coun
|
||||
for(var/connection_edge/edge in edges)
|
||||
edge.tick()
|
||||
|
||||
//Process fires.
|
||||
//Process fire zones.
|
||||
if(.)
|
||||
tick_progress = "processing fire"
|
||||
tick_progress = "processing fire zones"
|
||||
|
||||
for(var/zone/Z in active_fire_zones)
|
||||
Z.process_fire()
|
||||
|
||||
//Process hotspots.
|
||||
if(.)
|
||||
tick_progress = "processing hotspots"
|
||||
|
||||
for(var/obj/fire/fire in active_hotspots)
|
||||
fire.process()
|
||||
|
||||
@@ -19,7 +19,8 @@ client/proc/Zone_Info(turf/T as null|turf)
|
||||
mob << "No zone here."
|
||||
var/datum/gas_mixture/mix = T.return_air()
|
||||
mob << "[mix.return_pressure()] kPa [mix.temperature]C"
|
||||
mob << "O2: [mix.oxygen] N2: [mix.nitrogen] CO2: [mix.carbon_dioxide] TX: [mix.phoron]"
|
||||
for(var/g in mix.gas)
|
||||
mob << "[g]: [mix.gas[g]]\n"
|
||||
else
|
||||
if(zone_debug_images)
|
||||
for(var/zone in zone_debug_images)
|
||||
|
||||
+131
-131
@@ -10,6 +10,7 @@ Attach to transfer valve and open. BOOM.
|
||||
|
||||
*/
|
||||
|
||||
/turf/var/obj/fire/fire = null
|
||||
|
||||
//Some legacy definitions so fires can be started.
|
||||
atom/proc/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
@@ -34,12 +35,54 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh)
|
||||
if(air_contents.check_combustability(liquid))
|
||||
igniting = 1
|
||||
|
||||
if(! (locate(/obj/fire) in src))
|
||||
|
||||
new /obj/fire(src,1000)
|
||||
|
||||
create_fire(1000)
|
||||
return igniting
|
||||
|
||||
/zone/proc/process_fire()
|
||||
if(!air.check_combustability())
|
||||
for(var/turf/simulated/T in fire_tiles)
|
||||
if(istype(T.fire))
|
||||
T.fire.RemoveFire()
|
||||
T.fire = null
|
||||
fire_tiles.Cut()
|
||||
|
||||
if(!fire_tiles.len)
|
||||
air_master.active_fire_zones.Remove(src)
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/burn_gas = air.remove_ratio(vsc.fire_consuption_rate, fire_tiles.len)
|
||||
var/gm = burn_gas.group_multiplier
|
||||
|
||||
burn_gas.group_multiplier = 1
|
||||
burn_gas.zburn(force_burn = 1, no_check = 1)
|
||||
burn_gas.group_multiplier = gm
|
||||
|
||||
air.merge(burn_gas)
|
||||
|
||||
var/firelevel = air.calculate_firelevel()
|
||||
|
||||
for(var/turf/T in fire_tiles)
|
||||
if(T.fire)
|
||||
T.fire.firelevel = firelevel
|
||||
else
|
||||
fire_tiles -= T
|
||||
|
||||
/turf/proc/create_fire(fl)
|
||||
return 0
|
||||
|
||||
/turf/simulated/create_fire(fl)
|
||||
if(fire)
|
||||
fire.firelevel = max(fl, fire.firelevel)
|
||||
return 1
|
||||
|
||||
if(!zone)
|
||||
return 1
|
||||
|
||||
fire = new(src, fl)
|
||||
zone.fire_tiles |= src
|
||||
air_master.active_fire_zones |= zone
|
||||
return 0
|
||||
|
||||
/obj/fire
|
||||
//Icon for fire on turfs.
|
||||
|
||||
@@ -58,41 +101,14 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh)
|
||||
/obj/fire/process()
|
||||
. = 1
|
||||
|
||||
//get location and check if it is in a proper ZAS zone
|
||||
var/turf/simulated/S = loc
|
||||
|
||||
if(!istype(S))
|
||||
del src
|
||||
return
|
||||
|
||||
if(!S.zone)
|
||||
del src
|
||||
return
|
||||
|
||||
var/datum/gas_mixture/air_contents = S.return_air()
|
||||
//get liquid fuels on the ground.
|
||||
var/obj/effect/decal/cleanable/liquid_fuel/liquid = locate() in S
|
||||
//and the volatile stuff from the air
|
||||
var/datum/gas/volatile_fuel/fuel = locate() in air_contents.trace_gases
|
||||
|
||||
//since the air is processed in fractions, we need to make sure not to have any minuscle residue or
|
||||
//the amount of moles might get to low for some functions to catch them and thus result in wonky behaviour
|
||||
if(air_contents.oxygen < 0.1)
|
||||
air_contents.oxygen = 0
|
||||
if(air_contents.phoron < 0.1)
|
||||
air_contents.phoron = 0
|
||||
if(fuel)
|
||||
if(fuel.moles < 0.1)
|
||||
air_contents.trace_gases.Remove(fuel)
|
||||
|
||||
//check if there is something to combust
|
||||
if(!air_contents.check_combustability(liquid))
|
||||
//del src
|
||||
var/turf/simulated/my_tile = loc
|
||||
if(!istype(my_tile) || !my_tile.zone)
|
||||
if(my_tile.fire == src)
|
||||
my_tile.fire = null
|
||||
RemoveFire()
|
||||
return
|
||||
return 1
|
||||
|
||||
//get a firelevel and set the icon
|
||||
firelevel = air_contents.calculate_firelevel(liquid)
|
||||
var/datum/gas_mixture/air_contents = my_tile.return_air()
|
||||
|
||||
if(firelevel > 6)
|
||||
icon_state = "3"
|
||||
@@ -106,21 +122,26 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh)
|
||||
|
||||
//im not sure how to implement a version that works for every creature so for now monkeys are firesafe
|
||||
for(var/mob/living/carbon/human/M in loc)
|
||||
M.FireBurn(firelevel, air_contents.temperature, air_contents.return_pressure() ) //Burn the humans!
|
||||
M.FireBurn(firelevel, air_contents.temperature, air_contents.return_pressure()) //Burn the humans!
|
||||
|
||||
loc.fire_act(air_contents, air_contents.temperature, air_contents.return_volume())
|
||||
loc.fire_act(air_contents, air_contents.temperature, air_contents.volume)
|
||||
for(var/atom/A in loc)
|
||||
A.fire_act(air_contents, air_contents.temperature, air_contents.return_volume())
|
||||
A.fire_act(air_contents, air_contents.temperature, air_contents.volume)
|
||||
|
||||
//spread
|
||||
for(var/direction in cardinal)
|
||||
var/turf/simulated/enemy_tile = get_step(S, direction)
|
||||
var/turf/simulated/enemy_tile = get_step(my_tile, direction)
|
||||
|
||||
if(istype(enemy_tile))
|
||||
if(S.open_directions & direction) //Grab all valid bordering tiles
|
||||
var/datum/gas_mixture/acs = enemy_tile.return_air()
|
||||
var/obj/effect/decal/cleanable/liquid_fuel/liq = locate() in enemy_tile
|
||||
if(!acs) continue
|
||||
if(!acs.check_combustability(liq)) continue
|
||||
if(my_tile.open_directions & direction) //Grab all valid bordering tiles
|
||||
if(!enemy_tile.zone || enemy_tile.fire)
|
||||
continue
|
||||
|
||||
if(!enemy_tile.zone.fire_tiles.len)
|
||||
var/datum/gas_mixture/acs = enemy_tile.return_air()
|
||||
if(!acs || !acs.check_combustability())
|
||||
continue
|
||||
|
||||
//If extinguisher mist passed over the turf it's trying to spread to, don't spread and
|
||||
//reduce firelevel.
|
||||
if(enemy_tile.fire_protection > world.time-30)
|
||||
@@ -128,26 +149,11 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh)
|
||||
continue
|
||||
|
||||
//Spread the fire.
|
||||
if(!(locate(/obj/fire) in enemy_tile))
|
||||
if( prob( 50 + 50 * (firelevel/vsc.fire_firelevel_multiplier) ) && S.CanPass(null, enemy_tile, 0,0) && enemy_tile.CanPass(null, S, 0,0))
|
||||
new/obj/fire(enemy_tile,firelevel)
|
||||
if(prob( 50 + 50 * (firelevel/vsc.fire_firelevel_multiplier) ) && my_tile.CanPass(null, enemy_tile, 0,0) && enemy_tile.CanPass(null, my_tile, 0,0))
|
||||
enemy_tile.create_fire(firelevel)
|
||||
|
||||
else
|
||||
enemy_tile.adjacent_fire_act(loc, air_contents, air_contents.temperature, air_contents.return_volume())
|
||||
|
||||
//seperate part of the present gas
|
||||
//this is done to prevent the fire burning all gases in a single pass
|
||||
var/datum/gas_mixture/flow = air_contents.remove_ratio(vsc.fire_consuption_rate)
|
||||
///////////////////////////////// FLOW HAS BEEN CREATED /// DONT DELETE THE FIRE UNTIL IT IS MERGED BACK OR YOU WILL DELETE AIR ///////////////////////////////////////////////
|
||||
|
||||
if(flow)
|
||||
//burn baby burn!
|
||||
flow.zburn(liquid,1)
|
||||
//merge the air back
|
||||
S.assume_air(flow)
|
||||
|
||||
///////////////////////////////// FLOW HAS BEEN REMERGED /// feel free to delete the fire again from here on //////////////////////////////////////////////////////////////////
|
||||
|
||||
enemy_tile.adjacent_fire_act(loc, air_contents, air_contents.temperature, air_contents.volume)
|
||||
|
||||
/obj/fire/New(newLoc,fl)
|
||||
..()
|
||||
@@ -171,31 +177,29 @@ turf/simulated/hotspot_expose(exposed_temperature, exposed_volume, soh)
|
||||
..()
|
||||
|
||||
/obj/fire/proc/RemoveFire()
|
||||
if (istype(loc, /turf/simulated))
|
||||
if (istype(loc, /turf))
|
||||
SetLuminosity(0)
|
||||
loc = null
|
||||
air_master.active_hotspots.Remove(src)
|
||||
|
||||
|
||||
|
||||
turf/simulated/var/fire_protection = 0 //Protects newly extinguished tiles from being overrun again.
|
||||
turf/proc/apply_fire_protection()
|
||||
turf/simulated/apply_fire_protection()
|
||||
fire_protection = world.time
|
||||
|
||||
|
||||
datum/gas_mixture/proc/zburn(obj/effect/decal/cleanable/liquid_fuel/liquid, force_burn)
|
||||
var/value = 0
|
||||
|
||||
if((temperature > PHORON_MINIMUM_BURN_TEMPERATURE || force_burn) && check_recombustability(liquid))
|
||||
datum/gas_mixture/proc/zburn(obj/effect/decal/cleanable/liquid_fuel/liquid, force_burn, no_check = 0)
|
||||
. = 0
|
||||
if((temperature > PHORON_MINIMUM_BURN_TEMPERATURE || force_burn) && (no_check ||check_recombustability(liquid)))
|
||||
var/total_fuel = 0
|
||||
var/datum/gas/volatile_fuel/fuel = locate() in trace_gases
|
||||
var/total_oxidizers = 0
|
||||
|
||||
total_fuel += phoron
|
||||
|
||||
if(fuel)
|
||||
//Volatile Fuel
|
||||
total_fuel += fuel.moles
|
||||
for(var/g in gas)
|
||||
if(gas_data.flags[g] & XGM_GAS_FUEL)
|
||||
total_fuel += gas[g]
|
||||
if(gas_data.flags[g] & XGM_GAS_OXIDIZER)
|
||||
total_oxidizers += gas[g]
|
||||
|
||||
if(liquid)
|
||||
//Liquid Fuel
|
||||
@@ -208,36 +212,29 @@ datum/gas_mixture/proc/zburn(obj/effect/decal/cleanable/liquid_fuel/liquid, forc
|
||||
return 0
|
||||
|
||||
//Calculate the firelevel.
|
||||
var/firelevel = calculate_firelevel(liquid)
|
||||
var/firelevel = calculate_firelevel(liquid, total_fuel, total_oxidizers, force = 1)
|
||||
|
||||
//get the current inner energy of the gas mix
|
||||
//this must be taken here to prevent the addition or deletion of energy by a changing heat capacity
|
||||
var/starting_energy = temperature * heat_capacity()
|
||||
|
||||
//determine the amount of oxygen used
|
||||
var/total_oxygen = min(oxygen, 2 * total_fuel)
|
||||
var/used_oxidizers = min(total_oxidizers, total_fuel / 2)
|
||||
|
||||
//determine the amount of fuel actually used
|
||||
var/used_fuel_ratio = min(oxygen / 2 , total_fuel) / total_fuel
|
||||
var/used_fuel_ratio = min(2 * total_oxidizers , total_fuel) / total_fuel
|
||||
total_fuel = total_fuel * used_fuel_ratio
|
||||
|
||||
var/total_reactants = total_fuel + total_oxygen
|
||||
var/total_reactants = total_fuel + used_oxidizers
|
||||
|
||||
//determine the amount of reactants actually reacting
|
||||
var/used_reactants_ratio = min( max(total_reactants * firelevel / vsc.fire_firelevel_multiplier, 0.2), total_reactants) / total_reactants
|
||||
var/used_reactants_ratio = min(max(total_reactants * firelevel / vsc.fire_firelevel_multiplier, 0.2), total_reactants) / total_reactants
|
||||
|
||||
//remove and add gasses as calculated
|
||||
oxygen -= min(oxygen, total_oxygen * used_reactants_ratio )
|
||||
remove_by_flag(XGM_GAS_OXIDIZER, used_oxidizers * used_reactants_ratio)
|
||||
remove_by_flag(XGM_GAS_FUEL, total_fuel * used_reactants_ratio)
|
||||
|
||||
phoron -= min(phoron, (phoron * used_fuel_ratio * used_reactants_ratio ) * 3)
|
||||
if(phoron < 0)
|
||||
phoron = 0
|
||||
|
||||
carbon_dioxide += max(2 * total_fuel, 0)
|
||||
|
||||
if(fuel)
|
||||
fuel.moles -= (fuel.moles * used_fuel_ratio * used_reactants_ratio) * 5 //Fuel burns 5 times as quick
|
||||
if(fuel.moles <= 0) del fuel
|
||||
adjust_gas("carbon_dioxide", max(total_fuel*used_reactants_ratio, 0))
|
||||
|
||||
if(liquid)
|
||||
liquid.amount -= (liquid.amount * used_fuel_ratio * used_reactants_ratio) * 5 // liquid fuel burns 5 times as quick
|
||||
@@ -248,64 +245,67 @@ datum/gas_mixture/proc/zburn(obj/effect/decal/cleanable/liquid_fuel/liquid, forc
|
||||
temperature = (starting_energy + vsc.fire_fuel_energy_release * total_fuel) / heat_capacity()
|
||||
|
||||
update_values()
|
||||
value = total_reactants * used_reactants_ratio
|
||||
return value
|
||||
. = total_reactants * used_reactants_ratio
|
||||
|
||||
datum/gas_mixture/proc/check_recombustability(obj/effect/decal/cleanable/liquid_fuel/liquid)
|
||||
//this is a copy proc to continue a fire after its been started.
|
||||
. = 0
|
||||
for(var/g in gas)
|
||||
if(gas_data.flags[g] & XGM_GAS_OXIDIZER && gas[g] >= 0.1)
|
||||
. = 1
|
||||
break
|
||||
|
||||
var/datum/gas/volatile_fuel/fuel = locate() in trace_gases
|
||||
if(!.)
|
||||
return 0
|
||||
|
||||
if(oxygen && (phoron || fuel || liquid))
|
||||
if(liquid)
|
||||
return 1
|
||||
if(phoron >= 0.1)
|
||||
return 1
|
||||
if(fuel && fuel.moles >= 0.1)
|
||||
return 1
|
||||
if(liquid)
|
||||
return 1
|
||||
|
||||
return 0
|
||||
. = 0
|
||||
for(var/g in gas)
|
||||
if(gas_data.flags[g] & XGM_GAS_FUEL && gas[g] >= 0.1)
|
||||
. = 1
|
||||
break
|
||||
|
||||
datum/gas_mixture/proc/check_combustability(obj/effect/decal/cleanable/liquid_fuel/liquid)
|
||||
//this check comes up very often and is thus centralized here to ease adding stuff
|
||||
. = 0
|
||||
for(var/g in gas)
|
||||
if(gas_data.flags[g] & XGM_GAS_OXIDIZER && QUANTIZE(gas[g] * vsc.fire_consuption_rate) >= 0.1)
|
||||
. = 1
|
||||
break
|
||||
|
||||
var/datum/gas/volatile_fuel/fuel = locate() in trace_gases
|
||||
if(!.)
|
||||
return 0
|
||||
|
||||
if(oxygen && (phoron || fuel || liquid))
|
||||
if(liquid)
|
||||
return 1
|
||||
if(QUANTIZE(phoron * vsc.fire_consuption_rate) >= 0.1)
|
||||
return 1
|
||||
if(fuel && QUANTIZE(fuel.moles * vsc.fire_consuption_rate) >= 0.1)
|
||||
return 1
|
||||
if(liquid)
|
||||
return 1
|
||||
|
||||
return 0
|
||||
. = 0
|
||||
for(var/g in gas)
|
||||
if(gas_data.flags[g] & XGM_GAS_FUEL && QUANTIZE(gas[g] * vsc.fire_consuption_rate) >= 0.1)
|
||||
. = 1
|
||||
break
|
||||
|
||||
datum/gas_mixture/proc/calculate_firelevel(obj/effect/decal/cleanable/liquid_fuel/liquid)
|
||||
datum/gas_mixture/proc/calculate_firelevel(obj/effect/decal/cleanable/liquid_fuel/liquid, total_fuel = null, total_oxidizers = null, force = 0)
|
||||
//Calculates the firelevel based on one equation instead of having to do this multiple times in different areas.
|
||||
|
||||
var/datum/gas/volatile_fuel/fuel = locate() in trace_gases
|
||||
var/total_fuel = 0
|
||||
var/firelevel = 0
|
||||
|
||||
if(check_recombustability(liquid))
|
||||
if(force || check_recombustability(liquid))
|
||||
if(isnull(total_fuel))
|
||||
for(var/g in gas)
|
||||
if(gas_data.flags[g] & XGM_GAS_FUEL)
|
||||
total_fuel += gas[g]
|
||||
if(gas_data.flags[g] & XGM_GAS_OXIDIZER)
|
||||
total_oxidizers += gas[g]
|
||||
if(liquid)
|
||||
total_fuel += liquid.amount
|
||||
|
||||
total_fuel += phoron
|
||||
|
||||
if(liquid)
|
||||
total_fuel += liquid.amount
|
||||
|
||||
if(fuel)
|
||||
total_fuel += fuel.moles
|
||||
|
||||
var/total_combustables = (total_fuel + oxygen)
|
||||
|
||||
if(total_fuel > 0 && oxygen > 0)
|
||||
var/total_combustables = (total_fuel + total_oxidizers)
|
||||
|
||||
if(total_combustables > 0)
|
||||
//slows down the burning when the concentration of the reactants is low
|
||||
var/dampening_multiplier = total_combustables / (total_combustables + nitrogen + carbon_dioxide)
|
||||
var/dampening_multiplier = total_combustables / total_moles
|
||||
//calculates how close the mixture of the reactants is to the optimum
|
||||
var/mix_multiplier = 1 / (1 + (5 * ((oxygen / total_combustables) ** 2)))
|
||||
var/mix_multiplier = 1 / (1 + (5 * ((total_oxidizers / total_combustables) ** 2)))
|
||||
//toss everything together
|
||||
firelevel = vsc.fire_firelevel_multiplier * mix_multiplier * dampening_multiplier
|
||||
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
/xgm_gas/oxygen
|
||||
id = "oxygen"
|
||||
name = "Oxygen"
|
||||
specific_heat = 20 // J/(mol*K)
|
||||
molar_mass = 0.032 // kg/mol
|
||||
|
||||
flags = XGM_GAS_OXIDIZER
|
||||
|
||||
/xgm_gas/nitrogen
|
||||
id = "nitrogen"
|
||||
name = "Nitrogen"
|
||||
specific_heat = 20 // J/(mol*K)
|
||||
molar_mass = 0.028 // kg/mol
|
||||
|
||||
/xgm_gas/carbon_dioxide
|
||||
id = "carbon_dioxide"
|
||||
name = "Carbon Dioxide"
|
||||
specific_heat = 30 // J/(mol*K)
|
||||
molar_mass = 0.044 // kg/mol
|
||||
|
||||
/xgm_gas/phoron
|
||||
id = "phoron"
|
||||
name = "Phoron"
|
||||
specific_heat = 200 // J/(mol*K)
|
||||
|
||||
//Hypothetical group 14 (same as carbon), period 8 element.
|
||||
//Using multiplicity rule, it's atomic number is 162
|
||||
//and following a N/Z ratio of 1.5, the molar mass of a monatomic gas is:
|
||||
molar_mass = 0.405 // kg/mol
|
||||
|
||||
tile_overlay = "phoron"
|
||||
overlay_limit = 0.7
|
||||
flags = XGM_GAS_FUEL | XGM_GAS_CONTAMINANT
|
||||
|
||||
/xgm_gas/volatile_fuel
|
||||
id = "volatile_fuel"
|
||||
name = "Volatile Fuel"
|
||||
specific_heat = 253 // J/(mol*K) C8H18 gasoline. Isobaric, but good enough.
|
||||
molar_mass = 0.114 // kg/mol. same.
|
||||
|
||||
flags = XGM_GAS_FUEL
|
||||
|
||||
/xgm_gas/sleeping_agent
|
||||
id = "sleeping_agent"
|
||||
name = "Sleeping Agent"
|
||||
specific_heat = 40 // J/(mol*K)
|
||||
molar_mass = 0.044 // kg/mol. N2O
|
||||
|
||||
tile_overlay = "sleeping_agent"
|
||||
overlay_limit = 1
|
||||
|
||||
/xgm_gas/oxygen_agent_b
|
||||
id = "oxygen_agent_b"
|
||||
name = "Oxygen Agent-B" //what is this?
|
||||
specific_heat = 300 // J/(mol*K)
|
||||
molar_mass = 0.032 // kg/mol
|
||||
+6
-5
@@ -111,7 +111,7 @@ obj/var/contaminated = 0
|
||||
if(vsc.plc.GENETIC_CORRUPTION)
|
||||
if(rand(1,10000) < vsc.plc.GENETIC_CORRUPTION)
|
||||
randmutb(src)
|
||||
src << "\red High levels of phoron cause you to spontaneously mutate."
|
||||
src << "\red High levels of toxins cause you to spontaneously mutate."
|
||||
domutcheck(src,null)
|
||||
|
||||
|
||||
@@ -155,10 +155,11 @@ obj/var/contaminated = 0
|
||||
turf/Entered(obj/item/I)
|
||||
. = ..()
|
||||
//Items that are in phoron, but not on a mob, can still be contaminated.
|
||||
if(istype(I) && vsc.plc.CLOTH_CONTAMINATION)
|
||||
if(istype(I) && vsc.plc.CLOTH_CONTAMINATION && I.can_contaminate())
|
||||
var/datum/gas_mixture/env = return_air(1)
|
||||
if(!env)
|
||||
return
|
||||
if(env.phoron > MOLES_PHORON_VISIBLE + 1)
|
||||
if(I.can_contaminate())
|
||||
I.contaminate()
|
||||
for(var/g in env.gas)
|
||||
if(gas_data.flags[g] & XGM_GAS_CONTAMINANT && env.gas[g] > gas_data.overlay_limit[g] + 1)
|
||||
I.contaminate()
|
||||
break
|
||||
|
||||
+25
-20
@@ -1,17 +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)
|
||||
if(isnum(new_graphic))
|
||||
if(new_graphic == 1) new_graphic = plmaster
|
||||
else if(new_graphic == 2) new_graphic = slmaster
|
||||
if(gas_graphic) overlays -= gas_graphic
|
||||
if(new_graphic) overlays += new_graphic
|
||||
gas_graphic = new_graphic
|
||||
/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)
|
||||
@@ -185,17 +182,15 @@
|
||||
/turf/assume_air(datum/gas_mixture/giver) //use this for machines to adjust air
|
||||
return 0
|
||||
|
||||
/turf/proc/assume_gas(gasid, moles, temp = 0)
|
||||
return 0
|
||||
|
||||
/turf/return_air()
|
||||
//Create gas mixture to hold data for passing
|
||||
var/datum/gas_mixture/GM = new
|
||||
|
||||
GM.oxygen = oxygen
|
||||
GM.carbon_dioxide = carbon_dioxide
|
||||
GM.nitrogen = nitrogen
|
||||
GM.phoron = phoron
|
||||
|
||||
GM.adjust_multi("oxygen", oxygen, "carbon_dioxide", carbon_dioxide, "nitrogen", nitrogen, "phoron", phoron)
|
||||
GM.temperature = temperature
|
||||
GM.update_values()
|
||||
|
||||
return GM
|
||||
|
||||
@@ -204,10 +199,10 @@
|
||||
|
||||
var/sum = oxygen + carbon_dioxide + nitrogen + phoron
|
||||
if(sum>0)
|
||||
GM.oxygen = (oxygen/sum)*amount
|
||||
GM.carbon_dioxide = (carbon_dioxide/sum)*amount
|
||||
GM.nitrogen = (nitrogen/sum)*amount
|
||||
GM.phoron = (phoron/sum)*amount
|
||||
GM.gas["oxygen"] = (oxygen/sum)*amount
|
||||
GM.gas["carbon_dioxide"] = (carbon_dioxide/sum)*amount
|
||||
GM.gas["nitrogen"] = (nitrogen/sum)*amount
|
||||
GM.gas["phoron"] = (phoron/sum)*amount
|
||||
|
||||
GM.temperature = temperature
|
||||
GM.update_values()
|
||||
@@ -218,6 +213,16 @@
|
||||
var/datum/gas_mixture/my_air = return_air()
|
||||
my_air.merge(giver)
|
||||
|
||||
/turf/simulated/assume_gas(gasid, moles, temp = null)
|
||||
var/datum/gas_mixture/my_air = return_air()
|
||||
|
||||
if(isnull(temp))
|
||||
my_air.adjust_gas(gasid, moles)
|
||||
else
|
||||
my_air.adjust_gas_temp(gasid, moles, temp)
|
||||
|
||||
return 1
|
||||
|
||||
/turf/simulated/remove_air(amount as num)
|
||||
var/datum/gas_mixture/my_air = return_air()
|
||||
return my_air.remove(amount)
|
||||
@@ -240,11 +245,11 @@
|
||||
/turf/proc/make_air()
|
||||
air = new/datum/gas_mixture
|
||||
air.temperature = temperature
|
||||
air.adjust(oxygen, carbon_dioxide, nitrogen, phoron)
|
||||
air.adjust_multi("oxygen", oxygen, "carbon_dioxide", carbon_dioxide, "nitrogen", nitrogen, "phoron", phoron)
|
||||
air.group_multiplier = 1
|
||||
air.volume = CELL_VOLUME
|
||||
|
||||
/turf/simulated/proc/c_copy_air()
|
||||
if(!air) air = new/datum/gas_mixture
|
||||
air.copy_from(zone.air)
|
||||
air.group_multiplier = 1
|
||||
air.group_multiplier = 1
|
||||
|
||||
+17
-7
@@ -43,6 +43,7 @@ Class Procs:
|
||||
/zone/var/name
|
||||
/zone/var/invalid = 0
|
||||
/zone/var/list/contents = list()
|
||||
/zone/var/list/fire_tiles = list()
|
||||
|
||||
/zone/var/needs_update = 0
|
||||
|
||||
@@ -50,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
|
||||
@@ -67,7 +71,10 @@ Class Procs:
|
||||
add_tile_air(turf_air)
|
||||
T.zone = src
|
||||
contents.Add(T)
|
||||
T.set_graphic(air.graphic)
|
||||
if(T.fire)
|
||||
fire_tiles.Add(T)
|
||||
air_master.active_fire_zones.Add(src)
|
||||
T.update_graphic(air.graphic)
|
||||
|
||||
/zone/proc/remove(turf/simulated/T)
|
||||
#ifdef ZASDBG
|
||||
@@ -77,8 +84,9 @@ Class Procs:
|
||||
soft_assert(T in contents, "Lists are weird broseph")
|
||||
#endif
|
||||
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
|
||||
@@ -123,16 +131,18 @@ Class Procs:
|
||||
air.group_multiplier = contents.len+1
|
||||
|
||||
/zone/proc/tick()
|
||||
air.archive()
|
||||
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
|
||||
M << "O2: [air.oxygen] N2: [air.nitrogen] CO2: [air.carbon_dioxide] P: [air.phoron]"
|
||||
for(var/g in air.gas)
|
||||
M << "[gas_data.name[g]]: [air.gas[g]]"
|
||||
M << "P: [air.return_pressure()] kPa V: [air.volume]L T: [air.temperature]°K ([air.temperature - T0C]°C)"
|
||||
M << "O2 per N2: [(air.nitrogen ? air.oxygen/air.nitrogen : "N/A")] Moles: [air.total_moles]"
|
||||
M << "O2 per N2: [(air.gas["nitrogen"] ? air.gas["oxygen"]/air.gas["nitrogen"] : "N/A")] Moles: [air.total_moles]"
|
||||
M << "Simulated: [contents.len] ([air.group_multiplier])"
|
||||
//M << "Unsimulated: [unsimulated_contents.len]"
|
||||
//M << "Edges: [edges.len]"
|
||||
|
||||
@@ -0,0 +1,419 @@
|
||||
#define QUANTIZE(variable) (round(variable,0.0001))
|
||||
|
||||
/datum/gas_mixture
|
||||
//Associative list of gas moles.
|
||||
//Gases with 0 moles are not tracked and are pruned by update_values()
|
||||
var/list/gas = list()
|
||||
//Temperature in Kelvin of this gas mix.
|
||||
var/temperature = 0
|
||||
|
||||
//Sum of all the gas moles in this mix. Updated by update_values()
|
||||
var/total_moles = 0
|
||||
//Volume of this mix.
|
||||
var/volume = CELL_VOLUME
|
||||
//Size of the group this gas_mixture is representing. 1 for singletons.
|
||||
var/group_multiplier = 1
|
||||
|
||||
//List of active tile overlays for this gas_mixture. Updated by check_tile_graphic()
|
||||
var/list/graphic = list()
|
||||
|
||||
//Takes a gas string, and the amount of moles to adjust by. Calls update_values() if update isn't 0.
|
||||
/datum/gas_mixture/proc/adjust_gas(gasid, moles, update = 1)
|
||||
if(moles == 0)
|
||||
return
|
||||
|
||||
if (group_multiplier != 1)
|
||||
gas[gasid] += moles/group_multiplier
|
||||
else
|
||||
gas[gasid] += moles
|
||||
|
||||
if(update)
|
||||
update_values()
|
||||
|
||||
//Same as adjust_gas(), but takes a temperature which is mixed in with the gas.
|
||||
/datum/gas_mixture/proc/adjust_gas_temp(gasid, moles, temp, update = 1)
|
||||
if(moles == 0)
|
||||
return
|
||||
|
||||
if(moles > 0 && abs(temperature - temp) > MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
|
||||
var/self_heat_capacity = heat_capacity()
|
||||
var/giver_heat_capacity = gas_data.specific_heat[gasid] * moles
|
||||
var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity
|
||||
if(combined_heat_capacity != 0)
|
||||
temperature = (temp * giver_heat_capacity + temperature * self_heat_capacity) / combined_heat_capacity
|
||||
|
||||
if (group_multiplier != 1)
|
||||
gas[gasid] += moles/group_multiplier
|
||||
else
|
||||
gas[gasid] += moles
|
||||
|
||||
if(update)
|
||||
update_values()
|
||||
|
||||
//Variadic version of adjust_gas(). Takes any number of gas and mole pairs, and applies them.
|
||||
/datum/gas_mixture/proc/adjust_multi()
|
||||
ASSERT(!(args.len % 2))
|
||||
|
||||
for(var/i = 1; i < args.len; i += 2)
|
||||
adjust_gas(args[i], args[i+1], update = 0)
|
||||
|
||||
update_values()
|
||||
|
||||
//Variadic version of adjust_gas_temp(). Takes any number of gas, mole, and temperature tuples, and applies them.
|
||||
/datum/gas_mixture/proc/adjust_multi_temp()
|
||||
ASSERT(!(args.len % 3))
|
||||
|
||||
for(var/i = 1; i < args.len; i += 3)
|
||||
adjust_gas_temp(args[i], args[i + 1], args[i + 2], update = 0)
|
||||
|
||||
update_values()
|
||||
|
||||
//Merges all the gas from another mixture into this one. Respects group_multipliers and adjusts temperature correctly.
|
||||
/datum/gas_mixture/proc/merge(datum/gas_mixture/giver)
|
||||
if(!giver)
|
||||
return
|
||||
|
||||
if(abs(temperature-giver.temperature)>MINIMUM_TEMPERATURE_DELTA_TO_CONSIDER)
|
||||
var/self_heat_capacity = heat_capacity()
|
||||
var/giver_heat_capacity = giver.heat_capacity()
|
||||
var/combined_heat_capacity = giver_heat_capacity + self_heat_capacity
|
||||
if(combined_heat_capacity != 0)
|
||||
temperature = (giver.temperature*giver_heat_capacity + temperature*self_heat_capacity)/combined_heat_capacity
|
||||
|
||||
if((group_multiplier != 1)||(giver.group_multiplier != 1))
|
||||
for(var/g in giver.gas)
|
||||
gas[g] += giver.gas[g] * giver.group_multiplier / group_multiplier
|
||||
else
|
||||
for(var/g in giver.gas)
|
||||
gas[g] += giver.gas[g]
|
||||
|
||||
update_values()
|
||||
|
||||
//Returns the heat capacity of the gas mix based on the specific heat of the gases.
|
||||
/datum/gas_mixture/proc/heat_capacity()
|
||||
. = 0
|
||||
for(var/g in gas)
|
||||
. += gas_data.specific_heat[g] * gas[g]
|
||||
. *= group_multiplier
|
||||
|
||||
//Adds or removes thermal energy. Returns the actual thermal energy change, as in the case of removing energy we can't go below TCMB.
|
||||
/datum/gas_mixture/proc/add_thermal_energy(var/thermal_energy)
|
||||
if (total_moles == 0)
|
||||
return 0
|
||||
|
||||
var/heat_capacity = heat_capacity()
|
||||
if (thermal_energy < 0)
|
||||
if (temperature < TCMB)
|
||||
return 0
|
||||
var/thermal_energy_limit = -(temperature - TCMB)*heat_capacity //ensure temperature does not go below TCMB
|
||||
thermal_energy = max( thermal_energy, thermal_energy_limit ) //thermal_energy and thermal_energy_limit are negative here.
|
||||
temperature += thermal_energy/heat_capacity
|
||||
return thermal_energy
|
||||
|
||||
//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()*(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
|
||||
|
||||
//Returns the ideal gas specific entropy of the whole mix. This is the entropy per mole of /mixed/ gas.
|
||||
/datum/gas_mixture/proc/specific_entropy()
|
||||
if (!gas.len || total_moles == 0)
|
||||
return SPECIFIC_ENTROPY_VACUUM
|
||||
|
||||
. = 0
|
||||
for(var/g in gas)
|
||||
. += gas[g] * specific_entropy_gas(g)
|
||||
. /= total_moles
|
||||
|
||||
/*
|
||||
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]
|
||||
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()
|
||||
total_moles = 0
|
||||
for(var/g in gas)
|
||||
if(gas[g] <= 0)
|
||||
gas -= g
|
||||
else
|
||||
total_moles += gas[g]
|
||||
|
||||
//Returns the pressure of the gas mix. Only accurate if there have been no gas modifications since update_values() has been called.
|
||||
/datum/gas_mixture/proc/return_pressure()
|
||||
if(volume)
|
||||
return total_moles * R_IDEAL_GAS_EQUATION * temperature / volume
|
||||
return 0
|
||||
|
||||
//Removes moles from the gas mixture and returns a gas_mixture containing the removed air.
|
||||
/datum/gas_mixture/proc/remove(amount)
|
||||
amount = min(amount, total_moles * group_multiplier) //Can not take more air than the gas mixture has!
|
||||
if(amount <= 0)
|
||||
return null
|
||||
|
||||
var/datum/gas_mixture/removed = new
|
||||
|
||||
for(var/g in gas)
|
||||
removed.gas[g] = QUANTIZE((gas[g] / total_moles) * amount)
|
||||
gas[g] -= removed.gas[g] / group_multiplier
|
||||
|
||||
removed.temperature = temperature
|
||||
update_values()
|
||||
removed.update_values()
|
||||
|
||||
return removed
|
||||
|
||||
//Removes a ratio of gas from the mixture and returns a gas_mixture containing the removed air.
|
||||
/datum/gas_mixture/proc/remove_ratio(ratio, out_group_multiplier = 1)
|
||||
if(ratio <= 0)
|
||||
return null
|
||||
out_group_multiplier = max(1, min(group_multiplier, out_group_multiplier))
|
||||
|
||||
ratio = min(ratio, 1)
|
||||
|
||||
var/datum/gas_mixture/removed = new
|
||||
removed.group_multiplier = out_group_multiplier
|
||||
|
||||
for(var/g in gas)
|
||||
removed.gas[g] = (gas[g] * ratio * group_multiplier / out_group_multiplier)
|
||||
gas[g] = gas[g] * (1 - ratio)
|
||||
|
||||
removed.temperature = temperature
|
||||
update_values()
|
||||
removed.update_values()
|
||||
|
||||
return removed
|
||||
|
||||
//Removes moles from the gas mixture, limited by a given flag. Returns a gax_mixture containing the removed air.
|
||||
/datum/gas_mixture/proc/remove_by_flag(flag, amount)
|
||||
if(!flag || amount <= 0)
|
||||
return
|
||||
|
||||
var/sum = 0
|
||||
for(var/g in gas)
|
||||
if(gas_data.flags[g] & flag)
|
||||
sum += gas[g]
|
||||
|
||||
var/datum/gas_mixture/removed = new
|
||||
|
||||
for(var/g in gas)
|
||||
if(gas_data.flags[g] & flag)
|
||||
removed.gas[g] = QUANTIZE((gas[g] / sum) * amount)
|
||||
gas[g] -= removed.gas[g] / group_multiplier
|
||||
|
||||
removed.temperature = temperature
|
||||
update_values()
|
||||
removed.update_values()
|
||||
|
||||
return removed
|
||||
|
||||
//Copies gas and temperature from another gas_mixture.
|
||||
/datum/gas_mixture/proc/copy_from(datum/gas_mixture/sample)
|
||||
gas = sample.gas.Copy()
|
||||
temperature = sample.temperature
|
||||
|
||||
update_values()
|
||||
|
||||
return 1
|
||||
|
||||
//Checks if we are within acceptable range of another gas_mixture to suspend processing or merge.
|
||||
/datum/gas_mixture/proc/compare(datum/gas_mixture/sample)
|
||||
if(!sample) return 0
|
||||
|
||||
var/list/marked = list()
|
||||
for(var/g in gas)
|
||||
if((abs(gas[g] - sample.gas[g]) > MINIMUM_AIR_TO_SUSPEND) && \
|
||||
((gas[g] < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.gas[g]) || \
|
||||
(gas[g] > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.gas[g])))
|
||||
return 0
|
||||
marked[g] = 1
|
||||
|
||||
for(var/g in sample.gas)
|
||||
if(!marked[g])
|
||||
if((abs(gas[g] - sample.gas[g]) > MINIMUM_AIR_TO_SUSPEND) && \
|
||||
((gas[g] < (1 - MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.gas[g]) || \
|
||||
(gas[g] > (1 + MINIMUM_AIR_RATIO_TO_SUSPEND) * sample.gas[g])))
|
||||
return 0
|
||||
|
||||
if(total_moles > MINIMUM_AIR_TO_SUSPEND)
|
||||
if((abs(temperature - sample.temperature) > MINIMUM_TEMPERATURE_DELTA_TO_SUSPEND) && \
|
||||
((temperature < (1 - MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature) || \
|
||||
(temperature > (1 + MINIMUM_TEMPERATURE_RATIO_TO_SUSPEND)*sample.temperature)))
|
||||
return 0
|
||||
|
||||
return 1
|
||||
|
||||
/datum/gas_mixture/proc/react(atom/dump_location)
|
||||
zburn(null)
|
||||
|
||||
//Rechecks the gas_mixture and adjusts the graphic list if needed.
|
||||
//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.
|
||||
if(gas[g] <= gas_data.overlay_limit[g])
|
||||
if(!graphic_remove)
|
||||
graphic_remove = list()
|
||||
graphic_remove += gas_data.tile_overlay[g]
|
||||
else
|
||||
//Overlay isn't applied for this gas, check if it's valid and needs to be added.
|
||||
if(gas[g] > gas_data.overlay_limit[g])
|
||||
if(!graphic_add)
|
||||
graphic_add = list()
|
||||
graphic_add += gas_data.tile_overlay[g]
|
||||
|
||||
. = 0
|
||||
//Apply changes
|
||||
if(graphic_add && graphic_add.len)
|
||||
graphic += graphic_add
|
||||
. = 1
|
||||
if(graphic_remove && graphic_remove.len)
|
||||
graphic -= graphic_remove
|
||||
. = 1
|
||||
|
||||
//Simpler version of merge(), adjusts gas amounts directly and doesn't account for temperature or group_multiplier.
|
||||
/datum/gas_mixture/proc/add(datum/gas_mixture/right_side)
|
||||
for(var/g in right_side.gas)
|
||||
gas[g] += right_side.gas[g]
|
||||
|
||||
update_values()
|
||||
return 1
|
||||
|
||||
//Simpler version of remove(), adjusts gas amounts directly and doesn't account for group_multiplier.
|
||||
/datum/gas_mixture/proc/subtract(datum/gas_mixture/right_side)
|
||||
for(var/g in right_side.gas)
|
||||
gas[g] -= right_side.gas[g]
|
||||
|
||||
update_values()
|
||||
return 1
|
||||
|
||||
//Multiply all gas amounts by a factor.
|
||||
/datum/gas_mixture/proc/multiply(factor)
|
||||
for(var/g in gas)
|
||||
gas[g] *= factor
|
||||
|
||||
update_values()
|
||||
return 1
|
||||
|
||||
//Divide all gas amounts by a factor.
|
||||
/datum/gas_mixture/proc/divide(factor)
|
||||
for(var/g in gas)
|
||||
gas[g] /= factor
|
||||
|
||||
update_values()
|
||||
return 1
|
||||
|
||||
//Shares gas with another gas_mixture based on the amount of connecting tiles and a fixed lookup table.
|
||||
/datum/gas_mixture/proc/share_ratio(datum/gas_mixture/other, connecting_tiles, share_size = null, one_way = 0)
|
||||
var/static/list/sharing_lookup_table = list(0.30, 0.40, 0.48, 0.54, 0.60, 0.66)
|
||||
//Shares a specific ratio of gas between mixtures using simple weighted averages.
|
||||
var/ratio = sharing_lookup_table[6]
|
||||
|
||||
var/size = max(1, group_multiplier)
|
||||
if(isnull(share_size)) share_size = max(1, other.group_multiplier)
|
||||
|
||||
var/full_heat_capacity = heat_capacity()
|
||||
var/s_full_heat_capacity = other.heat_capacity()
|
||||
|
||||
var/list/avg_gas = list()
|
||||
|
||||
for(var/g in gas)
|
||||
avg_gas[g] += gas[g] * size
|
||||
|
||||
for(var/g in other.gas)
|
||||
avg_gas[g] += other.gas[g] * share_size
|
||||
|
||||
for(var/g in avg_gas)
|
||||
avg_gas[g] /= (size + share_size)
|
||||
|
||||
var/temp_avg = 0
|
||||
if(full_heat_capacity + s_full_heat_capacity)
|
||||
temp_avg = (temperature * full_heat_capacity + other.temperature * s_full_heat_capacity) / (full_heat_capacity + s_full_heat_capacity)
|
||||
|
||||
//WOOT WOOT TOUCH THIS AND YOU ARE A RETARD.
|
||||
if(sharing_lookup_table.len >= connecting_tiles) //6 or more interconnecting tiles will max at 42% of air moved per tick.
|
||||
ratio = sharing_lookup_table[connecting_tiles]
|
||||
//WOOT WOOT TOUCH THIS AND YOU ARE A RETARD
|
||||
|
||||
for(var/g in avg_gas)
|
||||
gas[g] = max(0, (gas[g] - avg_gas[g]) * (1 - ratio) + avg_gas[g])
|
||||
if(!one_way)
|
||||
other.gas[g] = max(0, (other.gas[g] - avg_gas[g]) * (1 - ratio) + avg_gas[g])
|
||||
|
||||
temperature = max(0, (temperature - temp_avg) * (1-ratio) + temp_avg)
|
||||
if(!one_way)
|
||||
other.temperature = max(0, (other.temperature - temp_avg) * (1-ratio) + temp_avg)
|
||||
|
||||
update_values()
|
||||
other.update_values()
|
||||
|
||||
if(compare(other)) return 1
|
||||
else return 0
|
||||
|
||||
//A wrapper around share_ratio for spacing gas at the same rate as if it were going into a large airless room.
|
||||
/datum/gas_mixture/proc/share_space(datum/gas_mixture/unsim_air)
|
||||
if(!unsim_air)
|
||||
return 0
|
||||
|
||||
var/old_pressure = return_pressure()
|
||||
|
||||
share_ratio(unsim_air, unsim_air.group_multiplier, max(1, max(group_multiplier + 3, 1) + unsim_air.group_multiplier), one_way = 1)
|
||||
|
||||
return abs(old_pressure - return_pressure())
|
||||
|
||||
//Equalizes a list of gas mixtures. Used for pipe networks.
|
||||
/proc/equalize_gases(datum/gas_mixture/list/gases)
|
||||
//Calculate totals from individual components
|
||||
var/total_volume = 0
|
||||
var/total_thermal_energy = 0
|
||||
var/total_heat_capacity = 0
|
||||
|
||||
var/list/total_gas = list()
|
||||
for(var/datum/gas_mixture/gasmix in gases)
|
||||
total_volume += gasmix.volume
|
||||
var/temp_heatcap = gasmix.heat_capacity()
|
||||
total_thermal_energy += gasmix.temperature * temp_heatcap
|
||||
total_heat_capacity += temp_heatcap
|
||||
for(var/g in gasmix.gas)
|
||||
total_gas[g] += gasmix.gas[g]
|
||||
|
||||
if(total_volume > 0)
|
||||
//Average out the gases
|
||||
for(var/g in total_gas)
|
||||
total_gas[g] /= total_volume
|
||||
|
||||
//Calculate temperature
|
||||
var/temperature = 0
|
||||
|
||||
if(total_heat_capacity > 0)
|
||||
temperature = total_thermal_energy / total_heat_capacity
|
||||
|
||||
//Update individual gas_mixtures
|
||||
for(var/datum/gas_mixture/gasmix in gases)
|
||||
gasmix.gas = total_gas.Copy()
|
||||
gasmix.temperature = temperature
|
||||
gasmix.multiply(gasmix.volume)
|
||||
|
||||
return 1
|
||||
@@ -0,0 +1,46 @@
|
||||
/var/xgm_gas_data/gas_data
|
||||
|
||||
/xgm_gas_data
|
||||
//Simple list of all the gas IDs.
|
||||
var/list/gases = list()
|
||||
//The friendly, human-readable name for the gas.
|
||||
var/list/name = list()
|
||||
//Specific heat of the gas. Used for calculating heat capacity.
|
||||
var/list/specific_heat = list()
|
||||
//Molar mass of the gas. Used for calculating specific entropy.
|
||||
var/list/molar_mass = list()
|
||||
//Tile overlays. /images, created from references to 'icons/effects/tile_effects.dmi'
|
||||
var/list/tile_overlay = list()
|
||||
//Overlay limits. There must be at least this many moles for the overlay to appear.
|
||||
var/list/overlay_limit = list()
|
||||
//Flags.
|
||||
var/list/flags = list()
|
||||
|
||||
/xgm_gas
|
||||
var/id = ""
|
||||
var/name = "Unnamed Gas"
|
||||
var/specific_heat = 20 // J/(mol*K)
|
||||
var/molar_mass = 0.032 // kg/mol
|
||||
|
||||
var/tile_overlay = null
|
||||
var/overlay_limit = null
|
||||
|
||||
var/flags = 0
|
||||
|
||||
/hook/startup/proc/generateGasData()
|
||||
gas_data = new
|
||||
for(var/p in (typesof(/xgm_gas) - /xgm_gas))
|
||||
var/xgm_gas/gas = new p
|
||||
|
||||
if(gas.id in gas_data.gases)
|
||||
error("Duplicate gas id `[gas.id]` in `[p]`")
|
||||
|
||||
gas_data.gases += gas.id
|
||||
gas_data.name[gas.id] = gas.name
|
||||
gas_data.specific_heat[gas.id] = gas.specific_heat
|
||||
gas_data.molar_mass[gas.id] = gas.molar_mass
|
||||
if(gas.tile_overlay) gas_data.tile_overlay[gas.id] = image('icons/effects/tile_effects.dmi', gas.tile_overlay, FLY_LAYER)
|
||||
if(gas.overlay_limit) gas_data.overlay_limit[gas.id] = gas.overlay_limit
|
||||
gas_data.flags[gas.id] = gas.flags
|
||||
|
||||
return 1
|
||||
+62
-1
@@ -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)
|
||||
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(cp<minp)minp=cp
|
||||
if(cp>maxp)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
|
||||
|
||||
@@ -303,3 +303,14 @@ proc/checkhtml(var/t)
|
||||
for(var/i = length(text); i > 0; i--)
|
||||
new_text += copytext(text, i, i+1)
|
||||
return new_text
|
||||
|
||||
//Used in preferences' SetFlavorText and human's set_flavor verb
|
||||
//Previews a string of len or less length
|
||||
proc/TextPreview(var/string,var/len=40)
|
||||
if(lentext(string) <= len)
|
||||
if(!lentext(string))
|
||||
return "\[...\]"
|
||||
else
|
||||
return string
|
||||
else
|
||||
return "[copytext(string, 1, 37)]..."
|
||||
|
||||
@@ -1306,11 +1306,10 @@ proc/is_hot(obj/item/W as obj)
|
||||
|
||||
//check if mob is lying down on something we can operate him on.
|
||||
/proc/can_operate(mob/living/carbon/M)
|
||||
return (locate(/obj/machinery/optable, M.loc) && M.resting) || \
|
||||
(locate(/obj/structure/stool/bed/roller, M.loc) && \
|
||||
(M.buckled || M.lying || M.weakened || M.stunned || M.paralysis || M.sleeping || M.stat)) && prob(75) || \
|
||||
(locate(/obj/structure/table/, M.loc) && \
|
||||
(M.lying || M.weakened || M.stunned || M.paralysis || M.sleeping || M.stat) && prob(66))
|
||||
return (M.lying && \
|
||||
locate(/obj/machinery/optable, M.loc) || \
|
||||
(locate(/obj/structure/stool/bed/roller, M.loc) && prob(75)) || \
|
||||
(locate(/obj/structure/table/, M.loc) && prob(66)))
|
||||
|
||||
/proc/reverse_direction(var/dir)
|
||||
switch(dir)
|
||||
|
||||
+39
-8
@@ -53,6 +53,11 @@
|
||||
return
|
||||
next_move = world.time + 9
|
||||
|
||||
if(aiCamera.in_camera_mode)
|
||||
aiCamera.camera_mode_off()
|
||||
aiCamera.captureimage(A, usr)
|
||||
return
|
||||
|
||||
/*
|
||||
AI restrained() currently does nothing
|
||||
if(restrained())
|
||||
@@ -81,12 +86,15 @@
|
||||
than anything else in the game, atoms have separate procs
|
||||
for AI shift, ctrl, and alt clicking.
|
||||
*/
|
||||
|
||||
/mob/living/silicon/ai/ShiftClickOn(var/atom/A)
|
||||
A.AIShiftClick(src)
|
||||
/mob/living/silicon/ai/CtrlClickOn(var/atom/A)
|
||||
A.AICtrlClick(src)
|
||||
/mob/living/silicon/ai/AltClickOn(var/atom/A)
|
||||
A.AIAltClick(src)
|
||||
/mob/living/silicon/ai/MiddleClickOn(var/atom/A)
|
||||
A.AIMiddleClick(src)
|
||||
|
||||
/*
|
||||
The following criminally helpful code is just the previous code cleaned up;
|
||||
@@ -103,7 +111,6 @@
|
||||
Topic("aiDisable=7", list("aiDisable"="7"), 1)
|
||||
return
|
||||
|
||||
|
||||
/atom/proc/AICtrlClick()
|
||||
return
|
||||
|
||||
@@ -113,18 +120,42 @@
|
||||
else
|
||||
Topic("aiDisable=4", list("aiDisable"="4"), 1)
|
||||
|
||||
/obj/machinery/power/apc/AICtrlClick() // turns off APCs.
|
||||
/obj/machinery/power/apc/AICtrlClick() // turns off/on APCs.
|
||||
Topic("breaker=1", list("breaker"="1"), 0) // 0 meaning no window (consistency! wait...)
|
||||
|
||||
/obj/machinery/turretid/AICtrlClick() //turns off/on Turrets
|
||||
src.enabled = !src.enabled
|
||||
src.updateTurrets()
|
||||
|
||||
/atom/proc/AIAltClick()
|
||||
return
|
||||
/atom/proc/AIAltClick(var/atom/A)
|
||||
AltClick(A)
|
||||
|
||||
/obj/machinery/door/airlock/AIAltClick() // Eletrifies doors.
|
||||
/obj/machinery/door/airlock/AIAltClick() // Electrifies doors.
|
||||
if(!secondsElectrified)
|
||||
// permenant shock
|
||||
// permanent shock
|
||||
Topic("aiEnable=6", list("aiEnable"="6"), 1) // 1 meaning no window (consistency!)
|
||||
else
|
||||
// disable/6 is not in Topic; disable/5 disables both temporary and permenant shock
|
||||
// disable/6 is not in Topic; disable/5 disables both temporary and permanent shock
|
||||
Topic("aiDisable=5", list("aiDisable"="5"), 1)
|
||||
return
|
||||
return
|
||||
|
||||
/obj/machinery/turretid/AIAltClick() //toggles lethal on turrets
|
||||
src.lethal = !src.lethal
|
||||
src.updateTurrets()
|
||||
|
||||
/atom/proc/AIMiddleClick()
|
||||
return
|
||||
|
||||
/obj/machinery/door/airlock/AIMiddleClick() // Toggles door bolt lights.
|
||||
if(!src.lights)
|
||||
Topic("aiEnable=10", list("aiEnable"="10"), 1) // 1 meaning no window (consistency!)
|
||||
else
|
||||
Topic("aiDisable=10", list("aiDisable"="10"), 1)
|
||||
return
|
||||
|
||||
//
|
||||
// Override AdjacentQuick for AltClicking
|
||||
//
|
||||
|
||||
/mob/living/silicon/ai/TurfAdjacent(var/turf/T)
|
||||
return (cameranet && cameranet.checkTurfVis(T))
|
||||
|
||||
+15
-2
@@ -252,7 +252,7 @@
|
||||
|
||||
/atom/proc/AltClick(var/mob/user)
|
||||
var/turf/T = get_turf(src)
|
||||
if(T && T.AdjacentQuick(user))
|
||||
if(T && user.TurfAdjacent(T))
|
||||
if(user.listed_turf == T)
|
||||
user.listed_turf = null
|
||||
else
|
||||
@@ -260,6 +260,9 @@
|
||||
user.client.statpanel = T.name
|
||||
return
|
||||
|
||||
/mob/proc/TurfAdjacent(var/turf/T)
|
||||
return T.AdjacentQuick(src)
|
||||
|
||||
/*
|
||||
Misc helpers
|
||||
|
||||
@@ -298,7 +301,17 @@
|
||||
|
||||
// Simple helper to face what you clicked on, in case it should be needed in more than one place
|
||||
/mob/proc/face_atom(var/atom/A)
|
||||
if( stat || (buckled && !buckled.movable) || !A || !x || !y || !A.x || !A.y ) return
|
||||
|
||||
// Snowflake for space vines.
|
||||
var/is_buckled = 0
|
||||
if(buckled)
|
||||
if(istype(buckled))
|
||||
if(!buckled.movable)
|
||||
is_buckled = 1
|
||||
else
|
||||
is_buckled = 0
|
||||
|
||||
if( stat || is_buckled || !A || !x || !y || !A.x || !A.y ) return
|
||||
var/dx = A.x - x
|
||||
var/dy = A.y - y
|
||||
if(!dx && !dy) return
|
||||
|
||||
@@ -37,6 +37,14 @@
|
||||
|
||||
face_atom(A) // change direction to face what you clicked on
|
||||
|
||||
if(aiCamera.in_camera_mode)
|
||||
aiCamera.camera_mode_off()
|
||||
if(is_component_functioning("camera"))
|
||||
aiCamera.captureimage(A, usr)
|
||||
else
|
||||
src << "<span class='userdanger'>Your camera isn't functional.</span>"
|
||||
return
|
||||
|
||||
/*
|
||||
cyborg restrained() currently does nothing
|
||||
if(restrained())
|
||||
|
||||
@@ -276,7 +276,7 @@
|
||||
var/list/nicename = null
|
||||
var/list/tankcheck = null
|
||||
var/breathes = "oxygen" //default, we'll check later
|
||||
var/list/contents = list()
|
||||
var/list/contents = list()
|
||||
|
||||
if(ishuman(C))
|
||||
var/mob/living/carbon/human/H = C
|
||||
@@ -284,7 +284,7 @@
|
||||
nicename = list ("suit", "back", "belt", "right hand", "left hand", "left pocket", "right pocket")
|
||||
tankcheck = list (H.s_store, C.back, H.belt, C.r_hand, C.l_hand, H.l_store, H.r_store)
|
||||
|
||||
else
|
||||
else
|
||||
|
||||
nicename = list("Right Hand", "Left Hand", "Back")
|
||||
tankcheck = list(C.r_hand, C.l_hand, C.back)
|
||||
@@ -295,30 +295,30 @@
|
||||
if (!isnull(t.manipulated_by) && t.manipulated_by != C.real_name && findtext(t.desc,breathes))
|
||||
contents.Add(t.air_contents.total_moles) //Someone messed with the tank and put unknown gasses
|
||||
continue //in it, so we're going to believe the tank is what it says it is
|
||||
switch(breathes)
|
||||
switch(breathes)
|
||||
//These tanks we're sure of their contents
|
||||
if("nitrogen") //So we're a bit more picky about them.
|
||||
|
||||
if(t.air_contents.nitrogen && !t.air_contents.oxygen)
|
||||
contents.Add(t.air_contents.nitrogen)
|
||||
|
||||
if(t.air_contents.gas["nitrogen"] && !t.air_contents.gas["oxygen"])
|
||||
contents.Add(t.air_contents.gas["nitrogen"])
|
||||
else
|
||||
contents.Add(0)
|
||||
contents.Add(0)
|
||||
|
||||
if ("oxygen")
|
||||
if(t.air_contents.oxygen && !t.air_contents.phoron)
|
||||
contents.Add(t.air_contents.oxygen)
|
||||
if(t.air_contents.gas["oxygen"] && !t.air_contents.gas["phoron"])
|
||||
contents.Add(t.air_contents.gas["oxygen"])
|
||||
else
|
||||
contents.Add(0)
|
||||
|
||||
// No races breath this, but never know about downstream servers.
|
||||
if ("carbon dioxide")
|
||||
if(t.air_contents.carbon_dioxide && !t.air_contents.phoron)
|
||||
contents.Add(t.air_contents.carbon_dioxide)
|
||||
if(t.air_contents.gas["carbon_dioxide"] && !t.air_contents.gas["phoron"])
|
||||
contents.Add(t.air_contents.gas["carbon_dioxide"])
|
||||
else
|
||||
contents.Add(0)
|
||||
|
||||
|
||||
else
|
||||
|
||||
|
||||
else
|
||||
//no tank so we set contents to 0
|
||||
contents.Add(0)
|
||||
|
||||
@@ -328,19 +328,19 @@
|
||||
var/bestcontents = 0
|
||||
for(var/i=1, i < contents.len + 1 , ++i)
|
||||
if(!contents[i])
|
||||
continue
|
||||
continue
|
||||
if(contents[i] > bestcontents)
|
||||
best = i
|
||||
bestcontents = contents[i]
|
||||
|
||||
|
||||
|
||||
|
||||
//We've determined the best container now we set it as our internals
|
||||
|
||||
if(best)
|
||||
C << "<span class='notice'>You are now running on internals from [tankcheck[best]] on your [nicename[best]].</span>"
|
||||
C.internal = tankcheck[best]
|
||||
|
||||
|
||||
|
||||
|
||||
if(C.internal)
|
||||
if(C.internals)
|
||||
C.internals.icon_state = "internal1"
|
||||
|
||||
@@ -24,15 +24,13 @@
|
||||
/obj/item/proc/attack(mob/living/M as mob, mob/living/user as mob, def_zone)
|
||||
|
||||
if (!istype(M)) // not sure if this is the right thing...
|
||||
return
|
||||
return 0
|
||||
var/messagesource = M
|
||||
if (can_operate(M)) //Checks if mob is lying down on table for surgery
|
||||
if (do_surgery(M,user,src))
|
||||
return
|
||||
return 0
|
||||
if (istype(M,/mob/living/carbon/brain))
|
||||
messagesource = M:container
|
||||
if (hitsound)
|
||||
playsound(loc, hitsound, 50, 1, -1)
|
||||
/////////////////////////
|
||||
user.lastattacked = M
|
||||
M.lastattacker = user
|
||||
@@ -63,7 +61,7 @@
|
||||
slime.Discipline = 0
|
||||
|
||||
if(power >= 3)
|
||||
if(istype(slime, /mob/living/carbon/slime/adult))
|
||||
if(slime.is_adult)
|
||||
if(prob(5 + round(power/2)))
|
||||
|
||||
if(slime.Victim)
|
||||
@@ -140,8 +138,13 @@
|
||||
|
||||
|
||||
if(istype(M, /mob/living/carbon/human))
|
||||
return M:attacked_by(src, user, def_zone)
|
||||
var/hit = M:attacked_by(src, user, def_zone)
|
||||
if (hit && hitsound)
|
||||
playsound(loc, hitsound, 50, 1, -1)
|
||||
return hit
|
||||
else
|
||||
if (hitsound)
|
||||
playsound(loc, hitsound, 50, 1, -1)
|
||||
switch(damtype)
|
||||
if("brute")
|
||||
if(istype(src, /mob/living/carbon/slime))
|
||||
|
||||
@@ -1,307 +1,294 @@
|
||||
/*
|
||||
HOW IT WORKS
|
||||
|
||||
The radio_controller is a global object maintaining all radio transmissions, think about it as about "ether".
|
||||
Note that walkie-talkie, intercoms and headsets handle transmission using nonstandard way.
|
||||
procs:
|
||||
|
||||
add_object(obj/device as obj, var/new_frequency as num, var/filter as text|null = null)
|
||||
Adds listening object.
|
||||
parameters:
|
||||
device - device receiving signals, must have proc receive_signal (see description below).
|
||||
one device may listen several frequencies, but not same frequency twice.
|
||||
new_frequency - see possibly frequencies below;
|
||||
filter - thing for optimization. Optional, but recommended.
|
||||
All filters should be consolidated in this file, see defines later.
|
||||
Device without listening filter will receive all signals (on specified frequency).
|
||||
Device with filter will receive any signals sent without filter.
|
||||
Device with filter will not receive any signals sent with different filter.
|
||||
returns:
|
||||
Reference to frequency object.
|
||||
|
||||
remove_object (obj/device, old_frequency)
|
||||
Obliviously, after calling this proc, device will not receive any signals on old_frequency.
|
||||
Other frequencies will left unaffected.
|
||||
|
||||
return_frequency(var/frequency as num)
|
||||
returns:
|
||||
Reference to frequency object. Use it if you need to send and do not need to listen.
|
||||
|
||||
radio_frequency is a global object maintaining list of devices that listening specific frequency.
|
||||
procs:
|
||||
|
||||
post_signal(obj/source as obj|null, datum/signal/signal, var/filter as text|null = null, var/range as num|null = null)
|
||||
Sends signal to all devices that wants such signal.
|
||||
parameters:
|
||||
source - object, emitted signal. Usually, devices will not receive their own signals.
|
||||
signal - see description below.
|
||||
filter - described above.
|
||||
range - radius of regular byond's square circle on that z-level. null means everywhere, on all z-levels.
|
||||
|
||||
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.
|
||||
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.
|
||||
TRANSMISSION_WIRE is currently unused.
|
||||
receive_param - for TRANSMISSION_RADIO here comes frequency.
|
||||
|
||||
datum/signal
|
||||
vars:
|
||||
source
|
||||
an object that emitted signal. Used for debug and bearing.
|
||||
data
|
||||
list with transmitting data. Usual use pattern:
|
||||
data["msg"] = "hello world"
|
||||
encryption
|
||||
Some number symbolizing "encryption key".
|
||||
Note that game actually do not use any cryptography here.
|
||||
If receiving object don't know right key, it must ignore encrypted signal in its receive_signal.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
Frequency range: 1200 to 1600
|
||||
Radiochat range: 1441 to 1489 (most devices refuse to be tune to other frequency, even during mapmaking)
|
||||
|
||||
Radio:
|
||||
1459 - standard radio chat
|
||||
1351 - Science
|
||||
1353 - Command
|
||||
1355 - Medical
|
||||
1357 - Engineering
|
||||
1359 - Security
|
||||
1441 - death squad
|
||||
1443 - Confession Intercom
|
||||
1347 - Cargo techs
|
||||
|
||||
Devices:
|
||||
1451 - tracking implant
|
||||
1457 - RSD default
|
||||
|
||||
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
|
||||
1439 for air pumps, air scrubbers, atmo control
|
||||
1441 for atmospherics - supply tanks
|
||||
1443 for atmospherics - distribution loop/mixed air tank
|
||||
1445 for bot nav beacons
|
||||
1447 for mulebot, secbot and ed209 control
|
||||
1449 for airlock controls, electropack, magnets
|
||||
1451 for toxin lab access
|
||||
1453 for engineering access
|
||||
1455 for AI access
|
||||
*/
|
||||
|
||||
var/list/radiochannels = list(
|
||||
"Common" = 1459,
|
||||
"Science" = 1351,
|
||||
"Command" = 1353,
|
||||
"Medical" = 1355,
|
||||
"Engineering" = 1357,
|
||||
"Security" = 1359,
|
||||
"Response Team" = 1345,
|
||||
"Deathsquad" = 1341,
|
||||
"Syndicate" = 1213,
|
||||
"Supply" = 1347,
|
||||
)
|
||||
//depenging helpers
|
||||
var/list/DEPT_FREQS = list(1351, 1355, 1357, 1359, 1213, 1345, 1341, 1347)
|
||||
|
||||
// central command channels, i.e deathsquid & response teams
|
||||
var/list/CENT_FREQS = list(1345, 1341)
|
||||
|
||||
var/const/COMM_FREQ = 1353 //command, colored gold in chat window
|
||||
var/const/SYND_FREQ = 1213
|
||||
|
||||
// department channels
|
||||
var/const/SEC_FREQ = 1359
|
||||
var/const/ENG_FREQ = 1357
|
||||
var/const/SCI_FREQ = 1351
|
||||
var/const/MED_FREQ = 1355
|
||||
var/const/SUP_FREQ = 1347
|
||||
|
||||
#define TRANSMISSION_WIRE 0
|
||||
#define TRANSMISSION_RADIO 1
|
||||
|
||||
/* filters */
|
||||
var/const/RADIO_TO_AIRALARM = "1"
|
||||
var/const/RADIO_FROM_AIRALARM = "2"
|
||||
var/const/RADIO_CHAT = "3"
|
||||
var/const/RADIO_ATMOSIA = "4"
|
||||
var/const/RADIO_NAVBEACONS = "5"
|
||||
var/const/RADIO_AIRLOCK = "6"
|
||||
var/const/RADIO_SECBOT = "7"
|
||||
var/const/RADIO_MULEBOT = "8"
|
||||
var/const/RADIO_MAGNETS = "9"
|
||||
|
||||
var/global/datum/controller/radio/radio_controller
|
||||
|
||||
/hook/startup/proc/createRadioController()
|
||||
radio_controller = new /datum/controller/radio()
|
||||
return 1
|
||||
|
||||
datum/controller/radio
|
||||
var/list/datum/radio_frequency/frequencies = list()
|
||||
|
||||
proc/add_object(obj/device as obj, var/new_frequency as num, var/filter = null as text|null)
|
||||
var/f_text = num2text(new_frequency)
|
||||
var/datum/radio_frequency/frequency = frequencies[f_text]
|
||||
|
||||
if(!frequency)
|
||||
frequency = new
|
||||
frequency.frequency = new_frequency
|
||||
frequencies[f_text] = frequency
|
||||
|
||||
frequency.add_listener(device, filter)
|
||||
return frequency
|
||||
|
||||
proc/remove_object(obj/device, old_frequency)
|
||||
var/f_text = num2text(old_frequency)
|
||||
var/datum/radio_frequency/frequency = frequencies[f_text]
|
||||
|
||||
if(frequency)
|
||||
frequency.remove_listener(device)
|
||||
|
||||
if(frequency.devices.len == 0)
|
||||
del(frequency)
|
||||
frequencies -= f_text
|
||||
|
||||
return 1
|
||||
|
||||
proc/return_frequency(var/new_frequency as num)
|
||||
var/f_text = num2text(new_frequency)
|
||||
var/datum/radio_frequency/frequency = frequencies[f_text]
|
||||
|
||||
if(!frequency)
|
||||
frequency = new
|
||||
frequency.frequency = new_frequency
|
||||
frequencies[f_text] = frequency
|
||||
|
||||
return frequency
|
||||
|
||||
datum/radio_frequency
|
||||
var/frequency as num
|
||||
var/list/list/obj/devices = list()
|
||||
|
||||
proc
|
||||
post_signal(obj/source as obj|null, datum/signal/signal, var/filter = null as text|null, var/range = null as num|null)
|
||||
//log_admin("DEBUG \[[world.timeofday]\]: post_signal {source=\"[source]\", [signal.debug_print()], filter=[filter]}")
|
||||
// var/N_f=0
|
||||
// var/N_nf=0
|
||||
// var/Nt=0
|
||||
var/turf/start_point
|
||||
if(range)
|
||||
start_point = get_turf(source)
|
||||
if(!start_point)
|
||||
del(signal)
|
||||
return 0
|
||||
if (filter) //here goes some copypasta. It is for optimisation. -rastaf0
|
||||
for(var/obj/device in devices[filter])
|
||||
if(device == source)
|
||||
continue
|
||||
if(range)
|
||||
var/turf/end_point = get_turf(device)
|
||||
if(!end_point)
|
||||
continue
|
||||
//if(max(abs(start_point.x-end_point.x), abs(start_point.y-end_point.y)) <= range)
|
||||
if(start_point.z!=end_point.z || get_dist(start_point, end_point) > range)
|
||||
continue
|
||||
device.receive_signal(signal, TRANSMISSION_RADIO, frequency)
|
||||
for(var/obj/device in devices["_default"])
|
||||
if(device == source)
|
||||
continue
|
||||
if(range)
|
||||
var/turf/end_point = get_turf(device)
|
||||
if(!end_point)
|
||||
continue
|
||||
//if(max(abs(start_point.x-end_point.x), abs(start_point.y-end_point.y)) <= range)
|
||||
if(start_point.z!=end_point.z || get_dist(start_point, end_point) > range)
|
||||
continue
|
||||
device.receive_signal(signal, TRANSMISSION_RADIO, frequency)
|
||||
// N_f++
|
||||
else
|
||||
for (var/next_filter in devices)
|
||||
// var/list/obj/DDD = devices[next_filter]
|
||||
// Nt+=DDD.len
|
||||
for(var/obj/device in devices[next_filter])
|
||||
if(device == source)
|
||||
continue
|
||||
if(range)
|
||||
var/turf/end_point = get_turf(device)
|
||||
if(!end_point)
|
||||
continue
|
||||
//if(max(abs(start_point.x-end_point.x), abs(start_point.y-end_point.y)) <= range)
|
||||
if(start_point.z!=end_point.z || get_dist(start_point, end_point) > range)
|
||||
continue
|
||||
device.receive_signal(signal, TRANSMISSION_RADIO, frequency)
|
||||
// N_nf++
|
||||
|
||||
// log_admin("DEBUG: post_signal(source=[source] ([source.x], [source.y], [source.z]),filter=[filter]) frequency=[frequency], N_f=[N_f], N_nf=[N_nf]")
|
||||
|
||||
|
||||
// del(signal)
|
||||
|
||||
add_listener(obj/device as obj, var/filter as text|null)
|
||||
if (!filter)
|
||||
filter = "_default"
|
||||
//log_admin("add_listener(device=[device],filter=[filter]) frequency=[frequency]")
|
||||
var/list/obj/devices_line = devices[filter]
|
||||
if (!devices_line)
|
||||
devices_line = new
|
||||
devices[filter] = devices_line
|
||||
devices_line+=device
|
||||
// var/list/obj/devices_line___ = devices[filter_str]
|
||||
// var/l = devices_line___.len
|
||||
//log_admin("DEBUG: devices_line.len=[devices_line.len]")
|
||||
//log_admin("DEBUG: devices(filter_str).len=[l]")
|
||||
|
||||
remove_listener(obj/device)
|
||||
for (var/devices_filter in devices)
|
||||
var/list/devices_line = devices[devices_filter]
|
||||
devices_line-=device
|
||||
while (null in devices_line)
|
||||
devices_line -= null
|
||||
if (devices_line.len==0)
|
||||
devices -= devices_filter
|
||||
del(devices_line)
|
||||
|
||||
|
||||
obj/proc
|
||||
receive_signal(datum/signal/signal, receive_method, receive_param)
|
||||
return null
|
||||
|
||||
datum/signal
|
||||
var/obj/source
|
||||
|
||||
var/transmission_method = 0
|
||||
//0 = wire
|
||||
//1 = radio transmission
|
||||
//2 = subspace transmission
|
||||
|
||||
var/data = list()
|
||||
var/encryption
|
||||
|
||||
var/frequency = 0
|
||||
|
||||
proc/copy_from(datum/signal/model)
|
||||
source = model.source
|
||||
transmission_method = model.transmission_method
|
||||
data = model.data
|
||||
encryption = model.encryption
|
||||
frequency = model.frequency
|
||||
|
||||
proc/debug_print()
|
||||
if (source)
|
||||
. = "signal = {source = '[source]' ([source:x],[source:y],[source:z])\n"
|
||||
else
|
||||
. = "signal = {source = '[source]' ()\n"
|
||||
for (var/i in data)
|
||||
. += "data\[\"[i]\"\] = \"[data[i]]\"\n"
|
||||
if(islist(data[i]))
|
||||
var/list/L = data[i]
|
||||
for(var/t in L)
|
||||
. += "data\[\"[i]\"\] list has: [t]"
|
||||
/*
|
||||
HOW IT WORKS
|
||||
|
||||
The radio_controller is a global object maintaining all radio transmissions, think about it as about "ether".
|
||||
Note that walkie-talkie, intercoms and headsets handle transmission using nonstandard way.
|
||||
procs:
|
||||
|
||||
add_object(obj/device as obj, var/new_frequency as num, var/filter as text|null = null)
|
||||
Adds listening object.
|
||||
parameters:
|
||||
device - device receiving signals, must have proc receive_signal (see description below).
|
||||
one device may listen several frequencies, but not same frequency twice.
|
||||
new_frequency - see possibly frequencies below;
|
||||
filter - thing for optimization. Optional, but recommended.
|
||||
All filters should be consolidated in this file, see defines later.
|
||||
Device without listening filter will receive all signals (on specified frequency).
|
||||
Device with filter will receive any signals sent without filter.
|
||||
Device with filter will not receive any signals sent with different filter.
|
||||
returns:
|
||||
Reference to frequency object.
|
||||
|
||||
remove_object (obj/device, old_frequency)
|
||||
Obliviously, after calling this proc, device will not receive any signals on old_frequency.
|
||||
Other frequencies will left unaffected.
|
||||
|
||||
return_frequency(var/frequency as num)
|
||||
returns:
|
||||
Reference to frequency object. Use it if you need to send and do not need to listen.
|
||||
|
||||
radio_frequency is a global object maintaining list of devices that listening specific frequency.
|
||||
procs:
|
||||
|
||||
post_signal(obj/source as obj|null, datum/signal/signal, var/filter as text|null = null, var/range as num|null = null)
|
||||
Sends signal to all devices that wants such signal.
|
||||
parameters:
|
||||
source - object, emitted signal. Usually, devices will not receive their own signals.
|
||||
signal - see description below.
|
||||
filter - described above.
|
||||
range - radius of regular byond's square circle on that z-level. null means everywhere, on all z-levels.
|
||||
|
||||
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.
|
||||
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.
|
||||
TRANSMISSION_WIRE is currently unused.
|
||||
receive_param - for TRANSMISSION_RADIO here comes frequency.
|
||||
|
||||
datum/signal
|
||||
vars:
|
||||
source
|
||||
an object that emitted signal. Used for debug and bearing.
|
||||
data
|
||||
list with transmitting data. Usual use pattern:
|
||||
data["msg"] = "hello world"
|
||||
encryption
|
||||
Some number symbolizing "encryption key".
|
||||
Note that game actually do not use any cryptography here.
|
||||
If receiving object don't know right key, it must ignore encrypted signal in its receive_signal.
|
||||
|
||||
*/
|
||||
|
||||
/*
|
||||
Frequency range: 1200 to 1600
|
||||
Radiochat range: 1441 to 1489 (most devices refuse to be tune to other frequency, even during mapmaking)
|
||||
|
||||
Radio:
|
||||
1459 - standard radio chat
|
||||
1351 - Science
|
||||
1353 - Command
|
||||
1355 - Medical
|
||||
1357 - Engineering
|
||||
1359 - Security
|
||||
1441 - death squad
|
||||
1443 - Confession Intercom
|
||||
1347 - Cargo techs
|
||||
|
||||
Devices:
|
||||
1451 - tracking implant
|
||||
1457 - RSD default
|
||||
|
||||
On the map:
|
||||
1311 for prison shuttle console (in fact, it is not used)
|
||||
1435 for status displays
|
||||
1437 for atmospherics/fire alerts
|
||||
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
|
||||
1445 for bot nav beacons
|
||||
1447 for mulebot, secbot and ed209 control
|
||||
1449 for airlock controls, electropack, magnets
|
||||
1451 for toxin lab access
|
||||
1453 for engineering access
|
||||
1455 for AI access
|
||||
*/
|
||||
|
||||
var/list/radiochannels = list(
|
||||
"Common" = 1459,
|
||||
"Science" = 1351,
|
||||
"Command" = 1353,
|
||||
"Medical" = 1355,
|
||||
"Engineering" = 1357,
|
||||
"Security" = 1359,
|
||||
"Response Team" = 1345,
|
||||
"Deathsquad" = 1341,
|
||||
"Syndicate" = 1213,
|
||||
"Supply" = 1347,
|
||||
)
|
||||
//depenging helpers
|
||||
var/list/DEPT_FREQS = list(1351, 1355, 1357, 1359, 1213, 1345, 1341, 1347)
|
||||
|
||||
// central command channels, i.e deathsquid & response teams
|
||||
var/list/CENT_FREQS = list(1345, 1341)
|
||||
|
||||
var/const/COMM_FREQ = 1353 //command, colored gold in chat window
|
||||
var/const/SYND_FREQ = 1213
|
||||
|
||||
// department channels
|
||||
var/const/SEC_FREQ = 1359
|
||||
var/const/ENG_FREQ = 1357
|
||||
var/const/SCI_FREQ = 1351
|
||||
var/const/MED_FREQ = 1355
|
||||
var/const/SUP_FREQ = 1347
|
||||
|
||||
#define TRANSMISSION_WIRE 0
|
||||
#define TRANSMISSION_RADIO 1
|
||||
|
||||
/* filters */
|
||||
//When devices register with the radio controller, they might register under a certain filter.
|
||||
//Other devices can then choose to send signals to only those devices that belong to a particular filter.
|
||||
//This is done for performance, so we don't send signals to lots of machines unnecessarily.
|
||||
|
||||
//This filter is special because devices belonging to default also recieve signals sent to any other filter.
|
||||
var/const/RADIO_DEFAULT = "radio_default"
|
||||
|
||||
var/const/RADIO_TO_AIRALARM = "radio_airalarm" //air alarms
|
||||
var/const/RADIO_FROM_AIRALARM = "radio_airalarm_rcvr" //devices interested in recieving signals from air alarms
|
||||
var/const/RADIO_CHAT = "radio_telecoms"
|
||||
var/const/RADIO_ATMOSIA = "radio_atmos"
|
||||
var/const/RADIO_NAVBEACONS = "radio_navbeacon"
|
||||
var/const/RADIO_AIRLOCK = "radio_airlock"
|
||||
var/const/RADIO_SECBOT = "radio_secbot"
|
||||
var/const/RADIO_MULEBOT = "radio_mulebot"
|
||||
var/const/RADIO_MAGNETS = "radio_magnet"
|
||||
|
||||
var/global/datum/controller/radio/radio_controller
|
||||
|
||||
/hook/startup/proc/createRadioController()
|
||||
radio_controller = new /datum/controller/radio()
|
||||
return 1
|
||||
|
||||
//callback used by objects to react to incoming radio signals
|
||||
/obj/proc/receive_signal(datum/signal/signal, receive_method, receive_param)
|
||||
return null
|
||||
|
||||
//The global radio controller
|
||||
/datum/controller/radio
|
||||
var/list/datum/radio_frequency/frequencies = list()
|
||||
|
||||
/datum/controller/radio/proc/add_object(obj/device as obj, var/new_frequency as num, var/filter = null as text|null)
|
||||
var/f_text = num2text(new_frequency)
|
||||
var/datum/radio_frequency/frequency = frequencies[f_text]
|
||||
|
||||
if(!frequency)
|
||||
frequency = new
|
||||
frequency.frequency = new_frequency
|
||||
frequencies[f_text] = frequency
|
||||
|
||||
frequency.add_listener(device, filter)
|
||||
return frequency
|
||||
|
||||
/datum/controller/radio/proc/remove_object(obj/device, old_frequency)
|
||||
var/f_text = num2text(old_frequency)
|
||||
var/datum/radio_frequency/frequency = frequencies[f_text]
|
||||
|
||||
if(frequency)
|
||||
frequency.remove_listener(device)
|
||||
|
||||
if(frequency.devices.len == 0)
|
||||
del(frequency)
|
||||
frequencies -= f_text
|
||||
|
||||
return 1
|
||||
|
||||
/datum/controller/radio/proc/return_frequency(var/new_frequency as num)
|
||||
var/f_text = num2text(new_frequency)
|
||||
var/datum/radio_frequency/frequency = frequencies[f_text]
|
||||
|
||||
if(!frequency)
|
||||
frequency = new
|
||||
frequency.frequency = new_frequency
|
||||
frequencies[f_text] = frequency
|
||||
|
||||
return frequency
|
||||
|
||||
/datum/radio_frequency
|
||||
var/frequency as num
|
||||
var/list/list/obj/devices = list()
|
||||
|
||||
/datum/radio_frequency/proc/post_signal(obj/source as obj|null, datum/signal/signal, var/filter = null as text|null, var/range = null as num|null)
|
||||
var/turf/start_point
|
||||
if(range)
|
||||
start_point = get_turf(source)
|
||||
if(!start_point)
|
||||
del(signal)
|
||||
return 0
|
||||
if (filter)
|
||||
send_to_filter(source, signal, filter, start_point, range)
|
||||
send_to_filter(source, signal, RADIO_DEFAULT, start_point, range)
|
||||
else
|
||||
//Broadcast the signal to everyone!
|
||||
for (var/next_filter in devices)
|
||||
send_to_filter(source, signal, next_filter, start_point, range)
|
||||
|
||||
//Sends a signal to all machines belonging to a given filter. Should be called by post_signal()
|
||||
/datum/radio_frequency/proc/send_to_filter(obj/source, datum/signal/signal, var/filter, var/turf/start_point = null, var/range = null)
|
||||
if (range && !start_point)
|
||||
return
|
||||
|
||||
for(var/obj/device in devices[filter])
|
||||
if(device == source)
|
||||
continue
|
||||
if(range)
|
||||
var/turf/end_point = get_turf(device)
|
||||
if(!end_point)
|
||||
continue
|
||||
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)
|
||||
|
||||
/datum/radio_frequency/proc/add_listener(obj/device as obj, var/filter as text|null)
|
||||
if (!filter)
|
||||
filter = RADIO_DEFAULT
|
||||
//log_admin("add_listener(device=[device],filter=[filter]) frequency=[frequency]")
|
||||
var/list/obj/devices_line = devices[filter]
|
||||
if (!devices_line)
|
||||
devices_line = new
|
||||
devices[filter] = devices_line
|
||||
devices_line+=device
|
||||
// var/list/obj/devices_line___ = devices[filter_str]
|
||||
// var/l = devices_line___.len
|
||||
//log_admin("DEBUG: devices_line.len=[devices_line.len]")
|
||||
//log_admin("DEBUG: devices(filter_str).len=[l]")
|
||||
|
||||
/datum/radio_frequency/proc/remove_listener(obj/device)
|
||||
for (var/devices_filter in devices)
|
||||
var/list/devices_line = devices[devices_filter]
|
||||
devices_line-=device
|
||||
while (null in devices_line)
|
||||
devices_line -= null
|
||||
if (devices_line.len==0)
|
||||
devices -= devices_filter
|
||||
del(devices_line)
|
||||
|
||||
/datum/signal
|
||||
var/obj/source
|
||||
|
||||
var/transmission_method = 0 //unused at the moment
|
||||
//0 = wire
|
||||
//1 = radio transmission
|
||||
//2 = subspace transmission
|
||||
|
||||
var/data = list()
|
||||
var/encryption
|
||||
|
||||
var/frequency = 0
|
||||
|
||||
/datum/signal/proc/copy_from(datum/signal/model)
|
||||
source = model.source
|
||||
transmission_method = model.transmission_method
|
||||
data = model.data
|
||||
encryption = model.encryption
|
||||
frequency = model.frequency
|
||||
|
||||
/datum/signal/proc/debug_print()
|
||||
if (source)
|
||||
. = "signal = {source = '[source]' ([source:x],[source:y],[source:z])\n"
|
||||
else
|
||||
. = "signal = {source = '[source]' ()\n"
|
||||
for (var/i in data)
|
||||
. += "data\[\"[i]\"\] = \"[data[i]]\"\n"
|
||||
if(islist(data[i]))
|
||||
var/list/L = data[i]
|
||||
for(var/t in L)
|
||||
. += "data\[\"[i]\"\] list has: [t]"
|
||||
@@ -98,6 +98,8 @@
|
||||
|
||||
//game_options.txt configs
|
||||
|
||||
var/atmos_machine_heat = 1.0
|
||||
|
||||
var/health_threshold_softcrit = 0
|
||||
var/health_threshold_crit = 0
|
||||
var/health_threshold_dead = -100
|
||||
@@ -112,6 +114,8 @@
|
||||
var/revival_cloning = 1
|
||||
var/revival_brain_life = -1
|
||||
|
||||
var/use_loyalty_implants = 0
|
||||
|
||||
//Used for modifying movement speed for mobs.
|
||||
//Unversal modifiers
|
||||
var/run_speed = 0
|
||||
@@ -521,10 +525,23 @@
|
||||
config.revival_cloning = value
|
||||
if("revival_brain_life")
|
||||
config.revival_brain_life = value
|
||||
if("organ_health_multiplier")
|
||||
config.organ_health_multiplier = value / 100
|
||||
if("organ_regeneration_multiplier")
|
||||
config.organ_regeneration_multiplier = value / 100
|
||||
if("bones_can_break")
|
||||
config.bones_can_break = value
|
||||
if("limbs_can_break")
|
||||
config.limbs_can_break = value
|
||||
|
||||
if("atmos_machine_heat")
|
||||
config.atmos_machine_heat = value
|
||||
|
||||
if("run_speed")
|
||||
config.run_speed = value
|
||||
if("walk_speed")
|
||||
config.walk_speed = value
|
||||
|
||||
if("human_delay")
|
||||
config.human_delay = value
|
||||
if("robot_delay")
|
||||
@@ -537,14 +554,11 @@
|
||||
config.slime_delay = value
|
||||
if("animal_delay")
|
||||
config.animal_delay = value
|
||||
if("organ_health_multiplier")
|
||||
config.organ_health_multiplier = value / 100
|
||||
if("organ_regeneration_multiplier")
|
||||
config.organ_regeneration_multiplier = value / 100
|
||||
if("bones_can_break")
|
||||
config.bones_can_break = value
|
||||
if("limbs_can_break")
|
||||
config.limbs_can_break = value
|
||||
|
||||
|
||||
if("use_loyalty_implants")
|
||||
config.use_loyalty_implants = 1
|
||||
|
||||
else
|
||||
log_misc("Unknown setting in configuration: '[name]'")
|
||||
|
||||
|
||||
@@ -16,6 +16,8 @@ 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 )
|
||||
if(lighting_controller != src)
|
||||
@@ -53,9 +55,19 @@ 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.tag = null
|
||||
A.related -= A
|
||||
active_areas -= A
|
||||
all_areas -= A
|
||||
changed_areas.Cut()
|
||||
|
||||
process_cost = (world.timeofday - started)
|
||||
|
||||
sleep(processing_interval)
|
||||
|
||||
@@ -109,17 +109,24 @@ datum/controller/game_controller/proc/setup_objects()
|
||||
var/obj/machinery/atmospherics/unary/vent_scrubber/T = U
|
||||
T.broadcast_status()
|
||||
|
||||
//Create the mining ore distribution map.
|
||||
//Create the mining ore distribution map.
|
||||
asteroid_ore_map = new /datum/ore_distribution()
|
||||
asteroid_ore_map.populate_distribution_map()
|
||||
|
||||
//Shitty hack to fix mining turf overlays, for some reason New() is not being called.
|
||||
for(var/turf/simulated/floor/plating/airless/asteroid/T in world)
|
||||
T.updateMineralOverlays()
|
||||
T.name = "asteroid"
|
||||
|
||||
//Set up spawn points.
|
||||
populate_spawn_points()
|
||||
|
||||
//Set up gear list.
|
||||
populate_gear_list()
|
||||
|
||||
//Set up roundstart seed list.
|
||||
populate_seed_list()
|
||||
|
||||
world << "\red \b Initializations complete."
|
||||
sleep(-1)
|
||||
|
||||
@@ -292,10 +299,16 @@ datum/controller/game_controller/proc/process_machines_power()
|
||||
var/area/A = active_areas[i]
|
||||
if(A.powerupdate && A.master == A)
|
||||
A.powerupdate -= 1
|
||||
for(var/area/SubArea in A.related)
|
||||
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)
|
||||
if(M)
|
||||
if(M.use_power)
|
||||
//check if the area has power for M's channel
|
||||
//this will keep stat updated in case the machine is moved from one area to another.
|
||||
M.power_change(A) //we've already made sure A is a master area, above.
|
||||
|
||||
if(!(M.stat & NOPOWER) && M.use_power)
|
||||
M.auto_use_power()
|
||||
|
||||
if(A.apc.len && A.master == A)
|
||||
@@ -342,7 +355,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)
|
||||
|
||||
@@ -48,7 +48,7 @@
|
||||
message_admins("Admin [key_name_admin(usr)] has restarted the [controller] controller.")
|
||||
return
|
||||
|
||||
/client/proc/debug_controller(controller in list("Master","Failsafe","Ticker","Lighting","Air","Jobs","Sun","Radio","Supply","Shuttles","Emergency Shuttle","Configuration","pAI", "Cameras", "Transfer Controller"))
|
||||
/client/proc/debug_controller(controller in list("Master","Failsafe","Ticker","Lighting","Air","Jobs","Sun","Radio","Supply","Shuttles","Emergency Shuttle","Configuration","pAI", "Cameras", "Transfer Controller", "Gas Data"))
|
||||
set category = "Debug"
|
||||
set name = "Debug Controller"
|
||||
set desc = "Debug the various periodic loop controllers for the game (be careful!)"
|
||||
@@ -100,5 +100,8 @@
|
||||
if("Transfer Controller")
|
||||
debug_variables(transfer_controller)
|
||||
feedback_add_details("admin_verb","DAutovoter")
|
||||
if("Gas Data")
|
||||
debug_variables(gas_data)
|
||||
feedback_add_details("admin_verv","DGasdata")
|
||||
message_admins("Admin [key_name_admin(usr)] is debugging the [controller] controller.")
|
||||
return
|
||||
|
||||
+12
-19
@@ -510,14 +510,9 @@ datum/mind
|
||||
I.Del()
|
||||
break
|
||||
H << "\blue <Font size =3><B>Your loyalty implant has been deactivated.</B></FONT>"
|
||||
if("add")
|
||||
var/obj/item/weapon/implant/loyalty/L = new/obj/item/weapon/implant/loyalty(H)
|
||||
L.imp_in = H
|
||||
L.implanted = 1
|
||||
var/datum/organ/external/affected = H.organs_by_name["head"]
|
||||
affected.implants += L
|
||||
L.part = affected
|
||||
|
||||
if("add")
|
||||
H.implant_loyalty(H, override = TRUE)
|
||||
H << "\red <Font size =3><B>You somehow have become the recepient of a loyalty transplant, and it just activated!</B></FONT>"
|
||||
if(src in ticker.mode.revolutionaries)
|
||||
special_role = null
|
||||
@@ -541,6 +536,8 @@ datum/mind
|
||||
special_role = null
|
||||
current << "\red <FONT size = 3><B>The nanobots in the loyalty implant remove all thoughts about being a traitor to Nanotrasen. Have a nice day!</B></FONT>"
|
||||
log_admin("[key_name_admin(usr)] has de-traitor'ed [current].")
|
||||
else
|
||||
|
||||
|
||||
else if (href_list["revolution"])
|
||||
current.hud_updateflag |= (1 << SPECIALROLE_HUD)
|
||||
@@ -567,7 +564,7 @@ datum/mind
|
||||
current << "\red <FONT size = 3><B>Revolution has been disappointed of your leader traits! You are a regular revolutionary now!</B></FONT>"
|
||||
else if(!(src in ticker.mode.revolutionaries))
|
||||
current << "\red <FONT size = 3> You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!</FONT>"
|
||||
current << "<font color=blue>Within the rules,</font> try to act as an opposing force to the crew. Further RP and try to make sure other players have </i>fun<i>! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! <b>Please remember all rules aside from those without explicit exceptions apply to antagonists.</i></b>"
|
||||
show_objectives(src)
|
||||
else
|
||||
return
|
||||
ticker.mode.revolutionaries += src
|
||||
@@ -580,7 +577,7 @@ datum/mind
|
||||
ticker.mode.revolutionaries -= src
|
||||
ticker.mode.update_rev_icons_removed(src)
|
||||
current << "\red <FONT size = 3><B>You have proved your devotion to revoltion! You are a head revolutionary now!</B></FONT>"
|
||||
current << "<font color=blue>Within the rules,</font> try to act as an opposing force to the crew. Further RP and try to make sure other players have </i>fun<i>! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! <b>Please remember all rules aside from those without explicit exceptions apply to antagonists.</i></b>"
|
||||
show_objectives(src)
|
||||
else if(!(src in ticker.mode.head_revolutionaries))
|
||||
current << "\blue You are a member of the revolutionaries' leadership now!"
|
||||
else
|
||||
@@ -659,11 +656,11 @@ datum/mind
|
||||
special_role = "Cultist"
|
||||
current << "<font color=\"purple\"><b><i>You catch a glimpse of the Realm of Nar-Sie, The Geometer of Blood. You now see how flimsy the world is, you see that it should be open to the knowledge of Nar-Sie.</b></i></font>"
|
||||
current << "<font color=\"purple\"><b><i>Assist your new compatriots in their dark dealings. Their goal is yours, and yours is theirs. You serve the Dark One above all else. Bring It back.</b></i></font>"
|
||||
current << "<font color=blue>Within the rules,</font> try to act as an opposing force to the crew. Further RP and try to make sure other players have </i>fun<i>! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! <b>Please remember all rules aside from those without explicit exceptions apply to antagonists.</i></b>"
|
||||
var/datum/game_mode/cult/cult = ticker.mode
|
||||
if (istype(cult))
|
||||
if(!config.objectives_disabled)
|
||||
cult.memorize_cult_objectives(src)
|
||||
show_objectives(src)
|
||||
log_admin("[key_name_admin(usr)] has cult'ed [current].")
|
||||
if("tome")
|
||||
var/mob/living/carbon/human/H = current
|
||||
@@ -704,7 +701,7 @@ datum/mind
|
||||
special_role = "Wizard"
|
||||
//ticker.mode.learn_basic_spells(current)
|
||||
current << "<B>\red You are the Space Wizard!</B>"
|
||||
current << "<font color=blue>Within the rules,</font> try to act as an opposing force to the crew. Further RP and try to make sure other players have </i>fun<i>! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! <b>Please remember all rules aside from those without explicit exceptions apply to antagonists.</i></b>"
|
||||
show_objectives(src)
|
||||
log_admin("[key_name_admin(usr)] has wizard'ed [current].")
|
||||
if("lair")
|
||||
current.loc = pick(wizardstart)
|
||||
@@ -735,8 +732,7 @@ datum/mind
|
||||
ticker.mode.grant_changeling_powers(current)
|
||||
special_role = "Changeling"
|
||||
current << "<B><font color='red'>Your powers are awoken. A flash of memory returns to us...we are a changeling!</font></B>"
|
||||
if(config.objectives_disabled)
|
||||
current << "<font color=blue>Within the rules,</font> try to act as an opposing force to the crew. Further RP and try to make sure other players have </i>fun<i>! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! <b>Please remember all rules aside from those without explicit exceptions apply to antagonists.</i></b>"
|
||||
show_objectives(src)
|
||||
log_admin("[key_name_admin(usr)] has changeling'ed [current].")
|
||||
if("autoobjectives")
|
||||
if(!config.objectives_disabled)
|
||||
@@ -777,10 +773,7 @@ datum/mind
|
||||
current.real_name = "[syndicate_name()] Operative #[ticker.mode.syndicates.len-1]"
|
||||
special_role = "Syndicate"
|
||||
current << "\blue You are a [syndicate_name()] agent!"
|
||||
if(config.objectives_disabled)
|
||||
current << "<font color=blue>Within the rules,</font> try to act as an opposing force to the crew. Further RP and try to make sure other players have </i>fun<i>! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! <b>Please remember all rules aside from those without explicit exceptions apply to antagonists.</i></b>"
|
||||
else
|
||||
ticker.mode.forge_syndicate_objectives(src)
|
||||
ticker.mode.forge_syndicate_objectives(src)
|
||||
ticker.mode.greet_syndicate(src)
|
||||
log_admin("[key_name_admin(usr)] has nuke op'ed [current].")
|
||||
if("lair")
|
||||
@@ -832,8 +825,8 @@ datum/mind
|
||||
special_role = "traitor"
|
||||
current << "<B>\red You are a traitor!</B>"
|
||||
log_admin("[key_name_admin(usr)] has traitor'ed [current].")
|
||||
if (config.objectives_disabled)
|
||||
current << "<i>You have been turned into an antagonist- <font color=blue>Within the rules,</font> try to act as an opposing force to the crew- This can be via corporate payoff, personal motives, or maybe just being a dick. Further RP and try to make sure other players have </i>fun<i>! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! <b>Please remember all rules aside from those without explicit exceptions apply to antagonist.</i></b>"
|
||||
show_objectives()
|
||||
|
||||
if(istype(current, /mob/living/silicon))
|
||||
var/mob/living/silicon/A = current
|
||||
call(/datum/game_mode/proc/add_law_zero)(A)
|
||||
|
||||
@@ -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
|
||||
|
||||
+39
-32
@@ -5,7 +5,7 @@
|
||||
//BIG NOTE: Don't add living things to crates, that's bad, it will break the shuttle.
|
||||
//NEW NOTE: Do NOT set the price of any crates below 7 points. Doing so allows infinite points.
|
||||
|
||||
var/list/all_supply_groups = list("Operations","Security","Hospitality","Engineering","Medical / Science","Hydroponics", "Supply", "Miscellaneous")
|
||||
var/list/all_supply_groups = list("Operations","Security","Hospitality","Engineering","Atmospherics","Medical","Science","Hydroponics", "Supply", "Miscellaneous")
|
||||
|
||||
/datum/supply_packs
|
||||
var/name = null
|
||||
@@ -149,7 +149,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
cost = 10
|
||||
containertype = /obj/structure/closet/crate/internals
|
||||
containername = "Internals crate"
|
||||
group = "Engineering"
|
||||
group = "Atmospherics"
|
||||
|
||||
/datum/supply_packs/evacuation
|
||||
name = "Emergency equipment"
|
||||
@@ -170,7 +170,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
cost = 35
|
||||
containertype = /obj/structure/closet/crate/internals
|
||||
containername = "Emergency crate"
|
||||
group = "Engineering"
|
||||
group = "Atmospherics"
|
||||
|
||||
/datum/supply_packs/inflatable
|
||||
name = "Inflatable barriers"
|
||||
@@ -180,7 +180,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
cost = 20
|
||||
containertype = /obj/structure/closet/crate
|
||||
containername = "Inflatable Barrier Crate"
|
||||
group = "Engineering"
|
||||
group = "Atmospherics"
|
||||
|
||||
/datum/supply_packs/janitor
|
||||
name = "Janitorial supplies"
|
||||
@@ -235,7 +235,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
/datum/supply_packs/cargotrain
|
||||
name = "Cargo Train Tug"
|
||||
contains = list(/obj/vehicle/train/cargo/engine)
|
||||
cost = 30
|
||||
cost = 45
|
||||
containertype = /obj/structure/largecrate
|
||||
containername = "Cargo Train Tug Crate"
|
||||
group = "Operations"
|
||||
@@ -243,7 +243,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
/datum/supply_packs/cargotrailer
|
||||
name = "Cargo Train Trolley"
|
||||
contains = list(/obj/vehicle/train/cargo/trolley)
|
||||
cost = 20
|
||||
cost = 15
|
||||
containertype = /obj/structure/largecrate
|
||||
containername = "Cargo Train Trolley Crate"
|
||||
group = "Operations"
|
||||
@@ -266,7 +266,10 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
/obj/item/weapon/minihoe,
|
||||
/obj/item/device/analyzer/plant_analyzer,
|
||||
/obj/item/clothing/gloves/botanic_leather,
|
||||
/obj/item/clothing/suit/apron) // Updated with new things
|
||||
/obj/item/clothing/suit/apron,
|
||||
/obj/item/weapon/minihoe,
|
||||
/obj/item/weapon/storage/box/botanydisk
|
||||
) // Updated with new things
|
||||
cost = 15
|
||||
containertype = /obj/structure/closet/crate/hydroponics
|
||||
containername = "Hydroponics crate"
|
||||
@@ -380,7 +383,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
cost = 10
|
||||
containertype = /obj/structure/closet/crate/medical
|
||||
containername = "Medical crate"
|
||||
group = "Medical / Science"
|
||||
group = "Medical"
|
||||
|
||||
/datum/supply_packs/virus
|
||||
name = "Virus sample crate"
|
||||
@@ -404,7 +407,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
containertype = "/obj/structure/closet/crate/secure"
|
||||
containername = "Virus sample crate"
|
||||
access = access_cmo
|
||||
group = "Medical / Science"
|
||||
group = "Science"
|
||||
|
||||
/datum/supply_packs/metal50
|
||||
name = "50 metal sheets"
|
||||
@@ -486,7 +489,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
cost = 16
|
||||
containertype = /obj/structure/largecrate
|
||||
containername = "coolant tank crate"
|
||||
group = "Medical / Science"
|
||||
group = "Science"
|
||||
|
||||
/datum/supply_packs/solar
|
||||
name = "Solar Pack crate"
|
||||
@@ -578,7 +581,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
containertype = /obj/structure/closet/crate/secure
|
||||
containername = "APLU \"Ripley\" Circuit Crate"
|
||||
access = access_robotics
|
||||
group = "Engineering"
|
||||
group = "Science"
|
||||
|
||||
/datum/supply_packs/mecha_odysseus
|
||||
name = "Circuit Crate (\"Odysseus\")"
|
||||
@@ -588,7 +591,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
containertype = /obj/structure/closet/crate/secure
|
||||
containername = "\"Odysseus\" Circuit Crate"
|
||||
access = access_robotics
|
||||
group = "Engineering"
|
||||
group = "Science"
|
||||
|
||||
|
||||
/datum/supply_packs/robotics
|
||||
@@ -627,7 +630,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
containertype = /obj/structure/closet/crate/secure/phoron
|
||||
containername = "Phoron assembly crate"
|
||||
access = access_tox_storage
|
||||
group = "Medical / Science"
|
||||
group = "Science"
|
||||
|
||||
/datum/supply_packs/weapons
|
||||
name = "Weapons crate"
|
||||
@@ -697,14 +700,6 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
access = access_armory
|
||||
group = "Security"
|
||||
|
||||
/datum/supply_packs/loyalty
|
||||
name = "Loyalty implant crate"
|
||||
contains = list (/obj/item/weapon/storage/lockbox/loyalty)
|
||||
cost = 60
|
||||
containertype = /obj/structure/closet/crate/secure
|
||||
containername = "Loyalty implant crate"
|
||||
access = access_armory
|
||||
group = "Security"
|
||||
|
||||
/datum/supply_packs/ballistic
|
||||
name = "Ballistic gear crate"
|
||||
@@ -741,6 +736,17 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
access = access_armory
|
||||
group = "Security"
|
||||
|
||||
/*
|
||||
/datum/supply_packs/loyalty
|
||||
name = "Loyalty implant crate"
|
||||
contains = list (/obj/item/weapon/storage/lockbox/loyalty)
|
||||
cost = 60
|
||||
containertype = /obj/structure/closet/crate/secure
|
||||
containername = "Loyalty implant crate"
|
||||
access = access_armory
|
||||
group = "Security"
|
||||
*/
|
||||
|
||||
/datum/supply_packs/expenergy
|
||||
name = "Experimental energy gear crate"
|
||||
contains = list(/obj/item/clothing/suit/armor/laserproof,
|
||||
@@ -845,6 +851,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
containername = "Arts and Crafts crate"
|
||||
group = "Operations"
|
||||
|
||||
|
||||
/datum/supply_packs/randomised/contraband
|
||||
num_contained = 5
|
||||
contains = list(/obj/item/seeds/bloodtomatoseed,
|
||||
@@ -893,7 +900,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
containertype = "/obj/structure/closet/crate/secure"
|
||||
containername = "Surgery crate"
|
||||
access = access_medical
|
||||
group = "Medical / Science"
|
||||
group = "Medical"
|
||||
|
||||
/datum/supply_packs/sterile
|
||||
name = "Sterile equipment crate"
|
||||
@@ -904,7 +911,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
cost = 15
|
||||
containertype = "/obj/structure/closet/crate"
|
||||
containername = "Sterile equipment crate"
|
||||
group = "Medical / Science"
|
||||
group = "Medical"
|
||||
|
||||
/datum/supply_packs/randomised/pizza
|
||||
num_contained = 5
|
||||
@@ -1202,7 +1209,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
containertype = /obj/structure/closet/crate/hydroponics
|
||||
containername = "Hydroponics tray crate"
|
||||
group = "Hydroponics"
|
||||
contains = list(/obj/machinery/hydroponics{anchored = 0})
|
||||
contains = list(/obj/machinery/portable_atmospherics/hydroponics{anchored = 0})
|
||||
access = access_hydroponics
|
||||
|
||||
/datum/supply_packs/canister_empty
|
||||
@@ -1211,14 +1218,14 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
containername = "Empty gas canister crate"
|
||||
containertype = /obj/structure/largecrate
|
||||
contains = list(/obj/machinery/portable_atmospherics/canister)
|
||||
group = "Engineering"
|
||||
group = "Atmospherics"
|
||||
|
||||
/datum/supply_packs/canister_air
|
||||
name = "Air canister"
|
||||
cost = 10
|
||||
containername = "Air canister crate"
|
||||
containertype = /obj/structure/largecrate
|
||||
group = "Engineering"
|
||||
group = "Atmospherics"
|
||||
contains = list(/obj/machinery/portable_atmospherics/canister/air)
|
||||
|
||||
/datum/supply_packs/canister_oxygen
|
||||
@@ -1226,7 +1233,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
cost = 15
|
||||
containername = "Oxygen canister crate"
|
||||
containertype = /obj/structure/largecrate
|
||||
group = "Engineering"
|
||||
group = "Atmospherics"
|
||||
contains = list(/obj/machinery/portable_atmospherics/canister/oxygen)
|
||||
|
||||
/datum/supply_packs/canister_nitrogen
|
||||
@@ -1234,7 +1241,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
cost = 10
|
||||
containername = "Nitrogen canister crate"
|
||||
containertype = /obj/structure/largecrate
|
||||
group = "Engineering"
|
||||
group = "Atmospherics"
|
||||
contains = list(/obj/machinery/portable_atmospherics/canister/nitrogen)
|
||||
|
||||
/datum/supply_packs/canister_phoron
|
||||
@@ -1243,7 +1250,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
containername = "Phoron gas canister crate"
|
||||
containertype = /obj/structure/closet/crate/secure/large
|
||||
access = access_atmospherics
|
||||
group = "Engineering"
|
||||
group = "Atmospherics"
|
||||
contains = list(/obj/machinery/portable_atmospherics/canister/phoron)
|
||||
|
||||
/datum/supply_packs/canister_sleeping_agent
|
||||
@@ -1252,7 +1259,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
containername = "N2O gas canister crate"
|
||||
containertype = /obj/structure/closet/crate/secure/large
|
||||
access = access_atmospherics
|
||||
group = "Engineering"
|
||||
group = "Atmospherics"
|
||||
contains = list(/obj/machinery/portable_atmospherics/canister/sleeping_agent)
|
||||
|
||||
/datum/supply_packs/canister_carbon_dioxide
|
||||
@@ -1261,7 +1268,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
containername = "CO2 canister crate"
|
||||
containertype = /obj/structure/closet/crate/secure/large
|
||||
access = access_atmospherics
|
||||
group = "Engineering"
|
||||
group = "Atmospherics"
|
||||
contains = list(/obj/machinery/portable_atmospherics/canister/carbon_dioxide)
|
||||
|
||||
/datum/supply_packs/pacman_parts
|
||||
@@ -1276,7 +1283,7 @@ var/list/all_supply_groups = list("Operations","Security","Hospitality","Enginee
|
||||
/obj/item/weapon/stock_parts/matter_bin,
|
||||
/obj/item/weapon/circuitboard/pacman)
|
||||
|
||||
/datum/supply_packs/pacman_parts
|
||||
/datum/supply_packs/super_pacman_parts
|
||||
name = "Super P.A.C.M.A.N. portable generator parts"
|
||||
cost = 55
|
||||
containername = "Super P.A.C.M.A.N. portable generator construction kit"
|
||||
|
||||
@@ -52,8 +52,10 @@
|
||||
icon_state = "soapnt"
|
||||
|
||||
/obj/item/weapon/soap/deluxe
|
||||
desc = "A deluxe Waffle Co. brand bar of soap. Smells of condoms."
|
||||
icon_state = "soapdeluxe"
|
||||
|
||||
/obj/item/weapon/soap/deluxe/New()
|
||||
desc = "A deluxe Waffle Co. brand bar of soap. Smells of [pick("lavender", "vanilla", "strawberry", "chocolate" ,"space")]."
|
||||
|
||||
/obj/item/weapon/soap/syndie
|
||||
desc = "An untrustworthy bar of soap. Smells of fear."
|
||||
@@ -162,7 +164,7 @@
|
||||
icon_state = "beartrap[armed]"
|
||||
user << "<span class='notice'>[src] is now [armed ? "armed" : "disarmed"]</span>"
|
||||
|
||||
/obj/item/weapon/legcuffs/beartrap/HasEntered(AM as mob|obj)
|
||||
/obj/item/weapon/legcuffs/beartrap/Crossed(AM as mob|obj)
|
||||
if(armed)
|
||||
if(ishuman(AM))
|
||||
if(isturf(src.loc))
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
/proc/captain_announce(var/text)
|
||||
world << "<h1 class='alert'>Priority Announcement</h1>"
|
||||
world << "<span class='alert'>[html_encode(text)]</span>"
|
||||
world << "<br>"
|
||||
|
||||
/proc/captain_announce(message as text, title = "Priority Announcement", announcer = "")
|
||||
world << "<h1 class='alert'>[html_encode(title)]</h1>"
|
||||
world << "<span class='alert'>[html_encode(message)]</span>"
|
||||
if(announcer)
|
||||
world << "<span class='alert'> -[html_encode(announcer)]</span>"
|
||||
world << "<br>"
|
||||
@@ -22,7 +22,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
var/poweralm = 1
|
||||
var/party = null
|
||||
level = null
|
||||
name = "Space"
|
||||
name = "Unknown"
|
||||
icon = 'icons/turf/areas.dmi'
|
||||
icon_state = "unknown"
|
||||
layer = 10
|
||||
@@ -35,6 +35,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
var/debug = 0
|
||||
var/powerupdate = 10 //We give everything 10 ticks to settle out it's power usage.
|
||||
var/requires_power = 1
|
||||
var/unlimited_power = 0
|
||||
var/always_unpowered = 0 //this gets overriden to 1 for space in area/New()
|
||||
|
||||
var/power_equip = 1
|
||||
@@ -54,6 +55,7 @@ NOTE: there are two lists of areas in the end of this file: centcom and station
|
||||
// var/list/lights // list of all lights on this area
|
||||
var/list/all_doors = list() //Added by Strumpetplaya - Alarm Change - Contains a list of doors adjacent to this area
|
||||
var/air_doors_activated = 0
|
||||
var/list/ambience = list('sound/ambience/ambigen1.ogg','sound/ambience/ambigen3.ogg','sound/ambience/ambigen4.ogg','sound/ambience/ambigen5.ogg','sound/ambience/ambigen6.ogg','sound/ambience/ambigen7.ogg','sound/ambience/ambigen8.ogg','sound/ambience/ambigen9.ogg','sound/ambience/ambigen10.ogg','sound/ambience/ambigen11.ogg','sound/ambience/ambigen12.ogg','sound/ambience/ambigen14.ogg')
|
||||
|
||||
/*Adding a wizard area teleport list because motherfucking lag -- Urist*/
|
||||
/*I am far too lazy to make it a proper list of areas so I'll just make it run the usual telepot routine at the start of the game*/
|
||||
@@ -90,9 +92,26 @@ var/list/ghostteleportlocs = list()
|
||||
return 1
|
||||
|
||||
/*-----------------------------------------------------------------------------*/
|
||||
/area/space
|
||||
name = "\improper Space"
|
||||
requires_power = 1
|
||||
always_unpowered = 1
|
||||
lighting_use_dynamic = 1
|
||||
power_light = 0
|
||||
power_equip = 0
|
||||
power_environ = 0
|
||||
ambience = list('sound/ambience/ambispace.ogg','sound/music/title2.ogg','sound/music/space.ogg','sound/music/main.ogg','sound/music/traitor.ogg')
|
||||
|
||||
/area/space/firealert()
|
||||
return
|
||||
|
||||
/area/space/readyalert()
|
||||
return
|
||||
|
||||
/area/space/partyalert()
|
||||
return
|
||||
/area/engine/
|
||||
|
||||
ambience = list('sound/ambience/ambisin1.ogg','sound/ambience/ambisin2.ogg','sound/ambience/ambisin3.ogg','sound/ambience/ambisin4.ogg')
|
||||
/area/turret_protected/
|
||||
|
||||
/area/arrival
|
||||
@@ -361,9 +380,10 @@ 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
|
||||
|
||||
/area/syndicate_mothership/control
|
||||
name = "\improper Syndicate Control Room"
|
||||
@@ -436,6 +456,7 @@ var/list/ghostteleportlocs = list()
|
||||
name = "\improper Syndicate Station"
|
||||
icon_state = "yellow"
|
||||
requires_power = 0
|
||||
unlimited_power = 1
|
||||
|
||||
/area/syndicate_station/start
|
||||
name = "\improper Syndicate Forward Operating Base"
|
||||
@@ -866,6 +887,7 @@ var/list/ghostteleportlocs = list()
|
||||
/area/chapel/main
|
||||
name = "\improper Chapel"
|
||||
icon_state = "chapel"
|
||||
ambience = list('sound/ambience/ambicha1.ogg','sound/ambience/ambicha2.ogg','sound/ambience/ambicha3.ogg','sound/ambience/ambicha4.ogg','sound/music/traitor.ogg')
|
||||
|
||||
/area/chapel/office
|
||||
name = "\improper Chapel Office"
|
||||
@@ -970,6 +992,10 @@ var/list/ghostteleportlocs = list()
|
||||
name = "\improper Engine Monitoring Room"
|
||||
icon_state = "engine_monitoring"
|
||||
|
||||
engine_waste
|
||||
name = "\improper Engine Waste Handling"
|
||||
icon_state = "engine_waste"
|
||||
|
||||
engineering_monitoring
|
||||
name = "\improper Engineering Monitoring Room"
|
||||
icon_state = "engine_monitoring"
|
||||
@@ -1022,7 +1048,8 @@ var/list/ghostteleportlocs = list()
|
||||
//Solars
|
||||
|
||||
/area/solar
|
||||
requires_power = 0
|
||||
requires_power = 1
|
||||
always_unpowered = 1
|
||||
luminosity = 1
|
||||
lighting_use_dynamic = 0
|
||||
|
||||
@@ -1052,7 +1079,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"
|
||||
@@ -1064,8 +1091,11 @@ 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"
|
||||
icon_state = "SolarcontrolA"
|
||||
|
||||
/area/assembly/chargebay
|
||||
name = "\improper Mech Bay"
|
||||
@@ -1102,6 +1132,7 @@ var/list/ghostteleportlocs = list()
|
||||
name = "\improper AI Satellite Teleporter Room"
|
||||
icon_state = "teleporter"
|
||||
music = "signal"
|
||||
ambience = list('sound/ambience/ambimalf.ogg')
|
||||
|
||||
//MedBay
|
||||
|
||||
@@ -1177,10 +1208,6 @@ var/list/ghostteleportlocs = list()
|
||||
name = "\improper Robotics"
|
||||
icon_state = "medresearch"
|
||||
|
||||
/area/medical/research
|
||||
name = "\improper Medical Research"
|
||||
icon_state = "medresearch"
|
||||
|
||||
/area/medical/virology
|
||||
name = "\improper Virology"
|
||||
icon_state = "virology"
|
||||
@@ -1192,6 +1219,7 @@ var/list/ghostteleportlocs = list()
|
||||
/area/medical/morgue
|
||||
name = "\improper Morgue"
|
||||
icon_state = "morgue"
|
||||
ambience = list('sound/ambience/ambimo1.ogg','sound/ambience/ambimo2.ogg','sound/music/main.ogg')
|
||||
|
||||
/area/medical/chemistry
|
||||
name = "\improper Chemistry"
|
||||
@@ -1378,12 +1406,11 @@ var/list/ghostteleportlocs = list()
|
||||
icon_state = "garden"
|
||||
|
||||
//rnd (Research and Development
|
||||
/area/rnd/research
|
||||
name = "\improper Research and Development"
|
||||
icon_state = "research"
|
||||
|
||||
/area/rnd/lab
|
||||
name = "\improper Research and Development"
|
||||
icon_state = "toxlab"
|
||||
|
||||
/area/rnd/hallway
|
||||
name = "\improper Research Lab"
|
||||
icon_state = "toxlab"
|
||||
|
||||
@@ -1692,10 +1719,12 @@ var/list/ghostteleportlocs = list()
|
||||
/area/turret_protected/ai_upload
|
||||
name = "\improper AI Upload Chamber"
|
||||
icon_state = "ai_upload"
|
||||
ambience = list('sound/ambience/ambimalf.ogg')
|
||||
|
||||
/area/turret_protected/ai_upload_foyer
|
||||
name = "AI Upload Access"
|
||||
icon_state = "ai_foyer"
|
||||
ambience = list('sound/ambience/ambimalf.ogg')
|
||||
|
||||
/area/turret_protected/ai_server_room
|
||||
name = "AI Server Room"
|
||||
@@ -1704,6 +1733,7 @@ var/list/ghostteleportlocs = list()
|
||||
/area/turret_protected/ai
|
||||
name = "\improper AI Chamber"
|
||||
icon_state = "ai_chamber"
|
||||
ambience = list('sound/ambience/ambimalf.ogg')
|
||||
|
||||
/area/turret_protected/ai_cyborg_station
|
||||
name = "\improper Cyborg Station"
|
||||
@@ -1774,6 +1804,8 @@ var/list/ghostteleportlocs = list()
|
||||
|
||||
|
||||
// Telecommunications Satellite
|
||||
/area/tcommsat/
|
||||
ambience = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
|
||||
|
||||
/area/tcommsat/entrance
|
||||
name = "\improper Telecoms Teleporter"
|
||||
@@ -1786,18 +1818,22 @@ var/list/ghostteleportlocs = list()
|
||||
/area/turret_protected/tcomsat
|
||||
name = "\improper Telecoms Satellite"
|
||||
icon_state = "tcomsatlob"
|
||||
ambience = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
|
||||
|
||||
/area/turret_protected/tcomfoyer
|
||||
name = "\improper Telecoms Foyer"
|
||||
icon_state = "tcomsatentrance"
|
||||
ambience = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
|
||||
|
||||
/area/turret_protected/tcomwest
|
||||
name = "\improper Telecommunications Satellite West Wing"
|
||||
icon_state = "tcomsatwest"
|
||||
ambience = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
|
||||
|
||||
/area/turret_protected/tcomeast
|
||||
name = "\improper Telecommunications Satellite East Wing"
|
||||
icon_state = "tcomsateast"
|
||||
ambience = list('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
|
||||
|
||||
/area/tcommsat/computer
|
||||
name = "\improper Telecoms Control Room"
|
||||
|
||||
+10
-44
@@ -16,16 +16,6 @@
|
||||
active_areas += src
|
||||
all_areas += src
|
||||
|
||||
if(type == /area) // override defaults for space. TODO: make space areas of type /area/space rather than /area
|
||||
requires_power = 1
|
||||
always_unpowered = 1
|
||||
lighting_use_dynamic = 1
|
||||
power_light = 0
|
||||
power_equip = 0
|
||||
power_environ = 0
|
||||
// lighting_state = 4
|
||||
//has_gravity = 0 // Space has gravity. Because.. because.
|
||||
|
||||
if(requires_power)
|
||||
luminosity = 0
|
||||
else
|
||||
@@ -71,18 +61,18 @@
|
||||
/area/proc/atmosalert(danger_level)
|
||||
// if(type==/area) //No atmos alarms in space
|
||||
// return 0 //redudant
|
||||
|
||||
|
||||
//Check all the alarms before lowering atmosalm. Raising is perfectly fine.
|
||||
for (var/area/RA in related)
|
||||
for (var/obj/machinery/alarm/AA in RA)
|
||||
if ( !(AA.stat & (NOPOWER|BROKEN)) && !AA.shorted)
|
||||
danger_level = max(danger_level, AA.danger_level)
|
||||
|
||||
|
||||
if(danger_level != atmosalm)
|
||||
if (danger_level < 1 && atmosalm >= 1)
|
||||
//closing the doors on red and opening on green provides a bit of hysteresis that will hopefully prevent fire doors from opening and closing repeatedly due to noise
|
||||
air_doors_open()
|
||||
|
||||
|
||||
if (danger_level < 2 && atmosalm >= 2)
|
||||
for(var/area/RA in related)
|
||||
for(var/obj/machinery/camera/C in RA)
|
||||
@@ -91,7 +81,7 @@
|
||||
aiPlayer.cancelAlarm("Atmosphere", src, src)
|
||||
for(var/obj/machinery/computer/station_alert/a in machines)
|
||||
a.cancelAlarm("Atmosphere", src, src)
|
||||
|
||||
|
||||
if (danger_level >= 2 && atmosalm < 2)
|
||||
var/list/cameras = list()
|
||||
for(var/area/RA in related)
|
||||
@@ -104,12 +94,12 @@
|
||||
for(var/obj/machinery/computer/station_alert/a in machines)
|
||||
a.triggerAlarm("Atmosphere", src, cameras, src)
|
||||
air_doors_close()
|
||||
|
||||
|
||||
atmosalm = danger_level
|
||||
for(var/area/RA in related)
|
||||
for (var/obj/machinery/alarm/AA in RA)
|
||||
AA.update_icon()
|
||||
|
||||
|
||||
return 1
|
||||
return 0
|
||||
|
||||
@@ -183,8 +173,6 @@
|
||||
a.cancelAlarm("Fire", src, src)
|
||||
|
||||
/area/proc/readyalert()
|
||||
if(name == "Space")
|
||||
return
|
||||
if(!eject)
|
||||
eject = 1
|
||||
updateicon()
|
||||
@@ -197,8 +185,6 @@
|
||||
return
|
||||
|
||||
/area/proc/partyalert()
|
||||
if(name == "Space") //no parties in space!!!
|
||||
return
|
||||
if (!( party ))
|
||||
party = 1
|
||||
updateicon()
|
||||
@@ -323,32 +309,12 @@
|
||||
L.client.ambience_playing = 1
|
||||
L << sound('sound/ambience/shipambience.ogg', repeat = 1, wait = 0, volume = 35, channel = 2)
|
||||
|
||||
if(prob(35))
|
||||
if(src.ambience.len && prob(35))
|
||||
sound = pick(ambience)
|
||||
|
||||
if(istype(src, /area/chapel))
|
||||
sound = pick('sound/ambience/ambicha1.ogg','sound/ambience/ambicha2.ogg','sound/ambience/ambicha3.ogg','sound/ambience/ambicha4.ogg','sound/music/traitor.ogg')
|
||||
else if(istype(src, /area/medical/morgue))
|
||||
sound = pick('sound/ambience/ambimo1.ogg','sound/ambience/ambimo2.ogg','sound/music/main.ogg')
|
||||
else if(type == /area)
|
||||
sound = pick('sound/ambience/ambispace.ogg','sound/music/title2.ogg','sound/music/space.ogg','sound/music/main.ogg','sound/music/traitor.ogg')
|
||||
else if(istype(src, /area/engine))
|
||||
sound = pick('sound/ambience/ambisin1.ogg','sound/ambience/ambisin2.ogg','sound/ambience/ambisin3.ogg','sound/ambience/ambisin4.ogg')
|
||||
else if(istype(src, /area/AIsattele) || istype(src, /area/turret_protected/ai) || istype(src, /area/turret_protected/ai_upload) || istype(src, /area/turret_protected/ai_upload_foyer))
|
||||
sound = pick('sound/ambience/ambimalf.ogg')
|
||||
else if(istype(src, /area/mine/explored) || istype(src, /area/mine/unexplored))
|
||||
sound = pick('sound/ambience/ambimine.ogg', 'sound/ambience/song_game.ogg')
|
||||
musVolume = 25
|
||||
else if(istype(src, /area/tcommsat) || istype(src, /area/turret_protected/tcomwest) || istype(src, /area/turret_protected/tcomeast) || istype(src, /area/turret_protected/tcomfoyer) || istype(src, /area/turret_protected/tcomsat))
|
||||
sound = pick('sound/ambience/ambisin2.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/signal.ogg', 'sound/ambience/ambigen10.ogg')
|
||||
else
|
||||
sound = pick('sound/ambience/ambigen1.ogg','sound/ambience/ambigen3.ogg','sound/ambience/ambigen4.ogg','sound/ambience/ambigen5.ogg','sound/ambience/ambigen6.ogg','sound/ambience/ambigen7.ogg','sound/ambience/ambigen8.ogg','sound/ambience/ambigen9.ogg','sound/ambience/ambigen10.ogg','sound/ambience/ambigen11.ogg','sound/ambience/ambigen12.ogg','sound/ambience/ambigen14.ogg')
|
||||
|
||||
if(!L.client.played)
|
||||
if(world.time > L.client.played + 600)
|
||||
L << sound(sound, repeat = 0, wait = 0, volume = musVolume, channel = 1)
|
||||
L.client.played = 1
|
||||
spawn(600) //ewww - this is very very bad
|
||||
if(L.&& L.client)
|
||||
L.client.played = 0
|
||||
L.client.played = world.time
|
||||
|
||||
/area/proc/gravitychange(var/gravitystate = 0, var/area/A)
|
||||
|
||||
|
||||
@@ -70,9 +70,6 @@
|
||||
/atom/proc/CheckExit()
|
||||
return 1
|
||||
|
||||
/atom/proc/HasEntered(atom/movable/AM as mob|obj)
|
||||
return
|
||||
|
||||
/atom/proc/HasProximity(atom/movable/AM as mob|obj)
|
||||
return
|
||||
|
||||
|
||||
@@ -276,15 +276,15 @@
|
||||
del(src)
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/power_change()
|
||||
..()
|
||||
if(stat & BROKEN)
|
||||
icon_state = "broken"
|
||||
else if(powered())
|
||||
icon_state = initial(icon_state)
|
||||
stat &= ~NOPOWER
|
||||
else
|
||||
spawn(rand(0, 15))
|
||||
src.icon_state = "c_unpowered"
|
||||
stat |= NOPOWER
|
||||
if (stat & NOPOWER)
|
||||
spawn(rand(0, 15))
|
||||
src.icon_state = "c_unpowered"
|
||||
else
|
||||
icon_state = initial(icon_state)
|
||||
|
||||
/obj/machinery/computer/scan_consolenew/New()
|
||||
..()
|
||||
@@ -345,7 +345,7 @@
|
||||
*
|
||||
* @return nothing
|
||||
*/
|
||||
/obj/machinery/computer/scan_consolenew/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null)
|
||||
/obj/machinery/computer/scan_consolenew/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
|
||||
|
||||
if(user == connected.occupant || user.stat)
|
||||
return
|
||||
@@ -425,7 +425,7 @@
|
||||
data["beakerVolume"] += R.volume
|
||||
|
||||
// update the ui if it exists, returns null if no ui is passed/found
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data)
|
||||
ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
|
||||
if (!ui)
|
||||
// the ui does not exist, so we'll create a new() one
|
||||
// for a list of parameters and their descriptions see the code docs in \code\modules\nano\nanoui.dm
|
||||
|
||||
@@ -136,14 +136,9 @@
|
||||
newtraitor << "<B>You are now a traitor.</B>"
|
||||
newtraitor.mind.special_role = "traitor"
|
||||
newtraitor.hud_updateflag |= 1 << SPECIALROLE_HUD
|
||||
var/obj_count = 1
|
||||
newtraitor << "\blue Your current objectives:"
|
||||
if(!config.objectives_disabled)
|
||||
for(var/datum/objective/objective in newtraitor.mind.objectives)
|
||||
newtraitor << "<B>Objective #[obj_count]</B>: [objective.explanation_text]"
|
||||
obj_count++
|
||||
else
|
||||
newtraitor << "<i>You have been selected this round as an antagonist- <font color=blue>Within the rules,</font> try to act as an opposing force to the crew- This can be via corporate payoff, personal motives, or maybe just being a dick. Further RP and try to make sure other players have </i>fun<i>! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! <b>Please remember all rules aside from those without explicit exceptions apply to antagonist.</i></b>"
|
||||
newtraitor << "<i>You have been selected this round as an antagonist!</i>"
|
||||
show_objectives(newtraitor.mind)
|
||||
|
||||
//else
|
||||
//message_admins("No new traitor being added.")
|
||||
//else
|
||||
@@ -194,14 +189,9 @@
|
||||
traitors += character.mind
|
||||
character << "\red <B>You are the traitor.</B>"
|
||||
character.mind.special_role = "traitor"
|
||||
if (config.objectives_disabled)
|
||||
character << "<i>You have been selected this round as an antagonist- <font color=blue>Within the rules,</font> try to act as an opposing force to the crew- This can be via corporate payoff, personal motives, or maybe just being a dick. Further RP and try to make sure other players have </i>fun<i>! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! <b>Please remember all rules aside from those without explicit exceptions apply to antagonist.</i></b>"
|
||||
else
|
||||
var/obj_count = 1
|
||||
character << "\blue Your current objectives:"
|
||||
for(var/datum/objective/objective in character.mind.objectives)
|
||||
character << "<B>Objective #[obj_count]</B>: [objective.explanation_text]"
|
||||
obj_count++
|
||||
character << "<i>You have been selected this round as an antagonist</i>!"
|
||||
show_objectives(character.mind)
|
||||
|
||||
//else
|
||||
//message_admins("New traitor roll failed. No new traitor.")
|
||||
//else
|
||||
|
||||
@@ -0,0 +1,449 @@
|
||||
/*
|
||||
* This roundtype is a replacement for the meteor round on upstream BS12 - players
|
||||
* expressed the desire for quick, chaotic and violent rounds, preferrably without
|
||||
* dependancy on other players.
|
||||
* I wanted to call it clusterfuck, but I figure that's a bit too overt. Think of
|
||||
* the children.
|
||||
* ~ Zuhayr
|
||||
*/
|
||||
|
||||
/datum/game_mode/calamity
|
||||
name = "calamity"
|
||||
config_tag = "calamity"
|
||||
required_players = 1
|
||||
votable = 0 //Remove after testing.
|
||||
|
||||
uplink_welcome = "Syndicate Uplink Console:"
|
||||
uplink_uses = 10
|
||||
|
||||
//Possible roundstart antag types.
|
||||
var/list/atypes = list("syndi","ling","tater","wiz","ninja","vox","slug","cult")
|
||||
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/const/waittime_l = 600
|
||||
var/const/waittime_h = 1800
|
||||
|
||||
/datum/game_mode/calamity/announce()
|
||||
world << "<B>The current game mode is - Calamity!</B>"
|
||||
world << "<B>This must be a Thursday. You never could get the hang of Thursdays...</B>"
|
||||
|
||||
/datum/game_mode/calamity/can_start()
|
||||
|
||||
if(!..())
|
||||
return 0
|
||||
|
||||
var/antag_count = player_list.len/antag_type_ratio
|
||||
|
||||
if(!antag_count)
|
||||
return 1
|
||||
|
||||
for(var/i=0;i<antag_count;i++)
|
||||
|
||||
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.
|
||||
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
|
||||
|
||||
log_debug("Calamity: selected [atype] (possible candidates: [candidates.len])")
|
||||
chosen_atypes += atype
|
||||
|
||||
for(var/j=0;j<max_antags;j++)
|
||||
var/datum/mind/chosen_candidate = pick(candidates)
|
||||
//Traitors and lings spawn THEN have roles applied; hence we don't set assigned_role here.
|
||||
if(atype != "tater" && atype != "ling" && atype != "cult")
|
||||
chosen_candidate.assigned_role = "MODE"
|
||||
chosen_candidate.special_role = atype
|
||||
chosen_candidates += chosen_candidate
|
||||
|
||||
if(atypes.len - i <= 0) break //Not enough valid types left to populate the remaining antag slots.
|
||||
|
||||
return 1
|
||||
|
||||
/datum/game_mode/calamity/post_setup()
|
||||
|
||||
if(chosen_atypes)
|
||||
for(var/atype in chosen_atypes)
|
||||
var/list/candidates = list()
|
||||
|
||||
for(var/datum/mind/player in chosen_candidates)
|
||||
if(player.special_role == atype)
|
||||
candidates += player
|
||||
chosen_candidates -= player
|
||||
|
||||
if(!candidates || !candidates.len)
|
||||
log_debug("No candidates for [atype].")
|
||||
continue
|
||||
|
||||
log_debug("Calamity: spawning [atype].")
|
||||
|
||||
for(var/datum/mind/player in candidates)
|
||||
player.special_role = get_candidate_role_text(atype)
|
||||
|
||||
switch(atype)
|
||||
if("syndi")
|
||||
spawn_syndicate(candidates)
|
||||
if("ling")
|
||||
spawn_changelings(candidates)
|
||||
if("tater")
|
||||
spawn_traitors(candidates)
|
||||
if("wiz")
|
||||
spawn_cabal(candidates)
|
||||
if("ninja")
|
||||
spawn_ninja(candidates)
|
||||
if("vox")
|
||||
spawn_vox_raiders(candidates)
|
||||
if("slug")
|
||||
spawn_borers(candidates)
|
||||
if("cult")
|
||||
spawn_cultists(candidates)
|
||||
|
||||
/datum/game_mode/calamity/declare_completion()
|
||||
|
||||
var/text = "<FONT size = 3><B>This terrible, terrible day has finally ended!</B></FONT><BR/>"
|
||||
|
||||
//Group antag objective completion.
|
||||
for(var/list/L in list(src.raiders, src.syndicates, src.cult, src.wizards))
|
||||
|
||||
if(L.len)
|
||||
var/datum/mind/M = L[1]
|
||||
text = "<BR/><FONT size = 2><B>The [M.special_role][L.len == 1 ? " was" : "s were"]:</B></FONT>"
|
||||
|
||||
for(var/datum/mind/P in L)
|
||||
text += "<br>[P.key] was [P.name] ("
|
||||
if(P.current)
|
||||
if(P.current.stat == DEAD)
|
||||
text += "died"
|
||||
else
|
||||
text += "survived"
|
||||
if(P.current.real_name != P.name)
|
||||
text += " as [P.current.real_name]"
|
||||
else
|
||||
text += "body destroyed"
|
||||
text += ")"
|
||||
|
||||
if(M.objectives.len)
|
||||
text += "<BR/><FONT size = 2>Their objectives were:<FONT>"
|
||||
var/num = 1
|
||||
for(var/datum/objective/O in M.objectives)
|
||||
text += "<BR/><B>Objective [num]:</B> [O.explanation_text]"
|
||||
num++
|
||||
|
||||
//Single antag objective completion.
|
||||
for(var/list/L in list(src.changelings, src.ninjas, src.borers, src.traitors))
|
||||
|
||||
if(L.len)
|
||||
var/datum/mind/M = L[1]
|
||||
text = "<BR/><FONT size = 2><B>The [M.special_role][L.len == 1 ? " was" : "s were"]:</B></FONT>"
|
||||
for(var/datum/mind/P in L)
|
||||
var/num = 1
|
||||
text += "<BR/><FONT size = 2>[P.key] was [P.name].<FONT>"
|
||||
if(P.objectives.len)
|
||||
for(var/datum/objective/O in P.objectives)
|
||||
text += "<BR/><B>Objective [num]:</B> [O.explanation_text]"
|
||||
num++
|
||||
..()
|
||||
return 1
|
||||
|
||||
//Converts chosen atype to an actual role string.
|
||||
/datum/game_mode/calamity/proc/get_candidate_role_text(var/role)
|
||||
|
||||
var/role_text
|
||||
|
||||
switch(role)
|
||||
if("syndi")
|
||||
role_text = "Syndicate Operative"
|
||||
if("ling")
|
||||
role_text = "Changeling"
|
||||
if("tater")
|
||||
role_text = "Traitor"
|
||||
if("wiz")
|
||||
role_text = "Cabalist"
|
||||
if("ninja")
|
||||
role_text = "Ninja"
|
||||
if("vox")
|
||||
role_text = "Vox Raider"
|
||||
if("slug")
|
||||
role_text = "Cortical Borer"
|
||||
if("cult")
|
||||
role_text = "Cultist"
|
||||
|
||||
return role_text
|
||||
|
||||
//Grabs candidate lists for various atypes.
|
||||
/datum/game_mode/calamity/proc/get_role_candidates(var/role)
|
||||
|
||||
var/list/possible_antags = list()
|
||||
switch(role)
|
||||
if("syndi")
|
||||
possible_antags = get_players_for_role(BE_OPERATIVE)
|
||||
if("ling")
|
||||
possible_antags = get_players_for_role(BE_CHANGELING)
|
||||
if("tater")
|
||||
possible_antags = get_players_for_role(BE_TRAITOR)
|
||||
if("wiz")
|
||||
possible_antags = get_players_for_role(BE_WIZARD)
|
||||
if("ninja")
|
||||
possible_antags = get_players_for_role(BE_NINJA)
|
||||
if("vox")
|
||||
possible_antags = get_players_for_role(BE_RAIDER)
|
||||
if("slug")
|
||||
possible_antags = get_players_for_role(BE_ALIEN)
|
||||
if("cult")
|
||||
possible_antags = get_players_for_role(BE_CULTIST)
|
||||
|
||||
var/list/filtered_antags = list()
|
||||
if(possible_antags)
|
||||
for(var/datum/mind/candidate in possible_antags)
|
||||
if(!(candidate in already_assigned_candidates))
|
||||
filtered_antags |= candidate
|
||||
already_assigned_candidates |= candidate
|
||||
|
||||
if(filtered_antags && islist(filtered_antags))
|
||||
return filtered_antags
|
||||
else
|
||||
return list(filtered_antags)
|
||||
|
||||
//Spawning procs for the various antag types.
|
||||
//A LOT OF THE FOLLOWING IS COPYPASTED FROM OTHER MODES AND NEEDS
|
||||
//TO BE FIXED UP. NINJA, NUKE AND CULT IN PARTICULAR ARE FUCKING AWFUL. ~ Z
|
||||
/datum/game_mode/calamity/proc/spawn_syndicate(var/list/candidates)
|
||||
|
||||
var/obj/effect/landmark/uplinklocker = locate("landmark*Syndicate-Uplink")
|
||||
var/obj/effect/landmark/nuke_spawn = locate("landmark*Nuclear-Bomb")
|
||||
|
||||
var/nuke_code = "[rand(10000, 99999)]"
|
||||
var/leader_selected = 0
|
||||
var/spawnpos = 1
|
||||
|
||||
for(var/datum/mind/player in candidates)
|
||||
|
||||
syndicates += player
|
||||
|
||||
if(spawnpos > synd_spawn.len)
|
||||
spawnpos = 1
|
||||
player.current.loc = synd_spawn[spawnpos]
|
||||
|
||||
player.current.real_name = "[syndicate_name()] Operative"
|
||||
spawn(0)
|
||||
NukeNameAssign(player)
|
||||
|
||||
forge_syndicate_objectives(player)
|
||||
greet_syndicate(player)
|
||||
equip_syndicate(player.current)
|
||||
|
||||
if(!leader_selected)
|
||||
prepare_syndicate_leader(player, nuke_code)
|
||||
leader_selected = 1
|
||||
|
||||
spawnpos++
|
||||
update_synd_icons_added(player)
|
||||
|
||||
update_all_synd_icons()
|
||||
|
||||
if(uplinklocker)
|
||||
new /obj/structure/closet/syndicate/nuclear(uplinklocker.loc)
|
||||
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
|
||||
|
||||
/datum/game_mode/calamity/proc/spawn_changelings(var/list/candidates)
|
||||
|
||||
for(var/datum/mind/player in candidates)
|
||||
|
||||
changelings += player
|
||||
grant_changeling_powers(player.current)
|
||||
player.special_role = "Changeling"
|
||||
|
||||
if(!config.objectives_disabled)
|
||||
player.objectives += new /datum/objective/escape()
|
||||
player.objectives += new /datum/objective/survive()
|
||||
|
||||
show_objectives(player)
|
||||
greet_changeling(player)
|
||||
|
||||
/datum/game_mode/calamity/proc/spawn_traitors(var/list/candidates)
|
||||
|
||||
for(var/datum/mind/player in candidates)
|
||||
traitors += player
|
||||
|
||||
if(!config.objectives_disabled)
|
||||
player.objectives += new /datum/objective/escape()
|
||||
player.objectives += new /datum/objective/survive()
|
||||
|
||||
show_objectives(player)
|
||||
|
||||
finalize_traitor(player)
|
||||
greet_traitor(player)
|
||||
|
||||
/datum/game_mode/calamity/proc/spawn_cabal(var/list/candidates)
|
||||
|
||||
for(var/datum/mind/player in candidates)
|
||||
wizards += player
|
||||
|
||||
if(!config.objectives_disabled)
|
||||
player.objectives += new /datum/objective/escape()
|
||||
player.objectives += new /datum/objective/survive()
|
||||
|
||||
show_objectives(player)
|
||||
|
||||
player.current.loc = pick(wizardstart)
|
||||
|
||||
equip_wizard(player.current)
|
||||
name_wizard(player.current)
|
||||
greet_wizard(player)
|
||||
|
||||
/datum/game_mode/calamity/proc/spawn_ninja(var/list/candidates)
|
||||
|
||||
//I hate that this is necessary. ~Z
|
||||
for(var/obj/effect/landmark/L in landmarks_list)
|
||||
if(L.name == "carpspawn")
|
||||
ninjastart.Add(L)
|
||||
|
||||
for(var/datum/mind/player in candidates)
|
||||
ninjas += player
|
||||
|
||||
player.current << browse(null, "window=playersetup")
|
||||
player.current = create_space_ninja(pick(ninjastart))
|
||||
player.current.ckey = player.key
|
||||
|
||||
if(player.current && !(istype(player.current,/mob/living/carbon/human))) return 0
|
||||
|
||||
//Ninja intro crawl goes here.
|
||||
|
||||
if(!config.objectives_disabled)
|
||||
player.objectives += new /datum/objective/ninja_highlander()
|
||||
player.objectives += new /datum/objective/survive()
|
||||
|
||||
show_objectives(player)
|
||||
|
||||
//Ninja objective announcement goes here.
|
||||
|
||||
//Set ninja internals.
|
||||
var/mob/living/carbon/human/N = player.current
|
||||
N.internal = N.s_store
|
||||
N.internals.icon_state = "internal1"
|
||||
if(N.wear_suit && istype(N.wear_suit,/obj/item/clothing/suit/space/space_ninja))
|
||||
var/obj/item/clothing/suit/space/space_ninja/S = N.wear_suit
|
||||
S:randomize_param()
|
||||
|
||||
/datum/game_mode/calamity/proc/spawn_vox_raiders(var/list/candidates)
|
||||
|
||||
//Create objectives.
|
||||
var/list/raid_objectives = forge_vox_objectives()
|
||||
|
||||
//Create raiders.
|
||||
for(var/datum/mind/player in candidates)
|
||||
raiders += player
|
||||
|
||||
//Place them on the shuttle.
|
||||
var/index = 1
|
||||
if(index > raider_spawn.len)
|
||||
index = 1
|
||||
player.current.loc = raider_spawn[index]
|
||||
index++
|
||||
|
||||
if(!config.objectives_disabled)
|
||||
player.objectives = raid_objectives
|
||||
|
||||
//Equip them.
|
||||
create_vox(player)
|
||||
greet_vox(player)
|
||||
|
||||
player.current << "<b><font color='red'>Your crew is transporting cortical stacks and critical resources back to the Shoal.\
|
||||
No delay or concession can be tolerated. Even putting holes in the station pales in comparison to failure.</b></font>"
|
||||
|
||||
spawn (rand(waittime_l, waittime_h))
|
||||
send_intercept()
|
||||
..()
|
||||
|
||||
/datum/game_mode/calamity/proc/spawn_borers(var/list/candidates)
|
||||
|
||||
var/list/possible_hosts = list()
|
||||
for(var/mob/living/carbon/human/H in mob_list)
|
||||
if(!(H.species.flags & IS_SYNTHETIC))
|
||||
possible_hosts += H
|
||||
|
||||
for(var/datum/mind/player in candidates)
|
||||
|
||||
if(!possible_hosts || possible_hosts.len)
|
||||
break
|
||||
|
||||
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)
|
||||
|
||||
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
|
||||
|
||||
var/datum/organ/external/head = target_host.get_organ("head")
|
||||
head.implants += B
|
||||
|
||||
player.current << "\blue <b>You are a cortical borer!</b> 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 <b>say</b>, to other borers with <b>say ;</b>, 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()
|
||||
|
||||
show_objectives(player)
|
||||
|
||||
/datum/game_mode/calamity/proc/spawn_cultists(var/list/candidates)
|
||||
|
||||
//Prune the list.
|
||||
var/list/jobs_to_skip = list("Chaplain","AI", "Cyborg", "Lawyer", "Head of Security", "Captain")
|
||||
if(config.protect_roles_from_antagonist)
|
||||
jobs_to_skip += list("Security Officer", "Warden", "Detective")
|
||||
|
||||
//Make cult objectives.
|
||||
var/cult_objectives = list()
|
||||
cult_objectives += new /datum/objective/cult_summon()
|
||||
|
||||
//Actually spawn cultists.
|
||||
for(var/datum/mind/player in candidates)
|
||||
|
||||
for(var/job in jobs_to_skip)
|
||||
if(player.assigned_role == job)
|
||||
continue
|
||||
|
||||
cult += player
|
||||
equip_cultist(player.current)
|
||||
grant_runeword(player.current)
|
||||
update_cult_icons_added(player)
|
||||
player.current << "\blue <b>You are a member of the cult!<b> Your dark masters have sent you forth to serve their vile will."
|
||||
player.current << "\red <b>This station sails above a weeping tear in the Cosmos. Bring the Geometer of Blood forth.</b>"
|
||||
|
||||
if(!config.objectives_disabled)
|
||||
|
||||
for(var/datum/objective/O in cult_objectives)
|
||||
player.objectives += O
|
||||
|
||||
player.objectives += new /datum/objective/escape()
|
||||
player.objectives += new /datum/objective/survive()
|
||||
|
||||
show_objectives(player)
|
||||
player.special_role = "Cultist"
|
||||
@@ -125,23 +125,13 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
|
||||
changeling.current << "<B>\red You are a changeling!</B>"
|
||||
changeling.current << "<b>\red Use say \":g message\" to communicate with your fellow changelings. Remember: you get all of their absorbed DNA if you absorb them.</b>"
|
||||
|
||||
if(config.objectives_disabled)
|
||||
changeling.current << "<font color=blue>Within the rules,</font> try to act as an opposing force to the crew. Further RP and try to make sure other players have </i>fun<i>! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! <b>Please remember all rules aside from those without explicit exceptions apply to antagonists.</i></b>"
|
||||
|
||||
if (!config.objectives_disabled)
|
||||
changeling.current << "<B>You must complete the following tasks:</B>"
|
||||
show_objectives(changeling)
|
||||
|
||||
if (changeling.current.mind)
|
||||
if (changeling.current.mind.assigned_role == "Clown")
|
||||
changeling.current << "You have evolved beyond your clownish nature, allowing you to wield weapons without harming yourself."
|
||||
changeling.current.mutations.Remove(CLUMSY)
|
||||
|
||||
if (!config.objectives_disabled)
|
||||
var/obj_count = 1
|
||||
for(var/datum/objective/objective in changeling.objectives)
|
||||
changeling.current << "<B>Objective #[obj_count]</B>: [objective.explanation_text]"
|
||||
obj_count++
|
||||
return
|
||||
|
||||
/*/datum/game_mode/changeling/check_finished()
|
||||
var/changelings_alive = 0
|
||||
|
||||
@@ -100,8 +100,7 @@
|
||||
cult_mind.current << "\blue You are a member of the cult!"
|
||||
if(!config.objectives_disabled)
|
||||
memorize_cult_objectives(cult_mind)
|
||||
else
|
||||
cult_mind.current << "<font color=blue>Within the rules,</font> try to act as an opposing force to the crew. Further RP and try to make sure other players have </i>fun<i>! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! <b>Please remember all rules aside from those without explicit exceptions apply to antagonists.</i></b>"
|
||||
show_objectives(cult_mind)
|
||||
cult_mind.special_role = "Cultist"
|
||||
|
||||
spawn (rand(waittime_l, waittime_h))
|
||||
|
||||
@@ -35,6 +35,7 @@
|
||||
desc = "A hood worn by the followers of Nar-Sie."
|
||||
flags_inv = HIDEFACE
|
||||
flags = FPRINT|TABLEPASS|HEADCOVERSEYES
|
||||
body_parts_covered = HEAD|EYES
|
||||
armor = list(melee = 30, bullet = 10, laser = 5,energy = 5, bomb = 0, bio = 0, rad = 0)
|
||||
cold_protection = HEAD
|
||||
min_cold_protection_temperature = SPACE_HELMET_MIN_COLD_PROTECTION_TEMPERATURE
|
||||
@@ -68,6 +69,7 @@
|
||||
desc = "A helm worn by the followers of Nar-Sie."
|
||||
flags_inv = HIDEFACE
|
||||
flags = FPRINT|TABLEPASS|HEADCOVERSEYES|HEADCOVERSMOUTH|BLOCKHAIR
|
||||
body_parts_covered = HEAD|FACE|EYES
|
||||
armor = list(melee = 30, bullet = 30, laser = 30,energy = 20, bomb = 0, bio = 0, rad = 0)
|
||||
siemens_coefficient = 0
|
||||
|
||||
@@ -77,7 +79,7 @@
|
||||
icon_state = "magusred"
|
||||
item_state = "magusred"
|
||||
flags = FPRINT | TABLEPASS
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|FEET|ARMS|HANDS
|
||||
allowed = list(/obj/item/weapon/book/tome,/obj/item/weapon/melee/cultblade)
|
||||
armor = list(melee = 50, bullet = 30, laser = 50,energy = 20, bomb = 25, bio = 10, rad = 0)
|
||||
flags_inv = HIDEGLOVES|HIDESHOES|HIDEJUMPSUIT
|
||||
@@ -91,6 +93,7 @@
|
||||
armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30)
|
||||
siemens_coefficient = 0
|
||||
|
||||
|
||||
/obj/item/clothing/suit/space/cult
|
||||
name = "cult armour"
|
||||
icon_state = "cult_armour"
|
||||
@@ -100,4 +103,5 @@
|
||||
allowed = list(/obj/item/weapon/book/tome,/obj/item/weapon/melee/cultblade,/obj/item/weapon/tank/emergency_oxygen,/obj/item/device/suit_cooling_unit)
|
||||
slowdown = 1
|
||||
armor = list(melee = 60, bullet = 50, laser = 30,energy = 15, bomb = 30, bio = 30, rad = 30)
|
||||
siemens_coefficient = 0
|
||||
siemens_coefficient = 0
|
||||
body_parts_covered = UPPER_TORSO|LOWER_TORSO|LEGS|ARMS|HANDS
|
||||
@@ -1,57 +1,57 @@
|
||||
/obj/structure/cult
|
||||
density = 1
|
||||
anchored = 1
|
||||
icon = 'icons/obj/cult.dmi'
|
||||
|
||||
/obj/structure/cult/talisman
|
||||
name = "Altar"
|
||||
desc = "A bloodstained altar dedicated to Nar-Sie"
|
||||
icon_state = "talismanaltar"
|
||||
|
||||
|
||||
/obj/structure/cult/forge
|
||||
name = "Daemon forge"
|
||||
desc = "A forge used in crafting the unholy weapons used by the armies of Nar-Sie"
|
||||
icon_state = "forge"
|
||||
|
||||
/obj/structure/cult/pylon
|
||||
name = "Pylon"
|
||||
desc = "A floating crystal that hums with an unearthly energy"
|
||||
icon_state = "pylon"
|
||||
luminosity = 5
|
||||
|
||||
|
||||
/obj/structure/cult/tome
|
||||
name = "Desk"
|
||||
desc = "A desk covered in arcane manuscripts and tomes in unknown languages. Looking at the text makes your skin crawl"
|
||||
icon_state = "tomealtar"
|
||||
// luminosity = 5
|
||||
|
||||
//sprites for this no longer exist -Pete
|
||||
//(they were stolen from another game anyway)
|
||||
/*
|
||||
/obj/structure/cult/pillar
|
||||
name = "Pillar"
|
||||
desc = "This should not exist"
|
||||
icon_state = "pillar"
|
||||
icon = 'magic_pillar.dmi'
|
||||
*/
|
||||
|
||||
/obj/effect/gateway
|
||||
name = "gateway"
|
||||
desc = "You're pretty sure that abyss is staring back"
|
||||
icon = 'icons/obj/cult.dmi'
|
||||
icon_state = "hole"
|
||||
density = 1
|
||||
unacidable = 1
|
||||
anchored = 1.0
|
||||
|
||||
/obj/effect/gateway/Bumped(mob/M as mob|obj)
|
||||
spawn(0)
|
||||
return
|
||||
return
|
||||
|
||||
/obj/effect/gateway/HasEntered(AM as mob|obj)
|
||||
spawn(0)
|
||||
return
|
||||
/obj/structure/cult
|
||||
density = 1
|
||||
anchored = 1
|
||||
icon = 'icons/obj/cult.dmi'
|
||||
|
||||
/obj/structure/cult/talisman
|
||||
name = "Altar"
|
||||
desc = "A bloodstained altar dedicated to Nar-Sie"
|
||||
icon_state = "talismanaltar"
|
||||
|
||||
|
||||
/obj/structure/cult/forge
|
||||
name = "Daemon forge"
|
||||
desc = "A forge used in crafting the unholy weapons used by the armies of Nar-Sie"
|
||||
icon_state = "forge"
|
||||
|
||||
/obj/structure/cult/pylon
|
||||
name = "Pylon"
|
||||
desc = "A floating crystal that hums with an unearthly energy"
|
||||
icon_state = "pylon"
|
||||
luminosity = 5
|
||||
|
||||
|
||||
/obj/structure/cult/tome
|
||||
name = "Desk"
|
||||
desc = "A desk covered in arcane manuscripts and tomes in unknown languages. Looking at the text makes your skin crawl"
|
||||
icon_state = "tomealtar"
|
||||
// luminosity = 5
|
||||
|
||||
//sprites for this no longer exist -Pete
|
||||
//(they were stolen from another game anyway)
|
||||
/*
|
||||
/obj/structure/cult/pillar
|
||||
name = "Pillar"
|
||||
desc = "This should not exist"
|
||||
icon_state = "pillar"
|
||||
icon = 'magic_pillar.dmi'
|
||||
*/
|
||||
|
||||
/obj/effect/gateway
|
||||
name = "gateway"
|
||||
desc = "You're pretty sure that abyss is staring back"
|
||||
icon = 'icons/obj/cult.dmi'
|
||||
icon_state = "hole"
|
||||
density = 1
|
||||
unacidable = 1
|
||||
anchored = 1.0
|
||||
|
||||
/obj/effect/gateway/Bumped(mob/M as mob|obj)
|
||||
spawn(0)
|
||||
return
|
||||
return
|
||||
|
||||
/obj/effect/gateway/Crossed(AM as mob|obj)
|
||||
spawn(0)
|
||||
return
|
||||
return
|
||||
@@ -71,7 +71,7 @@
|
||||
world << sound('sound/AI/commandreport.ogg')
|
||||
|
||||
// add an extra law to the AI to make sure it cooperates with the heads
|
||||
var/extra_law = "Crew authorized to know of pathogen [virus_name]'s existence are: Heads of command, any crew member with loyalty implant. Do not allow unauthorized personnel to gain knowledge of [virus_name]. Aid authorized personnel in quarantining and neutrlizing the outbreak. This law overrides all other laws."
|
||||
var/extra_law = "Crew authorized to know of pathogen [virus_name]'s existence are: Heads of command. Do not allow unauthorized personnel to gain knowledge of [virus_name]. Aid authorized personnel in quarantining and neutrlizing the outbreak. This law overrides all other laws."
|
||||
for(var/mob/living/silicon/ai/M in world)
|
||||
M.add_ion_law(extra_law)
|
||||
M << "\red " + extra_law
|
||||
|
||||
@@ -59,5 +59,6 @@
|
||||
desc = "A crappy paper hat that you are REQUIRED to wear."
|
||||
flags_inv = 0
|
||||
flags = FPRINT|TABLEPASS
|
||||
body_parts_covered = 0
|
||||
armor = list(melee = 0, bullet = 0, laser = 0,energy = 0, bomb = 0, bio = 0, rad = 0)
|
||||
|
||||
|
||||
@@ -315,24 +315,15 @@ ________________________________________________________________________________
|
||||
var/datum/gas_mixture/environment = T.return_air()
|
||||
|
||||
var/pressure = environment.return_pressure()
|
||||
var/total_moles = environment.total_moles()
|
||||
var/total_moles = environment.total_moles
|
||||
|
||||
dat += "Air Pressure: [round(pressure,0.1)] kPa"
|
||||
|
||||
if (total_moles)
|
||||
var/o2_level = environment.oxygen/total_moles
|
||||
var/n2_level = environment.nitrogen/total_moles
|
||||
var/co2_level = environment.carbon_dioxide/total_moles
|
||||
var/phoron_level = environment.phoron/total_moles
|
||||
var/unknown_level = 1-(o2_level+n2_level+co2_level+phoron_level)
|
||||
dat += "<ul>"
|
||||
dat += "<li>Nitrogen: [round(n2_level*100)]%</li>"
|
||||
dat += "<li>Oxygen: [round(o2_level*100)]%</li>"
|
||||
dat += "<li>Carbon Dioxide: [round(co2_level*100)]%</li>"
|
||||
dat += "<li>Phoron: [round(phoron_level*100)]%</li>"
|
||||
for(var/g in environment.gas)
|
||||
dat += "<li>[gas_data.name[g]]: [round((environment.gas[g] / total_moles) * 100)]%</li>"
|
||||
dat += "</ul>"
|
||||
if(unknown_level > 0.01)
|
||||
dat += "OTHER: [round(unknown_level)]%<br>"
|
||||
|
||||
dat += "Temperature: [round(environment.temperature-T0C)]°C"
|
||||
if(2)
|
||||
@@ -1040,8 +1031,7 @@ ________________________________________________________________________________
|
||||
drain = rand(G.mindrain,G.maxdrain)
|
||||
var/drained = 0
|
||||
if(PN&&do_after(U,10))
|
||||
drained = min(drain, PN.avail)
|
||||
PN.newload += drained
|
||||
drained = PN.draw_power(drain)
|
||||
if(drained < drain)//if no power on net, drain apcs
|
||||
for(var/obj/machinery/power/terminal/T in PN.nodes)
|
||||
if(istype(T.master, /obj/machinery/power/apc))
|
||||
@@ -1092,8 +1082,7 @@ ________________________________________________________________________________
|
||||
drain = (round((rand(G.mindrain,G.maxdrain))/2))
|
||||
var/drained = 0
|
||||
if(PN&&do_after(U,10))
|
||||
drained = min(drain, PN.avail)
|
||||
PN.newload += drained
|
||||
drained = PN.draw_power(drain)
|
||||
if(drained < drain)//if no power on net, drain apcs
|
||||
for(var/obj/machinery/power/terminal/T in PN.nodes)
|
||||
if(istype(T.master, /obj/machinery/power/apc))
|
||||
|
||||
@@ -4,8 +4,12 @@
|
||||
command_alert("Abnormal activity detected in [station_name()]'s powernet. As a precautionary measure, the station's power will be shut off for an indeterminate duration.", "Critical Power Failure")
|
||||
for(var/mob/M in player_list)
|
||||
M << sound('sound/AI/poweroff.ogg')
|
||||
|
||||
var/list/skipped_areas = list(/area/turret_protected/ai)
|
||||
|
||||
for(var/obj/machinery/power/smes/S in world)
|
||||
if(istype(get_area(S), /area/turret_protected) || S.z != 1)
|
||||
var/area/current_area = get_area(S)
|
||||
if(current_area.type in skipped_areas || S.z != 1)
|
||||
continue
|
||||
S.last_charge = S.charge
|
||||
S.last_output = S.output
|
||||
@@ -16,43 +20,14 @@
|
||||
S.updateicon()
|
||||
S.power_change()
|
||||
|
||||
var/list/skipped_areas = list(/area/engine/engineering, /area/turret_protected/ai)
|
||||
|
||||
for(var/area/A in world)
|
||||
if( !A.requires_power || A.always_unpowered )
|
||||
continue
|
||||
|
||||
var/skip = 0
|
||||
for(var/area_type in skipped_areas)
|
||||
if(istype(A,area_type))
|
||||
skip = 1
|
||||
break
|
||||
if(A.contents)
|
||||
for(var/atom/AT in A.contents)
|
||||
if(AT.z != 1) //Only check one, it's enough.
|
||||
skip = 1
|
||||
break
|
||||
if(skip) continue
|
||||
A.power_light = 0
|
||||
A.power_equip = 0
|
||||
A.power_environ = 0
|
||||
A.power_change()
|
||||
|
||||
|
||||
for(var/obj/machinery/power/apc/C in world)
|
||||
if(C.cell && C.z == 1)
|
||||
var/area/A = get_area(C)
|
||||
|
||||
var/skip = 0
|
||||
for(var/area_type in skipped_areas)
|
||||
if(istype(A,area_type))
|
||||
skip = 1
|
||||
break
|
||||
if(skip) continue
|
||||
|
||||
C.cell.charge = 0
|
||||
|
||||
/proc/power_restore(var/announce = 1)
|
||||
|
||||
var/list/skipped_areas = list(/area/turret_protected/ai)
|
||||
|
||||
if(announce)
|
||||
command_alert("Power has been restored to [station_name()]. We apologize for the inconvenience.", "Power Systems Nominal")
|
||||
for(var/mob/M in player_list)
|
||||
@@ -61,19 +36,14 @@
|
||||
if(C.cell && C.z == 1)
|
||||
C.cell.charge = C.cell.maxcharge
|
||||
for(var/obj/machinery/power/smes/S in world)
|
||||
if(istype(get_area(S), /area/turret_protected) || S.z != 1)
|
||||
var/area/current_area = get_area(S)
|
||||
if(current_area.type in skipped_areas || S.z != 1)
|
||||
continue
|
||||
S.charge = S.last_charge
|
||||
S.output = S.last_output
|
||||
S.online = S.last_online
|
||||
S.updateicon()
|
||||
S.power_change()
|
||||
for(var/area/A in world)
|
||||
if(A.name != "Space" && A.name != "Engine Walls" && A.name != "Chemical Lab Test Chamber" && A.name != "space" && A.name != "Escape Shuttle" && A.name != "Arrival Area" && A.name != "Arrival Shuttle" && A.name != "start area" && A.name != "Engine Combustion Chamber")
|
||||
A.power_light = 1
|
||||
A.power_equip = 1
|
||||
A.power_environ = 1
|
||||
A.power_change()
|
||||
|
||||
/proc/power_restore_quick(var/announce = 1)
|
||||
|
||||
|
||||
@@ -375,12 +375,7 @@ Malf AIs/silicons aren't added. Monkeys aren't added. Messes with objective comp
|
||||
var/directive = generate_ninja_directive(side)
|
||||
new_ninja << "\blue \nYou are an elite mercenary assassin of the Spider Clan, [new_ninja.real_name]. The dreaded \red <B>SPACE NINJA</B>!\blue You have a variety of abilities at your disposal, thanks to your nano-enhanced cyber armor. Remember your training (initialize your suit by right clicking on it)! \nYour current directive is: \red <B>[directive]</B>"
|
||||
new_ninja.mind.store_memory("<B>Directive:</B> \red [directive]<br>")
|
||||
|
||||
var/obj_count = 1
|
||||
new_ninja << "\blue Your current objectives:"
|
||||
for(var/datum/objective/objective in ninja_mind.objectives)
|
||||
new_ninja << "<B>Objective #[obj_count]</B>: [objective.explanation_text]"
|
||||
obj_count++
|
||||
show_objectives(new_ninja.mind)
|
||||
|
||||
sent_ninja_to_station = 1//And we're done.
|
||||
return new_ninja//Return the ninja in case we need to reference them later.
|
||||
|
||||
@@ -1,247 +1,3 @@
|
||||
// SPACE VINES (Note that this code is very similar to Biomass code)
|
||||
/obj/effect/spacevine
|
||||
name = "space vines"
|
||||
desc = "An extremely expansionistic species of vine."
|
||||
icon = 'icons/effects/spacevines.dmi'
|
||||
icon_state = "Light1"
|
||||
anchored = 1
|
||||
density = 0
|
||||
layer = 5
|
||||
pass_flags = PASSTABLE | PASSGRILLE
|
||||
var/energy = 0
|
||||
var/obj/effect/spacevine_controller/master = null
|
||||
var/mob/living/buckled_mob
|
||||
|
||||
New()
|
||||
return
|
||||
|
||||
Del()
|
||||
if(master)
|
||||
master.vines -= src
|
||||
master.growth_queue -= src
|
||||
..()
|
||||
|
||||
|
||||
/obj/effect/spacevine/attackby(obj/item/weapon/W as obj, mob/user as mob)
|
||||
if (!W || !user || !W.type) return
|
||||
switch(W.type)
|
||||
if(/obj/item/weapon/circular_saw) del src
|
||||
if(/obj/item/weapon/kitchen/utensil/knife) del src
|
||||
if(/obj/item/weapon/scalpel) del src
|
||||
if(/obj/item/weapon/twohanded/fireaxe) del src
|
||||
if(/obj/item/weapon/hatchet) del src
|
||||
if(/obj/item/weapon/melee/energy) del src
|
||||
|
||||
//less effective weapons
|
||||
if(/obj/item/weapon/wirecutters)
|
||||
if(prob(25)) del src
|
||||
if(/obj/item/weapon/shard)
|
||||
if(prob(25)) del src
|
||||
|
||||
else //weapons with subtypes
|
||||
if(istype(W, /obj/item/weapon/melee/energy/sword)) del src
|
||||
else if(istype(W, /obj/item/weapon/weldingtool))
|
||||
var/obj/item/weapon/weldingtool/WT = W
|
||||
if(WT.remove_fuel(0, user)) del src
|
||||
else
|
||||
manual_unbuckle(user)
|
||||
return
|
||||
//Plant-b-gone damage is handled in its entry in chemistry-reagents.dm
|
||||
..()
|
||||
|
||||
|
||||
/obj/effect/spacevine/attack_hand(mob/user as mob)
|
||||
manual_unbuckle(user)
|
||||
|
||||
|
||||
/obj/effect/spacevine/attack_paw(mob/user as mob)
|
||||
manual_unbuckle(user)
|
||||
|
||||
/obj/effect/spacevine/proc/unbuckle()
|
||||
if(buckled_mob)
|
||||
if(buckled_mob.buckled == src) //this is probably unneccesary, but it doesn't hurt
|
||||
buckled_mob.buckled = null
|
||||
buckled_mob.anchored = initial(buckled_mob.anchored)
|
||||
buckled_mob.update_canmove()
|
||||
buckled_mob = null
|
||||
return
|
||||
|
||||
/obj/effect/spacevine/proc/manual_unbuckle(mob/user as mob)
|
||||
if(buckled_mob)
|
||||
if(prob(50))
|
||||
if(buckled_mob.buckled == src)
|
||||
if(buckled_mob != user)
|
||||
buckled_mob.visible_message(\
|
||||
"<span class='notice'>[user.name] frees [buckled_mob.name] from the vines.</span>",\
|
||||
"<span class='notice'>[user.name] frees you from the vines.</span>",\
|
||||
"<span class='warning'>You hear shredding and ripping.</span>")
|
||||
else
|
||||
buckled_mob.visible_message(\
|
||||
"<span class='notice'>[buckled_mob.name] struggles free of the vines.</span>",\
|
||||
"<span class='notice'>You untangle the vines from around yourself.</span>",\
|
||||
"<span class='warning'>You hear shredding and ripping.</span>")
|
||||
unbuckle()
|
||||
else
|
||||
var/text = pick("rips","tears","pulls")
|
||||
user.visible_message(\
|
||||
"<span class='notice'>[user.name] [text] at the vines.</span>",\
|
||||
"<span class='notice'>You [text] at the vines.</span>",\
|
||||
"<span class='warning'>You hear shredding and ripping.</span>")
|
||||
return
|
||||
|
||||
/obj/effect/spacevine_controller
|
||||
var/list/obj/effect/spacevine/vines = list()
|
||||
var/list/growth_queue = list()
|
||||
var/reached_collapse_size
|
||||
var/reached_slowdown_size
|
||||
//What this does is that instead of having the grow minimum of 1, required to start growing, the minimum will be 0,
|
||||
//meaning if you get the spacevines' size to something less than 20 plots, it won't grow anymore.
|
||||
|
||||
New()
|
||||
if(!istype(src.loc,/turf/simulated/floor))
|
||||
del(src)
|
||||
|
||||
spawn_spacevine_piece(src.loc)
|
||||
processing_objects.Add(src)
|
||||
|
||||
Del()
|
||||
processing_objects.Remove(src)
|
||||
..()
|
||||
|
||||
proc/spawn_spacevine_piece(var/turf/location)
|
||||
var/obj/effect/spacevine/SV = new(location)
|
||||
growth_queue += SV
|
||||
vines += SV
|
||||
SV.master = src
|
||||
|
||||
process()
|
||||
if(!vines)
|
||||
del(src) //space vines exterminated. Remove the controller
|
||||
return
|
||||
if(!growth_queue)
|
||||
del(src) //Sanity check
|
||||
return
|
||||
if(vines.len >= 250 && !reached_collapse_size)
|
||||
reached_collapse_size = 1
|
||||
if(vines.len >= 30 && !reached_slowdown_size )
|
||||
reached_slowdown_size = 1
|
||||
|
||||
var/length = 0
|
||||
if(reached_collapse_size)
|
||||
length = 0
|
||||
else if(reached_slowdown_size)
|
||||
if(prob(25))
|
||||
length = 1
|
||||
else
|
||||
length = 0
|
||||
else
|
||||
length = 1
|
||||
length = min( 30 , max( length , vines.len / 5 ) )
|
||||
var/i = 0
|
||||
var/list/obj/effect/spacevine/queue_end = list()
|
||||
|
||||
for( var/obj/effect/spacevine/SV in growth_queue )
|
||||
i++
|
||||
queue_end += SV
|
||||
growth_queue -= SV
|
||||
if(SV.energy < 2) //If tile isn't fully grown
|
||||
if(prob(20))
|
||||
SV.grow()
|
||||
else //If tile is fully grown
|
||||
SV.buckle_mob()
|
||||
|
||||
//if(prob(25))
|
||||
SV.spread()
|
||||
if(i >= length)
|
||||
break
|
||||
|
||||
growth_queue = growth_queue + queue_end
|
||||
//sleep(5)
|
||||
//src.process()
|
||||
|
||||
/obj/effect/spacevine/proc/grow()
|
||||
if(!energy)
|
||||
src.icon_state = pick("Med1", "Med2", "Med3")
|
||||
energy = 1
|
||||
src.opacity = 1
|
||||
layer = 5
|
||||
else
|
||||
src.icon_state = pick("Hvy1", "Hvy2", "Hvy3")
|
||||
energy = 2
|
||||
|
||||
/obj/effect/spacevine/proc/buckle_mob()
|
||||
if(!buckled_mob && prob(25))
|
||||
for(var/mob/living/carbon/V in src.loc)
|
||||
if((V.stat != DEAD) && (V.buckled != src)) //if mob not dead or captured
|
||||
V.buckled = src
|
||||
V.loc = src.loc
|
||||
V.update_canmove()
|
||||
src.buckled_mob = V
|
||||
V << "<span class='danger'>The vines [pick("wind", "tangle", "tighten")] around you!</span>"
|
||||
break //only capture one mob at a time.
|
||||
|
||||
/obj/effect/spacevine/proc/spread()
|
||||
var/direction = pick(cardinal)
|
||||
var/step = get_step(src,direction)
|
||||
if(istype(step,/turf/simulated/floor))
|
||||
var/turf/simulated/floor/F = step
|
||||
if(!locate(/obj/effect/spacevine,F))
|
||||
if(F.Enter(src))
|
||||
if(master)
|
||||
master.spawn_spacevine_piece( F )
|
||||
|
||||
/*
|
||||
/obj/effect/spacevine/proc/Life()
|
||||
if (!src) return
|
||||
var/Vspread
|
||||
if (prob(50)) Vspread = locate(src.x + rand(-1,1),src.y,src.z)
|
||||
else Vspread = locate(src.x,src.y + rand(-1, 1),src.z)
|
||||
var/dogrowth = 1
|
||||
if (!istype(Vspread, /turf/simulated/floor)) dogrowth = 0
|
||||
for(var/obj/O in Vspread)
|
||||
if (istype(O, /obj/structure/window) || istype(O, /obj/effect/forcefield) || istype(O, /obj/effect/blob) || istype(O, /obj/effect/alien/weeds) || istype(O, /obj/effect/spacevine)) dogrowth = 0
|
||||
if (istype(O, /obj/machinery/door/))
|
||||
if(O:p_open == 0 && prob(50)) O:open()
|
||||
else dogrowth = 0
|
||||
if (dogrowth == 1)
|
||||
var/obj/effect/spacevine/B = new /obj/effect/spacevine(Vspread)
|
||||
B.icon_state = pick("vine-light1", "vine-light2", "vine-light3")
|
||||
spawn(20)
|
||||
if(B)
|
||||
B.Life()
|
||||
src.growth += 1
|
||||
if (src.growth == 10)
|
||||
src.name = "Thick Space Kudzu"
|
||||
src.icon_state = pick("vine-med1", "vine-med2", "vine-med3")
|
||||
src.opacity = 1
|
||||
src.waittime = 80
|
||||
if (src.growth == 20)
|
||||
src.name = "Dense Space Kudzu"
|
||||
src.icon_state = pick("vine-hvy1", "vine-hvy2", "vine-hvy3")
|
||||
src.density = 1
|
||||
spawn(src.waittime)
|
||||
if (src.growth < 20) src.Life()
|
||||
|
||||
*/
|
||||
|
||||
/obj/effect/spacevine/ex_act(severity)
|
||||
switch(severity)
|
||||
if(1.0)
|
||||
del(src)
|
||||
return
|
||||
if(2.0)
|
||||
if (prob(90))
|
||||
del(src)
|
||||
return
|
||||
if(3.0)
|
||||
if (prob(50))
|
||||
del(src)
|
||||
return
|
||||
return
|
||||
|
||||
/obj/effect/spacevine/fire_act(null, temp, volume) //hotspots kill vines
|
||||
del src
|
||||
|
||||
//Carn: Spacevines random event.
|
||||
/proc/spacevine_infestation()
|
||||
|
||||
@@ -256,5 +12,5 @@
|
||||
|
||||
if(turfs.len) //Pick a turf to spawn at if we can
|
||||
var/turf/simulated/floor/T = pick(turfs)
|
||||
new/obj/effect/spacevine_controller(T) //spawn a controller at turf
|
||||
new/obj/effect/plant_controller(T) //spawn a controller at turf
|
||||
message_admins("\blue Event: Spacevines spawned at [T.loc] ([T.x],[T.y],[T.z])")
|
||||
|
||||
@@ -481,3 +481,28 @@ proc/get_nt_opposed()
|
||||
dudes += man
|
||||
if(dudes.len == 0) return null
|
||||
return pick(dudes)
|
||||
|
||||
//Announces objectives/generic antag text.
|
||||
/proc/show_generic_antag_text(var/datum/mind/player)
|
||||
if(player.current)
|
||||
player.current << \
|
||||
"You are an antagonist! <font color=blue>Within the rules,</font> \
|
||||
try to act as an opposing force to the crew. Further RP and try to make sure \
|
||||
other players have <i>fun</i>! If you are confused or at a loss, always adminhelp, \
|
||||
and before taking extreme actions, please try to also contact the administration! \
|
||||
Think through your actions and make the roleplay immersive! <b>Please remember all \
|
||||
rules aside from those without explicit exceptions apply to antagonists.</b>"
|
||||
|
||||
/proc/show_objectives(var/datum/mind/player)
|
||||
|
||||
if(!player || !player.current) return
|
||||
|
||||
if(config.objectives_disabled)
|
||||
show_generic_antag_text(player)
|
||||
return
|
||||
|
||||
var/obj_count = 1
|
||||
player.current << "\blue Your current objectives:"
|
||||
for(var/datum/objective/objective in player.objectives)
|
||||
player.current << "<B>Objective #[obj_count]</B>: [objective.explanation_text]"
|
||||
obj_count++
|
||||
@@ -297,6 +297,7 @@ var/global/datum/controller/gameticker/ticker
|
||||
captainless=0
|
||||
if(player.mind.assigned_role != "MODE")
|
||||
job_master.EquipRank(player, player.mind.assigned_role, 0)
|
||||
UpdateFactionList(player)
|
||||
EquipCustomItems(player)
|
||||
if(captainless)
|
||||
for(var/mob/M in player_list)
|
||||
|
||||
@@ -2,8 +2,12 @@
|
||||
VOX HEIST ROUNDTYPE
|
||||
*/
|
||||
|
||||
var/global/list/raider_spawn = list()
|
||||
var/global/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' objective. Clumsy, rewrite sometime.
|
||||
|
||||
/datum/game_mode/
|
||||
var/list/datum/mind/raiders = list() //Antags.
|
||||
var/list/raid_objectives = list() //Raid objectives
|
||||
|
||||
/datum/game_mode/heist
|
||||
name = "heist"
|
||||
@@ -16,9 +20,6 @@ VOX HEIST ROUNDTYPE
|
||||
var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds)
|
||||
var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds)
|
||||
|
||||
var/list/raid_objectives = list() //Raid objectives.
|
||||
var/list/obj/cortical_stacks = list() //Stacks for 'leave nobody behind' objective.
|
||||
|
||||
/datum/game_mode/heist/announce()
|
||||
world << "<B>The current game mode is - Heist!</B>"
|
||||
world << "<B>An unidentified bluespace signature has slipped past the Icarus and is approaching [station_name()]!</B>"
|
||||
@@ -59,15 +60,6 @@ VOX HEIST ROUNDTYPE
|
||||
|
||||
/datum/game_mode/heist/post_setup()
|
||||
|
||||
//Build a list of spawn points.
|
||||
var/list/turf/raider_spawn = list()
|
||||
|
||||
for(var/obj/effect/landmark/L in landmarks_list)
|
||||
if(L.name == "voxstart")
|
||||
raider_spawn += get_turf(L)
|
||||
del(L)
|
||||
continue
|
||||
|
||||
//Generate objectives for the group.
|
||||
if(!config.objectives_disabled)
|
||||
raid_objectives = forge_vox_objectives()
|
||||
@@ -83,49 +75,57 @@ VOX HEIST ROUNDTYPE
|
||||
raider.current.loc = raider_spawn[index]
|
||||
index++
|
||||
|
||||
var/sounds = rand(2,8)
|
||||
var/i = 0
|
||||
var/newname = ""
|
||||
|
||||
while(i<=sounds)
|
||||
i++
|
||||
newname += pick(list("ti","hi","ki","ya","ta","ha","ka","ya","chi","cha","kah"))
|
||||
|
||||
var/mob/living/carbon/human/vox = raider.current
|
||||
|
||||
vox.real_name = capitalize(newname)
|
||||
vox.name = vox.real_name
|
||||
raider.name = vox.name
|
||||
vox.age = rand(12,20)
|
||||
vox.dna.mutantrace = "vox"
|
||||
vox.set_species("Vox")
|
||||
vox.languages = list() // Removing language from chargen.
|
||||
vox.flavor_text = ""
|
||||
vox.add_language("Vox-pidgin")
|
||||
vox.h_style = "Short Vox Quills"
|
||||
vox.f_style = "Shaved"
|
||||
for(var/datum/organ/external/limb in vox.organs)
|
||||
limb.status &= ~(ORGAN_DESTROYED | ORGAN_ROBOT)
|
||||
|
||||
//Now apply cortical stack.
|
||||
var/datum/organ/external/E = vox.get_organ("head")
|
||||
var/obj/item/weapon/implant/cortical/I = new(vox)
|
||||
I.imp_in = vox
|
||||
I.implanted = 1
|
||||
I.part = E
|
||||
E.implants += I
|
||||
cortical_stacks += I
|
||||
|
||||
vox.equip_vox_raider()
|
||||
vox.regenerate_icons()
|
||||
|
||||
raider.objectives = raid_objectives
|
||||
create_vox(raider)
|
||||
greet_vox(raider)
|
||||
|
||||
if(!config.objectives_disabled && raid_objectives)
|
||||
raider.objectives = raid_objectives
|
||||
|
||||
spawn (rand(waittime_l, waittime_h))
|
||||
send_intercept()
|
||||
|
||||
/datum/game_mode/heist/proc/is_raider_crew_safe()
|
||||
/datum/game_mode/proc/create_vox(var/datum/mind/newraider)
|
||||
|
||||
|
||||
var/sounds = rand(2,8)
|
||||
var/i = 0
|
||||
var/newname = ""
|
||||
|
||||
while(i<=sounds)
|
||||
i++
|
||||
newname += pick(list("ti","hi","ki","ya","ta","ha","ka","ya","chi","cha","kah"))
|
||||
|
||||
var/mob/living/carbon/human/vox = newraider.current
|
||||
|
||||
vox.real_name = capitalize(newname)
|
||||
vox.name = vox.real_name
|
||||
newraider.name = vox.name
|
||||
vox.age = rand(12,20)
|
||||
vox.dna.mutantrace = "vox"
|
||||
vox.set_species("Vox")
|
||||
vox.languages = list() // Removing language from chargen.
|
||||
vox.flavor_text = ""
|
||||
vox.add_language("Vox-pidgin")
|
||||
vox.h_style = "Short Vox Quills"
|
||||
vox.f_style = "Shaved"
|
||||
|
||||
for(var/datum/organ/external/limb in vox.organs)
|
||||
limb.status &= ~(ORGAN_DESTROYED | ORGAN_ROBOT)
|
||||
|
||||
//Generate cortical stack.
|
||||
var/datum/organ/external/affected = vox.get_organ("head")
|
||||
|
||||
var/obj/item/weapon/implant/cortical/I = new(vox)
|
||||
I.imp_in = vox
|
||||
I.implanted = 1
|
||||
affected.implants += I
|
||||
I.part = affected
|
||||
cortical_stacks += I
|
||||
|
||||
vox.equip_vox_raider()
|
||||
vox.regenerate_icons()
|
||||
|
||||
/datum/game_mode/proc/is_raider_crew_safe()
|
||||
|
||||
if(cortical_stacks.len == 0)
|
||||
return 0
|
||||
@@ -135,7 +135,7 @@ VOX HEIST ROUNDTYPE
|
||||
return 0
|
||||
return 1
|
||||
|
||||
/datum/game_mode/heist/proc/is_raider_crew_alive()
|
||||
/datum/game_mode/proc/is_raider_crew_alive()
|
||||
|
||||
for(var/datum/mind/raider in raiders)
|
||||
if(raider.current)
|
||||
@@ -143,7 +143,7 @@ VOX HEIST ROUNDTYPE
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/game_mode/heist/proc/forge_vox_objectives()
|
||||
/datum/game_mode/proc/forge_vox_objectives()
|
||||
|
||||
var/i = 1
|
||||
var/max_objectives = pick(2,2,2,2,3,3,3,4)
|
||||
@@ -171,20 +171,13 @@ VOX HEIST ROUNDTYPE
|
||||
|
||||
return objs
|
||||
|
||||
/datum/game_mode/heist/proc/greet_vox(var/datum/mind/raider)
|
||||
/datum/game_mode/proc/greet_vox(var/datum/mind/raider)
|
||||
raider.current << "\blue <B>You are a Vox Raider, fresh from the Shoal!</b>"
|
||||
raider.current << "\blue The Vox are a race of cunning, sharp-eyed nomadic raiders and traders endemic to the frontier and much of the unexplored galaxy. You and the crew have come to the Exodus for plunder, trade or both."
|
||||
raider.current << "\blue Vox are cowardly and will flee from larger groups, but corner one or find them en masse and they are vicious."
|
||||
raider.current << "\blue Use :V to voxtalk, :H to talk on your encrypted channel, and don't forget to turn on your nitrogen internals!"
|
||||
raider.current << "\red IF YOU HAVE NOT PLAYED A VOX BEFORE, REVIEW THIS THREAD: http://baystation12.net/forums/viewtopic.php?f=6&t=8657."
|
||||
var/obj_count = 1
|
||||
if(!config.objectives_disabled)
|
||||
for(var/datum/objective/objective in raider.objectives)
|
||||
raider.current << "<B>Objective #[obj_count]</B>: [objective.explanation_text]"
|
||||
obj_count++
|
||||
else
|
||||
raider.current << "<font color=blue>Within the rules,</font> try to act as an opposing force to the crew or come up with other fun ideas. Further RP and try to make sure other players have </i>fun<i>! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! <b>Please remember all rules aside from those without explicit exceptions apply to antagonists.</i></b>"
|
||||
|
||||
show_objectives(raider)
|
||||
|
||||
/datum/game_mode/heist/declare_completion()
|
||||
|
||||
@@ -292,6 +285,6 @@ datum/game_mode/proc/auto_declare_completion_heist()
|
||||
var/area/skipjack = locate(/area/shuttle/vox/station)
|
||||
for (var/mob/living/M in skipjack.contents)
|
||||
//maybe send the player a message that they've gone home/been kidnapped? Someone responsible for vox lore should write that.
|
||||
Del(M)
|
||||
del(M)
|
||||
for (var/obj/O in skipjack.contents)
|
||||
Del(O) //no hiding in lockers or anything
|
||||
del(O) //no hiding in lockers or anything
|
||||
@@ -131,11 +131,7 @@
|
||||
/datum/game_mode/proc/greet_meme(var/datum/mind/meme, var/you_are=1)
|
||||
if (you_are)
|
||||
meme.current << "<B>\red You are a meme!</B>"
|
||||
|
||||
var/obj_count = 1
|
||||
for(var/datum/objective/objective in meme.objectives)
|
||||
meme.current << "<B>Objective #[obj_count]</B>: [objective.explanation_text]"
|
||||
obj_count++
|
||||
show_objectives(meme)
|
||||
return
|
||||
|
||||
/datum/game_mode/meme/check_finished()
|
||||
|
||||
@@ -56,8 +56,8 @@
|
||||
if(ninja.current && !(istype(ninja.current,/mob/living/carbon/human))) return 0
|
||||
if(!config.objectives_disabled)
|
||||
forge_ninja_objectives(ninja)
|
||||
else
|
||||
ninja.current << "<font color=blue>Within the rules,</font> try to act as an opposing force to the crew. Further RP and try to make sure other players have </i>fun<i>! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! <b>Please remember all rules aside from those without explicit exceptions apply to antagonists.</i></b>"
|
||||
show_objectives(ninja)
|
||||
|
||||
var/mob/living/carbon/human/N = ninja.current
|
||||
N.internal = N.s_store
|
||||
N.internals.icon_state = "internal1"
|
||||
@@ -139,11 +139,7 @@
|
||||
ninja.current << "You are an elite mercenary assassin of the Spider Clan, [ninja.current.real_name]. You have a variety of abilities at your disposal, thanks to your nano-enhanced cyber armor.\nYour current directive is: \red <B>[directive]</B>\n \blue Try your best to adhere to this."
|
||||
ninja.store_memory("<B>Directive:</B> \red [directive]<br>")
|
||||
|
||||
var/obj_count = 1
|
||||
ninja.current << "\blue Your current objectives:"
|
||||
for(var/datum/objective/objective in ninja.objectives)
|
||||
ninja.current << "<B>Objective #[obj_count]</B>: [objective.explanation_text]"
|
||||
obj_count++
|
||||
show_objectives(ninja)
|
||||
|
||||
/datum/game_mode/proc/auto_declare_completion_ninja()
|
||||
if(ninjas.len)
|
||||
|
||||
@@ -1,3 +1,10 @@
|
||||
/*
|
||||
NUCLEAR EMERGENCY ROUNDTYPE
|
||||
*/
|
||||
|
||||
var/global/list/turf/synd_spawn = list()
|
||||
|
||||
|
||||
/datum/game_mode
|
||||
var/list/datum/mind/syndicates = list()
|
||||
|
||||
@@ -116,15 +123,7 @@
|
||||
|
||||
/datum/game_mode/nuclear/post_setup()
|
||||
|
||||
var/list/turf/synd_spawn = list()
|
||||
|
||||
for(var/obj/effect/landmark/A in landmarks_list)
|
||||
if(A.name == "Syndicate-Spawn")
|
||||
synd_spawn += get_turf(A)
|
||||
del(A)
|
||||
continue
|
||||
|
||||
var/obj/effect/landmark/uplinklocker = locate("landmark*Syndicate-Uplink") //i will be rewriting this shortly
|
||||
var/obj/effect/landmark/uplinkdevice = locate("landmark*Syndicate-Uplink") //i will be rewriting this shortly
|
||||
var/obj/effect/landmark/nuke_spawn = locate("landmark*Nuclear-Bomb")
|
||||
|
||||
var/nuke_code = "[rand(10000, 99999)]"
|
||||
@@ -139,8 +138,8 @@
|
||||
synd_mind.current.real_name = "[syndicate_name()] Operative" // placeholder while we get their actual name
|
||||
spawn(0)
|
||||
NukeNameAssign(synd_mind)
|
||||
if(!config.objectives_disabled)
|
||||
forge_syndicate_objectives(synd_mind)
|
||||
|
||||
forge_syndicate_objectives(synd_mind)
|
||||
greet_syndicate(synd_mind)
|
||||
equip_syndicate(synd_mind.current)
|
||||
|
||||
@@ -153,8 +152,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
|
||||
@@ -166,6 +166,7 @@
|
||||
|
||||
|
||||
/datum/game_mode/proc/prepare_syndicate_leader(var/datum/mind/synd_mind, var/nuke_code)
|
||||
var/obj/effect/landmark/code_spawn = locate("landmark*Nuclear-Code")
|
||||
if (nuke_code)
|
||||
synd_mind.store_memory("<B>Syndicate Nuclear Bomb Code</B>: [nuke_code]", 0, 0)
|
||||
synd_mind.current << "The nuclear authorization code is: <B>[nuke_code]</B>"
|
||||
@@ -173,7 +174,7 @@
|
||||
P.info = "The nuclear authorization code is: <b>[nuke_code]</b>"
|
||||
P.name = "nuclear bomb code"
|
||||
if (ticker.mode.config_tag=="nuclear")
|
||||
P.loc = synd_mind.current.loc
|
||||
P.loc = code_spawn.loc
|
||||
else
|
||||
var/mob/living/carbon/human/H = synd_mind.current
|
||||
P.loc = H.loc
|
||||
@@ -186,25 +187,18 @@
|
||||
|
||||
|
||||
/datum/game_mode/proc/forge_syndicate_objectives(var/datum/mind/syndicate)
|
||||
|
||||
if (config.objectives_disabled)
|
||||
return
|
||||
|
||||
var/datum/objective/nuclear/syndobj = new
|
||||
syndobj.owner = syndicate
|
||||
syndicate.objectives += syndobj
|
||||
|
||||
|
||||
/datum/game_mode/proc/greet_syndicate(var/datum/mind/syndicate, var/you_are=1)
|
||||
if (you_are)
|
||||
syndicate.current << "\blue You are a [syndicate_name()] agent!"
|
||||
var/obj_count = 1
|
||||
if(!config.objectives_disabled)
|
||||
for(var/datum/objective/objective in syndicate.objectives)
|
||||
syndicate.current << "<B>Objective #[obj_count]</B>: [objective.explanation_text]"
|
||||
obj_count++
|
||||
else
|
||||
syndicate.current << "<font color=blue>Within the rules,</font> try to act as an opposing force to the crew. Further RP and try to make sure other players have </i>fun<i>! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! <b>Please remember all rules aside from those without explicit exceptions apply to antagonists.</i></b>"
|
||||
return
|
||||
|
||||
show_objectives(syndicate)
|
||||
|
||||
/datum/game_mode/proc/random_radio_frequency()
|
||||
return 1337 // WHY??? -- Doohl
|
||||
@@ -230,6 +224,7 @@
|
||||
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)
|
||||
|
||||
/* 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)
|
||||
var/obj/item/clothing/head/helmet/space/rig/syndi/new_helmet = new(synd_mob)
|
||||
|
||||
@@ -245,8 +240,8 @@
|
||||
if("Skrell")
|
||||
new_suit.species_restricted = list("Skrell")
|
||||
|
||||
synd_mob.equip_to_slot_or_del(new_suit, slot_wear_suit)
|
||||
synd_mob.equip_to_slot_or_del(new_helmet, slot_head)
|
||||
synd_mob.equip_to_slot_or_del(new_suit, slot_in_backpack)
|
||||
synd_mob.equip_to_slot_or_del(new_helmet, slot_in_backpack)*/
|
||||
|
||||
// var/obj/item/weapon/implant/explosive/E = new/obj/item/weapon/implant/explosive(synd_mob)
|
||||
// E.imp_in = synd_mob
|
||||
|
||||
@@ -557,7 +557,7 @@ datum/objective/steal
|
||||
|
||||
for(var/obj/item/I in all_items) //Check for phoron tanks
|
||||
if(istype(I, steal_target))
|
||||
found_amount += (target_name=="28 moles of phoron (full tank)" ? (I:air_contents:phoron) : (I:amount))
|
||||
found_amount += (target_name=="28 moles of phoron (full tank)" ? (I:air_contents:gas["phoron"]) : (I:amount))
|
||||
return found_amount>=target_amount
|
||||
|
||||
if("50 coins (in bag)")
|
||||
@@ -930,4 +930,42 @@ datum/objective/heist/inviolate_death
|
||||
explanation_text = "Follow the Inviolate. Minimise death and loss of resources."
|
||||
check_completion()
|
||||
if(vox_kills > MAX_VOX_KILLS) return 0
|
||||
return 1
|
||||
return 1
|
||||
|
||||
//Borer objective(s).
|
||||
|
||||
/datum/objective/borer_survive
|
||||
explanation_text = "Survive in a host until the end of the round."
|
||||
|
||||
/datum/objective/borer_survive/check_completion()
|
||||
if(owner)
|
||||
var/mob/living/simple_animal/borer/B = owner
|
||||
if(istype(B) && B.stat < 2 && B.host && B.host.stat < 2) return 1
|
||||
return 0
|
||||
|
||||
/datum/objective/borer_reproduce
|
||||
explanation_text = "Reproduce at least once."
|
||||
|
||||
/datum/objective/borer_reproduce/check_completion()
|
||||
if(owner && owner.current)
|
||||
var/mob/living/simple_animal/borer/B = owner.current
|
||||
if(istype(B) && B.has_reproduced) return 1
|
||||
return 0
|
||||
|
||||
/datum/objective/ninja_highlander
|
||||
explanation_text = "You aspire to be a Grand Master of the Spider Clan. Kill all of your fellow acolytes."
|
||||
|
||||
/datum/objective/ninja_highlander/check_completion()
|
||||
if(owner)
|
||||
for(var/datum/mind/ninja in ticker.mode.ninjas)
|
||||
if(ninja != owner)
|
||||
if(ninja.current.stat < 2) return 0
|
||||
return 1
|
||||
return 0
|
||||
|
||||
/datum/objective/cult_summon
|
||||
explanation_text = "Summon Nar-Sie via the use of the appropriate rune (Hell join self). It will only work if nine cultists stand on and around it."
|
||||
|
||||
/datum/objective/cult_summon/check_completion()
|
||||
if(locate(/obj/machinery/singularity/narsie/large) in machines) return 1
|
||||
return 0
|
||||
@@ -118,16 +118,13 @@
|
||||
rev_mind.objectives += rev_obj
|
||||
|
||||
/datum/game_mode/proc/greet_revolutionary(var/datum/mind/rev_mind, var/you_are=1)
|
||||
var/obj_count = 1
|
||||
|
||||
rev_mind.special_role = "Head Revolutionary"
|
||||
|
||||
if (you_are)
|
||||
rev_mind.current << "\blue You are a member of the revolutionaries' leadership!"
|
||||
if(!config.objectives_disabled)
|
||||
for(var/datum/objective/objective in rev_mind.objectives)
|
||||
rev_mind.current << "<B>Objective #[obj_count]</B>: [objective.explanation_text]"
|
||||
rev_mind.special_role = "Head Revolutionary"
|
||||
obj_count++
|
||||
else
|
||||
rev_mind.current << "<font color=blue>Within the rules,</font> try to act as an opposing force to the crew. Further RP and try to make sure other players have </i>fun<i>! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! <b>Please remember all rules aside from those without explicit exceptions apply to antagonists.</i></b>"
|
||||
|
||||
show_objectives(rev_mind)
|
||||
|
||||
/////////////////////////////////////////////////////////////////////////////////
|
||||
//This are equips the rev heads with their gear, and makes the clown not clumsy//
|
||||
@@ -198,8 +195,7 @@
|
||||
revolutionaries += rev_mind
|
||||
rev_mind.current << "\red <FONT size = 3> You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill the heads to win the revolution!</FONT>"
|
||||
rev_mind.special_role = "Revolutionary"
|
||||
if(config.objectives_disabled)
|
||||
rev_mind.current << "<font color=blue>Within the rules,</font> try to act as an opposing force to the crew. Further RP and try to make sure other players have </i>fun<i>! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! <b>Please remember all rules aside from those without explicit exceptions apply to antagonists.</i></b>"
|
||||
show_objectives(rev_mind)
|
||||
update_rev_icons_added(rev_mind)
|
||||
return 1
|
||||
//////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
@@ -87,11 +87,8 @@
|
||||
update_rev_icons_added(rev_mind)
|
||||
|
||||
for(var/datum/mind/rev_mind in head_revolutionaries)
|
||||
var/obj_count = 1
|
||||
rev_mind.current << "\blue You are a member of the revolutionaries' leadership!"
|
||||
for(var/datum/objective/objective in rev_mind.objectives)
|
||||
rev_mind.current << "<B>Objective #[obj_count]</B>: [objective.explanation_text]"
|
||||
obj_count++
|
||||
show_objectives(rev_mind)
|
||||
|
||||
spawn (rand(waittime_l, waittime_h))
|
||||
send_intercept()
|
||||
|
||||
@@ -78,16 +78,10 @@
|
||||
send_intercept()
|
||||
|
||||
/datum/game_mode/revolution/rp_revolution/greet_revolutionary(var/datum/mind/rev_mind, var/you_are=1)
|
||||
var/obj_count = 1
|
||||
rev_mind.special_role = "Head Revolutionary"
|
||||
if (you_are)
|
||||
rev_mind.current << "\blue You are a member of the revolutionaries' leadership!"
|
||||
if(!config.objectives_disabled)
|
||||
for(var/datum/objective/objective in rev_mind.objectives)
|
||||
rev_mind.current << "<B>Objective #[obj_count]</B>: [objective.explanation_text]"
|
||||
rev_mind.special_role = "Head Revolutionary"
|
||||
obj_count++
|
||||
else
|
||||
rev_mind.current << "<font color=blue>Within the rules,</font> try to act as an opposing force to the crew. Further RP and try to make sure other players have </i>fun<i>! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! <b>Please remember all rules aside from those without explicit exceptions apply to antagonists.</i></b>"
|
||||
show_objectives(rev_mind)
|
||||
|
||||
// Show each head revolutionary up to 3 candidates
|
||||
var/list/already_considered = list()
|
||||
@@ -113,8 +107,7 @@
|
||||
revolutionaries += rev_mind
|
||||
rev_mind.current << "\red <FONT size = 3> You are now a revolutionary! Help your cause. Do not harm your fellow freedom fighters. You can identify your comrades by the red \"R\" icons, and your leaders by the blue \"R\" icons. Help them kill, capture or convert the heads to win the revolution!</FONT>"
|
||||
rev_mind.special_role = "Revolutionary"
|
||||
if(config.objectives_disabled)
|
||||
rev_mind.current << "<font color=blue>Within the rules,</font> try to act as an opposing force to the crew. Further RP and try to make sure other players have </i>fun<i>! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! <b>Please remember all rules aside from those without explicit exceptions apply to antagonists.</i></b>"
|
||||
show_objectives(rev_mind)
|
||||
update_rev_icons_added(rev_mind)
|
||||
H.hud_updateflag |= 1 << SPECIALROLE_HUD
|
||||
return 1
|
||||
|
||||
@@ -135,14 +135,7 @@
|
||||
|
||||
/datum/game_mode/proc/greet_traitor(var/datum/mind/traitor)
|
||||
traitor.current << "<B><font size=3 color=red>You are the traitor.</font></B>"
|
||||
if (!config.objectives_disabled)
|
||||
var/obj_count = 1
|
||||
for(var/datum/objective/objective in traitor.objectives)
|
||||
traitor.current << "<B>Objective #[obj_count]</B>: [objective.explanation_text]"
|
||||
obj_count++
|
||||
else
|
||||
traitor.current << "<i>You have been selected this round as an antagonist- <font color=blue>Within the rules,</font> try to act as an opposing force to the crew- This can be via corporate payoff, personal motives, or maybe just being a dick. Further RP and try to make sure other players have </i>fun<i>! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! <b>Please remember all rules aside from those without explicit exceptions apply to antagonist.</i></b>"
|
||||
return
|
||||
show_objectives(traitor)
|
||||
|
||||
|
||||
/datum/game_mode/proc/finalize_traitor(var/datum/mind/traitor)
|
||||
|
||||
@@ -13,10 +13,8 @@
|
||||
survive.owner = H.mind
|
||||
H.mind.objectives += survive
|
||||
H << "<B>You are the survivor! Your own safety matters above all else, trust no one and kill anyone who gets in your way. However, armed as you are, now would be the perfect time to settle that score or grab that pair of yellow gloves you've been eyeing...</B>"
|
||||
var/obj_count = 1
|
||||
for(var/datum/objective/OBJ in H.mind.objectives)
|
||||
H << "<B>Objective #[obj_count]</B>: [OBJ.explanation_text]"
|
||||
obj_count++
|
||||
show_objectives(H.mind)
|
||||
|
||||
var/randomize = pick("taser","egun","laser","revolver","detective","smg","nuclear","deagle","gyrojet","pulse","silenced","cannon","doublebarrel","shotgun","combatshotgun","mateba","smg","uzi","crossbow","saw")
|
||||
switch (randomize)
|
||||
if("taser")
|
||||
|
||||
@@ -135,16 +135,7 @@
|
||||
/datum/game_mode/proc/greet_wizard(var/datum/mind/wizard, var/you_are=1)
|
||||
if (you_are)
|
||||
wizard.current << "<B>\red You are the Space Wizard!</B>"
|
||||
wizard.current << "<B>The Space Wizards Federation has given you the following tasks:</B>"
|
||||
if(!config.objectives_disabled)
|
||||
var/obj_count = 1
|
||||
for(var/datum/objective/objective in wizard.objectives)
|
||||
wizard.current << "<B>Objective #[obj_count]</B>: [objective.explanation_text]"
|
||||
obj_count++
|
||||
else
|
||||
wizard.current << "<font color=blue>Within the rules,</font> try to act as an opposing force to the crew. Further RP and try to make sure other players have </i>fun<i>! If you are confused or at a loss, always adminhelp, and before taking extreme actions, please try to also contact the administration! Think through your actions and make the roleplay immersive! <b>Please remember all rules aside from those without explicit exceptions apply to antagonists.</i></b>"
|
||||
return
|
||||
|
||||
show_objectives(wizard)
|
||||
|
||||
/*/datum/game_mode/proc/learn_basic_spells(mob/living/carbon/human/wizard_mob)
|
||||
if (!istype(wizard_mob))
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user