From 13985d2f4fa1d2ab34860f4d3a97677d8762df82 Mon Sep 17 00:00:00 2001 From: ZomgPonies Date: Mon, 4 Nov 2013 14:31:58 -0500 Subject: [PATCH] Sayu grenade and assembly update --- baystation12.dme | 2 + code/WorkInProgress/Sayu/grenades.dm | 481 ++++++++++++++ code/WorkInProgress/Sayu/random_items.dm | 370 +++++++++++ .../items/weapons/grenades/chem_grenade.dm | 607 ++++++++++++------ .../objects/items/weapons/grenades/grenade.dm | 53 +- code/modules/assembly/assembly.dm | 12 +- code/modules/assembly/bomb.dm | 15 +- code/modules/assembly/holder.dm | 133 +--- code/modules/assembly/igniter.dm | 25 +- code/modules/assembly/infrared.dm | 40 +- code/modules/assembly/mousetrap.dm | 30 +- code/modules/assembly/proximity.dm | 37 +- code/modules/assembly/shock_kit.dm | 3 +- code/modules/assembly/signaler.dm | 67 +- code/modules/assembly/timer.dm | 56 +- code/modules/assembly/voice.dm | 44 ++ .../mob/living/carbon/human/human_defense.dm | 4 +- code/modules/mob/living/living_defense.dm | 4 +- 18 files changed, 1520 insertions(+), 463 deletions(-) create mode 100644 code/WorkInProgress/Sayu/grenades.dm create mode 100644 code/WorkInProgress/Sayu/random_items.dm create mode 100644 code/modules/assembly/voice.dm diff --git a/baystation12.dme b/baystation12.dme index 6bebcd7c8f2..855b8fb0c36 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -1376,7 +1376,9 @@ #include "code\WorkInProgress\Ported\policetape.dm" #include "code\WorkInProgress\Sayu\belt.dm" #include "code\WorkInProgress\Sayu\cargoprofile.dm" +#include "code\WorkInProgress\Sayu\grenades.dm" #include "code\WorkInProgress\Sayu\programmable.dm" +#include "code\WorkInProgress\Sayu\random_items.dm" #include "code\WorkInProgress\SkyMarshal\officer_stuff.dm" #include "code\WorkInProgress\SkyMarshal\Ultralight_procs.dm" #include "code\WorkInProgress\Yinadele\Supermatter.dm" diff --git a/code/WorkInProgress/Sayu/grenades.dm b/code/WorkInProgress/Sayu/grenades.dm new file mode 100644 index 00000000000..5a902401639 --- /dev/null +++ b/code/WorkInProgress/Sayu/grenades.dm @@ -0,0 +1,481 @@ +/obj/item/weapon/grenade/chem_grenade/dirt + payload_name = "dirt" + desc = "From the makers of BLAM! brand foaming space cleaner, this bomb guarantees steady work for any janitor." + stage = 2 + + New() + ..() + var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src) + var/list/muck = list("blood","carbon","flour","radium") + var/filth = pick(muck - "radium") // not usually radioactive + + B1.reagents.add_reagent(filth,25) + if(prob(25)) + B1.reagents.add_reagent(pick(muck - filth,25)) // but sometimes... + + beakers += B1 + + +/obj/item/weapon/grenade/chem_grenade/meat + payload_name = "meat" + desc = "Not always as messy as the name implies." + stage = 2 + + + New() + ..() + var/obj/item/weapon/reagent_containers/glass/beaker/large/B1 = new(src) + var/obj/item/weapon/reagent_containers/glass/beaker/large/B2 = new(src) + + B1.reagents.add_reagent("blood",60) + if(prob(5)) + B1.reagents.add_reagent("blood",1) // Quality control problems, causes a mess + B2.reagents.add_reagent("clonexadone",30) + + beakers += B1 + beakers += B2 + +/obj/item/weapon/grenade/chem_grenade/holywater + payload_name = "holy water" + desc = "Then shalt thou count to three, no more, no less." + stage = 2 + det_time = 30 + + New() + ..() + var/obj/item/weapon/reagent_containers/glass/beaker/large/B = new(src) + B.reagents.add_reagent("holywater",100) + beakers += B + +/obj/item/weapon/grenade/chem_grenade/soap + payload_name = "soap" + desc = "Not necessarily as clean as the name implies." + stage = 2 + + New() + ..() + var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src) + var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src) + + B1.reagents.add_reagent("cornoil",60) + B2.reagents.add_reagent("enzyme",5) + B2.reagents.add_reagent("ammonia",30) + + beakers += B1 + beakers += B2 + update_icon() + +/obj/item/weapon/grenade/chem_grenade/drugs + payload_name = "miracle" + desc = "How does it work?" + stage = 2 + + New() + ..() + var/obj/item/weapon/reagent_containers/glass/beaker/large/B1 = new(src) + var/obj/item/weapon/reagent_containers/glass/beaker/large/B2 = new(src) + + B1.reagents.add_reagent("space_drugs", 25) + B1.reagents.add_reagent("mindbreaker", 25) + B1.reagents.add_reagent("potassium", 25) + B2.reagents.add_reagent("phosphorus", 25) + B2.reagents.add_reagent("sugar", 25) + + beakers += B1 + beakers += B2 + update_icon() + +/obj/item/weapon/grenade/chem_grenade/ethanol + payload_name = "ethanol" + desc = "Ach, that hits the spot." + stage = 2 + + New() + ..() + var/obj/item/weapon/reagent_containers/glass/beaker/large/B1 = new(src) + var/obj/item/weapon/reagent_containers/glass/beaker/large/B2 = new(src) + + B1.reagents.add_reagent("ethanol", 75) + B1.reagents.add_reagent("potassium", 25) + B2.reagents.add_reagent("phosphorus", 25) + B2.reagents.add_reagent("sugar", 25) + B2.reagents.add_reagent("ethanol", 25) + + beakers += B1 + beakers += B2 + update_icon() + +// ------------------------------------- +// Grenades using new grenade assemblies +// ------------------------------------- +/obj/item/weapon/grenade/chem_grenade/lube + payload_name = "lubricant" + stage = 2 + + New() + ..() + var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src) + B1.reagents.add_reagent("lube",50) + beakers += B1 +/obj/item/weapon/grenade/chem_grenade/lube/remote + New() + ..() + CreateDefaultTrigger(/obj/item/device/assembly/signaler) +/obj/item/weapon/grenade/chem_grenade/lube/prox + New() + ..() + CreateDefaultTrigger(/obj/item/device/assembly/prox_sensor) +/obj/item/weapon/grenade/chem_grenade/lube/tripwire + New() + ..() + CreateDefaultTrigger(/obj/item/device/assembly/infra) + + +// Basic explosion grenade +/obj/item/weapon/grenade/chem_grenade/explosion + payload_name = "conventional" + stage = 2 + + New() + ..() + var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src) + var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src) + B1.reagents.add_reagent("glycerol",30) // todo: someone says NG is overpowered, test. + B1.reagents.add_reagent("sacid",15) + B2.reagents.add_reagent("sacid",15) + B2.reagents.add_reagent("pacid",30) + beakers += B1 + beakers += B2 + +// Assembly Variants +/obj/item/weapon/grenade/chem_grenade/explosion/remote + New() + ..() + CreateDefaultTrigger(/obj/item/device/assembly/signaler) + +/obj/item/weapon/grenade/chem_grenade/explosion/prox + New() + ..() + CreateDefaultTrigger(/obj/item/device/assembly/prox_sensor) + +/obj/item/weapon/grenade/chem_grenade/explosion/mine + New() + ..() + CreateDefaultTrigger(/obj/item/device/assembly/mousetrap) + +// Basic EMP grenade +/obj/item/weapon/grenade/chem_grenade/emp + payload_name = "EMP" + stage = 2 + + New() + ..() + var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src) + var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src) + B1.reagents.add_reagent("uranium",50) + B2.reagents.add_reagent("iron",50) + beakers += B1 + beakers += B2 + +// Assembly Variants +/obj/item/weapon/grenade/chem_grenade/emp/remote + New() + ..() + CreateDefaultTrigger(/obj/item/device/assembly/signaler) + +/obj/item/weapon/grenade/chem_grenade/emp/prox + New() + ..() + CreateDefaultTrigger(/obj/item/device/assembly/prox_sensor) + +/obj/item/weapon/grenade/chem_grenade/emp/mine + New() + ..() + CreateDefaultTrigger(/obj/item/device/assembly/mousetrap) + +// -------------------------------------- +// Dangerous slime core grenades +// -------------------------------------- +/* +/obj/item/weapon/grenade/chem_grenade/large/bluespace + payload_name = "bluespace slime" + desc = "A standard grenade casing containing weaponized slime extract." + stage = 2 + + New() + ..() + var/obj/item/slime_extract/bluespace/B1 = new(src) + B1.Uses = rand(1,3) + var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src) + B2.reagents.add_reagent("plasma",5 * B1.Uses) + beakers += B1 + beakers += B2 + +/obj/item/weapon/grenade/chem_grenade/large/bluespace/prox + New() + ..() + CreateDefaultTrigger(/obj/item/device/assembly/prox_sensor) + +/obj/item/weapon/grenade/chem_grenade/large/bluespace/mine + New() + ..() + CreateDefaultTrigger(/obj/item/device/assembly/mousetrap) + +/obj/item/weapon/grenade/chem_grenade/large/bluespace/remote + New() + ..() + CreateDefaultTrigger(/obj/item/device/assembly/signaler) +*/ + +/obj/item/weapon/grenade/chem_grenade/large/monster + payload_name = "gold slime" + desc = "A standard grenade containing weaponized slime extract." + stage = 2 + + New() + ..() + var/obj/item/slime_extract/gold/B1 = new(src) + B1.Uses = rand(1,3) + var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src) + B2.reagents.add_reagent("plasma",5 * B1.Uses) + beakers += B1 + beakers += B2 + +/obj/item/weapon/grenade/chem_grenade/large/monster/prox + New() + ..() + CreateDefaultTrigger(/obj/item/device/assembly/prox_sensor) + +/obj/item/weapon/grenade/chem_grenade/large/monster/mine + New() + ..() + CreateDefaultTrigger(/obj/item/device/assembly/mousetrap) + +/obj/item/weapon/grenade/chem_grenade/large/monster/remote + New() + ..() + CreateDefaultTrigger(/obj/item/device/assembly/signaler) + +/obj/item/weapon/grenade/chem_grenade/large/feast + payload_name = "silver slime" + desc = "A standard grenade containing weaponized slime extract." + stage = 2 + + New() + ..() + var/obj/item/slime_extract/silver/B1 = new(src) + B1.Uses = rand(1,3) + var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src) + B2.reagents.add_reagent("plasma",5 * B1.Uses) + beakers += B1 + beakers += B2 + +// Slime Clusterbusters +/*/obj/item/weapon/grenade/clusterbuster/bluespace + name = "Bluespace Megabomb" + desc = "Widely regarded as proof that while there is a God, He is Insane." + payload = /obj/item/weapon/grenade/chem_grenade/large/bluespace*/ + +/obj/item/weapon/grenade/clusterbuster/monster + name = "Monster Megabomb" + desc = "Widely regarded as proof that there is no God." + payload = /obj/item/weapon/grenade/chem_grenade/large/monster + +// -------------------------------------- +// Syndie Kits +// -------------------------------------- + +/obj/item/weapon/storage/box/syndie_kit/remotegrenade + name = "Remote Grenade Kit" + New() + ..() + new /obj/item/weapon/grenade/chem_grenade/explosion/remote(src) + new /obj/item/device/multitool(src) // used to adjust the chemgrenade's signaller + new /obj/item/device/assembly/signaler(src) + return +/obj/item/weapon/storage/box/syndie_kit/remoteemp + name = "Remote EMP Kit" + New() + ..() + new /obj/item/weapon/grenade/chem_grenade/emp/remote(src) + new /obj/item/device/multitool(src) // used to adjust the chemgrenade's signaller + new /obj/item/device/assembly/signaler(src) + return +/obj/item/weapon/storage/box/syndie_kit/remotelube + name = "Remote Lube Kit" + New() + ..() + new /obj/item/weapon/grenade/chem_grenade/lube(src) + new /obj/item/device/multitool(src) // used to adjust the chemgrenade's signaller + new /obj/item/device/assembly/signaler(src) + return +// -------------------------------------- +// Clusterbuster Variable Payload Grenade +// Adapted from flashbang/clusterbang +// -------------------------------------- + +/obj/item/weapon/grenade/clusterbuster + desc = "This highly intimidating bunch of hardware seems eager to be let loose." + name = "Clusterbang" + icon = 'icons/obj/grenade.dmi' + icon_state = "clusterbang" + var/payload = /obj/item/weapon/grenade/flashbang + + +// Subtypes + +// Serious grenades +/obj/item/weapon/grenade/clusterbuster/explosion + name = "Cluster Grenade" + payload = /obj/item/weapon/grenade/chem_grenade/explosion +/obj/item/weapon/grenade/clusterbuster/emp + name = "Electromagnetic Storm" + payload = /obj/item/weapon/grenade/chem_grenade/emp +/obj/item/weapon/grenade/clusterbuster/smoke + name = "Ninja Vanish" + payload = /obj/item/weapon/grenade/smokebomb + +// Not serious grenades +/obj/item/weapon/grenade/clusterbuster/meat + name = "Mega Meat Grenade" + payload = /obj/item/weapon/grenade/chem_grenade/meat +/obj/item/weapon/grenade/clusterbuster/booze + name = "Booze Grenade" + payload = /obj/item/weapon/reagent_containers/food/drinks/bottle/random_drink +/obj/item/weapon/grenade/clusterbuster/honk + name = "Mega Honk Grenade" + payload = /obj/item/weapon/bananapeel +/obj/item/weapon/grenade/clusterbuster/xmas + name = "Christmas Miracle" + payload = /obj/item/weapon/a_gift +/obj/item/weapon/grenade/clusterbuster/soap + name = "Megamaid's Passive-Aggressive Soap-creation Grenade" + payload = /obj/item/weapon/grenade/chem_grenade/soap +/obj/item/weapon/grenade/clusterbuster/dirt + name = "Megamaid's Job Security Grenade" + payload = /obj/effect/decal/cleanable/random +/obj/item/weapon/grenade/clusterbuster/megadirt + name = "Megamaid's Revenge Grenade" + payload = /obj/item/weapon/grenade/chem_grenade/dirt +/obj/item/weapon/grenade/clusterbuster/inferno + name = "Little Boy" + payload = /obj/item/weapon/grenade/chem_grenade/incendiary +/obj/item/weapon/grenade/clusterbuster/apocalypsefake + name = "Fun Bomb" + desc = "Not like the other bomb." + payload = /obj/item/toy/spinningtoy + +// Grenades that should never see the light of day +/obj/item/weapon/grenade/clusterbuster/apocalypse + name = "Apocalypse Bomb" + desc = "No matter what, do not EVER use this." + payload = /obj/machinery/singularity + +/obj/item/weapon/grenade/clusterbuster/ultima + name = "Earth Shattering Kaboom" + desc = "Contains one Aludium Q-36 explosive space modulator." + payload = /obj/item/weapon/grenade/chem_grenade/explosion + +/obj/item/weapon/grenade/clusterbuster/lube + name = "Newton's First Law" + desc = "An object in motion remains in motion." + payload = /obj/item/weapon/grenade/chem_grenade/lube + + +/*/obj/item/weapon/grenade/clusterbuster/bluespace + name = "Maximum Warp" + desc = "Spacetime: Nice job breaking it, hero." + payload = /obj/item/weapon/grenade/chem_grenade/large/bluespace*/ +/obj/item/weapon/grenade/clusterbuster/monster + name = "The Monster Mash" + desc = "It's a graveyeard smash." + payload = /obj/item/weapon/grenade/chem_grenade/large/monster +/obj/item/weapon/grenade/clusterbuster/banquet + name = "Bork Bork Bonanza" + desc = "Bork bork bork." + payload = /obj/item/weapon/grenade/clusterbuster/banquet/child + child + payload = /obj/item/weapon/grenade/chem_grenade/large/feast + +// Mob spawning grenades +/obj/item/weapon/grenade/clusterbuster/aviary + name = "Poly-Poly Grenade" + desc = "That's an uncomfortable number of birds." + payload = /mob/living/simple_animal/parrot +/obj/item/weapon/grenade/clusterbuster/monkey + name = "Barrel of Monkeys" + desc = "Not really that much fun." + payload = /mob/living/carbon/monkey +/obj/item/weapon/grenade/clusterbuster/fluffy + name = "Fluffy Love Bomb" + desc = "Exactly as snuggly as it sounds." + payload = /mob/living/simple_animal/corgi/puppy + +/obj/item/weapon/grenade/clusterbuster/prime() + var/numspawned = rand(4,8) + var/again = 0 + for(var/more = numspawned,more > 0,more--) + if(prob(35)) + again++ + numspawned -- + + for(,numspawned > 0, numspawned--) + spawn(0) + new /obj/item/weapon/grenade/clusterbuster/node(src.loc,payload,name)//Launches payload + playsound(src.loc, 'sound/weapons/armbomb.ogg', 75, 1, -3) + + for(,again > 0, again--) + spawn(0) + new /obj/item/weapon/grenade/clusterbuster/segment(src.loc,payload,name)//Creates a 'segment' that launches more payloads + playsound(src.loc, 'sound/weapons/armbomb.ogg', 75, 1, -3) + spawn(0) + del(src) + return + +/obj/item/weapon/grenade/clusterbuster/segment + desc = "What's happening? Aaah!" + name = "clusterbuster segment" + icon = 'icons/obj/grenade.dmi' + icon_state = "clusterbang_segment" + +/obj/item/weapon/grenade/clusterbuster/segment/New(var/turf/newloc,var/T,var/N)//Segments should never exist except part of the clusterbang, since these immediately 'do their thing' and asplode + icon_state = "clusterbang_segment_active" + active = 1 + payload = T + name = N + var/stepdist = rand(1,5) //How far to step + var/temploc = src.loc //Saves the current location to know where to step away from + walk_away(src,temploc,stepdist) //I must go, my people need me + var/dettime = rand(15,60) + spawn(dettime) + prime() + +/obj/item/weapon/grenade/clusterbuster/segment/prime() + var/numspawned = rand(4,8) + for(var/more = numspawned,more > 0,more--) + if(prob(35)) + numspawned -- + + for(,numspawned > 0, numspawned--) + new /obj/item/weapon/grenade/clusterbuster/node(src.loc,payload) + spawn(0) + playsound(src.loc, 'sound/weapons/armbomb.ogg', 75, 1, -3) + del(src) + return + +/obj/item/weapon/grenade/clusterbuster/node/New(var/turf/newloc,var/T,var/N) + icon_state = "flashbang_active" + active = 1 + payload = T + name = N + var/stepdist = rand(1,4) + var/temploc = src.loc + walk_away(src,temploc,stepdist) + var/dettime = rand(15,60) + spawn(dettime) + var/atom/A = new payload(loc) + if(istype(A,/obj/item/weapon/grenade)) + A:prime() + if(istype(A,/obj/machinery/singularity)) // I can't emphasize enough how much you should never use this grenade + A:energy = 200 + del src diff --git a/code/WorkInProgress/Sayu/random_items.dm b/code/WorkInProgress/Sayu/random_items.dm new file mode 100644 index 00000000000..275cfe44d94 --- /dev/null +++ b/code/WorkInProgress/Sayu/random_items.dm @@ -0,0 +1,370 @@ +// ------------------------------------- +// Generates an innocuous toy +// ------------------------------------- +/obj/item/toy/random + name = "Random Toy" + New() + ..() + var/list/types = list(/obj/item/toy/crossbow,/obj/item/toy/balloon,/obj/item/toy/spinningtoy,/obj/item/weapon/reagent_containers/spray/waterflower) + typesof(/obj/item/toy/prize) - /obj/item/toy/prize + var/T = pick(types) + new T(loc) + spawn(1) + del src + +// ------------------------------------- +// Random cleanables, clearly this makes sense +// ------------------------------------- + +/obj/effect/decal/cleanable/random + name = "Random Mess" + New() + ..() + var/list/list = typesof(/obj/effect/decal/cleanable) - list(/obj/effect/decal/cleanable,/obj/effect/decal/cleanable/random,/obj/effect/decal/cleanable/cobweb,/obj/effect/decal/cleanable/cobweb2) + var/T = pick(list) + new T(loc) + spawn(0) + del src + + +/obj/item/stack/sheet/animalhide/random + name = "Random animal hide" + New() + ..() + spawn(1) + var/htype = pick(/obj/item/stack/sheet/animalhide/cat,/obj/item/stack/sheet/animalhide/corgi,/obj/item/stack/sheet/animalhide/human,/obj/item/stack/sheet/animalhide/lizard,/obj/item/stack/sheet/animalhide/monkey) + var/obj/item/stack/S = new htype(loc) + S.amount = amount + del src + +// ------------------------------------- +// Not yet identified chemical. +// Could be anything! +// ------------------------------------- + +/obj/item/weapon/reagent_containers/glass/bottle/random_reagent + name = "unlabelled bottle" +// identify_probability = 0 + New() + ..() + var/datum/reagent/R = pick(chemical_reagents_list) + var/global/list/rare_chems = list("minttoxin","nanites","xenomicrobes","adminordrazine") + if(R == "blood" && prob(50)) // in contrast to pills, it is entirely reasonable to have vials of virus-free blood lying around. + var/datum/disease/advance/F = new(0) // By entirely reasonable I mean even odds. Let's not get crazy, here. + var/list/data = list("viruses"= list(F)) + reagents.add_reagent(R,volume,data) + else + if(rare_chems.Find(R)) + reagents.add_reagent(R,10) + else + reagents.add_reagent(R,rand(2,3)*10) + pixel_x = rand(-10,10) + pixel_y = rand(-10,10) + +//Cuts out the food and drink reagents +/obj/item/weapon/reagent_containers/glass/bottle/random_chem + name = "unlabelled chemical bottle" +// identify_probability = 0 + New() + ..() + var/global/list/chems_only = list("slimejelly","blood","water","lube","anti_toxin","toxin","cyanide","stoxin","inaprovaline","space_drugs","serotrotium","oxygen","copper","nitrogen","hydrogen","potassium","mercury","sulfur","carbon","chlorine","fluorine","sodium","phosphorus","lithium","sugar","sacid","pacid","glycerol","radium","ryetalyn","thermite","mutagen","virusfood","iron","gold","silver","uranium","aluminum","silicon","fuel","cleaner","plantbgone","plasma","leporazine","cryptobiolin","lexorin","kelotane","dermaline","dexalin","dexalinp","tricordrazine","synaptizine","impedrezene","hyronalin","arithrazine","alkysine","imidazoline","bicaridine","hyperzine","cryoxadone","clonexadone","spaceacillin","carpotoxin","zombiepowder","mindbreaker","fluorosurfactant","foaming_agent","ethanol","ammonia","diethylamine","ethylredoxrazine","chloralhydrate","lipozine","condensedcapsaicin","frostoil","amatoxin","psilocybin","enzyme","nothing","doctorsdelight","antifreeze","neurotoxin") + var/global/list/rare_chems = list("minttoxin","nanites","xenomicrobes","adminordrazine") + + var/datum/reagent/R = pick(chems_only + rare_chems) + if(R == "blood" && prob(50)) + var/datum/disease/advance/F = new(0) + var/list/data = list("viruses"= list(F)) + reagents.add_reagent(R,volume,data) + else + if(rare_chems.Find(R)) + reagents.add_reagent(R,10) + else + reagents.add_reagent(R,rand(2,3)*10) + name = "unlabelled bottle" + pixel_x = rand(-10,10) + pixel_y = rand(-10,10) + +/obj/item/weapon/reagent_containers/glass/bottle/random_base_chem + name = "unlabelled chemical bottle" +// identify_probability = 0 + New() + ..() + var/global/list/base_chems = list("water","oxygen","nitrogen","hydrogen","potassium","mercury","carbon","chlorine","fluorine","phosphorus","lithium","sulfur","sacid","radium","iron","aluminum","silicon","sugar","ethanol") + var/datum/reagent/R = pick(base_chems) + reagents.add_reagent(R,rand(2,6)*5) + name = "unlabelled bottle" + pixel_x = rand(-10,10) + pixel_y = rand(-10,10) +/obj/item/weapon/reagent_containers/food/drinks/bottle/random_drink + name = "unlabelled drink" + icon = 'icons/obj/drinks.dmi' + New() + ..() + var/list/drinks_only = list("beer2","hot_coco","orangejuice","tomatojuice","limejuice","carrotjuice","berryjuice","poisonberryjuice","watermelonjuice","lemonjuice","banana","nothing","potato","milk","soymilk","cream","coffee","tea","icecoffee","icetea","cola","nuka_cola","spacemountainwind","thirteenloko","dr_gibb","space_up","lemon_lime","beer","whiskey","gin","rum","vodka","holywater","tequilla","vermouth","wine","tonic","kahlua","cognac","hooch","ale","sodawater","ice","bilk","atomicbomb","threemileisland","goldschlager","patron","gintonic","cubalibre","whiskeycola","martini","vodkamartini","whiterussian","screwdrivercocktail","booger","bloodymary","gargleblaster","bravebull","tequillasunrise","toxinsspecial","beepskysmash","doctorsdelight","irishcream","manlydorf","longislandicedtea","moonshine","b52","irishcoffee","margarita","blackrussian","manhattan","manhattan_proj","whiskeysoda","antifreeze","barefoot","snowwhite","demonsblood","vodkatonic","ginfizz","bahama_mama","singulo","sbiten","devilskiss","red_mead","mead","iced_beer","grog","aloe","andalusia","alliescocktail","soy_latte","cafe_latte","acidspit","amasec","neurotoxin","hippiesdelight","bananahonk","silencer","changelingsting","irishcarbomb","syndicatebomb","erikasurprise","driestmartini") + if(prob(50)) + drinks_only += list("chloralhydrate","adminordrazine","mindbreaker","tricordrazine","blood") + + var/datum/reagent/R = pick(drinks_only) + if(R == "blood" && prob(40)) // it's entirely natural for you to have blood in drinking bottles. + var/datum/disease/advance/F = new(0) // it only rarely has to do with diseases. + var/list/data = list("viruses"= list(F)) + reagents.add_reagent(R,volume,data) + else + reagents.add_reagent(R,volume) + name = "unlabelled bottle" + icon_state = pick("alco-white","alco-green","alco-blue","alco-clear","alco-red") + pixel_x = rand(-5,5) + pixel_y = rand(-5,5) +/obj/item/weapon/reagent_containers/food/drinks/bottle/random_reagent // Same as the chembottle code except the container + name = "unlabelled drink?" + icon = 'icons/obj/drinks.dmi' + New() + ..() + var/datum/reagent/R = pick(chemical_reagents_list) + var/global/list/rare_chems = list("minttoxin","nanites","xenomicrobes","adminordrazine") + if(R == "blood" && prob(50)) + var/datum/disease/advance/F = new(0) + var/list/data = list("viruses"= list(F)) + reagents.add_reagent(R,volume,data) + else + if(rare_chems.Find(R)) + reagents.add_reagent(R,10) + else + reagents.add_reagent(R,rand(3,10)*10) + name = "unlabelled bottle" + icon_state = pick("alco-white","alco-green","alco-blue","alco-clear","alco-red") + pixel_x = rand(-5,5) + pixel_y = rand(-5,5) + spawn(0) + del src + +/obj/item/weapon/storage/pill_bottle/random_meds + name = "unlabelled pillbottle" + desc = "The sheer recklessness of this bottle's existence astounds you." + + New() + ..() + var/global/list/meds_only = list("anti_toxin","toxin","cyanide","stoxin","inaprovaline","space_drugs","serotrotium","ryetalyn","mutagen","leporazine","cryptobiolin","lexorin","kelotane","dermaline","dexalin","dexalinp","tricordrazine","synaptizine","impedrezene","hyronalin","arithrazine","alkysine","imidazoline","bicaridine","hyperzine","spaceacillin","carpotoxin","zombiepowder","mindbreaker","ethanol","ammonia","diethylamine","ethylredoxrazine","chloralhydrate","lipozine","condensedcapsaicin","frostoil","amatoxin","psilocybin","nothing","doctorsdelight","neurotoxin") + var/global/list/rare_meds = list("nanites","xenomicrobes","minttoxin","adminordrazine","blood") + + var/i = 1 + while(i < storage_slots) + + var/datum/reagent/R + if(prob(50)) + R = pick(meds_only + rare_meds) + else + R = pick(meds_only) + var/obj/item/weapon/reagent_containers/pill/P = new(src) + if(R == "blood") // 100% disease chance. Why else would you make a blood pill? I can think of nothing. + var/datum/disease/advance/F = new(0) // okay maybe vampires but that's about it + var/list/data = list("viruses"= list(F)) + P.reagents.add_reagent(R,P.volume,data) + else + if(rare_meds.Find(R)) + P.reagents.add_reagent(R,10) + else + P.reagents.add_reagent(R,rand(2,5)*10) + P.name = "Unlabelled Pill" + P.desc = "Something about this pill entices you to try it, against your better judgement." + i++ + pixel_x = rand(-10,10) + pixel_y = rand(-10,10) + return + +// ------------------------------------- +// Containers full of unknown crap +// ------------------------------------- + +/obj/structure/closet/crate/secure/unknownchemicals + name = "Grey-market Chemicals Grab Pack" + desc = "Crate full of chemicals of unknown type and value from a 'trusted' source." + req_one_access = list(access_chemistry,access_research,access_qm) // the qm knows a guy, you see. + + New() + ..() + sleep(2) + new/obj/item/weapon/reagent_containers/glass/bottle/random_base_chem(src) + new/obj/item/weapon/reagent_containers/glass/bottle/random_base_chem(src) + new/obj/item/weapon/reagent_containers/glass/bottle/random_base_chem(src) + new/obj/item/weapon/reagent_containers/glass/bottle/random_base_chem(src) + new/obj/item/weapon/reagent_containers/glass/bottle/random_base_chem(src) + new/obj/item/weapon/reagent_containers/glass/bottle/random_base_chem(src) + new/obj/item/weapon/reagent_containers/glass/bottle/random_base_chem(src) + new/obj/item/weapon/reagent_containers/glass/bottle/random_chem(src) + new/obj/item/weapon/reagent_containers/glass/bottle/random_chem(src) + new/obj/item/weapon/reagent_containers/glass/bottle/random_chem(src) + while(prob(50)) + new/obj/item/weapon/reagent_containers/glass/bottle/random_reagent(src) + + new/obj/item/weapon/storage/pill_bottle/random_meds(src) + while(prob(25)) + new/obj/item/weapon/storage/pill_bottle/random_meds(src) + return + +/obj/structure/closet/crate/secure/chemicals + name = "Chemical Supply Kit" + desc = "Full of basic chemistry supplies." + req_one_access = list(access_chemistry,access_research) + + New() + ..() + sleep(2) + var/global/list/base_chems = list("water","oxygen","nitrogen","hydrogen","potassium","mercury","carbon","chlorine","fluorine","phosphorus","lithium","sulfur","sacid","radium","iron","aluminum","silicon","sugar","ethanol") + for(var/chem in base_chems) + var/obj/item/weapon/reagent_containers/glass/bottle/B = new(src) + B.reagents.add_reagent(chem,B.volume) + if(prob(85)) + var/datum/reagent/r = chemical_reagents_list[chem] + B.name = "[r.name] bottle" +// B.identify_probability = 100 + else + B.name = "unlabelled bottle" + B.desc = "Looks like the label fell off." +// B.identify_probability = 0 + + +/obj/structure/closet/crate/bin/flowers + name = "flower barrel" + desc = "A bin full of fresh flowers for the bereaved." + anchored = 0 + New() + while(contents.len < 10) + var/flowertype = pick(/obj/item/weapon/grown/sunflower,/obj/item/weapon/grown/novaflower,/obj/item/weapon/reagent_containers/food/snacks/grown/poppy, + /obj/item/weapon/reagent_containers/food/snacks/grown/harebell,/obj/item/weapon/reagent_containers/food/snacks/grown/moonflower) + var/atom/movable/AM = new flowertype(src) + AM.pixel_x = rand(-10,10) + AM.pixel_y = rand(-5,5) + + +/obj/structure/closet/crate/bin/plants + name = "plant barrel" + desc = "Caution: Contents may contain vitamins and minerals. It is recommended that you deep fry them before eating." + anchored = 0 + New() + while(contents.len < 10) + var/ptype = pick(/obj/item/weapon/reagent_containers/food/snacks/grown/apple,/obj/item/weapon/reagent_containers/food/snacks/grown/banana, + /obj/item/weapon/reagent_containers/food/snacks/grown/berries, /obj/item/weapon/reagent_containers/food/snacks/grown/cabbage, + /obj/item/weapon/reagent_containers/food/snacks/grown/carrot, /obj/item/weapon/reagent_containers/food/snacks/grown/cherries, + /obj/item/weapon/reagent_containers/food/snacks/grown/chili, /obj/item/weapon/reagent_containers/food/snacks/grown/cocoapod, + /obj/item/weapon/reagent_containers/food/snacks/grown/corn, /obj/item/weapon/reagent_containers/food/snacks/grown/eggplant, + /obj/item/weapon/reagent_containers/food/snacks/grown/grapes, /obj/item/weapon/reagent_containers/food/snacks/grown/greengrapes, + /obj/item/weapon/reagent_containers/food/snacks/grown/icepepper, /obj/item/weapon/reagent_containers/food/snacks/grown/lemon, + /obj/item/weapon/reagent_containers/food/snacks/grown/lime, /obj/item/weapon/reagent_containers/food/snacks/grown/orange, + /obj/item/weapon/reagent_containers/food/snacks/grown/potato, /obj/item/weapon/reagent_containers/food/snacks/grown/pumpkin, + /obj/item/weapon/reagent_containers/food/snacks/grown/soybeans, /obj/item/weapon/reagent_containers/food/snacks/grown/sugarcane, + /obj/item/weapon/reagent_containers/food/snacks/grown/tomato, /obj/item/weapon/reagent_containers/food/snacks/grown/watermelon, + /obj/item/weapon/reagent_containers/food/snacks/grown/wheat, /obj/item/weapon/reagent_containers/food/snacks/grown/whitebeet, + /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/chanterelle, /obj/item/weapon/reagent_containers/food/snacks/grown/mushroom/plumphelmet) + var/obj/O = new ptype(src) + O.pixel_x = rand(-10,10) + O.pixel_y = rand(-5,5) + +/obj/structure/closet/secure_closet/random_drinks + name = "Unlabelled Booze" + req_access = list(access_bar) + icon_state = "cabinetdetective_locked" + icon_closed = "cabinetdetective" + icon_locked = "cabinetdetective_locked" + icon_opened = "cabinetdetective_open" + icon_broken = "cabinetdetective_broken" + icon_off = "cabinetdetective_broken" + + New() + ..() + sleep(2) + new/obj/item/weapon/reagent_containers/food/drinks/bottle/random_drink(src) + new/obj/item/weapon/reagent_containers/food/drinks/bottle/random_drink(src) + new/obj/item/weapon/reagent_containers/food/drinks/bottle/random_drink(src) + new/obj/item/weapon/reagent_containers/food/drinks/bottle/random_drink(src) + new/obj/item/weapon/reagent_containers/food/drinks/bottle/random_drink(src) + while(prob(25)) + new/obj/item/weapon/reagent_containers/food/drinks/bottle/random_reagent(src) + return + + +// ------------------------------------- +// Do not order this. +// If you order this, do not open it. +// If you open this, run. +// If you didn't run, pray. +// ------------------------------------- + +/obj/structure/largecrate/evil + name = "\improper Mysterious Crate" + desc = "What could it be?" + + attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/crowbar)) + var/list/menace = pick( /mob/living/simple_animal/hostile/carp,/mob/living/simple_animal/hostile/faithless,/mob/living/simple_animal/hostile/pirate, + /mob/living/simple_animal/hostile/creature,/mob/living/simple_animal/hostile/pirate/ranged, + /mob/living/simple_animal/hostile/hivebot,/mob/living/simple_animal/hostile/viscerator,/mob/living/simple_animal/hostile/pirate) + + visible_message("\red Something falls out of the [src]!") + var/obj/item/weapon/grenade/flashbang/clusterbang/C = new(src.loc) + C.prime() + spawn(10) + new menace(src.loc) + while(prob(15)) + new menace(get_step_rand(src.loc)) + ..() + else + ..() + + +// +// +// +// ??? +// +// +// + +/obj/structure/largecrate/schrodinger + name = "Schrodinger's Crate" + desc = "What happens if you open it?" + + attackby(obj/item/weapon/W as obj, mob/user as mob) + if(istype(W, /obj/item/weapon/crowbar)) + var/mob/living/simple_animal/cat/Cat1 = new(loc) + Cat1.apply_damage(250)//,TOX) + Cat1.name = "Schrodinger's Cat" + Cat1.desc = "It seems it's been dead for a while." + + var/mob/living/simple_animal/cat/Cat2 = new(loc) + Cat2.name = "Schrodinger's Cat" + Cat2.desc = "It's was alive the whole time!" + sleep(2) + if(prob(50)) + del Cat1 + else + del Cat2 + ..() + +// -------------------------------------- +// Collen's box of wonder and mystery +// -------------------------------------- +/obj/item/weapon/storage/box/grenades + name = "tactical grenades" + desc = "A box with 6 tactical grenades." + icon_state = "flashbang" + var/list/grenadelist = list(/obj/item/weapon/grenade/chem_grenade/metalfoam, /obj/item/weapon/grenade/chem_grenade/incendiary, + /obj/item/weapon/grenade/chem_grenade/antiweed, /obj/item/weapon/grenade/chem_grenade/cleaner, /obj/item/weapon/grenade/chem_grenade/teargas, + /obj/item/weapon/grenade/chem_grenade/holywater, /obj/item/weapon/grenade/chem_grenade/soap, /obj/item/weapon/grenade/chem_grenade/meat, + /obj/item/weapon/grenade/chem_grenade/dirt, /obj/item/weapon/grenade/chem_grenade/lube, /obj/item/weapon/grenade/smokebomb, + /obj/item/weapon/grenade/chem_grenade/drugs, /obj/item/weapon/grenade/chem_grenade/ethanol) // holy list batman + + New() + ..() + var/nade1 = pick(grenadelist) + var/nade2 = pick(grenadelist) + var/nade3 = pick(grenadelist) + var/nade4 = pick(grenadelist) + var/nade5 = pick(grenadelist) + var/nade6 = pick(grenadelist) + + new nade1(src) + new nade2(src) + new nade3(src) + new nade4(src) + new nade5(src) + new nade6(src) \ No newline at end of file diff --git a/code/game/objects/items/weapons/grenades/chem_grenade.dm b/code/game/objects/items/weapons/grenades/chem_grenade.dm index 61dd84935c4..b8ac280f7e5 100644 --- a/code/game/objects/items/weapons/grenades/chem_grenade.dm +++ b/code/game/objects/items/weapons/grenades/chem_grenade.dm @@ -1,190 +1,392 @@ +#define EMPTY 0 +#define WIRED 1 +#define READY 2 + /obj/item/weapon/grenade/chem_grenade - name = "Grenade Casing" + name = "grenade casing" + desc = "A do it yourself grenade casing!" icon_state = "chemg" item_state = "flashbang" - desc = "A hand made chemical grenade." - w_class = 2.0 - force = 2.0 - var/stage = 0 - var/state = 0 - var/path = 0 - var/obj/item/device/assembly_holder/detonator = null - var/list/beakers = new/list() - var/list/allowed_containers = list(/obj/item/weapon/reagent_containers/glass/beaker, /obj/item/weapon/reagent_containers/glass/beaker/large, /obj/item/weapon/reagent_containers/glass/bottle) + var/bomb_state = "chembomb" + var/payload_name = null // used for spawned grenades + w_class = 2 + force = 2 + var/stage = EMPTY + var/list/beakers = list() + var/list/allowed_containers = list(/obj/item/weapon/reagent_containers/glass/beaker, /obj/item/weapon/reagent_containers/glass/bottle) var/affected_area = 3 + var/obj/item/device/assembly_holder/nadeassembly = null + var/label = null - New() - var/datum/reagents/R = new/datum/reagents(1000) - reagents = R - R.my_atom = src - attack_self(mob/user as mob) - if(!stage || stage==1) - if(detonator) -// detonator.loc=src.loc - detonator.detached() - usr.put_in_hands(detonator) - detonator=null - stage=0 - icon_state = initial(icon_state) - else if(beakers.len) - for(var/obj/B in beakers) - if(istype(B)) - beakers -= B - user.put_in_hands(B) - name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]" - if(stage > 1 && !active && clown_check(user)) - user << "You prime \the [name]!" +/obj/item/weapon/grenade/chem_grenade/New() + create_reagents(1000) + if(payload_name) + payload_name += " " // formatting, ignore me + update_icon() - msg_admin_attack("[user.name] ([user.ckey]) primed \a [src]. (JMP)") - activate() - add_fingerprint(user) +/obj/item/weapon/grenade/chem_grenade/examine() + set src in usr + usr << desc + if(stage >= WIRED) + if(nadeassembly) + usr << nadeassembly.a_left.describe() + usr << nadeassembly.a_right.describe() + else + usr << "The timer is set to [det_time/10] second\s." + + +/obj/item/weapon/grenade/chem_grenade/proc/get_trigger() + if(!nadeassembly) return null + for(var/obj/O in list(nadeassembly.a_left, nadeassembly.a_right)) + if(!O || istype(O,/obj/item/device/assembly/igniter)) continue + return O + return null + + +/obj/item/weapon/grenade/chem_grenade/proc/update_overlays() + underlays = list() + if(nadeassembly) + underlays += "[nadeassembly.a_left.icon_state]_left" + for(var/O in nadeassembly.a_left.attached_overlays) + underlays += "[O]_l" + underlays += "[nadeassembly.a_right.icon_state]_right" + for(var/O in nadeassembly.a_right.attached_overlays) + underlays += "[O]_r" + +/obj/item/weapon/grenade/chem_grenade/update_icon() + if(nadeassembly) + icon = 'icons/obj/assemblies/new_assemblies.dmi' + icon_state = bomb_state + update_overlays() + var/obj/item/device/assembly/A = get_trigger() + if(stage != READY) + name = "bomb casing[label]" + else + if(!A) + name = "[payload_name]de-fused bomb[label]" // this should not actually happen + else + name = payload_name + A.bomb_name + label // time bombs, remote mines, etc + else + icon = 'icons/obj/grenade.dmi' + icon_state = initial(icon_state) + overlays = list() + switch(stage) + if(EMPTY) + name = "grenade casing[label]" + if(WIRED) + icon_state += "_ass" + name = "grenade casing[label]" + if(READY) + if(active) + icon_state += "_active" + else + icon_state += "_locked" + name = payload_name + "grenade" + label + + +/obj/item/weapon/grenade/chem_grenade/attack_self(mob/user) + if(stage == READY && !active) + var/turf/bombturf = get_turf(src) + var/area/A = get_area(bombturf) + if(nadeassembly) + nadeassembly.attack_self(user) + update_icon() + else if(clown_check(user)) + // This used to go before the assembly check, but that has absolutely zero to do with priming the damn thing. You could spam the admins with it. + var/log_str = "[key_name(usr)]? has primed a [name] for detonation at [A.name] (JMP)." + message_admins(log_str) + log_game(log_str) + user << "You prime the [name]! [det_time / 10] second\s!" + active = 1 + update_icon() if(iscarbon(user)) var/mob/living/carbon/C = user C.throw_mode_on() + spawn(det_time) + prime() - attackby(obj/item/weapon/W as obj, mob/user as mob) - if(istype(W,/obj/item/device/assembly_holder) && (!stage || stage==1) && path != 2) - var/obj/item/device/assembly_holder/det = W - if(istype(det.a_left,det.a_right.type) || (!isigniter(det.a_left) && !isigniter(det.a_right))) - user << "\red Assembly must contain one igniter." - return - if(!det.secured) - user << "\red Assembly must be secured with screwdriver." - return - path = 1 - user << "\blue You add [W] to the metal casing." - playsound(src.loc, 'sound/items/Screwdriver2.ogg', 25, -3) - user.remove_from_mob(det) - det.loc = src - detonator = det - icon_state = initial(icon_state) +"_ass" - name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]" - stage = 1 - else if(istype(W,/obj/item/weapon/screwdriver) && path != 2) - if(stage == 1) - path = 1 - if(beakers.len) - user << "\blue You lock the assembly." - name = "grenade" - else -// user << "\red You need to add at least one beaker before locking the assembly." - user << "\blue You lock the empty assembly." - name = "fake grenade" - playsound(src.loc, 'sound/items/Screwdriver.ogg', 25, -3) - icon_state = initial(icon_state) +"_locked" - stage = 2 - else if(stage == 2) - if(active && prob(95)) - user << "\red You trigger the assembly!" - prime() - return - else - user << "\blue You unlock the assembly." - playsound(src.loc, 'sound/items/Screwdriver.ogg', 25, -3) - name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]" - icon_state = initial(icon_state) + (detonator?"_ass":"") - stage = 1 - active = 0 - else if(is_type_in_list(W, allowed_containers) && (!stage || stage==1) && path != 2) - path = 1 - if(beakers.len == 2) - user << "\red The grenade can not hold more containers." - return +/obj/item/weapon/grenade/chem_grenade/attackby(obj/item/I, mob/user) + if(istype(I,/obj/item/weapon/hand_labeler)) + var/obj/item/weapon/hand_labeler/HL = I + if(length(HL.label)) + label = " ([HL.label])" + return 0 + else + if(label) + label = null + update_icon() + user << "You remove the label from [src]." + return 1 + if(istype(I, /obj/item/weapon/screwdriver)) + if(stage == WIRED) + if(beakers.len) + user << "You lock the assembly." + playsound(loc, 'sound/items/Screwdriver.ogg', 25, -3) + stage = READY + update_icon() + var/contained = "" + var/cores = "" + for(var/obj/O in beakers) + if(!O.reagents) continue + if(istype(O,/obj/item/slime_extract)) + cores += " [O]" + for(var/reagent in O.reagents.reagent_list) + contained += " [reagent] " + if(contained) + if(cores) + contained = "\[[cores];[contained]\]" + else + contained = "\[[contained]\]" + var/turf/bombturf = get_turf(loc) + var/area/A = bombturf.loc + var/log_str = "[key_name(usr)]? has completed [name] at [A.name] (JMP) [contained]." + message_admins(log_str) + log_game(log_str) else - if(W.reagents.total_volume) - user << "\blue You add \the [W] to the assembly." - user.drop_item() - W.loc = src - beakers += W - stage = 1 - name = "unsecured grenade with [beakers.len] containers[detonator?" and detonator":""]" - else - user << "\red \the [W] is empty." + user << "You need to add at least one beaker before locking the assembly." + else if(stage == READY && !nadeassembly) + det_time = det_time == 50 ? 30 : 50 //toggle between 30 and 50 + user << "You modify the time delay. It's set for [det_time / 10] second\s." + else if(stage == EMPTY) + user << "You need to add an activation mechanism." - examine() - set src in usr - usr << desc - if(detonator) - usr << "With attached [detonator.name]" + else if(stage == WIRED && is_type_in_list(I, allowed_containers)) + if(beakers.len == 2) + user << "[src] can not hold more containers." + return + else + if(I.reagents.total_volume) + user << "You add [I] to the assembly." + user.drop_item() + I.loc = src + beakers += I + else + user << "[I] is empty." - activate(mob/user as mob) - if(active) return - - if(detonator) - if(!isigniter(detonator.a_left)) - detonator.a_left.activate() - active = 1 - if(!isigniter(detonator.a_right)) - detonator.a_right.activate() - active = 1 - if(active) - icon_state = initial(icon_state) + "_active" - - if(user) - msg_admin_attack("[user.name] ([user.ckey]) primed \a [src] (JMP)") - - return - - proc/primed(var/primed = 1) - if(active) - icon_state = initial(icon_state) + (primed?"_primed":"_active") - - prime() - if(!stage || stage<2) return - - //if(prob(reliability)) - var/has_reagents = 0 - for(var/obj/item/weapon/reagent_containers/glass/G in beakers) - if(G.reagents.total_volume) has_reagents = 1 - - active = 0 - if(!has_reagents) - icon_state = initial(icon_state) +"_locked" - playsound(src.loc, 'sound/items/Screwdriver2.ogg', 50, 1) + else if(stage == EMPTY && istype(I, /obj/item/device/assembly_holder)) + var/obj/item/device/assembly_holder/A = I + if(!A.secured) + return + if(isigniter(A.a_left) == isigniter(A.a_right)) //Check if either part of the assembly has an igniter, but if both parts are igniters, then fuck it return - playsound(src.loc, 'sound/effects/bamf.ogg', 50, 1) + user.drop_item() + nadeassembly = A + A.master = src + A.loc = src - for(var/obj/item/weapon/reagent_containers/glass/G in beakers) - G.reagents.trans_to(src, G.reagents.total_volume) + stage = WIRED + user << "You add [A] to [src]!" + update_icon() - if(src.reagents.total_volume) //The possible reactions didnt use up all reagents. - var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/effect/system/steam_spread() - steam.set_up(10, 0, get_turf(src)) - steam.attach(src) - steam.start() + else if(stage == EMPTY && istype(I, /obj/item/weapon/cable_coil)) + var/obj/item/weapon/cable_coil/C = I + C.use(1) - for(var/atom/A in view(affected_area, src.loc)) - if( A == src ) continue - src.reagents.reaction(A, 1, 10) + stage = WIRED + user << "You rig [src]." + update_icon() + + else if(stage == READY && istype(I, /obj/item/weapon/wirecutters)) + user << "You unlock the assembly." + stage = WIRED + update_icon() + + else if(stage == WIRED && istype(I, /obj/item/weapon/wrench)) + user << "You open the grenade and remove the contents." + stage = EMPTY + payload_name = null + label = null + if(nadeassembly) + nadeassembly.loc = get_turf(src) + nadeassembly.master = null + nadeassembly = null + if(beakers.len) + for(var/obj/O in beakers) + O.loc = get_turf(src) + beakers = list() + update_icon() - invisibility = INVISIBILITY_MAXIMUM //Why am i doing this? - spawn(50) //To make sure all reagents can work - del(src) //correctly before deleting the grenade. - /*else - icon_state = initial(icon_state) + "_locked" - crit_fail = 1 - for(var/obj/item/weapon/reagent_containers/glass/G in beakers) - G.loc = get_turf(src.loc)*/ +//assembly stuff +/obj/item/weapon/grenade/chem_grenade/receive_signal() + prime() + +/obj/item/weapon/grenade/chem_grenade/HasProximity(atom/movable/AM) + if(nadeassembly) + nadeassembly.HasProximity(AM) + +/obj/item/weapon/grenade/chem_grenade/Move() // prox sensors and infrared care about this + ..() + if(nadeassembly) + nadeassembly.process_movement() + +/obj/item/weapon/grenade/chem_grenade/pickup() + ..() + if(nadeassembly) + nadeassembly.process_movement() + +/obj/item/weapon/grenade/chem_grenade/Crossed(atom/movable/AM) + if(nadeassembly) + nadeassembly.Crossed(AM) + +/obj/item/weapon/grenade/chem_grenade/on_found(mob/finder) + if(nadeassembly) + nadeassembly.on_found(finder) + +/obj/item/weapon/grenade/chem_grenade/hear_talk(mob/living/M, msg) + if(nadeassembly) + nadeassembly.hear_talk(M, msg) + +/obj/item/weapon/grenade/chem_grenade/Bump() + ..() + if(nadeassembly) + nadeassembly.process_movement() + +/obj/item/weapon/grenade/chem_grenade/throw_impact() // called when a throw stops + ..() + if(nadeassembly) + nadeassembly.process_movement() +/obj/item/weapon/grenade/chem_grenade/prime() + if(stage != READY) + return + + var/has_reagents = 0 + for(var/obj/item/weapon/reagent_containers/glass/G in beakers) + if(G.reagents.total_volume) + has_reagents = 1 + + if(!has_reagents) + playsound(loc, 'sound/items/Screwdriver2.ogg', 50, 1) + return + + playsound(loc, 'sound/effects/bamf.ogg', 50, 1) + + update_mob() + + invisibility = INVISIBILITY_MAXIMUM //kaboom + del nadeassembly // do this now to stop infrared beams + + for(var/obj/item/weapon/reagent_containers/glass/G in beakers) + G.reagents.trans_to(src, G.reagents.total_volume) + + if(reagents.total_volume) //The possible reactions didnt use up all reagents. + var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/effect/system/steam_spread() + steam.set_up(10, 0, get_turf(src)) + steam.attach(src) + steam.start() + + for(var/atom/A in view(affected_area, loc)) + if(A == src) + continue + reagents.reaction(A, 1, 10) + + + spawn(15) //Making sure all reagents can work + del(src) //correctly before deleting the grenade. + +/obj/item/weapon/grenade/chem_grenade/proc/CreateDefaultTrigger(var/typekey) + if(ispath(typekey,/obj/item/device/assembly)) + nadeassembly = new(src) + nadeassembly.a_left = new /obj/item/device/assembly/igniter(nadeassembly) + nadeassembly.a_left.holder = nadeassembly + nadeassembly.a_left.secured = 1 + nadeassembly.a_right = new typekey(nadeassembly) + if(!nadeassembly.a_right.secured) + nadeassembly.a_right.toggle_secure() // necessary because fuxing prock_sensors + nadeassembly.a_right.holder = nadeassembly + nadeassembly.secured = 1 + nadeassembly.master = src + nadeassembly.update_icon() + stage = READY + update_icon() + + +//Large chem grenades accept slime cores and use the appropriately. /obj/item/weapon/grenade/chem_grenade/large - name = "Large Chem Grenade" - desc = "An oversized grenade that affects a larger area." + name = "large grenade casing" + desc = "For oversized grenades; fits additional contents and affects a greater area." icon_state = "large_grenade" - allowed_containers = list(/obj/item/weapon/reagent_containers/glass/beaker/bluespace) + bomb_state = "largebomb" + allowed_containers = list(/obj/item/weapon/reagent_containers/glass,/obj/item/weapon/reagent_containers/food/condiment, + /obj/item/weapon/reagent_containers/food/drinks) origin_tech = "combat=3;materials=3" affected_area = 4 + +/obj/item/weapon/grenade/chem_grenade/large/prime() + if(stage != READY) + return + + var/has_reagents = 0 + var/obj/item/slime_extract/valid_core = null + + for(var/obj/item/weapon/reagent_containers/glass/G in beakers) + if(!istype(G)) continue + if(G.reagents.total_volume) has_reagents = 1 + for(var/obj/item/slime_extract/E in beakers) + if(!istype(E)) continue + if(E.Uses) valid_core = E + if(E.reagents.total_volume) has_reagents = 1 + + if(!has_reagents) + playsound(loc, 'sound/items/Screwdriver2.ogg', 50, 1) + return + + playsound(loc, 'sound/effects/bamf.ogg', 50, 1) + + update_mob() + + if(valid_core) + for(var/obj/item/weapon/reagent_containers/glass/G in beakers) + G.reagents.trans_to(valid_core, G.reagents.total_volume) + + //If there is still a core (sometimes it's used up) + //and there are reagents left, behave normally + + if(valid_core && valid_core.reagents && valid_core.reagents.total_volume) + valid_core.reagents.trans_to(src,valid_core.reagents.total_volume) + else + for(var/obj/item/weapon/reagent_containers/glass/G in beakers) + G.reagents.trans_to(src, G.reagents.total_volume) + + if(reagents.total_volume) //The possible reactions didnt use up all reagents. + var/datum/effect/effect/system/steam_spread/steam = new /datum/effect/effect/system/steam_spread() + steam.set_up(10, 0, get_turf(src)) + steam.attach(src) + steam.start() + + for(var/atom/A in view(affected_area, loc)) + if( A == src ) continue + reagents.reaction(A, 1, 10) + + invisibility = INVISIBILITY_MAXIMUM //Why am i doing this? + spawn(50) //To make sure all reagents can work + del(src) //correctly before deleting the grenade. + + + //I tried to just put it in the allowed_containers list but + //if you do that it must have reagents. If you're going to + //make a special case you might as well do it explicitly. -Sayu +/obj/item/weapon/grenade/chem_grenade/large/attackby(obj/item/I, mob/user) + if(istype(I, /obj/item/slime_extract) && stage == WIRED) + user << "You add [I] to the assembly." + user.drop_item() + I.loc = src + beakers += I + else + return ..() + + /obj/item/weapon/grenade/chem_grenade/metalfoam - name = "Metal-Foam Grenade" + payload_name = "metal foam" desc = "Used for emergency sealing of air breaches." - path = 1 - stage = 2 + stage = READY New() ..() @@ -195,72 +397,89 @@ B2.reagents.add_reagent("foaming_agent", 10) B2.reagents.add_reagent("pacid", 10) - detonator = new/obj/item/device/assembly_holder/timer_igniter(src) - beakers += B1 beakers += B2 - icon_state = initial(icon_state) +"_locked" + update_icon() + /obj/item/weapon/grenade/chem_grenade/incendiary - name = "Incendiary Grenade" + payload_name = "incendiary" desc = "Used for clearing rooms of living things." - path = 1 - stage = 2 + stage = READY New() ..() var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src) var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src) - B1.reagents.add_reagent("aluminum", 15) - B1.reagents.add_reagent("fuel",20) - B2.reagents.add_reagent("plasma", 15) - B2.reagents.add_reagent("sacid", 15) - B1.reagents.add_reagent("fuel",20) - - detonator = new/obj/item/device/assembly_holder/timer_igniter(src) + B1.reagents.add_reagent("aluminum", 25) + B2.reagents.add_reagent("plasma", 25) + B2.reagents.add_reagent("sacid", 25) beakers += B1 beakers += B2 - icon_state = initial(icon_state) +"_locked" + update_icon() + /obj/item/weapon/grenade/chem_grenade/antiweed - name = "weedkiller grenade" + payload_name = "weed killer" desc = "Used for purging large areas of invasive plant species. Contents under pressure. Do not directly inhale contents." - path = 1 - stage = 2 + stage = READY New() ..() var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src) var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src) - B1.reagents.add_reagent("plantbgone", 25) + B1.reagents.add_reagent("plantbgone", 30) + B1.reagents.add_reagent("potassium", 20) + B2.reagents.add_reagent("phosphorus", 20) + B2.reagents.add_reagent("sugar", 20) + B2.reagents.add_reagent("plantbgone", 10) + + beakers += B1 + beakers += B2 + update_icon() + + +/obj/item/weapon/grenade/chem_grenade/cleaner + payload_name = "cleaner" + desc = "BLAM!-brand foaming space cleaner. In a special applicator for rapid cleaning of wide areas." + stage = READY + + New() + ..() + var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src) + var/obj/item/weapon/reagent_containers/glass/beaker/large/B2 = new(src) + + B1.reagents.add_reagent("fluorosurfactant", 40) + B2.reagents.add_reagent("water", 40) + B2.reagents.add_reagent("cleaner", 60) + + beakers += B1 + beakers += B2 + update_icon() + + +/obj/item/weapon/grenade/chem_grenade/teargas + payload_name = "teargas" + desc = "Used for nonlethal riot control. Contents under pressure. Do not directly inhale contents." + stage = READY + + New() + ..() + var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src) + var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src) + + B1.reagents.add_reagent("condensedcapsaicin", 25) B1.reagents.add_reagent("potassium", 25) B2.reagents.add_reagent("phosphorus", 25) B2.reagents.add_reagent("sugar", 25) beakers += B1 beakers += B2 - icon_state = "grenade" + update_icon() -/obj/item/weapon/grenade/chem_grenade/cleaner - name = "Cleaner Grenade" - desc = "BLAM!-brand foaming space cleaner. In a special applicator for rapid cleaning of wide areas." - stage = 2 - path = 1 - - New() - ..() - var/obj/item/weapon/reagent_containers/glass/beaker/B1 = new(src) - var/obj/item/weapon/reagent_containers/glass/beaker/B2 = new(src) - - B1.reagents.add_reagent("fluorosurfactant", 40) - B2.reagents.add_reagent("water", 40) - B2.reagents.add_reagent("cleaner", 10) - - detonator = new/obj/item/device/assembly_holder/timer_igniter(src) - - beakers += B1 - beakers += B2 - icon_state = initial(icon_state) +"_locked" +#undef EMPTY +#undef WIRED +#undef READY \ No newline at end of file diff --git a/code/game/objects/items/weapons/grenades/grenade.dm b/code/game/objects/items/weapons/grenades/grenade.dm index 93f93c5e4b6..fc6c1e710a0 100644 --- a/code/game/objects/items/weapons/grenades/grenade.dm +++ b/code/game/objects/items/weapons/grenades/grenade.dm @@ -7,7 +7,7 @@ item_state = "flashbang" throw_speed = 4 throw_range = 20 - flags = FPRINT | TABLEPASS | CONDUCT + flags = FPRINT | CONDUCT slot_flags = SLOT_BELT var/active = 0 var/det_time = 50 @@ -15,10 +15,12 @@ /obj/item/weapon/grenade/proc/clown_check(var/mob/living/user) if((CLUMSY in user.mutations) && prob(50)) user << "Huh? How does this thing work?" - - activate(user) - add_fingerprint(user) + active = 1 + icon_state = initial(icon_state) + "_active" + playsound(loc, 'sound/weapons/armbomb.ogg', 75, 1, -3) spawn(5) + if(user) + user.drop_item() prime() return 0 return 1 @@ -54,41 +56,32 @@ /obj/item/weapon/grenade/attack_self(mob/user as mob) if(!active) if(clown_check(user)) - user << "You prime \the [name]! [det_time/10] seconds!" - - activate(user) + user << "You prime the [name]! [det_time/10] seconds!" + active = 1 + icon_state = initial(icon_state) + "_active" add_fingerprint(user) + var/turf/bombturf = get_turf(src) + var/area/A = get_area(bombturf) + var/log_str = "[key_name(usr)]? has primed a [name] for detonation at [A.name] (JMP)." + message_admins(log_str) + log_game(log_str) if(iscarbon(user)) var/mob/living/carbon/C = user C.throw_mode_on() - return - - -/obj/item/weapon/grenade/proc/activate(mob/user as mob) - if(active) - return - - if(user) - msg_admin_attack("[user.name] ([user.ckey]) primed \a [src] (JMP)") - - icon_state = initial(icon_state) + "_active" - active = 1 - playsound(loc, 'sound/weapons/armbomb.ogg', 75, 1, -3) - - spawn(det_time) - prime() - return + spawn(det_time) + prime() /obj/item/weapon/grenade/proc/prime() -// playsound(loc, 'sound/items/Welder2.ogg', 25, 1) - var/turf/T = get_turf(src) - if(T) - T.hotspot_expose(700,125) + +/obj/item/weapon/grenade/proc/update_mob() + if(ismob(loc)) + var/mob/M = loc + M.drop_from_inventory(src) /obj/item/weapon/grenade/attackby(obj/item/weapon/W as obj, mob/user as mob) - if(isscrewdriver(W)) + if(istype(W, /obj/item/weapon/screwdriver)) switch(det_time) if ("1") det_time = 10 @@ -104,12 +97,10 @@ user << "You set the [name] for instant detonation." add_fingerprint(user) ..() - return /obj/item/weapon/grenade/attack_hand() walk(src, null, null) ..() - return /obj/item/weapon/grenade/attack_paw(mob/user as mob) return attack_hand(user) diff --git a/code/modules/assembly/assembly.dm b/code/modules/assembly/assembly.dm index cd27eaa169b..570f6da3b2b 100644 --- a/code/modules/assembly/assembly.dm +++ b/code/modules/assembly/assembly.dm @@ -3,21 +3,23 @@ desc = "A small electronic device that should never exist." icon = 'icons/obj/assemblies/new_assemblies.dmi' icon_state = "" - flags = FPRINT | TABLEPASS| CONDUCT + flags = FPRINT | CONDUCT w_class = 2.0 m_amt = 100 g_amt = 0 - w_amt = 0 throwforce = 2 throw_speed = 3 throw_range = 10 origin_tech = "magnets=1" + var/bomb_name = "bomb" // used for naming bombs / mines + var/secured = 1 var/list/attached_overlays = null var/obj/item/device/assembly_holder/holder = null var/cooldown = 0//To prevent spam var/wires = WIRE_RECEIVE | WIRE_PULSE + var/datum/wires/connected = null // currently only used by timer/signaler var/const/WIRE_RECEIVE = 1 //Allows Pulsed(0) to call Activate() var/const/WIRE_PULSE = 2 //Allows Pulse(0) to act on the holder @@ -49,6 +51,8 @@ interact(mob/user as mob) //Called when attack_self is called return + proc/describe() // Called by grenades to describe the state of the trigger (time left, etc) + return "The trigger assembly looks broken!" process_cooldown() cooldown-- @@ -71,6 +75,8 @@ holder.process_activation(src, 1, 0) if(holder && (wires & WIRE_PULSE_SPECIAL)) holder.process_activation(src, 0, 1) +// if(connected && (wires & WIRE_PULSE)) +// connected.Pulse(src) // if(radio && (wires & WIRE_RADIO_PULSE)) //Not sure what goes here quite yet send signal? return 1 @@ -104,7 +110,7 @@ if((!A.secured) && (!secured)) attach_assembly(A,user) return - if(isscrewdriver(W)) + if(istype(W, /obj/item/weapon/screwdriver)) if(toggle_secure()) user << "\blue \The [src] is ready!" else diff --git a/code/modules/assembly/bomb.dm b/code/modules/assembly/bomb.dm index ca04edd7a48..325d2709ea0 100644 --- a/code/modules/assembly/bomb.dm +++ b/code/modules/assembly/bomb.dm @@ -6,7 +6,7 @@ w_class = 3.0 throw_speed = 2 throw_range = 4 - flags = FPRINT | TABLEPASS| CONDUCT //Copied this from old code, so this may or may not be necessary + flags = FPRINT | CONDUCT //Copied this from old code, so this may or may not be necessary var/status = 0 //0 - not readied //1 - bomb finished with welder var/obj/item/device/assembly_holder/bombassembly = null //The first part of the bomb is an assembly holder, holding an igniter+some device var/obj/item/weapon/tank/bombtank = null //the second part of the bomb is a plasma tank @@ -73,6 +73,19 @@ if(bombassembly) bombassembly.HasProximity(AM) +/obj/item/device/onetankbomb/Crossed(atom/movable/AM as mob|obj) //for mousetraps + if(bombassembly) + bombassembly.Crossed(AM) + +/obj/item/device/onetankbomb/on_found(mob/finder as mob) //for mousetraps + if(bombassembly) + bombassembly.on_found(finder) + +/obj/item/device/onetankbomb/hear_talk(mob/living/M as mob, msg) + if(bombassembly) + bombassembly.hear_talk(M, msg) + + // ---------- Procs below are for tanks that are used exclusively in 1-tank bombs ---------- /obj/item/weapon/tank/proc/bomb_assemble(W,user) //Bomb assembly proc. This turns assembly+tank into a bomb diff --git a/code/modules/assembly/holder.dm b/code/modules/assembly/holder.dm index 477313114d2..2cca18392aa 100644 --- a/code/modules/assembly/holder.dm +++ b/code/modules/assembly/holder.dm @@ -3,7 +3,7 @@ icon = 'icons/obj/assemblies/new_assemblies.dmi' icon_state = "holder" item_state = "assembly" - flags = FPRINT | TABLEPASS| CONDUCT + flags = FPRINT | CONDUCT throwforce = 5 w_class = 2.0 throw_speed = 3 @@ -12,19 +12,13 @@ var/secured = 0 var/obj/item/device/assembly/a_left = null var/obj/item/device/assembly/a_right = null - var/obj/special_assembly = null proc/attach(var/obj/item/device/D, var/obj/item/device/D2, var/mob/user) return - proc/attach_special(var/obj/O, var/mob/user) - return - proc/process_activation(var/obj/item/device/D) return - proc/detached() - return IsAssemblyHolder() @@ -46,23 +40,9 @@ a_right = D2 name = "[D.name]-[D2.name] assembly" update_icon() - usr.put_in_hands(src) - return 1 - attach_special(var/obj/O, var/mob/user) - if(!O) return - if(!O.IsSpecialAssembly()) return 0 - -/* if(O:Attach_Holder()) - special_assembly = O - update_icon() - src.name = "[a_left.name] [a_right.name] [special_assembly.name] assembly" -*/ - return - - update_icon() overlays.Cut() if(a_left) @@ -76,13 +56,6 @@ if(master) master.update_icon() -/* if(special_assembly) - special_assembly.update_icon() - if(special_assembly:small_icon_state) - src.overlays += special_assembly:small_icon_state - for(var/O in special_assembly:small_icon_state_overlays) - src.overlays += O -*/ examine() set src in view() @@ -100,8 +73,6 @@ a_left.HasProximity(AM) if(a_right) a_right.HasProximity(AM) - if(special_assembly) - special_assembly.HasProximity(AM) Crossed(atom/movable/AM as mob|obj) @@ -109,43 +80,52 @@ a_left.Crossed(AM) if(a_right) a_right.Crossed(AM) - if(special_assembly) - special_assembly.Crossed(AM) - on_found(mob/finder as mob) if(a_left) a_left.on_found(finder) if(a_right) a_right.on_found(finder) - if(special_assembly) - if(istype(special_assembly, /obj/item)) - var/obj/item/S = special_assembly - S.on_found(finder) - Move() - ..() + hear_talk(mob/living/M as mob, msg) + if(a_left) + a_left.hear_talk(M, msg) + if(a_right) + a_right.hear_talk(M, msg) + + proc/process_movement() // infrared beams and prox sensors if(a_left && a_right) a_left.holder_movement() a_right.holder_movement() -// if(special_assembly) -// special_assembly:holder_movement() + + Move() + ..() + process_movement() return + pickup() + ..() + process_movement() + + Bump() + ..() + process_movement() + + throw_impact() // called when a throw stops + ..() + process_movement() attack_hand()//Perhapse this should be a holder_pickup proc instead, can add if needbe I guess if(a_left && a_right) a_left.holder_movement() a_right.holder_movement() -// if(special_assembly) -// special_assembly:Holder_Movement() ..() return attackby(obj/item/weapon/W as obj, mob/user as mob) - if(isscrewdriver(W)) + if(istype(W, /obj/item/weapon/screwdriver)) if(!a_left || !a_right) user << "\red BUG:Assembly part missing, please report this!" return @@ -158,8 +138,6 @@ user << "\blue \The [src] can now be taken apart!" update_icon() return - else if(W.IsSpecialAssembly()) - attach_special(W, user) else ..() return @@ -177,10 +155,8 @@ if("Right") a_right.attack_self(user) return else - if(!istype(a_left,/obj/item/device/assembly/igniter)) - a_left.attack_self(user) - if(!istype(a_right,/obj/item/device/assembly/igniter)) - a_right.attack_self(user) + a_left.attack_self(user) + a_right.attack_self(user) else var/turf/T = get_turf(src) if(!T) return 0 @@ -197,8 +173,6 @@ process_activation(var/obj/D, var/normal = 1, var/special = 1) if(!D) return 0 - if(!secured) - visible_message("\icon[src] *beep* *beep*", "*beep* *beep*") if((normal) && (a_right) && (a_left)) if(a_right != D) a_right.pulsed(0) @@ -206,9 +180,6 @@ a_left.pulsed(0) if(master) master.receive_signal() -// if(special && special_assembly) -// if(!special_assembly == D) -// special_assembly.dothings() return 1 @@ -217,58 +188,6 @@ -/obj/item/device/assembly_holder/timer_igniter - name = "timer-igniter assembly" - New() - ..() - var/obj/item/device/assembly/igniter/ign = new(src) - ign.secured = 1 - ign.holder = src - var/obj/item/device/assembly/timer/tmr = new(src) - tmr.time=5 - tmr.secured = 1 - tmr.holder = src - processing_objects.Add(tmr) - a_left = tmr - a_right = ign - secured = 1 - update_icon() - name = initial(name) + " ([tmr.time] secs)" - loc.verbs += /obj/item/device/assembly_holder/timer_igniter/verb/configure - - detached() - loc.verbs -= /obj/item/device/assembly_holder/timer_igniter/verb/configure - ..() - - verb/configure() - set name = "Set Timer" - set category = "Object" - set src in usr - - if ( !(usr.stat || usr.restrained()) ) - var/obj/item/device/assembly_holder/holder - if(istype(src,/obj/item/weapon/grenade/chem_grenade)) - var/obj/item/weapon/grenade/chem_grenade/gren = src - holder=gren.detonator - var/obj/item/device/assembly/timer/tmr = holder.a_left - if(!istype(tmr,/obj/item/device/assembly/timer)) - tmr = holder.a_right - if(!istype(tmr,/obj/item/device/assembly/timer)) - usr << "This detonator has no timer." - return - - if(tmr.timing) - usr << "Clock is ticking already." - else - var/ntime = input("Enter desired time in seconds", "Time", "5") as num - if (ntime>0 && ntime<1000) - tmr.time = ntime - name = initial(name) + "([tmr.time] secs)" - usr << "Timer set to [tmr.time] seconds." - else - usr << "Timer can't be [ntime<=0?"negative":"more than 1000 seconds"]." - else - usr << "You cannot do this while [usr.stat?"unconscious/dead":"restrained"]." diff --git a/code/modules/assembly/igniter.dm b/code/modules/assembly/igniter.dm index bc535e85907..d39c2d05f10 100644 --- a/code/modules/assembly/igniter.dm +++ b/code/modules/assembly/igniter.dm @@ -4,32 +4,15 @@ icon_state = "igniter" m_amt = 500 g_amt = 50 - w_amt = 10 origin_tech = "magnets=1" - secured = 1 - wires = WIRE_RECEIVE + describe() + return "The igniter is [secured?"secured.":"unsecured."]" activate() if(!..()) return 0//Cooldown check - - if(holder && istype(holder.loc,/obj/item/weapon/grenade/chem_grenade)) - var/obj/item/weapon/grenade/chem_grenade/grenade = holder.loc - grenade.prime() - else - var/turf/location = get_turf(loc) - if(location) - location.hotspot_expose(1000,1000) - if (istype(src.loc,/obj/item/device/assembly_holder)) - if (istype(src.loc.loc, /obj/structure/reagent_dispensers/fueltank/)) - var/obj/structure/reagent_dispensers/fueltank/tank = src.loc.loc - if (tank && tank.modded) - tank.explode() - - var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread - s.set_up(3, 1, src) - s.start() - + var/turf/location = get_turf(loc) + if(location) location.hotspot_expose(1000,1000) return 1 diff --git a/code/modules/assembly/infrared.dm b/code/modules/assembly/infrared.dm index 47728ad295a..fd86cf3b562 100644 --- a/code/modules/assembly/infrared.dm +++ b/code/modules/assembly/infrared.dm @@ -6,10 +6,9 @@ icon_state = "infrared" m_amt = 1000 g_amt = 500 - w_amt = 100 origin_tech = "magnets=2" - wires = WIRE_PULSE + bomb_name = "tripwire mine" secured = 0 @@ -20,6 +19,8 @@ proc trigger_beam() + describe() + return "The infrared trigger is [on?"on":"off"]." activate() if(!..()) return 0//Cooldown check @@ -57,9 +58,19 @@ if(first) del(first) return - - if((!(first) && (secured && (istype(loc, /turf) || (holder && istype(holder.loc, /turf)))))) - var/obj/effect/beam/i_beam/I = new /obj/effect/beam/i_beam((holder ? holder.loc : loc) ) + if(first || !secured) return + var/turf/T = null + if(istype(loc,/turf)) + T = loc + else if (holder) + if (istype(holder.loc,/turf)) + T = holder.loc + else if (holder.master && istype(holder.master.loc,/turf)) //for onetankbombs and other tertiary builds with assemblies + T = holder.loc.loc + else if(istype(loc,/obj/item/weapon/grenade) && istype(loc.loc,/turf)) + T = loc.loc + if(T) + var/obj/effect/beam/i_beam/I = new /obj/effect/beam/i_beam(T) I.master = src I.density = 1 I.dir = dir @@ -94,7 +105,6 @@ holder_movement() if(!holder) return 0 -// dir = holder.dir del(first) return 1 @@ -102,8 +112,7 @@ trigger_beam() if((!secured)||(!on)||(cooldown > 0)) return 0 pulse(0) - if(!holder) - visible_message("\icon[src] *beep* *beep*") + visible_message("\icon[src] *beep* *beep*") cooldown = 2 spawn(10) process_cooldown() @@ -114,6 +123,8 @@ if(!secured) return user.set_machine(src) var/dat = text("Infrared Laser\nStatus: []
\nVisibility: []
\n
", (on ? text("On", src) : text("Off", src)), (src.visible ? text("Visible", src) : text("Invisible", src))) + if(holder) + dat += "
Beam direction: [dir2text(dir)] Counter-clockwise | Clockwise" dat += "

