diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index f1c58be502..1fe39b9717 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -16129,11 +16129,11 @@ /area/service/bar) "aMw" = ( /obj/machinery/vending/dinnerware{ - contraband = list(/obj/item/reagent_containers/food/condiment/flour = 4); + contraband = list(/obj/item/reagent_containers/food/condiment/flour=4); desc = "This vendor is full of condiments to put on food."; name = "\improper Condiments Vendor"; product_ads = "Get your sauces here!;No slave labour was used to make these products!;Nanotrasen Approved?!"; - products = list(/obj/item/storage/bag/tray = 8, /obj/item/reagent_containers/food/drinks/drinkingglass = 10, /obj/item/storage/box/cups = 5, /obj/item/reagent_containers/food/condiment/pack/ketchup = 20, /obj/item/reagent_containers/food/condiment/pack/mustard = 20, /obj/item/reagent_containers/food/condiment/pack/hotsauce = 20, /obj/item/reagent_containers/food/condiment/pack/astrotame = 20, /obj/item/reagent_containers/food/condiment/saltshaker = 20, /obj/item/reagent_containers/food/condiment/peppermill = 20) + products = list(/obj/item/storage/bag/tray=8,/obj/item/reagent_containers/food/drinks/drinkingglass=10,/obj/item/storage/box/cups=5,/obj/item/reagent_containers/food/condiment/pack/ketchup=20,/obj/item/reagent_containers/food/condiment/pack/mustard=20,/obj/item/reagent_containers/food/condiment/pack/hotsauce=20,/obj/item/reagent_containers/food/condiment/pack/astrotame=20,/obj/item/reagent_containers/food/condiment/saltshaker=20,/obj/item/reagent_containers/food/condiment/peppermill=20) }, /turf/open/floor/wood, /area/service/bar) @@ -17889,7 +17889,7 @@ /area/service/bar) "aRA" = ( /obj/machinery/vending/dinnerware{ - contraband = list(/obj/item/kitchen/rollingpin = 2, /obj/item/kitchen/knife/butcher = 2, /obj/item/reagent_containers/food/condiment/flour = 4) + contraband = list(/obj/item/kitchen/rollingpin=2,/obj/item/kitchen/knife/butcher=2,/obj/item/reagent_containers/food/condiment/flour=4) }, /turf/open/floor/plasteel/cafeteria, /area/service/kitchen) @@ -24597,6 +24597,9 @@ /obj/effect/turf_decal/tile/red{ dir = 4 }, +/obj/machinery/posialert{ + pixel_x = 32 + }, /turf/open/floor/plasteel/white, /area/science/robotics/lab) "biQ" = ( diff --git a/_maps/map_files/CogStation/CogStation.dmm b/_maps/map_files/CogStation/CogStation.dmm index 6f1ec5682b..855f1c5443 100644 --- a/_maps/map_files/CogStation/CogStation.dmm +++ b/_maps/map_files/CogStation/CogStation.dmm @@ -49200,6 +49200,9 @@ c_tag = "Robotics Lab"; dir = 4 }, +/obj/machinery/posialert{ + pixel_x = -32 + }, /turf/open/floor/plasteel/dark/side{ dir = 8 }, diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 776e50e9a5..6ba5945fa5 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -61512,12 +61512,12 @@ /obj/machinery/computer/operating{ dir = 1 }, -/obj/machinery/newscaster{ - pixel_y = -32 - }, /obj/effect/turf_decal/tile/purple{ dir = 8 }, +/obj/machinery/posialert{ + pixel_y = -32 + }, /turf/open/floor/plasteel/white, /area/science/robotics/lab) "dIR" = ( diff --git a/_maps/map_files/KiloStation/KiloStation.dmm b/_maps/map_files/KiloStation/KiloStation.dmm index 37a0292f45..6680f867c4 100644 --- a/_maps/map_files/KiloStation/KiloStation.dmm +++ b/_maps/map_files/KiloStation/KiloStation.dmm @@ -36997,6 +36997,9 @@ /obj/item/assembly/flash/handheld, /obj/item/assembly/flash/handheld, /obj/item/assembly/flash/handheld, +/obj/machinery/posialert{ + pixel_x = -32 + }, /turf/open/floor/plasteel/dark, /area/science/robotics/lab) "bhC" = ( @@ -43729,7 +43732,7 @@ }, /obj/item/reagent_containers/food/drinks/beer{ desc = "A station exclusive. Consumpt may result in seizures, blindness, drunkenness, or even death."; - list_reagents = list(/datum/reagent/consumable/ethanol/thirteenloko = 10); + list_reagents = list(/datum/reagent/consumable/ethanol/thirteenloko=10); name = "Kilo-Kocktail"; pixel_x = 5; pixel_y = 5 @@ -84892,7 +84895,7 @@ /obj/item/reagent_containers/food/drinks/bottle/grenadine, /obj/item/reagent_containers/food/drinks/beer{ desc = "A station exclusive. Consumpt may result in seizures, blindness, drunkenness, or even death."; - list_reagents = list(/datum/reagent/consumable/ethanol/thirteenloko = 10); + list_reagents = list(/datum/reagent/consumable/ethanol/thirteenloko=10); name = "Kilo-Kocktail"; pixel_x = 5; pixel_y = 5 @@ -84976,56 +84979,56 @@ /obj/item/reagent_containers/food/drinks/bottle/wine, /obj/item/reagent_containers/food/drinks/beer{ desc = "A station exclusive. Consumpt may result in seizures, blindness, drunkenness, or even death."; - list_reagents = list(/datum/reagent/consumable/ethanol/thirteenloko = 10); + list_reagents = list(/datum/reagent/consumable/ethanol/thirteenloko=10); name = "Kilo-Kocktail"; pixel_x = 5; pixel_y = 5 }, /obj/item/reagent_containers/food/drinks/beer{ desc = "A station exclusive. Consumpt may result in seizures, blindness, drunkenness, or even death."; - list_reagents = list(/datum/reagent/consumable/ethanol/thirteenloko = 10); + list_reagents = list(/datum/reagent/consumable/ethanol/thirteenloko=10); name = "Kilo-Kocktail"; pixel_x = 5; pixel_y = 5 }, /obj/item/reagent_containers/food/drinks/beer{ desc = "A station exclusive. Consumpt may result in seizures, blindness, drunkenness, or even death."; - list_reagents = list(/datum/reagent/consumable/ethanol/thirteenloko = 10); + list_reagents = list(/datum/reagent/consumable/ethanol/thirteenloko=10); name = "Kilo-Kocktail"; pixel_x = 5; pixel_y = 5 }, /obj/item/reagent_containers/food/drinks/beer{ desc = "A station exclusive. Consumpt may result in seizures, blindness, drunkenness, or even death."; - list_reagents = list(/datum/reagent/consumable/ethanol/thirteenloko = 10); + list_reagents = list(/datum/reagent/consumable/ethanol/thirteenloko=10); name = "Kilo-Kocktail"; pixel_x = 5; pixel_y = 5 }, /obj/item/reagent_containers/food/drinks/beer{ desc = "A station exclusive. Consumpt may result in seizures, blindness, drunkenness, or even death."; - list_reagents = list(/datum/reagent/consumable/ethanol/thirteenloko = 10); + list_reagents = list(/datum/reagent/consumable/ethanol/thirteenloko=10); name = "Kilo-Kocktail"; pixel_x = 5; pixel_y = 5 }, /obj/item/reagent_containers/food/drinks/beer{ desc = "A station exclusive. Consumpt may result in seizures, blindness, drunkenness, or even death."; - list_reagents = list(/datum/reagent/consumable/ethanol/thirteenloko = 10); + list_reagents = list(/datum/reagent/consumable/ethanol/thirteenloko=10); name = "Kilo-Kocktail"; pixel_x = 5; pixel_y = 5 }, /obj/item/reagent_containers/food/drinks/beer{ desc = "A station exclusive. Consumpt may result in seizures, blindness, drunkenness, or even death."; - list_reagents = list(/datum/reagent/consumable/ethanol/thirteenloko = 10); + list_reagents = list(/datum/reagent/consumable/ethanol/thirteenloko=10); name = "Kilo-Kocktail"; pixel_x = 5; pixel_y = 5 }, /obj/item/reagent_containers/food/drinks/beer{ desc = "A station exclusive. Consumpt may result in seizures, blindness, drunkenness, or even death."; - list_reagents = list(/datum/reagent/consumable/ethanol/thirteenloko = 10); + list_reagents = list(/datum/reagent/consumable/ethanol/thirteenloko=10); name = "Kilo-Kocktail"; pixel_x = 5; pixel_y = 5 diff --git a/_maps/map_files/LambdaStation/lambda.dmm b/_maps/map_files/LambdaStation/lambda.dmm index 97a17ff303..590e1980c0 100644 --- a/_maps/map_files/LambdaStation/lambda.dmm +++ b/_maps/map_files/LambdaStation/lambda.dmm @@ -7933,6 +7933,9 @@ /obj/structure/table, /obj/item/stack/cable_coil/random, /obj/machinery/camera/autoname, +/obj/machinery/posialert{ + pixel_y = 32 + }, /turf/open/floor/plasteel, /area/science/robotics/lab) "apy" = ( @@ -13514,7 +13517,7 @@ }, /mob/living/simple_animal/pet/gondola{ desc = "The last known gondola for lightyears, it is your duty to keep them safe from the filthy yellowed hands of the greytide."; - loot = list(/obj/effect/decal/cleanable/blood/gibs, /obj/item/stack/sheet/animalhide/gondola = 1); + loot = list(/obj/effect/decal/cleanable/blood/gibs,/obj/item/stack/sheet/animalhide/gondola=1); name = "Filbert" }, /turf/open/floor/plasteel/dark, @@ -38023,7 +38026,7 @@ dir = 5 }, /obj/machinery/vending/medical{ - products = list(/obj/item/reagent_containers/syringe = 12, /obj/item/reagent_containers/dropper = 3, /obj/item/healthanalyzer = 4, /obj/item/sensor_device = 4, /obj/item/pinpointer/crew = 2, /obj/item/reagent_containers/medspray/sterilizine = 1, /obj/item/stack/medical/gauze = 8, /obj/item/reagent_containers/pill/patch/styptic = 5, /obj/item/reagent_containers/medspray/styptic = 2, /obj/item/reagent_containers/pill/patch/silver_sulf = 5, /obj/item/reagent_containers/medspray/silver_sulf = 2, /obj/item/reagent_containers/pill/insulin = 10, /obj/item/reagent_containers/pill/salbutamol = 2, /obj/item/reagent_containers/glass/bottle/charcoal = 4, /obj/item/reagent_containers/glass/bottle/epinephrine = 4, /obj/item/reagent_containers/glass/bottle/salglu_solution = 3, /obj/item/reagent_containers/glass/bottle/morphine = 4, /obj/item/reagent_containers/glass/bottle/toxin = 3, /obj/item/reagent_containers/syringe/antiviral = 6, /obj/item/storage/hypospraykit/fire = 2, /obj/item/storage/hypospraykit/toxin = 2, /obj/item/storage/hypospraykit/o2 = 2, /obj/item/storage/hypospraykit/brute = 2, /obj/item/storage/hypospraykit/enlarge = 2, /obj/item/reagent_containers/glass/bottle/vial/small = 5, /obj/item/storage/briefcase/medical = 2, /obj/item/stack/sticky_tape/surgical = 3, /obj/item/healthanalyzer/wound = 4, /obj/item/stack/medical/ointment = 2, /obj/item/stack/medical/suture = 2, /obj/item/stack/medical/bone_gel = 4) + products = list(/obj/item/reagent_containers/syringe=12,/obj/item/reagent_containers/dropper=3,/obj/item/healthanalyzer=4,/obj/item/sensor_device=4,/obj/item/pinpointer/crew=2,/obj/item/reagent_containers/medspray/sterilizine=1,/obj/item/stack/medical/gauze=8,/obj/item/reagent_containers/pill/patch/styptic=5,/obj/item/reagent_containers/medspray/styptic=2,/obj/item/reagent_containers/pill/patch/silver_sulf=5,/obj/item/reagent_containers/medspray/silver_sulf=2,/obj/item/reagent_containers/pill/insulin=10,/obj/item/reagent_containers/pill/salbutamol=2,/obj/item/reagent_containers/glass/bottle/charcoal=4,/obj/item/reagent_containers/glass/bottle/epinephrine=4,/obj/item/reagent_containers/glass/bottle/salglu_solution=3,/obj/item/reagent_containers/glass/bottle/morphine=4,/obj/item/reagent_containers/glass/bottle/toxin=3,/obj/item/reagent_containers/syringe/antiviral=6,/obj/item/storage/hypospraykit/fire=2,/obj/item/storage/hypospraykit/toxin=2,/obj/item/storage/hypospraykit/o2=2,/obj/item/storage/hypospraykit/brute=2,/obj/item/storage/hypospraykit/enlarge=2,/obj/item/reagent_containers/glass/bottle/vial/small=5,/obj/item/storage/briefcase/medical=2,/obj/item/stack/sticky_tape/surgical=3,/obj/item/healthanalyzer/wound=4,/obj/item/stack/medical/ointment=2,/obj/item/stack/medical/suture=2,/obj/item/stack/medical/bone_gel=4) }, /turf/open/floor/plasteel/white, /area/medical/medbay/central) @@ -46027,7 +46030,7 @@ "bXK" = ( /obj/effect/turf_decal/trimline/blue/filled/line, /obj/machinery/vending/medical{ - products = list(/obj/item/reagent_containers/syringe = 12, /obj/item/reagent_containers/dropper = 3, /obj/item/healthanalyzer = 4, /obj/item/sensor_device = 4, /obj/item/pinpointer/crew = 2, /obj/item/reagent_containers/medspray/sterilizine = 1, /obj/item/stack/medical/gauze = 8, /obj/item/reagent_containers/pill/patch/styptic = 5, /obj/item/reagent_containers/medspray/styptic = 2, /obj/item/reagent_containers/pill/patch/silver_sulf = 5, /obj/item/reagent_containers/medspray/silver_sulf = 2, /obj/item/reagent_containers/pill/insulin = 10, /obj/item/reagent_containers/pill/salbutamol = 2, /obj/item/reagent_containers/glass/bottle/charcoal = 4, /obj/item/reagent_containers/glass/bottle/epinephrine = 4, /obj/item/reagent_containers/glass/bottle/salglu_solution = 3, /obj/item/reagent_containers/glass/bottle/morphine = 4, /obj/item/reagent_containers/glass/bottle/toxin = 3, /obj/item/reagent_containers/syringe/antiviral = 6, /obj/item/storage/hypospraykit/fire = 2, /obj/item/storage/hypospraykit/toxin = 2, /obj/item/storage/hypospraykit/o2 = 2, /obj/item/storage/hypospraykit/brute = 2, /obj/item/storage/hypospraykit/enlarge = 2, /obj/item/reagent_containers/glass/bottle/vial/small = 5, /obj/item/storage/briefcase/medical = 2, /obj/item/stack/sticky_tape/surgical = 3, /obj/item/healthanalyzer/wound = 4, /obj/item/stack/medical/ointment = 2, /obj/item/stack/medical/suture = 2, /obj/item/stack/medical/bone_gel = 4) + products = list(/obj/item/reagent_containers/syringe=12,/obj/item/reagent_containers/dropper=3,/obj/item/healthanalyzer=4,/obj/item/sensor_device=4,/obj/item/pinpointer/crew=2,/obj/item/reagent_containers/medspray/sterilizine=1,/obj/item/stack/medical/gauze=8,/obj/item/reagent_containers/pill/patch/styptic=5,/obj/item/reagent_containers/medspray/styptic=2,/obj/item/reagent_containers/pill/patch/silver_sulf=5,/obj/item/reagent_containers/medspray/silver_sulf=2,/obj/item/reagent_containers/pill/insulin=10,/obj/item/reagent_containers/pill/salbutamol=2,/obj/item/reagent_containers/glass/bottle/charcoal=4,/obj/item/reagent_containers/glass/bottle/epinephrine=4,/obj/item/reagent_containers/glass/bottle/salglu_solution=3,/obj/item/reagent_containers/glass/bottle/morphine=4,/obj/item/reagent_containers/glass/bottle/toxin=3,/obj/item/reagent_containers/syringe/antiviral=6,/obj/item/storage/hypospraykit/fire=2,/obj/item/storage/hypospraykit/toxin=2,/obj/item/storage/hypospraykit/o2=2,/obj/item/storage/hypospraykit/brute=2,/obj/item/storage/hypospraykit/enlarge=2,/obj/item/reagent_containers/glass/bottle/vial/small=5,/obj/item/storage/briefcase/medical=2,/obj/item/stack/sticky_tape/surgical=3,/obj/item/healthanalyzer/wound=4,/obj/item/stack/medical/ointment=2,/obj/item/stack/medical/suture=2,/obj/item/stack/medical/bone_gel=4) }, /turf/open/floor/plasteel/white, /area/medical/medbay/central) @@ -62219,7 +62222,7 @@ /area/engineering/break_room) "cUI" = ( /obj/machinery/vending/engineering{ - products = list(/obj/item/clothing/under/rank/engineering/engineer = 4, /obj/item/clothing/shoes/sneakers/orange = 4, /obj/item/clothing/head/hardhat = 4, /obj/item/storage/belt/utility = 4, /obj/item/clothing/glasses/meson/engine = 4, /obj/item/clothing/gloves/color/yellow = 2, /obj/item/screwdriver = 12, /obj/item/crowbar = 12, /obj/item/wirecutters = 12, /obj/item/multitool = 12, /obj/item/wrench = 12, /obj/item/t_scanner = 12, /obj/item/stock_parts/cell = 8, /obj/item/weldingtool = 8, /obj/item/clothing/head/welding = 8, /obj/item/light/tube = 10, /obj/item/clothing/suit/fire = 4, /obj/item/stock_parts/scanning_module = 5, /obj/item/stock_parts/micro_laser = 5, /obj/item/stock_parts/matter_bin = 5, /obj/item/stock_parts/manipulator = 5) + products = list(/obj/item/clothing/under/rank/engineering/engineer=4,/obj/item/clothing/shoes/sneakers/orange=4,/obj/item/clothing/head/hardhat=4,/obj/item/storage/belt/utility=4,/obj/item/clothing/glasses/meson/engine=4,/obj/item/clothing/gloves/color/yellow=2,/obj/item/screwdriver=12,/obj/item/crowbar=12,/obj/item/wirecutters=12,/obj/item/multitool=12,/obj/item/wrench=12,/obj/item/t_scanner=12,/obj/item/stock_parts/cell=8,/obj/item/weldingtool=8,/obj/item/clothing/head/welding=8,/obj/item/light/tube=10,/obj/item/clothing/suit/fire=4,/obj/item/stock_parts/scanning_module=5,/obj/item/stock_parts/micro_laser=5,/obj/item/stock_parts/matter_bin=5,/obj/item/stock_parts/manipulator=5) }, /obj/effect/turf_decal/trimline/yellow/filled/line{ dir = 1 @@ -70184,7 +70187,7 @@ }, /obj/structure/table/wood, /obj/item/reagent_containers/food/drinks/sillycup/smallcarton{ - list_reagents = list(/datum/reagent/consumable/milk = 20); + list_reagents = list(/datum/reagent/consumable/milk=20); name = "small milk carton"; pixel_x = -8; pixel_y = 5 diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 52fe46984f..847977dab0 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -1701,7 +1701,7 @@ name = "3maintenance loot spawner" }, /obj/effect/spawner/lootdrop/armory_contraband{ - loot = list(/obj/item/gun/ballistic/automatic/pistol = 5, /obj/item/gun/ballistic/shotgun/automatic/combat = 5, /obj/item/gun/ballistic/revolver/mateba, /obj/item/gun/ballistic/automatic/pistol/deagle, /obj/item/storage/box/syndie_kit/throwing_weapons = 3) + loot = list(/obj/item/gun/ballistic/automatic/pistol=5,/obj/item/gun/ballistic/shotgun/automatic/combat=5,/obj/item/gun/ballistic/revolver/mateba,/obj/item/gun/ballistic/automatic/pistol/deagle,/obj/item/storage/box/syndie_kit/throwing_weapons=3) }, /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -40928,6 +40928,9 @@ /obj/item/cautery{ pixel_y = 15 }, +/obj/machinery/posialert{ + pixel_y = -32 + }, /turf/open/floor/plasteel/white/corner{ dir = 4 }, @@ -57237,7 +57240,7 @@ "iqV" = ( /obj/structure/table/wood/poker, /obj/effect/spawner/lootdrop{ - loot = list(/obj/item/gun/ballistic/revolver/russian = 5, /obj/item/storage/box/syndie_kit/throwing_weapons, /obj/item/toy/cards/deck/syndicate = 2); + loot = list(/obj/item/gun/ballistic/revolver/russian=5,/obj/item/storage/box/syndie_kit/throwing_weapons,/obj/item/toy/cards/deck/syndicate=2); name = "gambling valuables spawner" }, /turf/open/floor/wood, diff --git a/_maps/map_files/OmegaStation/OmegaStation.dmm b/_maps/map_files/OmegaStation/OmegaStation.dmm index e681688066..301971dd2b 100644 --- a/_maps/map_files/OmegaStation/OmegaStation.dmm +++ b/_maps/map_files/OmegaStation/OmegaStation.dmm @@ -27988,6 +27988,9 @@ dir = 1 }, /obj/effect/turf_decal/bot, +/obj/machinery/posialert{ + pixel_y = 32 + }, /turf/open/floor/plasteel/dark, /area/science/robotics/lab) "bae" = ( diff --git a/_maps/map_files/PubbyStation/PubbyStation.dmm b/_maps/map_files/PubbyStation/PubbyStation.dmm index d8d18c4407..fab7081ace 100644 --- a/_maps/map_files/PubbyStation/PubbyStation.dmm +++ b/_maps/map_files/PubbyStation/PubbyStation.dmm @@ -15731,7 +15731,7 @@ /area/service/cafeteria/lunchroom) "aNb" = ( /obj/machinery/vending/sustenance{ - contraband = list(/obj/item/kitchen/knife = 6, /obj/item/reagent_containers/food/drinks/coffee = 12); + contraband = list(/obj/item/kitchen/knife=6,/obj/item/reagent_containers/food/drinks/coffee=12); desc = "A vending machine which vends food."; product_ads = "Sufficiently healthy." }, @@ -29619,6 +29619,9 @@ /obj/effect/turf_decal/tile/neutral{ dir = 8 }, +/obj/machinery/posialert{ + pixel_x = -32 + }, /turf/open/floor/plasteel/dark, /area/science/robotics/lab) "bsX" = ( @@ -38786,7 +38789,7 @@ input_tag = "mix_in"; name = "Gas Mix Tank Control"; output_tag = "mix_in"; - sensors = list("mix_sensor" = "Tank") + sensors = list("mix_sensor"="Tank") }, /obj/effect/turf_decal/tile/yellow, /obj/effect/turf_decal/tile/yellow{ @@ -40274,7 +40277,7 @@ input_tag = "n2o_in"; name = "Nitrous Oxide Supply Control"; output_tag = "n2o_out"; - sensors = list("n2o_sensor" = "Tank") + sensors = list("n2o_sensor"="Tank") }, /obj/effect/turf_decal/tile/yellow, /obj/effect/turf_decal/tile/yellow{ @@ -41663,7 +41666,7 @@ input_tag = "tox_in"; name = "Plasma Supply Control"; output_tag = "tox_out"; - sensors = list("tox_sensor" = "Tank") + sensors = list("tox_sensor"="Tank") }, /obj/effect/turf_decal/tile/yellow, /obj/effect/turf_decal/tile/yellow{ diff --git a/_maps/map_files/Snaxi/Snaxi.dmm b/_maps/map_files/Snaxi/Snaxi.dmm index 1e3c094cf6..e5aef6889f 100644 --- a/_maps/map_files/Snaxi/Snaxi.dmm +++ b/_maps/map_files/Snaxi/Snaxi.dmm @@ -9515,6 +9515,9 @@ /obj/machinery/atmospherics/pipe/simple/supply/hidden{ dir = 4 }, +/obj/machinery/posialert{ + pixel_x = -32 + }, /turf/open/floor/plasteel/white, /area/science/robotics/lab) "axr" = ( @@ -36866,7 +36869,7 @@ /area/engineering/secure_construction) "qzP" = ( /obj/machinery/vending/dinnerware{ - contraband = list(/obj/item/kitchen/rollingpin = 2, /obj/item/kitchen/knife/butcher = 2, /obj/item/reagent_containers/food/condiment/flour = 4) + contraband = list(/obj/item/kitchen/rollingpin=2,/obj/item/kitchen/knife/butcher=2,/obj/item/reagent_containers/food/condiment/flour=4) }, /turf/open/floor/plasteel/freezer, /area/service/kitchen) @@ -44901,7 +44904,7 @@ dir = 8 }, /obj/effect/spawner/lootdrop/armory_contraband{ - loot = list(/obj/item/gun/ballistic/automatic/pistol = 5, /obj/item/gun/ballistic/shotgun/automatic/combat = 5, /obj/item/gun/ballistic/revolver/mateba, /obj/item/gun/ballistic/automatic/pistol/deagle, /obj/item/storage/box/syndie_kit/throwing_weapons = 3) + loot = list(/obj/item/gun/ballistic/automatic/pistol=5,/obj/item/gun/ballistic/shotgun/automatic/combat=5,/obj/item/gun/ballistic/revolver/mateba,/obj/item/gun/ballistic/automatic/pistol/deagle,/obj/item/storage/box/syndie_kit/throwing_weapons=3) }, /obj/effect/spawner/lootdrop/maintenance{ lootcount = 3; diff --git a/auxmos.dll b/auxmos.dll index 4e0687fa2b..b1320fa1dc 100644 Binary files a/auxmos.dll and b/auxmos.dll differ diff --git a/auxmos.pdb b/auxmos.pdb index da06980179..0aa8e9379a 100644 Binary files a/auxmos.pdb and b/auxmos.pdb differ diff --git a/code/__DEFINES/atmospherics.dm b/code/__DEFINES/atmospherics.dm index 6266dcc6d3..c585a822ea 100644 --- a/code/__DEFINES/atmospherics.dm +++ b/code/__DEFINES/atmospherics.dm @@ -152,6 +152,10 @@ #define ATMOS_PASS_PROC -1 //ask CanAtmosPass() #define ATMOS_PASS_DENSITY -2 //just check density +// Adjacency flags +#define ATMOS_ADJACENT_ANY (1<<0) +#define ATMOS_ADJACENT_FIRELOCK (1<<1) + #define CANATMOSPASS(A, O) ( A.CanAtmosPass == ATMOS_PASS_PROC ? A.CanAtmosPass(O) : ( A.CanAtmosPass == ATMOS_PASS_DENSITY ? !A.density : A.CanAtmosPass ) ) #define CANVERTICALATMOSPASS(A, O) ( A.CanAtmosPassVertical == ATMOS_PASS_PROC ? A.CanAtmosPass(O, TRUE) : ( A.CanAtmosPassVertical == ATMOS_PASS_DENSITY ? !A.density : A.CanAtmosPassVertical ) ) @@ -323,14 +327,6 @@ #define QUANTIZE(variable) (round(variable,0.0000001))/*I feel the need to document what happens here. Basically this is used to catch most rounding errors, however it's previous value made it so that once gases got hot enough, most procedures wouldnt occur due to the fact that the mole counts would get rounded away. Thus, we lowered it a few orders of magnititude */ - -#ifdef TESTING -GLOBAL_LIST_INIT(atmos_adjacent_savings, list(0,0)) -#define CALCULATE_ADJACENT_TURFS(T) if (SSadjacent_air.queue[T]) { GLOB.atmos_adjacent_savings[1] += 1 } else { GLOB.atmos_adjacent_savings[2] += 1; SSadjacent_air.queue[T] = 1 } -#else -#define CALCULATE_ADJACENT_TURFS(T) SSadjacent_air.queue[T] = 1 -#endif - //If you're doing spreading things related to atmos, DO NOT USE CANATMOSPASS, IT IS NOT CHEAP. use this instead, the info is cached after all. it's tweaked just a bit to allow for circular checks #define TURFS_CAN_SHARE(T1, T2) (LAZYACCESS(T2.atmos_adjacent_turfs, T1) || LAZYLEN(T1.atmos_adjacent_turfs & T2.atmos_adjacent_turfs)) diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index a6d411a8dd..6dae40ce07 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -206,6 +206,19 @@ ///Time to spend without clicking on other things required for your shots to become accurate. #define GUN_AIMING_TIME (2 SECONDS) +//Autofire component +/// Compatible firemode is in the gun. Wait until it's held in the user hands. +#define AUTOFIRE_STAT_IDLE (1<<0) +/// Gun is active and in the user hands. Wait until user does a valid click. +#define AUTOFIRE_STAT_ALERT (1<<1) +/// Gun is shooting. +#define AUTOFIRE_STAT_FIRING (1<<2) + +#define COMSIG_AUTOFIRE_ONMOUSEDOWN "autofire_onmousedown" + #define COMPONENT_AUTOFIRE_ONMOUSEDOWN_BYPASS (1<<0) +#define COMSIG_AUTOFIRE_SHOT "autofire_shot" + #define COMPONENT_AUTOFIRE_SHOT_SUCCESS (1<<0) + //Object/Item sharpness #define SHARP_NONE 0 #define SHARP_EDGED 1 @@ -261,3 +274,4 @@ * a "inefficiently" prefix will be added to the message. */ #define FEEBLE_ATTACK_MSG_THRESHOLD 0.5 + diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 9de0dbe7c5..7a54b8482d 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -321,6 +321,12 @@ ///from base of mob/AltClickOn(): (atom/A) #define COMSIG_MOB_ALTCLICKON "mob_altclickon" +//Gun signals +///When a gun is switched to automatic fire mode +#define COMSIG_GUN_AUTOFIRE_SELECTED "gun_autofire_selected" +///When a gun is switched off of automatic fire mode +#define COMSIG_GUN_AUTOFIRE_DESELECTED "gun_autofire_deselected" + // Lighting: ///from base of [atom/proc/set_light]: (l_range, l_power, l_color, l_on) #define COMSIG_ATOM_SET_LIGHT "atom_set_light" @@ -348,12 +354,22 @@ #define COMSIG_ATOM_UPDATE_LIGHT_FLAGS "atom_update_light_flags" // /client signals -#define COMSIG_MOB_CLIENT_LOGIN "mob_client_login" //sent when a mob/login() finishes: (client) #define COMSIG_MOB_CLIENT_LOGOUT "mob_client_logout" //sent when a mob/logout() starts: (client) #define COMSIG_MOB_CLIENT_MOVE "mob_client_move" //sent when client/Move() finishes with no early returns: (client, direction, n, oldloc) #define COMSIG_MOB_CLIENT_CHANGE_VIEW "mob_client_change_view" //from base of /client/change_view(): (client, old_view, view) #define COMSIG_MOB_CLIENT_MOUSEMOVE "mob_client_mousemove" //from base of /client/MouseMove(): (object, location, control, params) +///sent when a mob/login() finishes: (client) +#define COMSIG_MOB_CLIENT_LOGIN "comsig_mob_client_login" +//from base of client/MouseDown(): (/client, object, location, control, params) +#define COMSIG_CLIENT_MOUSEDOWN "client_mousedown" +//from base of client/MouseUp(): (/client, object, location, control, params) +#define COMSIG_CLIENT_MOUSEUP "client_mouseup" + #define COMPONENT_CLIENT_MOUSEUP_INTERCEPT (1<<0) +//from base of client/MouseUp(): (/client, object, location, control, params) +#define COMSIG_CLIENT_MOUSEDRAG "client_mousedrag" + + // /mob/living signals #define COMSIG_LIVING_REGENERATE_LIMBS "living_regenerate_limbs" //from base of /mob/living/regenerate_limbs(): (noheal, excluded_limbs) #define COMSIG_LIVING_RESIST "living_resist" //from base of mob/living/resist() (/mob/living) diff --git a/code/__DEFINES/gun.dm b/code/__DEFINES/gun.dm new file mode 100644 index 0000000000..05ce5118a3 --- /dev/null +++ b/code/__DEFINES/gun.dm @@ -0,0 +1,3 @@ +#define SELECT_SEMI_AUTOMATIC 1 +#define SELECT_BURST_SHOT 2 +#define SELECT_FULLY_AUTOMATIC 3 diff --git a/code/__DEFINES/hud.dm b/code/__DEFINES/hud.dm index 128f9120c6..88cba1c449 100644 --- a/code/__DEFINES/hud.dm +++ b/code/__DEFINES/hud.dm @@ -4,3 +4,6 @@ #define HUD_STYLE_NOHUD 3 //No hud (for screenshots) #define HUD_VERSIONS 3 //Used in show_hud(); Please ensure this is the same as the maximum index. + +#define ui_borg_pda_send "CENTER+5:21,SOUTH:5" // To the right of the alert panel +#define ui_borg_pda_log "CENTER+6:21,SOUTH:5" diff --git a/code/__DEFINES/misc.dm b/code/__DEFINES/misc.dm index a88f40a19f..6607b91695 100644 --- a/code/__DEFINES/misc.dm +++ b/code/__DEFINES/misc.dm @@ -388,6 +388,23 @@ GLOBAL_LIST_INIT(pda_reskins, list(PDA_SKIN_CLASSIC = 'icons/obj/pda.dmi', PDA_S #define BEAT_SLOW 2 #define BEAT_NONE 0 +//Mouse buttons pressed/held/released +#define RIGHT_CLICK "right" +#define MIDDLE_CLICK "middle" +#define LEFT_CLICK "left" + +//Keys held down during the mouse action +#define CTRL_CLICK "ctrl" +#define ALT_CLICK "alt" +#define SHIFT_CLICK "shift" + +//Pixel coordinates within the icon, in the icon's coordinate space +#define ICON_X "icon-x" +#define ICON_Y "icon-y" + +//Pixel coordinates in screen_loc format ("[tile_x]:[pixel_x],[tile_y]:[pixel_y]") +#define SCREEN_LOC "screen-loc" + //https://secure.byond.com/docs/ref/info.html#/atom/var/mouse_opacity #define MOUSE_OPACITY_TRANSPARENT 0 #define MOUSE_OPACITY_ICON 1 diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 428784e953..73b2dd3006 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -673,6 +673,27 @@ Turf and target are separate in case you want to teleport some distance from a t if(final_x || final_y) return locate(final_x, final_y, T.z) +///Returns a turf based on text inputs, original turf and viewing client +/proc/parse_caught_click_modifiers(list/modifiers, turf/origin, client/viewing_client) + if(!modifiers) + return null + + var/screen_loc = splittext(LAZYACCESS(modifiers, SCREEN_LOC), ",") + var/list/actual_view = getviewsize(viewing_client ? viewing_client.view : world.view) + var/click_turf_x = splittext(screen_loc[1], ":") + var/click_turf_y = splittext(screen_loc[2], ":") + var/click_turf_z = origin.z + + var/click_turf_px = text2num(click_turf_x[2]) + var/click_turf_py = text2num(click_turf_y[2]) + click_turf_x = origin.x + text2num(click_turf_x[1]) - round(actual_view[1] / 2) - 1 + click_turf_y = origin.y + text2num(click_turf_y[1]) - round(actual_view[2] / 2) - 1 + + var/turf/click_turf = locate(clamp(click_turf_x, 1, world.maxx), clamp(click_turf_y, 1, world.maxy), click_turf_z) + LAZYSET(modifiers, ICON_X, "[(click_turf_px - click_turf.pixel_x) + ((click_turf_x - click_turf.x) * world.icon_size)]") + LAZYSET(modifiers, ICON_Y, "[(click_turf_py - click_turf.pixel_y) + ((click_turf_y - click_turf.y) * world.icon_size)]") + return click_turf + //Finds the distance between two atoms, in pixels //centered = FALSE counts from turf edge to edge //centered = TRUE counts from turf center to turf center diff --git a/code/_globalvars/lists/flavor_misc.dm b/code/_globalvars/lists/flavor_misc.dm index 5c8bf0b8fe..162eeffe78 100644 --- a/code/_globalvars/lists/flavor_misc.dm +++ b/code/_globalvars/lists/flavor_misc.dm @@ -320,7 +320,7 @@ GLOBAL_LIST_INIT(redacted_strings, list("\[REDACTED\]", "\[CLASSIFIED\]", "\[ARC GLOBAL_LIST_INIT(wisdoms, world.file2list("strings/wisdoms.txt")) //LANGUAGE CHARACTER CUSTOMIZATION -GLOBAL_LIST_INIT(speech_verbs, list("default","says","gibbers", "states", "chitters", "chimpers", "declares", "bellows", "buzzes" ,"beeps", "chirps", "clicks", "hisses" ,"poofs" , "puffs", "rattles", "mewls" ,"barks", "blorbles", "squeaks", "squawks", "flutters", "warbles", "caws", "gekkers", "clucks")) +GLOBAL_LIST_INIT(speech_verbs, list("default","says","gibbers", "states", "chitters", "chimpers", "declares", "bellows", "buzzes" ,"beeps", "chirps", "clicks", "hisses" ,"poofs" , "puffs", "rattles", "mewls" ,"barks", "blorbles", "squeaks", "squawks", "flutters", "warbles", "caws", "gekkers", "clucks","mumbles","crackles")) GLOBAL_LIST_INIT(roundstart_tongues, list("default","human tongue" = /obj/item/organ/tongue, "lizard tongue" = /obj/item/organ/tongue/lizard, "skeleton tongue" = /obj/item/organ/tongue/bone, "fly tongue" = /obj/item/organ/tongue/fly, "ipc tongue" = /obj/item/organ/tongue/robot/ipc, "xeno tongue" = /obj/item/organ/tongue/alien/hybrid)) /proc/get_roundstart_languages() diff --git a/code/_onclick/drag_drop.dm b/code/_onclick/drag_drop.dm index 58c182036d..a698706f1a 100644 --- a/code/_onclick/drag_drop.dm +++ b/code/_onclick/drag_drop.dm @@ -23,23 +23,31 @@ SEND_SIGNAL(src, COMSIG_MOUSEDROPPED_ONTO, dropping, user) return - -/client/MouseDown(object, location, control, params) - if (mouse_down_icon) +/client/MouseDown(datum/object, location, control, params) + if(!control) + return + if(QDELETED(object)) //Yep, you can click on qdeleted things before they have time to nullspace. Fun. + return + SEND_SIGNAL(src, COMSIG_CLIENT_MOUSEDOWN, object, location, control, params) + if(mouse_down_icon) mouse_pointer_icon = mouse_down_icon var/delay = mob.CanMobAutoclick(object, location, params) if(delay) selected_target[1] = object selected_target[2] = params while(selected_target[1]) - Click(selected_target[1], location, control, selected_target[2], TRUE) + Click(selected_target[1], location, control, selected_target[2]) sleep(delay) active_mousedown_item = mob.canMobMousedown(object, location, params) if(active_mousedown_item) active_mousedown_item.onMouseDown(object, location, params, mob) /client/MouseUp(object, location, control, params) - if (mouse_up_icon) + if(!control) + return + if(SEND_SIGNAL(src, COMSIG_CLIENT_MOUSEUP, object, location, control, params) & COMPONENT_CLIENT_MOUSEUP_INTERCEPT) + click_intercept_time = world.time + if(mouse_up_icon) mouse_pointer_icon = mouse_up_icon selected_target[1] = null if(active_mousedown_item) @@ -74,9 +82,6 @@ /obj/item/proc/onMouseUp(object, location, params, mob) return -/obj/item/gun/CanItemAutoclick(object, location, params) - . = automatic - /atom/proc/IsAutoclickable() . = 1 @@ -110,6 +115,7 @@ selected_target[2] = params if(active_mousedown_item) active_mousedown_item.onMouseDrag(src_object, over_object, src_location, over_location, params, mob) + SEND_SIGNAL(src, COMSIG_CLIENT_MOUSEDRAG, src_object, over_object, src_location, over_location, src_control, over_control, params) /obj/item/proc/onMouseDrag(src_object, over_object, src_location, over_location, params, mob) return diff --git a/code/_onclick/hud/robot.dm b/code/_onclick/hud/robot.dm index 03ad1b1821..e20bae87d7 100644 --- a/code/_onclick/hud/robot.dm +++ b/code/_onclick/hud/robot.dm @@ -342,3 +342,43 @@ if(.) return robot.modularInterface?.interact(robot) + +//borg pda +/datum/hud/robot/New(mob/owner) + . = ..() + + var/atom/movable/screen/using + + //PDA message + using = new /atom/movable/screen/robot/pda_msg_send + using.screen_loc = ui_borg_pda_send + using.hud = src + static_inventory += using + + //PDA log + using = new /atom/movable/screen/robot/pda_msg_show + using.screen_loc = ui_borg_pda_log + using.hud = src + static_inventory += using + +/atom/movable/screen/robot/pda_msg_send + name = "PDA - Send Message" + icon = 'icons/mob/screen_ai.dmi' + icon_state = "pda_send" + +/atom/movable/screen/robot/pda_msg_send/Click() + if(..()) + return + var/mob/living/silicon/robot/R = usr + R.cmd_send_pdamesg(usr) + +/atom/movable/screen/robot/pda_msg_show + name = "PDA - Show Message Log" + icon = 'icons/mob/screen_ai.dmi' + icon_state = "pda_receive" + +/atom/movable/screen/robot/pda_msg_show/Click() + if(..()) + return + var/mob/living/silicon/robot/R = usr + R.cmd_show_message_log(usr) diff --git a/code/controllers/subsystem/adjacent_air.dm b/code/controllers/subsystem/adjacent_air.dm deleted file mode 100644 index 99ee587826..0000000000 --- a/code/controllers/subsystem/adjacent_air.dm +++ /dev/null @@ -1,39 +0,0 @@ -SUBSYSTEM_DEF(adjacent_air) - name = "Atmos Adjacency" - flags = SS_BACKGROUND - runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME - wait = 10 - priority = FIRE_PRIORITY_ATMOS_ADJACENCY - var/list/queue = list() - -/datum/controller/subsystem/adjacent_air/stat_entry(msg) -#ifdef TESTING - msg = "P:[length(queue)], S:[GLOB.atmos_adjacent_savings[1]], T:[GLOB.atmos_adjacent_savings[2]]" -#else - msg = "P:[length(queue)]" -#endif - return ..() - -/datum/controller/subsystem/adjacent_air/Initialize() - while(length(queue)) - fire(mc_check = FALSE) - return ..() - -/datum/controller/subsystem/adjacent_air/fire(resumed = FALSE, mc_check = TRUE) - if(SSair.thread_running()) - pause() - return - - var/list/queue = src.queue - - while (length(queue)) - var/turf/currT = queue[1] - queue.Cut(1,2) - - currT.ImmediateCalculateAdjacentTurfs() - - if(mc_check) - if(MC_TICK_CHECK) - break - else - CHECK_TICK diff --git a/code/datums/action.dm b/code/datums/action.dm index ac8c909bd2..304aa47baa 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -23,6 +23,8 @@ var/icon_icon = 'icons/mob/actions.dmi' //This is the file for the ACTION icon var/button_icon_state = "default" //And this is the state for the action icon var/mob/owner + ///List of all mobs that are viewing our action button -> A unique movable for them to view. + var/list/viewers = list() /datum/action/New(Target) link_to(Target) @@ -121,6 +123,11 @@ return FALSE return TRUE +/datum/action/proc/UpdateButtons(status_only, force) + for(var/datum/hud/hud in viewers) + var/atom/movable/screen/movable/button = viewers[hud] + UpdateButtonIcon(button, status_only, force) + /datum/action/proc/UpdateButtonIcon(status_only = FALSE, force = FALSE) if(!button) return @@ -217,6 +224,8 @@ name = "Toggle Hood" /datum/action/item_action/toggle_firemode + icon_icon = 'icons/mob/actions/actions_items.dmi' + button_icon_state = "fireselect_no" name = "Toggle Firemode" /datum/action/item_action/rcl_col diff --git a/code/datums/components/fullauto.dm b/code/datums/components/fullauto.dm new file mode 100644 index 0000000000..4b9c25db91 --- /dev/null +++ b/code/datums/components/fullauto.dm @@ -0,0 +1,278 @@ +#define AUTOFIRE_MOUSEUP 0 +#define AUTOFIRE_MOUSEDOWN 1 + +/datum/component/automatic_fire + var/client/clicker + var/mob/living/shooter + var/atom/target + var/turf/target_loc //For dealing with locking on targets due to BYOND engine limitations (the mouse input only happening when mouse moves). + var/autofire_stat = AUTOFIRE_STAT_IDLE + var/mouse_parameters + var/autofire_shot_delay = 0.3 SECONDS //Time between individual shots. + var/mouse_status = AUTOFIRE_MOUSEUP //This seems hacky but there can be two MouseDown() without a MouseUp() in between if the user holds click and uses alt+tab, printscreen or similar. + + COOLDOWN_DECLARE(next_shot_cd) + +/datum/component/automatic_fire/Initialize(_autofire_shot_delay) + . = ..() + if(!isgun(parent)) + return COMPONENT_INCOMPATIBLE + var/obj/item/gun = parent + RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, .proc/wake_up) + RegisterSignal(parent, COMSIG_GUN_AUTOFIRE_SELECTED, .proc/wake_up) + RegisterSignal(parent, list(COMSIG_PARENT_PREQDELETED, COMSIG_ITEM_DROPPED, COMSIG_GUN_AUTOFIRE_DESELECTED), .proc/autofire_off) + if(_autofire_shot_delay) + autofire_shot_delay = _autofire_shot_delay + if(ismob(gun.loc)) + var/mob/user = gun.loc + wake_up(src, user) + + +/datum/component/automatic_fire/Destroy() + UnregisterSignal(parent, list(COMSIG_PARENT_PREQDELETED, COMSIG_ITEM_DROPPED, COMSIG_GUN_AUTOFIRE_DESELECTED)) + autofire_off() + return ..() + +/datum/component/automatic_fire/process(delta_time) + if(!(autofire_stat & AUTOFIRE_STAT_FIRING)) + STOP_PROCESSING(SSprojectiles, src) + return + + if(!COOLDOWN_FINISHED(src, next_shot_cd)) + return + + process_shot() + +/datum/component/automatic_fire/proc/wake_up(datum/source, mob/user, slot) + SIGNAL_HANDLER + + if(autofire_stat & (AUTOFIRE_STAT_ALERT)) + return //We've updated the firemode. No need for more. + if(autofire_stat & AUTOFIRE_STAT_FIRING) + stop_autofiring() //Let's stop shooting to avoid issues. + return + + var/obj/item/gun/G = parent + + if(iscarbon(user)) + var/mob/living/carbon/shooter = user + if(shooter.is_holding(parent) && G.fire_select == SELECT_FULLY_AUTOMATIC) + autofire_on(shooter.client) + else + autofire_off() + +// There is a gun and there is a user wielding it. The component now waits for the mouse click. +/datum/component/automatic_fire/proc/autofire_on(client/usercli) + SIGNAL_HANDLER + if(autofire_stat & (AUTOFIRE_STAT_ALERT|AUTOFIRE_STAT_FIRING)) + return + autofire_stat = AUTOFIRE_STAT_ALERT + clicker = usercli + shooter = clicker.mob + RegisterSignal(clicker, COMSIG_CLIENT_MOUSEDOWN, .proc/on_mouse_down) + RegisterSignal(shooter, COMSIG_MOB_CLIENT_LOGOUT, .proc/autofire_off) + if(!QDELETED(shooter)) + UnregisterSignal(shooter, COMSIG_MOB_CLIENT_LOGIN) + parent.RegisterSignal(src, COMSIG_AUTOFIRE_ONMOUSEDOWN, /obj/item/gun/.proc/autofire_bypass_check) + parent.RegisterSignal(parent, COMSIG_AUTOFIRE_SHOT, /obj/item/gun/.proc/do_autofire) + + +/datum/component/automatic_fire/proc/autofire_off(datum/source) + SIGNAL_HANDLER + if(autofire_stat & (AUTOFIRE_STAT_IDLE)) + return + if(autofire_stat & AUTOFIRE_STAT_FIRING) + stop_autofiring() + + autofire_stat = AUTOFIRE_STAT_IDLE + + if(!QDELETED(clicker)) + UnregisterSignal(clicker, list(COMSIG_CLIENT_MOUSEDOWN, COMSIG_CLIENT_MOUSEUP, COMSIG_CLIENT_MOUSEDRAG)) + mouse_status = AUTOFIRE_MOUSEUP //In regards to the component there's no click anymore to care about. + clicker = null + RegisterSignal(shooter, COMSIG_MOB_CLIENT_LOGIN, .proc/on_client_login) + if(!QDELETED(shooter)) + UnregisterSignal(shooter, COMSIG_MOB_CLIENT_LOGOUT) + shooter = null + parent.UnregisterSignal(parent, COMSIG_AUTOFIRE_SHOT) + parent.UnregisterSignal(src, COMSIG_AUTOFIRE_ONMOUSEDOWN) + +/datum/component/automatic_fire/proc/on_client_login(mob/source) + SIGNAL_HANDLER + if(!source.client) + return + if(source.is_holding(parent)) + autofire_on(source.client) + +/datum/component/automatic_fire/proc/on_mouse_down(client/source, atom/_target, turf/location, control, params) + var/list/modifiers = params2list(params) //If they're shift+clicking, for example, let's not have them accidentally shoot. + + if(LAZYACCESS(modifiers, SHIFT_CLICK)) + return + if(LAZYACCESS(modifiers, CTRL_CLICK)) + return + if(LAZYACCESS(modifiers, MIDDLE_CLICK)) + return + if(LAZYACCESS(modifiers, RIGHT_CLICK)) + return + if(LAZYACCESS(modifiers, ALT_CLICK)) + return + if(source.mob.in_throw_mode) + return + if(!isturf(source.mob.loc)) //No firing inside lockers and stuff. + return + if(get_dist(source.mob, _target) < 2) //Adjacent clicking. + return + + if(isnull(location)) //Clicking on a screen object. + if(_target.plane != CLICKCATCHER_PLANE) //The clickcatcher is a special case. We want the click to trigger then, under it. + return //If we click and drag on our worn backpack, for example, we want it to open instead. + _target = params2turf(modifiers["screen-loc"], get_turf(source.eye), source) + if(!_target) + CRASH("Failed to get the turf under clickcatcher") + + if(SEND_SIGNAL(src, COMSIG_AUTOFIRE_ONMOUSEDOWN, source, _target, location, control, params) & COMPONENT_AUTOFIRE_ONMOUSEDOWN_BYPASS) + return + + source.click_intercept_time = world.time //From this point onwards Click() will no longer be triggered. + + if(autofire_stat & (AUTOFIRE_STAT_IDLE)) + CRASH("on_mouse_down() called with [autofire_stat] autofire_stat") + if(autofire_stat & AUTOFIRE_STAT_FIRING) + stop_autofiring() //This can happen if we click and hold and then alt+tab, printscreen or other such action. MouseUp won't be called then and it will keep autofiring. + + target = _target + target_loc = get_turf(target) + mouse_parameters = params + start_autofiring() + + +//Dakka-dakka +/datum/component/automatic_fire/proc/start_autofiring() + if(autofire_stat == AUTOFIRE_STAT_FIRING) + return //Already pew-pewing. + autofire_stat = AUTOFIRE_STAT_FIRING + + clicker.mouse_override_icon = 'icons/effects/mouse_pointers/weapon_pointer.dmi' + clicker.mouse_pointer_icon = clicker.mouse_override_icon + + if(mouse_status == AUTOFIRE_MOUSEUP) //See mouse_status definition for the reason for this. + RegisterSignal(clicker, COMSIG_CLIENT_MOUSEUP, .proc/on_mouse_up) + mouse_status = AUTOFIRE_MOUSEDOWN + + RegisterSignal(shooter, COMSIG_MOB_SWAP_HANDS, .proc/stop_autofiring) + + if(isgun(parent)) + var/obj/item/gun/shoota = parent + if(!shoota.on_autofire_start(shooter)) //This is needed because the minigun has a do_after before firing and signals are async. + stop_autofiring() + return + if(autofire_stat != AUTOFIRE_STAT_FIRING) + return //Things may have changed while on_autofire_start() was being processed, due to do_after's sleep. + + if(!process_shot()) //First shot is processed instantly. + return //If it fails, such as when the gun is empty, then there's no need to schedule a second shot. + + START_PROCESSING(SSprojectiles, src) + RegisterSignal(clicker, COMSIG_CLIENT_MOUSEDRAG, .proc/on_mouse_drag) + + +/datum/component/automatic_fire/proc/on_mouse_up(datum/source, atom/object, turf/location, control, params) + SIGNAL_HANDLER + UnregisterSignal(clicker, COMSIG_CLIENT_MOUSEUP) + mouse_status = AUTOFIRE_MOUSEUP + if(autofire_stat == AUTOFIRE_STAT_FIRING) + stop_autofiring() + return COMPONENT_CLIENT_MOUSEUP_INTERCEPT + + +/datum/component/automatic_fire/proc/stop_autofiring(datum/source, atom/object, turf/location, control, params) + SIGNAL_HANDLER + switch(autofire_stat) + if(AUTOFIRE_STAT_IDLE, AUTOFIRE_STAT_ALERT) + return + STOP_PROCESSING(SSprojectiles, src) + autofire_stat = AUTOFIRE_STAT_ALERT + if(clicker) + clicker.mouse_override_icon = null + clicker.mouse_pointer_icon = clicker.mouse_override_icon + UnregisterSignal(clicker, COMSIG_CLIENT_MOUSEDRAG) + if(!QDELETED(shooter)) + UnregisterSignal(shooter, COMSIG_MOB_SWAP_HANDS) + target = null + target_loc = null + mouse_parameters = null + +/datum/component/automatic_fire/proc/on_mouse_drag(client/source, atom/src_object, atom/over_object, turf/src_location, turf/over_location, src_control, over_control, params) + SIGNAL_HANDLER + if(isnull(over_location)) //This happens when the mouse is over an inventory or screen object, or on entering deep darkness, for example. + var/list/modifiers = params2list(params) + var/new_target = params2turf(modifiers["screen-loc"], get_turf(source.eye), source) + mouse_parameters = params + if(!new_target) + if(QDELETED(target)) //No new target acquired, and old one was deleted, get us out of here. + stop_autofiring() + CRASH("on_mouse_drag failed to get the turf under screen object [over_object.type]. Old target was incidentally QDELETED.") + target = get_turf(target) //If previous target wasn't a turf, let's turn it into one to avoid locking onto a potentially moving target. + target_loc = target + CRASH("on_mouse_drag failed to get the turf under screen object [over_object.type]") + target = new_target + target_loc = new_target + return + target = over_object + target_loc = get_turf(over_object) + mouse_parameters = params + + +/datum/component/automatic_fire/proc/process_shot() + if(autofire_stat != AUTOFIRE_STAT_FIRING) + return + if(QDELETED(target) || get_turf(target) != target_loc) //Target moved or got destroyed since we last aimed. + target = target_loc //So we keep firing on the emptied tile until we move our mouse and find a new target. + if(get_dist(shooter, target) <= 0) + target = get_step(shooter, shooter.dir) //Shoot in the direction faced if the mouse is on the same tile as we are. + target_loc = target + else if(!in_view_range(shooter, target)) + stop_autofiring() //Elvis has left the building. + return FALSE + shooter.face_atom(target) + COOLDOWN_START(src, next_shot_cd, autofire_shot_delay) + if(SEND_SIGNAL(parent, COMSIG_AUTOFIRE_SHOT, target, shooter, mouse_parameters) & COMPONENT_AUTOFIRE_SHOT_SUCCESS) + return TRUE + stop_autofiring() + return FALSE + +// Gun procs. + +/obj/item/gun/proc/on_autofire_start(mob/living/shooter) + if(!can_shoot(shooter) || !can_trigger_gun(shooter) || semicd) + return FALSE + var/obj/item/bodypart/other_hand = shooter.has_hand_for_held_index(shooter.get_inactive_hand_index()) + if(weapon_weight == WEAPON_HEAVY && (shooter.get_inactive_held_item() || !other_hand)) + to_chat(shooter, "You need two hands to fire [src]!") + return FALSE + return TRUE + + +/obj/item/gun/proc/autofire_bypass_check(datum/source, client/clicker, atom/target, turf/location, control, params) + SIGNAL_HANDLER + if(clicker.mob.get_active_held_item() != src) + return COMPONENT_AUTOFIRE_ONMOUSEDOWN_BYPASS + + +/obj/item/gun/proc/do_autofire(datum/source, atom/target, mob/living/shooter, params) + SIGNAL_HANDLER_DOES_SLEEP + if(!can_shoot()) + shoot_with_empty_chamber(shooter) + return NONE + var/obj/item/gun/akimbo_gun = shooter.get_inactive_held_item() + var/bonus_spread = 0 + if(istype(akimbo_gun) && weapon_weight < WEAPON_MEDIUM) + if(akimbo_gun.weapon_weight < WEAPON_MEDIUM && akimbo_gun.can_trigger_gun(shooter)) + bonus_spread = dual_wield_spread + addtimer(CALLBACK(akimbo_gun, /obj/item/gun.proc/process_fire, target, shooter, TRUE, params, null, bonus_spread), 1) + process_fire(target, shooter, TRUE, params, null, bonus_spread) + return COMPONENT_AUTOFIRE_SHOT_SUCCESS //All is well, we can continue shooting. + +#undef AUTOFIRE_MOUSEUP +#undef AUTOFIRE_MOUSEDOWN diff --git a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm index b6de6c300a..c14b7b1d0a 100644 --- a/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm +++ b/code/game/gamemodes/dynamic/dynamic_rulesets_midround.dm @@ -86,6 +86,9 @@ return FALSE return TRUE +/datum/dynamic_ruleset/midround/from_ghosts/ready(forced = FALSE) + return ..() && (length(dead_players) + length(list_observers) >= required_applicants) + /datum/dynamic_ruleset/midround/from_ghosts/execute() var/list/possible_candidates = list() possible_candidates.Add(dead_players) diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index c0866ce165..2a0dbd316a 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -34,6 +34,8 @@ /obj/machinery/door/firedoor/Initialize(mapload) . = ..() CalculateAffectingAreas() + UpdateAdjacencyFlags() + /obj/machinery/door/firedoor/examine(mob/user) . = ..() @@ -53,6 +55,20 @@ var/area/A = I LAZYADD(A.firedoors, src) +/obj/machinery/door/firedoor/proc/UpdateAdjacencyFlags() + var/turf/T = get_turf(src) + if(flags_1 & ON_BORDER_1) + for(var/t in T.atmos_adjacent_turfs) + if(get_dir(loc, t) == dir) + var/turf/open/T2 = t + T.atmos_adjacent_turfs[T2] |= ATMOS_ADJACENT_FIRELOCK + T2.atmos_adjacent_turfs[T] |= ATMOS_ADJACENT_FIRELOCK + else + for(var/t in T.atmos_adjacent_turfs) + var/turf/open/T2 = t + T.atmos_adjacent_turfs[T2] |= ATMOS_ADJACENT_FIRELOCK + T2.atmos_adjacent_turfs[T] |= ATMOS_ADJACENT_FIRELOCK + /obj/machinery/door/firedoor/closed icon_state = "door_closed" opacity = TRUE diff --git a/code/game/machinery/posi_alert.dm b/code/game/machinery/posi_alert.dm new file mode 100644 index 0000000000..a2a67f22f9 --- /dev/null +++ b/code/game/machinery/posi_alert.dm @@ -0,0 +1,55 @@ +/obj/machinery/posialert + name = "automated positronic alert console" + desc = "A console that will ping when a positronic personality is available for download." + icon = 'icons/obj/machines/terminals.dmi' + icon_state = "posialert" + var/inuse = FALSE + var/online = TRUE + + var/obj/item/radio/radio + var/radio_key = /obj/item/encryptionkey/headset_sci + var/science_channel = "Science" + +/obj/machinery/posialert/Initialize(mapload, ndir, building) + . = ..() + radio = new(src) + radio.keyslot = new radio_key + radio.listening = 0 + radio.recalculateChannels() + if(building) + setDir(ndir) + pixel_x = (dir & 3)? 0 : (dir == 4 ? -32 : 32) + pixel_y = (dir & 3)? (dir ==1 ? -32 : 32) : 0 + + +/obj/machinery/posialert/Destroy() + QDEL_NULL(radio) + return ..() + +/obj/item/wallframe/posialert + name = "automated positronic alert console frame" + desc = "Used to build positronic alert consoles, just secure to the wall." + icon_state = "newscaster" + custom_materials = list(/datum/material/iron=14000, /datum/material/glass=8000) + result_path = /obj/machinery/posialert + +/obj/machinery/posialert/attack_hand(mob/living/user) + online = !online + to_chat(user, "You turn the posi-alert system [online ? "on" : "off"]!") + return + +/obj/machinery/posialert/attack_ghost(mob/user) + . = ..() + if(!online) + return + if(inuse) + return + inuse = TRUE + flick("posialertflash",src) + visible_message("There are positronic personalities available!") + radio.talk_into(src, "There are positronic personalities available!", science_channel) + playsound(loc, 'sound/machines/ping.ogg', 50) + addtimer(CALLBACK(src, .proc/liftcooldown), 300) + +/obj/machinery/posialert/proc/liftcooldown() + inuse = FALSE diff --git a/code/game/objects/items/devices/PDA/PDA.dm b/code/game/objects/items/devices/PDA/PDA.dm index 7fb1dd0065..5ff7bbc714 100644 --- a/code/game/objects/items/devices/PDA/PDA.dm +++ b/code/game/objects/items/devices/PDA/PDA.dm @@ -1232,6 +1232,51 @@ GLOBAL_LIST_EMPTY(PDAs) continue . += P +//borg pda stuff +/mob/living/silicon/robot/proc/cmd_send_pdamesg(mob/user) + var/list/plist = list() + var/list/namecounts = list() + + if(aiPDA.toff) + to_chat(user, "Turn on your receiver in order to send messages.") + return + + for (var/obj/item/pda/P in get_viewable_pdas()) + if (P == src) + continue + else if (P == aiPDA) + continue + + plist[avoid_assoc_duplicate_keys(P.owner, namecounts)] = P + + var/c = input(user, "Please select a PDA") as null|anything in sortList(plist) + + if (!c) + return + + var/selected = plist[c] + + if(aicamera.stored.len) + var/add_photo = input(user,"Do you want to attach a photo?","Photo","No") as null|anything in list("Yes","No") + if(add_photo=="Yes") + var/datum/picture/Pic = aicamera.selectpicture(user) + aiPDA.picture = Pic + + if(incapacitated()) + return + + aiPDA.create_message(src, selected) + + +/mob/living/silicon/robot/proc/cmd_show_message_log(mob/user) + if(incapacitated()) + return + if(!isnull(aiPDA)) + var/HTML = "