diff --git a/code/game/objects/effects/decals/misc.dm b/code/game/objects/effects/decals/misc.dm index 6b90cfd62c..752a5dff2c 100644 --- a/code/game/objects/effects/decals/misc.dm +++ b/code/game/objects/effects/decals/misc.dm @@ -24,55 +24,86 @@ var/range = 3 var/hits_left = 3 var/range_left = 3 + var/firstmove = TRUE + var/list/hit /obj/effect/decal/chempuff/blob_act(obj/structure/blob/B) return -/obj/effect/decal/chempuff/Initialize(mapload, stream_mode, speed, range, hits_left) +/obj/effect/decal/chempuff/Initialize(mapload, stream_mode, speed, range, hits_left, size) . = ..() + create_reagents(size, NONE, NO_REAGENTS_VALUE) stream = stream_mode src.speed = speed src.range = src.range_left = range src.hits_left = hits_left + hit = list() -/obj/effect/decal/chempuff/proc/hit_thing(atom/A) +/obj/effect/decal/chempuff/Destroy() + hit = null + return ..() + +/// proc called to handle us hitting something +/obj/effect/decal/chempuff/proc/hit_thing(atom/A, bump_hit) + // if the thing is invisible it usually is abstract/underfloor. also, don't hit ourselves. if(A == src || A.invisibility) return - if(!hits_left) + // don't hit anything on the first move unless overridden (see: we're colliding a wall blocking our move out of the first tile) + if(firstmove && !bump_hit) return - if(stream) - if(ismob(A)) - var/mob/M = A - if(!M.lying || !range_left) - reagents.reaction(M, VAPOR) - hits_left-- - else - if(!range_left) - reagents.reaction(A, VAPOR) - else - reagents.reaction(A) - if(ismob(A)) - hits_left-- + // we're out of hits or we already hit it + if(!hits_left || hit[A]) + return + var/living = isliving(A) + // if it's not dense and we're a stream instead of a mist, and we're not out of range + if(!A.density && stream && range_left && !bump_hit) + return + // non living mobs are effectively abstract + if(ismob(A) && !living) + return + hit[A] = TRUE + reagents.reaction(A, VAPOR) + // mobs absorb enough to decrement hits_left, as well as stuff blocking us. + if(ismob(A) || bump_hit) + hits_left-- /obj/effect/decal/chempuff/Crossed(atom/movable/AM, oldloc) . = ..() + // bump things moving into us as long as we're not on our first move/moving out of origin tile hit_thing(AM) +/obj/effect/decal/chempuff/Bump(atom/A) + . = ..() + // if we hit something blocking our movement, collide it regardless even if we're still on our origin tile + hit_thing(A, TRUE) + /obj/effect/decal/chempuff/proc/run_puff(atom/target) - set waitfor = FALSE - for(var/i in 1 to range) + var/safety = 255 + while(range_left) + if(!safety--) + CRASH("Spray ran out of safety.") + // move towards new turf + step_towards(src, target) + if(firstmove) + // mark first movement so future Cross()es result in collisions + firstmove = FALSE + // decrement range range_left-- + // if we got nullspaced, exit if(!isturf(loc)) break + // hit everything in it for(var/atom/T in loc) hit_thing(T) + // if we got deleted or ran out of hits, stop if(!hits_left || !isturf(loc)) break - if(hits_left && isturf(loc) && (!stream || !range_left)) - reagents.reaction(loc, VAPOR) - hits_left-- - if(!hits_left) + if(!hits_left || !isturf(loc)) + // yeah yeah sue me it's copypasted code but I don't want to declare a var. break + // hit the turf + hit_thing(loc) + sleep(speed) qdel(src) /obj/effect/decal/fakelattice diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index b90815d543..02c8a9802c 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -16,7 +16,7 @@ var/stream_mode = 0 //whether we use the more focused mode var/current_range = 3 //the range of tiles the sprayer will reach. var/spray_range = 3 //the range of tiles the sprayer will reach when in spray mode. - var/stream_range = 1 //the range of tiles the sprayer will reach when in stream mode. + var/stream_range = 3 //the range of tiles the sprayer will reach when in stream mode. var/stream_amount = 10 //the amount of reagents transfered when in stream mode. /// Amount of time it takes for a spray to completely travel. var/spray_delay = 8 @@ -74,19 +74,18 @@ return var/range = clamp(get_dist(src, A), 1, current_range) var/wait_step = CEILING(spray_delay * INVERSE(range), world.tick_lag) - var/obj/effect/decal/chempuff/D = new /obj/effect/decal/chempuff(get_turf(src), stream_mode, wait_step, range, stream_mode? 1 : range) + var/obj/effect/decal/chempuff/D = new /obj/effect/decal/chempuff(get_turf(src), stream_mode, wait_step, range, stream_mode? 1 : range, amount_per_transfer_from_this) var/turf/T = get_turf(src) if(!T) return log_reagent("SPRAY: [key_name(usr)] fired [src] ([REF(src)]) [COORD(T)] at [A] ([REF(A)]) [COORD(A)] (chempuff: [D.reagents.log_list()])") - D.create_reagents(amount_per_transfer_from_this, NONE, NO_REAGENTS_VALUE) if(stream_mode) reagents.trans_to(D, amount_per_transfer_from_this) else reagents.trans_to(D, amount_per_transfer_from_this, 1/range) - D.color = mix_color_from_reagents(D.reagents.reagent_list) + D.add_atom_colour(mix_color_from_reagents(D.reagents.reagent_list), TEMPORARY_COLOUR_PRIORITY) last_spray = world.time - D.run_puff(A) + INVOKE_ASYNC(D, /obj/effect/decal/chempuff/proc/run_puff, A) /obj/item/reagent_containers/spray/attack_self(mob/user) stream_mode = !stream_mode