mirror of
https://github.com/yogstation13/Yogstation.git
synced 2025-02-26 09:04:50 +00:00
Ports SSfoam and SSsmoke (#17742)
* Ports SSfoam and SSsmoke * Remove dupe define
This commit is contained in:
@@ -103,3 +103,11 @@
|
||||
PreInit();\
|
||||
}\
|
||||
/datum/controller/subsystem/processing/##X
|
||||
|
||||
#define FLUID_SUBSYSTEM_DEF(X) GLOBAL_REAL(SS##X, /datum/controller/subsystem/fluids/##X);\
|
||||
/datum/controller/subsystem/fluids/##X/New(){\
|
||||
NEW_SS_GLOBAL(SS##X);\
|
||||
PreInit();\
|
||||
}\
|
||||
/datum/controller/subsystem/fluids/##X/fire() {..() /*just so it shows up on the profiler*/} \
|
||||
/datum/controller/subsystem/fluids/##X
|
||||
|
||||
@@ -36,6 +36,9 @@
|
||||
// Similar to clamp but the bottom rolls around to the top and vice versa. min is inclusive, max is exclusive
|
||||
#define WRAP(val, min, max) ( min == max ? min : (val) - (round(((val) - (min))/((max) - (min))) * ((max) - (min))) )
|
||||
|
||||
/// Increments a value and wraps it if it exceeds some value. Can be used to circularly iterate through a list through `idx = WRAP_UP(idx, length_of_list)`.
|
||||
#define WRAP_UP(val, max) (((val) % (max)) + 1)
|
||||
|
||||
// Real modulus that handles decimals
|
||||
#define MODULUS(x, y) ( (x) - (y) * round((x) / (y)) )
|
||||
|
||||
@@ -220,3 +223,6 @@
|
||||
/// Like DT_PROB_RATE but easier to use, simply put `if(DT_PROB(10, 5))`
|
||||
#define DT_PROB(prob_per_second_percent, delta_time) (prob(100*DT_PROB_RATE(prob_per_second_percent/100, delta_time)))
|
||||
// )
|
||||
|
||||
/// The number of cells in a taxicab circle (rasterized diamond) of radius X.
|
||||
#define DIAMOND_AREA(X) (1 + 2*(X)*((X)+1))
|
||||
|
||||
@@ -175,6 +175,7 @@
|
||||
#define FIRE_PRIORITY_VIS 10
|
||||
#define FIRE_PRIORITY_GARBAGE 15
|
||||
#define FIRE_PRIORITY_WET_FLOORS 20
|
||||
#define FIRE_PRIORITY_FLUIDS 20
|
||||
#define FIRE_PRIORITY_AIR 20
|
||||
#define FIRE_PRIORITY_NPC 20
|
||||
#define FIRE_PRIORITY_PROCESS 25
|
||||
@@ -261,7 +262,7 @@
|
||||
|
||||
// Subsystem delta times or tickrates, in seconds. I.e, how many seconds in between each process() call for objects being processed by that subsystem.
|
||||
// Only use these defines if you want to access some other objects processing delta_time, otherwise use the delta_time that is sent as a parameter to process()
|
||||
#define SSFLUIDS_DT (SSfluids.wait/10)
|
||||
#define SSFLUIDS_DT (SSplumbing.wait/10)
|
||||
#define SSMACHINES_DT (SSmachines.wait/10)
|
||||
#define SSMOBS_DT (SSmobs.wait/10)
|
||||
#define SSOBJ_DT (SSobj.wait/10)
|
||||
|
||||
@@ -18,8 +18,16 @@
|
||||
#define LAZYACCESS(L, I) (L ? (isnum(I) ? (I > 0 && I <= length(L) ? L[I] : null) : L[I]) : null)
|
||||
#define LAZYSET(L, K, V) if(!L) { L = list(); } L[K] = V;
|
||||
#define LAZYLEN(L) length(L)
|
||||
#define LAZYCLEARLIST(L) if(L) L.Cut()
|
||||
///Accesses an associative list, returns null if nothing is found
|
||||
#define LAZYACCESSASSOC(L, I, K) L ? L[I] ? L[I][K] ? L[I][K] : null : null : null
|
||||
///Qdel every item in the list before setting the list to null
|
||||
#define QDEL_LAZYLIST(L) for(var/I in L) qdel(I); L = null;
|
||||
//These methods don't null the list
|
||||
///Use LAZYLISTDUPLICATE instead if you want it to null with no entries
|
||||
#define LAZYCOPY(L) (L ? L.Copy() : list() )
|
||||
/// Consider LAZYNULL instead
|
||||
#define LAZYCLEARLIST(L) if(L) L.Cut()
|
||||
///Returns the list if it's actually a valid list, otherwise will initialize it
|
||||
#define SANITIZE_LIST(L) ( islist(L) ? L : list() )
|
||||
#define reverseList(L) reverseRange(L.Copy())
|
||||
#define LAZYADDASSOC(L, K, V) if(!L) { L = list(); } L[K] += list(V);
|
||||
|
||||
@@ -72,3 +72,17 @@
|
||||
if(!GLOB.chemical_reactions_list[primary_reagent])
|
||||
GLOB.chemical_reactions_list[primary_reagent] = list()
|
||||
GLOB.chemical_reactions_list[primary_reagent] += R
|
||||
|
||||
//Creates foam from the reagent. Metaltype is for metal foam, notification is what to show people in textbox
|
||||
/datum/reagents/proc/create_foam(foamtype, foam_volume, result_type = null, notification = null, log = FALSE)
|
||||
var/location = get_turf(my_atom)
|
||||
|
||||
var/datum/effect_system/fluid_spread/foam/foam = new foamtype()
|
||||
foam.set_up(amount = foam_volume, holder = my_atom, location = location, carry = src, result_type = result_type)
|
||||
foam.start(log = log)
|
||||
|
||||
clear_reagents()
|
||||
if(!notification)
|
||||
return
|
||||
for(var/mob/M in viewers(5, location))
|
||||
to_chat(M, notification)
|
||||
|
||||
261
code/controllers/subsystem/fluids.dm
Normal file
261
code/controllers/subsystem/fluids.dm
Normal file
@@ -0,0 +1,261 @@
|
||||
// Flags indicating what parts of the fluid the subsystem processes.
|
||||
/// Indicates that a fluid subsystem processes fluid spreading.
|
||||
#define SS_PROCESSES_SPREADING (1<<0)
|
||||
/// Indicates that a fluid subsystem processes fluid effects.
|
||||
#define SS_PROCESSES_EFFECTS (1<<1)
|
||||
|
||||
/**
|
||||
* # Fluid Subsystem
|
||||
*
|
||||
* A subsystem that processes the propagation and effects of a particular fluid.
|
||||
*
|
||||
* Both fluid spread and effect processing are handled through a carousel system.
|
||||
* Fluids being spread and fluids being processed are organized into buckets.
|
||||
* Each fresh (non-resumed) fire one bucket of each is selected to be processed.
|
||||
* These selected buckets are then fully processed.
|
||||
* The next fresh fire selects the next bucket in each set for processing.
|
||||
* If this would walk off the end of a carousel list we wrap back to the first element.
|
||||
* This effectively makes each set a circular list, hence a carousel.
|
||||
*/
|
||||
SUBSYSTEM_DEF(fluids)
|
||||
name = "Fluid"
|
||||
wait = 0 // Will be autoset to whatever makes the most sense given the spread and effect waits.
|
||||
flags = SS_BACKGROUND|SS_KEEP_TIMING
|
||||
runlevels = RUNLEVEL_GAME|RUNLEVEL_POSTGAME
|
||||
|
||||
// Fluid spread processing:
|
||||
/// The amount of time (in deciseconds) before a fluid node is created and when it spreads.
|
||||
var/spread_wait = 1 SECONDS
|
||||
/// The number of buckets in the spread carousel.
|
||||
var/num_spread_buckets
|
||||
/// The set of buckets containing fluid nodes to spread.
|
||||
var/list/spread_carousel
|
||||
/// The index of the spread carousel bucket currently being processed.
|
||||
var/spread_bucket_index
|
||||
/// The set of fluid nodes we are currently processing spreading for.
|
||||
var/list/currently_spreading
|
||||
/// Whether the subsystem has resumed spreading fluid.
|
||||
var/resumed_spreading
|
||||
|
||||
// Fluid effect processing:
|
||||
/// The amount of time (in deciseconds) between effect processing ticks for each fluid node.
|
||||
var/effect_wait = 1 SECONDS
|
||||
/// The number of buckets in the effect carousel.
|
||||
var/num_effect_buckets
|
||||
/// The set of buckets containing fluid nodes to process effects for.
|
||||
var/list/effect_carousel
|
||||
/// The index of the currently processing bucket on the effect carousel.
|
||||
var/effect_bucket_index
|
||||
/// The set of fluid nodes we are currently processing effects for.
|
||||
var/list/currently_processing
|
||||
/// Whether the subsystem has resumed processing fluid effects.
|
||||
var/resumed_effect_processing
|
||||
|
||||
/datum/controller/subsystem/fluids/Initialize()
|
||||
initialize_waits()
|
||||
initialize_spread_carousel()
|
||||
initialize_effect_carousel()
|
||||
return SS_INIT_SUCCESS
|
||||
|
||||
/**
|
||||
* Initializes the subsystem waits.
|
||||
*
|
||||
* Ensures that the subsystem's fire wait evenly splits the spread and effect waits.
|
||||
*/
|
||||
/datum/controller/subsystem/fluids/proc/initialize_waits()
|
||||
if (spread_wait <= 0)
|
||||
WARNING("[src] has the invalid spread wait [spread_wait].")
|
||||
spread_wait = 1 SECONDS
|
||||
if (effect_wait <= 0)
|
||||
WARNING("[src] has the invalid effect wait [effect_wait].")
|
||||
spread_wait = 1 SECONDS
|
||||
|
||||
// Sets the overall wait of the subsystem to evenly divide both the effect and spread waits.
|
||||
var/max_wait = Gcd(spread_wait, effect_wait)
|
||||
if (max_wait < wait || wait <= 0)
|
||||
wait = max_wait
|
||||
else
|
||||
// If the wait of the subsystem overall is set to a valid value make the actual wait of the subsystem evenly divide that as well.
|
||||
// Makes effect bubbling possible with identical spread and effect waits.
|
||||
wait = Gcd(wait, max_wait)
|
||||
|
||||
|
||||
/**
|
||||
* Initializes the carousel used to process fluid spreading.
|
||||
*
|
||||
* Synchronizes the spread delta time with the actual target spread tick rate.
|
||||
* Builds the carousel buckets used to queue spreads.
|
||||
*/
|
||||
/datum/controller/subsystem/fluids/proc/initialize_spread_carousel()
|
||||
// Make absolutely certain that the spread wait is in sync with the target spread tick rate.
|
||||
num_spread_buckets = round(spread_wait / wait)
|
||||
spread_wait = wait * num_spread_buckets
|
||||
|
||||
spread_carousel = list()
|
||||
spread_carousel.len = num_spread_buckets
|
||||
for(var/i in 1 to num_spread_buckets)
|
||||
spread_carousel[i] = list()
|
||||
currently_spreading = list()
|
||||
spread_bucket_index = 1
|
||||
|
||||
/**
|
||||
* Initializes the carousel used to process fluid effects.
|
||||
*
|
||||
* Synchronizes the spread delta time with the actual target spread tick rate.
|
||||
* Builds the carousel buckets used to bubble processing.
|
||||
*/
|
||||
/datum/controller/subsystem/fluids/proc/initialize_effect_carousel()
|
||||
// Make absolutely certain that the effect wait is in sync with the target effect tick rate.
|
||||
num_effect_buckets = round(effect_wait / wait)
|
||||
effect_wait = wait * num_effect_buckets
|
||||
|
||||
effect_carousel = list()
|
||||
effect_carousel.len = num_effect_buckets
|
||||
for(var/i in 1 to num_effect_buckets)
|
||||
effect_carousel[i] = list()
|
||||
currently_processing = list()
|
||||
effect_bucket_index = 1
|
||||
|
||||
|
||||
/datum/controller/subsystem/fluids/fire(resumed)
|
||||
var/delta_time
|
||||
var/cached_bucket_index
|
||||
var/list/obj/effect/particle_effect/fluid/currentrun
|
||||
MC_SPLIT_TICK_INIT(2)
|
||||
|
||||
MC_SPLIT_TICK // Start processing fluid spread:
|
||||
if(!resumed_spreading)
|
||||
spread_bucket_index = WRAP_UP(spread_bucket_index, num_spread_buckets)
|
||||
currently_spreading = spread_carousel[spread_bucket_index]
|
||||
spread_carousel[spread_bucket_index] = list() // Reset the bucket so we don't process an _entire station's worth of foam_ spreading every 2 ticks when the foam flood event happens.
|
||||
resumed_spreading = TRUE
|
||||
|
||||
delta_time = spread_wait / (1 SECONDS)
|
||||
currentrun = currently_spreading
|
||||
while(currentrun.len)
|
||||
var/obj/effect/particle_effect/fluid/to_spread = currentrun[currentrun.len]
|
||||
currentrun.len--
|
||||
|
||||
if(!QDELETED(to_spread))
|
||||
to_spread.spread(delta_time)
|
||||
to_spread.spread_bucket = null
|
||||
|
||||
if (MC_TICK_CHECK)
|
||||
break
|
||||
|
||||
if(!currentrun.len)
|
||||
resumed_spreading = FALSE
|
||||
|
||||
MC_SPLIT_TICK // Start processing fluid effects:
|
||||
if(!resumed_effect_processing)
|
||||
effect_bucket_index = WRAP_UP(effect_bucket_index, num_effect_buckets)
|
||||
var/list/tmp_list = effect_carousel[effect_bucket_index]
|
||||
currently_processing = tmp_list.Copy()
|
||||
resumed_effect_processing = TRUE
|
||||
|
||||
delta_time = effect_wait / (1 SECONDS)
|
||||
cached_bucket_index = effect_bucket_index
|
||||
currentrun = currently_processing
|
||||
while(currentrun.len)
|
||||
var/obj/effect/particle_effect/fluid/to_process = currentrun[currentrun.len]
|
||||
currentrun.len--
|
||||
|
||||
if (QDELETED(to_process) || to_process.process(delta_time) == PROCESS_KILL)
|
||||
effect_carousel[cached_bucket_index] -= to_process
|
||||
to_process.effect_bucket = null
|
||||
to_process.datum_flags &= ~DF_ISPROCESSING
|
||||
|
||||
if (MC_TICK_CHECK)
|
||||
break
|
||||
|
||||
if(!currentrun.len)
|
||||
resumed_effect_processing = FALSE
|
||||
|
||||
|
||||
/**
|
||||
* Queues a fluid node to spread later after one full carousel rotation.
|
||||
*
|
||||
* Arguments:
|
||||
* - [node][/obj/effect/particle_effect/fluid]: The node to queue to spread.
|
||||
*/
|
||||
/datum/controller/subsystem/fluids/proc/queue_spread(obj/effect/particle_effect/fluid/node)
|
||||
if (node.spread_bucket)
|
||||
return
|
||||
|
||||
spread_carousel[spread_bucket_index] += node
|
||||
node.spread_bucket = spread_bucket_index
|
||||
|
||||
/**
|
||||
* Cancels a queued spread of a fluid node.
|
||||
*
|
||||
* Arguments:
|
||||
* - [node][/obj/effect/particle_effect/fluid]: The node to cancel the spread of.
|
||||
*/
|
||||
/datum/controller/subsystem/fluids/proc/cancel_spread(obj/effect/particle_effect/fluid/node)
|
||||
if(!node.spread_bucket)
|
||||
return
|
||||
|
||||
var/bucket_index = node.spread_bucket
|
||||
spread_carousel[bucket_index] -= node
|
||||
if (bucket_index == spread_bucket_index)
|
||||
currently_spreading -= node
|
||||
|
||||
node.spread_bucket = null
|
||||
|
||||
/**
|
||||
* Starts processing the effects of a fluid node.
|
||||
*
|
||||
* The fluid node will next process after one full bucket rotation.
|
||||
*
|
||||
* Arguments:
|
||||
* - [node][/obj/effect/particle_effect/fluid]: The node to start processing.
|
||||
*/
|
||||
/datum/controller/subsystem/fluids/proc/start_processing(obj/effect/particle_effect/fluid/node)
|
||||
if (node.datum_flags & DF_ISPROCESSING || node.effect_bucket)
|
||||
return
|
||||
|
||||
// Edit this value to make all fluids process effects (at the same time|offset by when they started processing| -> offset by a random amount <- )
|
||||
var/bucket_index = rand(1, num_effect_buckets)
|
||||
effect_carousel[bucket_index] += node
|
||||
node.effect_bucket = bucket_index
|
||||
node.datum_flags |= DF_ISPROCESSING
|
||||
|
||||
/**
|
||||
* Stops processing the effects of a fluid node.
|
||||
*
|
||||
* Arguments:
|
||||
* - [node][/obj/effect/particle_effect/fluid]: The node to stop processing.
|
||||
*/
|
||||
/datum/controller/subsystem/fluids/proc/stop_processing(obj/effect/particle_effect/fluid/node)
|
||||
if(!(node.datum_flags & DF_ISPROCESSING))
|
||||
return
|
||||
|
||||
var/bucket_index = node.effect_bucket
|
||||
if(!bucket_index)
|
||||
return
|
||||
|
||||
effect_carousel[bucket_index] -= node
|
||||
if (bucket_index == effect_bucket_index)
|
||||
currently_processing -= node
|
||||
|
||||
node.effect_bucket = null
|
||||
node.datum_flags &= ~DF_ISPROCESSING
|
||||
|
||||
#undef SS_PROCESSES_SPREADING
|
||||
#undef SS_PROCESSES_EFFECTS
|
||||
|
||||
|
||||
// Subtypes:
|
||||
|
||||
/// The subsystem responsible for processing smoke propagation and effects.
|
||||
FLUID_SUBSYSTEM_DEF(smoke)
|
||||
name = "Smoke"
|
||||
spread_wait = 0.1 SECONDS
|
||||
effect_wait = 2.0 SECONDS
|
||||
|
||||
/// The subsystem responsible for processing foam propagation and effects.
|
||||
FLUID_SUBSYSTEM_DEF(foam)
|
||||
name = "Foam"
|
||||
wait = 0.1 SECONDS // Makes effect bubbling work with foam.
|
||||
spread_wait = 0.2 SECONDS
|
||||
effect_wait = 0.2 SECONDS
|
||||
@@ -1,5 +1,5 @@
|
||||
PROCESSING_SUBSYSTEM_DEF(fluids)
|
||||
name = "Fluids"
|
||||
PROCESSING_SUBSYSTEM_DEF(plumbing)
|
||||
name = "Plumbing"
|
||||
wait = 10
|
||||
stat_tag = "FD" //its actually Fluid Ducts
|
||||
flags = SS_NO_INIT
|
||||
@@ -29,7 +29,7 @@
|
||||
|
||||
/datum/component/plumbing/process()
|
||||
if(!demand_connects || !reagents)
|
||||
STOP_PROCESSING(SSfluids, src)
|
||||
STOP_PROCESSING(SSplumbing, src)
|
||||
return
|
||||
if(reagents.total_volume < reagents.maximum_volume)
|
||||
for(var/D in GLOB.cardinals)
|
||||
@@ -117,7 +117,7 @@
|
||||
/datum/component/plumbing/proc/disable() //we stop acting like a plumbing thing and disconnect if we are, so we can safely be moved and stuff
|
||||
if(!active)
|
||||
return
|
||||
STOP_PROCESSING(SSfluids, src)
|
||||
STOP_PROCESSING(SSplumbing, src)
|
||||
for(var/A in ducts)
|
||||
var/datum/ductnet/D = ducts[A]
|
||||
D.remove_plumber(src)
|
||||
@@ -131,7 +131,7 @@
|
||||
active = TRUE
|
||||
|
||||
if(demand_connects)
|
||||
START_PROCESSING(SSfluids, src)
|
||||
START_PROCESSING(SSplumbing, src)
|
||||
|
||||
for(var/D in GLOB.cardinals)
|
||||
if(D & (demand_connects + supply_connects))
|
||||
|
||||
@@ -35,7 +35,9 @@
|
||||
if(cooldown_time > world.time)
|
||||
to_chat(user, span_danger("[src] cannot be activated for <b>[DisplayTimeText(world.time - cooldown_time)]</b>."))
|
||||
return
|
||||
new /obj/effect/particle_effect/foam(loc)
|
||||
var/datum/effect_system/fluid_spread/foam/foam = new
|
||||
foam.set_up(4, holder = src, location = loc)
|
||||
foam.start()
|
||||
uses--
|
||||
to_chat(user, span_notice("You activate [src]. It now has <b>[uses]</b> uses of foam remaining."))
|
||||
cooldown = world.time + cooldown_time
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
var/datum/action/innate/mecha/mech_toggle_thrusters/thrusters_action = new
|
||||
var/datum/action/innate/mecha/mech_defence_mode/defence_action = new
|
||||
var/datum/action/innate/mecha/mech_overload_mode/overload_action = new
|
||||
var/datum/effect_system/smoke_spread/smoke_system = new //not an action, but trigged by one
|
||||
var/datum/effect_system/fluid_spread/smoke/smoke_system = new //not an action, but trigged by one
|
||||
var/datum/action/innate/mecha/mech_smoke/smoke_action = new
|
||||
var/datum/action/innate/mecha/mech_zoom/zoom_action = new
|
||||
var/datum/action/innate/mecha/mech_switch_damtype/switch_damtype_action = new
|
||||
@@ -150,7 +150,7 @@
|
||||
add_airtank()
|
||||
spark_system.set_up(2, 0, src)
|
||||
spark_system.attach(src)
|
||||
smoke_system.set_up(3, src)
|
||||
smoke_system.set_up(3, location = src)
|
||||
smoke_system.attach(src)
|
||||
add_cell()
|
||||
add_scanmod()
|
||||
|
||||
@@ -67,7 +67,7 @@
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/anomaly/proc/anomalyNeutralize()
|
||||
new /obj/effect/particle_effect/smoke/bad(loc)
|
||||
new /obj/effect/particle_effect/fluid/smoke/bad(loc)
|
||||
|
||||
for(var/atom/movable/O in src)
|
||||
O.forceMove(drop_location())
|
||||
|
||||
@@ -37,15 +37,10 @@ would spawn and follow the beaker, even if it is carried or thrown.
|
||||
location = null
|
||||
return ..()
|
||||
|
||||
/datum/effect_system/proc/set_up(n = 3, c = FALSE, loca)
|
||||
if(n > 10)
|
||||
n = 10
|
||||
number = n
|
||||
cardinals = c
|
||||
if(isturf(loca))
|
||||
location = loca
|
||||
else
|
||||
location = get_turf(loca)
|
||||
/datum/effect_system/proc/set_up(number = 3, cardinals_only = FALSE, location)
|
||||
src.number = min(number, 10)
|
||||
src.cardinals = cardinals_only
|
||||
src.location = get_turf(location)
|
||||
|
||||
/datum/effect_system/proc/attach(atom/atom)
|
||||
holder = atom
|
||||
|
||||
@@ -50,9 +50,10 @@
|
||||
/datum/effect_system/explosion/smoke
|
||||
|
||||
/datum/effect_system/explosion/smoke/proc/create_smoke()
|
||||
var/datum/effect_system/smoke_spread/S = new
|
||||
S.set_up(2, location)
|
||||
var/datum/effect_system/fluid_spread/smoke/S = new
|
||||
S.set_up(2, location = location)
|
||||
S.start()
|
||||
|
||||
/datum/effect_system/explosion/smoke/start()
|
||||
..()
|
||||
addtimer(CALLBACK(src, .proc/create_smoke), 5)
|
||||
|
||||
@@ -1,355 +0,0 @@
|
||||
// Foam
|
||||
// Similar to smoke, but slower and mobs absorb its reagent through their exposed skin.
|
||||
#define ALUMINUM_FOAM 1
|
||||
#define IRON_FOAM 2
|
||||
#define RESIN_FOAM 3
|
||||
|
||||
|
||||
/obj/effect/particle_effect/foam
|
||||
name = "foam"
|
||||
icon_state = "foam"
|
||||
opacity = 0
|
||||
anchored = TRUE
|
||||
density = FALSE
|
||||
layer = EDGED_TURF_LAYER
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
var/amount = 3
|
||||
animate_movement = 0
|
||||
var/metal = 0
|
||||
var/lifetime = 40
|
||||
var/reagent_divisor = 7
|
||||
var/static/list/blacklisted_turfs = typecacheof(list(
|
||||
/turf/open/space/transit,
|
||||
/turf/open/chasm,
|
||||
/turf/open/lava))
|
||||
var/slippery_foam = TRUE
|
||||
var/one_apply_per_object = FALSE
|
||||
var/list/applied_atoms
|
||||
|
||||
/obj/effect/particle_effect/foam/firefighting
|
||||
name = "firefighting foam"
|
||||
lifetime = 20 //doesn't last as long as normal foam
|
||||
amount = 0 //no spread
|
||||
slippery_foam = FALSE
|
||||
var/absorbed_plasma = 0
|
||||
|
||||
/obj/effect/particle_effect/foam/firefighting/process()
|
||||
..()
|
||||
|
||||
var/turf/open/T = get_turf(src)
|
||||
var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in T)
|
||||
if(hotspot && istype(T) && T.air)
|
||||
qdel(hotspot)
|
||||
var/datum/gas_mixture/G = T.air
|
||||
var/plas_amt = min(30,G.get_moles(/datum/gas/plasma)) //Absorb some plasma
|
||||
G.adjust_moles(/datum/gas/plasma, -plas_amt)
|
||||
absorbed_plasma += plas_amt
|
||||
if(G.return_temperature() > T20C)
|
||||
G.set_temperature(max(G.return_temperature()/2,T20C))
|
||||
T.air_update_turf()
|
||||
|
||||
/obj/effect/particle_effect/foam/firefighting/kill_foam()
|
||||
STOP_PROCESSING(SSprocessing, src)
|
||||
|
||||
if(absorbed_plasma)
|
||||
var/obj/effect/decal/cleanable/plasma/P = (locate(/obj/effect/decal/cleanable/plasma) in get_turf(src))
|
||||
if(!P)
|
||||
P = new(loc)
|
||||
P.reagents.add_reagent(/datum/reagent/stable_plasma, absorbed_plasma)
|
||||
|
||||
flick("[icon_state]-disolve", src)
|
||||
QDEL_IN(src, 5)
|
||||
|
||||
/obj/effect/particle_effect/foam/firefighting/foam_mob(mob/living/L)
|
||||
if(!istype(L))
|
||||
return
|
||||
L.adjust_fire_stacks(-2)
|
||||
L.ExtinguishMob()
|
||||
|
||||
/obj/effect/particle_effect/foam/firefighting/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
return
|
||||
|
||||
/obj/effect/particle_effect/foam/metal
|
||||
name = "aluminium foam"
|
||||
metal = ALUMINUM_FOAM
|
||||
icon_state = "mfoam"
|
||||
slippery_foam = FALSE
|
||||
|
||||
/obj/effect/particle_effect/foam/metal/smart
|
||||
name = "smart foam"
|
||||
|
||||
/obj/effect/particle_effect/foam/metal/iron
|
||||
name = "iron foam"
|
||||
metal = IRON_FOAM
|
||||
|
||||
/obj/effect/particle_effect/foam/metal/resin
|
||||
name = "resin foam"
|
||||
metal = RESIN_FOAM
|
||||
|
||||
/obj/effect/particle_effect/foam/long_life
|
||||
lifetime = 150
|
||||
|
||||
/obj/effect/particle_effect/foam/Initialize()
|
||||
. = ..()
|
||||
create_reagents(1000) //limited by the size of the reagent holder anyway.
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
playsound(src, 'sound/effects/bubbles2.ogg', 80, 1, -3)
|
||||
applied_atoms = list()
|
||||
|
||||
/obj/effect/particle_effect/foam/ComponentInitialize()
|
||||
. = ..()
|
||||
if(slippery_foam)
|
||||
AddComponent(/datum/component/slippery, 100)
|
||||
|
||||
/obj/effect/particle_effect/foam/Destroy()
|
||||
STOP_PROCESSING(SSprocessing, src)
|
||||
return ..()
|
||||
|
||||
|
||||
/obj/effect/particle_effect/foam/proc/kill_foam()
|
||||
set waitfor = FALSE
|
||||
STOP_PROCESSING(SSprocessing, src)
|
||||
switch(metal)
|
||||
if(ALUMINUM_FOAM)
|
||||
new /obj/structure/foamedmetal(get_turf(src))
|
||||
if(IRON_FOAM)
|
||||
new /obj/structure/foamedmetal/iron(get_turf(src))
|
||||
if(RESIN_FOAM)
|
||||
new /obj/structure/foamedmetal/resin(get_turf(src))
|
||||
flick("[icon_state]-disolve", src)
|
||||
QDEL_IN(src, 5)
|
||||
|
||||
/obj/effect/particle_effect/foam/smart/kill_foam() //Smart foam adheres to area borders for walls
|
||||
STOP_PROCESSING(SSprocessing, src)
|
||||
if(metal)
|
||||
var/turf/T = get_turf(src)
|
||||
if(isspaceturf(T)) //Block up any exposed space
|
||||
T.PlaceOnTop(/turf/open/floor/plating/foam, flags = CHANGETURF_INHERIT_AIR)
|
||||
for(var/direction in GLOB.cardinals)
|
||||
var/turf/cardinal_turf = get_step(T, direction)
|
||||
if(get_area(cardinal_turf) != get_area(T)) //We're at an area boundary, so let's block off this turf!
|
||||
new/obj/structure/foamedmetal(T)
|
||||
break
|
||||
flick("[icon_state]-disolve", src)
|
||||
QDEL_IN(src, 5)
|
||||
|
||||
/obj/effect/particle_effect/foam/process()
|
||||
lifetime--
|
||||
if(lifetime < 1)
|
||||
kill_foam()
|
||||
return
|
||||
|
||||
var/fraction = 1/initial(reagent_divisor)
|
||||
for(var/obj/O in range(0,src))
|
||||
if(O.type == src.type)
|
||||
continue
|
||||
if(one_apply_per_object && (O in applied_atoms))
|
||||
continue
|
||||
if(isturf(O.loc))
|
||||
var/turf/T = O.loc
|
||||
if(T.intact && O.level == 1) //hidden under the floor
|
||||
continue
|
||||
if(lifetime % reagent_divisor)
|
||||
reagents.reaction(O, VAPOR, fraction)
|
||||
applied_atoms += O
|
||||
CHECK_TICK
|
||||
var/hit = 0
|
||||
for(var/mob/living/L in range(0,src))
|
||||
hit += foam_mob(L)
|
||||
CHECK_TICK
|
||||
if(hit)
|
||||
lifetime++ //this is so the decrease from mobs hit and the natural decrease don't cumulate.
|
||||
var/T = get_turf(src)
|
||||
if(!(one_apply_per_object && (T in applied_atoms)))
|
||||
if(lifetime % reagent_divisor)
|
||||
reagents.reaction(T, VAPOR, fraction)
|
||||
applied_atoms += T
|
||||
|
||||
if(--amount < 0)
|
||||
return
|
||||
CHECK_TICK
|
||||
spread_foam()
|
||||
|
||||
/obj/effect/particle_effect/foam/proc/foam_mob(mob/living/L)
|
||||
if(lifetime<1)
|
||||
return 0
|
||||
if(!istype(L))
|
||||
return 0
|
||||
var/fraction = 1/initial(reagent_divisor)
|
||||
if(lifetime % reagent_divisor)
|
||||
reagents.reaction(L, VAPOR, fraction)
|
||||
lifetime--
|
||||
return 1
|
||||
|
||||
/obj/effect/particle_effect/foam/proc/spread_foam()
|
||||
set waitfor = FALSE
|
||||
var/turf/t_loc = get_turf(src)
|
||||
for(var/turf/T in t_loc.GetAtmosAdjacentTurfs())
|
||||
var/obj/effect/particle_effect/foam/foundfoam = locate() in T //Don't spread foam where there's already foam!
|
||||
if(foundfoam)
|
||||
continue
|
||||
|
||||
if(is_type_in_typecache(T, blacklisted_turfs))
|
||||
continue
|
||||
|
||||
for(var/mob/living/L in T)
|
||||
foam_mob(L)
|
||||
var/obj/effect/particle_effect/foam/F = new src.type(T)
|
||||
F.amount = amount
|
||||
reagents.copy_to(F, (reagents.total_volume))
|
||||
F.add_atom_colour(color, FIXED_COLOUR_PRIORITY)
|
||||
F.metal = metal
|
||||
F.one_apply_per_object = one_apply_per_object
|
||||
|
||||
|
||||
/obj/effect/particle_effect/foam/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
if(prob(max(0, exposed_temperature - 475))) //foam dissolves when heated
|
||||
kill_foam()
|
||||
|
||||
|
||||
/obj/effect/particle_effect/foam/metal/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
return
|
||||
|
||||
|
||||
///////////////////////////////////////////////
|
||||
//FOAM EFFECT DATUM
|
||||
/datum/effect_system/foam_spread
|
||||
var/amount = 10 // the size of the foam spread.
|
||||
var/obj/chemholder
|
||||
effect_type = /obj/effect/particle_effect/foam
|
||||
var/metal = 0
|
||||
var/one_apply_per_object = FALSE
|
||||
|
||||
|
||||
/datum/effect_system/foam_spread/metal
|
||||
effect_type = /obj/effect/particle_effect/foam/metal
|
||||
|
||||
|
||||
/datum/effect_system/foam_spread/metal/smart
|
||||
effect_type = /obj/effect/particle_effect/foam/smart
|
||||
|
||||
|
||||
/datum/effect_system/foam_spread/long
|
||||
effect_type = /obj/effect/particle_effect/foam/long_life
|
||||
|
||||
/datum/effect_system/foam_spread/New()
|
||||
..()
|
||||
chemholder = new /obj()
|
||||
var/datum/reagents/R = new/datum/reagents(1000)
|
||||
chemholder.reagents = R
|
||||
R.my_atom = chemholder
|
||||
|
||||
/datum/effect_system/foam_spread/Destroy()
|
||||
qdel(chemholder)
|
||||
chemholder = null
|
||||
return ..()
|
||||
|
||||
/datum/effect_system/foam_spread/set_up(amt=5, loca, datum/reagents/carry = null)
|
||||
if(isturf(loca))
|
||||
location = loca
|
||||
else
|
||||
location = get_turf(loca)
|
||||
|
||||
amount = round(sqrt(amt / 2), 1)
|
||||
carry.copy_to(chemholder, carry.total_volume)
|
||||
|
||||
/datum/effect_system/foam_spread/metal/set_up(amt=5, loca, datum/reagents/carry = null, metaltype)
|
||||
..()
|
||||
metal = metaltype
|
||||
|
||||
/datum/effect_system/foam_spread/start()
|
||||
var/obj/effect/particle_effect/foam/F = new effect_type(location)
|
||||
F.one_apply_per_object = one_apply_per_object
|
||||
var/foamcolor = mix_color_from_reagents(chemholder.reagents.reagent_list)
|
||||
chemholder.reagents.copy_to(F, chemholder.reagents.total_volume/amount)
|
||||
F.add_atom_colour(foamcolor, FIXED_COLOUR_PRIORITY)
|
||||
F.amount = amount
|
||||
F.metal = metal
|
||||
|
||||
|
||||
//////////////////////////////////////////////////////////
|
||||
// FOAM STRUCTURE. Formed by metal foams. Dense and opaque, but easy to break
|
||||
/obj/structure/foamedmetal
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "metalfoam"
|
||||
density = TRUE
|
||||
opacity = 1 // changed in New()
|
||||
anchored = TRUE
|
||||
layer = EDGED_TURF_LAYER
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
name = "foamed metal"
|
||||
desc = "A lightweight foamed metal wall."
|
||||
gender = PLURAL
|
||||
max_integrity = 20
|
||||
CanAtmosPass = ATMOS_PASS_DENSITY
|
||||
|
||||
/obj/structure/foamedmetal/Initialize()
|
||||
. = ..()
|
||||
air_update_turf(1)
|
||||
|
||||
/obj/structure/foamedmetal/Move()
|
||||
var/turf/T = loc
|
||||
. = ..()
|
||||
move_update_air(T)
|
||||
|
||||
/obj/structure/foamedmetal/attack_paw(mob/user)
|
||||
return attack_hand(user)
|
||||
|
||||
/obj/structure/foamedmetal/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
|
||||
playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1)
|
||||
|
||||
/obj/structure/foamedmetal/attack_hand(mob/user)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
user.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
|
||||
to_chat(user, span_warning("You hit [src] but bounce off it!"))
|
||||
playsound(src.loc, 'sound/weapons/tap.ogg', 100, 1)
|
||||
|
||||
/obj/structure/foamedmetal/iron
|
||||
max_integrity = 50
|
||||
icon_state = "ironfoam"
|
||||
|
||||
//Atmos Backpack Resin, transparent, prevents atmos and filters the air
|
||||
/obj/structure/foamedmetal/resin
|
||||
name = "\improper ATMOS Resin"
|
||||
desc = "A lightweight, transparent resin used to suffocate fires, scrub the air of toxins, and restore the air to a safe temperature."
|
||||
opacity = FALSE
|
||||
icon_state = "atmos_resin"
|
||||
alpha = 120
|
||||
max_integrity = 10
|
||||
|
||||
/obj/structure/foamedmetal/resin/Initialize()
|
||||
. = ..()
|
||||
if(isopenturf(loc))
|
||||
var/turf/open/O = loc
|
||||
O.ClearWet()
|
||||
if(O.air)
|
||||
var/datum/gas_mixture/G = O.air
|
||||
G.set_temperature(293.15)
|
||||
for(var/obj/effect/hotspot/H in O)
|
||||
qdel(H)
|
||||
for(var/I in G.get_gases())
|
||||
if(I == /datum/gas/oxygen || I == /datum/gas/nitrogen)
|
||||
continue
|
||||
G.set_moles(I, 0)
|
||||
O.air_update_turf()
|
||||
for(var/obj/machinery/atmospherics/components/unary/U in O)
|
||||
if(!U.welded)
|
||||
U.welded = TRUE
|
||||
U.update_icon()
|
||||
U.visible_message(span_danger("[U] sealed shut!"))
|
||||
for(var/mob/living/L in O)
|
||||
L.ExtinguishMob()
|
||||
for(var/obj/item/Item in O)
|
||||
Item.extinguish()
|
||||
|
||||
/obj/structure/foamedmetal/resin/CanAllowThrough(atom/movable/mover, turf/target)
|
||||
. = ..()
|
||||
if(istype(mover) && (mover.pass_flags & PASSGLASS))
|
||||
return TRUE
|
||||
|
||||
#undef ALUMINUM_FOAM
|
||||
#undef IRON_FOAM
|
||||
#undef RESIN_FOAM
|
||||
@@ -1,336 +0,0 @@
|
||||
/////////////////////////////////////////////
|
||||
//// SMOKE SYSTEMS
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/obj/effect/particle_effect/smoke
|
||||
name = "smoke"
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = "smoke"
|
||||
pixel_x = -32
|
||||
pixel_y = -32
|
||||
opacity = 0
|
||||
layer = FLY_LAYER
|
||||
anchored = TRUE
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
animate_movement = 0
|
||||
var/amount = 4
|
||||
var/lifetime = 5
|
||||
var/opaque = 1 //whether the smoke can block the view when in enough amount
|
||||
|
||||
|
||||
/obj/effect/particle_effect/smoke/proc/fade_out(frames = 16)
|
||||
if(alpha == 0) //Handle already transparent case
|
||||
return
|
||||
if(frames == 0)
|
||||
frames = 1 //We will just assume that by 0 frames, the coder meant "during one frame".
|
||||
var/lighting_updated = FALSE
|
||||
var/step = alpha / frames
|
||||
for(var/i = 0, i < frames, i++)
|
||||
alpha -= step
|
||||
if(alpha < 160)
|
||||
set_opacity(0) //if we were blocking view, we aren't now because we're fading out
|
||||
if(!lighting_updated) // Only update lights around me once we have sufficiently faded, and only do it once
|
||||
lighting_updated = TRUE
|
||||
for(var/atom/L in view(15, src)) // Floodlights reach 15 tiles max, this should be sufficient
|
||||
L.light?.force_update()
|
||||
CHECK_TICK
|
||||
stoplag()
|
||||
|
||||
/obj/effect/particle_effect/smoke/Initialize()
|
||||
. = ..()
|
||||
create_reagents(500)
|
||||
START_PROCESSING(SSobj, src)
|
||||
|
||||
|
||||
/obj/effect/particle_effect/smoke/Destroy()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
return ..()
|
||||
|
||||
/obj/effect/particle_effect/smoke/proc/kill_smoke()
|
||||
STOP_PROCESSING(SSobj, src)
|
||||
INVOKE_ASYNC(src, .proc/fade_out)
|
||||
QDEL_IN(src, 10)
|
||||
|
||||
/obj/effect/particle_effect/smoke/process()
|
||||
lifetime--
|
||||
if(lifetime < 1)
|
||||
kill_smoke()
|
||||
return 0
|
||||
for(var/mob/living/L in range(0,src))
|
||||
smoke_mob(L)
|
||||
return 1
|
||||
|
||||
/obj/effect/particle_effect/smoke/proc/smoke_mob(mob/living/carbon/C)
|
||||
if(!istype(C))
|
||||
return 0
|
||||
if(lifetime<1)
|
||||
return 0
|
||||
if(C.internal != null || C.has_smoke_protection())
|
||||
return 0
|
||||
if(C.smoke_delay)
|
||||
return 0
|
||||
C.smoke_delay++
|
||||
addtimer(CALLBACK(src, .proc/remove_smoke_delay, C), 10)
|
||||
return 1
|
||||
|
||||
/obj/effect/particle_effect/smoke/proc/remove_smoke_delay(mob/living/carbon/C)
|
||||
if(C)
|
||||
C.smoke_delay = 0
|
||||
|
||||
/obj/effect/particle_effect/smoke/proc/spread_smoke()
|
||||
var/turf/t_loc = get_turf(src)
|
||||
if(!t_loc)
|
||||
return
|
||||
var/list/newsmokes = list()
|
||||
for(var/turf/T in t_loc.GetAtmosAdjacentTurfs())
|
||||
var/obj/effect/particle_effect/smoke/foundsmoke = locate() in T //Don't spread smoke where there's already smoke!
|
||||
if(foundsmoke)
|
||||
continue
|
||||
for(var/mob/living/L in T)
|
||||
smoke_mob(L)
|
||||
var/obj/effect/particle_effect/smoke/S = new type(T)
|
||||
reagents.copy_to(S, reagents.total_volume)
|
||||
S.setDir(pick(GLOB.cardinals))
|
||||
S.amount = amount-1
|
||||
S.add_atom_colour(color, FIXED_COLOUR_PRIORITY)
|
||||
S.lifetime = lifetime
|
||||
if(S.amount>0)
|
||||
if(opaque)
|
||||
S.set_opacity(TRUE)
|
||||
newsmokes.Add(S)
|
||||
|
||||
if(newsmokes.len)
|
||||
spawn(1) //the smoke spreads rapidly but not instantly
|
||||
for(var/obj/effect/particle_effect/smoke/SM in newsmokes)
|
||||
SM.spread_smoke()
|
||||
|
||||
|
||||
/datum/effect_system/smoke_spread
|
||||
var/amount = 10
|
||||
effect_type = /obj/effect/particle_effect/smoke
|
||||
|
||||
/datum/effect_system/smoke_spread/set_up(radius = 5, loca)
|
||||
if(isturf(loca))
|
||||
location = loca
|
||||
else
|
||||
location = get_turf(loca)
|
||||
amount = radius
|
||||
|
||||
/datum/effect_system/smoke_spread/start()
|
||||
if(holder)
|
||||
location = get_turf(holder)
|
||||
var/obj/effect/particle_effect/smoke/S = new effect_type(location)
|
||||
S.amount = amount
|
||||
if(S.amount)
|
||||
S.spread_smoke()
|
||||
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Bad smoke
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/obj/effect/particle_effect/smoke/bad
|
||||
lifetime = 8
|
||||
|
||||
/obj/effect/particle_effect/smoke/bad/smoke_mob(mob/living/carbon/M)
|
||||
if(..())
|
||||
M.drop_all_held_items()
|
||||
M.adjustOxyLoss(1)
|
||||
M.emote("cough")
|
||||
return 1
|
||||
|
||||
/obj/effect/particle_effect/smoke/bad/Crossed(atom/movable/AM, oldloc)
|
||||
. = ..()
|
||||
if(istype(AM, /obj/item/projectile/beam))
|
||||
var/obj/item/projectile/beam/B = AM
|
||||
B.damage = (B.damage/2)
|
||||
|
||||
/datum/effect_system/smoke_spread/bad
|
||||
effect_type = /obj/effect/particle_effect/smoke/bad
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Nanofrost smoke
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/obj/effect/particle_effect/smoke/freezing
|
||||
name = "nanofrost smoke"
|
||||
color = "#B2FFFF"
|
||||
opaque = 0
|
||||
|
||||
/datum/effect_system/smoke_spread/freezing
|
||||
effect_type = /obj/effect/particle_effect/smoke/freezing
|
||||
var/blast = 0
|
||||
var/temperature = 2
|
||||
var/weldvents = TRUE
|
||||
var/distcheck = TRUE
|
||||
|
||||
/datum/effect_system/smoke_spread/freezing/proc/Chilled(atom/A)
|
||||
if(isopenturf(A))
|
||||
var/turf/open/T = A
|
||||
if(T.air)
|
||||
var/datum/gas_mixture/G = T.air
|
||||
if(!distcheck || get_dist(T, location) < blast) // Otherwise we'll get silliness like people using Nanofrost to kill people through walls with cold air
|
||||
G.set_temperature(temperature)
|
||||
T.air_update_turf()
|
||||
for(var/obj/effect/hotspot/H in T)
|
||||
qdel(H)
|
||||
if(G.get_moles(/datum/gas/plasma))
|
||||
G.adjust_moles(/datum/gas/nitrogen, G.get_moles(/datum/gas/plasma))
|
||||
G.set_moles(/datum/gas/plasma, 0)
|
||||
if (weldvents)
|
||||
for(var/obj/machinery/atmospherics/components/unary/U in T)
|
||||
if(!isnull(U.welded) && !U.welded) //must be an unwelded vent pump or vent scrubber.
|
||||
U.welded = TRUE
|
||||
U.update_icon()
|
||||
U.visible_message(span_danger("[U] was frozen shut!"))
|
||||
for(var/mob/living/L in T)
|
||||
L.ExtinguishMob()
|
||||
for(var/obj/item/Item in T)
|
||||
Item.extinguish()
|
||||
|
||||
/datum/effect_system/smoke_spread/freezing/set_up(radius = 5, loca, blast_radius = 0)
|
||||
..()
|
||||
blast = blast_radius
|
||||
|
||||
/datum/effect_system/smoke_spread/freezing/start()
|
||||
if(blast)
|
||||
for(var/turf/T in RANGE_TURFS(blast, location))
|
||||
Chilled(T)
|
||||
..()
|
||||
|
||||
/datum/effect_system/smoke_spread/freezing/decon
|
||||
temperature = 293.15
|
||||
distcheck = FALSE
|
||||
weldvents = FALSE
|
||||
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Sleep smoke
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/obj/effect/particle_effect/smoke/sleeping
|
||||
color = "#9C3636"
|
||||
lifetime = 10
|
||||
|
||||
/obj/effect/particle_effect/smoke/sleeping/smoke_mob(mob/living/carbon/M)
|
||||
if(..())
|
||||
M.Sleeping(200)
|
||||
M.emote("cough")
|
||||
return 1
|
||||
|
||||
/datum/effect_system/smoke_spread/sleeping
|
||||
effect_type = /obj/effect/particle_effect/smoke/sleeping
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Chem smoke
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/obj/effect/particle_effect/smoke/chem
|
||||
lifetime = 10
|
||||
|
||||
|
||||
/obj/effect/particle_effect/smoke/chem/process()
|
||||
if(..())
|
||||
var/turf/T = get_turf(src)
|
||||
var/fraction = 1/initial(lifetime)
|
||||
for(var/atom/movable/AM in T)
|
||||
if(AM.type == src.type)
|
||||
continue
|
||||
if(T.intact && AM.level == 1) //hidden under the floor
|
||||
continue
|
||||
reagents.reaction(AM, TOUCH, fraction)
|
||||
|
||||
reagents.reaction(T, TOUCH, fraction)
|
||||
return 1
|
||||
|
||||
/obj/effect/particle_effect/smoke/chem/smoke_mob(mob/living/carbon/M)
|
||||
if(lifetime<1)
|
||||
return 0
|
||||
if(!istype(M))
|
||||
return 0
|
||||
var/mob/living/carbon/C = M
|
||||
if(C.internal != null || C.has_smoke_protection())
|
||||
return 0
|
||||
var/fraction = 1/initial(lifetime)
|
||||
reagents.copy_to(C, fraction*reagents.total_volume)
|
||||
reagents.reaction(M, INGEST, fraction)
|
||||
return 1
|
||||
|
||||
|
||||
|
||||
/datum/effect_system/smoke_spread/chem
|
||||
var/obj/chemholder
|
||||
effect_type = /obj/effect/particle_effect/smoke/chem
|
||||
|
||||
/datum/effect_system/smoke_spread/chem/New()
|
||||
..()
|
||||
chemholder = new /obj()
|
||||
var/datum/reagents/R = new/datum/reagents(500)
|
||||
chemholder.reagents = R
|
||||
R.my_atom = chemholder
|
||||
|
||||
/datum/effect_system/smoke_spread/chem/Destroy()
|
||||
qdel(chemholder)
|
||||
chemholder = null
|
||||
return ..()
|
||||
|
||||
/datum/effect_system/smoke_spread/chem/set_up(datum/reagents/carry = null, radius = 1, loca, silent = FALSE)
|
||||
if(isturf(loca))
|
||||
location = loca
|
||||
else
|
||||
location = get_turf(loca)
|
||||
amount = radius
|
||||
carry.copy_to(chemholder, carry.total_volume)
|
||||
|
||||
if(!silent)
|
||||
var/contained = ""
|
||||
for(var/reagent in carry.reagent_list)
|
||||
contained += " [reagent] "
|
||||
if(contained)
|
||||
contained = "\[[contained]\]"
|
||||
|
||||
var/where = "[AREACOORD(location)]"
|
||||
if(carry.my_atom.fingerprintslast)
|
||||
var/mob/M = get_mob_by_key(carry.my_atom.fingerprintslast)
|
||||
var/more = ""
|
||||
if(M)
|
||||
more = "[ADMIN_LOOKUPFLW(M)] "
|
||||
message_admins("Smoke: ([ADMIN_VERBOSEJMP(location)])[contained]. Key: [more ? more : carry.my_atom.fingerprintslast].")
|
||||
log_game("A chemical smoke reaction has taken place in ([where])[contained]. Last touched by [carry.my_atom.fingerprintslast].")
|
||||
else
|
||||
message_admins("Smoke: ([ADMIN_VERBOSEJMP(location)])[contained]. No associated key.")
|
||||
log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key.")
|
||||
|
||||
|
||||
/datum/effect_system/smoke_spread/chem/start()
|
||||
var/mixcolor = mix_color_from_reagents(chemholder.reagents.reagent_list)
|
||||
if(holder)
|
||||
location = get_turf(holder)
|
||||
var/obj/effect/particle_effect/smoke/chem/S = new effect_type(location)
|
||||
|
||||
if(chemholder.reagents.total_volume > 1) // can't split 1 very well
|
||||
chemholder.reagents.copy_to(S, chemholder.reagents.total_volume)
|
||||
|
||||
if(mixcolor)
|
||||
S.add_atom_colour(mixcolor, FIXED_COLOUR_PRIORITY) // give the smoke color, if it has any to begin with
|
||||
S.amount = amount
|
||||
if(S.amount)
|
||||
S.spread_smoke() //calling process right now so the smoke immediately attacks mobs.
|
||||
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Transparent smoke
|
||||
/////////////////////////////////////////////
|
||||
|
||||
//Same as the base type, but the smoke produced is not opaque
|
||||
/datum/effect_system/smoke_spread/transparent
|
||||
effect_type = /obj/effect/particle_effect/smoke/transparent
|
||||
|
||||
/obj/effect/particle_effect/smoke/transparent
|
||||
opaque = FALSE
|
||||
|
||||
/proc/do_smoke(range=0, location=null, smoke_type=/obj/effect/particle_effect/smoke)
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.effect_type = smoke_type
|
||||
smoke.set_up(range, location)
|
||||
smoke.start()
|
||||
@@ -0,0 +1,159 @@
|
||||
/////////////////////////////////////////////
|
||||
//// SMOKE SYSTEMS
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* A group of fluid objects.
|
||||
*/
|
||||
/datum/fluid_group
|
||||
/// The set of fluid objects currently in this group.
|
||||
var/list/nodes
|
||||
/// The number of fluid object that this group wants to have contained.
|
||||
var/target_size
|
||||
/// The total number of fluid objects that have ever been in this group.
|
||||
var/total_size = 0
|
||||
|
||||
/datum/fluid_group/New(target_size = 0)
|
||||
. = ..()
|
||||
src.nodes = list()
|
||||
src.target_size = target_size
|
||||
|
||||
/datum/fluid_group/Destroy(force)
|
||||
QDEL_LAZYLIST(nodes)
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* Adds a fluid node to this fluid group.
|
||||
*
|
||||
* Is a noop if the node is already in the group.
|
||||
* Removes the node from any other fluid groups it is in.
|
||||
* Syncs the group of the node with the group it is being added to (this one).
|
||||
* Increments the total size of the fluid group.
|
||||
*
|
||||
* Arguments:
|
||||
* - [node][/obj/effect/particle_effect/fluid]: The fluid node that is going to be added to this group.
|
||||
*
|
||||
* Returns:
|
||||
* - [TRUE]: If the node to be added is in this group by the end of the proc.
|
||||
* - [FALSE]: Otherwise.
|
||||
*/
|
||||
/datum/fluid_group/proc/add_node(obj/effect/particle_effect/fluid/node)
|
||||
if(!istype(node))
|
||||
CRASH("Attempted to add non-fluid node [isnull(node) ? "NULL" : node] to a fluid group.")
|
||||
if(QDELING(node))
|
||||
CRASH("Attempted to add qdeling node to a fluid group")
|
||||
|
||||
if(node.group)
|
||||
if(node.group == src)
|
||||
return TRUE
|
||||
if(!node.group.remove_node(node))
|
||||
return FALSE
|
||||
|
||||
nodes += node
|
||||
node.group = src
|
||||
total_size++
|
||||
return TRUE
|
||||
|
||||
|
||||
/**
|
||||
* Removes a fluid node from this fluid group.
|
||||
*
|
||||
* Is a noop if the node is not in this group.
|
||||
* Nulls the nodes fluid group ref to sync it with its new state.
|
||||
* DOES NOT decrement the total size of the fluid group.
|
||||
*
|
||||
* Arguments:
|
||||
* - [node][/obj/effect/particle_effect/fluid]: The fluid node that is going to be removed from this group.
|
||||
*
|
||||
* Returns:
|
||||
* - [TRUE]: If the node to be removed is not in the group by the end of the proc.
|
||||
*/
|
||||
/datum/fluid_group/proc/remove_node(obj/effect/particle_effect/fluid/node)
|
||||
if(node.group != src)
|
||||
return TRUE
|
||||
|
||||
nodes -= node
|
||||
node.group = null
|
||||
return TRUE // Note: does not decrement total size since we don't want the group to expand again when it begins to dissipate or it will never stop.
|
||||
|
||||
|
||||
/**
|
||||
* A particle effect that belongs to a fluid group.
|
||||
*/
|
||||
/obj/effect/particle_effect/fluid
|
||||
name = "fluid"
|
||||
/// The fluid group that this particle effect belongs to.
|
||||
var/datum/fluid_group/group
|
||||
/// What SSfluid bucket this particle effect is currently in.
|
||||
var/tmp/effect_bucket
|
||||
/// The index of the fluid spread bucket this is being spread in.
|
||||
var/tmp/spread_bucket
|
||||
|
||||
/obj/effect/particle_effect/fluid/Initialize(mapload, datum/fluid_group/group, obj/effect/particle_effect/fluid/source)
|
||||
// We don't pass on explosions. Don't wanna set off a chain reaction in our reagents
|
||||
flags_1 |= PREVENT_CONTENTS_EXPLOSION_1
|
||||
. = ..()
|
||||
if(!group)
|
||||
group = source?.group || new
|
||||
group.add_node(src)
|
||||
source?.transfer_fingerprints_to(src)
|
||||
|
||||
/obj/effect/particle_effect/fluid/Destroy()
|
||||
group.remove_node(src)
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* Attempts to spread this fluid node to wherever it can spread.
|
||||
*
|
||||
* Exact results vary by subtype implementation.
|
||||
*/
|
||||
/obj/effect/particle_effect/fluid/proc/spread()
|
||||
CRASH("The base fluid spread proc is not implemented and should not be called. You called it.")
|
||||
|
||||
|
||||
/**
|
||||
* A factory which produces fluid groups.
|
||||
*/
|
||||
/datum/effect_system/fluid_spread
|
||||
effect_type = /obj/effect/particle_effect/fluid
|
||||
/// The amount of smoke to produce.
|
||||
var/amount = 10
|
||||
|
||||
/datum/effect_system/fluid_spread/set_up(range = 1, amount = DIAMOND_AREA(range), atom/holder, atom/location, ...)
|
||||
src.holder = holder
|
||||
src.location = location
|
||||
src.amount = amount
|
||||
|
||||
/datum/effect_system/fluid_spread/start(log = FALSE)
|
||||
var/location = src.location || get_turf(holder)
|
||||
var/obj/effect/particle_effect/fluid/flood = new effect_type(location, new /datum/fluid_group(amount))
|
||||
if (log) // Smoke is used as an aesthetic effect in a tonne of places and we don't want, say, a broken secway spamming admin chat.
|
||||
help_out_the_admins(flood, holder, location)
|
||||
flood.spread()
|
||||
|
||||
/**
|
||||
* Handles logging the beginning of a fluid flood.
|
||||
*
|
||||
* Arguments:
|
||||
* - [flood][/obj/effect/particle_effect/fluid]: The first cell of the fluid flood.
|
||||
* - [holder][/atom]: What the flood originated from.
|
||||
* - [location][/atom]: Where the flood originated.
|
||||
*/
|
||||
/datum/effect_system/fluid_spread/proc/help_out_the_admins(obj/effect/particle_effect/fluid/flood, atom/holder, atom/location)
|
||||
var/source_msg
|
||||
var/blame_msg
|
||||
if (holder)
|
||||
holder.transfer_fingerprints_to(flood) // This is important. If this doesn't exist thermobarics are annoying to adjudicate.
|
||||
|
||||
source_msg = "from inside of [ismob(holder) ? ADMIN_LOOKUPFLW(holder) : ADMIN_VERBOSEJMP(holder)]"
|
||||
var/lastkey = holder.fingerprintslast
|
||||
if (lastkey)
|
||||
var/mob/scapegoat = get_mob_by_key(lastkey)
|
||||
blame_msg = " last touched by [ADMIN_LOOKUPFLW(scapegoat)]"
|
||||
else
|
||||
blame_msg = " with no known fingerprints"
|
||||
else
|
||||
source_msg = "with no known source"
|
||||
|
||||
message_admins("\A [flood] flood started at [ADMIN_VERBOSEJMP(location)] [source_msg][blame_msg].")
|
||||
log_game("\A [flood] flood started at [location || "nonexistant location"] [holder ? "from [holder] last touched by [holder || "N/A"]" : "with no known source"].")
|
||||
@@ -0,0 +1,404 @@
|
||||
/// The minimum foam range required to start diluting the reagents past the minimum dilution rate.
|
||||
#define MINIMUM_FOAM_DILUTION_RANGE 3
|
||||
/// The minumum foam-area based divisor used to decrease foam exposure volume.
|
||||
#define MINIMUM_FOAM_DILUTION DIAMOND_AREA(MINIMUM_FOAM_DILUTION_RANGE)
|
||||
/// The effective scaling of the reagents in the foam. (Total delivered at or below [MINIMUM_FOAM_DILUTION])
|
||||
#define FOAM_REAGENT_SCALE 3.2
|
||||
|
||||
/**
|
||||
* ## Foam
|
||||
*
|
||||
* Similar to smoke, but slower and mobs absorb its reagent through their exposed skin.
|
||||
*/
|
||||
/obj/effect/particle_effect/fluid/foam
|
||||
name = "foam"
|
||||
icon_state = "foam"
|
||||
opacity = FALSE
|
||||
anchored = TRUE
|
||||
density = FALSE
|
||||
layer = EDGED_TURF_LAYER
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
animate_movement = NO_STEPS
|
||||
/// The types of turfs that this foam cannot spread to.
|
||||
var/static/list/blacklisted_turfs = typecacheof(list(
|
||||
/turf/open/space/transit,
|
||||
/turf/open/chasm,
|
||||
/turf/open/lava,
|
||||
))
|
||||
/// The typepath for what this foam leaves behind when it dissipates.
|
||||
var/atom/movable/result_type = null
|
||||
/// Whether or not this foam can produce a remnant movable if something of the same type is already on its turf.
|
||||
var/allow_duplicate_results = TRUE
|
||||
/// The amount of time this foam stick around for before it dissipates.
|
||||
var/lifetime = 8 SECONDS
|
||||
/// Whether or not this foam should be slippery.
|
||||
var/slippery_foam = TRUE
|
||||
|
||||
|
||||
/obj/effect/particle_effect/fluid/foam/Initialize(mapload)
|
||||
. = ..()
|
||||
if(slippery_foam)
|
||||
AddComponent(/datum/component/slippery, 100)
|
||||
create_reagents(1000)
|
||||
playsound(src, 'sound/effects/bubbles2.ogg', 80, TRUE, -3)
|
||||
//AddElement(/datum/element/atmos_sensitive, mapload)
|
||||
SSfoam.start_processing(src)
|
||||
|
||||
/obj/effect/particle_effect/fluid/foam/Destroy()
|
||||
SSfoam.stop_processing(src)
|
||||
if (spread_bucket)
|
||||
SSfoam.cancel_spread(src)
|
||||
return ..()
|
||||
|
||||
/**
|
||||
* Makes the foam dissipate and create whatever remnants it must.
|
||||
*/
|
||||
/obj/effect/particle_effect/fluid/foam/proc/kill_foam()
|
||||
SSfoam.stop_processing(src)
|
||||
if (spread_bucket)
|
||||
SSfoam.cancel_spread(src)
|
||||
make_result()
|
||||
flick("[icon_state]-disolve", src)
|
||||
QDEL_IN(src, 0.5 SECONDS)
|
||||
|
||||
/**
|
||||
* Makes the foam leave behind something when it dissipates.
|
||||
*
|
||||
* Returns the thing the foam leaves behind for further modification by subtypes.
|
||||
*/
|
||||
/obj/effect/particle_effect/fluid/foam/proc/make_result()
|
||||
if(isnull(result_type))
|
||||
return null
|
||||
|
||||
var/atom/location = loc
|
||||
var/atom/movable/result = (!allow_duplicate_results && (locate(result_type) in location)) || (new result_type(location))
|
||||
transfer_fingerprints_to(result)
|
||||
return result
|
||||
|
||||
/obj/effect/particle_effect/fluid/foam/process(delta_time)
|
||||
var/ds_delta_time = delta_time SECONDS
|
||||
lifetime -= ds_delta_time
|
||||
if(lifetime <= 0)
|
||||
kill_foam()
|
||||
return
|
||||
|
||||
var/fraction = (ds_delta_time * MINIMUM_FOAM_DILUTION) / (initial(lifetime) * max(MINIMUM_FOAM_DILUTION, group.total_size))
|
||||
var/turf/location = loc
|
||||
for(var/obj/object in location)
|
||||
if(object == src)
|
||||
continue
|
||||
if(isturf(object.loc))
|
||||
var/turf/turf = object.loc
|
||||
if(turf.intact && object.level == 1) //hidden under the floor
|
||||
continue
|
||||
reagents.reaction(object, VAPOR, fraction)
|
||||
|
||||
var/hit = 0
|
||||
for(var/mob/living/foamer in location)
|
||||
hit += foam_mob(foamer, delta_time)
|
||||
if(hit)
|
||||
lifetime += ds_delta_time //this is so the decrease from mobs hit and the natural decrease don't cumulate.
|
||||
|
||||
reagents.reaction(location, VAPOR, fraction)
|
||||
|
||||
/**
|
||||
* Applies the effect of this foam to a mob.
|
||||
*
|
||||
* Arguments:
|
||||
* - [foaming][/mob/living]: The mob that this foam is acting on.
|
||||
* - delta_time: The amount of time that this foam is acting on them over.
|
||||
*
|
||||
* Returns:
|
||||
* - [TRUE]: If the foam was successfully applied to the mob. Used to scale how quickly foam dissipates according to the number of mobs it is applied to.
|
||||
* - [FALSE]: Otherwise.
|
||||
*/
|
||||
/obj/effect/particle_effect/fluid/foam/proc/foam_mob(mob/living/foaming, delta_time)
|
||||
if(lifetime <= 0)
|
||||
return FALSE
|
||||
if(!istype(foaming))
|
||||
return FALSE
|
||||
|
||||
delta_time = min(delta_time SECONDS, lifetime)
|
||||
var/fraction = (delta_time * MINIMUM_FOAM_DILUTION) / (initial(lifetime) * max(MINIMUM_FOAM_DILUTION, group.total_size))
|
||||
reagents.reaction(foaming, VAPOR, fraction)
|
||||
lifetime -= delta_time
|
||||
return TRUE
|
||||
|
||||
/obj/effect/particle_effect/fluid/foam/spread(delta_time = 0.2 SECONDS)
|
||||
if(group.total_size > group.target_size)
|
||||
return
|
||||
var/turf/location = get_turf(src)
|
||||
if(!istype(location))
|
||||
return FALSE
|
||||
|
||||
for(var/turf/spread_turf as anything in location.reachableAdjacentTurfs())
|
||||
var/obj/effect/particle_effect/fluid/foam/foundfoam = locate() in spread_turf //Don't spread foam where there's already foam!
|
||||
if(foundfoam)
|
||||
continue
|
||||
|
||||
if(is_type_in_typecache(spread_turf, blacklisted_turfs))
|
||||
continue
|
||||
|
||||
for(var/mob/living/foaming in spread_turf)
|
||||
foam_mob(foaming, delta_time)
|
||||
|
||||
var/obj/effect/particle_effect/fluid/foam/spread_foam = new type(spread_turf, group, src)
|
||||
reagents.copy_to(spread_foam, (reagents.total_volume))
|
||||
spread_foam.add_atom_colour(color, FIXED_COLOUR_PRIORITY)
|
||||
spread_foam.result_type = result_type
|
||||
SSfoam.queue_spread(spread_foam)
|
||||
|
||||
/obj/effect/particle_effect/fluid/foam/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
if(prob(max(0, exposed_temperature - 475))) //foam dissolves when heated
|
||||
kill_foam()
|
||||
|
||||
/obj/effect/particle_effect/fluid/foam/metal/temperature_expose(datum/gas_mixture/air, exposed_temperature, exposed_volume)
|
||||
return
|
||||
|
||||
/// A factory for foam fluid floods.
|
||||
/datum/effect_system/fluid_spread/foam
|
||||
effect_type = /obj/effect/particle_effect/fluid/foam
|
||||
/// A container for all of the chemicals we distribute through the foam.
|
||||
var/datum/reagents/chemholder
|
||||
/// The amount that
|
||||
var/reagent_scale = FOAM_REAGENT_SCALE
|
||||
/// What type of thing the foam should leave behind when it dissipates.
|
||||
var/atom/movable/result_type = null
|
||||
|
||||
|
||||
/datum/effect_system/fluid_spread/foam/New()
|
||||
..()
|
||||
chemholder = new(1000, NO_REACT)
|
||||
|
||||
/datum/effect_system/fluid_spread/foam/Destroy()
|
||||
QDEL_NULL(chemholder)
|
||||
return ..()
|
||||
|
||||
/datum/effect_system/fluid_spread/foam/set_up(range = 1, amount = DIAMOND_AREA(range), atom/holder, atom/location = null, datum/reagents/carry = null, result_type = null)
|
||||
. = ..()
|
||||
carry?.copy_to(chemholder, carry.total_volume)
|
||||
if(!isnull(result_type))
|
||||
src.result_type = result_type
|
||||
|
||||
/datum/effect_system/fluid_spread/foam/start(log = FALSE)
|
||||
var/obj/effect/particle_effect/fluid/foam/foam = new effect_type(location, new /datum/fluid_group(amount))
|
||||
var/foamcolor = mix_color_from_reagents(chemholder.reagent_list)
|
||||
if(reagent_scale > 1) // Make room in case we were created by a particularly stuffed payload.
|
||||
foam.reagents.maximum_volume *= reagent_scale
|
||||
chemholder.copy_to(foam, chemholder.total_volume, reagent_scale) // Foam has an amplifying effect on the reagents it is supplied with. This is balanced by the reagents being diluted as the area the foam covers increases.
|
||||
foam.add_atom_colour(foamcolor, FIXED_COLOUR_PRIORITY)
|
||||
if(!isnull(result_type))
|
||||
foam.result_type = result_type
|
||||
if (log)
|
||||
help_out_the_admins(foam, holder, location)
|
||||
SSfoam.queue_spread(foam)
|
||||
|
||||
|
||||
// Short-lived foam
|
||||
/// A foam variant which dissipates quickly.
|
||||
/obj/effect/particle_effect/fluid/foam/short_life
|
||||
lifetime = 1 SECONDS
|
||||
|
||||
/datum/effect_system/fluid_spread/foam/short
|
||||
effect_type = /obj/effect/particle_effect/fluid/foam/short_life
|
||||
|
||||
// Long lasting foam
|
||||
/// A foam variant which lasts for an extended amount of time.
|
||||
/obj/effect/particle_effect/fluid/foam/long_life
|
||||
lifetime = 30 SECONDS
|
||||
|
||||
/// A factory which produces foam with an extended lifespan.
|
||||
/datum/effect_system/fluid_spread/foam/long
|
||||
effect_type = /obj/effect/particle_effect/fluid/foam/long_life
|
||||
reagent_scale = FOAM_REAGENT_SCALE * (30 / 8)
|
||||
|
||||
|
||||
// Firefighting foam
|
||||
/// A variant of foam which absorbs plasma in the air if there is a fire.
|
||||
/obj/effect/particle_effect/fluid/foam/firefighting
|
||||
name = "firefighting foam"
|
||||
lifetime = 20 //doesn't last as long as normal foam
|
||||
result_type = /obj/effect/decal/cleanable/plasma
|
||||
allow_duplicate_results = FALSE
|
||||
slippery_foam = FALSE
|
||||
/// The amount of plasma gas this foam has absorbed. To be deposited when the foam dissipates.
|
||||
var/absorbed_plasma = 0
|
||||
|
||||
/obj/effect/particle_effect/fluid/foam/firefighting/Initialize(mapload)
|
||||
. = ..()
|
||||
//RemoveElement(/datum/element/atmos_sensitive)
|
||||
|
||||
/obj/effect/particle_effect/fluid/foam/firefighting/process()
|
||||
..()
|
||||
|
||||
var/turf/open/location = loc
|
||||
if(!istype(location))
|
||||
return
|
||||
|
||||
var/obj/effect/hotspot/hotspot = locate() in location
|
||||
if(!(hotspot && location.air))
|
||||
return
|
||||
|
||||
QDEL_NULL(hotspot)
|
||||
var/datum/gas_mixture/air = location.air
|
||||
var/scrub_amt = min(30, air.get_moles(/datum/gas/plasma)) //Absorb some plasma
|
||||
air.adjust_moles(/datum/gas/plasma, -scrub_amt)
|
||||
absorbed_plasma += scrub_amt
|
||||
|
||||
if (air.return_temperature() > T20C)
|
||||
air.set_temperature(max(air.return_temperature() / 2, T20C))
|
||||
|
||||
location.air_update_turf(FALSE, FALSE)
|
||||
|
||||
/obj/effect/particle_effect/fluid/foam/firefighting/make_result()
|
||||
var/atom/movable/deposit = ..()
|
||||
if(istype(deposit) && deposit.reagents && absorbed_plasma > 0)
|
||||
deposit.reagents.add_reagent(/datum/reagent/stable_plasma, absorbed_plasma)
|
||||
absorbed_plasma = 0
|
||||
return deposit
|
||||
|
||||
/obj/effect/particle_effect/fluid/foam/firefighting/foam_mob(mob/living/foaming, delta_time)
|
||||
if(!istype(foaming))
|
||||
return
|
||||
foaming.adjust_fire_stacks(-2)
|
||||
foaming.ExtinguishMob()
|
||||
|
||||
/// A factory which produces firefighting foam
|
||||
/datum/effect_system/fluid_spread/foam/firefighting
|
||||
effect_type = /obj/effect/particle_effect/fluid/foam/firefighting
|
||||
|
||||
// Metal foam
|
||||
|
||||
/// A foam variant which
|
||||
/obj/effect/particle_effect/fluid/foam/metal
|
||||
name = "aluminium foam"
|
||||
result_type = /obj/structure/foamedmetal
|
||||
icon_state = "mfoam"
|
||||
slippery_foam = FALSE
|
||||
|
||||
/// A factory which produces aluminium metal foam.
|
||||
/datum/effect_system/fluid_spread/foam/metal
|
||||
effect_type = /obj/effect/particle_effect/fluid/foam/metal
|
||||
|
||||
/// FOAM STRUCTURE. Formed by metal foams. Dense and opaque, but easy to break
|
||||
/obj/structure/foamedmetal
|
||||
icon = 'icons/effects/effects.dmi'
|
||||
icon_state = "metalfoam"
|
||||
density = TRUE
|
||||
opacity = TRUE // changed in New()
|
||||
anchored = TRUE
|
||||
layer = EDGED_TURF_LAYER
|
||||
resistance_flags = FIRE_PROOF | ACID_PROOF
|
||||
name = "foamed metal"
|
||||
desc = "A lightweight foamed metal wall that can be used as base to construct a wall."
|
||||
gender = PLURAL
|
||||
max_integrity = 20
|
||||
CanAtmosPass = ATMOS_PASS_DENSITY
|
||||
///Var used to prevent spamming of the construction sound
|
||||
var/next_beep = 0
|
||||
|
||||
/obj/structure/foamedmetal/Initialize(mapload)
|
||||
. = ..()
|
||||
air_update_turf(1)
|
||||
|
||||
/obj/structure/foamedmetal/Move()
|
||||
var/turf/T = loc
|
||||
. = ..()
|
||||
move_update_air(T)
|
||||
|
||||
/obj/structure/foamedmetal/attack_paw(mob/user, list/modifiers)
|
||||
return attack_hand(user, modifiers)
|
||||
|
||||
/obj/structure/foamedmetal/play_attack_sound(damage_amount, damage_type = BRUTE, damage_flag = 0)
|
||||
playsound(src.loc, 'sound/weapons/tap.ogg', 100, TRUE)
|
||||
|
||||
/obj/structure/foamedmetal/attack_hand(mob/user, list/modifiers)
|
||||
. = ..()
|
||||
if(.)
|
||||
return
|
||||
user.changeNext_move(CLICK_CD_MELEE)
|
||||
user.do_attack_animation(src, ATTACK_EFFECT_PUNCH)
|
||||
to_chat(user, span_warning("You hit [src] but bounce off it!"))
|
||||
playsound(src.loc, 'sound/weapons/tap.ogg', 100, TRUE)
|
||||
|
||||
/// A metal foam variant which produces slightly sturdier walls.
|
||||
/obj/effect/particle_effect/fluid/foam/metal/iron
|
||||
name = "iron foam"
|
||||
result_type = /obj/structure/foamedmetal/iron
|
||||
|
||||
/// A factory which produces iron metal foam.
|
||||
/datum/effect_system/fluid_spread/foam/metal/iron
|
||||
effect_type = /obj/effect/particle_effect/fluid/foam/metal/iron
|
||||
|
||||
/// A variant of metal foam walls with higher durability.
|
||||
/obj/structure/foamedmetal/iron
|
||||
max_integrity = 50
|
||||
icon_state = "ironfoam"
|
||||
|
||||
/// A variant of metal foam which only produces walls at area boundaries.
|
||||
/obj/effect/particle_effect/fluid/foam/metal/smart
|
||||
name = "smart foam"
|
||||
|
||||
/// A factory which produces smart aluminium metal foam.
|
||||
/datum/effect_system/fluid_spread/foam/metal/smart
|
||||
effect_type = /obj/effect/particle_effect/fluid/foam/metal/smart
|
||||
|
||||
/obj/effect/particle_effect/fluid/foam/metal/smart/make_result() //Smart foam adheres to area borders for walls
|
||||
var/turf/open/location = loc
|
||||
if(isspaceturf(location))
|
||||
location.PlaceOnTop(/turf/open/floor/plating/foam)
|
||||
|
||||
for(var/cardinal in GLOB.cardinals)
|
||||
var/turf/cardinal_turf = get_step(location, cardinal)
|
||||
if(get_area(cardinal_turf) != get_area(location))
|
||||
return ..()
|
||||
return null
|
||||
|
||||
/datum/effect_system/fluid_spread/foam/metal/resin
|
||||
effect_type = /obj/effect/particle_effect/fluid/foam/metal/resin
|
||||
|
||||
/// A foam variant which produces atmos resin walls.
|
||||
/obj/effect/particle_effect/fluid/foam/metal/resin
|
||||
name = "resin foam"
|
||||
result_type = /obj/structure/foamedmetal/resin
|
||||
|
||||
/// Atmos Backpack Resin, transparent, prevents atmos and filters the air
|
||||
/obj/structure/foamedmetal/resin
|
||||
name = "\improper ATMOS Resin"
|
||||
desc = "A lightweight, transparent resin used to suffocate fires, scrub the air of toxins, and restore the air to a safe temperature. It can be used as base to construct a wall."
|
||||
opacity = FALSE
|
||||
icon_state = "atmos_resin"
|
||||
alpha = 120
|
||||
max_integrity = 10
|
||||
|
||||
/obj/structure/foamedmetal/resin/Initialize(mapload)
|
||||
. = ..()
|
||||
var/turf/open/location = loc
|
||||
if(!istype(location))
|
||||
return
|
||||
|
||||
location.ClearWet()
|
||||
if(location.air)
|
||||
var/datum/gas_mixture/air = location.air
|
||||
air.set_temperature(T20C)
|
||||
for(var/obj/effect/hotspot/fire in location)
|
||||
qdel(fire)
|
||||
|
||||
for(var/gas_type in air.get_gases())
|
||||
switch(gas_type)
|
||||
if(/datum/gas/oxygen, /datum/gas/nitrogen)
|
||||
continue
|
||||
else
|
||||
air.set_moles(gas_type, 0)
|
||||
location.air_update_turf()
|
||||
|
||||
for(var/obj/machinery/atmospherics/components/unary/comp in location)
|
||||
if(!comp.welded)
|
||||
comp.welded = TRUE
|
||||
comp.update_icon()
|
||||
comp.visible_message(span_danger("[comp] sealed shut!"))
|
||||
|
||||
for(var/mob/living/potential_tinder in location)
|
||||
potential_tinder.ExtinguishMob()
|
||||
for(var/obj/item/potential_tinder in location)
|
||||
potential_tinder.extinguish()
|
||||
@@ -0,0 +1,455 @@
|
||||
/**
|
||||
* A fluid which spreads through the air affecting every mob it engulfs.
|
||||
*/
|
||||
/obj/effect/particle_effect/fluid/smoke
|
||||
name = "smoke"
|
||||
icon = 'icons/effects/96x96.dmi'
|
||||
icon_state = "smoke"
|
||||
pixel_x = -32
|
||||
pixel_y = -32
|
||||
opacity = TRUE
|
||||
layer = FLY_LAYER
|
||||
anchored = TRUE
|
||||
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
||||
animate_movement = FALSE
|
||||
/// How long the smoke sticks around before it dissipates.
|
||||
var/lifetime = 10 SECONDS
|
||||
/// Makes the smoke react to changes on/of its turf.
|
||||
var/static/loc_connections = list(
|
||||
COMSIG_TURF_CALCULATED_ADJACENT_ATMOS = .proc/react_to_atmos_adjacency_changes
|
||||
)
|
||||
|
||||
/obj/effect/particle_effect/fluid/smoke/Initialize(mapload, datum/fluid_group/group, ...)
|
||||
. = ..()
|
||||
create_reagents(500)
|
||||
setDir(pick(GLOB.cardinals))
|
||||
//AddElement(/datum/element/connect_loc, loc_connections)
|
||||
SSsmoke.start_processing(src)
|
||||
|
||||
/obj/effect/particle_effect/fluid/smoke/Destroy()
|
||||
SSsmoke.stop_processing(src)
|
||||
if (spread_bucket)
|
||||
SSsmoke.cancel_spread(src)
|
||||
return ..()
|
||||
|
||||
|
||||
/**
|
||||
* Makes the smoke fade out and then deletes it.
|
||||
*/
|
||||
/obj/effect/particle_effect/fluid/smoke/proc/kill_smoke()
|
||||
SSsmoke.stop_processing(src)
|
||||
if (spread_bucket)
|
||||
SSsmoke.cancel_spread(src)
|
||||
INVOKE_ASYNC(src, .proc/fade_out)
|
||||
QDEL_IN(src, 1 SECONDS)
|
||||
|
||||
/**
|
||||
* Animates the smoke gradually fading out of visibility.
|
||||
* Also makes the smoke turf transparent as it passes 160 alpha.
|
||||
*
|
||||
* Arguments:
|
||||
* - frames = 0.8 [SECONDS]: The amount of time the smoke should fade out over.
|
||||
*/
|
||||
/obj/effect/particle_effect/fluid/smoke/proc/fade_out(frames = 0.8 SECONDS)
|
||||
if(alpha == 0) //Handle already transparent case
|
||||
if(opacity)
|
||||
set_opacity(FALSE)
|
||||
return
|
||||
|
||||
if(frames == 0)
|
||||
set_opacity(FALSE)
|
||||
alpha = 0
|
||||
return
|
||||
|
||||
var/time_to_transparency = round(((alpha - 160) / alpha) * frames)
|
||||
if(time_to_transparency >= 1)
|
||||
addtimer(CALLBACK(src, /atom.proc/set_opacity, FALSE), time_to_transparency)
|
||||
else
|
||||
set_opacity(FALSE)
|
||||
animate(src, time = frames, alpha = 0)
|
||||
|
||||
|
||||
/obj/effect/particle_effect/fluid/smoke/spread(delta_time = 0.1 SECONDS)
|
||||
if(group.total_size > group.target_size)
|
||||
return
|
||||
var/turf/t_loc = get_turf(src)
|
||||
if(!t_loc)
|
||||
return
|
||||
|
||||
for(var/turf/spread_turf in t_loc.GetAtmosAdjacentTurfs())
|
||||
if(group.total_size > group.target_size)
|
||||
break
|
||||
if(locate(type) in spread_turf)
|
||||
continue // Don't spread smoke where there's already smoke!
|
||||
for(var/mob/living/smoker in spread_turf)
|
||||
smoke_mob(smoker, delta_time)
|
||||
|
||||
var/obj/effect/particle_effect/fluid/smoke/spread_smoke = new type(spread_turf, group, src)
|
||||
reagents.copy_to(spread_smoke, reagents.total_volume)
|
||||
spread_smoke.add_atom_colour(color, FIXED_COLOUR_PRIORITY)
|
||||
spread_smoke.lifetime = lifetime
|
||||
|
||||
// the smoke spreads rapidly, but not instantly
|
||||
SSfoam.queue_spread(spread_smoke)
|
||||
|
||||
|
||||
/obj/effect/particle_effect/fluid/smoke/process(delta_time)
|
||||
lifetime -= delta_time SECONDS
|
||||
if(lifetime <= 0)
|
||||
kill_smoke()
|
||||
return FALSE
|
||||
for(var/mob/living/smoker in loc) // In case smoke somehow winds up in a locker or something this should still behave sanely.
|
||||
smoke_mob(smoker, delta_time)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Handles the effects of this smoke on any mobs it comes into contact with.
|
||||
*
|
||||
* Arguments:
|
||||
* - [smoker][/mob/living/carbon]: The mob that is being exposed to this smoke.
|
||||
* - delta_time: A scaling factor for the effects this has. Primarily based off of tick rate to normalize effects to units of rate/sec.
|
||||
*
|
||||
* Returns whether the smoke effect was applied to the mob.
|
||||
*/
|
||||
/obj/effect/particle_effect/fluid/smoke/proc/smoke_mob(mob/living/carbon/smoker, delta_time)
|
||||
if(!istype(smoker))
|
||||
return FALSE
|
||||
if(lifetime < 1)
|
||||
return FALSE
|
||||
if(smoker.internal != null || smoker.has_smoke_protection())
|
||||
return FALSE
|
||||
if(smoker.smoke_delay)
|
||||
return FALSE
|
||||
|
||||
smoker.smoke_delay = TRUE
|
||||
addtimer(VARSET_CALLBACK(smoker, smoke_delay, FALSE), 1 SECONDS)
|
||||
return TRUE
|
||||
|
||||
/**
|
||||
* Makes the smoke react to nearby opening/closing airlocks and the like.
|
||||
* Makes it possible for smoke to spread through airlocks that open after the edge of the smoke cloud has already spread past them.
|
||||
*
|
||||
* Arguments:
|
||||
* - [source][/turf]: The turf that has been touched by an atmos adjacency change.
|
||||
*/
|
||||
/obj/effect/particle_effect/fluid/smoke/proc/react_to_atmos_adjacency_changes(turf/source)
|
||||
SIGNAL_HANDLER
|
||||
if(!group)
|
||||
return NONE
|
||||
if (spread_bucket)
|
||||
return NONE
|
||||
SSsmoke.queue_spread(src)
|
||||
|
||||
/// A factory which produces clouds of smoke.
|
||||
/datum/effect_system/fluid_spread/smoke
|
||||
effect_type = /obj/effect/particle_effect/fluid/smoke
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Transparent smoke
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/// Same as the base type, but the smoke produced is not opaque
|
||||
/datum/effect_system/fluid_spread/smoke/transparent
|
||||
effect_type = /obj/effect/particle_effect/fluid/smoke/transparent
|
||||
|
||||
/// Same as the base type, but is not opaque.
|
||||
/obj/effect/particle_effect/fluid/smoke/transparent
|
||||
opacity = FALSE
|
||||
|
||||
/**
|
||||
* A helper proc used to spawn small puffs of smoke.
|
||||
*
|
||||
* Arguments:
|
||||
* - range: The amount of smoke to produce as number of steps from origin covered.
|
||||
* - amount: The amount of smoke to produce as the total desired coverage area. Autofilled from the range arg if not set.
|
||||
* - location: Where to produce the smoke cloud.
|
||||
* - smoke_type: The smoke typepath to spawn.
|
||||
*/
|
||||
/proc/do_smoke(range = 0, amount = DIAMOND_AREA(range), atom/holder = null, location = null, smoke_type = /obj/effect/particle_effect/fluid/smoke, log = FALSE)
|
||||
var/datum/effect_system/fluid_spread/smoke/smoke = new
|
||||
smoke.effect_type = smoke_type
|
||||
smoke.set_up(amount = amount, holder = holder, location = location)
|
||||
smoke.start(log = log)
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Quick smoke
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/// Smoke that dissipates as quickly as possible.
|
||||
/obj/effect/particle_effect/fluid/smoke/quick
|
||||
lifetime = 1 SECONDS
|
||||
opacity = FALSE
|
||||
|
||||
/// A factory which produces smoke that dissipates as quickly as possible.
|
||||
/datum/effect_system/fluid_spread/smoke/quick
|
||||
effect_type = /obj/effect/particle_effect/fluid/smoke/quick
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Bad smoke
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/// Smoke that makes you cough and reduces the power of lasers.
|
||||
/obj/effect/particle_effect/fluid/smoke/bad
|
||||
lifetime = 16 SECONDS
|
||||
|
||||
/obj/effect/particle_effect/fluid/smoke/bad/Initialize(mapload)
|
||||
. = ..()
|
||||
/*var/static/list/loc_connections = list(
|
||||
COMSIG_ATOM_ENTERED = .proc/on_entered,
|
||||
)*/
|
||||
RegisterSignal(src, COMSIG_ATOM_ENTERED, .proc/on_entered)
|
||||
//AddElement(/datum/element/connect_loc, loc_connections)
|
||||
|
||||
/obj/effect/particle_effect/fluid/smoke/bad/smoke_mob(mob/living/carbon/smoker)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
|
||||
smoker.drop_all_held_items()
|
||||
smoker.adjustOxyLoss(1)
|
||||
smoker.emote("cough")
|
||||
|
||||
/**
|
||||
* Reduces the power of any beam projectile that passes through the smoke.
|
||||
*
|
||||
* Arguments:
|
||||
* - [source][/datum]: The location that has just been entered. If [/datum/element/connect_loc] is working this is [src.loc][/atom/var/loc].
|
||||
* - [arrived][/atom/movable]: The atom that has just entered the source location.
|
||||
* - [old_loc][/atom]: The location the entering atom just was in.
|
||||
* - [old_locs][/list/atom]: The set of locations the entering atom was just in.
|
||||
*/
|
||||
/obj/effect/particle_effect/fluid/smoke/bad/proc/on_entered(datum/source, atom/movable/arrived, atom/oldloc)
|
||||
SIGNAL_HANDLER
|
||||
if(istype(arrived, /obj/item/projectile/beam))
|
||||
var/obj/item/projectile/beam/beam = arrived
|
||||
beam.damage = (beam.damage/2)
|
||||
|
||||
/// A factory which produces smoke that makes you cough.
|
||||
/datum/effect_system/fluid_spread/smoke/bad
|
||||
effect_type = /obj/effect/particle_effect/fluid/smoke/bad
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Bad Smoke (But Green (and Black))
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/// Green smoke that makes you cough.
|
||||
/obj/effect/particle_effect/fluid/smoke/bad/green
|
||||
name = "green smoke"
|
||||
color = "#00FF00"
|
||||
opacity = FALSE
|
||||
|
||||
/// A factory which produces green smoke that makes you cough.
|
||||
/datum/effect_system/fluid_spread/smoke/bad/green
|
||||
effect_type = /obj/effect/particle_effect/fluid/smoke/bad/green
|
||||
|
||||
/// Black smoke that makes you cough. (Actually dark grey)
|
||||
/obj/effect/particle_effect/fluid/smoke/bad/black
|
||||
name = "black smoke"
|
||||
color = "#383838"
|
||||
opacity = FALSE
|
||||
|
||||
/// A factory which produces black smoke that makes you cough.
|
||||
/datum/effect_system/fluid_spread/smoke/bad/black
|
||||
effect_type = /obj/effect/particle_effect/fluid/smoke/bad/black
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Nanofrost smoke
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/// Light blue, transparent smoke which is usually paired with a blast that chills every turf in the area.
|
||||
/obj/effect/particle_effect/fluid/smoke/freezing
|
||||
name = "nanofrost smoke"
|
||||
color = "#B2FFFF"
|
||||
opacity = FALSE
|
||||
|
||||
/// A factory which produces light blue, transparent smoke and a blast that chills every turf in the area.
|
||||
/datum/effect_system/fluid_spread/smoke/freezing
|
||||
effect_type = /obj/effect/particle_effect/fluid/smoke/freezing
|
||||
/// The radius in which to chill every open turf.
|
||||
var/blast = 0
|
||||
/// The temperature to set the turfs air temperature to.
|
||||
var/temperature = 2
|
||||
/// Whether to weld every vent and air scrubber in the affected area shut.
|
||||
var/weldvents = TRUE
|
||||
/// Whether to make sure each affected turf is actually within range before cooling it.
|
||||
var/distcheck = TRUE
|
||||
|
||||
/**
|
||||
* Chills an open turf.
|
||||
*
|
||||
* Forces the air temperature to a specific value.
|
||||
* Transmutes all of the plasma in the air into nitrogen.
|
||||
* Extinguishes all fires and burning objects/mobs in the turf.
|
||||
* May freeze all vents and vent scrubbers shut.
|
||||
*
|
||||
* Arguments:
|
||||
* - [chilly][/turf/open]: The open turf to chill
|
||||
*/
|
||||
/datum/effect_system/fluid_spread/smoke/freezing/proc/Chilled(turf/open/chilly)
|
||||
if(!istype(chilly))
|
||||
return
|
||||
|
||||
if(chilly.air)
|
||||
var/datum/gas_mixture/air = chilly.air
|
||||
if(!distcheck || get_dist(location, chilly) < blast) // Otherwise we'll get silliness like people using Nanofrost to kill people through walls with cold air
|
||||
air.set_temperature(temperature)
|
||||
|
||||
if(air.get_moles(/datum/gas/plasma))
|
||||
air.adjust_moles(/datum/gas/nitrogen, air.get_moles(/datum/gas/plasma))
|
||||
air.set_moles(/datum/gas/plasma, 0)
|
||||
|
||||
for(var/obj/effect/hotspot/fire in chilly)
|
||||
qdel(fire)
|
||||
chilly.air_update_turf()
|
||||
|
||||
if(weldvents)
|
||||
for(var/obj/machinery/atmospherics/components/unary/comp in chilly)
|
||||
if(!isnull(comp.welded) && !comp.welded) //must be an unwelded vent pump or vent scrubber.
|
||||
comp.welded = TRUE
|
||||
comp.update_icon()
|
||||
comp.visible_message(span_danger("[comp] is frozen shut!"))
|
||||
|
||||
// Extinguishes everything in the turf
|
||||
for(var/mob/living/potential_tinder in chilly)
|
||||
potential_tinder.ExtinguishMob()
|
||||
for(var/obj/item/potential_tinder in chilly)
|
||||
potential_tinder.extinguish()
|
||||
|
||||
/datum/effect_system/fluid_spread/smoke/freezing/set_up(range = 5, amount = DIAMOND_AREA(range), atom/holder, atom/location, blast_radius = 0)
|
||||
. = ..()
|
||||
blast = blast_radius
|
||||
|
||||
/datum/effect_system/fluid_spread/smoke/freezing/start(log = FALSE)
|
||||
if(blast)
|
||||
for(var/turf/T in RANGE_TURFS(blast, location))
|
||||
Chilled(T)
|
||||
return ..()
|
||||
|
||||
/// A variant of the base freezing smoke formerly used by the vent decontamination event.
|
||||
/datum/effect_system/fluid_spread/smoke/freezing/decon
|
||||
temperature = 293.15
|
||||
distcheck = FALSE
|
||||
weldvents = FALSE
|
||||
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Sleep smoke
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/// Smoke which knocks you out if you breathe it in.
|
||||
/obj/effect/particle_effect/fluid/smoke/sleeping
|
||||
color = "#9C3636"
|
||||
lifetime = 20 SECONDS
|
||||
|
||||
/obj/effect/particle_effect/fluid/smoke/sleeping/smoke_mob(mob/living/carbon/smoker, delta_time)
|
||||
if(..())
|
||||
smoker.Sleeping(20 SECONDS)
|
||||
smoker.emote("cough")
|
||||
return TRUE
|
||||
|
||||
/// A factory which produces sleeping smoke.
|
||||
/datum/effect_system/fluid_spread/smoke/sleeping
|
||||
effect_type = /obj/effect/particle_effect/fluid/smoke/sleeping
|
||||
|
||||
/////////////////////////////////////////////
|
||||
// Chem smoke
|
||||
/////////////////////////////////////////////
|
||||
|
||||
/**
|
||||
* Smoke which contains reagents which it applies to everything it comes into contact with.
|
||||
*/
|
||||
/obj/effect/particle_effect/fluid/smoke/chem
|
||||
lifetime = 20 SECONDS
|
||||
|
||||
/obj/effect/particle_effect/fluid/smoke/chem/process(delta_time)
|
||||
. = ..()
|
||||
if(!.)
|
||||
return
|
||||
|
||||
var/turf/location = get_turf(src)
|
||||
var/fraction = (delta_time SECONDS) / initial(lifetime)
|
||||
for(var/atom/movable/thing as anything in location)
|
||||
if(thing == src)
|
||||
continue
|
||||
if(location.intact && thing.level == 1) //hidden under the floor
|
||||
continue
|
||||
reagents.reaction(thing, TOUCH, fraction)
|
||||
|
||||
reagents.reaction(location, TOUCH, fraction)
|
||||
return TRUE
|
||||
|
||||
/obj/effect/particle_effect/fluid/smoke/chem/smoke_mob(mob/living/carbon/smoker, delta_time)
|
||||
if(lifetime < 1)
|
||||
return FALSE
|
||||
if(!istype(smoker))
|
||||
return FALSE
|
||||
if(smoker.internal != null || smoker.has_smoke_protection())
|
||||
return FALSE
|
||||
|
||||
var/fraction = (delta_time SECONDS) / initial(lifetime)
|
||||
reagents.copy_to(smoker, reagents.total_volume, fraction)
|
||||
reagents.reaction(smoker, INGEST, fraction)
|
||||
return TRUE
|
||||
|
||||
|
||||
/// A factory which produces clouds of chemical bearing smoke.
|
||||
/datum/effect_system/fluid_spread/smoke/chem
|
||||
/// Evil evil hack so we have something to "hold" our reagents
|
||||
var/datum/reagents/chemholder
|
||||
effect_type = /obj/effect/particle_effect/fluid/smoke/chem
|
||||
|
||||
/datum/effect_system/fluid_spread/smoke/chem/New()
|
||||
..()
|
||||
chemholder = new(1000, NO_REACT)
|
||||
|
||||
/datum/effect_system/fluid_spread/smoke/chem/Destroy()
|
||||
QDEL_NULL(chemholder)
|
||||
return ..()
|
||||
|
||||
|
||||
/datum/effect_system/fluid_spread/smoke/chem/set_up(range = 1, amount = DIAMOND_AREA(range), atom/holder, atom/location = null, datum/reagents/carry = null, silent = FALSE)
|
||||
. = ..()
|
||||
carry?.copy_to(chemholder, carry.total_volume)
|
||||
|
||||
if(silent)
|
||||
return
|
||||
|
||||
var/list/contained_reagents = list()
|
||||
for(var/datum/reagent/reagent as anything in chemholder.reagent_list)
|
||||
contained_reagents += "[reagent.volume]u [reagent]"
|
||||
|
||||
var/where = "[AREACOORD(location)]"
|
||||
var/contained = length(contained_reagents) ? "[contained_reagents.Join(", ", " \[", "\]")] @ [chemholder.chem_temp]K" : null
|
||||
if(carry.my_atom?.fingerprintslast) //Some reagents don't have a my_atom in some cases
|
||||
var/mob/M = get_mob_by_key(carry.my_atom.fingerprintslast)
|
||||
var/more = ""
|
||||
if(M)
|
||||
more = "[ADMIN_LOOKUPFLW(M)] "
|
||||
message_admins("Smoke: ([ADMIN_VERBOSEJMP(location)])[contained]. Key: [more ? more : carry.my_atom.fingerprintslast].")
|
||||
log_game("A chemical smoke reaction has taken place in ([where])[contained]. Last touched by [carry.my_atom.fingerprintslast].")
|
||||
else
|
||||
message_admins("Smoke: ([ADMIN_VERBOSEJMP(location)])[contained]. No associated key.")
|
||||
log_game("A chemical smoke reaction has taken place in ([where])[contained]. No associated key.")
|
||||
|
||||
/datum/effect_system/fluid_spread/smoke/chem/start(log = FALSE)
|
||||
var/start_loc = holder ? get_turf(holder) : src.location
|
||||
var/mixcolor = mix_color_from_reagents(chemholder.reagent_list)
|
||||
var/obj/effect/particle_effect/fluid/smoke/chem/smoke = new effect_type(start_loc, new /datum/fluid_group(amount))
|
||||
chemholder.copy_to(smoke, chemholder.total_volume)
|
||||
|
||||
if(mixcolor)
|
||||
smoke.add_atom_colour(mixcolor, FIXED_COLOUR_PRIORITY) // give the smoke color, if it has any to begin with
|
||||
if (log)
|
||||
help_out_the_admins(smoke, holder, location)
|
||||
smoke.spread() // Making the smoke spread immediately.
|
||||
|
||||
/**
|
||||
* A version of chemical smoke with a very short lifespan.
|
||||
*/
|
||||
/obj/effect/particle_effect/fluid/smoke/chem/quick
|
||||
lifetime = 4 SECONDS
|
||||
opacity = FALSE
|
||||
alpha = 100
|
||||
|
||||
/datum/effect_system/fluid_spread/smoke/chem/quick
|
||||
effect_type = /obj/effect/particle_effect/fluid/smoke/chem/quick
|
||||
@@ -161,12 +161,12 @@
|
||||
s.start()
|
||||
|
||||
if(entersmoke)
|
||||
var/datum/effect_system/smoke_spread/s = new
|
||||
s.set_up(4, 1, src, 0)
|
||||
var/datum/effect_system/fluid_spread/smoke/s = new
|
||||
s.set_up(4, holder = src, location = src)
|
||||
s.start()
|
||||
if(exitsmoke)
|
||||
var/datum/effect_system/smoke_spread/s = new
|
||||
s.set_up(4, 1, dest, 0)
|
||||
var/datum/effect_system/fluid_spread/smoke/s = new
|
||||
s.set_up(4, holder = src, location = dest)
|
||||
s.start()
|
||||
|
||||
uses--
|
||||
|
||||
@@ -928,15 +928,15 @@ CIGARETTE PACKETS ARE IN FANCY.DM
|
||||
//open flame removed because vapes are a closed system, they wont light anything on fire
|
||||
|
||||
if(super && vapetime >= vapedelay)//Time to start puffing those fat vapes, yo.
|
||||
var/datum/effect_system/smoke_spread/chem/smoke_machine/s = new
|
||||
s.set_up(reagents, 1, 24, loc)
|
||||
s.start()
|
||||
var/datum/effect_system/fluid_spread/smoke/chem/smoke_machine/puff = new
|
||||
puff.set_up(1, location = loc, carry = reagents, efficiency = 24)
|
||||
puff.start()
|
||||
vapetime -= vapedelay
|
||||
|
||||
if((obj_flags & EMAGGED) && vapetime >= vapedelay)
|
||||
var/datum/effect_system/smoke_spread/chem/smoke_machine/s = new
|
||||
s.set_up(reagents, 4, 24, loc)
|
||||
s.start()
|
||||
var/datum/effect_system/fluid_spread/smoke/chem/smoke_machine/puff = new
|
||||
puff.set_up(4, location = loc, carry = reagents, efficiency = 24)
|
||||
puff.start()
|
||||
vapetime -= vapedelay
|
||||
if(prob(5))//small chance for the vape to break and deal damage if it's emagged
|
||||
playsound(get_turf(src), 'sound/effects/pop_expl.ogg', 50, 0)
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
/obj/item/soap/suicide_act(mob/user)
|
||||
user.say(";FFFFFFFFFFFFFFFFUUUUUUUDGE!!", forced="soap suicide")
|
||||
user.visible_message(span_suicide("[user] lifts [src] to [user.p_their()] mouth and gnaws on it furiously, producing a thick froth! [user.p_they(TRUE)]'ll never get that BB gun now!"))
|
||||
new /obj/effect/particle_effect/foam(loc)
|
||||
new /obj/effect/particle_effect/fluid/foam(loc)
|
||||
return (TOXLOSS)
|
||||
|
||||
/obj/item/soap/proc/decreaseUses(mob/user, amount = 1)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
icon_state = "smokewhite"
|
||||
item_state = "flashbang"
|
||||
slot_flags = ITEM_SLOT_BELT
|
||||
var/datum/effect_system/smoke_spread/bad/smoke
|
||||
var/datum/effect_system/fluid_spread/smoke/bad/smoke
|
||||
|
||||
/obj/item/grenade/smokebomb/Initialize()
|
||||
. = ..()
|
||||
@@ -19,7 +19,7 @@
|
||||
/obj/item/grenade/smokebomb/prime()
|
||||
update_mob()
|
||||
playsound(src, 'sound/effects/smoke.ogg', 50, 1, -3)
|
||||
smoke.set_up(4, src)
|
||||
smoke.set_up(4, location = src)
|
||||
smoke.start()
|
||||
|
||||
|
||||
|
||||
@@ -776,8 +776,8 @@
|
||||
R.SetLockdown(1)
|
||||
R.anchored = TRUE
|
||||
R.expansion_count++
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(1, R.loc)
|
||||
var/datum/effect_system/fluid_spread/smoke/smoke = new
|
||||
smoke.set_up(1, location = R.loc)
|
||||
smoke.start()
|
||||
sleep(0.2 SECONDS)
|
||||
for(var/i in 1 to 4)
|
||||
|
||||
@@ -60,8 +60,8 @@
|
||||
return
|
||||
var/area/thearea = GLOB.teleportlocs[A]
|
||||
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(2, user.loc)
|
||||
var/datum/effect_system/fluid_spread/smoke/smoke = new
|
||||
smoke.set_up(2, location = user.loc)
|
||||
smoke.attach(user)
|
||||
smoke.start()
|
||||
var/list/L = list()
|
||||
|
||||
@@ -285,12 +285,12 @@
|
||||
if(!Adj|| !isturf(target))
|
||||
return
|
||||
for(var/S in target)
|
||||
if(istype(S, /obj/effect/particle_effect/foam/metal/resin) || istype(S, /obj/structure/foamedmetal/resin))
|
||||
if(istype(S, /obj/effect/particle_effect/fluid/foam/metal/resin) || istype(S, /obj/structure/foamedmetal/resin))
|
||||
to_chat(user, span_warning("There's already resin here!"))
|
||||
return
|
||||
if(resin_charges)
|
||||
var/obj/effect/particle_effect/foam/metal/resin/F = new (get_turf(target))
|
||||
F.amount = 0
|
||||
var/obj/effect/particle_effect/fluid/foam/metal/resin/foam = new (get_turf(target))
|
||||
foam.group.target_size = 0
|
||||
resin_charges--
|
||||
addtimer(CALLBACK(src, .proc/add_foam_charge), 5 SECONDS)
|
||||
else
|
||||
@@ -313,8 +313,9 @@
|
||||
anchored = TRUE
|
||||
|
||||
/obj/effect/resin_container/proc/Smoke()
|
||||
var/obj/effect/particle_effect/foam/metal/resin/S = new /obj/effect/particle_effect/foam/metal/resin(get_turf(loc))
|
||||
S.amount = 4
|
||||
var/datum/effect_system/fluid_spread/foam/metal/resin/foaming = new
|
||||
foaming.set_up(4, location = src)
|
||||
foaming.start()
|
||||
playsound(src,'sound/effects/bamf.ogg',100,1)
|
||||
qdel(src)
|
||||
|
||||
|
||||
@@ -10,8 +10,8 @@
|
||||
|
||||
/obj/structure/hivebot_beacon/Initialize()
|
||||
. = ..()
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(2, loc)
|
||||
var/datum/effect_system/fluid_spread/smoke/smoke = new
|
||||
smoke.set_up(2, location = loc)
|
||||
smoke.start()
|
||||
visible_message(span_boldannounce("[src] warps in!"))
|
||||
playsound(src.loc, 'sound/effects/empulse.ogg', 25, 1)
|
||||
|
||||
@@ -40,7 +40,7 @@
|
||||
activated = TRUE
|
||||
create_reagents(max_volume, DRAINABLE)
|
||||
reagents.add_reagent(reagent_id, start_volume)
|
||||
START_PROCESSING(SSfluids, src) //It's main function is to be plumbed, so use SSfluids
|
||||
START_PROCESSING(SSplumbing, src) //It's main function is to be plumbed, so use SSplumbing
|
||||
if(erupting_state)
|
||||
icon_state = erupting_state
|
||||
else
|
||||
|
||||
@@ -86,7 +86,7 @@
|
||||
to_chat(H, "Unable to reach your apprentice! You can either attack the spellbook with the contract to refund your points, or wait and try again later.")
|
||||
|
||||
/obj/item/antag_spawner/contract/spawn_antag(client/C, turf/T, kind ,datum/mind/user)
|
||||
new /obj/effect/particle_effect/smoke(T)
|
||||
new /obj/effect/particle_effect/fluid/smoke(T)
|
||||
var/mob/living/carbon/human/M = new/mob/living/carbon/human(T)
|
||||
C.prefs.apply_prefs_to(M)
|
||||
M.key = C.key
|
||||
|
||||
@@ -172,7 +172,7 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/blob/blobspore/death(gibbed)
|
||||
// On death, create a small smoke of harmful gas (s-Acid)
|
||||
var/datum/effect_system/smoke_spread/chem/S = new
|
||||
var/datum/effect_system/fluid_spread/smoke/chem/S = new
|
||||
var/turf/location = get_turf(src)
|
||||
|
||||
// Create the reagents to put into the air
|
||||
@@ -187,7 +187,7 @@
|
||||
|
||||
// Attach the smoke spreader and setup/start it.
|
||||
S.attach(location)
|
||||
S.set_up(reagents, death_cloud_size, location, silent = TRUE)
|
||||
S.set_up(death_cloud_size, location = location, carry = reagents, silent = TRUE)
|
||||
S.start()
|
||||
if(factory)
|
||||
factory.spore_delay = world.time + factory.spore_cooldown //put the factory on cooldown
|
||||
|
||||
@@ -138,7 +138,7 @@
|
||||
|
||||
/datum/action/bloodsucker/targeted/haste/batdash/FireTargetedPower(atom/target_atom)
|
||||
. = ..()
|
||||
do_smoke(2, owner.loc, smoke_type = /obj/effect/particle_effect/smoke/transparent) //so you can attack people after hasting
|
||||
do_smoke(2, owner.loc, smoke_type = /obj/effect/particle_effect/fluid/smoke/transparent) //so you can attack people after hasting
|
||||
|
||||
/datum/action/bloodsucker/targeted/bloodbolt
|
||||
name = "Blood Bolt"
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
DeactivatePower()
|
||||
|
||||
/datum/effect_system/steam_spread/bloodsucker
|
||||
effect_type = /obj/effect/particle_effect/smoke/vampsmoke
|
||||
effect_type = /obj/effect/particle_effect/fluid/smoke/vampsmoke
|
||||
|
||||
#undef GOHOME_START
|
||||
#undef GOHOME_FLICKER_ONE
|
||||
|
||||
@@ -108,7 +108,7 @@
|
||||
span_notice("You spin!"),
|
||||
)
|
||||
return
|
||||
do_smoke(0, owner.loc, smoke_type = /obj/effect/particle_effect/smoke/transparent)
|
||||
do_smoke(0, owner.loc, smoke_type = /obj/effect/particle_effect/fluid/smoke/transparent)
|
||||
|
||||
/datum/action/bloodsucker/targeted/lunge/proc/lunge_end(atom/hit_atom)
|
||||
var/mob/living/user = owner
|
||||
|
||||
@@ -81,7 +81,7 @@
|
||||
var/sound_dist = max(-6, -level_current) // world.view is 7, so 7-6 = hearing distance of 1
|
||||
playsound(get_turf(owner), 'sound/magic/summon_karp.ogg', sound_strength, 1, sound_dist)
|
||||
var/datum/effect_system/steam_spread/puff = new /datum/effect_system/steam_spread/()
|
||||
puff.effect_type = /obj/effect/particle_effect/smoke/vampsmoke
|
||||
puff.effect_type = /obj/effect/particle_effect/fluid/smoke/vampsmoke
|
||||
puff.set_up(3, 0, my_turf)
|
||||
puff.start()
|
||||
|
||||
@@ -110,7 +110,7 @@
|
||||
// Effect Destination
|
||||
playsound(get_turf(owner), 'sound/magic/summon_karp.ogg', sound_strength, 1, sound_dist)
|
||||
puff = new /datum/effect_system/steam_spread/()
|
||||
puff.effect_type = /obj/effect/particle_effect/smoke/vampsmoke
|
||||
puff.effect_type = /obj/effect/particle_effect/fluid/smoke/vampsmoke
|
||||
puff.set_up(3, 0, target_turf)
|
||||
puff.start()
|
||||
|
||||
|
||||
@@ -124,16 +124,15 @@
|
||||
// Effect
|
||||
playsound(get_turf(owner), 'sound/magic/smoke.ogg', 20, 1)
|
||||
var/datum/effect_system/steam_spread/puff = new /datum/effect_system/steam_spread/()
|
||||
puff.effect_type = /obj/effect/particle_effect/smoke/vampsmoke
|
||||
puff.effect_type = /obj/effect/particle_effect/fluid/smoke/vampsmoke
|
||||
puff.set_up(3, 0, get_turf(owner))
|
||||
puff.attach(owner) //OPTIONAL
|
||||
puff.start()
|
||||
owner.spin(8, 1) //Spin around like a loon.
|
||||
|
||||
/obj/effect/particle_effect/smoke/vampsmoke
|
||||
opaque = FALSE
|
||||
amount = 0
|
||||
/obj/effect/particle_effect/fluid/smoke/vampsmoke
|
||||
opacity = FALSE
|
||||
lifetime = 0
|
||||
|
||||
/obj/effect/particle_effect/smoke/vampsmoke/fade_out(frames = 6)
|
||||
/obj/effect/particle_effect/fluid/smoke/vampsmoke/fade_out(frames = 6)
|
||||
..(frames)
|
||||
|
||||
@@ -338,8 +338,8 @@
|
||||
..()
|
||||
|
||||
/datum/status_effect/brazil_penance/on_apply()
|
||||
var/datum/effect_system/smoke_spread/S = new
|
||||
S.set_up(1, get_turf(owner))
|
||||
var/datum/effect_system/fluid_spread/smoke/S = new
|
||||
S.set_up(1, location = get_turf(owner))
|
||||
S.start()
|
||||
owner.revive(full_heal = TRUE) //this totally won't be used to bypass stuff(tm)
|
||||
owner.regenerate_organs()
|
||||
|
||||
@@ -546,7 +546,7 @@
|
||||
disarm()
|
||||
return
|
||||
if(is_station_level(bomb_location.z))
|
||||
var/datum/round_event_control/E = locate(/datum/round_event_control/vent_clog/beer) in SSevents.control
|
||||
var/datum/round_event_control/E = locate(/datum/round_event_control/scrubber_overflow/beer) in SSevents.control
|
||||
if(E)
|
||||
E.runEvent()
|
||||
addtimer(CALLBACK(src, .proc/really_actually_explode), 110)
|
||||
@@ -570,8 +570,8 @@
|
||||
R.my_atom = src
|
||||
R.add_reagent(/datum/reagent/consumable/ethanol/beer, 100)
|
||||
|
||||
var/datum/effect_system/foam_spread/foam = new
|
||||
foam.set_up(200, get_turf(src), R)
|
||||
var/datum/effect_system/fluid_spread/foam/foam = new
|
||||
foam.set_up(200, location = get_turf(src), carry = R)
|
||||
foam.start()
|
||||
disarm()
|
||||
|
||||
|
||||
@@ -28,8 +28,8 @@
|
||||
SpeakPeace(list("Welcome to the error handling room.","Something's goofed up bad to send you here.","You should probably tell an admin what you were doing, or make a bug report."))
|
||||
for(var/obj/structure/signpost/salvation/S in orange(7))
|
||||
S.invisibility = 0
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(1, S.loc)
|
||||
var/datum/effect_system/fluid_spread/smoke/smoke = new
|
||||
smoke.set_up(1, location = S.loc)
|
||||
smoke.start()
|
||||
break
|
||||
if(1)
|
||||
|
||||
@@ -76,7 +76,11 @@
|
||||
return
|
||||
next_extinguish = world.time + extinguish_cooldown
|
||||
extinguishes_left--
|
||||
H.visible_message(span_warning("[H]'s suit spews out a tonne of space lube!"),span_warning("Your suit spews out a tonne of space lube!"))
|
||||
H.visible_message(span_warning("[H]'s suit spews out a tonne of space lube!"), span_warning("Your suit spews out a tonne of space lube!"))
|
||||
H.ExtinguishMob()
|
||||
new /obj/effect/particle_effect/foam(loc) //Truely terrifying.
|
||||
var/datum/effect_system/fluid_spread/foam/foam = new
|
||||
var/datum/reagents/foamreagent = new /datum/reagents(15)
|
||||
foamreagent.add_reagent(/datum/reagent/lube, 15)
|
||||
foam.set_up(4, holder = src, location = loc, carry = foamreagent)
|
||||
foam.start() //Truly terrifying.
|
||||
return 0
|
||||
|
||||
@@ -133,16 +133,15 @@ In my current plan for it, 'solid' will be defined as anything with density == 1
|
||||
penetrate(clong)
|
||||
else if(istype(clong, type))
|
||||
var/obj/effect/immovablerod/other = clong
|
||||
visible_message("<span class='danger'>[src] collides with [other]!\
|
||||
</span>")
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(2, get_turf(src))
|
||||
visible_message(span_danger("[src] collides with [other]!"))
|
||||
var/datum/effect_system/fluid_spread/smoke/smoke = new
|
||||
smoke.set_up(2, location = get_turf(src))
|
||||
smoke.start()
|
||||
qdel(src)
|
||||
qdel(other)
|
||||
|
||||
/obj/effect/immovablerod/proc/penetrate(mob/living/L)
|
||||
L.visible_message(span_danger("[L] is penetrated by an immovable rod!") , span_userdanger("The rod penetrates you!") , "<span class ='danger'>You hear a CLANG!</span>")
|
||||
L.visible_message(span_danger("[L] is penetrated by an immovable rod!") , span_userdanger("The rod penetrates you!") , span_danger("You hear a CLANG!"))
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
H.adjustBruteLoss(160)
|
||||
|
||||
133
code/modules/events/scrubber_overflow.dm
Normal file
133
code/modules/events/scrubber_overflow.dm
Normal file
@@ -0,0 +1,133 @@
|
||||
/datum/round_event_control/scrubber_overflow
|
||||
name = "Scrubber Overflow: Normal"
|
||||
typepath = /datum/round_event/scrubber_overflow
|
||||
weight = 10
|
||||
max_occurrences = 3
|
||||
min_players = 10
|
||||
|
||||
/datum/round_event/scrubber_overflow
|
||||
announceWhen = 1
|
||||
startWhen = 5
|
||||
endWhen = 35
|
||||
/// The probability that the ejected reagents will be dangerous
|
||||
var/danger_chance = 1
|
||||
/// Amount of reagents ejected from each scrubber
|
||||
var/reagents_amount = 50
|
||||
/// Probability of an individual scrubber overflowing
|
||||
var/overflow_probability = 50
|
||||
/// Specific reagent to force all scrubbers to use, null for random reagent choice
|
||||
var/forced_reagent
|
||||
/// A list of scrubbers that will have reagents ejected from them
|
||||
var/list/scrubbers = list()
|
||||
/// The list of chems that scrubbers can produce
|
||||
var/list/safer_chems = list(
|
||||
/datum/reagent/water,
|
||||
/datum/reagent/carbon,
|
||||
/datum/reagent/consumable/flour,
|
||||
/datum/reagent/space_cleaner,
|
||||
/datum/reagent/consumable/nutriment,
|
||||
/datum/reagent/consumable/condensedcapsaicin,
|
||||
/datum/reagent/drug/mushroomhallucinogen,
|
||||
/datum/reagent/lube,
|
||||
/datum/reagent/glitter/pink,
|
||||
/datum/reagent/cryptobiolin,
|
||||
/datum/reagent/toxin/plantbgone,
|
||||
/datum/reagent/blood,
|
||||
/datum/reagent/medicine/charcoal,
|
||||
/datum/reagent/drug/space_drugs,
|
||||
/datum/reagent/medicine/morphine,
|
||||
/datum/reagent/water/holywater,
|
||||
/datum/reagent/consumable/ethanol,
|
||||
/datum/reagent/consumable/hot_coco,
|
||||
/datum/reagent/toxin/acid,
|
||||
/datum/reagent/toxin/mindbreaker,
|
||||
/datum/reagent/toxin/rotatium,
|
||||
/datum/reagent/bluespace,
|
||||
/datum/reagent/pax,
|
||||
/datum/reagent/consumable/laughter,
|
||||
/datum/reagent/concentrated_barbers_aid,
|
||||
/datum/reagent/colorful_reagent,
|
||||
/datum/reagent/peaceborg/confuse,
|
||||
/datum/reagent/peaceborg/tire,
|
||||
/datum/reagent/consumable/sodiumchloride,
|
||||
/datum/reagent/consumable/ethanol/beer,
|
||||
/datum/reagent/hair_dye,
|
||||
/datum/reagent/consumable/sugar,
|
||||
/datum/reagent/glitter/white,
|
||||
/datum/reagent/growthserum
|
||||
)
|
||||
//needs to be chemid unit checked at some point
|
||||
|
||||
/datum/round_event/scrubber_overflow/announce(fake)
|
||||
priority_announce("The scrubbers network is experiencing a backpressure surge. Some ejection of contents may occur.", "Atmospherics alert")
|
||||
|
||||
/datum/round_event/scrubber_overflow/setup()
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent_scrubber/temp_vent in GLOB.machines)
|
||||
var/turf/scrubber_turf = get_turf(temp_vent)
|
||||
if(!scrubber_turf)
|
||||
continue
|
||||
if(!is_station_level(scrubber_turf.z))
|
||||
continue
|
||||
if(temp_vent.welded)
|
||||
continue
|
||||
if(!prob(overflow_probability))
|
||||
continue
|
||||
scrubbers += temp_vent
|
||||
|
||||
if(!scrubbers.len)
|
||||
return kill()
|
||||
|
||||
/datum/round_event/scrubber_overflow/start()
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent_scrubber/vent as anything in scrubbers)
|
||||
if(!vent.loc)
|
||||
CRASH("SCRUBBER SURGE: [vent] has no loc somehow?")
|
||||
|
||||
var/datum/reagents/dispensed_reagent = new /datum/reagents(reagents_amount)
|
||||
dispensed_reagent.my_atom = vent
|
||||
if (forced_reagent)
|
||||
dispensed_reagent.add_reagent(forced_reagent, reagents_amount)
|
||||
else if (prob(danger_chance))
|
||||
dispensed_reagent.add_reagent(get_random_reagent_id(), reagents_amount)
|
||||
new /mob/living/simple_animal/cockroach(get_turf(vent))
|
||||
new /mob/living/simple_animal/cockroach(get_turf(vent))
|
||||
else
|
||||
dispensed_reagent.add_reagent(pick(safer_chems), reagents_amount)
|
||||
|
||||
dispensed_reagent.create_foam(/datum/effect_system/fluid_spread/foam/short, reagents_amount)
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
/datum/round_event_control/scrubber_overflow/threatening
|
||||
name = "Scrubber Overflow: Threatening"
|
||||
typepath = /datum/round_event/scrubber_overflow/threatening
|
||||
weight = 4
|
||||
min_players = 25
|
||||
max_occurrences = 1
|
||||
earliest_start = 35 MINUTES
|
||||
|
||||
/datum/round_event/scrubber_overflow/threatening
|
||||
danger_chance = 10
|
||||
reagents_amount = 100
|
||||
|
||||
/datum/round_event_control/scrubber_overflow/catastrophic
|
||||
name = "Scrubber Overflow: Catastrophic"
|
||||
typepath = /datum/round_event/scrubber_overflow/catastrophic
|
||||
weight = 2
|
||||
min_players = 35
|
||||
max_occurrences = 1
|
||||
earliest_start = 45 MINUTES
|
||||
|
||||
/datum/round_event/scrubber_overflow/catastrophic
|
||||
danger_chance = 30
|
||||
reagents_amount = 150
|
||||
|
||||
/datum/round_event_control/scrubber_overflow/beer // Used when the beer nuke "detonates"
|
||||
name = "Scrubber Overflow: Beer"
|
||||
typepath = /datum/round_event/scrubber_overflow/beer
|
||||
weight = 0
|
||||
max_occurrences = 0
|
||||
|
||||
/datum/round_event/scrubber_overflow/beer
|
||||
overflow_probability = 100
|
||||
forced_reagent = /datum/reagent/consumable/ethanol/beer
|
||||
reagents_amount = 100
|
||||
@@ -1,138 +0,0 @@
|
||||
/datum/round_event_control/vent_clog
|
||||
name = "Clogged Vents: Normal"
|
||||
typepath = /datum/round_event/vent_clog
|
||||
weight = 10
|
||||
max_occurrences = 3
|
||||
min_players = 10
|
||||
|
||||
/datum/round_event/vent_clog
|
||||
announceWhen = 1
|
||||
startWhen = 5
|
||||
endWhen = 35
|
||||
var/interval = 2
|
||||
var/list/vents = list()
|
||||
var/randomProbability = 1
|
||||
var/reagentsAmount = 100
|
||||
var/list/saferChems = list(/datum/reagent/water,/datum/reagent/carbon,/datum/reagent/consumable/flour,/datum/reagent/space_cleaner,/datum/reagent/consumable/nutriment,/datum/reagent/consumable/condensedcapsaicin,/datum/reagent/drug/mushroomhallucinogen,/datum/reagent/lube,/datum/reagent/glitter/pink,/datum/reagent/cryptobiolin,
|
||||
/datum/reagent/toxin/plantbgone,/datum/reagent/blood,/datum/reagent/medicine/charcoal,/datum/reagent/drug/space_drugs,/datum/reagent/medicine/morphine,/datum/reagent/water/holywater,/datum/reagent/consumable/ethanol,/datum/reagent/consumable/hot_coco,/datum/reagent/toxin/acid,/datum/reagent/toxin/mindbreaker,/datum/reagent/toxin/rotatium,/datum/reagent/bluespace,
|
||||
/datum/reagent/pax,/datum/reagent/consumable/laughter,/datum/reagent/concentrated_barbers_aid,/datum/reagent/colorful_reagent,/datum/reagent/peaceborg/confuse,/datum/reagent/peaceborg/tire,/datum/reagent/consumable/sodiumchloride,/datum/reagent/consumable/ethanol/beer,/datum/reagent/hair_dye,/datum/reagent/consumable/sugar,/datum/reagent/glitter/white,/datum/reagent/growthserum)
|
||||
//needs to be chemid unit checked at some point
|
||||
|
||||
/datum/round_event/vent_clog/announce()
|
||||
priority_announce("The scrubbers network is experiencing a backpressure surge. Some ejection of contents may occur.", "Atmospherics alert")
|
||||
|
||||
/datum/round_event/vent_clog/setup()
|
||||
endWhen = rand(25, 100)
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent_scrubber/temp_vent in GLOB.machines)
|
||||
var/turf/T = get_turf(temp_vent)
|
||||
if(T && is_station_level(T.z) && !temp_vent.welded)
|
||||
vents += temp_vent
|
||||
if(!vents.len)
|
||||
return kill()
|
||||
|
||||
/datum/round_event/vent_clog/start()
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent in vents)
|
||||
if(vent && vent.loc)
|
||||
var/datum/reagents/R = new/datum/reagents(1000)
|
||||
R.my_atom = vent
|
||||
if (prob(randomProbability))
|
||||
R.add_reagent(get_random_reagent_id(), reagentsAmount)
|
||||
else
|
||||
R.add_reagent(pick(saferChems), reagentsAmount)
|
||||
|
||||
var/datum/effect_system/foam_spread/foam = new
|
||||
foam.one_apply_per_object = TRUE
|
||||
foam.set_up(200, get_turf(vent), R)
|
||||
foam.start()
|
||||
|
||||
CHECK_TICK
|
||||
|
||||
/datum/round_event_control/vent_clog/threatening
|
||||
name = "Clogged Vents: Threatening"
|
||||
typepath = /datum/round_event/vent_clog/threatening
|
||||
weight = 4
|
||||
min_players = 25
|
||||
max_occurrences = 1
|
||||
earliest_start = 35 MINUTES
|
||||
|
||||
/datum/round_event/vent_clog/threatening
|
||||
randomProbability = 10
|
||||
reagentsAmount = 200
|
||||
|
||||
/datum/round_event_control/vent_clog/catastrophic
|
||||
name = "Clogged Vents: Catastrophic"
|
||||
typepath = /datum/round_event/vent_clog/catastrophic
|
||||
weight = 2
|
||||
min_players = 35
|
||||
max_occurrences = 1
|
||||
earliest_start = 45 MINUTES
|
||||
|
||||
/datum/round_event/vent_clog/catastrophic
|
||||
randomProbability = 30
|
||||
reagentsAmount = 250
|
||||
|
||||
/datum/round_event_control/vent_clog/beer
|
||||
name = "Foamy beer stationwide"
|
||||
typepath = /datum/round_event/vent_clog/beer
|
||||
max_occurrences = 0
|
||||
|
||||
/datum/round_event_control/vent_clog/cleaner
|
||||
name = "Cleaner stationwide"
|
||||
typepath = /datum/round_event/vent_clog/cleaner
|
||||
max_occurrences = 0
|
||||
weight = 10
|
||||
min_players = 5
|
||||
max_occurrences = 1
|
||||
|
||||
/datum/round_event_control/vent_clog/plasma_decon
|
||||
name = "Plasma decontamination"
|
||||
typepath = /datum/round_event/vent_clog/plasma_decon
|
||||
max_occurrences = 0
|
||||
|
||||
/datum/round_event/vent_clog/beer
|
||||
reagentsAmount = 100
|
||||
|
||||
/datum/round_event/vent_clog/beer/announce()
|
||||
priority_announce("The scrubbers network is experiencing an unexpected surge of pressurized beer. Some ejection of contents may occur.", "Atmospherics alert")
|
||||
|
||||
/datum/round_event/vent_clog/beer/start()
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent in vents)
|
||||
if(vent && vent.loc)
|
||||
var/datum/reagents/R = new/datum/reagents(100)
|
||||
R.my_atom = vent
|
||||
R.add_reagent(/datum/reagent/consumable/ethanol/beer, reagentsAmount)
|
||||
|
||||
var/datum/effect_system/foam_spread/foam = new
|
||||
foam.one_apply_per_object = TRUE
|
||||
foam.set_up(200, get_turf(vent), R)
|
||||
foam.start()
|
||||
CHECK_TICK
|
||||
|
||||
/datum/round_event/vent_clog/cleaner
|
||||
reagentsAmount = 100
|
||||
|
||||
/datum/round_event/vent_clog/cleaner/announce()
|
||||
priority_announce("The scrubbers network cleaning cycle has been triggered. Some ejection of contents may occur.", "Atmospherics alert")
|
||||
|
||||
/datum/round_event/vent_clog/cleaner/start()
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent in vents)
|
||||
if(vent && vent.loc)
|
||||
var/datum/reagents/R = new/datum/reagents(100)
|
||||
R.my_atom = vent
|
||||
R.add_reagent(/datum/reagent/space_cleaner, reagentsAmount)
|
||||
|
||||
var/datum/effect_system/foam_spread/foam = new
|
||||
foam.set_up(200, get_turf(vent), R)
|
||||
foam.start()
|
||||
CHECK_TICK
|
||||
|
||||
/datum/round_event/vent_clog/plasma_decon/announce()
|
||||
priority_announce("We are deploying an experimental plasma decontamination system. Please stand away from the vents and do not breathe the smoke that comes out.", "Central Command Update")
|
||||
|
||||
/datum/round_event/vent_clog/plasma_decon/start()
|
||||
for(var/obj/machinery/atmospherics/components/unary/vent in vents)
|
||||
if(vent && vent.loc)
|
||||
var/datum/effect_system/smoke_spread/freezing/decon/smoke = new
|
||||
smoke.set_up(7, get_turf(vent), 7)
|
||||
smoke.start()
|
||||
CHECK_TICK
|
||||
@@ -55,6 +55,6 @@
|
||||
I.name = "cursed " + I.name
|
||||
|
||||
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(0, H.loc)
|
||||
var/datum/effect_system/fluid_spread/smoke/smoke = new
|
||||
smoke.set_up(0, location = H.loc)
|
||||
smoke.start()
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
return //Sad Trombone
|
||||
var/mob/dead/observer/C = pick(candidates)
|
||||
|
||||
new /obj/effect/particle_effect/smoke(W.loc)
|
||||
new /obj/effect/particle_effect/fluid/smoke(W.loc)
|
||||
|
||||
var/mob/living/carbon/human/I = new /mob/living/carbon/human(W.loc)
|
||||
W.dna.transfer_identity(I, transfer_SE=1)
|
||||
|
||||
@@ -31,8 +31,8 @@
|
||||
moblocs.len -= 1
|
||||
|
||||
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(0, H.loc)
|
||||
var/datum/effect_system/fluid_spread/smoke/smoke = new
|
||||
smoke.set_up(0, location = H.loc)
|
||||
smoke.start()
|
||||
|
||||
//---//
|
||||
@@ -65,8 +65,8 @@
|
||||
mobnames.len -= 1
|
||||
|
||||
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(0, H.loc)
|
||||
var/datum/effect_system/fluid_spread/smoke/smoke = new
|
||||
smoke.set_up(0, location = H.loc)
|
||||
smoke.start()
|
||||
|
||||
//---//
|
||||
@@ -99,6 +99,6 @@
|
||||
mobs -= mobs[mobs.len]
|
||||
|
||||
for(var/mob/living/carbon/human/H in GLOB.alive_mob_list)
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(0, H.loc)
|
||||
var/datum/effect_system/fluid_spread/smoke/smoke = new
|
||||
smoke.set_up(0, location = H.loc)
|
||||
smoke.start()
|
||||
|
||||
@@ -16,7 +16,7 @@
|
||||
/obj/item/reagent_containers/food/snacks/burger/plain/Initialize()
|
||||
. = ..()
|
||||
if(prob(1))
|
||||
new/obj/effect/particle_effect/smoke(get_turf(src))
|
||||
new/obj/effect/particle_effect/fluid/smoke(get_turf(src))
|
||||
playsound(src, 'sound/effects/smoke.ogg', 50, TRUE)
|
||||
visible_message(span_warning("Oh, ye gods! [src] is ruined! But what if...?"))
|
||||
name = "steamed ham"
|
||||
|
||||
@@ -80,8 +80,8 @@
|
||||
if(!grilled_item)
|
||||
grill_fuel -= GRILL_FUELUSAGE_IDLE
|
||||
if(DT_PROB(0.5, delta_time))
|
||||
var/datum/effect_system/smoke_spread/bad/smoke = new
|
||||
smoke.set_up(1, loc)
|
||||
var/datum/effect_system/fluid_spread/smoke/bad/smoke = new
|
||||
smoke.set_up(1, location = loc)
|
||||
smoke.start()
|
||||
if(grilled_item)
|
||||
SEND_SIGNAL(grilled_item, COMSIG_ITEM_GRILLED, src, 1)
|
||||
|
||||
@@ -319,9 +319,9 @@
|
||||
if(notice)
|
||||
return null
|
||||
//Totally nanite construction system not an immersion breaking spawning
|
||||
var/datum/effect_system/smoke_spread/s = new
|
||||
s.set_up(4,get_turf(centerpiece))
|
||||
s.start()
|
||||
var/datum/effect_system/fluid_spread/smoke/fourth_wall_guard = new
|
||||
fourth_wall_guard.set_up(4, location = get_turf(centerpiece))
|
||||
fourth_wall_guard.start()
|
||||
var/obj/machinery/bsa/full/cannon = new(get_turf(centerpiece),centerpiece.get_cannon_direction())
|
||||
qdel(centerpiece.front)
|
||||
qdel(centerpiece.back)
|
||||
|
||||
@@ -56,10 +56,10 @@
|
||||
wine_power = 60
|
||||
|
||||
/obj/item/reagent_containers/food/snacks/grown/onion/slice(accuracy, obj/item/W, mob/user)
|
||||
var/datum/effect_system/smoke_spread/chem/S = new //Since the onion is destroyed when it's sliced,
|
||||
var/datum/effect_system/fluid_spread/smoke/chem/S = new //Since the onion is destroyed when it's sliced,
|
||||
var/splat_location = get_turf(src) //we need to set up the smoke beforehand
|
||||
S.attach(splat_location)
|
||||
S.set_up(reagents, 0, splat_location, 0)
|
||||
S.set_up(0, location = splat_location, carry = reagents)
|
||||
if(..())
|
||||
S.start()
|
||||
return TRUE
|
||||
|
||||
@@ -401,11 +401,11 @@
|
||||
name = "gaseous decomposition"
|
||||
|
||||
/datum/plant_gene/trait/smoke/on_squash(obj/item/reagent_containers/food/snacks/grown/G, atom/target)
|
||||
var/datum/effect_system/smoke_spread/chem/S = new
|
||||
var/datum/effect_system/fluid_spread/smoke/chem/S = new
|
||||
var/splat_location = get_turf(target)
|
||||
var/smoke_amount = round(sqrt(G.seed.potency * 0.1), 1)
|
||||
S.attach(splat_location)
|
||||
S.set_up(G.reagents, smoke_amount, splat_location, 0)
|
||||
S.set_up(smoke_amount, location = splat_location, carry = G.reagents)
|
||||
S.start()
|
||||
G.reagents.clear_reagents()
|
||||
|
||||
|
||||
@@ -64,7 +64,7 @@
|
||||
log_admin("[key_name(usr)] activated a bluespace capsule away from the mining level at [AREACOORD(T)]")
|
||||
|
||||
playsound(src, 'sound/effects/phasein.ogg', 100, TRUE)
|
||||
new /obj/effect/particle_effect/smoke(get_turf(src))
|
||||
new /obj/effect/particle_effect/fluid/smoke(get_turf(src))
|
||||
qdel(src)
|
||||
|
||||
/obj/item/survivalcapsule/luxury
|
||||
|
||||
@@ -124,7 +124,7 @@
|
||||
explosion(src.loc,1,2,4,flame_range = 2)
|
||||
qdel(src)
|
||||
else
|
||||
deployed_smartmetal = WEAKREF(new /obj/effect/particle_effect/foam/metal/smart(get_turf(src)))
|
||||
deployed_smartmetal = WEAKREF(new /obj/effect/particle_effect/fluid/foam/metal/smart(get_turf(src)))
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
|
||||
@@ -253,7 +253,9 @@
|
||||
T.MakeSlippery(TURF_WET_WATER, min_wet_time = 20 SECONDS, wet_time_to_add = 15 SECONDS)
|
||||
else
|
||||
visible_message(span_danger("[src] whirs and bubbles violently, before releasing a plume of froth!"))
|
||||
new /obj/effect/particle_effect/foam(loc)
|
||||
var/datum/effect_system/fluid_spread/foam/foam = new
|
||||
foam.set_up(2, holder = src, location = loc)
|
||||
foam.start()
|
||||
|
||||
else
|
||||
..()
|
||||
|
||||
@@ -273,7 +273,9 @@
|
||||
|
||||
/mob/living/simple_animal/bot/firebot/temperature_expose(datum/gas_mixture/air, temperature, volume)
|
||||
if((temperature > T0C + 200 || temperature < BODYTEMP_COLD_DAMAGE_LIMIT) && foam_cooldown + FOAM_INTERVAL < world.time)
|
||||
new /obj/effect/particle_effect/foam/firefighting(loc)
|
||||
var/datum/effect_system/fluid_spread/foam/firefighting/foam = new
|
||||
foam.set_up(3, holder = src, location = loc)
|
||||
foam.start()
|
||||
foam_cooldown = world.time
|
||||
..()
|
||||
|
||||
|
||||
@@ -210,8 +210,8 @@
|
||||
visible_message(span_boldwarning("[src] spews smoke from the tip of their spine!"))
|
||||
else
|
||||
visible_message(span_boldwarning("[src] spews smoke from its maw!"))
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(2, T)
|
||||
var/datum/effect_system/fluid_spread/smoke/smoke = new
|
||||
smoke.set_up(2, location = T)
|
||||
smoke.start()
|
||||
|
||||
/obj/item/gps/internal/legionnaire
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
response_help = "dips a finger into"
|
||||
response_disarm = "gently scoops and pours aside"
|
||||
emote_see = list("bubbles", "oozes")
|
||||
loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/particle_effect/foam)
|
||||
loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/particle_effect/fluid/foam)
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/clown/lube/Life()
|
||||
. = ..()
|
||||
@@ -226,7 +226,7 @@
|
||||
armour_penetration = 20
|
||||
attacktext = "steals the girlfriend of"
|
||||
attack_sound = 'sound/items/airhorn2.ogg'
|
||||
loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/effect/particle_effect/foam, /obj/item/soap)
|
||||
loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/effect/particle_effect/fluid/foam, /obj/item/soap)
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/clown/clownhulk/honcmunculus
|
||||
name = "Honkmunculus"
|
||||
@@ -246,7 +246,7 @@
|
||||
melee_damage_upper = 10
|
||||
attacktext = "ferociously mauls"
|
||||
environment_smash = ENVIRONMENT_SMASH_NONE
|
||||
loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/xeno/bodypartless, /obj/effect/particle_effect/foam, /obj/item/soap)
|
||||
loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/xeno/bodypartless, /obj/effect/particle_effect/fluid/foam, /obj/item/soap)
|
||||
attack_reagent = /datum/reagent/peaceborg/confuse
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/clown/clownhulk/destroyer
|
||||
@@ -267,7 +267,7 @@
|
||||
attacktext = "acts out divine vengeance on"
|
||||
obj_damage = 50
|
||||
environment_smash = ENVIRONMENT_SMASH_RWALLS
|
||||
loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/effect/particle_effect/foam, /obj/item/soap)
|
||||
loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/effect/particle_effect/fluid/foam, /obj/item/soap)
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/clown/clownhulk/punisher
|
||||
name = "The Punisher"
|
||||
@@ -288,7 +288,7 @@
|
||||
attacktext = "flexes on"
|
||||
obj_damage = 50
|
||||
environment_smash = ENVIRONMENT_SMASH_RWALLS
|
||||
loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/effect/particle_effect/foam, /obj/item/soap)
|
||||
loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/human, /obj/effect/particle_effect/fluid/foam, /obj/item/soap)
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/clown/mutant
|
||||
name = "Unknown"
|
||||
@@ -324,7 +324,7 @@
|
||||
mob_size = MOB_SIZE_LARGE
|
||||
speed = 20
|
||||
attacktext = "bounces off of"
|
||||
loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/xeno/bodypartless, /obj/effect/particle_effect/foam, /obj/item/soap, /obj/effect/gibspawner/generic, /obj/effect/gibspawner/generic/animal, /obj/effect/gibspawner/human/bodypartless, /obj/effect/gibspawner/human)
|
||||
loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/xeno/bodypartless, /obj/effect/particle_effect/fluid/foam, /obj/item/soap, /obj/effect/gibspawner/generic, /obj/effect/gibspawner/generic/animal, /obj/effect/gibspawner/human/bodypartless, /obj/effect/gibspawner/human)
|
||||
attack_reagent = /datum/reagent/toxin/mindbreaker
|
||||
|
||||
/mob/living/simple_animal/hostile/retaliate/clown/mutant/thicc
|
||||
@@ -338,5 +338,5 @@
|
||||
mob_size = MOB_SIZE_LARGE
|
||||
speed = 20
|
||||
attacktext = "bounces off of"
|
||||
loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/xeno/bodypartless, /obj/effect/particle_effect/foam, /obj/item/soap, /obj/effect/gibspawner/generic, /obj/effect/gibspawner/generic/animal, /obj/effect/gibspawner/human/bodypartless, /obj/effect/gibspawner/human)
|
||||
loot = list(/obj/item/clothing/mask/gas/clown_hat, /obj/effect/gibspawner/xeno/bodypartless, /obj/effect/particle_effect/fluid/foam, /obj/item/soap, /obj/effect/gibspawner/generic, /obj/effect/gibspawner/generic/animal, /obj/effect/gibspawner/human/bodypartless, /obj/effect/gibspawner/human)
|
||||
attack_reagent = /datum/reagent/consumable/banana
|
||||
@@ -224,8 +224,8 @@
|
||||
|
||||
/mob/living/simple_animal/hostile/venus_human_trap/proc/check_gas()
|
||||
for(var/contents in src.loc)
|
||||
if(istype(contents, /obj/effect/particle_effect/smoke/chem))
|
||||
var/obj/effect/particle_effect/smoke/chem/gas = contents
|
||||
if(istype(contents, /obj/effect/particle_effect/fluid/smoke/chem))
|
||||
var/obj/effect/particle_effect/fluid/smoke/chem/gas = contents
|
||||
if(gas.reagents.has_reagent(/datum/reagent/toxin/plantbgone, 1))
|
||||
return TRUE
|
||||
return FALSE
|
||||
|
||||
@@ -2,11 +2,10 @@
|
||||
|
||||
//Smoke bomb
|
||||
/obj/item/clothing/suit/space/space_ninja/proc/ninjasmoke()
|
||||
|
||||
if(!ninjacost(0,N_SMOKE_BOMB))
|
||||
if(!ninjacost(0, N_SMOKE_BOMB))
|
||||
var/mob/living/carbon/human/H = affecting
|
||||
var/datum/effect_system/smoke_spread/bad/smoke = new
|
||||
smoke.set_up(4, H.loc)
|
||||
var/datum/effect_system/fluid_spread/smoke/bad/smoke = new
|
||||
smoke.set_up(4, location = H.loc)
|
||||
smoke.start()
|
||||
playsound(H.loc, 'sound/effects/bamf.ogg', 50, 2)
|
||||
s_bombs--
|
||||
|
||||
@@ -145,8 +145,8 @@
|
||||
|
||||
/obj/item/gun/magic/wand/teleport/zap_self(mob/living/user)
|
||||
if(do_teleport(user, user, 10, channel = TELEPORT_CHANNEL_MAGIC))
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(3, user.loc)
|
||||
var/datum/effect_system/fluid_spread/smoke/smoke = new
|
||||
smoke.set_up(3, location = user.loc)
|
||||
smoke.start()
|
||||
charges--
|
||||
..()
|
||||
@@ -166,8 +166,8 @@
|
||||
|
||||
if(do_teleport(user, destination, channel=TELEPORT_CHANNEL_MAGIC))
|
||||
for(var/t in list(origin, destination))
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(0, t)
|
||||
var/datum/effect_system/fluid_spread/smoke/smoke = new
|
||||
smoke.set_up(0, location = t)
|
||||
smoke.start()
|
||||
..()
|
||||
|
||||
|
||||
@@ -71,8 +71,9 @@
|
||||
if(!stuff.anchored && stuff.loc && !isobserver(stuff))
|
||||
if(do_teleport(stuff, stuff, 10, channel = TELEPORT_CHANNEL_MAGIC))
|
||||
teleammount++
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(max(round(4 - teleammount),0), stuff.loc) //Smoke drops off if a lot of stuff is moved for the sake of sanity
|
||||
var/smoke_range = max(round(4 - teleammount), 0)
|
||||
var/datum/effect_system/fluid_spread/smoke/smoke = new
|
||||
smoke.set_up(smoke_range, location = stuff.loc) //Smoke drops off if a lot of stuff is moved for the sake of sanity
|
||||
smoke.start()
|
||||
|
||||
/obj/item/projectile/magic/safety
|
||||
@@ -92,8 +93,8 @@
|
||||
|
||||
if(do_teleport(target, destination_turf, channel=TELEPORT_CHANNEL_MAGIC))
|
||||
for(var/t in list(origin_turf, destination_turf))
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(0, t)
|
||||
var/datum/effect_system/fluid_spread/smoke/smoke = new
|
||||
smoke.set_up(0, location = t)
|
||||
smoke.start()
|
||||
|
||||
/obj/item/projectile/magic/door
|
||||
|
||||
@@ -15,17 +15,19 @@
|
||||
var/setting = 1 // displayed range is 3 * setting
|
||||
var/max_range = 3 // displayed max range is 3 * max range
|
||||
|
||||
/datum/effect_system/smoke_spread/chem/smoke_machine/set_up(datum/reagents/carry, setting=1, efficiency=10, loc, silent=FALSE)
|
||||
amount = setting
|
||||
carry.copy_to(chemholder, 20)
|
||||
carry.remove_any(amount * 16 / efficiency)
|
||||
location = loc
|
||||
/datum/effect_system/fluid_spread/smoke/chem/smoke_machine/set_up(range = 1, amount = DIAMOND_AREA(range), atom/location = null, datum/reagents/carry = null, efficiency = 10, silent=FALSE)
|
||||
src.location = get_turf(location)
|
||||
src.amount = amount
|
||||
carry?.copy_to(chemholder, 20)
|
||||
carry?.remove_any(amount / efficiency)
|
||||
|
||||
/datum/effect_system/smoke_spread/chem/smoke_machine
|
||||
effect_type = /obj/effect/particle_effect/smoke/chem/smoke_machine
|
||||
/// A factory which produces clouds of smoke for the smoke machine.
|
||||
/datum/effect_system/fluid_spread/smoke/chem/smoke_machine
|
||||
effect_type = /obj/effect/particle_effect/fluid/smoke/chem/smoke_machine
|
||||
|
||||
/obj/effect/particle_effect/smoke/chem/smoke_machine
|
||||
opaque = FALSE
|
||||
/// Smoke which is produced by the smoke machine. Slightly transparent and does not block line of sight.
|
||||
/obj/effect/particle_effect/fluid/smoke/chem/smoke_machine
|
||||
opacity = FALSE
|
||||
alpha = 100
|
||||
|
||||
/obj/machinery/smoke_machine/Initialize()
|
||||
@@ -54,9 +56,9 @@
|
||||
if(new_volume < reagents.total_volume)
|
||||
reagents.reaction(loc, TOUCH) // if someone manages to downgrade it without deconstructing
|
||||
reagents.clear_reagents()
|
||||
efficiency = 9
|
||||
efficiency = 18
|
||||
for(var/obj/item/stock_parts/capacitor/C in component_parts)
|
||||
efficiency += C.rating
|
||||
efficiency += 2 * C.rating
|
||||
max_range = 1
|
||||
for(var/obj/item/stock_parts/manipulator/M in component_parts)
|
||||
max_range += M.rating
|
||||
@@ -70,12 +72,12 @@
|
||||
on = FALSE
|
||||
update_icon()
|
||||
return
|
||||
var/turf/T = get_turf(src)
|
||||
var/smoke_test = locate(/obj/effect/particle_effect/smoke) in T
|
||||
var/turf/location = get_turf(src)
|
||||
var/smoke_test = locate(/obj/effect/particle_effect/fluid/smoke) in location
|
||||
if(on && !smoke_test)
|
||||
update_icon()
|
||||
var/datum/effect_system/smoke_spread/chem/smoke_machine/smoke = new()
|
||||
smoke.set_up(reagents, setting*3, efficiency, T)
|
||||
var/datum/effect_system/fluid_spread/smoke/chem/smoke_machine/smoke = new()
|
||||
smoke.set_up(setting * 3, location = location, carry = reagents, efficiency = efficiency)
|
||||
smoke.start()
|
||||
|
||||
/obj/machinery/smoke_machine/attackby(obj/item/I, mob/user, params)
|
||||
|
||||
@@ -249,25 +249,25 @@
|
||||
color = "#A6FAFF55"
|
||||
taste_description = "the inside of a fire extinguisher"
|
||||
|
||||
/datum/reagent/firefighting_foam/reaction_turf(turf/open/T, reac_volume)
|
||||
if (!istype(T))
|
||||
/datum/reagent/firefighting_foam/reaction_turf(turf/open/exposed_turf, reac_volume)
|
||||
. = ..()
|
||||
if (!istype(exposed_turf))
|
||||
return
|
||||
|
||||
if(reac_volume >= 1)
|
||||
var/obj/effect/particle_effect/foam/firefighting/F = (locate(/obj/effect/particle_effect/foam) in T)
|
||||
if(!F)
|
||||
F = new(T)
|
||||
else if(istype(F))
|
||||
F.lifetime = initial(F.lifetime) //reduce object churn a little bit when using smoke by keeping existing foam alive a bit longer
|
||||
var/obj/effect/particle_effect/fluid/foam/firefighting/foam = (locate(/obj/effect/particle_effect/fluid/foam) in exposed_turf)
|
||||
if(!foam)
|
||||
foam = new(exposed_turf)
|
||||
else if(istype(foam))
|
||||
foam.lifetime = initial(foam.lifetime) //reduce object churn a little bit when using smoke by keeping existing foam alive a bit longer
|
||||
|
||||
var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in T)
|
||||
if(hotspot && !isspaceturf(T))
|
||||
if(T.air)
|
||||
var/datum/gas_mixture/G = T.air
|
||||
if(G.return_temperature() > T20C)
|
||||
G.set_temperature(max(G.return_temperature()/2,T20C))
|
||||
G.react(src)
|
||||
qdel(hotspot)
|
||||
var/obj/effect/hotspot/hotspot = (locate(/obj/effect/hotspot) in exposed_turf)
|
||||
if(hotspot && !isspaceturf(exposed_turf) && exposed_turf.air)
|
||||
var/datum/gas_mixture/air = exposed_turf.air
|
||||
if(air.return_temperature() > T20C)
|
||||
air.set_temperature(max(air.return_temperature()/2, T20C))
|
||||
air.react(src)
|
||||
qdel(hotspot)
|
||||
|
||||
/datum/reagent/firefighting_foam/reaction_obj(obj/O, reac_volume)
|
||||
O.extinguish()
|
||||
|
||||
@@ -32,8 +32,8 @@
|
||||
var/datum/reagents/R = new/datum/reagents(5)
|
||||
R.my_atom = holder.my_atom
|
||||
R.add_reagent(/datum/reagent/toxin/acid/fluacid, 5)
|
||||
var/datum/effect_system/smoke_spread/chem/S = new
|
||||
S.set_up(R, 0.5, holder.my_atom, 0)
|
||||
var/datum/effect_system/fluid_spread/smoke/chem/S = new
|
||||
S.set_up(0.5, location = holder, carry = R,)
|
||||
S.start()
|
||||
playsound(get_turf(holder.my_atom), 'sound/effects/smoke.ogg', 50, 1, -3)
|
||||
|
||||
|
||||
@@ -382,15 +382,7 @@
|
||||
mob_react = FALSE
|
||||
|
||||
/datum/chemical_reaction/foam/on_reaction(datum/reagents/holder, created_volume)
|
||||
var/location = get_turf(holder.my_atom)
|
||||
for(var/mob/M in viewers(5, location))
|
||||
to_chat(M, span_danger("The solution spews out foam!"))
|
||||
var/datum/effect_system/foam_spread/s = new()
|
||||
s.set_up(created_volume*2, location, holder)
|
||||
s.start()
|
||||
holder.clear_reagents()
|
||||
return
|
||||
|
||||
holder.create_foam(/datum/effect_system/fluid_spread/foam, 2 * created_volume, notification = span_danger("The solution spews out foam!"))
|
||||
|
||||
/datum/chemical_reaction/metalfoam
|
||||
name = "Metal Foam"
|
||||
@@ -399,15 +391,7 @@
|
||||
mob_react = FALSE
|
||||
|
||||
/datum/chemical_reaction/metalfoam/on_reaction(datum/reagents/holder, created_volume)
|
||||
var/location = get_turf(holder.my_atom)
|
||||
|
||||
for(var/mob/M in viewers(5, location))
|
||||
to_chat(M, span_danger("The solution spews out a metallic foam!"))
|
||||
|
||||
var/datum/effect_system/foam_spread/metal/s = new()
|
||||
s.set_up(created_volume*5, location, holder, 1)
|
||||
s.start()
|
||||
holder.clear_reagents()
|
||||
holder.create_foam(/datum/effect_system/fluid_spread/foam/metal, 5 * created_volume, /obj/structure/foamedmetal, span_danger("The solution spews out a metallic foam!"))
|
||||
|
||||
/datum/chemical_reaction/smart_foam
|
||||
name = "Smart Metal Foam"
|
||||
@@ -416,12 +400,7 @@
|
||||
mob_react = TRUE
|
||||
|
||||
/datum/chemical_reaction/smart_foam/on_reaction(datum/reagents/holder, created_volume)
|
||||
var/turf/location = get_turf(holder.my_atom)
|
||||
location.visible_message(span_danger("The solution spews out metallic foam!"))
|
||||
var/datum/effect_system/foam_spread/metal/smart/s = new()
|
||||
s.set_up(created_volume * 5, location, holder, TRUE)
|
||||
s.start()
|
||||
holder.clear_reagents()
|
||||
holder.create_foam(/datum/effect_system/fluid_spread/foam/metal/smart, 5 * created_volume, /obj/structure/foamedmetal, span_danger("The solution spews out metallic foam!"))
|
||||
|
||||
/datum/chemical_reaction/ironfoam
|
||||
name = "Iron Foam"
|
||||
@@ -430,13 +409,7 @@
|
||||
mob_react = FALSE
|
||||
|
||||
/datum/chemical_reaction/ironfoam/on_reaction(datum/reagents/holder, created_volume)
|
||||
var/location = get_turf(holder.my_atom)
|
||||
for(var/mob/M in viewers(5, location))
|
||||
to_chat(M, span_danger("The solution spews out a metallic foam!"))
|
||||
var/datum/effect_system/foam_spread/metal/s = new()
|
||||
s.set_up(created_volume*5, location, holder, 2)
|
||||
s.start()
|
||||
holder.clear_reagents()
|
||||
holder.create_foam(/datum/effect_system/fluid_spread/foam/metal/iron, 5 * created_volume, /obj/structure/foamedmetal/iron, span_danger("The solution spews out a metallic foam!"))
|
||||
|
||||
/datum/chemical_reaction/foaming_agent
|
||||
name = "Foaming Agent"
|
||||
|
||||
@@ -292,11 +292,11 @@
|
||||
holder.remove_reagent(/datum/reagent/smoke_powder, created_volume*3)
|
||||
var/smoke_radius = round(sqrt(created_volume * 1.5), 1)
|
||||
var/location = get_turf(holder.my_atom)
|
||||
var/datum/effect_system/smoke_spread/chem/S = new
|
||||
var/datum/effect_system/fluid_spread/smoke/chem/S = new
|
||||
S.attach(location)
|
||||
playsound(location, 'sound/effects/smoke.ogg', 50, 1, -3)
|
||||
if(S)
|
||||
S.set_up(holder, smoke_radius, location, 0)
|
||||
S.set_up(smoke_radius, location = location, carry = holder)
|
||||
S.start()
|
||||
if(holder && holder.my_atom)
|
||||
holder.clear_reagents()
|
||||
@@ -311,11 +311,11 @@
|
||||
/datum/chemical_reaction/smoke_powder_smoke/on_reaction(datum/reagents/holder, created_volume)
|
||||
var/location = get_turf(holder.my_atom)
|
||||
var/smoke_radius = round(sqrt(created_volume / 2), 1)
|
||||
var/datum/effect_system/smoke_spread/chem/S = new
|
||||
var/datum/effect_system/fluid_spread/smoke/chem/S = new
|
||||
S.attach(location)
|
||||
playsound(location, 'sound/effects/smoke.ogg', 50, 1, -3)
|
||||
if(S)
|
||||
S.set_up(holder, smoke_radius, location, 0)
|
||||
S.set_up(smoke_radius, location = location, carry = holder)
|
||||
S.start()
|
||||
if(holder && holder.my_atom)
|
||||
holder.clear_reagents()
|
||||
|
||||
@@ -254,8 +254,8 @@
|
||||
loaded_item = null
|
||||
|
||||
/obj/machinery/rnd/experimentor/proc/throwSmoke(turf/where)
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(0, where)
|
||||
var/datum/effect_system/fluid_spread/smoke/smoke = new
|
||||
smoke.set_up(0, location = where)
|
||||
smoke.start()
|
||||
|
||||
|
||||
@@ -338,28 +338,28 @@
|
||||
autoexperiment = 0
|
||||
visible_message(span_danger("[src] destroys [exp_on], leaking dangerous gas!"))
|
||||
chosenchem = pick(/datum/reagent/carbon,/datum/reagent/uranium/radium,/datum/reagent/toxin,/datum/reagent/consumable/condensedcapsaicin,/datum/reagent/drug/mushroomhallucinogen,/datum/reagent/drug/space_drugs,/datum/reagent/consumable/ethanol,/datum/reagent/consumable/ethanol/beepsky_smash)
|
||||
var/datum/reagents/R = new/datum/reagents(50)
|
||||
R.my_atom = src
|
||||
R.add_reagent(chosenchem , 50)
|
||||
var/datum/reagents/tmp_holder = new/datum/reagents(50)
|
||||
tmp_holder.my_atom = src
|
||||
tmp_holder.add_reagent(chosenchem , 50)
|
||||
investigate_log("Experimentor has released [chosenchem] smoke.", INVESTIGATE_EXPERIMENTOR)
|
||||
var/datum/effect_system/smoke_spread/chem/smoke = new
|
||||
smoke.set_up(R, 0, src, silent = TRUE)
|
||||
var/datum/effect_system/fluid_spread/smoke/chem/smoke = new
|
||||
smoke.set_up(0, location = src, carry = tmp_holder, silent = TRUE)
|
||||
playsound(src, 'sound/effects/smoke.ogg', 50, 1, -3)
|
||||
smoke.start()
|
||||
qdel(R)
|
||||
qdel(tmp_holder)
|
||||
ejectItem(TRUE)
|
||||
else if(prob(EFFECT_PROB_VERYLOW-badThingCoeffIfCrit))
|
||||
autoexperiment = 0
|
||||
visible_message(span_danger("[src]'s chemical chamber has sprung a leak!"))
|
||||
chosenchem = pick(/datum/reagent/mutationtoxin/felinid,/datum/reagent/nanomachines,/datum/reagent/toxin/acid)
|
||||
var/datum/reagents/R = new/datum/reagents(50)
|
||||
R.my_atom = src
|
||||
R.add_reagent(chosenchem , 50)
|
||||
var/datum/effect_system/smoke_spread/chem/smoke = new
|
||||
smoke.set_up(R, 0, src, silent = TRUE)
|
||||
var/datum/reagents/tmp_holder = new/datum/reagents(50)
|
||||
tmp_holder.my_atom = src
|
||||
tmp_holder.add_reagent(chosenchem , 50)
|
||||
var/datum/effect_system/fluid_spread/smoke/chem/smoke = new
|
||||
smoke.set_up(0, location = src, carry = tmp_holder, silent = TRUE)
|
||||
playsound(src, 'sound/effects/smoke.ogg', 50, 1, -3)
|
||||
smoke.start()
|
||||
qdel(R)
|
||||
qdel(tmp_holder)
|
||||
ejectItem(TRUE)
|
||||
warn_admins(usr, "[chosenchem] smoke")
|
||||
investigate_log("Experimentor has released <font color='red'>[chosenchem]</font> smoke!", INVESTIGATE_EXPERIMENTOR)
|
||||
@@ -444,15 +444,15 @@
|
||||
else if(prob(EFFECT_PROB_VERYLOW-badThingCoeff))
|
||||
autoexperiment = 0
|
||||
visible_message(span_danger("[src] malfunctions, shattering [exp_on] and releasing a dangerous cloud of coolant!"))
|
||||
var/datum/reagents/R = new/datum/reagents(50)
|
||||
R.my_atom = src
|
||||
R.add_reagent(/datum/reagent/consumable/frostoil, 50)
|
||||
var/datum/reagents/tmp_holder = new/datum/reagents(50)
|
||||
tmp_holder.my_atom = src
|
||||
tmp_holder.add_reagent(/datum/reagent/consumable/frostoil, 50)
|
||||
investigate_log("Experimentor has released frostoil gas.", INVESTIGATE_EXPERIMENTOR)
|
||||
var/datum/effect_system/smoke_spread/chem/smoke = new
|
||||
smoke.set_up(R, 0, src, silent = TRUE)
|
||||
var/datum/effect_system/fluid_spread/smoke/chem/smoke = new
|
||||
smoke.set_up(0, location = src, carry = tmp_holder, silent = TRUE)
|
||||
playsound(src, 'sound/effects/smoke.ogg', 50, 1, -3)
|
||||
smoke.start()
|
||||
qdel(R)
|
||||
qdel(tmp_holder)
|
||||
ejectItem(TRUE)
|
||||
else if(prob(EFFECT_PROB_LOW-badThingCoeff))
|
||||
autoexperiment = 0
|
||||
@@ -472,8 +472,8 @@
|
||||
else if(prob(EFFECT_PROB_MEDIUM-badThingCoeff))
|
||||
autoexperiment = 0
|
||||
visible_message(span_warning("[src] malfunctions, releasing a flurry of chilly air as [exp_on] pops out!"))
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(0, loc)
|
||||
var/datum/effect_system/fluid_spread/smoke/smoke = new
|
||||
smoke.set_up(0, location = loc)
|
||||
smoke.start()
|
||||
ejectItem()
|
||||
////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
@@ -639,8 +639,8 @@
|
||||
//////////////// RELIC PROCS /////////////////////////////
|
||||
|
||||
/obj/item/relic/proc/throwSmoke(turf/where)
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(0, get_turf(where))
|
||||
var/datum/effect_system/fluid_spread/smoke/smoke = new
|
||||
smoke.set_up(0, location = get_turf(where))
|
||||
smoke.start()
|
||||
|
||||
/obj/item/relic/proc/corgicannon(mob/user)
|
||||
|
||||
@@ -45,11 +45,11 @@ Burning extracts:
|
||||
|
||||
/obj/item/slimecross/burning/orange/do_effect(mob/user)
|
||||
user.visible_message(span_danger("[src] boils over with a caustic gas!"))
|
||||
var/datum/reagents/R = new/datum/reagents(100)
|
||||
R.add_reagent(/datum/reagent/consumable/condensedcapsaicin, 100)
|
||||
var/datum/reagents/tmp_holder = new/datum/reagents(100)
|
||||
tmp_holder.add_reagent(/datum/reagent/consumable/condensedcapsaicin, 100)
|
||||
|
||||
var/datum/effect_system/smoke_spread/chem/smoke = new
|
||||
smoke.set_up(R, 7, get_turf(user))
|
||||
var/datum/effect_system/fluid_spread/smoke/chem/smoke = new
|
||||
smoke.set_up(7, location = get_turf(user), carry = tmp_holder)
|
||||
smoke.start()
|
||||
..()
|
||||
|
||||
@@ -120,11 +120,11 @@ Burning extracts:
|
||||
|
||||
/obj/item/slimecross/burning/darkblue/do_effect(mob/user)
|
||||
user.visible_message(span_danger("[src] releases a burst of chilling smoke!"))
|
||||
var/datum/reagents/R = new/datum/reagents(100)
|
||||
R.add_reagent(/datum/reagent/consumable/frostoil, 40)
|
||||
user.reagents.add_reagent(/datum/reagent/medicine/cryoxadone,10)
|
||||
var/datum/effect_system/smoke_spread/chem/smoke = new
|
||||
smoke.set_up(R, 7, get_turf(user))
|
||||
var/datum/reagents/tmp_holder = new/datum/reagents(100)
|
||||
tmp_holder.add_reagent(/datum/reagent/consumable/frostoil, 40)
|
||||
user.reagents.add_reagent(/datum/reagent/medicine/regen_jelly, 10)
|
||||
var/datum/effect_system/fluid_spread/smoke/chem/smoke = new
|
||||
smoke.set_up(7, location = get_turf(user), carry = tmp_holder)
|
||||
smoke.start()
|
||||
..()
|
||||
|
||||
|
||||
@@ -320,11 +320,7 @@
|
||||
return 250
|
||||
|
||||
if(SLIME_ACTIVATE_MAJOR)
|
||||
var/location = get_turf(user)
|
||||
var/datum/effect_system/foam_spread/s = new()
|
||||
s.set_up(20, location, user.reagents)
|
||||
s.start()
|
||||
user.reagents.clear_reagents()
|
||||
user.reagents.create_foam(/datum/effect_system/fluid_spread/foam, 20)
|
||||
user.visible_message(span_danger("Foam spews out from [user]'s skin!"), span_warning("You activate [src], and foam bursts out of your skin!"))
|
||||
return 600
|
||||
|
||||
|
||||
@@ -147,8 +147,10 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
|
||||
|
||||
var/sparks_spread = 0
|
||||
var/sparks_amt = 0 //cropped at 10
|
||||
var/smoke_spread = 0 //1 - harmless, 2 - harmful
|
||||
var/smoke_amt = 0 //cropped at 10
|
||||
/// The typepath of the smoke to create on cast.
|
||||
var/smoke_spread = null
|
||||
/// The amount of smoke to create on case. This is a range so a value of 5 will create enough smoke to cover everything within 5 steps.
|
||||
var/smoke_amt = 0
|
||||
|
||||
var/centcom_cancast = TRUE //Whether or not the spell should be allowed on z2
|
||||
|
||||
@@ -356,19 +358,10 @@ GLOBAL_LIST_INIT(spells, typesof(/obj/effect/proc_holder/spell)) //needed for th
|
||||
to_chat(target, text("[message]"))
|
||||
if(sparks_spread)
|
||||
do_sparks(sparks_amt, FALSE, location)
|
||||
if(smoke_spread)
|
||||
if(smoke_spread == 1)
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(smoke_amt, location)
|
||||
smoke.start()
|
||||
else if(smoke_spread == 2)
|
||||
var/datum/effect_system/smoke_spread/bad/smoke = new
|
||||
smoke.set_up(smoke_amt, location)
|
||||
smoke.start()
|
||||
else if(smoke_spread == 3)
|
||||
var/datum/effect_system/smoke_spread/sleeping/smoke = new
|
||||
smoke.set_up(smoke_amt, location)
|
||||
smoke.start()
|
||||
if(ispath(smoke_spread, /datum/effect_system/fluid_spread/smoke)) // Dear god this code is :agony:
|
||||
var/datum/effect_system/fluid_spread/smoke/smoke = new smoke_spread()
|
||||
smoke.set_up(smoke_amt, location = location)
|
||||
smoke.start()
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/proc/cast(list/targets,mob/user = usr)
|
||||
|
||||
@@ -183,7 +183,7 @@
|
||||
include_user = TRUE
|
||||
cooldown_min = 20 //25 deciseconds reduction per rank
|
||||
|
||||
smoke_spread = 3
|
||||
smoke_spread = /datum/effect_system/fluid_spread/smoke/sleeping
|
||||
smoke_amt = 4
|
||||
action_icon_state = "smoke"
|
||||
action_background_icon_state = "bg_cult"
|
||||
|
||||
@@ -220,7 +220,7 @@
|
||||
var/list/dancefloor_turfs
|
||||
var/list/dancefloor_turfs_types
|
||||
var/dancefloor_exists = FALSE
|
||||
var/datum/effect_system/smoke_spread/transparent/dancefloor_devil/smoke
|
||||
var/datum/effect_system/fluid_spread/smoke/transparent/dancefloor_devil/smoke
|
||||
|
||||
|
||||
/obj/effect/proc_holder/spell/targeted/summon_dancefloor/cast(list/targets, mob/user = usr)
|
||||
@@ -229,7 +229,7 @@
|
||||
|
||||
if(!smoke)
|
||||
smoke = new()
|
||||
smoke.set_up(0, get_turf(user))
|
||||
smoke.set_up(0, location = get_turf(user))
|
||||
smoke.start()
|
||||
|
||||
if(dancefloor_exists)
|
||||
@@ -253,8 +253,8 @@
|
||||
T.ChangeTurf((i % 2 == 0) ? /turf/open/floor/light/colour_cycle/dancefloor_a : /turf/open/floor/light/colour_cycle/dancefloor_b, flags = CHANGETURF_INHERIT_AIR)
|
||||
i++
|
||||
|
||||
/datum/effect_system/smoke_spread/transparent/dancefloor_devil
|
||||
effect_type = /obj/effect/particle_effect/smoke/transparent/dancefloor_devil
|
||||
/datum/effect_system/fluid_spread/smoke/transparent/dancefloor_devil
|
||||
effect_type = /obj/effect/particle_effect/fluid/smoke/transparent/dancefloor_devil
|
||||
|
||||
/obj/effect/particle_effect/smoke/transparent/dancefloor_devil
|
||||
/obj/effect/particle_effect/fluid/smoke/transparent/dancefloor_devil
|
||||
lifetime = 2
|
||||
|
||||
@@ -72,7 +72,7 @@
|
||||
include_user = TRUE
|
||||
cooldown_min = 20 //25 deciseconds reduction per rank
|
||||
|
||||
smoke_spread = 2
|
||||
smoke_spread = /datum/effect_system/fluid_spread/smoke/bad
|
||||
smoke_amt = 4
|
||||
|
||||
action_icon_state = "smoke"
|
||||
@@ -90,7 +90,7 @@
|
||||
range = -1
|
||||
include_user = TRUE
|
||||
|
||||
smoke_spread = 1
|
||||
smoke_spread = /datum/effect_system/fluid_spread/smoke
|
||||
smoke_amt = 2
|
||||
|
||||
action_icon_state = "smoke"
|
||||
@@ -124,7 +124,7 @@
|
||||
cooldown_min = 5 //4 deciseconds reduction per rank
|
||||
|
||||
|
||||
smoke_spread = 1
|
||||
smoke_spread = /datum/effect_system/fluid_spread/smoke
|
||||
smoke_amt = 0
|
||||
|
||||
inner_tele_radius = 0
|
||||
@@ -155,7 +155,7 @@
|
||||
include_user = TRUE
|
||||
cooldown_min = 200 //100 deciseconds reduction per rank
|
||||
|
||||
smoke_spread = 1
|
||||
smoke_spread = /datum/effect_system/fluid_spread/smoke
|
||||
smoke_amt = 2
|
||||
sound1 = 'sound/magic/teleport_diss.ogg'
|
||||
sound2 = 'sound/magic/teleport_app.ogg'
|
||||
|
||||
@@ -47,7 +47,11 @@
|
||||
. = ..()
|
||||
if(prob(33))
|
||||
visible_message(span_danger("[src] spews out a ton of space lube!"))
|
||||
new /obj/effect/particle_effect/foam(loc) //YEET
|
||||
var/datum/effect_system/fluid_spread/foam/foam = new
|
||||
var/datum/reagents/foamreagent = new /datum/reagents(25)
|
||||
foamreagent.add_reagent(/datum/reagent/lube, 25)
|
||||
foam.set_up(4, holder = src, location = loc, carry = foamreagent)
|
||||
foam.start()
|
||||
|
||||
/obj/vehicle/sealed/car/clowncar/attacked_by(obj/item/I, mob/living/user)
|
||||
. = ..()
|
||||
@@ -106,11 +110,11 @@
|
||||
new /obj/item/grown/bananapeel/specialpeel(loc)
|
||||
if(2)
|
||||
visible_message(span_danger("[user] has pressed one of the colorful buttons on [src] and unknown chemicals flood out of it."))
|
||||
var/datum/reagents/R = new/datum/reagents(300)
|
||||
R.my_atom = src
|
||||
R.add_reagent(get_random_reagent_id(), 100)
|
||||
var/datum/effect_system/foam_spread/foam = new
|
||||
foam.set_up(200, loc, R)
|
||||
var/datum/reagents/tmp_holder = new/datum/reagents(300)
|
||||
tmp_holder.my_atom = src
|
||||
tmp_holder.add_reagent(get_random_reagent_id(), 100)
|
||||
var/datum/effect_system/fluid_spread/foam/short/foam = new
|
||||
foam.set_up(4, location = loc, carry = tmp_holder)
|
||||
foam.start()
|
||||
if(3)
|
||||
visible_message(span_danger("[user] has pressed one of the colorful buttons on [src] and the clown car turns on its singularity disguise system."))
|
||||
@@ -119,11 +123,11 @@
|
||||
addtimer(CALLBACK(src, .proc/ResetIcon), 100)
|
||||
if(4)
|
||||
visible_message(span_danger("[user] has pressed one of the colorful buttons on [src] and the clown car spews out a cloud of laughing gas."))
|
||||
var/datum/reagents/R = new/datum/reagents(300)
|
||||
R.my_atom = src
|
||||
R.add_reagent(/datum/reagent/consumable/superlaughter, 50)
|
||||
var/datum/effect_system/smoke_spread/chem/smoke = new()
|
||||
smoke.set_up(R, 4)
|
||||
var/datum/reagents/tmp_holder = new/datum/reagents(300)
|
||||
tmp_holder.my_atom = src
|
||||
tmp_holder.add_reagent(/datum/reagent/consumable/superlaughter, 50)
|
||||
var/datum/effect_system/fluid_spread/smoke/chem/smoke = new()
|
||||
smoke.set_up(4, location = loc, carry = tmp_holder)
|
||||
smoke.attach(src)
|
||||
smoke.start()
|
||||
if(5)
|
||||
|
||||
@@ -126,7 +126,7 @@ LOG_VIRUS
|
||||
LOG_CLONING
|
||||
|
||||
## Enable the demo subsystem
|
||||
DEMOS_ENABLED
|
||||
#DEMOS_ENABLED
|
||||
|
||||
##Log camera pictures - Must have picture logging enabled
|
||||
# PICTURE_LOGGING_CAMERA
|
||||
|
||||
@@ -331,6 +331,7 @@
|
||||
#include "code\controllers\subsystem\events.dm"
|
||||
#include "code\controllers\subsystem\explosions.dm"
|
||||
#include "code\controllers\subsystem\fire_burning.dm"
|
||||
#include "code\controllers\subsystem\fluids.dm"
|
||||
#include "code\controllers\subsystem\garbage.dm"
|
||||
#include "code\controllers\subsystem\icon_smooth.dm"
|
||||
#include "code\controllers\subsystem\idlenpcpool.dm"
|
||||
@@ -378,11 +379,11 @@
|
||||
#include "code\controllers\subsystem\weather.dm"
|
||||
#include "code\controllers\subsystem\processing\fastprocess.dm"
|
||||
#include "code\controllers\subsystem\processing\fields.dm"
|
||||
#include "code\controllers\subsystem\processing\fluids.dm"
|
||||
#include "code\controllers\subsystem\processing\instruments.dm"
|
||||
#include "code\controllers\subsystem\processing\nanites.dm"
|
||||
#include "code\controllers\subsystem\processing\networks.dm"
|
||||
#include "code\controllers\subsystem\processing\obj.dm"
|
||||
#include "code\controllers\subsystem\processing\plumbing.dm"
|
||||
#include "code\controllers\subsystem\processing\processing.dm"
|
||||
#include "code\controllers\subsystem\processing\projectiles.dm"
|
||||
#include "code\controllers\subsystem\processing\quirks.dm"
|
||||
@@ -1003,11 +1004,12 @@
|
||||
#include "code\game\objects\effects\decals\turfdecal\weather.dm"
|
||||
#include "code\game\objects\effects\effect_system\effect_system.dm"
|
||||
#include "code\game\objects\effects\effect_system\effects_explosion.dm"
|
||||
#include "code\game\objects\effects\effect_system\effects_foam.dm"
|
||||
#include "code\game\objects\effects\effect_system\effects_other.dm"
|
||||
#include "code\game\objects\effects\effect_system\effects_smoke.dm"
|
||||
#include "code\game\objects\effects\effect_system\effects_sparks.dm"
|
||||
#include "code\game\objects\effects\effect_system\effects_water.dm"
|
||||
#include "code\game\objects\effects\effect_system\fluid_spread\_fluid_spread.dm"
|
||||
#include "code\game\objects\effects\effect_system\fluid_spread\effects_foam.dm"
|
||||
#include "code\game\objects\effects\effect_system\fluid_spread\effects_smoke.dm"
|
||||
#include "code\game\objects\effects\spawners\bombspawner.dm"
|
||||
#include "code\game\objects\effects\spawners\bundle.dm"
|
||||
#include "code\game\objects\effects\spawners\food_drink.dm"
|
||||
@@ -2105,6 +2107,7 @@
|
||||
#include "code\modules\events\prison_break.dm"
|
||||
#include "code\modules\events\processor_overload.dm"
|
||||
#include "code\modules\events\radiation_storm.dm"
|
||||
#include "code\modules\events\scrubber_overflow.dm"
|
||||
#include "code\modules\events\sentience.dm"
|
||||
#include "code\modules\events\shuttle_catastrophe.dm"
|
||||
#include "code\modules\events\shuttle_loan.dm"
|
||||
@@ -2117,7 +2120,6 @@
|
||||
#include "code\modules\events\supermatter_surge.dm"
|
||||
#include "code\modules\events\swarmer.dm"
|
||||
#include "code\modules\events\tzimisce.dm"
|
||||
#include "code\modules\events\vent_clog.dm"
|
||||
#include "code\modules\events\wormholes.dm"
|
||||
#include "code\modules\events\zombie_infection.dm"
|
||||
#include "code\modules\events\holiday\halloween.dm"
|
||||
|
||||
@@ -4,12 +4,12 @@
|
||||
can_attach_mob = TRUE
|
||||
var/glitter_type = "glitter"
|
||||
|
||||
/datum/effect_system/smoke_spread/chem/glitter
|
||||
effect_type = /obj/effect/particle_effect/smoke/chem/glitter
|
||||
datum/effect_system/fluid_spread/smoke/chem/glitter
|
||||
effect_type = /obj/effect/particle_effect/fluid/smoke/chem/glitter
|
||||
|
||||
/obj/effect/particle_effect/smoke/chem/glitter
|
||||
lifetime = 6
|
||||
opaque = TRUE
|
||||
/obj/effect/particle_effect/fluid/smoke/chem/glitter
|
||||
lifetime = 6 SECONDS
|
||||
opacity = TRUE
|
||||
|
||||
/obj/item/grenade/plastic/glitterbomb/Initialize()
|
||||
. = ..()
|
||||
@@ -17,8 +17,8 @@
|
||||
reagents.add_reagent(glitter_type, 20)
|
||||
|
||||
/obj/item/grenade/plastic/glitterbomb/prime()
|
||||
var/datum/effect_system/smoke_spread/chem/glitter/smoke = new()
|
||||
smoke.set_up(reagents, 4, target)
|
||||
var/datum/effect_system/fluid_spread/smoke/chem/glitter/smoke = new()
|
||||
smoke.set_up(4, location = target, carry = reagents)
|
||||
smoke.start()
|
||||
playsound(target, 'sound/items/party_horn.ogg', 50, 1, -1)
|
||||
target.cut_overlay(plastic_overlay, TRUE)
|
||||
|
||||
@@ -42,9 +42,9 @@
|
||||
user.visible_message(span_danger("[user] coughs while using [src], filling the area with smoke!"), span_userdanger("You cough while using [src], filling the area with smoke!"))
|
||||
smoke_spread = 5
|
||||
var/turf/location = get_turf(user)
|
||||
var/datum/effect_system/smoke_spread/chem/smoke = new
|
||||
var/datum/effect_system/fluid_spread/smoke/chem/smoke = new
|
||||
smoke.attach(location)
|
||||
smoke.set_up(boof.reagents, smoke_spread, location, silent = TRUE)
|
||||
smoke.set_up(smoke_spread, location = location, carry = boof.reagents, silent = TRUE)
|
||||
smoke.start()
|
||||
qdel(boof)
|
||||
update_icon()
|
||||
|
||||
@@ -534,10 +534,10 @@
|
||||
B.reagents.clear_reagents() //Just in case!
|
||||
B.invisibility = INFINITY //This ought to do the trick
|
||||
B.reagents.add_reagent(/datum/reagent/shadowling_blindness_smoke, 10)
|
||||
var/datum/effect_system/smoke_spread/chem/S = new
|
||||
var/datum/effect_system/fluid_spread/smoke/chem/S = new
|
||||
S.attach(B)
|
||||
if(S)
|
||||
S.set_up(B.reagents, 4, 0, B.loc)
|
||||
S.set_up(4, location = B.loc, carry = B.reagents)
|
||||
S.start()
|
||||
qdel(B)
|
||||
|
||||
|
||||
@@ -55,16 +55,15 @@
|
||||
penetrate(clong)
|
||||
else if(istype(clong, type))
|
||||
var/obj/effect/immovablerod/other = clong
|
||||
visible_message("<span class='danger'>[src] collides with [other]!\
|
||||
</span>")
|
||||
var/datum/effect_system/smoke_spread/smoke = new
|
||||
smoke.set_up(2, get_turf(src))
|
||||
visible_message(span_danger("[src] collides with [other]!"))
|
||||
var/datum/effect_system/fluid_spread/smoke/smoke = new
|
||||
smoke.set_up(2, location = get_turf(src))
|
||||
smoke.start()
|
||||
qdel(src)
|
||||
qdel(other)
|
||||
|
||||
/obj/effect/immovablerod/duck/penetrate(mob/living/L)
|
||||
L.visible_message(span_danger("[L] is QUACKED by an immovable duck!") , span_userdanger("You get QUACKED!!!") , "<span class ='danger'>You hear a QUACK!</span>")
|
||||
L.visible_message(span_danger("[L] is QUACKED by an immovable duck!") , span_userdanger("You get QUACKED!!!") , span_danger("You hear a QUACK!"))
|
||||
if(ishuman(L))
|
||||
var/mob/living/carbon/human/H = L
|
||||
H.adjustBruteLoss(160)
|
||||
|
||||
Reference in New Issue
Block a user