diff --git a/baystation12.dme b/baystation12.dme
index cf62483361c..bd4705e5d7c 100644
--- a/baystation12.dme
+++ b/baystation12.dme
@@ -225,6 +225,7 @@
#include "code\datums\wires\particle_accelerator.dm"
#include "code\datums\wires\radio.dm"
#include "code\datums\wires\robot.dm"
+#include "code\datums\wires\syndicatebomb.dm"
#include "code\datums\wires\vending.dm"
#include "code\datums\wires\wires.dm"
#include "code\defines\obj.dm"
@@ -418,6 +419,7 @@
#include "code\game\machinery\status_display.dm"
#include "code\game\machinery\suit_storage_unit.dm"
#include "code\game\machinery\syndicatebeacon.dm"
+#include "code\game\machinery\syndicatebomb.dm"
#include "code\game\machinery\telepad.dm"
#include "code\game\machinery\teleporter.dm"
#include "code\game\machinery\transformer.dm"
@@ -475,6 +477,7 @@
#include "code\game\machinery\computer\station_alert.dm"
#include "code\game\machinery\computer\store.dm"
#include "code\game\machinery\computer\syndicate_specops_shuttle.dm"
+#include "code\game\machinery\computer\telecrystalconsoles.dm"
#include "code\game\machinery\computer\telescience.dm"
#include "code\game\machinery\computer\xenos_shuttle.dm"
#include "code\game\machinery\doors\airlock.dm"
@@ -646,6 +649,7 @@
#include "code\game\objects\items\weapons\cosmetics.dm"
#include "code\game\objects\items\weapons\dice.dm"
#include "code\game\objects\items\weapons\dna_injector.dm"
+#include "code\game\objects\items\weapons\dnascrambler.dm"
#include "code\game\objects\items\weapons\explosives.dm"
#include "code\game\objects\items\weapons\extinguisher.dm"
#include "code\game\objects\items\weapons\flamethrower.dm"
@@ -684,6 +688,7 @@
#include "code\game\objects\items\weapons\grenades\grenade.dm"
#include "code\game\objects\items\weapons\grenades\smokebomb.dm"
#include "code\game\objects\items\weapons\grenades\spawnergrenade.dm"
+#include "code\game\objects\items\weapons\grenades\syndieminibomb.dm"
#include "code\game\objects\items\weapons\implants\deadman.dm"
#include "code\game\objects\items\weapons\implants\implant.dm"
#include "code\game\objects\items\weapons\implants\implantcase.dm"
diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm
index 104b29310c4..9123843cb17 100644
--- a/code/datums/uplink_item.dm
+++ b/code/datums/uplink_item.dm
@@ -15,6 +15,8 @@ var/list/uplink_items = list()
continue
if(I.gamemodes.len && ticker && !(ticker.mode.name in I.gamemodes))
continue
+ if(I.excludefrom.len && ticker && (ticker.mode.name in I.excludefrom))
+ continue
if(I.last)
last += I
continue
@@ -44,6 +46,7 @@ var/list/uplink_items = list()
var/last = 0 // Appear last
var/abstract = 0
var/list/gamemodes = list() // Empty list means it is in all the gamemodes. Otherwise place the gamemode name here.
+ var/list/excludefrom = list() //Empty list does nothing. Place the name of gamemode you don't want this item to be available in here. This is so you dont have to list EVERY mode to exclude something.
var/list/job = null
/datum/uplink_item/proc/spawn_item(var/turf/loc, var/obj/item/device/uplink/U)
@@ -102,7 +105,7 @@ var/list/uplink_items = list()
name = "1 Banana Grenade"
desc = "A grenade that explodes into HONK! brand banana peels that are genetically modified to be extra slippery and extrude caustic acid when stepped on"
item = /obj/item/weapon/grenade/clown_grenade
- cost = 4
+ cost = 8
job = list("Clown")
//Detective
@@ -110,14 +113,14 @@ var/list/uplink_items = list()
name = "Evidence Forger"
desc = "An evidence scanner that allows you forge evidence by setting the output before scanning the item."
item = /obj/item/device/detective_scanner/forger
- cost = 3
+ cost = 6
job = list("Detective")
/datum/uplink_item/jobspecific/conversionkit
name = "Conversion Kit Bundle"
desc = "A bundle that comes with a professional revolver conversion kit and 1 box of .357 ammo. The kit allows you to convert your revolver to fire lethal rounds or vice versa, modification is nearly perfect and will not result in catastrophic failure."
item = /obj/item/weapon/storage/box/syndie_kit/conversion
- cost = 6
+ cost = 12
job = list("Detective")
//Chef
@@ -125,14 +128,14 @@ var/list/uplink_items = list()
name = "Chef Excellence's Special Sauce"
desc = "A custom made sauce made from the toxin glands of 1000 space carp, if somebody ingests enough they'll be dead in 3 minutes or less guaranteed."
item = /obj/item/weapon/reagent_containers/food/condiment/syndisauce
- cost = 2
+ cost = 4
job = list("Chef")
/datum/uplink_item/jobspecific/meatcleaver
name = "Meat Cleaver"
desc = "A mean looking meat cleaver that does damage comparable to an Energy Sword but with the added benefit of chopping your victim into hunks of meat after they've died and the chance to stun when thrown."
item = /obj/item/weapon/butch/meatcleaver
- cost = 5
+ cost = 10
job = list("Chef")
//Janitor
@@ -141,7 +144,7 @@ var/list/uplink_items = list()
name = "Proximity Mine"
desc = "An Anti-Personnel proximity mine cleverly disguised as a wet floor caution sign that is triggered by running past it, activate it to start the 15 second timer and activate again to disarm."
item = /obj/item/weapon/caution/proximity_sign
- cost = 2
+ cost = 4
job = list("Janitor")
//Medical
@@ -151,15 +154,16 @@ var/list/uplink_items = list()
name = "Radiation Laser"
desc = "A radiation laser concealed inside of a Health Analyser, After a moderate delay, causes temporary collapse and radiation. Has adjustable controls, but will not function as a regular health analyzer, only appears like one. May not function correctly on radiation resistent humanoids!"
item = /obj/item/device/rad_laser
- cost = 3
+ cost = 6
job = list(
"Chief Medical Officer",
"Medical Doctor",
- //"Geneticist",
- //"Psychiatrist",
- //"Chemist",
- //"Paramedic",
- "Virologist"
+ "Geneticist",
+ "Psychiatrist",
+ "Chemist",
+ "Paramedic",
+ "Virologist",
+ "Brig Physician"
)
//Assistant
@@ -168,7 +172,7 @@ var/list/uplink_items = list()
name = "Pickpocket's Gloves"
desc = "A pair of sleek gloves to aid in pickpocketing, while wearing these you can see inside the pockets of any unsuspecting mark, loot the ID or pockets without them knowing, and pickpocketing puts the item directly into your hand."
item = /obj/item/clothing/gloves/black/thief
- cost = 3
+ cost = 6
job = list("Civilian")
/*
@@ -184,7 +188,7 @@ var/list/uplink_items = list()
name = "Boozey Shotgun Shells"
desc = "A box containing 6 shotgun shells that simulate the effects of extreme drunkeness on the target, more effective for each type of alcohol in the target's system."
item = /obj/item/weapon/storage/box/syndie_kit/boolets
- cost = 3
+ cost = 6
job = list("Bartender")
//Engineer
@@ -193,7 +197,7 @@ var/list/uplink_items = list()
name = "Power Gloves"
desc = "Insulated gloves that can utilize the power of the station to deliver a short arc of electricity at a target. Must be standing on a powered cable to use."
item = /obj/item/clothing/gloves/yellow/power
- cost = 7
+ cost = 14
job = list("Station Engineer","Chief Engineer")
// DANGEROUS WEAPONS
@@ -205,67 +209,134 @@ var/list/uplink_items = list()
name = "Fully Loaded Revolver"
desc = "A traditional handgun which fires .357 rounds. Has 7 chambers. Can down an unarmoured target with two shots."
item = /obj/item/weapon/gun/projectile/revolver
- cost = 6
+ cost = 13
+
+/datum/uplink_item/dangerous/pistol
+ name = "Stechkin Pistol"
+ desc = "A small, easily concealable handgun that uses 10mm magazines and is compatible with suppressors."
+ item = /obj/item/weapon/gun/projectile/automatic/pistol
+ cost = 9
/datum/uplink_item/dangerous/smg
name = "C-20r Submachine Gun"
desc = "A fully-loaded Scarborough Arms-developed submachine gun that fires 12mm automatic rounds with a 20-round magazine."
item = /obj/item/weapon/gun/projectile/automatic/c20r
- cost = 6
+ cost = 14
gamemodes = list("nuclear emergency")
/datum/uplink_item/dangerous/machinegun
name = "L6 Squad Automatic Weapon"
desc = "A traditionally constructed machine gun made by AA-2531. This deadly weapon has a massive 50-round magazine of 7.62×51mm ammunition."
item = /obj/item/weapon/gun/projectile/automatic/l6_saw
- cost = 10
- gamemodes = list("nuclear emergency")
-
-
-/datum/uplink_item/dangerous/ammo
- name = "Ammo-357"
- desc = "Seven additional rounds for the revolver. Reports indicate the presence of machinery aboard Nanotrasen space stations suitable for producing extra .357 cartridges."
- item = /obj/item/ammo_box/a357
- cost = 2
-
-/datum/uplink_item/ammo/smg
- name = "Ammo-12mm"
- desc = "A 20-round 12mm magazine for use in the C-20r submachine gun."
- item = /obj/item/ammo_box/magazine/m12mm
- cost = 1
- gamemodes = list("nuclear emergency")
-
-
-/datum/uplink_item/ammo/machinegun
- name = "Ammo-7.62×51mm"
- desc = "A 50-round magazine of 7.62×51mm ammunition for use in the L6 SAW machinegun. By the time you need to use this, you'll already be on a pile of corpses."
- item = /obj/item/ammo_box/magazine/m762
- cost = 3
+ cost = 40
gamemodes = list("nuclear emergency")
/datum/uplink_item/dangerous/crossbow
name = "Energy Crossbow"
desc = "A miniature energy crossbow that is small enough both to fit into a pocket and to slip into a backpack unnoticed by observers. Fires bolts tipped with toxin, a poisonous substance that is the product of a living organism. Stuns enemies for a short period of time. Recharges automatically."
item = /obj/item/weapon/gun/energy/crossbow
- cost = 7
+ cost = 12
+ excludefrom = list("nuclear emergency")
/datum/uplink_item/dangerous/sword
name = "Energy Sword"
desc = "The esword is an edged weapon with a blade of pure energy. The sword is small enough to be pocketed when inactive. Activating it produces a loud, distinctive noise."
item = /obj/item/weapon/melee/energy/sword
- cost = 4
+ cost = 8
/datum/uplink_item/dangerous/manhacks
- name = "Manhack Delivery Grenade"
- desc = "The manhack grenade is a highly specialized grenades that, once thrown, will deploy a swarm of Viscerators to attack any nearby crewmembers. WARNING: Viscerator progrmaming does not include safeties. They may turn on you!"
+ name = "Viscerator Delivery Grenade"
+ desc = "A unique grenade that deploys a swarm of viscerators upon activation, which will chase down and shred any non-operatives in the area."
item = /obj/item/weapon/grenade/spawnergrenade/manhacks
- cost = 7
+ cost = 8
+ gamemodes = list("nuclear emergency")
+
+/datum/uplink_item/dangerous/bioterror
+ name = "Biohazardous Chemical Sprayer"
+ desc = "A chemical sprayer that allows a wide dispersal of selected chemicals. Especially tailored by the Tiger Cooperative, the deadly blend it comes stocked with will disorient, damage, and disable your foes... \
+ Use with extreme caution, to prevent exposure to yourself and your fellow operatives."
+ item = /obj/item/weapon/reagent_containers/spray/chemsprayer/bioterror
+ cost = 20
+ gamemodes = list("nuclear emergency")
/datum/uplink_item/dangerous/emp
name = "5 EMP Grenades"
desc = "A box that contains 5 EMP grenades. Useful to disrupt communication and silicon lifeforms."
item = /obj/item/weapon/storage/box/emps
+ cost = 5
+
+/datum/uplink_item/dangerous/syndicate_minibomb
+ name = "Syndicate Minibomb"
+ desc = "The Minibomb is a grenade with a five-second fuse."
+ item = /obj/item/weapon/grenade/syndieminibomb
+ cost = 6
+
+/datum/uplink_item/dangerous/gygax
+ name = "Gygax Exosuit"
+ desc = "A lightweight exosuit, painted in a dark scheme. Its speed and equipment selection make it excellent for hit-and-run style attacks. \
+ This model lacks a method of space propulsion, and therefore it is advised to repair the mothership's teleporter if you wish to make use of it."
+ item = /obj/mecha/combat/gygax/dark/loaded
+ cost = 90
+ gamemodes = list("nuclear emergency")
+
+/datum/uplink_item/dangerous/mauler
+ name = "Mauler Exosuit"
+ desc = "A massive and incredibly deadly Syndicate exosuit. Features long-range targetting, thrust vectoring, and deployable smoke."
+ item = /obj/mecha/combat/marauder/mauler/loaded
+ cost = 140
+ gamemodes = list("nuclear emergency")
+
+// Ammunition
+
+/datum/uplink_item/ammo
+ category = "Ammunition"
+
+/datum/uplink_item/ammo/revolver
+ name = "Ammo-357"
+ desc = "A box that contains seven additional rounds for the revolver, made using an automatic lathe."
+ item = /obj/item/ammo_box/a357
+ cost = 4
+
+/datum/uplink_item/ammo/pistol
+ name = "Ammo-10mm"
+ desc = "An additional 8-round 10mm magazine for use in the Stetchkin pistol."
+ item = /obj/item/ammo_box/magazine/m10mm
+ cost = 1
+
+/datum/uplink_item/ammo/smg
+ name = "Ammo-12mm"
+ desc = "A 20-round 12mm magazine for use in the C-20r submachine gun."
+ item = /obj/item/ammo_box/magazine/m12mm
+ cost = 2
+ gamemodes = list("nuclear emergency")
+
+/datum/uplink_item/ammo/machinegun
+ name = "Ammo-7.62×51mm"
+ desc = "A 50-round magazine of 7.62×51mm ammunition for use in the L6 SAW machinegun. By the time you need to use this, you'll already be on a pile of corpses."
+ item = /obj/item/ammo_box/magazine/m762
+ cost = 12
+ gamemodes = list("nuclear emergency")
+
+/datum/uplink_item/ammo/bullstun
+ name = "Ammo-12g Stun Slug"
+ desc = "An additional 8-round stun slug magazine for use in the Bulldog shotgun. Saying that they're non-lethal would be lying."
+ item = /obj/item/ammo_box/magazine/m12g
+ cost = 2
+ gamemodes = list("nuclear emergency")
+
+/datum/uplink_item/ammo/bullbuck
+ name = "Ammo-12g Buckshot"
+ desc = "An alternative 8-round buckshot magazine for use in the Bulldog shotgun. Front towards enemy."
+ item = /obj/item/ammo_box/magazine/m12g/buckshot
+ cost = 2
+ gamemodes = list("nuclear emergency")
+
+/datum/uplink_item/ammo/bulldragon
+ name = "Ammo-12g Dragon's Breath"
+ desc = "An alternative 8-round dragon's breath magazine for use in the Bulldog shotgun. I'm a fire starter, twisted fire starter!"
+ item = /obj/item/ammo_box/magazine/m12g/dragon
cost = 3
+ gamemodes = list("nuclear emergency")
// STEALTHY WEAPONS
@@ -277,7 +348,8 @@ var/list/uplink_items = list()
name = "Paralysis Pen"
desc = "A syringe disguised as a functional pen, filled with a neuromuscular-blocking drug that renders a target mute on injection that will eventually cause them to pass out. The pen holds one dose of paralyzing agent,though it can be refilled."
item = /obj/item/weapon/pen/paralysis
- cost = 4
+ cost = 8
+ excludefrom = list("nuclear emergency")
/datum/uplink_item/stealthy_weapons/soap
name = "Syndicate Soap"
@@ -289,7 +361,7 @@ var/list/uplink_items = list()
name = "Detomatix PDA Cartridge"
desc = "When inserted into a personal digital assistant, this cartridge gives you five opportunities to detonate PDAs of crewmembers who have their message feature enabled. The concussive effect from the explosion will knock the recipient out for a short period, and deafen them for longer. It has a chance to detonate your PDA."
item = /obj/item/weapon/cartridge/syndicate
- cost = 3 */
+ cost = 6 */
// Commented out until a fix can be found, currently doesn't work with the PDA NanoUI and people keep wasting Telecrystals on it. -- Dave
@@ -297,8 +369,7 @@ var/list/uplink_items = list()
name = "Stetchkin Silencer"
desc = "Fitted for use on the Stetchkin pistol, this silencer will make its shots quieter when equipped onto it."
item = /obj/item/weapon/silencer
- cost = 1
- gamemodes = list("nuclear emergency")
+ cost = 3
// STEALTHY TOOLS
@@ -309,37 +380,50 @@ var/list/uplink_items = list()
name = "Chameleon Jumpsuit"
desc = "A jumpsuit used to imitate the uniforms of Nanotrasen crewmembers."
item = /obj/item/clothing/under/chameleon
- cost = 3
+ cost = 4
+
+/datum/uplink_item/stealthy_tools/chameleon_stamp
+ name = "Chameleon Stamp"
+ desc = "A stamp that can be activated to imitate an official Nanotrasen Stamp™. The disguised stamp will work exactly like the real stamp and will allow you to forge false documents to gain access or equipment; \
+ it can also be used in a washing machine to forge clothing."
+ item = /obj/item/weapon/stamp/chameleon
+ cost = 1
/datum/uplink_item/stealthy_tools/syndigolashes
name = "No-Slip Syndicate Shoes"
desc = "These allow you to run on wet floors. They do not work on lubricated surfaces."
item = /obj/item/clothing/shoes/syndigaloshes
- cost = 2
+ cost = 4
/datum/uplink_item/stealthy_tools/agent_card
name = "Agent ID Card"
desc = "Agent cards prevent artificial intelligences from tracking the wearer, and can copy access from other identification cards. The access is cumulative, so scanning one card does not erase the access gained from another."
item = /obj/item/weapon/card/id/syndicate
- cost = 2
+ cost = 3
/datum/uplink_item/stealthy_tools/voice_changer
name = "Voice Changer"
desc = "A conspicuous gas mask that mimics the voice named on your identification card. When no identification is worn, the mask will render your voice unrecognizable."
item = /obj/item/clothing/mask/gas/voice
- cost = 4
+ cost = 5
/datum/uplink_item/stealthy_tools/chameleon_proj
name = "Chameleon-Projector"
desc = "Projects an image across a user, disguising them as an object scanned with it, as long as they don't move the projector from their hand. The disguised user cannot run and rojectiles pass over them."
item = /obj/item/device/chameleon
+ cost = 7
+
+/datum/uplink_item/stealthy_tools/dnascrambler
+ name = "DNA Scrambler"
+ desc = "A syringe with one injection that randomizes appearance and name upon use. A cheaper but less versatile alternative to an agent card and voice changer."
+ item = /obj/item/weapon/dnascrambler
cost = 4
-/datum/uplink_item/stealthy_tools/mindslave
- name = "Mindslave Implant"
- desc = "A box containing an implanter filled with a mindslave implant that when injected into another person makes them loyal to you and your cause, unless of course they're already implanted by someone else. Loyalty ends if the implant is no longer in their system."
- item = /obj/item/weapon/storage/box/syndie_kit/mindslave
- cost = 5
+/datum/uplink_item/stealthy_tools/smugglersatchel
+ name = "Smuggler's Satchel"
+ desc = "This satchel is thin enough to be hidden in the gap between plating and tiling, great for stashing your stolen goods. Comes with a crowbar and a floor tile inside."
+ item = /obj/item/weapon/storage/backpack/satchel_flat
+ cost = 2
// DEVICE AND TOOLS
@@ -351,7 +435,7 @@ var/list/uplink_items = list()
name = "Cryptographic Sequencer"
desc = "The emag is a small card that unlocks hidden functions in electronic devices, subverts intended functions and characteristically breaks security mechanisms."
item = /obj/item/weapon/card/emag
- cost = 3
+ cost = 6
/datum/uplink_item/device_tools/toolbox
name = "Fully Loaded Toolbox"
@@ -362,79 +446,112 @@ var/list/uplink_items = list()
/datum/uplink_item/device_tools/medkit
name = "Syndicate Medical Supply Kit"
- desc = "A basic medical kit for treating injuries in the field."
- item = /obj/item/weapon/storage/firstaid/adv
- cost = 3
+ desc = "The syndicate medkit is a suspicious black and red. Included is a combat stimulant injector for rapid healing, a medical hud for quick identification of injured comrades, \
+ and other medical supplies helpful for a medical field operative."
+ item = /obj/item/weapon/storage/firstaid/tactical
+ cost = 9
gamemodes = list("nuclear emergency")
-
/datum/uplink_item/device_tools/space_suit
name = "Space Suit"
- desc = "The red syndicate space suit is less encumbering than Nanotrasen variants, fits inside bags, and has a weapon slot. Nanotrasen crewmembers are trained to report red space suit sightings."
+ desc = "The red and black syndicate space suit is less encumbering than Nanotrasen variants, fits inside bags, and has a weapon slot. Nanotrasen crewmembers are trained to report red space suit sightings."
item = /obj/item/weapon/storage/box/syndie_kit/space
- cost = 3
+ cost = 5
/datum/uplink_item/device_tools/thermal
name = "Thermal Imaging Glasses"
desc = "These glasses are thermals disguised as engineers' optical meson scanners. They allow you to see organisms through walls by capturing the upper portion of the infrared light spectrum, emitted as heat and light by objects. Hotter objects, such as warm bodies, cybernetic organisms and artificial intelligence cores emit more of this light than cooler objects like walls and airlocks."
item = /obj/item/clothing/glasses/thermal/syndi
- cost = 3
+ cost = 6
/datum/uplink_item/device_tools/surveillance
name = "Camera Surveillance Kit"
desc = "This kit contains 5 Camera bugs and one mobile receiver. Attach camera bugs to a camera to enable remote viewing."
item = /obj/item/weapon/storage/box/syndie_kit/surveillance
- cost = 3
+ cost = 5
/datum/uplink_item/device_tools/camerabugs
name = "Camera Bugs"
desc = "This is a Camera bug resupply giving you 5 more camera bugs."
item = /obj/item/weapon/storage/box/surveillance
- cost = 2
+ cost = 4
/datum/uplink_item/device_tools/binary
name = "Binary Translator Key"
desc = "A key, that when inserted into a radio headset, allows you to listen to and talk with artificial intelligences and cybernetic organisms in binary."
item = /obj/item/device/encryptionkey/binary
- cost = 3
+ cost = 5
/datum/uplink_item/device_tools/cipherkey
name = "Centcomm Encryption Key"
desc = "A key, that when inserted into a radio headset, allows you to listen to and talk on all known radio channels."
item = /obj/item/device/encryptionkey/syndicate/hacked
- cost = 2
+ cost = 4
/datum/uplink_item/device_tools/hacked_module
name = "Hacked AI Upload Module"
desc = "When used with an upload console, this module allows you to upload priority laws to an artificial intelligence. Be careful with their wording, as artificial intelligences may look for loopholes to exploit."
item = /obj/item/weapon/aiModule/syndicate
- cost = 7
+ cost = 14
/datum/uplink_item/device_tools/plastic_explosives
name = "Composition C-4"
- desc = "C-4 is plastic explosive of the common variety Composition C. You can use it to breach walls, attach it to organisms to destroy them, or connect a signaler to its wiring to make it remotely detonable. It has a modifiable timer with a minimum setting of 10 seconds."
+ desc = "C-4 is plastic explosive of the common variety Composition C. You can use it to breach walls or connect a signaler to its wiring to make it remotely detonable. It has a modifiable timer with a minimum setting of 10 seconds."
item = /obj/item/weapon/plastique
- cost = 2
+ cost = 1
/datum/uplink_item/device_tools/powersink
name = "Power sink"
desc = "When screwed to wiring attached to an electric grid, then activated, this large device places excessive load on the grid, causing a stationwide blackout. The sink cannot be carried because of its excessive size. Ordering this sends you a small beacon that will teleport the power sink to your location on activation."
item = /obj/item/device/powersink
- cost = 5
+ cost = 10
/datum/uplink_item/device_tools/singularity_beacon
name = "Singularity Beacon"
desc = "When screwed to wiring attached to an electric grid, then activated, this large device pulls the singularity towards it. Does not work when the singularity is still in containment. A singularity beacon can cause catastrophic damage to a space station, leading to an emergency evacuation. Because of its size, it cannot be carried. Ordering this sends you a small beacon that will teleport the larger beacon to your location on activation."
item = /obj/item/device/radio/beacon/syndicate
- cost = 7
+ cost = 14
+
+/datum/uplink_item/device_tools/syndicate_bomb
+ name = "Syndicate Bomb"
+ desc = "The Syndicate Bomb has an adjustable timer with a minimum setting of 60 seconds. Ordering the bomb sends you a small beacon, which will teleport the explosive to your location when you activate it. \
+ You can wrench the bomb down to prevent removal. The crew may attempt to defuse the bomb."
+ item = /obj/item/device/radio/beacon/syndicate/bomb
+ cost = 11
+
+/datum/uplink_item/device_tools/syndicate_detonator
+ name = "Syndicate Detonator"
+ desc = "The Syndicate Detonator is a companion device to the Syndicate Bomb. Simply press the included button and an encrypted radio frequency will instruct all live syndicate bombs to detonate. \
+ Useful for when speed matters or you wish to synchronize multiple bomb blasts. Be sure to stand clear of the blast radius before using the detonator."
+ item = /obj/item/device/syndicatedetonator
+ cost = 3
+ gamemodes = list("nuclear emergency")
+
+/datum/uplink_item/device_tools/pdapinpointer
+ name = "PDA Pinpointer"
+ desc = "A pinpointer that tracks any PDA on the station. Useful for locating assassination targets or other high-value targets that you can't find. WARNING: Can only set once."
+ item = /obj/item/weapon/pinpointer/pdapinpointer
+ cost = 4
+
+/datum/uplink_item/device_tools/ai_detector
+ name = "Artificial Intelligence Detector" // changed name in case newfriends thought it detected disguised ai's
+ desc = "A functional multitool that turns red when it detects an artificial intelligence watching it or its holder. Knowing when an artificial intelligence is watching you is useful for knowing when to maintain cover."
+ item = /obj/item/device/multitool/ai_detect
+ cost = 1
/datum/uplink_item/device_tools/teleporter
name = "Teleporter Circuit Board"
desc = "A printed circuit board that completes the teleporter onboard the mothership. Advise you test fire the teleporter before entering it, as malfunctions can occur."
item = /obj/item/weapon/circuitboard/teleporter
- cost = 20
+ cost = 40
gamemodes = list("nuclear emergency")
+/datum/uplink_item/device_tools/shield
+ name = "Energy Shield"
+ desc = "An incredibly useful personal shield projector, capable of reflecting energy projectiles and defending against other attacks."
+ item = /obj/item/weapon/shield/energy
+ cost = 16
+ gamemodes = list("nuclear emergency")
// IMPLANTS
@@ -445,26 +562,37 @@ var/list/uplink_items = list()
name = "Freedom Implant"
desc = "An implant injected into the body and later activated using a bodily gesture to attempt to slip restraints."
item = /obj/item/weapon/storage/box/syndie_kit/imp_freedom
- cost = 3
+ cost = 5
/datum/uplink_item/implants/uplink
name = "Uplink Implant"
desc = "An implant injected into the body, and later activated using a bodily gesture to open an uplink with 5 telecrystals. The ability for an agent to open an uplink after their posessions have been stripped from them makes this implant excellent for escaping confinement."
item = /obj/item/weapon/storage/box/syndie_kit/imp_uplink
- cost = 10
+ cost = 20
/datum/uplink_item/implants/explosive
name = "Explosive Implant"
desc = "An implant injected into the body, and later activated using a vocal command to cause a large explosion from the implant."
item = /obj/item/weapon/storage/box/syndie_kit/imp_explosive
- cost = 6
+ cost = 12
/datum/uplink_item/implants/compression
name = "Compressed Matter Implant"
desc = "An implant injected into the body, and later activated using a bodily gesture to retrieve an item that was earlier compressed."
item = /obj/item/weapon/storage/box/syndie_kit/imp_compress
- cost = 4
+ cost = 8
+/datum/uplink_item/implants/mindslave
+ name = "Mindslave Implant"
+ desc = "A box containing an implanter filled with a mindslave implant that when injected into another person makes them loyal to you and your cause, unless of course they're already implanted by someone else. Loyalty ends if the implant is no longer in their system."
+ item = /obj/item/weapon/storage/box/syndie_kit/mindslave
+ cost = 10
+
+/datum/uplink_item/implants/adrenal
+ name = "Adrenal Implant"
+ desc = "An implant injected into the body, and later activated using a bodily gesture to inject a chemical cocktail, which has a mild healing effect along with removing all stuns and increasing his speed."
+ item = /obj/item/weapon/storage/box/syndie_kit/imp_adrenal
+ cost = 8
// POINTLESS BADASSERY
@@ -475,20 +603,22 @@ var/list/uplink_items = list()
name = "Syndicate Bundle"
desc = "Syndicate Bundles are specialised groups of items that arrive in a plain box. These items are collectively worth more than 10 telecrystals, but you do not know which specialisation you will receive."
item = /obj/item/weapon/storage/box/syndicate
- cost = 10
+ cost = 20
+ excludefrom = list("nuclear emergency")
/datum/uplink_item/badass/syndiecards
name = "Syndicate Playing Cards"
desc = "A special deck of space-grade playing cards with a mono-molecular edge and metal reinforcement, making them lethal weapons both when wielded as a blade and when thrown. \
You can also play card games with them."
item = /obj/item/toy/cards/deck/syndicate
- cost = 2
+ cost = 1
+ excludefrom = list("nuclear emergency")
/datum/uplink_item/badass/balloon
name = "For showing that you are The Boss"
desc = "A useless red balloon with the syndicate logo on it, which can blow the deepest of covers."
item = /obj/item/toy/syndicateballoon
- cost = 10
+ cost = 20
/datum/uplink_item/badass/random
name = "Random Item"
diff --git a/code/datums/wires/syndicatebomb.dm b/code/datums/wires/syndicatebomb.dm
index 8c60b0e4546..af084ee00f9 100644
--- a/code/datums/wires/syndicatebomb.dm
+++ b/code/datums/wires/syndicatebomb.dm
@@ -9,24 +9,29 @@ var/const/WIRE_DELAY = 4 // Raises the timer on pulse, does nothing on cut
var/const/WIRE_PROCEED = 8 // Lowers the timer, explodes if cut while the bomb is active
var/const/WIRE_ACTIVATE = 16 // Will start a bombs timer if pulsed, will hint if pulsed while already active, will stop a timer a bomb on cut
+
+/datum/wires/syndicatebomb/CanUse(var/mob/living/L)
+ var/obj/machinery/syndicatebomb/P = holder
+ if(P.open_panel)
+ return 1
+ return 0
+
/datum/wires/syndicatebomb/UpdatePulsed(var/index)
var/obj/machinery/syndicatebomb/P = holder
- if(P.degutted)
- return
switch(index)
if(WIRE_BOOM)
if (P.active)
- P.loc.visible_message("\red \icon[holder] An alarm sounds! It's go-")
+ P.loc.visible_message("\icon[holder] An alarm sounds! It's go-")
P.timer = 0
if(WIRE_UNBOLT)
- P.loc.visible_message("\blue \icon[holder] The bolts spin in place for a moment.")
+ P.loc.visible_message("\icon[holder] The bolts spin in place for a moment.")
if(WIRE_DELAY)
playsound(P.loc, 'sound/machines/chime.ogg', 30, 1)
- P.loc.visible_message("\blue \icon[holder] The bomb chirps.")
+ P.loc.visible_message("\icon[holder] The bomb chirps.")
P.timer += 10
if(WIRE_PROCEED)
playsound(P.loc, 'sound/machines/buzz-sigh.ogg', 30, 1)
- P.loc.visible_message("\red \icon[holder] The bomb buzzes ominously!")
+ P.loc.visible_message("\icon[holder] The bomb buzzes ominously!")
if (P.timer >= 61) //Long fuse bombs can suddenly become more dangerous if you tinker with them
P.timer = 60
if (P.timer >= 21)
@@ -36,26 +41,20 @@ var/const/WIRE_ACTIVATE = 16 // Will start a bombs timer if pulsed, will hint if
if(WIRE_ACTIVATE)
if(!P.active && !P.defused)
playsound(P.loc, 'sound/machines/click.ogg', 30, 1)
- P.loc.visible_message("\red \icon[holder] You hear the bomb start ticking!")
+ P.loc.visible_message("\icon[holder] You hear the bomb start ticking!")
P.active = 1
- if(!P.open_panel) //Needs to exist in case the wire is pulsed with a signaler while the panel is closed
- P.icon_state = "syndicate-bomb-active"
- else
- P.icon_state = "syndicate-bomb-active-wires"
- processing_objects.Add(P)
+ P.icon_state = "[initial(P.icon_state)]-active[P.open_panel ? "-wires" : ""]"
else
- P.loc.visible_message("\blue \icon[holder] The bomb seems to hesitate for a moment.")
+ P.loc.visible_message("\icon[holder] The bomb seems to hesitate for a moment.")
P.timer += 5
/datum/wires/syndicatebomb/UpdateCut(var/index, var/mended)
var/obj/machinery/syndicatebomb/P = holder
- if(P.degutted)
- return
switch(index)
if(WIRE_EXPLODE)
if(!mended)
if(P.active)
- P.loc.visible_message("\red \icon[holder] An alarm sounds! It's go-")
+ P.loc.visible_message("\icon[holder] An alarm sounds! It's go-")
P.timer = 0
else
P.defused = 1
@@ -64,15 +63,15 @@ var/const/WIRE_ACTIVATE = 16 // Will start a bombs timer if pulsed, will hint if
if(WIRE_UNBOLT)
if (!mended && P.anchored)
playsound(P.loc, 'sound/effects/stealthoff.ogg', 30, 1)
- P.loc.visible_message("\blue \icon[holder] The bolts lift out of the ground!")
+ P.loc.visible_message("\icon[holder] The bolts lift out of the ground!")
P.anchored = 0
if(WIRE_PROCEED)
if(!mended && P.active)
- P.loc.visible_message("\red \icon[holder] An alarm sounds! It's go-")
+ P.loc.visible_message("\icon[holder] An alarm sounds! It's go-")
P.timer = 0
if(WIRE_ACTIVATE)
if (!mended && P.active)
- P.loc.visible_message("\blue \icon[holder] The timer stops! The bomb has been defused!")
- P.icon_state = "syndicate-bomb-inactive-wires" //no cutting possible with the panel closed
+ P.loc.visible_message("\icon[holder] The timer stops! The bomb has been defused!")
+ P.icon_state = "[initial(P.icon_state)]-inactive[P.open_panel ? "-wires" : ""]"
P.active = 0
P.defused = 1
\ No newline at end of file
diff --git a/code/datums/wires/wires.dm b/code/datums/wires/wires.dm
index 3f3c67b8245..c3d07013d14 100644
--- a/code/datums/wires/wires.dm
+++ b/code/datums/wires/wires.dm
@@ -278,4 +278,12 @@ var/const/POWER = 8
/datum/wires/proc/IsAllCut()
if(wires_status == (1 << wire_count) - 1)
return 1
- return 0
\ No newline at end of file
+ return 0
+
+//
+//Shuffle and Mend
+//
+
+/datum/wires/proc/Shuffle()
+ wires_status = 0
+ GenerateWires()
\ No newline at end of file
diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm
index b70f6ed85e6..636a9c4fc19 100644
--- a/code/defines/obj/weapon.dm
+++ b/code/defines/obj/weapon.dm
@@ -122,9 +122,10 @@
item_state = "card-id"
w_class = 1.0
+/*
/obj/item/weapon/disk/nuclear/pickup(mob/living/user as mob)
if(issyndicate(user))
- set_security_level(3)
+ set_security_level(3)*/ //Nuke Ops rework makes stealth approach significantly harder; this makes it damn near impossible; besides, it's horrendously meta.
/*
/obj/item/weapon/game_kit
diff --git a/code/game/atoms.dm b/code/game/atoms.dm
index 3d95c217060..8f742df8cef 100644
--- a/code/game/atoms.dm
+++ b/code/game/atoms.dm
@@ -463,3 +463,9 @@ its easier to just keep the beam vertical.
/atom/proc/checkpass(passflag)
return pass_flags&passflag
+
+/atom/proc/isinspace()
+ if(istype(get_turf(src), /turf/space))
+ return 1
+ else
+ return 0
diff --git a/code/game/gamemodes/changeling/changeling.dm b/code/game/gamemodes/changeling/changeling.dm
index 4353c6532ea..004b7c78849 100644
--- a/code/game/gamemodes/changeling/changeling.dm
+++ b/code/game/gamemodes/changeling/changeling.dm
@@ -15,7 +15,7 @@ var/list/possible_changeling_IDs = list("Alpha","Beta","Gamma","Delta","Epsilon"
recommended_enemies = 2
uplink_welcome = "Syndicate Uplink Console:"
- uplink_uses = 10
+ uplink_uses = 20
var/const/prob_int_murder_target = 50 // intercept names the assassination target half the time
var/const/prob_right_murder_target_l = 25 // lower bound on probability of naming right assassination target
diff --git a/code/game/gamemodes/cult/cult.dm b/code/game/gamemodes/cult/cult.dm
index b236ef43cc1..41ade69eb3b 100644
--- a/code/game/gamemodes/cult/cult.dm
+++ b/code/game/gamemodes/cult/cult.dm
@@ -29,7 +29,7 @@
recommended_enemies = 4
uplink_welcome = "Nar-Sie Uplink Console:"
- uplink_uses = 10
+ uplink_uses = 20
var/datum/mind/sacrifice_target = null
var/finished = 0
diff --git a/code/game/gamemodes/extended/extended.dm b/code/game/gamemodes/extended/extended.dm
index 2c37c1bb841..245e1e16e00 100644
--- a/code/game/gamemodes/extended/extended.dm
+++ b/code/game/gamemodes/extended/extended.dm
@@ -4,7 +4,7 @@
required_players = 0
uplink_welcome = "Syndicate Uplink Console:"
- uplink_uses = 10
+ uplink_uses = 20
var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds)
var/const/waittime_h = 1800
diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm
index ecd4e23cfdd..2ecd5bd3b8e 100644
--- a/code/game/gamemodes/game_mode.dm
+++ b/code/game/gamemodes/game_mode.dm
@@ -295,9 +295,9 @@ Implants;
// If they're a traitor or likewise, give them extra TC in exchange.
var/obj/item/device/uplink/hidden/suplink = man.mind.find_syndicate_uplink()
if(suplink)
- var/extra = 4
+ var/extra = 0 //was 4; with the TC rebalance, this isn't really needed, anymore
suplink.uses += extra
- man << "\red We have received notice that enemy intelligence suspects you to be linked with us. We have thus invested significant resources to increase your uplink's capacity."
+ man << "\red We have received notice that enemy intelligence suspects you to be linked with us. We recommend adjusting your plans and equipment accordingly."
else
// Give them a warning!
man << "\red They are on to you!"
diff --git a/code/game/gamemodes/nuclear/nuclear.dm b/code/game/gamemodes/nuclear/nuclear.dm
index f8497391637..662aa81b1e7 100644
--- a/code/game/gamemodes/nuclear/nuclear.dm
+++ b/code/game/gamemodes/nuclear/nuclear.dm
@@ -8,12 +8,12 @@ proc/issyndicate(mob/living/M as mob)
name = "nuclear emergency"
config_tag = "nuclear"
required_players = 6
- required_players_secret = 15 // 25 players - 5 players to be the nuke ops = 20 players remaining
- required_enemies = 3
- recommended_enemies = 4
+ required_players_secret = 20 // 20 players - 5 players to be the nuke ops = 15 players remaining
+ required_enemies = 5
+ recommended_enemies = 5
uplink_welcome = "Corporate Backed Uplink Console:"
- uplink_uses = 40
+ uplink_uses = 120
var/const/agents_possible = 5 //If we ever need more syndicate agents.
var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds)
@@ -128,7 +128,7 @@ proc/issyndicate(mob/living/M as mob)
for(var/datum/mind/synd_mind in syndicates)
if(spawnpos > synd_spawn.len)
- spawnpos = 1
+ spawnpos = 2
synd_mind.current.loc = synd_spawn[spawnpos]
forge_syndicate_objectives(synd_mind)
@@ -162,6 +162,18 @@ proc/issyndicate(mob/living/M as mob)
spawn(1)
// NukeNameAssign(nukelastname(synd_mind.current),syndicates) //allows time for the rest of the syndies to be chosen
synd_mind.current.real_name = "[pick(first_names_male)] [pick(last_names)]"
+ synd_mind.current << "You are the Syndicate leader for this mission. You are responsible for the distribution of telecrystals and your ID is the only one who can open the launch bay doors."
+ synd_mind.current << "If you feel you are not up to this task, give your ID to another operative."
+
+ var/list/foundIDs = synd_mind.current.search_contents_for(/obj/item/weapon/card/id)
+
+ if(foundIDs.len)
+ for(var/obj/item/weapon/card/id/ID in foundIDs)
+ ID.name = "lead agent card"
+ ID.access += access_syndicate_leader
+ else
+ message_admins("Warning: Nuke Ops spawned without access to leave their spawn area!")
+
if (nuke_code)
synd_mind.store_memory("Syndicate Nuclear Bomb Code: [nuke_code]", 0, 0)
synd_mind.current << "The nuclear authorization code is: [nuke_code]"
@@ -210,18 +222,20 @@ proc/issyndicate(mob/living/M as mob)
synd_mob.equip_to_slot_or_del(new /obj/item/clothing/under/syndicate(synd_mob), slot_w_uniform)
synd_mob.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(synd_mob), slot_shoes)
- synd_mob.equip_to_slot_or_del(new /obj/item/clothing/gloves/swat(synd_mob), slot_gloves)
+ synd_mob.equip_or_collect(new /obj/item/clothing/gloves/combat(synd_mob), slot_gloves)
synd_mob.equip_to_slot_or_del(new /obj/item/weapon/card/id/syndicate(synd_mob), slot_wear_id)
if(synd_mob.backbag == 2) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(synd_mob), slot_back)
if(synd_mob.backbag == 3) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_norm(synd_mob), slot_back)
if(synd_mob.backbag == 4) synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(synd_mob), slot_back)
- synd_mob.equip_to_slot_or_del(new /obj/item/ammo_box/magazine/m10mm(synd_mob), slot_in_backpack)
- synd_mob.equip_to_slot_or_del(new /obj/item/ammo_box/magazine/m10mm(synd_mob), slot_in_backpack)
- synd_mob.equip_to_slot_or_del(new /obj/item/ammo_box/magazine/m10mm(synd_mob), slot_in_backpack)
synd_mob.equip_to_slot_or_del(new /obj/item/weapon/reagent_containers/pill/cyanide(synd_mob), slot_in_backpack)
synd_mob.equip_to_slot_or_del(new /obj/item/weapon/gun/projectile/automatic/pistol(synd_mob), slot_belt)
synd_mob.equip_to_slot_or_del(new /obj/item/weapon/storage/box/engineer(synd_mob.back), slot_in_backpack)
+ var/obj/item/device/radio/uplink/U = new /obj/item/device/radio/uplink(synd_mob)
+ U.hidden_uplink.uplink_owner="[synd_mob.key]"
+ U.hidden_uplink.uses = 20
+ synd_mob.equip_to_slot_or_del(U, slot_in_backpack)
+
var/obj/item/clothing/suit/space/rig/syndi/new_suit = new(synd_mob)
var/obj/item/clothing/head/helmet/space/rig/syndi/new_helmet = new(synd_mob)
@@ -232,10 +246,13 @@ proc/issyndicate(mob/living/M as mob)
switch(race)
if("Unathi")
new_suit.species_restricted = list("Unathi")
+ new_helmet.species_restricted = list("Unathi")
if("Tajaran")
new_suit.species_restricted = list("Tajaran")
+ new_helmet.species_restricted = list("Tajaran")
if("Skrell")
new_suit.species_restricted = list("Skrell")
+ new_helmet.species_restricted = list("Skrell")
if("Vox" || "Vox Armalis")
synd_mob.equip_to_slot_or_del(new /obj/item/clothing/mask/breath(synd_mob), slot_wear_mask)
synd_mob.equip_to_slot_or_del(new /obj/item/weapon/tank/nitrogen(synd_mob), slot_l_hand)
@@ -243,6 +260,7 @@ proc/issyndicate(mob/living/M as mob)
if (synd_mob.internals)
synd_mob.internals.icon_state = "internal1"
new_suit.species_restricted = list ("Vox", "Vox Armalis")
+ new_helmet.species_restricted = list ("Vox", "Vox Armalis")
synd_mob.equip_to_slot_or_del(new_suit, slot_wear_suit)
@@ -252,6 +270,7 @@ proc/issyndicate(mob/living/M as mob)
var/obj/item/weapon/implant/dexplosive/E = new/obj/item/weapon/implant/dexplosive(synd_mob)
E.imp_in = synd_mob
E.implanted = 1
+ synd_mob.faction |= "syndicate"
synd_mob.update_icons()
return 1
@@ -365,6 +384,9 @@ proc/issyndicate(mob/living/M as mob)
text += "(Syndicates used [TC_uses] TC) [purchases]"
+ if(TC_uses==0 && station_was_nuked && !is_operatives_are_dead())
+ text += ""
+
world << text
return 1
diff --git a/code/game/gamemodes/nuclear/pinpointer.dm b/code/game/gamemodes/nuclear/pinpointer.dm
index baf79eda425..ce93498919c 100644
--- a/code/game/gamemodes/nuclear/pinpointer.dm
+++ b/code/game/gamemodes/nuclear/pinpointer.dm
@@ -266,4 +266,81 @@
if(16 to INFINITY)
icon_state = "pinonfar"
- spawn(5) .()
\ No newline at end of file
+ spawn(5) .()
+
+/obj/item/weapon/pinpointer/pdapinpointer
+ name = "pda pinpointer"
+ desc = "A pinpointer that has been illegally modified to track the PDA of a crewmember for malicious reasons."
+ var/obj/target = null
+ var/used = 0
+
+ attack_self()
+ if(!active)
+ active = 1
+ point_at(target)
+ usr << "\blue You activate the pinpointer"
+ else
+ active = 0
+ icon_state = "pinoff"
+ usr << "\blue You deactivate the pinpointer"
+
+ verb/select_pda()
+ set category = "Object"
+ set name = "Select pinpointer target"
+ set src in view(1)
+
+ if(used)
+ usr << "Target has already been set!"
+ return
+
+ var/list/L = list()
+ L["Cancel"] = "Cancel"
+ var/length = 1
+ for (var/obj/item/device/pda/P in world)
+ if(P.name != "\improper PDA")
+ L[text("([length]) [P.name]")] = P
+ length++
+
+ var/t = input("Select pinpointer target. WARNING: Can only set once.") as null|anything in L
+ if(t == "Cancel")
+ return
+ target = L[t]
+ if(!target)
+ usr << "Failed to locate [target]!"
+ return
+ active = 1
+ point_at(target)
+ usr << "You set the pinpointer to locate [target]"
+ used = 1
+
+
+ examine()
+ ..()
+ if (target)
+ usr << "\blue Tracking [target]"
+
+ proc/point_at(atom/target)
+ if(!active)
+ return
+ if(!target)
+ icon_state = "pinonnull"
+ return
+
+ var/turf/T = get_turf(target)
+ var/turf/L = get_turf(src)
+
+ if(T.z != L.z)
+ icon_state = "pinonnull"
+ else
+ dir = get_dir(L, T)
+ switch(get_dist(L, T))
+ if(-1)
+ icon_state = "pinondirect"
+ if(1 to 8)
+ icon_state = "pinonclose"
+ if(9 to 16)
+ icon_state = "pinonmedium"
+ if(16 to INFINITY)
+ icon_state = "pinonfar"
+ spawn(5)
+ .()
\ No newline at end of file
diff --git a/code/game/gamemodes/revolution/revolution.dm b/code/game/gamemodes/revolution/revolution.dm
index 963a1619262..a02ce9519f5 100644
--- a/code/game/gamemodes/revolution/revolution.dm
+++ b/code/game/gamemodes/revolution/revolution.dm
@@ -23,7 +23,7 @@
uplink_welcome = "Revolutionary Uplink Console:"
- uplink_uses = 10
+ uplink_uses = 20
var/finished = 0
var/checkwin_counter = 0
diff --git a/code/game/gamemodes/revolution/rp_revolution.dm b/code/game/gamemodes/revolution/rp_revolution.dm
index 522cc2cf701..33977ca811e 100644
--- a/code/game/gamemodes/revolution/rp_revolution.dm
+++ b/code/game/gamemodes/revolution/rp_revolution.dm
@@ -9,7 +9,7 @@
recommended_enemies = 3
uplink_welcome = "Revolutionary Uplink Console:"
- uplink_uses = 5
+ uplink_uses = 10
newscaster_announcements = /datum/news_announcement/revolution_inciting_event
diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm
index 512ae04bdd4..594d7cb9f23 100644
--- a/code/game/gamemodes/traitor/traitor.dm
+++ b/code/game/gamemodes/traitor/traitor.dm
@@ -15,7 +15,7 @@
uplink_welcome = "Syndicate Uplink Console:"
- uplink_uses = 10
+ uplink_uses = 20
var/const/waittime_l = 600 //lower bound on time before intercept arrives (in tenths of seconds)
var/const/waittime_h = 1800 //upper bound on time before intercept arrives (in tenths of seconds)
diff --git a/code/game/gamemodes/vampire/vampire.dm b/code/game/gamemodes/vampire/vampire.dm
index 5461db3d339..7c5f39977a6 100644
--- a/code/game/gamemodes/vampire/vampire.dm
+++ b/code/game/gamemodes/vampire/vampire.dm
@@ -7,15 +7,15 @@
/datum/game_mode/vampire
name = "vampire"
config_tag = "vampire"
- restricted_jobs = list("AI", "Cyborg", "Mobile MMI", "Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Chaplain", "Security Pod Pilot", "Nanotrasen Recruiter", "Magistrate") //Consistent screening has filtered all infiltration attempts on high value jobs
- protected_jobs = list()
- required_players = 1
- required_players_secret = 15
+ restricted_jobs = list("AI", "Cyborg")
+ protected_jobs = list("Security Officer", "Warden", "Detective", "Head of Security", "Captain", "Head of Personnel", "Blueshield", "Nanotrasen Representative", "Security Pod Pilot", "Nanotrasen Recruiter", "Magistrate", "Chaplain")
+ required_players = 2
+ required_players_secret = 10
required_enemies = 1
- recommended_enemies = 4
+ recommended_enemies = 2
uplink_welcome = "Syndicate Uplink Console:"
- uplink_uses = 10
+ uplink_uses = 20
var/const/prob_int_murder_target = 50 // intercept names the assassination target half the time
var/const/prob_right_murder_target_l = 25 // lower bound on probability of naming right assassination target
@@ -56,7 +56,7 @@
if(player.assigned_role == job)
possible_vampires -= player
- vampire_amount = max(1,round(num_players() / 10)) //1 + round(num_players() / 10)
+ vampire_amount = 1 + round(num_players() / 10)
if(possible_vampires.len>0)
for(var/i = 0, i < vampire_amount, i++)
diff --git a/code/game/gamemodes/wizard/wizard.dm b/code/game/gamemodes/wizard/wizard.dm
index 8a818ea3f1e..0194d34b2ef 100644
--- a/code/game/gamemodes/wizard/wizard.dm
+++ b/code/game/gamemodes/wizard/wizard.dm
@@ -10,7 +10,7 @@
recommended_enemies = 1
uplink_welcome = "Wizardly Uplink Console:"
- uplink_uses = 10
+ uplink_uses = 20
var/finished = 0
diff --git a/code/game/jobs/access.dm b/code/game/jobs/access.dm
index 93bc5207d32..979cc63ed27 100644
--- a/code/game/jobs/access.dm
+++ b/code/game/jobs/access.dm
@@ -101,6 +101,7 @@
//The Syndicate
/var/const/access_syndicate = 150//General Syndicate Access
+/var/const/access_syndicate_leader = 151//Nuke Op Leader Access
//MONEY
/var/const/access_crate_cash = 200
diff --git a/code/game/jobs/job/civilian.dm b/code/game/jobs/job/civilian.dm
index b09f2cc3335..968736075f3 100644
--- a/code/game/jobs/job/civilian.dm
+++ b/code/game/jobs/job/civilian.dm
@@ -1,7 +1,7 @@
/datum/job/civilian
title = "Civilian"
flag = CIVILIAN
- department_flag = CIVILIAN
+ department_flag = SUPPORT
total_positions = -1
spawn_positions = -1
supervisors = "absolutely everyone"
diff --git a/code/game/jobs/job/support.dm b/code/game/jobs/job/support.dm
index 6e64040b184..70e2ab4bbf5 100644
--- a/code/game/jobs/job/support.dm
+++ b/code/game/jobs/job/support.dm
@@ -87,18 +87,18 @@
equip(var/mob/living/carbon/human/H)
if(!H) return 0
- H.equip_to_slot_or_del(new /obj/item/clothing/under/rank/hydroponics(H), slot_w_uniform)
- H.equip_to_slot_or_del(new /obj/item/clothing/shoes/black(H), slot_shoes)
- H.equip_to_slot_or_del(new /obj/item/clothing/gloves/botanic_leather(H), slot_gloves)
- H.equip_to_slot_or_del(new /obj/item/clothing/suit/apron(H), slot_wear_suit)
- H.equip_to_slot_or_del(new /obj/item/device/analyzer/plant_analyzer(H), slot_s_store)
- H.equip_to_slot_or_del(new /obj/item/device/pda/botanist(H), slot_wear_pda)
+ H.equip_or_collect(new /obj/item/clothing/under/rank/hydroponics(H), slot_w_uniform)
+ H.equip_or_collect(new /obj/item/clothing/shoes/black(H), slot_shoes)
+ H.equip_or_collect(new /obj/item/clothing/gloves/botanic_leather(H), slot_gloves)
+ H.equip_or_collect(new /obj/item/clothing/suit/apron(H), slot_wear_suit)
+ H.equip_or_collect(new /obj/item/device/analyzer/plant_analyzer(H), slot_s_store)
+ H.equip_or_collect(new /obj/item/device/pda/botanist(H), slot_wear_pda)
switch(H.backbag)
- if(1) H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H), slot_r_hand)
- if(2) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack(H), slot_back)
- if(3) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel_hyd(H), slot_back)
- if(4) H.equip_to_slot_or_del(new /obj/item/weapon/storage/backpack/satchel(H), slot_back)
- H.equip_to_slot_or_del(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack)
+ if(1) H.equip_or_collect(new /obj/item/weapon/storage/box/survival(H), slot_r_hand)
+ if(2) H.equip_or_collect(new /obj/item/weapon/storage/backpack(H), slot_back)
+ if(3) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel_hyd(H), slot_back)
+ if(4) H.equip_or_collect(new /obj/item/weapon/storage/backpack/satchel(H), slot_back)
+ H.equip_or_collect(new /obj/item/weapon/storage/box/survival(H.back), slot_in_backpack)
return 1
diff --git a/code/game/jobs/job_controller.dm b/code/game/jobs/job_controller.dm
index afe69e34765..3134dbc73c0 100644
--- a/code/game/jobs/job_controller.dm
+++ b/code/game/jobs/job_controller.dm
@@ -100,6 +100,7 @@ var/global/datum/controller/occupations/job_master
Debug("Running FOC, Job: [job], Level: [level], Flag: [flag]")
var/list/candidates = list()
for(var/mob/new_player/player in unassigned)
+ Debug(" - Player: [player] Banned: [jobban_isbanned(player, job.title)] Old Enough: [!job.player_old_enough(player.client)] Flag && Be Special: [flag] && [player.client.prefs.be_special] Job Department: [player.client.prefs.GetJobDepartment(job, level)] Job Flag: [job.flag] Job Department Flag = [job.department_flag]")
if(jobban_isbanned(player, job.title))
Debug("FOC isbanned failed, Player: [player]")
continue
@@ -331,6 +332,7 @@ var/global/datum/controller/occupations/job_master
// If the job isn't filled
if((job.current_positions < job.spawn_positions) || job.spawn_positions == -1)
Debug("DO pass, Player: [player], Level:[level], Job:[job.title]")
+ Debug(" - Job Flag: [job.flag] Job Department: [player.client.prefs.GetJobDepartment(job, level)] Job Current Pos: [job.current_positions] Job Spawn Positions = [job.spawn_positions]")
AssignRole(player, job.title)
unassigned -= player
break
diff --git a/code/game/jobs/jobs.dm b/code/game/jobs/jobs.dm
index 2714290d6b7..34c89783be7 100644
--- a/code/game/jobs/jobs.dm
+++ b/code/game/jobs/jobs.dm
@@ -116,7 +116,6 @@ var/list/support_positions = list(
"Mime",
"Barber",
"Magistrate",
- "Nanotrasen Representative",
"Nanotrasen Recruiter"
)
diff --git a/code/game/machinery/computer/card.dm b/code/game/machinery/computer/card.dm
index 8a920d8ac93..4fc52baa7ad 100644
--- a/code/game/machinery/computer/card.dm
+++ b/code/game/machinery/computer/card.dm
@@ -107,6 +107,7 @@
data["science_jobs"] = format_jobs(science_positions)
data["security_jobs"] = format_jobs(security_positions)
data["support_jobs"] = format_jobs(support_positions)
+ data["civilian_jobs"] = format_jobs(civilian_positions)
data["special_jobs"] = format_jobs(whitelisted_positions)
data["centcom_jobs"] = format_jobs(get_all_centcom_jobs())
diff --git a/code/game/machinery/computer/telecrystalconsoles.dm b/code/game/machinery/computer/telecrystalconsoles.dm
new file mode 100644
index 00000000000..ae076b34349
--- /dev/null
+++ b/code/game/machinery/computer/telecrystalconsoles.dm
@@ -0,0 +1,221 @@
+#define NUKESCALINGMODIFIER 1
+
+var/list/possible_uplinker_IDs = list("Alfa","Bravo","Charlie","Delta","Echo","Foxtrot","Zero", "Niner")
+
+
+/obj/machinery/computer/telecrystals
+ name = "\improper Telecrystal assignment station"
+ desc = "A device used to manage telecrystals during group operations. You shouldn't be looking at this particular one..."
+ icon_state = "tcstation"
+
+/////////////////////////////////////////////
+/obj/machinery/computer/telecrystals/uplinker
+ name = "\improper Telecrystal upload/recieve station"
+ desc = "A device used to manage telecrystals during group operations. To use, simply insert your uplink. With your uplink installed \
+ you can upload your telecrystals to the group's pool using the console, or be assigned additional telecrystals by your lieutenant."
+ icon_state = "tcstation"
+ var/obj/item/uplinkholder = null
+ var/obj/machinery/computer/telecrystals/boss/linkedboss = null
+
+/obj/machinery/computer/telecrystals/uplinker/New()
+ ..()
+
+ var/ID
+ if(possible_uplinker_IDs.len)
+ ID = pick(possible_uplinker_IDs)
+ possible_uplinker_IDs -= ID
+ name = "[name] [ID]"
+ else
+ name = "[name] [rand(1,999)]"
+
+
+/obj/machinery/computer/telecrystals/uplinker/attackby(var/obj/item/O as obj, var/mob/user as mob)
+ if(istype(O, /obj/item))
+
+ if(uplinkholder)
+ user << "The [src] already has an uplink in it."
+ return
+
+ if(O.hidden_uplink)
+ var/obj/item/P = user.get_active_hand()
+ user.drop_item()
+ uplinkholder = P
+ P.loc = src
+ P.add_fingerprint(user)
+ update_icon()
+ updateUsrDialog()
+ else
+ user << "The [O] doesn't appear to be an uplink..."
+
+
+
+/obj/machinery/computer/telecrystals/uplinker/update_icon()
+ overlays.Cut()
+ if(uplinkholder)
+ overlays += "[initial(icon_state)]-closed"
+
+
+/obj/machinery/computer/telecrystals/uplinker/proc/ejectuplink()
+ if(uplinkholder)
+ uplinkholder.loc = get_turf(src.loc)
+ uplinkholder = null
+ update_icon()
+
+/obj/machinery/computer/telecrystals/uplinker/proc/donateTC(var/amt, var/addLog = 1)
+ if(uplinkholder && linkedboss)
+ if(amt <= uplinkholder.hidden_uplink.uses)
+ uplinkholder.hidden_uplink.uses -= amt
+ linkedboss.storedcrystals += amt
+ if(addLog)
+ linkedboss.logTransfer("[src] donated [amt] telecrystals to [linkedboss].")
+
+/obj/machinery/computer/telecrystals/uplinker/proc/giveTC(var/amt, var/addLog = 1)
+ if(uplinkholder && linkedboss)
+ if(amt <= linkedboss.storedcrystals)
+ uplinkholder.hidden_uplink.uses += amt
+ linkedboss.storedcrystals -= amt
+ if(addLog)
+ linkedboss.logTransfer("[src] recieved [amt] telecrystals from [linkedboss].")
+
+///////
+
+/obj/machinery/computer/telecrystals/uplinker/attack_hand(mob/user as mob)
+ if(..())
+ return
+ src.add_fingerprint(user)
+ user.set_machine(src)
+
+ var/dat = ""
+ if(linkedboss)
+ dat += "[linkedboss] has [linkedboss.storedcrystals] telecrystals available for distribution.
"
+ else
+ dat += "No linked management consoles detected. Scan for uplink stations using the management console.
"
+
+ if(uplinkholder)
+ dat += "[uplinkholder.hidden_uplink.uses] telecrystals remain in this uplink.
"
+ if(linkedboss)
+ dat += "Donate TC: 1 | 5"
+ dat += "
Eject Uplink"
+
+
+ var/datum/browser/popup = new(user, "computer", "Telecrystal Upload/Recieve Station", 700, 500)
+ popup.set_content(dat)
+ popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
+ popup.open()
+ return
+
+/obj/machinery/computer/telecrystals/uplinker/Topic(href, href_list)
+ if(..())
+ return
+
+ if(href_list["donate1"])
+ donateTC(1)
+
+ if(href_list["donate5"])
+ donateTC(5)
+
+ if(href_list["eject"])
+ ejectuplink()
+
+ src.updateUsrDialog()
+
+
+/////////////////////////////////////////
+/obj/machinery/computer/telecrystals/boss
+ name = "team Telecrystal management console"
+ desc = "A device used to manage telecrystals during group operations. To use, simply initialize the machine by scanning for nearby uplink stations. \
+ Once the consoles are linked up, you can assign any telecrystals amongst your operatives; be they donated by your agents or rationed to the squad \
+ based on the danger rating of the mission."
+ icon_state = "tcboss"
+ var/virgin = 1
+ var/scanrange = 10
+ var/storedcrystals = 0
+ var/list/TCstations = list()
+ var/list/transferlog = list()
+
+/obj/machinery/computer/telecrystals/boss/proc/logTransfer(var/logmessage)
+ transferlog += ("[worldtime2text()] [logmessage]")
+
+/obj/machinery/computer/telecrystals/boss/proc/scanUplinkers()
+ for(var/obj/machinery/computer/telecrystals/uplinker/A in range(scanrange, src.loc))
+ if(!A.linkedboss)
+ TCstations += A
+ A.linkedboss = src
+ if(virgin)
+ getDangerous()
+ virgin = 0
+
+/obj/machinery/computer/telecrystals/boss/proc/getDangerous()//This scales the TC assigned with the round population.
+ ..()
+ var/danger
+ danger = player_list.len
+ while(!IsMultiple(++danger,10))//Just round up to the nearest multiple of ten.
+ scaleTC(danger)
+
+/obj/machinery/computer/telecrystals/boss/proc/scaleTC(var/amt)//Its own proc, since it'll probably need a lot of tweaks for balance, use a fancier algorhithm, etc.
+ storedcrystals += amt * NUKESCALINGMODIFIER
+
+/////////
+
+/obj/machinery/computer/telecrystals/boss/attack_hand(var/mob/user as mob)
+ if(..())
+ return
+ src.add_fingerprint(user)
+ user.set_machine(src)
+
+
+ var/dat = ""
+ dat += "Scan for TC stations.
"
+ dat += "This [src] has [storedcrystals] telecrystals available for distribution.
"
+ dat += "
"
+
+
+ for(var/obj/machinery/computer/telecrystals/uplinker/A in TCstations)
+ dat += "[A.name] | "
+ if(A.uplinkholder)
+ dat += "[A.uplinkholder.hidden_uplink.uses] telecrystals."
+ if(storedcrystals)
+ dat+= "
Add TC: 1 | 5"
+ dat += "
"
+
+ if(TCstations.len)
+ dat += "
Evenly distribute remaining TC.
"
+
+
+ for(var/entry in transferlog)
+ dat += "[entry]
"
+
+
+ var/datum/browser/popup = new(user, "computer", "Team Telecrystal Management Console", 700, 500)
+ popup.set_content(dat)
+ popup.set_title_image(user.browse_rsc_icon(src.icon, src.icon_state))
+ popup.open()
+ return
+
+/obj/machinery/computer/telecrystals/boss/Topic(href, href_list)
+ if(..())
+ return
+
+ if(href_list["scan"])
+ scanUplinkers()
+
+ if(href_list["give1"])
+ var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["give1"])
+ A.giveTC(1)
+
+ if(href_list["give5"])
+ var/obj/machinery/computer/telecrystals/uplinker/A = locate(href_list["give5"])
+ A.giveTC(5)
+
+ if(href_list["distrib"])
+ var/sanity = 0
+ while(storedcrystals && sanity < 100)
+ for(var/obj/machinery/computer/telecrystals/uplinker/A in TCstations)
+ A.giveTC(1,0)
+ sanity++
+ logTransfer("[src] evenly distributed telecrystals.")
+
+ src.updateUsrDialog()
+ return
+
+#undef NUKESCALINGMODIFIER
\ No newline at end of file
diff --git a/code/game/machinery/computer/telescience.dm b/code/game/machinery/computer/telescience.dm
index 153ab91dbc3..792afd86693 100644
--- a/code/game/machinery/computer/telescience.dm
+++ b/code/game/machinery/computer/telescience.dm
@@ -34,23 +34,33 @@
src.attack_hand()
/obj/machinery/computer/telescience/attack_hand(mob/user)
+ ui_interact(user)
+
+/obj/machinery/computer/telescience/ui_interact(mob/user, ui_key = "main", var/datum/nanoui/ui = null, var/force_open = 1)
if(..())
return
if(stat & (NOPOWER|BROKEN))
return
- var/t = ""
- t += "Set X"
- t += "Set Y"
- t += "Set Z"
- t += "
Current set coordinates:"
- t += "([x_co], [y_co], [z_co])"
- t += "
Send"
- t += " Receive"
- t += "
Recalibrate"
- var/datum/browser/popup = new(user, "telesci", name, 640, 480)
- popup.set_content(t)
- popup.open()
- return
+
+ // On first use, the coordinates are null. Rather than displaying null, we'll set them to unset.
+ if(!x_co)
+ x_co = "Unset"
+ if(!y_co)
+ y_co = "Unset"
+ if(!z_co)
+ z_co = "Unset"
+
+ var/data[0]
+ data["coordx"] = x_co
+ data["coordy"] = y_co
+ data["coordz"] = z_co
+
+ // Set up the Nano UI
+ ui = nanomanager.try_update_ui(user, src, ui_key, ui, data, force_open)
+ if (!ui)
+ ui = new(user, src, ui_key, "telescience_console.tmpl", "Telescience Console UI", 640, 480)
+ ui.set_initial_data(data)
+ ui.open()
/obj/machinery/computer/telescience/proc/telefail(var/level)
var/teleturf = get_turf(telepad)
@@ -63,7 +73,7 @@
s.start()
if(2)
for(var/mob/living/carbon/human/M in viewers(telepad, null))
- if(M.loc.loc == telepad.loc.loc) //stops the geneticists with xray vision getting irradiated
+ if(M.loc.loc == telepad.loc.loc) // Stops the geneticists with X-Ray vision getting irradiated
M.apply_effect((rand(50, 100)), IRRADIATE, 0)
M << "\red You feel irradiated."
if(3)
@@ -174,14 +184,14 @@
/obj/machinery/computer/telescience/proc/checkFail()
var/fail = 0
- if(x_co == "")
- usr << "\red Error: set X coordinates."
+ if(x_co == "" || x_co == "Unset")
+ usr << "\red Error: set X coordinate."
fail = 1
- if(y_co == "")
- usr << "\red Error: set Y coordinates."
+ if(y_co == "" || y_co == "Unset")
+ usr << "\red Error: set Y coordinate."
fail = 1
- if(z_co == "")
- usr << "\red Error: set Z coordinates."
+ if(z_co == "" || z_co == "Unset")
+ usr << "\red Error: set Z coordinate."
fail = 1
if(x_co < 11 || x_co > 245)
usr << "\red Error: X is less than 11 or greater than 245."
@@ -208,30 +218,36 @@
a = copytext(sanitize(a), 1, 20)
x_co = a
x_co = text2num(x_co)
+ nanomanager.update_uis(src)
return
if(href_list["sety"])
var/b = input("Please input desired Y coordinate.", name, y_co) as num
b = copytext(sanitize(b), 1, 20)
y_co = b
y_co = text2num(y_co)
+ nanomanager.update_uis(src)
return
if(href_list["setz"])
var/c = input("Please input desired Z coordinate.", name, z_co) as num
c = copytext(sanitize(c), 1, 20)
z_co = c
z_co = text2num(z_co)
+ nanomanager.update_uis(src)
return
if(href_list["send"])
teleprep(0)
+ nanomanager.update_uis(src)
return
if(href_list["receive"])
teleprep(1)
+ nanomanager.update_uis(src)
return
if(href_list["recal"])
if(telepad == null)
for(var/obj/machinery/telepad/T in range(src,10))
telepad = T
- if(!telepad) return
+ if(!telepad)
+ return
var/teleturf = get_turf(telepad)
teles_left = rand(8,12)
x_off = rand(-10,10)
@@ -240,12 +256,13 @@
s.set_up(5, 1, teleturf)
s.start()
usr << "\blue Calibration successful."
+ nanomanager.update_uis(src)
return
-/obj/machinery/computer/telescience/attackby(I as obj, user as mob) //Emagging.
+/obj/machinery/computer/telescience/attackby(I as obj, user as mob) // Emagging
if(istype(I,/obj/item/weapon/card/emag))
if (src.emagged == 0)
- user << "\blue You scramble the Telescience authentication key to an unknown signal, you should be able to teleport to more places now!"
+ user << "\blue You scramble the Telescience authentication key to an unknown signal. You should be able to teleport to more places now!"
src.emagged = 1
else
user << "\red The machine seems unaffected by the card swipe..."
diff --git a/code/game/machinery/syndicatebomb.dm b/code/game/machinery/syndicatebomb.dm
new file mode 100644
index 00000000000..90ff796bb59
--- /dev/null
+++ b/code/game/machinery/syndicatebomb.dm
@@ -0,0 +1,310 @@
+/obj/machinery/syndicatebomb
+ icon = 'icons/obj/assemblies.dmi'
+ name = "syndicate bomb"
+ icon_state = "syndicate-bomb"
+ desc = "A large and menacing device. Can be bolted down with a wrench."
+
+ anchored = 0
+ density = 0
+ layer = MOB_LAYER - 0.1 //so people can't hide it and it's REALLY OBVIOUS
+ unacidable = 1
+
+ var/datum/wires/syndicatebomb/wires = null
+ var/timer = 60
+ var/open_panel = 0 //are the wires exposed?
+ var/active = 0 //is the bomb counting down?
+ var/defused = 0 //is the bomb capable of exploding?
+ var/obj/item/weapon/bombcore/payload = /obj/item/weapon/bombcore/
+ var/beepsound = 'sound/items/timer.ogg'
+
+/obj/machinery/syndicatebomb/process()
+ if(active && !defused && (timer > 0)) //Tick Tock
+ var/volume = (timer <= 10 ? 30 : 5) // Tick louder when the bomb is closer to being detonated.
+ playsound(loc, beepsound, volume, 0)
+ timer--
+ if(active && !defused && (timer <= 0)) //Boom
+ active = 0
+ timer = 60
+ update_icon()
+ if(payload in src)
+ payload.detonate()
+ return
+ if(!active || defused) //Counter terrorists win
+ if(defused && payload in src)
+ payload.defuse()
+ return
+
+/obj/machinery/syndicatebomb/New()
+ wires = new(src)
+ payload = new payload(src)
+ update_icon()
+ ..()
+
+
+/obj/machinery/syndicatebomb/examine()
+ ..()
+ usr << "A digital display on it reads \"[timer]\"."
+
+/obj/machinery/syndicatebomb/update_icon()
+ icon_state = "[initial(icon_state)][active ? "-active" : "-inactive"][open_panel ? "-wires" : ""]"
+
+/obj/machinery/syndicatebomb/attackby(var/obj/item/I, var/mob/user)
+ if(istype(I, /obj/item/weapon/wrench))
+ if(!anchored)
+ if(!isturf(src.loc) || istype(src.loc, /turf/space))
+ user << "The bomb must be placed on solid ground to attach it"
+ else
+ user << "You firmly wrench the bomb to the floor"
+ playsound(loc, 'sound/items/ratchet.ogg', 50, 1)
+ anchored = 1
+ if(active)
+ user << "The bolts lock in place"
+ else
+ if(!active)
+ user << "You wrench the bomb from the floor"
+ playsound(loc, 'sound/items/ratchet.ogg', 50, 1)
+ anchored = 0
+ else
+ user << "The bolts are locked down!"
+
+ else if(istype(I, /obj/item/weapon/screwdriver))
+ open_panel = !open_panel
+ update_icon()
+ user << "You [open_panel ? "open" : "close"] the wire panel."
+
+ else if(istype(I, /obj/item/weapon/wirecutters) || istype(I, /obj/item/device/multitool) || istype(I, /obj/item/device/assembly/signaler ))
+ if(open_panel)
+ wires.Interact(user)
+
+ else if(istype(I, /obj/item/weapon/crowbar))
+ if(open_panel && isWireCut(WIRE_BOOM) && isWireCut(WIRE_UNBOLT) && isWireCut(WIRE_DELAY) && isWireCut(WIRE_PROCEED) && isWireCut(WIRE_ACTIVATE))
+ if(payload)
+ user << "You carefully pry out [payload]."
+ payload.loc = user.loc
+ payload = null
+ else
+ user << "There isn't anything in here to remove!"
+ else if (open_panel)
+ user << "The wires conneting the shell to the explosives are holding it down!"
+ else
+ user << "The cover is screwed on, it won't pry off!"
+ else if(istype(I, /obj/item/weapon/bombcore))
+ if(!payload)
+ payload = I
+ user << "You place [payload] into [src]."
+ user.drop_item()
+ payload.loc = src
+ else
+ user << "[payload] is already loaded into [src], you'll have to remove it first."
+ else
+ ..()
+
+/obj/machinery/syndicatebomb/attack_hand(var/mob/user)
+ interact(user)
+
+/obj/machinery/syndicatebomb/attack_ai()
+ return
+
+/obj/machinery/syndicatebomb/interact(var/mob/user)
+ if(wires)
+ wires.Interact(user)
+ if(!open_panel)
+ if(!active)
+ spawn()
+ settings(user)
+ return
+ else if(anchored)
+ user << "The bomb is bolted to the floor!"
+ return
+
+/obj/machinery/syndicatebomb/proc/settings(var/mob/user)
+ var/newtime = input(user, "Please set the timer.", "Timer", "[timer]") as num
+ newtime = Clamp(newtime, 60, 60000)
+ if(in_range(src, user) && isliving(user)) //No running off and setting bombs from across the station
+ timer = newtime
+ src.loc.visible_message("\icon[src] timer set for [timer] seconds.")
+ if(alert(user,"Would you like to start the countdown now?",,"Yes","No") == "Yes" && in_range(src, user) && isliving(user))
+ if(defused || active)
+ if(defused)
+ src.loc.visible_message("\icon[src] Device error: User intervention required.")
+ return
+ else
+ src.loc.visible_message("\icon[src] [timer] seconds until detonation, please clear the area.")
+ playsound(loc, 'sound/machines/click.ogg', 30, 1)
+ active = 1
+ update_icon()
+ add_fingerprint(user)
+
+ var/turf/bombturf = get_turf(src)
+ var/area/A = get_area(bombturf)
+ if(payload && !istype(payload, /obj/item/weapon/bombcore/training))
+ message_admins("[key_name(user)]? has primed a [name] ([payload]) for detonation at [A.name] (JMP).")
+ log_game("[key_name(user)] has primed a [name] ([payload]) for detonation at [A.name]([bombturf.x],[bombturf.y],[bombturf.z])")
+ payload.adminlog = "The [src.name] that [key_name(user)] had primed detonated!"
+
+/obj/machinery/syndicatebomb/proc/isWireCut(var/index)
+ return wires.IsIndexCut(index)
+
+///Bomb Subtypes///
+
+/obj/machinery/syndicatebomb/training
+ name = "training bomb"
+ icon_state = "training-bomb"
+ desc = "A salvaged syndicate device gutted of its explosives to be used as a training aid for aspiring bomb defusers."
+ payload = /obj/item/weapon/bombcore/training/
+
+/obj/machinery/syndicatebomb/badmin
+ name = "generic summoning badmin bomb"
+ desc = "Oh god what is in this thing?"
+ payload = /obj/item/weapon/bombcore/badmin/summon/
+
+/obj/machinery/syndicatebomb/badmin/clown
+ name = "clown bomb"
+ icon_state = "clown-bomb"
+ desc = "HONK."
+ payload = /obj/item/weapon/bombcore/badmin/summon/clown
+ beepsound = 'sound/items/bikehorn.ogg'
+
+/obj/machinery/syndicatebomb/badmin/varplosion
+ payload = /obj/item/weapon/bombcore/badmin/explosion/
+
+///Bomb Cores///
+
+/obj/item/weapon/bombcore
+ name = "bomb payload"
+ desc = "A powerful secondary explosive of syndicate design and unknown composition, it should be stable under normal conditions..."
+ icon = 'icons/obj/assemblies.dmi'
+ icon_state = "bombcore"
+ item_state = "eshield0"
+ w_class = 3.0
+ origin_tech = "syndicate=6;combat=5"
+ var/adminlog = null
+
+/obj/item/weapon/bombcore/ex_act(severity) //Little boom can chain a big boom
+ src.detonate()
+
+/obj/item/weapon/bombcore/proc/detonate()
+ if(adminlog)
+ message_admins(adminlog)
+ log_game(adminlog)
+ explosion(get_turf(src),2,5,11)
+ del(src)
+
+/obj/item/weapon/bombcore/proc/defuse()
+//Note: Because of how var/defused is used you shouldn't override this UNLESS you intend to set the var to 0 or
+// otherwise remove the core/reset the wires before the end of defuse(). It will repeatedly be called otherwise.
+
+///Bomb Core Subtypes///
+
+/obj/item/weapon/bombcore/training
+ name = "dummy payload"
+ desc = "A nanotrasen replica of a syndicate payload. Its not intended to explode but to announce that it WOULD have exploded, then rewire itself to allow for more training."
+ origin_tech = null
+ var/defusals = 0
+ var/attempts = 0
+
+/obj/item/weapon/bombcore/training/proc/reset()
+ var/obj/machinery/syndicatebomb/holder = src.loc
+ if(istype(holder))
+ if(holder.wires)
+ holder.wires.Shuffle()
+ holder.defused = 0
+ holder.open_panel = 0
+ holder.update_icon()
+ holder.updateDialog()
+
+/obj/item/weapon/bombcore/training/detonate()
+ var/obj/machinery/syndicatebomb/holder = src.loc
+ if(istype(holder))
+ attempts++
+ holder.loc.visible_message("\icon[holder] Alert: Bomb has detonated. Your score is now [defusals] for [attempts]. Resetting wires...")
+ reset()
+ else
+ del(src)
+
+/obj/item/weapon/bombcore/training/defuse()
+ var/obj/machinery/syndicatebomb/holder = src.loc
+ if(istype(holder))
+ attempts++
+ defusals++
+ holder.loc.visible_message("\icon[holder] Alert: Bomb has been defused. Your score is now [defusals] for [attempts]! Resetting wires in 5 seconds...")
+ sleep(50) //Just in case someone is trying to remove the bomb core this gives them a little window to crowbar it out
+ if(istype(holder))
+ reset()
+
+/obj/item/weapon/bombcore/badmin
+ name = "badmin payload"
+ desc = "If you're seeing this someone has either made a mistake or gotten dangerously savvy with var editing!"
+ origin_tech = null
+
+/obj/item/weapon/bombcore/badmin/defuse() //because we wouldn't want them being harvested by players
+ var/obj/machinery/syndicatebomb/B = src.loc
+ del(B)
+ del(src)
+
+/obj/item/weapon/bombcore/badmin/summon/
+ var/summon_path = /obj/item/weapon/reagent_containers/food/snacks/cookie
+ var/amt_summon = 1
+
+/obj/item/weapon/bombcore/badmin/summon/detonate()
+ var/obj/machinery/syndicatebomb/B = src.loc
+ for(var/i = 0; i < amt_summon; i++)
+ var/atom/movable/X = new summon_path
+ X.loc = get_turf(src)
+ if(prob(50))
+ for(var/j = 1, j <= rand(1, 3), j++)
+ step(X, pick(NORTH,SOUTH,EAST,WEST))
+ del(B)
+ del(src)
+
+/obj/item/weapon/bombcore/badmin/summon/clown
+ summon_path = /mob/living/simple_animal/hostile/retaliate/clown
+ amt_summon = 100
+
+/obj/item/weapon/bombcore/badmin/summon/clown/defuse()
+ playsound(src.loc, 'sound/misc/sadtrombone.ogg', 50)
+ ..()
+
+/obj/item/weapon/bombcore/badmin/explosion/
+ var/HeavyExplosion = 2
+ var/MediumExplosion = 5
+ var/LightExplosion = 11
+
+/obj/item/weapon/bombcore/badmin/explosion/detonate()
+ explosion(get_turf(src),HeavyExplosion,MediumExplosion,LightExplosion)
+
+///Syndicate Detonator (aka the big red button)///
+
+/obj/item/device/syndicatedetonator
+ name = "big red button"
+ desc = "Nothing good can come of pressing a button this garish..."
+ icon = 'icons/obj/assemblies.dmi'
+ icon_state = "bigred"
+ item_state = "electronic"
+ w_class = 1.0
+ origin_tech = "syndicate=2"
+ var/cooldown = 0
+ var/detonated = 0
+ var/existant = 0
+
+/obj/item/device/syndicatedetonator/attack_self(mob/user as mob)
+ if(!cooldown)
+ for(var/obj/machinery/syndicatebomb/B in machines)
+ if(B.active)
+ B.timer = 0
+ detonated++
+ existant++
+ playsound(user, 'sound/machines/click.ogg', 20, 1)
+ user << "[existant] found, [detonated] triggered."
+ if(detonated)
+ var/turf/T = get_turf(src)
+ var/area/A = get_area(T)
+ detonated--
+ var/log_str = "[key_name(user)]? has remotely detonated [detonated ? "syndicate bombs" : "a syndicate bomb"] using a [name] at [A.name] (JMP)."
+ bombers += log_str
+ message_admins(log_str)
+ log_game("[key_name(user)] has remotely detonated [detonated ? "syndicate bombs" : "a syndicate bomb"] using a [name] at [A.name]([T.x],[T.y],[T.z])")
+ detonated = 0
+ existant = 0
+ cooldown = 1
+ spawn(30) cooldown = 0
\ No newline at end of file
diff --git a/code/game/mecha/combat/gygax.dm b/code/game/mecha/combat/gygax.dm
index a68fd42e0e5..ab30fab2269 100644
--- a/code/game/mecha/combat/gygax.dm
+++ b/code/game/mecha/combat/gygax.dm
@@ -5,8 +5,8 @@
initial_icon = "gygax"
step_in = 3
dir_in = 1 //Facing North.
- health = 300
- deflect_chance = 15
+ health = 250
+ deflect_chance = 5
damage_absorption = list("brute"=0.75,"fire"=1,"bullet"=0.8,"laser"=0.7,"energy"=0.85,"bomb"=1)
max_temperature = 25000
infra_luminosity = 6
@@ -15,8 +15,9 @@
wreckage = /obj/effect/decal/mecha_wreckage/gygax
internal_damage_threshold = 35
max_equip = 3
- maxsize = 1
+ maxsize = 2
force = 10
+ step_energy_drain = 3
/obj/mecha/combat/gygax/loaded/New()
..()
@@ -27,25 +28,25 @@
return
/obj/mecha/combat/gygax/dark
- desc = "A lightweight exosuit used by Nanotrasen Death Squads. A significantly upgraded Gygax security mech."
+ desc = "A lightweight exosuit, painted in a dark scheme. This model appears to have some modifications."
name = "Dark Gygax"
icon_state = "darkgygax"
initial_icon = "darkgygax"
- health = 400
- deflect_chance = 25
+ health = 300
+ deflect_chance = 15
damage_absorption = list("brute"=0.6,"fire"=0.8,"bullet"=0.6,"laser"=0.5,"energy"=0.65,"bomb"=0.8)
- max_temperature = 45000
+ max_temperature = 35000
overload_coeff = 1
+ operation_req_access = list(access_syndicate)
wreckage = /obj/effect/decal/mecha_wreckage/gygax/dark
max_equip = 4
maxsize = 2
- step_energy_drain = 5
-/obj/mecha/combat/gygax/dark/New()
+/obj/mecha/combat/gygax/dark/loaded/New()
..()
- var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot
+ var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/carbine
ME.attach(src)
- ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang/clusterbang
+ ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack/flashbang
ME.attach(src)
ME = new /obj/item/mecha_parts/mecha_equipment/teleporter
ME.attach(src)
diff --git a/code/game/mecha/combat/marauder.dm b/code/game/mecha/combat/marauder.dm
index 6e924e13ebb..c332603ab46 100644
--- a/code/game/mecha/combat/marauder.dm
+++ b/code/game/mecha/combat/marauder.dm
@@ -43,7 +43,23 @@
operation_req_access = list(access_syndicate)
wreckage = /obj/effect/decal/mecha_wreckage/mauler
-/obj/mecha/combat/marauder/New()
+/obj/mecha/combat/marauder/mauler/loaded/New()
+ ..()
+ var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/lmg(src)
+ ME.attach(src)
+ ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/scattershot(src)
+ ME.attach(src)
+ ME = new /obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack(src)
+ ME.attach(src)
+ ME = new /obj/item/mecha_parts/mecha_equipment/tesla_energy_relay(src)
+ ME.attach(src)
+ ME = new /obj/item/mecha_parts/mecha_equipment/antiproj_armor_booster(src)
+ ME.attach(src)
+ src.smoke_system.set_up(3, 0, src)
+ src.smoke_system.attach(src)
+ return
+
+/obj/mecha/combat/marauder/loaded/New()
..()
var/obj/item/mecha_parts/mecha_equipment/ME = new /obj/item/mecha_parts/mecha_equipment/weapon/energy/pulse
ME.attach(src)
diff --git a/code/game/mecha/equipment/weapons/weapons.dm b/code/game/mecha/equipment/weapons/weapons.dm
index 282a4a88d9f..01d95855f8c 100644
--- a/code/game/mecha/equipment/weapons/weapons.dm
+++ b/code/game/mecha/equipment/weapons/weapons.dm
@@ -201,13 +201,45 @@
return
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/carbine
- name = "\improper FNX-66 Carbine"
+ name = "FNX-66 Carbine"
icon_state = "mecha_carbine"
equip_cooldown = 5
- projectile = /obj/item/projectile/bullet/incendiary/mech
- projectiles = 12
+ projectile = /obj/item/projectile/bullet/incendiary/shell/dragonsbreath
+ fire_sound = 'sound/weapons/Gunshot.ogg'
+ projectiles = 24
projectile_energy_cost = 15
+ var/projectiles_per_shot = 1
+ var/deviation = 0.0
+ action(atom/target)
+ if(!action_checks(target)) return
+ var/turf/targloc = get_turf(target)
+ var/target_x = targloc.x
+ var/target_y = targloc.y
+ var/target_z = targloc.z
+ targloc = null
+ spawn for(var/i=1 to min(projectiles, projectiles_per_shot))
+ if(!chassis) break
+ var/turf/curloc = get_turf(chassis)
+ targloc = locate(target_x+GaussRandRound(deviation,1),target_y+GaussRandRound(deviation,1),target_z)
+ if (!targloc || !curloc)
+ continue
+ if (targloc == curloc)
+ continue
+
+ playsound(chassis, fire_sound, 50, 1)
+ var/obj/item/projectile/A = new projectile(curloc)
+ src.projectiles--
+ A.original = target
+ A.current = curloc
+ A.yo = targloc.y - curloc.y
+ A.xo = targloc.x - curloc.x
+ A.process()
+ sleep(2)
+ set_ready_state(0)
+ log_message("Fired from [src.name], targeting [target].")
+ do_after_cooldown()
+ return
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/silenced
name = "\improper S.H.H. \"Quietus\" Carbine"
@@ -222,7 +254,7 @@
name = "LBX AC 10 \"Scattershot\""
icon_state = "mecha_scatter"
equip_cooldown = 20
- projectile = /obj/item/projectile/bullet/midbullet10
+ projectile = /obj/item/projectile/bullet/midbullet12
fire_sound = 'sound/weapons/Gunshot.ogg'
projectiles = 40
projectile_energy_cost = 25
@@ -263,7 +295,7 @@
equip_cooldown = 10
projectile = /obj/item/projectile/bullet/weakbullet
fire_sound = 'sound/weapons/Gunshot.ogg'
- projectiles = 50
+ projectiles = 300
projectile_energy_cost = 20
var/projectiles_per_shot = 3
var/deviation = 0.3
@@ -299,11 +331,11 @@
return
/obj/item/mecha_parts/mecha_equipment/weapon/ballistic/missile_rack
- name = "SRM-4 Missile Rack"
+ name = "SRM-8 Missile Rack"
icon_state = "mecha_missilerack"
projectile = /obj/item/missile
fire_sound = 'sound/effects/bang.ogg'
- projectiles = 4
+ projectiles = 8
projectile_energy_cost = 1000
equip_cooldown = 60
var/missile_speed = 2
@@ -331,7 +363,7 @@
throw_impact(atom/hit_atom)
if(primed)
- explosion(hit_atom,1,2,2)
+ explosion(hit_atom, 0, 0, 2, 4)
del(src)
else
..()
@@ -345,7 +377,7 @@
projectiles = 6
missile_speed = 1.5
projectile_energy_cost = 800
- equip_cooldown = 150
+ equip_cooldown = 60
var/det_time = 20
size=1
action(target)
diff --git a/code/game/objects/items/devices/multitool.dm b/code/game/objects/items/devices/multitool.dm
index 497b5c4ef39..85a30681b1a 100644
--- a/code/game/objects/items/devices/multitool.dm
+++ b/code/game/objects/items/devices/multitool.dm
@@ -18,4 +18,44 @@
m_amt = 50
g_amt = 20
origin_tech = "magnets=1;engineering=1"
- var/obj/machinery/telecomms/buffer // simple machine buffer for device linkage
\ No newline at end of file
+ var/obj/machinery/telecomms/buffer // simple machine buffer for device linkage
+
+// Syndicate device disguised as a multitool; it will turn red when an AI camera is nearby.
+
+
+/obj/item/device/multitool/ai_detect
+ var/track_delay = 0
+
+/obj/item/device/multitool/ai_detect/New()
+ ..()
+ processing_objects += src
+
+
+/obj/item/device/multitool/ai_detect/Del()
+ processing_objects -= src
+ ..()
+
+/obj/item/device/multitool/ai_detect/process()
+
+ if(track_delay > world.time)
+ return
+
+ var/found_eye = 0
+
+ for(var/mob/aiEye/A in living_mob_list)
+
+ var/turf/our_turf = get_turf(src)
+ var/turf/eye_turf = get_turf(A)
+
+ if(get_dist(our_turf, eye_turf) < 9)
+ found_eye = 1
+ break
+
+ if(found_eye)
+ icon_state = "[initial(icon_state)]_red"
+ else
+ icon_state = initial(icon_state)
+
+ track_delay = world.time + 10 // 1 second
+ return
+
diff --git a/code/game/objects/items/devices/radio/beacon.dm b/code/game/objects/items/devices/radio/beacon.dm
index 6780d0e4977..0fd6dddf69b 100644
--- a/code/game/objects/items/devices/radio/beacon.dm
+++ b/code/game/objects/items/devices/radio/beacon.dm
@@ -48,6 +48,18 @@
del(src)
return
+/obj/item/device/radio/beacon/syndicate/bomb
+ name = "suspicious beacon"
+ desc = "A label on it reads: Warning: Activating this device will send a high-ordinance explosive to your location."
+ origin_tech = "bluespace=1;syndicate=7"
+
+/obj/item/device/radio/beacon/syndicate/bomb/attack_self(mob/user as mob)
+ if(user)
+ user << "\blue Locked In"
+ new /obj/machinery/syndicatebomb( user.loc )
+ playsound(src, 'sound/effects/pop.ogg', 100, 1, 1)
+ del(src)
+ return
/obj/item/device/telepad_beacon
diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplinks.dm
index 5dc95d86680..de6dcdb21e3 100644
--- a/code/game/objects/items/devices/uplinks.dm
+++ b/code/game/objects/items/devices/uplinks.dm
@@ -277,4 +277,4 @@ var/list/world_uplinks = list()
/obj/item/device/radio/headset/uplink/New()
..()
hidden_uplink = new(src)
- hidden_uplink.uses = 10
+ hidden_uplink.uses = 20
diff --git a/code/game/objects/items/devices/violin.dm b/code/game/objects/items/devices/violin.dm
index b44c99faf3f..47acfb7c132 100644
--- a/code/game/objects/items/devices/violin.dm
+++ b/code/game/objects/items/devices/violin.dm
@@ -7,396 +7,26 @@
icon_state = "violin"
item_state = "violin"
force = 10
- var/datum/song/song
- var/playing = 0
- var/help = 0
- var/edit = 1
- var/repeat = 0
+ var/datum/song/handheld/song
-/obj/item/device/violin/proc/playnote(var/note as text)
- //world << "Note: [note]"
- var/soundfile
- /*BYOND loads resource files at compile time if they are ''. This means you can't really manipulate them dynamically.
- Tried doing it dynamically at first but its more trouble than its worth. Would have saved many lines tho.*/
- switch(note)
- if("Cn1") soundfile = 'sound/violin/Cn1.mid'
- if("C#1") soundfile = 'sound/violin/C#1.mid'
- if("Db1") soundfile = 'sound/violin/Db1.mid'
- if("Dn1") soundfile = 'sound/violin/Dn1.mid'
- if("D#1") soundfile = 'sound/violin/D#1.mid'
- if("Eb1") soundfile = 'sound/violin/Eb1.mid'
- if("En1") soundfile = 'sound/violin/En1.mid'
- if("E#1") soundfile = 'sound/violin/E#1.mid'
- if("Fb1") soundfile = 'sound/violin/Fb1.mid'
- if("Fn1") soundfile = 'sound/violin/Fn1.mid'
- if("F#1") soundfile = 'sound/violin/F#1.mid'
- if("Gb1") soundfile = 'sound/violin/Gb1.mid'
- if("Gn1") soundfile = 'sound/violin/Gn1.mid'
- if("G#1") soundfile = 'sound/violin/G#1.mid'
- if("Ab1") soundfile = 'sound/violin/Ab1.mid'
- if("An1") soundfile = 'sound/violin/An1.mid'
- if("A#1") soundfile = 'sound/violin/A#1.mid'
- if("Bb1") soundfile = 'sound/violin/Bb1.mid'
- if("Bn1") soundfile = 'sound/violin/Bn1.mid'
- if("B#1") soundfile = 'sound/violin/B#1.mid'
- if("Cb2") soundfile = 'sound/violin/Cb2.mid'
- if("Cn2") soundfile = 'sound/violin/Cn2.mid'
- if("C#2") soundfile = 'sound/violin/C#2.mid'
- if("Db2") soundfile = 'sound/violin/Db2.mid'
- if("Dn2") soundfile = 'sound/violin/Dn2.mid'
- if("D#2") soundfile = 'sound/violin/D#2.mid'
- if("Eb2") soundfile = 'sound/violin/Eb2.mid'
- if("En2") soundfile = 'sound/violin/En2.mid'
- if("E#2") soundfile = 'sound/violin/E#2.mid'
- if("Fb2") soundfile = 'sound/violin/Fb2.mid'
- if("Fn2") soundfile = 'sound/violin/Fn2.mid'
- if("F#2") soundfile = 'sound/violin/F#2.mid'
- if("Gb2") soundfile = 'sound/violin/Gb2.mid'
- if("Gn2") soundfile = 'sound/violin/Gn2.mid'
- if("G#2") soundfile = 'sound/violin/G#2.mid'
- if("Ab2") soundfile = 'sound/violin/Ab2.mid'
- if("An2") soundfile = 'sound/violin/An2.mid'
- if("A#2") soundfile = 'sound/violin/A#2.mid'
- if("Bb2") soundfile = 'sound/violin/Bb2.mid'
- if("Bn2") soundfile = 'sound/violin/Bn2.mid'
- if("B#2") soundfile = 'sound/violin/B#2.mid'
- if("Cb3") soundfile = 'sound/violin/Cb3.mid'
- if("Cn3") soundfile = 'sound/violin/Cn3.mid'
- if("C#3") soundfile = 'sound/violin/C#3.mid'
- if("Db3") soundfile = 'sound/violin/Db3.mid'
- if("Dn3") soundfile = 'sound/violin/Dn3.mid'
- if("D#3") soundfile = 'sound/violin/D#3.mid'
- if("Eb3") soundfile = 'sound/violin/Eb3.mid'
- if("En3") soundfile = 'sound/violin/En3.mid'
- if("E#3") soundfile = 'sound/violin/E#3.mid'
- if("Fb3") soundfile = 'sound/violin/Fb3.mid'
- if("Fn3") soundfile = 'sound/violin/Fn3.mid'
- if("F#3") soundfile = 'sound/violin/F#3.mid'
- if("Gb3") soundfile = 'sound/violin/Gb3.mid'
- if("Gn3") soundfile = 'sound/violin/Gn3.mid'
- if("G#3") soundfile = 'sound/violin/G#3.mid'
- if("Ab3") soundfile = 'sound/violin/Ab3.mid'
- if("An3") soundfile = 'sound/violin/An3.mid'
- if("A#3") soundfile = 'sound/violin/A#3.mid'
- if("Bb3") soundfile = 'sound/violin/Bb3.mid'
- if("Bn3") soundfile = 'sound/violin/Bn3.mid'
- if("B#3") soundfile = 'sound/violin/B#3.mid'
- if("Cb4") soundfile = 'sound/violin/Cb4.mid'
- if("Cn4") soundfile = 'sound/violin/Cn4.mid'
- if("C#4") soundfile = 'sound/violin/C#4.mid'
- if("Db4") soundfile = 'sound/violin/Db4.mid'
- if("Dn4") soundfile = 'sound/violin/Dn4.mid'
- if("D#4") soundfile = 'sound/violin/D#4.mid'
- if("Eb4") soundfile = 'sound/violin/Eb4.mid'
- if("En4") soundfile = 'sound/violin/En4.mid'
- if("E#4") soundfile = 'sound/violin/E#4.mid'
- if("Fb4") soundfile = 'sound/violin/Fb4.mid'
- if("Fn4") soundfile = 'sound/violin/Fn4.mid'
- if("F#4") soundfile = 'sound/violin/F#4.mid'
- if("Gb4") soundfile = 'sound/violin/Gb4.mid'
- if("Gn4") soundfile = 'sound/violin/Gn4.mid'
- if("G#4") soundfile = 'sound/violin/G#4.mid'
- if("Ab4") soundfile = 'sound/violin/Ab4.mid'
- if("An4") soundfile = 'sound/violin/An4.mid'
- if("A#4") soundfile = 'sound/violin/A#4.mid'
- if("Bb4") soundfile = 'sound/violin/Bb4.mid'
- if("Bn4") soundfile = 'sound/violin/Bn4.mid'
- if("B#4") soundfile = 'sound/violin/B#4.mid'
- if("Cb5") soundfile = 'sound/violin/Cb5.mid'
- if("Cn5") soundfile = 'sound/violin/Cn5.mid'
- if("C#5") soundfile = 'sound/violin/C#5.mid'
- if("Db5") soundfile = 'sound/violin/Db5.mid'
- if("Dn5") soundfile = 'sound/violin/Dn5.mid'
- if("D#5") soundfile = 'sound/violin/D#5.mid'
- if("Eb5") soundfile = 'sound/violin/Eb5.mid'
- if("En5") soundfile = 'sound/violin/En5.mid'
- if("E#5") soundfile = 'sound/violin/E#5.mid'
- if("Fb5") soundfile = 'sound/violin/Fb5.mid'
- if("Fn5") soundfile = 'sound/violin/Fn5.mid'
- if("F#5") soundfile = 'sound/violin/F#5.mid'
- if("Gb5") soundfile = 'sound/violin/Gb5.mid'
- if("Gn5") soundfile = 'sound/violin/Gn5.mid'
- if("G#5") soundfile = 'sound/violin/G#5.mid'
- if("Ab5") soundfile = 'sound/violin/Ab5.mid'
- if("An5") soundfile = 'sound/violin/An5.mid'
- if("A#5") soundfile = 'sound/violin/A#5.mid'
- if("Bb5") soundfile = 'sound/violin/Bb5.mid'
- if("Bn5") soundfile = 'sound/violin/Bn5.mid'
- if("B#5") soundfile = 'sound/violin/B#5.mid'
- if("Cb6") soundfile = 'sound/violin/Cb6.mid'
- if("Cn6") soundfile = 'sound/violin/Cn6.mid'
- if("C#6") soundfile = 'sound/violin/C#6.mid'
- if("Db6") soundfile = 'sound/violin/Db6.mid'
- if("Dn6") soundfile = 'sound/violin/Dn6.mid'
- if("D#6") soundfile = 'sound/violin/D#6.mid'
- if("Eb6") soundfile = 'sound/violin/Eb6.mid'
- if("En6") soundfile = 'sound/violin/En6.mid'
- if("E#6") soundfile = 'sound/violin/E#6.mid'
- if("Fb6") soundfile = 'sound/violin/Fb6.mid'
- if("Fn6") soundfile = 'sound/violin/Fn6.mid'
- if("F#6") soundfile = 'sound/violin/F#6.mid'
- if("Gb6") soundfile = 'sound/violin/Gb6.mid'
- if("Gn6") soundfile = 'sound/violin/Gn6.mid'
- if("G#6") soundfile = 'sound/violin/G#6.mid'
- if("Ab6") soundfile = 'sound/violin/Ab6.mid'
- if("An6") soundfile = 'sound/violin/An6.mid'
- if("A#6") soundfile = 'sound/violin/A#6.mid'
- if("Bb6") soundfile = 'sound/violin/Bb6.mid'
- if("Bn6") soundfile = 'sound/violin/Bn6.mid'
- if("B#6") soundfile = 'sound/violin/B#6.mid'
- if("Cb7") soundfile = 'sound/violin/Cb7.mid'
- if("Cn7") soundfile = 'sound/violin/Cn7.mid'
- if("C#7") soundfile = 'sound/violin/C#7.mid'
- if("Db7") soundfile = 'sound/violin/Db7.mid'
- if("Dn7") soundfile = 'sound/violin/Dn7.mid'
- if("D#7") soundfile = 'sound/violin/D#7.mid'
- if("Eb7") soundfile = 'sound/violin/Eb7.mid'
- if("En7") soundfile = 'sound/violin/En7.mid'
- if("E#7") soundfile = 'sound/violin/E#7.mid'
- if("Fb7") soundfile = 'sound/violin/Fb7.mid'
- if("Fn7") soundfile = 'sound/violin/Fn7.mid'
- if("F#7") soundfile = 'sound/violin/F#7.mid'
- if("Gb7") soundfile = 'sound/violin/Gb7.mid'
- if("Gn7") soundfile = 'sound/violin/Gn7.mid'
- if("G#7") soundfile = 'sound/violin/G#7.mid'
- if("Ab7") soundfile = 'sound/violin/Ab7.mid'
- if("An7") soundfile = 'sound/violin/An7.mid'
- if("A#7") soundfile = 'sound/violin/A#7.mid'
- if("Bb7") soundfile = 'sound/violin/Bb7.mid'
- if("Bn7") soundfile = 'sound/violin/Bn7.mid'
- if("B#7") soundfile = 'sound/violin/B#7.mid'
- if("Cb8") soundfile = 'sound/violin/Cb8.mid'
- if("Cn8") soundfile = 'sound/violin/Cn8.mid'
- if("C#8") soundfile = 'sound/violin/C#8.mid'
- if("Db8") soundfile = 'sound/violin/Db8.mid'
- if("Dn8") soundfile = 'sound/violin/Dn8.mid'
- if("D#8") soundfile = 'sound/violin/D#8.mid'
- if("Eb8") soundfile = 'sound/violin/Eb8.mid'
- if("En8") soundfile = 'sound/violin/En8.mid'
- if("E#8") soundfile = 'sound/violin/E#8.mid'
- if("Fb8") soundfile = 'sound/violin/Fb8.mid'
- if("Fn8") soundfile = 'sound/violin/Fn8.mid'
- if("F#8") soundfile = 'sound/violin/F#8.mid'
- if("Gb8") soundfile = 'sound/violin/Gb8.mid'
- if("Gn8") soundfile = 'sound/violin/Gn8.mid'
- if("G#8") soundfile = 'sound/violin/G#8.mid'
- if("Ab8") soundfile = 'sound/violin/Ab8.mid'
- if("An8") soundfile = 'sound/violin/An8.mid'
- if("A#8") soundfile = 'sound/violin/A#8.mid'
- if("Bb8") soundfile = 'sound/violin/Bb8.mid'
- if("Bn8") soundfile = 'sound/violin/Bn8.mid'
- if("B#8") soundfile = 'sound/violin/B#8.mid'
- if("Cb9") soundfile = 'sound/violin/Cb9.mid'
- if("Cn9") soundfile = 'sound/violin/Cn9.mid'
- else return
+/obj/item/device/violin/New()
+ song = new("violin", src)
+ song.instrumentExt = "ogg"
- hearers(15, get_turf(src)) << sound(soundfile)
-
-/obj/item/device/violin/proc/playsong()
- do
- var/cur_oct[7]
- var/cur_acc[7]
- for(var/i = 1 to 7)
- cur_oct[i] = "3"
- cur_acc[i] = "n"
-
- for(var/line in song.lines)
- //world << line
- for(var/beat in text2list(lowertext(line), ","))
- //world << "beat: [beat]"
- var/list/notes = text2list(beat, "/")
- for(var/note in text2list(notes[1], "-"))
- //world << "note: [note]"
- if(!playing || !isliving(loc))//If the violin is playing, or isn't held by a person
- playing = 0
- return
- if(lentext(note) == 0)
- continue
- //world << "Parse: [copytext(note,1,2)]"
- var/cur_note = text2ascii(note) - 96
- if(cur_note < 1 || cur_note > 7)
- continue
- for(var/i=2 to lentext(note))
- var/ni = copytext(note,i,i+1)
- if(!text2num(ni))
- if(ni == "#" || ni == "b" || ni == "n")
- cur_acc[cur_note] = ni
- else if(ni == "s")
- cur_acc[cur_note] = "#" // so shift is never required
- else
- cur_oct[cur_note] = ni
- playnote(uppertext(copytext(note,1,2)) + cur_acc[cur_note] + cur_oct[cur_note])
- if(notes.len >= 2 && text2num(notes[2]))
- sleep(song.tempo / text2num(notes[2]))
- else
- sleep(song.tempo)
- if(repeat > 0)
- repeat-- //Infinite loops are baaaad.
- while(repeat > 0)
- playing = 0
+/obj/item/device/violin/Destroy()
+ del(song)
+ song = null
+ ..()
/obj/item/device/violin/attack_self(mob/user as mob)
- if(!isliving(user) || user.stat || user.restrained() || user.lying) return
- user.set_machine(src)
+ interact(user)
- var/dat = "