Merge pull request #2222 from Cyantime/bombzone

Adds a plasma research outpost.
This commit is contained in:
Spades
2017-09-29 18:13:10 -04:00
committed by GitHub
14 changed files with 1084 additions and 89 deletions
@@ -236,8 +236,7 @@
dir = SOUTH
initialize_directions = SOUTH|NORTH|EAST
obj/machinery/atmospherics/trinary/filter/m_filter/New()
..()
obj/machinery/atmospherics/trinary/filter/m_filter/init_dir()
switch(dir)
if(NORTH)
initialize_directions = WEST|NORTH|SOUTH
@@ -181,8 +181,7 @@ obj/machinery/atmospherics/trinary/mixer/t_mixer
//node 3 is the outlet, nodes 1 & 2 are intakes
obj/machinery/atmospherics/trinary/mixer/t_mixer/New()
..()
obj/machinery/atmospherics/trinary/mixer/t_mixer/init_dir()
switch(dir)
if(NORTH)
initialize_directions = EAST|NORTH|WEST
@@ -227,8 +226,7 @@ obj/machinery/atmospherics/trinary/mixer/m_mixer
//node 3 is the outlet, nodes 1 & 2 are intakes
obj/machinery/atmospherics/trinary/mixer/m_mixer/New()
..()
obj/machinery/atmospherics/trinary/mixer/m_mixer/init_dir()
switch(dir)
if(NORTH)
initialize_directions = WEST|NORTH|SOUTH
@@ -231,3 +231,42 @@
/area/shuttle/tether/transit
name = "Tether Shuttle Transit"
icon_state = "shuttle2"
/area/rnd/outpost
name = "\improper Research Outpost Hallway"
icon_state = "research"
/area/rnd/outpost/airlock
name = "\improper Research Outpost Airlock"
icon_state = "green"
/area/rnd/outpost/eva
name = "Research Outpost EVA Storage"
icon_state = "eva"
/area/rnd/outpost/chamber
name = "\improper Research Outpost Burn Chamber"
icon_state = "engine"
/area/rnd/outpost/atmos
name = "Research Outpost Atmospherics"
icon_state = "atmos"
/area/rnd/outpost/storage
name = "\improper Research Outpost Gas Storage"
icon_state = "toxstorage"
/area/rnd/outpost/mixing
name = "\improper Research Outpost Gas Mixing"
icon_state = "toxmix"
/area/rnd/outpost/heating
name = "\improper Research Outpost Gas Heating"
icon_state = "toxmix"
/area/rnd/outpost/testing
name = "\improper Research Outpost Testing"
icon_state = "toxtest"
/area/maintenance/substation/outpost
name = "Research Outpost Substation"
+51 -25
View File
@@ -4,6 +4,7 @@
icon = 'icons/obj/meter_vr.dmi'
icon_state = "meterX"
var/obj/machinery/atmospherics/pipe/target = null
var/list/pipes_on_turf = list()
anchored = 1.0
power_channel = ENVIRON
var/frequency = 0
@@ -13,12 +14,29 @@
/obj/machinery/meter/New()
..()
src.target = locate(/obj/machinery/atmospherics/pipe) in loc
spawn(5)
target = select_target()
return 1
/obj/machinery/meter/initialize()
. = ..()
if (!target)
src.target = locate(/obj/machinery/atmospherics/pipe) in loc
spawn(5)
target = select_target()
/obj/machinery/meter/Destroy()
pipes_on_turf.Cut()
target = null
return ..()
/obj/machinery/meter/proc/select_target()
var/obj/machinery/atmospherics/pipe/P
for(P in loc)
if(!P.hides_under_flooring())
break
if(!P)
P = locate(/obj/machinery/atmospherics/pipe) in loc
return P
/obj/machinery/meter/process()
if(!target)
@@ -88,35 +106,43 @@
/obj/machinery/meter/Click()
if(istype(usr, /mob/living/carbon/human) || istype(usr, /mob/living/silicon/ai)) // ghosts can call ..() for examine
usr.examinate(src)
return 1
var/mob/living/L = usr
if(!L.get_active_hand() || !L.Adjacent(src))
usr.examinate(src)
return 1
return ..()
/obj/machinery/meter/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
if (!istype(W, /obj/item/weapon/wrench))
return ..()
playsound(src, W.usesound, 50, 1)
user << "<span class='notice'>You begin to unfasten \the [src]...</span>"
if (do_after(user, 40 * W.toolspeed))
user.visible_message( \
"<span class='notice'>\The [user] unfastens \the [src].</span>", \
"<span class='notice'>You have unfastened \the [src].</span>", \
"You hear ratchet.")
new /obj/item/pipe_meter(src.loc)
qdel(src)
/obj/machinery/meter/attackby(var/obj/item/W, var/mob/user)
if(iswrench(W))
playsound(src, W.usesound, 50, 1)
to_chat(user, "<span class='notice'>You begin to unfasten \the [src]...</span>")
if(do_after(user, 40 * W.toolspeed))
user.visible_message( \
"<span class='notice'>\The [user] unfastens \the [src].</span>", \
"<span class='notice'>You have unfastened \the [src].</span>", \
"You hear ratchet.")
new /obj/item/pipe_meter(get_turf(src))
qdel(src)
return
if(ismultitool(W))
for(var/obj/machinery/atmospherics/pipe/P in loc)
pipes_on_turf |= P
if(!pipes_on_turf.len)
return
target = pipes_on_turf[1]
pipes_on_turf.Remove(target)
pipes_on_turf.Add(target)
to_chat(user, "<span class='notice'>Pipe meter set to moniter \the [target].</span>")
return
return ..()
// TURF METER - REPORTS A TILE'S AIR CONTENTS
/obj/machinery/meter/turf/New()
..()
src.target = loc
return 1
/obj/machinery/meter/turf/initialize()
if (!target)
src.target = loc
/obj/machinery/meter/turf/select_target()
return loc
/obj/machinery/meter/turf/attackby(var/obj/item/weapon/W as obj, var/mob/user as mob)
return
+129
View File
@@ -0,0 +1,129 @@
/obj/machinery/portable_atmospherics/powered/pump/huge
name = "Huge Air Pump"
icon = 'icons/obj/atmos.dmi'
icon_state = "siphon:0"
anchored = 1
volume = 500000
use_power = 1
idle_power_usage = 50 //internal circuitry, friction losses and stuff
active_power_usage = 1000 // Blowers running
power_rating = 100000 //100 kW ~ 135 HP
var/global/gid = 1
var/id = 0
/obj/machinery/portable_atmospherics/powered/pump/huge/New()
..()
cell = null
id = gid
gid++
name = "[name] (ID [id])"
/obj/machinery/portable_atmospherics/powered/pump/huge/attack_hand(var/mob/user)
to_chat(user, "<span class='notice'>You can't directly interact with this machine. Use the pump control console.</span>")
/obj/machinery/portable_atmospherics/powered/pump/huge/update_icon()
overlays.Cut()
if(on && !(stat & (NOPOWER|BROKEN)))
icon_state = "siphon:1"
else
icon_state = "siphon:0"
/obj/machinery/portable_atmospherics/powered/pump/huge/power_change()
var/old_stat = stat
..()
if (old_stat != stat)
update_icon()
/obj/machinery/portable_atmospherics/powered/pump/huge/process()
if(!anchored || (stat & (NOPOWER|BROKEN)))
on = 0
last_flow_rate = 0
last_power_draw = 0
update_icon()
var/new_use_power = 1 + on
if(new_use_power != use_power)
update_use_power(new_use_power)
if(!on)
return
var/power_draw = -1
var/datum/gas_mixture/environment = loc.return_air()
var/pressure_delta
var/output_volume
var/air_temperature
if(direction_out)
pressure_delta = target_pressure - environment.return_pressure()
output_volume = environment.volume * environment.group_multiplier
air_temperature = environment.temperature? environment.temperature : air_contents.temperature
else
pressure_delta = environment.return_pressure() - target_pressure
output_volume = air_contents.volume * air_contents.group_multiplier
air_temperature = air_contents.temperature? air_contents.temperature : environment.temperature
var/transfer_moles = pressure_delta*output_volume/(air_temperature * R_IDEAL_GAS_EQUATION)
if(pressure_delta > 0.01)
if(direction_out)
power_draw = pump_gas(src, air_contents, environment, transfer_moles, power_rating)
else
power_draw = pump_gas(src, environment, air_contents, transfer_moles, power_rating)
if (power_draw < 0)
last_flow_rate = 0
last_power_draw = 0
else
use_power(power_draw)
update_connected_network()
/obj/machinery/portable_atmospherics/powered/pump/huge/attackby(var/obj/item/I, var/mob/user)
if(istype(I, /obj/item/weapon/wrench))
if(on)
user << "<span class='warning'>Turn \the [src] off first!</span>"
return
anchored = !anchored
playsound(get_turf(src), I.usesound, 50, 1)
user << "<span class='notice'>You [anchored ? "wrench" : "unwrench"] \the [src].</span>"
return
//doesn't use power cells
if(istype(I, /obj/item/weapon/cell))
return
if (istype(I, /obj/item/weapon/screwdriver))
return
//doesn't hold tanks
if(istype(I, /obj/item/weapon/tank))
return
..()
/obj/machinery/portable_atmospherics/powered/pump/huge/stationary
name = "Stationary Air Pump"
/obj/machinery/portable_atmospherics/powered/pump/huge/stationary/attackby(var/obj/item/I, var/mob/user)
if(istype(I, /obj/item/weapon/wrench))
user << "<span class='warning'>The bolts are too tight for you to unscrew!</span>"
return
..()
/obj/machinery/portable_atmospherics/powered/pump/huge/stationary/purge
on = 1
start_pressure = 0
target_pressure = 0
/obj/machinery/portable_atmospherics/powered/pump/huge/stationary/purge/power_change()
..()
if(!(stat & (NOPOWER|BROKEN)))
on = 1
update_icon()
+384
View File
@@ -0,0 +1,384 @@
#define MODE_SINGLE 1
#define MODE_DOUBLE 2
#define MODE_CANISTER 3
/obj/machinery/bomb_tester
name = "explosive effect simulator"
desc = "A device that can calculate the potential explosive yield of provided gases."
icon = 'icons/obj/machines/bomb_tester_vr.dmi'
icon_state = "generic"
anchored = 1
density = 1
idle_power_usage = 50
active_power_usage = 1.5 KILOWATTS
circuit = /obj/item/weapon/circuitboard/bomb_tester
var/icon_name = "generic"
var/obj/item/weapon/tank/tank1
var/obj/item/weapon/tank/tank2
var/obj/machinery/portable_atmospherics/canister/test_canister
var/sim_mode = MODE_SINGLE
var/sim_canister_output = 10*ONE_ATMOSPHERE
var/simulating = 0
var/simulation_started = 0
var/simulation_delay = 20 SECONDS
var/simulation_results
var/datum/gas_mixture/faketank
var/faketank_integrity
/obj/machinery/bomb_tester/New()
..()
default_apply_parts()
RefreshParts()
faketank = new
/obj/machinery/bomb_tester/Destroy()
tank1 = null //Base machine Destroy()
tank2 = null //handles deleting contents
test_canister = null
..()
/obj/machinery/bomb_tester/dismantle()
if(tank1)
tank1.forceMove(get_turf(src))
tank1 = null
if(tank2)
tank2.forceMove(get_turf(src))
tank2 = null
simulation_finish(1)
return ..()
/obj/machinery/bomb_tester/process()
..()
if(test_canister && !Adjacent(test_canister))
test_canister = null
if(simulating && world.time >= simulation_started + simulation_delay)
simulation_finish()
/obj/machinery/bomb_tester/update_icon()
overlays.Cut()
if(tank1)
overlays += image(icon, "[icon_name]-tank1")
if(tank2)
overlays += image(icon, "[icon_name]-tank2")
if(stat & NOPOWER)
icon_state = "[icon_name]-p"
else
icon_state = "[icon_name][simulating]"
/obj/machinery/bomb_tester/power_change()
..()
update_icon()
if(simulating && stat & NOPOWER)
simulation_finish(1)
/obj/machinery/bomb_tester/RefreshParts()
..()
var/scan_rating = 0
for(var/obj/item/weapon/stock_parts/scanning_module/S in component_parts)
scan_rating += S.rating
simulation_delay = 25 SECONDS - scan_rating SECONDS
/obj/machinery/bomb_tester/attackby(var/obj/item/I, var/mob/user)
if(default_deconstruction_screwdriver(user, I))
return
if(default_deconstruction_crowbar(user, I))
return
if(default_part_replacement(user, I))
return
if(istype(I, /obj/item/weapon/tank))
if(!tank1 || !tank2)
user.drop_item(I)
I.forceMove(src)
if(!tank1)
tank1 = I
else
tank2 = I
update_icon()
updateUsrDialog()
to_chat(user, "<span class='notice'>You connect \the [I] to \the [src]'s [I==tank1 ? "primary" : "secondary"] slot.</span>")
return
..()
/obj/machinery/bomb_tester/attack_hand(var/mob/user)
add_fingerprint(user)
interact(user)
/obj/machinery/bomb_tester/interact(var/mob/user)
if(stat & NOPOWER)
return
var/dat = "<HEAD><TITLE>Bomb Tester</TITLE></HEAD>"
dat += "<font face='terminal' size ='3'>Virtual Explosive Simulator v1.03</font>"
dat += "<br>"
if(simulating)
dat += "<br><center>Simulation in progress! Please wait for results.</center>"
else
dat += "<br><center>Mode: [sim_mode==MODE_SINGLE?"Single Tank":"<A href='?src=\ref[src];set_mode=1'>Single Tank</a>"] -- [sim_mode==MODE_DOUBLE?"Transfer Valve":"<A href='?src=\ref[src];set_mode=2'>Transfer Valve</a>"] -- [sim_mode==MODE_CANISTER?"Canister":"<A href='?src=\ref[src];set_mode=3'>Canister</a>"]</center>"
dat += "<br>"
dat += "<br><center><u>Gas Sources</u></center>"
dat += "<br><center><A href='?src=\ref[src];tank=1'>[tank1?"\[[tank1.name]\]":"\[Primary Slot\]"]</a> -- <A href='?src=\ref[src];tank=2'>[tank2?"\[[tank2.name]\]":"\[Secondary Slot\]"]</a></center>"
dat += "<br><center>Connected Canister: [test_canister?"[test_canister.name] -- ":"None -- "]<A href='?src=\ref[src];canister_scan=1'>[test_canister?"\[Rescan\]":"\[Scan for canister\]"]</a></center>"
if(test_canister)
dat += "<br><center>Canister Release Pressure: [sim_canister_output] Kilopascals</center>"
dat += "<br><center>"
dat += "<A href='?src=\ref[src];set_can_pressure=-1000'>-1000</a>|"
dat += "<A href='?src=\ref[src];set_can_pressure=-100'>-100</a>|"
dat += "<A href='?src=\ref[src];set_can_pressure=-10'>-10</a>|"
dat += "<A href='?src=\ref[src];set_can_pressure=-1'>-1</a> ||| "
dat += "<A href='?src=\ref[src];set_can_pressure=1'>+1</a>|"
dat += "<A href='?src=\ref[src];set_can_pressure=10'>+10</a>|"
dat += "<A href='?src=\ref[src];set_can_pressure=100'>+100</a>|"
dat += "<A href='?src=\ref[src];set_can_pressure=1000'>+1000</a>"
dat += "</center>"
dat += "<br><br>"
dat += "<br><center><font size='6'><b><A href='?src=\ref[src];start_sim=1'>BEGIN SIMULATION</a></b></font></center>"
user.set_machine(src)
user << browse(dat, "window=bomb_tester")
onclose(user, "bomb_tester")
/obj/machinery/bomb_tester/Topic(href, href_list)
if(..())
return
if(stat & NOPOWER)
return
if(!usr.Adjacent(src))
usr << browse(null, "window=bomb_tester")
usr.unset_machine()
return
if(simulating)
return
if(href_list["set_mode"])
sim_mode = text2num(href_list["set_mode"])
var/text_mode
switch(sim_mode)
if(MODE_SINGLE)
text_mode = "single gas tank detonation"
if(MODE_DOUBLE)
text_mode = "tank transfer valve detonation"
if(MODE_CANISTER)
text_mode = "canister-assisted single gas tank detonation"
to_chat(usr, "<span class='notice'>[src] set to simulate a [text_mode].</span>")
if(href_list["tank"])
var/tankvar = "tank[href_list["tank"]]"
var/obj/item/weapon/tank/T
if(vars[tankvar])
T = vars[tankvar]
T.forceMove(get_turf(src))
vars[tankvar] = null
else if(istype(usr.get_active_hand(),/obj/item/weapon/tank))
T = usr.get_active_hand()
usr.drop_item(T)
T.forceMove(src)
vars[tankvar] = T
update_icon()
if(href_list["canister_scan"])
for(var/obj/machinery/portable_atmospherics/canister/C in orange(1,src))
if(C && C == test_canister)
continue
else if(C)
test_canister = C
break
else
test_canister = null
if(href_list["set_can_pressure"])
var/change = text2num(href_list["set_can_pressure"])
sim_canister_output = Clamp(sim_canister_output+change, ONE_ATMOSPHERE/10, ONE_ATMOSPHERE*10)
if(href_list["start_sim"])
start_simulating()
updateUsrDialog()
/obj/machinery/bomb_tester/proc/start_simulating()
simulating = 1
update_use_power(2)
simulation_started = world.time
update_icon()
switch(sim_mode)
if(MODE_SINGLE)
if(!tank1)
simulation_results = "Error"
return
spawn()
single_tank_sim()
if(MODE_DOUBLE)
if(!tank1 || !tank2)
simulation_results = "Error"
return
spawn()
ttv_sim()
if(MODE_CANISTER)
if(!tank1 || !test_canister)
simulation_results = "Error"
return
spawn()
canister_sim()
/obj/machinery/bomb_tester/proc/simulate_tank() //This is a heavily cut down version of check_status() from tanks.dm
faketank.react()
var/pressure = faketank.return_pressure()
if(pressure > TANK_FRAGMENT_PRESSURE)
if(faketank_integrity <= 7)
faketank.react()
faketank.react()
faketank.react()
pressure = faketank.return_pressure()
var/strength = (pressure-TANK_FRAGMENT_PRESSURE)/TANK_FRAGMENT_SCALE
var/mult = ((faketank.volume/140)**(1/2)) * (faketank.total_moles**2/3)/((29*0.64) **2/3) //Don't ask me what this is, see tanks.dm
var/dev = round((mult*strength)*0.15)
var/heavy = round((mult*strength)*0.35)
var/light = round((mult*strength)*0.80)
simulation_results += "<hr>Final Result: Explosive tank rupture. [dev?"Extreme damage within [2.5*dev] meters. ":""][heavy?"Heavy damage within [2.5*heavy] meters. ":""][light?"Light damage within [2.5*light] meters. ":""]Hazardous shrapnel produced."
return 1
else
faketank_integrity -= 7
else if(pressure > TANK_RUPTURE_PRESSURE)
faketank.react()
if(faketank_integrity <= 0)
simulation_results += "<hr>Final Result: Tank rupture, minimal concussive force. Hazardous shrapnel produced."
return 1
else
faketank_integrity -= 5
else if(pressure > TANK_LEAK_PRESSURE || faketank.temperature - T0C > 173)
faketank_integrity -= 1
return 0
/obj/machinery/bomb_tester/proc/single_tank_sim()
faketank.volume = tank1.volume
faketank.copy_from(tank1.air_contents)
faketank_integrity = tank1.integrity
simulation_results = "<center><h1><b>Single Tank Ignition Test</b></h1></center>"
simulation_results += "<hr>"
simulation_results += "<br>Initial gas tank status:<br>[format_gas_for_results(faketank)]"
faketank.add_thermal_energy(15000)
var/intervals = 0
while(intervals < 10)
intervals++
simulation_results += "<hr>[intervals*2] seconds after ignition."
if(simulate_tank())
break
simulation_results += "<br>Gas tank status:<br>[format_gas_for_results(faketank)]"
sleep(2)
if(intervals == 10)
simulation_results += "<hr>Final Result: No detonation."
/obj/machinery/bomb_tester/proc/ttv_sim()
faketank.volume = tank1.air_contents.volume + tank2.air_contents.volume
faketank.copy_from(tank1.air_contents)
faketank_integrity = tank1.integrity
faketank.merge(tank2.air_contents)
simulation_results = "<center><h1><b>Tank Transfer Valve Mixture Test</b></h1></center>"
simulation_results += "<hr>"
simulation_results += "<br>Initial gas mixture status:<br>[format_gas_for_results(faketank)]"
var/intervals = 0
while(intervals < 10)
intervals++
simulation_results += "<hr>[intervals*2] seconds after combining."
if(simulate_tank())
break
simulation_results += "<br>Gas mixture status:<br>[format_gas_for_results(faketank)]"
sleep(2)
if(intervals == 10)
simulation_results += "<hr>Final Result: No detonation."
/obj/machinery/bomb_tester/proc/canister_sim()
test_canister.anchored = 1
faketank.volume = tank1.air_contents.volume
faketank.copy_from(tank1.air_contents)
faketank_integrity = tank1.integrity
var/datum/gas_mixture/fakecanister = new
fakecanister.volume = test_canister.air_contents.volume
fakecanister.copy_from(test_canister.air_contents)
var/fakecanister_RFL = test_canister.release_flow_rate
simulation_results = "<center><h1><b>Canister-Assisted Single Tank Ignition Test</b></h1></center>"
simulation_results += "<hr>"
simulation_results += "<br>Initial gas tank status:<br>[format_gas_for_results(faketank)]"
var/intervals = 0
while(intervals < 10)
intervals++
simulation_results += "<hr>[intervals*2] seconds after combining."
var/pressure_delta = sim_canister_output - faketank.return_pressure()
if(pressure_delta > 0)
var/transfer_moles = calculate_transfer_moles(fakecanister, faketank, pressure_delta)
transfer_moles = min(transfer_moles, (fakecanister_RFL/fakecanister.volume)*fakecanister.total_moles)
pump_gas_passive(src, fakecanister, faketank, transfer_moles)
if(simulate_tank())
break
simulation_results += "<br>Gas tank status:<br>[format_gas_for_results(faketank)]"
sleep(2)
if(intervals == 10)
simulation_results += "<hr>Final Result: No detonation."
/obj/machinery/bomb_tester/proc/simulation_finish(cancelled = 0)
simulating = 0
update_use_power(1)
update_icon()
if(test_canister && test_canister.anchored && !test_canister.connected_port)
test_canister.anchored = 0
if(cancelled)
return
if(simulation_results == "Error")
playsound(get_turf(src), 'sound/machines/buzz-sigh.ogg', 50, 0)
state("Invalid parameters.")
else
ping("Simulation complete!")
playsound(loc, "sound/effects/printer.ogg", 50, 1)
var/obj/item/weapon/paper/P = new(get_turf(src))
P.name = "Explosive Simulator printout"
P.info = simulation_results
/obj/machinery/bomb_tester/proc/format_gas_for_results(var/datum/gas_mixture/G)
G.update_values() //Just in case
var/results = ""
var/pressure = G.return_pressure()
results += "Pressure: [round(pressure,0.1)] kPa"
if(G.total_moles)
results += "<br>Temperature: [round(G.temperature-T0C)]&deg;C"
for(var/mix in G.gas)
results += "<br>[gas_data.name[mix]]: [round((G.gas[mix] / G.total_moles) * 100)]%"
return results
#undef MODE_SINGLE
#undef MODE_DOUBLE
#undef MODE_CANISTER
@@ -35,4 +35,14 @@
origin_tech = list(TECH_ENGINEERING = 4, TECH_POWER = 3)
req_components = list(
/obj/item/stack/cable_coil = 20,
/obj/item/weapon/stock_parts/capacitor/super = 3)
/obj/item/weapon/stock_parts/capacitor/super = 3)
// Board for the bomb tester in bomb_tester_vr.dm
/obj/item/weapon/circuitboard/bomb_tester
name = T_BOARD("explosive effect simulator")
build_path = /obj/machinery/bomb_tester
board_type = new /datum/frame/frame_types/machine
origin_tech = list(TECH_PHORON = 3, TECH_DATA = 2, TECH_MAGNET = 2)
req_components = list(
/obj/item/weapon/stock_parts/matter_bin/adv = 1,
/obj/item/weapon/stock_parts/scanning_module = 5)
@@ -6,4 +6,8 @@
/obj/effect/floor_decal/flesh/colour
name = "flesh"
icon = 'icons/turf/stomach_vr.dmi'
icon_state = "c_flesh_floor_edges"
icon_state = "c_flesh_floor_edges"
/obj/effect/floor_decal/industrial/outline/red
name = "red outline"
color = COLOR_RED
@@ -157,7 +157,8 @@
//Meters
/obj/machinery/meter
description_info = "Measures the volume and temperature of the pipe under the meter."
description_info = "Measures the volume and temperature of the pipe under the meter.\
Using a multitool on this will cycle through any other pipes on the same tile."
//Pipe dispensers
/obj/machinery/pipedispenser
+8 -1
View File
@@ -172,4 +172,11 @@
id = "thermoregulator"
req_tech = list(TECH_ENGINEERING = 4, TECH_POWER = 3)
build_path = /obj/item/weapon/circuitboard/thermoregulator
sort_string = "HABAF"
sort_string = "HABAF"
/datum/design/circuit/bomb_tester
name = "Explosive Effect Simulator"
id = "bomb_tester"
req_tech = list(TECH_PHORON = 3, TECH_DATA = 2, TECH_MAGNET = 2)
build_path = /obj/item/weapon/circuitboard/bomb_tester
sort_string = "HABAG"