mirror of
https://github.com/ParadiseSS13/Paradise.git
synced 2026-08-26 21:48:21 +01:00
Adds Chemical flamethrowers (#25091)
* Initial work * Good enough to open a PR out of draft * Make these use the vars on the flamethrower * Moar fixes * Undefines define * Update code/game/objects/items/weapons/chemical_flamethrower.dm Co-authored-by: GDN <96800819+GDNgit@users.noreply.github.com> * Update code/game/objects/items/weapons/chemical_flamethrower.dm Co-authored-by: GDN <96800819+GDNgit@users.noreply.github.com> * Update code/game/objects/items/weapons/chemical_flamethrower.dm Co-authored-by: GDN <96800819+GDNgit@users.noreply.github.com> * Update code/game/objects/items/weapons/chemical_flamethrower.dm Co-authored-by: GDN <96800819+GDNgit@users.noreply.github.com> * Update code/game/objects/items/weapons/chemical_flamethrower.dm Co-authored-by: GDN <96800819+GDNgit@users.noreply.github.com> * This won't compile * GDN review * Fixes CI * Fixes CI even more * 5 ammo per tile now * Heavily nerfs adding multiple fires * Adds phlogiston as a burnable reagent * Fixes the fire name * Placeholder sprite + ammo use fix * Now in cargo partially * Apply suggestions from code review Co-authored-by: Henri215 <77684085+Henri215@users.noreply.github.com> Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com> * Update code/game/objects/items/weapons/chemical_flamethrower/chemical_flamethrower.dm Co-authored-by: GDN <96800819+GDNgit@users.noreply.github.com> Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com> * Update code/game/objects/items/weapons/chemical_flamethrower/fire_effect.dm Co-authored-by: GDN <96800819+GDNgit@users.noreply.github.com> Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com> * Update code/game/objects/items/weapons/chemical_flamethrower/fire_effect.dm Co-authored-by: GDN <96800819+GDNgit@users.noreply.github.com> Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com> * Lewc Review * Adds nuclear variant * Adds the chem flamethrower to the nukie uplink, alongside ammo * More fire armor tweaks * GDN review * Update code/modules/reagents/chemistry/reagents/pyrotechnic.dm Co-authored-by: 1080pCat <96908085+1080pCat@users.noreply.github.com> Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com> * Update code/game/objects/items/weapons/chemical_flamethrower/chemical_flamethrower.dm Co-authored-by: 1080pCat <96908085+1080pCat@users.noreply.github.com> Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com> * Apply suggestions from code review Co-authored-by: 1080pCat <96908085+1080pCat@users.noreply.github.com> Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com> * Update code/game/objects/items/weapons/chemical_flamethrower/chemical_flamethrower.dm Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com> * Update code/game/objects/items/weapons/chemical_flamethrower/fire_effect.dm Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com> * TEMPORARY PUSH * Adds inhands * Update code/game/objects/items/weapons/chemical_flamethrower/chemical_flamethrower.dm Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com> * Update code/game/objects/items/weapons/chemical_flamethrower/chemical_flamethrower.dm Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com> * Fixes inhands * Makes air hot again * Lewc review * Audible messages and canister refilling * Update code/game/objects/items/weapons/chemical_flamethrower/chemical_flamethrower.dm Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com> Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com> --------- Signed-off-by: DGamerL <108773801+DGamerL@users.noreply.github.com> Co-authored-by: GDN <96800819+GDNgit@users.noreply.github.com> Co-authored-by: Henri215 <77684085+Henri215@users.noreply.github.com> Co-authored-by: 1080pCat <96908085+1080pCat@users.noreply.github.com> Co-authored-by: Luc <89928798+lewcc@users.noreply.github.com> Co-authored-by: Burzah <116982774+Burzah@users.noreply.github.com>
This commit is contained in:
co-authored by
GDN
Henri215
1080pCat
Luc
Burzah
parent
6ae5bfef8a
commit
e3c73110db
@@ -0,0 +1,288 @@
|
||||
/obj/item/chemical_flamethrower
|
||||
name = "chemical flamethrower"
|
||||
desc = "I love the smell of napalm in the morning."
|
||||
icon = 'icons/obj/chemical_flamethrower.dmi'
|
||||
icon_state = "chem_flame"
|
||||
lefthand_file = 'icons/mob/inhands/flamethrower_lefthand.dmi'
|
||||
righthand_file = 'icons/mob/inhands/flamethrower_righthand.dmi'
|
||||
flags = CONDUCT
|
||||
force = 5
|
||||
throwforce = 10
|
||||
throw_speed = 1
|
||||
throw_range = 5
|
||||
w_class = WEIGHT_CLASS_NORMAL
|
||||
slot_flags = SLOT_FLAG_BACK
|
||||
materials = list(MAT_METAL = 5000)
|
||||
resistance_flags = FIRE_PROOF
|
||||
origin_tech = "combat=1;plasmatech=2;engineering=2"
|
||||
|
||||
/// How many canisters fit in our flamethrower?
|
||||
var/max_canisters = 1
|
||||
/// All our loaded canisters in a list
|
||||
var/list/canisters = list()
|
||||
/// Is this a type of flamethrower that starts loaded?
|
||||
var/should_start_with_canisters = FALSE
|
||||
|
||||
/// The burn temperature of our currently stored chemical in the canister
|
||||
var/canister_burn_temp = T0C + 300
|
||||
/// The burn duration of our currently stored chemical in the canister
|
||||
var/canister_burn_duration = 10 SECONDS
|
||||
/// How many firestacks will our reagent apply
|
||||
var/canister_fire_applications = 1
|
||||
/// Is this a syndicate flamethrower
|
||||
var/syndicate = FALSE
|
||||
|
||||
/obj/item/chemical_flamethrower/Initialize(mapload)
|
||||
. = ..()
|
||||
if(should_start_with_canisters && !length(canisters))
|
||||
canisters += new /obj/item/chemical_canister
|
||||
update_canister_stats()
|
||||
update_icon_state()
|
||||
|
||||
/obj/item/chemical_flamethrower/Destroy()
|
||||
QDEL_LIST_CONTENTS(canisters)
|
||||
return ..()
|
||||
|
||||
/obj/item/chemical_flamethrower/update_icon_state()
|
||||
icon_state = "chem_flame[max_canisters == 2 ? "_2" : ""][syndicate ? "_s" : ""]"
|
||||
item_state = icon_state
|
||||
|
||||
/obj/item/chemical_flamethrower/update_overlays()
|
||||
. = ..()
|
||||
var/iterator = 1
|
||||
for(var/obj/item/chemical_canister as anything in canisters)
|
||||
. += mutable_appearance('icons/obj/chemical_flamethrower.dmi', "[chemical_canister.icon_state]_[iterator]")
|
||||
iterator++
|
||||
|
||||
/obj/item/chemical_flamethrower/attack_self(mob/user)
|
||||
. = ..()
|
||||
if(length(canisters))
|
||||
unequip_canisters(user)
|
||||
|
||||
/obj/item/chemical_flamethrower/proc/unequip_canisters(mob/user)
|
||||
if(!length(canisters))
|
||||
return
|
||||
|
||||
var/obj/item/chemical_canister/canister_to_remove = canisters[length(canisters)]
|
||||
canister_to_remove.forceMove(get_turf(src))
|
||||
user.put_in_hands(canister_to_remove)
|
||||
canisters -= canister_to_remove
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
|
||||
/obj/item/chemical_flamethrower/attackby(obj/item/I, mob/user, params)
|
||||
. = ..()
|
||||
if(!istype(I, /obj/item/chemical_canister))
|
||||
to_chat(user, "<span class='notice'>You can't fit [I] in there!</span>")
|
||||
return
|
||||
if(length(canisters) >= max_canisters)
|
||||
to_chat(user, "<span class='notice'>[src] is already full!</span>")
|
||||
return
|
||||
|
||||
if(!user.unEquip(I))
|
||||
return
|
||||
|
||||
to_chat(user, "<span class='notice'>You put [I] into [src].</span>")
|
||||
canisters += I
|
||||
I.forceMove(src)
|
||||
update_canister_stats()
|
||||
|
||||
/obj/item/chemical_flamethrower/proc/update_canister_stats()
|
||||
if(!length(canisters))
|
||||
canister_burn_temp = null
|
||||
canister_burn_duration = null
|
||||
canister_fire_applications = null
|
||||
return
|
||||
|
||||
var/burn_temp
|
||||
var/burn_duration
|
||||
var/fire_applications
|
||||
var/how_many_canisters = length(canisters)
|
||||
|
||||
for(var/obj/item/chemical_canister/canister as anything in canisters)
|
||||
if(!canister.ammo)
|
||||
continue
|
||||
burn_temp += canister.chem_burn_temp
|
||||
burn_duration += canister.chem_burn_duration
|
||||
fire_applications += canister.fire_applications
|
||||
|
||||
canister_burn_temp = round(burn_temp / how_many_canisters, 1)
|
||||
canister_burn_duration = round(burn_duration / how_many_canisters, 1)
|
||||
canister_fire_applications = round(fire_applications / how_many_canisters, 1)
|
||||
update_icon(UPDATE_OVERLAYS)
|
||||
|
||||
/obj/item/chemical_flamethrower/afterattack(atom/target, mob/user, flag)
|
||||
. = ..()
|
||||
if(flag || !user)
|
||||
return
|
||||
|
||||
if(user.mind?.martial_art?.no_guns)
|
||||
to_chat(user, "<span class='warning'>[user.mind.martial_art.no_guns_message]</span>")
|
||||
return
|
||||
|
||||
if(HAS_TRAIT(user, TRAIT_CHUNKYFINGERS))
|
||||
to_chat(user, "<span class='warning'>Your meaty finger is far too large for the trigger guard!</span>")
|
||||
return
|
||||
|
||||
if(user.get_active_hand() == src) // Make sure our user is still holding us
|
||||
var/turf/target_turf = get_turf(target)
|
||||
if(target_turf)
|
||||
var/turf_list = get_line(user, target_turf)
|
||||
add_attack_logs(user, target, "Chemical Flamethrowered at [target.x], [target.y], [target.z]")
|
||||
INVOKE_ASYNC(src, PROC_REF(flame_turf), turf_list, user)
|
||||
|
||||
/obj/item/chemical_flamethrower/proc/flame_turf(list/turflist = list(), mob/user)
|
||||
if(!length(turflist))
|
||||
return
|
||||
|
||||
var/turf/previousturf = get_turf(src)
|
||||
for(var/turf/simulated/T in turflist)
|
||||
if(iswallturf(T)) // No going through walls
|
||||
break
|
||||
if(!use_ammo(3))
|
||||
to_chat(user, "<span class='warning'>You hear a click!</span>")
|
||||
playsound(user, 'sound/weapons/empty.ogg', 100, TRUE)
|
||||
break // Whoops! No ammo!
|
||||
|
||||
if(T == previousturf)
|
||||
continue // So we don't burn the tile we be standin on
|
||||
|
||||
var/found_obstruction = FALSE
|
||||
for(var/obj/thing in T)
|
||||
if(thing.density && !istype(thing, /obj/structure/table))
|
||||
found_obstruction = TRUE
|
||||
break
|
||||
if(found_obstruction)
|
||||
break
|
||||
|
||||
make_flame(T)
|
||||
update_canister_stats() // In case we ran out of some fuel this fire
|
||||
sleep(1)
|
||||
previousturf = T
|
||||
|
||||
/obj/item/chemical_flamethrower/proc/make_flame(turf/spawn_turf)
|
||||
new /obj/effect/fire(spawn_turf, canister_burn_temp, (canister_burn_duration + rand(1, 3) SECONDS), canister_fire_applications) // For that spicy randomness (and to save your ears from all fires extinguishing at the same time)
|
||||
|
||||
/*
|
||||
* Uses `amount` ammo from the flamethrower.
|
||||
* Returns `TRUE` if ammo could be consumed, returns `FALSE` if it failed somehow
|
||||
* It will use up ammo if it failed.
|
||||
*/
|
||||
/obj/item/chemical_flamethrower/proc/use_ammo(amount)
|
||||
var/total_ammo
|
||||
for(var/obj/item/chemical_canister/canister as anything in canisters)
|
||||
total_ammo += canister.ammo
|
||||
if(total_ammo - amount < 0)
|
||||
return FALSE
|
||||
|
||||
var/length = length(canisters)
|
||||
var/difference = amount
|
||||
for(var/i in 0 to length)
|
||||
var/obj/item/chemical_canister/canister = canisters[length - i]
|
||||
if(canister.ammo - difference <= 0)
|
||||
difference -= canister.ammo
|
||||
canister.ammo = 0
|
||||
else
|
||||
canister.ammo -= difference
|
||||
difference = 0
|
||||
|
||||
if(!difference)
|
||||
break
|
||||
|
||||
return !difference
|
||||
|
||||
/obj/item/chemical_flamethrower/extended
|
||||
name = "extended capacity chemical flamethrower"
|
||||
desc = "A flamethrower that accepts two chemical canisters to create lasting fires."
|
||||
max_canisters = 2
|
||||
|
||||
/obj/item/chemical_flamethrower/extended/nuclear
|
||||
name = "\improper Syndicate extended capacity chemical flamethrower"
|
||||
desc = "A flamethrower that accepts two chemical canisters to create lasting fires. As black as the ash of your enemies."
|
||||
syndicate = TRUE
|
||||
|
||||
/obj/item/chemical_flamethrower/extended/nuclear/Initialize(mapload)
|
||||
. = ..()
|
||||
for(var/i in 1 to max_canisters)
|
||||
canisters += new /obj/item/chemical_canister/extended/nuclear
|
||||
update_canister_stats()
|
||||
|
||||
/obj/item/chemical_canister
|
||||
name = "chemical canister"
|
||||
desc = "A simple canister of fuel. Does not accept any pyrotechnics except for welding fuel."
|
||||
icon = 'icons/obj/chemical_flamethrower.dmi'
|
||||
icon_state = "normal"
|
||||
container_type = OPENCONTAINER
|
||||
/// How much ammo do we have? Empty at 0.
|
||||
var/ammo = 100
|
||||
/// Which reagent IDs do we accept
|
||||
var/list/accepted_chemicals = list("fuel")
|
||||
/// The burn temperature of our currently stored chemical
|
||||
var/chem_burn_temp = T0C + 300
|
||||
/// The burn duration of our currently stored chemical
|
||||
var/chem_burn_duration = 10 SECONDS
|
||||
/// How many firestacks will our reagent apply
|
||||
var/fire_applications = 1
|
||||
/// The currently stored reagent ID
|
||||
var/current_reagent_id
|
||||
/// How many units of the reagent do we need to have it's effects kick in?
|
||||
var/required_volume = 10
|
||||
/// Do we have a locked in reagent type?
|
||||
var/has_filled_reagent = FALSE
|
||||
/// Are we silent on the first change of reagents?
|
||||
var/first_time_silent = FALSE // The reason for this is so we can have canisters that spawn with reagents but don't announce it on `Initialize()`
|
||||
|
||||
/obj/item/chemical_canister/Initialize(mapload)
|
||||
. = ..()
|
||||
create_reagents(50)
|
||||
|
||||
/obj/item/chemical_canister/on_reagent_change()
|
||||
if(has_filled_reagent && ammo != 0)
|
||||
audible_message("<span class='notice'>[src]'s speaker beeps: no new chemicals are accepted!</span>")
|
||||
return
|
||||
|
||||
if(!reagents.get_master_reagent_id() || !(reagents.get_master_reagent_id() in accepted_chemicals))
|
||||
reagents.clear_reagents()
|
||||
audible_message("<span class='notice'>[src]'s speaker beeps: the most present chemical isn't accepted!</span>")
|
||||
return
|
||||
|
||||
current_reagent_id = reagents.get_master_reagent_id()
|
||||
reagents.isolate_reagent(current_reagent_id)
|
||||
var/has_enough_reagents = reagents.total_volume >= required_volume
|
||||
|
||||
if(!first_time_silent)
|
||||
audible_message("<span class='notice'>[src]'s speaker beeps: \
|
||||
All reagents are removed except for [current_reagent_id]. \
|
||||
The reservoir has [reagents.total_volume] out of [required_volume] units. \
|
||||
Reagent effects are [has_enough_reagents ? "in effect" : "not active"].</span>")
|
||||
first_time_silent = FALSE
|
||||
|
||||
if(has_enough_reagents)
|
||||
var/datum/reagent/reagent_to_burn = reagents.reagent_list[1]
|
||||
chem_burn_duration = reagent_to_burn.burn_duration
|
||||
chem_burn_temp = reagent_to_burn.burn_temperature
|
||||
fire_applications = reagent_to_burn.fire_stack_applications
|
||||
ammo = initial(ammo)
|
||||
has_filled_reagent = TRUE
|
||||
|
||||
/obj/item/chemical_canister/extended
|
||||
name = "extended capacity chemical canister"
|
||||
desc = "An extended version of the original design. Does not accept any pyrotechnics except for welding fuel."
|
||||
icon_state = "extended"
|
||||
ammo = 200
|
||||
required_volume = 20 // Bigger canister? More reagents needed.
|
||||
|
||||
/obj/item/chemical_canister/extended/nuclear
|
||||
icon_state = "pyro"
|
||||
accepted_chemicals = list("napalm")
|
||||
first_time_silent = TRUE
|
||||
|
||||
/obj/item/chemical_canister/extended/nuclear/Initialize(mapload)
|
||||
..()
|
||||
reagents.add_reagent("napalm", 30) // Overload it with napalm!
|
||||
|
||||
/obj/item/chemical_canister/pyrotechnics
|
||||
name = "extended capacity chemical canister"
|
||||
desc = "A specialized canister designed to accept certain pyrotechnics."
|
||||
icon_state = "pyro"
|
||||
ammo = 150
|
||||
accepted_chemicals = list("phlogiston", "phlogiston_dust", "napalm", "fuel", "thermite", "clf3", "plasma")
|
||||
@@ -0,0 +1,116 @@
|
||||
GLOBAL_LIST_EMPTY(flame_effects)
|
||||
#define MAX_FIRE_EXIST_TIME 10 MINUTES // That's a lot of fuel, but you are not gonna make it last for longer
|
||||
|
||||
/obj/effect/fire
|
||||
name = "fire"
|
||||
desc = "You don't think you should touch this."
|
||||
icon = 'icons/effects/chemical_fire.dmi'
|
||||
icon_state = "fire1"
|
||||
|
||||
/// How hot is our fire?
|
||||
var/temperature
|
||||
/// How long will our fire last
|
||||
var/duration = 10 SECONDS
|
||||
/// How many firestacks does the fire give to mobs
|
||||
var/application_stacks = 1
|
||||
|
||||
/obj/effect/fire/Initialize(mapload, reagent_temperature, reagent_duration, fire_applications)
|
||||
. = ..()
|
||||
|
||||
if(reagent_duration < 0 || reagent_temperature <= 0) // There is no reason for this thing to exist
|
||||
qdel(src)
|
||||
return
|
||||
|
||||
duration = reagent_duration
|
||||
temperature = reagent_temperature
|
||||
application_stacks = max(application_stacks, fire_applications)
|
||||
|
||||
for(var/obj/effect/fire/flame in get_turf(src))
|
||||
if(!istype(flame) || flame == src)
|
||||
continue
|
||||
merge_flames(flame)
|
||||
|
||||
GLOB.flame_effects += src
|
||||
START_PROCESSING(SSprocessing, src)
|
||||
|
||||
/obj/effect/fire/Destroy()
|
||||
. = ..()
|
||||
GLOB.flame_effects -= src
|
||||
STOP_PROCESSING(SSprocessing, src)
|
||||
|
||||
/obj/effect/fire/process()
|
||||
if(duration <= 0)
|
||||
fizzle()
|
||||
return
|
||||
duration -= 2 SECONDS
|
||||
|
||||
for(var/atom/movable/thing_to_burn in get_turf(src))
|
||||
if(isliving(thing_to_burn))
|
||||
damage_mob(thing_to_burn)
|
||||
continue
|
||||
|
||||
if(isobj(thing_to_burn))
|
||||
var/obj/obj_to_burn = thing_to_burn
|
||||
obj_to_burn.fire_act(null, temperature)
|
||||
continue
|
||||
|
||||
var/turf/location = get_turf(src)
|
||||
if(!location)
|
||||
return
|
||||
var/datum/gas_mixture/air = location.private_unsafe_get_air()
|
||||
if(!air)
|
||||
return FALSE
|
||||
var/datum/milla_safe/fire_heat_air/milla = new()
|
||||
milla.invoke_async(src, location)
|
||||
|
||||
/datum/milla_safe/fire_heat_air
|
||||
|
||||
/datum/milla_safe/fire_heat_air/on_run(obj/effect/fire/fire, turf/T)
|
||||
var/datum/gas_mixture/env = get_turf_air(T)
|
||||
env.set_temperature(fire.temperature)
|
||||
|
||||
/obj/effect/fire/water_act(volume, temperature, source, method)
|
||||
. = ..()
|
||||
duration -= 10 SECONDS
|
||||
if(duration <= 0)
|
||||
fizzle()
|
||||
|
||||
/obj/effect/fire/Crossed(atom/movable/AM, oldloc)
|
||||
. = ..()
|
||||
if(isliving(AM))
|
||||
damage_mob(AM)
|
||||
to_chat(AM, "<span class='warning'>[src] burns you!</span>")
|
||||
return
|
||||
|
||||
if(isitem(AM))
|
||||
var/obj/item/item_to_burn = AM
|
||||
item_to_burn.fire_act(null, temperature)
|
||||
return
|
||||
|
||||
/obj/effect/fire/proc/fizzle()
|
||||
playsound(src, 'sound/effects/fire_sizzle.ogg', 50, TRUE)
|
||||
qdel(src)
|
||||
|
||||
/obj/effect/fire/proc/merge_flames(obj/effect/fire/merging_flame)
|
||||
duration = min((duration + (merging_flame.duration / 4)), MAX_FIRE_EXIST_TIME)
|
||||
temperature = ((merging_flame.temperature + temperature) / 2) // No making a sun by just clicking 10 times on a turf
|
||||
merging_flame.fizzle()
|
||||
|
||||
/obj/effect/fire/proc/damage_mob(mob/living/mob_to_burn)
|
||||
if(!istype(mob_to_burn))
|
||||
return
|
||||
var/fire_damage = temperature / 100
|
||||
if(ishuman(mob_to_burn))
|
||||
var/mob/living/carbon/human/human_to_burn = mob_to_burn
|
||||
var/fire_armour = human_to_burn.get_thermal_protection()
|
||||
if(fire_armour >= FIRE_IMMUNITY_MAX_TEMP_PROTECT)
|
||||
return
|
||||
|
||||
if(fire_armour == FIRE_SUIT_MAX_TEMP_PROTECT) // Good protection but you won't survive infinitely in it
|
||||
fire_damage /= 4
|
||||
|
||||
mob_to_burn.adjustFireLoss(fire_damage)
|
||||
mob_to_burn.adjust_fire_stacks(application_stacks)
|
||||
mob_to_burn.IgniteMob()
|
||||
|
||||
#undef MAX_FIRE_EXIST_TIME
|
||||
@@ -557,6 +557,13 @@
|
||||
/obj/item/storage/box/syndie_kit/pen_bomb/populate_contents()
|
||||
new /obj/item/grenade/syndieminibomb/pen(src)
|
||||
|
||||
/obj/item/storage/box/syndie_kit/chemical_canister
|
||||
name = "\improper Chemical flamethrower canisters"
|
||||
|
||||
/obj/item/storage/box/syndie_kit/chemical_canister/populate_contents()
|
||||
new /obj/item/chemical_canister/extended/nuclear(src)
|
||||
new /obj/item/chemical_canister/extended/nuclear(src)
|
||||
|
||||
/obj/item/storage/box/syndie_kit/decoy
|
||||
name = "\improper Decoy Grenade kit"
|
||||
|
||||
|
||||
Reference in New Issue
Block a user