Refresh" dat += "

Close" user << browse(dat, "window=infra") @@ -128,6 +139,17 @@ onclose(usr, "infra") return + if(href_list["rotate"]) + switch(href_list["rotate"]) + if("-1") + dir = turn(dir,90) + update_icon() + del(first) + if("1") + dir = turn(dir,-90) + update_icon() + del(first) + if(href_list["state"]) on = !(on) update_icon() @@ -170,7 +192,7 @@ var/visible = 0.0 var/left = null anchored = 1.0 - flags = TABLEPASS + flags = 0 /obj/effect/beam/i_beam/proc/hit() diff --git a/code/modules/assembly/mousetrap.dm b/code/modules/assembly/mousetrap.dm index ff3abadccba..422f163c0e4 100644 --- a/code/modules/assembly/mousetrap.dm +++ b/code/modules/assembly/mousetrap.dm @@ -3,16 +3,32 @@ desc = "A handy little spring-loaded trap for catching pesty rodents." icon_state = "mousetrap" m_amt = 100 - w_amt = 10 origin_tech = "combat=1" var/armed = 0 + bomb_name = "contact mine" examine() ..() if(armed) usr << "It looks like it's armed." + activate() + if(..()) + armed = !armed + if(!armed) + if(ishuman(usr)) + var/mob/living/carbon/human/user = usr + if(((user.getBrainLoss() >= 60 || (CLUMSY in user.mutations)) && prob(50))) + user << "Your hand slips, setting off the trigger." + pulse(0) + update_icon() + if(usr) + playsound(usr.loc, 'sound/weapons/handcuffs.ogg', 30, 1, -3) + + describe() + return "The pressure switch is [armed?"primed":"safe"]." + update_icon() if(armed) icon_state = "mousetraparmed" @@ -37,14 +53,12 @@ affecting = H.get_organ(type) H.Stun(3) if(affecting) - if(affecting.take_damage(1, 0)) - H.UpdateDamageIcon() H.updatehealth() else if(ismouse(target)) var/mob/living/simple_animal/mouse/M = target visible_message("\red SPLAT!") M.splat() - playsound(target.loc, 'sound/effects/snap.ogg', 50, 1) + playsound(src.loc, 'sound/effects/snap.ogg', 50, 1) armed = 0 update_icon() pulse(0) @@ -81,7 +95,7 @@ ..() - Crossed(AM as mob|obj) + Crossed(var/atom/movable/AM as mob|obj) if(armed) if(ishuman(AM)) var/mob/living/carbon/H = AM @@ -89,7 +103,9 @@ triggered(H) H.visible_message("[H] accidentally steps on [src].", \ "You accidentally step on [src]") - if(ismouse(AM)) + else if(ismouse(AM)) + triggered(AM) + else if(AM.density) // For mousetrap grenades, set off by anything heavy triggered(AM) ..() @@ -112,4 +128,4 @@ /obj/item/device/assembly/mousetrap/armed icon_state = "mousetraparmed" - armed = 1 \ No newline at end of file + armed = 1 diff --git a/code/modules/assembly/proximity.dm b/code/modules/assembly/proximity.dm index d026ef83b9b..ae1d3e22a99 100644 --- a/code/modules/assembly/proximity.dm +++ b/code/modules/assembly/proximity.dm @@ -4,23 +4,24 @@ icon_state = "prox" m_amt = 800 g_amt = 200 - w_amt = 50 origin_tech = "magnets=1" - wires = WIRE_PULSE - secured = 0 + bomb_name = "proximity mine" + var/scanning = 0 var/timing = 0 var/time = 10 - var/range = 2 - proc toggle_scan() sense() + describe() + if(timing) + return "\blue The proximity sensor is arming." + return "The proximity sensor is [scanning?"armed":"disarmed"]." activate() if(!..()) return 0//Cooldown check @@ -48,13 +49,9 @@ sense() - var/turf/mainloc = get_turf(src) -// if(scanning && cooldown <= 0) -// mainloc.visible_message("\icon[src] *boop* *boop*", "*boop* *boop*") - if((!holder && !secured)||(!scanning)||(cooldown > 0)) return 0 + if((!secured)||(!scanning)||(cooldown > 0)) return 0 pulse(0) - if(!holder) - mainloc.visible_message("\icon[src] *beep* *beep*", "*beep* *beep*") + visible_message("\icon[src] *beep* *beep*", "*beep* *beep*") cooldown = 2 spawn(10) process_cooldown() @@ -62,12 +59,6 @@ process() - if(scanning) - var/turf/mainloc = get_turf(src) - for(var/mob/living/A in range(range,mainloc)) - if (A.move_speed < 12) - sense() - if(timing && (time >= 0)) time-- if(timing && time <= 0) @@ -102,9 +93,6 @@ attached_overlays += "prox_scanning" if(holder) holder.update_icon() - if(holder && istype(holder.loc,/obj/item/weapon/grenade/chem_grenade)) - var/obj/item/weapon/grenade/chem_grenade/grenade = holder.loc - grenade.primed(scanning) return @@ -113,6 +101,9 @@ sense() return + holder_movement() + sense() + interact(mob/user as mob)//TODO: Change this to the wires thingy if(!secured) @@ -121,7 +112,6 @@ var/second = time % 60 var/minute = (time - second) / 60 var/dat = text("Proximity Sensor\n[] []:[]\n- - + +\n", (timing ? text("Arming", src) : text("Not Arming", src)), minute, second, src, src, src, src) - dat += text("
Range: - [] +", src, range, src) dat += "
[scanning?"Armed":"Unarmed"] (Movement sensor active when armed!)" dat += "

