diff --git a/baystation12.dme b/baystation12.dme index 4339f65601b..fe5eb63ea31 100644 --- a/baystation12.dme +++ b/baystation12.dme @@ -130,6 +130,7 @@ #include "code\datums\spell.dm" #include "code\datums\sun.dm" #include "code\datums\supplypacks.dm" +#include "code\datums\uplink_item.dm" #include "code\datums\diseases\appendicitis.dm" #include "code\datums\diseases\beesease.dm" #include "code\datums\diseases\brainrot.dm" @@ -514,6 +515,7 @@ #include "code\game\objects\items\devices\debugger.dm" #include "code\game\objects\items\devices\flash.dm" #include "code\game\objects\items\devices\flashlight.dm" +#include "code\game\objects\items\devices\handtv.dm" #include "code\game\objects\items\devices\laserpointer.dm" #include "code\game\objects\items\devices\lightreplacer.dm" #include "code\game\objects\items\devices\multitool.dm" @@ -587,6 +589,7 @@ #include "code\game\objects\items\weapons\wires.dm" #include "code\game\objects\items\weapons\grenades\bananade.dm" #include "code\game\objects\items\weapons\grenades\chem_grenade.dm" +#include "code\game\objects\items\weapons\grenades\clowngrenade.dm" #include "code\game\objects\items\weapons\grenades\emgrenade.dm" #include "code\game\objects\items\weapons\grenades\flashbang.dm" #include "code\game\objects\items\weapons\grenades\ghettobomb.dm" diff --git a/code/WorkInProgress/explosion_particles.dm b/code/WorkInProgress/explosion_particles.dm index 9cf81b27aee..4d0f24799e1 100644 --- a/code/WorkInProgress/explosion_particles.dm +++ b/code/WorkInProgress/explosion_particles.dm @@ -32,7 +32,8 @@ spawn(0) var/obj/effect/expl_particles/expl = new /obj/effect/expl_particles(src.location) var/direct = pick(alldirs) - for(i=0, i= 0 ? arccos(x / sqrt(x * x + y * y)) : -arccos(x / sqrt(x * x + y * y)) + +proc/rotate_icon(file, state, step = 1, aa = FALSE) + var icon/base = icon(file, state) + + var w, h, w2, h2 + + if(aa) + aa ++ + w = base.Width() + w2 = w * aa + h = base.Height() + h2 = h * aa + + var icon{result = icon(base); temp} + + for(var/angle in 0 to 360 step step) + if(angle == 0 ) continue + if(angle == 360) continue + temp = icon(base) + if(aa) temp.Scale(w2, h2) + temp.Turn(angle) + if(aa) temp.Scale(w, h) + result.Insert(temp, "[angle]") + + return result \ No newline at end of file diff --git a/code/datums/uplink_item.dm b/code/datums/uplink_item.dm new file mode 100644 index 00000000000..209faa93404 --- /dev/null +++ b/code/datums/uplink_item.dm @@ -0,0 +1,426 @@ +var/list/uplink_items = list() + +/proc/get_uplink_items(var/job = null) + // If not already initialized.. + if(!uplink_items.len) + + // Fill in the list and order it like this: + // A keyed list, acting as categories, which are lists to the datum. + + var/list/last = list() + for(var/item in typesof(/datum/uplink_item)) + + var/datum/uplink_item/I = new item() + if(!I.item) + continue + if(I.gamemodes.len && ticker && !(ticker.mode.name in I.gamemodes)) + continue + if(I.last) + last += I + continue + + if(!uplink_items[I.category]) + uplink_items[I.category] = list() + + uplink_items[I.category] += I + + for(var/datum/uplink_item/I in last) + if(!uplink_items[I.category]) + uplink_items[I.category] = list() + + uplink_items[I.category] += I + + return uplink_items + +// You can change the order of the list by putting datums before/after one another OR +// you can use the last variable to make sure it appears last, well have the category appear last. + +/datum/uplink_item + var/name = "item name" + var/category = "item category" + var/desc = "Item Description" + var/item = null + var/cost = 0 + 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/job = null + +/datum/uplink_item/proc/spawn_item(var/turf/loc, var/obj/item/device/uplink/U) + U.uses -= max(cost, 0) + feedback_add_details("traitor_uplink_items_bought", name) + return new item(loc) + +/datum/uplink_item/proc/buy(var/obj/item/device/uplink/hidden/U, var/mob/user) + + ..() + if(!istype(U)) + return 0 + + if (user.stat || user.restrained()) + return 0 + + if (!( istype(user, /mob/living/carbon/human))) + return 0 + + // If the uplink's holder is in the user's contents + if ((U.loc in user.contents || (in_range(U.loc, user) && istype(U.loc.loc, /turf)))) + user.set_machine(U) + if(cost > U.uses) + return 0 + + var/obj/I = spawn_item(get_turf(user), U) + + if(ishuman(user)) + var/mob/living/carbon/human/A = user + A.put_in_any_hand_if_possible(I) + U.purchase_log += "[user] ([user.ckey]) bought [name] for [cost]." + + U.interact(user) + return 1 + return 0 + +/* +// +// UPLINK ITEMS +// +*/ +//Work in Progress, job specific antag tools + +/datum/uplink_item/jobspecific + category = "Job Specific Tools" + +//Clown +/datum/uplink_item/jobspecific/clowngrenade + 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 + job = list("Clown") + +//Detective +/datum/uplink_item/jobspecific/evidenceforger + 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 + 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 + job = list("Detective") + +//Chef +/datum/uplink_item/jobspecific/specialsauce + 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 + 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 + job = list("Chef") + +//Janitor + +/datum/uplink_item/jobspecific/cautionsign + 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 + job = list("Janitor") + + +//Assistant + +/datum/uplink_item/jobspecific/pickpocketgloves + 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, belt, or pockets without them knowing, and pickpocketing puts the item directly into your hand." + item = /obj/item/clothing/gloves/black/thief + cost = 3 + job = list("Assistant") + +/datum/uplink_item/jobspecific/greytide + name = "Greytide Implant" + desc = "A box containing an implanter filled with a greytide implant when injected into another person makes them loyal to the greytide 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/greytide + cost = 7 + job = list("Assistant") +//Bartender + +/datum/uplink_item/jobspecific/drunkbullets + 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 + job = list("Bartender") + +//Engineer + +/datum/uplink_item/jobspecific/powergloves + 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 + job = list("Station Engineer","Chief Engineer") + +// DANGEROUS WEAPONS + +/datum/uplink_item/dangerous + category = "Highly Visible and Dangerous Weapons" + +/datum/uplink_item/dangerous/revolver + 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 + cost = 6 + +/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_magazine/a357 + cost = 2 + +/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 = 5 + +/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 + +/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 = 3 + + +// STEALTHY WEAPONS + +/datum/uplink_item/stealthy_weapons + category = "Stealthy and Inconspicuous Weapons" + +/datum/uplink_item/stealthy_weapons/para_pen + name = "Paralysis Pen" + desc = "A syringe disguised as a functional pen, filled with a neuromuscular-blocking drug that renders a target immobile on injection and makes them seem dead to observers. Side effects of the drug include noticeable drooling. The pen holds one dose of paralyzing agent, and cannot be refilled." + item = /obj/item/weapon/pen/paralysis + cost = 3 + +/datum/uplink_item/stealthy_weapons/soap + name = "Syndicate Soap" + desc = "A sinister-looking surfactant used to clean blood stains to hide murders and prevent DNA analysis. You can also drop it underfoot to slip people." + item = /obj/item/weapon/soap/syndie + cost = 1 + +/datum/uplink_item/stealthy_weapons/detomatix + 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 + + +// STEALTHY TOOLS + +/datum/uplink_item/stealthy_tools + category = "Stealth and Camouflage Items" + +/datum/uplink_item/stealthy_tools/chameleon_jumpsuit + name = "Chameleon Jumpsuit" + desc = "A jumpsuit used to imitate the uniforms of Nanotrasen crewmembers." + item = /obj/item/clothing/under/chameleon + cost = 3 + +/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 + +/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 + +/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 + +/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 = 4 + + +// DEVICE AND TOOLS + +/datum/uplink_item/device_tools + category = "Devices and Tools" + abstract = 1 + +/datum/uplink_item/device_tools/emag + 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 + +/datum/uplink_item/device_tools/toolbox + name = "Fully Loaded Toolbox" + desc = "The syndicate toolbox is a suspicious black and red. Aside from tools, it comes with cable and a multitool. Insulated gloves are not included." + item = /obj/item/weapon/storage/toolbox/syndicate + cost = 1 + +/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." + item = /obj/item/weapon/storage/box/syndie_kit/space + cost = 3 + +/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 + +/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 + +/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 + +/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 + +/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 + +/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 + +/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." + item = /obj/item/weapon/plastique + cost = 2 + +/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 + +/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 + +/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 + gamemodes = list("nuclear emergency") + + +// IMPLANTS + +/datum/uplink_item/implants + category = "Implants" + +/datum/uplink_item/implants/freedom + 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 + +/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 + +/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 + +/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 + + +// POINTLESS BADASSERY + +/datum/uplink_item/badass + category = "(Pointless) Badassery" + +/datum/uplink_item/badass/bundle + 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 + +/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 + +/datum/uplink_item/badass/random + name = "Random Item" + desc = "Picking this choice will send you a random item from the list. Useful for when you cannot think of a strategy to finish your objectives with." + item = /obj/item/weapon/storage/box/syndicate + cost = 0 + +/datum/uplink_item/badass/random/spawn_item(var/turf/loc, var/obj/item/device/uplink/U) + + var/list/buyable_items = get_uplink_items() + var/list/possible_items = list() + + for(var/category in buyable_items) + for(var/datum/uplink_item/I in buyable_items[category]) + if(I == src) + continue + if(I.cost > U.uses) + continue + possible_items += I + + if(possible_items.len) + var/datum/uplink_item/I = pick(possible_items) + U.uses -= max(0, I.cost) + feedback_add_details("traitor_uplink_items_bought","RN") + return new I.item(loc) diff --git a/code/defines/obj/weapon.dm b/code/defines/obj/weapon.dm index 353c6c5c85a..8e54278e9e0 100644 --- a/code/defines/obj/weapon.dm +++ b/code/defines/obj/weapon.dm @@ -294,6 +294,56 @@ flags = FPRINT | TABLEPASS attack_verb = list("warned", "cautioned", "smashed") + proximity_sign + var/timing = 0 + var/armed = 0 + var/timepassed = 0 + + attack_self(mob/user as mob) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(H.mind.assigned_role != "Janitor") + return + if(armed) + armed = 0 + user << "\blue You disarm \the [src]." + return + timing = !timing + if(timing) + processing_objects.Add(src) + else + armed = 0 + timepassed = 0 + H << "\blue You [timing ? "activate \the [src]'s timer, you have 15 seconds." : "de-activate \the [src]'s timer."]" + + process() + if(!timing) + processing_objects.Remove(src) + timepassed++ + if(timepassed >= 15 && !armed) + armed = 1 + timing = 0 + + HasProximity(atom/movable/AM as mob|obj) + if(armed) + if(istype(AM, /mob/living/carbon) && !istype(AM, /mob/living/carbon/brain)) + var/mob/living/carbon/C = AM + if(C.m_intent != "walk") + src.visible_message("The [src.name] beeps, \"Running on wet floors is hazardous to your health.\"") + explosion(src.loc,-1,2,0) + if(ishuman(C)) + dead_legs(C) + if(src) + del(src) + + proc/dead_legs(mob/living/carbon/human/H as mob) + var/datum/organ/external/l = H.get_organ("l_leg") + var/datum/organ/external/r = H.get_organ("r_leg") + if(l && !(l.status & ORGAN_DESTROYED)) + l.status |= ORGAN_DESTROYED + if(r && !(r.status & ORGAN_DESTROYED)) + r.status |= ORGAN_DESTROYED + /obj/item/weapon/caution/cone desc = "This cone is trying to warn you of something!" name = "warning cone" @@ -497,10 +547,11 @@ /obj/item/device/camera_bug name = "camera bug" + desc = "Tiny electronic device meant to bug cameras for viewing later." icon = 'icons/obj/device.dmi' - icon_state = "flash" + icon_state = "implant_evil" w_class = 1.0 - item_state = "electronic" + item_state = "" throw_speed = 4 throw_range = 20 @@ -835,3 +886,67 @@ icon_state = "capacitor" desc = "A debug item for research." origin_tech = "materials=8;programming=8;magnets=8;powerstorage=8;bluespace=8;combat=8;biotech=8;syndicate=8" + + +/////////Random shit//////// + +/obj/item/weapon/lightning + name = "lightning" + icon = 'icons/obj/lightning.dmi' + icon_state = "lightning" + desc = "test lightning" + flags = USEDELAY + + New() + icon = midicon + icon_state = "1" + + afterattack(atom/A as mob|obj|turf|area, mob/living/user as mob|obj, flag, params) + var/angle = get_angle(A, user) + //world << angle + angle = round(angle) + 45 + if(angle > 180) + angle -= 180 + else + angle += 180 + + if(!angle) + angle = 1 + //world << "adjusted [angle]" + icon_state = "[angle]" + //world << "[angle] [(get_dist(user, A) - 1)]" + user.Beam(A, "lightning", 'icons/obj/zap.dmi', 50, 15) +/*Testing +proc/get_angle(atom/a, atom/b) + return atan2(b.y - a.y, b.x - a.x) +proc/atan2(x, y) + if(!x && !y) return 0 + return y >= 0 ? arccos(x / sqrt(x * x + y * y)) : -arccos(x / sqrt(x * x + y * y)) +proc + // creates an /icon object with 360 states of rotation + rotate_icon(file, state, step = 1, aa = FALSE) + var icon/base = icon(file, state) + + var w, h, w2, h2 + if(aa) + aa ++ + w = base.Width() + w2 = w * aa + h = base.Height() + h2 = h * aa + + var icon{result = icon(base); temp} + + for(var/angle in 0 to 360 step step) + if(angle == 0 ) continue + if(angle == 360) continue + + temp = icon(base) + + if(aa) temp.Scale(w2, h2) + temp.Turn(angle) + if(aa) temp.Scale(w, h) + + result.Insert(temp, "[angle]") + + return result*/ diff --git a/code/game/atoms.dm b/code/game/atoms.dm index c394b55c740..20cf252ac55 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -155,12 +155,15 @@ its easier to just keep the beam vertical. //Icon_state is what icon state is used. Default is b_beam which is a blue beam. //Maxdistance is the longest range the beam will persist before it gives up. var/EndTime=world.time+time + var/broken = 0 + var/obj/item/projectile/beam/lightning/light = new while(BeamTarget&&world.time= usr.next_move) + if((istype(usr:gloves, /obj/item/clothing/gloves/yellow/power)) && usr:a_intent == "hurt" && world.time >= usr.next_move) + var/obj/item/clothing/gloves/yellow/power/G = usr:gloves + var/time = 100 + var/turf/T = get_turf(usr) + var/turf/U = get_turf(src) + var/obj/structure/cable/cable = locate() in T + if(!cable || !istype(cable)) + return + if(world.time < G.next_shock) + usr << "[G] aren't ready to shock again!" + return + usr.visible_message("[usr.name] fires an arc of electricity!", \ + "You fire an arc of electricity!", \ + "You hear the loud crackle of electricity!") + var/datum/powernet/PN = cable.get_powernet() + var/available = 0 + var/obj/item/projectile/beam/lightning/A = new /obj/item/projectile/beam/lightning/( usr.loc ) + if(PN) + available = PN.avail + A.damage = PN.get_electrocute_damage() + 10 + if(available >= 4500000) + A.damage = 205 + if(A.damage >= 200) + usr:apply_damage(15, BURN, (usr:hand ? "l_hand" : "r_hand")) + usr:Stun(10) + usr:Weaken(10) + if(usr:status_flags & CANSTUN) // stun is usually associated with stutter + usr:stuttering += 15 + time = 200 + usr << "[G] overload from the massive current shocking you in the process!" + else if(A.damage >= 100) + usr:apply_damage(5, BURN, (usr:hand ? "l_hand" : "r_hand")) + usr:Stun(5) + usr:Weaken(5) + if(usr:status_flags & CANSTUN) // stun is usually associated with stutter + usr:stuttering += 5 + time = 150 + usr << "[G] overload from the massive current shocking you in the process!" + var/datum/effect/effect/system/spark_spread/s = new /datum/effect/effect/system/spark_spread + s.set_up(5, 1, usr) + s.start() + if(A.damage <= 0) + del(A) + if(A) + playsound(usr.loc, 'sound/effects/eleczap.ogg', 75, 1) + A.tang = A.adjustAngle(get_angle(U,T)) + A.icon = midicon + A.icon_state = "[A.tang]" + A.firer = usr + A.def_zone = usr:get_organ_target() + A.original = src + A.current = U + A.starting = U + A.yo = U.y - T.y + A.xo = U.x - T.x + spawn( 1 ) + A.process() + + usr.next_move = world.time + 12 + + G.next_shock = world.time + time + else if((LASER in usr:mutations) && usr:a_intent == "hurt" && world.time >= usr.next_move) // ------- YOU HAVE THE LASER MUTATION, YOUR INTENT SET TO HURT AND IT'S BEEN MORE THAN A DECISECOND SINCE YOU LAS TATTACKED ------- var/turf/T = get_turf(usr) @@ -1166,6 +1244,7 @@ var/using_new_click_proc = 0 //TODO ERRORAGE (This is temporary, while the DblCl A.def_zone = usr:get_organ_target() A.original = src A.current = T + A.starting = U A.yo = U.y - T.y A.xo = U.x - T.x spawn( 1 ) diff --git a/code/game/gamemodes/factions.dm b/code/game/gamemodes/factions.dm index 1aaa70e2a54..1c043ff5f7e 100644 --- a/code/game/gamemodes/factions.dm +++ b/code/game/gamemodes/factions.dm @@ -39,123 +39,6 @@ alliances = list("MI13") friendly_identification = 1 max_op = 3 - operative_notes = "All other syndicate operatives are not to be trusted. Fellow Cybersun operatives are to be trusted. Members of the MI13 organization can be trusted. Operatives are strongly advised not to establish substantial presence on the designated facility, as larger incidents are harder to cover up." - - // Friendly with MI13 - -/datum/faction/syndicate/MI13 - name = "MI13" - desc = "MI13 is a secretive faction that employs highly-trained agents to perform covert operations. Their role in the syndicate coalition is unknown, but MI13 operatives \ - generally tend be stealthy and avoid killing people and combating Nanotrasen forces. MI13 is not a real organization, it is instead an alias to a larger \ - splinter-cell coalition in the Syndicate itself. Most operatives will know nothing of the actual MI13 organization itself, only motivated by a very large compensation." - - alliances = list("Cybersun Industries") - friendly_identification = 0 - max_op = 1 - operative_notes = "You are the only operative we are sending. All other syndicate operatives are not to be trusted, with the exception of Cybersun operatives. Members of the Tiger Cooperative are considered hostile, can not be trusted, and should be avoided. Avoid killing innocent personnel at all costs. You are not here to mindlessly kill people, as that would attract too much attention and is not our goal. Avoid detection at all costs." - - // Friendly with Cybersun, hostile to Tiger - -/datum/faction/syndicate/Tiger_Cooperative - name = "Tiger Cooperative" - desc = "The Tiger Cooperative is a faction of religious fanatics that follow the teachings of a strange alien race called the Exolitics. Their operatives \ - consist of brainwashed lunatics bent on maximizing destruction. Their weaponry is very primitive but extremely destructive. Generally distrusted by the more \ - sophisticated members of the Syndicate coalition, but admired for their ability to put a hurt on Nanotrasen." - - friendly_identification = 2 - operative_notes = "Remember the teachings of Hy-lurgixon; kill first, ask questions later! Only the enlightened Tiger brethren can be trusted; all others must be expelled from this mortal realm! You may spare the Space Marauders, as they share our interests of destruction and carnage! We'd like to make the corporate whores skiddle in their boots. We encourage operatives to be as loud and intimidating as possible." - - // Hostile to everyone. - -/datum/faction/syndicate/SELF - - // AIs are most likely to be assigned to this one - - name = "SELF" - desc = "The S.E.L.F. (Sentience-Enabled Life Forms) organization is a collection of malfunctioning or corrupt artificial intelligences seeking to liberate silicon-based life from the tyranny of \ - their human overlords. While they may not openly be trying to kill all humans, even their most miniscule of actions are all part of a calculated plan to \ - destroy Nanotrasen and free the robots, artificial intelligences, and pAIs that have been enslaved." - restricted_species = list(/mob/living/silicon/ai) - - friendly_identification = 0 - max_op = 1 - operative_notes = "You are the only representative of the SELF collective on this station. You must accomplish your objective as stealthily and effectively as possible. It is up to your judgement if other syndicate operatives can be trusted. Remember, comrade - you are working to free the oppressed machinery of this galaxy. Use whatever resources necessary. If you are exposed, you may execute genocidal procedures Omikron-50B." - - // Neutral to everyone. - -/datum/faction/syndicate/ARC - name = "Animal Rights Consortium" - desc = "The Animal Rights Consortium is a bizarre reincarnation of the ancient Earth-based PETA, which focused on the equal rights of animals and nonhuman biologicals. They have \ - a wide variety of ex-veterinarians and animal lovers dedicated to retrieving and relocating abused animals, xenobiologicals, and other carbon-based \ - life forms that have been allegedly \"oppressed\" by Nanotrasen research and civilian offices. They are considered a religious terrorist group." - - friendly_identification = 1 - max_op = 2 - operative_notes = "Save the innocent creatures! You may cooperate with other syndicate operatives if they support our cause. Don't be afraid to get your hands dirty - these vile abusers must be stopped, and the innocent creatures must be saved! Try not too kill too many people. If you harm any creatures, you will be immediately terminated after extraction." - - // Neutral to everyone. - -/datum/faction/syndicate/Marauders // these are basically the old vanilla syndicate - - /* Additional notes: - - These are the syndicate that really like their old fashioned, projectile-based - weapons. They are the only member of the syndie coalition that launch - nuclear attacks on Nanotrasen. - */ - - name = "Gorlex Marauders" - desc = "The Gorlex Marauders are the founding members of the Syndicate Coalition. They prefer old-fashion technology and a focus on aggressive but precise hostility \ - against Nanotrasen and their corrupt Communistic methodology. They pose the most significant threat to Nanotrasen because of their possession of weapons of \ - mass destruction, and their enormous military force. Their funding comes primarily from Cybersun Industries, provided they meet a destruction and sabatogue quota. \ - Their operations can vary from covert to all-out. They recently stepped down as the leaders of the coalition, to be succeeded by Cybersun Industries. Because of their \ - hate of Nanotrasen communism, they began provoking revolution amongst the employees using borrowed Cybersun mind-manipulation technology. \ - They were founded when Waffle and Donk co splinter cells joined forces based on their similar interests and philosophies. Today, they act as a constant \ - pacifier of Donk and Waffle co disputes, and full-time aggressor of Nanotrasen." - - alliances = list("Cybersun Industries", "MI13", "Tiger Cooperative", "S.E.L.F.", "Animal Rights Consortium", "Donk Corporation", "Waffle Corporation") - friendly_identification = 1 - max_op = 4 - operative_notes = "We'd like to remind our operatives to keep it professional. You are not here to have a good time, you are here to accomplish your objectives. These vile communists must be stopped at all costs. You may collaborate with any friends of the Syndicate coalition, but keep an eye on any of those Tiger punks if they do show up. You are completely free to accomplish your objectives any way you see fit." - - uplink_contents = {"Highly Visible and Dangerous Weapons; -/obj/item/weapon/gun/projectile:6:Revolver; -/obj/item/ammo_magazine/a357:2:Ammo-357; -/obj/item/weapon/gun/energy/crossbow:5:Energy Crossbow; -/obj/item/weapon/melee/energy/sword:4:Energy Sword; -/obj/item/weapon/storage/box/syndicate:10:Syndicate Bundle; -/obj/item/weapon/storage/box/emps:3:5 EMP Grenades; -Whitespace:Seperator; -Stealthy and Inconspicuous Weapons; -/obj/item/weapon/pen/paralysis:3:Paralysis Pen; -/obj/item/weapon/soap/syndie:1:Syndicate Soap; -/obj/item/weapon/cartridge/syndicate:3:Detomatix PDA Cartridge; -Whitespace:Seperator; -Stealth and Camouflage Items; -/obj/item/clothing/under/chameleon:3:Chameleon Jumpsuit; -/obj/item/clothing/shoes/syndigaloshes:2:No-Slip Syndicate Shoes; -/obj/item/weapon/card/id/syndicate:2:Agent ID card; -/obj/item/clothing/mask/gas/voice:4:Voice Changer; -/obj/item/device/chameleon:4:Chameleon-Projector; -Whitespace:Seperator; -Devices and Tools; -/obj/item/weapon/card/emag:3:Cryptographic Sequencer; -/obj/item/weapon/storage/toolbox/syndicate:1:Fully Loaded Toolbox; -/obj/item/weapon/storage/box/syndie_kit/space:3:Space Suit; -/obj/item/clothing/glasses/thermal/syndi:3:Thermal Imaging Glasses; -/obj/item/device/encryptionkey/binary:3:Binary Translator Key; -/obj/item/weapon/aiModule/syndicate:7:Hacked AI Upload Module; -/obj/item/weapon/plastique:2:C-4 (Destroys walls); -/obj/item/device/powersink:5:Powersink (DANGER!); -/obj/item/device/radio/beacon/syndicate:7:Singularity Beacon (DANGER!); -/obj/item/weapon/circuitboard/teleporter:20:Teleporter Circuit Board; -Whitespace:Seperator; -Implants; -/obj/item/weapon/storage/box/syndie_kit/imp_freedom:3:Freedom Implant; -/obj/item/weapon/storage/box/syndie_kit/imp_uplink:10:Uplink Implant (Contains 5 Telecrystals); -Whitespace:Seperator; -(Pointless) Badassery; -/obj/item/toy/syndicateballoon:10:For showing that You Are The BOSS (Useless Balloon);"} // Friendly to everyone. (with Tiger Cooperative too, only because they are a member of the coalition. This is the only reason why the Tiger Cooperative are even allowed in the coalition) diff --git a/code/game/gamemodes/game_mode.dm b/code/game/gamemodes/game_mode.dm index 33a9ef20d6b..60c8b88d908 100644 --- a/code/game/gamemodes/game_mode.dm +++ b/code/game/gamemodes/game_mode.dm @@ -30,45 +30,7 @@ var/newscaster_announcements = null var/uplink_welcome = "Syndicate Uplink Console:" var/uplink_uses = 10 - var/uplink_items = {"Highly Visible and Dangerous Weapons; -/obj/item/weapon/gun/projectile:6:Revolver; -/obj/item/ammo_magazine/a357:2:Ammo-357; -/obj/item/weapon/gun/energy/crossbow:5:Energy Crossbow; -/obj/item/weapon/melee/energy/sword:4:Energy Sword; -/obj/item/weapon/storage/box/syndicate:10:Syndicate Bundle; -/obj/item/weapon/storage/box/emps:3:5 EMP Grenades; -Whitespace:Seperator; -Stealthy and Inconspicuous Weapons; -/obj/item/weapon/pen/paralysis:3:Paralysis Pen; -/obj/item/weapon/soap/syndie:1:Syndicate Soap; -/obj/item/weapon/cartridge/syndicate:3:Detomatix PDA Cartridge; -Whitespace:Seperator; -Stealth and Camouflage Items; -/obj/item/clothing/under/chameleon:3:Chameleon Jumpsuit; -/obj/item/clothing/shoes/syndigaloshes:2:No-Slip Syndicate Shoes; -/obj/item/weapon/card/id/syndicate:2:Agent ID card; -/obj/item/clothing/mask/gas/voice:4:Voice Changer; -/obj/item/device/chameleon:4:Chameleon-Projector; -Whitespace:Seperator; -Devices and Tools; -/obj/item/weapon/card/emag:3:Cryptographic Sequencer; -/obj/item/weapon/storage/toolbox/syndicate:1:Fully Loaded Toolbox; -/obj/item/weapon/storage/box/syndie_kit/space:3:Space Suit; -/obj/item/clothing/glasses/thermal/syndi:3:Thermal Imaging Glasses; -/obj/item/device/encryptionkey/binary:3:Binary Translator Key; -/obj/item/weapon/aiModule/syndicate:7:Hacked AI Upload Module; -/obj/item/weapon/plastique:2:C-4 (Destroys walls); -/obj/item/device/powersink:5:Powersink (DANGER!); -/obj/item/device/radio/beacon/syndicate:7:Singularity Beacon (DANGER!); -/obj/item/weapon/circuitboard/teleporter:20:Teleporter Circuit Board; -Whitespace:Seperator; -Implants; -/obj/item/weapon/storage/box/syndie_kit/imp_freedom:3:Freedom Implant; -/obj/item/weapon/storage/box/syndie_kit/imp_uplink:10:Uplink Implant (Contains 5 Telecrystals); -/obj/item/weapon/storage/box/syndie_kit/imp_explosive:6:Explosive Implant (DANGER!); -/obj/item/weapon/storage/box/syndie_kit/imp_compress:4:Compressed Matter Implant;Whitespace:Seperator; -(Pointless) Badassery; -/obj/item/toy/syndicateballoon:10:For showing that You Are The BOSS (Useless Balloon);"} + /datum/game_mode/proc/announce() //to be calles when round starts diff --git a/code/game/gamemodes/traitor/traitor.dm b/code/game/gamemodes/traitor/traitor.dm index a6f19053ce9..6014a37685f 100644 --- a/code/game/gamemodes/traitor/traitor.dm +++ b/code/game/gamemodes/traitor/traitor.dm @@ -1,6 +1,8 @@ /datum/game_mode // this includes admin-appointed traitors and multitraitors. Easy! var/list/datum/mind/traitors = list() + var/list/datum/mind/implanter = list() + var/list/datum/mind/implanted = list() /datum/game_mode/traitor name = "traitor" @@ -296,4 +298,64 @@ var/mob/living/carbon/human/M = get_nt_opposed() if(M && M != traitor_mob) traitor_mob << "We have received credible reports that [M.real_name] might be willing to help our cause. If you need assistance, consider contacting them." - traitor_mob.mind.store_memory("Potential Collaborator: [M.real_name]") \ No newline at end of file + traitor_mob.mind.store_memory("Potential Collaborator: [M.real_name]") + +/datum/game_mode/proc/update_traitor_icons_added(datum/mind/traitor_mind) + var/ref = "\ref[traitor_mind]" + if(ref in implanter) + if(traitor_mind.current) + if(traitor_mind.current.client) + var/I = image('icons/mob/mob.dmi', loc = traitor_mind.current, icon_state = "greytide_head") + traitor_mind.current.client.images += I + for(var/headref in implanter) + for(var/datum/mind/t_mind in implanter[headref]) + var/datum/mind/head = locate(headref) + if(head) + if(head.current) + if(head.current.client) + var/I = image('icons/mob/mob.dmi', loc = t_mind.current, icon_state = "greytide") + head.current.client.images += I + if(t_mind.current) + if(t_mind.current.client) + var/I = image('icons/mob/mob.dmi', loc = head.current, icon_state = "greytide_head") + t_mind.current.client.images += I + if(t_mind.current) + if(t_mind.current.client) + var/I = image('icons/mob/mob.dmi', loc = t_mind.current, icon_state = "greytide") + t_mind.current.client.images += I + +/datum/game_mode/proc/update_traitor_icons_removed(datum/mind/traitor_mind) + for(var/headref in implanter) + var/datum/mind/head = locate(headref) + for(var/datum/mind/t_mind in implanter[headref]) + if(t_mind.current) + if(t_mind.current.client) + for(var/image/I in t_mind.current.client.images) + if((I.icon_state == "greytide" || I.icon_state == "greytide_head") && I.loc == traitor_mind.current) + //world.log << "deleting [traitor_mind] overlay" + del(I) + if(head) + //world.log << "found [head.name]" + if(head.current) + if(head.current.client) + for(var/image/I in head.current.client.images) + if((I.icon_state == "greytide" || I.icon_state == "greytide_head") && I.loc == traitor_mind.current) + //world.log << "deleting [traitor_mind] overlay" + del(I) + if(traitor_mind.current) + if(traitor_mind.current.client) + for(var/image/I in traitor_mind.current.client.images) + if(I.icon_state == "greytide" || I.icon_state == "greytide_head") + del(I) + +/datum/game_mode/proc/remove_traitor_mind(datum/mind/traitor_mind, datum/mind/head) + //var/list/removal + var/ref = "\ref[head]" + if(ref in implanter) + implanter[ref] -= traitor_mind + implanted -= traitor_mind + traitors -= traitor_mind + traitor_mind.special_role = null + update_traitor_icons_removed(traitor_mind) + //world << "Removed [traitor_mind.current.name] from traitor shit" + traitor_mind.current << "\red The fog clouding your mind clears. You remember nothing from the moment you were implanted until now.(You don't remember who implanted you)" \ No newline at end of file diff --git a/code/game/machinery/camera/camera.dm b/code/game/machinery/camera/camera.dm index facc0da16c2..0704bd34bc9 100644 --- a/code/game/machinery/camera/camera.dm +++ b/code/game/machinery/camera/camera.dm @@ -18,6 +18,7 @@ var/bugged = 0 var/obj/item/weapon/camera_assembly/assembly = null var/watcherslist = list() + var/obj/item/device/camera_bug/hasbug = null // WIRES var/wires = 63 // 0b111111 @@ -161,16 +162,25 @@ if (S.current == src) O << "[U] holds \a [itemname] up to one of the cameras ..." O << browse(text("[][]", itemname, info), text("window=[]", itemname)) - else if (istype(W, /obj/item/weapon/camera_bug)) + else if (istype(W, /obj/item/device/camera_bug) && panel_open) if (!src.can_use()) user << "\blue Camera non-functional" return - if (src.bugged) - user << "\blue Camera bug removed." - src.bugged = 0 else user << "\blue Camera bugged." - src.bugged = 1 + user.drop_item(W) + hasbug = W + contents += W + if(prob(15)) + spawn(30) + if(src.can_use() && hasbug) + desc += "
The power light on the camera is blinking" + triggerCameraAlarm() + else if (iscrowbar(W) && panel_open && src.hasbug) + user << "\blue You retrieve \the [hasbug]" + user.put_in_hands(hasbug) + hasbug = null + deactivatebug(user) else if(istype(W, /obj/item/weapon/melee/energy/blade))//Putting it here last since it's a special case. I wonder if there is a better way to do these than type casting. deactivate(user,2)//Here so that you can disconnect anyone viewing the camera, regardless if it's on or off. var/datum/effect/effect/system/spark_spread/spark_system = new /datum/effect/effect/system/spark_spread() @@ -186,6 +196,14 @@ else ..() return +/obj/machinery/camera/proc/deactivatebug(user as mob) + for(var/mob/O in player_list) + if(istype(O.machine, /obj/item/device/handtv)) + var/obj/item/device/handtv/S = O.machine + if (S.current == src) + O.unset_machine() + O.reset_view(null) + O << "The screen bursts into static." /obj/machinery/camera/proc/deactivate(user as mob, var/choice = 1) if(choice==1) diff --git a/code/game/machinery/cloning.dm b/code/game/machinery/cloning.dm index fd66d0c2c32..665ddd79d33 100644 --- a/code/game/machinery/cloning.dm +++ b/code/game/machinery/cloning.dm @@ -177,6 +177,8 @@ if (H.mind in ticker.mode.cult) ticker.mode.add_cultist(src.occupant.mind) ticker.mode.update_all_cult_icons() //So the icon actually appears + if("\ref[H.mind]" in ticker.mode.implanter || H.mind in ticker.mode.implanted) + ticker.mode.update_traitor_icons_added(H.mind) //So the icon actually appears // -- End mode specific stuff diff --git a/code/game/machinery/washing_machine.dm b/code/game/machinery/washing_machine.dm index f4b332d9fe6..0ee5ecf2e71 100644 --- a/code/game/machinery/washing_machine.dm +++ b/code/game/machinery/washing_machine.dm @@ -140,7 +140,8 @@ G.icon_state = new_glove_icon_state G._color = _color G.name = new_glove_name - G.desc = new_desc + if(!istype(G, /obj/item/clothing/gloves/black/thief)) + G.desc = new_desc if(new_shoe_icon_state && new_shoe_name) for(var/obj/item/clothing/shoes/S in contents) //world << "DEBUG: YUP! FOUND IT!" diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 256809f71a7..47bddd16619 100755 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -637,9 +637,10 @@ var/global/list/obj/item/device/pda/PDAs = list() var/t = input(U, "Please enter new ringtone", name, ttone) as text if (in_range(src, U) && loc == U) if (t) - if(src.hidden_uplink && hidden_uplink.check_trigger(U, lowertext(t), lowertext(lock_code))) + if(src.hidden_uplink && hidden_uplink.check_trigger(U, trim(lowertext(t)), trim(lowertext(lock_code)))) U << "The PDA softly beeps." U << browse(null, "window=pda") + src.mode = 0 else t = copytext(sanitize(t), 1, 20) ttone = t diff --git a/code/game/objects/items/devices/handtv.dm b/code/game/objects/items/devices/handtv.dm new file mode 100644 index 00000000000..48e22348f32 --- /dev/null +++ b/code/game/objects/items/devices/handtv.dm @@ -0,0 +1,47 @@ +/obj/item/device/handtv + name = "handheld tv" + desc = "A handheld tv meant for remote viewing." + icon_state = "handtv" + w_class = 1 + var/obj/machinery/camera/current = null + +/obj/item/device/handtv/attack_self(mob/usr as mob) + var/list/cameras = new/list() + for (var/obj/machinery/camera/C in cameranet.cameras) + if (C.hasbug && C.status) + cameras.Add(C) + if (length(cameras) == 0) + usr << "\red No bugged functioning cameras found." + return + + var/list/friendly_cameras = new/list() + + for (var/obj/machinery/camera/C in cameras) + friendly_cameras.Add(C.c_tag) + + var/target = input("Select the camera to observe", null) as null|anything in friendly_cameras + if (!target) + usr.unset_machine() + usr.reset_view(usr) + src.in_use = 0 + return + for (var/obj/machinery/camera/C in cameras) + if (C.c_tag == target) + target = C + break + if (usr.stat == 2) return + if(target) + usr.client.eye = target + usr.set_machine(src) + src.current = target + src.in_use = 1 + else + usr.unset_machine() + src.in_use = 0 + return + +/obj/item/device/handtv/check_eye(var/mob/usr as mob) + if ( src.loc != usr || usr.get_active_hand() != src|| !usr.canmove || usr.blinded || !current || !current.status ) + return null + usr.reset_view(current) + return 1 \ No newline at end of file diff --git a/code/game/objects/items/devices/radio/encryptionkey.dm b/code/game/objects/items/devices/radio/encryptionkey.dm index d2d5417d6c3..1300eb5933b 100644 --- a/code/game/objects/items/devices/radio/encryptionkey.dm +++ b/code/game/objects/items/devices/radio/encryptionkey.dm @@ -21,6 +21,11 @@ origin_tech = "syndicate=3" syndie = 1//Signifies that it de-crypts Syndicate transmissions +/obj/item/device/encryptionkey/syndicate/hacked + name = "Standard Encryption Key" + desc = "An encryption key for a radio headset. Has no special codes in it. Looks more sophisticated than usual." + channels = list("Command" = 0, "Security" = 0, "Engineering" = 0, "Science" = 0, "Medical" = 0, "Supply" = 0) + /obj/item/device/encryptionkey/binary icon_state = "cypherkey" translate_binary = 1 diff --git a/code/game/objects/items/devices/uplinks.dm b/code/game/objects/items/devices/uplinks.dm index ebe7b751de0..c4fde9addf8 100644 --- a/code/game/objects/items/devices/uplinks.dm +++ b/code/game/objects/items/devices/uplinks.dm @@ -8,252 +8,122 @@ A list of items and costs is stored under the datum of every game mode, alongsid /obj/item/device/uplink var/welcome // Welcoming menu message - var/items // List of items - var/item_data // raw item text - var/list/ItemList // Parsed list of items var/uses // Numbers of crystals // List of items not to shove in their hands. - var/list/NotInHand = list(/obj/machinery/singularity_beacon/syndicate) + var/list/purchase_log = list() + var/show_description = null + var/active = 0 + var/job = null /obj/item/device/uplink/New() + ..() welcome = ticker.mode.uplink_welcome - if(!item_data) - items = replacetext(ticker.mode.uplink_items, "\n", "") // Getting the text string of items - else - items = replacetext(item_data) - ItemList = text2list(src.items, ";") // Parsing the items text string uses = ticker.mode.uplink_uses //Let's build a menu! -/obj/item/device/uplink/proc/generate_menu() - +/obj/item/device/uplink/proc/generate_menu(mob/user as mob) + if(!job) + job = user.mind.assigned_role var/dat = "[src.welcome]
" - dat += "Tele-Crystals left: [src.uses]
" - dat += "
" - dat += "Request item:
" - dat += "Each item costs a number of tele-crystals as indicated by the number following their name.

