mirror of
https://github.com/Bubberstation/Bubberstation.git
synced 2026-07-21 04:57:57 +01:00
00ccf0c6b5
# Conflicts: # .github/CODEOWNERS # .github/workflows/compile_changelogs.yml # .github/workflows/stale.yml # SQL/database_changelog.md # _maps/map_files/CatwalkStation/CatwalkStation_2023.dmm # code/__DEFINES/atom_hud.dm # code/__DEFINES/inventory.dm # code/__DEFINES/mobs.dm # code/__DEFINES/species_clothing_paths.dm # code/__DEFINES/subsystems.dm # code/__DEFINES/surgery.dm # code/__HELPERS/global_lists.dm # code/_globalvars/lists/maintenance_loot.dm # code/_globalvars/traits/_traits.dm # code/controllers/subsystem/minor_mapping.dm # code/controllers/subsystem/processing/quirks.dm # code/controllers/subsystem/shuttle.dm # code/datums/components/palette.dm # code/datums/components/surgery_initiator.dm # code/datums/diseases/advance/advance.dm # code/datums/hud.dm # code/datums/mood.dm # code/datums/mutations/chameleon.dm # code/datums/quirks/negative_quirks/nyctophobia.dm # code/datums/status_effects/debuffs/debuffs.dm # code/datums/status_effects/debuffs/drunk.dm # code/datums/status_effects/debuffs/slime/slime_leech.dm # code/datums/weather/weather.dm # code/game/data_huds.dm # code/game/objects/items.dm # code/game/objects/items/devices/scanners/health_analyzer.dm # code/game/objects/items/frog_statue.dm # code/game/objects/items/rcd/RLD.dm # code/game/objects/items/robot/items/hypo.dm # code/game/objects/items/stacks/medical.dm # code/game/objects/items/stacks/wrap.dm # code/game/objects/items/storage/garment.dm # code/game/objects/items/tools/medical/defib.dm # code/game/objects/items/weaponry.dm # code/game/objects/items/weaponry/melee/misc.dm # code/game/objects/structures/crates_lockers/closets/secure/security.dm # code/game/objects/structures/curtains.dm # code/game/objects/structures/dresser.dm # code/game/objects/structures/girders.dm # code/game/objects/structures/maintenance.dm # code/game/objects/structures/mirror.dm # code/modules/admin/greyscale_modify_menu.dm # code/modules/admin/verbs/light_debug.dm # code/modules/antagonists/ashwalker/ashwalker.dm # code/modules/antagonists/heretic/knowledge/starting_lore.dm # code/modules/antagonists/ninja/ninjaDrainAct.dm # code/modules/art/paintings.dm # code/modules/client/preferences.dm # code/modules/client/verbs/ooc.dm # code/modules/clothing/head/wig.dm # code/modules/events/disease_outbreak.dm # code/modules/holodeck/holo_effect.dm # code/modules/jobs/job_types/head_of_security.dm # code/modules/jobs/job_types/security_officer.dm # code/modules/library/skill_learning/generic_skillchips/point.dm # code/modules/mining/lavaland/ash_flora.dm # code/modules/mining/lavaland/mining_loot/megafauna/ash_drake.dm # code/modules/mob/dead/new_player/new_player.dm # code/modules/mob/living/basic/guardian/guardian.dm # code/modules/mob/living/basic/space_fauna/space_dragon/space_dragon.dm # code/modules/mob/living/carbon/carbon.dm # code/modules/mob/living/carbon/human/human.dm # code/modules/mob/living/carbon/human/human_defines.dm # code/modules/mob/living/carbon/life.dm # code/modules/mob/living/living.dm # code/modules/mob/living/living_defines.dm # code/modules/mob/mob.dm # code/modules/mob_spawn/ghost_roles/mining_roles.dm # code/modules/mod/mod_control.dm # code/modules/mod/modules/modules_general.dm # code/modules/modular_computers/computers/item/computer_ui.dm # code/modules/paperwork/paper.dm # code/modules/paperwork/paperbin.dm # code/modules/power/lighting/light.dm # code/modules/projectiles/guns/energy/kinetic_accelerator.dm # code/modules/projectiles/projectile.dm # code/modules/reagents/chemistry/reagents/drinks/alcohol_reagents.dm # code/modules/reagents/chemistry/reagents/food_reagents.dm # code/modules/reagents/chemistry/reagents/other_reagents.dm # code/modules/reagents/chemistry/reagents/pyrotechnic_reagents.dm # code/modules/research/xenobiology/crossbreeding/_clothing.dm # code/modules/research/xenobiology/crossbreeding/prismatic.dm # code/modules/surgery/advanced/brainwashing.dm # code/modules/surgery/advanced/lobotomy.dm # code/modules/surgery/amputation.dm # code/modules/surgery/blood_filter.dm # code/modules/surgery/bodyparts/_bodyparts.dm # code/modules/surgery/brain_surgery.dm # code/modules/surgery/cavity_implant.dm # code/modules/surgery/coronary_bypass.dm # code/modules/surgery/gastrectomy.dm # code/modules/surgery/healing.dm # code/modules/surgery/limb_augmentation.dm # code/modules/surgery/organ_manipulation.dm # code/modules/surgery/revival.dm # code/modules/surgery/sleeper_protocol.dm # code/modules/surgery/surgery_helpers.dm # code/modules/surgery/surgery_step.dm # code/modules/unit_tests/_unit_tests.dm # code/modules/unit_tests/designs.dm # code/modules/unit_tests/icon_state_worn.dm # code/modules/unit_tests/screenshots/screenshot_antag_icons_cultist.png # code/modules/unit_tests/screenshots/screenshot_antag_icons_headrevolutionary.png # code/modules/unit_tests/screenshots/screenshot_antag_icons_provocateur.png # code/modules/unit_tests/screenshots/screenshot_husk_body.png # code/modules/unit_tests/screenshots/screenshot_husk_body_missing_limbs.png # icons/map_icons/clothing/head/_head.dmi # icons/map_icons/clothing/shoes.dmi # icons/map_icons/items/_item.dmi # icons/mob/huds/hud.dmi # icons/mob/inhands/64x64_lefthand.dmi # icons/mob/inhands/64x64_righthand.dmi # icons/obj/machines/computer.dmi # tgui/packages/tgui/interfaces/OperatingComputer.jsx # tgui/packages/tgui/interfaces/PreferencesMenu/CharacterPreferences/MainPage.tsx # tgui/packages/tgui/interfaces/PreferencesMenu/types.ts # tgui/packages/tgui/interfaces/SurgeryInitiator.tsx # tools/icon_cutter/check.py
693 lines
24 KiB
Plaintext
693 lines
24 KiB
Plaintext
#define REAGENT_SPILL_DIVISOR 200
|
|
#define COOLER_JUG_EJECT_TIME (8 SECONDS)
|
|
|
|
/obj/structure/reagent_dispensers
|
|
name = "Dispenser"
|
|
desc = "..."
|
|
icon = 'icons/obj/medical/chemical_tanks.dmi'
|
|
icon_state = "water"
|
|
abstract_type = /obj/structure/reagent_dispensers
|
|
density = TRUE
|
|
anchored = FALSE
|
|
pressure_resistance = 2*ONE_ATMOSPHERE
|
|
max_integrity = 300
|
|
/// In units, how much the dispenser can hold
|
|
var/tank_volume = 1000
|
|
/// The ID of the reagent that the dispenser uses
|
|
var/reagent_id = /datum/reagent/water
|
|
/// Can you turn this into a plumbing tank?
|
|
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
|
|
/// How much reagent to leak
|
|
var/amount_to_leak = 10
|
|
/// An assembly attached to the tank - if this dispenser accepts_rig
|
|
var/obj/item/assembly_holder/rig = null
|
|
/// Whether this dispenser can be rigged with an assembly (and blown up with an igniter)
|
|
var/accepts_rig = FALSE
|
|
//overlay of attached assemblies
|
|
var/mutable_appearance/assembliesoverlay
|
|
/// The person who attached an assembly to this dispenser, for bomb logging purposes
|
|
var/last_rigger = ""
|
|
/// is it climbable? some of our wall-mounted dispensers should not have this
|
|
var/climbable = FALSE
|
|
|
|
// This check is necessary for assemblies to automatically detect that we are compatible
|
|
/obj/structure/reagent_dispensers/IsSpecialAssembly()
|
|
return accepts_rig
|
|
|
|
/obj/structure/reagent_dispensers/Destroy()
|
|
QDEL_NULL(rig)
|
|
return ..()
|
|
|
|
/**
|
|
* rig_boom: Wrapper to log when a reagent_dispenser is set off by an assembly
|
|
*
|
|
*/
|
|
/obj/structure/reagent_dispensers/proc/rig_boom()
|
|
log_bomber(last_rigger, "rigged [src] exploded", src)
|
|
boom()
|
|
|
|
/obj/structure/reagent_dispensers/Initialize(mapload)
|
|
. = ..()
|
|
|
|
if(icon_state == "water" && check_holidays(APRIL_FOOLS))
|
|
icon_state = "water_fools"
|
|
if(climbable)
|
|
AddElement(/datum/element/climbable, climb_time = 4 SECONDS, climb_stun = 4 SECONDS)
|
|
AddElement(/datum/element/elevation, pixel_shift = 14)
|
|
|
|
/obj/structure/reagent_dispensers/examine(mob/user)
|
|
. = ..()
|
|
if(can_be_tanked)
|
|
. += span_notice("Use a sheet of iron to convert this into a plumbing-compatible tank.")
|
|
if(openable)
|
|
if(!leaking)
|
|
. += span_notice("Its tap looks like it could be <b>wrenched</b> open.")
|
|
else
|
|
. += span_warning("Its tap is <b>wrenched</b> open!")
|
|
if(accepts_rig && get_dist(user, src) <= 2)
|
|
if(rig)
|
|
. += span_warning("There is some kind of device <b>rigged</b> to the tank!")
|
|
else
|
|
. += span_notice("It looks like you could <b>rig</b> a device to the tank.")
|
|
|
|
|
|
/obj/structure/reagent_dispensers/take_damage(damage_amount, damage_type = BRUTE, damage_flag = 0, sound_effect = 1, attack_dir)
|
|
. = ..()
|
|
if(. && atom_integrity > 0)
|
|
if(tank_volume && (damage_flag == BULLET || damage_flag == LASER))
|
|
boom()
|
|
|
|
/obj/structure/reagent_dispensers/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers)
|
|
if(attacking_item.is_refillable())
|
|
return FALSE //so we can refill them via their afterattack.
|
|
if(istype(attacking_item, /obj/item/assembly_holder) && accepts_rig)
|
|
if(rig)
|
|
balloon_alert(user, "another device is in the way!")
|
|
return ..()
|
|
var/obj/item/assembly_holder/holder = attacking_item
|
|
if(!(locate(/obj/item/assembly/igniter) in holder.assemblies))
|
|
return ..()
|
|
|
|
user.balloon_alert_to_viewers("attaching rig...")
|
|
add_fingerprint(user)
|
|
if(!do_after(user, 2 SECONDS, target = src) || !user.transferItemToLoc(holder, src))
|
|
return
|
|
rig = holder
|
|
holder.master = src
|
|
holder.on_attach()
|
|
assembliesoverlay = holder
|
|
assembliesoverlay.pixel_w += 6
|
|
assembliesoverlay.pixel_z += 1
|
|
add_overlay(assembliesoverlay)
|
|
RegisterSignal(src, COMSIG_IGNITER_ACTIVATE, PROC_REF(rig_boom))
|
|
log_bomber(user, "attached [holder.name] to ", src)
|
|
last_rigger = user
|
|
user.balloon_alert_to_viewers("attached rig")
|
|
return
|
|
|
|
if(istype(attacking_item, /obj/item/stack/sheet/iron) && can_be_tanked)
|
|
var/obj/item/stack/sheet/iron/metal_stack = attacking_item
|
|
metal_stack.use(1)
|
|
var/obj/structure/reagent_dispensers/plumbed/storage/new_tank = new /obj/structure/reagent_dispensers/plumbed/storage(drop_location())
|
|
new_tank.reagents.maximum_volume = reagents.maximum_volume
|
|
reagents.trans_to(new_tank, reagents.total_volume)
|
|
new_tank.name = "stationary [name]"
|
|
new_tank.update_appearance(UPDATE_OVERLAYS)
|
|
new_tank.set_anchored(anchored)
|
|
qdel(src)
|
|
return FALSE
|
|
|
|
return ..()
|
|
|
|
/obj/structure/reagent_dispensers/Exited(atom/movable/gone, direction)
|
|
. = ..()
|
|
if(gone == rig)
|
|
rig = null
|
|
|
|
/obj/structure/reagent_dispensers/attack_hand(mob/user, list/modifiers)
|
|
. = ..()
|
|
if(. || !rig)
|
|
return
|
|
// mousetrap rigs only make sense if you can set them off, can't step on them
|
|
// If you see a mousetrap-rigged fuel tank, just leave it alone
|
|
rig.on_found()
|
|
if(QDELETED(src))
|
|
return
|
|
user.balloon_alert_to_viewers("detaching rig...")
|
|
if(!do_after(user, 2 SECONDS, target = src))
|
|
return
|
|
user.balloon_alert_to_viewers("detached rig")
|
|
user.log_message("detached [rig] from [src].", LOG_GAME)
|
|
if(!user.put_in_hands(rig))
|
|
rig.forceMove(get_turf(user))
|
|
rig = null
|
|
last_rigger = null
|
|
cut_overlays(assembliesoverlay)
|
|
UnregisterSignal(src, COMSIG_IGNITER_ACTIVATE)
|
|
|
|
/obj/structure/reagent_dispensers/Initialize(mapload)
|
|
create_reagents(tank_volume, DRAINABLE | AMOUNT_VISIBLE)
|
|
if(reagent_id)
|
|
reagents.add_reagent(reagent_id, tank_volume)
|
|
. = ..()
|
|
|
|
/**
|
|
* boom: Detonate a reagent dispenser.
|
|
*
|
|
* This is most dangerous for fuel tanks, which will explosion().
|
|
* Other dispensers will scatter their contents within range.
|
|
*/
|
|
/obj/structure/reagent_dispensers/proc/boom(damage_type = BRUTE, guaranteed_violent = FALSE) //SKYRAT EDIT CHANGE
|
|
if(QDELETED(src))
|
|
return // little bit of sanity sauce before we wreck ourselves somehow
|
|
var/datum/reagent/fuel/volatiles = reagents.has_reagent(/datum/reagent/fuel)
|
|
var/fuel_amt = 0
|
|
if(istype(volatiles) && volatiles.volume >= 25)
|
|
fuel_amt = volatiles.volume
|
|
reagents.del_reagent(/datum/reagent/fuel) // not actually used for the explosion
|
|
if(reagents.total_volume)
|
|
if(!fuel_amt)
|
|
visible_message(span_danger("\The [src] ruptures!"))
|
|
// Leave it up to future terrorists to figure out the best way to mix reagents with fuel for a useful boom here
|
|
chem_splash(loc, null, 2 + floor((reagents.total_volume + fuel_amt) / 1000), list(reagents), extra_heat=(fuel_amt / 50),adminlog=(fuel_amt<25))
|
|
|
|
if(fuel_amt) // with that done, actually explode
|
|
visible_message(span_danger("\The [src] explodes!"))
|
|
// old code for reference:
|
|
// standard fuel tank = 1000 units = heavy_impact_range = 1, light_impact_range = 5, flame_range = 5
|
|
// big fuel tank = 5000 units = devastation_range = 1, heavy_impact_range = 2, light_impact_range = 7, flame_range = 12
|
|
// It did not account for how much fuel was actually in the tank at all, just the size of the tank.
|
|
// I encourage others to better scale these numbers in the future.
|
|
// As it stands this is a minor nerf in exchange for an easy bombing technique working that has been broken for a while.
|
|
switch(fuel_amt)
|
|
if(25 to 150)
|
|
explosion(src, light_impact_range = 1, flame_range = 2)
|
|
if(150 to 300)
|
|
explosion(src, light_impact_range = 2, flame_range = 3)
|
|
if(300 to 750)
|
|
explosion(src, heavy_impact_range = 1, light_impact_range = 3, flame_range = 5)
|
|
if(750 to 1500)
|
|
explosion(src, heavy_impact_range = 1, light_impact_range = 4, flame_range = 6)
|
|
if(1500 to INFINITY)
|
|
explosion(src, devastation_range = 1, heavy_impact_range = 2, light_impact_range = 6, flame_range = 8)
|
|
qdel(src)
|
|
|
|
/obj/structure/reagent_dispensers/atom_deconstruct(disassembled = TRUE)
|
|
if(!disassembled)
|
|
boom()
|
|
|
|
/obj/structure/reagent_dispensers/proc/tank_leak()
|
|
if(leaking && reagents && reagents.total_volume >= amount_to_leak)
|
|
reagents.expose(get_turf(src), TOUCH, amount_to_leak / max(amount_to_leak, reagents.total_volume))
|
|
reagents.remove_reagent(reagent_id, amount_to_leak)
|
|
playsound(src, 'sound/effects/glug.ogg', 33, TRUE, SILENCED_SOUND_EXTRARANGE)
|
|
return TRUE
|
|
return FALSE
|
|
|
|
/obj/structure/reagent_dispensers/proc/knock_down()
|
|
var/range = reagents.total_volume / REAGENT_SPILL_DIVISOR
|
|
do_chem_smoke(round(range), drop_location(), drop_location(), carry = reagents, silent = FALSE, log = TRUE)
|
|
reagents.clear_reagents()
|
|
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"] tap")
|
|
user.log_message("[leaking ? "opened" : "closed"] [src].", LOG_GAME)
|
|
tank_leak()
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
/obj/structure/reagent_dispensers/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE)
|
|
. = ..()
|
|
tank_leak()
|
|
|
|
/obj/structure/reagent_dispensers/watertank
|
|
name = "water tank"
|
|
desc = "A water tank."
|
|
icon_state = "water"
|
|
openable = TRUE
|
|
climbable = TRUE
|
|
|
|
/obj/structure/reagent_dispensers/watertank/high
|
|
name = "high-capacity water tank"
|
|
desc = "A highly pressurized water tank made to hold gargantuan amounts of water."
|
|
icon_state = "water_high" //I was gonna clean my room...
|
|
tank_volume = 3000
|
|
|
|
/obj/structure/reagent_dispensers/foamtank//SKYRAT EDIT - ICON OVERRIDDEN BY AESTHETICS - SEE MODULE
|
|
name = "firefighting foam tank"
|
|
desc = "A tank full of firefighting foam."
|
|
icon_state = "foam"
|
|
reagent_id = /datum/reagent/firefighting_foam
|
|
tank_volume = 500
|
|
openable = TRUE
|
|
climbable = TRUE
|
|
|
|
/obj/structure/reagent_dispensers/fueltank//SKYRAT EDIT - ICON OVERRIDDEN BY AESTHETICS - SEE MODULE
|
|
name = "fuel tank"
|
|
desc = "A tank full of industrial welding fuel. Do not consume."
|
|
icon_state = "fuel"
|
|
reagent_id = /datum/reagent/fuel
|
|
openable = TRUE
|
|
accepts_rig = TRUE
|
|
climbable = TRUE
|
|
|
|
/obj/structure/reagent_dispensers/fueltank/Initialize(mapload)
|
|
. = ..()
|
|
|
|
if(check_holidays(APRIL_FOOLS))
|
|
icon_state = "fuel_fools"
|
|
|
|
/obj/structure/reagent_dispensers/fueltank/boom(damage_type = BRUTE, guaranteed_violent = FALSE) //SKYRAT EDIT CHANGE
|
|
if(damage_type == BURN || guaranteed_violent)
|
|
explosion(src, heavy_impact_range = 1, light_impact_range = 5, flame_range = 5)
|
|
qdel(src)
|
|
else
|
|
. = ..()
|
|
//SKYRAT EDIT END
|
|
|
|
/obj/structure/reagent_dispensers/fueltank/blob_act(obj/structure/blob/B)
|
|
boom(guaranteed_violent = TRUE) //SKYRAT EDIT CHANGE
|
|
|
|
/obj/structure/reagent_dispensers/fueltank/ex_act()
|
|
boom(guaranteed_violent = TRUE) //SKYRAT EDIT CHANGE
|
|
return TRUE
|
|
|
|
/obj/structure/reagent_dispensers/fueltank/fire_act(exposed_temperature, exposed_volume)
|
|
boom(guaranteed_violent = TRUE) //SKYRAT EDIT CHANGE
|
|
|
|
/obj/structure/reagent_dispensers/fueltank/zap_act(power, zap_flags)
|
|
. = ..() //extend the zap
|
|
if(ZAP_OBJ_DAMAGE & zap_flags)
|
|
boom(guaranteed_violent = TRUE) //SKYRAT EDIT CHANGE
|
|
|
|
/obj/structure/reagent_dispensers/fueltank/bullet_act(obj/projectile/hitting_projectile)
|
|
if(hitting_projectile.damage > 0 && ((hitting_projectile.damage_type == BURN) || (hitting_projectile.damage_type == BRUTE)))
|
|
log_bomber(hitting_projectile.firer, "detonated a", src, "via projectile")
|
|
boom(guaranteed_violent = TRUE) // SKYRAT EDIT CHANGE
|
|
return hitting_projectile.on_hit(src, 0)
|
|
|
|
// we override parent like this because otherwise we won't actually properly log the fact that a projectile caused this welding tank to explode.
|
|
// if this sucks, feel free to change it, but make sure the damn thing will log. thanks.
|
|
return ..()
|
|
|
|
/obj/structure/reagent_dispensers/fueltank/attackby(obj/item/attacking_item, mob/user, list/modifiers, list/attack_modifiers)
|
|
if(attacking_item.tool_behaviour != TOOL_WELDER)
|
|
return ..()
|
|
|
|
var/obj/item/weldingtool/refilling_welder = attacking_item
|
|
if(istype(refilling_welder) && !refilling_welder.welding)
|
|
if(refilling_welder.reagents.has_reagent(/datum/reagent/fuel, refilling_welder.max_fuel))
|
|
to_chat(user, span_warning("Your [refilling_welder.name] is already full!"))
|
|
return
|
|
reagents.trans_to(refilling_welder, refilling_welder.max_fuel, transferred_by = user)
|
|
user.visible_message(span_notice("[user] refills [user.p_their()] [refilling_welder.name]."), span_notice("You refill [refilling_welder]."))
|
|
playsound(src, 'sound/effects/refill.ogg', 50, TRUE)
|
|
refilling_welder.update_appearance()
|
|
return
|
|
|
|
var/obj/item/lighter/refilling_lighter = attacking_item
|
|
if(istype(refilling_lighter) && !refilling_lighter.lit)
|
|
if(refilling_lighter.reagents.has_reagent(/datum/reagent/fuel, refilling_lighter.maximum_fuel))
|
|
to_chat(user, span_warning("Your [refilling_lighter.name] is already full!"))
|
|
return
|
|
reagents.trans_to(refilling_lighter, refilling_lighter.maximum_fuel, transferred_by = user)
|
|
user.visible_message(span_notice("[user] refills [user.p_their()] [refilling_lighter.name]."), span_notice("You refill [refilling_lighter]."))
|
|
playsound(src, 'sound/effects/refill.ogg', 25, TRUE)
|
|
return
|
|
|
|
if(!reagents.has_reagent(/datum/reagent/fuel))
|
|
to_chat(user, span_warning("[src] is out of fuel!"))
|
|
return
|
|
user.visible_message(
|
|
span_danger("[user] catastrophically fails at refilling [user.p_their()] [attacking_item.name]!"),
|
|
span_userdanger("That was stupid of you."))
|
|
log_bomber(user, "detonated a", src, "via [attacking_item.name]")
|
|
boom()
|
|
|
|
/obj/structure/reagent_dispensers/fueltank/large
|
|
name = "high capacity fuel tank"
|
|
desc = "A tank full of a high quantity of welding fuel. Keep away from open flames."
|
|
icon_state = "fuel_high"
|
|
tank_volume = 5000
|
|
|
|
/obj/structure/reagent_dispensers/fueltank/large/boom(damage_type = BRUTE, guaranteed_violent = FALSE) //SKYRAT EDIT CHANGE
|
|
if(damage_type == BURN || guaranteed_violent)
|
|
explosion(src, devastation_range = 1, heavy_impact_range = 2, light_impact_range = 7, flame_range = 12)
|
|
qdel(src)
|
|
else
|
|
. = ..()
|
|
//SKYRAT EDIT END
|
|
|
|
/// Wall mounted dispeners, like pepper spray or virus food. Not a normal tank, and shouldn't be able to be turned into a plumbed stationary one.
|
|
/obj/structure/reagent_dispensers/wall
|
|
anchored = TRUE
|
|
density = FALSE
|
|
can_be_tanked = FALSE
|
|
|
|
/obj/structure/reagent_dispensers/wall/peppertank
|
|
name = "pepper spray refiller"
|
|
desc = "Contains condensed capsaicin for use in law \"enforcement.\""
|
|
icon_state = "pepper"
|
|
reagent_id = /datum/reagent/consumable/condensedcapsaicin
|
|
|
|
MAPPING_DIRECTIONAL_HELPERS(/obj/structure/reagent_dispensers/wall/peppertank, 30)
|
|
|
|
/obj/structure/reagent_dispensers/wall/peppertank/Initialize(mapload)
|
|
. = ..()
|
|
if(prob(1))
|
|
desc = "IT'S PEPPER TIME, BITCH!"
|
|
if(mapload)
|
|
find_and_mount_on_atom()
|
|
|
|
/obj/structure/reagent_dispensers/water_cooler
|
|
name = "water cooler"
|
|
desc = "A machine that cools and dispenses liquids to drink. The 'hot' handle doesn't seem to do anything."
|
|
icon_state = "water_cooler"
|
|
anchored = TRUE
|
|
tank_volume = 200
|
|
can_be_tanked = FALSE
|
|
max_integrity = 150
|
|
custom_materials = list(/datum/material/plastic = SHEET_MATERIAL_AMOUNT * 25)
|
|
///Paper cups left from the cooler.
|
|
var/paper_cups = 25
|
|
///Reference to our jug.
|
|
var/obj/item/reagent_containers/cooler_jug/our_jug
|
|
///Have we been tipped?
|
|
var/tipped = FALSE
|
|
|
|
/obj/structure/reagent_dispensers/water_cooler/Initialize(mapload)
|
|
. = ..()
|
|
if(prob(2) && mapload)
|
|
reagents.convert_reagent(/datum/reagent/water, /datum/reagent/consumable/fruit_punch)
|
|
create_jug()
|
|
refresh_appearance()
|
|
|
|
/obj/structure/reagent_dispensers/water_cooler/Destroy()
|
|
. = ..()
|
|
our_jug = null
|
|
|
|
/obj/structure/reagent_dispensers/water_cooler/examine(mob/user)
|
|
. = ..()
|
|
if (paper_cups > 1)
|
|
. += "There are [paper_cups] paper cups left."
|
|
else if (paper_cups == 1)
|
|
. += "There is one paper cup left."
|
|
else
|
|
. += "There are no paper cups left."
|
|
|
|
/obj/structure/reagent_dispensers/water_cooler/attack_hand(mob/living/user, list/modifiers)
|
|
. = ..()
|
|
if(.)
|
|
return
|
|
|
|
|
|
if(tipped)
|
|
balloon_alert(user, "un-tipping...")
|
|
if(!do_after(user, 5 SECONDS, src))
|
|
return
|
|
tipped = FALSE
|
|
refresh_appearance()
|
|
return
|
|
|
|
|
|
if(user.combat_mode && our_jug)
|
|
balloon_alert(user, "removing jug...")
|
|
if(!do_after(user, COOLER_JUG_EJECT_TIME, src))
|
|
return
|
|
eject_jug(user)
|
|
return
|
|
|
|
if(!paper_cups)
|
|
to_chat(user, span_warning("There aren't any cups left!"))
|
|
return
|
|
user.visible_message(span_notice("[user] takes a cup from [src]."), span_notice("You take a paper cup from [src]."))
|
|
var/obj/item/reagent_containers/cup/glass/sillycup/new_cup = new(get_turf(src))
|
|
user.put_in_hands(new_cup)
|
|
paper_cups--
|
|
|
|
/obj/structure/reagent_dispensers/water_cooler/update_overlays()
|
|
. = ..()
|
|
if(!reagents)
|
|
return
|
|
|
|
if(!reagents.total_volume)
|
|
return
|
|
|
|
var/mixcolor
|
|
var/vol_counter = 0
|
|
var/vol_temp
|
|
|
|
for(var/datum/reagent/stored_reagent as anything in reagents.reagent_list)
|
|
vol_temp = stored_reagent.volume
|
|
vol_counter += vol_temp
|
|
|
|
var/chosen_color = stored_reagent.color
|
|
if(istype(stored_reagent, /datum/reagent/water))
|
|
if(!mixcolor)
|
|
mixcolor = "#2694D6" //Override the water to be a nice blue
|
|
continue
|
|
else
|
|
chosen_color = "#2694D6"
|
|
else
|
|
if(!mixcolor)
|
|
mixcolor = stored_reagent.color
|
|
continue
|
|
else
|
|
chosen_color = stored_reagent.color
|
|
|
|
if (length(mixcolor) >= length(chosen_color))
|
|
mixcolor = BlendRGB(mixcolor, chosen_color, vol_temp/vol_counter)
|
|
else
|
|
mixcolor = BlendRGB(chosen_color, mixcolor, vol_temp/vol_counter)
|
|
|
|
if(mixcolor)
|
|
var/overlay_tag
|
|
if(vol_counter > 100)
|
|
overlay_tag = "100"
|
|
else
|
|
overlay_tag = "50" //Can't be 0, because there'd be no mixcolor
|
|
var/mutable_appearance/tank_overlay = mutable_appearance('icons/obj/medical/chemical_tanks.dmi', "water_cooler_overlay[overlay_tag]")
|
|
tank_overlay.color = mixcolor
|
|
. += tank_overlay
|
|
|
|
/obj/structure/reagent_dispensers/water_cooler/wrench_act(mob/living/user, obj/item/tool)
|
|
if(user.combat_mode)
|
|
return NONE
|
|
|
|
. = ITEM_INTERACT_BLOCKING
|
|
if(default_unfasten_wrench(user, tool, time = 6 SECONDS) == SUCCESSFUL_UNFASTEN)
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
/obj/structure/reagent_dispensers/water_cooler/attack_hand_secondary(mob/user, modifiers)
|
|
if(tipped)
|
|
balloon_alert(user, "it's already tipped!")
|
|
return
|
|
|
|
if(anchored)
|
|
balloon_alert(user, "it's anchored!")
|
|
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
|
|
|
if(!do_after(user, 1.5 SECONDS, src))
|
|
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
|
INVOKE_ASYNC(src, PROC_REF(boom), user)
|
|
return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN
|
|
|
|
/obj/structure/reagent_dispensers/water_cooler/item_interaction(mob/living/user, obj/item/tool, list/modifiers)
|
|
if(!istype(tool, /obj/item/reagent_containers/cooler_jug))
|
|
return
|
|
|
|
if(tipped)
|
|
balloon_alert(user, "it's tipped!")
|
|
return
|
|
|
|
var/obj/item/reagent_containers/cooler_jug/new_jug = tool
|
|
balloon_alert(user, "replacing jug...")
|
|
if(!do_after(user, COOLER_JUG_EJECT_TIME, src))
|
|
return
|
|
|
|
if(!user.transferItemToLoc(new_jug, src))
|
|
return ITEM_INTERACT_BLOCKING
|
|
|
|
eject_jug(user, our_jug)
|
|
our_jug = new_jug
|
|
our_jug.reagents.trans_to(reagents, tank_volume)
|
|
balloon_alert(user, "attached")
|
|
user.log_message("attached a [new_jug] to [src] at [AREACOORD(src)] containing ([new_jug.reagents.get_reagent_log_string()])", LOG_ATTACK)
|
|
add_fingerprint(user)
|
|
refresh_appearance()
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
/obj/structure/reagent_dispensers/water_cooler/boom()
|
|
if(QDELETED(src))
|
|
return
|
|
if(reagents.total_volume)
|
|
visible_message(span_danger("\The [src] flips on it's side and spills everywhere!"))
|
|
chem_splash(get_turf(src), null, 2 + floor((reagents.total_volume) / 1000), list(reagents))
|
|
eject_jug(throw_away = TRUE)
|
|
playsound(src, 'sound/effects/glass/glassbash.ogg', 100)
|
|
tip_over()
|
|
|
|
/obj/structure/reagent_dispensers/water_cooler/proc/refresh_appearance()
|
|
if(tipped)
|
|
icon_state = "water_cooler_disgraced"
|
|
else
|
|
if(!our_jug)
|
|
icon_state = "water_cooler_forlorn"
|
|
else
|
|
icon_state = "water_cooler"
|
|
|
|
update_overlays()
|
|
update_appearance()
|
|
|
|
///Creates an empty jug inside of the cooler. Doesn't need to be filled bc it absorbs the cooler's reagent on eject.
|
|
/obj/structure/reagent_dispensers/water_cooler/proc/create_jug()
|
|
our_jug = new /obj/item/reagent_containers/cooler_jug(src)
|
|
|
|
///Eject the jug in a variety of ways. If there is a user, the jug goes into their hands. throw_away is passed on tip, to empty and throw the jug away. We delete the reagents since we create a splash before this is called.
|
|
/obj/structure/reagent_dispensers/water_cooler/proc/eject_jug(mob/living/user, throw_away = FALSE)
|
|
if(!our_jug)
|
|
return
|
|
|
|
if(user)
|
|
user.put_in_hands(our_jug)
|
|
else
|
|
our_jug.forceMove(drop_location())
|
|
|
|
if(throw_away)
|
|
var/turf/turf_to_throw_at = get_ranged_target_turf(src, pick(GLOB.alldirs), 2)
|
|
our_jug.throw_at(turf_to_throw_at, 2, 3)
|
|
reagents.remove_all(tank_volume) //Gets spilled on floor during boom()
|
|
else
|
|
reagents.trans_to(our_jug.reagents, tank_volume)
|
|
|
|
our_jug = null
|
|
refresh_appearance()
|
|
|
|
///Handles the visual stuff related to the cooler itself tipping.
|
|
/obj/structure/reagent_dispensers/water_cooler/proc/tip_over()
|
|
tipped = TRUE
|
|
refresh_appearance()
|
|
|
|
///Pre-tipped version for mapping.
|
|
/obj/structure/reagent_dispensers/water_cooler/fallen
|
|
tipped = TRUE
|
|
reagent_id = null
|
|
anchored = FALSE
|
|
|
|
/obj/structure/reagent_dispensers/water_cooler/fallen/Initialize(mapload)
|
|
. = ..()
|
|
tip_over()
|
|
|
|
/obj/structure/reagent_dispensers/water_cooler/fallen/create_jug()
|
|
return
|
|
|
|
/obj/structure/reagent_dispensers/water_cooler/jugless
|
|
reagent_id = null
|
|
anchored = FALSE
|
|
|
|
/obj/structure/reagent_dispensers/water_cooler/jugless/create_jug()
|
|
return
|
|
|
|
///Punch cooler. Starts full of healing juice. In case anyone wants to map one somewhere as a healing station.
|
|
/obj/structure/reagent_dispensers/water_cooler/punch_cooler
|
|
name = "punch cooler"
|
|
desc = "A machine that dispenses fruit punch to drink. This juice is unbearably sweet, and can only be safely consumed in the presence of a liquid cooler. Engage with caution."
|
|
reagent_id = /datum/reagent/consumable/fruit_punch
|
|
|
|
/obj/structure/reagent_dispensers/beerkeg
|
|
name = "beer keg"
|
|
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)
|
|
if(!QDELETED(src))
|
|
qdel(src)
|
|
|
|
/obj/structure/reagent_dispensers/wall/virusfood
|
|
name = "virus food dispenser"
|
|
desc = "A dispenser of low-potency virus mutagenic."
|
|
icon_state = "virus_food"
|
|
reagent_id = /datum/reagent/consumable/virus_food
|
|
|
|
MAPPING_DIRECTIONAL_HELPERS(/obj/structure/reagent_dispensers/wall/virusfood, 30)
|
|
|
|
/obj/structure/reagent_dispensers/wall/virusfood/Initialize(mapload)
|
|
. = ..()
|
|
if(mapload)
|
|
find_and_mount_on_atom()
|
|
|
|
/obj/structure/reagent_dispensers/cooking_oil
|
|
name = "vat of cooking oil"
|
|
desc = "A huge metal vat with a tap on the front. Filled with cooking oil for use in frying food."
|
|
icon_state = "vat"
|
|
reagent_id = /datum/reagent/consumable/nutriment/fat/oil
|
|
openable = TRUE
|
|
|
|
/obj/structure/reagent_dispensers/servingdish
|
|
name = "serving dish"
|
|
desc = "A dish full of food slop for your bowl."
|
|
icon = 'icons/obj/service/kitchen.dmi'
|
|
icon_state = "serving"
|
|
reagent_id = /datum/reagent/consumable/nutraslop
|
|
|
|
/obj/structure/reagent_dispensers/plumbed
|
|
name = "stationary water tank"
|
|
anchored = TRUE
|
|
icon_state = "water_stationary" //SKYRAT EDIT - ICON OVERRIDDEN BY AESTHETICS - SEE MODULE
|
|
desc = "A stationary, plumbed, water tank."
|
|
can_be_tanked = FALSE
|
|
|
|
/obj/structure/reagent_dispensers/plumbed/Initialize(mapload)
|
|
. = ..()
|
|
AddComponent(/datum/component/plumbing/simple_supply)
|
|
|
|
/obj/structure/reagent_dispensers/plumbed/wrench_act(mob/living/user, obj/item/tool)
|
|
. = ..()
|
|
default_unfasten_wrench(user, tool)
|
|
return ITEM_INTERACT_SUCCESS
|
|
|
|
/obj/structure/reagent_dispensers/plumbed/storage
|
|
name = "stationary storage tank"
|
|
icon_state = "tank_stationary"
|
|
reagent_id = null //start empty
|
|
|
|
/obj/structure/reagent_dispensers/plumbed/storage/Initialize(mapload)
|
|
. = ..()
|
|
AddElement(/datum/element/simple_rotation)
|
|
|
|
|
|
/obj/structure/reagent_dispensers/plumbed/storage/update_overlays()
|
|
. = ..()
|
|
if(!reagents)
|
|
return
|
|
|
|
if(!reagents.total_volume)
|
|
return
|
|
|
|
var/mutable_appearance/tank_color = mutable_appearance('icons/obj/medical/chemical_tanks.dmi', "tank_chem_overlay")
|
|
tank_color.color = mix_color_from_reagents(reagents.reagent_list)
|
|
. += tank_color
|
|
|
|
/obj/structure/reagent_dispensers/plumbed/fuel
|
|
name = "stationary fuel tank"
|
|
icon_state = "fuel_stationary"
|
|
desc = "A stationary, plumbed, fuel tank."
|
|
reagent_id = /datum/reagent/fuel
|
|
accepts_rig = TRUE
|
|
|
|
#undef REAGENT_SPILL_DIVISOR
|
|
#undef COOLER_JUG_EJECT_TIME
|