Refresh" dat += "

Close" @@ -149,11 +139,6 @@ time += tp time = min(max(round(time), 0), 600) - if(href_list["range"]) - var/r = text2num(href_list["range"]) - range += r - range = min(max(range, 1), 5) - if(href_list["close"]) usr << browse(null, "window=prox") return diff --git a/code/modules/assembly/shock_kit.dm b/code/modules/assembly/shock_kit.dm index 880424e66bd..2f2f5ae2164 100644 --- a/code/modules/assembly/shock_kit.dm +++ b/code/modules/assembly/shock_kit.dm @@ -1,12 +1,13 @@ /obj/item/assembly/shock_kit name = "electrohelmet assembly" desc = "This appears to be made from both an electropack and a helmet." + icon = 'icons/obj/assemblies.dmi' icon_state = "shock_kit" var/obj/item/clothing/head/helmet/part1 = null var/obj/item/device/radio/electropack/part2 = null var/status = 0 w_class = 5.0 - flags = FPRINT | TABLEPASS| CONDUCT + flags = FPRINT | CONDUCT /obj/item/assembly/shock_kit/Del() del(part1) diff --git a/code/modules/assembly/signaler.dm b/code/modules/assembly/signaler.dm index db4a80a98c5..40937cc8774 100644 --- a/code/modules/assembly/signaler.dm +++ b/code/modules/assembly/signaler.dm @@ -5,25 +5,27 @@ item_state = "signaler" m_amt = 1000 g_amt = 200 - w_amt = 100 origin_tech = "magnets=1" wires = WIRE_RECEIVE | WIRE_PULSE | WIRE_RADIO_PULSE | WIRE_RADIO_RECEIVE secured = 1 + var/receiving = 0 + + bomb_name = "remote-control bomb" var/code = 30 var/frequency = 1457 var/delay = 0 - var/airlock_wire = null var/datum/radio_frequency/radio_connection - var/deadman = 0 + var/airlock_wire = null New() ..() spawn(40) set_frequency(frequency) return - + describe() + return "\The [src]'s power light is [receiving?"on":"off"]" activate() if(cooldown > 0) return 0 @@ -49,6 +51,7 @@ Send Signal
+ Reciever is [receiving?"on":"off"]
Frequency/Code for signaler:
Frequency: - @@ -89,6 +92,8 @@ src.code = round(src.code) src.code = min(100, src.code) src.code = max(1, src.code) + if(href_list["receive"]) + receiving = !receiving if(href_list["send"]) spawn( 0 ) @@ -108,16 +113,13 @@ signal.encryption = code signal.data["message"] = "ACTIVATE" radio_connection.post_signal(src, signal) - return -/* - for(var/obj/item/device/assembly/signaler/S in world) - if(!S) continue - if(S == src) continue - if((S.frequency == src.frequency) && (S.code == src.code)) - spawn(0) - if(S) S.pulse(0) - return 0*/ + var/time = time2text(world.realtime,"hh:mm:ss") + var/turf/T = get_turf(src) + if(usr) + lastsignalers.Add("[time] : [usr.key] used [src] @ location ([T.x],[T.y],[T.z]) : [format_frequency(frequency)]/[code]") + + return pulse(var/radio = 0) if(istype(src.loc, /obj/machinery/door/airlock) && src.airlock_wire && src.wires) @@ -129,16 +131,17 @@ ..(radio) return 1 - receive_signal(datum/signal/signal) - if(!signal) return 0 - if(signal.encryption != code) return 0 - if(!(src.wires & WIRE_RADIO_RECEIVE)) return 0 - pulse(1) + if( !receiving || !signal ) + return 0 - if(!holder) - for(var/mob/O in hearers(1, src.loc)) - O.show_message(text("\icon[] *beep* *beep*", src), 3, "*beep* *beep*", 2) + if(signal.encryption != code) + return 0 + if(!(src.wires & WIRE_RADIO_RECEIVE)) return 0 + + pulse(1) + for(var/mob/O in hearers(1, src.loc)) + O.show_message(text("\icon[] *beep* *beep*", src), 3, "*beep* *beep*", 2) return @@ -152,28 +155,6 @@ radio_connection = radio_controller.add_object(src, frequency, RADIO_CHAT) return - process() - if(!deadman) - processing_objects.Remove(src) - var/mob/M = src.loc - if(!M || !ismob(M)) - if(prob(5)) - signal() - deadman = 0 - processing_objects.Remove(src) - else if(prob(5)) - M.visible_message("[M]'s finger twitches a bit over [src]'s signal button!") - return - - verb/deadman_it() - set src in usr - set name = "Threaten to push the button!" - set desc = "BOOOOM!" - deadman = 1 - processing_objects.Add(src) - usr.visible_message("\red [usr] moves their finger over [src]'s signal button...") - - // Embedded signaller used in anomalies. /obj/item/device/assembly/signaler/anomaly name = "anomaly core" diff --git a/code/modules/assembly/timer.dm b/code/modules/assembly/timer.dm index ac01841718e..f773d23229f 100644 --- a/code/modules/assembly/timer.dm +++ b/code/modules/assembly/timer.dm @@ -4,25 +4,28 @@ icon_state = "timer" m_amt = 500 g_amt = 50 - w_amt = 10 origin_tech = "magnets=1" - wires = WIRE_PULSE - secured = 0 + bomb_name = "time bomb" + var/timing = 0 var/time = 10 + var/repeat = 0 + var/set_time = 10 proc timer_end() + describe() + if(timing) + return "The timer is counting down from [time]!" + return "The timer is set for [time] seconds." activate() if(!..()) return 0//Cooldown check - timing = !timing - update_icon() return 0 @@ -39,10 +42,9 @@ timer_end() - if(!secured) return 0 + if((!secured)||(cooldown > 0)) return 0 pulse(0) - if(!holder) - visible_message("\icon[src] *beep* *beep*", "*beep* *beep*") + loc.visible_message("\icon[src] *beep* *beep*", "*beep* *beep*") cooldown = 2 spawn(10) process_cooldown() @@ -53,9 +55,9 @@ if(timing && (time > 0)) time-- if(timing && time <= 0) - timing = 0 + timing = repeat timer_end() - time = 10 + time = set_time return @@ -76,9 +78,24 @@ return 0 var/second = time % 60 var/minute = (time - second) / 60 - var/dat = text("Timing Unit\n[] []:[]\n- - + +\n", (timing ? text("Timing", src) : text("Not Timing", src)), minute, second, src, src, src, src) - dat += "

