diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm index e413e2ddba..4b50904ea2 100644 --- a/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_syndicate_base1.dmm @@ -12,6 +12,10 @@ /turf/closed/wall/mineral/plastitanium, /area/ruin/powered/syndicate_lava_base) "ae" = ( +/obj/item/weapon/bombcore/large/underwall, +/turf/closed/wall/mineral/plastitanium, +/area/ruin/powered/syndicate_lava_base) +"af" = ( /obj/structure/closet/secure_closet/bar{ req_access = null; req_access_txt = "150" @@ -20,7 +24,7 @@ dir = 10 }, /area/ruin/powered/syndicate_lava_base) -"af" = ( +"ag" = ( /obj/structure/table/wood, /obj/item/weapon/reagent_containers/food/snacks/syndicake, /obj/item/weapon/reagent_containers/food/snacks/syndicake, @@ -32,7 +36,7 @@ }, /turf/open/floor/plasteel/podhatch, /area/ruin/powered/syndicate_lava_base) -"ag" = ( +"ah" = ( /obj/structure/table/wood, /obj/item/weapon/reagent_containers/food/snacks/salad/validsalad, /turf/open/floor/plasteel/podhatch{ @@ -41,7 +45,7 @@ dir = 6 }, /area/ruin/powered/syndicate_lava_base) -"ah" = ( +"ai" = ( /obj/structure/rack{ icon = 'icons/obj/stationobjs.dmi'; icon_state = "minibar_left"; @@ -50,7 +54,7 @@ /obj/item/weapon/reagent_containers/food/drinks/bottle/vodka, /turf/open/floor/wood, /area/ruin/powered/syndicate_lava_base) -"ai" = ( +"aj" = ( /obj/structure/rack{ icon = 'icons/obj/stationobjs.dmi'; icon_state = "minibar_right"; @@ -59,7 +63,7 @@ /obj/item/weapon/reagent_containers/food/drinks/bottle/gin, /turf/open/floor/wood, /area/ruin/powered/syndicate_lava_base) -"aj" = ( +"ak" = ( /obj/structure/dresser, /obj/structure/mirror{ desc = "Mirror mirror on the wall, who is the most robust of them all?"; @@ -67,40 +71,40 @@ }, /turf/open/floor/plasteel/vault, /area/ruin/powered/syndicate_lava_base) -"ak" = ( +"al" = ( /obj/item/weapon/twohanded/required/kirbyplants{ icon_state = "plant-21"; layer = 4.1 }, /turf/open/floor/plasteel/vault, /area/ruin/powered/syndicate_lava_base) -"al" = ( +"am" = ( /obj/item/weapon/twohanded/required/kirbyplants{ icon_state = "plant-22" }, /turf/open/floor/plasteel/vault, /area/ruin/powered/syndicate_lava_base) -"am" = ( +"an" = ( /obj/structure/table/wood, /obj/item/weapon/clipboard, /obj/item/toy/figure/syndie, /turf/open/floor/plasteel/vault, /area/ruin/powered/syndicate_lava_base) -"an" = ( +"ao" = ( /obj/machinery/portable_atmospherics/canister/air, /turf/open/floor/plasteel/podhatch{ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"ao" = ( +"ap" = ( /turf/open/floor/plasteel/black, /area/ruin/powered/syndicate_lava_base) -"ap" = ( +"aq" = ( /turf/open/floor/plasteel/vault{ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"aq" = ( +"ar" = ( /obj/item/stack/sheet/mineral/plastitanium{ amount = 30 }, @@ -112,10 +116,10 @@ dir = 9 }, /area/ruin/powered/syndicate_lava_base) -"ar" = ( +"as" = ( /turf/open/floor/wood, /area/ruin/powered/syndicate_lava_base) -"as" = ( +"at" = ( /obj/effect/mob_spawn/human/lavaland_syndicate{ tag = "icon-sleeper_s (EAST)"; icon_state = "sleeper_s"; @@ -123,10 +127,10 @@ }, /turf/open/floor/plasteel/grimy, /area/ruin/powered/syndicate_lava_base) -"at" = ( +"au" = ( /turf/open/floor/plasteel/grimy, /area/ruin/powered/syndicate_lava_base) -"au" = ( +"av" = ( /obj/effect/mob_spawn/human/lavaland_syndicate{ tag = "icon-sleeper_s (WEST)"; icon_state = "sleeper_s"; @@ -134,7 +138,7 @@ }, /turf/open/floor/plasteel/grimy, /area/ruin/powered/syndicate_lava_base) -"av" = ( +"aw" = ( /obj/structure/reagent_dispensers/watertank, /turf/open/floor/plasteel/podhatch{ tag = "icon-podhatch (EAST)"; @@ -142,7 +146,7 @@ dir = 4 }, /area/ruin/powered/syndicate_lava_base) -"aw" = ( +"ax" = ( /obj/item/stack/cable_coil/white, /obj/item/stack/cable_coil/white, /obj/item/stack/packageWrap, @@ -152,17 +156,6 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"ax" = ( -/obj/structure/table/wood, -/obj/item/ammo_box/magazine/m10mm, -/obj/item/ammo_box/magazine/m10mm, -/obj/item/ammo_box/magazine/m10mm, -/obj/item/ammo_box/magazine/m10mm, -/obj/item/ammo_box/magazine/sniper_rounds, -/obj/item/ammo_box/magazine/sniper_rounds, -/obj/item/ammo_box/magazine/sniper_rounds, -/turf/open/floor/plasteel/grimy, -/area/ruin/powered/syndicate_lava_base) "ay" = ( /obj/structure/table/wood, /obj/item/ammo_box/magazine/m10mm, @@ -172,12 +165,23 @@ /obj/item/ammo_box/magazine/sniper_rounds, /obj/item/ammo_box/magazine/sniper_rounds, /obj/item/ammo_box/magazine/sniper_rounds, +/turf/open/floor/plasteel/grimy, +/area/ruin/powered/syndicate_lava_base) +"az" = ( +/obj/structure/table/wood, +/obj/item/ammo_box/magazine/m10mm, +/obj/item/ammo_box/magazine/m10mm, +/obj/item/ammo_box/magazine/m10mm, +/obj/item/ammo_box/magazine/m10mm, +/obj/item/ammo_box/magazine/sniper_rounds, +/obj/item/ammo_box/magazine/sniper_rounds, +/obj/item/ammo_box/magazine/sniper_rounds, /obj/item/ammo_box/magazine/sniper_rounds, /obj/item/ammo_box/magazine/sniper_rounds, /obj/item/ammo_box/magazine/sniper_rounds, /turf/open/floor/plasteel/grimy, /area/ruin/powered/syndicate_lava_base) -"az" = ( +"aA" = ( /obj/structure/reagent_dispensers/fueltank, /turf/open/floor/plasteel/podhatch{ tag = "icon-podhatch (SOUTHEAST)"; @@ -185,7 +189,7 @@ dir = 6 }, /area/ruin/powered/syndicate_lava_base) -"aA" = ( +"aB" = ( /obj/item/stack/sheet/metal{ amount = 50 }, @@ -198,7 +202,7 @@ dir = 10 }, /area/ruin/powered/syndicate_lava_base) -"aB" = ( +"aC" = ( /obj/structure/table/wood, /obj/item/weapon/paper_bin, /obj/item/weapon/pen, @@ -206,18 +210,18 @@ icon_state = "wood-broken4" }, /area/ruin/powered/syndicate_lava_base) -"aC" = ( +"aD" = ( /obj/structure/table/wood, /obj/item/weapon/storage/box/drinkingglasses, /turf/open/floor/wood, /area/ruin/powered/syndicate_lava_base) -"aD" = ( +"aE" = ( /obj/structure/table/wood, /obj/item/toy/nuke, /obj/item/weapon/book/manual/nuclear, /turf/open/floor/wood, /area/ruin/powered/syndicate_lava_base) -"aE" = ( +"aF" = ( /obj/structure/table/wood, /obj/item/weapon/lighter{ pixel_y = 3 @@ -225,18 +229,18 @@ /obj/item/weapon/storage/fancy/cigarettes/cigpack_syndicate, /turf/open/floor/wood, /area/ruin/powered/syndicate_lava_base) -"aF" = ( +"aG" = ( /obj/structure/table/wood, /obj/item/weapon/storage/fancy/donut_box, /turf/open/floor/wood, /area/ruin/powered/syndicate_lava_base) -"aG" = ( +"aH" = ( /obj/structure/extinguisher_cabinet{ pixel_x = 26 }, /turf/open/floor/wood, /area/ruin/powered/syndicate_lava_base) -"aH" = ( +"aI" = ( /obj/effect/mob_spawn/human/lavaland_syndicate/comms{ tag = "icon-sleeper_s (EAST)"; icon_state = "sleeper_s"; @@ -244,26 +248,26 @@ }, /turf/open/floor/plasteel/grimy, /area/ruin/powered/syndicate_lava_base) -"aI" = ( +"aJ" = ( /obj/structure/sign/nosmoking_2, /turf/closed/wall/mineral/plastitanium, /area/ruin/powered/syndicate_lava_base) -"aJ" = ( +"aK" = ( /obj/structure/closet/crate/bin, /obj/item/trash/syndi_cakes, /turf/open/floor/plasteel/black, /area/ruin/powered/syndicate_lava_base) -"aK" = ( +"aL" = ( /obj/structure/chair/stool/bar, /turf/open/floor/plasteel/vault{ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"aL" = ( +"aM" = ( /obj/structure/chair/stool/bar, /turf/open/floor/plasteel/black, /area/ruin/powered/syndicate_lava_base) -"aM" = ( +"aN" = ( /obj/structure/table/wood, /obj/item/weapon/lipstick/random{ pixel_x = 3; @@ -279,12 +283,12 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"aN" = ( +"aO" = ( /turf/open/floor/plasteel/vault{ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"aO" = ( +"aP" = ( /obj/structure/dresser, /obj/structure/mirror{ desc = "Mirror mirror on the wall, who is the most robust of them all?"; @@ -294,13 +298,13 @@ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"aP" = ( +"aQ" = ( /obj/item/target, /turf/open/floor/plasteel/vault{ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"aQ" = ( +"aR" = ( /obj/structure/closet/emcloset{ anchored = 1 }, @@ -311,7 +315,7 @@ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"aR" = ( +"aS" = ( /obj/item/weapon/twohanded/required/kirbyplants{ icon_state = "plant-21"; layer = 4.1 @@ -320,9 +324,6 @@ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"aS" = ( -/turf/open/floor/plasteel/black, -/area/ruin/powered/syndicate_lava_base) "aT" = ( /obj/machinery/door/airlock/hatch{ name = "Dormitories"; @@ -402,11 +403,6 @@ }, /area/ruin/powered/syndicate_lava_base) "bb" = ( -/turf/open/floor/plasteel/vault{ - dir = 5 - }, -/area/ruin/powered/syndicate_lava_base) -"bc" = ( /obj/item/weapon/twohanded/required/kirbyplants{ icon_state = "plant-22" }, @@ -414,24 +410,24 @@ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"bd" = ( +"bc" = ( /obj/structure/bookcase/random, /turf/open/floor/plasteel/vault{ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"be" = ( +"bd" = ( /obj/item/weapon/twohanded/required/kirbyplants{ icon_state = "plant-21"; layer = 4.1 }, /turf/open/floor/plasteel/black, /area/ruin/powered/syndicate_lava_base) -"bf" = ( +"be" = ( /obj/structure/bookcase/random, /turf/open/floor/plasteel/black, /area/ruin/powered/syndicate_lava_base) -"bg" = ( +"bf" = ( /obj/structure/toilet{ tag = "icon-toilet00 (WEST)"; icon_state = "toilet00"; @@ -441,7 +437,7 @@ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"bh" = ( +"bg" = ( /obj/machinery/door/airlock/hatch{ name = "Lounge"; req_access_txt = "150" @@ -450,13 +446,13 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"bi" = ( +"bh" = ( /obj/machinery/chem_dispenser, /turf/open/floor/plasteel/podhatch{ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"bj" = ( +"bi" = ( /obj/structure/table/reinforced, /obj/item/weapon/reagent_containers/glass/beaker/large, /obj/item/weapon/reagent_containers/glass/beaker, @@ -474,7 +470,7 @@ dir = 1 }, /area/ruin/powered/syndicate_lava_base) -"bk" = ( +"bj" = ( /obj/machinery/chem_master, /turf/open/floor/plasteel/podhatch{ tag = "icon-podhatch (EAST)"; @@ -482,7 +478,7 @@ dir = 4 }, /area/ruin/powered/syndicate_lava_base) -"bl" = ( +"bk" = ( /obj/structure/noticeboard{ pixel_y = 32 }, @@ -495,7 +491,7 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"bm" = ( +"bl" = ( /obj/structure/table/reinforced, /obj/item/weapon/clipboard, /obj/item/weapon/folder/white, @@ -509,7 +505,7 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"bn" = ( +"bm" = ( /obj/structure/table/reinforced, /obj/item/weapon/storage/box/beakers{ pixel_x = 3; @@ -522,17 +518,17 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"bo" = ( +"bn" = ( /turf/open/floor/plasteel/podhatch{ dir = 9 }, /area/ruin/powered/syndicate_lava_base) -"bp" = ( +"bo" = ( /turf/open/floor/plasteel/podhatch{ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"bq" = ( +"bp" = ( /obj/structure/table/reinforced, /obj/machinery/reagentgrinder{ desc = "Used to grind things up into raw materials and liquids."; @@ -543,7 +539,7 @@ }, /turf/open/floor/plasteel/podhatch/corner, /area/ruin/powered/syndicate_lava_base) -"br" = ( +"bq" = ( /obj/structure/reagent_dispensers/virusfood{ pixel_y = 32 }, @@ -555,7 +551,7 @@ }, /turf/open/floor/plasteel/podhatch, /area/ruin/powered/syndicate_lava_base) -"bs" = ( +"br" = ( /obj/structure/extinguisher_cabinet{ pixel_x = 0; pixel_y = 32 @@ -563,7 +559,7 @@ /obj/machinery/computer/pandemic, /turf/open/floor/plasteel/podhatch, /area/ruin/powered/syndicate_lava_base) -"bt" = ( +"bs" = ( /obj/structure/table/reinforced, /obj/item/weapon/storage/box/beakers{ pixel_x = 3; @@ -572,7 +568,7 @@ /obj/item/weapon/storage/box/syringes, /turf/open/floor/plasteel/podhatch, /area/ruin/powered/syndicate_lava_base) -"bu" = ( +"bt" = ( /obj/structure/bed/roller, /obj/machinery/iv_drip, /obj/item/weapon/reagent_containers/blood/random, @@ -582,49 +578,49 @@ dir = 6 }, /area/ruin/powered/syndicate_lava_base) -"bv" = ( +"bu" = ( /obj/structure/grille, /obj/structure/window/reinforced/fulltile, /turf/open/floor/plating, /area/ruin/powered/syndicate_lava_base) -"bw" = ( +"bv" = ( /mob/living/carbon/monkey, /turf/open/floor/plasteel/vault{ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"bx" = ( +"bw" = ( /obj/structure/bed/roller, /turf/open/floor/plasteel/vault{ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"by" = ( +"bx" = ( /obj/structure/grille, /obj/structure/window/reinforced/fulltile, /turf/open/floor/plasteel/vault{ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"bz" = ( +"by" = ( /mob/living/carbon/monkey, /turf/open/floor/plasteel/vault{ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"bA" = ( +"bz" = ( /obj/structure/window/reinforced, /turf/open/floor/plasteel/vault{ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"bB" = ( +"bA" = ( /obj/machinery/door/window/brigdoor, /turf/open/floor/plasteel/vault{ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"bC" = ( +"bB" = ( /obj/machinery/chem_heater, /obj/structure/extinguisher_cabinet{ pixel_x = -26 @@ -633,13 +629,13 @@ dir = 10 }, /area/ruin/powered/syndicate_lava_base) -"bD" = ( +"bC" = ( /obj/structure/chair/office/dark{ dir = 1 }, /turf/open/floor/plasteel/podhatch, /area/ruin/powered/syndicate_lava_base) -"bE" = ( +"bD" = ( /obj/structure/closet/crate/bin, /turf/open/floor/plasteel/podhatch{ tag = "icon-podhatch (SOUTHEAST)"; @@ -647,10 +643,10 @@ dir = 6 }, /area/ruin/powered/syndicate_lava_base) -"bF" = ( +"bE" = ( /turf/open/floor/plasteel/vault, /area/ruin/powered/syndicate_lava_base) -"bG" = ( +"bF" = ( /obj/item/device/assembly/igniter, /obj/item/device/assembly/igniter, /obj/item/device/assembly/igniter, @@ -671,7 +667,7 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"bH" = ( +"bG" = ( /obj/structure/table/reinforced, /obj/item/weapon/book/manual/wiki/infections, /obj/item/stack/sheet/mineral/silver{ @@ -683,7 +679,7 @@ dir = 4 }, /area/ruin/powered/syndicate_lava_base) -"bI" = ( +"bH" = ( /obj/structure/chair/office/dark{ dir = 8 }, @@ -691,14 +687,14 @@ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"bJ" = ( +"bI" = ( /obj/machinery/door/airlock/hatch{ name = "Monkey Pen"; req_access_txt = "150" }, /turf/open/floor/plasteel/black, /area/ruin/powered/syndicate_lava_base) -"bK" = ( +"bJ" = ( /obj/structure/table/reinforced, /obj/item/weapon/gun/ballistic/automatic/c20r/toy/unrestricted, /obj/item/weapon/gun/ballistic/automatic/c20r/toy/unrestricted, @@ -706,7 +702,7 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"bL" = ( +"bK" = ( /obj/item/weapon/twohanded/required/kirbyplants{ icon_state = "plant-21"; layer = 4.1 @@ -715,7 +711,7 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"bM" = ( +"bL" = ( /obj/structure/table/reinforced, /obj/item/clothing/gloves/color/latex, /obj/item/clothing/gloves/color/latex, @@ -729,14 +725,22 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"bN" = ( -/obj/machinery/smartfridge/chemistry/virology/preloaded, +"bM" = ( +/obj/machinery/smartfridge/chemistry/virology, /turf/open/floor/plasteel/podhatch{ tag = "icon-podhatch (EAST)"; icon_state = "podhatch"; dir = 4 }, /area/ruin/powered/syndicate_lava_base) +"bN" = ( +/obj/machinery/vending/toyliberationstation{ + req_access_txt = "150" + }, +/turf/open/floor/plasteel/vault{ + dir = 5 + }, +/area/ruin/powered/syndicate_lava_base) "bO" = ( /obj/machinery/iv_drip, /obj/item/weapon/reagent_containers/blood/random, @@ -925,15 +929,10 @@ /turf/closed/wall/mineral/plastitanium, /area/ruin/powered/syndicate_lava_base) "cj" = ( -/turf/open/floor/plasteel/podhatch{ - dir = 8 - }, -/area/ruin/powered/syndicate_lava_base) -"ck" = ( /obj/structure/sign/biohazard, /turf/closed/wall/mineral/plastitanium, /area/ruin/powered/syndicate_lava_base) -"cl" = ( +"ck" = ( /obj/machinery/door/airlock/hatch{ name = "Virology Lab"; req_access_txt = "150" @@ -942,7 +941,7 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"cm" = ( +"cl" = ( /obj/structure/rack, /obj/item/ammo_box/foambox{ pixel_x = -3; @@ -957,7 +956,7 @@ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"cn" = ( +"cm" = ( /obj/item/weapon/twohanded/required/kirbyplants{ icon_state = "plant-22" }, @@ -965,28 +964,28 @@ dir = 9 }, /area/ruin/powered/syndicate_lava_base) -"co" = ( +"cn" = ( /turf/open/floor/plasteel/podhatch{ tag = "icon-podhatch (NORTH)"; icon_state = "podhatch"; dir = 1 }, /area/ruin/powered/syndicate_lava_base) -"cp" = ( +"co" = ( /turf/open/floor/plasteel/podhatch/corner{ tag = "icon-podhatchcorner (EAST)"; icon_state = "podhatchcorner"; dir = 4 }, /area/ruin/powered/syndicate_lava_base) -"cq" = ( +"cp" = ( /turf/open/floor/plasteel/podhatch/corner{ tag = "icon-podhatchcorner (WEST)"; icon_state = "podhatchcorner"; dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"cr" = ( +"cq" = ( /obj/item/weapon/twohanded/required/kirbyplants{ icon_state = "plant-21"; layer = 4.1 @@ -995,13 +994,13 @@ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"cs" = ( +"cr" = ( /obj/structure/grille, /obj/structure/window/reinforced/fulltile, /obj/structure/sign/bluecross_2, /turf/open/floor/plating, /area/ruin/powered/syndicate_lava_base) -"ct" = ( +"cs" = ( /obj/structure/table, /obj/item/weapon/storage/firstaid/regular{ pixel_x = 3; @@ -1014,7 +1013,7 @@ }, /turf/open/floor/plasteel/vault, /area/ruin/powered/syndicate_lava_base) -"cu" = ( +"ct" = ( /obj/machinery/sleeper/syndie{ dir = 8 }, @@ -1022,7 +1021,7 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"cv" = ( +"cu" = ( /obj/structure/closet/crate/secure, /obj/item/target, /obj/item/target, @@ -1036,41 +1035,38 @@ dir = 6 }, /area/ruin/powered/syndicate_lava_base) -"cw" = ( +"cv" = ( /turf/open/floor/plasteel/podhatch{ dir = 10 }, /area/ruin/powered/syndicate_lava_base) -"cx" = ( +"cw" = ( /turf/open/floor/plasteel/podhatch, /area/ruin/powered/syndicate_lava_base) -"cy" = ( +"cx" = ( /obj/structure/extinguisher_cabinet{ pixel_y = -32 }, /turf/open/floor/plasteel/podhatch, /area/ruin/powered/syndicate_lava_base) -"cz" = ( -/turf/open/floor/plasteel/podhatch, -/area/ruin/powered/syndicate_lava_base) -"cA" = ( +"cy" = ( /turf/open/floor/plasteel/podhatch/corner{ tag = "icon-podhatchcorner (NORTH)"; icon_state = "podhatchcorner"; dir = 1 }, /area/ruin/powered/syndicate_lava_base) -"cB" = ( +"cz" = ( /turf/open/floor/plasteel/podhatch/corner, /area/ruin/powered/syndicate_lava_base) -"cC" = ( +"cA" = ( /turf/open/floor/plasteel/podhatch{ tag = "icon-podhatch (SOUTHEAST)"; icon_state = "podhatch"; dir = 6 }, /area/ruin/powered/syndicate_lava_base) -"cD" = ( +"cB" = ( /obj/machinery/door/airlock/hatch{ name = "Infirmary"; req_access_txt = "150" @@ -1079,7 +1075,7 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"cE" = ( +"cC" = ( /obj/structure/bed/roller, /obj/machinery/iv_drip, /obj/item/weapon/reagent_containers/blood/random, @@ -1087,7 +1083,7 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"cF" = ( +"cD" = ( /obj/structure/grille, /obj/structure/window/reinforced/fulltile, /obj/machinery/door/poddoor/preopen{ @@ -1096,7 +1092,7 @@ }, /turf/open/floor/plating, /area/ruin/powered/syndicate_lava_base) -"cG" = ( +"cE" = ( /obj/machinery/door/airlock/hatch{ name = "Experimentation Room"; req_access_txt = "150" @@ -1105,7 +1101,7 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"cH" = ( +"cF" = ( /obj/machinery/door/airlock/hatch{ name = "Telecommunications Control"; req_access_txt = "150" @@ -1114,10 +1110,10 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"cI" = ( +"cG" = ( /turf/open/floor/engine, /area/ruin/powered/syndicate_lava_base) -"cJ" = ( +"cH" = ( /obj/structure/noticeboard{ pixel_y = 32 }, @@ -1125,7 +1121,7 @@ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"cK" = ( +"cI" = ( /obj/structure/table, /obj/item/weapon/storage/toolbox/syndicate, /obj/item/device/multitool, @@ -1133,7 +1129,7 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"cL" = ( +"cJ" = ( /obj/item/weapon/surgicaldrill, /obj/item/weapon/circular_saw, /obj/structure/table/reinforced, @@ -1141,7 +1137,7 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"cM" = ( +"cK" = ( /obj/structure/sink{ dir = 4; icon_state = "sink"; @@ -1155,7 +1151,7 @@ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"cN" = ( +"cL" = ( /obj/item/stack/cable_coil/white{ pixel_x = 3; pixel_y = 3 @@ -1167,14 +1163,14 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"cO" = ( +"cM" = ( /obj/structure/table/reinforced, /obj/item/device/flashlight/lamp, /turf/open/floor/plasteel/vault{ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"cP" = ( +"cN" = ( /obj/structure/table/reinforced, /obj/item/device/radio/intercom{ broadcasting = 0; @@ -1188,19 +1184,19 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"cQ" = ( +"cO" = ( /obj/machinery/computer/camera_advanced, /turf/open/floor/plasteel/vault{ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"cR" = ( +"cP" = ( /obj/structure/filingcabinet/chestdrawer, /turf/open/floor/plasteel/vault{ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"cS" = ( +"cQ" = ( /obj/item/weapon/cautery, /obj/item/weapon/scalpel, /obj/structure/table/reinforced, @@ -1208,14 +1204,14 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"cT" = ( +"cR" = ( /obj/structure/table/optable, /obj/item/weapon/surgical_drapes, /turf/open/floor/plasteel/vault{ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"cU" = ( +"cS" = ( /obj/item/weapon/retractor, /obj/item/weapon/hemostat, /obj/structure/table/reinforced, @@ -1223,7 +1219,7 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"cV" = ( +"cT" = ( /obj/structure/sign/nosmoking_2{ pixel_x = 32 }, @@ -1231,7 +1227,7 @@ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"cW" = ( +"cU" = ( /obj/item/weapon/twohanded/required/kirbyplants{ icon_state = "plant-22" }, @@ -1242,7 +1238,7 @@ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"cX" = ( +"cV" = ( /obj/structure/table/reinforced, /obj/item/device/radio/intercom{ broadcasting = 1; @@ -1256,13 +1252,13 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"cY" = ( +"cW" = ( /obj/structure/sign/fire{ pixel_x = -32 }, /turf/open/floor/engine, /area/ruin/powered/syndicate_lava_base) -"cZ" = ( +"cX" = ( /obj/structure/table/reinforced, /obj/item/device/assembly/signaler, /obj/item/device/assembly/signaler, @@ -1273,7 +1269,7 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"da" = ( +"cY" = ( /obj/structure/table/reinforced, /obj/item/stack/sheet/plasteel{ amount = 15 @@ -1284,13 +1280,13 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"db" = ( +"cZ" = ( /obj/structure/filingcabinet/security, /turf/open/floor/plasteel/vault{ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"dc" = ( +"da" = ( /obj/structure/table/reinforced, /obj/item/weapon/paper_bin, /obj/item/weapon/pen, @@ -1298,27 +1294,27 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"dd" = ( +"db" = ( /obj/machinery/computer/message_monitor, /obj/item/weapon/paper/monitorkey, /turf/open/floor/plasteel/vault{ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"de" = ( +"dc" = ( /turf/open/floor/plasteel/vault{ tag = "icon-vault (NORTHEAST)"; dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"df" = ( +"dd" = ( /obj/effect/baseturf_helper, /turf/open/floor/plasteel/vault{ tag = "icon-vault (NORTHEAST)"; dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"dg" = ( +"de" = ( /obj/machinery/button/door{ id = "lavalandsyndi"; name = "Syndicate Experimentor Lockdown Control"; @@ -1327,7 +1323,7 @@ }, /turf/open/floor/engine, /area/ruin/powered/syndicate_lava_base) -"dh" = ( +"df" = ( /obj/machinery/button/door{ id = "lavalandsyndi"; name = "Syndicate Experimentor Lockdown Control"; @@ -1338,7 +1334,7 @@ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"di" = ( +"dg" = ( /obj/item/stack/sheet/mineral/plastitanium{ amount = 30 }, @@ -1350,16 +1346,16 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"dj" = ( +"dh" = ( /obj/structure/filingcabinet/medical, /turf/open/floor/plasteel/vault{ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"dk" = ( +"di" = ( /turf/open/floor/circuit/green, /area/ruin/powered/syndicate_lava_base) -"dl" = ( +"dj" = ( /obj/machinery/door/poddoor/preopen{ id = "lavalandsyndi"; name = "Syndicate Research Experimentor Shutters" @@ -1372,7 +1368,7 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"dm" = ( +"dk" = ( /obj/item/stack/sheet/metal{ amount = 50 }, @@ -1389,7 +1385,16 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"dn" = ( +"dl" = ( +/obj/machinery/door/airlock/hatch{ + name = "Self Destruct Control"; + req_access_txt = "150" + }, +/turf/open/floor/plasteel/vault{ + dir = 8 + }, +/area/ruin/powered/syndicate_lava_base) +"dm" = ( /obj/machinery/telecomms/relay/preset/ruskie{ use_power = 0 }, @@ -1398,7 +1403,7 @@ dir = 5 }, /area/ruin/powered/syndicate_lava_base) -"do" = ( +"dn" = ( /obj/machinery/door/airlock/hatch{ name = "Syndicate Recon Outpost"; req_access_txt = "150" @@ -1408,6 +1413,9 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) +"do" = ( +/turf/open/floor/circuit/red, +/area/ruin/powered/syndicate_lava_base) "dp" = ( /obj/machinery/door/airlock/hatch{ name = "Monkey Pen"; @@ -1434,6 +1442,10 @@ }, /area/ruin/powered/syndicate_lava_base) "ds" = ( +/obj/machinery/syndicatebomb/self_destruct, +/turf/open/floor/circuit/red, +/area/ruin/powered/syndicate_lava_base) +"dt" = ( /obj/structure/bed/roller, /obj/machinery/iv_drip, /mob/living/carbon/monkey, @@ -1441,85 +1453,12 @@ dir = 8 }, /area/ruin/powered/syndicate_lava_base) -"dt" = ( +"du" = ( /obj/structure/sign/securearea{ pixel_y = 32 }, /turf/open/floor/plating/lava/smooth/lava_land_surface, /area/lavaland/surface/outdoors) -"du" = ( -/obj/item/weapon/bombcore/large/underwall, -/turf/closed/wall/mineral/plastitanium, -/area/ruin/powered/syndicate_lava_base) -"dv" = ( -/obj/item/weapon/bombcore/large/underwall, -/turf/closed/wall/mineral/plastitanium, -/area/ruin/powered/syndicate_lava_base) -"dw" = ( -/obj/item/weapon/bombcore/large/underwall, -/turf/closed/wall/mineral/plastitanium, -/area/ruin/powered/syndicate_lava_base) -"dx" = ( -/obj/item/weapon/bombcore/large/underwall, -/turf/closed/wall/mineral/plastitanium, -/area/ruin/powered/syndicate_lava_base) -"dy" = ( -/obj/item/weapon/bombcore/large/underwall, -/turf/closed/wall/mineral/plastitanium, -/area/ruin/powered/syndicate_lava_base) -"dz" = ( -/obj/item/weapon/bombcore/large/underwall, -/turf/closed/wall/mineral/plastitanium, -/area/ruin/powered/syndicate_lava_base) -"dA" = ( -/obj/item/weapon/bombcore/large/underwall, -/turf/closed/wall/mineral/plastitanium, -/area/ruin/powered/syndicate_lava_base) -"dB" = ( -/obj/item/weapon/bombcore/large/underwall, -/turf/closed/wall/mineral/plastitanium, -/area/ruin/powered/syndicate_lava_base) -"dC" = ( -/obj/item/weapon/bombcore/large/underwall, -/turf/closed/wall/mineral/plastitanium, -/area/ruin/powered/syndicate_lava_base) -"dD" = ( -/obj/item/weapon/bombcore/large/underwall, -/turf/closed/wall/mineral/plastitanium, -/area/ruin/powered/syndicate_lava_base) -"dE" = ( -/obj/item/weapon/bombcore/large/underwall, -/turf/closed/wall/mineral/plastitanium, -/area/ruin/powered/syndicate_lava_base) -"dF" = ( -/obj/machinery/door/airlock/hatch{ - name = "Self Destruct Control"; - req_access_txt = "150" - }, -/turf/open/floor/plasteel/vault{ - dir = 8 - }, -/area/ruin/powered/syndicate_lava_base) -"dG" = ( -/turf/open/floor/circuit/red, -/area/ruin/powered/syndicate_lava_base) -"dH" = ( -/obj/item/weapon/bombcore/large/underwall, -/turf/closed/wall/mineral/plastitanium, -/area/ruin/powered/syndicate_lava_base) -"dI" = ( -/turf/open/floor/circuit/red, -/area/ruin/powered/syndicate_lava_base) -"dJ" = ( -/obj/machinery/syndicatebomb/self_destruct, -/turf/open/floor/circuit/red, -/area/ruin/powered/syndicate_lava_base) -"dK" = ( -/turf/open/floor/circuit/red, -/area/ruin/powered/syndicate_lava_base) -"dL" = ( -/turf/open/floor/circuit/red, -/area/ruin/powered/syndicate_lava_base) (1,1,1) = {" aa @@ -1831,7 +1770,7 @@ ad ad ad ad -dD +ae ad ad ac @@ -1856,23 +1795,23 @@ ad ad ad ad -dw +ae ad ad ad ad ad ad -dA +ae ad ad -cI -cI -cI -cY -cI -cI -cI +cG +cG +cG +cW +cG +cG +cG ad ac ab @@ -1892,27 +1831,27 @@ ab ab ab ad -ap -ap -ap +aq +aq +aq aY -ap +aq aY -bA -bK -ap +bz +bJ +bN bV cf -cm -cv +cl +cu ad -cI -cI -cI -cI -cI -cI -cI +cG +cG +cG +cG +cG +cG +cG ad ab ab @@ -1932,27 +1871,27 @@ ab ab ab ad -ap -aP -aN -aN -aN -aN -bB -aN -ap -ap +aq +aQ +aO +aO +aO +aO +bA +aO +aq +aq cg -ap -ap -cF -cI -cI -cI -cI -cI -cI -cI +aq +aq +cD +cG +cG +cG +cG +cG +cG +cG ad ab ab @@ -1972,27 +1911,27 @@ ab ac ac ad -ap -ap -ap +aq +aq +aq aZ -ap +aq aZ -bA -bL -ap +bz +bK +aq bW ad -aR -ap +aS +aq ad -cI -cI -cI -cI -cI -cI -cI +cG +cG +cG +cG +cG +cG +cG ad ab ab @@ -2023,16 +1962,16 @@ ad ad ad ad -bv +bu cg ad -cI -cI -cI -cI -cI -cI -cI +cG +cG +cG +cG +cG +cG +cG ad ac ab @@ -2049,30 +1988,30 @@ ab ab ab ad -an -av -az -aI -aQ +ao +aw +aA +aJ +aR aU ba ad -bi -bC -aR +bh +bB +aS bO bO cf -cn -cw +cm +cv ad -cI -cI -cI -cI -cI -cI -cI +cG +cG +cG +cG +cG +cG +cG ad ac ab @@ -2089,30 +2028,30 @@ ab ab ab ad -ao ap -ao +aq ap +aq +aq ap -ao -ap +aq ad -bj -bD -ap -ao +bi +bC +aq ap +aq ch -co -cz +cn +cw ad -cI -cI -cI -cI -dg -cI -cI +cG +cG +cG +cG +de +cG +cG ad ac ac @@ -2129,31 +2068,31 @@ ab ab ac ad +aq ap -ao +aq ap -ao -ao ap -ao +aq +ap ad -bk -bE -ap -ap -ap +bj +bD +aq +aq +aq ci -co -cy +cn +cx ad cf -cF -cF -cF +cD +cD +cD ad -dl +dj ad -dH +ae ad ad ab @@ -2169,32 +2108,32 @@ ab ab ac ad +ar +ax +aB +ad +aS aq -aw -aA +bb ad -aR -ap -bc -ad -bl -bF -ap +bk +bE +aq bP bX ad -co -cz -dB -aR -cN -bG -cZ -dh -ap -cW -bv -ds +cn +cw +ae +aS +cL +bF +cX +df +aq +cU +bu +dt ad ab ab @@ -2216,25 +2155,25 @@ ad ad aV ad -dx -bm -bF -ap +ae +bl +bE +aq bQ bY -bv -co -cz -cG -ap -ap -ap -ap -ap -ap -ap +bu +cn +cw +cE +aq +aq +aq +aq +aq +aq +aq dp -aN +aO ad ab ab @@ -2248,33 +2187,33 @@ ab ab ab ad -ae -ar -ar -aB -aJ +af +as +as +aC +aK +aq ap -ao -bd +bc ad -bn -bG -bM +bm +bF +bL bR bZ ad -co -cz +cn +cw cf -ap -ap -cV -da -di -dm -aR -bv -ds +aq +aq +cT +cY +dg +dk +aS +bu +dt ad ab ab @@ -2288,23 +2227,23 @@ ab ab ab ad -af -ar -ar -aC -aK -ao +ag +as +as +aD +aL ap -be +aq +bd ad ad -bv -bv -bv +bu +bu +bu ad ad -co -cz +cn +cw ad ad ad @@ -2316,7 +2255,7 @@ ad ad ad ad -dt +du ab ab ab @@ -2328,34 +2267,34 @@ ab ab ab ad -ag -ar -ar -aD -aL +ah +as +as +aE +aM +aq ap -ao -ap -bh -bo +aq +bg +bn aY aY aY aY aY -cp -cA +co +cy aY aY aY aY aY aY -cw -do +cv +dn dq -aN -do +aO +dn ab ab ab @@ -2367,35 +2306,35 @@ ab ab ab ab -du +ae ad -ar -ar -aE -aK -ao +as +as +aF +aL ap -ao -bh -bp +aq +ap +bg +bo aZ aZ aZ aZ aZ -cq -cB +cp +cz aZ aZ aZ aZ aZ aZ -cC -do +cA +dn dr -aN -do +aO +dn ab ab ab @@ -2408,23 +2347,23 @@ ab ab ab ad -ah -ar -ar -aF -ao +ai +as +as +aG ap -ao -bc +aq +ap +bb ad ad -bv -bv -bv +bu +bu +bu ad ad -co -cz +cn +cw ad ad ad @@ -2436,7 +2375,7 @@ ad ad ad ad -dt +du ab ab ab @@ -2448,30 +2387,30 @@ ab ab ab ad -ai -ar -ar -aG +aj +as +as +aH +aq ap -ao -ap -bf +aq +be ad -bq -bH -bN +bp +bG +bM bS ca -ck -co -cz -dC -aR -ap -cW -db -dj -dE +cj +cn +cw +ae +aS +aq +cU +cZ +dh +ae ac ac ac @@ -2497,20 +2436,20 @@ ad aT ad ad -br -bI -ap -ap +bq +bH +aq +aq cb -cl -co -cz -cH +ck +cn +cw +cF +aq ap -ao -ao -ao ap +ap +aq ad ac ac @@ -2528,29 +2467,29 @@ ab ab ab ad -aj -as -ax -aH -aM +ak +at +ay +aI +aN ad -ap -aR +aq +aS ad -bs -ap -ao +br +aq ap +aq bP ad -co -cz +cn +cw cf -ap -cO -cX -dc -ap +aq +cM +cV +da +aq ad ad ad @@ -2568,33 +2507,33 @@ ab ab ab ad -ak -at -at -at -aN +al +au +au +au +aO aT -ap -ap +aq +aq ad -bt -ap -ao +bs +aq ap +aq cc -bv -co -cz +bu +cn +cw ad -cJ -cP -bI -dd -ap +cH +cN +bH +db +aq ad -ap -dI -ap +aq +do +aq ad ab ab @@ -2610,31 +2549,31 @@ ab ad ad ad -dv +ae ad ad ad +aq +aq +ad +bt +aq ap -ap -ad -bu -ap -ao bT cd -bv -co -cz +bu +cn +cw ad -ap -cQ -ap -ap -ap -dF -dG -dJ -dL +aq +cO +aq +aq +aq +dl +do +ds +do ad ab ab @@ -2648,33 +2587,33 @@ ab ab ab ad -al -at -at -at -aN +am +au +au +au +aO aT +aq +aq +ae +bu +bu ap -ap -dy -bv -bv -ao -by -by -dz -cr -cC +bx +bx +ae +cq +cA ad -cK -cR -aN -aN -bL +cI +cP +aO +aO +bK ad -ap -dK -ap +aq +do +aq ad ab ab @@ -2688,28 +2627,28 @@ ab ab ab ad -am -au -ay -au +an +av +az +av +aP +ad +aq +aS +ad +bv +bI +ap +bI aO ad -ap -aR -ad -bw -bJ -ao -bJ -aN -ad -cs -cD +cr +cB ad ad ad ad -cH +cF ad ad ad @@ -2737,21 +2676,21 @@ ad aW ad ad +bw +bx +ap bx -by -ao -by ce ad -ct -ap -ap -cL -cS +cs +aq +aq +cJ +cQ ad -de -dk -dk +dc +di +di ad ab ab @@ -2775,23 +2714,23 @@ ab ac ad aX -bg +bf ad -by -by -ao -by -by +bx +bx +ap +bx +bx ad -ap -ap -ap -ap -cT +aq +aq +aq +aq +cR ad -df -dk -dn +dd +di +dm ad ab ab @@ -2817,21 +2756,21 @@ ad ad ad ad -bx -bJ -ao +bw +bI +ap bU -aN +aO ad -cu -cE -cu -cM -cU +ct +cC +ct +cK +cS ad -de -dk -dk +dc +di +di ad ac ab @@ -2857,10 +2796,10 @@ ab ab ac ad -bz -by -ao by +bx +ap +bx ce ad ad diff --git a/_maps/map_files/TgStation/tgstation.2.1.3.dmm b/_maps/map_files/TgStation/tgstation.2.1.3.dmm index b00c11274b..229d5755a1 100644 --- a/_maps/map_files/TgStation/tgstation.2.1.3.dmm +++ b/_maps/map_files/TgStation/tgstation.2.1.3.dmm @@ -1142,6 +1142,10 @@ /obj/effect/turf_decal/bot{ dir = 2 }, +/obj/structure/window/reinforced{ + dir = 1; + layer = 2.9 + }, /turf/open/floor/plasteel{ dir = 2 }, @@ -1338,6 +1342,13 @@ /obj/effect/turf_decal/bot{ dir = 2 }, +/obj/structure/window/reinforced{ + dir = 1; + layer = 2.9 + }, +/obj/structure/window/reinforced{ + dir = 4 + }, /turf/open/floor/plasteel{ dir = 2 }, @@ -1356,6 +1367,13 @@ /obj/effect/turf_decal/bot{ dir = 2 }, +/obj/structure/window/reinforced{ + dir = 1; + layer = 2.9 + }, +/obj/structure/window/reinforced{ + dir = 8 + }, /turf/open/floor/plasteel{ dir = 2 }, @@ -53772,6 +53790,10 @@ /obj/effect/turf_decal/bot{ dir = 2 }, +/obj/structure/window/reinforced{ + dir = 1; + layer = 2.9 + }, /turf/open/floor/plasteel{ dir = 2 }, @@ -112232,11 +112254,11 @@ btp cbv ccq bns -cjD -cjD -cjD -cjD -cnj +aof +aof +aof +aof +amw aaa aaa aaa @@ -112489,13 +112511,13 @@ ckS bky ccq cds -cjD +aof ckt cly cmw -cnj -cnj -cnj +amw +amw +amw aaa aaa aaf @@ -113003,13 +113025,13 @@ cbg bTr cct cdu -cjG +aqx cku clz cmx -cnj -cnj -cnj +amw +amw +amw aaa aaa aaf @@ -113260,11 +113282,11 @@ bky bky bky bky -cjD -cjD -cjD -cjD -cnj +aof +aof +aof +aof +amw aaa aaa aaa diff --git a/code/__DEFINES/MC.dm b/code/__DEFINES/MC.dm index c33543ac4e..f5879c52b1 100644 --- a/code/__DEFINES/MC.dm +++ b/code/__DEFINES/MC.dm @@ -1,12 +1,12 @@ -#define MC_TICK_CHECK ( ( world.tick_usage > GLOB.CURRENT_TICKLIMIT || src.state != SS_RUNNING ) ? pause() : 0 ) +#define MC_TICK_CHECK ( ( world.tick_usage > Master.current_ticklimit || src.state != SS_RUNNING ) ? pause() : 0 ) -#define MC_SPLIT_TICK_INIT(phase_count) var/original_tick_limit = GLOB.CURRENT_TICKLIMIT; var/split_tick_phases = ##phase_count +#define MC_SPLIT_TICK_INIT(phase_count) var/original_tick_limit = Master.current_ticklimit; var/split_tick_phases = ##phase_count #define MC_SPLIT_TICK \ if(split_tick_phases > 1){\ - GLOB.CURRENT_TICKLIMIT = ((original_tick_limit - world.tick_usage) / split_tick_phases) + world.tick_usage;\ + Master.current_ticklimit = ((original_tick_limit - world.tick_usage) / split_tick_phases) + world.tick_usage;\ --split_tick_phases;\ } else {\ - GLOB.CURRENT_TICKLIMIT = original_tick_limit;\ + Master.current_ticklimit = original_tick_limit;\ } // Used to smooth out costs to try and avoid oscillation. diff --git a/code/__DEFINES/tick.dm b/code/__DEFINES/tick.dm index 0c8c17da6f..4c88fd643e 100644 --- a/code/__DEFINES/tick.dm +++ b/code/__DEFINES/tick.dm @@ -3,5 +3,5 @@ #define TICK_LIMIT_MC 70 #define TICK_LIMIT_MC_INIT_DEFAULT 98 -#define TICK_CHECK ( world.tick_usage > GLOB.CURRENT_TICKLIMIT ) +#define TICK_CHECK ( world.tick_usage > Master.current_ticklimit ) #define CHECK_TICK if TICK_CHECK stoplag() diff --git a/code/__HELPERS/sorts/__main.dm b/code/__HELPERS/sorts/__main.dm index c26126c0a6..7da17da503 100644 --- a/code/__HELPERS/sorts/__main.dm +++ b/code/__HELPERS/sorts/__main.dm @@ -626,14 +626,13 @@ GLOBAL_DATUM_INIT(sortInstance, /datum/sortInstance, new()) var/val2 = fetchElement(L,cursor2) while(1) - if(call(cmp)(val1,val2) < 0) + if(call(cmp)(val1,val2) <= 0) if(++cursor1 >= end1) break val1 = fetchElement(L,cursor1) else moveElement(L,cursor2,cursor1) - ++cursor2 if(++cursor2 >= end2) break ++end1 @@ -653,4 +652,4 @@ GLOBAL_DATUM_INIT(sortInstance, /datum/sortInstance, new()) #undef MIN_GALLOP #undef MIN_MERGE -#undef fetchElement \ No newline at end of file +#undef fetchElement diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 10ee2dfb0c..ea3811085b 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -1215,7 +1215,7 @@ proc/pick_closest_path(value, list/matches = get_fancy_list_of_atom_types()) . += round(i*DELTA_CALC) sleep(i*world.tick_lag*DELTA_CALC) i *= 2 - while (world.tick_usage > min(TICK_LIMIT_TO_RUN, GLOB.CURRENT_TICKLIMIT)) + while (world.tick_usage > min(TICK_LIMIT_TO_RUN, Master.current_ticklimit)) #undef DELTA_CALC diff --git a/code/_onclick/autoclick.dm b/code/_onclick/autoclick.dm index 1ceeb182ed..7b6e2f108a 100644 --- a/code/_onclick/autoclick.dm +++ b/code/_onclick/autoclick.dm @@ -14,7 +14,7 @@ selected_target[1] = null /client/MouseDrag(src_object,atom/over_object,src_location,over_location,src_control,over_control,params) - if(selected_target[1] && over_object.IsAutoclickable()) + if(selected_target[1] && over_object && over_object.IsAutoclickable()) selected_target[1] = over_object selected_target[2] = params diff --git a/code/_onclick/click.dm b/code/_onclick/click.dm index 4a4c441edc..a9f76f7f9d 100644 --- a/code/_onclick/click.dm +++ b/code/_onclick/click.dm @@ -1,467 +1,469 @@ -/* - Click code cleanup - ~Sayu -*/ - -// 1 decisecond click delay (above and beyond mob/next_move) -//This is mainly modified by click code, to modify click delays elsewhere, use next_move and changeNext_move() -/mob/var/next_click = 0 - -// THESE DO NOT EFFECT THE BASE 1 DECISECOND DELAY OF NEXT_CLICK -/mob/var/next_move_adjust = 0 //Amount to adjust action/click delays by, + or - -/mob/var/next_move_modifier = 1 //Value to multiply action/click delays by - - -//Delays the mob's next click/action by num deciseconds -// eg: 10-3 = 7 deciseconds of delay -// eg: 10*0.5 = 5 deciseconds of delay -// DOES NOT EFFECT THE BASE 1 DECISECOND DELAY OF NEXT_CLICK - -/mob/proc/changeNext_move(num) - next_move = world.time + ((num+next_move_adjust)*next_move_modifier) - - -/* - Before anything else, defer these calls to a per-mobtype handler. This allows us to - remove istype() spaghetti code, but requires the addition of other handler procs to simplify it. - - Alternately, you could hardcode every mob's variation in a flat ClickOn() proc; however, - that's a lot of code duplication and is hard to maintain. - - Note that this proc can be overridden, and is in the case of screen objects. -*/ -/atom/Click(location,control,params) - if(initialized) - usr.ClickOn(src, params) - -/atom/DblClick(location,control,params) - if(initialized) - usr.DblClickOn(src,params) - -/atom/MouseWheel(delta_x,delta_y,location,control,params) - if(initialized) - usr.MouseWheelOn(src, delta_x, delta_y, params) - -/* - Standard mob ClickOn() - Handles exceptions: Buildmode, middle click, modified clicks, mech actions - - After that, mostly just check your state, check whether you're holding an item, - check whether you're adjacent to the target, then pass off the click to whoever - is recieving it. - The most common are: - * mob/UnarmedAttack(atom,adjacent) - used here only when adjacent, with no item in hand; in the case of humans, checks gloves - * atom/attackby(item,user) - used only when adjacent - * item/afterattack(atom,user,adjacent,params) - used both ranged and adjacent - * mob/RangedAttack(atom,params) - used only ranged, only used for tk and laser eyes but could be changed -*/ -/mob/proc/ClickOn( atom/A, params ) - if(world.time <= next_click) - return - next_click = world.time + 1 - - if(client && client.click_intercept) - if(call(client.click_intercept, "InterceptClickOn")(src, params, A)) - return - - var/list/modifiers = params2list(params) - if(modifiers["shift"] && modifiers["middle"]) - ShiftMiddleClickOn(A) - return - if(modifiers["shift"] && modifiers["ctrl"]) - CtrlShiftClickOn(A) - return - if(modifiers["middle"]) - MiddleClickOn(A) - return - if(modifiers["shift"]) - ShiftClickOn(A) - return - if(modifiers["alt"]) // alt and alt-gr (rightalt) - AltClickOn(A) - return - if(modifiers["ctrl"]) - CtrlClickOn(A) - return - - if(incapacitated(ignore_restraints = 1)) - return - - face_atom(A) - - if(next_move > world.time) // in the year 2000... - return - - if(A.IsObscured()) - return - - if(istype(loc,/obj/mecha)) - var/obj/mecha/M = loc - return M.click_action(A,src,params) - - if(restrained()) - changeNext_move(CLICK_CD_HANDCUFFED) //Doing shit in cuffs shall be vey slow - RestrainedClickOn(A) - return - - if(in_throw_mode) - throw_item(A) - return - - var/obj/item/W = get_active_held_item() - - if(W == A) - W.attack_self(src) - update_inv_hands() - return - - //These are always reachable. - //User itself, current loc, and user inventory - if(DirectAccess(A)) - if(W) - melee_item_attack_chain(src,W,A,params) - else - if(ismob(A)) - changeNext_move(CLICK_CD_MELEE) - UnarmedAttack(A) - return - - //Can't reach anything else in lockers or other weirdness - if(!loc.AllowClick()) - return - - //Standard reach turf to turf or reaching inside storage - if(CanReach(A,W)) - if(W) - melee_item_attack_chain(src,W,A,params) - else - if(ismob(A)) - changeNext_move(CLICK_CD_MELEE) - UnarmedAttack(A,1) - else - if(W) - W.afterattack(A,src,0,params) - else - RangedAttack(A,params) - -//Is the atom obscured by a PREVENT_CLICK_UNDER object above it -/atom/proc/IsObscured() - if(!isturf(loc)) //This only makes sense for things directly on turfs for now - return FALSE - var/turf/T = get_turf_pixel(src) - if(!T) - return FALSE - for(var/atom/movable/AM in T) - if(AM.flags & PREVENT_CLICK_UNDER && AM.density && AM.layer > layer) - return TRUE - return FALSE - -/turf/IsObscured() - for(var/atom/movable/AM in src) - if(AM.flags & PREVENT_CLICK_UNDER && AM.density) - return TRUE - return FALSE - -/atom/movable/proc/CanReach(atom/target,obj/item/tool,view_only = FALSE) - if(isturf(target) || isturf(target.loc) || DirectAccess(target)) //Directly accessible atoms - if(Adjacent(target) || (tool && CheckToolReach(src, target, tool.reach))) //Adjacent or reaching attacks - return TRUE - else - //Things inside storage insde another storage - //Eg Contents of a box in a backpack - var/atom/outer_storage = get_atom_on_turf(target) - if(outer_storage == target) //whatever that is we don't want infinite loop. - return FALSE - if(outer_storage && CanReach(outer_storage,tool) && outer_storage.CanReachStorage(target,src,view_only ? STORAGE_VIEW_DEPTH : INVENTORY_DEPTH)) - return TRUE - return FALSE - -//Can [target] in this container be reached by [user], can't be more than [depth] levels deep -/atom/proc/CanReachStorage(atom/target,user,depth) - return FALSE - -/obj/item/weapon/storage/CanReachStorage(atom/target,user,depth) - while(target && depth > 0) - target = target.loc - depth-- - if(target == src) - return TRUE - return FALSE - -/atom/movable/proc/DirectAccess(atom/target) - if(target == src) - return TRUE - if(target == loc) - return TRUE - -/mob/DirectAccess(atom/target) - if(..()) - return TRUE - if(target in contents) //This could probably use moving down and restricting to inventory only - return TRUE - return FALSE - -/mob/living/DirectAccess(atom/target) - if(..()) //Lightweight checks first - return TRUE - if(target in GetAllContents()) - return TRUE - -/atom/proc/AllowClick() - return FALSE - -/turf/AllowClick() - return TRUE - -/proc/CheckToolReach(atom/movable/here, atom/movable/there, reach) - if(!here || !there) - return - switch(reach) - if(0) - return FALSE - if(1) - return FALSE //here.Adjacent(there) - if(2 to INFINITY) - var/obj/dummy = new(get_turf(here)) - dummy.pass_flags |= PASSTABLE - dummy.invisibility = INVISIBILITY_ABSTRACT - for(var/i in 1 to reach) //Limit it to that many tries - var/turf/T = get_step(dummy, get_dir(dummy, there)) - if(dummy.CanReach(there)) - qdel(dummy) - return TRUE - if(!dummy.Move(T)) //we're blocked! - qdel(dummy) - return - qdel(dummy) - -// Default behavior: ignore double clicks (the second click that makes the doubleclick call already calls for a normal click) -/mob/proc/DblClickOn(atom/A, params) - return - - -/* - Translates into attack_hand, etc. - - Note: proximity_flag here is used to distinguish between normal usage (flag=1), - and usage when clicking on things telekinetically (flag=0). This proc will - not be called at ranged except with telekinesis. - - proximity_flag is not currently passed to attack_hand, and is instead used - in human click code to allow glove touches only at melee range. -*/ -/mob/proc/UnarmedAttack(atom/A, proximity_flag) - if(ismob(A)) - changeNext_move(CLICK_CD_MELEE) - return - -/* - Ranged unarmed attack: - - This currently is just a default for all mobs, involving - laser eyes and telekinesis. You could easily add exceptions - for things like ranged glove touches, spitting alien acid/neurotoxin, - animals lunging, etc. -*/ -/mob/proc/RangedAttack(atom/A, params) -/* - Restrained ClickOn - - Used when you are handcuffed and click things. - Not currently used by anything but could easily be. -*/ -/mob/proc/RestrainedClickOn(atom/A) - return - -/* - Middle click - Only used for swapping hands -*/ -/mob/proc/MiddleClickOn(atom/A) - return - -/mob/living/carbon/MiddleClickOn(atom/A) - if(!src.stat && src.mind && src.mind.changeling && src.mind.changeling.chosen_sting && (istype(A, /mob/living/carbon)) && (A != src)) - next_click = world.time + 5 - mind.changeling.chosen_sting.try_to_sting(src, A) - else - swap_hand() - -/mob/living/simple_animal/drone/MiddleClickOn(atom/A) - swap_hand() - -// In case of use break glass -/* -/atom/proc/MiddleClick(mob/M as mob) - return -*/ - -/* - Shift click - For most mobs, examine. - This is overridden in ai.dm -*/ -/mob/proc/ShiftClickOn(atom/A) - A.ShiftClick(src) - return -/atom/proc/ShiftClick(mob/user) - if(user.client && user.client.eye == user || user.client.eye == user.loc) - user.examinate(src) - return - -/* - Ctrl click - For most objects, pull -*/ - -/mob/proc/CtrlClickOn(atom/A) - A.CtrlClick(src) - return - -/atom/proc/CtrlClick(mob/user) - var/mob/living/ML = user - if(istype(ML)) - ML.pulled(src) - -/mob/living/carbon/human/CtrlClick(mob/user) - if(ishuman(user) && Adjacent(user)) - var/mob/living/carbon/human/H = user - H.dna.species.grab(H, src, H.martial_art) - H.next_click = world.time + CLICK_CD_MELEE - else - ..() -/* - Alt click - Unused except for AI -*/ -/mob/proc/AltClickOn(atom/A) - A.AltClick(src) - return - -/mob/living/carbon/AltClickOn(atom/A) - if(!src.stat && src.mind && src.mind.changeling && src.mind.changeling.chosen_sting && (istype(A, /mob/living/carbon)) && (A != src)) - next_click = world.time + 5 - mind.changeling.chosen_sting.try_to_sting(src, A) - else - ..() - -/atom/proc/AltClick(mob/user) - var/turf/T = get_turf(src) - if(T && user.TurfAdjacent(T)) - if(user.listed_turf == T) - user.listed_turf = null - else - user.listed_turf = T - user.client.statpanel = T.name - return - -/mob/proc/TurfAdjacent(turf/T) - return T.Adjacent(src) - -/* - Control+Shift click - Unused except for AI -*/ -/mob/proc/CtrlShiftClickOn(atom/A) - A.CtrlShiftClick(src) - return - -/mob/proc/ShiftMiddleClickOn(atom/A) - src.pointed(A) - return - -/atom/proc/CtrlShiftClick(mob/user) - return - -/* - Misc helpers - - Laser Eyes: as the name implies, handles this since nothing else does currently - face_atom: turns the mob towards what you clicked on -*/ -/mob/proc/LaserEyes(atom/A) - return - -/mob/living/LaserEyes(atom/A) - changeNext_move(CLICK_CD_RANGE) - var/turf/T = get_turf(src) - var/turf/U = get_turf(A) - - var/obj/item/projectile/beam/LE = new /obj/item/projectile/beam( loc ) - LE.icon = 'icons/effects/genetics.dmi' - LE.icon_state = "eyelasers" - playsound(usr.loc, 'sound/weapons/taser2.ogg', 75, 1) - - LE.firer = src - LE.def_zone = get_organ_target() - LE.original = A - LE.current = T - LE.yo = U.y - T.y - LE.xo = U.x - T.x - LE.fire() - -// Simple helper to face what you clicked on, in case it should be needed in more than one place -/mob/proc/face_atom(atom/A) - if( buckled || stat != CONSCIOUS || !A || !x || !y || !A.x || !A.y ) - return - var/dx = A.x - x - var/dy = A.y - y - if(!dx && !dy) // Wall items are graphically shifted but on the floor - if(A.pixel_y > 16) - setDir(NORTH) - else if(A.pixel_y < -16) - setDir(SOUTH) - else if(A.pixel_x > 16) - setDir(EAST) - else if(A.pixel_x < -16) - setDir(WEST) - return - - if(abs(dx) < abs(dy)) - if(dy > 0) - setDir(NORTH) - else - setDir(SOUTH) - else - if(dx > 0) - setDir(EAST) - else - setDir(WEST) - -/obj/screen/click_catcher - icon = 'icons/mob/screen_gen.dmi' - icon_state = "click_catcher" - plane = CLICKCATCHER_PLANE - mouse_opacity = 2 - screen_loc = "CENTER" - -/obj/screen/click_catcher/New() - ..() - transform = matrix(200, 0, 0, 0, 200, 0) - -/obj/screen/click_catcher/Click(location, control, params) - var/list/modifiers = params2list(params) - if(modifiers["middle"] && istype(usr, /mob/living/carbon)) - var/mob/living/carbon/C = usr - C.swap_hand() - else - var/turf/T = params2turf(modifiers["screen-loc"], get_turf(usr)) - if(T) - T.Click(location, control, params) - . = 1 - - -/* MouseWheelOn */ - -/mob/proc/MouseWheelOn(atom/A, delta_x, delta_y, params) - return - -/mob/dead/observer/MouseWheelOn(atom/A, delta_x, delta_y, params) - var/list/modifier = params2list(params) - if(modifier["shift"]) - var/view = 0 - if(delta_y > 0) - view = -1 - else - view = 1 - add_view_range(view) +/* + Click code cleanup + ~Sayu +*/ + +// 1 decisecond click delay (above and beyond mob/next_move) +//This is mainly modified by click code, to modify click delays elsewhere, use next_move and changeNext_move() +/mob/var/next_click = 0 + +// THESE DO NOT EFFECT THE BASE 1 DECISECOND DELAY OF NEXT_CLICK +/mob/var/next_move_adjust = 0 //Amount to adjust action/click delays by, + or - +/mob/var/next_move_modifier = 1 //Value to multiply action/click delays by + + +//Delays the mob's next click/action by num deciseconds +// eg: 10-3 = 7 deciseconds of delay +// eg: 10*0.5 = 5 deciseconds of delay +// DOES NOT EFFECT THE BASE 1 DECISECOND DELAY OF NEXT_CLICK + +/mob/proc/changeNext_move(num) + next_move = world.time + ((num+next_move_adjust)*next_move_modifier) + + +/* + Before anything else, defer these calls to a per-mobtype handler. This allows us to + remove istype() spaghetti code, but requires the addition of other handler procs to simplify it. + + Alternately, you could hardcode every mob's variation in a flat ClickOn() proc; however, + that's a lot of code duplication and is hard to maintain. + + Note that this proc can be overridden, and is in the case of screen objects. +*/ +/atom/Click(location,control,params) + if(initialized) + usr.ClickOn(src, params) + +/atom/DblClick(location,control,params) + if(initialized) + usr.DblClickOn(src,params) + +/atom/MouseWheel(delta_x,delta_y,location,control,params) + if(initialized) + usr.MouseWheelOn(src, delta_x, delta_y, params) + +/* + Standard mob ClickOn() + Handles exceptions: Buildmode, middle click, modified clicks, mech actions + + After that, mostly just check your state, check whether you're holding an item, + check whether you're adjacent to the target, then pass off the click to whoever + is recieving it. + The most common are: + * mob/UnarmedAttack(atom,adjacent) - used here only when adjacent, with no item in hand; in the case of humans, checks gloves + * atom/attackby(item,user) - used only when adjacent + * item/afterattack(atom,user,adjacent,params) - used both ranged and adjacent + * mob/RangedAttack(atom,params) - used only ranged, only used for tk and laser eyes but could be changed +*/ +/mob/proc/ClickOn( atom/A, params ) + if(world.time <= next_click) + return + next_click = world.time + 1 + + if(client && client.click_intercept) + if(call(client.click_intercept, "InterceptClickOn")(src, params, A)) + return + + var/list/modifiers = params2list(params) + if(modifiers["shift"] && modifiers["middle"]) + ShiftMiddleClickOn(A) + return + if(modifiers["shift"] && modifiers["ctrl"]) + CtrlShiftClickOn(A) + return + if(modifiers["middle"]) + MiddleClickOn(A) + return + if(modifiers["shift"]) + ShiftClickOn(A) + return + if(modifiers["alt"]) // alt and alt-gr (rightalt) + AltClickOn(A) + return + if(modifiers["ctrl"]) + CtrlClickOn(A) + return + + if(incapacitated(ignore_restraints = 1)) + return + + face_atom(A) + + if(next_move > world.time) // in the year 2000... + return + + if(A.IsObscured()) + return + + if(istype(loc,/obj/mecha)) + var/obj/mecha/M = loc + return M.click_action(A,src,params) + + if(restrained()) + changeNext_move(CLICK_CD_HANDCUFFED) //Doing shit in cuffs shall be vey slow + RestrainedClickOn(A) + return + + if(in_throw_mode) + throw_item(A) + return + + var/obj/item/W = get_active_held_item() + + if(W == A) + W.attack_self(src) + update_inv_hands() + return + + //These are always reachable. + //User itself, current loc, and user inventory + if(DirectAccess(A)) + if(W) + melee_item_attack_chain(src,W,A,params) + else + if(ismob(A)) + changeNext_move(CLICK_CD_MELEE) + UnarmedAttack(A) + return + + //Can't reach anything else in lockers or other weirdness + if(!loc.AllowClick()) + return + + //Standard reach turf to turf or reaching inside storage + if(CanReach(A,W)) + if(W) + melee_item_attack_chain(src,W,A,params) + else + if(ismob(A)) + changeNext_move(CLICK_CD_MELEE) + UnarmedAttack(A,1) + else + if(W) + W.afterattack(A,src,0,params) + else + RangedAttack(A,params) + +//Is the atom obscured by a PREVENT_CLICK_UNDER object above it +/atom/proc/IsObscured() + if(!isturf(loc)) //This only makes sense for things directly on turfs for now + return FALSE + var/turf/T = get_turf_pixel(src) + if(!T) + return FALSE + for(var/atom/movable/AM in T) + if(AM.flags & PREVENT_CLICK_UNDER && AM.density && AM.layer > layer) + return TRUE + return FALSE + +/turf/IsObscured() + for(var/atom/movable/AM in src) + if(AM.flags & PREVENT_CLICK_UNDER && AM.density) + return TRUE + return FALSE + +/atom/movable/proc/CanReach(atom/target,obj/item/tool,view_only = FALSE) + if(isturf(target) || isturf(target.loc) || DirectAccess(target)) //Directly accessible atoms + if(Adjacent(target) || (tool && CheckToolReach(src, target, tool.reach))) //Adjacent or reaching attacks + return TRUE + else + //Things inside storage insde another storage + //Eg Contents of a box in a backpack + var/atom/outer_storage = get_atom_on_turf(target) + if(outer_storage == target) //whatever that is we don't want infinite loop. + return FALSE + if(outer_storage && CanReach(outer_storage,tool) && outer_storage.CanReachStorage(target,src,view_only ? STORAGE_VIEW_DEPTH : INVENTORY_DEPTH)) + return TRUE + return FALSE + +//Can [target] in this container be reached by [user], can't be more than [depth] levels deep +/atom/proc/CanReachStorage(atom/target,user,depth) + return FALSE + +/obj/item/weapon/storage/CanReachStorage(atom/target,user,depth) + while(target && depth > 0) + target = target.loc + depth-- + if(target == src) + return TRUE + return FALSE + +/atom/movable/proc/DirectAccess(atom/target) + if(target == src) + return TRUE + if(target == loc) + return TRUE + +/mob/DirectAccess(atom/target) + if(..()) + return TRUE + if(target in contents) //This could probably use moving down and restricting to inventory only + return TRUE + return FALSE + +/mob/living/DirectAccess(atom/target) + if(..()) //Lightweight checks first + return TRUE + if(target in GetAllContents()) + return TRUE + +/atom/proc/AllowClick() + return FALSE + +/turf/AllowClick() + return TRUE + +/proc/CheckToolReach(atom/movable/here, atom/movable/there, reach) + if(!here || !there) + return + switch(reach) + if(0) + return FALSE + if(1) + return FALSE //here.Adjacent(there) + if(2 to INFINITY) + var/obj/dummy = new(get_turf(here)) + dummy.pass_flags |= PASSTABLE + dummy.invisibility = INVISIBILITY_ABSTRACT + for(var/i in 1 to reach) //Limit it to that many tries + var/turf/T = get_step(dummy, get_dir(dummy, there)) + if(dummy.CanReach(there)) + qdel(dummy) + return TRUE + if(!dummy.Move(T)) //we're blocked! + qdel(dummy) + return + qdel(dummy) + +// Default behavior: ignore double clicks (the second click that makes the doubleclick call already calls for a normal click) +/mob/proc/DblClickOn(atom/A, params) + return + + +/* + Translates into attack_hand, etc. + + Note: proximity_flag here is used to distinguish between normal usage (flag=1), + and usage when clicking on things telekinetically (flag=0). This proc will + not be called at ranged except with telekinesis. + + proximity_flag is not currently passed to attack_hand, and is instead used + in human click code to allow glove touches only at melee range. +*/ +/mob/proc/UnarmedAttack(atom/A, proximity_flag) + if(ismob(A)) + changeNext_move(CLICK_CD_MELEE) + return + +/* + Ranged unarmed attack: + + This currently is just a default for all mobs, involving + laser eyes and telekinesis. You could easily add exceptions + for things like ranged glove touches, spitting alien acid/neurotoxin, + animals lunging, etc. +*/ +/mob/proc/RangedAttack(atom/A, params) +/* + Restrained ClickOn + + Used when you are handcuffed and click things. + Not currently used by anything but could easily be. +*/ +/mob/proc/RestrainedClickOn(atom/A) + return + +/* + Middle click + Only used for swapping hands +*/ +/mob/proc/MiddleClickOn(atom/A) + return + +/mob/living/carbon/MiddleClickOn(atom/A) + if(!src.stat && src.mind && src.mind.changeling && src.mind.changeling.chosen_sting && (istype(A, /mob/living/carbon)) && (A != src)) + next_click = world.time + 5 + mind.changeling.chosen_sting.try_to_sting(src, A) + else + swap_hand() + +/mob/living/simple_animal/drone/MiddleClickOn(atom/A) + swap_hand() + +// In case of use break glass +/* +/atom/proc/MiddleClick(mob/M as mob) + return +*/ + +/* + Shift click + For most mobs, examine. + This is overridden in ai.dm +*/ +/mob/proc/ShiftClickOn(atom/A) + A.ShiftClick(src) + return +/atom/proc/ShiftClick(mob/user) + if(user.client && user.client.eye == user || user.client.eye == user.loc) + user.examinate(src) + return + +/* + Ctrl click + For most objects, pull +*/ + +/mob/proc/CtrlClickOn(atom/A) + A.CtrlClick(src) + return + +/atom/proc/CtrlClick(mob/user) + var/mob/living/ML = user + if(istype(ML)) + ML.pulled(src) + +/mob/living/carbon/human/CtrlClick(mob/user) + if(ishuman(user) && Adjacent(user)) + if(world.time < user.next_move) + return FALSE + var/mob/living/carbon/human/H = user + H.dna.species.grab(H, src, H.mind.martial_art) + H.changeNext_move(CLICK_CD_MELEE) + else + ..() +/* + Alt click + Unused except for AI +*/ +/mob/proc/AltClickOn(atom/A) + A.AltClick(src) + return + +/mob/living/carbon/AltClickOn(atom/A) + if(!src.stat && src.mind && src.mind.changeling && src.mind.changeling.chosen_sting && (istype(A, /mob/living/carbon)) && (A != src)) + next_click = world.time + 5 + mind.changeling.chosen_sting.try_to_sting(src, A) + else + ..() + +/atom/proc/AltClick(mob/user) + var/turf/T = get_turf(src) + if(T && user.TurfAdjacent(T)) + if(user.listed_turf == T) + user.listed_turf = null + else + user.listed_turf = T + user.client.statpanel = T.name + return + +/mob/proc/TurfAdjacent(turf/T) + return T.Adjacent(src) + +/* + Control+Shift click + Unused except for AI +*/ +/mob/proc/CtrlShiftClickOn(atom/A) + A.CtrlShiftClick(src) + return + +/mob/proc/ShiftMiddleClickOn(atom/A) + src.pointed(A) + return + +/atom/proc/CtrlShiftClick(mob/user) + return + +/* + Misc helpers + + Laser Eyes: as the name implies, handles this since nothing else does currently + face_atom: turns the mob towards what you clicked on +*/ +/mob/proc/LaserEyes(atom/A) + return + +/mob/living/LaserEyes(atom/A) + changeNext_move(CLICK_CD_RANGE) + var/turf/T = get_turf(src) + var/turf/U = get_turf(A) + + var/obj/item/projectile/beam/LE = new /obj/item/projectile/beam( loc ) + LE.icon = 'icons/effects/genetics.dmi' + LE.icon_state = "eyelasers" + playsound(usr.loc, 'sound/weapons/taser2.ogg', 75, 1) + + LE.firer = src + LE.def_zone = get_organ_target() + LE.original = A + LE.current = T + LE.yo = U.y - T.y + LE.xo = U.x - T.x + LE.fire() + +// Simple helper to face what you clicked on, in case it should be needed in more than one place +/mob/proc/face_atom(atom/A) + if( buckled || stat != CONSCIOUS || !A || !x || !y || !A.x || !A.y ) + return + var/dx = A.x - x + var/dy = A.y - y + if(!dx && !dy) // Wall items are graphically shifted but on the floor + if(A.pixel_y > 16) + setDir(NORTH) + else if(A.pixel_y < -16) + setDir(SOUTH) + else if(A.pixel_x > 16) + setDir(EAST) + else if(A.pixel_x < -16) + setDir(WEST) + return + + if(abs(dx) < abs(dy)) + if(dy > 0) + setDir(NORTH) + else + setDir(SOUTH) + else + if(dx > 0) + setDir(EAST) + else + setDir(WEST) + +/obj/screen/click_catcher + icon = 'icons/mob/screen_gen.dmi' + icon_state = "click_catcher" + plane = CLICKCATCHER_PLANE + mouse_opacity = 2 + screen_loc = "CENTER" + +/obj/screen/click_catcher/New() + ..() + transform = matrix(200, 0, 0, 0, 200, 0) + +/obj/screen/click_catcher/Click(location, control, params) + var/list/modifiers = params2list(params) + if(modifiers["middle"] && istype(usr, /mob/living/carbon)) + var/mob/living/carbon/C = usr + C.swap_hand() + else + var/turf/T = params2turf(modifiers["screen-loc"], get_turf(usr)) + if(T) + T.Click(location, control, params) + . = 1 + + +/* MouseWheelOn */ + +/mob/proc/MouseWheelOn(atom/A, delta_x, delta_y, params) + return + +/mob/dead/observer/MouseWheelOn(atom/A, delta_x, delta_y, params) + var/list/modifier = params2list(params) + if(modifier["shift"]) + var/view = 0 + if(delta_y > 0) + view = -1 + else + view = 1 + add_view_range(view) diff --git a/code/controllers/master.dm b/code/controllers/master.dm index 574c31a0b0..0f4ae021ad 100644 --- a/code/controllers/master.dm +++ b/code/controllers/master.dm @@ -14,15 +14,6 @@ GLOBAL_REAL(Master, /datum/controller/master) = new //Master -> SSPreInit -> GLOB -> world -> config -> SSInit -> Failsafe //GOT IT MEMORIZED? -GLOBAL_VAR_INIT(MC_restart_clear, 0) -GLOBAL_VAR_INIT(MC_restart_timeout, 0) -GLOBAL_VAR_INIT(MC_restart_count, 0) - - -//current tick limit, assigned by the queue controller before running a subsystem. -//used by check_tick as well so that the procs subsystems call can obey that SS's tick limits -GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING) - /datum/controller/master name = "Master" @@ -59,6 +50,14 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING) var/current_runlevel //for scheduling different subsystems for different stages of the round + var/static/restart_clear = 0 + var/static/restart_timeout = 0 + var/static/restart_count = 0 + + //current tick limit, assigned before running a subsystem. + //used by CHECK_TICK as well so that the procs subsystems call can obey that SS's tick limits + var/static/current_ticklimit = TICK_LIMIT_RUNNING + /datum/controller/master/New() // Highlander-style: there can only be one! Kill off the old and replace it with the new. subsystems = list() @@ -90,14 +89,14 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING) // -1 if we encountered a runtime trying to recreate it /proc/Recreate_MC() . = -1 //so if we runtime, things know we failed - if (world.time < GLOB.MC_restart_timeout) + if (world.time < Master.restart_timeout) return 0 - if (world.time < GLOB.MC_restart_clear) - GLOB.MC_restart_count *= 0.5 + if (world.time < Master.restart_clear) + Master.restart_count *= 0.5 - var/delay = 50 * ++GLOB.MC_restart_count - GLOB.MC_restart_timeout = world.time + delay - GLOB.MC_restart_clear = world.time + (delay * 2) + var/delay = 50 * ++Master.restart_count + Master.restart_timeout = world.time + delay + Master.restart_clear = world.time + (delay * 2) Master.processing = 0 //stop ticking this one try new/datum/controller/master() @@ -165,13 +164,13 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING) var/start_timeofday = REALTIMEOFDAY // Initialize subsystems. - GLOB.CURRENT_TICKLIMIT = config.tick_limit_mc_init + current_ticklimit = config.tick_limit_mc_init for (var/datum/controller/subsystem/SS in subsystems) if (SS.flags & SS_NO_INIT) continue SS.Initialize(REALTIMEOFDAY) CHECK_TICK - GLOB.CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING + current_ticklimit = TICK_LIMIT_RUNNING var/time = (REALTIMEOFDAY - start_timeofday) / 10 var/msg = "Initializations complete within [time] second[time == 1 ? "" : "s"]!" @@ -206,6 +205,7 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING) set waitfor = 0 if(delay) sleep(delay) + testing("Master starting processing") var/rtn = Loop() if (rtn > 0 || processing < 0) return //this was suppose to happen. @@ -276,7 +276,7 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING) while (1) tickdrift = max(0, MC_AVERAGE_FAST(tickdrift, (((REALTIMEOFDAY - init_timeofday) - (world.time - init_time)) / world.tick_lag))) if (processing <= 0) - GLOB.CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING + current_ticklimit = TICK_LIMIT_RUNNING sleep(10) continue @@ -284,7 +284,7 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING) // because sleeps are processed in the order received, so longer sleeps are more likely to run first if (world.tick_usage > TICK_LIMIT_MC) sleep_delta += 2 - GLOB.CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING * 0.5 + current_ticklimit = TICK_LIMIT_RUNNING * 0.5 sleep(world.tick_lag * (processing + sleep_delta)) continue @@ -322,7 +322,7 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING) if (!error_level) iteration++ error_level++ - GLOB.CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING + current_ticklimit = TICK_LIMIT_RUNNING sleep(10) continue @@ -334,7 +334,7 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING) if (!error_level) iteration++ error_level++ - GLOB.CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING + current_ticklimit = TICK_LIMIT_RUNNING sleep(10) continue error_level-- @@ -345,7 +345,7 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING) iteration++ last_run = world.time src.sleep_delta = MC_AVERAGE_FAST(src.sleep_delta, sleep_delta) - GLOB.CURRENT_TICKLIMIT = TICK_LIMIT_RUNNING - (TICK_LIMIT_RUNNING * 0.25) //reserve the tail 1/4 of the next tick for the mc. + current_ticklimit = TICK_LIMIT_RUNNING - (TICK_LIMIT_RUNNING * 0.25) //reserve the tail 1/4 of the next tick for the mc. sleep(world.tick_lag * (processing + sleep_delta)) @@ -436,7 +436,7 @@ GLOBAL_VAR_INIT(CURRENT_TICKLIMIT, TICK_LIMIT_RUNNING) tick_precentage = max(tick_precentage*0.5, tick_precentage-queue_node.tick_overrun) - GLOB.CURRENT_TICKLIMIT = round(world.tick_usage + tick_precentage) + current_ticklimit = round(world.tick_usage + tick_precentage) if (!(queue_node_flags & SS_TICKER)) ran_non_ticker = TRUE diff --git a/code/controllers/subsystem/atoms.dm b/code/controllers/subsystem/atoms.dm index 0391f6ba70..48bdbad112 100644 --- a/code/controllers/subsystem/atoms.dm +++ b/code/controllers/subsystem/atoms.dm @@ -150,7 +150,7 @@ SUBSYSTEM_DEF(atoms) /datum/controller/subsystem/atoms/Shutdown() var/initlog = InitLog() if(initlog) - text2file("[GLOB.log_directory]/initialize.log", initlog) + text2file(initlog, "[GLOB.log_directory]/initialize.log") #undef BAD_INIT_QDEL_BEFORE #undef BAD_INIT_DIDNT_INIT diff --git a/code/controllers/subsystem/blackbox.dm b/code/controllers/subsystem/blackbox.dm index fa0b86a908..ecc5f3cc17 100644 --- a/code/controllers/subsystem/blackbox.dm +++ b/code/controllers/subsystem/blackbox.dm @@ -1,7 +1,8 @@ SUBSYSTEM_DEF(blackbox) name = "Blackbox" wait = 6000 - flags = SS_NO_TICK_CHECK + flags = SS_NO_TICK_CHECK | SS_NO_INIT + runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME var/list/msg_common = list() var/list/msg_science = list() diff --git a/code/controllers/subsystem/fields.dm b/code/controllers/subsystem/fields.dm deleted file mode 100644 index 8e9f387478..0000000000 --- a/code/controllers/subsystem/fields.dm +++ /dev/null @@ -1,27 +0,0 @@ - -SUBSYSTEM_DEF(fields) - name = "Fields" - wait = 2 - priority = 40 - flags = SS_KEEP_TIMING - var/list/datum/proximity_monitor/advanced/running = list() - var/list/datum/proximity_monitor/advanced/currentrun = list() - -/datum/controller/subsystem/fields/fire(resumed = 0) - if(!resumed) - src.currentrun = running.Copy() - var/list/currentrun = src.currentrun - while(currentrun.len) - var/datum/proximity_monitor/advanced/F = currentrun[currentrun.len] - currentrun.len-- - if(!F.requires_processing) - continue - F.process() - if(MC_TICK_CHECK) - return - -/datum/controller/subsystem/fields/proc/register_new_field(datum/proximity_monitor/advanced/F) - running += F - -/datum/controller/subsystem/fields/proc/unregister_field(datum/proximity_monitor/advanced/F) - running -= F diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index 84d79009c0..2611bc53e6 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -61,7 +61,7 @@ SUBSYSTEM_DEF(garbage) for(var/path in sleptDestroy) dellog += "Path : [path] \n" dellog += "Sleeps : [sleptDestroy[path]] \n" - text2file("[GLOB.log_directory]/qdel.log", dellog.Join()) + text2file(dellog.Join(), "[GLOB.log_directory]/qdel.log") /datum/controller/subsystem/garbage/fire() HandleToBeQueued() diff --git a/code/controllers/subsystem/processing/fields.dm b/code/controllers/subsystem/processing/fields.dm new file mode 100644 index 0000000000..6a878fa142 --- /dev/null +++ b/code/controllers/subsystem/processing/fields.dm @@ -0,0 +1,6 @@ +PROCESSING_SUBSYSTEM_DEF(fields) + name = "Fields" + wait = 2 + priority = 40 + flags = SS_KEEP_TIMING | SS_NO_INIT + runlevels = RUNLEVEL_GAME | RUNLEVEL_POSTGAME diff --git a/code/datums/martial.dm b/code/datums/martial.dm index b20bf556d5..fa02a2f092 100644 --- a/code/datums/martial.dm +++ b/code/datums/martial.dm @@ -79,681 +79,17 @@ /datum/martial_art/proc/teach(mob/living/carbon/human/H,make_temporary=0) if(make_temporary) temporary = 1 - if(temporary && H.martial_art) - if(!H.martial_art.allow_temp_override) + if(temporary && H.mind.martial_art) + if(!H.mind.martial_art.allow_temp_override) return - base = H.martial_art + base = H.mind.martial_art if(help_verb) H.verbs += help_verb - H.martial_art = src + H.mind.martial_art = src /datum/martial_art/proc/remove(mob/living/carbon/human/H) - if(H.martial_art != src) + if(H.mind.martial_art != src) return - H.martial_art = base + H.mind.martial_art = base if(help_verb) H.verbs -= help_verb - -/datum/martial_art/boxing - name = "Boxing" - -/datum/martial_art/boxing/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) - to_chat(A, "Can't disarm while boxing!") - return 1 - -/datum/martial_art/boxing/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D) - to_chat(A, "Can't grab while boxing!") - return 1 - -/datum/martial_art/boxing/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) - - A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) - - var/atk_verb = pick("left hook","right hook","straight punch") - - var/damage = rand(5, 8) + A.dna.species.punchdamagelow - if(!damage) - playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1) - D.visible_message("[A] has attempted to [atk_verb] [D]!", \ - "[A] has attempted to [atk_verb] [D]!", null, COMBAT_MESSAGE_RANGE) - add_logs(A, D, "attempted to hit", atk_verb) - return 0 - - - var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.zone_selected)) - var/armor_block = D.run_armor_check(affecting, "melee") - - playsound(D.loc, A.dna.species.attack_sound, 25, 1, -1) - - D.visible_message("[A] has [atk_verb]ed [D]!", \ - "[A] has [atk_verb]ed [D]!", null, COMBAT_MESSAGE_RANGE) - - D.apply_damage(damage, STAMINA, affecting, armor_block) - add_logs(A, D, "punched (boxing) ") - if(D.getStaminaLoss() > 50) - var/knockout_prob = D.getStaminaLoss() + rand(-15,15) - if((D.stat != DEAD) && prob(knockout_prob)) - D.visible_message("[A] has knocked [D] out with a haymaker!", \ - "[A] has knocked [D] out with a haymaker!") - D.apply_effect(10,WEAKEN,armor_block) - D.SetSleeping(5) - D.forcesay(GLOB.hit_appends) - add_logs(A, D, "knocked out (boxing) ") - else if(D.lying) - D.forcesay(GLOB.hit_appends) - return 1 - -/mob/living/carbon/human/proc/wrestling_help() - set name = "Recall Teachings" - set desc = "Remember how to wrestle." - set category = "Wrestling" - - to_chat(usr, "You flex your muscles and have a revelation...") - to_chat(usr, "Clinch: Grab. Passively gives you a chance to immediately aggressively grab someone. Not always successful.") - to_chat(usr, "Suplex: Disarm someone you are grabbing. Suplexes your target to the floor. Greatly injures them and leaves both you and your target on the floor.") - to_chat(usr, "Advanced grab: Grab. Passively causes stamina damage when grabbing someone.") - -#define TORNADO_COMBO "HHD" -#define THROWBACK_COMBO "DHD" -#define PLASMA_COMBO "HDDDH" - -/datum/martial_art/plasma_fist - name = "Plasma Fist" - help_verb = /mob/living/carbon/human/proc/plasma_fist_help - - -/datum/martial_art/plasma_fist/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D) - if(findtext(streak,TORNADO_COMBO)) - streak = "" - Tornado(A,D) - return 1 - if(findtext(streak,THROWBACK_COMBO)) - streak = "" - Throwback(A,D) - return 1 - if(findtext(streak,PLASMA_COMBO)) - streak = "" - Plasma(A,D) - return 1 - return 0 - -/datum/martial_art/plasma_fist/proc/TornadoAnimate(mob/living/carbon/human/A) - set waitfor = FALSE - for(var/i in list(NORTH,SOUTH,EAST,WEST,EAST,SOUTH,NORTH,SOUTH,EAST,WEST,EAST,SOUTH)) - if(!A) - break - A.setDir(i) - playsound(A.loc, 'sound/weapons/punch1.ogg', 15, 1, -1) - sleep(1) - -/datum/martial_art/plasma_fist/proc/Tornado(mob/living/carbon/human/A, mob/living/carbon/human/D) - A.say("TORNADO SWEEP!") - TornadoAnimate(A) - var/obj/effect/proc_holder/spell/aoe_turf/repulse/R = new(null) - var/list/turfs = list() - for(var/turf/T in range(1,A)) - turfs.Add(T) - R.cast(turfs) - add_logs(A, D, "tornado sweeped(Plasma Fist)") - return - -/datum/martial_art/plasma_fist/proc/Throwback(mob/living/carbon/human/A, mob/living/carbon/human/D) - D.visible_message("[A] has hit [D] with Plasma Punch!", \ - "[A] has hit [D] with Plasma Punch!") - playsound(D.loc, 'sound/weapons/punch1.ogg', 50, 1, -1) - var/atom/throw_target = get_edge_target_turf(D, get_dir(D, get_step_away(D, A))) - D.throw_at(throw_target, 200, 4,A) - A.say("HYAH!") - add_logs(A, D, "threw back (Plasma Fist)") - return - -/datum/martial_art/plasma_fist/proc/Plasma(mob/living/carbon/human/A, mob/living/carbon/human/D) - A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) - playsound(D.loc, 'sound/weapons/punch1.ogg', 50, 1, -1) - A.say("PLASMA FIST!") - D.visible_message("[A] has hit [D] with THE PLASMA FIST TECHNIQUE!", \ - "[A] has hit [D] with THE PLASMA FIST TECHNIQUE!") - D.gib() - add_logs(A, D, "gibbed (Plasma Fist)") - return - -/datum/martial_art/plasma_fist/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) - add_to_streak("H",D) - if(check_streak(A,D)) - return 1 - basic_hit(A,D) - return 1 - -/datum/martial_art/plasma_fist/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) - add_to_streak("D",D) - if(check_streak(A,D)) - return 1 - basic_hit(A,D) - return 1 - -/datum/martial_art/plasma_fist/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D) - add_to_streak("G",D) - if(check_streak(A,D)) - return 1 - basic_hit(A,D) - return 1 - -/mob/living/carbon/human/proc/plasma_fist_help() - set name = "Recall Teachings" - set desc = "Remember the martial techniques of the Plasma Fist." - set category = "Plasma Fist" - - to_chat(usr, "You clench your fists and have a flashback of knowledge...") - to_chat(usr, "Tornado Sweep: Harm Harm Disarm. Repulses target and everyone back.") - to_chat(usr, "Throwback: Disarm Harm Disarm. Throws the target and an item at them.") - to_chat(usr, "The Plasma Fist: Harm Disarm Disarm Disarm Harm. Knocks the brain out of the opponent and gibs their body.") - -//Used by the gang of the same name. Uses combos. Basic attacks bypass armor and never miss -#define WRIST_WRENCH_COMBO "DD" -#define BACK_KICK_COMBO "HG" -#define STOMACH_KNEE_COMBO "GH" -#define HEAD_KICK_COMBO "DHH" -#define ELBOW_DROP_COMBO "HDHDH" -/datum/martial_art/the_sleeping_carp - name = "The Sleeping Carp" - deflection_chance = 100 - no_guns = TRUE - allow_temp_override = FALSE - help_verb = /mob/living/carbon/human/proc/sleeping_carp_help - -/datum/martial_art/the_sleeping_carp/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D) - if(findtext(streak,WRIST_WRENCH_COMBO)) - streak = "" - wristWrench(A,D) - return 1 - if(findtext(streak,BACK_KICK_COMBO)) - streak = "" - backKick(A,D) - return 1 - if(findtext(streak,STOMACH_KNEE_COMBO)) - streak = "" - kneeStomach(A,D) - return 1 - if(findtext(streak,HEAD_KICK_COMBO)) - streak = "" - headKick(A,D) - return 1 - if(findtext(streak,ELBOW_DROP_COMBO)) - streak = "" - elbowDrop(A,D) - return 1 - return 0 - -/datum/martial_art/the_sleeping_carp/proc/wristWrench(mob/living/carbon/human/A, mob/living/carbon/human/D) - if(!D.stat && !D.stunned && !D.weakened) - A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) - D.visible_message("[A] grabs [D]'s wrist and wrenches it sideways!", \ - "[A] grabs your wrist and violently wrenches it to the side!") - playsound(get_turf(A), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) - D.emote("scream") - D.drop_item() - D.apply_damage(5, BRUTE, pick("l_arm", "r_arm")) - D.Stun(3) - return 1 - add_logs(A, D, "wrist wrenched (Sleeping Carp)") - return basic_hit(A,D) - -/datum/martial_art/the_sleeping_carp/proc/backKick(mob/living/carbon/human/A, mob/living/carbon/human/D) - if(A.dir == D.dir && !D.stat && !D.weakened) - A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) - D.visible_message("[A] kicks [D] in the back!", \ - "[A] kicks you in the back, making you stumble and fall!") - step_to(D,get_step(D,D.dir),1) - D.Weaken(4) - playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1) - return 1 - add_logs(A, D, "back-kicked (Sleeping Carp)") - return basic_hit(A,D) - -/datum/martial_art/the_sleeping_carp/proc/kneeStomach(mob/living/carbon/human/A, mob/living/carbon/human/D) - if(!D.stat && !D.weakened) - A.do_attack_animation(D, ATTACK_EFFECT_KICK) - D.visible_message("[A] knees [D] in the stomach!", \ - "[A] winds you with a knee in the stomach!") - D.audible_message("[D] gags!") - D.losebreath += 3 - D.Stun(2) - playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1) - return 1 - add_logs(A, D, "stomach kneed (Sleeping Carp)") - return basic_hit(A,D) - -/datum/martial_art/the_sleeping_carp/proc/headKick(mob/living/carbon/human/A, mob/living/carbon/human/D) - if(!D.stat && !D.weakened) - A.do_attack_animation(D, ATTACK_EFFECT_KICK) - D.visible_message("[A] kicks [D] in the head!", \ - "[A] kicks you in the jaw!") - D.apply_damage(20, BRUTE, "head") - D.drop_item() - playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1) - D.Stun(4) - return 1 - add_logs(A, D, "head kicked (Sleeping Carp)") - return basic_hit(A,D) - -/datum/martial_art/the_sleeping_carp/proc/elbowDrop(mob/living/carbon/human/A, mob/living/carbon/human/D) - if(D.weakened || D.resting || D.stat) - A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) - D.visible_message("[A] elbow drops [D]!", \ - "[A] piledrives you with their elbow!") - if(D.stat) - D.death() //FINISH HIM! - D.apply_damage(50, BRUTE, "chest") - playsound(get_turf(D), 'sound/weapons/punch1.ogg', 75, 1, -1) - return 1 - add_logs(A, D, "elbow dropped (Sleeping Carp)") - return basic_hit(A,D) - -/datum/martial_art/the_sleeping_carp/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D) - add_to_streak("G",D) - if(check_streak(A,D)) - return 1 - if(A.grab_state >= GRAB_AGGRESSIVE) - D.grabbedby(A, 1) - else - A.start_pulling(D, 1) - if(A.pulling) - D.drop_all_held_items() - D.stop_pulling() - if(A.a_intent == INTENT_GRAB) - add_logs(A, D, "grabbed", addition="aggressively") - A.grab_state = GRAB_AGGRESSIVE //Instant aggressive grab - else - add_logs(A, D, "grabbed", addition="passively") - A.grab_state = GRAB_PASSIVE - return 1 - -/datum/martial_art/the_sleeping_carp/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) - add_to_streak("H",D) - if(check_streak(A,D)) - return 1 - A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) - var/atk_verb = pick("punches", "kicks", "chops", "hits", "slams") - D.visible_message("[A] [atk_verb] [D]!", \ - "[A] [atk_verb] you!") - D.apply_damage(rand(10,15), BRUTE) - playsound(get_turf(D), 'sound/weapons/punch1.ogg', 25, 1, -1) - if(prob(D.getBruteLoss()) && !D.lying) - D.visible_message("[D] stumbles and falls!", "The blow sends you to the ground!") - D.Weaken(4) - add_logs(A, D, "[atk_verb] (Sleeping Carp)") - return 1 - - -/datum/martial_art/the_sleeping_carp/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) - add_to_streak("D",D) - if(check_streak(A,D)) - return 1 - return ..() - -/mob/living/carbon/human/proc/sleeping_carp_help() - set name = "Recall Teachings" - set desc = "Remember the martial techniques of the Sleeping Carp clan." - set category = "Sleeping Carp" - - to_chat(usr, "You retreat inward and recall the teachings of the Sleeping Carp...") - - to_chat(usr, "Wrist Wrench: Disarm Disarm. Forces opponent to drop item in hand.") - to_chat(usr, "Back Kick: Harm Grab. Opponent must be facing away. Knocks down.") - to_chat(usr, "Stomach Knee: Grab Harm. Knocks the wind out of opponent and stuns.") - to_chat(usr, "Head Kick: Disarm Harm Harm. Decent damage, forces opponent to drop item in hand.") - to_chat(usr, "Elbow Drop: Harm Disarm Harm Disarm Harm. Opponent must be on the ground. Deals huge damage, instantly kills anyone in critical condition.") - -//CQC -#define SLAM_COMBO "GH" -#define KICK_COMBO "HH" -#define RESTRAIN_COMBO "GG" -#define PRESSURE_COMBO "DG" -#define CONSECUTIVE_COMBO "DDH" -/datum/martial_art/cqc - name = "CQC" - help_verb = /mob/living/carbon/human/proc/CQC_help - block_chance = 75 - -/datum/martial_art/cqc/proc/drop_restraining() - restraining = 0 - -/datum/martial_art/cqc/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D) - if(findtext(streak,SLAM_COMBO)) - streak = "" - Slam(A,D) - return 1 - if(findtext(streak,KICK_COMBO)) - streak = "" - Kick(A,D) - return 1 - if(findtext(streak,RESTRAIN_COMBO)) - streak = "" - Restrain(A,D) - return 1 - if(findtext(streak,PRESSURE_COMBO)) - streak = "" - Pressure(A,D) - return 1 - if(findtext(streak,CONSECUTIVE_COMBO)) - streak = "" - Consecutive(A,D) - return 0 - -/datum/martial_art/cqc/proc/Slam(mob/living/carbon/human/A, mob/living/carbon/human/D) - if(!D.stat || !D.weakened) - D.visible_message("[A] slams [D] into the ground!", \ - "[A] slams you into the ground!") - playsound(get_turf(A), 'sound/weapons/slam.ogg', 50, 1, -1) - D.apply_damage(10, BRUTE) - D.Weaken(6) - add_logs(A, D, "cqc slammed") - return 1 - -/datum/martial_art/cqc/proc/Kick(mob/living/carbon/human/A, mob/living/carbon/human/D) - if(!D.stat || !D.weakened) - D.visible_message("[A] kicks [D] back!", \ - "[A] kicks you back!") - playsound(get_turf(A), 'sound/weapons/cqchit1.ogg', 50, 1, -1) - var/atom/throw_target = get_edge_target_turf(D, A.dir) - D.throw_at(throw_target, 1, 14, A) - D.apply_damage(10, BRUTE) - add_logs(A, D, "cqc kicked") - if(D.weakened && !D.stat) - D.visible_message("[A] kicks [D]'s head, knocking them out!", \ - "[A] kicks your head, knocking you out!") - playsound(get_turf(A), 'sound/weapons/genhit1.ogg', 50, 1, -1) - D.SetSleeping(15) - D.adjustBrainLoss(25) - return 1 - -/datum/martial_art/cqc/proc/Pressure(mob/living/carbon/human/A, mob/living/carbon/human/D) - D.visible_message("[A] forces their arm on [D]'s neck!") - D.adjustStaminaLoss(60) - playsound(get_turf(A), 'sound/weapons/cqchit1.ogg', 50, 1, -1) - return 1 - -/datum/martial_art/cqc/proc/Restrain(mob/living/carbon/human/A, mob/living/carbon/human/D) - if(restraining) - return - if(!D.stat) - D.visible_message("[A] locks [D] into a restraining position!", \ - "[A] locks you into a restraining position!") - D.adjustStaminaLoss(20) - D.Stun(5) - restraining = 1 - addtimer(CALLBACK(src, .proc/drop_restraining), 50, TIMER_UNIQUE) - return 1 - -/datum/martial_art/cqc/proc/Consecutive(mob/living/carbon/human/A, mob/living/carbon/human/D) - if(!D.stat) - D.visible_message("[A] strikes [D]'s abdomen, neck and back consecutively", \ - "[A] strikes your abdomen, neck and back consecutively!") - playsound(get_turf(D), 'sound/weapons/cqchit2.ogg', 50, 1, -1) - var/obj/item/I = D.get_active_held_item() - if(I && D.drop_item()) - A.put_in_hands(I) - D.adjustStaminaLoss(50) - D.apply_damage(25, BRUTE) - return 1 - -/datum/martial_art/cqc/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D) - add_to_streak("G",D) - if(check_streak(A,D)) - return 1 - if(A.grab_state >= GRAB_AGGRESSIVE) - D.grabbedby(A, 1) - else - A.start_pulling(D, 1) - if(A.pulling) - D.stop_pulling() - add_logs(A, D, "grabbed", addition="aggressively") - A.grab_state = GRAB_AGGRESSIVE //Instant aggressive grab - - return 1 - -/datum/martial_art/cqc/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) - add_to_streak("H",D) - if(check_streak(A,D)) - return 1 - add_logs(A, D, "CQC'd") - A.do_attack_animation(D) - var/picked_hit_type = pick("CQC'd", "Big Bossed") - var/bonus_damage = 13 - if(D.weakened || D.resting || D.lying) - bonus_damage += 5 - picked_hit_type = "stomps on" - D.apply_damage(bonus_damage, BRUTE) - if(picked_hit_type == "kicks" || picked_hit_type == "stomps on") - playsound(get_turf(D), 'sound/weapons/cqchit2.ogg', 50, 1, -1) - else - playsound(get_turf(D), 'sound/weapons/cqchit1.ogg', 50, 1, -1) - D.visible_message("[A] [picked_hit_type] [D]!", \ - "[A] [picked_hit_type] you!") - add_logs(A, D, "[picked_hit_type] with CQC") - if(A.resting && !D.stat && !D.weakened) - D.visible_message("[A] leg sweeps [D]!", \ - "[A] leg sweeps you!") - playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, 1, -1) - D.apply_damage(10, BRUTE) - D.Weaken(3) - add_logs(A, D, "cqc sweeped") - return 1 - -/datum/martial_art/cqc/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) - add_to_streak("D",D) - var/obj/item/I = null - if(check_streak(A,D)) - return 1 - if(prob(65)) - if(!D.stat || !D.weakened || !restraining) - I = D.get_active_held_item() - D.visible_message("[A] strikes [D]'s jaw with their hand!", \ - "[A] strikes your jaw, disorienting you!") - playsound(get_turf(D), 'sound/weapons/cqchit1.ogg', 50, 1, -1) - if(I && D.drop_item()) - A.put_in_hands(I) - D.Jitter(2) - D.apply_damage(5, BRUTE) - else - D.visible_message("[A] attempted to disarm [D]!", \ - "[A] attempted to disarm [D]!") - playsound(D, 'sound/weapons/punchmiss.ogg', 25, 1, -1) - add_logs(A, D, "disarmed with CQC", "[I ? " grabbing \the [I]" : ""]") - if(restraining && A.pulling == D) - D.visible_message("[A] puts [D] into a chokehold!", \ - "[A] puts you into a chokehold!") - D.SetSleeping(20) - restraining = 0 - if(A.grab_state < GRAB_NECK) - A.grab_state = GRAB_NECK - else - restraining = 0 - return 0 - return 1 - -/mob/living/carbon/human/proc/CQC_help() - set name = "Remember The Basics" - set desc = "You try to remember some of the basics of CQC." - set category = "CQC" - - to_chat(usr, "You try to remember some of the basics of CQC.") - - to_chat(usr, "Slam: Grab Harm. Slam opponent into the ground, weakens and knocks down.") - to_chat(usr, "CQC Kick: Harm Disarm Harm. Knocks opponent away. Knocks out stunned or weakened opponents.") - to_chat(usr, "Restrain: Grab Grab. Locks opponents into a restraining position, disarm to knock them out with a choke hold.") - to_chat(usr, "Pressure: Disarm Grab. Decent stamina damage.") - to_chat(usr, "Consecutive CQC: Disarm Disarm Harm. Mainly offensive move, huge damage and decent stamina damage.") - - to_chat(usr, "In addition, by having your throw mode on when being attacked, you enter an active defense mode where you have a chance to block and sometimes even counter attacks done to you.") - -//ITEMS - -/obj/item/clothing/gloves/boxing - var/datum/martial_art/boxing/style = new - -/obj/item/clothing/gloves/boxing/equipped(mob/user, slot) - if(!ishuman(user)) - return - if(slot == slot_gloves) - var/mob/living/carbon/human/H = user - style.teach(H,1) - return - -/obj/item/clothing/gloves/boxing/dropped(mob/user) - if(!ishuman(user)) - return - var/mob/living/carbon/human/H = user - if(H.get_item_by_slot(slot_gloves) == src) - style.remove(H) - return - -/obj/item/weapon/storage/belt/champion/wrestling - name = "Wrestling Belt" - var/datum/martial_art/wrestling/style = new - -/obj/item/weapon/storage/belt/champion/wrestling/equipped(mob/user, slot) - if(!ishuman(user)) - return - if(slot == slot_belt) - var/mob/living/carbon/human/H = user - style.teach(H,1) - return - -/obj/item/weapon/storage/belt/champion/wrestling/dropped(mob/user) - if(!ishuman(user)) - return - var/mob/living/carbon/human/H = user - if(H.get_item_by_slot(slot_belt) == src) - style.remove(H) - return - -/obj/item/weapon/plasma_fist_scroll - name = "frayed scroll" - desc = "An aged and frayed scrap of paper written in shifting runes. There are hand-drawn illustrations of pugilism." - icon = 'icons/obj/wizard.dmi' - icon_state ="scroll2" - var/used = 0 - -/obj/item/weapon/plasma_fist_scroll/attack_self(mob/user) - if(!ishuman(user)) - return - if(!used) - var/mob/living/carbon/human/H = user - var/datum/martial_art/plasma_fist/F = new/datum/martial_art/plasma_fist(null) - F.teach(H) - to_chat(H, "You have learned the ancient martial art of Plasma Fist.") - used = 1 - desc = "It's completely blank." - name = "empty scroll" - icon_state = "blankscroll" - -/obj/item/weapon/cqc_manual - name = "old manual" - desc = "A small, black manual. There are drawn instructions of tactical hand-to-hand combat." - icon = 'icons/obj/library.dmi' - icon_state ="cqcmanual" - -/obj/item/weapon/cqc_manual/attack_self(mob/living/carbon/human/user) - if(!istype(user) || !user) - return - to_chat(user, "You remember the basics of CQC.") - var/datum/martial_art/cqc/D = new(null) - D.teach(user) - user.drop_item() - visible_message("[src] beeps ominously, and a moment later it bursts up in flames.") - new /obj/effect/decal/cleanable/ash(get_turf(src)) - qdel(src) - -/obj/item/weapon/sleeping_carp_scroll - name = "mysterious scroll" - desc = "A scroll filled with strange markings. It seems to be drawings of some sort of martial art." - icon = 'icons/obj/wizard.dmi' - icon_state = "scroll2" - -/obj/item/weapon/sleeping_carp_scroll/attack_self(mob/living/carbon/human/user) - if(!istype(user) || !user) - return - var/message = "You have learned the ancient martial art of the Sleeping Carp! Your hand-to-hand combat has become much more effective, and you are now able to deflect any projectiles \ - directed toward you. However, you are also unable to use any ranged weaponry. You can learn more about your newfound art by using the Recall Teachings verb in the Sleeping Carp tab." - to_chat(user, message) - var/datum/martial_art/the_sleeping_carp/theSleepingCarp = new(null) - theSleepingCarp.teach(user) - user.drop_item() - visible_message("[src] lights up in fire and quickly burns to ash.") - new /obj/effect/decal/cleanable/ash(get_turf(src)) - qdel(src) - -/obj/item/weapon/twohanded/bostaff - name = "bo staff" - desc = "A long, tall staff made of polished wood. Traditionally used in ancient old-Earth martial arts. Can be wielded to both kill and incapacitate." - force = 10 - w_class = WEIGHT_CLASS_BULKY - slot_flags = SLOT_BACK - force_unwielded = 10 - force_wielded = 24 - throwforce = 20 - throw_speed = 2 - attack_verb = list("smashed", "slammed", "whacked", "thwacked") - icon = 'icons/obj/weapons.dmi' - icon_state = "bostaff0" - block_chance = 50 - -/obj/item/weapon/twohanded/bostaff/update_icon() - icon_state = "bostaff[wielded]" - return - -/obj/item/weapon/twohanded/bostaff/attack(mob/target, mob/living/user) - add_fingerprint(user) - if((CLUMSY in user.disabilities) && prob(50)) - to_chat(user, "You club yourself over the head with [src].") - user.Weaken(3) - if(ishuman(user)) - var/mob/living/carbon/human/H = user - H.apply_damage(2*force, BRUTE, "head") - else - user.take_bodypart_damage(2*force) - return - if(iscyborg(target)) - return ..() - if(!isliving(target)) - return ..() - var/mob/living/carbon/C = target - if(C.stat) - to_chat(user, "It would be dishonorable to attack a foe while they cannot retaliate.") - return - if(user.a_intent == INTENT_DISARM) - if(!wielded) - return ..() - if(!ishuman(target)) - return ..() - var/mob/living/carbon/human/H = target - var/list/fluffmessages = list("[user] clubs [H] with [src]!", \ - "[user] smacks [H] with the butt of [src]!", \ - "[user] broadsides [H] with [src]!", \ - "[user] smashes [H]'s head with [src]!", \ - "[user] beats [H] with front of [src]!", \ - "[user] twirls and slams [H] with [src]!") - H.visible_message("[pick(fluffmessages)]", \ - "[pick(fluffmessages)]") - playsound(get_turf(user), 'sound/effects/woodhit.ogg', 75, 1, -1) - H.adjustStaminaLoss(rand(13,20)) - if(prob(10)) - H.visible_message("[H] collapses!", \ - "Your legs give out!") - H.Weaken(4) - if(H.staminaloss && !H.sleeping) - var/total_health = (H.health - H.staminaloss) - if(total_health <= HEALTH_THRESHOLD_CRIT && !H.stat) - H.visible_message("[user] delivers a heavy hit to [H]'s head, knocking them out cold!", \ - "[user] knocks you unconscious!") - H.SetSleeping(30) - H.adjustBrainLoss(25) - else - return ..() - -/obj/item/weapon/twohanded/bostaff/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance) - if(wielded) - return ..() - return 0 - diff --git a/code/datums/martial/boxing.dm b/code/datums/martial/boxing.dm new file mode 100644 index 0000000000..6a3a059890 --- /dev/null +++ b/code/datums/martial/boxing.dm @@ -0,0 +1,67 @@ +/datum/martial_art/boxing + name = "Boxing" + +/datum/martial_art/boxing/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) + to_chat(A, "Can't disarm while boxing!") + return 1 + +/datum/martial_art/boxing/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D) + to_chat(A, "Can't grab while boxing!") + return 1 + +/datum/martial_art/boxing/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) + + A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) + + var/atk_verb = pick("left hook","right hook","straight punch") + + var/damage = rand(5, 8) + A.dna.species.punchdamagelow + if(!damage) + playsound(D.loc, A.dna.species.miss_sound, 25, 1, -1) + D.visible_message("[A] has attempted to [atk_verb] [D]!", \ + "[A] has attempted to [atk_verb] [D]!", null, COMBAT_MESSAGE_RANGE) + add_logs(A, D, "attempted to hit", atk_verb) + return 0 + + + var/obj/item/bodypart/affecting = D.get_bodypart(ran_zone(A.zone_selected)) + var/armor_block = D.run_armor_check(affecting, "melee") + + playsound(D.loc, A.dna.species.attack_sound, 25, 1, -1) + + D.visible_message("[A] has [atk_verb]ed [D]!", \ + "[A] has [atk_verb]ed [D]!", null, COMBAT_MESSAGE_RANGE) + + D.apply_damage(damage, STAMINA, affecting, armor_block) + add_logs(A, D, "punched (boxing) ") + if(D.getStaminaLoss() > 50) + var/knockout_prob = D.getStaminaLoss() + rand(-15,15) + if((D.stat != DEAD) && prob(knockout_prob)) + D.visible_message("[A] has knocked [D] out with a haymaker!", \ + "[A] has knocked [D] out with a haymaker!") + D.apply_effect(10,WEAKEN,armor_block) + D.SetSleeping(5) + D.forcesay(GLOB.hit_appends) + add_logs(A, D, "knocked out (boxing) ") + else if(D.lying) + D.forcesay(GLOB.hit_appends) + return 1 + +/obj/item/clothing/gloves/boxing + var/datum/martial_art/boxing/style = new + +/obj/item/clothing/gloves/boxing/equipped(mob/user, slot) + if(!ishuman(user)) + return + if(slot == slot_gloves) + var/mob/living/carbon/human/H = user + style.teach(H,1) + return + +/obj/item/clothing/gloves/boxing/dropped(mob/user) + if(!ishuman(user)) + return + var/mob/living/carbon/human/H = user + if(H.get_item_by_slot(slot_gloves) == src) + style.remove(H) + return diff --git a/code/datums/martial/cqc.dm b/code/datums/martial/cqc.dm new file mode 100644 index 0000000000..ebb570fa0c --- /dev/null +++ b/code/datums/martial/cqc.dm @@ -0,0 +1,199 @@ +#define SLAM_COMBO "GH" +#define KICK_COMBO "HH" +#define RESTRAIN_COMBO "GG" +#define PRESSURE_COMBO "DG" +#define CONSECUTIVE_COMBO "DDH" + +/datum/martial_art/cqc + name = "CQC" + help_verb = /mob/living/carbon/human/proc/CQC_help + block_chance = 75 + +/datum/martial_art/cqc/proc/drop_restraining() + restraining = 0 + +/datum/martial_art/cqc/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D) + if(findtext(streak,SLAM_COMBO)) + streak = "" + Slam(A,D) + return 1 + if(findtext(streak,KICK_COMBO)) + streak = "" + Kick(A,D) + return 1 + if(findtext(streak,RESTRAIN_COMBO)) + streak = "" + Restrain(A,D) + return 1 + if(findtext(streak,PRESSURE_COMBO)) + streak = "" + Pressure(A,D) + return 1 + if(findtext(streak,CONSECUTIVE_COMBO)) + streak = "" + Consecutive(A,D) + return 0 + +/datum/martial_art/cqc/proc/Slam(mob/living/carbon/human/A, mob/living/carbon/human/D) + if(!D.stat || !D.weakened) + D.visible_message("[A] slams [D] into the ground!", \ + "[A] slams you into the ground!") + playsound(get_turf(A), 'sound/weapons/slam.ogg', 50, 1, -1) + D.apply_damage(10, BRUTE) + D.Weaken(6) + add_logs(A, D, "cqc slammed") + return 1 + +/datum/martial_art/cqc/proc/Kick(mob/living/carbon/human/A, mob/living/carbon/human/D) + if(!D.stat || !D.weakened) + D.visible_message("[A] kicks [D] back!", \ + "[A] kicks you back!") + playsound(get_turf(A), 'sound/weapons/cqchit1.ogg', 50, 1, -1) + var/atom/throw_target = get_edge_target_turf(D, A.dir) + D.throw_at(throw_target, 1, 14, A) + D.apply_damage(10, BRUTE) + add_logs(A, D, "cqc kicked") + if(D.weakened && !D.stat) + D.visible_message("[A] kicks [D]'s head, knocking them out!", \ + "[A] kicks your head, knocking you out!") + playsound(get_turf(A), 'sound/weapons/genhit1.ogg', 50, 1, -1) + D.SetSleeping(15) + D.adjustBrainLoss(25) + return 1 + +/datum/martial_art/cqc/proc/Pressure(mob/living/carbon/human/A, mob/living/carbon/human/D) + D.visible_message("[A] forces their arm on [D]'s neck!") + D.adjustStaminaLoss(60) + playsound(get_turf(A), 'sound/weapons/cqchit1.ogg', 50, 1, -1) + return 1 + +/datum/martial_art/cqc/proc/Restrain(mob/living/carbon/human/A, mob/living/carbon/human/D) + if(restraining) + return + if(!D.stat) + D.visible_message("[A] locks [D] into a restraining position!", \ + "[A] locks you into a restraining position!") + D.adjustStaminaLoss(20) + D.Stun(5) + restraining = 1 + addtimer(CALLBACK(src, .proc/drop_restraining), 50, TIMER_UNIQUE) + return 1 + +/datum/martial_art/cqc/proc/Consecutive(mob/living/carbon/human/A, mob/living/carbon/human/D) + if(!D.stat) + D.visible_message("[A] strikes [D]'s abdomen, neck and back consecutively", \ + "[A] strikes your abdomen, neck and back consecutively!") + playsound(get_turf(D), 'sound/weapons/cqchit2.ogg', 50, 1, -1) + var/obj/item/I = D.get_active_held_item() + if(I && D.drop_item()) + A.put_in_hands(I) + D.adjustStaminaLoss(50) + D.apply_damage(25, BRUTE) + return 1 + +/datum/martial_art/cqc/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D) + add_to_streak("G",D) + if(check_streak(A,D)) + return 1 + if(A.grab_state >= GRAB_AGGRESSIVE) + D.grabbedby(A, 1) + else + A.start_pulling(D, 1) + if(A.pulling) + D.stop_pulling() + add_logs(A, D, "grabbed", addition="aggressively") + A.grab_state = GRAB_AGGRESSIVE //Instant aggressive grab + + return 1 + +/datum/martial_art/cqc/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) + add_to_streak("H",D) + if(check_streak(A,D)) + return 1 + add_logs(A, D, "CQC'd") + A.do_attack_animation(D) + var/picked_hit_type = pick("CQC'd", "Big Bossed") + var/bonus_damage = 13 + if(D.weakened || D.resting || D.lying) + bonus_damage += 5 + picked_hit_type = "stomps on" + D.apply_damage(bonus_damage, BRUTE) + if(picked_hit_type == "kicks" || picked_hit_type == "stomps on") + playsound(get_turf(D), 'sound/weapons/cqchit2.ogg', 50, 1, -1) + else + playsound(get_turf(D), 'sound/weapons/cqchit1.ogg', 50, 1, -1) + D.visible_message("[A] [picked_hit_type] [D]!", \ + "[A] [picked_hit_type] you!") + add_logs(A, D, "[picked_hit_type] with CQC") + if(A.resting && !D.stat && !D.weakened) + D.visible_message("[A] leg sweeps [D]!", \ + "[A] leg sweeps you!") + playsound(get_turf(A), 'sound/effects/hit_kick.ogg', 50, 1, -1) + D.apply_damage(10, BRUTE) + D.Weaken(3) + add_logs(A, D, "cqc sweeped") + return 1 + +/datum/martial_art/cqc/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) + add_to_streak("D",D) + var/obj/item/I = null + if(check_streak(A,D)) + return 1 + if(prob(65)) + if(!D.stat || !D.weakened || !restraining) + I = D.get_active_held_item() + D.visible_message("[A] strikes [D]'s jaw with their hand!", \ + "[A] strikes your jaw, disorienting you!") + playsound(get_turf(D), 'sound/weapons/cqchit1.ogg', 50, 1, -1) + if(I && D.drop_item()) + A.put_in_hands(I) + D.Jitter(2) + D.apply_damage(5, BRUTE) + else + D.visible_message("[A] attempted to disarm [D]!", \ + "[A] attempted to disarm [D]!") + playsound(D, 'sound/weapons/punchmiss.ogg', 25, 1, -1) + add_logs(A, D, "disarmed with CQC", "[I ? " grabbing \the [I]" : ""]") + if(restraining && A.pulling == D) + D.visible_message("[A] puts [D] into a chokehold!", \ + "[A] puts you into a chokehold!") + D.SetSleeping(20) + restraining = 0 + if(A.grab_state < GRAB_NECK) + A.grab_state = GRAB_NECK + else + restraining = 0 + return 0 + return 1 + +/mob/living/carbon/human/proc/CQC_help() + set name = "Remember The Basics" + set desc = "You try to remember some of the basics of CQC." + set category = "CQC" + + to_chat(usr, "You try to remember some of the basics of CQC.") + + to_chat(usr, "Slam: Grab Harm. Slam opponent into the ground, weakens and knocks down.") + to_chat(usr, "CQC Kick: Harm Disarm Harm. Knocks opponent away. Knocks out stunned or weakened opponents.") + to_chat(usr, "Restrain: Grab Grab. Locks opponents into a restraining position, disarm to knock them out with a choke hold.") + to_chat(usr, "Pressure: Disarm Grab. Decent stamina damage.") + to_chat(usr, "Consecutive CQC: Disarm Disarm Harm. Mainly offensive move, huge damage and decent stamina damage.") + + to_chat(usr, "In addition, by having your throw mode on when being attacked, you enter an active defense mode where you have a chance to block and sometimes even counter attacks done to you.") + +/obj/item/weapon/cqc_manual + name = "old manual" + desc = "A small, black manual. There are drawn instructions of tactical hand-to-hand combat." + icon = 'icons/obj/library.dmi' + icon_state ="cqcmanual" + +/obj/item/weapon/cqc_manual/attack_self(mob/living/carbon/human/user) + if(!istype(user) || !user) + return + to_chat(user, "You remember the basics of CQC.") + var/datum/martial_art/cqc/D = new(null) + D.teach(user) + user.drop_item() + visible_message("[src] beeps ominously, and a moment later it bursts up in flames.") + new /obj/effect/decal/cleanable/ash(get_turf(src)) + qdel(src) diff --git a/code/datums/martial/krav_maga.dm b/code/datums/martial/krav_maga.dm index 5bc9b0588b..eb5f74b411 100644 --- a/code/datums/martial/krav_maga.dm +++ b/code/datums/martial/krav_maga.dm @@ -13,12 +13,12 @@ to_chat(owner, "You can't use Krav Maga while you're incapacitated.") return var/mob/living/carbon/human/H = owner - if (H.martial_art.streak == "neck_chop") + if (H.mind.martial_art.streak == "neck_chop") owner.visible_message("[owner] assumes a neutral stance.", "Your next attack is cleared.") - H.martial_art.streak = "" + H.mind.martial_art.streak = "" else owner.visible_message("[owner] assumes the Neck Chop stance!", "Your next attack will be a Neck Chop.") - H.martial_art.streak = "neck_chop" + H.mind.martial_art.streak = "neck_chop" /datum/action/leg_sweep name = "Leg Sweep - Trips the victim, knocking them down for a brief moment." @@ -29,12 +29,12 @@ to_chat(owner, "You can't use Krav Maga while you're incapacitated.") return var/mob/living/carbon/human/H = owner - if (H.martial_art.streak == "leg_sweep") + if (H.mind.martial_art.streak == "leg_sweep") owner.visible_message("[owner] assumes a neutral stance.", "Your next attack is cleared.") - H.martial_art.streak = "" + H.mind.martial_art.streak = "" else owner.visible_message("[owner] assumes the Leg Sweep stance!", "Your next attack will be a Leg Sweep.") - H.martial_art.streak = "leg_sweep" + H.mind.martial_art.streak = "leg_sweep" /datum/action/lung_punch//referred to internally as 'quick choke' name = "Lung Punch - Delivers a strong punch just above the victim's abdomen, constraining the lungs. The victim will be unable to breathe for a short time." @@ -45,12 +45,12 @@ to_chat(owner, "You can't use Krav Maga while you're incapacitated.") return var/mob/living/carbon/human/H = owner - if (H.martial_art.streak == "quick_choke") + if (H.mind.martial_art.streak == "quick_choke") owner.visible_message("[owner] assumes a neutral stance.", "Your next attack is cleared.") - H.martial_art.streak = "" + H.mind.martial_art.streak = "" else owner.visible_message("[owner] assumes the Lung Punch stance!", "Your next attack will be a Lung Punch.") - H.martial_art.streak = "quick_choke"//internal name for lung punch + H.mind.martial_art.streak = "quick_choke"//internal name for lung punch /datum/martial_art/krav_maga/teach(var/mob/living/carbon/human/H,var/make_temporary=0) ..() diff --git a/code/datums/martial/plasma_fist.dm b/code/datums/martial/plasma_fist.dm new file mode 100644 index 0000000000..c79ef032ee --- /dev/null +++ b/code/datums/martial/plasma_fist.dm @@ -0,0 +1,114 @@ +#define TORNADO_COMBO "HHD" +#define THROWBACK_COMBO "DHD" +#define PLASMA_COMBO "HDDDH" + +/datum/martial_art/plasma_fist + name = "Plasma Fist" + help_verb = /mob/living/carbon/human/proc/plasma_fist_help + + +/datum/martial_art/plasma_fist/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D) + if(findtext(streak,TORNADO_COMBO)) + streak = "" + Tornado(A,D) + return 1 + if(findtext(streak,THROWBACK_COMBO)) + streak = "" + Throwback(A,D) + return 1 + if(findtext(streak,PLASMA_COMBO)) + streak = "" + Plasma(A,D) + return 1 + return 0 + +/datum/martial_art/plasma_fist/proc/TornadoAnimate(mob/living/carbon/human/A) + set waitfor = FALSE + for(var/i in list(NORTH,SOUTH,EAST,WEST,EAST,SOUTH,NORTH,SOUTH,EAST,WEST,EAST,SOUTH)) + if(!A) + break + A.setDir(i) + playsound(A.loc, 'sound/weapons/punch1.ogg', 15, 1, -1) + sleep(1) + +/datum/martial_art/plasma_fist/proc/Tornado(mob/living/carbon/human/A, mob/living/carbon/human/D) + A.say("TORNADO SWEEP!") + TornadoAnimate(A) + var/obj/effect/proc_holder/spell/aoe_turf/repulse/R = new(null) + var/list/turfs = list() + for(var/turf/T in range(1,A)) + turfs.Add(T) + R.cast(turfs) + add_logs(A, D, "tornado sweeped(Plasma Fist)") + return + +/datum/martial_art/plasma_fist/proc/Throwback(mob/living/carbon/human/A, mob/living/carbon/human/D) + D.visible_message("[A] has hit [D] with Plasma Punch!", \ + "[A] has hit [D] with Plasma Punch!") + playsound(D.loc, 'sound/weapons/punch1.ogg', 50, 1, -1) + var/atom/throw_target = get_edge_target_turf(D, get_dir(D, get_step_away(D, A))) + D.throw_at(throw_target, 200, 4,A) + A.say("HYAH!") + add_logs(A, D, "threw back (Plasma Fist)") + return + +/datum/martial_art/plasma_fist/proc/Plasma(mob/living/carbon/human/A, mob/living/carbon/human/D) + A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) + playsound(D.loc, 'sound/weapons/punch1.ogg', 50, 1, -1) + A.say("PLASMA FIST!") + D.visible_message("[A] has hit [D] with THE PLASMA FIST TECHNIQUE!", \ + "[A] has hit [D] with THE PLASMA FIST TECHNIQUE!") + D.gib() + add_logs(A, D, "gibbed (Plasma Fist)") + return + +/datum/martial_art/plasma_fist/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) + add_to_streak("H",D) + if(check_streak(A,D)) + return 1 + basic_hit(A,D) + return 1 + +/datum/martial_art/plasma_fist/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) + add_to_streak("D",D) + if(check_streak(A,D)) + return 1 + basic_hit(A,D) + return 1 + +/datum/martial_art/plasma_fist/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D) + add_to_streak("G",D) + if(check_streak(A,D)) + return 1 + basic_hit(A,D) + return 1 + +/mob/living/carbon/human/proc/plasma_fist_help() + set name = "Recall Teachings" + set desc = "Remember the martial techniques of the Plasma Fist." + set category = "Plasma Fist" + + to_chat(usr, "You clench your fists and have a flashback of knowledge...") + to_chat(usr, "Tornado Sweep: Harm Harm Disarm. Repulses target and everyone back.") + to_chat(usr, "Throwback: Disarm Harm Disarm. Throws the target and an item at them.") + to_chat(usr, "The Plasma Fist: Harm Disarm Disarm Disarm Harm. Knocks the brain out of the opponent and gibs their body.") + +/obj/item/weapon/plasma_fist_scroll + name = "frayed scroll" + desc = "An aged and frayed scrap of paper written in shifting runes. There are hand-drawn illustrations of pugilism." + icon = 'icons/obj/wizard.dmi' + icon_state ="scroll2" + var/used = 0 + +/obj/item/weapon/plasma_fist_scroll/attack_self(mob/user) + if(!ishuman(user)) + return + if(!used) + var/mob/living/carbon/human/H = user + var/datum/martial_art/plasma_fist/F = new/datum/martial_art/plasma_fist(null) + F.teach(H) + to_chat(H, "You have learned the ancient martial art of Plasma Fist.") + used = 1 + desc = "It's completely blank." + name = "empty scroll" + icon_state = "blankscroll" diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm new file mode 100644 index 0000000000..f079d2a7db --- /dev/null +++ b/code/datums/martial/sleeping_carp.dm @@ -0,0 +1,247 @@ +#define WRIST_WRENCH_COMBO "DD" +#define BACK_KICK_COMBO "HG" +#define STOMACH_KNEE_COMBO "GH" +#define HEAD_KICK_COMBO "DHH" +#define ELBOW_DROP_COMBO "HDHDH" + +/datum/martial_art/the_sleeping_carp + name = "The Sleeping Carp" + deflection_chance = 100 + no_guns = TRUE + allow_temp_override = FALSE + help_verb = /mob/living/carbon/human/proc/sleeping_carp_help + +/datum/martial_art/the_sleeping_carp/proc/check_streak(mob/living/carbon/human/A, mob/living/carbon/human/D) + if(findtext(streak,WRIST_WRENCH_COMBO)) + streak = "" + wristWrench(A,D) + return 1 + if(findtext(streak,BACK_KICK_COMBO)) + streak = "" + backKick(A,D) + return 1 + if(findtext(streak,STOMACH_KNEE_COMBO)) + streak = "" + kneeStomach(A,D) + return 1 + if(findtext(streak,HEAD_KICK_COMBO)) + streak = "" + headKick(A,D) + return 1 + if(findtext(streak,ELBOW_DROP_COMBO)) + streak = "" + elbowDrop(A,D) + return 1 + return 0 + +/datum/martial_art/the_sleeping_carp/proc/wristWrench(mob/living/carbon/human/A, mob/living/carbon/human/D) + if(!D.stat && !D.stunned && !D.weakened) + A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) + D.visible_message("[A] grabs [D]'s wrist and wrenches it sideways!", \ + "[A] grabs your wrist and violently wrenches it to the side!") + playsound(get_turf(A), 'sound/weapons/thudswoosh.ogg', 50, 1, -1) + D.emote("scream") + D.drop_item() + D.apply_damage(5, BRUTE, pick("l_arm", "r_arm")) + D.Stun(3) + return 1 + add_logs(A, D, "wrist wrenched (Sleeping Carp)") + return basic_hit(A,D) + +/datum/martial_art/the_sleeping_carp/proc/backKick(mob/living/carbon/human/A, mob/living/carbon/human/D) + if(A.dir == D.dir && !D.stat && !D.weakened) + A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) + D.visible_message("[A] kicks [D] in the back!", \ + "[A] kicks you in the back, making you stumble and fall!") + step_to(D,get_step(D,D.dir),1) + D.Weaken(4) + playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1) + return 1 + add_logs(A, D, "back-kicked (Sleeping Carp)") + return basic_hit(A,D) + +/datum/martial_art/the_sleeping_carp/proc/kneeStomach(mob/living/carbon/human/A, mob/living/carbon/human/D) + if(!D.stat && !D.weakened) + A.do_attack_animation(D, ATTACK_EFFECT_KICK) + D.visible_message("[A] knees [D] in the stomach!", \ + "[A] winds you with a knee in the stomach!") + D.audible_message("[D] gags!") + D.losebreath += 3 + D.Stun(2) + playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1) + return 1 + add_logs(A, D, "stomach kneed (Sleeping Carp)") + return basic_hit(A,D) + +/datum/martial_art/the_sleeping_carp/proc/headKick(mob/living/carbon/human/A, mob/living/carbon/human/D) + if(!D.stat && !D.weakened) + A.do_attack_animation(D, ATTACK_EFFECT_KICK) + D.visible_message("[A] kicks [D] in the head!", \ + "[A] kicks you in the jaw!") + D.apply_damage(20, BRUTE, "head") + D.drop_item() + playsound(get_turf(D), 'sound/weapons/punch1.ogg', 50, 1, -1) + D.Stun(4) + return 1 + add_logs(A, D, "head kicked (Sleeping Carp)") + return basic_hit(A,D) + +/datum/martial_art/the_sleeping_carp/proc/elbowDrop(mob/living/carbon/human/A, mob/living/carbon/human/D) + if(D.weakened || D.resting || D.stat) + A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) + D.visible_message("[A] elbow drops [D]!", \ + "[A] piledrives you with their elbow!") + if(D.stat) + D.death() //FINISH HIM! + D.apply_damage(50, BRUTE, "chest") + playsound(get_turf(D), 'sound/weapons/punch1.ogg', 75, 1, -1) + return 1 + add_logs(A, D, "elbow dropped (Sleeping Carp)") + return basic_hit(A,D) + +/datum/martial_art/the_sleeping_carp/grab_act(mob/living/carbon/human/A, mob/living/carbon/human/D) + add_to_streak("G",D) + if(check_streak(A,D)) + return 1 + if(A.grab_state >= GRAB_AGGRESSIVE) + D.grabbedby(A, 1) + else + A.start_pulling(D, 1) + if(A.pulling) + D.drop_all_held_items() + D.stop_pulling() + if(A.a_intent == INTENT_GRAB) + add_logs(A, D, "grabbed", addition="aggressively") + A.grab_state = GRAB_AGGRESSIVE //Instant aggressive grab + else + add_logs(A, D, "grabbed", addition="passively") + A.grab_state = GRAB_PASSIVE + return 1 + +/datum/martial_art/the_sleeping_carp/harm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) + add_to_streak("H",D) + if(check_streak(A,D)) + return 1 + A.do_attack_animation(D, ATTACK_EFFECT_PUNCH) + var/atk_verb = pick("punches", "kicks", "chops", "hits", "slams") + D.visible_message("[A] [atk_verb] [D]!", \ + "[A] [atk_verb] you!") + D.apply_damage(rand(10,15), BRUTE) + playsound(get_turf(D), 'sound/weapons/punch1.ogg', 25, 1, -1) + if(prob(D.getBruteLoss()) && !D.lying) + D.visible_message("[D] stumbles and falls!", "The blow sends you to the ground!") + D.Weaken(4) + add_logs(A, D, "[atk_verb] (Sleeping Carp)") + return 1 + + +/datum/martial_art/the_sleeping_carp/disarm_act(mob/living/carbon/human/A, mob/living/carbon/human/D) + add_to_streak("D",D) + if(check_streak(A,D)) + return 1 + return ..() + +/mob/living/carbon/human/proc/sleeping_carp_help() + set name = "Recall Teachings" + set desc = "Remember the martial techniques of the Sleeping Carp clan." + set category = "Sleeping Carp" + + to_chat(usr, "You retreat inward and recall the teachings of the Sleeping Carp...") + + to_chat(usr, "Wrist Wrench: Disarm Disarm. Forces opponent to drop item in hand.") + to_chat(usr, "Back Kick: Harm Grab. Opponent must be facing away. Knocks down.") + to_chat(usr, "Stomach Knee: Grab Harm. Knocks the wind out of opponent and stuns.") + to_chat(usr, "Head Kick: Disarm Harm Harm. Decent damage, forces opponent to drop item in hand.") + to_chat(usr, "Elbow Drop: Harm Disarm Harm Disarm Harm. Opponent must be on the ground. Deals huge damage, instantly kills anyone in critical condition.") + +/obj/item/weapon/sleeping_carp_scroll + name = "mysterious scroll" + desc = "A scroll filled with strange markings. It seems to be drawings of some sort of martial art." + icon = 'icons/obj/wizard.dmi' + icon_state = "scroll2" + +/obj/item/weapon/sleeping_carp_scroll/attack_self(mob/living/carbon/human/user) + if(!istype(user) || !user) + return + var/message = "You have learned the ancient martial art of the Sleeping Carp! Your hand-to-hand combat has become much more effective, and you are now able to deflect any projectiles \ + directed toward you. However, you are also unable to use any ranged weaponry. You can learn more about your newfound art by using the Recall Teachings verb in the Sleeping Carp tab." + to_chat(user, message) + var/datum/martial_art/the_sleeping_carp/theSleepingCarp = new(null) + theSleepingCarp.teach(user) + user.drop_item() + visible_message("[src] lights up in fire and quickly burns to ash.") + new /obj/effect/decal/cleanable/ash(get_turf(src)) + qdel(src) + +/obj/item/weapon/twohanded/bostaff + name = "bo staff" + desc = "A long, tall staff made of polished wood. Traditionally used in ancient old-Earth martial arts. Can be wielded to both kill and incapacitate." + force = 10 + w_class = WEIGHT_CLASS_BULKY + slot_flags = SLOT_BACK + force_unwielded = 10 + force_wielded = 24 + throwforce = 20 + throw_speed = 2 + attack_verb = list("smashed", "slammed", "whacked", "thwacked") + icon = 'icons/obj/weapons.dmi' + icon_state = "bostaff0" + block_chance = 50 + +/obj/item/weapon/twohanded/bostaff/update_icon() + icon_state = "bostaff[wielded]" + return + +/obj/item/weapon/twohanded/bostaff/attack(mob/target, mob/living/user) + add_fingerprint(user) + if((CLUMSY in user.disabilities) && prob(50)) + to_chat(user, "You club yourself over the head with [src].") + user.Weaken(3) + if(ishuman(user)) + var/mob/living/carbon/human/H = user + H.apply_damage(2*force, BRUTE, "head") + else + user.take_bodypart_damage(2*force) + return + if(iscyborg(target)) + return ..() + if(!isliving(target)) + return ..() + var/mob/living/carbon/C = target + if(C.stat) + to_chat(user, "It would be dishonorable to attack a foe while they cannot retaliate.") + return + if(user.a_intent == INTENT_DISARM) + if(!wielded) + return ..() + if(!ishuman(target)) + return ..() + var/mob/living/carbon/human/H = target + var/list/fluffmessages = list("[user] clubs [H] with [src]!", \ + "[user] smacks [H] with the butt of [src]!", \ + "[user] broadsides [H] with [src]!", \ + "[user] smashes [H]'s head with [src]!", \ + "[user] beats [H] with front of [src]!", \ + "[user] twirls and slams [H] with [src]!") + H.visible_message("[pick(fluffmessages)]", \ + "[pick(fluffmessages)]") + playsound(get_turf(user), 'sound/effects/woodhit.ogg', 75, 1, -1) + H.adjustStaminaLoss(rand(13,20)) + if(prob(10)) + H.visible_message("[H] collapses!", \ + "Your legs give out!") + H.Weaken(4) + if(H.staminaloss && !H.sleeping) + var/total_health = (H.health - H.staminaloss) + if(total_health <= HEALTH_THRESHOLD_CRIT && !H.stat) + H.visible_message("[user] delivers a heavy hit to [H]'s head, knocking them out cold!", \ + "[user] knocks you unconscious!") + H.SetSleeping(30) + H.adjustBrainLoss(25) + else + return ..() + +/obj/item/weapon/twohanded/bostaff/hit_reaction(mob/living/carbon/human/owner, attack_text, final_block_chance) + if(wielded) + return ..() + return 0 diff --git a/code/datums/martial/wrestling.dm b/code/datums/martial/wrestling.dm index 5554ceeaeb..fc1c7a9b6d 100644 --- a/code/datums/martial/wrestling.dm +++ b/code/datums/martial/wrestling.dm @@ -1,3 +1,13 @@ +/mob/living/carbon/human/proc/wrestling_help() + set name = "Recall Teachings" + set desc = "Remember how to wrestle." + set category = "Wrestling" + + to_chat(usr, "You flex your muscles and have a revelation...") + to_chat(usr, "Clinch: Grab. Passively gives you a chance to immediately aggressively grab someone. Not always successful.") + to_chat(usr, "Suplex: Disarm someone you are grabbing. Suplexes your target to the floor. Greatly injures them and leaves both you and your target on the floor.") + to_chat(usr, "Advanced grab: Grab. Passively causes stamina damage when grabbing someone.") + /datum/martial_art/wrestling name = "Wrestling" var/datum/action/slam/slam = new/datum/action/slam() @@ -40,7 +50,7 @@ return owner.visible_message("[owner] prepares to BODY SLAM!", "Your next attack will be a BODY SLAM.") var/mob/living/carbon/human/H = owner - H.martial_art.streak = "slam" + H.mind.martial_art.streak = "slam" /datum/action/throw_wrassle name = "Throw (Cinch) - Spin a cinched opponent around and throw them." @@ -52,7 +62,7 @@ return owner.visible_message("[owner] prepares to THROW!", "Your next attack will be a THROW.") var/mob/living/carbon/human/H = owner - H.martial_art.streak = "throw" + H.mind.martial_art.streak = "throw" /datum/action/kick name = "Kick - A powerful kick, sends people flying away from you. Also useful for escaping from bad situations." @@ -64,7 +74,7 @@ return owner.visible_message("[owner] prepares to KICK!", "Your next attack will be a KICK.") var/mob/living/carbon/human/H = owner - H.martial_art.streak = "kick" + H.mind.martial_art.streak = "kick" /datum/action/strike name = "Strike - Hit a neaby opponent with a quick attack." @@ -76,7 +86,7 @@ return owner.visible_message("[owner] prepares to STRIKE!", "Your next attack will be a STRIKE.") var/mob/living/carbon/human/H = owner - H.martial_art.streak = "strike" + H.mind.martial_art.streak = "strike" /datum/action/drop name = "Drop - Smash down onto an opponent." @@ -88,7 +98,7 @@ return owner.visible_message("[owner] prepares to LEG DROP!", "Your next attack will be a LEG DROP.") var/mob/living/carbon/human/H = owner - H.martial_art.streak = "drop" + H.mind.martial_art.streak = "drop" /datum/martial_art/wrestling/teach(var/mob/living/carbon/human/H,var/make_temporary=0) ..() @@ -430,3 +440,23 @@ D.Stun(rand(3,5)) add_logs(A, D, "cinched") return 1 + +/obj/item/weapon/storage/belt/champion/wrestling + name = "Wrestling Belt" + var/datum/martial_art/wrestling/style = new + +/obj/item/weapon/storage/belt/champion/wrestling/equipped(mob/user, slot) + if(!ishuman(user)) + return + if(slot == slot_belt) + var/mob/living/carbon/human/H = user + style.teach(H,1) + return + +/obj/item/weapon/storage/belt/champion/wrestling/dropped(mob/user) + if(!ishuman(user)) + return + var/mob/living/carbon/human/H = user + if(H.get_item_by_slot(slot_belt) == src) + style.remove(H) + return diff --git a/code/datums/mind.dm b/code/datums/mind.dm index 04bec0a7a4..7f7310665b 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -50,7 +50,8 @@ var/datum/faction/faction //associated faction var/datum/changeling/changeling //changeling holder var/linglink - + var/datum/martial_art/martial_art = null + var/static/default_martial_art = new/datum/martial_art var/miming = 0 // Mime's vow of silence var/list/antag_datums var/antag_hud_icon_state = null //this mind's ANTAG_HUD should have this icon_state diff --git a/code/game/gamemodes/cult/cult_items.dm b/code/game/gamemodes/cult/cult_items.dm index ed1a64eede..4be11267ef 100644 --- a/code/game/gamemodes/cult/cult_items.dm +++ b/code/game/gamemodes/cult/cult_items.dm @@ -375,8 +375,8 @@ desc = "Used by veteran cultists to instantly transport items to their needful bretheren." w_class = WEIGHT_CLASS_SMALL brightness_on = 1 - icon_state = "torch-on" - item_state = "torch-on" + icon_state = "torch" + item_state = "torch" color = "#ff0000" on_damage = 15 slot_flags = null diff --git a/code/game/gamemodes/gang/gang.dm b/code/game/gamemodes/gang/gang.dm index ca51e20cc6..bb4bf455dc 100644 --- a/code/game/gamemodes/gang/gang.dm +++ b/code/game/gamemodes/gang/gang.dm @@ -332,3 +332,4 @@ GLOBAL_LIST_INIT(gang_outfit_pool, list(/obj/item/clothing/suit/jacket/leather,/ SSticker.station_explosion_cinematic(1,"gang war", null) SSticker.mode.explosion_in_progress = 0 SSticker.force_ending = TRUE + diff --git a/code/game/gamemodes/gang/gang_datum.dm b/code/game/gamemodes/gang/gang_datum.dm index 075309b9d3..0ff9ef4f2d 100644 --- a/code/game/gamemodes/gang/gang_datum.dm +++ b/code/game/gamemodes/gang/gang_datum.dm @@ -28,6 +28,7 @@ var/static/list/boss_items = list( /datum/gang_item/function/gang_ping, /datum/gang_item/function/recall, + /datum/gang_item/clothing/under, /datum/gang_item/clothing/suit, /datum/gang_item/clothing/hat, @@ -36,21 +37,29 @@ /datum/gang_item/clothing/mask, /datum/gang_item/clothing/hands, /datum/gang_item/clothing/belt, + /datum/gang_item/weapon/shuriken, /datum/gang_item/weapon/switchblade, + /datum/gang_item/weapon/improvised, + /datum/gang_item/weapon/ammo/improvised_ammo, + /datum/gang_item/weapon/surplus, + /datum/gang_item/weapon/ammo/surplus_ammo, /datum/gang_item/weapon/pistol, /datum/gang_item/weapon/ammo/pistol_ammo, /datum/gang_item/weapon/sniper, /datum/gang_item/weapon/ammo/sniper_ammo, + /datum/gang_item/weapon/machinegun, /datum/gang_item/weapon/uzi, /datum/gang_item/weapon/ammo/uzi_ammo, /datum/gang_item/equipment/sharpener, /datum/gang_item/equipment/spraycan, - /datum/gang_item/equipment/c4, + /datum/gang_item/equipment/sharpener, /datum/gang_item/equipment/emp, + /datum/gang_item/equipment/c4, /datum/gang_item/equipment/frag, - /datum/gang_item/equipment/implant_breaker, /datum/gang_item/equipment/stimpack, + /datum/gang_item/equipment/implant_breaker, + /datum/gang_item/equipment/wetwork_boots, /datum/gang_item/equipment/pen, /datum/gang_item/equipment/dominator ) @@ -66,21 +75,29 @@ /datum/gang_item/clothing/mask, /datum/gang_item/clothing/hands, /datum/gang_item/clothing/belt, - /datum/gang_item/weapon/shuriken, + + /datum/gang_item/weapon/shuriken, /datum/gang_item/weapon/switchblade, + /datum/gang_item/weapon/improvised, + /datum/gang_item/weapon/ammo/improvised_ammo, + /datum/gang_item/weapon/surplus, + /datum/gang_item/weapon/ammo/surplus_ammo, /datum/gang_item/weapon/pistol, /datum/gang_item/weapon/ammo/pistol_ammo, /datum/gang_item/weapon/sniper, /datum/gang_item/weapon/ammo/sniper_ammo, + /datum/gang_item/weapon/machinegun, /datum/gang_item/weapon/uzi, /datum/gang_item/weapon/ammo/uzi_ammo, /datum/gang_item/equipment/sharpener, /datum/gang_item/equipment/spraycan, - /datum/gang_item/equipment/c4, + /datum/gang_item/equipment/sharpener, /datum/gang_item/equipment/emp, + /datum/gang_item/equipment/c4, /datum/gang_item/equipment/frag, - /datum/gang_item/equipment/implant_breaker, /datum/gang_item/equipment/stimpack, + /datum/gang_item/equipment/implant_breaker, + /datum/gang_item/equipment/wetwork_boots, ) /datum/gang/New(loc,gangname) @@ -165,7 +182,6 @@ var/diff = domination_timer - world.time return diff / 10 - //////////////////////////////////////////// MESSAGING @@ -283,4 +299,4 @@ ganghud = new() /datum/gang/multiverse/income() - return \ No newline at end of file + return diff --git a/code/game/gamemodes/gang/gang_items.dm b/code/game/gamemodes/gang/gang_items.dm index b5237040f1..aec9b040cd 100644 --- a/code/game/gamemodes/gang/gang_items.dm +++ b/code/game/gamemodes/gang/gang_items.dm @@ -199,10 +199,34 @@ cost = 5 item_path = /obj/item/weapon/switchblade +/datum/gang_item/weapon/surplus + name = "Surplus Rifle" + id = "surplus" + cost = 8 + item_path = /obj/item/weapon/gun/ballistic/automatic/surplus + +/datum/gang_item/weapon/ammo/surplus_ammo + name = "Surplus Rifle Ammo" + id = "surplus_ammo" + cost = 5 + item_path = /obj/item/ammo_box/magazine/m10mm/rifle + +/datum/gang_item/weapon/improvised + name = "Sawn-Off Improvised Shotgun" + id = "sawn" + cost = 6 + item_path = /obj/item/weapon/gun/ballistic/revolver/doublebarrel/improvised/sawn + +/datum/gang_item/weapon/ammo/improvised_ammo + name = "Box of Buckshot" + id = "buckshot" + cost = 5 + item_path = /obj/item/weapon/storage/box/lethalshot + /datum/gang_item/weapon/pistol name = "10mm Pistol" id = "pistol" - cost = 25 + cost = 30 item_path = /obj/item/weapon/gun/ballistic/automatic/pistol /datum/gang_item/weapon/ammo/pistol_ammo @@ -223,12 +247,19 @@ cost = 15 item_path = /obj/item/ammo_box/magazine/sniper_rounds +/datum/gang_item/weapon/machinegun + name = "Mounted Machine Gun" + id = "MG" + cost = 50 + item_path = /obj/machinery/manned_turret + spawn_msg = "The mounted machine gun features enhanced responsiveness. Hold down on the trigger while firing to control where you're shooting." + /datum/gang_item/weapon/uzi name = "Uzi SMG" id = "uzi" cost = 60 item_path = /obj/item/weapon/gun/ballistic/automatic/mini_uzi - id = "uzi" + /datum/gang_item/weapon/ammo/uzi_ammo name = "Uzi Ammo" @@ -236,8 +267,6 @@ cost = 40 item_path = /obj/item/ammo_box/magazine/uzim9mm - - /////////////////// //EQUIPMENT /////////////////// @@ -274,13 +303,13 @@ /datum/gang_item/equipment/frag name = "Fragmentation Grenade" id = "frag nade" - cost = 10 + cost = 18 item_path = /obj/item/weapon/grenade/syndieminibomb/concussion/frag /datum/gang_item/equipment/stimpack name = "Black Market Stimulants" id = "stimpack" - cost = 15 + cost = 12 item_path = /obj/item/weapon/reagent_containers/syringe/stimulants /datum/gang_item/equipment/implant_breaker @@ -297,6 +326,18 @@ if(spawn_msg) to_chat(user, spawn_msg) +/datum/gang_item/equipment/wetwork_boots + name = "Wetwork boots" + id = "wetwork" + cost = 20 + item_path = /obj/item/clothing/shoes/combat/gang + +/obj/item/clothing/shoes/combat/gang + name = "Wetwork boots" + desc = "A gang's best hitmen are prepared for anything." + permeability_coefficient = 0.01 + flags = NOSLIP + /datum/gang_item/equipment/pen name = "Recruitment Pen" id = "pen" @@ -390,4 +431,4 @@ return ..() /datum/gang_item/equipment/dominator/spawn_item(mob/living/carbon/user, datum/gang/gang, obj/item/device/gangtool/gangtool) - new item_path(user.loc) \ No newline at end of file + new item_path(user.loc) diff --git a/code/game/gamemodes/gang/gang_pen.dm b/code/game/gamemodes/gang/gang_pen.dm index 01b8504e82..d60a3cb57b 100644 --- a/code/game/gamemodes/gang/gang_pen.dm +++ b/code/game/gamemodes/gang/gang_pen.dm @@ -66,4 +66,4 @@ cooldown = 0 icon_state = "pen" var/mob/M = get(src, /mob) - to_chat(M, "\icon[src] [src][(src.loc == M)?(""):(" in your [src.loc]")] vibrates softly. It is ready to be used again.") \ No newline at end of file + to_chat(M, "\icon[src] [src][(src.loc == M)?(""):(" in your [src.loc]")] vibrates softly. It is ready to be used again.") diff --git a/code/game/gamemodes/gang/recaller.dm b/code/game/gamemodes/gang/recaller.dm index c9fcf3c074..ad2da7b502 100644 --- a/code/game/gamemodes/gang/recaller.dm +++ b/code/game/gamemodes/gang/recaller.dm @@ -240,6 +240,7 @@ /obj/item/device/gangtool/spare/lt promotable = 1 + ///////////// Internal tool used by gang regulars /////////// /obj/item/device/gangtool/soldier diff --git a/code/game/gamemodes/miniantags/morph/morph.dm b/code/game/gamemodes/miniantags/morph/morph.dm index a4e9d9482e..0d8093905e 100644 --- a/code/game/gamemodes/miniantags/morph/morph.dm +++ b/code/game/gamemodes/miniantags/morph/morph.dm @@ -35,7 +35,12 @@ var/morphed = 0 var/atom/movable/form = null var/morph_time = 0 - + var/static/list/blacklist_typecache = typecacheof(list( + /obj/screen, + /obj/singularity, + /mob/living/simple_animal/hostile/morph, + /obj/effect)) + var/playstyle_string = "You are a morph, an abomination of science created primarily with changeling cells. \ You may take the form of anything nearby by shift-clicking it. This process will alert any nearby \ observers, and can only be performed once every five seconds. While morphed, you move faster, but do \ @@ -67,13 +72,7 @@ ..() /mob/living/simple_animal/hostile/morph/proc/allowed(atom/movable/A) // make it into property/proc ? not sure if worth it - if(istype(A,/obj/screen)) - return 0 - if(istype(A,/obj/singularity)) - return 0 - if(istype(A,/mob/living/simple_animal/hostile/morph)) - return 0 - return 1 + return !is_type_in_typecache(A, blacklist_typecache) /mob/living/simple_animal/hostile/morph/proc/eat(atom/movable/A) if(A && A.loc != src) @@ -100,6 +99,7 @@ visible_message("[src] suddenly twists and changes shape, becoming a copy of [target]!", \ "You twist your body and assume the form of [target].") appearance = target.appearance + copy_overlays(target) alpha = max(alpha, 150) //fucking chameleons transform = initial(transform) pixel_y = initial(pixel_y) diff --git a/code/game/machinery/porta_turret/portable_turret.dm b/code/game/machinery/porta_turret/portable_turret.dm index 6bab77fd6f..22c6c57b17 100644 --- a/code/game/machinery/porta_turret/portable_turret.dm +++ b/code/game/machinery/porta_turret/portable_turret.dm @@ -1,9 +1,9 @@ #define TURRET_STUN 0 #define TURRET_LETHAL 1 -#define POPUP_ANIM_TIME 5 -#define POPDOWN_ANIM_TIME 5 //Be sure to change the icon animation at the same time or it'll look bad - +#define POPUP_ANIM_TIME 5 +#define POPDOWN_ANIM_TIME 5 //Be sure to change the icon animation at the same time or it'll look bad + /obj/machinery/porta_turret name = "turret" icon = 'icons/obj/turrets.dmi' @@ -87,9 +87,9 @@ if(has_cover) cover = new /obj/machinery/porta_turret_cover(loc) cover.parent_turret = src - underlays += image('icons/obj/turrets.dmi',icon_state = "basedark") + underlays += image('icons/obj/turrets.dmi',icon_state = "basedark") if(!has_cover) - INVOKE_ASYNC(src, .proc/popUp) + INVOKE_ASYNC(src, .proc/popUp) /obj/machinery/porta_turret/update_icon() cut_overlays() @@ -368,10 +368,10 @@ var/list/targets = list() var/turretview = view(scan_range, base) for(var/A in turretview) - var/atom/AA = A - if(AA.invisibility>SEE_INVISIBLE_LIVING) - continue - + var/atom/AA = A + if(AA.invisibility>SEE_INVISIBLE_LIVING) + continue + if(check_anomalies)//if it's set to check for simple animals if(istype(A, /mob/living/simple_animal)) var/mob/living/simple_animal/SA = A @@ -426,7 +426,7 @@ raising = 1 if(cover) flick("popup", cover) - sleep(POPUP_ANIM_TIME) + sleep(POPUP_ANIM_TIME) raising = 0 if(cover) cover.icon_state = "openTurretCover" @@ -442,7 +442,7 @@ raising = 1 if(cover) flick("popdown", cover) - sleep(POPDOWN_ANIM_TIME) + sleep(POPDOWN_ANIM_TIME) raising = 0 if(cover) cover.icon_state = "turretCover" @@ -553,6 +553,7 @@ use_power = 0 has_cover = 0 scan_range = 9 + req_access = list(GLOB.access_syndicate) stun_projectile = /obj/item/projectile/bullet lethal_projectile = /obj/item/projectile/bullet lethal_projectile_sound = 'sound/weapons/Gunshot.ogg' @@ -569,6 +570,8 @@ return 10 //Syndicate turrets shoot everything not in their faction /obj/machinery/porta_turret/syndicate/pod + max_integrity = 40 + integrity_failure = 20 obj_integrity = 40 stun_projectile = /obj/item/projectile/bullet/weakbullet3 lethal_projectile = /obj/item/projectile/bullet/weakbullet3 @@ -792,7 +795,7 @@ /obj/item/wallframe/turret_control name = "turret control frame" desc = "Used for building turret control panels" - icon_state = "apc" + icon_state = "apc" result_path = /obj/machinery/turretid materials = list(MAT_METAL=MINERAL_MATERIAL_AMOUNT) @@ -921,3 +924,170 @@ on = 0 spawn(100) on = 1 + +/////// MANNED TURRET //////// + +/obj/machinery/manned_turret + name = "machine gun turret" + desc = "While the trigger is held down, this gun will redistribute recoil to allow its user to easily shift targets." + icon = 'icons/obj/turrets.dmi' + icon_state = "machinegun" + can_buckle = TRUE + density = TRUE + max_integrity = 100 + obj_integrity = 100 + buckle_lying = 0 + layer = ABOVE_MOB_LAYER + var/view_range = 10 + var/cooldown = 0 + var/projectile_type = /obj/item/projectile/bullet/weakbullet3 + var/rate_of_fire = 1 + var/number_of_shots = 40 + var/cooldown_duration = 90 + var/atom/target + var/turf/target_turf + var/warned = FALSE + +//BUCKLE HOOKS + +/obj/machinery/manned_turret/unbuckle_mob(mob/living/buckled_mob,force = 0) + playsound(src,'sound/mecha/mechmove01.ogg', 50, 1) + for(var/obj/item/I in buckled_mob.held_items) + if(istype(I, /obj/item/gun_control)) + qdel(I) + if(istype(buckled_mob)) + buckled_mob.pixel_x = 0 + buckled_mob.pixel_y = 0 + if(buckled_mob.client) + buckled_mob.client.change_view(world.view) + anchored = FALSE + . = ..() + +/obj/machinery/manned_turret/user_buckle_mob(mob/living/M, mob/living/carbon/user) + if(user.incapacitated() || !istype(user)) + return + M.forceMove(get_turf(src)) + ..() + for(var/V in M.held_items) + var/obj/item/I = V + if(istype(I)) + if(M.dropItemToGround(I)) + var/obj/item/gun_control/TC = new /obj/item/gun_control(src) + M.put_in_hands(TC) + else //Entries in the list should only ever be items or null, so if it's not an item, we can assume it's an empty hand + var/obj/item/gun_control/TC = new /obj/item/gun_control(src) + M.put_in_hands(TC) + M.pixel_y = 14 + layer = ABOVE_MOB_LAYER + setDir(SOUTH) + playsound(src,'sound/mecha/mechmove01.ogg', 50, 1) + anchored = TRUE + if(user.client) + user.client.change_view(view_range) + +/obj/item/gun_control + name = "turret controls" + icon = 'icons/obj/weapons.dmi' + icon_state = "offhand" + w_class = WEIGHT_CLASS_HUGE + flags = ABSTRACT | NODROP + resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF | NOBLUDGEON + var/obj/machinery/manned_turret/turret + +/obj/item/gun_control/New(obj/machinery/manned_turret/MT) + if(MT) + turret = MT + else + qdel(src) + +/obj/item/gun_control/CanItemAutoclick() + return 1 + +/obj/item/gun_control/afterattack(atom/targeted_atom, mob/user) + ..() + var/obj/machinery/manned_turret/E = user.buckled + E.setDir(get_dir(E,targeted_atom)) + user.setDir(E.dir) + switch(E.dir) + if(NORTH) + E.layer = BELOW_MOB_LAYER + user.pixel_x = 0 + user.pixel_y = -14 + if(NORTHEAST) + E.layer = BELOW_MOB_LAYER + user.pixel_x = -8 + user.pixel_y = -4 + if(EAST) + E.layer = ABOVE_MOB_LAYER + user.pixel_x = -14 + user.pixel_y = 0 + if(SOUTHEAST) + E.layer = BELOW_MOB_LAYER + user.pixel_x = -8 + user.pixel_y = 4 + if(SOUTH) + E.layer = ABOVE_MOB_LAYER + user.pixel_x = 0 + user.pixel_y = 14 + if(SOUTHWEST) + E.layer = BELOW_MOB_LAYER + user.pixel_x = 8 + user.pixel_y = 4 + if(WEST) + E.layer = ABOVE_MOB_LAYER + user.pixel_x = 14 + user.pixel_y = 0 + if(NORTHWEST) + E.layer = BELOW_MOB_LAYER + user.pixel_x = 8 + user.pixel_y = -4 + E.checkfire(targeted_atom, user) + +/obj/machinery/manned_turret/proc/checkfire(atom/targeted_atom, mob/user) + target = targeted_atom + if(target == user || target == get_turf(src)) + return + if(world.time < cooldown) + if(!warned && world.time > (cooldown - cooldown_duration + rate_of_fire*number_of_shots)) // To capture the window where one is done firing + warned = TRUE + playsound(src, 'sound/weapons/sear.ogg', 100, 1) + return + else + cooldown = world.time + cooldown_duration + warned = FALSE + INVOKE_ASYNC(src, /obj/machinery/manned_turret/.proc/volley) + +/obj/machinery/manned_turret/proc/volley() + target_turf = get_turf(target) + for(var/i in 1 to number_of_shots) + addtimer(CALLBACK(src, /obj/machinery/manned_turret/.proc/fire_helper), i*rate_of_fire) + + +/obj/machinery/manned_turret/proc/fire_helper() + if(!src) + return + var/turf/targets_from = get_turf(src) + if(QDELETED(target)) + target = target_turf + var/obj/item/projectile/P = new projectile_type(targets_from) + P.current = targets_from + P.starting = targets_from + P.firer = src + P.original = target + playsound(src, 'sound/weapons/Gunshot_smg.ogg', 75, 1) + P.yo = target.y - targets_from.y + rand(-1,1) + P.xo = target.x - targets_from.x + rand(-1,1) + P.fire() + +/obj/machinery/manned_turret/ultimate // Admin-only proof of concept for autoclicker automatics + name = "Infinity Gun" + view_range = 12 + projectile_type = /obj/item/projectile/bullet/weakbullet3 + + +/obj/machinery/manned_turret/ultimate/checkfire(atom/targeted_atom, mob/user) + target = targeted_atom + if(target == user || target == get_turf(src)) + return + target_turf = get_turf(target) + fire_helper(target_turf) diff --git a/code/game/machinery/vending.dm b/code/game/machinery/vending.dm index ebe4c79730..6c86899cf0 100644 --- a/code/game/machinery/vending.dm +++ b/code/game/machinery/vending.dm @@ -1152,6 +1152,32 @@ IF YOU MODIFY THE PRODUCTS LIST OF A MACHINE, MAKE SURE TO UPDATE ITS RESUPPLY C premium = list(/obj/item/clothing/under/suit_jacket/checkered=1,/obj/item/clothing/head/mailman=1,/obj/item/clothing/under/rank/mailman=1,/obj/item/clothing/suit/jacket/leather=1,/obj/item/clothing/suit/jacket/leather/overcoat=1,/obj/item/clothing/under/pants/mustangjeans=1,/obj/item/clothing/neck/necklace/dope=3,/obj/item/clothing/suit/jacket/letterman_nanotrasen=1) refill_canister = /obj/item/weapon/vending_refill/clothing +/obj/machinery/vending/toyliberationstation + name = "\improper Syndicate Donksoft Toy Vendor" + desc = "A ages 8 and up approved vendor that dispenses toys. If you were to find the right wires, you can unlock the adult mode setting!" + icon_state = "syndi" + req_access_txt = "1" + product_slogans = "Get your cool toys today!;Trigger a valid hunter today!;Quality toy weapons for cheap prices!;Give them to HoPs for all access!;Give them to HoS to get perma briged!" + product_ads = "Feel robust with your toys!;Express your inner child today!;Toy weapons don't kill people, but valid hunters do!;Who needs responsibilities when you have toy weapons?;Make your next murder FUN!" + vend_reply = "Come back for more!" + products = list(/obj/item/weapon/gun/ballistic/automatic/toy/unrestricted = 10, + /obj/item/weapon/gun/ballistic/automatic/toy/pistol/unrestricted = 10, + /obj/item/weapon/gun/ballistic/shotgun/toy/unrestricted = 10, + /obj/item/toy/sword = 10, /obj/item/ammo_box/foambox = 20, + /obj/item/toy/foamblade = 10, + /obj/item/toy/syndicateballoon = 10, + /obj/item/clothing/suit/syndicatefake = 5, + /obj/item/clothing/head/syndicatefake = 5) //OPS IN DORMS oh wait it's just a assistant + contraband = list(/obj/item/weapon/gun/ballistic/shotgun/toy/crossbow = 10, //Congrats, you unlocked the +18 setting! + /obj/item/weapon/gun/ballistic/automatic/c20r/toy/unrestricted = 10, + /obj/item/weapon/gun/ballistic/automatic/l6_saw/toy/unrestricted = 10, + /obj/item/ammo_box/foambox/riot = 20, + /obj/item/toy/katana = 10, + /obj/item/weapon/twohanded/dualsaber/toy = 5, + /obj/item/toy/cards/deck/syndicate = 10) //Gambling and it hurts, making it a +18 item + armor = list(melee = 100, bullet = 100, laser = 100, energy = 100, bomb = 0, bio = 0, rad = 0, fire = 100, acid = 50) + resistance_flags = FIRE_PROOF + #undef STANDARD_CHARGE #undef CONTRABAND_CHARGE #undef COIN_CHARGE diff --git a/code/game/mecha/equipment/tools/mining_tools.dm b/code/game/mecha/equipment/tools/mining_tools.dm index 02a93ee610..dbee8bd677 100644 --- a/code/game/mecha/equipment/tools/mining_tools.dm +++ b/code/game/mecha/equipment/tools/mining_tools.dm @@ -106,36 +106,19 @@ icon_state = "mecha_analyzer" selectable = 0 equip_cooldown = 30 - var/scanning = 0 + var/scanning_time = 0 /obj/item/mecha_parts/mecha_equipment/mining_scanner/New() ..() START_PROCESSING(SSobj, src) -/obj/item/mecha_parts/mecha_equipment/mining_scanner/attach(obj/mecha/M) - ..() - M.occupant_sight_flags |= SEE_TURFS - if(M.occupant) - M.occupant.update_sight() - -/obj/item/mecha_parts/mecha_equipment/mining_scanner/detach() - chassis.occupant_sight_flags &= ~SEE_TURFS - if(chassis.occupant) - chassis.occupant.update_sight() - return ..() - /obj/item/mecha_parts/mecha_equipment/mining_scanner/process() if(!loc) STOP_PROCESSING(SSobj, src) qdel(src) - if(scanning) - return - if(istype(loc,/obj/mecha/working)) + if(istype(loc,/obj/mecha/working) && scanning_time <= world.time) var/obj/mecha/working/mecha = loc if(!mecha.occupant) return - var/list/L = list(mecha.occupant) - scanning = 1 - mineral_scan_pulse(L,get_turf(loc)) - spawn(equip_cooldown) - scanning = 0 + scanning_time = world.time + equip_cooldown + mineral_scan_pulse(get_turf(src)) diff --git a/code/game/objects/effects/proximity.dm b/code/game/objects/effects/proximity.dm index bfa6cd8fa9..62471505d0 100644 --- a/code/game/objects/effects/proximity.dm +++ b/code/game/objects/effects/proximity.dm @@ -93,6 +93,4 @@ /obj/effect/abstract/proximity_checker/Crossed(atom/movable/AM) set waitfor = FALSE - var/atom/H = monitor.host - testing("HasProx: [H] -> [AM]") - H.HasProximity(AM) + monitor.host.HasProximity(AM) diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm index 14e4f5a01c..9c14a4376a 100644 --- a/code/game/objects/items/stacks/sheets/leather.dm +++ b/code/game/objects/items/stacks/sheets/leather.dm @@ -196,13 +196,6 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( \ user.visible_message("[user] starts cutting hair off \the [src].", "You start cutting the hair off \the [src]...", "You hear the sound of a knife rubbing against flesh.") if(do_after(user,50, target = src)) to_chat(user, "You cut the hair from this [src.singular_name].") - //Try locating an exisitng stack on the tile and add to there if possible - for(var/obj/item/stack/sheet/hairlesshide/HS in user.loc) - if(HS.amount < 50) - HS.amount++ - use(1) - break - //If it gets to here it means it did not find a suitable stack on the tile. var/obj/item/stack/sheet/hairlesshide/HS = new(user.loc) HS.amount = 1 use(1) @@ -230,3 +223,9 @@ GLOBAL_LIST_INIT(sinew_recipes, list ( \ HS.amount = 1 wetness = initial(wetness) src.use(1) + +/obj/item/stack/sheet/wetleather/microwave_act(obj/machinery/microwave/MW) + ..() + var/obj/item/stack/sheet/leather/L = new(loc) + L.amount = amount + qdel(src) diff --git a/code/game/objects/items/weapons/dna_injector.dm b/code/game/objects/items/weapons/dna_injector.dm index f0fd4947f2..ecc8d3a362 100644 --- a/code/game/objects/items/weapons/dna_injector.dm +++ b/code/game/objects/items/weapons/dna_injector.dm @@ -51,6 +51,7 @@ M.updateappearance(mutations_overlay_update=1) log_attack(log_msg) return TRUE + return FALSE /obj/item/weapon/dnainjector/attack(mob/target, mob/user) if(!user.IsAdvancedToolUser()) @@ -307,11 +308,11 @@ /obj/item/weapon/dnainjector/timed/inject(mob/living/carbon/M, mob/user) prepare() + if(M.stat == DEAD) //prevents dead people from having their DNA changed + to_chat(user, "You can't modify [M]'s DNA while [M.p_theyre()] dead.") + return FALSE if(M.has_dna() && !(M.disabilities & NOCLONE)) - if(M.stat == DEAD) //prevents dead people from having their DNA changed - to_chat(user, "You can't modify [M]'s DNA while [M.p_theyre()] dead.") - return M.radiation += rand(20/(damage_coeff ** 2),50/(damage_coeff ** 2)) var/log_msg = "[key_name(user)] injected [key_name(M)] with the [name]" var/endtime = world.time+duration @@ -352,9 +353,9 @@ M.updateappearance(mutations_overlay_update=1) M.dna.temporary_mutations[UI_CHANGED] = endtime log_attack(log_msg) + return TRUE else - to_chat(user, "It appears that [M] does not have compatible DNA.") - return + return FALSE /obj/item/weapon/dnainjector/timed/hulk name = "\improper DNA injector (Hulk)" diff --git a/code/game/objects/items/weapons/implants/implant_krav_maga.dm b/code/game/objects/items/weapons/implants/implant_krav_maga.dm index 1db7601255..60823f3279 100644 --- a/code/game/objects/items/weapons/implants/implant_krav_maga.dm +++ b/code/game/objects/items/weapons/implants/implant_krav_maga.dm @@ -19,7 +19,9 @@ var/mob/living/carbon/human/H = imp_in if(!ishuman(H)) return - if(istype(H.martial_art, /datum/martial_art/krav_maga)) + if(!H.mind) + return + if(istype(H.mind.martial_art, /datum/martial_art/krav_maga)) style.remove(H) else style.teach(H,1) diff --git a/code/game/objects/items/weapons/storage/belt.dm b/code/game/objects/items/weapons/storage/belt.dm index 5b1c641383..f2e9ca9fc6 100644 --- a/code/game/objects/items/weapons/storage/belt.dm +++ b/code/game/objects/items/weapons/storage/belt.dm @@ -247,10 +247,10 @@ ) /obj/item/weapon/storage/belt/military - name = "military belt" - desc = "A syndicate belt designed to be used by boarding parties. Its style is modeled after the hardsuits they wear." - icon_state = "militarybelt" - item_state = "military" + name = "chest rig" + desc = "A set of tactical webbing worn by Syndicate boarding parties." + icon_state = "explorer1" + item_state = "explorer1" max_w_class = WEIGHT_CLASS_SMALL /obj/item/weapon/storage/belt/military/abductor diff --git a/code/game/objects/structures/crates_lockers/closets/secure/security.dm b/code/game/objects/structures/crates_lockers/closets/secure/security.dm index 98a52994e9..9d24b44f33 100644 --- a/code/game/objects/structures/crates_lockers/closets/secure/security.dm +++ b/code/game/objects/structures/crates_lockers/closets/secure/security.dm @@ -106,7 +106,7 @@ new /obj/item/device/flashlight/seclite(src) new /obj/item/clothing/gloves/krav_maga/sec(src) new /obj/item/weapon/door_remote/head_of_security(src) - new /obj/item/weapon/gun/ballistic/shotgun/automatic/dual_tube(src) + new /obj/item/weapon/gun/ballistic/shotgun/automatic/combat/compact(src) /obj/structure/closet/secure_closet/security name = "security officer's locker" diff --git a/code/game/objects/structures/ghost_role_spawners.dm b/code/game/objects/structures/ghost_role_spawners.dm index 05414f0a4d..91fbf13e3c 100644 --- a/code/game/objects/structures/ghost_role_spawners.dm +++ b/code/game/objects/structures/ghost_role_spawners.dm @@ -152,6 +152,8 @@ var/transfer_choice = alert("Transfer your soul to [src]? (Warning, your old body will die!)",,"Yes","No") if(transfer_choice != "Yes") return + if(QDELETED(src) || uses <= 0) + return log_game("[user.ckey] golem-swapped into [src]") user.visible_message("A faint light leaves [user], moving to [src] and animating it!","You leave your old body behind, and transfer into [src]!") create(ckey = user.ckey, flavour = FALSE, name = user.real_name) diff --git a/code/game/turfs/simulated/chasm.dm b/code/game/turfs/simulated/chasm.dm index 8b24a4c816..4f22487537 100644 --- a/code/game/turfs/simulated/chasm.dm +++ b/code/game/turfs/simulated/chasm.dm @@ -111,6 +111,9 @@ initial_gas_mix = "o2=14;n2=23;TEMP=300" planetary_atmos = TRUE baseturf = /turf/open/chasm/straight_down/lava_land_surface + light_range = 1.9 //slightly less range than lava + light_power = 0.65 //less bright, too + light_color = LIGHT_COLOR_LAVA //let's just say you're falling into lava, that makes sense right /turf/open/chasm/straight_down/lava_land_surface/drop(atom/movable/AM) //Make sure the item is still there after our sleep diff --git a/code/game/turfs/simulated/minerals.dm b/code/game/turfs/simulated/minerals.dm index 54f3ad5ad5..708427a11a 100644 --- a/code/game/turfs/simulated/minerals.dm +++ b/code/game/turfs/simulated/minerals.dm @@ -73,6 +73,8 @@ for(i in 1 to mineralAmt) new mineralType(src) SSblackbox.add_details("ore_mined",mineralType) + for(var/obj/effect/temp_visual/mining_overlay/M in src) + qdel(M) ChangeTurf(turf_type, defer_change) addtimer(CALLBACK(src, .proc/AfterChange), 1, TIMER_UNIQUE) playsound(src, 'sound/effects/break_stone.ogg', 50, 1) //beautiful destruction diff --git a/code/modules/atmospherics/machinery/other/meter.dm b/code/modules/atmospherics/machinery/other/meter.dm index bd9f3e35df..a403210242 100644 --- a/code/modules/atmospherics/machinery/other/meter.dm +++ b/code/modules/atmospherics/machinery/other/meter.dm @@ -19,7 +19,7 @@ /obj/machinery/meter/Initialize(mapload) . = ..() SSair.atmos_machinery += src - if (mapload && !target) + if (!target) target = locate(/obj/machinery/atmospherics/pipe) in loc /obj/machinery/meter/Destroy() diff --git a/code/modules/clothing/clothing.dm b/code/modules/clothing/clothing.dm index f287870ef6..8a943b4c26 100644 --- a/code/modules/clothing/clothing.dm +++ b/code/modules/clothing/clothing.dm @@ -271,6 +271,8 @@ BLIND // can't see anything /obj/item/clothing/head name = "head" icon = 'icons/obj/clothing/hats.dmi' + icon_state = "top_hat" + item_state = "that" body_parts_covered = HEAD slot_flags = SLOT_HEAD var/blockTracking = 0 //For AI tracking diff --git a/code/modules/clothing/glasses/engine_goggles.dm b/code/modules/clothing/glasses/engine_goggles.dm index 6a9ac41a0d..2f70c3bfdf 100644 --- a/code/modules/clothing/glasses/engine_goggles.dm +++ b/code/modules/clothing/glasses/engine_goggles.dm @@ -7,25 +7,34 @@ actions_types = list(/datum/action/item_action/toggle_mode) origin_tech = "materials=3;magnets=3;engineering=3;plasmatech=3" - var/mode = 0 //0 - regular mesons mode 1 - t-ray mode + mode = FALSE //FALSE - regular mesons mode TRUE - t-ray mode var/range = 1 -/obj/item/clothing/glasses/meson/engine/attack_self(mob/user) +/obj/item/clothing/glasses/meson/engine/toggle_mode(mob/user, voluntary) + var/turf/T = get_turf(src) + if(T && T.z == ZLEVEL_MINING && mode) + if(picked_excuse) + to_chat(user, "Due to [picked_excuse], the [name] cannot currently be swapped to \[Meson] mode.") + return mode = !mode if(mode) - START_PROCESSING(SSobj, src) vision_flags = 0 darkness_view = 2 invis_view = SEE_INVISIBLE_LIVING lighting_alpha = null - to_chat(user, "You toggle the goggles' scanning mode to \[T-Ray].") + if(voluntary) + to_chat(user, "You toggle the goggles' scanning mode to \[T-Ray].") + else + to_chat(user, "The goggles abruptly toggle to \[T-Ray] mode!") else - STOP_PROCESSING(SSobj, src) vision_flags = SEE_TURFS darkness_view = 1 lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE - to_chat(loc, "You toggle the goggles' scanning mode to \[Meson].") + if(voluntary) + to_chat(user, "You toggle the goggles' scanning mode to \[Meson].") + else + to_chat(user, "The goggles abruptly toggle to \[Meson] mode!") if(ishuman(user)) var/mob/living/carbon/human/H = user @@ -37,8 +46,14 @@ var/datum/action/A = X A.UpdateButtonIcon() +/obj/item/clothing/glasses/meson/engine/attack_self(mob/user) + toggle_mode(user, TRUE) + /obj/item/clothing/glasses/meson/engine/process() if(!mode) + var/turf/T = get_turf(src) + if(T && T.z == ZLEVEL_MINING) + toggle_mode(loc) return if(!ishuman(loc)) @@ -47,7 +62,6 @@ var/mob/living/carbon/human/user = loc if(user.glasses != src) return - scan() /obj/item/clothing/glasses/meson/engine/proc/scan() @@ -89,13 +103,17 @@ icon_state = "trayson-tray_off" origin_tech = "materials=3;magnets=2;engineering=2" - mode = 1 - var/on = 0 + mode = TRUE + var/on = FALSE vision_flags = 0 darkness_view = 2 invis_view = SEE_INVISIBLE_LIVING range = 2 +/obj/item/clothing/glasses/meson/engine/tray/Initialize() + . = ..() + picked_excuse = null + /obj/item/clothing/glasses/meson/engine/tray/process() if(!on) return @@ -108,15 +126,10 @@ if(user.glasses == src) user.update_inv_glasses() -/obj/item/clothing/glasses/meson/engine/tray/attack_self(mob/user) +/obj/item/clothing/glasses/meson/engine/tray/toggle_mode(mob/user, voluntary) on = !on - if(on) - START_PROCESSING(SSobj, src) - to_chat(user, "You turn the goggles on.") - else - STOP_PROCESSING(SSobj, src) - to_chat(user, "You turn the goggles off.") + to_chat(user, "[voluntary ? "You turn the goggles":"The goggles turn"] [on ? "on":"off"][voluntary ? ".":"!"]") update_icon() for(var/X in actions) diff --git a/code/modules/clothing/glasses/glasses.dm b/code/modules/clothing/glasses/glasses.dm index 2f6089bc56..1cc0cc6163 100644 --- a/code/modules/clothing/glasses/glasses.dm +++ b/code/modules/clothing/glasses/glasses.dm @@ -31,14 +31,60 @@ /obj/item/clothing/glasses/meson name = "Optical Meson Scanner" - desc = "Used by engineering and mining staff to see basic structural and terrain layouts through walls, regardless of lighting condition." + desc = "Used by engineering and mining staff to see basic structural and terrain layouts through walls, regardless of lighting conditions." icon_state = "meson" item_state = "meson" origin_tech = "magnets=1;engineering=2" darkness_view = 2 vision_flags = SEE_TURFS - lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE + lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_VISIBLE glass_colour_type = /datum/client_colour/glass_colour/lightgreen + var/static/list/meson_mining_failure_excuses = list("seismic activity", "excessive lava", "ambient radiation", "electromagnetic storms", "bluespace disruption", \ + "gravity", "dust", "dense rock", "ash", "badly understood science", "radiant heat") + var/picked_excuse + var/mode = FALSE //if FALSE, is in normal meson mode. + +/obj/item/clothing/glasses/meson/Initialize() + . = ..() + picked_excuse = pick(meson_mining_failure_excuses) + START_PROCESSING(SSobj, src) + +/obj/item/clothing/glasses/meson/Destroy() + STOP_PROCESSING(SSobj, src) + return ..() + +/obj/item/clothing/glasses/meson/examine(mob/user) + ..() + var/turf/T = get_turf(src) + if(T && T.z == ZLEVEL_MINING && mode && picked_excuse) + to_chat(user, "Due to [picked_excuse], these Meson Scanners will not be able to display terrain layouts in this area.") + +/obj/item/clothing/glasses/meson/proc/toggle_mode(mob/user) + if(vision_flags & SEE_TURFS) + mode = TRUE + vision_flags &= ~SEE_TURFS + if(ishuman(user)) + var/mob/living/carbon/human/H = user + if(picked_excuse) + to_chat(H, "Due to [picked_excuse], your Meson Scanners will not be able to display terrain layouts in this area.") + if(H.glasses == src) + H.update_sight() + else if(!(vision_flags & SEE_TURFS)) + mode = FALSE + vision_flags |= SEE_TURFS + if(ishuman(user)) + var/mob/living/carbon/human/H = user + to_chat(H, "Your Meson Scanners have reactivated.") + if(H.glasses == src) + H.update_sight() + +/obj/item/clothing/glasses/meson/process() + var/turf/T = get_turf(src) + if(T && T.z == ZLEVEL_MINING) + if(!mode) + toggle_mode(loc) + else if(mode) + toggle_mode(loc) /obj/item/clothing/glasses/meson/night name = "Night Vision Optical Meson Scanner" @@ -47,7 +93,7 @@ item_state = "nvgmeson" origin_tech = "magnets=4;engineering=5;plasmatech=4" darkness_view = 8 - lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE + lighting_alpha = LIGHTING_PLANE_ALPHA_MOSTLY_INVISIBLE glass_colour_type = /datum/client_colour/glass_colour/green /obj/item/clothing/glasses/meson/gar diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index a8ed4d2100..1cadd5cc0d 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -14,14 +14,14 @@ /obj/item/clothing/suit/armor/vest name = "armor vest" - desc = "A slim armored vest that protects against most types of damage." + desc = "A slim Type I armored vest that provides decent protection against most types of damage." icon_state = "armoralt" item_state = "armoralt" blood_overlay_type = "armor" dog_fashion = /datum/dog_fashion/back /obj/item/clothing/suit/armor/vest/alt - desc = "An armored vest that protects against most types of damage." + desc = "A Type I armored vest that provides decent protection against most types of damage." icon_state = "armor" item_state = "armor" @@ -31,7 +31,7 @@ /obj/item/clothing/suit/armor/hos name = "armored greatcoat" - desc = "A greatcoat enchanced with a special alloy for some protection and style for those with a commanding presence." + desc = "A greatcoat enhanced with a special alloy for some extra protection and style for those with a commanding presence." icon_state = "hos" item_state = "greatcoat" body_parts_covered = CHEST|GROIN|ARMS|LEGS @@ -77,7 +77,7 @@ /obj/item/clothing/suit/armor/vest/capcarapace name = "captain's carapace" - desc = "An armored vest reinforced with ceramic plates and pauldrons to provide additional protection whilst still offering maximum mobility and flexibility. Issued only to the station's finest, although it does chafe your nipples." + desc = "An fireproof armored chestpiece reinforced with ceramic plates and plasteel pauldrons to provide additional protection whilst still offering maximum mobility and flexibility. Issued only to the station's finest, although it does chafe your nipples." icon_state = "capcarapace" item_state = "armor" body_parts_covered = CHEST|GROIN @@ -93,7 +93,7 @@ /obj/item/clothing/suit/armor/riot name = "riot suit" - desc = "A suit of armor with heavy padding to protect against melee attacks." + desc = "A suit of semi-flexible polycarbonate body armor with heavy padding to protect against melee attacks." icon_state = "riot" item_state = "swat_suit" body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS @@ -115,7 +115,7 @@ /obj/item/clothing/suit/armor/bulletproof name = "bulletproof armor" - desc = "A bulletproof vest that excels in protecting the wearer against traditional projectile weaponry and explosives to a minor extent." + desc = "A Type III heavy bulletproof vest that excels in protecting the wearer against traditional projectile weaponry and explosives to a minor extent." icon_state = "bulletproof" item_state = "armor" blood_overlay_type = "armor" diff --git a/code/modules/fields/fields.dm b/code/modules/fields/fields.dm index 4e18e45e9a..0e15d24e03 100644 --- a/code/modules/fields/fields.dm +++ b/code/modules/fields/fields.dm @@ -28,7 +28,6 @@ var/square_depth_up = 0 var/square_depth_down = 0 //Processing - var/requires_processing = FALSE var/process_inner_turfs = FALSE //Don't do this unless it's absolutely necessary var/process_edge_turfs = FALSE //Don't do this either unless it's absolutely necessary, you can just track what things are inside manually or on the initial setup. var/setup_edge_turfs = FALSE //Setup edge turfs/all field turfs. Set either or both to ON when you need it, it's defaulting to off unless you do to save CPU. @@ -40,11 +39,7 @@ var/list/turf/field_turfs_new = list() var/list/turf/edge_turfs_new = list() -/datum/proximity_monitor/advanced/New() - SSfields.register_new_field(src) - /datum/proximity_monitor/advanced/Destroy() - SSfields.unregister_field(src) full_cleanup() return ..() diff --git a/code/modules/fields/peaceborg_dampener.dm b/code/modules/fields/peaceborg_dampener.dm index 9cfc34f127..5d2d2829a9 100644 --- a/code/modules/fields/peaceborg_dampener.dm +++ b/code/modules/fields/peaceborg_dampener.dm @@ -3,7 +3,6 @@ //Only use square radius for this! /datum/proximity_monitor/advanced/peaceborg_dampener name = "\improper Hyperkinetic Dampener Field" - requires_processing = TRUE setup_edge_turfs = TRUE setup_field_turfs = TRUE field_shape = FIELD_SHAPE_RADIUS_SQUARE @@ -22,10 +21,15 @@ use_host_turf = TRUE /datum/proximity_monitor/advanced/peaceborg_dampener/New() + START_PROCESSING(SSfields, src) tracked = list() staging = list() ..() +/datum/proximity_monitor/advanced/peaceborg_dampener/Destroy() + STOP_PROCESSING(SSfields, src) + return ..() + /datum/proximity_monitor/advanced/peaceborg_dampener/process() if(!istype(projector)) qdel(src) diff --git a/code/modules/language/language_holder.dm b/code/modules/language/language_holder.dm index 84bf984ca9..918f179591 100644 --- a/code/modules/language/language_holder.dm +++ b/code/modules/language/language_holder.dm @@ -125,7 +125,7 @@ /datum/language_holder/synthetic languages = list(/datum/language/common) - shadow_languages = list(/datum/language/machine, /datum/language/draconic) + shadow_languages = list(/datum/language/common, /datum/language/machine, /datum/language/draconic) /datum/language_holder/universal/New() ..() diff --git a/code/modules/library/lib_machines.dm b/code/modules/library/lib_machines.dm index dc443cf265..68665e2d81 100644 --- a/code/modules/library/lib_machines.dm +++ b/code/modules/library/lib_machines.dm @@ -270,7 +270,7 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums if(5) dat += "

Upload a New Title

" if(!scanner) - findscanner(9) + scanner = findscanner(9) if(!scanner) dat += "No scanner found within wireless network range.
" else if(!scanner.cache) @@ -314,7 +314,7 @@ GLOBAL_LIST(cachedbooks) // List of our cached book datums popup.open() /obj/machinery/computer/libraryconsole/bookmanagement/proc/findscanner(viewrange) - for(var/obj/machinery/libraryscanner/S in range(viewrange)) + for(var/obj/machinery/libraryscanner/S in range(viewrange, get_turf(src))) return S return null diff --git a/code/modules/mining/equipment.dm b/code/modules/mining/equipment.dm index f33f73f7c6..a9315b7bea 100644 --- a/code/modules/mining/equipment.dm +++ b/code/modules/mining/equipment.dm @@ -169,7 +169,7 @@ icon = 'icons/obj/mining.dmi' icon_state = "resonator" item_state = "resonator" - desc = "A handheld device that creates small fields of energy that resonate until they detonate, crushing rock. It can also be activated without a target to create a field at the user's location, to act as a delayed time trap. It's more effective in a vacuum." + desc = "A handheld device that creates small fields of energy that resonate until they detonate, crushing rock. It's more effective in a vacuum." w_class = WEIGHT_CLASS_NORMAL force = 15 throwforce = 10 @@ -188,18 +188,6 @@ fieldlimit = 6 quick_burst_mod = 1 -/obj/item/weapon/resonator/proc/CreateResonance(target, creator) - var/turf/T = get_turf(target) - var/obj/effect/resonance/R = locate(/obj/effect/resonance) in T - if(R) - R.resonance_damage *= quick_burst_mod - R.burst() - return - if(fields.len < fieldlimit) - playsound(src,'sound/weapons/resonator_fire.ogg',50,1) - var/obj/effect/resonance/RE = new(T, creator, burst_time, src) - fields += RE - /obj/item/weapon/resonator/attack_self(mob/user) if(burst_time == 50) burst_time = 30 @@ -208,57 +196,76 @@ burst_time = 50 to_chat(user, "You set the resonator's fields to detonate after 5 seconds.") -/obj/item/weapon/resonator/afterattack(atom/target, mob/user, proximity_flag) - if(proximity_flag) - if(!check_allowed_items(target, 1)) - return +/obj/item/weapon/resonator/proc/CreateResonance(target, mob/user) + var/turf/T = get_turf(target) + var/obj/effect/temp_visual/resonance/R = locate(/obj/effect/temp_visual/resonance) in T + if(R) + R.damage_multiplier = quick_burst_mod + R.burst() + return + if(LAZYLEN(fields) < fieldlimit) + new /obj/effect/temp_visual/resonance(T, user, src, burst_time) user.changeNext_move(CLICK_CD_MELEE) - CreateResonance(target, user) -/obj/effect/resonance +/obj/item/weapon/resonator/pre_attackby(atom/target, mob/user, params) + if(check_allowed_items(target, 1)) + CreateResonance(target, user) + return TRUE + +/obj/effect/temp_visual/resonance name = "resonance field" desc = "A resonating field that significantly damages anything inside of it when the field eventually ruptures. More damaging in low pressure environments." - icon = 'icons/effects/effects.dmi' icon_state = "shield1" layer = ABOVE_ALL_MOB_LAYER - anchored = TRUE - mouse_opacity = 0 + duration = 50 var/resonance_damage = 20 + var/damage_multiplier = 1 var/creator var/obj/item/weapon/resonator/res -/obj/effect/resonance/New(loc, set_creator, timetoburst, set_resonator) - ..() +/obj/effect/temp_visual/resonance/Initialize(mapload, set_creator, set_resonator, set_duration) + duration = set_duration + . = ..() creator = set_creator res = set_resonator - check_pressure() - addtimer(CALLBACK(src, .proc/burst), timetoburst) + if(res) + res.fields += src + playsound(src,'sound/weapons/resonator_fire.ogg',50,1) + transform = matrix()*0.75 + animate(src, transform = matrix()*1.5, time = duration) + deltimer(timerid) + timerid = addtimer(CALLBACK(src, .proc/burst), duration, TIMER_STOPPABLE) -/obj/effect/resonance/Destroy() +/obj/effect/temp_visual/resonance/Destroy() if(res) res.fields -= src + res = null + creator = null . = ..() -/obj/effect/resonance/proc/check_pressure() - var/turf/proj_turf = get_turf(src) +/obj/effect/temp_visual/resonance/proc/check_pressure(turf/proj_turf) + if(!proj_turf) + proj_turf = get_turf(src) if(!istype(proj_turf)) return var/datum/gas_mixture/environment = proj_turf.return_air() var/pressure = environment.return_pressure() + resonance_damage = initial(resonance_damage) if(pressure < 50) name = "strong [initial(name)]" - resonance_damage = 60 + resonance_damage *= 3 else name = initial(name) - resonance_damage = initial(resonance_damage) + resonance_damage *= damage_multiplier -/obj/effect/resonance/proc/burst() - check_pressure() +/obj/effect/temp_visual/resonance/proc/burst() var/turf/T = get_turf(src) - playsound(src,'sound/weapons/resonator_blast.ogg',50,1) + new /obj/effect/temp_visual/resonance_crush(T) if(ismineralturf(T)) var/turf/closed/mineral/M = T M.gets_drilled(creator) + check_pressure(T) + playsound(T,'sound/weapons/resonator_blast.ogg',50,1) for(var/mob/living/L in T) if(creator) add_logs(creator, L, "used a resonator field on", "resonator") @@ -266,6 +273,16 @@ L.apply_damage(resonance_damage, BRUTE) qdel(src) +/obj/effect/temp_visual/resonance_crush + icon_state = "shield1" + layer = ABOVE_ALL_MOB_LAYER + duration = 4 + +/obj/effect/temp_visual/resonance_crush/Initialize() + . = ..() + transform = matrix()*1.5 + animate(src, transform = matrix()*0.1, alpha = 50, time = 4) + /**********************Facehugger toy**********************/ /obj/item/clothing/mask/facehugger/toy @@ -345,28 +362,23 @@ /**********************Mining Scanners**********************/ /obj/item/device/mining_scanner - desc = "A scanner that checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations. Wear material scanners for optimal results." + desc = "A scanner that checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations." name = "manual mining scanner" icon_state = "mining1" item_state = "analyzer" w_class = WEIGHT_CLASS_SMALL flags = CONDUCT slot_flags = SLOT_BELT - var/cooldown = 0 + var/cooldown = 35 + var/current_cooldown = 0 origin_tech = "engineering=1;magnets=1" /obj/item/device/mining_scanner/attack_self(mob/user) if(!user.client) return - if(!cooldown) - cooldown = TRUE - addtimer(CALLBACK(src, .proc/clear_cooldown), 40) - var/list/mobs = list() - mobs |= user - mineral_scan_pulse(mobs, get_turf(user)) - -/obj/item/device/mining_scanner/proc/clear_cooldown() - cooldown = FALSE + if(current_cooldown <= world.time) + current_cooldown = world.time + cooldown + mineral_scan_pulse(get_turf(user)) //Debug item to identify all ore spread quickly @@ -379,7 +391,7 @@ qdel(src) /obj/item/device/t_scanner/adv_mining_scanner - desc = "A scanner that automatically checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations. Wear meson scanners for optimal results. This one has an extended range." + desc = "A scanner that automatically checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations. This one has an extended range." name = "advanced automatic mining scanner" icon_state = "mining0" item_state = "analyzer" @@ -387,77 +399,47 @@ flags = CONDUCT slot_flags = SLOT_BELT var/cooldown = 35 - var/on_cooldown = 0 + var/current_cooldown = 0 var/range = 7 - var/meson = TRUE origin_tech = "engineering=3;magnets=3" -/obj/item/device/t_scanner/adv_mining_scanner/material - meson = FALSE - desc = "A scanner that automatically checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations. Wear material scanners for optimal results. This one has an extended range." - /obj/item/device/t_scanner/adv_mining_scanner/lesser name = "automatic mining scanner" - desc = "A scanner that automatically checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations. Wear meson scanners for optimal results." + desc = "A scanner that automatically checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations." range = 4 cooldown = 50 -/obj/item/device/t_scanner/adv_mining_scanner/lesser/material - desc = "A scanner that automatically checks surrounding rock for useful minerals; it can also be used to stop gibtonite detonations. Wear material scanners for optimal results." - meson = FALSE - /obj/item/device/t_scanner/adv_mining_scanner/scan() - if(!on_cooldown) - on_cooldown = 1 - spawn(cooldown) - on_cooldown = 0 + if(current_cooldown <= world.time) + current_cooldown = world.time + cooldown var/turf/t = get_turf(src) - var/list/mobs = recursive_mob_check(t, 1,0,0) - if(!mobs.len) - return - if(meson) - mineral_scan_pulse(mobs, t, range) - else - mineral_scan_pulse_material(mobs, t, range) + mineral_scan_pulse(t, range) -//For use with mesons -/proc/mineral_scan_pulse(list/mobs, turf/T, range = world.view) +/proc/mineral_scan_pulse(turf/T, range = world.view) var/list/minerals = list() for(var/turf/closed/mineral/M in range(range, T)) if(M.scan_state) minerals += M - if(minerals.len) - for(var/mob/user in mobs) - if(user.client) - var/client/C = user.client - for(var/turf/closed/mineral/M in minerals) - var/turf/F = get_turf(M) - var/image/I = image('icons/turf/smoothrocks.dmi', loc = F, icon_state = M.scan_state, layer = FLASH_LAYER) - I.plane = FULLSCREEN_PLANE - C.images += I - spawn(30) - if(C) - C.images -= I - -//For use with material scanners -/proc/mineral_scan_pulse_material(list/mobs, turf/T, range = world.view) - var/list/minerals = list() - for(var/turf/closed/mineral/M in range(range, T)) - if(M.scan_state) - minerals += M - if(minerals.len) + if(LAZYLEN(minerals)) for(var/turf/closed/mineral/M in minerals) + var/obj/effect/temp_visual/mining_overlay/oldC = locate(/obj/effect/temp_visual/mining_overlay) in M + if(oldC) + qdel(oldC) var/obj/effect/temp_visual/mining_overlay/C = new /obj/effect/temp_visual/mining_overlay(M) C.icon_state = M.scan_state /obj/effect/temp_visual/mining_overlay + plane = FULLSCREEN_PLANE layer = FLASH_LAYER - icon = 'icons/turf/smoothrocks.dmi' - anchored = 1 - mouse_opacity = 0 - duration = 30 - pixel_x = -4 - pixel_y = -4 + icon = 'icons/effects/ore_visuals.dmi' + appearance_flags = 0 //to avoid having TILE_BOUND in the flags, so that the 480x480 icon states let you see it no matter where you are + duration = 35 + pixel_x = -224 + pixel_y = -224 + +/obj/effect/temp_visual/mining_overlay/Initialize() + . = ..() + animate(src, alpha = 0, time = duration, easing = EASE_IN) /**********************Xeno Warning Sign**********************/ @@ -529,7 +511,6 @@ return ..() /obj/item/projectile/destabilizer/on_hit(atom/target, blocked = 0) - if(isliving(target)) var/mob/living/L = target var/datum/status_effect/crusher_mark/CM = L.apply_status_effect(STATUS_EFFECT_CRUSHERMARK) @@ -539,7 +520,6 @@ var/turf/closed/mineral/M = target_turf new /obj/effect/temp_visual/kinetic_blast(M) M.gets_drilled(firer) - ..() /obj/item/weapon/twohanded/required/mining_hammer/afterattack(atom/target, mob/user, proximity_flag) @@ -570,7 +550,6 @@ else L.apply_damage(50, BRUTE, blocked = def_check) - /obj/item/weapon/twohanded/required/mining_hammer/proc/Recharge() if(!charged) charged = TRUE diff --git a/code/modules/mining/lavaland/necropolis_chests.dm b/code/modules/mining/lavaland/necropolis_chests.dm index e2ee4d4c96..8a3f4ee633 100644 --- a/code/modules/mining/lavaland/necropolis_chests.dm +++ b/code/modules/mining/lavaland/necropolis_chests.dm @@ -821,7 +821,9 @@ timer = world.time + cooldown_time if(isliving(target) && chaser_timer <= world.time) //living and chasers off cooldown? fire one! chaser_timer = world.time + chaser_cooldown - new /obj/effect/temp_visual/hierophant/chaser(get_turf(user), user, target, chaser_speed, friendly_fire_check) + var/obj/effect/temp_visual/hierophant/chaser/C = new(get_turf(user), user, target, chaser_speed, friendly_fire_check) + C.damage = 30 + C.monster_damage_boost = FALSE add_logs(user, target, "fired a chaser at", src) else INVOKE_ASYNC(src, .proc/cardinal_blasts, T, user) //otherwise, just do cardinal blast diff --git a/code/modules/mining/machine_vending.dm b/code/modules/mining/machine_vending.dm index ae0ad90dfe..371fb11fec 100644 --- a/code/modules/mining/machine_vending.dm +++ b/code/modules/mining/machine_vending.dm @@ -19,7 +19,7 @@ new /datum/data/mining_equipment("Stabilizing Serum", /obj/item/weapon/hivelordstabilizer, 400), new /datum/data/mining_equipment("Fulton Beacon", /obj/item/fulton_core, 400), new /datum/data/mining_equipment("Shelter Capsule", /obj/item/weapon/survivalcapsule, 400), - new /datum/data/mining_equipment("GAR scanners", /obj/item/clothing/glasses/meson/gar, 500), + new /datum/data/mining_equipment("GAR Meson Scanners", /obj/item/clothing/glasses/meson/gar, 500), new /datum/data/mining_equipment("Explorer's Webbing", /obj/item/weapon/storage/belt/mining, 500), new /datum/data/mining_equipment("Survival Medipen", /obj/item/weapon/reagent_containers/hypospray/medipen/survival, 500), new /datum/data/mining_equipment("Brute First-Aid Kit", /obj/item/weapon/storage/firstaid/brute, 600), diff --git a/code/modules/mining/minebot.dm b/code/modules/mining/minebot.dm index 67b29af1e4..7ee5ed51c7 100644 --- a/code/modules/mining/minebot.dm +++ b/code/modules/mining/minebot.dm @@ -44,7 +44,6 @@ var/light_on = 0 var/datum/action/innate/minedrone/toggle_light/toggle_light_action - var/datum/action/innate/minedrone/toggle_meson_vision/toggle_meson_vision_action var/datum/action/innate/minedrone/toggle_mode/toggle_mode_action var/datum/action/innate/minedrone/dump_ore/dump_ore_action @@ -52,8 +51,6 @@ ..() toggle_light_action = new() toggle_light_action.Grant(src) - toggle_meson_vision_action = new() - toggle_meson_vision_action.Grant(src) toggle_mode_action = new() toggle_mode_action.Grant(src) dump_ore_action = new() @@ -189,23 +186,6 @@ user.light_on = !user.light_on to_chat(user, "You toggle your light [user.light_on ? "on" : "off"].") -/datum/action/innate/minedrone/toggle_meson_vision - name = "Toggle Meson Vision" - button_icon_state = "meson" - -/datum/action/innate/minedrone/toggle_meson_vision/Activate() - var/mob/living/simple_animal/hostile/mining_drone/user = owner - if(user.sight & SEE_TURFS) - user.sight &= ~SEE_TURFS - user.lighting_alpha = LIGHTING_PLANE_ALPHA_VISIBLE - else - user.sight |= SEE_TURFS - user.lighting_alpha = LIGHTING_PLANE_ALPHA_INVISIBLE - - user.sync_lighting_plane_alpha() - - to_chat(user, "You toggle your meson vision [(user.sight & SEE_TURFS) ? "on" : "off"].") - /datum/action/innate/minedrone/toggle_mode name = "Toggle Mode" button_icon_state = "mech_cycle_equip_off" diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 04e0007a5b..edd10ea9e2 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -36,7 +36,8 @@ //initialise organs create_internal_organs() - martial_art = default_martial_art + if(mind) + mind.martial_art = mind.default_martial_art handcrafting = new() diff --git a/code/modules/mob/living/carbon/human/human_defense.dm b/code/modules/mob/living/carbon/human/human_defense.dm index fcfc40f604..18fa2e8c60 100644 --- a/code/modules/mob/living/carbon/human/human_defense.dm +++ b/code/modules/mob/living/carbon/human/human_defense.dm @@ -40,12 +40,13 @@ if(spec_return) return spec_return - if(martial_art && martial_art.deflection_chance) //Some martial arts users can deflect projectiles! - if(prob(martial_art.deflection_chance)) - if(!lying && dna && !dna.check_mutation(HULK)) //But only if they're not lying down, and hulks can't do it - visible_message("[src] deflects the projectile; [p_they()] can't be hit with ranged weapons!", "You deflect the projectile!") - playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, 1) - return 0 + if(mind) + if(mind.martial_art && mind.martial_art.deflection_chance) //Some martial arts users can deflect projectiles! + if(prob(mind.martial_art.deflection_chance)) + if(!lying && dna && !dna.check_mutation(HULK)) //But only if they're not lying down, and hulks can't do it + visible_message("[src] deflects the projectile; [p_they()] can't be hit with ranged weapons!", "You deflect the projectile!") + playsound(src, pick('sound/weapons/bulletflyby.ogg', 'sound/weapons/bulletflyby2.ogg', 'sound/weapons/bulletflyby3.ogg'), 75, 1) + return 0 if(!(P.original == src && P.firer == src)) //can't block or reflect when shooting yourself if(istype(P, /obj/item/projectile/energy) || istype(P, /obj/item/projectile/beam)) @@ -103,10 +104,11 @@ return 0 /mob/living/carbon/human/proc/check_block() - if(martial_art && martial_art.block_chance \ - && prob(martial_art.block_chance) && in_throw_mode \ - && !stat && !weakened && !stunned) - return TRUE + if(mind) + if(mind.martial_art && mind.martial_art.block_chance \ + && prob(mind.martial_art.block_chance) && in_throw_mode \ + && !stat && !weakened && !stunned) + return TRUE return FALSE /mob/living/carbon/human/hitby(atom/movable/AM, skipcatch = 0, hitpush = 1, blocked = 0) diff --git a/code/modules/mob/living/carbon/human/human_defines.dm b/code/modules/mob/living/carbon/human/human_defines.dm index f697215a4a..c1f5075b43 100644 --- a/code/modules/mob/living/carbon/human/human_defines.dm +++ b/code/modules/mob/living/carbon/human/human_defines.dm @@ -39,9 +39,6 @@ var/bleed_rate = 0 //how much are we bleeding var/bleedsuppress = 0 //for stopping bloodloss, eventually this will be limb-based like bleeding - var/datum/martial_art/martial_art = null - var/static/default_martial_art = new/datum/martial_art - var/name_override //For temporary visible name changes var/drunkenness = 0 //Overall drunkenness - check handle_alcohol() in life.dm for effects diff --git a/code/modules/mob/living/carbon/human/human_helpers.dm b/code/modules/mob/living/carbon/human/human_helpers.dm index 3a4b241f10..0620ebd062 100644 --- a/code/modules/mob/living/carbon/human/human_helpers.dm +++ b/code/modules/mob/living/carbon/human/human_helpers.dm @@ -144,9 +144,9 @@ if(NOGUNS in src.dna.species.species_traits) to_chat(src, "Your fingers don't fit in the trigger guard!") return 0 - - if(martial_art && martial_art.no_guns) //great dishonor to famiry - to_chat(src, "Use of ranged weaponry would bring dishonor to the clan.") - return 0 + if(mind) + if(mind.martial_art && mind.martial_art.no_guns) //great dishonor to famiry + to_chat(src, "Use of ranged weaponry would bring dishonor to the clan.") + return 0 return . diff --git a/code/modules/mob/living/carbon/human/login.dm b/code/modules/mob/living/carbon/human/login.dm new file mode 100644 index 0000000000..1ac24cffa9 --- /dev/null +++ b/code/modules/mob/living/carbon/human/login.dm @@ -0,0 +1,9 @@ +/mob/living/carbon/human/Login() + ..() + if(src.martial_art == default_martial_art && mind.stored_martial_art) //If the mind has a martial art stored and the body has the default one. + src.mind.stored_martial_art.teach(src) //Running teach so that it deals with help verbs. + else if(src.martial_art != default_martial_art && src.martial_art != mind.stored_martial_art) //If the body has a martial art which is not the default one and is not stored in the mind. + if(src.martial_art_owner != mind) + src.martial_art.remove(src) + else + src.mind.stored_martial_art = src.martial_art diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index b3f436ec68..cf92de53e1 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -1304,7 +1304,7 @@ /datum/species/proc/spec_hitby(atom/movable/AM, mob/living/carbon/human/H) return -/datum/species/proc/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style = M.martial_art) +/datum/species/proc/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style) if(!istype(M)) return CHECK_DNA_AND_SPECIES(M) @@ -1312,6 +1312,8 @@ if(!istype(M)) //sanity check for drones. return + if(M.mind) + attacker_style = M.mind.martial_art if((M != H) && M.a_intent != INTENT_HELP && H.check_shields(0, M.name, attack_type = UNARMED_ATTACK)) add_logs(M, H, "attempted to touch") H.visible_message("[M] attempted to touch [H]!") diff --git a/code/modules/mob/living/carbon/human/species_types/golems.dm b/code/modules/mob/living/carbon/human/species_types/golems.dm index c60b99a9b0..09c566e6a4 100644 --- a/code/modules/mob/living/carbon/human/species_types/golems.dm +++ b/code/modules/mob/living/carbon/human/species_types/golems.dm @@ -406,7 +406,7 @@ else reactive_teleport(H) -/datum/species/golem/bluespace/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style = M.martial_art) +/datum/species/golem/bluespace/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style) ..() if(world.time > last_teleport + teleport_cooldown && M != H && M.a_intent != INTENT_HELP) reactive_teleport(H) @@ -490,7 +490,7 @@ var/golem_name = "[uppertext(clown_name)]" return golem_name -/datum/species/golem/bananium/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style = M.martial_art) +/datum/species/golem/bananium/spec_attack_hand(mob/living/carbon/human/M, mob/living/carbon/human/H, datum/martial_art/attacker_style) ..() if(world.time > last_banana + banana_cooldown && M != H && M.a_intent != INTENT_HELP) new/obj/item/weapon/grown/bananapeel/specialpeel(get_turf(H)) diff --git a/code/modules/mob/living/silicon/robot/robot_modules.dm b/code/modules/mob/living/silicon/robot/robot_modules.dm index 7ab7fa928d..cdbb5e77aa 100644 --- a/code/modules/mob/living/silicon/robot/robot_modules.dm +++ b/code/modules/mob/living/silicon/robot/robot_modules.dm @@ -526,7 +526,6 @@ name = "Miner" basic_modules = list( /obj/item/device/assembly/flash/cyborg, - /obj/item/borg/sight/meson, /obj/item/weapon/storage/bag/ore/cyborg, /obj/item/weapon/pickaxe/drill/cyborg, /obj/item/weapon/shovel, diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm index 2ae7f02247..fd42582317 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/colossus.dm @@ -123,8 +123,9 @@ Difficulty: Very Hard /mob/living/simple_animal/hostile/megafauna/colossus/proc/enrage(mob/living/L) if(ishuman(L)) var/mob/living/carbon/human/H = L - if(H.martial_art && prob(H.martial_art.deflection_chance)) - . = TRUE + if(H.mind) + if(H.mind.martial_art && prob(H.mind.martial_art.deflection_chance)) + . = TRUE /mob/living/simple_animal/hostile/megafauna/colossus/proc/alternating_dir_shots() dir_shots(GLOB.diagonals) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm index f0f93da269..fad0ab17df 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/hierophant.dm @@ -525,7 +525,9 @@ Difficulty: Hard targetturf = get_turf(target) /obj/effect/temp_visual/hierophant/chaser/proc/make_blast() - new /obj/effect/temp_visual/hierophant/blast(loc, caster, friendly_fire_check) + var/obj/effect/temp_visual/hierophant/blast/B = new(loc, caster, friendly_fire_check) + B.damage = damage + B.monster_damage_boost = monster_damage_boost /obj/effect/temp_visual/hierophant/telegraph icon = 'icons/effects/96x96.dmi' diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 38bbe95a1a..e85dca9cad 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -295,8 +295,12 @@ return A else var/atom/movable/AM = A - if(AM == buckled) //Kind of unnecessary but let's just be sure + if(AM == buckled) continue + if(ismob(AM)) + var/mob/M = AM + if(M.buckled) + continue if(!AM.CanPass(src) || AM.density) if(AM.anchored) return AM diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 0dc080bd19..976e48707b 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -44,8 +44,8 @@ ..() -/obj/item/weapon/paper/New() - ..() +/obj/item/weapon/paper/Initialize() + . = ..() pixel_y = rand(-8, 8) pixel_x = rand(-9, 9) update_icon() diff --git a/code/modules/paperwork/paperbin.dm b/code/modules/paperwork/paperbin.dm index cf7c28d2ba..0818c7c32f 100644 --- a/code/modules/paperwork/paperbin.dm +++ b/code/modules/paperwork/paperbin.dm @@ -110,7 +110,7 @@ papers.Add(P) total_paper++ update_icon() - else if(istype(I, /obj/item/weapon/pen)) + else if(istype(I, /obj/item/weapon/pen) && !bin_pen) var/obj/item/weapon/pen/P = I if(!user.transferItemToLoc(P, src)) return diff --git a/code/modules/projectiles/boxes_magazines/external_mag.dm b/code/modules/projectiles/boxes_magazines/external_mag.dm index 11112ec974..8733cd2e1e 100644 --- a/code/modules/projectiles/boxes_magazines/external_mag.dm +++ b/code/modules/projectiles/boxes_magazines/external_mag.dm @@ -13,6 +13,21 @@ max_ammo = 8 multiple_sprites = 2 +/obj/item/ammo_box/magazine/m10mm/rifle + name = "rifle magazine (10mm)" + desc = "A well-worn magazine fitted for the surplus rifle." + icon_state = "75-8" + origin_tech = "combat=2" + ammo_type = /obj/item/ammo_casing/c10mm + caliber = "10mm" + max_ammo = 10 + +/obj/item/ammo_box/magazine/m10mm/rifle/update_icon() + if(ammo_count()) + icon_state = "75-8" + else + icon_state = "75-0" + /obj/item/ammo_box/magazine/m10mm/fire name = "pistol magazine (10mm incendiary)" desc = "A gun magazine. Loaded with rounds which ignite the target." @@ -52,16 +67,31 @@ /obj/item/ammo_box/magazine/wt550m9/wtap name = "wt550 magazine (Armour Piercing 4.6x30mm)" + icon_state = "46x30mmtA-20" ammo_type = /obj/item/ammo_casing/c46x30mmap +/obj/item/ammo_box/magazine/wt550m9/wtap/update_icon() + ..() + icon_state = "46x30mmtA-[round(ammo_count(),4)]" + /obj/item/ammo_box/magazine/wt550m9/wttx name = "wt550 magazine (Toxin Tipped 4.6x30mm)" + icon_state = "46x30mmtT-20" ammo_type = /obj/item/ammo_casing/c46x30mmtox +/obj/item/ammo_box/magazine/wt550m9/wttx/update_icon() + ..() + icon_state = "46x30mmtT-[round(ammo_count(),4)]" + /obj/item/ammo_box/magazine/wt550m9/wtic name = "wt550 magazine (Incindiary 4.6x30mm)" + icon_state = "46x30mmtI-20" ammo_type = /obj/item/ammo_casing/c46x30mminc +/obj/item/ammo_box/magazine/wt550m9/wtic/update_icon() + ..() + icon_state = "46x30mmtI-[round(ammo_count(),4)]" + /obj/item/ammo_box/magazine/uzim9mm name = "uzi magazine (9mm)" icon_state = "uzi9mm-32" diff --git a/code/modules/projectiles/boxes_magazines/internal_mag.dm b/code/modules/projectiles/boxes_magazines/internal_mag.dm index 3e7112ffed..9476d728a6 100644 --- a/code/modules/projectiles/boxes_magazines/internal_mag.dm +++ b/code/modules/projectiles/boxes_magazines/internal_mag.dm @@ -109,6 +109,11 @@ ammo_type = /obj/item/ammo_casing/shotgun/buckshot max_ammo = 6 +/obj/item/ammo_box/magazine/internal/shot/com/compact + name = "compact combat shotgun internal magazine" + ammo_type = /obj/item/ammo_casing/shotgun/buckshot + max_ammo = 4 + /obj/item/ammo_box/magazine/internal/shot/dual name = "double-barrel shotgun internal magazine" max_ammo = 2 diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm index 1ffdaf0d29..0235bbe84d 100644 --- a/code/modules/projectiles/guns/ballistic/automatic.dm +++ b/code/modules/projectiles/guns/ballistic/automatic.dm @@ -375,8 +375,29 @@ pin = /obj/item/device/firing_pin/implant/pindicate origin_tech = "combat=7;syndicate=6" +// Old Semi-Auto Rifle // +/obj/item/weapon/gun/ballistic/automatic/surplus + name = "Surplus Rifle" + desc = "One of countless obsolete ballistic rifles that still sees use as a cheap deterrent. Uses 10mm ammo and its bulky frame prevents one-hand firing." + origin_tech = "combat=3;materials=2" + icon_state = "surplus" + item_state = "moistnugget" + weapon_weight = WEAPON_HEAVY + mag_type = /obj/item/ammo_box/magazine/m10mm/rifle + fire_delay = 30 + burst_size = 1 + can_unsuppress = 1 + can_suppress = 1 + w_class = WEIGHT_CLASS_HUGE + slot_flags = SLOT_BACK + actions_types = list() +/obj/item/weapon/gun/ballistic/automatic/surplus/update_icon() + if(magazine) + icon_state = "surplus" + else + icon_state = "surplus-e" // Laser rifle (rechargeable magazine) // diff --git a/code/modules/projectiles/guns/ballistic/revolver.dm b/code/modules/projectiles/guns/ballistic/revolver.dm index 6ce52748ec..ac3c56b88a 100644 --- a/code/modules/projectiles/guns/ballistic/revolver.dm +++ b/code/modules/projectiles/guns/ballistic/revolver.dm @@ -344,6 +344,15 @@ slung = 0 update_icon() +/obj/item/weapon/gun/ballistic/revolver/doublebarrel/improvised/sawn + name = "sawn-off improvised shotgun" + desc = "A single-shot shotgun, better not miss" + icon_state = "ishotgun" + item_state = "gun" + w_class = WEIGHT_CLASS_NORMAL + sawn_state = SAWN_OFF + slot_flags = SLOT_BELT + /obj/item/weapon/gun/ballistic/revolver/reverse //Fires directly at its user... unless the user is a clown, of course. clumsy_check = 0 diff --git a/code/modules/projectiles/guns/ballistic/shotgun.dm b/code/modules/projectiles/guns/ballistic/shotgun.dm index 7195afd146..5f376370d4 100644 --- a/code/modules/projectiles/guns/ballistic/shotgun.dm +++ b/code/modules/projectiles/guns/ballistic/shotgun.dm @@ -192,6 +192,14 @@ mag_type = /obj/item/ammo_box/magazine/internal/shot/com w_class = WEIGHT_CLASS_HUGE +/obj/item/weapon/gun/ballistic/shotgun/automatic/combat/compact + name = "compact combat shotgun" + desc = "A compact version of the semi automatic combat shotgun. For close encounters." + icon_state = "cshotgunc" + origin_tech = "combat=4;materials=2" + mag_type = /obj/item/ammo_box/magazine/internal/shot/com/compact + w_class = WEIGHT_CLASS_BULKY + //Dual Feed Shotgun /obj/item/weapon/gun/ballistic/shotgun/automatic/dual_tube diff --git a/code/modules/projectiles/projectile/special.dm.rej b/code/modules/projectiles/projectile/special.dm.rej deleted file mode 100644 index 2af063669d..0000000000 --- a/code/modules/projectiles/projectile/special.dm.rej +++ /dev/null @@ -1,10 +0,0 @@ -diff a/code/modules/projectiles/projectile/special.dm b/code/modules/projectiles/projectile/special.dm (rejected hunks) -@@ -203,7 +203,7 @@ - range = 4 - dismemberment = 20 - impact_effect_type = /obj/effect/temp_visual/impact_effect/purple_laser -- var/mine_range = 4 //mines this many additional tiles -+ var/mine_range = 3 //mines this many additional tiles - - /obj/item/projectile/plasma/Initialize() - . = ..() diff --git a/code/modules/reagents/chemistry/holder.dm b/code/modules/reagents/chemistry/holder.dm index 2c8ef5e065..55a59bed61 100644 --- a/code/modules/reagents/chemistry/holder.dm +++ b/code/modules/reagents/chemistry/holder.dm @@ -453,14 +453,14 @@ /datum/reagents/proc/check_ignoreslow(mob/M) if(istype(M, /mob)) - if(M.reagents.has_reagent("morphine")||M.reagents.has_reagent("ephedrine")) + if(M.reagents.has_reagent("morphine")) return 1 else M.status_flags &= ~IGNORESLOWDOWN /datum/reagents/proc/check_gofast(mob/M) if(istype(M, /mob)) - if(M.reagents.has_reagent("unholywater")||M.reagents.has_reagent("nuka_cola")||M.reagents.has_reagent("stimulants")) + if(M.reagents.has_reagent("unholywater")||M.reagents.has_reagent("nuka_cola")||M.reagents.has_reagent("stimulants")||M.reagents.has_reagent("ephedrine")) return 1 else M.status_flags &= ~GOTTAGOFAST diff --git a/code/modules/reagents/chemistry/machinery/pandemic.dm b/code/modules/reagents/chemistry/machinery/pandemic.dm index 5a73c5dcf4..481704ac41 100644 --- a/code/modules/reagents/chemistry/machinery/pandemic.dm +++ b/code/modules/reagents/chemistry/machinery/pandemic.dm @@ -1,285 +1,183 @@ /obj/machinery/computer/pandemic name = "PanD.E.M.I.C 2200" desc = "Used to work with viruses." - density = 1 - anchored = 1 + density = TRUE + anchored = TRUE icon = 'icons/obj/chemical.dmi' icon_state = "mixer0" circuit = /obj/item/weapon/circuitboard/computer/pandemic - use_power = 1 + use_power = TRUE idle_power_usage = 20 resistance_flags = ACID_PROOF - var/temp_html = "" - var/wait = null - var/obj/item/weapon/reagent_containers/beaker = null + var/wait + var/obj/item/weapon/reagent_containers/beaker /obj/machinery/computer/pandemic/Initialize() . = ..() update_icon() -/obj/machinery/computer/pandemic/proc/GetVirusByIndex(index) - if(beaker && beaker.reagents) - if(beaker.reagents.reagent_list.len) - var/datum/reagent/blood/BL = locate() in beaker.reagents.reagent_list - if(BL) - if(BL.data && BL.data["viruses"]) - var/list/viruses = BL.data["viruses"] - return viruses[index] - return null +/obj/machinery/computer/pandemic/Destroy() + QDEL_NULL(beaker) + return ..() -/obj/machinery/computer/pandemic/proc/GetResistancesByIndex(index) - if(beaker && beaker.reagents) - if(beaker.reagents.reagent_list.len) - var/datum/reagent/blood/BL = locate() in beaker.reagents.reagent_list - if(BL) - if(BL.data && BL.data["resistances"]) - var/list/resistances = BL.data["resistances"] - return resistances[index] - return null +/obj/machinery/computer/pandemic/proc/get_by_index(thing, index) + if(!beaker || !beaker.reagents) + return + var/datum/reagent/blood/B = locate() in beaker.reagents.reagent_list + if(B && B.data[thing]) + return B.data[thing][index] -/obj/machinery/computer/pandemic/proc/GetVirusTypeByIndex(index) - var/datum/disease/D = GetVirusByIndex(index) +/obj/machinery/computer/pandemic/proc/get_virus_id_by_index(index) + var/datum/disease/D = get_by_index("viruses", index) if(D) return D.GetDiseaseID() - return null -/obj/machinery/computer/pandemic/proc/replicator_cooldown(waittime) - wait = 1 +/obj/machinery/computer/pandemic/proc/get_viruses_data(datum/reagent/blood/B) + . = list() + if(!islist(B.data["viruses"])) + return + var/list/V = B.data["viruses"] + var/index = 1 + for(var/virus in V) + var/datum/disease/D = virus + if(!istype(D) || D.visibility_flags & HIDDEN_PANDEMIC) + continue + + var/list/this = list() + this["name"] = D.name + if(istype(D, /datum/disease/advance)) + var/datum/disease/advance/A = SSdisease.archive_diseases[D.GetDiseaseID()] + if(A.name == "Unknown") + this["can_rename"] = TRUE + this["name"] = A.name + this["is_adv"] = TRUE + this["resistance"] = A.totalResistance() + this["stealth"] = A.totalStealth() + this["stage_speed"] = A.totalStageSpeed() + this["transmission"] = A.totalTransmittable() + this["symptoms"] = list() + for(var/symptom in A.symptoms) + var/datum/symptom/S = symptom + var/list/this_symptom = list() + this_symptom["name"] = S.name + this["symptoms"] += list(this_symptom) + this["index"] = index++ + this["agent"] = D.agent + this["description"] = D.desc || "none" + this["spread"] = D.spread_text || "none" + this["cure"] = D.cure_text || "none" + + . += list(this) + +/obj/machinery/computer/pandemic/proc/get_resistance_data(datum/reagent/blood/B) + . = list() + if(!islist(B.data["resistances"])) + return + var/list/resistances = B.data["resistances"] + for(var/id in resistances) + var/list/this = list() + var/datum/disease/D = SSdisease.archive_diseases[id] + if(D) + this["id"] = id + this["name"] = D.name + . += list(this) + +/obj/machinery/computer/pandemic/proc/reset_replicator_cooldown() + wait = FALSE update_icon() - spawn(waittime) - wait = null - update_icon() - playsound(src.loc, 'sound/machines/ping.ogg', 30, 1) + playsound(loc, 'sound/machines/ping.ogg', 30, 1) /obj/machinery/computer/pandemic/update_icon() if(stat & BROKEN) icon_state = (beaker ? "mixer1_b" : "mixer0_b") return - icon_state = "mixer[(beaker)?"1":"0"][(powered()) ? "" : "_nopower"]" - + icon_state = "mixer[(beaker) ? "1" : "0"][powered() ? "" : "_nopower"]" if(wait) cut_overlays() else add_overlay("waitlight") -/obj/machinery/computer/pandemic/Topic(href, href_list) +/obj/machinery/computer/pandemic/proc/eject_beaker() + beaker.forceMove(get_turf(src)) + beaker = null + update_icon() + +/obj/machinery/computer/pandemic/ui_interact(mob/user, ui_key = "main", datum/tgui/ui, force_open = FALSE, datum/tgui/master_ui, datum/ui_state/state = GLOB.default_state) + ui = SStgui.try_update_ui(user, src, ui_key, ui, force_open) + if(!ui) + ui = new(user, src, ui_key, "pandemic", name, 575, 500, master_ui, state) + ui.open() + +/obj/machinery/computer/pandemic/ui_data(mob/user) + var/list/data = list() + data["is_ready"] = !wait + if(beaker) + data["has_beaker"] = TRUE + if(!beaker.reagents.total_volume || !beaker.reagents.reagent_list) + data["beaker_empty"] = TRUE + var/datum/reagent/blood/B = locate() in beaker.reagents.reagent_list + if(B) + data["has_blood"] = TRUE + data["blood"] = list() + data["blood"]["dna"] = B.data["blood_DNA"] || "none" + data["blood"]["type"] = B.data["blood_type"] || "none" + data["viruses"] = get_viruses_data(B) + data["resistances"] = get_resistance_data(B) + + return data + +/obj/machinery/computer/pandemic/ui_act(action, params) if(..()) return - - usr.set_machine(src) - if(!beaker) return - - if (href_list["create_vaccine"]) - if(!src.wait) - var/obj/item/weapon/reagent_containers/glass/bottle/B = new/obj/item/weapon/reagent_containers/glass/bottle(src.loc) - if(B) - B.pixel_x = rand(-3, 3) - B.pixel_y = rand(-3, 3) - var/path = GetResistancesByIndex(text2num(href_list["create_vaccine"])) - var/vaccine_type = path - var/vaccine_name = "Unknown" - - if(!ispath(vaccine_type)) - if(SSdisease.archive_diseases[path]) - var/datum/disease/D = SSdisease.archive_diseases[path] - if(D) - vaccine_name = D.name - vaccine_type = path - else if(vaccine_type) - var/datum/disease/D = new vaccine_type(0, null) - if(D) - vaccine_name = D.name - - if(vaccine_type) - - B.name = "[vaccine_name] vaccine bottle" - B.reagents.add_reagent("vaccine", 15, list(vaccine_type)) - replicator_cooldown(200) - else - temp_html = "The replicator is not ready yet." - updateUsrDialog() - return - else if (href_list["create_virus_culture"]) - if(!wait) - var/type = GetVirusTypeByIndex(text2num(href_list["create_virus_culture"]))//the path is received as string - converting - var/datum/disease/D = null - if(!ispath(type)) - D = GetVirusByIndex(text2num(href_list["create_virus_culture"])) - var/datum/disease/advance/A = SSdisease.archive_diseases[D.GetDiseaseID()] - if(A) - D = new A.type(0, A) - else if(type) - if(type in SSdisease.diseases) // Make sure this is a disease - D = new type(0, null) - if(!D) - return - var/name = stripped_input(usr,"Name:","Name the culture",D.name,MAX_NAME_LEN) - if(name == null || wait) - return - var/obj/item/weapon/reagent_containers/glass/bottle/B = new/obj/item/weapon/reagent_containers/glass/bottle(src.loc) - B.icon_state = "bottle3" - B.pixel_x = rand(-3, 3) - B.pixel_y = rand(-3, 3) - replicator_cooldown(50) - var/list/data = list("viruses"=list(D)) - B.name = "[name] culture bottle" - B.desc = "A small bottle. Contains [D.agent] culture in synthblood medium." - B.reagents.add_reagent("blood",20,data) - updateUsrDialog() - else - temp_html = "The replicator is not ready yet." - updateUsrDialog() - return - else if (href_list["empty_beaker"]) - beaker.reagents.clear_reagents() - updateUsrDialog() - return - else if (href_list["eject"]) - beaker.forceMove(get_turf(loc)) - beaker = null - icon_state = "mixer0" - updateUsrDialog() - return - else if (href_list["emptyeject_beaker"]) - beaker.reagents.clear_reagents() - beaker.forceMove(get_turf(loc)) - beaker = null - icon_state = "mixer0" - updateUsrDialog() - return - else if(href_list["clear"]) - temp_html = "" - updateUsrDialog() - return - else if(href_list["name_disease"]) - var/new_name = stripped_input(usr, "Name the Disease", "New Name", "", MAX_NAME_LEN) - if(!new_name) - return - if(..()) - return - var/id = GetVirusTypeByIndex(text2num(href_list["name_disease"])) - if(SSdisease.archive_diseases[id]) + switch(action) + if("eject_beaker") + eject_beaker() + . = TRUE + if("empty_beaker") + beaker.reagents.clear_reagents() + . = TRUE + if("empty_eject_beaker") + beaker.reagents.clear_reagents() + eject_beaker() + . = TRUE + if("rename_disease") + var/id = get_virus_id_by_index(text2num(params["index"])) var/datum/disease/advance/A = SSdisease.archive_diseases[id] - A.AssignName(new_name) - for(var/datum/disease/advance/AD in SSdisease.processing) - AD.Refresh() - updateUsrDialog() - - - else - usr << browse(null, "window=pandemic") - updateUsrDialog() - return - - add_fingerprint(usr) - return - -/obj/machinery/computer/pandemic/attack_hand(mob/user) - if(..()) - return - user.set_machine(src) - var/dat = "" - if(temp_html) - dat = "[src.temp_html]

Main Menu" - else if(!beaker) - dat += "Please insert beaker.
" - dat += "Close" - else - var/datum/reagents/R = beaker.reagents - var/datum/reagent/blood/Blood = null - for(var/datum/reagent/blood/B in R.reagent_list) - if(B) - Blood = B - break - if(!R.total_volume||!R.reagent_list.len) - dat += "The beaker is empty
" - else if(!Blood) - dat += "No blood sample found in beaker." - else if(!Blood.data) - dat += "No blood data found in beaker." - else - dat += "

Blood sample data:

" - dat += "Blood DNA: [(Blood.data["blood_DNA"]||"none")]
" - dat += "Blood Type: [(Blood.data["blood_type"]||"none")]
" - - - if(Blood.data["viruses"]) - var/list/vir = Blood.data["viruses"] - if(vir.len) - var/i = 0 - for(var/datum/disease/D in Blood.data["viruses"]) - i++ - if(!(D.visibility_flags & HIDDEN_PANDEMIC)) - - if(istype(D, /datum/disease/advance)) - - var/datum/disease/advance/A = D - D = SSdisease.archive_diseases[A.GetDiseaseID()] - if(D && D.name == "Unknown") - dat += "Name Disease
" - - if(!D) - CRASH("We weren't able to get the advance disease from the archive.") - - dat += "Disease Agent: [D?"[D.agent] - Create virus culture bottle":"none"]
" - dat += "Common name: [(D.name||"none")]
" - dat += "Description: [(D.desc||"none")]
" - dat += "Spread: [(D.spread_text||"none")]
" - dat += "Possible cure: [(D.cure_text||"none")]

" - if(istype(D, /datum/disease/advance)) - var/datum/disease/advance/A = D - dat += "Stealth: [(A.totalStealth())]
" - dat += "Resistance: [(A.totalResistance())]
" - dat += "Stage Speed: [(A.totalStageSpeed())]
" - dat += "Transmission: [(A.totalTransmittable())]

" - dat += "Symptoms: " - var/english_symptoms = list() - for(var/datum/symptom/S in A.symptoms) - english_symptoms += S.name - dat += english_list(english_symptoms) - - else - dat += "No detectable virus in the sample." - else - dat += "No detectable virus in the sample." - - dat += "
Contains antibodies to: " - if(Blood.data["resistances"]) - var/list/res = Blood.data["resistances"] - if(res.len) - dat += "
    " - var/i = 0 - for(var/type in Blood.data["resistances"]) - i++ - var/disease_name = "Unknown" - - if(!ispath(type)) - var/datum/disease/advance/A = SSdisease.archive_diseases[type] - if(A) - disease_name = A.name - else - var/datum/disease/D = new type(0, null) - disease_name = D.name - - dat += "
  • [disease_name] - Create vaccine bottle
  • " - dat += "

" - else - dat += "nothing
" - else - dat += "nothing
" - dat += "
Eject beaker[((R.total_volume&&R.reagent_list.len) ? "-- Empty beaker":"")]" - dat += "[((R.total_volume&&R.reagent_list.len) ? "-- Empty and Eject beaker":"")]
" - dat += "Close" - - user << browse("[src.name]
[dat]", "window=pandemic;size=575x400") - onclose(user, "pandemic") - return - + if(A) + var/new_name = stripped_input(usr, "Name the disease", "New name", "", MAX_NAME_LEN) + if(!new_name || ..()) + return + A.AssignName(new_name) + for(var/datum/disease/advance/AD in SSdisease.processing) + AD.Refresh() + . = TRUE + if("create_culture_bottle") + var/id = get_virus_id_by_index(text2num(params["index"])) + var/datum/disease/advance/A = new(FALSE, SSdisease.archive_diseases[id]) + var/list/data = list("viruses" = list(A)) + var/obj/item/weapon/reagent_containers/glass/bottle/B = new(get_turf(src)) + B.name = "[A.name] culture bottle" + B.desc = "A small bottle. Contains [A.agent] culture in synthblood medium." + B.reagents.add_reagent("blood", 20, data) + wait = TRUE + update_icon() + addtimer(CALLBACK(src, .proc/reset_replicator_cooldown), 50) + . = TRUE + if("create_vaccine_bottle") + var/index = params["index"] + var/datum/disease/D = SSdisease.archive_diseases[index] + var/obj/item/weapon/reagent_containers/glass/bottle/B = new(get_turf(src)) + B.name = "[D.name] vaccine bottle" + B.reagents.add_reagent("vaccine", 15, list(index)) + wait = TRUE + update_icon() + addtimer(CALLBACK(src, .proc/reset_replicator_cooldown), 200) + . = TRUE /obj/machinery/computer/pandemic/attackby(obj/item/I, mob/user, params) if(istype(I, /obj/item/weapon/reagent_containers) && (I.container_type & OPENCONTAINER)) - . = 1 //no afterattack + . = TRUE //no afterattack if(stat & (NOPOWER|BROKEN)) return if(beaker) @@ -288,15 +186,15 @@ if(!user.drop_item()) return - beaker = I - beaker.loc = src + beaker = I + beaker.forceMove(src) to_chat(user, "You add the beaker to the machine.") - updateUsrDialog() - icon_state = "mixer1" + update_icon() else return ..() /obj/machinery/computer/pandemic/on_deconstruction() if(beaker) - beaker.loc = get_turf(src) - ..() \ No newline at end of file + beaker.forceMove(get_turf(src)) + beaker = null + . = ..() \ No newline at end of file diff --git a/code/modules/reagents/chemistry/reagents/other_reagents.dm b/code/modules/reagents/chemistry/reagents/other_reagents.dm index b30207eaf3..f3cc8b8620 100644 --- a/code/modules/reagents/chemistry/reagents/other_reagents.dm +++ b/code/modules/reagents/chemistry/reagents/other_reagents.dm @@ -160,6 +160,12 @@ var/obj/item/toy/carpplushie/dehy_carp/dehy = O dehy.Swell() // Makes a carp + else if(istype(O, /obj/item/stack/sheet/hairlesshide)) + var/obj/item/stack/sheet/hairlesshide/HH = O + var/obj/item/stack/sheet/wetleather/WL = new(get_turf(HH)) + WL.amount = HH.amount + qdel(HH) + /* * Water reaction to a mob */ @@ -367,11 +373,15 @@ if(ishuman(M)) var/mob/living/carbon/human/N = M - if(N.dna.species.id == "human") // If they're human, turn em to the "orange" race, and give em spiky black hair + N.hair_style = "Spiky" + N.facial_hair_style = "Shaved" + N.facial_hair_color = "000" + N.hair_color = "000" + if(!(HAIR in N.dna.species.species_traits)) //No hair? No problem! + N.dna.species.species_traits += HAIR + if(N.dna.species.use_skintones) N.skin_tone = "orange" - N.hair_style = "Spiky" - N.hair_color = "000" - if(MUTCOLORS in N.dna.species.species_traits) //Aliens with custom colors simply get turned orange + else if(MUTCOLORS in N.dna.species.species_traits) //Aliens with custom colors simply get turned orange N.dna.features["mcolor"] = "f80" N.regenerate_icons() if(prob(7)) @@ -380,7 +390,7 @@ else M.visible_message("[M] flexes [M.p_their()] arms.") if(prob(10)) - M.say(pick("Check these sweet biceps bro!", "Deal with it.", "CHUG! CHUG! CHUG! CHUG!", "Winning!", "NERDS!", "My name is John and I hate every single one of you.")) + M.say(pick("Shit was SO cash.", "You are everything bad in the world.", "What sports do you play, other than 'jack off to naked drawn Japanese people?'", "Don’t be a stranger. Just hit me with your best shot.", "My name is John and I hate every single one of you.")) ..() return @@ -1126,7 +1136,7 @@ /datum/reagent/nitrous_oxide/reaction_mob(mob/M, method=TOUCH, reac_volume) if(method == VAPOR) M.drowsyness += max(round(reac_volume, 1), 2) - + /datum/reagent/nitrous_oxide/on_mob_life(mob/living/M) M.drowsyness += 2 if(ishuman(M)) diff --git a/code/modules/recycling/conveyor2.dm b/code/modules/recycling/conveyor2.dm index 28e8550b45..72e42b500f 100644 --- a/code/modules/recycling/conveyor2.dm +++ b/code/modules/recycling/conveyor2.dm @@ -104,11 +104,12 @@ if(!operating) return use_power(100) - affecting = loc.contents - src // moved items will be all in loc - sleep(1) + addtimer(CALLBACK(src, .proc/convey, affecting), 1) + +/obj/machinery/conveyor/proc/convey(list/affecting) for(var/atom/movable/A in affecting) - if(A.loc == loc) + if((A.loc == loc) && A.has_gravity()) A.ConveyorMove(movedir) // attack with item, place item on conveyor diff --git a/code/modules/surgery/bodyparts/helpers.dm b/code/modules/surgery/bodyparts/helpers.dm index 2bc650656f..9a787f9fda 100644 --- a/code/modules/surgery/bodyparts/helpers.dm +++ b/code/modules/surgery/bodyparts/helpers.dm @@ -83,14 +83,18 @@ //sometimes we want to ignore that we don't have the required amount of legs. /mob/proc/get_leg_ignore() - return 0 + return FALSE /mob/living/carbon/alien/larva/get_leg_ignore() - return 1 + return TRUE /mob/living/carbon/human/get_leg_ignore() if(movement_type & FLYING) - return 1 + return TRUE + var/obj/item/weapon/tank/jetpack/J = get_jetpack() + if(J && J.on && !has_gravity()) + return TRUE + return FALSE /mob/living/proc/get_missing_limbs() return list() diff --git a/code/modules/uplink/uplink_item.dm b/code/modules/uplink/uplink_item.dm index 03ff44c505..667742afc4 100644 --- a/code/modules/uplink/uplink_item.dm +++ b/code/modules/uplink/uplink_item.dm @@ -914,8 +914,8 @@ GLOBAL_LIST_EMPTY(uplink_items) // Global list so we only initialize this once. cost = 3 /datum/uplink_item/device_tools/military_belt - name = "Military Belt" - desc = "A robust seven-slot red belt that is capable of holding all manner of tatical equipment." + name = "Chest Rig" + desc = "A robust seven-slot set of webbing that is capable of holding all manner of tatical equipment." item = /obj/item/weapon/storage/belt/military cost = 1 exclude_modes = list(/datum/game_mode/nuclear) diff --git a/html/changelogs/AutoChangeLog-pr-1087.yml b/html/changelogs/AutoChangeLog-pr-1087.yml new file mode 100644 index 0000000000..c94c89bed0 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-1087.yml @@ -0,0 +1,4 @@ +author: "Lzimann" +delete-after: True +changes: + - rscadd: "Pandemic is now tgui!" diff --git a/html/changelogs/AutoChangeLog-pr-1091.yml b/html/changelogs/AutoChangeLog-pr-1091.yml new file mode 100644 index 0000000000..b8d5699997 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-1091.yml @@ -0,0 +1,5 @@ +author: "Joan" +delete-after: True +changes: + - tweak: "Resonator fields now visually show how long they have until they burst." + - bugfix: "Hitting a legion skull with a resonator will now produce a field." diff --git a/html/changelogs/AutoChangeLog-pr-1096.yml b/html/changelogs/AutoChangeLog-pr-1096.yml new file mode 100644 index 0000000000..fff14de59e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-1096.yml @@ -0,0 +1,4 @@ +author: "Steelpoint" +delete-after: True +changes: + - rscadd: "The Warden's Cycler Shotgun has been replaced with a Compact Combat Shotgun. A unique weapon, it can fit in armour slots but at the sacrifice of a smaller ammo capacity of four shells." diff --git a/html/changelogs/AutoChangeLog-pr-1101.yml b/html/changelogs/AutoChangeLog-pr-1101.yml new file mode 100644 index 0000000000..f57bf23e13 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-1101.yml @@ -0,0 +1,4 @@ +author: "CitadelStationBot" +delete-after: True +changes: + - bugfix: "Spessmen seems to have stopped suffering from the mental condition that makes them believe they can't move fast if they have only one leg, even if they're in space and using a jetpack!" diff --git a/html/changelogs/AutoChangeLog-pr-1102.yml b/html/changelogs/AutoChangeLog-pr-1102.yml new file mode 100644 index 0000000000..8e01bbc5ad --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-1102.yml @@ -0,0 +1,4 @@ +author: "That Really Good Soda Flavor" +delete-after: True +changes: + - bugfix: "Martial arts are no longer lost when mind-swapping, cloning, moving your brain, et cetera." diff --git a/html/changelogs/AutoChangeLog-pr-1103.yml b/html/changelogs/AutoChangeLog-pr-1103.yml new file mode 100644 index 0000000000..39ae5952ab --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-1103.yml @@ -0,0 +1,7 @@ +author: "coiax" +delete-after: True +changes: + - rscadd: "Galactic Common has been added to silicon's internal language +database, meaning even if a cyborg is created from someone who +previously did not know Galactic Common, they will be able to speak it +as a silicon." diff --git a/html/changelogs/AutoChangeLog-pr-1116.yml b/html/changelogs/AutoChangeLog-pr-1116.yml new file mode 100644 index 0000000000..d63e6e64ba --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-1116.yml @@ -0,0 +1,4 @@ +author: "ma44" +delete-after: True +changes: + - rscadd: "Reports of syndicate base on lavaland has been outfitted with a state of the art donksoft toy weapon dispenser." diff --git a/html/changelogs/AutoChangeLog-pr-1117.yml b/html/changelogs/AutoChangeLog-pr-1117.yml new file mode 100644 index 0000000000..a5cdcb8039 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-1117.yml @@ -0,0 +1,4 @@ +author: "Joan" +delete-after: True +changes: + - tweak: "Chasms will glow dimly, like lava." diff --git a/html/changelogs/AutoChangeLog-pr-1119.yml b/html/changelogs/AutoChangeLog-pr-1119.yml new file mode 100644 index 0000000000..e41fb408be --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-1119.yml @@ -0,0 +1,4 @@ +author: "Steelpoint" +delete-after: True +changes: + - rscadd: "Auto Rifle alt ammo mags (AP, Incendiary, Uranium Tipped) now have a coloured stripe to denote them." diff --git a/html/changelogs/AutoChangeLog-pr-1121.yml b/html/changelogs/AutoChangeLog-pr-1121.yml new file mode 100644 index 0000000000..18f8cc544e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-1121.yml @@ -0,0 +1,6 @@ +author: "Joan" +delete-after: True +changes: + - rscdel: "Nanotrasen has taken a lower bid for their meson suppliers, and meson scanners will no longer display terrain layouts while on the planet." + - tweak: "However, they have discovered that, with some tweaks, mineral scanners will no longer actually require you to be wearing mesons." + - tweak: "The cheaper mesons will not completely remove reliance on light." diff --git a/html/changelogs/AutoChangeLog-pr-1129.yml b/html/changelogs/AutoChangeLog-pr-1129.yml new file mode 100644 index 0000000000..695dc0b148 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-1129.yml @@ -0,0 +1,4 @@ +author: "That Really Good Soda Flavor" +delete-after: True +changes: + - bugfix: "Fixed a bug where paper bins could swallow up pens into the void." diff --git a/html/changelogs/AutoChangeLog-pr-1130.yml b/html/changelogs/AutoChangeLog-pr-1130.yml new file mode 100644 index 0000000000..c7dacb5662 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-1130.yml @@ -0,0 +1,10 @@ +author: "Robustin" +delete-after: True +changes: + - rscadd: "Gang influence is now decentralized, each gangster has their own influence that they can increase by spraying (and protecting) their tags and new influence-enhancing bling." + - rscadd: "Gang uniforms are now created based on your gang's color and can be purchased by any gang member. They will increase the wearer's influence and provide protection, but will make it fairly obvious which gang you belong to." + - rscadd: "Gangs have access to a new surplus rifle; it is a semi-automatic rifle that is very bulky and has a very low rate of fire. Gang members can buy this gun for just 8 influence." + - rscadd: "Gangs have access to the new machine gun turret; it unleashes a volley of bullets with an extended view range. It does not run out of ammo, but a significant delay between volleys and its stationary nature leaves the gunner vulnerable to flanking and return fire. Holding down the trigger will allow you to aim the gun while firing. It will cost gangs 50 influence." + - rscadd: "The sawn-off improvised shotgun is now available to gangs for 6 influence. With buckshot shells being easy to produce or purchase, this gun gives the most \"bang for your buck\" but its single-shell capacity will leave you vulnerable during a pitched gunfight." + - rscadd: "The Wetwork boots give gangs access to a lightly armored noslip variant." + - tweak: "The armored gang outfits are now slightly more resistant to ballistic and bomb damage" diff --git a/html/changelogs/AutoChangeLog-pr-1141.yml b/html/changelogs/AutoChangeLog-pr-1141.yml new file mode 100644 index 0000000000..2b8841490d --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-1141.yml @@ -0,0 +1,4 @@ +author: "Tacolizard" +delete-after: True +changes: + - tweak: "Station based armour is slightly more descriptive of what it does." diff --git a/html/changelogs/AutoChangeLog-pr-1146.yml b/html/changelogs/AutoChangeLog-pr-1146.yml new file mode 100644 index 0000000000..c7b4db56f6 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-1146.yml @@ -0,0 +1,4 @@ +author: "That Really Good Soda Flavor" +delete-after: True +changes: + - tweak: "Changed spray tan overdoses to be more realistic." diff --git a/html/changelogs/AutoChangeLog-pr-1147.yml b/html/changelogs/AutoChangeLog-pr-1147.yml new file mode 100644 index 0000000000..6c524da4aa --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-1147.yml @@ -0,0 +1,5 @@ +author: "QualityVan" +delete-after: True +changes: + - rscadd: "Hairless hides now become wet when exposed to water" + - rscadd: "You can microwave wet leather to dry it" diff --git a/html/changelogs/AutoChangeLog-pr-1149.yml b/html/changelogs/AutoChangeLog-pr-1149.yml new file mode 100644 index 0000000000..4a5c010dd4 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-1149.yml @@ -0,0 +1,4 @@ +author: "Steelpoint" +delete-after: True +changes: + - rscadd: "Boxstation armoury weapon racks now have glass panes to help prevent the weapons easily flying out of a breached hull." diff --git a/icons/effects/ore_visuals.dmi b/icons/effects/ore_visuals.dmi new file mode 100644 index 0000000000..30a05b043a Binary files /dev/null and b/icons/effects/ore_visuals.dmi differ diff --git a/icons/obj/ammo.dmi b/icons/obj/ammo.dmi index 87d4e5ed22..33149a3e2e 100644 Binary files a/icons/obj/ammo.dmi and b/icons/obj/ammo.dmi differ diff --git a/icons/obj/guns/projectile.dmi b/icons/obj/guns/projectile.dmi index dfb1f4c51b..611a27e6a7 100644 Binary files a/icons/obj/guns/projectile.dmi and b/icons/obj/guns/projectile.dmi differ diff --git a/icons/obj/turrets.dmi b/icons/obj/turrets.dmi index c4077b6601..b186c3f224 100644 Binary files a/icons/obj/turrets.dmi and b/icons/obj/turrets.dmi differ diff --git a/icons/obj/vending.dmi b/icons/obj/vending.dmi index 8e08060f0d..c7b9bbcdc8 100644 Binary files a/icons/obj/vending.dmi and b/icons/obj/vending.dmi differ diff --git a/icons/turf/mining.dmi b/icons/turf/mining.dmi index 66c07a8146..8770f77cd9 100644 Binary files a/icons/turf/mining.dmi and b/icons/turf/mining.dmi differ diff --git a/icons/turf/smoothrocks.dmi b/icons/turf/smoothrocks.dmi index a7e9864617..ba2bbce955 100644 Binary files a/icons/turf/smoothrocks.dmi and b/icons/turf/smoothrocks.dmi differ diff --git a/tgstation.dme b/tgstation.dme index 994dab7459..c2cb44f546 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -197,7 +197,6 @@ #include "code\controllers\subsystem\dbcore.dm" #include "code\controllers\subsystem\disease.dm" #include "code\controllers\subsystem\events.dm" -#include "code\controllers\subsystem\fields.dm" #include "code\controllers\subsystem\fire_burning.dm" #include "code\controllers\subsystem\garbage.dm" #include "code\controllers\subsystem\icon_smooth.dm" @@ -232,6 +231,7 @@ #include "code\controllers\subsystem\vote.dm" #include "code\controllers\subsystem\weather.dm" #include "code\controllers\subsystem\processing\fastprocess.dm" +#include "code\controllers\subsystem\processing\fields.dm" #include "code\controllers\subsystem\processing\flightpacks.dm" #include "code\controllers\subsystem\processing\obj.dm" #include "code\controllers\subsystem\processing\overlays.dm" @@ -324,7 +324,11 @@ #include "code\datums\helper_datums\icon_snapshot.dm" #include "code\datums\helper_datums\teleport.dm" #include "code\datums\helper_datums\topic_input.dm" +#include "code\datums\martial\boxing.dm" +#include "code\datums\martial\cqc.dm" #include "code\datums\martial\krav_maga.dm" +#include "code\datums\martial\plasma_fist.dm" +#include "code\datums\martial\sleeping_carp.dm" #include "code\datums\martial\wrestling.dm" #include "code\datums\ruins\lavaland.dm" #include "code\datums\ruins\space.dm" diff --git a/tgui/assets/tgui.js b/tgui/assets/tgui.js index d7b7e7f257..c609f0d32b 100644 --- a/tgui/assets/tgui.js +++ b/tgui/assets/tgui.js @@ -1,16 +1,16 @@ -require=function t(e,n,a){function r(o,s){if(!n[o]){if(!e[o]){var u="function"==typeof require&&require;if(!s&&u)return u(o,!0);if(i)return i(o,!0);var p=Error("Cannot find module '"+o+"'");throw p.code="MODULE_NOT_FOUND",p}var c=n[o]={exports:{}};e[o][0].call(c.exports,function(t){var n=e[o][1][t];return r(n?n:t)},c,c.exports,t,e,n,a)}return n[o].exports}for(var i="function"==typeof require&&require,o=0;o2?p[2]:void 0,l=Math.min((void 0===c?o:r(c,o))-u,o-s),f=1;for(s>u&&u+l>s&&(f=-1,u+=l-1,s+=l-1);l-- >0;)u in n?n[s]=n[u]:delete n[s],s+=f,u+=f;return n}},{76:76,79:79,80:80}],6:[function(t,e,n){"use strict";var a=t(80),r=t(76),i=t(79);e.exports=[].fill||function(t){for(var e=a(this),n=i(e.length),o=arguments,s=o.length,u=r(s>1?o[1]:void 0,n),p=s>2?o[2]:void 0,c=void 0===p?n:r(p,n);c>u;)e[u++]=t;return e}},{76:76,79:79,80:80}],7:[function(t,e,n){var a=t(78),r=t(79),i=t(76);e.exports=function(t){return function(e,n,o){var s,u=a(e),p=r(u.length),c=i(o,p);if(t&&n!=n){for(;p>c;)if(s=u[c++],s!=s)return!0}else for(;p>c;c++)if((t||c in u)&&u[c]===n)return t||c;return!t&&-1}}},{76:76,78:78,79:79}],8:[function(t,e,n){var a=t(17),r=t(34),i=t(80),o=t(79),s=t(9);e.exports=function(t){var e=1==t,n=2==t,u=3==t,p=4==t,c=6==t,l=5==t||c;return function(f,d,h){for(var m,v,g=i(f),b=r(g),y=a(d,h,3),x=o(b.length),_=0,w=e?s(f,x):n?s(f,0):void 0;x>_;_++)if((l||_ in b)&&(m=b[_],v=y(m,_,g),t))if(e)w[_]=v;else if(v)switch(t){case 3:return!0;case 5:return m;case 6:return _;case 2:w.push(m)}else if(p)return!1;return c?-1:u||p?p:w}}},{17:17,34:34,79:79,80:80,9:9}],9:[function(t,e,n){var a=t(38),r=t(36),i=t(83)("species");e.exports=function(t,e){var n;return r(t)&&(n=t.constructor,"function"!=typeof n||n!==Array&&!r(n.prototype)||(n=void 0),a(n)&&(n=n[i],null===n&&(n=void 0))),new(void 0===n?Array:n)(e)}},{36:36,38:38,83:83}],10:[function(t,e,n){var a=t(11),r=t(83)("toStringTag"),i="Arguments"==a(function(){return arguments}());e.exports=function(t){var e,n,o;return void 0===t?"Undefined":null===t?"Null":"string"==typeof(n=(e=Object(t))[r])?n:i?a(e):"Object"==(o=a(e))&&"function"==typeof e.callee?"Arguments":o}},{11:11,83:83}],11:[function(t,e,n){var a={}.toString;e.exports=function(t){return a.call(t).slice(8,-1)}},{}],12:[function(t,e,n){"use strict";var a=t(46),r=t(31),i=t(60),o=t(17),s=t(69),u=t(18),p=t(27),c=t(42),l=t(44),f=t(82)("id"),d=t(30),h=t(38),m=t(65),v=t(19),g=Object.isExtensible||h,b=v?"_s":"size",y=0,x=function(t,e){if(!h(t))return"symbol"==typeof t?t:("string"==typeof t?"S":"P")+t;if(!d(t,f)){if(!g(t))return"F";if(!e)return"E";r(t,f,++y)}return"O"+t[f]},_=function(t,e){var n,a=x(e);if("F"!==a)return t._i[a];for(n=t._f;n;n=n.n)if(n.k==e)return n};e.exports={getConstructor:function(t,e,n,r){var c=t(function(t,i){s(t,c,e),t._i=a.create(null),t._f=void 0,t._l=void 0,t[b]=0,void 0!=i&&p(i,n,t[r],t)});return i(c.prototype,{clear:function(){for(var t=this,e=t._i,n=t._f;n;n=n.n)n.r=!0,n.p&&(n.p=n.p.n=void 0),delete e[n.i];t._f=t._l=void 0,t[b]=0},"delete":function(t){var e=this,n=_(e,t);if(n){var a=n.n,r=n.p;delete e._i[n.i],n.r=!0,r&&(r.n=a),a&&(a.p=r),e._f==n&&(e._f=a),e._l==n&&(e._l=r),e[b]--}return!!n},forEach:function(t){for(var e,n=o(t,arguments.length>1?arguments[1]:void 0,3);e=e?e.n:this._f;)for(n(e.v,e.k,this);e&&e.r;)e=e.p},has:function(t){return!!_(this,t)}}),v&&a.setDesc(c.prototype,"size",{get:function(){return u(this[b])}}),c},def:function(t,e,n){var a,r,i=_(t,e);return i?i.v=n:(t._l=i={i:r=x(e,!0),k:e,v:n,p:a=t._l,n:void 0,r:!1},t._f||(t._f=i),a&&(a.n=i),t[b]++,"F"!==r&&(t._i[r]=i)),t},getEntry:_,setStrong:function(t,e,n){c(t,e,function(t,e){this._t=t,this._k=e,this._l=void 0},function(){for(var t=this,e=t._k,n=t._l;n&&n.r;)n=n.p;return t._t&&(t._l=n=n?n.n:t._t._f)?"keys"==e?l(0,n.k):"values"==e?l(0,n.v):l(0,[n.k,n.v]):(t._t=void 0,l(1))},n?"entries":"values",!n,!0),m(e)}}},{17:17,18:18,19:19,27:27,30:30,31:31,38:38,42:42,44:44,46:46,60:60,65:65,69:69,82:82}],13:[function(t,e,n){var a=t(27),r=t(10);e.exports=function(t){return function(){if(r(this)!=t)throw TypeError(t+"#toJSON isn't generic");var e=[];return a(this,!1,e.push,e),e}}},{10:10,27:27}],14:[function(t,e,n){"use strict";var a=t(31),r=t(60),i=t(4),o=t(38),s=t(69),u=t(27),p=t(8),c=t(30),l=t(82)("weak"),f=Object.isExtensible||o,d=p(5),h=p(6),m=0,v=function(t){return t._l||(t._l=new g)},g=function(){this.a=[]},b=function(t,e){return d(t.a,function(t){return t[0]===e})};g.prototype={get:function(t){var e=b(this,t);return e?e[1]:void 0},has:function(t){return!!b(this,t)},set:function(t,e){var n=b(this,t);n?n[1]=e:this.a.push([t,e])},"delete":function(t){var e=h(this.a,function(e){return e[0]===t});return~e&&this.a.splice(e,1),!!~e}},e.exports={getConstructor:function(t,e,n,a){var i=t(function(t,r){s(t,i,e),t._i=m++,t._l=void 0,void 0!=r&&u(r,n,t[a],t)});return r(i.prototype,{"delete":function(t){return o(t)?f(t)?c(t,l)&&c(t[l],this._i)&&delete t[l][this._i]:v(this)["delete"](t):!1},has:function(t){return o(t)?f(t)?c(t,l)&&c(t[l],this._i):v(this).has(t):!1}}),i},def:function(t,e,n){return f(i(e))?(c(e,l)||a(e,l,{}),e[l][t._i]=n):v(t).set(e,n),t},frozenStore:v,WEAK:l}},{27:27,30:30,31:31,38:38,4:4,60:60,69:69,8:8,82:82}],15:[function(t,e,n){"use strict";var a=t(29),r=t(22),i=t(61),o=t(60),s=t(27),u=t(69),p=t(38),c=t(24),l=t(43),f=t(66);e.exports=function(t,e,n,d,h,m){var v=a[t],g=v,b=h?"set":"add",y=g&&g.prototype,x={},_=function(t){var e=y[t];i(y,t,"delete"==t?function(t){return m&&!p(t)?!1:e.call(this,0===t?0:t)}:"has"==t?function(t){return m&&!p(t)?!1:e.call(this,0===t?0:t)}:"get"==t?function(t){return m&&!p(t)?void 0:e.call(this,0===t?0:t)}:"add"==t?function(t){return e.call(this,0===t?0:t),this}:function(t,n){return e.call(this,0===t?0:t,n),this})};if("function"==typeof g&&(m||y.forEach&&!c(function(){(new g).entries().next()}))){var w,k=new g,E=k[b](m?{}:-0,1)!=k,S=c(function(){k.has(1)}),C=l(function(t){new g(t)});C||(g=e(function(e,n){u(e,g,t);var a=new v;return void 0!=n&&s(n,h,a[b],a),a}),g.prototype=y,y.constructor=g),m||k.forEach(function(t,e){w=1/e===-(1/0)}),(S||w)&&(_("delete"),_("has"),h&&_("get")),(w||E)&&_(b),m&&y.clear&&delete y.clear}else g=d.getConstructor(e,t,h,b),o(g.prototype,n);return f(g,t),x[t]=g,r(r.G+r.W+r.F*(g!=v),x),m||d.setStrong(g,t,h),g}},{22:22,24:24,27:27,29:29,38:38,43:43,60:60,61:61,66:66,69:69}],16:[function(t,e,n){var a=e.exports={version:"1.2.6"};"number"==typeof __e&&(__e=a)},{}],17:[function(t,e,n){var a=t(2);e.exports=function(t,e,n){if(a(t),void 0===e)return t;switch(n){case 1:return function(n){return t.call(e,n)};case 2:return function(n,a){return t.call(e,n,a)};case 3:return function(n,a,r){return t.call(e,n,a,r)}}return function(){return t.apply(e,arguments)}}},{2:2}],18:[function(t,e,n){e.exports=function(t){if(void 0==t)throw TypeError("Can't call method on "+t);return t}},{}],19:[function(t,e,n){e.exports=!t(24)(function(){return 7!=Object.defineProperty({},"a",{get:function(){return 7}}).a})},{24:24}],20:[function(t,e,n){var a=t(38),r=t(29).document,i=a(r)&&a(r.createElement);e.exports=function(t){return i?r.createElement(t):{}}},{29:29,38:38}],21:[function(t,e,n){var a=t(46);e.exports=function(t){var e=a.getKeys(t),n=a.getSymbols;if(n)for(var r,i=n(t),o=a.isEnum,s=0;i.length>s;)o.call(t,r=i[s++])&&e.push(r);return e}},{46:46}],22:[function(t,e,n){var a=t(29),r=t(16),i=t(31),o=t(61),s=t(17),u="prototype",p=function(t,e,n){var c,l,f,d,h=t&p.F,m=t&p.G,v=t&p.S,g=t&p.P,b=t&p.B,y=m?a:v?a[e]||(a[e]={}):(a[e]||{})[u],x=m?r:r[e]||(r[e]={}),_=x[u]||(x[u]={});m&&(n=e);for(c in n)l=!h&&y&&c in y,f=(l?y:n)[c],d=b&&l?s(f,a):g&&"function"==typeof f?s(Function.call,f):f,y&&!l&&o(y,c,f),x[c]!=f&&i(x,c,d),g&&_[c]!=f&&(_[c]=f)};a.core=r,p.F=1,p.G=2,p.S=4,p.P=8,p.B=16,p.W=32,e.exports=p},{16:16,17:17,29:29,31:31,61:61}],23:[function(t,e,n){var a=t(83)("match");e.exports=function(t){var e=/./;try{"/./"[t](e)}catch(n){try{return e[a]=!1,!"/./"[t](e)}catch(r){}}return!0}},{83:83}],24:[function(t,e,n){e.exports=function(t){try{return!!t()}catch(e){return!0}}},{}],25:[function(t,e,n){"use strict";var a=t(31),r=t(61),i=t(24),o=t(18),s=t(83);e.exports=function(t,e,n){var u=s(t),p=""[t];i(function(){var e={};return e[u]=function(){return 7},7!=""[t](e)})&&(r(String.prototype,t,n(o,u,p)),a(RegExp.prototype,u,2==e?function(t,e){return p.call(t,this,e)}:function(t){return p.call(t,this)}))}},{18:18,24:24,31:31,61:61,83:83}],26:[function(t,e,n){"use strict";var a=t(4);e.exports=function(){var t=a(this),e="";return t.global&&(e+="g"),t.ignoreCase&&(e+="i"),t.multiline&&(e+="m"),t.unicode&&(e+="u"),t.sticky&&(e+="y"),e}},{4:4}],27:[function(t,e,n){var a=t(17),r=t(40),i=t(35),o=t(4),s=t(79),u=t(84);e.exports=function(t,e,n,p){var c,l,f,d=u(t),h=a(n,p,e?2:1),m=0;if("function"!=typeof d)throw TypeError(t+" is not iterable!");if(i(d))for(c=s(t.length);c>m;m++)e?h(o(l=t[m])[0],l[1]):h(t[m]);else for(f=d.call(t);!(l=f.next()).done;)r(f,h,l.value,e)}},{17:17,35:35,4:4,40:40,79:79,84:84}],28:[function(t,e,n){var a=t(78),r=t(46).getNames,i={}.toString,o="object"==typeof window&&Object.getOwnPropertyNames?Object.getOwnPropertyNames(window):[],s=function(t){try{return r(t)}catch(e){return o.slice()}};e.exports.get=function(t){return o&&"[object Window]"==i.call(t)?s(t):r(a(t))}},{46:46,78:78}],29:[function(t,e,n){var a=e.exports="undefined"!=typeof window&&window.Math==Math?window:"undefined"!=typeof self&&self.Math==Math?self:Function("return this")();"number"==typeof __g&&(__g=a)},{}],30:[function(t,e,n){var a={}.hasOwnProperty;e.exports=function(t,e){return a.call(t,e)}},{}],31:[function(t,e,n){var a=t(46),r=t(59);e.exports=t(19)?function(t,e,n){return a.setDesc(t,e,r(1,n))}:function(t,e,n){return t[e]=n,t}},{19:19,46:46,59:59}],32:[function(t,e,n){e.exports=t(29).document&&document.documentElement},{29:29}],33:[function(t,e,n){e.exports=function(t,e,n){var a=void 0===n;switch(e.length){case 0:return a?t():t.call(n);case 1:return a?t(e[0]):t.call(n,e[0]);case 2:return a?t(e[0],e[1]):t.call(n,e[0],e[1]);case 3:return a?t(e[0],e[1],e[2]):t.call(n,e[0],e[1],e[2]);case 4:return a?t(e[0],e[1],e[2],e[3]):t.call(n,e[0],e[1],e[2],e[3])}return t.apply(n,e)}},{}],34:[function(t,e,n){var a=t(11);e.exports=Object("z").propertyIsEnumerable(0)?Object:function(t){return"String"==a(t)?t.split(""):Object(t)}},{11:11}],35:[function(t,e,n){var a=t(45),r=t(83)("iterator"),i=Array.prototype;e.exports=function(t){return void 0!==t&&(a.Array===t||i[r]===t)}},{45:45,83:83}],36:[function(t,e,n){var a=t(11);e.exports=Array.isArray||function(t){return"Array"==a(t)}},{11:11}],37:[function(t,e,n){var a=t(38),r=Math.floor;e.exports=function(t){return!a(t)&&isFinite(t)&&r(t)===t}},{38:38}],38:[function(t,e,n){e.exports=function(t){return"object"==typeof t?null!==t:"function"==typeof t}},{}],39:[function(t,e,n){var a=t(38),r=t(11),i=t(83)("match");e.exports=function(t){var e;return a(t)&&(void 0!==(e=t[i])?!!e:"RegExp"==r(t))}},{11:11,38:38,83:83}],40:[function(t,e,n){var a=t(4);e.exports=function(t,e,n,r){try{return r?e(a(n)[0],n[1]):e(n)}catch(i){var o=t["return"];throw void 0!==o&&a(o.call(t)),i}}},{4:4}],41:[function(t,e,n){"use strict";var a=t(46),r=t(59),i=t(66),o={};t(31)(o,t(83)("iterator"),function(){return this}),e.exports=function(t,e,n){t.prototype=a.create(o,{next:r(1,n)}),i(t,e+" Iterator")}},{31:31,46:46,59:59,66:66,83:83}],42:[function(t,e,n){"use strict";var a=t(48),r=t(22),i=t(61),o=t(31),s=t(30),u=t(45),p=t(41),c=t(66),l=t(46).getProto,f=t(83)("iterator"),d=!([].keys&&"next"in[].keys()),h="@@iterator",m="keys",v="values",g=function(){return this};e.exports=function(t,e,n,b,y,x,_){p(n,e,b);var w,k,E=function(t){if(!d&&t in A)return A[t];switch(t){case m:return function(){return new n(this,t)};case v:return function(){return new n(this,t)}}return function(){return new n(this,t)}},S=e+" Iterator",C=y==v,P=!1,A=t.prototype,O=A[f]||A[h]||y&&A[y],T=O||E(y);if(O){var R=l(T.call(new t));c(R,S,!0),!a&&s(A,h)&&o(R,f,g),C&&O.name!==v&&(P=!0,T=function(){return O.call(this)})}if(a&&!_||!d&&!P&&A[f]||o(A,f,T),u[e]=T,u[S]=g,y)if(w={values:C?T:E(v),keys:x?T:E(m),entries:C?E("entries"):T},_)for(k in w)k in A||i(A,k,w[k]);else r(r.P+r.F*(d||P),e,w);return w}},{22:22,30:30,31:31,41:41,45:45,46:46,48:48,61:61,66:66,83:83}],43:[function(t,e,n){var a=t(83)("iterator"),r=!1;try{var i=[7][a]();i["return"]=function(){r=!0},Array.from(i,function(){throw 2})}catch(o){}e.exports=function(t,e){if(!e&&!r)return!1;var n=!1;try{var i=[7],o=i[a]();o.next=function(){return{done:n=!0}},i[a]=function(){return o},t(i)}catch(s){}return n}},{83:83}],44:[function(t,e,n){e.exports=function(t,e){return{value:e,done:!!t}}},{}],45:[function(t,e,n){e.exports={}},{}],46:[function(t,e,n){var a=Object;e.exports={create:a.create,getProto:a.getPrototypeOf,isEnum:{}.propertyIsEnumerable,getDesc:a.getOwnPropertyDescriptor,setDesc:a.defineProperty,setDescs:a.defineProperties,getKeys:a.keys,getNames:a.getOwnPropertyNames,getSymbols:a.getOwnPropertySymbols,each:[].forEach}},{}],47:[function(t,e,n){var a=t(46),r=t(78);e.exports=function(t,e){for(var n,i=r(t),o=a.getKeys(i),s=o.length,u=0;s>u;)if(i[n=o[u++]]===e)return n}},{46:46,78:78}],48:[function(t,e,n){e.exports=!1},{}],49:[function(t,e,n){e.exports=Math.expm1||function(t){return 0==(t=+t)?t:t>-1e-6&&1e-6>t?t+t*t/2:Math.exp(t)-1}},{}],50:[function(t,e,n){e.exports=Math.log1p||function(t){return(t=+t)>-1e-8&&1e-8>t?t-t*t/2:Math.log(1+t)}},{}],51:[function(t,e,n){e.exports=Math.sign||function(t){return 0==(t=+t)||t!=t?t:0>t?-1:1}},{}],52:[function(t,e,n){var a,r,i,o=t(29),s=t(75).set,u=o.MutationObserver||o.WebKitMutationObserver,p=o.process,c=o.Promise,l="process"==t(11)(p),f=function(){var t,e,n;for(l&&(t=p.domain)&&(p.domain=null,t.exit());a;)e=a.domain,n=a.fn,e&&e.enter(),n(),e&&e.exit(),a=a.next;r=void 0,t&&t.enter()};if(l)i=function(){p.nextTick(f)};else if(u){var d=1,h=document.createTextNode("");new u(f).observe(h,{characterData:!0}),i=function(){h.data=d=-d}}else i=c&&c.resolve?function(){c.resolve().then(f)}:function(){s.call(o,f)};e.exports=function(t){var e={fn:t,next:void 0,domain:l&&p.domain};r&&(r.next=e),a||(a=e,i()),r=e}},{11:11,29:29,75:75}],53:[function(t,e,n){var a=t(46),r=t(80),i=t(34);e.exports=t(24)(function(){var t=Object.assign,e={},n={},a=Symbol(),r="abcdefghijklmnopqrst";return e[a]=7,r.split("").forEach(function(t){n[t]=t}),7!=t({},e)[a]||Object.keys(t({},n)).join("")!=r})?function(t,e){for(var n=r(t),o=arguments,s=o.length,u=1,p=a.getKeys,c=a.getSymbols,l=a.isEnum;s>u;)for(var f,d=i(o[u++]),h=c?p(d).concat(c(d)):p(d),m=h.length,v=0;m>v;)l.call(d,f=h[v++])&&(n[f]=d[f]);return n}:Object.assign},{24:24,34:34,46:46,80:80}],54:[function(t,e,n){var a=t(22),r=t(16),i=t(24);e.exports=function(t,e){var n=(r.Object||{})[t]||Object[t],o={};o[t]=e(n),a(a.S+a.F*i(function(){n(1)}),"Object",o)}},{16:16,22:22,24:24}],55:[function(t,e,n){var a=t(46),r=t(78),i=a.isEnum;e.exports=function(t){return function(e){for(var n,o=r(e),s=a.getKeys(o),u=s.length,p=0,c=[];u>p;)i.call(o,n=s[p++])&&c.push(t?[n,o[n]]:o[n]);return c}}},{46:46,78:78}],56:[function(t,e,n){var a=t(46),r=t(4),i=t(29).Reflect;e.exports=i&&i.ownKeys||function(t){var e=a.getNames(r(t)),n=a.getSymbols;return n?e.concat(n(t)):e}},{29:29,4:4,46:46}],57:[function(t,e,n){"use strict";var a=t(58),r=t(33),i=t(2);e.exports=function(){for(var t=i(this),e=arguments.length,n=Array(e),o=0,s=a._,u=!1;e>o;)(n[o]=arguments[o++])===s&&(u=!0);return function(){var a,i=this,o=arguments,p=o.length,c=0,l=0;if(!u&&!p)return r(t,n,i);if(a=n.slice(),u)for(;e>c;c++)a[c]===s&&(a[c]=o[l++]);for(;p>l;)a.push(o[l++]);return r(t,a,i)}}},{2:2,33:33,58:58}],58:[function(t,e,n){e.exports=t(29)},{29:29}],59:[function(t,e,n){e.exports=function(t,e){return{enumerable:!(1&t),configurable:!(2&t),writable:!(4&t),value:e}}},{}],60:[function(t,e,n){var a=t(61);e.exports=function(t,e){for(var n in e)a(t,n,e[n]);return t}},{61:61}],61:[function(t,e,n){var a=t(29),r=t(31),i=t(82)("src"),o="toString",s=Function[o],u=(""+s).split(o);t(16).inspectSource=function(t){return s.call(t)},(e.exports=function(t,e,n,o){"function"==typeof n&&(n.hasOwnProperty(i)||r(n,i,t[e]?""+t[e]:u.join(e+"")),n.hasOwnProperty("name")||r(n,"name",e)),t===a?t[e]=n:(o||delete t[e],r(t,e,n))})(Function.prototype,o,function(){return"function"==typeof this&&this[i]||s.call(this)})},{16:16,29:29,31:31,82:82}],62:[function(t,e,n){e.exports=function(t,e){var n=e===Object(e)?function(t){return e[t]}:e;return function(e){return(e+"").replace(t,n)}}},{}],63:[function(t,e,n){e.exports=Object.is||function(t,e){return t===e?0!==t||1/t===1/e:t!=t&&e!=e}},{}],64:[function(t,e,n){var a=t(46).getDesc,r=t(38),i=t(4),o=function(t,e){if(i(t),!r(e)&&null!==e)throw TypeError(e+": can't set as prototype!")};e.exports={set:Object.setPrototypeOf||("__proto__"in{}?function(e,n,r){try{r=t(17)(Function.call,a(Object.prototype,"__proto__").set,2),r(e,[]),n=!(e instanceof Array)}catch(i){n=!0}return function(t,e){return o(t,e),n?t.__proto__=e:r(t,e),t}}({},!1):void 0),check:o}},{17:17,38:38,4:4,46:46}],65:[function(t,e,n){"use strict";var a=t(29),r=t(46),i=t(19),o=t(83)("species");e.exports=function(t){var e=a[t];i&&e&&!e[o]&&r.setDesc(e,o,{configurable:!0,get:function(){return this}})}},{19:19,29:29,46:46,83:83}],66:[function(t,e,n){var a=t(46).setDesc,r=t(30),i=t(83)("toStringTag");e.exports=function(t,e,n){t&&!r(t=n?t:t.prototype,i)&&a(t,i,{configurable:!0,value:e})}},{30:30,46:46,83:83}],67:[function(t,e,n){var a=t(29),r="__core-js_shared__",i=a[r]||(a[r]={});e.exports=function(t){return i[t]||(i[t]={})}},{29:29}],68:[function(t,e,n){var a=t(4),r=t(2),i=t(83)("species");e.exports=function(t,e){var n,o=a(t).constructor;return void 0===o||void 0==(n=a(o)[i])?e:r(n)}},{2:2,4:4,83:83}],69:[function(t,e,n){e.exports=function(t,e,n){if(!(t instanceof e))throw TypeError(n+": use the 'new' operator!");return t}},{}],70:[function(t,e,n){var a=t(77),r=t(18);e.exports=function(t){return function(e,n){var i,o,s=r(e)+"",u=a(n),p=s.length;return 0>u||u>=p?t?"":void 0:(i=s.charCodeAt(u),55296>i||i>56319||u+1===p||(o=s.charCodeAt(u+1))<56320||o>57343?t?s.charAt(u):i:t?s.slice(u,u+2):(i-55296<<10)+(o-56320)+65536)}}},{18:18,77:77}],71:[function(t,e,n){var a=t(39),r=t(18);e.exports=function(t,e,n){if(a(e))throw TypeError("String#"+n+" doesn't accept regex!");return r(t)+""}},{18:18,39:39}],72:[function(t,e,n){var a=t(79),r=t(73),i=t(18);e.exports=function(t,e,n,o){var s=i(t)+"",u=s.length,p=void 0===n?" ":n+"",c=a(e);if(u>=c)return s;""==p&&(p=" ");var l=c-u,f=r.call(p,Math.ceil(l/p.length));return f.length>l&&(f=f.slice(0,l)),o?f+s:s+f}},{18:18,73:73,79:79}],73:[function(t,e,n){"use strict";var a=t(77),r=t(18);e.exports=function(t){var e=r(this)+"",n="",i=a(t);if(0>i||i==1/0)throw RangeError("Count can't be negative");for(;i>0;(i>>>=1)&&(e+=e))1&i&&(n+=e);return n}},{18:18,77:77}],74:[function(t,e,n){var a=t(22),r=t(18),i=t(24),o=" \n\x0B\f\r  ᠎              \u2028\u2029\ufeff",s="["+o+"]",u="​…",p=RegExp("^"+s+s+"*"),c=RegExp(s+s+"*$"),l=function(t,e){var n={};n[t]=e(f),a(a.P+a.F*i(function(){return!!o[t]()||u[t]()!=u}),"String",n)},f=l.trim=function(t,e){return t=r(t)+"",1&e&&(t=t.replace(p,"")),2&e&&(t=t.replace(c,"")),t};e.exports=l},{18:18,22:22,24:24}],75:[function(t,e,n){var a,r,i,o=t(17),s=t(33),u=t(32),p=t(20),c=t(29),l=c.process,f=c.setImmediate,d=c.clearImmediate,h=c.MessageChannel,m=0,v={},g="onreadystatechange",b=function(){var t=+this;if(v.hasOwnProperty(t)){var e=v[t];delete v[t],e()}},y=function(t){b.call(t.data)};f&&d||(f=function(t){for(var e=[],n=1;arguments.length>n;)e.push(arguments[n++]);return v[++m]=function(){s("function"==typeof t?t:Function(t),e)},a(m),m},d=function(t){delete v[t]},"process"==t(11)(l)?a=function(t){l.nextTick(o(b,t,1))}:h?(r=new h,i=r.port2,r.port1.onmessage=y,a=o(i.postMessage,i,1)):c.addEventListener&&"function"==typeof postMessage&&!c.importScripts?(a=function(t){c.postMessage(t+"","*")},c.addEventListener("message",y,!1)):a=g in p("script")?function(t){u.appendChild(p("script"))[g]=function(){u.removeChild(this),b.call(t)}}:function(t){setTimeout(o(b,t,1),0)}),e.exports={set:f,clear:d}},{11:11,17:17,20:20,29:29,32:32,33:33}],76:[function(t,e,n){var a=t(77),r=Math.max,i=Math.min;e.exports=function(t,e){return t=a(t),0>t?r(t+e,0):i(t,e)}},{77:77}],77:[function(t,e,n){var a=Math.ceil,r=Math.floor;e.exports=function(t){return isNaN(t=+t)?0:(t>0?r:a)(t)}},{}],78:[function(t,e,n){var a=t(34),r=t(18);e.exports=function(t){return a(r(t))}},{18:18,34:34}],79:[function(t,e,n){var a=t(77),r=Math.min;e.exports=function(t){return t>0?r(a(t),9007199254740991):0}},{77:77}],80:[function(t,e,n){var a=t(18);e.exports=function(t){return Object(a(t))}},{18:18}],81:[function(t,e,n){var a=t(38);e.exports=function(t,e){if(!a(t))return t;var n,r;if(e&&"function"==typeof(n=t.toString)&&!a(r=n.call(t)))return r;if("function"==typeof(n=t.valueOf)&&!a(r=n.call(t)))return r;if(!e&&"function"==typeof(n=t.toString)&&!a(r=n.call(t)))return r;throw TypeError("Can't convert object to primitive value")}},{38:38}],82:[function(t,e,n){var a=0,r=Math.random();e.exports=function(t){return"Symbol(".concat(void 0===t?"":t,")_",(++a+r).toString(36))}},{}],83:[function(t,e,n){var a=t(67)("wks"),r=t(82),i=t(29).Symbol;e.exports=function(t){return a[t]||(a[t]=i&&i[t]||(i||r)("Symbol."+t))}},{29:29,67:67,82:82}],84:[function(t,e,n){var a=t(10),r=t(83)("iterator"),i=t(45);e.exports=t(16).getIteratorMethod=function(t){return void 0!=t?t[r]||t["@@iterator"]||i[a(t)]:void 0}},{10:10,16:16,45:45,83:83}],85:[function(t,e,n){"use strict";var a,r=t(46),i=t(22),o=t(19),s=t(59),u=t(32),p=t(20),c=t(30),l=t(11),f=t(33),d=t(24),h=t(4),m=t(2),v=t(38),g=t(80),b=t(78),y=t(77),x=t(76),_=t(79),w=t(34),k=t(82)("__proto__"),E=t(8),S=t(7)(!1),C=Object.prototype,P=Array.prototype,A=P.slice,O=P.join,T=r.setDesc,R=r.getDesc,M=r.setDescs,j={};o||(a=!d(function(){return 7!=T(p("div"),"a",{get:function(){return 7}}).a}),r.setDesc=function(t,e,n){if(a)try{return T(t,e,n)}catch(r){}if("get"in n||"set"in n)throw TypeError("Accessors not supported!");return"value"in n&&(h(t)[e]=n.value),t},r.getDesc=function(t,e){if(a)try{return R(t,e)}catch(n){}return c(t,e)?s(!C.propertyIsEnumerable.call(t,e),t[e]):void 0},r.setDescs=M=function(t,e){h(t);for(var n,a=r.getKeys(e),i=a.length,o=0;i>o;)r.setDesc(t,n=a[o++],e[n]);return t}),i(i.S+i.F*!o,"Object",{getOwnPropertyDescriptor:r.getDesc,defineProperty:r.setDesc,defineProperties:M});var L="constructor,hasOwnProperty,isPrototypeOf,propertyIsEnumerable,toLocaleString,toString,valueOf".split(","),N=L.concat("length","prototype"),D=L.length,F=function(){var t,e=p("iframe"),n=D,a=">";for(e.style.display="none",u.appendChild(e),e.src="javascript:",t=e.contentWindow.document,t.open(),t.write("