From 65882f0b9ab39fbbd792cdd5d5a058d10b81e2f8 Mon Sep 17 00:00:00 2001 From: Bloop Date: Sat, 15 Jul 2023 17:50:48 -0400 Subject: [PATCH] Some thrown liquid logic improvement (#22453) * Makes liquids spill on the tile adjacent to a wall when thrown, lets them ricochet off other objects as well * Just adds some documentation This file could use it * Thrown reagents should always expose the tile they hit, even if the liquid lands elsewhere --- code/modules/reagents/reagent_containers.dm | 8 +-- .../code/liquid_systems/liquid_turf.dm | 72 ++++++++++++++++++- 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/code/modules/reagents/reagent_containers.dm b/code/modules/reagents/reagent_containers.dm index dbd540e4cb9..8f38dad586d 100644 --- a/code/modules/reagents/reagent_containers.dm +++ b/code/modules/reagents/reagent_containers.dm @@ -225,16 +225,16 @@ log_combat(thrown_by, M, "splashed", R) reagents.expose(target, TOUCH, splash_multiplier) reagents.expose(target_turf, TOUCH, (1 - splash_multiplier)) // 1 - splash_multiplier because it's what didn't hit the target - target_turf.add_liquid_from_reagents(reagents, reagent_multiplier = (1 - splash_multiplier)) // skyrat edit: liquid spills (molotov buff) (huge) + target_turf.add_liquid_from_reagents(reagents, reagent_multiplier = (1 - splash_multiplier)) // SKYRAT EDIT ADDITION - liquid spills (molotov buff) (huge) else if(bartender_check(target) && thrown) visible_message(span_notice("[src] lands onto the [target.name] without spilling a single drop.")) return else - if(isturf(target)) //SKYRAT EDIT CHANGE - var/turf/T = target - T.add_liquid_from_reagents(reagents) + //SKYRAT EDIT CHANGE START - liquid spills on non-mobs + if(target.can_liquid_spill_on_hit()) + target.add_liquid_from_reagents(reagents, thrown_from = src, thrown_to = target) if(reagents.reagent_list.len && thrown_by) log_combat(thrown_by, target, "splashed (thrown) [english_list(reagents.reagent_list)]", "in [AREACOORD(target)]") log_game("[key_name(thrown_by)] splashed (thrown) [english_list(reagents.reagent_list)] on [target] in [AREACOORD(target)].") diff --git a/modular_skyrat/modules/liquids/code/liquid_systems/liquid_turf.dm b/modular_skyrat/modules/liquids/code/liquid_systems/liquid_turf.dm index 943f88fd8e2..7182a6411c9 100644 --- a/modular_skyrat/modules/liquids/code/liquid_systems/liquid_turf.dm +++ b/modular_skyrat/modules/liquids/code/liquid_systems/liquid_turf.dm @@ -71,14 +71,82 @@ SSliquids.add_active_turf(src) -/turf/proc/add_liquid_from_reagents(datum/reagents/giver, no_react = FALSE, reagent_multiplier = 1) +/** + * Adds liquid to a turf from a given reagents list. + * + * Tries to add liquid to an atom's turf location. The atom could also be the turf itself. + * Calls add_liquid_list() on this turf if it exists. + * + * Arguments: + * * datum/reagents/giver - the reagents to add to the liquid_turf + * * no_react - whether or not we want to react immediately upon adding the reagents + * * reagent_multiplier - multiplies the individual reagents' volumes by this value + * * atom/thrown_from - the atom that the liquid is being thrown from (like a beaker). Null by default. + * * atom/thrown_target - the atom that the liquid is being thrown at. Null by default. + * + */ +/atom/proc/add_liquid_from_reagents(datum/reagents/giver, no_react = FALSE, reagent_multiplier = 1, atom/thrown_from = null, atom/thrown_to = null) + // if we are throwing something, see if we should bounce the liquid off the target atom + if(thrown_from) + var/turf/bounced_to = throw_back_liquid(thrown_from) + if(bounced_to) + giver.expose(thrown_to, TOUCH) // make sure we expose the hit target, since we aren't directly adding liquid there + bounced_to.add_liquid_from_reagents(giver, no_react, reagent_multiplier) + return + + // otherwise business as usual var/list/compiled_list = list() for(var/r in giver.reagent_list) var/datum/reagent/R = r compiled_list[R.type] = R.volume * reagent_multiplier if(!compiled_list.len) //No reagents to add, don't bother going further return - add_liquid_list(compiled_list, no_react, giver.chem_temp) + + // is this a turf? + var/turf/add_location = src + if(!isturf(add_location)) + add_location = loc + + // still can't find a turf? get out of here + if(!isturf(add_location)) + return + + add_location.add_liquid_list(compiled_list, no_react, giver.chem_temp) + +/** + * Bounces a thrown liquid off of a some object that has density. + * + * Finds an adjacent turf to bounce the liquid to. + * + * Arguments: + * * thrown_by - the mob throwing the atom that is doing the liquid spilling. Required. + * + * Returns: the found turf if there was one, null otherwise. + */ +/atom/proc/throw_back_liquid(atom/thrown_from) + if(!thrown_from || !density) + return + + // first check the direction the throw came from + var/found_adjacent_turf = get_open_turf_in_dir(src, get_dir(src, thrown_from.loc)) + + if(found_adjacent_turf) + return found_adjacent_turf + + // there might not be an open turf in that direction (someone stuck in a wall perhaps?) so try to get any adjacent open turf nearby + var/alternate_adjacent_turfs = get_adjacent_open_turfs(src) + if(!length(alternate_adjacent_turfs)) + return + + return pick(alternate_adjacent_turfs) + +/** + * Can liquid spills on this atom? + * + * Returns: TRUE or FALSE + */ +/atom/proc/can_liquid_spill_on_hit() + return isturf(src) || (flags_ricochet & RICOCHET_HARD) || !density //More efficient than add_liquid for multiples /turf/proc/add_liquid_list(reagent_list, no_react = FALSE, chem_temp = 300)