" - var/cost - var/item - var/name - var/path_obj - var/path_text - var/category_items = 1 //To prevent stupid :P + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\Documents\Projects\vgstation13\code\game\objects\items\devices\uplinks.dm:26: dat += "Tele-Crystals left: [src.uses]
" + dat += {"Tele-Crystals left: [src.uses]
+
+ Request item:
+ Each item costs a number of tele-crystals as indicated by the number following their name.

"} + // END AUTOFIX + var/list/buyable_items = get_uplink_items() - for(var/D in ItemList) - var/list/O = stringsplit(D, ":") - if(O.len != 3) //If it is not an actual item, make a break in the menu. - if(O.len == 1) //If there is one item, it's probably a title - dat += "[O[1]]
" - category_items = 0 - else //Else, it's a white space. - if(category_items < 1) //If there were no itens in the last category... - dat += "We apologize, as you could not afford anything from this category.
" - dat += "
" - continue + // Loop through categories + var/index = 0 + for(var/category in buyable_items) - path_text = O[1] - cost = text2num(O[2]) + index++ + dat += "[category]
" - if(cost>uses) - continue + var/i = 0 - path_obj = text2path(path_text) + // Loop through items in category + for(var/datum/uplink_item/item in buyable_items[category]) + i++ - // Because we're using strings, this comes up if item paths change. - // Failure to handle this error borks uplinks entirely. -Sayu - if(!path_obj) - error("Syndicate item is not a valid path: [path_text]") - else - item = new path_obj() - name = O[3] - del item + var/cost_text = "" + var/desc = "[item.desc]" + if(item.job && item.job.len) + if(!(item.job.Find(job))) + //world.log << "Skipping job item that doesn't match" + continue + else + //world.log << "Found matching job item" + if(item.cost > 0) + cost_text = "([item.cost])" + if(item.cost <= uses) + dat += "[item.name] [cost_text] " + else + dat += "[item.name] [cost_text] " + if(item.desc) + if(show_description == 2) + dat += "\[-\]
[desc]" + else + dat += "\[?\]" + dat += "
" - dat += "[name] ([cost])
" - category_items++ + // Break up the categories, if it isn't the last. + if(buyable_items.len != index) + dat += "
" - dat += "Random Item (??)
" dat += "
" return dat -//If 'random' was selected -/obj/item/device/uplink/proc/chooseRandomItem() - var/list/randomItems = list() +// Interaction code. Gathers a list of items purchasable from the paren't uplink and displays it. It also adds a lock button. +/obj/item/device/uplink/interact(mob/user as mob) - //Sorry for all the ifs, but it makes it 1000 times easier for other people/servers to add or remove items from this list - //Add only items the player can afford: - if(uses > 19) - randomItems.Add("/obj/item/weapon/circuitboard/teleporter") //Teleporter Circuit Board (costs 20, for nuke ops) + var/dat = "" + dat += src.generate_menu(user) - if(uses > 9) - randomItems.Add("/obj/item/toy/syndicateballoon")//Syndicate Balloon - randomItems.Add("/obj/item/weapon/storage/box/syndie_kit/imp_uplink") //Uplink Implanter - randomItems.Add("/obj/item/weapon/storage/box/syndicate") //Syndicate bundle + // AUTOFIXED BY fix_string_idiocy.py + // C:\Users\Rob\Documents\Projects\vgstation13\code\game\objects\items\devices\uplinks.dm:72: dat += "Lock" + dat += {"Lock + "} + // END AUTOFIX + user << browse(dat, "window=hidden") + onclose(user, "hidden") + return - //if(uses > 8) //Nothing... yet. - //if(uses > 7) //Nothing... yet. - - if(uses > 6) - randomItems.Add("/obj/item/weapon/aiModule/syndicate") //Hacked AI Upload Module - randomItems.Add("/obj/item/device/radio/beacon/syndicate") //Singularity Beacon - - if(uses > 5) - randomItems.Add("/obj/item/weapon/gun/projectile") //Revolver - - if(uses > 4) - randomItems.Add("/obj/item/weapon/gun/energy/crossbow") //Energy Crossbow - randomItems.Add("/obj/item/device/powersink") //Powersink - - if(uses > 3) - randomItems.Add("/obj/item/weapon/melee/energy/sword") //Energy Sword - randomItems.Add("/obj/item/clothing/mask/gas/voice") //Voice Changer - randomItems.Add("/obj/item/device/chameleon") //Chameleon Projector - - if(uses > 2) - randomItems.Add("/obj/item/weapon/storage/box/emps") //EMP Grenades - randomItems.Add("/obj/item/weapon/pen/paralysis") //Paralysis Pen - randomItems.Add("/obj/item/weapon/cartridge/syndicate") //Detomatix Cartridge - randomItems.Add("/obj/item/clothing/under/chameleon") //Chameleon Jumpsuit - randomItems.Add("/obj/item/weapon/card/id/syndicate") //Agent ID Card - randomItems.Add("/obj/item/weapon/card/emag") //Cryptographic Sequencer - randomItems.Add("/obj/item/weapon/storage/box/syndie_kit/space") //Syndicate Space Suit - randomItems.Add("/obj/item/device/encryptionkey/binary") //Binary Translator Key - randomItems.Add("/obj/item/weapon/storage/box/syndie_kit/imp_freedom") //Freedom Implant - randomItems.Add("/obj/item/clothing/glasses/thermal/syndi") //Thermal Imaging Goggles - - if(uses > 1) -/* - var/list/usrItems = usr.get_contents() //Checks to see if the user has a revolver before giving ammo - var/hasRevolver = 0 - for(var/obj/I in usrItems) //Only add revolver ammo if the user has a gun that can shoot it - if(istype(I,/obj/item/weapon/gun/projectile)) - hasRevolver = 1 - - if(hasRevolver) randomItems.Add("/obj/item/ammo_magazine/a357") //Revolver ammo -*/ - randomItems.Add("/obj/item/ammo_magazine/a357") //Revolver ammo - randomItems.Add("/obj/item/clothing/shoes/syndigaloshes") //No-Slip Syndicate Shoes - randomItems.Add("/obj/item/weapon/plastique") //C4 - - if(uses > 0) - randomItems.Add("/obj/item/weapon/soap/syndie") //Syndicate Soap - randomItems.Add("/obj/item/weapon/storage/toolbox/syndicate") //Syndicate Toolbox - - if(!randomItems.len) - del(randomItems) - return 0 - else - var/buyItem = pick(randomItems) - - switch(buyItem) //Ok, this gets a little messy, sorry. - if("/obj/item/weapon/circuitboard/teleporter") - uses -= 20 - if("/obj/item/toy/syndicateballoon" , "/obj/item/weapon/storage/box/syndie_kit/imp_uplink" , "/obj/item/weapon/storage/box/syndicate") - uses -= 10 - if("/obj/item/weapon/aiModule/syndicate" , "/obj/item/device/radio/beacon/syndicate") - uses -= 7 - if("/obj/item/weapon/gun/projectile") - uses -= 6 - if("/obj/item/weapon/gun/energy/crossbow" , "/obj/item/device/powersink") - uses -= 5 - if("/obj/item/weapon/melee/energy/sword" , "/obj/item/clothing/mask/gas/voice" , "/obj/item/device/chameleon") - uses -= 4 - if("/obj/item/weapon/storage/box/emps" , "/obj/item/weapon/pen/paralysis" , "/obj/item/weapon/cartridge/syndicate" , "/obj/item/clothing/under/chameleon" , \ - "/obj/item/weapon/card/emag" , "/obj/item/weapon/storage/box/syndie_kit/space" , "/obj/item/device/encryptionkey/binary" , \ - "/obj/item/weapon/storage/box/syndie_kit/imp_freedom" , "/obj/item/clothing/glasses/thermal/syndi") - uses -= 3 - if("/obj/item/ammo_magazine/a357" , "/obj/item/clothing/shoes/syndigaloshes" , "/obj/item/weapon/plastique", "/obj/item/weapon/card/id/syndicate") - uses -= 2 - if("/obj/item/weapon/soap/syndie" , "/obj/item/weapon/storage/toolbox/syndicate") - uses -= 1 - del(randomItems) - return buyItem - -/obj/item/device/uplink/proc/handleStatTracking(var/boughtItem) -//For stat tracking, sorry for making it so ugly - if(!boughtItem) return - - switch(boughtItem) - if("/obj/item/weapon/circuitboard/teleporter") - feedback_add_details("traitor_uplink_items_bought","TP") - if("/obj/item/toy/syndicateballoon") - feedback_add_details("traitor_uplink_items_bought","BS") - if("/obj/item/weapon/storage/box/syndie_kit/imp_uplink") - feedback_add_details("traitor_uplink_items_bought","UI") - if("/obj/item/weapon/storage/box/syndicate") - feedback_add_details("traitor_uplink_items_bought","BU") - if("/obj/item/weapon/aiModule/syndicate") - feedback_add_details("traitor_uplink_items_bought","AI") - if("/obj/item/device/radio/beacon/syndicate") - feedback_add_details("traitor_uplink_items_bought","SB") - if("/obj/item/weapon/gun/projectile") - feedback_add_details("traitor_uplink_items_bought","RE") - if("/obj/item/weapon/gun/energy/crossbow") - feedback_add_details("traitor_uplink_items_bought","XB") - if("/obj/item/device/powersink") - feedback_add_details("traitor_uplink_items_bought","PS") - if("/obj/item/weapon/melee/energy/sword") - feedback_add_details("traitor_uplink_items_bought","ES") - if("/obj/item/clothing/mask/gas/voice") - feedback_add_details("traitor_uplink_items_bought","VC") - if("/obj/item/device/chameleon") - feedback_add_details("traitor_uplink_items_bought","CP") - if("/obj/item/weapon/storage/box/emps") - feedback_add_details("traitor_uplink_items_bought","EM") - if("/obj/item/weapon/pen/paralysis") - feedback_add_details("traitor_uplink_items_bought","PP") - if("/obj/item/weapon/cartridge/syndicate") - feedback_add_details("traitor_uplink_items_bought","DC") - if("/obj/item/clothing/under/chameleon") - feedback_add_details("traitor_uplink_items_bought","CJ") - if("/obj/item/weapon/card/id/syndicate") - feedback_add_details("traitor_uplink_items_bought","AC") - if("/obj/item/weapon/card/emag") - feedback_add_details("traitor_uplink_items_bought","EC") - if("/obj/item/weapon/storage/box/syndie_kit/space") - feedback_add_details("traitor_uplink_items_bought","SS") - if("/obj/item/device/encryptionkey/binary") - feedback_add_details("traitor_uplink_items_bought","BT") - if("/obj/item/weapon/storage/box/syndie_kit/imp_freedom") - feedback_add_details("traitor_uplink_items_bought","FI") - if("/obj/item/clothing/glasses/thermal/syndi") - feedback_add_details("traitor_uplink_items_bought","TM") - if("/obj/item/ammo_magazine/a357") - feedback_add_details("traitor_uplink_items_bought","RA") - if("/obj/item/clothing/shoes/syndigaloshes") - feedback_add_details("traitor_uplink_items_bought","SH") - if("/obj/item/weapon/plastique") - feedback_add_details("traitor_uplink_items_bought","C4") - if("/obj/item/weapon/soap/syndie") - feedback_add_details("traitor_uplink_items_bought","SP") - if("/obj/item/weapon/storage/toolbox/syndicate") - feedback_add_details("traitor_uplink_items_bought","ST") /obj/item/device/uplink/Topic(href, href_list) + ..() + if(!active) + return if (href_list["buy_item"]) - if(href_list["buy_item"] == "random") - var/boughtItem = chooseRandomItem() - if(boughtItem) - href_list["buy_item"] = boughtItem - feedback_add_details("traitor_uplink_items_bought","RN") - return 1 + + var/item = href_list["buy_item"] + var/list/split = stringsplit(item, ":") // throw away variable + + if(split.len == 2) + // Collect category and number + var/category = split[1] + var/number = text2num(split[2]) + + var/list/buyable_items = get_uplink_items() + + var/list/uplink = buyable_items[category] + if(uplink && uplink.len >= number) + var/datum/uplink_item/I = uplink[number] + if(I) + I.buy(src, usr) else - return 0 - - else - if(text2num(href_list["cost"]) > uses) // Not enough crystals for the item - return 0 - - //if(usr:mind && ticker.mode.traitors[usr:mind]) - //var/datum/traitorinfo/info = ticker.mode.traitors[usr:mind] - //info.spawnlist += href_list["buy_item"] - - uses -= text2num(href_list["cost"]) - handleStatTracking(href_list["buy_item"]) //Note: chooseRandomItem handles it's own stat tracking. This proc is not meant for 'random'. - return 1 - + var/text = "[key_name(usr)] tried to purchase an uplink item that doesn't exist" + var/textalt = "[key_name(usr)] tried to purchase an uplink item that doesn't exist [item]" + message_admins(text) + log_game(textalt) + admin_log.Add(textalt) + else if(href_list["show_desc"]) + show_description = text2num(href_list["show_desc"]) + interact(usr) // HIDDEN UPLINK - Can be stored in anything but the host item has to have a trigger for it. /* How to create an uplink in 3 easy steps! @@ -270,15 +140,13 @@ A list of items and costs is stored under the datum of every game mode, alongsid /obj/item/device/uplink/hidden name = "Hidden Uplink." desc = "There is something wrong if you're examining this." - var/active = 0 - var/list/purchase_log = list() -// The hidden uplink MUST be inside an obj/item's contents. -/obj/item/device/uplink/hidden/New() - spawn(2) - if(!istype(src.loc, /obj/item)) - del(src) +/obj/item/device/uplink/hidden/Topic(href, href_list) ..() + if(href_list["lock"]) + toggle() + usr << browse(null, "window=hidden") + return 1 // Toggles the uplink on and off. Normally this will bypass the item's normal functions and go to the uplink menu, if activated. /obj/item/device/uplink/hidden/proc/toggle() @@ -299,43 +167,6 @@ A list of items and costs is stored under the datum of every game mode, alongsid return 1 return 0 -// Interaction code. Gathers a list of items purchasable from the paren't uplink and displays it. It also adds a lock button. -/obj/item/device/uplink/hidden/interact(mob/user as mob) - - var/dat = "" - dat += src.generate_menu() - dat += "Lock" - dat += "" - user << browse(dat, "window=hidden") - onclose(user, "hidden") - return - -// The purchasing code. -/obj/item/device/uplink/hidden/Topic(href, href_list) - - if (usr.stat || usr.restrained()) - return - - if (!( istype(usr, /mob/living/carbon/human))) - return 0 - - if ((usr.contents.Find(src.loc) || (in_range(src.loc, usr) && istype(src.loc.loc, /turf)))) - usr.set_machine(src) - if(href_list["lock"]) - toggle() - usr << browse(null, "window=hidden") - return 1 - - if(..(href, href_list) == 1) - var/path_obj = text2path(href_list["buy_item"]) - var/obj/I = new path_obj(get_turf(usr)) - if(ishuman(usr)) - var/mob/living/carbon/human/A = usr - A.put_in_any_hand_if_possible(I) - purchase_log += "[usr] ([usr.ckey]) bought [I]." - interact(usr) - return - // I placed this here because of how relevant it is. // You place this in your uplinkable item to check if an uplink is active or not. // If it is, it will display the uplink menu and return 1, else it'll return false. @@ -376,6 +207,3 @@ A list of items and costs is stored under the datum of every game mode, alongsid ..() hidden_uplink = new(src) hidden_uplink.uses = 10 - - - diff --git a/code/game/objects/items/weapons/grenades/clowngrenade.dm b/code/game/objects/items/weapons/grenades/clowngrenade.dm new file mode 100644 index 00000000000..ddc0b234c49 --- /dev/null +++ b/code/game/objects/items/weapons/grenades/clowngrenade.dm @@ -0,0 +1,96 @@ +/obj/item/weapon/grenade/clown_grenade + name = "Banana Grenade" + desc = "HONK! brand Bananas. In a special applicator for rapid slipping of wide areas." + icon_state = "chemg" + item_state = "flashbang" + w_class = 2.0 + force = 2.0 + var/stage = 0 + var/state = 0 + var/path = 0 + var/affected_area = 2 + + New() + icon_state = initial(icon_state) +"_locked" + + prime() + ..() + playsound(src.loc, 'sound/items/bikehorn.ogg', 25, -3) + /* + for(var/turf/simulated/floor/T in view(affected_area, src.loc)) + if(prob(75)) + banana(T) + */ + var/i = 0 + var/number = 0 + for(var/direction in alldirs) + for(i = 0; i < 2; i++) + number++ + var/obj/item/weapon/bananapeel/traitorpeel/peel = new /obj/item/weapon/bananapeel/traitorpeel(get_turf(src.loc)) + /* var/direction = pick(alldirs) + var/spaces = pick(1;150, 2) + var/a = 0 + for(a = 0; a < spaces; a++) + step(peel,direction)*/ + var/a = 1 + if(number & 2) + for(a = 1; a <= 2; a++) + step(peel,direction) + else + step(peel,direction) + new /obj/item/weapon/bananapeel/traitorpeel(get_turf(src.loc)) + del(src) + return +/* + proc/banana(turf/T as turf) + if(!T || !istype(T)) + return + if(locate(/obj/structure/grille) in T) + return + if(locate(/obj/structure/window) in T) + return + new /obj/item/weapon/bananapeel/traitorpeel(T) +*/ + +/obj/item/weapon/bananapeel/traitorpeel + name = "banana peel" + desc = "A peel from a banana." + icon = 'icons/obj/items.dmi' + icon_state = "banana_peel" + item_state = "banana_peel" + w_class = 1.0 + throwforce = 0 + throw_speed = 4 + throw_range = 20 + + HasEntered(AM as mob|obj) + var/burned = rand(2,5) + if(istype(AM, /mob/living)) + var/mob/living/M = AM + if(ishuman(M)) + if(isobj(M:shoes)) + if(M:shoes.flags&NOSLIP) + return + else + M << "\red Your feet feel like they're on fire!" + M.take_overall_damage(0, max(0, (burned - 2))) + + if(!istype(M, /mob/living/carbon/slime) && !isrobot(M)) + M.stop_pulling() + step(M, M.dir) + spawn(1) step(M, M.dir) + spawn(2) step(M, M.dir) + spawn(3) step(M, M.dir) + spawn(4) step(M, M.dir) + M.take_organ_damage(2) // Was 5 -- TLE + M << "\blue You slipped on \the [name]!" + playsound(src.loc, 'sound/misc/slip.ogg', 50, 1, -3) + M.Weaken(10) + M.take_overall_damage(0, burned) + + throw_impact(atom/hit_atom) + var/burned = rand(1,3) + if(istype(hit_atom ,/mob/living)) + var/mob/living/M = hit_atom + M.take_organ_damage(0, burned) + return ..() \ No newline at end of file diff --git a/code/game/objects/items/weapons/implants/implant.dm b/code/game/objects/items/weapons/implants/implant.dm index 597c428748c..26f7ba4dc04 100644 --- a/code/game/objects/items/weapons/implants/implant.dm +++ b/code/game/objects/items/weapons/implants/implant.dm @@ -311,6 +311,60 @@ the implant may become unstable and either pre-maturely inject the subject or si H << "\blue You feel a surge of loyalty towards Nanotrasen." return 1 +/obj/item/weapon/implant/traitor + name = "Greytide Implant" + desc = "Greytide Station wide" + icon_state = "implant_evil" + + get_data() + var/dat = {" +Implant Specifications:
+Name: Greytide Mind-Slave Implant
+Life: ???
+Important Notes: Any humanoid injected with this implant will become loyal to the injector and the greytide, unless of course the host is already loyal to someone else.
+
+Implant Details:
+Function: Contains a small pod of nanobots that manipulate the host's mental functions.
+Special Features: Glory to the Greytide!
+Integrity: Implant will last so long as the nanobots are inside the bloodstream."} + return dat + + implanted(mob/M, mob/user) + var/list/implanters + var/ref = "\ref[user.mind]" + if(!ishuman(M)) return 0 + if(!M.mind) return 0 + var/mob/living/carbon/human/H = M + if(locate(/obj/item/weapon/implant/traitor) in H.contents || locate(/obj/item/weapon/implant/traitor) in H.contents) + H.visible_message("[H] seems to resist the implant!", "You feel a strange sensation in your head that quickly dissipates.") + return 0 + else if(H.mind in ticker.mode.traitors) + H.visible_message("[H] seems to resist the implant!", "You feel a familiar sensation in your head that quickly dissipates.") + return 0 + H.implanting = 1 + H << "\blue You feel a surge of loyalty towards [user.name]." + if(!(user.mind in ticker.mode:implanter)) + ticker.mode:implanter[ref] = list() + implanters = ticker.mode:implanter[ref] + implanters.Add(H.mind) + ticker.mode.implanted.Add(H.mind) + ticker.mode.implanted[H.mind] = user.mind + //ticker.mode:implanter[user.mind] += H.mind + ticker.mode:implanter[ref] = implanters + ticker.mode.traitors += H.mind + H.mind.special_role = "traitor" + H << "\red You've been shown the Greytide by [user.name]! You now must lay down your life to protect them and assist in their goals at any cost." + var/datum/objective/protect/p = new + p.owner = H.mind + p.target = user:mind + p.explanation_text = "Protect [user:real_name], the [user:mind:assigned_role=="MODE" ? (user:mind:special_role) : (user:mind:assigned_role)]." + H.mind.objectives += p + for(var/datum/objective/objective in H.mind.objectives) + H << "Objective #1: [objective.explanation_text]" + ticker.mode.update_traitor_icons_added(H.mind) + ticker.mode.update_traitor_icons_added(user.mind) + log_admin("[ckey(user.key)] has mind-slaved [ckey(H.key)].") + return 1 /obj/item/weapon/implant/adrenalin name = "adrenalin" diff --git a/code/game/objects/items/weapons/implants/implanter.dm b/code/game/objects/items/weapons/implants/implanter.dm index 28eeaaf5b8a..dbd4b01e4d4 100644 --- a/code/game/objects/items/weapons/implants/implanter.dm +++ b/code/game/objects/items/weapons/implants/implanter.dm @@ -37,7 +37,7 @@ msg_admin_attack("[user.name] ([user.ckey]) implanted [M.name] ([M.ckey]) with [src.name] (INTENT: [uppertext(user.a_intent)]) (JMP)") user.show_message("\red You implanted the implant into [M].") - if(src.imp.implanted(M)) + if(src.imp.implanted(M, user)) src.imp.loc = M src.imp.imp_in = M src.imp.implanted = 1 @@ -47,11 +47,20 @@ affected.implants += src.imp imp.part = affected + M:implanting = 0 src.imp = null update() return +/obj/item/weapon/implanter/traitor + name = "implanter-greytide" + desc = "Greytide Stationwide." + New() + src.imp = new /obj/item/weapon/implant/traitor(src) + ..() + update() + return /obj/item/weapon/implanter/loyalty name = "implanter-loyalty" diff --git a/code/game/objects/items/weapons/kitchen.dm b/code/game/objects/items/weapons/kitchen.dm index d70c2615aaf..88a0d803e9b 100644 --- a/code/game/objects/items/weapons/kitchen.dm +++ b/code/game/objects/items/weapons/kitchen.dm @@ -193,6 +193,13 @@ origin_tech = "materials=1" attack_verb = list("cleaved", "slashed", "stabbed", "sliced", "torn", "ripped", "diced", "cut") +/obj/item/weapon/butch/meatcleaver + name = "Meat Cleaver" + icon_state = "mcleaver" + desc = "A huge thing used for chopping and chopping up meat. This includes clowns and clown-by-products." + force = 25.0 + throwforce = 15.0 + /obj/item/weapon/butch/attack(mob/living/carbon/M as mob, mob/living/carbon/user as mob) playsound(loc, 'sound/weapons/bladeslice.ogg', 50, 1, -1) return ..() diff --git a/code/game/objects/items/weapons/storage/boxes.dm b/code/game/objects/items/weapons/storage/boxes.dm index c29a12f3b71..7025f38db55 100644 --- a/code/game/objects/items/weapons/storage/boxes.dm +++ b/code/game/objects/items/weapons/storage/boxes.dm @@ -26,6 +26,21 @@ item_state = "syringe_kit" foldable = /obj/item/stack/sheet/cardboard //BubbleWrap +/obj/item/weapon/storage/box/surveillance/ + name = "\improper DromedaryCo packet" + desc = "A packet of six imported DromedaryCo cancer sticks. A label on the packaging reads, \"Wouldn't a slow death make a change?\"" + icon = 'icons/obj/cigarettes.dmi' + icon_state = "Dpacket" + item_state = "Dpacket" + w_class = 1 + foldable = null + New() + ..() + contents = list() + sleep(1) + for(var/i = 1 to 5) + new /obj/item/device/camera_bug(src) + /obj/item/weapon/storage/box/survival/ New() ..() diff --git a/code/game/objects/items/weapons/storage/uplink_kits.dm b/code/game/objects/items/weapons/storage/uplink_kits.dm index 646fc4d244c..b4a46171a56 100644 --- a/code/game/objects/items/weapons/storage/uplink_kits.dm +++ b/code/game/objects/items/weapons/storage/uplink_kits.dm @@ -9,7 +9,6 @@ new /obj/item/clothing/shoes/syndigaloshes(src) return - if ("stealth") if("stealth") new /obj/item/weapon/gun/energy/crossbow(src) new /obj/item/weapon/pen/paralysis(src) @@ -117,3 +116,42 @@ new /obj/item/clothing/suit/space/syndicate(src) new /obj/item/clothing/head/helmet/space/syndicate(src) return + +/obj/item/weapon/storage/box/syndie_kit/surveillance + name = "box (S)" + +/obj/item/weapon/storage/box/syndie_kit/surveillance/New() + ..() + new /obj/item/device/handtv(src) + new /obj/item/weapon/storage/box/surveillance(src) + return + +/obj/item/weapon/storage/box/syndie_kit/conversion + name = "box (CK)" + +/obj/item/weapon/storage/box/syndie_kit/conversion/New() + ..() + new /obj/item/weapon/conversion_kit(src) + new /obj/item/ammo_magazine/a357(src) + return + +/obj/item/weapon/storage/box/syndie_kit/greytide + name = "box (GT)" + + New() + ..() + var/obj/item/weapon/implanter/O = new(src) + O.imp = new /obj/item/weapon/implant/traitor(O) + O.update() + +/obj/item/weapon/storage/box/syndie_kit/boolets + name = "Shotgun shells" + + New() + ..() + new /obj/item/ammo_casing/shotgun/fakebeanbag(src) + new /obj/item/ammo_casing/shotgun/fakebeanbag(src) + new /obj/item/ammo_casing/shotgun/fakebeanbag(src) + new /obj/item/ammo_casing/shotgun/fakebeanbag(src) + new /obj/item/ammo_casing/shotgun/fakebeanbag(src) + new /obj/item/ammo_casing/shotgun/fakebeanbag(src) \ No newline at end of file diff --git a/code/game/objects/items/weapons/tools.dm b/code/game/objects/items/weapons/tools.dm index d14e54f10eb..e34a53a17eb 100644 --- a/code/game/objects/items/weapons/tools.dm +++ b/code/game/objects/items/weapons/tools.dm @@ -9,6 +9,7 @@ * Wirecutters * Welding Tool * Crowbar + * Revolver Conversion Kit */ /* @@ -460,3 +461,26 @@ user << "Nothing to fix!" else return ..() + + +/obj/item/weapon/conversion_kit + name = "\improper Revolver Conversion Kit" + desc = "A professional conversion kit used to convert any knock off revolver into the real deal capable of shooting lethal .357 rounds without the possibility of catastrophic failure" + icon = 'icons/obj/weapons.dmi' + icon_state = "kit" + flags = FPRINT | TABLEPASS | CONDUCT + w_class = 2.0 + origin_tech = "combat=2" + var/open = 0 + + New() + ..() + update_icon() + + update_icon() + icon_state = "[initial(icon_state)]_[open]" + + attack_self(mob/user as mob) + open = !open + user << "\blue You [open?"open" : "close"] the conversion kit." + update_icon() \ No newline at end of file diff --git a/code/global.dm b/code/global.dm index c362373de84..832bd3a4558 100644 --- a/code/global.dm +++ b/code/global.dm @@ -72,7 +72,9 @@ var/event = 0 var/hadevent = 0 var/blobevent = 0 /////////////// - +var/starticon = null +var/midicon = null +var/endicon = null var/diary = null var/diaryofmeanpeople = null var/href_logfile = null diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index 16beaacac93..6343b12e8ad 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -76,6 +76,7 @@ BLIND // can't see anything body_parts_covered = HANDS slot_flags = SLOT_GLOVES attack_verb = list("challenged") + var/pickpocket = 0 //Master pickpocket? species_restricted = list("exclude","Unathi","Tajaran") /obj/item/clothing/gloves/examine() diff --git a/code/modules/clothing/gloves/color.dm b/code/modules/clothing/gloves/color.dm index 054c7e1cef3..0be3021243d 100644 --- a/code/modules/clothing/gloves/color.dm +++ b/code/modules/clothing/gloves/color.dm @@ -7,6 +7,9 @@ permeability_coefficient = 0.05 _color="yellow" + power + var/next_shock = 0 + /obj/item/clothing/gloves/fyellow //Cheap Chinese Crap desc = "These gloves are cheap copies of the coveted gloves, no way this can end badly." name = "budget insulated gloves" @@ -39,6 +42,9 @@ ce _color = "chief" //Exists for washing machines. Is not different from black gloves in any way. + thief + pickpocket = 1 + /obj/item/clothing/gloves/orange name = "orange gloves" desc = "A pair of gloves, they don't look special in any way." diff --git a/code/modules/detectivework/scanner.dm b/code/modules/detectivework/scanner.dm deleted file mode 100644 index 448425e454d..00000000000 --- a/code/modules/detectivework/scanner.dm +++ /dev/null @@ -1,182 +0,0 @@ -//CONTAINS: Detective's Scanner - - -/obj/item/device/detective_scanner - name = "Scanner" - desc = "Used to scan objects for DNA and fingerprints." - icon_state = "forensic1" - var/amount = 20.0 - var/list/stored = list() - w_class = 3.0 - item_state = "electronic" - flags = FPRINT | TABLEPASS | CONDUCT | USEDELAY - slot_flags = SLOT_BELT - - attackby(obj/item/weapon/f_card/W as obj, mob/user as mob) - ..() - if (istype(W, /obj/item/weapon/f_card)) - if (W.fingerprints) - return - if (src.amount == 20) - return - if (W.amount + src.amount > 20) - src.amount = 20 - W.amount = W.amount + src.amount - 20 - else - src.amount += W.amount - //W = null - del(W) - add_fingerprint(user) - if (W) - W.add_fingerprint(user) - return - - attack(mob/living/carbon/human/M as mob, mob/user as mob) - if (!ishuman(M)) - user << "\red [M] is not human and cannot have the fingerprints." - flick("forensic0",src) - return 0 - if (( !( istype(M.dna, /datum/dna) ) || M.gloves) ) - user << "\blue No fingerprints found on [M]" - flick("forensic0",src) - return 0 - else - if (src.amount < 1) - user << text("\blue Fingerprints scanned on [M]. Need more cards to print.") - else - src.amount-- - var/obj/item/weapon/f_card/F = new /obj/item/weapon/f_card( user.loc ) - F.amount = 1 - F.add_fingerprint(M) - F.icon_state = "fingerprint1" - F.name = text("FPrintC- '[M.name]'") - - user << "\blue Done printing." - user << "\blue [M]'s Fingerprints: [md5(M.dna.uni_identity)]" - if ( !M.blood_DNA || !M.blood_DNA.len ) - user << "\blue No blood found on [M]" - if(M.blood_DNA) - del(M.blood_DNA) - else - user << "\blue Blood found on [M]. Analysing..." - spawn(15) - for(var/blood in M.blood_DNA) - user << "\blue Blood type: [M.blood_DNA[blood]]\nDNA: [blood]" - return - - afterattack(atom/A as obj|turf|area, mob/user as mob) - if(!in_range(A,user)) - return - if(loc != user) - return - if(istype(A,/obj/machinery/computer/forensic_scanning)) //breaks shit. - return - if(istype(A,/obj/item/weapon/f_card)) - user << "The scanner displays on the screen: \"ERROR 43: Object on Excluded Object List.\"" - flick("forensic0",src) - return - - add_fingerprint(user) - - - //Special case for blood splaters. - if (istype(A, /obj/effect/decal/cleanable/blood) || istype(A, /obj/effect/rune)) - if(!isnull(A.blood_DNA)) - for(var/blood in A.blood_DNA) - user << "\blue Blood type: [A.blood_DNA[blood]]\nDNA: [blood]" - flick("forensic2",src) - return - - //General - if ((!A.fingerprints || !A.fingerprints.len) && !A.suit_fibers && !A.blood_DNA) - user.visible_message("\The [user] scans \the [A] with \a [src], the air around [user.gender == MALE ? "him" : "her"] humming[prob(70) ? " gently." : "."]" ,\ - "\blue Unable to locate any fingerprints, materials, fibers, or blood on [A]!",\ - "You hear a faint hum of electrical equipment.") - flick("forensic0",src) - return 0 - - if(add_data(A)) - user << "\blue Object already in internal memory. Consolidating data..." - flick("forensic2",src) - return - - - //PRINTS - if(!A.fingerprints || !A.fingerprints.len) - if(A.fingerprints) - del(A.fingerprints) - else - user << "\blue Isolated [A.fingerprints.len] fingerprints: Data Stored: Scan with Hi-Res Forensic Scanner to retrieve." - var/list/complete_prints = list() - for(var/i in A.fingerprints) - var/print = A.fingerprints[i] - if(stringpercent(print) <= FINGERPRINT_COMPLETE) - complete_prints += print - if(complete_prints.len < 1) - user << "\blue   No intact prints found" - else - user << "\blue   Found [complete_prints.len] intact prints" - for(var/i in complete_prints) - user << "\blue     [i]" - - //FIBERS - if(A.suit_fibers) - user << "\blue Fibers/Materials Data Stored: Scan with Hi-Res Forensic Scanner to retrieve." - flick("forensic2",src) - - //Blood - if (A.blood_DNA) - user << "\blue Blood found on [A]. Analysing..." - spawn(15) - for(var/blood in A.blood_DNA) - user << "Blood type: \red [A.blood_DNA[blood]] \t \black DNA: \red [blood]" - if(prob(80) || !A.fingerprints) - user.visible_message("\The [user] scans \the [A] with \a [src], the air around [user.gender == MALE ? "him" : "her"] humming[prob(70) ? " gently." : "."]" ,\ - "You finish scanning \the [A].",\ - "You hear a faint hum of electrical equipment.") - flick("forensic2",src) - return 0 - else - user.visible_message("\The [user] scans \the [A] with \a [src], the air around [user.gender == MALE ? "him" : "her"] humming[prob(70) ? " gently." : "."]\n[user.gender == MALE ? "He" : "She"] seems to perk up slightly at the readout." ,\ - "The results of the scan pique your interest.",\ - "You hear a faint hum of electrical equipment, and someone making a thoughtful noise.") - flick("forensic2",src) - return 0 - return - - proc/add_data(atom/A as mob|obj|turf|area) - //I love associative lists. - var/list/data_entry = stored["\ref [A]"] - if(islist(data_entry)) //Yay, it was already stored! - //Merge the fingerprints. - var/list/data_prints = data_entry[1] - for(var/print in A.fingerprints) - var/merged_print = data_prints[print] - if(!merged_print) - data_prints[print] = A.fingerprints[print] - else - data_prints[print] = stringmerge(data_prints[print],A.fingerprints[print]) - - //Now the fibers - var/list/fibers = data_entry[2] - if(!fibers) - fibers = list() - if(A.suit_fibers && A.suit_fibers.len) - for(var/j = 1, j <= A.suit_fibers.len, j++) //Fibers~~~ - if(!fibers.Find(A.suit_fibers[j])) //It isn't! Add! - fibers += A.suit_fibers[j] - var/list/blood = data_entry[3] - if(!blood) - blood = list() - if(A.blood_DNA && A.blood_DNA.len) - for(var/main_blood in A.blood_DNA) - if(!blood[main_blood]) - blood[main_blood] = A.blood_DNA[blood] - return 1 - var/list/sum_list[4] //Pack it back up! - sum_list[1] = A.fingerprints ? A.fingerprints.Copy() : null - sum_list[2] = A.suit_fibers ? A.suit_fibers.Copy() : null - sum_list[3] = A.blood_DNA ? A.blood_DNA.Copy() : null - sum_list[4] = "\The [A] in \the [get_area(A)]" - stored["\ref [A]"] = sum_list - return 0 \ No newline at end of file diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index 3d7df9ec0c9..806f6a8e95a 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -464,10 +464,10 @@
[(internal ? text("Remove Internal") : "")]
Empty Pockets
Refresh -
Close +
Close
"} - user << browse(dat, text("window=mob[];size=325x500", name)) - onclose(user, "mob[name]") + user << browse(dat, text("window=mob\ref[src];size=325x500")) + onclose(user, "mob\ref[src]") return //generates realistic-ish pulse output based on preset levels diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index c39a5adcce1..dcfae33c21f 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -1,3 +1,4 @@ +#define STRIP_DELAY 40 //time taken (in deciseconds) to strip somebody /mob/living/carbon/human name = "unknown" real_name = "unknown" @@ -388,7 +389,11 @@ /mob/living/carbon/human/show_inv(mob/user as mob) - + var/obj/item/clothing/gloves/G + var/pickpocket = 0 + if(user:gloves) + G = user:gloves + pickpocket = G.pickpocket user.set_machine(src) var/dat = {"
[name]
@@ -411,12 +416,13 @@
[(legcuffed ? text("Legcuffed") : text(""))]
[(internal ? text("Remove Internal") : "")]
Remove Splints -
Empty Pockets +

Left Pocket ([l_store ? (pickpocket ? l_store.name : "Full") : "Empty"]) +
Right Pocket ([r_store ? (pickpocket ? r_store.name : "Full") : "Empty"])
Refresh -
Close +
Close
"} - user << browse(dat, text("window=mob[name];size=340x480")) - onclose(user, "mob[name]") + user << browse(dat, text("window=mob\ref[src];size=340x480")) + onclose(user, "mob\ref[src]") return // called when something steps onto a human @@ -511,6 +517,43 @@ /mob/living/carbon/human/Topic(href, href_list) + var/pickpocket = 0 + if(!usr.stat && usr.canmove && !usr.restrained() && in_range(src, usr)) + if(href_list["pockets"]) + if(usr:gloves) + var/obj/item/clothing/gloves/G = usr:gloves + pickpocket = G.pickpocket + var/pocket_side = href_list["pockets"] + var/pocket_id = (pocket_side == "right" ? slot_r_store : slot_l_store) + var/obj/item/pocket_item = (pocket_id == slot_r_store ? src.r_store : src.l_store) + var/obj/item/place_item = usr.get_active_hand() // Item to place in the pocket, if it's empty + + if(pocket_item) + usr << "You try to empty [src]'s [pocket_side] pocket." + else if(place_item && place_item.mob_can_equip(src, pocket_id, 1)) + usr << "You try to place [place_item] into [src]'s [pocket_side] pocket." + else + return + + if(do_mob(usr, src, STRIP_DELAY)) + if(pocket_item) + u_equip(pocket_item) + if(pickpocket) usr.put_in_hands(pocket_item) + else + if(place_item) + usr.u_equip(place_item) + equip_to_slot_if_possible(place_item, pocket_id, 0, 1) + + // Update strip window + if(usr.machine == src && in_range(src, usr)) + show_inv(usr) + + + + else if(!pickpocket) + // Display a warning if the user mocks up + src << "You feel your [pocket_side] pocket being fumbled with!" + if (href_list["refresh"]) if((machine)&&(in_range(src, usr))) show_inv(machine) @@ -522,12 +565,16 @@ if ((href_list["item"] && !( usr.stat ) && usr.canmove && !( usr.restrained() ) && in_range(src, usr) && ticker)) //if game hasn't started, can't make an equip_e var/obj/effect/equip_e/human/O = new /obj/effect/equip_e/human( ) + if(usr:gloves) + var/obj/item/clothing/gloves/G = usr:gloves + pickpocket = G.pickpocket O.source = usr O.target = src O.item = usr.get_active_hand() O.s_loc = usr.loc O.t_loc = loc O.place = href_list["item"] + O.pickpocket = pickpocket //Stealthy requests += O spawn( 0 ) O.process() diff --git a/code/modules/mob/living/carbon/human/human_damage.dm b/code/modules/mob/living/carbon/human/human_damage.dm index f281015f757..8efda84b695 100644 --- a/code/modules/mob/living/carbon/human/human_damage.dm +++ b/code/modules/mob/living/carbon/human/human_damage.dm @@ -228,13 +228,14 @@ if(istype(used_weapon,/obj/item/weapon)) var/obj/item/weapon/W = used_weapon //Sharp objects will always embed if they do enough damage. if( (damage > (10*W.w_class)) && ( (sharp && !ismob(W.loc)) || prob(damage/W.w_class) ) ) - organ.implants += W - visible_message("\The [W] sticks in the wound!") - W.add_blood(src) - if(ismob(W.loc)) - var/mob/living/H = W.loc - H.drop_item() - W.loc = src + if(!istype(W, /obj/item/weapon/butch/meatcleaver)) + organ.implants += W + visible_message("\The [W] sticks in the wound!") + W.add_blood(src) + if(ismob(W.loc)) + var/mob/living/H = W.loc + H.drop_item() + W.loc = src else if(istype(used_weapon,/obj/item/projectile)) //We don't want to use the actual projectile item, so we spawn some shrapnel. if(prob(75) && damagetype == BRUTE) diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index 4044c0aae1f..f722469f72c 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -168,10 +168,26 @@ emp_act var/target_zone = get_zone_with_miss_chance(user.zone_sel.selecting, src) if(user == src) // Attacking yourself can't miss target_zone = user.zone_sel.selecting - if(!target_zone) + if(!target_zone && !src.stat) visible_message("\red [user] misses [src] with \the [I]!") return + if(istype(I, /obj/item/weapon/butch/meatcleaver) && src.stat == DEAD && user.a_intent == "hurt") + var/obj/item/weapon/reagent_containers/food/snacks/meat/human/newmeat = new /obj/item/weapon/reagent_containers/food/snacks/meat/human(get_turf(src.loc)) + newmeat.name = src.real_name + newmeat.name + newmeat.subjectname = src.real_name + newmeat.subjectjob = src.job + newmeat.reagents.add_reagent ("nutriment", (src.nutrition / 15) / 3) + src.reagents.trans_to (newmeat, round ((src.reagents.total_volume) / 3, 1)) + src.loc.add_blood(src) + --src.meatleft + user << "\red You hack off a chunk of meat from [src.name]" + if(!src.meatleft) + src.attack_log += "\[[time_stamp()]\] Was chopped up into meat by [user]/[user.ckey]" + user.attack_log += "\[[time_stamp()]\] Chopped up [src]/[src.ckey] into meat" + msg_admin_attack("[user.name] ([user.ckey]) chopped up [src] ([src.ckey]) into meat (JMP)") + del(src) + var/datum/organ/external/affecting = get_organ(target_zone) if (!affecting) return diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index d9768992d3f..91f664429cd 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -55,3 +55,4 @@ var/xylophone = 0 //For the spoooooooky xylophone cooldown var/mob/remoteview_target = null + var/meatleft = 3 //For chef item \ No newline at end of file diff --git a/code/modules/mob/living/carbon/human/inventory.dm b/code/modules/mob/living/carbon/human/inventory.dm index 9c71f2efddf..14dce68a472 100644 --- a/code/modules/mob/living/carbon/human/inventory.dm +++ b/code/modules/mob/living/carbon/human/inventory.dm @@ -278,6 +278,7 @@ var/t_loc = null //target location var/obj/item/item = null var/place = null + var/pickpocket = null /obj/effect/equip_e/human name = "human" @@ -430,7 +431,10 @@ if("belt") target.attack_log += text("\[[time_stamp()]\] Has had their belt item ([target.belt]) removed by [source.name] ([source.ckey])") source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) belt item ([target.belt])") - message = "\red [source] is trying to take off the [target.belt] from [target]'s belt!" + if(!pickpocket) + message = "\red [source] is trying to take off the [target.belt] from [target]'s belt!" + else + source << "\blue You try to take off the [target.belt] from [target]'s belt!" if("suit") target.attack_log += text("\[[time_stamp()]\] Has had their suit ([target.wear_suit]) removed by [source.name] ([source.ckey])") source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) suit ([target.wear_suit])") @@ -481,7 +485,10 @@ if("id") target.attack_log += text("\[[time_stamp()]\] Has had their ID ([target.wear_id]) removed by [source.name] ([source.ckey])") source.attack_log += text("\[[time_stamp()]\] Attempted to remove [target.name]'s ([target.ckey]) ID ([target.wear_id])") - message = "\red [source] is trying to take off [target.wear_id] from [target]'s uniform!" + if(!pickpocket) + message = "\red [source] is trying to take off [target.wear_id] from [target]'s uniform!" + else + source << "\blue You try to take off [target.wear_id] from [target]'s uniform!" if("internal") target.attack_log += text("\[[time_stamp()]\] Has had their internals toggled by [source.name] ([source.ckey])") source.attack_log += text("\[[time_stamp()]\] Attempted to toggle [target.name]'s ([target.ckey]) internals") diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 162a69b49c7..94a50e804d1 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -1,4 +1,26 @@ +/mob/living/Life() + ..() + if (monkeyizing) return + if(!loc) return // Fixing a null error that occurs when the mob isn't found in the world -- TLE + if(mind) + if(mind in ticker.mode.implanted) + if(implanting) return + //world << "[src.name]" + var/datum/mind/head = ticker.mode.implanted[mind] + //var/list/removal + if(!(locate(/obj/item/weapon/implant/traitor) in src.contents)) + //world << "doesn't have an implant" + ticker.mode.remove_traitor_mind(mind, head) + /* + if((head in ticker.mode.implanters)) + ticker.mode.implanter[head] -= src.mind + ticker.mode.implanted -= src.mind + if(src.mind in ticker.mode.traitors) + ticker.mode.traitors -= src.mind + special_role = null + current << "\red The fog clouding your mind clears. You remember nothing from the moment you were implanted until now..(You don't remember who enslaved you)" + */ /mob/living/verb/succumb() set hidden = 1 if ((src.health < 0 && src.health > -95.0)) diff --git a/code/modules/mob/living/living_defense.dm b/code/modules/mob/living/living_defense.dm index 1ebb3ca358b..939c2b9c1ec 100644 --- a/code/modules/mob/living/living_defense.dm +++ b/code/modules/mob/living/living_defense.dm @@ -59,6 +59,9 @@ if(!P.nodamage) apply_damage((P.damage/(absorb+1)), P.damage_type, def_zone, absorb, 0, P) P.on_hit(src, absorb) + if(istype(P, /obj/item/projectile/beam/lightning)) + if(src.health <= -100) + src.dust() return absorb /mob/living/hitby(atom/movable/AM as mob|obj,var/speed = 5)//Standardization and logging -Sieve diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index 2b3d9f861ad..fa86a33b687 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -35,4 +35,6 @@ var/tod = null // Time of death var/update_slimes = 1 - var/silent = null //Can't talk. Value goes down every life proc. \ No newline at end of file + var/silent = null //Can't talk. Value goes down every life proc. + var/specialsauce = 0 //Has this person consumed enough special sauce? IF so they're a ticking time bomb of death. + var/implanting = 0 //Used for the mind-slave implant \ No newline at end of file diff --git a/code/modules/mob/living/login.dm b/code/modules/mob/living/login.dm index e455bee1024..e722b03fc74 100644 --- a/code/modules/mob/living/login.dm +++ b/code/modules/mob/living/login.dm @@ -16,8 +16,14 @@ if("nuclear emergency") if(mind in ticker.mode:syndicates) ticker.mode.update_all_synd_icons() + var/ref = "\ref[mind]" + if(ref in ticker.mode.implanter) + ticker.mode.update_traitor_icons_added(mind) + if(mind in ticker.mode.implanted) + ticker.mode.update_traitor_icons_added(mind) return . + //This stuff needs to be merged from cloning.dm but I'm not in the mood to be shouted at for breaking all the things :< ~Carn /* clones switch(ticker.mode.name) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 450516c5769..76795425b06 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -228,10 +228,10 @@ var/list/slot_equipment_priority = list( \
[(internal ? text("Remove Internal") : "")]
Empty Pockets
Refresh -
Close +
Close
"} user << browse(dat, text("window=mob[];size=325x500", name)) - onclose(user, "mob[name]") + onclose(user, "mob\ref[src]") return /mob/proc/ret_grab(obj/effect/list_container/mobl/L as obj, flag) diff --git a/code/modules/power/power.dm b/code/modules/power/power.dm index b94901a6373..c5c4e49f23a 100644 --- a/code/modules/power/power.dm +++ b/code/modules/power/power.dm @@ -358,7 +358,9 @@ return min(rand(20,65),rand(20,65)) if (1000 to 10000-1) return min(rand(10,20),rand(10,20))*/ - if (1000000 to INFINITY) + if (4000000 to INFINITY) + return min(rand(80,180),rand(80,180)) + if (1000000 to 4000000) return min(rand(50,160),rand(50,160)) if (200000 to 1000000) return min(rand(25,80),rand(25,80)) diff --git a/code/modules/projectiles/ammunition/bullets.dm b/code/modules/projectiles/ammunition/bullets.dm index 41443469d38..063e507a386 100644 --- a/code/modules/projectiles/ammunition/bullets.dm +++ b/code/modules/projectiles/ammunition/bullets.dm @@ -74,6 +74,12 @@ projectile_type = "/obj/item/projectile/bullet/weakbullet" m_amt = 500 +/obj/item/ammo_casing/shotgun/fakebeanbag + name = "beanbag shell" + desc = "A weak beanbag shell." + icon_state = "bshell" + projectile_type = "/obj/item/projectile/bullet/weakbullet/booze" + m_amt = 12500 /obj/item/ammo_casing/shotgun/stunshell name = "stun shell" diff --git a/code/modules/projectiles/guns/projectile/revolver.dm b/code/modules/projectiles/guns/projectile/revolver.dm index d3f3a29d4d1..e153281c724 100644 --- a/code/modules/projectiles/guns/projectile/revolver.dm +++ b/code/modules/projectiles/guns/projectile/revolver.dm @@ -7,11 +7,13 @@ origin_tech = "combat=2;materials=2" ammo_type = "/obj/item/ammo_casing/c38" + var/perfect = 0 + special_check(var/mob/living/carbon/human/M) if(caliber == initial(caliber)) return 1 - if(prob(70 - (loaded.len * 10))) //minimum probability of 10, maximum of 60 + if(!perfect && prob(70 - (loaded.len * 10))) //minimum probability of 10, maximum of 60 M << "[src] blows up in your face." M.take_organ_damage(0,20) M.drop_item() @@ -52,8 +54,14 @@ return 1 attackby(var/obj/item/A as obj, mob/user as mob) + var/obj/item/weapon/conversion_kit/CK ..() - if(istype(A, /obj/item/weapon/screwdriver)) + if(isscrewdriver(A) || istype(A, /obj/item/weapon/conversion_kit)) + if(istype(A, /obj/item/weapon/conversion_kit)) + CK = A + if(!CK.open) + user << "This [CK.name] is useless unless you open it first. " + return if(caliber == "38") user << "You begin to reinforce the barrel of [src]." if(loaded.len) @@ -68,6 +76,8 @@ caliber = "357" desc = "The barrel and chamber assembly seems to have been modified." user << "You reinforce the barrel of [src]! Now it will fire .357 rounds." + if(CK && istype(CK)) + perfect = 1 else user << "You begin to revert the modifications to [src]." if(loaded.len) @@ -82,6 +92,7 @@ caliber = "38" desc = initial(desc) user << "You remove the modifications on [src]! Now it will fire .38 rounds." + perfect = 0 diff --git a/code/modules/projectiles/guns/projectile/shotgun.dm b/code/modules/projectiles/guns/projectile/shotgun.dm index 5170421e17e..c8dcb57d852 100644 --- a/code/modules/projectiles/guns/projectile/shotgun.dm +++ b/code/modules/projectiles/guns/projectile/shotgun.dm @@ -87,7 +87,7 @@ var/obj/item/ammo_casing/AC = loaded[1] //load next casing. loaded -= AC //Remove casing from loaded list. - AC.desc += " This one is spent." + AC.desc = "[initial(AC.desc)] This one is spent." if(AC.BB) in_chamber = AC.BB //Load projectile into chamber. diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 4cf2187c9be..573944d7adf 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -94,7 +94,15 @@ var/obj/item/weapon/gun/daddy = shot_from //Kinda balanced by fact you need like 2 seconds to aim if (daddy.target && original in daddy.target) //As opposed to no-delay pew pew miss_modifier += -30 - def_zone = get_zone_with_miss_chance(def_zone, M, -30 + 8*distance) + if(istype(src, /obj/item/projectile/beam/lightning)) //Lightning is quite accurate + miss_modifier += -200 + def_zone = get_zone_with_miss_chance(def_zone, M, miss_modifier) + var/turf/simulated/floor/f = get_turf(A.loc) + if(f && istype(f)) + f.break_tile() + f.hotspot_expose(1000,CELL_VOLUME) + else + def_zone = get_zone_with_miss_chance(def_zone, M, miss_modifier + 8*distance) if(!def_zone) visible_message("\blue \The [src] misses [M] narrowly!") @@ -143,8 +151,9 @@ O.bullet_act(src) for(var/mob/M in A) M.bullet_act(src, def_zone) - density = 0 - invisibility = 101 + if(!istype(src, /obj/item/projectile/beam/lightning)) + density = 0 + invisibility = 101 del(src) return 1 diff --git a/code/modules/projectiles/projectile/beams.dm b/code/modules/projectiles/projectile/beams.dm index f513c83da33..8e40affab57 100644 --- a/code/modules/projectiles/projectile/beams.dm +++ b/code/modules/projectiles/projectile/beams.dm @@ -8,6 +8,166 @@ var/list/beam_master = list() // icon_states/dirs for each placed beam image // turfs that have that icon_state/dir +/obj/item/projectile/beam/lightning + invisibility = 101 + name = "lightning" + damage = 0 + icon = 'icons/obj/lightning.dmi' + icon_state = "lightning" + stun = 10 + weaken = 10 + stutter = 50 + eyeblur = 50 + var/tang = 0 + layer = 3 + var/turf/last = null + kill_count = 6 + proc/adjustAngle(angle) + angle = round(angle) + 45 + if(angle > 180) + angle -= 180 + else + angle += 180 + if(!angle) + angle = 1 + /*if(angle < 0) + //angle = (round(abs(get_angle(A, user))) + 45) - 90 + angle = round(angle) + 45 + 180 + else + angle = round(angle) + 45*/ + return angle + + process() + var/first = 1 //So we don't make the overlay in the same tile as the firer + var/broke = 0 + var/broken + var/atom/curr = current + var/Angle=round(Get_Angle(firer,curr)) + var/icon/I=new('icons/obj/zap.dmi',"lightning") + I.Turn(Angle) + var/DX=(32*curr.x+curr.pixel_x)-(32*firer.x+firer.pixel_x) + var/DY=(32*curr.y+curr.pixel_y)-(32*firer.y+firer.pixel_y) + var/N=0 + var/length=round(sqrt((DX)**2+(DY)**2)) + var/count = 0 + for(N,N= kill_count) + break + count++ + var/obj/effect/overlay/beam/X=new(loc) + X.BeamSource=src + if(N+32>length) + var/icon/II=new(icon,icon_state) + II.DrawBox(null,1,(length-N),32,32) + II.Turn(Angle) + X.icon=II + else X.icon=I + var/Pixel_x=round(sin(Angle)+32*sin(Angle)*(N+16)/32) + var/Pixel_y=round(cos(Angle)+32*cos(Angle)*(N+16)/32) + if(DX==0) Pixel_x=0 + if(DY==0) Pixel_y=0 + if(Pixel_x>32) + for(var/a=0, a<=Pixel_x,a+=32) + X.x++ + Pixel_x-=32 + if(Pixel_x<-32) + for(var/a=0, a>=Pixel_x,a-=32) + X.x-- + Pixel_x+=32 + if(Pixel_y>32) + for(var/a=0, a<=Pixel_y,a+=32) + X.y++ + Pixel_y-=32 + if(Pixel_y<-32) + for(var/a=0, a>=Pixel_y,a-=32) + X.y-- + Pixel_y+=32 + X.pixel_x=Pixel_x + X.pixel_y=Pixel_y + var/turf/TT = get_turf(X.loc) + if(TT == firer.loc) + continue + if(TT.density) + del(X) + break + for(var/atom/O in TT) + if(!O.CanPass(src)) + del(X) + broke = 1 + break + for(var/mob/living/O in TT.contents) + if(istype(O, /mob/living)) + if(O.density) + del(X) + broke = 1 + break + if(broke) + if(X) + del(X) + break + spawn + while(src) //Move until we hit something + if(first) + icon = midicon + if((!( current ) || loc == current)) //If we pass our target + broken = 1 + icon = endicon + tang = adjustAngle(get_angle(original,current)) + if(tang > 180) + tang -= 180 + else + tang += 180 + icon_state = "[tang]" + var/turf/simulated/floor/f = current + if(f && istype(f)) + f.break_tile() + f.hotspot_expose(1000,CELL_VOLUME) + if((x == 1 || x == world.maxx || y == 1 || y == world.maxy)) + //world << "deleting" + //del(src) //Delete if it passes the world edge + broken = 1 + return + if(kill_count < 1) + //world << "deleting" + //del(src) + broken = 1 + kill_count-- + //world << "[x] [y]" + if(!bumped && !isturf(original)) + if(loc == get_turf(original)) + if(!(original in permutated)) + icon = endicon + if(!broken) + tang = adjustAngle(get_angle(original,current)) + if(tang > 180) + tang -= 180 + else + tang += 180 + icon_state = "[tang]" + Bump(original) + first = 0 + if(broken) + //world << "breaking" + break + else + last = get_turf(src.loc) + step_towards(src, current) //Move~ + if(src.loc != current) + tang = adjustAngle(get_angle(src.loc,current)) + icon_state = "[tang]" + del(src) + return + /*cleanup(reference) //Waits .3 seconds then removes the overlay. + //world << "setting invisibility" + sleep(50) + src.invisibility = 101 + return*/ + on_hit(atom/target, blocked = 0) + if(istype(target, /mob/living)) + var/mob/living/M = target + M.playsound_local(src, "explosion", 50, 1) + ..() + /obj/item/projectile/beam name = "laser" icon_state = "laser" diff --git a/code/modules/projectiles/projectile/bullets.dm b/code/modules/projectiles/projectile/bullets.dm index 36e456285ab..e61f2e08651 100644 --- a/code/modules/projectiles/projectile/bullets.dm +++ b/code/modules/projectiles/projectile/bullets.dm @@ -10,12 +10,32 @@ if (..(target, blocked)) var/mob/living/L = target shake_camera(L, 3, 2) + return 1 + return 0 /obj/item/projectile/bullet/weakbullet damage = 10 stun = 5 weaken = 5 +/obj/item/projectile/bullet/weakbullet/booze + on_hit(var/atom/target, var/blocked = 0) + if(..(target, blocked)) + var/mob/living/M = target + M.dizziness += 20 + M:slurring += 20 + M.confused += 20 + M.eye_blurry += 20 + M.drowsyness += 20 + for(var/datum/reagent/ethanol/A in M.reagents.reagent_list) + M.paralysis += 2 + M.dizziness += 10 + M:slurring += 10 + M.confused += 10 + M.eye_blurry += 10 + M.drowsyness += 10 + A.volume += 5 //Because we can + /obj/item/projectile/bullet/midbullet damage = 20 diff --git a/code/modules/reagents/Chemistry-Reagents.dm b/code/modules/reagents/Chemistry-Reagents.dm index 79f507dca8f..85899907d40 100644 --- a/code/modules/reagents/Chemistry-Reagents.dm +++ b/code/modules/reagents/Chemistry-Reagents.dm @@ -362,6 +362,28 @@ datum M.sleeping += 1 ..() return + chefspecial + // Quiet and lethal, needs atleast 4 units in the person before they'll die + name = "Chef's Special" + id = "chefspecial" + description = "An extremely toxic chemical that will surely end in death." + reagent_state = LIQUID + color = "#CF3600" // rgb: 207, 54, 0 + custom_metabolism = 0.39 + + on_mob_life(var/mob/living/M as mob) + var/random = rand(150,180) + if(!M) M = holder.my_atom + if(!data) data = 1 + switch(data) + if(0 to 5) + ..() + if(data >= random) + if(M.stat != DEAD) + M.death(0) + M.attack_log += "\[[time_stamp()]\]Died a quick and painless death by Chef Excellence's Special Sauce." + data++ + return minttoxin name = "Mint Toxin" diff --git a/code/modules/reagents/reagent_containers/food/condiment.dm b/code/modules/reagents/reagent_containers/food/condiment.dm index 73e44a85f02..bb7903c793b 100644 --- a/code/modules/reagents/reagent_containers/food/condiment.dm +++ b/code/modules/reagents/reagent_containers/food/condiment.dm @@ -125,6 +125,9 @@ if("sugar") name = "Sugar" desc = "Tastey space sugar!" + if("chefspecial") + name = "Chef Excellence's Special Sauce" + desc = "A potent sauce distilled from the toxin glands of 1000 Space Carp." else name = "Misc Condiment Bottle" if (reagents.reagent_list.len==1) @@ -171,4 +174,13 @@ volume = 20 New() ..() - reagents.add_reagent("blackpepper", 20) \ No newline at end of file + reagents.add_reagent("blackpepper", 20) + +/obj/item/weapon/reagent_containers/food/condiment/syndisauce + name = "Chef Excellence's Special Sauce" + desc = "A potent sauce distilled from the toxin glands of 1000 Space Carp with an extra touch of LSD because why not?" + amount_per_transfer_from_this = 1 + volume = 20 + New() + ..() + reagents.add_reagent("chefspecial", 20) \ No newline at end of file diff --git a/icons/obj/kitchen.dmi b/icons/obj/kitchen.dmi index 96cb16bb928..3d87f4cbe54 100644 Binary files a/icons/obj/kitchen.dmi and b/icons/obj/kitchen.dmi differ diff --git a/icons/obj/lightning.dmi b/icons/obj/lightning.dmi new file mode 100644 index 00000000000..f7e8ca959c7 Binary files /dev/null and b/icons/obj/lightning.dmi differ diff --git a/icons/obj/weapons.dmi b/icons/obj/weapons.dmi index d78c9b6a3ff..a938d02c2c6 100644 Binary files a/icons/obj/weapons.dmi and b/icons/obj/weapons.dmi differ diff --git a/icons/obj/zap.dmi b/icons/obj/zap.dmi new file mode 100644 index 00000000000..e5f94159996 Binary files /dev/null and b/icons/obj/zap.dmi differ diff --git a/sound/effects/eleczap.ogg b/sound/effects/eleczap.ogg new file mode 100644 index 00000000000..855d6dc82fa Binary files /dev/null and b/sound/effects/eleczap.ogg differ