mirror of
https://github.com/vgstation-coders/vgstation13.git
synced 2025-12-10 10:21:11 +00:00
The Paint & Linen Update [Splinter 2]: Splashplosions (#35528)
* Soft Reset * gotta set up the FLAXOIL define * test_reach * deprecated comment has left the building
This commit is contained in:
@@ -236,6 +236,8 @@
|
||||
|
||||
#define isfloor(A) (istype(A, /turf/simulated/floor) || istype(A, /turf/unsimulated/floor) || istype(A, /turf/simulated/floor/shuttle) || istype(A, /turf/simulated/floor/shuttle/brig))
|
||||
|
||||
#define iswall(A) (istype(A, /turf/simulated/wall) || istype(A, /turf/unsimulated/wall))
|
||||
|
||||
#define isshuttleturf(A) (istype(A, /turf/simulated/wall/shuttle) || istype(A, /turf/simulated/floor/shuttle))
|
||||
|
||||
#define issilent(A) (A.silent || (ishuman(A) && (A.mind && A.mind.miming || A:species:flags & SPECIES_NO_MOUTH))) //Remember that silent is not the same as miming. Miming you can emote, silent you can't gesticulate at all
|
||||
|
||||
@@ -524,6 +524,8 @@
|
||||
#define MIMOSA "mimosa"
|
||||
#define LEMONDROP "lemondrop"
|
||||
|
||||
#define FLAXOIL "flax_oil"
|
||||
|
||||
// How many units of reagent are consumed per tick, by default.
|
||||
#define REAGENTS_METABOLISM 0.2
|
||||
|
||||
|
||||
@@ -201,3 +201,14 @@ var/static/list/counterclockwise_perpendicular_dirs = list(EAST,WEST,EAST|WEST,S
|
||||
return "↙"
|
||||
if(NORTHWEST)
|
||||
return "↖"
|
||||
|
||||
/proc/splitdiagonals(var/dir)
|
||||
switch(dir)
|
||||
if(NORTHEAST)
|
||||
return list(NORTH,EAST)
|
||||
if(SOUTHEAST)
|
||||
return list(SOUTH,EAST)
|
||||
if(SOUTHWEST)
|
||||
return list(SOUTH,WEST)
|
||||
if(NORTHWEST)
|
||||
return list(NORTH,WEST)
|
||||
|
||||
@@ -22,6 +22,8 @@
|
||||
var/vector/origin_floored //the floored origin vector
|
||||
var/vector/direction //direction of the ray
|
||||
var/original_damage //original damage of the ray when applicable
|
||||
var/turf/final_turf
|
||||
var/turf/previous_turf
|
||||
|
||||
/ray/proc/toString()
|
||||
return "\[Ray\](\n- origin = " + origin.toString() + "\n- origin_floored = "+ origin_floored.toString() + "\n- direction = " + direction.toString() + "\n- z-level = " + num2text(z) + "\n)"
|
||||
@@ -112,6 +114,10 @@
|
||||
//our result
|
||||
var/list/rayCastHit/hits = list()
|
||||
|
||||
var/turf/T = vector2turf(origin.floored(), z)
|
||||
previous_turf = T
|
||||
final_turf = T
|
||||
|
||||
while(distance < max_distance)
|
||||
//moving one step further
|
||||
pointer += a_step
|
||||
@@ -134,7 +140,10 @@
|
||||
continue
|
||||
|
||||
//getting the turf at our current (floored) vector
|
||||
var/turf/T = vector2turf(new_position, z)
|
||||
T = vector2turf(new_position, z)
|
||||
if (!T.density)
|
||||
previous_turf = final_turf
|
||||
final_turf = T
|
||||
|
||||
//trying hit at turf
|
||||
var/rayCastHitInfo/info = new /rayCastHitInfo(src, makeweakref(T), new_position, new_position_unfloored, distance)
|
||||
|
||||
128
code/__HELPERS/test_reach.dm
Normal file
128
code/__HELPERS/test_reach.dm
Normal file
@@ -0,0 +1,128 @@
|
||||
//test_reach(), by Deity Link
|
||||
//Basically sends a cheap projectile that moves from a turf A to a turf B in a "straight" line. Returns true if it reaches turf B without hitting anything on the way there (other than turf B itself)
|
||||
//Useful for instance to check if an item thrown/projectile fired from a A to B would reach its target
|
||||
|
||||
/proc/test_reach(var/turf/origin,var/turf/destination,var/_pass_flags=0)
|
||||
if (!origin || !destination)
|
||||
return FALSE
|
||||
if (origin.z != destination.z)
|
||||
return FALSE
|
||||
if (origin == destination)
|
||||
return TRUE
|
||||
var/obj/test_reach/test = new(origin,destination,_pass_flags)
|
||||
var/result = test.main()
|
||||
qdel(test)
|
||||
return result
|
||||
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////
|
||||
|
||||
/obj/test_reach
|
||||
invisibility = 101
|
||||
pass_flags = 0
|
||||
|
||||
var/dist_x
|
||||
var/dist_y
|
||||
var/dx = 0
|
||||
var/dy = 0
|
||||
var/error = 0
|
||||
var/target_angle = 0
|
||||
var/bumped = 0
|
||||
var/max_range = 100
|
||||
var/turf/starting
|
||||
var/turf/target
|
||||
|
||||
var/result = FALSE
|
||||
var/finished = FALSE
|
||||
|
||||
/obj/test_reach/New(var/turf/loc,var/turf/destination,var/_pass_flags)
|
||||
..()
|
||||
starting = loc
|
||||
target = destination
|
||||
pass_flags = _pass_flags
|
||||
|
||||
/obj/test_reach/proc/main()
|
||||
//let's do our first movement by carefully going around any adjacent wall if another cardinal direction toward our destination is possible
|
||||
//this fixes a quirk with bresenham paths where it may decide to run into adjacent walls on its first step even when it doesn't make "sense"
|
||||
var/orientation = get_dir(loc,target)
|
||||
if (orientation in diagonal)
|
||||
var/turf/gotta_move = null
|
||||
for (var/direction in splitdiagonals(orientation))
|
||||
var/turf/T = get_step(loc,direction)
|
||||
if (!T.density && T.Adjacent(src))
|
||||
if (!gotta_move)
|
||||
gotta_move = T
|
||||
else
|
||||
gotta_move = null
|
||||
if (gotta_move)
|
||||
loc = gotta_move
|
||||
starting = loc
|
||||
if (starting == target)
|
||||
return TRUE
|
||||
//init
|
||||
dist_x = abs(target.x - starting.x)
|
||||
dist_y = abs(target.y - starting.y)
|
||||
if (target.x > starting.x)
|
||||
dx = EAST
|
||||
else
|
||||
dx = WEST
|
||||
|
||||
if (target.y > starting.y)
|
||||
dy = NORTH
|
||||
else
|
||||
dy = SOUTH
|
||||
|
||||
if(dist_x > dist_y)
|
||||
error = dist_x/2 - dist_y
|
||||
else
|
||||
error = dist_y/2 - dist_x
|
||||
|
||||
//main loop
|
||||
while(loc && !finished)
|
||||
loop()
|
||||
|
||||
return result
|
||||
|
||||
/obj/test_reach/proc/loop()
|
||||
if(loc && !finished)
|
||||
if(dist_x > dist_y)
|
||||
bresenham_step(dist_x,dist_y,dx,dy)
|
||||
else
|
||||
bresenham_step(dist_y,dist_x,dy,dx)
|
||||
|
||||
bumped = 0
|
||||
|
||||
/obj/test_reach/proc/bresenham_step(var/distA, var/distB, var/dA, var/dB)//based on the code I wrote forever ago in projectiles.dm
|
||||
if(max_range < 1)
|
||||
finished = TRUE
|
||||
return
|
||||
max_range--
|
||||
if(error < 0)
|
||||
var/atom/step = get_step(src, dB)
|
||||
if(!step)
|
||||
finished = TRUE
|
||||
return
|
||||
Move(step)
|
||||
error += distA
|
||||
if (loc == target)
|
||||
result = TRUE
|
||||
finished = TRUE
|
||||
else
|
||||
var/atom/step = get_step(src, dA)
|
||||
if(!step)
|
||||
finished = TRUE
|
||||
return
|
||||
Move(step)
|
||||
error -= distB
|
||||
dir = dA
|
||||
if(error < 0)
|
||||
dir = dA + dB
|
||||
if (loc == target)
|
||||
result = TRUE
|
||||
finished = TRUE
|
||||
|
||||
/obj/test_reach/to_bump(var/atom/A)
|
||||
if (A == target)
|
||||
result = TRUE
|
||||
finished = TRUE
|
||||
else
|
||||
finished = TRUE
|
||||
@@ -451,6 +451,12 @@
|
||||
return TRUE
|
||||
if(locate(/obj/effect/unwall_field) in loc) //Annoying workaround for this -kanef
|
||||
return TRUE
|
||||
if(istype(mover, /obj/item/projectile/beam))
|
||||
var/obj/item/projectile/beam/B = mover
|
||||
var/returns = bounds_dist(src, B.previous_turf) >= 0
|
||||
if (returns && B.previous_turf)
|
||||
B.final_turf = B.previous_turf
|
||||
return returns
|
||||
return bounds_dist(src, mover) >= 0
|
||||
|
||||
// harderforce is for things like lighting overlays which should only be moved in EXTREMELY specific sitations.
|
||||
|
||||
@@ -110,12 +110,16 @@ steam.start() -- spawns the effect
|
||||
icon_state = "extinguish"
|
||||
density = 0
|
||||
|
||||
/datum/effect/system/steam_spread/set_up(n = 3, c = 0, turf/loc)
|
||||
/datum/effect/system/steam_spread
|
||||
var/color
|
||||
|
||||
/datum/effect/system/steam_spread/set_up(n = 3, c = 0, turf/loc, var/_color = null)
|
||||
if(n > 10)
|
||||
n = 10
|
||||
number = n
|
||||
cardinals = c
|
||||
location = loc
|
||||
color = _color
|
||||
|
||||
/datum/effect/system/steam_spread/start()
|
||||
var/i = 0
|
||||
@@ -124,6 +128,9 @@ steam.start() -- spawns the effect
|
||||
if(holder)
|
||||
src.location = get_turf(holder)
|
||||
var/obj/effect/steam/steam = new /obj/effect/steam(src.location)
|
||||
if (color)
|
||||
steam.icon_state = "extinguish_gray"
|
||||
steam.color = color
|
||||
var/direction
|
||||
if(src.cardinals)
|
||||
direction = pick(cardinal)
|
||||
|
||||
@@ -297,16 +297,8 @@
|
||||
|
||||
reservoir.reagents.trans_to(src, reservoir.reagents.total_volume)
|
||||
|
||||
if(src.reagents.total_volume) //The possible reactions didnt use up all reagents.
|
||||
var/datum/effect/system/steam_spread/steam = new /datum/effect/system/steam_spread()
|
||||
steam.set_up(10, 0, get_turf(src))
|
||||
steam.attach(src)
|
||||
steam.start()
|
||||
|
||||
for(var/atom/A in view(affected_area, get_turf(src)))
|
||||
if( A == src )
|
||||
continue
|
||||
src.reagents.reaction(A, 1, 10)
|
||||
if(reagents.total_volume) //The possible reactions didnt use up all reagents.
|
||||
reagents.splashplosion(affected_area)
|
||||
|
||||
invisibility = INVISIBILITY_MAXIMUM //Why am i doing this?
|
||||
spawn(50) //To make sure all reagents can work
|
||||
|
||||
@@ -223,7 +223,10 @@ var/list/one_way_windows
|
||||
return TRUE
|
||||
if(!density)
|
||||
return TRUE
|
||||
if(istype(mover))
|
||||
if(istype(mover, /obj/item/projectile/beam))
|
||||
var/obj/item/projectile/beam/B = mover
|
||||
return bounds_dist(border_dummy, B.previous_turf) >= 0
|
||||
else if(istype(mover))
|
||||
return bounds_dist(border_dummy, mover) >= 0
|
||||
else if(get_dir(loc, target) == dir)
|
||||
return FALSE
|
||||
|
||||
@@ -12,10 +12,16 @@
|
||||
w_class = W_CLASS_MEDIUM
|
||||
fire_delay = 1
|
||||
fire_sound = 'sound/weapons/shotgun.ogg'
|
||||
empty_sound = 'sound/weapons/magazine_load_click.ogg'
|
||||
conventional_firearm = 0
|
||||
var/hard = 1 //When toggled on, the gun's shots will deal damage. When off, they deal no damage, but deliver five times the reagents.
|
||||
var/max_reagents = 50
|
||||
var/obj/item/projectile/projectile_type = /obj/item/projectile/bullet/liquid_blob
|
||||
|
||||
var/mixed_color = null
|
||||
var/mixed_alpha = 255
|
||||
var/radius = 0
|
||||
|
||||
/obj/item/weapon/gun/siren/isHandgun()
|
||||
return FALSE
|
||||
|
||||
@@ -24,6 +30,15 @@
|
||||
create_reagents(max_reagents)
|
||||
reagents.add_reagent(WATER, max_reagents)
|
||||
|
||||
/obj/item/weapon/gun/siren/click_empty(mob/user = null)
|
||||
if (user)
|
||||
if(empty_sound)
|
||||
to_chat(user, "<span class='warning'>No liquid left inside \the [src]</span>")
|
||||
playsound(user, empty_sound, 100, 1)
|
||||
else
|
||||
if(empty_sound)
|
||||
playsound(src, empty_sound, 100, 1)
|
||||
|
||||
/obj/item/weapon/gun/siren/verb/flush_reagents()
|
||||
set name = "Flush contents"
|
||||
set category = "Object"
|
||||
@@ -38,9 +53,13 @@
|
||||
if(in_chamber)
|
||||
QDEL_NULL(in_chamber)
|
||||
|
||||
/obj/item/weapon/gun/siren/on_reagent_change()
|
||||
mixed_color = mix_color_from_reagents(reagents.reagent_list)
|
||||
mixed_alpha = mix_alpha_from_reagents(reagents.reagent_list)
|
||||
|
||||
/obj/item/weapon/gun/siren/examine(mob/user)
|
||||
..()
|
||||
to_chat(user, "<span class='info'>It has [round(reagents.total_volume/10)] round\s remaining.</span>")
|
||||
to_chat(user, "<span class='info'>It has [round(reagents.total_volume/5)] round\s remaining.</span>")
|
||||
if(hard >= 0)
|
||||
if(hard)
|
||||
to_chat(user, "<span class='info'>It is set to \"hard liquid\".</span>")
|
||||
@@ -54,11 +73,13 @@
|
||||
desc = initial(desc)
|
||||
fire_sound = initial(fire_sound)
|
||||
recoil = 1
|
||||
radius = 0
|
||||
else
|
||||
to_chat(user, "<span class='info'>You set \the [src] to fire soft liquid.</span>")
|
||||
desc = "The most efficient ranged mass reagent delivery system there is."
|
||||
fire_sound = 'sound/items/egg_squash.ogg'
|
||||
recoil = 0
|
||||
radius = 1
|
||||
|
||||
/obj/item/weapon/gun/siren/afterattack(atom/A, mob/living/user, flag, params, struggle = 0)
|
||||
if(flag)
|
||||
@@ -67,7 +88,7 @@
|
||||
to_chat(user, "<span class='warning'>A label sticks the trigger to the trigger guard!</span>")//Such a new feature, the player might not know what's wrong if it doesn't tell them.
|
||||
|
||||
return
|
||||
if(reagents.total_volume < 10)
|
||||
if(reagents.total_volume < 5)
|
||||
return click_empty(user)
|
||||
if(in_chamber)
|
||||
if(in_chamber.reagents && in_chamber.reagents.total_volume)
|
||||
@@ -78,18 +99,18 @@
|
||||
in_chamber.reagents.remove_reagent(R.id, reagents.get_reagent_amount(R.id)*4)
|
||||
in_chamber.reagents.trans_to(src, in_chamber.reagents.total_volume)
|
||||
QDEL_NULL(in_chamber)
|
||||
in_chamber = new projectile_type(src, hard)
|
||||
reagents.trans_to(in_chamber, 10)
|
||||
if(!hard) //When set to no-damage mode, each shot has five times the reagents.
|
||||
in_chamber = new projectile_type(src, hard, mixed_color, mixed_alpha, radius)
|
||||
reagents.trans_to(in_chamber, 5)
|
||||
if(!hard) //When set to no-damage mode, each shot has ten times the reagents.
|
||||
for(var/datum/reagent/R in in_chamber.reagents.reagent_list)
|
||||
in_chamber.reagents.add_reagent(R.id, reagents.get_reagent_amount(R.id)*4)
|
||||
R.volume *= 10
|
||||
Fire(A,user,params, "struggle" = struggle)
|
||||
|
||||
/obj/item/weapon/gun/siren/process_chambered()
|
||||
return in_chamber
|
||||
|
||||
/obj/item/weapon/gun/siren/can_discharge()
|
||||
if(reagents.total_volume < 10)
|
||||
if(reagents.total_volume < 5)
|
||||
return 1
|
||||
|
||||
/obj/item/weapon/gun/siren/caduceus
|
||||
@@ -118,7 +139,7 @@
|
||||
|
||||
/obj/item/weapon/gun/siren/supersoaker
|
||||
name = "super soaker"
|
||||
desc = "For ages 10 and up."
|
||||
desc = "For ages 10 and up. Pump it to shoot further."
|
||||
icon_state = "super_soaker"
|
||||
item_state = "super_soaker"
|
||||
inhand_states = list("left_hand" = 'icons/mob/in-hand/left/guns.dmi', "right_hand" = 'icons/mob/in-hand/right/guns.dmi')
|
||||
@@ -139,16 +160,18 @@
|
||||
if(harm_labeled >= min_harm_label)
|
||||
to_chat(user, "<span class='warning'>A label sticks the trigger to the trigger guard!</span>")//Such a new feature, the player might not know what's wrong if it doesn't tell them.
|
||||
return
|
||||
if(reagents.total_volume < 10 && !in_chamber)
|
||||
if(reagents.total_volume < 5 && !in_chamber)
|
||||
return click_empty(user)
|
||||
if(!in_chamber)
|
||||
in_chamber = new projectile_type(src, max(3+(round(pumps/2)),15))
|
||||
reagents.trans_to(in_chamber, 10)
|
||||
in_chamber = new projectile_type(src, min(3+(round(pumps/2)),15), mixed_color, mixed_alpha)
|
||||
reagents.trans_to(in_chamber, 5)
|
||||
for(var/datum/reagent/R in in_chamber.reagents.reagent_list)
|
||||
R.volume *= 4//so here we're just doubling our quantity of reagents from 10 to 20//moved from projectile code
|
||||
in_chamber.firer = user
|
||||
Fire(A,user,params, struggle = struggle)
|
||||
if(reagents.total_volume >= 10)
|
||||
in_chamber = new projectile_type(src)
|
||||
reagents.trans_to(in_chamber, 10)
|
||||
if(pumps > 0)
|
||||
pumps--
|
||||
QDEL_NULL(in_chamber)
|
||||
|
||||
/obj/item/weapon/gun/siren/supersoaker/attack_self(mob/user)
|
||||
if(world.time - last_pump >= 1)
|
||||
|
||||
@@ -46,7 +46,8 @@ var/list/beam_master = list()
|
||||
|
||||
var/turf/T = vector2turf(info.point, z)
|
||||
T.last_beam_damage = fired_beam.damage
|
||||
|
||||
fired_beam.final_turf = final_turf
|
||||
fired_beam.previous_turf = previous_turf
|
||||
if(!A.Cross(fired_beam, T) || (!isturf(fired_beam.original) && A == fired_beam.original))
|
||||
var/ret = fired_beam.to_bump(A)
|
||||
if(ret)
|
||||
@@ -82,6 +83,8 @@ var/list/beam_master = list()
|
||||
var/beam_color = null
|
||||
var/beam_shift = null// the beam will animate() toward this color after being fired
|
||||
var/list/ray/past_rays = list() //full of rays
|
||||
var/turf/final_turf = null
|
||||
var/turf/previous_turf = null
|
||||
|
||||
/obj/item/projectile/beam/Destroy()
|
||||
QDEL_LIST_NULL(past_rays)
|
||||
@@ -100,7 +103,8 @@ var/list/beam_master = list()
|
||||
hits = shot_ray.cast(travel_range)
|
||||
else
|
||||
hits = shot_ray.cast(MAX_BEAM_DISTANCE)
|
||||
|
||||
final_turf = shot_ray.final_turf
|
||||
previous_turf = shot_ray.previous_turf
|
||||
if(!gcDestroyed)
|
||||
past_rays += shot_ray
|
||||
else
|
||||
@@ -118,11 +122,13 @@ var/list/beam_master = list()
|
||||
shot_ray.draw(last_hit.distance, icon, icon_state, color_override = beam_color, color_shift = beam_shift)
|
||||
|
||||
if(last_hit.hit_type == RAY_CAST_REBOUND)
|
||||
final_turf=null
|
||||
ASSERT(!gcDestroyed)
|
||||
spawn()
|
||||
rebound(last_hit.hit_atom)
|
||||
|
||||
if(last_hit.hit_type == RAY_CAST_PORTAL)
|
||||
final_turf=null
|
||||
ASSERT(!gcDestroyed)
|
||||
spawn()
|
||||
portal(last_hit.hit_atom)
|
||||
@@ -1156,32 +1162,25 @@ var/list/laser_tag_vests = list(/obj/item/clothing/suit/tag/redtag, /obj/item/cl
|
||||
penetration = 0
|
||||
pass_flags = PASSTABLE
|
||||
var/has_splashed = FALSE
|
||||
var/atom/splashed_atom = null
|
||||
|
||||
/obj/item/projectile/beam/liquid_stream/New(atom/A, var/t_range)
|
||||
/obj/item/projectile/beam/liquid_stream/New(atom/A, var/t_range=3, var/m_color, var/m_alpha=255)
|
||||
..(A)
|
||||
create_reagents(20)
|
||||
if(t_range)
|
||||
travel_range = t_range
|
||||
else
|
||||
travel_range = 0
|
||||
|
||||
/obj/item/projectile/beam/liquid_stream/OnFired()
|
||||
beam_color = mix_color_from_reagents(reagents.reagent_list)
|
||||
alpha = mix_alpha_from_reagents(reagents.reagent_list)
|
||||
..()
|
||||
beam_color = m_color
|
||||
alpha = m_alpha
|
||||
|
||||
/obj/item/projectile/beam/liquid_stream/on_hit(var/atom/A, var/blocked = 0)
|
||||
if(reagents.total_volume)
|
||||
for(var/datum/reagent/R in reagents.reagent_list)
|
||||
reagents.add_reagent(R.id, reagents.get_reagent_amount(R.id))//so here we're just doubling our quantity of reagents from 10 to 20
|
||||
if(istype(A, /mob))
|
||||
if(reagents.total_volume && istype(A, /mob))
|
||||
if(firer.zone_sel.selecting == TARGET_MOUTH && def_zone == LIMB_HEAD && ishuman(A)) //if aiming at head and is humanoid
|
||||
var/mob/living/carbon/human/victim = A
|
||||
if(!victim.check_body_part_coverage(MOUTH)) //if not covered with mask or something
|
||||
victim.visible_message("<span class='warning'>[A] swallows \the [src]!</span>",
|
||||
"<span class='warning'>You swallow \the [src]!</span>")
|
||||
reagents.trans_to(A, reagents.total_volume) //20% chance to get in mouth and in system, if mouth targeting was possible at all with projectiles this chance should be scrapped
|
||||
reagents.trans_to(A, reagents.total_volume)
|
||||
has_splashed = TRUE //guess we arent stacking with the splash
|
||||
qdel(src)
|
||||
return 1
|
||||
else
|
||||
A.visible_message("<span class='warning'>\The [src] gets blocked from [A]'s mouth!</span>",
|
||||
@@ -1190,16 +1189,35 @@ var/list/laser_tag_vests = list(/obj/item/clothing/suit/tag/redtag, /obj/item/cl
|
||||
var/splash_verb = pick("douses","completely soaks","drenches","splashes")
|
||||
A.visible_message("<span class='warning'>\The [src] [splash_verb] [A]!</span>",
|
||||
"<span class='warning'>\The [src] [splash_verb] you!</span>")
|
||||
splash_sub(reagents, get_turf(A), reagents.total_volume/2, firer)//then we splash 10 of those on the turf in front (or under in case of mobs) of the hit atom
|
||||
else
|
||||
splash_sub(reagents, get_turf(src), reagents.total_volume/2, firer)
|
||||
splash_sub(reagents, A, reagents.total_volume, firer)//and 10 more on the atom itself
|
||||
has_splashed = TRUE
|
||||
return 1
|
||||
|
||||
/obj/item/projectile/beam/liquid_stream/OnDeath()
|
||||
if(!has_splashed && loc)
|
||||
splash_sub(reagents, get_turf(src), reagents.total_volume)
|
||||
/obj/item/projectile/beam/liquid_stream/to_bump(var/atom/A)
|
||||
splashed_atom = A//doesn't matter if it's actually the atom we end up splashing since we only use that var on bullet_die()
|
||||
. = ..()
|
||||
|
||||
/obj/item/projectile/beam/liquid_stream/bullet_die()//splashes reagents on the hit atom, or in front of it in case of turfs and border objects
|
||||
if(reagents && reagents.total_volume && !has_splashed && ((bumped && splashed_atom) || final_turf))
|
||||
if (splashed_atom && !isturf(splashed_atom) && (previous_turf && previous_turf.Adjacent(splashed_atom)))
|
||||
if (splashed_atom.flow_flags & ON_BORDER)
|
||||
loc = previous_turf
|
||||
else
|
||||
loc = get_turf(splashed_atom)
|
||||
else if (isturf(splashed_atom))
|
||||
loc = final_turf
|
||||
else
|
||||
loc = previous_turf
|
||||
playsound(loc, 'sound/effects/slosh.ogg', 20, 1)
|
||||
reagents.splashplosion(0)
|
||||
has_splashed = TRUE
|
||||
..()
|
||||
//I never want to deal wity ray casts ever again
|
||||
/obj/item/projectile/beam/liquid_stream/fireto(var/vector/origin, var/vector/direction)//splashes reagents on the turf if the projectile ran out
|
||||
..()
|
||||
if (reagents && reagents.total_volume && final_turf && !has_splashed)
|
||||
loc = final_turf
|
||||
reagents.splashplosion(0)
|
||||
has_splashed = TRUE
|
||||
qdel(src)
|
||||
|
||||
|
||||
/obj/item/projectile/beam/liquid_stream/proc/adjust_strength(var/t_range)
|
||||
if(t_range)
|
||||
|
||||
@@ -904,8 +904,10 @@
|
||||
custom_impact = 1
|
||||
rotate = 0
|
||||
var/hard = 0
|
||||
var/radius = 1//big glob of liquid, splashes a bit on surroundings
|
||||
var/atom/splashed_atom = null
|
||||
|
||||
/obj/item/projectile/bullet/liquid_blob/New(atom/T, var/hardness = null)
|
||||
/obj/item/projectile/bullet/liquid_blob/New(atom/T, var/hardness = null, var/mixed_color=null, var/mixed_alpha=255, var/_rad=1)
|
||||
..(T)
|
||||
hard = hardness
|
||||
if(hard)
|
||||
@@ -913,19 +915,15 @@
|
||||
create_reagents(10)
|
||||
else
|
||||
create_reagents(50)
|
||||
icon += mixed_color
|
||||
alpha = mixed_alpha
|
||||
radius = _rad
|
||||
|
||||
/obj/item/projectile/bullet/liquid_blob/OnFired()
|
||||
src.icon += mix_color_from_reagents(reagents.reagent_list)
|
||||
src.alpha = mix_alpha_from_reagents(reagents.reagent_list)
|
||||
..()
|
||||
|
||||
/obj/item/projectile/bullet/liquid_blob/on_hit(atom/A as mob|obj|turf|area)
|
||||
if(!A)
|
||||
return
|
||||
..()
|
||||
if(reagents.total_volume)
|
||||
for(var/datum/reagent/R in reagents.reagent_list)
|
||||
reagents.add_reagent(R.id, reagents.get_reagent_amount(R.id))
|
||||
/obj/item/projectile/bullet/liquid_blob/to_bump(var/atom/A)
|
||||
splashed_atom = A//doesn't matter if it's actually the atom we end up splashing since we only use that var on bullet_die()
|
||||
. = ..()
|
||||
if (. && A)
|
||||
if ((special_collision == PROJECTILE_COLLISION_DEFAULT) || (special_collision == PROJECTILE_COLLISION_BLOCKED))
|
||||
if(istype(A, /mob))
|
||||
if(hard)
|
||||
var/splash_verb = pick("dousing","completely soaking","drenching","splashing")
|
||||
@@ -935,15 +933,16 @@
|
||||
var/splash_verb = pick("douses","completely soaks","drenches","splashes")
|
||||
A.visible_message("<span class='warning'>\The [src] [splash_verb] [A]!</span>",
|
||||
"<span class='warning'>\The [src] [splash_verb] you!</span>")
|
||||
splash_sub(reagents, get_turf(A), reagents.total_volume/2)
|
||||
else
|
||||
splash_sub(reagents, get_turf(src), reagents.total_volume/2)
|
||||
splash_sub(reagents, A, reagents.total_volume)
|
||||
return 1
|
||||
|
||||
/obj/item/projectile/bullet/liquid_blob/OnDeath()
|
||||
if(get_turf(src))
|
||||
playsound(src, 'sound/effects/slosh.ogg', 20, 1)
|
||||
|
||||
/obj/item/projectile/bullet/liquid_blob/bullet_die()
|
||||
if(reagents.total_volume)
|
||||
var/turf/T = get_turf(splashed_atom)
|
||||
if (!T.density && T.Adjacent(src))
|
||||
loc = T
|
||||
playsound(loc, 'sound/effects/slosh.ogg', 20, 1)
|
||||
reagents.splashplosion(radius)
|
||||
..()
|
||||
|
||||
/obj/item/projectile/bullet/pellet
|
||||
name = "buckshot pellet"
|
||||
|
||||
@@ -1989,10 +1989,7 @@
|
||||
user?.attack_log += text("\[[time_stamp()]\] <span class='danger'>Threw a [lit ? "lit" : "unlit"] molotov to \the [hit_atom], containing [reagents.get_reagent_ids()]</span>")
|
||||
log_attack("[lit ? "Lit" : "Unlit"] molotov shattered at [formatJumpTo(get_turf(hit_atom))], thrown by [key_name(user)] and containing [reagents.get_reagent_ids()]")
|
||||
message_admins("[lit ? "Lit" : "Unlit"] molotov shattered at [formatJumpTo(get_turf(hit_atom))], thrown by [key_name_admin(user)] and containing [reagents.get_reagent_ids()]")
|
||||
reagents.reaction(get_turf(src), TOUCH) //splat the floor AND the thing we hit, otherwise fuel wouldn't ignite when hitting anything that wasn't a floor
|
||||
if(hit_atom != get_turf(src)) //prevent spilling on the floor twice though
|
||||
var/list/hit_zone = user && user.zone_sel ? list(user.zone_sel.selecting) : ALL_LIMBS
|
||||
reagents.reaction(hit_atom, TOUCH, zone_sels = hit_zone) //maybe this could be improved?
|
||||
reagents.splashplosion(reagents.total_volume >= (reagents.maximum_volume/2))//splashing everything on the tile hit, and the surrounding ones if we're over half full.
|
||||
invisibility = INVISIBILITY_MAXIMUM //so it stays a while to ignite any fuel
|
||||
|
||||
if(molotov == 1) //for molotovs
|
||||
@@ -2000,7 +1997,6 @@
|
||||
new /obj/effect/decal/cleanable/ash(get_turf(src))
|
||||
var/turf/loca = get_turf(src)
|
||||
if(loca)
|
||||
// to_chat(world, "<span class='warning'>Burning...</span>")
|
||||
loca.hotspot_expose(700, 1000,surfaces=istype(loc,/turf))
|
||||
else
|
||||
new /obj/item/weapon/reagent_containers/glass/rag(get_turf(src))
|
||||
|
||||
44
code/modules/reagents/splashplosion.dm
Normal file
44
code/modules/reagents/splashplosion.dm
Normal file
@@ -0,0 +1,44 @@
|
||||
|
||||
//Hits every turfs in view and their content with our reagents (provided they are not blocked by windows or other turfs)
|
||||
//Can be set to inject hit mob with some of the reagents based on their permeability. False by default.
|
||||
/datum/reagents/proc/splashplosion(var/range=3,var/allow_permeability=FALSE)
|
||||
if (reagent_list.len <= 0)
|
||||
return
|
||||
|
||||
var/list/hit_turfs = list()
|
||||
var/turf/epicenter = get_turf(my_atom)
|
||||
|
||||
var/datum/effect/system/steam_spread/steam = new /datum/effect/system/steam_spread()
|
||||
steam.set_up(max(range,1)*3, 0, epicenter, mix_color_from_reagents(reagent_list))
|
||||
steam.start()
|
||||
|
||||
playsound(epicenter, 'sound/effects/bamf.ogg', max(10,15*range), 0, range-4)
|
||||
|
||||
if (!range)
|
||||
hit_turfs = list(epicenter)
|
||||
else
|
||||
for(var/turf/T in dview(range, epicenter, INVISIBILITY_MAXIMUM))
|
||||
if (cheap_pythag(T.x - epicenter.x,T.y - epicenter.y) <= range + 0.5)
|
||||
if (test_reach(epicenter,T,PASSTABLE|PASSGRILLE|PASSMOB|PASSMACHINE|PASSGIRDER))
|
||||
hit_turfs += T
|
||||
|
||||
for(var/datum/reagent/R in reagent_list)
|
||||
var/min_volume_per_tile = max(1,R.volume/hit_turfs.len)
|
||||
//the volume is affected by the number of turfs hit. The less turfs hit, the more concentrated the splashing.
|
||||
//and the closer to the epicenter, the more splashing as well
|
||||
|
||||
for (var/turf/T in hit_turfs)
|
||||
var/volume_for_this_tile = round((R.volume - min_volume_per_tile) / max(1,get_dist(epicenter,T))) + min_volume_per_tile
|
||||
if (!T.density)
|
||||
for (var/atom/movable/AM in T.contents)
|
||||
if (ismob(AM))
|
||||
if (isanimal(AM))
|
||||
R.reaction_animal(AM, TOUCH, volume_for_this_tile,hit_turfs)
|
||||
else
|
||||
R.reaction_mob(AM, TOUCH, volume_for_this_tile, ALL_LIMBS, allow_permeability, hit_turfs)
|
||||
else if (isobj(AM) && !istype(AM,/atom/movable/lighting_overlay))
|
||||
R.reaction_obj(AM, volume_for_this_tile,hit_turfs)
|
||||
R.reaction_turf(T, volume_for_this_tile,hit_turfs)
|
||||
|
||||
clear_reagents()
|
||||
|
||||
@@ -539,20 +539,38 @@
|
||||
else
|
||||
to_chat(mob, "<span class = 'notice'>Your pupils dilate further.</span>")
|
||||
|
||||
/datum/disease2/effect/colorsmoke
|
||||
/datum/disease2/effect/colorsplash
|
||||
name = "Colorful Syndrome"
|
||||
desc = "Causes the infected to synthesize smoke & rainbow colourant."
|
||||
desc = "Causes the infected to expulse bursts of paint from their pores."
|
||||
encyclopedia = "The paint can be washed off items, and removed from floors and walls using bleach or acetone. The infected's own skin color will match the color of their last paint burst, but they can recover their original color with a shower, or exposure to space cleaner."
|
||||
stage = 3
|
||||
badness = EFFECT_DANGER_HINDRANCE
|
||||
var/list/random_color_list = list("#00aedb","#a200ff","#f47835","#d41243","#d11141","#00b159","#00aedb","#f37735","#ffc425","#008744","#0057e7","#d62d20","#ffa700")
|
||||
max_multiplier = 3
|
||||
|
||||
/datum/disease2/effect/colorsmoke/activate(var/mob/living/mob)
|
||||
if (ismouse(mob))//people don't like infected mice ruining maint
|
||||
var/mob/living/simple_animal/mouse/M = mob
|
||||
if (!initial(M.infectable))
|
||||
return
|
||||
/datum/disease2/effect/colorsplash/activate(var/mob/living/mob)
|
||||
var/obj/item/weapon/reagent_containers/R = new(get_turf(mob))
|
||||
R.invisibility = 101
|
||||
var/list/colors_to_use = random_color_list.Copy()
|
||||
var/range = 2 + round(max(1,multiplier))
|
||||
var/color_count = round(max(1,multiplier))
|
||||
|
||||
if (ismouse(mob))
|
||||
range = 0
|
||||
color_count = 1
|
||||
|
||||
var/color_to_use = ""
|
||||
|
||||
for(var/i = 1 to color_count)
|
||||
color_to_use = pick(colors_to_use)
|
||||
colors_to_use -= color_to_use
|
||||
R.reagents.add_reagent(FLAXOIL, 10 * max(1,range), list("color" = color_to_use, "alpha" = 255))
|
||||
R.reagents.splashplosion(range)
|
||||
range--
|
||||
|
||||
qdel(R)
|
||||
to_chat(mob, "<span class='notice'>You feel colorful!</span>")
|
||||
mob.reagents.add_reagent(COLORFUL_REAGENT, 5)
|
||||
mob.reagents.add_reagent(PAISMOKE, 5)
|
||||
mob.color = color_to_use
|
||||
|
||||
/datum/disease2/effect/cleansmoke
|
||||
name = "Cleaning Syndrome"
|
||||
|
||||
@@ -110,6 +110,7 @@
|
||||
#include "code\__HELPERS\path.dm"
|
||||
#include "code\__HELPERS\priority_queue.dm"
|
||||
#include "code\__HELPERS\sanitize_values.dm"
|
||||
#include "code\__HELPERS\test_reach.dm"
|
||||
#include "code\__HELPERS\text.dm"
|
||||
#include "code\__HELPERS\time.dm"
|
||||
#include "code\__HELPERS\timed_alerts.dm"
|
||||
@@ -2423,6 +2424,7 @@
|
||||
#include "code\modules\reagents\randomized_reagent.dm"
|
||||
#include "code\modules\reagents\reagent_containers.dm"
|
||||
#include "code\modules\reagents\reagent_dispenser.dm"
|
||||
#include "code\modules\reagents\splashplosion.dm"
|
||||
#include "code\modules\reagents\syringe_gun.dm"
|
||||
#include "code\modules\reagents\machinery\centrifuge.dm"
|
||||
#include "code\modules\reagents\machinery\chem_dispenser.dm"
|
||||
|
||||
Reference in New Issue
Block a user