From 6b7df7b174f26c0af301f6d7ca85cefe9c1ab56b Mon Sep 17 00:00:00 2001 From: TemporalOroboros Date: Wed, 29 Dec 2021 08:03:06 -0800 Subject: [PATCH] Fixes gunpowder and teslium grenades being completely nonfunctional. (#63393) * Makes gunpowder work in grenades and bomb cores. * Cleans up some of the code * Commit * Clears grenades reagent holder on detonation. * Variable casing/bombcore holder volume, O(n*r) large chem grenades, and including holder reagents in the chem splash reagent check. * Fix inverted early return --- code/game/machinery/syndicatebomb.dm | 21 +- .../objects/items/grenades/atmos_grenades.dm | 2 +- .../objects/items/grenades/chem_grenade.dm | 173 +++++++++++------ code/modules/aquarium/aquarium.dm | 2 +- code/modules/reagents/chem_splash.dm | 183 +++++++++++------- .../chemistry/machinery/chem_dispenser.dm | 2 +- code/modules/reagents/reagent_dispenser.dm | 2 +- 7 files changed, 248 insertions(+), 137 deletions(-) diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm index 727423390f1..655236cf875 100644 --- a/code/game/machinery/syndicatebomb.dm +++ b/code/game/machinery/syndicatebomb.dm @@ -384,16 +384,27 @@ name = "chemical payload" desc = "An explosive payload designed to spread chemicals, dangerous or otherwise, across a large area. Properties of the core may vary with grenade casing type, and must be loaded before use." icon_state = "chemcore" + /// The initial volume of the reagent holder the bombcore has. + var/core_holder_volume = 1000 + /// The set of beakers that have been inserted into the bombcore. var/list/beakers = list() + /// The maximum number of beakers that this bombcore can have. var/max_beakers = 1 // Read on about grenade casing properties below + /// The range this spreads the reagents added to the bombcore. var/spread_range = 5 + /// How much this heats the reagents in it on detonation. var/temp_boost = 50 + /// The amount of reagents released with each detonation. var/time_release = 0 +/obj/item/bombcore/chemical/Initialize(mapload) + . = ..() + create_reagents(core_holder_volume) + /obj/item/bombcore/chemical/detonate() if(time_release > 0) - var/total_volume = 0 + var/total_volume = reagents.total_volume for(var/obj/item/reagent_containers/RC in beakers) total_volume += RC.reagents.total_volume @@ -408,7 +419,7 @@ reactants.my_atom = src for(var/obj/item/reagent_containers/RC in beakers) RC.reagents.trans_to(reactants, RC.reagents.total_volume*fraction, 1, 1, 1) - chem_splash(get_turf(src), spread_range, list(reactants), temp_boost) + chem_splash(get_turf(src), reagents, spread_range, list(reactants), temp_boost) // Detonate it again in one second, until it's out of juice. addtimer(CALLBACK(src, .proc/detonate), 10) @@ -428,7 +439,7 @@ if(S && S.reagents && S.reagents.total_volume) reactants += S.reagents - if(!chem_splash(get_turf(src), spread_range, reactants, temp_boost)) + if(!chem_splash(get_turf(src), reagents, spread_range, reactants, temp_boost)) playsound(loc, 'sound/items/screwdriver2.ogg', 50, TRUE) return // The Explosion didn't do anything. No need to log, or disappear. @@ -438,10 +449,6 @@ playsound(loc, 'sound/effects/bamf.ogg', 75, TRUE, 5) - if(loc && istype(loc, /obj/machinery/syndicatebomb/)) - qdel(loc) - qdel(src) - /obj/item/bombcore/chemical/attackby(obj/item/I, mob/user, params) if(I.tool_behaviour == TOOL_CROWBAR && beakers.len > 0) I.play_tool_sound(src) diff --git a/code/game/objects/items/grenades/atmos_grenades.dm b/code/game/objects/items/grenades/atmos_grenades.dm index c15ab8fe8d8..652073b6982 100644 --- a/code/game/objects/items/grenades/atmos_grenades.dm +++ b/code/game/objects/items/grenades/atmos_grenades.dm @@ -108,7 +108,7 @@ var/turf/detonation_turf = get_turf(src) - chem_splash(detonation_turf, breach_range, reactants) + chem_splash(detonation_turf, null, breach_range, reactants) playsound(src, 'sound/effects/spray2.ogg', 100, TRUE) log_game("A grenade detonated at [AREACOORD(detonation_turf)]") diff --git a/code/game/objects/items/grenades/chem_grenade.dm b/code/game/objects/items/grenades/chem_grenade.dm index 0d7e4c8ea6f..bc202213fd8 100644 --- a/code/game/objects/items/grenades/chem_grenade.dm +++ b/code/game/objects/items/grenades/chem_grenade.dm @@ -2,30 +2,41 @@ name = "chemical grenade" desc = "A custom made grenade." icon_state = "chemg" + base_icon_state = "chemg" inhand_icon_state = "flashbang" w_class = WEIGHT_CLASS_SMALL force = 2 + /// Which stage of construction this grenade is currently at. var/stage = GRENADE_EMPTY + /// The set of reagent containers that have been added to this grenade casing. var/list/obj/item/reagent_containers/glass/beakers = list() + /// The types of reagent containers that can be added to this grenade casing. var/list/allowed_containers = list(/obj/item/reagent_containers/glass/beaker, /obj/item/reagent_containers/glass/bottle) + /// The types of reagent containers that can't be added to this grenade casing. var/list/banned_containers = list(/obj/item/reagent_containers/glass/beaker/bluespace) //Containers to exclude from specific grenade subtypes + /// The maximum volume of the reagents in the grenade casing. + var/casing_holder_volume = 1000 + /// The range that this grenade can splash reagents at if they aren't consumed on detonation. var/affected_area = 3 - var/ignition_temp = 10 // The amount of heat added to the reagents when this grenade goes off. - var/threatscale = 1 // Used by advanced grenades to make them slightly more worthy. - var/no_splash = FALSE //If the grenade deletes even if it has no reagents to splash with. Used for slime core reactions. - var/casedesc = "This basic model accepts both beakers and bottles. It heats contents by 10 K upon ignition." // Appears when examining empty casings. + /// The amount of temperature that is added to the reagents on detonation. + var/ignition_temp = 10 + /// How much to scale the reagents by when the grenade detonates. Used by advanced grenades to make them slightly more worthy. + var/threatscale = 1 + /// The description when examining empty casings. + var/casedesc = "This basic model accepts both beakers and bottles. It heats contents by 10 K upon ignition." + /// Whether or not the grenade is currently acting as a landmine. Currently broken and not my current project. var/obj/item/assembly/prox_sensor/landminemode = null +/obj/item/grenade/chem_grenade/Initialize(mapload) + . = ..() + create_reagents(casing_holder_volume) + stage_change() // If no argument is set, it will change the stage to the current stage, useful for stock grenades that start READY. + wires = new /datum/wires/explosive/chem_grenade(src) + /obj/item/grenade/chem_grenade/ComponentInitialize() . = ..() AddElement(/datum/element/empprotection, EMP_PROTECT_WIRES) -/obj/item/grenade/chem_grenade/Initialize(mapload) - . = ..() - create_reagents(1000) - stage_change() // If no argument is set, it will change the stage to the current stage, useful for stock grenades that start READY. - wires = new /datum/wires/explosive/chem_grenade(src) - /obj/item/grenade/chem_grenade/examine(mob/user) display_timer = (stage == GRENADE_READY) //show/hide the timer based on assembly state . = ..() @@ -46,6 +57,42 @@ for(var/obj/item/reagent_containers/glass/glass_beaker in beakers) . += span_notice("You see a [glass_beaker.name] inside the grenade.") +/obj/item/grenade/chem_grenade/update_name(updates) + switch(stage) + if(GRENADE_EMPTY) + name = "[initial(name)] casing" + if(GRENADE_WIRED) + name = "unsecured [initial(name)]" + if(GRENADE_READY) + name = initial(name) + return ..() + +/obj/item/grenade/chem_grenade/update_desc(updates) + switch(stage) + if(GRENADE_EMPTY) + desc = "A do it yourself [initial(name)]! [initial(casedesc)]" + if(GRENADE_WIRED) + desc = "An unsecured [initial(name)] assembly." + if(GRENADE_READY) + desc = initial(desc) + return ..() + + +/obj/item/grenade/chem_grenade/update_icon_state() + if(active) + icon_state = "[base_icon_state]_active" + return ..() + + switch(stage) + if(GRENADE_EMPTY) + icon_state = base_icon_state + if(GRENADE_WIRED) + icon_state = "[base_icon_state]_ass" + if(GRENADE_READY) + icon_state = "[base_icon_state]_locked" + return ..() + + /obj/item/grenade/chem_grenade/attack_self(mob/user) if(stage == GRENADE_READY && !active) ..() @@ -126,18 +173,7 @@ /obj/item/grenade/chem_grenade/proc/stage_change(N) if(N) stage = N - if(stage == GRENADE_EMPTY) - name = "[initial(name)] casing" - desc = "A do it yourself [initial(name)]! [initial(casedesc)]" - icon_state = initial(icon_state) - else if(stage == GRENADE_WIRED) - name = "unsecured [initial(name)]" - desc = "An unsecured [initial(name)] assembly." - icon_state = "[initial(icon_state)]_ass" - else if(stage == GRENADE_READY) - name = initial(name) - desc = initial(desc) - icon_state = "[initial(icon_state)]_locked" + update_appearance() /obj/item/grenade/chem_grenade/on_found(mob/finder) var/obj/item/assembly/assembly = wires.get_attached(wires.get_wire(1)) @@ -164,12 +200,13 @@ to_chat(user, span_warning("You prime [src], activating its proximity sensor.")) else to_chat(user, span_warning("You prime [src]! [DisplayTimeText(det_time)]!")) + + active = TRUE + update_icon_state() playsound(src, 'sound/weapons/armbomb.ogg', volume, TRUE) - icon_state = initial(icon_state) + "_active" if(landminemode) landminemode.activate() return - active = TRUE addtimer(CALLBACK(src, .proc/detonate), isnull(delayoverride)? det_time : delayoverride) /obj/item/grenade/chem_grenade/detonate(mob/living/lanced_by) @@ -182,22 +219,13 @@ reactants += glass_beaker.reagents var/turf/detonation_turf = get_turf(src) + if (chem_splash(detonation_turf, reagents, affected_area, reactants, ignition_temp, threatscale)) + // logs from custom assemblies priming are handled by the wire component + log_game("A grenade detonated at [AREACOORD(detonation_turf)]") - if(!chem_splash(detonation_turf, affected_area, reactants, ignition_temp, threatscale) && !no_splash) - playsound(src, 'sound/items/screwdriver2.ogg', 50, TRUE) - if(beakers.len) - for(var/obj/beaker as anything in beakers) - beaker.forceMove(drop_location()) - beakers = list() - stage_change(GRENADE_EMPTY) - active = FALSE - return -// logs from custom assemblies priming are handled by the wire component - log_game("A grenade detonated at [AREACOORD(detonation_turf)]") + active = FALSE + update_appearance() - update_mob() - - qdel(src) //Large chem grenades accept slime cores and use the appropriately. /obj/item/grenade/chem_grenade/large @@ -205,6 +233,7 @@ desc = "A custom made large grenade. Larger splash range and increased ignition temperature compared to basic grenades. Fits exotic and bluespace based containers." casedesc = "This casing affects a larger area than the basic model and can fit exotic containers, including slime cores and bluespace beakers. Heats contents by 25 K upon ignition." icon_state = "large_grenade" + base_icon_state = "large_grenade" allowed_containers = list(/obj/item/reagent_containers/glass, /obj/item/reagent_containers/food/condiment, /obj/item/reagent_containers/food/drinks) banned_containers = list() affected_area = 5 @@ -213,29 +242,52 @@ /obj/item/grenade/chem_grenade/large/detonate(mob/living/lanced_by) if(stage != GRENADE_READY) - return + return FALSE - for(var/obj/item/slime_extract/slime_extract in beakers) - if (!slime_extract.Uses) + + var/extract_total_volume = 0 + var/extract_maximum_volume = 0 + var/list/extracts = list() + + var/beaker_total_volume = 0 + var/list/other_containers = list() + + for(var/obj/item/thing as anything in beakers) + if(!thing.reagents) continue - for(var/obj/item/reagent_containers/glass/glass_beaker in beakers) - glass_beaker.reagents.trans_to(slime_extract, glass_beaker.reagents.total_volume) + if(istype(thing, /obj/item/slime_extract)) + var/obj/item/slime_extract/extract = thing + if(!extract.Uses) + continue - //If there is still a core (sometimes it's used up) - //and there are reagents left, behave normally, - //otherwise drop it on the ground for timed reactions like gold. - - if(!slime_extract) - continue - - if(slime_extract.reagents && slime_extract.reagents.total_volume) - for(var/obj/item/reagent_containers/glass/glass_beaker in beakers) - slime_extract.reagents.trans_to(glass_beaker, slime_extract.reagents.total_volume) + extract_total_volume += extract.reagents.total_volume + extract_maximum_volume += extract.reagents.maximum_volume + extracts += extract else - slime_extract.forceMove(get_turf(src)) - no_splash = TRUE - ..() + beaker_total_volume += thing.reagents.total_volume + other_containers += thing + + + var/available_extract_volume = extract_maximum_volume - extract_total_volume + if(beaker_total_volume <= 0 || available_extract_volume <= 0) + return ..() + + var/container_ratio = available_extract_volume / beaker_total_volume + var/datum/reagents/tmp_holder = new/datum/reagents(beaker_total_volume) + for(var/obj/item/container as anything in other_containers) + container.reagents.trans_to(tmp_holder, container.reagents.total_volume * container_ratio, 1, preserve_data = TRUE, no_react = TRUE) + + for(var/obj/item/slime_extract/extract as anything in extracts) + var/available_volume = extract.reagents.maximum_volume - extract.reagents.total_volume + tmp_holder.trans_to(extract, beaker_total_volume * (available_volume / available_extract_volume), 1, preserve_data = TRUE, no_react = TRUE) + + extract.reagents.handle_reactions() // Reaction handling in the transfer proc is reciprocal and we don't want to blow up the tmp holder early. + if(QDELETED(extract)) + beakers -= extract + extracts -= extract + + return ..() //I tried to just put it in the allowed_containers list but //if you do that it must have reagents. If you're going to @@ -254,6 +306,7 @@ desc = "A custom made cryogenic grenade. Rapidly cools contents upon ignition." casedesc = "Upon ignition, it rapidly cools contents by 100 K. Smaller splash range than regular casings." icon_state = "cryog" + base_icon_state = "cryog" affected_area = 2 ignition_temp = -100 @@ -262,6 +315,7 @@ desc = "A custom made pyrotechnical grenade. Heats up contents upon ignition." casedesc = "Upon ignition, it rapidly heats contents by 500 K." icon_state = "pyrog" + base_icon_state = "pyrog" ignition_temp = 500 // This is enough to expose a hotspot. /obj/item/grenade/chem_grenade/adv_release // Intended for weaker, but longer lasting effects. Could have some interesting uses. @@ -269,6 +323,7 @@ desc = "A custom made advanced release grenade. It is able to be detonated more than once. Can be configured using a multitool." casedesc = "This casing is able to detonate more than once. Can be configured using a multitool." icon_state = "timeg" + base_icon_state = "timeg" var/unit_spread = 10 // Amount of units per repeat. Can be altered with a multitool. /obj/item/grenade/chem_grenade/adv_release/multitool_act(mob/living/user, obj/item/tool) @@ -292,14 +347,15 @@ for(var/obj/item/reagent_containers/reagent_container in beakers) total_volume += reagent_container.reagents.total_volume if(!total_volume) - qdel(src) + active = FALSE + update_appearance() return var/fraction = unit_spread/total_volume var/datum/reagents/reactants = new(unit_spread) reactants.my_atom = src for(var/obj/item/reagent_containers/reagent_container in beakers) reagent_container.reagents.trans_to(reactants, reagent_container.reagents.total_volume*fraction, threatscale, 1, 1) - chem_splash(get_turf(src), affected_area, list(reactants), ignition_temp, threatscale) + chem_splash(get_turf(src), reagents, affected_area, list(reactants), ignition_temp, threatscale) var/turf/detonated_turf = get_turf(src) addtimer(CALLBACK(src, .proc/detonate), det_time) @@ -574,6 +630,7 @@ name = "holy hand grenade" desc = "A vessel of concentrated religious might." icon_state = "holy_grenade" + base_icon_state = "holy_grenade" stage = GRENADE_READY /obj/item/grenade/chem_grenade/holy/Initialize(mapload) diff --git a/code/modules/aquarium/aquarium.dm b/code/modules/aquarium/aquarium.dm index c6fc660471d..457c181790d 100644 --- a/code/modules/aquarium/aquarium.dm +++ b/code/modules/aquarium/aquarium.dm @@ -249,7 +249,7 @@ if(fluid_type != AQUARIUM_FLUID_AIR) var/datum/reagents/reagent_splash = new() reagent_splash.add_reagent(/datum/reagent/water, 30) - chem_splash(droploc, 3, list(reagent_splash)) + chem_splash(droploc, null, 3, list(reagent_splash)) update_appearance() #undef AQUARIUM_LAYER_STEP diff --git a/code/modules/reagents/chem_splash.dm b/code/modules/reagents/chem_splash.dm index 36231075d58..4b4a95809ab 100644 --- a/code/modules/reagents/chem_splash.dm +++ b/code/modules/reagents/chem_splash.dm @@ -4,75 +4,122 @@ // Threatscale is a multiplier for the 'threat' of the grenade. If you're increasing the affected range drastically, you might want to improve this. // Extra heat affects the temperature of the mixture, and may cause it to react in different ways. - -/proc/chem_splash(turf/epicenter, affected_range = 3, list/datum/reagents/reactants = list(), extra_heat = 0, threatscale = 1, adminlog = 1) +/** + * The basic chemical bomb proc. + * Combines a set of reagent holders into one holder and reacts it. + * If there are any reagents left over it spreads them across the surrounding environment. + * The maximum volume of the holder is temporarily adjusted to allow for reactions which increase total volume to work at full effectiveness. + * The maximum volume of the holder is then reset to its original value. + * + * Arguments: + * - [epicenter][/turf]: The epicenter of the splash if some of the reagents aren't consumed. + * - [holder][/datum/reagents]: The holder to combine all of the reagents into. A temporary one is created if this is null. + * - [reactants][/list/datum/reagents]: The set of reagent holders to combine. + * - extra_heat: Some amount to heat the combined reagents by before reacting them. + * - threatscale: A multiplier for the reagent quantities involved. + * - adminlog: Whether to alert the admins that this has occured. + */ +/proc/chem_splash(turf/epicenter, datum/reagents/holder = null, affected_range = 3, list/datum/reagents/reactants = list(), extra_heat = 0, threatscale = 1, adminlog = 1) if(!isturf(epicenter) || !reactants.len || threatscale <= 0) return - var/has_reagents - var/total_reagents - for(var/datum/reagents/R in reactants) - if(R.total_volume) - has_reagents = 1 - total_reagents += R.total_volume - if(!has_reagents) + var/total_reagents = holder?.total_volume + var/maximum_reagents = holder?.maximum_volume + for(var/datum/reagents/reactant in reactants) + if(reactant.total_volume) + total_reagents += reactant.total_volume + maximum_reagents += reactant.maximum_volume + + if (total_reagents <= 0) + return FALSE + + var/tmp_holder = null + var/original_max_volume = null + if (isnull(holder)) + tmp_holder = TRUE + holder = new /datum/reagents(maximum_reagents * threatscale) + holder.my_atom = epicenter + else + tmp_holder = FALSE + original_max_volume = holder.maximum_volume + if(threatscale < 1) + holder.multiply_reagents(threatscale) + holder.maximum_volume = maximum_reagents * threatscale + else + holder.maximum_volume = maximum_reagents * threatscale + holder.multiply_reagents(threatscale) + + for(var/datum/reagents/reactant as anything in reactants) + reactant.trans_to(holder, reactant.total_volume, threatscale, preserve_data = TRUE, no_react = TRUE) + + holder.chem_temp += extra_heat // Average temperature of reagents + extra heat. + holder.handle_reactions() // React them now. + + if(holder.total_volume) + if(affected_range >= 0) + spread_reagents(holder, epicenter, affected_range) + holder.clear_reagents() + + if(tmp_holder) + qdel(holder) + else + holder.maximum_volume = original_max_volume + + return TRUE + + +/** + * Exposes all accessible atoms within some distance of an epicenter to some reagents. + * Does not clear the source reagent holder; that must be done manually if it is desired. + * + * Arguments: + * - [source][/datum/reagents]: The reagents to spread around. + * - [epicenter][/atom]: The epicenter/source location of the reagent spread. + * - spread_range: The range in which to spread the reagents. + */ +/proc/spread_reagents(datum/reagents/source, atom/epicenter, spread_range) + var/datum/effect_system/steam_spread/steam = new /datum/effect_system/steam_spread() + steam.set_up(10, 0, epicenter) + steam.attach(epicenter) + steam.start() + + + var/list/viewable = view(spread_range, epicenter) + var/list/accessible = list(epicenter) + for(var/i in 1 to spread_range) + var/list/turflist = list() + for(var/turf/T in (orange(i, epicenter) - orange(i-1, epicenter))) + turflist |= T + for(var/turf/T in turflist) + if(!(get_dir(T,epicenter) in GLOB.cardinals) && (abs(T.x - epicenter.x) == abs(T.y - epicenter.y) )) + turflist.Remove(T) + turflist.Add(T) // we move the purely diagonal turfs to the end of the list. + for(var/turf/T in turflist) + if(accessible[T]) + continue + for(var/thing in T.get_atmos_adjacent_turfs(alldir = TRUE)) + var/turf/NT = thing + if(!(NT in accessible)) + continue + if(!(get_dir(T,NT) in GLOB.cardinals)) + continue + accessible[T] = 1 + break + + var/chem_temp = source.chem_temp + var/list/reactable = accessible + for(var/turf/T in accessible) + reactable += T + for(var/atom/A in T.get_all_contents()) + if(!(A in viewable)) + continue + reactable |= A + if(chem_temp >= 300) + T.hotspot_expose(chem_temp*2, 5) + if(!reactable.len) //Nothing to react with. Probably means we're in nullspace. return - - var/datum/reagents/splash_holder = new/datum/reagents(total_reagents*threatscale) - splash_holder.my_atom = epicenter // For some reason this is setting my_atom to null, and causing runtime errors. - var/total_temp = 0 - - for(var/datum/reagents/R in reactants) - R.trans_to(splash_holder, R.total_volume, threatscale, 1, 1) - total_temp += R.chem_temp - splash_holder.chem_temp = (total_temp/reactants.len) + extra_heat // Average temperature of reagents + extra heat. - splash_holder.handle_reactions() // React them now. - - if(splash_holder.total_volume && affected_range >= 0) //The possible reactions didnt use up all reagents, so we spread it around. - var/datum/effect_system/steam_spread/steam = new /datum/effect_system/steam_spread() - steam.set_up(10, 0, epicenter) - steam.attach(epicenter) - steam.start() - - var/list/viewable = view(affected_range, epicenter) - - var/list/accessible = list(epicenter) - for(var/i in 1 to affected_range) - var/list/turflist = list() - for(var/turf/T in (orange(i, epicenter) - orange(i-1, epicenter))) - turflist |= T - for(var/turf/T in turflist) - if(!(get_dir(T,epicenter) in GLOB.cardinals) && (abs(T.x - epicenter.x) == abs(T.y - epicenter.y) )) - turflist.Remove(T) - turflist.Add(T) // we move the purely diagonal turfs to the end of the list. - for(var/turf/T in turflist) - if(accessible[T]) - continue - for(var/thing in T.get_atmos_adjacent_turfs(alldir = TRUE)) - var/turf/NT = thing - if(!(NT in accessible)) - continue - if(!(get_dir(T,NT) in GLOB.cardinals)) - continue - accessible[T] = 1 - break - var/list/reactable = accessible - for(var/turf/T in accessible) - for(var/atom/A in T.get_all_contents()) - if(!(A in viewable)) - continue - reactable |= A - if(extra_heat >= 300) - T.hotspot_expose(extra_heat*2, 5) - if(!reactable.len) //Nothing to react with. Probably means we're in nullspace. - return - for(var/thing in reactable) - var/atom/A = thing - var/distance = max(1,get_dist(A, epicenter)) - var/fraction = 0.5/(2 ** distance) //50/25/12/6... for a 200u splash, 25/12/6/3... for a 100u, 12/6/3/1 for a 50u - splash_holder.expose(A, TOUCH, fraction) - - qdel(splash_holder) - return 1 - - + for(var/thing in reactable) + var/atom/A = thing + var/distance = max(1, get_dist(A, epicenter)) + var/fraction = 0.5 / (2 ** distance) //50/25/12/6... for a 200u splash, 25/12/6/3... for a 100u, 12/6/3/1 for a 50u + source.expose(A, TOUCH, fraction) diff --git a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm index 8486c263b0c..181a179e271 100644 --- a/code/modules/reagents/chemistry/machinery/chem_dispenser.dm +++ b/code/modules/reagents/chemistry/machinery/chem_dispenser.dm @@ -391,7 +391,7 @@ for(var/i in 1 to total) Q.add_reagent(pick(dispensable_reagents), 10, reagtemp = dispensed_temperature) R += Q - chem_splash(get_turf(src), 3, R) + chem_splash(get_turf(src), null, 3, R) if(beaker?.reagents) beaker.reagents.remove_all() cell.use(total/powerefficiency) diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index e2258c81867..06c977813a6 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -52,7 +52,7 @@ /obj/structure/reagent_dispensers/proc/boom() visible_message(span_danger("\The [src] ruptures!")) - chem_splash(loc, 5, list(reagents)) + chem_splash(loc, null, 5, list(reagents)) qdel(src) /obj/structure/reagent_dispensers/deconstruct(disassembled = TRUE)