diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index 8d4f8ecca88..ce781371194 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -315,3 +315,76 @@ /obj/effect/decal/cleanable/ants/update_overlays() . = ..() . += emissive_appearance(icon, "[icon_state]_light", alpha = src.alpha) + +/obj/effect/decal/cleanable/fuel_pool + name = "pool of fuel" + desc = "A pool of flammable fuel. Its probably wise to clean this off before something ignites it..." + icon_state = "fuel_pool" + layer = LOW_OBJ_LAYER + beauty = -50 + clean_type = CLEAN_TYPE_BLOOD + mouse_opacity = MOUSE_OPACITY_OPAQUE + /// Maximum amount of hotspots this pool can create before deleting itself + var/burn_amount = 3 + /// Is this fuel pool currently burning? + var/burning = FALSE + /// Type of hotspot fuel pool spawns upon being ignited + var/hotspot_type = /obj/effect/hotspot + +/obj/effect/decal/cleanable/fuel_pool/Initialize(mapload, burn_stacks) + . = ..() + for(var/obj/effect/decal/cleanable/fuel_pool/pool in get_turf(src)) //Can't use locate because we also belong to that turf + if(pool == src) + continue + pool.burn_amount = max(min(pool.burn_amount + burn_stacks, 10), 1) + return INITIALIZE_HINT_QDEL + + if(burn_stacks) + burn_amount = max(min(burn_stacks, 10), 1) + +/obj/effect/decal/cleanable/fuel_pool/fire_act(exposed_temperature, exposed_volume) + . = ..() + ignite() + +/** + * Ignites the fuel pool. This should be the only way to ignite fuel pools. + */ +/obj/effect/decal/cleanable/fuel_pool/proc/ignite() + if(burning) + return + burning = TRUE + burn_process() + +/** + * Spends 1 burn_amount and spawns a hotspot. If burn_amount is equal to 0, deletes the fuel pool. + * Else, queues another call of this proc upon hotspot getting deleted and ignites other fuel pools around itself after 0.5 seconds. + * THIS SHOULD NOT BE CALLED DIRECTLY. + */ +/obj/effect/decal/cleanable/fuel_pool/proc/burn_process() + SIGNAL_HANDLER + + burn_amount -= 1 + var/obj/effect/hotspot/hotspot = new hotspot_type(get_turf(src)) + addtimer(CALLBACK(src, .proc/ignite_others), 0.5 SECONDS) + + if(!burn_amount) + qdel(src) + return + + RegisterSignal(hotspot, COMSIG_PARENT_QDELETING, .proc/burn_process) + +/** + * Ignites other oil pools around itself. + */ +/obj/effect/decal/cleanable/fuel_pool/proc/ignite_others() + for(var/obj/effect/decal/cleanable/fuel_pool/oil in range(1, get_turf(src))) + oil.ignite() + +/obj/effect/decal/cleanable/fuel_pool/bullet_act(obj/projectile/hit_proj) + . = ..() + ignite() + +/obj/effect/decal/cleanable/fuel_pool/attackby(obj/item/item, mob/user, params) + if(item.ignition_effect(src, user)) + ignite() + return ..() diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index 8e9cbeafd2b..4d5adc1cbbe 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -1158,11 +1158,22 @@ if(methods & (TOUCH|VAPOR)) exposed_mob.adjust_fire_stacks(reac_volume / 10) -/datum/reagent/fuel/on_mob_life(mob/living/carbon/M, delta_time, times_fired) - M.adjustToxLoss(0.5*delta_time, 0) +/datum/reagent/fuel/on_mob_life(mob/living/carbon/victim, delta_time, times_fired) + victim.adjustToxLoss(0.5 * delta_time, 0) ..() return TRUE +/datum/reagent/fuel/expose_turf(turf/exposed_turf, reac_volume) + . = ..() + + if(!istype(exposed_turf) || isspaceturf(exposed_turf)) + return + + if((reac_volume < 5)) + return + + new /obj/effect/decal/cleanable/fuel_pool(exposed_turf, round(reac_volume / 5)) + /datum/reagent/space_cleaner name = "Space Cleaner" description = "A compound used to clean things. Now with 50% more sodium hypochlorite!" diff --git a/code/modules/reagents/reagent_dispenser.dm b/code/modules/reagents/reagent_dispenser.dm index 48d88b4654c..c741f4c3a9f 100644 --- a/code/modules/reagents/reagent_dispenser.dm +++ b/code/modules/reagents/reagent_dispenser.dm @@ -15,6 +15,10 @@ var/can_be_tanked = TRUE ///Is this source self-replenishing? var/refilling = FALSE + ///Can this dispenser be opened using a wrench? + var/openable = FALSE + ///Is this dispenser slowly leaking its reagent? + var/leaking = FALSE /obj/structure/reagent_dispensers/Initialize(mapload) . = ..() @@ -26,6 +30,8 @@ . = ..() if(can_be_tanked) . += span_notice("Use a sheet of iron to convert this into a plumbing-compatible tank.") + if(leaking) + . += span_warning("Its tap is wrenched open!") /obj/structure/reagent_dispensers/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir) . = ..() @@ -36,6 +42,7 @@ /obj/structure/reagent_dispensers/attackby(obj/item/W, mob/user, params) if(W.is_refillable()) return FALSE //so we can refill them via their afterattack. + if(istype(W, /obj/item/stack/sheet/iron) && can_be_tanked) var/obj/item/stack/sheet/iron/metal_stack = W metal_stack.use(1) @@ -47,8 +54,8 @@ new_tank.set_anchored(anchored) qdel(src) return FALSE - else - return ..() + + return ..() /obj/structure/reagent_dispensers/Initialize(mapload) create_reagents(tank_volume, DRAINABLE | AMOUNT_VISIBLE) @@ -68,10 +75,27 @@ else qdel(src) +/obj/structure/reagent_dispensers/wrench_act(mob/living/user, obj/item/tool) + . = ..() + if(!openable) + return FALSE + leaking = !leaking + balloon_alert(user, "[leaking ? "opened" : "closed"] [src]'s tap") + log_game("[key_name(user)] [leaking ? "opened" : "closed"] [src]") + if(leaking && reagents) + reagents.expose(get_turf(src), TOUCH, 10 / max(10, reagents.total_volume)) + return TOOL_ACT_TOOLTYPE_SUCCESS + +/obj/structure/reagent_dispensers/Moved(atom/OldLoc, Dir) + . = ..() + if(leaking && reagents) + reagents.expose(get_turf(src), TOUCH, 10 / max(10, reagents.total_volume)) + /obj/structure/reagent_dispensers/watertank name = "water tank" desc = "A water tank." icon_state = "water" + openable = TRUE /obj/structure/reagent_dispensers/watertank/high name = "high-capacity water tank" @@ -85,12 +109,14 @@ icon_state = "foam" reagent_id = /datum/reagent/firefighting_foam tank_volume = 500 + openable = TRUE /obj/structure/reagent_dispensers/fueltank name = "fuel tank" desc = "A tank full of industrial welding fuel. Do not consume." icon_state = "fuel" reagent_id = /datum/reagent/fuel + openable = TRUE /obj/structure/reagent_dispensers/fueltank/Initialize(mapload) . = ..() @@ -208,6 +234,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/reagent_dispensers/wall/peppertank, 3 desc = "Beer is liquid bread, it's good for you..." icon_state = "beer" reagent_id = /datum/reagent/consumable/ethanol/beer + openable = TRUE /obj/structure/reagent_dispensers/beerkeg/blob_act(obj/structure/blob/B) explosion(src, heavy_impact_range = 3, light_impact_range = 5, flame_range = 10, flash_range = 7) @@ -228,6 +255,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/structure/reagent_dispensers/wall/virusfood, 30 icon_state = "vat" anchored = TRUE reagent_id = /datum/reagent/consumable/cooking_oil + openable = TRUE /obj/structure/reagent_dispensers/servingdish name = "serving dish" diff --git a/icons/effects/effects.dmi b/icons/effects/effects.dmi index 87c4886af17..d126ca45a3f 100644 Binary files a/icons/effects/effects.dmi and b/icons/effects/effects.dmi differ