Move all the non-weapons out of code/game/objects/weapons (#29820)

This commit is contained in:
Charlie Nolan
2025-08-06 01:37:56 +00:00
committed by GitHub
parent 379a368ccd
commit 8ffefd8777
64 changed files with 63 additions and 63 deletions
+243
View File
@@ -0,0 +1,243 @@
/obj/item/tank/jetpack
name = "Jetpack (Empty)"
desc = "A tank of compressed gas for use as propulsion in zero-gravity areas. Use with caution."
icon_state = "jetpack"
w_class = WEIGHT_CLASS_BULKY
item_state = "jetpack"
lefthand_file = 'icons/mob/inhands/jetpack_lefthand.dmi'
righthand_file = 'icons/mob/inhands/jetpack_righthand.dmi'
distribute_pressure = ONE_ATMOSPHERE * O2STANDARD
actions_types = list(/datum/action/item_action/set_internals, /datum/action/item_action/toggle_jetpack, /datum/action/item_action/jetpack_stabilization)
var/gas_type = "oxygen"
var/on = FALSE
var/volume_rate = 500 //Needed for borg jetpack transfer
var/stabilize = FALSE
var/thrust_callback
/obj/item/tank/jetpack/Initialize(mapload)
. = ..()
thrust_callback = CALLBACK(src, PROC_REF(allow_thrust), 0.01)
configure_jetpack(stabilize)
/obj/item/tank/jetpack/Destroy()
thrust_callback = null
return ..()
/**
* configures/re-configures the jetpack component
*
* Arguments
* stabilize - Should this jetpack be stabalized
*/
/obj/item/tank/jetpack/proc/configure_jetpack(stabilize)
src.stabilize = stabilize
AddComponent( \
/datum/component/jetpack, \
src.stabilize, \
COMSIG_JETPACK_ACTIVATED, \
COMSIG_JETPACK_DEACTIVATED, \
JETPACK_ACTIVATION_FAILED, \
thrust_callback, \
/datum/effect_system/trail_follow/ion \
)
/obj/item/tank/jetpack/populate_gas()
if(gas_type)
switch(gas_type)
if("oxygen")
air_contents.set_oxygen(((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)))
if("carbon dioxide")
air_contents.set_carbon_dioxide(((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)))
/obj/item/tank/jetpack/on_mob_move(direction, mob/user)
if(on)
var/turf/T = get_step(src, REVERSE_DIR(direction))
if(!has_gravity(T))
new /obj/effect/particle_effect/ion_trails(T, direction)
/obj/item/tank/jetpack/ui_action_click(mob/user, actiontype)
if(actiontype == /datum/action/item_action/toggle_jetpack)
cycle(user)
else if(actiontype == /datum/action/item_action/jetpack_stabilization)
toggle_stabilization(user)
else
toggle_internals(user)
/obj/item/tank/jetpack/proc/toggle_stabilization(mob/user)
if(on)
configure_jetpack(!stabilize)
to_chat(user, "<span class='notice'>You turn [src]'s stabilization [stabilize ? "on" : "off"].</span>")
/obj/item/tank/jetpack/proc/cycle(mob/user)
if(user.incapacitated())
return
if(!on)
turn_on(user)
to_chat(user, "<span class='notice'>You turn the jetpack on.</span>")
else
turn_off(user)
to_chat(user, "<span class='notice'>You turn the jetpack off.</span>")
update_action_buttons()
/obj/item/tank/jetpack/proc/turn_on(mob/user)
if(SEND_SIGNAL(src, COMSIG_JETPACK_ACTIVATED, user) & JETPACK_ACTIVATION_FAILED)
return FALSE
on = TRUE
icon_state = "[initial(icon_state)]-on"
/obj/item/tank/jetpack/proc/turn_off(mob/user)
SEND_SIGNAL(src, COMSIG_JETPACK_DEACTIVATED, user)
on = FALSE
icon_state = initial(icon_state)
/obj/item/tank/jetpack/dropped(mob/user, silent)
. = ..()
if(on)
turn_off(user)
/obj/item/tank/jetpack/proc/allow_thrust(num)
if(!ismob(loc))
return FALSE
var/mob/user = loc
if((num < 0.005 || air_contents.total_moles() < num))
turn_off(user)
return FALSE
var/datum/gas_mixture/removed = air_contents.remove(num)
if(removed.total_moles() < 0.005)
turn_off(user)
return FALSE
var/turf/T = get_turf(user)
T.blind_release_air(removed)
return TRUE
/obj/item/tank/jetpack/improvised
name = "improvised jetpack"
desc = "A jetpack made from two air tanks, a fire extinguisher and some atmospherics equipment. It doesn't look like it can hold much."
icon_state = "jetpack-improvised"
item_state = "jetpack-improvised"
volume = 20 //normal jetpacks have 70 volume
gas_type = null //it starts empty
/obj/item/tank/jetpack/improvised/allow_thrust(num, mob/living/user)
if(rand(0, 250) == 0)
to_chat(user, "<span class='notice'>You feel your jetpack's engines cut out.</span>")
turn_off(user)
return
return ..()
/obj/item/tank/jetpack/void
name = "Void Jetpack (Oxygen)"
desc = "It works well in a void."
icon_state = "jetpack-void"
item_state = "jetpack-void"
/obj/item/tank/jetpack/void/grey
icon_state = "jetpack-void-grey"
item_state = "jetpack-void-grey"
/obj/item/tank/jetpack/void/gold
name = "Retro Jetpack (Oxygen)"
icon_state = "jetpack-void-gold"
item_state = "jetpack-void-gold"
/obj/item/tank/jetpack/oxygen
name = "Jetpack (Oxygen)"
desc = "A tank of compressed oxygen for use as propulsion in zero-gravity areas. Use with caution."
/obj/item/tank/jetpack/oxygen/harness
name = "jet harness (oxygen)"
desc = "A lightweight tactical harness, used by those who don't want to be weighed down by traditional jetpacks."
icon_state = "jetpack-mini"
item_state = "jetpack-mini"
volume = 40
throw_range = 7
w_class = WEIGHT_CLASS_NORMAL
/obj/item/tank/jetpack/oxygen/captain
name = "Captain's jetpack"
desc = "A compact, lightweight jetpack containing a high amount of compressed oxygen."
icon_state = "jetpack-captain"
item_state = "jetpack-captain"
volume = 90
w_class = WEIGHT_CLASS_NORMAL
/obj/item/tank/jetpack/oxygen/security
name = "security jetpack (oxygen)"
desc = "A tank of compressed oxygen for use as propulsion in zero-gravity areas by security forces."
icon_state = "jetpack-sec"
item_state = "jetpack-sec"
/obj/item/tank/jetpack/carbondioxide
name = "Jetpack (Carbon Dioxide)"
desc = "A tank of compressed carbon dioxide for use as propulsion in zero-gravity areas. Painted black to indicate that it should not be used as a source for internals."
distribute_pressure = 0
icon_state = "jetpack-black"
item_state = "jetpack-black"
gas_type = "carbon dioxide"
/obj/item/tank/jetpack/suit
name = "hardsuit jetpack upgrade"
desc = "A modular, compact set of thrusters designed to integrate with a hardsuit. It is fueled by a tank inserted into the suit's storage compartment."
icon_state = "jetpack-mining"
item_state = "jetpack-black"
origin_tech = "materials=4;magnets=4;engineering=5"
w_class = WEIGHT_CLASS_NORMAL
actions_types = list(/datum/action/item_action/toggle_jetpack, /datum/action/item_action/jetpack_stabilization)
volume = 1
slot_flags = null
gas_type = null
var/datum/gas_mixture/temp_air_contents
var/obj/item/tank/internals/tank = null
var/mob/living/carbon/human/cur_user
/obj/item/tank/jetpack/suit/New()
..()
STOP_PROCESSING(SSobj, src)
temp_air_contents = air_contents
/obj/item/tank/jetpack/suit/attack_self__legacy__attackchain()
return
/obj/item/tank/jetpack/suit/cycle(mob/user)
if(!istype(loc, /obj/item/clothing/suit/space/hardsuit))
to_chat(user, "<span class='warning'>[src] must be connected to a hardsuit!</span>")
return
var/mob/living/carbon/human/H = user
if(!istype(H.s_store, /obj/item/tank))
to_chat(user, "<span class='warning'>You need a tank in your suit storage!</span>")
return
..()
/obj/item/tank/jetpack/suit/turn_on(mob/user)
if(!istype(loc, /obj/item/clothing/suit/space/hardsuit) || !ishuman(loc.loc) || loc.loc != user)
return
var/mob/living/carbon/human/H = user
tank = H.s_store
air_contents = tank.air_contents
START_PROCESSING(SSobj, src)
cur_user = user
..()
/obj/item/tank/jetpack/suit/turn_off(mob/user)
tank = null
air_contents = temp_air_contents
STOP_PROCESSING(SSobj, src)
cur_user = null
..()
/obj/item/tank/jetpack/suit/process()
if(!istype(loc, /obj/item/clothing/suit/space/hardsuit) || !ishuman(loc.loc))
turn_off(cur_user)
return
var/mob/living/carbon/human/H = loc.loc
if(!tank || tank != H.s_store)
turn_off(cur_user)
return
..()
+217
View File
@@ -0,0 +1,217 @@
/* Types of tanks!
* Contains:
* Oxygen
* Anesthetic
* Air
* Plasma
* Emergency Oxygen
* Generic
*/
/*
* Oxygen
*/
/obj/item/tank/internals
name = "internals tank"
desc = "A tank for use in internals. If you see this, please submit a bug report."
icon_state = "generic"
distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE
force = 10
/obj/item/tank/internals/oxygen
name = "oxygen tank"
desc = "A tank of oxygen. This one is blue."
icon_state = "oxygen"
dog_fashion = /datum/dog_fashion/back
/obj/item/tank/internals/oxygen/populate_gas()
air_contents.set_oxygen((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
/obj/item/tank/internals/oxygen/yellow
desc = "A tank of oxygen, this one is yellow."
icon_state = "oxygen_f"
/obj/item/tank/internals/oxygen/red
desc = "A tank of oxygen, this one is red."
icon_state = "oxygen_fr"
/obj/item/tank/internals/oxygen/empty/populate_gas()
return
/*
* Anesthetic
*/
/obj/item/tank/internals/anesthetic
name = "anesthetic tank"
desc = "A tank with an N2O/O2 gas mix."
icon_state = "anesthetic"
item_state = "an_tank"
distribute_pressure = ONE_ATMOSPHERE
/obj/item/tank/internals/anesthetic/populate_gas()
air_contents.set_oxygen((3 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C) * O2STANDARD)
air_contents.set_sleeping_agent((3 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C) * N2STANDARD)
/*
* Plasma
*/
/obj/item/tank/internals/plasma
name = "plasma tank"
desc = "Contains dangerous plasma. Do not inhale. Warning: extremely flammable."
icon_state = "plasma"
slot_flags = null //they have no straps!
force = 8
/obj/item/tank/internals/plasma/populate_gas()
air_contents.set_toxins((3 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
/obj/item/tank/internals/plasma/attackby__legacy__attackchain(obj/item/I, mob/user, params)
if(istype(I, /obj/item/flamethrower))
var/obj/item/flamethrower/F = I
if((!F.status)||(F.ptank))
return
master = F
F.ptank = src
user.transfer_item_to(src, F)
F.update_icon()
else
return ..()
/obj/item/tank/internals/plasma/full/populate_gas()
air_contents.set_toxins((10 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
/obj/item/tank/internals/plasma/empty/populate_gas()
return
/*
* Plasmaman Plasma Tank
*/
/obj/item/tank/internals/plasmaman
name = "plasma internals tank"
desc = "A tank of plasma gas designed specifically for use as internals, particularly for plasma-based lifeforms. If you're not a Plasmaman, you probably shouldn't use this."
icon_state = "plasma_fr"
item_state = "plasma_fr"
/obj/item/tank/internals/plasmaman/populate_gas()
air_contents.set_toxins((3 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
/obj/item/tank/internals/plasmaman/full/populate_gas()
air_contents.set_toxins((10 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
/obj/item/tank/internals/plasmaman/belt
icon_state = "plasmaman_tank_belt"
item_state = "plasmaman_tank_belt"
slot_flags = ITEM_SLOT_BELT
flags_2 = ALLOW_BELT_NO_JUMPSUIT_2
force = 5
volume = 18 // Lasts 1h 16m 30s
w_class = WEIGHT_CLASS_SMALL
/obj/item/tank/internals/plasmaman/belt/full/populate_gas()
air_contents.set_toxins((10 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
/obj/item/tank/internals/plasmaman/belt/empty/populate_gas()
return
/obj/item/tank/internals/emergency_oxygen/plasma
name = "emergency plasma tank"
desc = "An emergency tank designed specifically for Plasmamen."
icon_state = "emergency_p"
/obj/item/tank/internals/emergency_oxygen/plasma/populate_gas()
air_contents.set_toxins((10 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
/*
* Emergency Oxygen
*/
/obj/item/tank/internals/emergency_oxygen
name = "emergency oxygen tank"
desc = "Used for emergencies. Contains very little oxygen, so try to conserve it until you actually need it."
icon_state = "emergency"
slot_flags = ITEM_SLOT_BELT
flags_2 = ALLOW_BELT_NO_JUMPSUIT_2
w_class = WEIGHT_CLASS_SMALL
force = 4
volume = 1 // Roughly 4m 15s of air
/obj/item/tank/internals/emergency_oxygen/populate_gas()
air_contents.set_oxygen((10 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
/obj/item/tank/internals/emergency_oxygen/empty/populate_gas()
return
/obj/item/tank/internals/emergency_oxygen/engi
name = "extended-capacity emergency oxygen tank"
icon_state = "emergency_engi"
volume = 3 // Lasts 12m 45s
/obj/item/tank/internals/emergency_oxygen/engi/empty/populate_gas()
return
/obj/item/tank/internals/emergency_oxygen/engi/syndi
name = "suspicious emergency oxygen tank"
icon_state = "emergency_syndi"
desc = "A dark emergency oxygen tank. The label on the back reads \"Original Oxygen Tank Design, Do Not Steal.\""
volume = 11 // Lasts 46m 45s
/obj/item/tank/internals/emergency_oxygen/double
name = "double emergency oxygen tank"
icon_state = "emergency_double"
volume = 6 // Lasts 25m 30s
/obj/item/tank/internals/emergency_oxygen/double/empty/populate_gas()
return
/*
* Nitrogen
*/
/obj/item/tank/internals/nitrogen
name = "nitrogen tank"
desc = "A tank of nitrogen."
icon_state = "oxygen_fr"
/obj/item/tank/internals/nitrogen/populate_gas()
air_contents.set_nitrogen((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
/obj/item/tank/internals/emergency_oxygen/nitrogen
name = "emergency nitrogen tank"
desc = "An emergency tank designed specifically for Vox."
icon_state = "emergency_nitrogen"
/obj/item/tank/internals/emergency_oxygen/nitrogen/populate_gas()
air_contents.set_nitrogen((10 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
/obj/item/tank/internals/emergency_oxygen/double/vox
name = "vox specialized nitrogen tank"
desc = "A high-tech nitrogen tank designed specifically for Vox."
icon_state = "emergency_vox"
volume = 18 // Lasts 1h 16m 30s
/obj/item/tank/internals/emergency_oxygen/double/vox/populate_gas()
air_contents.set_nitrogen((10 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C))
/*
* Air Mix
*/
/obj/item/tank/internals/air
name = "air tank"
desc = "Mixed anyone?"
icon_state = "air"
item_state = "air"
distribute_pressure = ONE_ATMOSPHERE
/obj/item/tank/internals/air/populate_gas()
air_contents.set_oxygen((3 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C) * O2STANDARD)
air_contents.set_nitrogen((3 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C) * N2STANDARD)
/*
* Generic
*/
/obj/item/tank/internals/generic
name = "gas tank"
desc = "A generic tank used for storing and transporting gasses. Can be used for internals."
item_state = "generic"
/obj/item/tank/internals/generic/populate_gas()
return
+373
View File
@@ -0,0 +1,373 @@
//Hydroponics tank and base code
/obj/item/watertank
name = "backpack water tank"
desc = "A S.U.N.S.H.I.N.E. brand watertank backpack with nozzle to water plants."
icon = 'icons/obj/watertank.dmi'
icon_state = "waterbackpack"
item_state = "waterbackpack"
w_class = WEIGHT_CLASS_BULKY
slot_flags = ITEM_SLOT_BACK
slowdown = 1
actions_types = list(/datum/action/item_action/toggle_mister)
armor = list(MELEE = 0, BULLET = 0, LASER = 0, ENERGY = 0, BOMB = 0, RAD = 0, FIRE = 100, ACID = 30)
resistance_flags = FIRE_PROOF
var/obj/item/noz
var/on = FALSE
var/volume = 500
/obj/item/watertank/New()
..()
create_reagents(volume)
noz = make_noz()
/obj/item/watertank/Destroy()
if(on)
remove_noz()
QDEL_NULL(noz)
return ..()
/obj/item/watertank/ui_action_click(mob/user)
toggle_mister(user)
/obj/item/watertank/item_action_slot_check(slot, mob/user)
if(slot == ITEM_SLOT_BACK)
return TRUE
/obj/item/watertank/proc/toggle_mister(mob/user)
if(user.stat || HAS_TRAIT(user, TRAIT_HANDS_BLOCKED) || !Adjacent(user))
return
if(user.get_item_by_slot(ITEM_SLOT_BACK) != src)
to_chat(user, "<span class='notice'>The watertank needs to be on your back to use.</span>")
return
on = !on
if(on)
if(!noz)
noz = make_noz()
//Detach the nozzle into the user's hands
if(!user.put_in_hands(noz))
on = FALSE
to_chat(user, "<span class='notice'>You need a free hand to hold the mister.</span>")
return
noz.forceMove(user)
else
//Remove from their hands and put back "into" the tank
remove_noz()
return
/obj/item/watertank/proc/make_noz()
return new /obj/item/reagent_containers/spray/mister(src)
/obj/item/watertank/equipped(mob/user, slot)
..()
if(slot != ITEM_SLOT_BACK)
remove_noz()
/obj/item/watertank/proc/remove_noz()
if(ismob(noz.loc))
var/mob/M = noz.loc
M.drop_item_to_ground(noz, force = TRUE)
return
/obj/item/watertank/attack_hand(mob/user)
if(loc == user)
toggle_mister(user)
return
..()
/obj/item/watertank/MouseDrop(obj/over_object)
if(ishuman(loc))
var/mob/living/carbon/human/H = loc
switch(over_object.name)
if("r_hand")
if(H.r_hand)
return
if(!H.unequip(src))
return
H.put_in_r_hand(src)
if("l_hand")
if(H.l_hand)
return
if(!H.unequip(src))
return
H.put_in_l_hand(src)
return
/obj/item/watertank/attackby__legacy__attackchain(obj/item/W, mob/user, params)
if(W == noz)
remove_noz()
return
..()
// This mister item is intended as an extension of the watertank and always attached to it.
// Therefore, it's designed to be "locked" to the player's hands or extended back onto
// the watertank backpack. Allowing it to be placed elsewhere or created without a parent
// watertank object will likely lead to weird behaviour or runtimes.
/obj/item/reagent_containers/spray/mister
name = "water mister"
desc = "A mister nozzle attached to a water tank."
icon = 'icons/obj/watertank.dmi'
icon_state = "mister"
item_state = "mister"
w_class = WEIGHT_CLASS_BULKY
amount_per_transfer_from_this = 50
possible_transfer_amounts = list(25,50,100)
volume = 500
var/obj/item/watertank/tank
/obj/item/reagent_containers/spray/mister/Initialize(mapload)
if(!check_tank_exists(loc, src))
return INITIALIZE_HINT_QDEL
tank = loc
reagents = tank.reagents //This mister is really just a proxy for the tank's reagents
RegisterSignal(src, COMSIG_ACTIVATE_SELF, TYPE_PROC_REF(/datum, signal_cancel_activate_self))
return ..()
/obj/item/reagent_containers/spray/mister/Destroy()
tank = null
reagents = null // Unset, this is the tanks reagents
return ..()
/obj/item/reagent_containers/spray/mister/dropped(mob/user as mob)
..()
to_chat(user, "<span class='notice'>The mister snaps back onto the watertank.</span>")
tank.on = FALSE
loc = tank
/proc/check_tank_exists(parent_tank, mob/living/carbon/human/M, obj/O)
if(!parent_tank || (!istype(parent_tank, /obj/item/watertank) && !istype(parent_tank, /obj/item/mod/module/firefighting_tank))) //To avoid weird issues from admin spawns
return FALSE
else
return TRUE
/obj/item/reagent_containers/spray/mister/Move()
..()
if(loc != tank.loc)
loc = tank.loc
/obj/item/reagent_containers/spray/mister/normal_act(atom/target, mob/living/user)
if(target.loc == loc || target == tank)
return FALSE
return ..()
//Janitor tank
/obj/item/watertank/janitor
desc = "A janitorial watertank backpack with nozzle to clean dirt and graffiti."
icon_state = "waterbackpackjani"
item_state = "waterbackpackjani"
/obj/item/watertank/janitor/New()
..()
reagents.add_reagent("cleaner", 500)
/obj/item/reagent_containers/spray/mister/janitor
name = "janitor spray nozzle"
desc = "A janitorial spray nozzle attached to a watertank, designed to clean up large messes."
icon_state = "misterjani"
item_state = "misterjani"
spray_maxrange = 4
spray_currentrange = 4
amount_per_transfer_from_this = 10
possible_transfer_amounts = null
/obj/item/watertank/janitor/make_noz()
return new /obj/item/reagent_containers/spray/mister/janitor(src)
/obj/item/reagent_containers/spray/mister/janitor/activate_self(mob/user)
if(..())
return FINISH_ATTACK
amount_per_transfer_from_this = (amount_per_transfer_from_this == 5 ? 10 : 5)
spray_currentrange = (spray_currentrange == 2 ? spray_maxrange : 2)
to_chat(user, "<span class='notice'>You [amount_per_transfer_from_this == 5 ? "remove" : "fix"] the nozzle. You'll now use [amount_per_transfer_from_this] units per spray.</span>")
//ATMOS FIRE FIGHTING BACKPACK
#define EXTINGUISHER 0
#define NANOFROST 1
#define METAL_FOAM 2
/obj/item/watertank/atmos
name = "backpack firefighter tank"
desc = "A refridgerated and pressurized backpack tank with extinguisher nozzle, intended to fight fires. Swaps between extinguisher, nanofrost launcher, and metal foam dispenser for breaches. Nanofrost converts plasma in the air to nitrogen, but only if it is combusting at the time."
icon_state = "waterbackpackatmos"
item_state = "waterbackpackatmos"
/obj/item/watertank/atmos/New()
..()
reagents.add_reagent("water", 500)
/obj/item/watertank/atmos/make_noz()
return new /obj/item/extinguisher/mini/nozzle(src)
/obj/item/watertank/atmos/dropped(mob/user as mob)
..()
icon_state = "waterbackpackatmos"
if(istype(noz, /obj/item/extinguisher/mini/nozzle))
var/obj/item/extinguisher/mini/nozzle/N = noz
N.nozzle_mode = 0
/obj/item/extinguisher/mini/nozzle
name = "extinguisher nozzle"
desc = "A heavy duty nozzle attached to a firefighter's backpack tank."
icon = 'icons/obj/watertank.dmi'
icon_state = "atmos_nozzle_1"
item_state = "nozzleatmos"
has_safety = FALSE
safety_active = FALSE
reagent_capacity = 500
precision = TRUE
cooling_power = 5
w_class = WEIGHT_CLASS_HUGE
flags = NODROP //Necessary to ensure that the nozzle and tank never seperate
/// A reference to the tank that this nozzle is linked to
var/obj/item/watertank/tank
/// What mode are we currently in?
var/nozzle_mode = EXTINGUISHER
/// How many shots of metal foam do we have?
var/metal_synthesis_charge = 5
/// Time to refill 1 charge of metal foam.
var/metal_regen_time = 2 SECONDS
/// Refire delay for nanofrost chunks.
var/nanofrost_cooldown_time = 2 SECONDS
COOLDOWN_DECLARE(nanofrost_cooldown)
/obj/item/extinguisher/mini/nozzle/examine(mob/user)
. = ..()
switch(nozzle_mode)
if(EXTINGUISHER)
. += "<span class='notice'>[src] is currently set to extinguishing mode.</span>"
if(NANOFROST)
. += "<span class='notice'>[src] is currently set to nanofrost mode.</span>"
if(METAL_FOAM)
. += "<span class='notice'>[src] is currently set to metal foam mode.</span>"
/obj/item/extinguisher/mini/nozzle/Initialize(mapload)
if(!check_tank_exists(loc, src))
return INITIALIZE_HINT_QDEL
tank = loc
reagents = tank.reagents
reagent_capacity = tank.volume
return ..()
/obj/item/extinguisher/mini/nozzle/Destroy()
tank = null
reagents = null // Unset, this is the tanks reagents
return ..()
/obj/item/extinguisher/mini/nozzle/Move()
..()
if(tank && loc != tank.loc)
forceMove(tank)
/obj/item/extinguisher/mini/nozzle/activate_self(mob/user)
..()
switch(nozzle_mode)
if(EXTINGUISHER)
nozzle_mode = NANOFROST
to_chat(user, "Swapped to nanofrost launcher")
if(NANOFROST)
nozzle_mode = METAL_FOAM
to_chat(user, "Swapped to metal foam synthesizer")
if(METAL_FOAM)
nozzle_mode = EXTINGUISHER
to_chat(user, "Swapped to water extinguisher")
update_icon(UPDATE_ICON_STATE)
return ITEM_INTERACT_COMPLETE
/obj/item/extinguisher/mini/nozzle/update_icon_state()
switch(nozzle_mode)
if(EXTINGUISHER)
icon_state = "atmos_nozzle_1"
tank.icon_state = "waterbackpackatmos_0"
if(NANOFROST)
icon_state = "atmos_nozzle_2"
tank.icon_state = "waterbackpackatmos_1"
if(METAL_FOAM)
icon_state = "atmos_nozzle_3"
tank.icon_state = "waterbackpackatmos_2"
/obj/item/extinguisher/mini/nozzle/dropped(mob/user)
..()
if(istype(tank, /obj/item/mod/module/firefighting_tank))
return
to_chat(user, "<span class='notice'>The nozzle snaps back onto the tank!</span>")
tank.on = FALSE
loc = tank
/obj/item/extinguisher/mini/nozzle/extinguisher_spray(atom/A, mob/living/user)
if(nozzle_mode == EXTINGUISHER)
return ..()
. = TRUE
switch(nozzle_mode)
if(NANOFROST)
if(reagents.total_volume < 100)
to_chat(user, "<span class='warning'>You need at least 100 units of water to use the nanofrost launcher!</span>")
return
if(COOLDOWN_TIMELEFT(src, nanofrost_cooldown))
to_chat(user, "<span class='warning'>The nanofrost launcher is still recharging!</span>")
return
COOLDOWN_START(src, nanofrost_cooldown, nanofrost_cooldown_time)
reagents.remove_any(100)
var/obj/effect/nanofrost_container/iceball = new /obj/effect/nanofrost_container(get_turf(src))
log_game("[key_name(user)] used Nanofrost at [get_area(user)] ([user.x], [user.y], [user.z]).")
playsound(src,'sound/items/syringeproj.ogg', 40, TRUE)
iceball.throw_at(A, 6, 2, user)
sleep(2)
iceball.Smoke()
return
if(METAL_FOAM)
if(!user.Adjacent(A) || !isturf(A))
return
if(metal_synthesis_charge <= 0)
to_chat(user, "<span class='warning'>Metal foam mix is still being synthesized!</span>")
return
if(reagents.total_volume < 10)
to_chat(user, "<span class='warning'>You need at least 10 units of water to use the metal foam synthesizer!</span>")
return
var/obj/effect/particle_effect/foam/metal/foam = new /obj/effect/particle_effect/foam/metal(get_turf(A), TRUE)
foam.spread_amount = 0
reagents.remove_any(10)
metal_synthesis_charge--
addtimer(CALLBACK(src, PROC_REF(refill_metal_charge)), metal_regen_time)
return
/obj/item/extinguisher/mini/nozzle/proc/refill_metal_charge()
metal_synthesis_charge++
/obj/effect/nanofrost_container
name = "nanofrost container"
desc = "A frozen shell of ice containing nanofrost that freezes the surrounding area after activation."
icon_state = "frozen_smoke_capsule"
mouse_opacity = MOUSE_OPACITY_TRANSPARENT
pass_flags = PASSTABLE
/obj/effect/nanofrost_container/proc/Smoke()
var/datum/effect_system/smoke_spread/freezing/S = new
S.set_up(amount = 6, only_cardinals = FALSE, source = loc)
S.start()
new /obj/effect/decal/cleanable/flour/nanofrost(get_turf(src))
playsound(src, 'sound/effects/bamf.ogg', 100, TRUE)
qdel(src)
/obj/effect/nanofrost_container/anomaly
name = "nanofrost anomaly"
desc = "A frozen shell of ice containing nanofrost that freezes the surrounding area."
icon_state = "frozen_smoke_anomaly"
#undef EXTINGUISHER
#undef NANOFROST
#undef METAL_FOAM