mirror of
https://github.com/Aurorastation/Aurora.3.git
synced 2026-08-30 16:38:22 +01:00
changes: - bugfix: "Operating table less likely to get non-real occupant bug when installed on a shuttle." - bugfix: "Antifuel grenades now reliably neutralize spilled welding fuel and napalm gel." - bugfix: "Generic cleaning products/tools no longer remove spilled welding fuel or napalm gel- requires antifuel reagent." --------- Signed-off-by: Batrachophreno <Batrochophreno@gmail.com> Co-authored-by: VMSolidus <evilexecutive@gmail.com>
270 lines
7.8 KiB
Plaintext
270 lines
7.8 KiB
Plaintext
// Foam
|
|
// Similar to smoke, but spreads out more
|
|
// metal foams leave behind a foamed metal wall
|
|
|
|
/obj/effect/effect/foam
|
|
name = "foam"
|
|
icon_state = "foam"
|
|
opacity = 0
|
|
anchored = 1
|
|
density = 0
|
|
layer = ABOVE_OBJ_LAYER
|
|
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
|
|
animate_movement = 0
|
|
var/solid_time = 120
|
|
var/amount = 3
|
|
var/expand = 1
|
|
var/metal = 0
|
|
var/reagents_checked = FALSE
|
|
|
|
/obj/effect/effect/foam/New(var/loc, var/ismetal = 0)
|
|
..(loc)
|
|
icon_state = "[ismetal? "m" : ""]foam"
|
|
metal = ismetal
|
|
playsound(src, 'sound/effects/bubbles2.ogg', 80, 1, -3)
|
|
addtimer(CALLBACK(src, PROC_REF(tick)), 3 + metal * 3)
|
|
addtimer(CALLBACK(src, PROC_REF(post)), solid_time)
|
|
|
|
var/static/list/loc_connections = list(
|
|
COMSIG_ATOM_ENTERED = PROC_REF(on_entered),
|
|
)
|
|
|
|
AddElement(/datum/element/connect_loc, loc_connections)
|
|
|
|
/obj/effect/effect/foam/proc/tick()
|
|
process()
|
|
checkReagents()
|
|
|
|
/obj/effect/effect/foam/proc/post()
|
|
STOP_PROCESSING(SSprocessing, src)
|
|
sleep(30)
|
|
if(metal)
|
|
var/obj/structure/foamedmetal/M = new /obj/structure/foamedmetal(src.loc)
|
|
M.metal = metal
|
|
M.update_icon()
|
|
flick("[icon_state]-disolve", src)
|
|
QDEL_IN(src, 5)
|
|
|
|
/obj/effect/effect/foam/proc/checkReagents() // transfer any reagents to the floor
|
|
reagents_checked = TRUE
|
|
if(!metal && reagents)
|
|
var/turf/T = get_turf(src)
|
|
reagents.touch_turf(T)
|
|
for(var/obj/O in T)
|
|
reagents.touch_obj(O)
|
|
|
|
/obj/effect/effect/foam/proc/add_carried_reagents(var/list/reagent_ids)
|
|
if(metal || !LAZYLEN(reagent_ids))
|
|
return FALSE
|
|
|
|
if(!reagents)
|
|
create_reagents(10)
|
|
|
|
var/added = FALSE
|
|
for(var/id in reagent_ids)
|
|
if(reagents.add_reagent(id, 1, safety = 1))
|
|
added = TRUE
|
|
return added
|
|
|
|
/obj/effect/effect/foam/process()
|
|
if(--amount < 0)
|
|
return
|
|
|
|
for(var/direction in GLOB.cardinals)
|
|
var/turf/T = get_step(src, direction)
|
|
if(!T)
|
|
continue
|
|
|
|
if(!T.Enter(src))
|
|
continue
|
|
|
|
var/obj/effect/effect/foam/F = locate() in T
|
|
if(F)
|
|
if(!metal && reagents)
|
|
if(F.add_carried_reagents(reagents.reagent_volumes) && F.reagents_checked)
|
|
F.checkReagents()
|
|
continue
|
|
|
|
F = new(T, metal)
|
|
F.amount = amount
|
|
if(!metal)
|
|
if(reagents)
|
|
F.add_carried_reagents(reagents.reagent_volumes)
|
|
|
|
/obj/effect/effect/foam/fire_act(exposed_temperature, exposed_volume) // foam disolves when heated, except metal foams
|
|
. = ..()
|
|
|
|
if(!metal && prob(max(0, exposed_temperature - 475)))
|
|
flick("[icon_state]-disolve", src)
|
|
|
|
QDEL_IN(src, 5)
|
|
|
|
/obj/effect/effect/foam/proc/on_entered(datum/source, atom/movable/arrived, atom/old_loc, list/atom/old_locs)
|
|
SIGNAL_HANDLER
|
|
|
|
if(metal)
|
|
return
|
|
if(istype(arrived, /mob/living))
|
|
var/mob/living/M = arrived
|
|
M.slip("the foam", 6)
|
|
|
|
/obj/effect/effect/foam/spray
|
|
amount = 1 // only spread a little bit
|
|
solid_time = 3 SECONDS
|
|
|
|
/obj/effect/effect/foam/spray/initial
|
|
amount = 0 // don't spread
|
|
|
|
/datum/effect/effect/system/foam_spread
|
|
var/amount = 5 // the size of the foam spread.
|
|
var/list/carried_reagents // the IDs of reagents present when the foam was mixed
|
|
var/metal = 0 // 0 = foam, 1 = metalfoam, 2 = ironfoam
|
|
|
|
/datum/effect/effect/system/foam_spread/set_up(amt=5, loca, var/datum/reagents/carry = null, var/metalfoam = 0)
|
|
amount = round(sqrt(amt / 3), 1)
|
|
if(istype(loca, /turf/))
|
|
location = loca
|
|
else
|
|
location = get_turf(loca)
|
|
|
|
carried_reagents = list()
|
|
metal = metalfoam
|
|
|
|
// bit of a hack here. Foam carries along any reagent also present in the glass it is mixed with (defaults to water if none is present). Rather than actually transfer the reagents, this makes a list of the reagent ids and spawns 1 unit of that reagent when the foam disolves.
|
|
|
|
if(carry && !metal)
|
|
for(var/_R in carry.reagent_volumes)
|
|
carried_reagents += _R
|
|
|
|
/datum/effect/effect/system/foam_spread/start()
|
|
set waitfor = FALSE
|
|
var/obj/effect/effect/foam/F = locate() in location
|
|
if(F)
|
|
F.amount += amount
|
|
if(!metal && F.add_carried_reagents(carried_reagents) && F.reagents_checked)
|
|
F.checkReagents()
|
|
return
|
|
|
|
F = new /obj/effect/effect/foam(location, metal)
|
|
F.amount = amount
|
|
|
|
if(!metal) // don't carry other chemicals if a metal foam
|
|
if(LAZYLEN(carried_reagents))
|
|
F.add_carried_reagents(carried_reagents)
|
|
else
|
|
F.create_reagents(10)
|
|
F.reagents.add_reagent(/singleton/reagent/water, 1, safety = 1)
|
|
|
|
// wall formed by metal foams, dense and opaque, but easy to break
|
|
|
|
/obj/structure/foamedmetal
|
|
icon = 'icons/effects/effects.dmi'
|
|
icon_state = "metalfoam"
|
|
density = 1
|
|
opacity = 1 // changed in New()
|
|
anchored = 1
|
|
name = "foamed metal"
|
|
desc = "A lightweight foamed metal wall."
|
|
var/metal = 1 // 1 = aluminum, 2 = iron
|
|
|
|
/obj/structure/foamedmetal/New()
|
|
..()
|
|
update_nearby_tiles(1)
|
|
|
|
/obj/structure/foamedmetal/Destroy()
|
|
density = 0
|
|
update_nearby_tiles(1)
|
|
set_opacity(0)
|
|
return ..()
|
|
|
|
/obj/structure/foamedmetal/update_icon()
|
|
if(metal == 1)
|
|
icon_state = "metalfoam"
|
|
else
|
|
icon_state = "ironfoam"
|
|
|
|
/obj/structure/foamedmetal/ex_act(severity)
|
|
qdel(src)
|
|
|
|
/obj/structure/foamedmetal/bullet_act(obj/projectile/hitting_projectile, def_zone, piercing_hit)
|
|
. = ..()
|
|
if(. != BULLET_ACT_HIT)
|
|
return .
|
|
|
|
if(metal == 1 || prob(50))
|
|
qdel(src)
|
|
|
|
/obj/structure/foamedmetal/attack_hand(var/mob/user)
|
|
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
|
user.do_attack_animation(src)
|
|
if ((user.mutations & HULK) || (prob(75 - metal * 25)))
|
|
user.visible_message(SPAN_WARNING("[user] smashes through the foamed metal."), SPAN_NOTICE("You smash through the metal foam wall."))
|
|
qdel(src)
|
|
else
|
|
to_chat(user, SPAN_NOTICE("You hit the metal foam but bounce off it."))
|
|
shake_animation()
|
|
|
|
/obj/structure/foamedmetal/attackby(obj/item/attacking_item, mob/user)
|
|
user.setClickCooldown(DEFAULT_ATTACK_COOLDOWN)
|
|
if(istype(attacking_item, /obj/item/grab))
|
|
var/obj/item/grab/G = attacking_item
|
|
if(G.state < GRAB_AGGRESSIVE)
|
|
to_chat(user, SPAN_WARNING("You need a stronger grip to do that!"))
|
|
return TRUE
|
|
G.affecting.forceMove(src.loc)
|
|
visible_message(SPAN_WARNING("[G.assailant] smashes [G.affecting] through the foamed metal wall."))
|
|
G.affecting.take_overall_damage(15)
|
|
qdel(attacking_item)
|
|
qdel(src)
|
|
return TRUE
|
|
|
|
else if(istype(attacking_item, /obj/item/stack/material))
|
|
var/obj/item/stack/material/S = attacking_item
|
|
if(S.get_amount() < 4)
|
|
to_chat(user, SPAN_NOTICE("There isn't enough material here to construct a wall."))
|
|
return TRUE
|
|
|
|
var/singleton/material/M = GET_SINGLETON(S.default_type)
|
|
if(!istype(M))
|
|
return TRUE
|
|
if(M.integrity < 50)
|
|
to_chat(user, SPAN_NOTICE("This material is too soft for use in wall construction."))
|
|
return TRUE
|
|
user.visible_message("<b>[user]</b> starts slotting material into \the [src]...", SPAN_NOTICE("You start slotting material into \the [src], forming it into a wall..."))
|
|
if(!do_after(user, 10 SECONDS) || !S.use(4))
|
|
return TRUE
|
|
var/turf/Tsrc = get_turf(src)
|
|
var/original_type = Tsrc.type
|
|
Tsrc.ChangeTurf(/turf/simulated/wall)
|
|
var/turf/simulated/wall/T = Tsrc
|
|
T.under_turf = original_type
|
|
T.set_material(M)
|
|
T.add_hiddenprint(usr)
|
|
qdel(src)
|
|
return TRUE
|
|
|
|
else if(istype(attacking_item, /obj/item/stack/tile/floor))
|
|
var/turf/T = get_turf(src)
|
|
if(T.type != /turf/space && !isopenturf(T)) // need to do a hard check here because transit turfs are also space turfs
|
|
to_chat(user, SPAN_WARNING("The tile below \the [src] isn't an open space, or space itself!"))
|
|
return TRUE
|
|
var/obj/item/stack/tile/floor/S = attacking_item
|
|
S.use(1)
|
|
T.ChangeTurf(/turf/simulated/floor/airless)
|
|
qdel(src)
|
|
return TRUE
|
|
|
|
user.do_attack_animation(src, used_item = attacking_item)
|
|
if(prob(attacking_item.force * 20 - metal * 25))
|
|
user.visible_message(SPAN_WARNING("[user] smashes through the foamed metal."), SPAN_NOTICE("You smash through the foamed metal with \the [attacking_item]."))
|
|
qdel(src)
|
|
else
|
|
to_chat(user, SPAN_NOTICE("You hit the metal foam to no effect."))
|
|
shake_animation()
|
|
return TRUE
|
|
|
|
/obj/structure/foamedmetal/CanPass(atom/movable/mover, turf/target, height=1.5, air_group = 0)
|
|
if(air_group)
|
|
return 0
|
|
return ..()
|