Refresh" - dat += "

Close" + var/set_second = set_time % 60 + var/set_minute = (set_time - set_second) / 60 + if(second < 10) second = "0[second]" + if(set_second < 10) set_second = "0[set_second]" + + var/dat = {" + +

Timing Unit

+ [minute]:[second] [timing?"Stop":"Start"] Reset
+ Repeat: [repeat?"On":"Off"]
+ Timer set for + - - [set_minute]:[set_second] + + +
+
+

+ Refresh +

+ Close"} user << browse(dat, "window=timer") onclose(user, "timer") return @@ -92,13 +109,20 @@ return if(href_list["time"]) - timing = text2num(href_list["time"]) + timing = !timing update_icon() + if(href_list["reset"]) + time = set_time + + if(href_list["repeat"]) + repeat = !repeat if(href_list["tp"]) var/tp = text2num(href_list["tp"]) - time += tp - time = min(max(round(time), 0), 600) + set_time += tp + set_time = min(max(round(set_time), 5), 600) + if(!timing) + time = set_time if(href_list["close"]) usr << browse(null, "window=timer") diff --git a/code/modules/assembly/voice.dm b/code/modules/assembly/voice.dm new file mode 100644 index 00000000000..0a5c7116c9d --- /dev/null +++ b/code/modules/assembly/voice.dm @@ -0,0 +1,44 @@ +/obj/item/device/assembly/voice + name = "voice analyzer" + desc = "A small electronic device able to record a voice sample, and send a signal when that sample is repeated." + icon_state = "voice" + m_amt = 500 + g_amt = 50 + origin_tech = "magnets=1" + var/listening = 0 + var/recorded = null //the activation message + + bomb_name = "voice-activated bomb" + + describe() + if(recorded || listening) + return "A meter on [src] flickers with every nearby sound." + else + return "[src] is deactivated." + + hear_talk(mob/living/M as mob, msg) + if(listening) + recorded = msg + listening = 0 + var/turf/T = get_turf(src) //otherwise it won't work in hand + T.visible_message("\icon[src] beeps, \"Activation message is '[recorded]'.\"") + else + if(findtext(msg, recorded)) + pulse(0) + + activate() + return // previously this toggled listning when not in a holder, that's a little silly. It was only called in attack_self that way. + + + attack_self(mob/user) + if(!user || !secured) return 0 + + listening = !listening + var/turf/T = get_turf(src) + T.visible_message("\icon[src] beeps, \"[listening ? "Now" : "No longer"] recording input.\"") + return 1 + + + toggle_secure() + . = ..() + listening = 0 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 6e8f9077adf..ac944b7c070 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -78,13 +78,13 @@ emp_act update_icons() src << "\blue Your [C.name] was disrupted!" Stun(2) - +/* if(istype(equipped(),/obj/item/device/assembly/signaler)) var/obj/item/device/assembly/signaler/signaler = equipped() if(signaler.deadman && prob(80)) src.visible_message("\red [src] triggers their deadman's switch!") signaler.signal() - +*/ return //END TASER NERF diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index f8ff70bb3d3..6d6c7f8e260 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -45,13 +45,13 @@ Stun(2) flash_weak_pain() - +/* if(istype(equipped(),/obj/item/device/assembly/signaler)) var/obj/item/device/assembly/signaler/signaler = equipped() if(signaler.deadman && prob(80)) src.visible_message("\red [src] triggers their deadman's switch!") signaler.signal() - +*/ var/absorb = run_armor_check(def_zone, P.flag) if(absorb >= 2) P.on_hit(src,2)