MILLA phase 2 (#27659)

* MILLA phase 2

* Lint.

* Build Rust library

* Assorted bugfixes and tweaks

* Simplify fire mechanics and make hotspot sending to DM more reliable.

* Assorted tweaks, fixed an issue in the core engine and removed the softcap it made necesary.

* SM fixes, slower plasmafire, less overpowered pyro anomalies, and air alarm improvements.

* Review fixes.

* Build Rust library

* Unbalanced icon.

* Rebalance immovable rods.

* Unbalanced has alerts, can fight airflow (but get slowed)

* Build Rust library

* Stronger space cooling, slower temperature flow, faster burns, burnt floors, and a hotspot display fix.

* Build Rust library

* Tweaks to avoid merge conflict

* Oops.

* Build Rust library

* Rebalance wind.

* Rebalance temperature flow and space cooling.

* Fix gas flamethrower.

* Build Rust library

* Make air push slowdown directional, so you don't get slowed while moving with the air.

* Variable name cleanup.

* Reduce the speed of wind pushes.

* Prevent wind pushes from breaking your pull.

* Prevent swaps during wind push.

* Made supermatter crytals reliably run last in atmos machinery.

* Sped up plasmafire burning, but dropped the minimum burn amount.

* Rebalanced SM heat output.

* Rebalanced pyro anomaly.

* Build Rust library

* Lint

* Build Rust library

* Uncap fuel burnt readout.

* Added Custom air alarm mode, dropped Refill cap to ONE_ATMOSPHERE.

* Updated air alarm modes to use pressure settings instead of ONE_ATMOSPHERE

* Added a list of areas not in Filtering to atmos alert computer.

* Increase pressure gradient and vent output, especially at low distro pressure.

* Changed Immovable Rod from Moderate to Major.

* Lint

* Build Rust library

* More lint!

* Build Rust library

* Magboots, scaled slowdown, and nukie borg immunity

* Wind image

* Wind v2

* Wind v3

* pngcrush

* pngcrush again

* Moved hotspot removal into SSair, add wind effect.

* Lint

* Build Rust library

* Fix hotspots.

* Hotspot visual based on gas burnt

* Build Rust library

* Scaled wind to gas amount, stopped first wind push while moving.

* Made Rust panic logging safer.

* Made MILLA full tick and sleep timers more honest.

* Pressure overlay, ghost mode, atmos goggles.

* Build Rust library

* Lint

* Build Rust library

* More lint-y stuff.

* Build Rust library

* Repair pressure overlay if it loses its loc.

* Bind pressure overlays to their tile better.

* Build Rust library

* Make the pressure overlay work on z=1 and not proliferate effects.

* Don't block the supply shuttle.

* Don't fine for special effects.

* Maybe don't fine for ghosts, either.

* Build Rust library

* Make pressure overlay play nice with shuttles.

* Build Rust library

* Pressure scanning for borgs.

* Build Rust library

* Lint

* Build Rust library

* Made explosions not generate so much wind.

* Removed an old and non-functional proc.

* Clientless mobs can get pushed again.

* Build Rust library

* cargo fmt

* Build Rust library

* Don't divide by zero.

* Plasmafire generator for the Shadow

* Update shadow to use plasmafire generators

* Fix shadow's plasmafire generators going out on depart.

* Prevent heat2color from runtiming at absolute zero.

* Better nanofrost

* Build Rust library

* Singularity immunity

* Build Rust library

* Add back meson mode to atmospheric scanner goggles, so they don't stare deeply into the SM

* Build Rust library

* Dump panic outputs into data/ instead.

* Build Rust library

* Apply suggestions from code review

Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>
Signed-off-by: Charlie Nolan <funnyman3595@gmail.com>

* Saner handling of MILLA crash.

* Build Rust library

---------

Signed-off-by: Charlie Nolan <funnyman3595@gmail.com>
Co-authored-by: paradisess13[bot] <165046124+paradisess13[bot]@users.noreply.github.com>
Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>
This commit is contained in:
Charlie Nolan
2025-01-01 20:12:05 +00:00
committed by GitHub
co-authored by Burzah paradisess13[bot] <165046124+paradisess13[bot]@users.noreply.github.com>
parent b7c800727e
commit e6f99049f6
95 changed files with 2442 additions and 1708 deletions
+2 -8
View File
@@ -341,7 +341,6 @@
/obj/effect/anomaly/pyro
name = "pyroclastic anomaly"
icon_state = "mustard"
var/ticks = 0
var/produces_slime = TRUE
aSignal = /obj/item/assembly/signaler/anomaly/pyro
@@ -351,16 +350,11 @@
/obj/effect/anomaly/pyro/anomalyEffect()
..()
ticks++
for(var/mob/living/M in hearers(4, src))
if(prob(50))
M.adjust_fire_stacks(4)
M.IgniteMob()
if(ticks < 4)
return
else
ticks = 0
var/turf/simulated/T = get_turf(src)
if(istype(T))
var/datum/gas_mixture/air = new()
@@ -382,8 +376,8 @@
//Make it hot and burny for the new slime
var/datum/gas_mixture/air = new()
air.set_temperature(1000)
air.set_toxins(500)
air.set_oxygen(500)
air.set_toxins(125)
air.set_oxygen(125)
T.blind_release_air(air)
var/new_colour = pick("red", "orange")
var/mob/living/simple_animal/slime/S = new(T, new_colour)
@@ -175,53 +175,71 @@
name = "nanofrost smoke"
color = "#B2FFFF"
opacity = FALSE
var/spread_range = 6
lifetime = 0.5 SECONDS_TO_LIFE_CYCLES
/datum/effect_system/smoke_spread/freezing
effect_type = /obj/effect/particle_effect/smoke/freezing
var/blast = FALSE
/datum/effect_system/smoke_spread/freezing/proc/Chilled(atom/A)
if(issimulatedturf(A))
var/turf/simulated/T = A
if(!T.blocks_air)
var/datum/milla_safe/smoke_spread_chill/milla = new()
milla.invoke_async(src, T)
for(var/obj/machinery/atmospherics/unary/vent_pump/V in T)
if(!isnull(V.welded) && !V.welded) //must be an unwelded vent pump.
V.welded = TRUE
V.update_icon()
V.visible_message("<span class='danger'>[V] was frozen shut!</span>")
for(var/obj/machinery/atmospherics/unary/vent_scrubber/U in T)
if(!isnull(U.welded) && !U.welded) //must be an unwelded vent scrubber.
U.welded = TRUE
U.update_icon()
U.visible_message("<span class='danger'>[U] was frozen shut!</span>")
for(var/mob/living/L in T)
L.ExtinguishMob()
for(var/obj/item/Item in T)
Item.extinguish()
/obj/effect/particle_effect/smoke/freezing/process()
. = ..()
var/turf/T = get_turf(src)
if(!istype(T))
return
/datum/milla_safe/smoke_spread_chill
for(var/obj/machinery/atmospherics/unary/vent_pump/V in T)
if(!isnull(V.welded) && !V.welded) //must be an unwelded vent pump.
V.welded = TRUE
V.update_icon()
V.visible_message("<span class='danger'>[V] was frozen shut!</span>")
for(var/obj/machinery/atmospherics/unary/vent_scrubber/U in T)
if(!isnull(U.welded) && !U.welded) //must be an unwelded vent scrubber.
U.welded = TRUE
U.update_icon()
U.visible_message("<span class='danger'>[U] was frozen shut!</span>")
for(var/mob/living/L in T)
L.ExtinguishMob()
for(var/obj/item/Item in T)
Item.extinguish()
/datum/milla_safe/smoke_spread_chill/on_run(datum/effect_system/smoke_spread/smoke, turf/T)
var/datum/milla_safe/nanofrost_extinguish/milla = new()
milla.invoke_async(src, T)
/datum/milla_safe/nanofrost_extinguish/on_run(obj/effect/particle_effect/smoke/freezing/smoke, turf/T)
if(!istype(T))
return
var/datum/gas_mixture/env = get_turf_air(T)
if(get_dist(T, smoke) < 2) // Otherwise we'll get silliness like people using Nanofrost to kill people through walls with cold air
env.set_temperature(2)
for(var/obj/effect/hotspot/H in T)
for(var/obj/effect/hotspot/fake/H in T)
qdel(H)
if(env.toxins())
env.set_nitrogen(env.nitrogen() + env.toxins())
env.set_toxins(0)
/datum/effect_system/smoke_spread/freezing/set_up(amount = 5, only_cardinals = FALSE, source, desired_direction, datum/reagents/chemicals, blasting = FALSE)
..()
blast = blasting
if(env.fuel_burnt() == 0)
return
/datum/effect_system/smoke_spread/freezing/start()
if(blast)
for(var/turf/T in RANGE_TURFS(2, location))
Chilled(T)
..()
env.set_temperature(2)
env.set_nitrogen(env.nitrogen() + env.toxins())
env.set_toxins(0)
if(smoke.spread_range <= 0 || smoke.lifetime > 0)
return
// Spread the smoke, up to spread_range.
for(var/direction in list(NORTH, SOUTH, EAST, WEST))
var/turf/neighbor = get_step(T, direction)
if(isnull(neighbor))
continue
if(neighbor.density)
continue
var/has_nanofrost = FALSE
for(var/datum/effect_system/smoke_spread/freezing in neighbor)
has_nanofrost = TRUE
break
if(has_nanofrost)
continue
if(prob(50))
continue
var/obj/effect/particle_effect/smoke/freezing/new_smoke = new(neighbor)
new_smoke.spread_range = smoke.spread_range - 1
/////////////////////////////////////////////
// Sleep smoke
@@ -26,20 +26,20 @@
playsound(src, "sparks", 100, TRUE, SHORT_RANGE_SOUND_EXTRARANGE)
var/turf/T = loc
if(isturf(T))
T.hotspot_expose(hotspottemp, 100)
T.hotspot_expose(hotspottemp, 1)
QDEL_IN(src, 20)
/obj/effect/particle_effect/sparks/Destroy()
var/turf/T = loc
if(isturf(T))
T.hotspot_expose(hotspottemp,100)
T.hotspot_expose(hotspottemp,1)
return ..()
/obj/effect/particle_effect/sparks/Move()
..()
var/turf/T = loc
if(isturf(T))
T.hotspot_expose(hotspottemp,100)
T.hotspot_expose(hotspottemp,1)
/datum/effect_system/spark_spread
effect_type = /obj/effect/particle_effect/sparks
+1 -1
View File
@@ -104,7 +104,7 @@
qdel(src)
if(isturf(loc)) //start a fire if possible
var/turf/T = loc
T.hotspot_expose(700, 5)
T.hotspot_expose(700, 1)
/obj/item/candle/proc/unlight()
if(lit)
@@ -188,7 +188,7 @@
/obj/item/flashlight/flare/process()
var/turf/pos = get_turf(src)
if(pos && produce_heat)
pos.hotspot_expose(produce_heat, 5)
pos.hotspot_expose(produce_heat, 1)
fuel = max(fuel - 1, 0)
if(!fuel || !on)
turn_off()
+52 -64
View File
@@ -625,18 +625,17 @@ SLIME SCANNER
* Used in chat-based gas scans.
*/
/proc/atmos_scan(mob/user, atom/target, silent = FALSE, print = TRUE, milla_turf_details = FALSE)
var/mixture
var/datum/gas_mixture/air
var/list/milla = null
if(milla_turf_details)
if(milla_turf_details && istype(target, /turf))
milla = new/list(MILLA_TILE_SIZE)
get_tile_atmos(target, milla)
var/datum/gas_mixture/GM = new()
GM.copy_from_milla(milla)
mixture = GM
air = new()
air.copy_from_milla(milla)
else
mixture = target.return_analyzable_air()
if(!mixture)
return FALSE
air = target.return_analyzable_air()
if(!air)
return FALSE
var/list/message = list()
if(!silent && isliving(user))
@@ -646,64 +645,53 @@ SLIME SCANNER
if(!print)
return TRUE
var/list/airs = islist(mixture) ? mixture : list(mixture)
for(var/datum/gas_mixture/air as anything in airs)
var/mix_name = capitalize(lowertext(target.name))
if(length(air) > 1) //not a unary gas mixture
var/mix_number = airs.Find(air)
message += "<span class='boldnotice'>Node [mix_number]</span>"
mix_name += " - Node [mix_number]"
var/total_moles = air.total_moles()
var/pressure = air.return_pressure()
var/volume = air.return_volume() //could just do mixture.volume... but safety, I guess?
var/heat_capacity = air.heat_capacity()
var/thermal_energy = air.thermal_energy()
var/total_moles = air.total_moles()
var/pressure = air.return_pressure()
var/volume = air.return_volume() //could just do mixture.volume... but safety, I guess?
var/heat_capacity = air.heat_capacity()
var/thermal_energy = air.thermal_energy()
if(total_moles)
message += "<span class='notice'>Total: [round(total_moles, 0.01)] moles</span>"
if(air.oxygen() && (milla_turf_details || air.oxygen() / total_moles > 0.01))
message += " <span class='oxygen'>Oxygen: [round(air.oxygen(), 0.01)] moles ([round(air.oxygen() / total_moles * 100, 0.01)] %)</span>"
if(air.nitrogen() && (milla_turf_details || air.nitrogen() / total_moles > 0.01))
message += " <span class='nitrogen'>Nitrogen: [round(air.nitrogen(), 0.01)] moles ([round(air.nitrogen() / total_moles * 100, 0.01)] %)</span>"
if(air.carbon_dioxide() && (milla_turf_details || air.carbon_dioxide() / total_moles > 0.01))
message += " <span class='carbon_dioxide'>Carbon Dioxide: [round(air.carbon_dioxide(), 0.01)] moles ([round(air.carbon_dioxide() / total_moles * 100, 0.01)] %)</span>"
if(air.toxins() && (milla_turf_details || air.toxins() / total_moles > 0.01))
message += " <span class='plasma'>Plasma: [round(air.toxins(), 0.01)] moles ([round(air.toxins() / total_moles * 100, 0.01)] %)</span>"
if(air.sleeping_agent() && (milla_turf_details || air.sleeping_agent() / total_moles > 0.01))
message += " <span class='sleeping_agent'>Nitrous Oxide: [round(air.sleeping_agent(), 0.01)] moles ([round(air.sleeping_agent() / total_moles * 100, 0.01)] %)</span>"
if(air.agent_b() && (milla_turf_details || air.agent_b() / total_moles > 0.01))
message += " <span class='agent_b'>Agent B: [round(air.agent_b(), 0.01)] moles ([round(air.agent_b() / total_moles * 100, 0.01)] %)</span>"
message += "<span class='notice'>Temperature: [round(air.temperature()-T0C)] &deg;C ([round(air.temperature())] K)</span>"
message += "<span class='notice'>Volume: [round(volume)] Liters</span>"
message += "<span class='notice'>Pressure: [round(pressure, 0.1)] kPa</span>"
message += "<span class='notice'>Heat Capacity: [DisplayJoules(heat_capacity)] / K</span>"
message += "<span class='notice'>Thermal Energy: [DisplayJoules(thermal_energy)]</span>"
else
message += "<span class='notice'>[target] is empty!</span>"
message += "<span class='notice'>Volume: [round(volume)] Liters</span>" // don't want to change the order volume appears in, suck it
if(total_moles)
message += "<span class='notice'>Total: [round(total_moles, 0.01)] moles</span>"
if(air.oxygen() && (milla_turf_details || air.oxygen() / total_moles > 0.01))
message += " <span class='oxygen'>Oxygen: [round(air.oxygen(), 0.01)] moles ([round(air.oxygen() / total_moles * 100, 0.01)] %)</span>"
if(air.nitrogen() && (milla_turf_details || air.nitrogen() / total_moles > 0.01))
message += " <span class='nitrogen'>Nitrogen: [round(air.nitrogen(), 0.01)] moles ([round(air.nitrogen() / total_moles * 100, 0.01)] %)</span>"
if(air.carbon_dioxide() && (milla_turf_details || air.carbon_dioxide() / total_moles > 0.01))
message += " <span class='carbon_dioxide'>Carbon Dioxide: [round(air.carbon_dioxide(), 0.01)] moles ([round(air.carbon_dioxide() / total_moles * 100, 0.01)] %)</span>"
if(air.toxins() && (milla_turf_details || air.toxins() / total_moles > 0.01))
message += " <span class='plasma'>Plasma: [round(air.toxins(), 0.01)] moles ([round(air.toxins() / total_moles * 100, 0.01)] %)</span>"
if(air.sleeping_agent() && (milla_turf_details || air.sleeping_agent() / total_moles > 0.01))
message += " <span class='sleeping_agent'>Nitrous Oxide: [round(air.sleeping_agent(), 0.01)] moles ([round(air.sleeping_agent() / total_moles * 100, 0.01)] %)</span>"
if(air.agent_b() && (milla_turf_details || air.agent_b() / total_moles > 0.01))
message += " <span class='agent_b'>Agent B: [round(air.agent_b(), 0.01)] moles ([round(air.agent_b() / total_moles * 100, 0.01)] %)</span>"
message += "<span class='notice'>Temperature: [round(air.temperature()-T0C)] &deg;C ([round(air.temperature())] K)</span>"
message += "<span class='notice'>Volume: [round(volume)] Liters</span>"
message += "<span class='notice'>Pressure: [round(pressure, 0.1)] kPa</span>"
message += "<span class='notice'>Heat Capacity: [DisplayJoules(heat_capacity)] / K</span>"
message += "<span class='notice'>Thermal Energy: [DisplayJoules(thermal_energy)]</span>"
else
message += length(airs) > 1 ? "<span class='notice'>This node is empty!</span>" : "<span class='notice'>[target] is empty!</span>"
message += "<span class='notice'>Volume: [round(volume)] Liters</span>" // don't want to change the order volume appears in, suck it
if(milla)
// Values from milla/src/lib.rs, +1 due to array indexing difference.
message += "<span class='notice'>Airtight North: [(milla[MILLA_INDEX_AIRTIGHT_DIRECTIONS] & MILLA_NORTH) ? "yes" : "no"]</span>"
message += "<span class='notice'>Airtight East: [(milla[MILLA_INDEX_AIRTIGHT_DIRECTIONS] & MILLA_EAST) ? "yes" : "no"]</span>"
message += "<span class='notice'>Airtight South: [(milla[MILLA_INDEX_AIRTIGHT_DIRECTIONS] & MILLA_SOUTH) ? "yes" : "no"]</span>"
message += "<span class='notice'>Airtight West: [(milla[MILLA_INDEX_AIRTIGHT_DIRECTIONS] & MILLA_WEST) ? "yes" : "no"]</span>"
switch(milla[MILLA_INDEX_ATMOS_MODE])
// These are enum values, so they don't get increased.
if(0)
message += "<span class='notice'>Atmos Mode: Space</span>"
if(1)
message += "<span class='notice'>Atmos Mode: Sealed</span>"
if(2)
message += "<span class='notice'>Atmos Mode: Exposed to Environment (ID: [milla[MILLA_INDEX_ENVIRONMENT_ID]])</span>"
else
message += "<span class='notice'>Atmos Mode: Unknown ([milla[MILLA_INDEX_ATMOS_MODE]]), contact a coder.</span>"
message += "<span class='notice'>Superconductivity North: [milla[MILLA_INDEX_SUPERCONDUCTIVITY_NORTH]]</span>"
message += "<span class='notice'>Superconductivity East: [milla[MILLA_INDEX_SUPERCONDUCTIVITY_EAST]]</span>"
message += "<span class='notice'>Superconductivity South: [milla[MILLA_INDEX_SUPERCONDUCTIVITY_SOUTH]]</span>"
message += "<span class='notice'>Superconductivity West: [milla[MILLA_INDEX_SUPERCONDUCTIVITY_WEST]]</span>"
message += "<span class='notice'>Turf's Innate Heat Capacity: [milla[MILLA_INDEX_INNATE_HEAT_CAPACITY]]</span>"
if(milla)
// Values from milla/src/lib.rs, +1 due to array indexing difference.
message += "<span class='notice'>Airtight N/E/S/W: [(milla[MILLA_INDEX_AIRTIGHT_DIRECTIONS] & MILLA_NORTH) ? "yes" : "no"]/[(milla[MILLA_INDEX_AIRTIGHT_DIRECTIONS] & MILLA_EAST) ? "yes" : "no"]/[(milla[MILLA_INDEX_AIRTIGHT_DIRECTIONS] & MILLA_SOUTH) ? "yes" : "no"]/[(milla[MILLA_INDEX_AIRTIGHT_DIRECTIONS] & MILLA_WEST) ? "yes" : "no"]</span>"
switch(milla[MILLA_INDEX_ATMOS_MODE])
// These are enum values, so they don't get increased.
if(0)
message += "<span class='notice'>Atmos Mode: Space</span>"
if(1)
message += "<span class='notice'>Atmos Mode: Sealed</span>"
if(2)
message += "<span class='notice'>Atmos Mode: Exposed to Environment (ID: [milla[MILLA_INDEX_ENVIRONMENT_ID]])</span>"
else
message += "<span class='notice'>Atmos Mode: Unknown ([milla[MILLA_INDEX_ATMOS_MODE]]), contact a coder.</span>"
message += "<span class='notice'>Superconductivity N/E/S/W: [milla[MILLA_INDEX_SUPERCONDUCTIVITY_NORTH]]/[milla[MILLA_INDEX_SUPERCONDUCTIVITY_EAST]]/[milla[MILLA_INDEX_SUPERCONDUCTIVITY_SOUTH]]/[milla[MILLA_INDEX_SUPERCONDUCTIVITY_WEST]]</span>"
message += "<span class='notice'>Turf's Innate Heat Capacity: [milla[MILLA_INDEX_INNATE_HEAT_CAPACITY]]</span>"
message += "<span class='notice'>Hotspot: [floor(milla[MILLA_INDEX_HOTSPOT_TEMPERATURE]-T0C)] &deg;C ([floor(milla[MILLA_INDEX_HOTSPOT_TEMPERATURE])] K), [round(milla[MILLA_INDEX_HOTSPOT_VOLUME] * CELL_VOLUME, 1)] Liters ([milla[MILLA_INDEX_HOTSPOT_VOLUME]]x)</span>"
message += "<span class='notice'>Wind: ([round(milla[MILLA_INDEX_WIND_X], 0.001)], [round(milla[MILLA_INDEX_WIND_Y], 0.001)])</span>"
message += "<span class='notice'>Fuel burnt last tick: [milla[MILLA_INDEX_FUEL_BURNT]] moles</span>"
to_chat(user, chat_box_examine(message.Join("\n")))
return TRUE
+1 -1
View File
@@ -71,7 +71,7 @@
if(tool_enabled)
var/turf/T = get_turf(src)
if(T) // Implants for instance won't find a turf
T.hotspot_expose(2500, 5)
T.hotspot_expose(2500, 1)
if(prob(5))
remove_fuel(1)
if(refills_over_time)
+1 -1
View File
@@ -269,7 +269,7 @@ LIGHTERS ARE IN LIGHTERS.DM
// There used to be a species check here, but synthetics can smoke now
is_being_smoked = TRUE
if(location)
location.hotspot_expose(700, 5)
location.hotspot_expose(700, 1)
if(reagents && reagents.total_volume) // check if it has any reagents at all
if(is_being_smoked) // if it's being smoked, transfer reagents to the mob
var/mob/living/carbon/C = loc
+2 -2
View File
@@ -135,7 +135,7 @@
/obj/item/lighter/process()
var/turf/location = get_turf(src)
if(location)
location.hotspot_expose(700, 5)
location.hotspot_expose(700, 1)
return
/obj/item/lighter/update_icon_state()
@@ -263,7 +263,7 @@
if(smoketime < 1)
matchburnout()
if(location)
location.hotspot_expose(700, 5)
location.hotspot_expose(700, 1)
return
/obj/item/match/fire_act(datum/gas_mixture/air, exposed_temperature, exposed_volume, global_overlay = TRUE)
@@ -154,7 +154,7 @@
/obj/item/bio_chip_implanter/shock, // 50TC
/obj/item/dnainjector/telemut/darkbundle, // 0TC
/obj/item/clothing/suit/hooded/chaplain_hoodie, // 0TC
/obj/item/clothing/glasses/meson/engine/tray, // 0TC
/obj/item/clothing/glasses/meson/engine/atmos, // 0TC
/obj/item/clothing/mask/chameleon/voice_change, // 10TC
/obj/item/card/id/syndicate, // 10TC
/obj/item/clothing/shoes/chameleon/noslip, // 10TC
@@ -328,7 +328,7 @@
/obj/effect/nanofrost_container/proc/Smoke()
var/datum/effect_system/smoke_spread/freezing/S = new
S.set_up(amount = 6, only_cardinals = FALSE, source = loc, desired_direction = null, chemicals = null, blasting = TRUE)
S.set_up(amount = 6, only_cardinals = FALSE, source = loc)
S.start()
new /obj/effect/decal/cleanable/flour/nanofrost(get_turf(src))
playsound(src, 'sound/effects/bamf.ogg', 100, TRUE)
@@ -22,6 +22,7 @@
new /obj/item/holosign_creator/engineering(src)
new /obj/item/flash(src)
new /obj/item/clothing/glasses/meson/engine(src)
new /obj/item/clothing/glasses/meson/engine/atmos(src)
new /obj/item/door_remote/chief_engineer(src)
new /obj/item/rpd(src)
new /obj/item/reagent_containers/drinks/mug/ce(src)
@@ -119,6 +120,6 @@
new /obj/item/watertank/atmos(src)
new /obj/item/clothing/suit/fire/firefighter/atmos(src)
new /obj/item/clothing/head/hardhat/atmos(src)
new /obj/item/clothing/glasses/meson/engine(src)
new /obj/item/clothing/glasses/meson/engine/atmos(src)
new /obj/item/rpd(src)
new /obj/item/dest_tagger(src)
@@ -0,0 +1,41 @@
/obj/structure/plasmafire_generator
name = "Plasmafire Generator"
desc = "A magical thing that you really shouldn't be able to see."
anchored = TRUE
alpha = 0
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
resistance_flags = LAVA_PROOF | FIRE_PROOF
flags = NODECONSTRUCT
/obj/structure/plasmafire_generator/Initialize(mapload)
. = ..()
START_PROCESSING(SSprocessing, src)
// for sanity checks
/obj/structure/plasmafire_generator/Destroy()
STOP_PROCESSING(SSprocessing, src)
return ..()
/obj/structure/plasmafire_generator/process()
var/turf/T = get_turf(src)
if(!istype(T))
return
var/datum/gas_mixture/fire = new()
fire.set_toxins(10)
fire.set_oxygen(4)
fire.set_temperature(500)
T.blind_release_air(fire)
/obj/structure/plasmafire_generator/shadow
var/enabled = FALSE
/obj/structure/plasmafire_generator/shadow/onShuttleMove(turf/oldT, turf/T1, rotation, mob/caller)
if(T1.z != 1)
enabled = TRUE
return ..()
/obj/structure/plasmafire_generator/shadow/process()
if(!enabled)
return
return ..()