mirror of
https://github.com/goonstation/goonstation-2020.git
synced 2026-08-23 20:16:11 +01:00
459 lines
14 KiB
Plaintext
459 lines
14 KiB
Plaintext
|
|
/* ================================================== */
|
|
/* -------------------- Grenades -------------------- */
|
|
/* ================================================== */
|
|
|
|
/obj/item/chem_grenade
|
|
name = "metal casing"
|
|
icon_state = "chemg1"
|
|
icon = 'icons/obj/chemical.dmi'
|
|
inhand_image_icon = 'icons/mob/inhand/hand_weapons.dmi'
|
|
item_state = "flashbang"
|
|
w_class = 2.0
|
|
force = 2.0
|
|
var/stage = 0
|
|
var/state = 0
|
|
var/icon_state_armed = "chemg4"
|
|
var/list/beakers = new/list()
|
|
throw_speed = 4
|
|
throw_range = 20
|
|
flags = FPRINT | TABLEPASS | CONDUCT | ONBELT | EXTRADELAY | NOSPLASH
|
|
stamina_damage = 1
|
|
stamina_cost = 1
|
|
stamina_crit_chance = 0
|
|
|
|
New()
|
|
var/datum/reagents/R = new/datum/reagents(150000)
|
|
reagents = R
|
|
R.my_atom = src
|
|
|
|
attackby(obj/item/W as obj, mob/user as mob)
|
|
if (istype(W,/obj/item/grenade_fuse) && !stage)
|
|
boutput(user, "<span style=\"color:blue\">You add [W] to the metal casing.</span>")
|
|
playsound(get_turf(src), "sound/items/Screwdriver2.ogg", 25, -3)
|
|
qdel(W) //Okay so we're not really adding anything here. cheating.
|
|
icon_state = "chemg2"
|
|
name = "unsecured grenade"
|
|
stage = 1
|
|
else if (isscrewingtool(W) && stage == 1)
|
|
if (beakers.len)
|
|
boutput(user, "<span style=\"color:blue\">You lock the assembly.</span>")
|
|
playsound(get_turf(src), "sound/items/Screwdriver.ogg", 25, -3)
|
|
name = "grenade"
|
|
icon_state = "chemg3"
|
|
stage = 2
|
|
else
|
|
boutput(user, "<span style=\"color:red\">You need to add at least one beaker before locking the assembly.</span>")
|
|
else if (istype(W,/obj/item/reagent_containers/glass) && stage == 1)
|
|
if (beakers.len == 2)
|
|
boutput(user, "<span style='color:red'>The grenade can not hold more containers.</span>")
|
|
return
|
|
var/obj/item/reagent_containers/glass/G = W
|
|
if (G.initial_volume > 50) // anything bigger than a regular beaker, but someone could varedit their reagent holder beyond this for admin nonsense
|
|
boutput(user, "<span style='color:red'>This beaker is too large!</span>")
|
|
return
|
|
else
|
|
if (G.reagents && G.reagents.total_volume)
|
|
boutput(user, "<span style='color:blue'>You add \the [G] to the assembly.</span>")
|
|
user.drop_item()
|
|
G.set_loc(src)
|
|
beakers += G
|
|
else
|
|
boutput(user, "<span style='color:red'>\The [G] is empty.</span>")
|
|
else if (stage == 2 && (istype(W, /obj/item/assembly/rad_ignite) || istype(W, /obj/item/assembly/prox_ignite) || istype(W, /obj/item/assembly/time_ignite)))
|
|
var/obj/item/assembly/S = W
|
|
if (!S || !S:status)
|
|
return
|
|
boutput(user, "<span style=\"color:blue\">You attach the [src.name] to the [S.name]!</span>")
|
|
logTheThing("bombing", user, null, "made a chemical bomb with a [S.name].")
|
|
message_admins("[key_name(user)] made a chemical bomb with a [S.name].")
|
|
|
|
var/obj/item/assembly/chem_bomb/R = new /obj/item/assembly/chem_bomb( user )
|
|
R.attacher = key_name(user)
|
|
|
|
switch(S:part1.type)
|
|
if (/obj/item/device/timer)
|
|
R.desc = "A very intricate igniter and timer assembly mounted to a chem grenade."
|
|
R.name = "Timer/Igniter/Chem Grenade Assembly"
|
|
if (/obj/item/device/prox_sensor)
|
|
R.desc = "A very intricate igniter and proximity sensor electrical assembly mounted to a chem grenade."
|
|
R.name = "Proximity/Igniter/Chem Grenade Assembly"
|
|
if (/obj/item/device/radio/signaler)
|
|
R.desc = "A very intricate igniter and signaller electrical assembly mounted to a chem grenade."
|
|
R.name = "Radio/Igniter/Chem Grenade Assembly"
|
|
|
|
R.triggering_device = S:part1
|
|
R.c_state(0)
|
|
S:part1.set_loc(R)
|
|
S:part1.master = R
|
|
R.igniter = S:part2
|
|
R.igniter.status = 1
|
|
S:part2.set_loc(R)
|
|
S:part2.master = R
|
|
S.layer = initial(S.layer)
|
|
user.u_equip(S)
|
|
user.put_in_hand_or_drop(R)
|
|
src.master = R
|
|
src.layer = initial(src.layer)
|
|
user.u_equip(src)
|
|
src.set_loc(R)
|
|
R.payload = src
|
|
S:part1 = null
|
|
S:part2 = null
|
|
//S = null
|
|
qdel(S)
|
|
|
|
// warcrimes: Why the fuck is autothrow a feature why would this ever be a feature WHY. Now it wont do it unless it's primed i think.
|
|
afterattack(atom/target as mob|obj|turf|area, mob/user as mob)
|
|
if (get_dist(user, target) <= 1 || (!isturf(target) && !isturf(target.loc)) || !isturf(user.loc) || !src.state)
|
|
return
|
|
var/area/a = get_area(target)
|
|
if(a.sanctuary) return
|
|
if (user.equipped() == src)
|
|
if (src.arm(user))
|
|
return ..()
|
|
user.drop_item()
|
|
src.throw_at(get_turf(target), 10, 3)
|
|
return
|
|
else if (isghostdrone(user))
|
|
var/mob/living/silicon/ghostdrone/G = user
|
|
if (istype(G.active_tool, /obj/item/magtractor))
|
|
var/obj/item/magtractor/mag = G.active_tool
|
|
if (mag.holding == src)
|
|
if (src.arm(user))
|
|
return ..()
|
|
mag.dropItem()
|
|
src.throw_at(get_turf(target), 10, 3)
|
|
return
|
|
|
|
attack_self(mob/user as mob)
|
|
src.arm(user)
|
|
|
|
attack_hand()
|
|
walk(src,0)
|
|
return ..()
|
|
|
|
proc/arm(mob/user as mob)
|
|
if (src.state || src.stage != 2)
|
|
return 1
|
|
var/area/a = get_area(src)
|
|
if(a.sanctuary) return
|
|
// Custom grenades only. Metal foam etc grenades cannot be modified (Convair880).
|
|
var/log_reagents = null
|
|
if (src.name == "grenade")
|
|
for (var/obj/item/reagent_containers/glass/G in src.beakers)
|
|
if (G.reagents.total_volume) log_reagents += "[log_reagents(G)] "
|
|
message_admins("[log_reagents ? "Custom grenade" : "Grenade ([src])"] primed at [log_loc(src)] by [key_name(user)].")
|
|
logTheThing("combat", user, null, "primes a [log_reagents ? "custom grenade" : "grenade ([src.type])"] at [log_loc(user)].[log_reagents ? " [log_reagents]" : ""]")
|
|
|
|
boutput(user, "<span style='color:red'>You prime the grenade! 3 seconds!</span>")
|
|
src.state = 1
|
|
src.icon_state = icon_state_armed
|
|
playsound(get_turf(src), "sound/weapons/armbomb.ogg", 75, 1, -3)
|
|
SPAWN_DBG(3 SECONDS)
|
|
if (src && !src.disposed)
|
|
a = get_area(src)
|
|
if(a.sanctuary) return
|
|
explode()
|
|
|
|
proc/explode()
|
|
var/has_reagents = 0
|
|
for (var/obj/item/reagent_containers/glass/G in beakers)
|
|
if (G.reagents.total_volume) has_reagents = 1
|
|
|
|
if (!has_reagents)
|
|
playsound(src.loc, "sound/items/Screwdriver2.ogg", 50, 1)
|
|
state = 0
|
|
return
|
|
|
|
playsound(src.loc, "sound/effects/bamf.ogg", 50, 1)
|
|
|
|
for (var/obj/item/reagent_containers/glass/G in beakers)
|
|
G.reagents.trans_to(src, G.reagents.total_volume)
|
|
|
|
if (src.reagents.total_volume) //The possible reactions didnt use up all reagents.
|
|
var/datum/effects/system/steam_spread/steam = unpool(/datum/effects/system/steam_spread)
|
|
steam.set_up(10, 0, get_turf(src))
|
|
steam.attach(src)
|
|
steam.start()
|
|
var/min_dispersal = src.reagents.get_dispersal()
|
|
for (var/atom/A in range(min_dispersal, get_turf(src.loc)))
|
|
if ( A == src ) continue
|
|
if (src && src.reagents) // Erik: fix for cannot execute null.grenade effects()
|
|
src.reagents.grenade_effects(src, A)
|
|
src.reagents.reaction(A, 1, 10)
|
|
|
|
invisibility = 100 //Why am i doing this?
|
|
if (src.master) src.master.invisibility = 100
|
|
SPAWN_DBG(5 SECONDS) //To make sure all reagents can work
|
|
if (src.master) qdel(src.master)
|
|
if (src) qdel(src) //correctly before deleting the grenade.
|
|
|
|
/obj/item/grenade_fuse
|
|
name = "grenade fuse"
|
|
desc = "A fuse mechanism with a safety lever."
|
|
icon = 'icons/obj/items.dmi'
|
|
icon_state = "grenade_fuse"
|
|
item_state = "pen"
|
|
force = 0
|
|
w_class = 1
|
|
m_amt = 100
|
|
|
|
/* =================================================== */
|
|
/* -------------------- Sub-Types -------------------- */
|
|
/* =================================================== */
|
|
|
|
// Order matters. Water resp. the final smoke ingredient should always be the last reagent added to the beaker.
|
|
// If it's not, the foam resp. smoke reaction occurs prematurely without carrying the target reagents with them.
|
|
|
|
/obj/item/chem_grenade/metalfoam
|
|
name = "metal foam grenade"
|
|
desc = "Used for emergency sealing of air breaches."
|
|
icon = 'icons/obj/grenade.dmi'
|
|
icon_state = "metal_foam"
|
|
icon_state_armed = "metal_foam1"
|
|
stage = 2
|
|
|
|
New()
|
|
..()
|
|
var/obj/item/reagent_containers/glass/B1 = new(src)
|
|
var/obj/item/reagent_containers/glass/B2 = new(src)
|
|
|
|
B1.reagents.add_reagent("aluminium", 30)
|
|
B2.reagents.add_reagent("fluorosurfactant", 10)
|
|
B2.reagents.add_reagent("acid", 10)
|
|
|
|
beakers += B1
|
|
beakers += B2
|
|
|
|
/obj/item/chem_grenade/firefighting
|
|
name = "fire fighting grenade"
|
|
desc = "Can help to put out dangerous fires from a distance."
|
|
icon = 'icons/obj/grenade.dmi'
|
|
icon_state = "fire_fighting"
|
|
icon_state_armed = "fire_fighting1"
|
|
stage = 2
|
|
|
|
New()
|
|
..()
|
|
var/obj/item/reagent_containers/glass/B1 = new(src)
|
|
var/obj/item/reagent_containers/glass/B2 = new(src)
|
|
|
|
B1.reagents.add_reagent("ff-foam", 30)
|
|
B2.reagents.add_reagent("ff-foam", 30)
|
|
|
|
beakers += B1
|
|
beakers += B2
|
|
|
|
/obj/item/chem_grenade/cleaner
|
|
name = "cleaner grenade"
|
|
desc = "BLAM!-brand foaming space cleaner. In a special applicator for rapid cleaning of wide areas."
|
|
icon = 'icons/obj/grenade.dmi'
|
|
icon_state = "cleaner"
|
|
icon_state_armed = "cleaner1"
|
|
stage = 2
|
|
|
|
New()
|
|
..()
|
|
var/obj/item/reagent_containers/glass/B1 = new(src)
|
|
var/obj/item/reagent_containers/glass/B2 = new(src)
|
|
|
|
B1.reagents.add_reagent("fluorosurfactant", 30)
|
|
B2.reagents.add_reagent("cleaner", 20)
|
|
B2.reagents.add_reagent("water", 30)
|
|
|
|
beakers += B1
|
|
beakers += B2
|
|
|
|
/obj/item/chem_grenade/fcleaner
|
|
name = "cleaner grenade"
|
|
desc = "BLAM!-brand foaming space cleaner. In a special applicator for rapid cleaning of wide areas."
|
|
icon = 'icons/obj/grenade.dmi'
|
|
icon_state = "cleaner"
|
|
icon_state_armed = "cleaner1"
|
|
stage = 2
|
|
|
|
New()
|
|
..()
|
|
var/obj/item/reagent_containers/glass/B1 = new(src)
|
|
var/obj/item/reagent_containers/glass/B2 = new(src)
|
|
|
|
B1.reagents.add_reagent("fluorosurfactant", 10)
|
|
B1.reagents.add_reagent("lube", 10)
|
|
|
|
B2.reagents.add_reagent("pacid", 10) //The syndicate are sending the strong stuff now -Spy
|
|
B2.reagents.add_reagent("water", 10)
|
|
|
|
beakers += B1
|
|
beakers += B2
|
|
|
|
/obj/item/chem_grenade/flashbang
|
|
name = "flashbang"
|
|
desc = "A standard stun grenade."
|
|
icon = 'icons/obj/grenade.dmi'
|
|
icon_state = "flashbang"
|
|
icon_state_armed = "flashbang1"
|
|
stage = 2
|
|
is_syndicate = 1
|
|
mats = 6
|
|
|
|
New()
|
|
..()
|
|
var/obj/item/reagent_containers/glass/B1 = new(src)
|
|
var/obj/item/reagent_containers/glass/B2 = new(src)
|
|
|
|
B1.reagents.add_reagent("aluminium", 10)
|
|
B1.reagents.add_reagent("potassium", 10)
|
|
B1.reagents.add_reagent("cola", 10)
|
|
B1.reagents.add_reagent("chlorine", 10)
|
|
|
|
B2.reagents.add_reagent("sulfur", 10)
|
|
B2.reagents.add_reagent("oxygen", 10)
|
|
B2.reagents.add_reagent("phosphorus", 10)
|
|
|
|
beakers += B1
|
|
beakers += B2
|
|
|
|
revolution //convertssss
|
|
explode()
|
|
if (ticker && ticker.mode && istype(ticker.mode, /datum/game_mode/revolution))
|
|
var/datum/game_mode/revolution/R = ticker.mode
|
|
var/min_dispersal = src.reagents.get_dispersal()
|
|
for (var/mob/M in range(max(min_dispersal,6), get_turf(src.loc)))
|
|
if (ishuman(M))
|
|
var/mob/living/carbon/human/H = M
|
|
var/safety = 0
|
|
if (H.eyes_protected_from_light() && H.ears_protected_from_sound())
|
|
safety = 1
|
|
|
|
if (safety == 0)
|
|
var/can_convert = 1
|
|
var/list/U = R.get_unconvertables()
|
|
if (!H.client || !H.mind)
|
|
can_convert = 0
|
|
else if (H.mind in U)
|
|
can_convert = 0
|
|
else if (H.mind in R.head_revolutionaries)
|
|
can_convert = 0
|
|
else
|
|
can_convert = 1
|
|
|
|
for (var/obj/item/implant/antirev/found_imp in H.implant)
|
|
found_imp.on_remove(H)
|
|
H.implant.Remove(found_imp)
|
|
qdel(found_imp)
|
|
|
|
playsound(H.loc, 'sound/impact_sounds/Crystal_Shatter_1.ogg', 50, 0.1, 0, 0.9)
|
|
H.visible_message("<span style=\"color:blue\">The loyalty implant inside [H] shatters into one million pieces!</span>")
|
|
|
|
if (can_convert && !(H.mind in R.revolutionaries))
|
|
R.add_revolutionary(H.mind)
|
|
|
|
..()
|
|
|
|
|
|
/obj/item/chem_grenade/cryo
|
|
name = "cryo grenade"
|
|
desc = "An experimental non-lethal grenade using cryogenic technologies."
|
|
icon = 'icons/obj/grenade.dmi'
|
|
icon_state = "cryo"
|
|
icon_state_armed = "cryo1"
|
|
stage = 2
|
|
|
|
New()
|
|
..()
|
|
var/obj/item/reagent_containers/glass/B1 = new(src)
|
|
|
|
B1.reagents.add_reagent("cryostylane", 35)
|
|
|
|
beakers += B1
|
|
|
|
/obj/item/chem_grenade/incendiary
|
|
name = "incendiary grenade"
|
|
desc = "A rather volatile grenade that creates a small fire."
|
|
icon = 'icons/obj/grenade.dmi'
|
|
icon_state = "incendiary"
|
|
icon_state_armed = "incendiary1"
|
|
stage = 2
|
|
|
|
New()
|
|
..()
|
|
var/obj/item/reagent_containers/glass/B1 = new(src)
|
|
B1.reagents.add_reagent("infernite", 20)
|
|
beakers += B1
|
|
|
|
/obj/item/chem_grenade/very_incendiary
|
|
name = "high range incendiary grenade"
|
|
desc = "A rather volatile grenade that creates a large fire."
|
|
icon = 'icons/obj/grenade.dmi'
|
|
icon_state = "high_range_incendiary"
|
|
icon_state_armed = "high_range_incendiary1"
|
|
stage = 2
|
|
|
|
New()
|
|
..()
|
|
var/obj/item/reagent_containers/glass/B1 = new(src)
|
|
B1.reagents.add_reagent("firedust", 20)
|
|
beakers += B1
|
|
|
|
/obj/item/chem_grenade/very_incendiary/vr
|
|
icon = 'icons/effects/VR.dmi'
|
|
icon_state = "chemg3"
|
|
icon_state_armed = "chemg4"
|
|
|
|
/obj/item/chem_grenade/shock
|
|
name = "shock grenade"
|
|
desc = "An arc flashing grenade that shocks everyone close by."
|
|
icon = 'icons/obj/grenade.dmi'
|
|
icon_state = "shock"
|
|
icon_state_armed = "shock1"
|
|
stage = 2
|
|
|
|
New()
|
|
..()
|
|
var/obj/item/reagent_containers/glass/B1 = new(src)
|
|
B1.reagents.add_reagent("voltagen", 40)
|
|
beakers += B1
|
|
|
|
/obj/item/chem_grenade/pepper
|
|
name = "crowd dispersal grenade"
|
|
desc = "An non-lethal grenade for use against protests, riots, vagrancy and loitering. Not to be used as a food additive."
|
|
icon = 'icons/obj/grenade.dmi'
|
|
icon_state = "pepper"
|
|
icon_state_armed = "pepper1"
|
|
stage = 2
|
|
|
|
New()
|
|
..()
|
|
var/obj/item/reagent_containers/glass/B1 = new(src)
|
|
var/obj/item/reagent_containers/glass/B2 = new(src)
|
|
|
|
B1.reagents.add_reagent("capsaicin", 25)
|
|
B1.reagents.add_reagent("water",25)
|
|
|
|
B2.reagents.add_reagent("fluorosurfactant", 25)
|
|
|
|
beakers += B1
|
|
beakers += B2
|
|
|
|
/obj/item/chem_grenade/sarin
|
|
name = "sarin gas grenade"
|
|
desc = "A smoke grenade containing an extremely lethal nerve agent. Use of this mixture constitutes a war crime, so... try not to leave any witnesses."
|
|
icon = 'icons/obj/grenade.dmi'
|
|
icon_state = "sarin"
|
|
icon_state_armed = "sarin1"
|
|
stage = 2
|
|
|
|
New()
|
|
..()
|
|
var/obj/item/reagent_containers/glass/B1 = new(src)
|
|
var/obj/item/reagent_containers/glass/B2 = new(src)
|
|
|
|
B1.reagents.add_reagent("sarin", 25)
|
|
B1.reagents.add_reagent("sugar",25)
|
|
|
|
B2.reagents.add_reagent("phosphorus", 25)
|
|
B2.reagents.add_reagent("potassium", 25)
|
|
|
|
beakers += B1
|
|
beakers += B2 |