diff --git a/_maps/RandomRuins/LavaRuins/lavaland_surface_elephant_graveyard.dmm b/_maps/RandomRuins/LavaRuins/lavaland_surface_elephant_graveyard.dmm new file mode 100644 index 0000000000..f590af752b --- /dev/null +++ b/_maps/RandomRuins/LavaRuins/lavaland_surface_elephant_graveyard.dmm @@ -0,0 +1,1721 @@ +//MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"aa" = ( +/turf/template_noop, +/area/template_noop) +"ab" = ( +/turf/closed/mineral/volcanic/lava_land_surface, +/area/lavaland/surface) +"ac" = ( +/turf/closed/mineral/volcanic/lava_land_surface, +/area/ruin/unpowered/elephant_graveyard) +"ad" = ( +/obj/effect/decal/cleanable/cobweb, +/obj/structure/closet/crate/grave/lead_researcher, +/obj/effect/decal/cleanable/blood/gibs/old, +/obj/effect/mob_spawn/human/skeleton, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ae" = ( +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"af" = ( +/obj/effect/decal/cleanable/blood/drip, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ag" = ( +/obj/effect/decal/cleanable/vomit, +/obj/item/shovel, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ah" = ( +/obj/effect/decal/cleanable/blood/old, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ai" = ( +/obj/effect/decal/cleanable/blood/tracks{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aj" = ( +/obj/effect/decal/cleanable/blood/tracks{ + dir = 4 + }, +/obj/item/paper/fluff/ruins/elephant_graveyard/final_message, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ak" = ( +/turf/open/floor/plating/asteroid/basalt/wasteland{ + icon_state = "wasteland_dug" + }, +/area/ruin/unpowered/elephant_graveyard) +"al" = ( +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"am" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"an" = ( +/obj/item/reagent_containers/food/snacks/deadmouse, +/obj/item/assembly/mousetrap, +/turf/open/floor/plating/asteroid/basalt/wasteland{ + icon_state = "wasteland_dug" + }, +/area/ruin/unpowered/elephant_graveyard) +"ao" = ( +/obj/structure/statue/bone/skull/half, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ap" = ( +/obj/structure/statue/bone/skull/half{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aq" = ( +/obj/item/reagent_containers/glass/bottle/frostoil{ + desc = "A small bottle. Contains cold sauce. There's a label on here: APPLY ON SEVERE BURNS."; + volume = 10 + }, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ar" = ( +/obj/structure/flora/rock, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"as" = ( +/obj/structure/flora/rock, +/obj/item/pickaxe{ + layer = 2.5; + pixel_x = -8; + pixel_y = 5 + }, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"at" = ( +/turf/closed/mineral/strong/wasteland, +/area/lavaland/surface) +"au" = ( +/obj/structure/table, +/obj/item/t_scanner/adv_mining_scanner/lesser, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"av" = ( +/obj/structure/barricade/wooden/crude, +/obj/structure/barricade/wooden, +/obj/effect/decal/cleanable/blood/splatter, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aw" = ( +/obj/structure/table, +/obj/item/paper/crumpled/muddy/fluff/elephant_graveyard/rnd_notes, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ax" = ( +/obj/structure/statue/bone/rib{ + dir = 1 + }, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ay" = ( +/obj/structure/statue/bone/rib, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"az" = ( +/obj/structure/table, +/obj/item/pen, +/obj/item/pen, +/obj/item/pen, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aA" = ( +/turf/closed/wall, +/area/ruin/unpowered/elephant_graveyard) +"aB" = ( +/obj/item/chair, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aC" = ( +/obj/effect/decal/remains/human, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aD" = ( +/obj/structure/table, +/obj/item/reagent_containers/glass/bottle/plasma{ + volume = 25 + }, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aE" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aF" = ( +/obj/structure/table, +/obj/machinery/power/floodlight, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aG" = ( +/obj/structure/table, +/obj/effect/spawner/lootdrop/glowstick, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aH" = ( +/turf/closed/wall/mineral/titanium, +/area/ruin/powered/graveyard_shuttle) +"aI" = ( +/obj/effect/spawner/structure/window/shuttle, +/obj/structure/grille, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/powered/graveyard_shuttle) +"aJ" = ( +/obj/structure/table, +/obj/item/clipboard, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aK" = ( +/obj/item/cigbutt, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aL" = ( +/obj/structure/table, +/obj/item/paper_bin, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aM" = ( +/obj/structure/table, +/obj/item/clothing/gloves/color/black, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aN" = ( +/turf/closed/wall/mineral/titanium/nodiagonal, +/area/ruin/powered/graveyard_shuttle) +"aO" = ( +/obj/effect/decal/cleanable/glass, +/obj/machinery/computer, +/turf/open/floor/mineral/titanium/white, +/area/ruin/powered/graveyard_shuttle) +"aP" = ( +/obj/structure/bed, +/obj/item/flashlight/lantern, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aQ" = ( +/obj/machinery/power/floodlight, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aR" = ( +/obj/structure/table, +/obj/item/taperecorder, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aS" = ( +/obj/structure/table, +/obj/item/tape/random, +/obj/item/tape/random, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aT" = ( +/obj/structure/closet/crate/bin, +/obj/item/trash/candle, +/obj/item/trash/can, +/obj/item/trash/can, +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/cigbutt, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aU" = ( +/obj/structure/bed, +/obj/item/bedsheet/brown, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aV" = ( +/obj/structure/bed, +/obj/item/bedsheet/brown, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aW" = ( +/obj/structure/filingcabinet/chestdrawer, +/obj/item/clothing/mask/gas/explorer/folded, +/turf/open/floor/mineral/titanium/white, +/area/ruin/powered/graveyard_shuttle) +"aX" = ( +/obj/structure/reagent_dispensers/fueltank, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"aY" = ( +/obj/structure/sign/warning/nosmoking/circle, +/turf/closed/wall, +/area/ruin/unpowered/elephant_graveyard) +"aZ" = ( +/obj/item/organ/brain, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ba" = ( +/obj/structure/headpike/bone, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bb" = ( +/obj/effect/decal/cleanable/oil/streak, +/obj/effect/decal/cleanable/glass, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bc" = ( +/obj/structure/sign/poster/ripped, +/turf/closed/wall, +/area/ruin/unpowered/elephant_graveyard) +"bd" = ( +/obj/item/organ/heart, +/obj/item/organ/eyes, +/obj/item/organ/ears, +/obj/effect/decal/cleanable/blood/gibs/old, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"be" = ( +/obj/item/organ/lungs, +/obj/item/organ/liver, +/obj/effect/decal/cleanable/blood/old, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bf" = ( +/turf/closed/mineral/strong/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bg" = ( +/obj/structure/sign/warning/securearea, +/turf/closed/wall/mineral/titanium, +/area/ruin/powered/graveyard_shuttle) +"bh" = ( +/obj/effect/decal/cleanable/oil, +/obj/structure/chair/office/light, +/turf/open/floor/mineral/titanium/white, +/area/ruin/powered/graveyard_shuttle) +"bi" = ( +/obj/effect/turf_decal/delivery/white, +/turf/open/floor/circuit/off, +/area/ruin/powered/graveyard_shuttle) +"bj" = ( +/obj/structure/barricade/wooden, +/obj/structure/mineral_door/wood, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bk" = ( +/obj/item/kitchen/knife/combat/bone, +/obj/item/organ/tongue, +/obj/effect/decal/cleanable/blood/old, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bl" = ( +/obj/effect/decal/cleanable/shreds, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bm" = ( +/obj/structure/closet/wardrobe/curator, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bn" = ( +/obj/structure/sink/oil_well, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bo" = ( +/obj/item/stack/medical/gauze/improvised, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bp" = ( +/turf/open/floor/mineral/titanium/white, +/area/ruin/powered/graveyard_shuttle) +"bq" = ( +/obj/machinery/iv_drip, +/turf/open/floor/mineral/titanium/white, +/area/ruin/powered/graveyard_shuttle) +"br" = ( +/obj/structure/sign/warning/nosmoking/circle, +/turf/closed/wall/mineral/titanium, +/area/ruin/powered/graveyard_shuttle) +"bs" = ( +/obj/structure/fence/door, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bt" = ( +/obj/structure/table, +/turf/closed/mineral/strong/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bu" = ( +/obj/structure/bed, +/obj/item/trash/pistachios, +/obj/item/trash/chips, +/obj/item/bedsheet/brown, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bv" = ( +/obj/effect/decal/remains/human, +/obj/item/clothing/under/misc/overalls, +/obj/item/clothing/mask/bandana/green, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bw" = ( +/obj/structure/rack, +/obj/item/shovel, +/obj/item/wrench, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bx" = ( +/obj/item/reagent_containers/food/snacks/deadmouse, +/obj/item/assembly/mousetrap, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"by" = ( +/obj/structure/closet/emcloset, +/obj/item/light/bulb, +/obj/effect/turf_decal/box/white, +/turf/open/floor/mineral/titanium/purple, +/area/ruin/powered/graveyard_shuttle) +"bz" = ( +/obj/item/paper/crumpled/muddy/fluff/elephant_graveyard/mutiny, +/obj/item/cigbutt, +/obj/item/cigbutt, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bA" = ( +/obj/machinery/suit_storage_unit/mining/eva, +/obj/effect/turf_decal/box/white, +/turf/open/floor/mineral/titanium/purple, +/area/ruin/powered/graveyard_shuttle) +"bB" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bC" = ( +/obj/structure/barricade/sandbags, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bD" = ( +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/elephant_graveyard) +"bE" = ( +/obj/structure/shuttle/engine/heater, +/obj/structure/window{ + dir = 1 + }, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/turf/open/floor/mineral/titanium/purple, +/area/ruin/powered/graveyard_shuttle) +"bF" = ( +/obj/effect/decal/cleanable/dirt, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/elephant_graveyard) +"bG" = ( +/obj/effect/decal/remains/human, +/obj/item/tank/internals/emergency_oxygen/empty, +/obj/effect/decal/cleanable/blood/old, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bH" = ( +/obj/item/paper/fluff/ruins/elephant_graveyard, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface) +"bI" = ( +/obj/structure/shuttle/engine/propulsion, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/powered/graveyard_shuttle) +"bJ" = ( +/obj/structure/sign/warning/xeno_mining, +/turf/closed/wall, +/area/ruin/unpowered/elephant_graveyard) +"bK" = ( +/obj/structure/sign/warning/explosives, +/turf/closed/wall, +/area/ruin/unpowered/elephant_graveyard) +"bL" = ( +/obj/effect/decal/cleanable/blood/gibs/old, +/obj/effect/decal/cleanable/blood/splatter, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bM" = ( +/obj/item/storage/fancy/cigarettes/cigpack_mindbreaker, +/obj/structure/closet/crate/grave, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bN" = ( +/obj/structure/sign/warning/securearea, +/obj/structure/sign/warning/securearea, +/turf/closed/mineral/strong/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bO" = ( +/obj/item/paper/fluff/ruins/elephant_graveyard, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bP" = ( +/obj/structure/barricade/wooden/crude, +/obj/item/paper/fluff/ruins/elephant_graveyard, +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/ruin/unpowered/elephant_graveyard) +"bQ" = ( +/obj/structure/filingcabinet/chestdrawer, +/obj/effect/decal/cleanable/cobweb, +/obj/item/paper/fluff/ruins/elephant_graveyard/hypothesis, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/mineral/titanium/white, +/area/ruin/powered/graveyard_shuttle) +"bR" = ( +/obj/effect/decal/cleanable/generic, +/obj/item/cigbutt, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bS" = ( +/obj/effect/decal/cleanable/oil/slippery, +/obj/machinery/rnd/destructive_analyzer, +/turf/open/floor/mineral/titanium/white, +/area/ruin/powered/graveyard_shuttle) +"bT" = ( +/obj/structure/barricade/wooden, +/obj/item/paper/fluff/ruins/elephant_graveyard, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bU" = ( +/obj/item/light/bulb/broken, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/mineral/titanium/white, +/area/ruin/powered/graveyard_shuttle) +"bV" = ( +/obj/effect/decal/cleanable/dirt, +/turf/closed/mineral/volcanic/lava_land_surface, +/area/ruin/unpowered/elephant_graveyard) +"bW" = ( +/obj/effect/decal/cleanable/glass, +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/door/airlock/shuttle{ + name = "archaeology shuttle airlock" + }, +/turf/open/floor/mineral/titanium/purple, +/area/ruin/powered/graveyard_shuttle) +"bX" = ( +/obj/effect/decal/remains/human, +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/clothing/head/fedora/curator, +/obj/item/clothing/suit/curator, +/turf/open/floor/mineral/titanium/white, +/area/ruin/powered/graveyard_shuttle) +"bY" = ( +/obj/effect/decal/cleanable/dirt/dust, +/obj/item/cigbutt, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"bZ" = ( +/turf/open/floor/plating/asteroid/basalt/lava_land_surface, +/area/lavaland/surface) +"ca" = ( +/obj/structure/table, +/obj/item/storage/firstaid/o2, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cb" = ( +/obj/machinery/power/port_gen/pacman, +/obj/effect/mapping_helpers/network_builder/power_cable, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cc" = ( +/obj/effect/decal/remains/human, +/obj/effect/decal/cleanable/blood/old, +/obj/effect/decal/cleanable/shreds, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cd" = ( +/obj/item/trash/can, +/obj/structure/bedsheetbin/empty, +/obj/structure/table, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ce" = ( +/obj/structure/stone_tile/slab/cracked, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cf" = ( +/obj/structure/bed, +/obj/item/wirecutters, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cg" = ( +/obj/structure/stone_tile/center/cracked, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ch" = ( +/obj/effect/decal/remains/human, +/obj/item/restraints/handcuffs/cable/zipties/used, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ci" = ( +/obj/structure/stone_tile/surrounding_tile, +/turf/open/floor/plating/asteroid/basalt/wasteland{ + icon_state = "wasteland_dug" + }, +/area/ruin/unpowered/elephant_graveyard) +"cj" = ( +/obj/structure/stone_tile/block/cracked, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ck" = ( +/obj/structure/reagent_dispensers/water_cooler, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cl" = ( +/obj/structure/closet/crate/grave, +/obj/effect/mob_spawn/human/skeleton, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cm" = ( +/obj/structure/table/optable, +/obj/item/storage/backpack/explorer, +/obj/item/reagent_containers/food/drinks/soda_cans/cola, +/obj/item/restraints/handcuffs/cable/zipties/used, +/turf/open/floor/mineral/titanium/white, +/area/ruin/powered/graveyard_shuttle) +"cn" = ( +/obj/structure/stone_tile/cracked, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"co" = ( +/obj/effect/decal/cleanable/blood/drip, +/obj/structure/stone_tile/cracked, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cq" = ( +/obj/structure/stone_tile/block/cracked{ + dir = 4 + }, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cr" = ( +/obj/structure/bonfire/prelit, +/obj/effect/decal/cleanable/ash, +/obj/item/organ/tail/lizard, +/obj/effect/decal/cleanable/blood/old, +/obj/structure/stone_tile/slab/cracked, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cs" = ( +/obj/structure/ore_box, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"ct" = ( +/obj/structure/stone_tile, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cu" = ( +/obj/structure/stone_tile{ + dir = 8 + }, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cv" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/mineral/titanium/white, +/area/ruin/powered/graveyard_shuttle) +"cw" = ( +/obj/structure/closet/crate/grave, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/mob_spawn/human/skeleton, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) +"cx" = ( +/obj/item/light/bulb/broken, +/obj/effect/turf_decal/caution/stand_clear/white, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/mineral/titanium/purple, +/area/ruin/powered/graveyard_shuttle) +"cz" = ( +/obj/structure/stone_tile, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating/asteroid/basalt/wasteland, +/area/ruin/unpowered/elephant_graveyard) + +(1,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +ab +ab +ab +ab +ab +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +"} +(2,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +aa +ab +ab +ab +at +ab +ab +ab +ac +ac +ac +ac +bf +ac +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +aa +aa +"} +(3,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +ab +ab +bf +bf +bf +bf +bf +ac +ac +ac +ac +bf +bf +bf +ac +ac +ab +ab +ab +aa +aa +aa +aa +aa +aa +aa +aa +"} +(4,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +ab +ab +bf +bf +aT +bR +bf +bf +bf +ac +bf +bf +bf +bf +bf +bf +bf +ac +ac +ab +ab +aa +aa +aa +aa +aa +aa +aa +"} +(5,1,1) = {" +aa +aa +aa +aa +aa +ab +ab +ab +bf +bf +bf +bz +aK +bY +ae +bf +bf +bf +cs +aE +bJ +bf +bf +bf +ac +ac +ac +ab +ab +ab +aa +aa +aa +aa +aa +"} +(6,1,1) = {" +aa +aa +aa +aa +ab +ab +bf +bf +bf +bf +aA +bc +aA +aY +ae +bv +ae +cl +ae +ae +aC +bs +bO +ae +ae +ac +ac +ac +ac +ab +ab +ab +aa +aa +aa +"} +(7,1,1) = {" +aa +aa +aa +aa +ab +bf +bf +bf +aq +al +al +al +aQ +ae +ae +ak +ae +ae +ae +ae +bK +bf +bf +bf +ae +ac +ac +ac +ac +ac +ac +ab +ab +aa +aa +"} +(8,1,1) = {" +aa +aa +ab +ab +ab +bf +bf +al +al +ar +ae +ae +ae +ar +aZ +ae +ba +ae +ba +ae +ae +ae +ae +bf +ae +ac +ac +ac +ac +ac +ac +ac +ab +ab +aa +"} +(9,1,1) = {" +aa +ab +ab +bf +bf +bf +al +al +ak +ae +aE +ae +ae +ae +ba +ae +af +ae +ae +ae +ba +ae +ak +bf +ae +ae +ac +ac +ac +ac +ac +ac +ac +ac +aa +"} +(10,1,1) = {" +ab +ab +bf +bf +bf +al +am +ae +ae +ae +ae +cl +ae +ae +ae +co +bd +bk +ae +ae +ae +ae +aE +bf +bf +ae +ae +ac +ac +ac +ac +bG +bM +ac +ac +"} +(11,1,1) = {" +at +bf +bf +bf +bf +al +ae +ae +ao +ae +ax +ax +ax +ax +ae +ae +be +cr +ae +cz +ae +ae +bn +cw +bf +bf +bB +ac +ac +ac +ac +bL +ae +ae +ac +"} +(12,1,1) = {" +at +bf +bf +bf +bf +al +cl +ae +ae +ae +ae +ci +cj +ce +ae +cj +ae +cq +ae +ae +cu +ae +ae +ae +bf +bf +bC +ac +ac +ac +ac +ac +ac +bD +ac +"} +(13,1,1) = {" +bf +ad +ae +bf +cl +al +ae +ae +ae +ae +cg +ae +ak +ak +cn +ae +cq +ae +ct +ar +ae +cl +ae +ae +bf +bf +ae +ac +ac +ac +ac +ac +ac +ae +ac +"} +(14,1,1) = {" +bf +aj +ae +bf +ae +al +aE +ae +ap +ae +ay +ay +ay +ay +ae +ae +ak +ae +ae +bn +ae +ae +aE +aQ +bf +cl +bB +ae +ac +ac +ac +ac +ac +ae +ac +"} +(15,1,1) = {" +bf +ai +ag +bf +an +al +ae +ae +ae +ae +ae +ae +ae +ae +ae +ae +ae +cw +ae +ae +ae +ae +ae +al +bf +ac +ae +ae +bB +ac +ac +ac +ac +bD +ac +"} +(16,1,1) = {" +bf +ai +bf +bf +bf +al +al +al +ae +ae +aE +ae +ar +ae +ba +ae +ae +ae +ae +ae +ba +ae +ae +al +bf +ac +ac +ae +ae +bB +ac +ac +ac +bB +bP +"} +(17,1,1) = {" +bf +ae +af +bf +bf +aE +bf +al +as +au +az +aG +aM +aR +ae +ae +ba +ae +ba +ae +ae +aE +cl +al +bf +bf +ac +ac +ae +bD +ac +ac +ac +bF +bT +"} +(18,1,1) = {" +at +bf +ah +bf +bf +af +bf +ae +ae +aw +aB +ae +ae +aS +ae +ae +aE +ae +ae +ae +ae +ae +ae +al +cb +bf +ac +ac +ac +ae +bB +bB +bF +bB +bP +"} +(19,1,1) = {" +ab +bf +af +av +af +ae +bf +ae +bt +aD +ch +ae +ae +ca +ae +al +al +al +al +al +al +al +al +bx +bf +bf +ac +ac +ac +ac +bF +bB +bV +ac +ac +"} +(20,1,1) = {" +aa +at +bf +bf +bf +bf +bf +bj +bf +aF +aJ +aL +al +al +al +bw +bf +ac +bm +ae +bn +bf +bf +bf +bf +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +"} +(21,1,1) = {" +aa +aa +ab +ac +ac +bf +aU +aE +bf +bf +bf +bf +ck +aX +ae +bf +bf +bf +bf +bf +bf +bf +bf +ac +ac +ac +ac +ac +ac +ac +ac +ac +ac +ab +ab +"} +(22,1,1) = {" +aa +aa +ab +ab +ac +bf +aU +ae +bl +cd +bf +bf +bf +bN +ae +bf +bf +bf +bf +ac +ac +ac +ac +ac +ac +ac +ac +ab +ab +ab +ab +ab +ab +bZ +bZ +"} +(23,1,1) = {" +aa +aa +aa +ab +ab +bf +aV +bl +aE +bu +bf +bf +bf +bf +bb +bf +bf +bf +bf +ab +ab +ab +ab +ab +ab +ab +ab +bZ +bZ +bZ +bH +bZ +bZ +bZ +ab +"} +(24,1,1) = {" +aa +aa +aa +aa +ab +at +aP +bo +cc +cf +bf +aH +aH +bg +bW +bg +aH +aH +aH +bH +bZ +bZ +bZ +bZ +bZ +bZ +bZ +bZ +bZ +bZ +bZ +bZ +ab +ab +ab +"} +(25,1,1) = {" +aa +aa +aa +aa +aa +at +bf +bf +bf +bf +aH +aN +bQ +bh +cv +bU +by +aH +aH +bI +bZ +bZ +bZ +bZ +bZ +bZ +bZ +bZ +bZ +ab +ab +ab +ab +ab +ab +"} +(26,1,1) = {" +aa +aa +aa +aa +aa +ab +ab +ab +ab +ab +aI +aO +bX +bi +bp +bi +cx +bE +aH +bI +bZ +bZ +bZ +bZ +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +"} +(27,1,1) = {" +aa +aa +aa +aa +aa +aa +ab +ab +ab +ab +aH +aN +aW +cm +bq +bS +bA +aH +aH +bI +bZ +bZ +bZ +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +aa +"} +(28,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +ab +ab +ab +ab +aH +aH +aH +br +aH +aH +aH +aH +bZ +bZ +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +aa +aa +"} +(29,1,1) = {" +aa +aa +aa +aa +aa +aa +aa +aa +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +ab +aa +aa +aa +aa +aa +"} diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 40f05e974c..0c91f2cff9 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -124873,10 +124873,6 @@ }, /turf/open/floor/plasteel/airless/solarpanel, /area/solar/port/aft) -"egC" = ( -/obj/effect/spawner/structure/window/reinforced, -/turf/open/floor/plating, -/area/chapel/office) "egD" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 1 @@ -162453,7 +162449,7 @@ edT eeC efp egd -egC +efg aaa aad aaa @@ -162710,7 +162706,7 @@ edU eeD efq ege -egC +efg aaa aad aaa @@ -162967,7 +162963,7 @@ edV eeE efr ege -egC +efg aad ajr aaa diff --git a/code/__DEFINES/_flags/_flags.dm b/code/__DEFINES/_flags/_flags.dm index 9facaf5d70..abc0507bf4 100644 --- a/code/__DEFINES/_flags/_flags.dm +++ b/code/__DEFINES/_flags/_flags.dm @@ -74,8 +74,10 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define FLYING (1<<1) #define VENTCRAWLING (1<<2) #define FLOATING (1<<3) -#define UNSTOPPABLE (1<<4) //When moving, will Bump()/Cross()/Uncross() everything, but won't be stopped. -#define CRAWLING (1<<5) //Applied if you're crawling around on the ground/resting. +///When moving, will Bump()/Cross()/Uncross() everything, but won't be stopped. +#define UNSTOPPABLE (1<<4) +///Applied if you're crawling around on the ground/resting. +#define CRAWLING (1<<5) //Fire and Acid stuff, for resistance_flags #define LAVA_PROOF (1<<0) diff --git a/code/__DEFINES/citadel_defines.dm b/code/__DEFINES/citadel_defines.dm index 82dc87e465..07f24fd8a3 100644 --- a/code/__DEFINES/citadel_defines.dm +++ b/code/__DEFINES/citadel_defines.dm @@ -101,8 +101,5 @@ #define TOGGLES_CITADEL 0 -//component stuff -#define COMSIG_VORE_TOGGLED "voremode_toggled" // totally not copypasta - //belly sound pref things #define NORMIE_HEARCHECK 4 diff --git a/code/__DEFINES/combat.dm b/code/__DEFINES/combat.dm index 7c3d77f490..fc7d9e13e0 100644 --- a/code/__DEFINES/combat.dm +++ b/code/__DEFINES/combat.dm @@ -29,38 +29,27 @@ #define EFFECT_DROWSY "drowsy" #define EFFECT_JITTER "jitter" -// /mob/living/combat_flags -#define CAN_TOGGLE_COMBAT_MODE(mob) FORCE_BOOLEAN((mob.stat == CONSCIOUS) && !(mob.combat_flags & COMBAT_FLAG_HARD_STAMCRIT)) - -/// Default combat flags for those affected by ((stamina combat)) +/// Default combat flags for those affected by sprinting (combat mode has been made into its own component) #define COMBAT_FLAGS_DEFAULT NONE -/// Default combat flags for everyone else (so literally everyone but humans) -#define COMBAT_FLAGS_STAMSYSTEM_EXEMPT (COMBAT_FLAG_SPRINT_ACTIVE | COMBAT_FLAG_COMBAT_ACTIVE | COMBAT_FLAG_SPRINT_TOGGLED | COMBAT_FLAG_COMBAT_TOGGLED | COMBAT_FLAG_SPRINT_FORCED | COMBAT_FLAG_COMBAT_FORCED) -/// Default combat flags for those only affected by sprint (so just silicons) -#define COMBAT_FLAGS_STAMEXEMPT_YESSPRINT (COMBAT_FLAG_COMBAT_ACTIVE | COMBAT_FLAG_COMBAT_TOGGLED | COMBAT_FLAG_COMBAT_FORCED) +/// Default combat flags for everyone else (so literally everyone but humans). +#define COMBAT_FLAGS_SPRINT_EXEMPT (COMBAT_FLAG_SPRINT_ACTIVE | COMBAT_FLAG_SPRINT_TOGGLED | COMBAT_FLAG_SPRINT_FORCED) -/// The user wants combat mode on -#define COMBAT_FLAG_COMBAT_TOGGLED (1<<0) /// The user wants sprint mode on -#define COMBAT_FLAG_SPRINT_TOGGLED (1<<1) -/// Combat mode is currently active -#define COMBAT_FLAG_COMBAT_ACTIVE (1<<2) +#define COMBAT_FLAG_SPRINT_TOGGLED (1<<0) /// Sprint is currently active -#define COMBAT_FLAG_SPRINT_ACTIVE (1<<3) +#define COMBAT_FLAG_SPRINT_ACTIVE (1<<1) /// Currently attempting to crawl under someone -#define COMBAT_FLAG_ATTEMPTING_CRAWL (1<<4) +#define COMBAT_FLAG_ATTEMPTING_CRAWL (1<<2) /// Currently stamcritted -#define COMBAT_FLAG_HARD_STAMCRIT (1<<5) +#define COMBAT_FLAG_HARD_STAMCRIT (1<<3) /// Currently attempting to resist up from the ground -#define COMBAT_FLAG_RESISTING_REST (1<<6) +#define COMBAT_FLAG_RESISTING_REST (1<<4) /// Intentionally resting -#define COMBAT_FLAG_INTENTIONALLY_RESTING (1<<7) +#define COMBAT_FLAG_INTENTIONALLY_RESTING (1<<5) /// Currently stamcritted but not as violently -#define COMBAT_FLAG_SOFT_STAMCRIT (1<<8) -/// Force combat mode on at all times, overrides everything including combat disable traits. -#define COMBAT_FLAG_COMBAT_FORCED (1<<9) +#define COMBAT_FLAG_SOFT_STAMCRIT (1<<6) /// Force sprint mode on at all times, overrides everything including sprint disable traits. -#define COMBAT_FLAG_SPRINT_FORCED (1<<10) +#define COMBAT_FLAG_SPRINT_FORCED (1<<7) // Helpers for getting someone's stamcrit state. Cast to living. #define NOT_STAMCRIT 0 diff --git a/code/__DEFINES/dcs/flags.dm b/code/__DEFINES/dcs/flags.dm index 59c0c58b8d..2dbd4874d9 100644 --- a/code/__DEFINES/dcs/flags.dm +++ b/code/__DEFINES/dcs/flags.dm @@ -75,3 +75,11 @@ #define ID_COMPONENT_KNOWLEDGE_NONE 0 /// Has full knowledge #define ID_COMPONENT_KNOWLEDGE_FULL 1 + +// Combat mode flags. +/// The user wants combat mode on +#define COMBAT_MODE_TOGGLED (1<<0) +/// combat mode is active. +#define COMBAT_MODE_ACTIVE (1<<1) +/// combat mode is not active +#define COMBAT_MODE_INACTIVE (1<<2) \ No newline at end of file diff --git a/code/__DEFINES/dcs/signals.dm b/code/__DEFINES/dcs/signals.dm index 6c68e7ecad..ea9ebbec02 100644 --- a/code/__DEFINES/dcs/signals.dm +++ b/code/__DEFINES/dcs/signals.dm @@ -149,7 +149,8 @@ // /mob signals #define COMSIG_MOB_CLICKED_SHIFT_ON "mob_shift_click_on" //from base of /atom/ShiftClick(): (atom/A), for return values, see COMSIG_CLICK_SHIFT -#define COMSIG_MOB_FOV_VIEW "mob_visible_atoms" //from base of mob/fov_view(): (list/visible_atoms) +#define COMSIG_MOB_FOV_VIEW "mob_visible_atoms" //from base of /mob/fov_view(): (list/visible_atoms) +#define COMSIG_MOB_POINTED "mob_pointed" //from base of /mob/verb/pointed(): (atom/A) #define COMSIG_MOB_EXAMINATE "mob_examinate" //from base of /mob/verb/examinate(): (atom/A), for return values, see COMSIG_CLICK_SHIFT #define COMPONENT_EXAMINATE_BLIND 3 //outputs the "something is there but you can't see it" message. #define COMSIG_MOB_DEATH "mob_death" //from base of mob/death(): (gibbed) @@ -192,7 +193,12 @@ #define COMSIG_MOB_SPELL_CAN_CAST "mob_spell_can_cast" //from base of /obj/effect/proc_holder/spell/can_cast(): (spell) -#define COMSIG_ROBOT_UPDATE_ICONS "robot_update_icons" //from base of robot/update_icons(): () +// /client signals +#define COMSIG_MOB_CLIENT_LOGIN "mob_client_login" //sent when a mob/login() finishes: (client) +#define COMSIG_MOB_CLIENT_LOGOUT "mob_client_logout" //sent when a mob/logout() starts: (client) +#define COMSIG_MOB_CLIENT_MOVE "mob_client_move" //sent when client/Move() finishes with no early returns: (client, direction, n, oldloc) +#define COMSIG_MOB_CLIENT_CHANGE_VIEW "mob_client_change_view" //from base of /client/change_view(): (client, old_view, view) +#define COMSIG_MOB_CLIENT_MOUSEMOVE "mob_client_mousemove" //from base of /client/MouseMove(): (object, location, control, params) // /mob/living signals #define COMSIG_LIVING_REGENERATE_LIMBS "living_regenerate_limbs" //from base of /mob/living/regenerate_limbs(): (noheal, excluded_limbs) @@ -204,17 +210,10 @@ #define COMSIG_LIVING_MINOR_SHOCK "living_minor_shock" //sent by stuff like stunbatons and tasers: () #define COMSIG_LIVING_REVIVE "living_revive" //from base of mob/living/revive() (full_heal, admin_revive) -#define COMSIG_MOB_CLIENT_LOGIN "mob_client_login" //sent when a mob/login() finishes: (client) -#define COMSIG_MOB_CLIENT_LOGOUT "mob_client_logout" //sent when a mob/logout() starts: (client) -#define COMSIG_MOB_CLIENT_MOVE "mob_client_move" //sent when client/Move() finishes with no early returns: (client, direction, n, oldloc) -#define COMSIG_MOB_CLIENT_CHANGE_VIEW "mob_client_change_view" //from base of /client/change_view(): (client, old_view, view) - #define COMSIG_MOB_RESET_PERSPECTIVE "mob_reset_perspective" //from base of /mob/reset_perspective(): (atom/target) #define COMSIG_LIVING_GUN_PROCESS_FIRE "living_gun_process_fire" //from base of /obj/item/gun/proc/process_fire(): (atom/target, params, zone_override) // This returns flags as defined for block in __DEFINES/combat.dm! #define COMSIG_LIVING_RUN_BLOCK "living_do_run_block" //from base of mob/living/do_run_block(): (real_attack, atom/object, damage, attack_text, attack_type, armour_penetration, mob/attacker, def_zone) -#define COMSIG_LIVING_COMBAT_ENABLED "combatmode_enabled" //from base of mob/living/enable_combat_mode() (was_forced) -#define COMSIG_LIVING_COMBAT_DISABLED "combatmode_disabled" //from base of mob/living/disable_combat_mode() (was_forced) #define COMSIG_LIVING_GET_BLOCKING_ITEMS "get_blocking_items" //from base of mob/living/get_blocking_items(): (list/items) //ALL OF THESE DO NOT TAKE INTO ACCOUNT WHETHER AMOUNT IS 0 OR LOWER AND ARE SENT REGARDLESS! @@ -232,6 +231,10 @@ #define COMSIG_CARBON_SOUNDBANG "carbon_soundbang" //from base of mob/living/carbon/soundbang_act(): (list(intensity)) #define COMSIG_CARBON_IDENTITY_TRANSFERRED_TO "carbon_id_transferred_to" //from datum/dna/transfer_identity(): (datum/dna, transfer_SE) #define COMSIG_CARBON_TACKLED "carbon_tackled" //sends from tackle.dm on tackle completion + +// /mob/living/silicon signals +#define COMSIG_ROBOT_UPDATE_ICONS "robot_update_icons" //from base of robot/update_icons(): () + // /mob/living/simple_animal/hostile signals #define COMSIG_HOSTILE_ATTACKINGTARGET "hostile_attackingtarget" #define COMPONENT_HOSTILE_NO_ATTACK 1 @@ -342,6 +345,14 @@ //NTnet #define COMSIG_COMPONENT_NTNET_RECEIVE "ntnet_receive" //called on an object by its NTNET connection component on receive. (sending_id(number), sending_netname(text), data(datum/netdata)) +//Combat mode +#define COMSIG_TOGGLE_COMBAT_MODE "toggle_combat_mode" //safely toggles combat mode. +#define COMSIG_DISABLE_COMBAT_MODE "disable_combat_mode" //safely disables combat mode. +#define COMSIG_ENABLE_COMBAT_MODE "enable_combat_mode" //safely enables combat mode. +#define COMSIG_LIVING_COMBAT_ENABLED "combatmode_enabled" //from base of datum/component/combat_mode/enable_combat_mode() (was_forced) +#define COMSIG_LIVING_COMBAT_DISABLED "combatmode_disabled" //from base of datum/component/combat_mode/disable_combat_mode() (was_forced) +#define COMSIG_COMBAT_MODE_CHECK "combatmode_check" //called when checking the combat mode flags (enabled/disabled/forced) + //Nanites #define COMSIG_HAS_NANITES "has_nanites" //() returns TRUE if nanites are found #define COMSIG_NANITE_IS_STEALTHY "nanite_is_stealthy" //() returns TRUE if nanites have stealth diff --git a/code/__DEFINES/mobs.dm b/code/__DEFINES/mobs.dm index 29ab67271c..8d8b9f47ae 100644 --- a/code/__DEFINES/mobs.dm +++ b/code/__DEFINES/mobs.dm @@ -126,6 +126,13 @@ #define SCREWYHUD_DEAD 2 #define SCREWYHUD_HEALTHY 3 +//Threshold levels for beauty for humans +#define BEAUTY_LEVEL_HORRID -66 +#define BEAUTY_LEVEL_BAD -33 +#define BEAUTY_LEVEL_DECENT 33 +#define BEAUTY_LEVEL_GOOD 66 +#define BEAUTY_LEVEL_GREAT 100 + //Moods levels for humans #define MOOD_LEVEL_HAPPY4 15 #define MOOD_LEVEL_HAPPY3 10 diff --git a/code/__DEFINES/tgs.dm b/code/__DEFINES/tgs.dm index e164a4ec96..7c0811ec59 100644 --- a/code/__DEFINES/tgs.dm +++ b/code/__DEFINES/tgs.dm @@ -1,253 +1,343 @@ -//tgstation-server DMAPI +// tgstation-server DMAPI -#define TGS_DMAPI_VERSION "5.1.1" +#define TGS_DMAPI_VERSION "5.2.1" -//All functions and datums outside this document are subject to change with any version and should not be relied on +// All functions and datums outside this document are subject to change with any version and should not be relied on. -//CONFIGURATION +// CONFIGURATION -//create this define if you want to do configuration outside of this file +/// Create this define if you want to do TGS configuration outside of this file. #ifndef TGS_EXTERNAL_CONFIGURATION -//Comment this out once you've filled in the below +// Comment this out once you've filled in the below. #error TGS API unconfigured -//Uncomment this if you wish to allow the game to interact with TGS 3 -//This will raise the minimum required security level of your game to TGS_SECURITY_TRUSTED due to it utilizing call()() +// Uncomment this if you wish to allow the game to interact with TGS 3. +// This will raise the minimum required security level of your game to TGS_SECURITY_TRUSTED due to it utilizing call()() //#define TGS_V3_API -//Required interfaces (fill in with your codebase equivalent): +// Required interfaces (fill in with your codebase equivalent): -//create a global variable named `Name` and set it to `Value` +/// Create a global variable named `Name` and set it to `Value`. #define TGS_DEFINE_AND_SET_GLOBAL(Name, Value) -//Read the value in the global variable `Name` +/// Read the value in the global variable `Name`. #define TGS_READ_GLOBAL(Name) -//Set the value in the global variable `Name` to `Value` +/// Set the value in the global variable `Name` to `Value`. #define TGS_WRITE_GLOBAL(Name, Value) -//Disallow ANYONE from reflecting a given `path`, security measure to prevent in-game use of DD -> TGS capabilities +/// Disallow ANYONE from reflecting a given `path`, security measure to prevent in-game use of DD -> TGS capabilities. #define TGS_PROTECT_DATUM(Path) -//Display an announcement `message` from the server to all players +/// Display an announcement `message` from the server to all players. #define TGS_WORLD_ANNOUNCE(message) -//Notify current in-game administrators of a string `event` +/// Notify current in-game administrators of a string `event`. #define TGS_NOTIFY_ADMINS(event) -//Write an info `message` to a server log +/// Write an info `message` to a server log. #define TGS_INFO_LOG(message) -//Write an warning `message` to a server log +/// Write an warning `message` to a server log. #define TGS_WARNING_LOG(message) -//Write an error `message` to a server log +/// Write an error `message` to a server log. #define TGS_ERROR_LOG(message) -//Get the number of connected /clients +/// Get the number of connected /clients. #define TGS_CLIENT_COUNT #endif -//EVENT CODES +// EVENT CODES -#define TGS_EVENT_REBOOT_MODE_CHANGE -1 //Before a reboot mode change, extras parameters are the current and new reboot mode enums -#define TGS_EVENT_PORT_SWAP -2 //Before a port change is about to happen, extra parameters is new port -#define TGS_EVENT_INSTANCE_RENAMED -3 //Before the instance is renamed, extra parameter is the new name -#define TGS_EVENT_WATCHDOG_REATTACH -4 //After the watchdog reattaches to DD, extra parameter is the new /datum/tgs_version of the server +/// Before a reboot mode change, extras parameters are the current and new reboot mode enums +#define TGS_EVENT_REBOOT_MODE_CHANGE -1 +/// Before a port change is about to happen, extra parameters is new port +#define TGS_EVENT_PORT_SWAP -2 +/// Before the instance is renamed, extra parameter is the new name +#define TGS_EVENT_INSTANCE_RENAMED -3 +/// After the watchdog reattaches to DD, extra parameter is the new [/datum/tgs_version] of the server +#define TGS_EVENT_WATCHDOG_REATTACH -4 -//See the descriptions for the parameters of these codes here: https://github.com/tgstation/tgstation-server/blob/master/src/Tgstation.Server.Host/Components/EventType.cs +/// When the repository is reset to its origin reference. Parameters: Reference name, Commit SHA #define TGS_EVENT_REPO_RESET_ORIGIN 0 +/// When the repository performs a checkout. Parameters: Checkout git object #define TGS_EVENT_REPO_CHECKOUT 1 +/// When the repository performs a fetch operation. No parameters #define TGS_EVENT_REPO_FETCH 2 +/// When the repository merges a pull request. Parameters: PR Number, PR Sha, (Nullable) Comment made by TGS user #define TGS_EVENT_REPO_MERGE_PULL_REQUEST 3 +/// Before the repository makes a sychronize operation. Parameters: Absolute repostiory path #define TGS_EVENT_REPO_PRE_SYNCHRONIZE 4 +/// Before a BYOND install operation begins. Parameters: [/datum/tgs_version] of the installing BYOND #define TGS_EVENT_BYOND_INSTALL_START 5 +/// When a BYOND install operation fails. Parameters: Error message #define TGS_EVENT_BYOND_INSTALL_FAIL 6 +/// When the active BYOND version changes. Parameters: (Nullable) [/datum/tgs_version] of the current BYOND, [/datum/tgs_version] of the new BYOND #define TGS_EVENT_BYOND_ACTIVE_VERSION_CHANGE 7 +/// When the compiler starts running. Parameters: Game directory path, origin commit SHA #define TGS_EVENT_COMPILE_START 8 +/// When a compile is cancelled. No parameters #define TGS_EVENT_COMPILE_CANCELLED 9 +/// When a compile fails. Parameters: Game directory path, [TRUE]/[FALSE] based on if the cause for failure was DMAPI validation #define TGS_EVENT_COMPILE_FAILURE 10 -#define TGS_EVENT_COMPILE_COMPLETE 11 // Note, this event fires before the new .dmb is loaded into the watchdog. Consider using the TGS_EVENT_DEPLOYMENT_COMPLETE instead +/// When a compile operation completes. Note, this event fires before the new .dmb is loaded into the watchdog. Consider using the [TGS_EVENT_DEPLOYMENT_COMPLETE] instead. Parameters: Game directory path +#define TGS_EVENT_COMPILE_COMPLETE 11 +/// When an automatic update for the current instance begins. No parameters #define TGS_EVENT_INSTANCE_AUTO_UPDATE_START 12 +/// When the repository encounters a merge conflict: Parameters: Base SHA, target SHA, base reference, target reference #define TGS_EVENT_REPO_MERGE_CONFLICT 13 +/// When a deployment completes. No Parameters #define TGS_EVENT_DEPLOYMENT_COMPLETE 14 +/// Before the watchdog shuts down. Not sent for graceful shutdowns. No parameters. #define TGS_EVENT_WATCHDOG_SHUTDOWN 15 +/// Before the watchdog detaches for a TGS update/restart. No parameters. #define TGS_EVENT_WATCHDOG_DETACH 16 -//OTHER ENUMS +// OTHER ENUMS +/// The server will reboot normally. #define TGS_REBOOT_MODE_NORMAL 0 +/// The server will stop running on reboot. #define TGS_REBOOT_MODE_SHUTDOWN 1 +/// The watchdog will restart on reboot. #define TGS_REBOOT_MODE_RESTART 2 +/// DreamDaemon Trusted security level. #define TGS_SECURITY_TRUSTED 0 +/// DreamDaemon Safe security level. #define TGS_SECURITY_SAFE 1 +/// DreamDaemon Ultrasafe security level. #define TGS_SECURITY_ULTRASAFE 2 //REQUIRED HOOKS -//Call this somewhere in /world/New() that is always run -//IMPORTANT: This function may sleep! -//event_handler: optional user defined event handler. The default behaviour is to broadcast the event in english to all connected admin channels -//minimum_required_security_level: The minimum required security level to run the game in which the DMAPI is integrated +/** + * Call this somewhere in [/world/proc/New] that is always run. This function may sleep! + * + * * event_handler - Optional user defined [/datum/tgs_event_handler]. + * * minimum_required_security_level: The minimum required security level to run the game in which the DMAPI is integrated. Can be one of [TGS_SECURITY_ULTRASAFE], [TGS_SECURITY_SAFE], or [TGS_SECURITY_TRUSTED]. + */ /world/proc/TgsNew(datum/tgs_event_handler/event_handler, minimum_required_security_level = TGS_SECURITY_ULTRASAFE) return -//Call this when your initializations are complete and your game is ready to play before any player interactions happen -//This may use world.sleep_offline to make this happen so ensure no changes are made to it while this call is running -//Most importantly, before this point, note that any static files or directories may be in use by another server. Your code should account for this -//This function should not be called before ..() in /world/New() +/** + * Call this when your initializations are complete and your game is ready to play before any player interactions happen. + * + * This may use [/world/var/sleep_offline] to make this happen so ensure no changes are made to it while this call is running. + * Before this point, note that any static files or directories may be in use by another server. Your code should account for this. + * This function should not be called before ..() in [/world/proc/New]. + */ /world/proc/TgsInitializationComplete() return -//Put this at the start of /world/Topic() +/// Put this at the start of [/world/proc/Topic]. #define TGS_TOPIC var/tgs_topic_return = TgsTopic(args[1]); if(tgs_topic_return) return tgs_topic_return -//Call this at the beginning of world/Reboot(reason) +/** + * Call this at the beginning of [world/proc/Reboot]. + */ /world/proc/TgsReboot() return -//DATUM DEFINITIONS -//unless otherwise specified all datums defined here should be considered read-only, warranty void if written +// DATUM DEFINITIONS +// All datums defined here should be considered read-only -//represents git revision information about the current world build +/// Represents git revision information. /datum/tgs_revision_information - var/commit //full sha of compiled commit - var/origin_commit //full sha of last known remote commit. This may be null if the TGS repository is not currently tracking a remote branch + /// Full SHA of the commit. + var/commit + /// Full sha of last known remote commit. This may be null if the TGS repository is not currently tracking a remote branch. + var/origin_commit -//represents a version of tgstation-server +/// Represents a version. /datum/tgs_version - var/suite //The suite/major version, can be >=3 + /// The suite/major version number + var/suite - //this group of variables can be null to represent a wild card - var/minor //The minor version - var/patch //The patch version - var/deprecated_patch //The legacy version + // This group of variables can be null to represent a wild card + /// The minor version number. null for wildcards + var/minor + /// The patch version number. null for wildcards + var/patch - var/raw_parameter //The unparsed parameter - var/deprefixed_parameter //The version only bit of raw_parameter + /// Legacy version number. Generally null + var/deprecated_patch -//if the tgs_version is a wildcard version + /// Unparsed string value + var/raw_parameter + /// String value minus prefix + var/deprefixed_parameter + +/** + * Returns [TRUE]/[FALSE] based on if the [/datum/tgs_version] contains wildcards. + */ /datum/tgs_version/proc/Wildcard() return -//if the tgs_version equals some other_version +/** + * Returns [TRUE]/[FALSE] based on if the [/datum/tgs_version] equals some other version. + * + * other_version - The [/datum/tgs_version] to compare against. + */ /datum/tgs_version/proc/Equals(datum/tgs_version/other_version) return -//represents a merge of a GitHub pull request +/// Represents a merge of a GitHub pull request. /datum/tgs_revision_information/test_merge - var/number //pull request number - var/title //pull request title - var/body //pull request body - var/author //pull request github author - var/url //link to pull request html - var/pull_request_commit //commit of the pull request when it was merged - var/time_merged //timestamp of when the merge commit for the pull request was created - var/comment //optional comment left by the one who initiated the test merge + /// The pull request number. + var/number + /// The pull request title when it was merged. + var/title + /// The pull request body when it was merged. + var/body + /// The GitHub username of the pull request's author. + var/author + /// An http URL to the pull request. + var/url + /// The SHA of the pull request when that was merged. + var/pull_request_commit + /// ISO 8601 timestamp of when the pull request was merged. + var/time_merged + /// (Nullable) Comment left by the TGS user who initiated the merge.. + var/comment -//represents a connected chat channel +/// Represents a connected chat channel. /datum/tgs_chat_channel - var/id //internal channel representation - var/friendly_name //user friendly channel name - var/connection_name //the name of the configured chat connection - var/is_admin_channel //if the server operator has marked this channel for game admins only - var/is_private_channel //if this is a private chat channel - var/custom_tag //user defined string associated with channel + /// TGS internal channel ID. + var/id + /// User friendly name of the channel. + var/friendly_name + /// Name of the chat connection. This is the IRC server address or the Discord guild. + var/connection_name + /// [TRUE]/[FALSE] based on if the server operator has marked this channel for game admins only. + var/is_admin_channel + /// [TRUE]/[FALSE] if the channel is a private message channel for a [/datum/tgs_chat_user]. + var/is_private_channel + /// Tag string associated with the channel in TGS + var/custom_tag -//represents a chat user +// Represents a chat user /datum/tgs_chat_user - var/id //Internal user representation, requires channel to be unique - var/friendly_name //The user's public name - var/mention //The text to use to ping this user in a message - var/datum/tgs_chat_channel/channel //The /datum/tgs_chat_channel this user was from + /// TGS internal user ID. + var/id + // The user's display name. + var/friendly_name + // The string to use to ping this user in a message. + var/mention + /// The [/datum/tgs_chat_channel] the user was from + var/datum/tgs_chat_channel/channel -//user definable callback for handling events -//extra parameters may be specified depending on the event +/** + * User definable callback for handling TGS events. + * + * event_code - One of the TGS_EVENT_ defines. Extra parameters will be documented in each + */ /datum/tgs_event_handler/proc/HandleEvent(event_code, ...) set waitfor = FALSE return -//user definable chat command +/// User definable chat command /datum/tgs_chat_command - var/name = "" //the string to trigger this command on a chat bot. e.g. TGS3_BOT: do_this_command - var/help_text = "" //help text for this command - var/admin_only = FALSE //set to TRUE if this command should only be usable by registered chat admins + /// The string to trigger this command on a chat bot. e.g `@bot name ...` or `!tgs name ...` + var/name = "" + /// The help text displayed for this command + var/help_text = "" + /// If this command should be available to game administrators only + var/admin_only = FALSE -//override to implement command -//sender: The tgs_chat_user who send to command -//params: The trimmed string following the command name -//The return value will be stringified and sent to the appropriate chat +/** + * Process command activation. Should return a string to respond to the issuer with. + * + * sender - The [/datum/tgs_chat_user] who issued the command. + * params - The trimmed string following the command `/datum/tgs_chat_command/var/name]. + */ /datum/tgs_chat_command/proc/Run(datum/tgs_chat_user/sender, params) CRASH("[type] has no implementation for Run()") -//FUNCTIONS +// API FUNCTIONS -//Returns the respective supported /datum/tgs_version of the API +/// Returns the maximum supported [/datum/tgs_version] of the DMAPI. /world/proc/TgsMaximumAPIVersion() return +/// Returns the minimum supported [/datum/tgs_version] of the DMAPI. /world/proc/TgsMinimumAPIVersion() return -//Returns TRUE if the world was launched under the server tools and the API matches, FALSE otherwise -//No function below this succeeds if it returns FALSE or if TgsNew() has yet to be called +/** + * Returns [TRUE] if DreamDaemon was launched under TGS, the API matches, and was properly initialized. [FALSE] will be returned otherwise. + */ /world/proc/TgsAvailable() return -//Forces a hard reboot of BYOND by ending the process -//unlike del(world) clients will try to reconnect -//If the service has not requested a shutdown, the next server will take over +// No function below this succeeds if it TgsAvailable() returns FALSE or if TgsNew() has yet to be called. + +/** + * Forces a hard reboot of DreamDaemon by ending the process. + * + * Unlike del(world) clients will try to reconnect. + * If TGS has not requested a [TGS_REBOOT_MODE_SHUTDOWN] DreamDaemon will be launched again + */ /world/proc/TgsEndProcess() return -//Send a message to non-admin connected chats -//message: The message to send -//admin_only: If TRUE, message will instead be sent to only admin connected chats -/world/proc/TgsTargetedChatBroadcast(message, admin_only) +/** + * Send a message to connected chats. + * + * message - The string to send. + * admin_only: If [TRUE], message will be sent to admin connected chats. Vice-versa applies. + */ +/world/proc/TgsTargetedChatBroadcast(message, admin_only = FALSE) return -//Send a private message to a specific user -//message: The message to send -//user: The /datum/tgs_chat_user to send to +/** + * Send a private message to a specific user. + * + * message - The string to send. + * user: The [/datum/tgs_chat_user] to PM. + */ /world/proc/TgsChatPrivateMessage(message, datum/tgs_chat_user/user) return -//The following functions will sleep if a call to TgsNew() is sleeping +// The following functions will sleep if a call to TgsNew() is sleeping -//Sends a message to connected game chats -//message: The message to send -//channels: optional channels to limit the broadcast to -/world/proc/TgsChatBroadcast(message, list/channels) +/** + * Send a message to connected chats that are flagged as game-related in TGS. + * + * message - The string to send. + * channels - Optional list of [/datum/tgs_chat_channel]s to restrict the message to. + */ +/world/proc/TgsChatBroadcast(message, list/channels = null) return -//Gets the current /datum/tgs_version of the server tools running the server +/// Returns the current [/datum/tgs_version] of TGS if it is running the server, null otherwise. /world/proc/TgsVersion() return -//Gets the current /datum/tgs_version of the DMAPI being used +/// Returns the current [/datum/tgs_version] of the DMAPI being used if it was activated, null otherwise. /world/proc/TgsApiVersion() return -//Gets the name of the TGS instance running the game +/// Returns the name of the TGS instance running the game if TGS is present, null otherwise. /world/proc/TgsInstanceName() return -//Get the current `/datum/tgs_revision_information` +/// Return the current [/datum/tgs_revision_information] of the running server if TGS is present, null otherwise. /world/proc/TgsRevision() return -//Get the current BYOND security level +/// Returns the current BYOND security level as a TGS_SECURITY_ define if TGS is present, null otherwise. /world/proc/TgsSecurityLevel() return -//Gets a list of active `/datum/tgs_revision_information/test_merge`s +/// Returns a list of active [/datum/tgs_revision_information/test_merge]s if TGS is present, null otherwise. /world/proc/TgsTestMerges() return -//Gets a list of connected tgs_chat_channel +/// Returns a list of connected [/datum/tgs_chat_channel]s if TGS is present, null otherwise. /world/proc/TgsChatChannelInfo() return diff --git a/code/__DEFINES/traits.dm b/code/__DEFINES/traits.dm index 7b14c6215c..ef3b2c54c3 100644 --- a/code/__DEFINES/traits.dm +++ b/code/__DEFINES/traits.dm @@ -182,6 +182,7 @@ #define TRAIT_PARA "paraplegic" #define TRAIT_EMPATH "empath" #define TRAIT_FRIENDLY "friendly" +#define TRAIT_SNOB "snob" #define TRAIT_CULT_EYES "cult_eyes" #define TRAIT_AUTO_CATCH_ITEM "auto_catch_item" #define TRAIT_CLOWN_MENTALITY "clown_mentality" // The future is now, clownman. diff --git a/code/__HELPERS/_logging.dm b/code/__HELPERS/_logging.dm index 5e0ac99bae..48f54fd60f 100644 --- a/code/__HELPERS/_logging.dm +++ b/code/__HELPERS/_logging.dm @@ -154,8 +154,8 @@ /proc/log_subsystem(subsystem, text) WRITE_LOG(GLOB.subsystem_log, "[subsystem]: [text]") -/proc/log_click(object, location, control, params, client/C, event = "clicked") - WRITE_LOG(GLOB.click_log, "CLICK: [C.ckey] - [event] : [object] | [location] | [control] | [params]") +/proc/log_click(atom/object, atom/location, control, params, client/C, event = "clicked", unexpected) + WRITE_LOG(GLOB.click_log, "[unexpected? "ERROR" :"CLICK"]: [C.ckey] - [event] : [istype(object)? "[object] ([COORD(object)])" : object] | [istype(location)? "[location] ([COORD(location)])" : location] | [control] | [params]") /* Log to both DD and the logfile. */ /proc/log_world(text) diff --git a/code/__HELPERS/unsorted.dm b/code/__HELPERS/unsorted.dm index 919c4c879f..508b737474 100644 --- a/code/__HELPERS/unsorted.dm +++ b/code/__HELPERS/unsorted.dm @@ -15,6 +15,8 @@ var/textb = copytext(HTMLstring, 6, 8) return rgb(255 - hex2num(textr), 255 - hex2num(textg), 255 - hex2num(textb)) +//Better performant than an artisanal proc and more reliable than Turn(). From TGMC. +#define REVERSE_DIR(dir) ( ((dir & 85) << 1) | ((dir & 170) >> 1) ) //Returns location. Returns null if no location was found. /proc/get_teleport_loc(turf/location,mob/target,distance = 1, density = FALSE, errorx = 0, errory = 0, eoffsetx = 0, eoffsety = 0) /* diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index 2b6c387810..9419000e02 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -244,15 +244,14 @@ GLOBAL_LIST_INIT(bitfields, list( "MOBILITY_RESIST" = MOBILITY_RESIST ), "combat_flags" = list( - "COMBAT_FLAG_COMBAT_TOGGLED" = COMBAT_FLAG_COMBAT_TOGGLED, "COMBAT_FLAG_SPRINT_TOGGLED" = COMBAT_FLAG_SPRINT_TOGGLED, - "COMBAT_FLAG_COMBAT_ACTIVE" = COMBAT_FLAG_COMBAT_ACTIVE, "COMBAT_FLAG_SPRINT_ACTIVE" = COMBAT_FLAG_SPRINT_ACTIVE, "COMBAT_FLAG_ATTEMPTING_CRAWL" = COMBAT_FLAG_ATTEMPTING_CRAWL, "COMBAT_FLAG_HARD_STAMCRIT" = COMBAT_FLAG_HARD_STAMCRIT, "COMBAT_FLAG_SOFT_STAMCRIT" = COMBAT_FLAG_SOFT_STAMCRIT, "COMBAT_FLAG_INTENTIONALLY_RESTING" = COMBAT_FLAG_INTENTIONALLY_RESTING, - "COMBAT_FLAG_RESISTING_REST" = COMBAT_FLAG_RESISTING_REST + "COMBAT_FLAG_RESISTING_REST" = COMBAT_FLAG_RESISTING_REST, + "COMBAT_FLAG_SPRINT_FORCED" = COMBAT_FLAG_SPRINT_FORCED ), "shield_flags" = list( "SHIELD_TRANSPARENT" = SHIELD_TRANSPARENT, diff --git a/code/_onclick/drag_drop.dm b/code/_onclick/drag_drop.dm index 9638b040f9..8e2e0c3fb5 100644 --- a/code/_onclick/drag_drop.dm +++ b/code/_onclick/drag_drop.dm @@ -24,16 +24,6 @@ return -/client - var/list/atom/selected_target[2] - var/obj/item/active_mousedown_item = null - var/mouseParams = "" - var/mouseLocation = null - var/mouseObject = null - var/mouseControlObject = null - var/middragtime = 0 - var/atom/middragatom - /client/MouseDown(object, location, control, params) if (mouse_down_icon) mouse_pointer_icon = mouse_down_icon @@ -84,12 +74,6 @@ /obj/item/proc/onMouseUp(object, location, params, mob) return -/obj/item - var/canMouseDown = FALSE - -/obj/item/gun - var/automatic = 0 //can gun use it, 0 is no, anything above 0 is the delay between clicks in ds - /obj/item/gun/CanItemAutoclick(object, location, params) . = automatic @@ -108,16 +92,10 @@ mouseLocation = location mouseObject = object mouseControlObject = control - if(mob && LAZYLEN(mob.mousemove_intercept_objects)) - for(var/datum/D in mob.mousemove_intercept_objects) - D.onMouseMove(object, location, control, params) - if(!show_popup_menus && mob) //CIT CHANGE - passes onmousemove() to mobs - mob.onMouseMove(object, location, control, params) //CIT CHANGE - ditto + if(mob) + SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_MOUSEMOVE, object, location, control, params) ..() -/datum/proc/onMouseMove(object, location, control, params) - return - /client/MouseDrag(src_object,atom/over_object,src_location,over_location,src_control,over_control,params) var/list/L = params2list(params) if (L["middle"]) diff --git a/code/_onclick/hud/alert.dm b/code/_onclick/hud/alert.dm index 7c116cc606..3cedd92255 100644 --- a/code/_onclick/hud/alert.dm +++ b/code/_onclick/hud/alert.dm @@ -642,9 +642,6 @@ so as to remain in compliance with the most up-to-date laws." mymob.client.screen |= alert return 1 -/mob - var/list/alerts = list() // contains /obj/screen/alert only // On /mob so clientless mobs will throw alerts properly - /obj/screen/alert/Click(location, control, params) if(!usr || !usr.client) return diff --git a/code/_onclick/hud/fullscreen.dm b/code/_onclick/hud/fullscreen.dm index 3cfa71e19d..d82f3e7cf5 100644 --- a/code/_onclick/hud/fullscreen.dm +++ b/code/_onclick/hud/fullscreen.dm @@ -1,7 +1,3 @@ - -/mob - var/list/screens = list() - /mob/proc/overlay_fullscreen(category, type, severity) var/obj/screen/fullscreen/screen = screens[category] if (!screen || screen.type != type) diff --git a/code/_onclick/hud/hud.dm b/code/_onclick/hud/hud.dm index f054cb0c8e..57335a966e 100644 --- a/code/_onclick/hud/hud.dm +++ b/code/_onclick/hud/hud.dm @@ -114,8 +114,6 @@ GLOBAL_LIST_INIT(available_ui_styles, list( return ..() -/mob - var/hud_type = /datum/hud /mob/proc/create_mob_hud() if(!client || hud_used) diff --git a/code/_onclick/hud/human.dm b/code/_onclick/hud/human.dm index f281853b0f..9380cf98aa 100644 --- a/code/_onclick/hud/human.dm +++ b/code/_onclick/hud/human.dm @@ -246,13 +246,6 @@ using.screen_loc = ui_pull_resist using.hud = src static_inventory += using - - //CIT CHANGES - combat mode buttons - using = new /obj/screen/combattoggle() - using.icon = tg_ui_icon_to_cit_ui(ui_style) - using.screen_loc = ui_combat_toggle - using.hud = src - static_inventory += using //END OF CIT CHANGES using = new /obj/screen/human/toggle() diff --git a/code/_onclick/hud/parallax.dm b/code/_onclick/hud/parallax.dm index 25a49c8d6b..d8ef1c525a 100755 --- a/code/_onclick/hud/parallax.dm +++ b/code/_onclick/hud/parallax.dm @@ -1,16 +1,4 @@ -/client - var/list/parallax_layers - var/list/parallax_layers_cached - var/atom/movable/movingmob - var/turf/previous_turf - var/dont_animate_parallax //world.time of when we can state animate()ing parallax again - var/last_parallax_shift //world.time of last update - var/parallax_throttle = 0 //ds between updates - var/parallax_movedir = 0 - var/parallax_layers_max = 3 - var/parallax_animate_timer - /datum/hud/proc/create_parallax(mob/viewmob) var/mob/screenmob = viewmob || mymob var/client/C = screenmob.client diff --git a/code/_onclick/item_attack.dm b/code/_onclick/item_attack.dm index efb2094291..7ffb870971 100644 --- a/code/_onclick/item_attack.dm +++ b/code/_onclick/item_attack.dm @@ -113,7 +113,7 @@ /obj/attacked_by(obj/item/I, mob/living/user) var/totitemdamage = I.force var/bad_trait - if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && iscarbon(user)) + if(!SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) totitemdamage *= 0.5 bad_trait = SKILL_COMBAT_MODE //blacklist combat skills. if(I.used_skills && user.mind) @@ -157,9 +157,11 @@ /mob/living/proc/pre_attacked_by(obj/item/I, mob/living/user) . = I.force var/bad_trait - if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && iscarbon(user)) + if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) . *= 0.5 bad_trait = SKILL_COMBAT_MODE //blacklist combat skills. + if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) + . *= 1.5 if(!CHECK_MOBILITY(user, MOBILITY_STAND)) . *= 0.5 if(!user.mind || !I.used_skills) @@ -171,10 +173,6 @@ continue user.mind.auto_gain_experience(skill, I.skill_gain) -/mob/living/carbon/pre_attacked_by(obj/item/I, mob/living/user) - . = ..() - if(!(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) - . *= 1.5 // Proximity_flag is 1 if this afterattack was called on something adjacent, in your square, or on your person. // Click parameters is the params string from byond Click() code, see that documentation. @@ -214,7 +212,7 @@ if(!user) return var/bad_trait - if(iscarbon(user) && !(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) . *= STAM_COST_NO_COMBAT_MULT bad_trait = SKILL_COMBAT_MODE if(used_skills && user.mind) diff --git a/code/controllers/subsystem/materials.dm b/code/controllers/subsystem/materials.dm index cc07f8e963..96d733e8da 100644 --- a/code/controllers/subsystem/materials.dm +++ b/code/controllers/subsystem/materials.dm @@ -11,7 +11,11 @@ SUBSYSTEM_DEF(materials) ///Dictionary of category || list of material refs var/list/materials_by_category ///List of stackcrafting recipes for materials using rigid materials - var/list/rigid_stack_recipes = list(new/datum/stack_recipe("chair", /obj/structure/chair/greyscale, one_per_turf = TRUE, on_floor = TRUE, applies_mats = TRUE)) + var/list/rigid_stack_recipes = list( + new /datum/stack_recipe("chair", /obj/structure/chair/greyscale, one_per_turf = TRUE, on_floor = TRUE, applies_mats = TRUE), + new /datum/stack_recipe("toilet", /obj/structure/toilet/greyscale, one_per_turf = TRUE, on_floor = TRUE, applies_mats = TRUE), + new /datum/stack_recipe("sink", /obj/structure/sink/greyscale, one_per_turf = TRUE, on_floor = TRUE, applies_mats = TRUE), + ) ///Ran on initialize, populated the materials and materials_by_category dictionaries with their appropiate vars (See these variables for more info) /datum/controller/subsystem/materials/proc/InitializeMaterials() diff --git a/code/datums/action.dm b/code/datums/action.dm index 00e7e0ad5d..0033df09d7 100644 --- a/code/datums/action.dm +++ b/code/datums/action.dm @@ -731,14 +731,6 @@ if(next_use_time > world.time) START_PROCESSING(SSfastprocess, src) - -//Stickmemes -/datum/action/item_action/stickmen - name = "Summon Stick Minions" - desc = "Allows you to summon faithful stickmen allies to aide you in battle." - icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' - button_icon_state = "art_summon" - //surf_ss13 /datum/action/item_action/bhop name = "Activate Jump Boots" diff --git a/code/datums/brain_damage/magic.dm b/code/datums/brain_damage/magic.dm new file mode 100644 index 0000000000..249907a1b8 --- /dev/null +++ b/code/datums/brain_damage/magic.dm @@ -0,0 +1,60 @@ +//Magical traumas, caused by spells and curses. +//Blurs the line between the victim's imagination and reality +//Unlike regular traumas this can affect the victim's body and surroundings + +/datum/brain_trauma/magic + resilience = TRAUMA_RESILIENCE_LOBOTOMY + +/datum/brain_trauma/magic/stalker + name = "Stalking Phantom" + desc = "Patient is stalked by a phantom only they can see." + scan_desc = "extra-sensory paranoia" + gain_text = "You feel like something wants to kill you..." + lose_text = "You no longer feel eyes on your back." + var/obj/effect/hallucination/simple/stalker_phantom/stalker + var/close_stalker = FALSE //For heartbeat + +/datum/brain_trauma/magic/stalker/on_gain() + create_stalker() + ..() + +/datum/brain_trauma/magic/stalker/proc/create_stalker() + var/turf/stalker_source = locate(owner.x + pick(-12, 12), owner.y + pick(-12, 12), owner.z) //random corner + stalker = new(stalker_source, owner) + +/datum/brain_trauma/magic/stalker/on_lose() + QDEL_NULL(stalker) + ..() + +/datum/brain_trauma/magic/stalker/on_life() + // Dead and unconscious people are not interesting to the psychic stalker. + if(owner.stat != CONSCIOUS) + return + + // Not even nullspace will keep it at bay. + if(!stalker || !stalker.loc || stalker.z != owner.z) + qdel(stalker) + create_stalker() + + if(get_dist(owner, stalker) <= 1) + playsound(owner, 'sound/magic/demon_attack1.ogg', 50) + owner.visible_message("[owner] is torn apart by invisible claws!", "Ghostly claws tear your body apart!") + owner.take_bodypart_damage(rand(20, 45)) + else if(prob(50)) + stalker.forceMove(get_step_towards(stalker, owner)) + if(get_dist(owner, stalker) <= 8) + if(!close_stalker) + var/sound/slowbeat = sound('sound/health/slowbeat.ogg', repeat = TRUE) + owner.playsound_local(owner, slowbeat, 40, 0, channel = CHANNEL_HEARTBEAT) + close_stalker = TRUE + else + if(close_stalker) + owner.stop_sound_channel(CHANNEL_HEARTBEAT) + close_stalker = FALSE + ..() + +/obj/effect/hallucination/simple/stalker_phantom + name = "???" + desc = "It's coming closer..." + image_icon = 'icons/mob/lavaland/lavaland_monsters.dmi' + image_state = "curseblob" diff --git a/code/datums/components/art.dm b/code/datums/components/art.dm deleted file mode 100644 index f6d3cb6c61..0000000000 --- a/code/datums/components/art.dm +++ /dev/null @@ -1,56 +0,0 @@ - -#define BAD_ART 12.5 -#define GOOD_ART 25 -#define GREAT_ART 50 - -/datum/component/art - var/impressiveness = 0 - -/datum/component/art/Initialize(impress) - impressiveness = impress - if(isobj(parent)) - RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_obj_examine) - else - RegisterSignal(parent, COMSIG_PARENT_EXAMINE, .proc/on_other_examine) - if(isstructure(parent)) - RegisterSignal(parent, COMSIG_ATOM_ATTACK_HAND, .proc/on_attack_hand) - if(isitem(parent)) - RegisterSignal(parent, COMSIG_ITEM_ATTACK_SELF, .proc/apply_moodlet) - -/datum/component/art/proc/apply_moodlet(mob/M, impress) - M.visible_message("[M] stops and looks intently at [parent].", \ - "You stop to take in [parent].") - switch(impress) - if (0 to BAD_ART) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artbad", /datum/mood_event/artbad) - if (BAD_ART to GOOD_ART) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artok", /datum/mood_event/artok) - if (GOOD_ART to GREAT_ART) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgood", /datum/mood_event/artgood) - if(GREAT_ART to INFINITY) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgreat", /datum/mood_event/artgreat) - - -/datum/component/art/proc/on_other_examine(datum/source, mob/M) - apply_moodlet(M, impressiveness) - -/datum/component/art/proc/on_obj_examine(datum/source, mob/M) - var/obj/O = parent - apply_moodlet(M, impressiveness *(O.obj_integrity/O.max_integrity)) - -/datum/component/art/proc/on_attack_hand(datum/source, mob/M) - to_chat(M, "You start examining [parent]...") - if(!do_after(M, 20, target = parent)) - return - on_obj_examine(source, M) - -/datum/component/art/rev - -/datum/component/art/rev/apply_moodlet(mob/M, impress) - M.visible_message("[M] stops to inspect [parent].", \ - "You take in [parent], inspecting the fine craftsmanship of the proletariat.") - - if(M.mind && M.mind.has_antag_datum(/datum/antagonist/rev)) - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgreat", /datum/mood_event/artgreat) - else - SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artbad", /datum/mood_event/artbad) diff --git a/code/datums/components/combat_mode.dm b/code/datums/components/combat_mode.dm new file mode 100644 index 0000000000..b53d407162 --- /dev/null +++ b/code/datums/components/combat_mode.dm @@ -0,0 +1,217 @@ +/** + * Combat mode component. It makes the user face whichever atom the mouse pointer is hovering, + * amongst other things designed outside of this file, namely PvP and PvE stuff, hence the name. + * Can be toggled on and off by clicking the screen hud object or by pressing the assigned hotkey (default 'C') + */ +/datum/component/combat_mode + var/mode_flags = COMBAT_MODE_INACTIVE + var/combatmessagecooldown + var/lastmousedir + var/obj/screen/combattoggle/hud_icon + var/hud_loc + +/datum/component/combat_mode/Initialize(hud_loc = ui_combat_toggle) + if(!isliving(parent)) + return COMPONENT_INCOMPATIBLE + var/mob/living/L = parent + + src.hud_loc = hud_loc + + RegisterSignal(L, SIGNAL_TRAIT(TRAIT_COMBAT_MODE_LOCKED), .proc/update_combat_lock) + RegisterSignal(L, COMSIG_TOGGLE_COMBAT_MODE, .proc/user_toggle_intentional_combat_mode) + RegisterSignal(L, COMSIG_DISABLE_COMBAT_MODE, .proc/safe_disable_combat_mode) + RegisterSignal(L, COMSIG_ENABLE_COMBAT_MODE, .proc/safe_enable_combat_mode) + RegisterSignal(L, COMSIG_MOB_DEATH, .proc/on_death) + RegisterSignal(L, COMSIG_MOB_CLIENT_LOGOUT, .proc/on_logout) + RegisterSignal(L, COMSIG_MOB_HUD_CREATED, .proc/on_mob_hud_created) + RegisterSignal(L, COMSIG_COMBAT_MODE_CHECK, .proc/check_flags) + + update_combat_lock() + + if(L.client) + on_mob_hud_created(L) + +/datum/component/combat_mode/Destroy() + if(parent) + safe_disable_combat_mode(parent) + if(hud_icon) + QDEL_NULL(hud_icon) + return ..() + +/// Creates the hud screen object. +/datum/component/combat_mode/proc/on_mob_hud_created(mob/source) + hud_icon = new + hud_icon.hud = source.hud_used + hud_icon.icon = tg_ui_icon_to_cit_ui(source.hud_used.ui_style) + hud_icon.screen_loc = hud_loc + source.hud_used.static_inventory += hud_icon + hud_icon.update_icon() + +/// Combat mode can be locked out, forcibly disabled by a status trait. +/datum/component/combat_mode/proc/update_combat_lock() + var/locked = HAS_TRAIT(parent, TRAIT_COMBAT_MODE_LOCKED) + var/desired = (mode_flags & COMBAT_MODE_TOGGLED) + var/actual = (mode_flags & COMBAT_MODE_ACTIVE) + if(actual) + if(locked) + disable_combat_mode(parent, FALSE, TRUE) + else if(!desired) + disable_combat_mode(parent, TRUE, TRUE) + else + if(desired && !locked) + enable_combat_mode(parent, FALSE, TRUE) + +/// Enables combat mode. Please use 'safe_enable_combat_mode' instead, if you wish to also enable the toggle flag. +/datum/component/combat_mode/proc/enable_combat_mode(mob/living/source, silent = TRUE, forced = TRUE, visible = FALSE, locked = FALSE, playsound = FALSE) + if(locked) + if(hud_icon) + hud_icon.combat_on = TRUE + hud_icon.update_icon() + return + if(mode_flags & COMBAT_MODE_ACTIVE) + return + mode_flags |= COMBAT_MODE_ACTIVE + mode_flags &= ~COMBAT_MODE_INACTIVE + SEND_SIGNAL(source, COMSIG_LIVING_COMBAT_ENABLED, forced) + if(!silent) + var/self_message = forced? "Your muscles reflexively tighten!" : "You drop into a combative stance!" + if(visible && (forced || world.time >= combatmessagecooldown)) + combatmessagecooldown = world.time + 10 SECONDS + if(!forced) + if(source.a_intent != INTENT_HELP) + source.visible_message("[source] [source.resting ? "tenses up" : "drops into a combative stance"].", self_message) + else + source.visible_message("[source] [pick("looks","seems","goes")] [pick("alert","attentive","vigilant")].") + else + source.visible_message("[source] drops into a combative stance!", self_message) + else + to_chat(source, self_message) + if(playsound) + source.playsound_local(source, 'sound/misc/ui_toggle.ogg', 50, FALSE, pressure_affected = FALSE) //Sound from interbay! + RegisterSignal(source, COMSIG_MOB_CLIENT_MOUSEMOVE, .proc/onMouseMove) + RegisterSignal(source, COMSIG_MOVABLE_MOVED, .proc/on_move) + RegisterSignal(source, COMSIG_MOB_CLIENT_MOVE, .proc/on_client_move) + if(hud_icon) + hud_icon.combat_on = TRUE + hud_icon.update_icon() + +/// Disables combat mode. Please use 'safe_disable_combat_mode' instead, if you wish to also disable the toggle flag. +/datum/component/combat_mode/proc/disable_combat_mode(mob/living/source, silent = TRUE, forced = TRUE, visible = FALSE, locked = FALSE, playsound = FALSE) + if(locked) + if(hud_icon) + hud_icon.combat_on = FALSE + hud_icon.update_icon() + return + if(!(mode_flags & COMBAT_MODE_ACTIVE)) + return + mode_flags &= ~COMBAT_MODE_ACTIVE + mode_flags |= COMBAT_MODE_INACTIVE + SEND_SIGNAL(source, COMSIG_LIVING_COMBAT_DISABLED, forced) + if(!silent) + var/self_message = forced? "Your muscles are forcibly relaxed!" : "You relax your stance." + if(visible) + source.visible_message("[source] relaxes [source.p_their()] stance.", self_message) + else + to_chat(source, self_message) + if(playsound) + source.playsound_local(source, 'sound/misc/ui_toggleoff.ogg', 50, FALSE, pressure_affected = FALSE) //Slightly modified version of the toggleon sound! + UnregisterSignal(source, list(COMSIG_MOB_CLIENT_MOUSEMOVE, COMSIG_MOVABLE_MOVED, COMSIG_MOB_CLIENT_MOVE)) + if(hud_icon) + hud_icon.combat_on = FALSE + hud_icon.update_icon() + +///Changes the user direction to (try) keep match the pointer. +/datum/component/combat_mode/proc/on_move(atom/movable/source, dir, atom/oldloc, forced) + var/mob/living/L = source + if(mode_flags & COMBAT_MODE_ACTIVE && L.client && lastmousedir && lastmousedir != dir) + L.setDir(lastmousedir, ismousemovement = TRUE) + +/// Added movement delay if moving backward. +/datum/component/combat_mode/proc/on_client_move(mob/source, client/client, direction, n, oldloc, added_delay) + if(oldloc != n && direction == REVERSE_DIR(source.dir)) + client.move_delay += added_delay*0.5 + +///Changes the user direction to (try) match the pointer. +/datum/component/combat_mode/proc/onMouseMove(mob/source, object, location, control, params) + if(source.client.show_popup_menus) + return + source.face_atom(object, TRUE) + lastmousedir = source.dir + +/// Toggles whether the user is intentionally in combat mode. THIS should be the proc you generally use! Has built in visual/to other player feedback, as well as an audible cue to ourselves. +/datum/component/combat_mode/proc/user_toggle_intentional_combat_mode(mob/living/source) + if(mode_flags & COMBAT_MODE_TOGGLED) + safe_disable_combat_mode(source) + else if(source.stat == CONSCIOUS && !(source.combat_flags & COMBAT_FLAG_HARD_STAMCRIT)) + safe_enable_combat_mode(source) + +/// Enables intentionally being in combat mode. Please try to use the COMSIG_COMBAT_MODE_CHECK signal for feedback when possible. +/datum/component/combat_mode/proc/safe_enable_combat_mode(mob/living/source, silent = FALSE, visible = TRUE) + if((mode_flags & COMBAT_MODE_TOGGLED) && (mode_flags & COMBAT_MODE_ACTIVE)) + return TRUE + mode_flags |= COMBAT_MODE_TOGGLED + enable_combat_mode(source, silent, FALSE, visible, HAS_TRAIT(source, TRAIT_COMBAT_MODE_LOCKED), TRUE) + if(source.client) + source.client.show_popup_menus = FALSE + if(iscarbon(source)) //I dislike this typecheck. It probably should be removed once that spoiled apple is componentized too. + var/mob/living/carbon/C = source + if(C.voremode) + C.disable_vore_mode() + return TRUE + +/// Disables intentionally being in combat mode. Please try to use the COMSIG_COMBAT_MODE_CHECK signal for feedback when possible. +/datum/component/combat_mode/proc/safe_disable_combat_mode(mob/living/source, silent = FALSE, visible = FALSE) + if(!(mode_flags & COMBAT_MODE_TOGGLED) && !(mode_flags & COMBAT_MODE_ACTIVE)) + return TRUE + mode_flags &= ~COMBAT_MODE_TOGGLED + disable_combat_mode(source, silent, FALSE, visible, !(mode_flags & COMBAT_MODE_ACTIVE), TRUE) + if(source.client) + source.client.show_popup_menus = TRUE + return TRUE + +/// Returns a field of flags that are contained in both the second arg and our bitfield variable. +/datum/component/combat_mode/proc/check_flags(mob/living/source, flags) + return mode_flags & (flags) + +/// Disables combat mode upon death. +/datum/component/combat_mode/proc/on_death(mob/living/source) + safe_disable_combat_mode(source) + +/// Disables combat mode upon logout +/datum/component/combat_mode/proc/on_logout(mob/living/source) + safe_disable_combat_mode(source) + +/// The screen button. +/obj/screen/combattoggle + name = "toggle combat mode" + icon = 'modular_citadel/icons/ui/screen_midnight.dmi' + icon_state = "combat_off" + var/mutable_appearance/flashy + var/combat_on = FALSE ///Wheter combat mode is enabled or not, so we don't have to store a reference. + +/obj/screen/combattoggle/Click() + if(hud && usr == hud.mymob) + SEND_SIGNAL(hud.mymob, COMSIG_TOGGLE_COMBAT_MODE) + +/obj/screen/combattoggle/update_icon_state() + var/mob/living/user = hud?.mymob + if(!user) + return + if(combat_on) + icon_state = "combat" + else if(HAS_TRAIT(user, TRAIT_COMBAT_MODE_LOCKED)) + icon_state = "combat_locked" + else + icon_state = "combat_off" + +/obj/screen/combattoggle/update_overlays() + . = ..() + var/mob/living/carbon/user = hud?.mymob + if(!(user?.client)) + return + + if(combat_on) + if(!flashy) + flashy = mutable_appearance('icons/mob/screen_gen.dmi', "togglefull_flash") + flashy.color = user.client.prefs.hud_toggle_color + . += flashy //TODO - beg lummox jr for the ability to force mutable appearances or images to be created rendering from their first frame of animation rather than being based entirely around the client's frame count diff --git a/code/datums/components/crafting/guncrafting.dm b/code/datums/components/crafting/guncrafting.dm index e06583ab61..caf200446f 100644 --- a/code/datums/components/crafting/guncrafting.dm +++ b/code/datums/components/crafting/guncrafting.dm @@ -12,6 +12,7 @@ /obj/item/weaponcrafting/stock name = "rifle stock" desc = "A classic rifle stock that doubles as a grip, roughly carved out of wood." + custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 6) icon_state = "riflestock" /obj/item/weaponcrafting/durathread_string diff --git a/code/datums/components/crafting/recipes/recipes_primal.dm b/code/datums/components/crafting/recipes/recipes_primal.dm index ae611e5855..bb4f4ce6d5 100644 --- a/code/datums/components/crafting/recipes/recipes_primal.dm +++ b/code/datums/components/crafting/recipes/recipes_primal.dm @@ -116,4 +116,41 @@ always_availible = FALSE reqs = list(/obj/item/stack/rods = 1, /obj/item/stack/sheet/mineral/sandstone = 4) - category = CAT_PRIMAL \ No newline at end of file + category = CAT_PRIMAL + +/datum/crafting_recipe/rib + name = "Collosal Rib" + always_availible = FALSE + reqs = list( + /obj/item/stack/sheet/bone = 10, + /datum/reagent/oil = 5) + result = /obj/structure/statue/bone/rib + subcategory = CAT_PRIMAL + +/datum/crafting_recipe/skull + name = "Skull Carving" + always_availible = FALSE + reqs = list( + /obj/item/stack/sheet/bone = 6, + /datum/reagent/oil = 5) + result = /obj/structure/statue/bone/skull + category = CAT_PRIMAL + +/datum/crafting_recipe/halfskull + name = "Cracked Skull Carving" + always_availible = FALSE + reqs = list( + /obj/item/stack/sheet/bone = 3, + /datum/reagent/oil = 5) + result = /obj/structure/statue/bone/skull/half + category = CAT_PRIMAL + +/datum/crafting_recipe/boneshovel + name = "Serrated Bone Shovel" + always_availible = FALSE + reqs = list( + /obj/item/stack/sheet/bone = 4, + /datum/reagent/oil = 5, + /obj/item/shovel/spade = 1) + result = /obj/item/shovel/serrated + category = CAT_PRIMAL diff --git a/code/datums/components/lockon_aiming.dm b/code/datums/components/lockon_aiming.dm index 045611ab9d..2f4401862d 100644 --- a/code/datums/components/lockon_aiming.dm +++ b/code/datums/components/lockon_aiming.dm @@ -47,14 +47,11 @@ if(icon_state) lock_icon_state = icon_state generate_lock_visuals() - var/mob/M = parent - LAZYOR(M.mousemove_intercept_objects, src) + RegisterSignal(parent, COMSIG_MOB_CLIENT_MOUSEMOVE, .proc/onMouseMove) START_PROCESSING(SSfastprocess, src) /datum/component/lockon_aiming/Destroy() - var/mob/M = parent clear_visuals() - LAZYREMOVE(M.mousemove_intercept_objects, src) STOP_PROCESSING(SSfastprocess, src) return ..() @@ -120,7 +117,7 @@ return LAZYREMOVE(immune_weakrefs, A.weak_reference) -/datum/component/lockon_aiming/onMouseMove(object,location,control,params) +/datum/component/lockon_aiming/proc/onMouseMove(object,location,control,params) var/mob/M = parent if(!istype(M) || !M.client) return diff --git a/code/datums/components/mood.dm b/code/datums/components/mood.dm index 37d77a45bc..88ad75f345 100644 --- a/code/datums/components/mood.dm +++ b/code/datums/components/mood.dm @@ -321,6 +321,28 @@ if(0 to NUTRITION_LEVEL_STARVING) add_event(null, "nutrition", /datum/mood_event/starving) +/datum/component/mood/proc/update_beauty(area/A) + if(A.outdoors) //if we're outside, we don't care. + clear_event(null, "area_beauty") + return FALSE + if(HAS_TRAIT(parent, TRAIT_SNOB)) + switch(A.beauty) + if(-INFINITY to BEAUTY_LEVEL_HORRID) + add_event(null, "area_beauty", /datum/mood_event/horridroom) + return + if(BEAUTY_LEVEL_HORRID to BEAUTY_LEVEL_BAD) + add_event(null, "area_beauty", /datum/mood_event/badroom) + return + switch(A.beauty) + if(-INFINITY to BEAUTY_LEVEL_DECENT) + clear_event(null, "area_beauty") + if(BEAUTY_LEVEL_DECENT to BEAUTY_LEVEL_GOOD) + add_event(null, "area_beauty", /datum/mood_event/decentroom) + if(BEAUTY_LEVEL_GOOD to BEAUTY_LEVEL_GREAT) + add_event(null, "area_beauty", /datum/mood_event/goodroom) + if(BEAUTY_LEVEL_GREAT to INFINITY) + add_event(null, "area_beauty", /datum/mood_event/greatroom) + ///Called when parent is revived. /datum/component/mood/proc/on_revive(datum/source, full_heal) START_PROCESSING(SSdcs, src) diff --git a/code/datums/components/phantomthief.dm b/code/datums/components/phantomthief.dm index 57ab75f7a3..6b7e7221c3 100644 --- a/code/datums/components/phantomthief.dm +++ b/code/datums/components/phantomthief.dm @@ -20,7 +20,7 @@ valid_slots = _valid_slots /datum/component/wearertargeting/phantomthief/proc/handlefilterstuff(mob/living/user, was_forced = FALSE) - if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + if(!SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) user.remove_filter("phantomthief") else user.add_filter("phantomthief", 4, list(type = "drop_shadow", x = filter_x, y = filter_y, size = filter_size, color = filter_color)) diff --git a/code/datums/components/summoning.dm b/code/datums/components/summoning.dm index 61718301b3..1d66cf9307 100644 --- a/code/datums/components/summoning.dm +++ b/code/datums/components/summoning.dm @@ -59,7 +59,7 @@ var/mob/living/simple_animal/L = new chosen_mob_type(spawn_location) if(ishostile(L)) var/mob/living/simple_animal/hostile/H = L - H.friends += summoner // do not attack our summon boy + H.friends[summoner]++ // do not attack our summon boy spawned_mobs += L if(faction != null) L.faction = faction diff --git a/code/datums/elements/art.dm b/code/datums/elements/art.dm new file mode 100644 index 0000000000..960d22af56 --- /dev/null +++ b/code/datums/elements/art.dm @@ -0,0 +1,64 @@ + +#define BAD_ART 12.5 +#define GOOD_ART 25 +#define GREAT_ART 50 + +/datum/element/art + element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH + id_arg_index = 2 + var/impressiveness = 0 + +/datum/element/art/Attach(datum/target, impress) + . = ..() + if(. == ELEMENT_INCOMPATIBLE || !isatom(target) || isarea(target)) + return ELEMENT_INCOMPATIBLE + impressiveness = impress + if(isobj(target)) + RegisterSignal(target, COMSIG_PARENT_EXAMINE, .proc/on_obj_examine) + if(isstructure(target)) + RegisterSignal(target, COMSIG_ATOM_ATTACK_HAND, .proc/on_attack_hand) + if(isitem(target)) + RegisterSignal(target, COMSIG_ITEM_ATTACK_SELF, .proc/apply_moodlet) + else + RegisterSignal(target, COMSIG_PARENT_EXAMINE, .proc/on_other_examine) + +/datum/element/art/Detach(datum/target) + UnregisterSignal(target, list(COMSIG_PARENT_EXAMINE, COMSIG_ATOM_ATTACK_HAND, COMSIG_ITEM_ATTACK_SELF)) + return ..() + +/datum/element/art/proc/apply_moodlet(atom/source, mob/M, impress) + M.visible_message("[M] stops and looks intently at [source].", \ + "You stop to take in [source].") + switch(impress) + if (0 to BAD_ART) + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artbad", /datum/mood_event/artbad) + if (BAD_ART to GOOD_ART) + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artok", /datum/mood_event/artok) + if (GOOD_ART to GREAT_ART) + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgood", /datum/mood_event/artgood) + if(GREAT_ART to INFINITY) + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgreat", /datum/mood_event/artgreat) + +/datum/element/art/proc/on_other_examine(atom/source, mob/M) + apply_moodlet(source, M, impressiveness) + +/datum/element/art/proc/on_obj_examine(atom/source, mob/M) + var/obj/O = source + apply_moodlet(source, M, impressiveness *(O.obj_integrity/O.max_integrity)) + +/datum/element/art/proc/on_attack_hand(atom/source, mob/M) + to_chat(M, "You start examining [source]...") + if(!do_after(M, 20, target = source)) + return + on_obj_examine(source, M) + +/datum/element/art/rev + +/datum/element/art/rev/apply_moodlet(atom/source, mob/M, impress) + M.visible_message("[M] stops to inspect [source].", \ + "You take in [source], inspecting the fine craftsmanship of the proletariat.") + + if(M.mind && M.mind.has_antag_datum(/datum/antagonist/rev)) + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artgreat", /datum/mood_event/artgreat) + else + SEND_SIGNAL(M, COMSIG_ADD_MOOD_EVENT, "artbad", /datum/mood_event/artbad) diff --git a/code/datums/elements/beauty.dm b/code/datums/elements/beauty.dm new file mode 100644 index 0000000000..8acfda73e1 --- /dev/null +++ b/code/datums/elements/beauty.dm @@ -0,0 +1,34 @@ +/datum/element/beauty + element_flags = ELEMENT_BESPOKE|ELEMENT_DETACH + id_arg_index = 2 + var/beauty = 0 + +/datum/element/beauty/Attach(datum/target, beautyamount) + . = ..() + if(. == ELEMENT_INCOMPATIBLE || !isatom(target) || isarea(target)) + return ELEMENT_INCOMPATIBLE + beauty = beautyamount + RegisterSignal(target, COMSIG_ENTER_AREA, .proc/enter_area) + RegisterSignal(target, COMSIG_EXIT_AREA, .proc/exit_area) + var/area/A = get_area(target) + if(A) + enter_area(null, A) + +/datum/element/beauty/Detach(datum/target) + UnregisterSignal(target, list(COMSIG_ENTER_AREA, COMSIG_EXIT_AREA)) + var/area/A = get_area(target) + if(A) + exit_area(null, A) + return ..() + +/datum/element/beauty/proc/enter_area(datum/source, area/A) + if(A.outdoors) + return + A.totalbeauty += beauty + A.update_beauty() + +/datum/element/beauty/proc/exit_area(datum/source, area/A) + if(A.outdoors) + return + A.totalbeauty -= beauty + A.update_beauty() diff --git a/code/datums/elements/tactical.dm b/code/datums/elements/tactical.dm index c74850795b..4b49552fbe 100644 --- a/code/datums/elements/tactical.dm +++ b/code/datums/elements/tactical.dm @@ -14,12 +14,12 @@ /datum/element/tactical/Detach(datum/target) UnregisterSignal(target, list(COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED)) - unmodify() + unmodify(target) return ..() /datum/element/tactical/proc/modify(obj/item/source, mob/user, slot) if(allowed_slot && slot != allowed_slot) - unmodify() + unmodify(source, user) return var/image/I = image(icon = source.icon, icon_state = source.icon_state, loc = user) diff --git a/code/datums/martial/_martial.dm b/code/datums/martial/_martial.dm index a9b4733fd8..a6b64a5d65 100644 --- a/code/datums/martial/_martial.dm +++ b/code/datums/martial/_martial.dm @@ -43,11 +43,11 @@ /datum/martial_art/proc/damage_roll(mob/living/carbon/human/A, mob/living/carbon/human/D) //Here we roll for our damage to be added into the damage var in the various attack procs. This is changed depending on whether we are in combat mode, lying down, or if our target is in combat mode. var/damage = rand(A.dna.species.punchdamagelow, A.dna.species.punchdamagehigh) - if(!(D.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + if(SEND_SIGNAL(D, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) damage *= 1.5 if(!CHECK_MOBILITY(A, MOBILITY_STAND)) damage *= 0.5 - if(!(A.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + if(SEND_SIGNAL(A, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) damage *= 0.25 return damage diff --git a/code/datums/materials/_material.dm b/code/datums/materials/_material.dm index c658ac215d..1a8ce755e1 100644 --- a/code/datums/materials/_material.dm +++ b/code/datums/materials/_material.dm @@ -24,6 +24,8 @@ Simple datum which is instanced once per type and is used for every object of sa var/value_per_unit = 0 ///Armor modifiers, multiplies an items normal armor vars by these amounts. var/armor_modifiers = list("melee" = 1, "bullet" = 1, "laser" = 1, "energy" = 1, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 1, "acid" = 1) + ///How beautiful is this material per unit? + var/beauty_modifier = 0 ///This proc is called when the material is added to an object. /datum/material/proc/on_applied(atom/source, amount, material_flags) @@ -39,6 +41,9 @@ Simple datum which is instanced once per type and is used for every object of sa if(istype(source, /obj)) //objs on_applied_obj(source, amount, material_flags) + if(beauty_modifier) + addtimer(CALLBACK(source, /datum.proc/_AddElement, list(/datum/element/beauty, beauty_modifier * amount)), 0) + ///This proc is called when the material is added to an object specifically. /datum/material/proc/on_applied_obj(var/obj/o, amount, material_flags) if(material_flags & MATERIAL_AFFECT_STATISTICS) diff --git a/code/datums/materials/basemats.dm b/code/datums/materials/basemats.dm index f189a91353..d4921a04d2 100644 --- a/code/datums/materials/basemats.dm +++ b/code/datums/materials/basemats.dm @@ -19,6 +19,7 @@ integrity_modifier = 0.1 sheet_type = /obj/item/stack/sheet/glass value_per_unit = 0.0025 + beauty_modifier = 0.05 armor_modifiers = list("melee" = 0.2, "bullet" = 0.2, "laser" = 0, "energy" = 1, "bomb" = 0, "bio" = 0.2, "rad" = 0.2, "fire" = 1, "acid" = 0.2) // yeah ok /* @@ -35,6 +36,7 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/silver value_per_unit = 0.025 + beauty_modifier = 0.075 ///Slight force increase /datum/material/gold @@ -46,6 +48,7 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/gold value_per_unit = 0.0625 + beauty_modifier = 0.15 armor_modifiers = list("melee" = 1.1, "bullet" = 1.1, "laser" = 1.15, "energy" = 1.15, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 0.7, "acid" = 1.1) ///Has no special properties @@ -58,6 +61,8 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/diamond value_per_unit = 0.25 + beauty_modifier = 0.3 + armor_modifiers = list("melee" = 1.3, "bullet" = 1.3, "laser" = 0.6, "energy" = 1, "bomb" = 1.2, "bio" = 1, "rad" = 1, "fire" = 1, "acid" = 1) ///Is slightly radioactive /datum/material/uranium @@ -68,6 +73,7 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/uranium value_per_unit = 0.05 + beauty_modifier = 0.3 //It shines so beautiful armor_modifiers = list("melee" = 1.5, "bullet" = 1.4, "laser" = 0.5, "energy" = 0.5, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 1, "acid" = 1) /datum/material/uranium/on_applied(atom/source, amount, material_flags) @@ -88,6 +94,7 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/plasma value_per_unit = 0.1 + beauty_modifier = 0.15 armor_modifiers = list("melee" = 1.4, "bullet" = 0.7, "laser" = 0, "energy" = 1.2, "bomb" = 0, "bio" = 1.2, "rad" = 1, "fire" = 0, "acid" = 0.5) /datum/material/plasma/on_applied(atom/source, amount, material_flags) @@ -109,6 +116,7 @@ Unless you know what you're doing, only use the first three numbers. They're in color = list(119/255, 217/255, 396/255,0, 0,0,0,0, 0,0,0,0, 0,0,0,1, 0,0,0,0) alpha = 200 categories = list(MAT_CATEGORY_ORE = TRUE) + beauty_modifier = 0.5 sheet_type = /obj/item/stack/sheet/bluespace_crystal value_per_unit = 0.15 @@ -121,6 +129,7 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/bananium value_per_unit = 0.5 + beauty_modifier = 0.5 armor_modifiers = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 100, "bio" = 0, "rad" = 0, "fire" = 10, "acid" = 0) //Clowns cant be blown away /datum/material/bananium/on_applied(atom/source, amount, material_flags) @@ -144,6 +153,7 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_ORE = TRUE, MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/titanium value_per_unit = 0.0625 + beauty_modifier = 0.05 armor_modifiers = list("melee" = 1.35, "bullet" = 1.3, "laser" = 1.3, "energy" = 1.25, "bomb" = 1.25, "bio" = 1, "rad" = 1, "fire" = 0.7, "acid" = 1) /datum/material/runite @@ -154,6 +164,7 @@ Unless you know what you're doing, only use the first three numbers. They're in strength_modifier = 1.3 categories = list(MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/runite + beauty_modifier = 0.5 armor_modifiers = list("melee" = 1.35, "bullet" = 2, "laser" = 0.5, "energy" = 1.25, "bomb" = 1.25, "bio" = 1, "rad" = 1, "fire" = 1.4, "acid" = 1) //rune is weak against magic lasers but strong against bullets. This is the combat triangle. ///Force decrease @@ -165,6 +176,7 @@ Unless you know what you're doing, only use the first three numbers. They're in strength_modifier = 0.85 sheet_type = /obj/item/stack/sheet/plastic value_per_unit = 0.0125 + beauty_modifier = -0.01 armor_modifiers = list("melee" = 1.5, "bullet" = 1.1, "laser" = 0.3, "energy" = 0.5, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 1.1, "acid" = 1) ///Force decrease and mushy sound effect. (Not yet implemented) @@ -176,6 +188,30 @@ Unless you know what you're doing, only use the first three numbers. They're in strength_modifier = 0.8 value_per_unit = 0.025 +/datum/material/wood + name = "wood" + id = "wood" + desc = "Flexible, durable, but flamable. Hard to come across in space." + color = "#bb8e53" + strength_modifier = 0.5 + sheet_type = /obj/item/stack/sheet/mineral/wood + categories = list(MAT_CATEGORY_RIGID = TRUE) + value_per_unit = 0.06 + beauty_modifier = 0.1 + armor_modifiers = list("melee" = 1.1, "bullet" = 1.1, "laser" = 0.4, "energy" = 0.4, "bomb" = 1, "bio" = 0.2, "rad" = 0, "fire" = 0, "acid" = 0.3) + +/datum/material/wood/on_applied_obj(obj/source, amount, material_flags) + . = ..() + if(material_flags & MATERIAL_AFFECT_STATISTICS) + var/obj/wooden = source + wooden.resistance_flags |= FLAMMABLE + +/datum/material/wood/on_removed_obj(obj/source, material_flags) + . = ..() + if(material_flags & MATERIAL_AFFECT_STATISTICS) + var/obj/wooden = source + wooden.resistance_flags &= ~FLAMMABLE + ///Stronk force increase /datum/material/adamantine name = "adamantine" @@ -186,6 +222,7 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/adamantine value_per_unit = 0.25 + beauty_modifier = 0.4 armor_modifiers = list("melee" = 1.5, "bullet" = 1.5, "laser" = 1.3, "energy" = 1.3, "bomb" = 1, "bio" = 1, "rad" = 1, "fire" = 2.5, "acid" = 1) ///RPG Magic. (Admin only) @@ -197,6 +234,7 @@ Unless you know what you're doing, only use the first three numbers. They're in categories = list(MAT_CATEGORY_RIGID = TRUE) sheet_type = /obj/item/stack/sheet/mineral/mythril value_per_unit = 0.75 + beauty_modifier = 0.5 armor_modifiers = list("melee" = 2, "bullet" = 2, "laser" = 2, "energy" = 2, "bomb" = 2, "bio" = 2, "rad" = 2, "fire" = 2, "acid" = 2) /datum/material/mythril/on_applied_obj(atom/source, amount, material_flags) diff --git a/code/datums/mind.dm b/code/datums/mind.dm index b7eac62e83..fb91edb2c9 100644 --- a/code/datums/mind.dm +++ b/code/datums/mind.dm @@ -97,9 +97,6 @@ if(current) // remove ourself from our old body's mind variable current.mind = null SStgui.on_transfer(current, new_character) - if(iscarbon(current)) - var/mob/living/carbon/C = current - C.disable_intentional_combat_mode(TRUE) if(key) if(new_character.key != key) //if we're transferring into a body with a key associated which is not ours diff --git a/code/datums/mood_events/generic_negative_events.dm b/code/datums/mood_events/generic_negative_events.dm index c56425b074..f5692c297a 100644 --- a/code/datums/mood_events/generic_negative_events.dm +++ b/code/datums/mood_events/generic_negative_events.dm @@ -153,7 +153,13 @@ mood_change = -4 timeout = 2400 +/datum/mood_event/graverobbing + description ="I just desecrated someone's grave... I can't believe I did that...\n" + mood_change = -8 + timeout = 3 MINUTES + //These are unused so far but I want to remember them to use them later + /datum/mood_event/cloned_corpse description = "I recently saw my own corpse...\n" mood_change = -6 @@ -162,6 +168,8 @@ description = "HE'S CUTTING ME OPEN!!\n" mood_change = -8 +//End unused + /datum/mood_event/sad_empath description = "Someone seems upset...\n" mood_change = -2 @@ -199,6 +207,8 @@ mood_change = -2 timeout = 1 MINUTES +//Cursed stuff end. + /datum/mood_event/vampcandle description = "Something is making your mind feel... loose...\n" mood_change = -15 diff --git a/code/datums/ruins/lavaland.dm b/code/datums/ruins/lavaland.dm index 8f3811ca71..933eaf082e 100644 --- a/code/datums/ruins/lavaland.dm +++ b/code/datums/ruins/lavaland.dm @@ -250,4 +250,12 @@ cost = 5 placement_weight = 3 always_place = TRUE - allow_duplicates = TRUE + allow_duplicates = TRUE + +/datum/map_template/ruin/lavaland/elephant_graveyard + name = "Elephant Graveyard" + id = "Graveyard" + description = "An abandoned graveyard, calling to those unable to continue." + suffix = "lavaland_surface_elephant_graveyard.dmm" + allow_duplicates = FALSE + cost = 10 diff --git a/code/datums/tgs_event_handler.dm b/code/datums/tgs_event_handler.dm index a3324121bf..731be64183 100644 --- a/code/datums/tgs_event_handler.dm +++ b/code/datums/tgs_event_handler.dm @@ -1,3 +1,6 @@ +/datum/tgs_event_handler/impl + var/datum/timedevent/reattach_timer + /datum/tgs_event_handler/impl/HandleEvent(event_code, ...) switch(event_code) if(TGS_EVENT_REBOOT_MODE_CHANGE) @@ -18,3 +21,19 @@ if(TGS_EVENT_DEPLOYMENT_COMPLETE) message_admins("TGS: Deployment complete!") to_chat(world, "Server updated, changes will be applied on the next round...") + if(TGS_EVENT_WATCHDOG_DETACH) + message_admins("TGS restarting...") + reattach_timer = addtimer(CALLBACK(src, .proc/LateOnReattach), 1 MINUTES) + if(TGS_EVENT_WATCHDOG_REATTACH) + var/datum/tgs_version/old_version = world.TgsVersion() + var/datum/tgs_version/new_version = args[2] + if(!old_version.Equals(new_version)) + to_chat(world, "TGS updated to v[old_version.deprefixed_parameter]") + else + message_admins("TGS: Back online") + if(reattach_timer) + deltimer(reattach_timer) + reattach_timer = null + +/datum/tgs_event_handler/impl/proc/LateOnReattach() + message_admins("Warning: TGS hasn't notified us of it coming back for a full minute! Is there a problem?") diff --git a/code/datums/traits/neutral.dm b/code/datums/traits/neutral.dm index d1b5240798..4b039aa1b5 100644 --- a/code/datums/traits/neutral.dm +++ b/code/datums/traits/neutral.dm @@ -10,6 +10,15 @@ lose_text = "You can taste again!" medical_record_text = "Patient suffers from ageusia and is incapable of tasting food or reagents." +/datum/quirk/snob + name = "Snob" + desc = "You care about the finer things, if a room doesn't look nice its just not really worth it, is it?" + value = 0 + gain_text = "You feel like you understand what things should look like." + lose_text = "Well who cares about deco anyways?" + medical_record_text = "Patient seems to be rather stuck up." + mob_trait = TRAIT_SNOB + /datum/quirk/pineapple_liker name = "Ananas Affinity" desc = "You find yourself greatly enjoying fruits of the ananas genus. You can't seem to ever get enough of their sweet goodness!" diff --git a/code/datums/wires/_wires.dm b/code/datums/wires/_wires.dm index a96e14d4d7..11e7e12bd8 100644 --- a/code/datums/wires/_wires.dm +++ b/code/datums/wires/_wires.dm @@ -11,9 +11,6 @@ if(A.attachable) return TRUE -/atom - var/datum/wires/wires = null - /atom/proc/attempt_wire_interaction(mob/user) if(!wires) return WIRE_INTERACTION_FAIL diff --git a/code/game/area/areas.dm b/code/game/area/areas.dm index 5fac1a4b65..dabbe93bec 100644 --- a/code/game/area/areas.dm +++ b/code/game/area/areas.dm @@ -38,6 +38,10 @@ var/poweralm = TRUE var/lightswitch = TRUE + var/totalbeauty = 0 //All beauty in this area combined, only includes indoor area. + var/beauty = 0 // Beauty average per open turf in the area + var/beauty_threshold = 150 //If a room is too big it doesn't have beauty. + var/requires_power = TRUE /// This gets overridden to 1 for space in area/Initialize(). var/always_unpowered = FALSE @@ -65,7 +69,7 @@ /// Hides area from player Teleport function. var/hidden = FALSE /// Is the area teleport-safe: no space / radiation / aggresive mobs / other dangers - var/safe = FALSE + var/safe = FALSE /// If false, loading multiple maps with this area type will create multiple instances. var/unique = TRUE @@ -192,6 +196,7 @@ GLOBAL_LIST_EMPTY(teleportlocs) /area/LateInitialize() if(!base_area) //we don't want to run it twice. power_change() // all machines set to current power level, also updates icon + update_beauty() /area/proc/reg_in_areas_in_z() if(contents.len) @@ -538,6 +543,16 @@ GLOBAL_LIST_EMPTY(teleportlocs) L.client.played = TRUE addtimer(CALLBACK(L.client, /client/proc/ResetAmbiencePlayed), 600) +///Divides total beauty in the room by roomsize to allow us to get an average beauty per tile. +/area/proc/update_beauty() + if(!areasize) + beauty = 0 + return FALSE + if(areasize >= beauty_threshold) + beauty = 0 + return FALSE //Too big + beauty = totalbeauty / areasize + /area/Exited(atom/movable/M) SEND_SIGNAL(src, COMSIG_AREA_EXITED, M) SEND_SIGNAL(M, COMSIG_EXIT_AREA, src) //The atom that exits the area diff --git a/code/game/area/areas/ruins/lavaland.dm b/code/game/area/areas/ruins/lavaland.dm index 76f090d5e3..19a1fd503d 100644 --- a/code/game/area/areas/ruins/lavaland.dm +++ b/code/game/area/areas/ruins/lavaland.dm @@ -32,6 +32,14 @@ /area/ruin/powered/seedvault icon_state = "dk_yellow" +/area/ruin/unpowered/elephant_graveyard + name = "Elephant Graveyard" + icon_state = "dk_yellow" + +/area/ruin/powered/graveyard_shuttle + name = "Elephant Graveyard" + icon_state = "green" + /area/ruin/unpowered/syndicate_lava_base name = "Secret Base" icon_state = "dk_yellow" diff --git a/code/game/atoms.dm b/code/game/atoms.dm index 1ff27bafa9..a83eaed9d3 100644 --- a/code/game/atoms.dm +++ b/code/game/atoms.dm @@ -47,6 +47,8 @@ ///Modifier that raises/lowers the effect of the amount of a material, prevents small and easy to get items from being death machines. var/material_modifier = 1 + var/datum/wires/wires = null + var/icon/blood_splatter_icon var/list/fingerprints var/list/fingerprintshidden @@ -313,10 +315,11 @@ . += desc if(custom_materials) + var/list/materials_list = list() for(var/i in custom_materials) var/datum/material/M = i - . += "It is made out of [M.name]." - + materials_list += "[M.name]" + . += "It is made out of [english_list(materials_list)]." if(reagents) if(reagents.reagents_holder_flags & TRANSPARENT) . += "It contains:" diff --git a/code/game/gamemodes/sandbox/h_sandbox.dm b/code/game/gamemodes/sandbox/h_sandbox.dm index e1fbb636c8..e97d276296 100644 --- a/code/game/gamemodes/sandbox/h_sandbox.dm +++ b/code/game/gamemodes/sandbox/h_sandbox.dm @@ -2,8 +2,7 @@ GLOBAL_VAR_INIT(hsboxspawn, TRUE) -/mob - var/datum/hSB/sandbox = null + /mob/proc/CanBuild() sandbox = new/datum/hSB sandbox.owner = src.ckey diff --git a/code/game/machinery/autolathe.dm b/code/game/machinery/autolathe.dm index 3b32213509..4eeb6b8b0f 100644 --- a/code/game/machinery/autolathe.dm +++ b/code/game/machinery/autolathe.dm @@ -60,7 +60,8 @@ /datum/material/runite, /datum/material/plastic, /datum/material/adamantine, - /datum/material/mythril + /datum/material/mythril, + /datum/material/wood ) /// Base print speed diff --git a/code/game/machinery/doors/shutters.dm b/code/game/machinery/doors/shutters.dm index 87e8c8f6a7..362dde1157 100644 --- a/code/game/machinery/doors/shutters.dm +++ b/code/game/machinery/doors/shutters.dm @@ -53,7 +53,9 @@ if("opening") rad_insulation = 1 if("closing") - rad_insulation = 0.2 + rad_insulation = -0.5 + +// A 3x3 N2 SM setup won't irradiate you if you're behind the shutter at -0.9 insulation. If it starts to delam, it'll start irradiating you slowly. Keep the value between -0.1 to -0.9 /obj/machinery/door/poddoor/shutters/window name = "windowed shutters" diff --git a/code/game/objects/effects/contraband.dm b/code/game/objects/effects/contraband.dm index 69aa3fb654..0954d12790 100644 --- a/code/game/objects/effects/contraband.dm +++ b/code/game/objects/effects/contraband.dm @@ -51,6 +51,7 @@ icon = 'icons/obj/contraband.dmi' plane = ABOVE_WALL_PLANE anchored = TRUE + buildable_sign = FALSE //Cannot be unwrenched from a wall. var/ruined = FALSE var/random_basetype var/never_random = FALSE // used for the 'random' subclasses. @@ -69,6 +70,8 @@ name = "poster - [name]" desc = "A large piece of space-resistant printed paper. [desc]" + addtimer(CALLBACK(src, /datum.proc/_AddElement, list(/datum/element/beauty, 300)), 0) + /obj/structure/sign/poster/proc/randomise(base_type) var/list/poster_types = subtypesof(base_type) var/list/approved_types = list() diff --git a/code/game/objects/effects/decals/cleanable.dm b/code/game/objects/effects/decals/cleanable.dm index 5720d5ce34..34996177af 100644 --- a/code/game/objects/effects/decals/cleanable.dm +++ b/code/game/objects/effects/decals/cleanable.dm @@ -5,6 +5,7 @@ var/blood_state = "" //I'm sorry but cleanable/blood code is ass, and so is blood_DNA var/bloodiness = 0 //0-100, amount of blood in this decal, used for making footprints and affecting the alpha of bloody footprints var/mergeable_decal = TRUE //when two of these are on a same tile or do we need to merge them into just one? + var/beauty = 0 /obj/effect/decal/cleanable/Initialize(mapload, list/datum/disease/diseases) . = ..() @@ -26,6 +27,8 @@ if(LAZYLEN(diseases_to_add)) AddComponent(/datum/component/infective, diseases_to_add) + addtimer(CALLBACK(src, /datum.proc/_AddElement, list(/datum/element/beauty, beauty)), 0) + /obj/effect/decal/cleanable/proc/replace_decal(obj/effect/decal/cleanable/C) // Returns true if we should give up in favor of the pre-existing decal if(mergeable_decal) qdel(C) diff --git a/code/game/objects/effects/decals/cleanable/aliens.dm b/code/game/objects/effects/decals/cleanable/aliens.dm index 3afc0ef671..fa4bfe7e67 100644 --- a/code/game/objects/effects/decals/cleanable/aliens.dm +++ b/code/game/objects/effects/decals/cleanable/aliens.dm @@ -3,6 +3,7 @@ name = "xeno blood" desc = "It's green and acidic. It looks like... blood?" color = BLOOD_COLOR_XENO + beauty = -250 /obj/effect/decal/cleanable/blood/splatter/xeno color = BLOOD_COLOR_XENO diff --git a/code/game/objects/effects/decals/cleanable/humans.dm b/code/game/objects/effects/decals/cleanable/humans.dm index ab0d1caca4..a5acc7d394 100644 --- a/code/game/objects/effects/decals/cleanable/humans.dm +++ b/code/game/objects/effects/decals/cleanable/humans.dm @@ -7,6 +7,7 @@ blood_state = BLOOD_STATE_BLOOD bloodiness = BLOOD_AMOUNT_PER_DECAL color = BLOOD_COLOR_HUMAN //default so we don't have white splotches everywhere. + beauty = -100 /obj/effect/decal/cleanable/blood/replace_decal(obj/effect/decal/cleanable/blood/C) if (C.blood_DNA) @@ -45,12 +46,14 @@ icon_state = "tracks" desc = "They look like tracks left by wheels." random_icon_states = null + beauty = -50 /obj/effect/decal/cleanable/trail_holder //not a child of blood on purpose name = "blood" icon_state = "ltrails_1" desc = "Your instincts say you shouldn't be following these." random_icon_states = null + beauty = -50 var/list/existing_dirs = list() /obj/effect/decal/cleanable/trail_holder/update_icon() diff --git a/code/game/objects/effects/decals/cleanable/misc.dm b/code/game/objects/effects/decals/cleanable/misc.dm index e06c172519..2e45bbfca5 100644 --- a/code/game/objects/effects/decals/cleanable/misc.dm +++ b/code/game/objects/effects/decals/cleanable/misc.dm @@ -3,6 +3,7 @@ desc = "Someone should clean that up." icon = 'icons/obj/objects.dmi' icon_state = "shards" + beauty = -50 /obj/effect/decal/cleanable/ash name = "ashes" @@ -10,6 +11,7 @@ icon = 'icons/obj/objects.dmi' icon_state = "ash" mergeable_decal = FALSE + beauty = -50 /obj/effect/decal/cleanable/ash/Initialize() . = ..() @@ -24,6 +26,7 @@ /obj/effect/decal/cleanable/ash/large name = "large pile of ashes" icon_state = "big_ash" + beauty = -100 /obj/effect/decal/cleanable/ash/large/Initialize() . = ..() @@ -34,6 +37,7 @@ desc = "Back to sand." icon = 'icons/obj/shards.dmi' icon_state = "tiny" + beauty = -100 /obj/effect/decal/cleanable/glass/Initialize() . = ..() @@ -52,6 +56,7 @@ canSmoothWith = list(/obj/effect/decal/cleanable/dirt, /turf/closed/wall, /obj/structure/falsewall) smooth = SMOOTH_FALSE mouse_opacity = MOUSE_OPACITY_TRANSPARENT + beauty = -75 /obj/effect/decal/cleanable/dirt/Initialize() . = ..() @@ -72,6 +77,10 @@ desc = "It's still good. Four second rule!" icon_state = "flour" +/obj/effect/decal/cleanable/dirt/dust + name = "dust" + desc = "A thin layer of dust coating the floor." + /obj/effect/decal/cleanable/greenglow/ecto name = "ectoplasmic puddle" desc = "You know who to call." @@ -80,8 +89,11 @@ /obj/effect/decal/cleanable/greenglow name = "glowing goo" desc = "Jeez. I hope that's not for lunch." + light_power = 1 + light_range = 1 light_color = LIGHT_COLOR_GREEN icon_state = "greenglow" + beauty = -300 /obj/effect/decal/cleanable/greenglow/Initialize(mapload) . = ..() @@ -97,6 +109,7 @@ layer = WALL_OBJ_LAYER icon_state = "cobweb1" resistance_flags = FLAMMABLE + beauty = -100 /obj/effect/decal/cleanable/cobweb/cobweb2 icon_state = "cobweb2" @@ -108,10 +121,12 @@ icon = 'icons/effects/effects.dmi' icon_state = "molten" mergeable_decal = FALSE + beauty = -150 /obj/effect/decal/cleanable/molten_object/large name = "big gooey grey mass" icon_state = "big_molten" + beauty = -300 //Vomit (sorry) /obj/effect/decal/cleanable/vomit @@ -120,6 +135,7 @@ icon = 'icons/effects/blood.dmi' icon_state = "vomit_1" random_icon_states = list("vomit_1", "vomit_2", "vomit_3", "vomit_4") + beauty = -150 /obj/effect/decal/cleanable/vomit/attack_hand(mob/user) . = ..() @@ -152,6 +168,7 @@ gender = NEUTER icon = 'icons/effects/tomatodecal.dmi' random_icon_states = list("tomato_floor1", "tomato_floor2", "tomato_floor3") + beauty = -100 /obj/effect/decal/cleanable/plant_smudge name = "plant smudge" diff --git a/code/game/objects/effects/decals/cleanable/robots.dm b/code/game/objects/effects/decals/cleanable/robots.dm index cf030df120..2765330977 100644 --- a/code/game/objects/effects/decals/cleanable/robots.dm +++ b/code/game/objects/effects/decals/cleanable/robots.dm @@ -10,6 +10,7 @@ blood_state = BLOOD_STATE_OIL bloodiness = BLOOD_AMOUNT_PER_DECAL mergeable_decal = FALSE + beauty = -50 /obj/effect/decal/cleanable/robot_debris/Initialize(mapload, list/datum/disease/diseases) . = ..() @@ -50,6 +51,7 @@ random_icon_states = list("floor1", "floor2", "floor3", "floor4", "floor5", "floor6", "floor7") blood_state = BLOOD_STATE_OIL bloodiness = BLOOD_AMOUNT_PER_DECAL + beauty = -100 /obj/effect/decal/cleanable/oil/Initialize() . = ..() @@ -58,6 +60,7 @@ /obj/effect/decal/cleanable/oil/streak random_icon_states = list("streak1", "streak2", "streak3", "streak4", "streak5") + beauty = -50 /obj/effect/decal/cleanable/oil/slippery diff --git a/code/game/objects/items.dm b/code/game/objects/items.dm index 76c282e14d..28c60c9eba 100644 --- a/code/game/objects/items.dm +++ b/code/game/objects/items.dm @@ -145,6 +145,9 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) var/skill_difficulty = THRESHOLD_UNTRAINED //how difficult it's to use this item in general. var/skill_gain = DEF_SKILL_GAIN //base skill value gain from using this item. + var/canMouseDown = FALSE + + /obj/item/Initialize() if (attack_verb) @@ -429,14 +432,12 @@ GLOBAL_VAR_INIT(rpg_loot_items, FALSE) return usr.client.Click(src, src_location, src_control, params) var/list/directaccess = usr.DirectAccess() //This, specifically, is what requires the copypaste. If this were after the adjacency check, then it'd be impossible to use items in your inventory, among other things. //If this were before the above checks, then trying to click on items would act a little funky and signal overrides wouldn't work. - if(iscarbon(usr)) - var/mob/living/carbon/C = usr - if((C.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && ((C.CanReach(src) || (src in directaccess)) && (C.CanReach(over) || (over in directaccess)))) - if(!C.get_active_held_item()) - C.UnarmedAttack(src, TRUE) - if(C.get_active_held_item() == src) - melee_attack_chain(C, over) - return TRUE //returning TRUE as a "is this overridden?" flag + if(SEND_SIGNAL(usr, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE) && ((usr.CanReach(src) || (src in directaccess)) && (usr.CanReach(over) || (over in directaccess)))) + if(!usr.get_active_held_item()) + usr.UnarmedAttack(src, TRUE) + if(usr.get_active_held_item() == src) + melee_attack_chain(usr, over) + return TRUE //returning TRUE as a "is this overridden?" flag if(!Adjacent(usr) || !over.Adjacent(usr)) return // should stop you from dragging through windows diff --git a/code/game/objects/items/kitchen.dm b/code/game/objects/items/kitchen.dm index 168bca0b9a..77d9f09eff 100644 --- a/code/game/objects/items/kitchen.dm +++ b/code/game/objects/items/kitchen.dm @@ -104,10 +104,10 @@ desc = "An occult looking dagger that is cold to the touch. Somehow, the flawless orb on the pommel is made entirely of liquid blood." icon = 'icons/obj/ice_moon/artifacts.dmi' icon_state = "bloodletter" - w_class = WEIGHT_CLASS_NORMAL + w_class = WEIGHT_CLASS_NORMAL /// Bleed stacks applied when an organic mob target is hit var/bleed_stacks_per_hit = 3 - + /obj/item/kitchen/knife/bloodletter/afterattack(atom/target, mob/user, proximity_flag, click_parameters) . = ..() if(!isliving(target) || !proximity_flag) @@ -198,6 +198,7 @@ throw_speed = 3 throw_range = 7 w_class = WEIGHT_CLASS_NORMAL + custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 1.5) attack_verb = list("bashed", "battered", "bludgeoned", "thrashed", "whacked") custom_price = 200 diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm index be68db8d01..68b8861cee 100644 --- a/code/game/objects/items/shields.dm +++ b/code/game/objects/items/shields.dm @@ -113,7 +113,7 @@ return TRUE /obj/item/shield/proc/user_shieldbash(mob/living/user, atom/target, harmful) - if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) //Combat mode has to be enabled for shield bashing + if(!SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) //Combat mode has to be enabled for shield bashing return FALSE if(!(shield_flags & SHIELD_CAN_BASH)) to_chat(user, "[src] can't be used to shield bash!") @@ -283,7 +283,7 @@ obj/item/shield/riot/bullet_proof item_state = "buckler" lefthand_file = 'icons/mob/inhands/equipment/shields_lefthand.dmi' righthand_file = 'icons/mob/inhands/equipment/shields_righthand.dmi' - custom_materials = null + custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 10) resistance_flags = FLAMMABLE repair_material = /obj/item/stack/sheet/mineral/wood block_chance = 30 diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 5f2b9fda41..f26f3587a4 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -279,11 +279,13 @@ GLOBAL_LIST_INIT(wood_recipes, list ( \ icon_state = "sheet-wood" item_state = "sheet-wood" icon = 'icons/obj/stack_objects.dmi' + custom_materials = list(/datum/material/wood=MINERAL_MATERIAL_AMOUNT) sheettype = "wood" armor = list("melee" = 0, "bullet" = 0, "laser" = 0, "energy" = 0, "bomb" = 0, "bio" = 0, "rad" = 0, "fire" = 50, "acid" = 0) resistance_flags = FLAMMABLE merge_type = /obj/item/stack/sheet/mineral/wood novariants = TRUE + material_type = /datum/material/wood grind_results = list(/datum/reagent/carbon = 20) /obj/item/stack/sheet/mineral/wood/attackby(obj/item/W, mob/user, params) // NOTE: sheet_types.dm is where the WOOD stack lives. Maybe move this over there. diff --git a/code/game/objects/items/tanks/jetpack.dm b/code/game/objects/items/tanks/jetpack.dm index e81294ceea..817258d1c7 100644 --- a/code/game/objects/items/tanks/jetpack.dm +++ b/code/game/objects/items/tanks/jetpack.dm @@ -14,13 +14,15 @@ var/full_speed = TRUE // If the jetpack will have a speedboost in space/nograv or not var/datum/effect_system/trail_follow/ion/ion_trail -/obj/item/tank/jetpack/New() +/obj/item/tank/jetpack/Initialize() ..() + ion_trail = new + ion_trail.set_up(src) + +/obj/item/tank/jetpack/populate_gas() if(gas_type) air_contents.gases[gas_type] = ((6 * ONE_ATMOSPHERE) * volume / (R_IDEAL_GAS_EQUATION * T20C)) - ion_trail = new - ion_trail.set_up(src) /obj/item/tank/jetpack/ui_action_click(mob/user, action) if(istype(action, /datum/action/item_action/toggle_jetpack)) @@ -188,8 +190,8 @@ var/obj/item/tank/internals/tank = null var/mob/living/carbon/human/cur_user -/obj/item/tank/jetpack/suit/New() - ..() +/obj/item/tank/jetpack/suit/Initialize() + . = ..() STOP_PROCESSING(SSobj, src) temp_air_contents = air_contents diff --git a/code/game/objects/items/tanks/tank_types.dm b/code/game/objects/items/tanks/tank_types.dm index 0e6dfaa1b3..8f5303da8e 100644 --- a/code/game/objects/items/tanks/tank_types.dm +++ b/code/game/objects/items/tanks/tank_types.dm @@ -12,15 +12,13 @@ */ /obj/item/tank/internals/oxygen name = "oxygen tank" - desc = "A tank of oxygen." + desc = "A tank of oxygen, this one is blue." icon_state = "oxygen" distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE force = 10 dog_fashion = /datum/dog_fashion/back - -/obj/item/tank/internals/oxygen/New() - ..() +/obj/item/tank/internals/oxygen/populate_gas() air_contents.gases[/datum/gas/oxygen] = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) return @@ -35,6 +33,8 @@ icon_state = "oxygen_fr" dog_fashion = null +/obj/item/tank/internals/oxygen/empty/populate_gas() + return /* * Anesthetic @@ -46,11 +46,9 @@ item_state = "an_tank" force = 10 -/obj/item/tank/internals/anesthetic/New() - ..() +/obj/item/tank/internals/anesthetic/populate_gas() air_contents.gases[/datum/gas/oxygen] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD air_contents.gases[/datum/gas/nitrous_oxide] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD - return /* * Air @@ -63,11 +61,9 @@ force = 10 dog_fashion = /datum/dog_fashion/back -/obj/item/tank/internals/air/New() - ..() +/obj/item/tank/internals/air/populate_gas() air_contents.gases[/datum/gas/oxygen] = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * O2STANDARD air_contents.gases[/datum/gas/nitrogen] = (6*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) * N2STANDARD - return /* @@ -82,10 +78,8 @@ force = 8 -/obj/item/tank/internals/plasma/New() - ..() +/obj/item/tank/internals/plasma/populate_gas() air_contents.gases[/datum/gas/plasma] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) - return /obj/item/tank/internals/plasma/attackby(obj/item/W, mob/user, params) if(istype(W, /obj/item/flamethrower)) @@ -100,10 +94,8 @@ else return ..() -/obj/item/tank/internals/plasma/full/New() - ..() // Plasma asserted in parent +/obj/item/tank/internals/plasma/full/populate_gas() air_contents.gases[/datum/gas/plasma] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) - return /* @@ -118,13 +110,10 @@ force = 10 distribute_pressure = TANK_DEFAULT_RELEASE_PRESSURE -/obj/item/tank/internals/plasmaman/New() - ..() +/obj/item/tank/internals/plasmaman/populate_gas() air_contents.gases[/datum/gas/plasma] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) - return -/obj/item/tank/internals/plasmaman/full/New() - ..() // Plasma asserted in parent +/obj/item/tank/internals/plasmaman/full/populate_gas() air_contents.gases[/datum/gas/plasma] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) return @@ -137,12 +126,12 @@ volume = 6 w_class = WEIGHT_CLASS_SMALL //thanks i forgot this -/obj/item/tank/internals/plasmaman/belt/full/New() - ..() // Plasma asserted in parent +/obj/item/tank/internals/plasmaman/belt/full/populate_gas() air_contents.gases[/datum/gas/plasma] = (10*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) return - +/obj/item/tank/internals/plasmaman/belt/empty/populate_gas() + return /* * Emergency Oxygen @@ -159,17 +148,25 @@ volume = 3 //Tiny. Real life equivalents only have 21 breaths of oxygen in them. They're EMERGENCY tanks anyway -errorage (dangercon 2011) -/obj/item/tank/internals/emergency_oxygen/New() - ..() +/obj/item/tank/internals/emergency_oxygen/populate_gas() air_contents.gases[/datum/gas/oxygen] = (3*ONE_ATMOSPHERE)*volume/(R_IDEAL_GAS_EQUATION*T20C) return +/obj/item/tank/internals/emergency_oxygen/empty/populate_gas() + return + /obj/item/tank/internals/emergency_oxygen/engi name = "extended-capacity emergency oxygen tank" icon_state = "emergency_engi" volume = 6 +/obj/item/tank/internals/emergency_oxygen/engi/empty/populate_gas() + return + /obj/item/tank/internals/emergency_oxygen/double name = "double emergency oxygen tank" icon_state = "emergency_double" volume = 10 + +/obj/item/tank/internals/emergency_oxygen/double/empty/populate_gas() + return \ No newline at end of file diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm index 1c92ed4e61..95712f386a 100644 --- a/code/game/objects/items/tanks/tanks.dm +++ b/code/game/objects/items/tanks/tanks.dm @@ -60,14 +60,19 @@ H.update_action_buttons_icon() -/obj/item/tank/New() - ..() +/obj/item/tank/Initialize() + . = ..() air_contents = new(volume) //liters air_contents.temperature = T20C + populate_gas() + START_PROCESSING(SSobj, src) +/obj/item/tank/proc/populate_gas() + return + /obj/item/tank/Destroy() if(air_contents) qdel(air_contents) @@ -78,9 +83,9 @@ /obj/item/tank/examine(mob/user) var/obj/icon = src . = ..() - if (istype(src.loc, /obj/item/assembly)) + if(istype(src.loc, /obj/item/assembly)) icon = src.loc - if(!in_range(src, user)) + if(!in_range(src, user) && !isobserver(user)) if (icon == src) . += "If you want any more information you'll need to get closer." return diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index aa0aa70e03..1bb4579176 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -477,20 +477,12 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 throw_speed = 5 throw_range = 2 attack_verb = list("busted") + var/impressiveness = 45 -/obj/item/statuebust/attack_self(mob/living/user) - add_fingerprint(user) - user.examinate(src) - -/obj/item/statuebust/examine(mob/living/user) +/obj/item/statuebust/Initialize() . = ..() - if(.) - return - if (!isliving(user)) - return - user.visible_message("[user] stops to admire [src].", \ - "You take in [src], admiring its fine craftsmanship.") - SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "artgood", /datum/mood_event/artgood) + AddElement(/datum/element/art, impressiveness) + addtimer(CALLBACK(src, /datum.proc/_AddElement, list(/datum/element/beauty, 1000)), 0) /obj/item/tailclub name = "tail club" @@ -566,6 +558,7 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 force = 10 throwforce = 12 attack_verb = list("beat", "smacked") + custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 3.5) w_class = WEIGHT_CLASS_BULKY var/homerun_ready = 0 var/homerun_able = 0 diff --git a/code/game/objects/structures/artstuff.dm b/code/game/objects/structures/artstuff.dm index 98f772a116..fcc26d1313 100644 --- a/code/game/objects/structures/artstuff.dm +++ b/code/game/objects/structures/artstuff.dm @@ -240,7 +240,7 @@ /obj/structure/sign/painting/Initialize(mapload, dir, building) . = ..() SSpersistence.painting_frames += src - AddComponent(/datum/component/art, 20) + AddElement(/datum/element/art, 20) if(dir) setDir(dir) if(building) diff --git a/code/game/objects/structures/bedsheet_bin.dm b/code/game/objects/structures/bedsheet_bin.dm index 57d7e08862..bd6dcb2aff 100644 --- a/code/game/objects/structures/bedsheet_bin.dm +++ b/code/game/objects/structures/bedsheet_bin.dm @@ -261,6 +261,11 @@ LINEN BINS var/list/sheets = list() var/obj/item/hidden = null +/obj/structure/bedsheetbin/empty + amount = 0 + icon_state = "linenbin-empty" + anchored = FALSE + /obj/structure/bedsheetbin/examine(mob/user) . = ..() if(amount < 1) diff --git a/code/game/objects/structures/flora.dm b/code/game/objects/structures/flora.dm index e03ece2dfa..c1f8af43f0 100644 --- a/code/game/objects/structures/flora.dm +++ b/code/game/objects/structures/flora.dm @@ -303,6 +303,7 @@ /obj/item/twohanded/required/kirbyplants/Initialize() . = ..() AddElement(/datum/element/tactical) + addtimer(CALLBACK(src, /datum.proc/_AddElement, list(/datum/element/beauty, 500)), 0) /obj/item/twohanded/required/kirbyplants/random icon = 'icons/obj/flora/_flora.dmi' diff --git a/code/game/objects/structures/signs/_signs.dm b/code/game/objects/structures/signs/_signs.dm index a1de5fe6a3..aa31fe9542 100644 --- a/code/game/objects/structures/signs/_signs.dm +++ b/code/game/objects/structures/signs/_signs.dm @@ -36,6 +36,7 @@ "You unfasten [src].") var/obj/item/sign_backing/SB = new (get_turf(user)) SB.icon_state = icon_state + SB.set_custom_materials(custom_materials) //This is here so picture frames and wooden things don't get messed up. SB.sign_path = type SB.setDir(dir) qdel(src) diff --git a/code/game/objects/structures/signs/signs_plaques.dm b/code/game/objects/structures/signs/signs_plaques.dm index 78c88cd09d..d1067f1963 100644 --- a/code/game/objects/structures/signs/signs_plaques.dm +++ b/code/game/objects/structures/signs/signs_plaques.dm @@ -46,3 +46,4 @@ name = "Mr. Deempisi portrait" desc = "Under the painting a plaque reads: 'While the meat grinder may not have spared you, fear not. Not one part of you has gone to waste... You were delicious.'" icon_state = "monkey_painting" + custom_materials = list(/datum/material/wood = 2000) //The same as /obj/structure/sign/picture_frame diff --git a/code/game/objects/structures/signs/signs_warning.dm b/code/game/objects/structures/signs/signs_warning.dm index f735ed7bc9..3138d44e9d 100644 --- a/code/game/objects/structures/signs/signs_warning.dm +++ b/code/game/objects/structures/signs/signs_warning.dm @@ -73,3 +73,8 @@ name = "\improper ENGINEERING SAFETY" desc = "A sign detailing the various safety protocols when working on-site to ensure a safe shift." icon_state = "safety" + +/obj/structure/sign/warning/explosives + name = "\improper HIGH EXPLOSIVES sign" + desc = "A warning sign which reads 'HIGH EXPLOSIVES'." + icon_state = "explosives" diff --git a/code/game/objects/structures/statues.dm b/code/game/objects/structures/statues.dm index 1f9491f4cf..466912f93e 100644 --- a/code/game/objects/structures/statues.dm +++ b/code/game/objects/structures/statues.dm @@ -11,6 +11,12 @@ var/impressiveness = 15 CanAtmosPass = ATMOS_PASS_DENSITY + +/obj/structure/statue/Initialize() + . = ..() + AddElement(/datum/element/art, impressiveness) + addtimer(CALLBACK(src, /datum.proc/_AddElement, list(/datum/element/beauty, impressiveness * 75)), 0) + /obj/structure/statue/attackby(obj/item/W, mob/living/user, params) add_fingerprint(user) if(!(flags_1 & NODECONSTRUCT_1)) @@ -29,29 +35,6 @@ return return ..() -/obj/structure/statue/attack_hand(mob/living/user) - . = ..() - if(.) - return - user.changeNext_move(CLICK_CD_MELEE) - add_fingerprint(user) - if(!do_after(user, 20, target = src)) - return - user.visible_message("[user] rubs some dust off [src].", \ - "You take in [src], rubbing some dust off its surface.") - if(!ishuman(user)) // only humans have the capacity to appreciate art - return - var/totalimpressiveness = (impressiveness *(obj_integrity/max_integrity)) - switch(totalimpressiveness) - if(GREAT_ART to 100) - SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "artgreat", /datum/mood_event/artgreat) - if (GOOD_ART to GREAT_ART) - SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "artgood", /datum/mood_event/artgood) - if (BAD_ART to GOOD_ART) - SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "artok", /datum/mood_event/artok) - if (0 to BAD_ART) - SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "artbad", /datum/mood_event/artbad) - /obj/structure/statue/deconstruct(disassembled = TRUE) if(!(flags_1 & NODECONSTRUCT_1)) if(material_drop_type) diff --git a/code/game/objects/structures/watercloset.dm b/code/game/objects/structures/watercloset.dm index fbb1eac7d1..ddf7fa6bc6 100644 --- a/code/game/objects/structures/watercloset.dm +++ b/code/game/objects/structures/watercloset.dm @@ -11,6 +11,8 @@ var/cistern = 0 //if the cistern bit is open var/w_items = 0 //the combined w_class of all the items in the cistern var/mob/living/swirlie = null //the mob being given a swirlie + var/buildstacktype = /obj/item/stack/sheet/metal //they're metal now, shut up + var/buildstackamount = 1 /obj/structure/toilet/Initialize() . = ..() @@ -72,7 +74,18 @@ /obj/structure/toilet/update_icon_state() icon_state = "toilet[open][cistern]" +/obj/structure/toilet/deconstruct() + if(!(flags_1 & NODECONSTRUCT_1)) + if(buildstacktype) + new buildstacktype(loc,buildstackamount) + else + for(var/i in custom_materials) + var/datum/material/M = i + new M.sheet_type(loc, FLOOR(custom_materials[M] / MINERAL_MATERIAL_AMOUNT, 1)) + ..() + /obj/structure/toilet/attackby(obj/item/I, mob/living/user, params) + add_fingerprint(user) if(istype(I, /obj/item/crowbar)) to_chat(user, "You start to [cistern ? "replace the lid on the cistern" : "lift the lid off the cistern"]...") playsound(loc, 'sound/effects/stonedoor_openclose.ogg', 50, 1) @@ -80,7 +93,9 @@ user.visible_message("[user] [cistern ? "replaces the lid on the cistern" : "lifts the lid off the cistern"]!", "You [cistern ? "replace the lid on the cistern" : "lift the lid off the cistern"]!", "You hear grinding porcelain.") cistern = !cistern update_icon() - + else if(I.tool_behaviour == TOOL_WRENCH && !(flags_1&NODECONSTRUCT_1)) + I.play_tool_sound(src) + deconstruct() else if(cistern) if(user.a_intent != INTENT_HARM) if(I.w_class > WEIGHT_CLASS_NORMAL) @@ -95,6 +110,10 @@ w_items += I.w_class to_chat(user, "You carefully place [I] into the cistern.") + if(istype(I, /obj/item/reagent_containers/food/snacks/cube)) + var/obj/item/reagent_containers/food/snacks/cube/cube = I + cube.Expand() + return else if(istype(I, /obj/item/reagent_containers)) if (!open) return @@ -130,6 +149,11 @@ /obj/structure/toilet/secret/prison secret_type = /obj/effect/spawner/lootdrop/prison_loot_toilet +/obj/structure/toilet/greyscale + + material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR + buildstacktype = null + /obj/structure/urinal name = "urinal" desc = "The HU-452, an experimental urinal. Comes complete with experimental urinal cake." @@ -459,6 +483,8 @@ anchored = TRUE var/busy = FALSE //Something's being washed at the moment var/dispensedreagent = /datum/reagent/water // for whenever plumbing happens + var/buildstacktype = /obj/item/stack/sheet/metal + var/buildstackamount = 1 /obj/structure/sink/attack_hand(mob/living/user) . = ..() @@ -537,6 +563,11 @@ playsound(loc, 'sound/effects/slosh.ogg', 25, 1) return + if(O.tool_behaviour == TOOL_WRENCH && !(flags_1&NODECONSTRUCT_1)) + O.play_tool_sound(src) + deconstruct() + return + if(istype(O, /obj/item/stack/medical/gauze)) var/obj/item/stack/medical/gauze/G = O new /obj/item/reagent_containers/rag(src.loc) @@ -568,9 +599,18 @@ else return ..() -/obj/structure/sink/deconstruct(disassembled = TRUE) - new /obj/item/stack/sheet/metal (loc, 3) - qdel(src) +/obj/structure/sink/deconstruct() + if(!(flags_1 & NODECONSTRUCT_1)) + drop_materials() + ..() + +/obj/structure/sink/proc/drop_materials() + if(buildstacktype) + new buildstacktype(loc,buildstackamount) + else + for(var/i in custom_materials) + var/datum/material/M = i + new M.sheet_type(loc, FLOOR(custom_materials[M] / MINERAL_MATERIAL_AMOUNT, 1)) /obj/structure/sink/kitchen name = "kitchen sink" @@ -655,6 +695,11 @@ icon_state = "puddle" resistance_flags = UNACIDABLE +/obj/structure/sink/greyscale + icon_state = "sink_greyscale" + material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR + buildstacktype = null + //ATTACK HAND IGNORING PARENT RETURN VALUE /obj/structure/sink/puddle/attack_hand(mob/M) icon_state = "puddle-splash" @@ -669,6 +714,10 @@ /obj/structure/sink/puddle/deconstruct(disassembled = TRUE) qdel(src) +/obj/structure/sink/greyscale + material_flags = MATERIAL_ADD_PREFIX | MATERIAL_COLOR + buildstacktype = null + //Shower Curtains// //Defines used are pre-existing in layers.dm// diff --git a/code/game/turfs/simulated/floor/fancy_floor.dm b/code/game/turfs/simulated/floor/fancy_floor.dm index c9b429cecc..06cd38a4c3 100644 --- a/code/game/turfs/simulated/floor/fancy_floor.dm +++ b/code/game/turfs/simulated/floor/fancy_floor.dm @@ -11,6 +11,7 @@ desc = "Stylish dark wood." icon_state = "wood" floor_tile = /obj/item/stack/tile/wood + custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 0.25) broken_states = list("wood-broken", "wood-broken2", "wood-broken3", "wood-broken4", "wood-broken5", "wood-broken6", "wood-broken7") footstep = FOOTSTEP_WOOD barefootstep = FOOTSTEP_WOOD_BAREFOOT diff --git a/code/game/turfs/simulated/minerals.dm b/code/game/turfs/simulated/minerals.dm index 7d476d559e..048394b942 100644 --- a/code/game/turfs/simulated/minerals.dm +++ b/code/game/turfs/simulated/minerals.dm @@ -832,7 +832,7 @@ initial_gas_mix = OPENTURF_DEFAULT_ATMOS defer_change = TRUE - + /turf/closed/mineral/gibtonite/ice environment_type = "snow_cavern" icon_state = "icerock_Gibtonite" @@ -846,3 +846,55 @@ turf_type = /turf/open/floor/plating/asteroid/snow/ice/icemoon baseturfs = /turf/open/floor/plating/asteroid/snow/ice/icemoon initial_gas_mix = ICEMOON_DEFAULT_ATMOS + +/turf/closed/mineral/strong + name = "Very strong rock" + desc = "Seems to be stronger than the other rocks in the area. Only a master of mining techniques could destroy this." + environment_type = "basalt" + turf_type = /turf/open/floor/plating/asteroid/basalt/lava_land_surface + baseturfs = /turf/open/floor/plating/asteroid/basalt/lava_land_surface + initial_gas_mix = LAVALAND_DEFAULT_ATMOS + defer_change = 1 + smooth_icon = 'icons/turf/walls/rock_wall.dmi' + +/* +/turf/closed/mineral/strong/attackby(obj/item/I, mob/user, params) + if(!ishuman(user)) + to_chat(usr, "Only a more advanced species could break a rock such as this one!") + return FALSE + var/mob/living/carbon/human/H = user + if(H.mind.get_skill_level(/datum/skill/mining) >= SKILL_LEVEL_MASTER) + . = ..() + else + to_chat(usr, "The rock seems to be too strong to destroy. Maybe I can break it once I become a master miner.") +*/ + +/turf/closed/mineral/strong/gets_drilled(mob/user) + if(!ishuman(user)) + return // see attackby + /* + var/mob/living/carbon/human/H = user + if(!(H.mind.get_skill_level(/datum/skill/mining) >= SKILL_LEVEL_MASTER)) + return + */ + drop_ores() +// H.client.give_award(/datum/award/achievement/skill/legendary_miner, H) + var/flags = NONE + if(defer_change) // TODO: make the defer change var a var for any changeturf flag + flags = CHANGETURF_DEFER_CHANGE + ScrapeAway(flags=flags) + addtimer(CALLBACK(src, .proc/AfterChange), 1, TIMER_UNIQUE) + playsound(src, 'sound/effects/break_stone.ogg', 50, TRUE) //beautiful destruction +// H.mind.adjust_experience(/datum/skill/mining, 100) //yay! + +/turf/closed/mineral/strong/proc/drop_ores() + if(prob(10)) + new /obj/item/stack/sheet/mineral/mythril(src, 5) + else + new /obj/item/stack/sheet/mineral/adamantine(src, 5) + +/turf/closed/mineral/strong/acid_melt() + return + +/turf/closed/mineral/strong/ex_act(severity, target) + return diff --git a/code/modules/client/client_colour.dm b/code/modules/client/client_colour.dm index 22b15ea868..d89598f6cb 100644 --- a/code/modules/client/client_colour.dm +++ b/code/modules/client/client_colour.dm @@ -17,11 +17,6 @@ //eg: "Bloody screen" > "goggles colour" as the former is much more important -/mob - var/list/client_colours = list() - - - /* Adds an instance of colour_type to the mob's client_colours list colour_type - a typepath (subtyped from /datum/client_colour) @@ -113,4 +108,4 @@ priority = INFINITY //we can't see colors anyway! /datum/client_colour/monochrome/trance - priority = 1 \ No newline at end of file + priority = 1 diff --git a/code/modules/client/client_defines.dm b/code/modules/client/client_defines.dm index 1659a4ff37..7d87a82afb 100644 --- a/code/modules/client/client_defines.dm +++ b/code/modules/client/client_defines.dm @@ -99,7 +99,37 @@ /// custom movement keys for this client var/list/movement_keys = list() + ///Autoclick list of two elements, first being the clicked thing, second being the parameters. + var/list/atom/selected_target[2] + ///Autoclick variable referencing the associated item. + var/obj/item/active_mousedown_item = null + ///Used in MouseDrag to preserve the original mouse click parameters + var/mouseParams = "" + ///Used in MouseDrag to preserve the last mouse-entered location. + var/mouseLocation = null + ///Used in MouseDrag to preserve the last mouse-entered object. + var/mouseObject = null + var/mouseControlObject = null + //Middle-mouse-button click dragtime control for aimbot exploit detection. + var/middragtime = 0 + //Middle-mouse-button clicked object control for aimbot exploit detection. + var/atom/middragatom + /// Messages currently seen by this client var/list/seen_messages ///When was the last time we warned them about not cryoing without an ahelp, set to -5 minutes so that rounstart cryo still warns - var/cryo_warned = -5 MINUTES \ No newline at end of file + var/cryo_warned = -5 MINUTES + + var/list/parallax_layers + var/list/parallax_layers_cached + var/atom/movable/movingmob + var/turf/previous_turf + ///world.time of when we can state animate()ing parallax again + var/dont_animate_parallax + ///world.time of last parallax update + var/last_parallax_shift + ///ds between parallax updates + var/parallax_throttle = 0 + var/parallax_movedir = 0 + var/parallax_layers_max = 3 + var/parallax_animate_timer diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index ce7ef441c4..d575a53afa 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -789,9 +789,9 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) log_game("[key_name(src)] is using the middle click aimbot exploit") message_admins("[ADMIN_LOOKUPFLW(src)] [ADMIN_KICK(usr)] is using the middle click aimbot exploit") add_system_note("aimbot", "Is using the middle click aimbot exploit") - log_click(object, location, control, params, src, "lockout (spam - minute ab c [ab] s [middragtime])") + log_click(object, location, control, params, src, "lockout (spam - minute ab c [ab] s [middragtime])", TRUE) else - log_click(object, location, control, params, src, "lockout (spam - minute)") + log_click(object, location, control, params, src, "lockout (spam - minute)", TRUE) log_game("[key_name(src)] Has hit the per-minute click limit of [mcl] clicks in a given game minute") message_admins("[ADMIN_LOOKUPFLW(src)] [ADMIN_KICK(usr)] Has hit the per-minute click limit of [mcl] clicks in a given game minute") to_chat(src, "[msg]") @@ -811,7 +811,7 @@ GLOBAL_LIST_EMPTY(external_rsc_urls) return if(ab) //Citadel edit, things with stuff. - log_click(object, location, control, params, src, "dropped (ab c [ab] s [middragtime])") + log_click(object, location, control, params, src, "dropped (ab c [ab] s [middragtime])", TRUE) return if(prefs.log_clicks) diff --git a/code/modules/clothing/glasses/phantomthief.dm b/code/modules/clothing/glasses/phantomthief.dm index fecf660450..6d209ec695 100644 --- a/code/modules/clothing/glasses/phantomthief.dm +++ b/code/modules/clothing/glasses/phantomthief.dm @@ -24,7 +24,7 @@ . += "[DisplayTimeText(nextadrenalinepop - world.time)] left before the adrenaline injector can be used again." /obj/item/clothing/glasses/phantomthief/syndicate/proc/injectadrenaline(mob/living/user, was_forced = FALSE) - if(user.combat_flags & COMBAT_FLAG_COMBAT_TOGGLED && world.time >= nextadrenalinepop) + if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_TOGGLED) && world.time >= nextadrenalinepop) nextadrenalinepop = world.time + 5 MINUTES user.reagents.add_reagent(/datum/reagent/syndicateadrenals, 5) user.playsound_local(user, 'sound/misc/adrenalinject.ogg', 100, 0, pressure_affected = FALSE) diff --git a/code/modules/clothing/masks/gasmask.dm b/code/modules/clothing/masks/gasmask.dm index 90b3d7d86b..2778c6abeb 100644 --- a/code/modules/clothing/masks/gasmask.dm +++ b/code/modules/clothing/masks/gasmask.dm @@ -198,6 +198,7 @@ desc = "A creepy wooden mask. Surprisingly expressive for a poorly carved bit of wood." icon_state = "tiki_eyebrow" item_state = "tiki_eyebrow" + custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 1.25) resistance_flags = FLAMMABLE max_integrity = 100 actions_types = list(/datum/action/item_action/adjust) diff --git a/code/modules/clothing/shoes/miscellaneous.dm b/code/modules/clothing/shoes/miscellaneous.dm index 9c6c81372a..b197f4cf38 100644 --- a/code/modules/clothing/shoes/miscellaneous.dm +++ b/code/modules/clothing/shoes/miscellaneous.dm @@ -45,6 +45,7 @@ desc = "A pair of rather plain wooden sandals." name = "sandals" icon_state = "wizard" + custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 0.5) strip_delay = 50 equip_delay_other = 50 permeability_coefficient = 0.9 diff --git a/code/modules/clothing/spacesuits/miscellaneous.dm b/code/modules/clothing/spacesuits/miscellaneous.dm index f4fd3f7bf3..3d55e569dc 100644 --- a/code/modules/clothing/spacesuits/miscellaneous.dm +++ b/code/modules/clothing/spacesuits/miscellaneous.dm @@ -444,7 +444,6 @@ Contains: desc = "Powerful wards are built into this hardsuit, protecting the user from all manner of paranormal threats. Alas, this one looks pretty worn out and rusted." armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60) slowdown = 0.8 - obj_flags = IMMUTABLE_SLOW //rest in peace rusty joints. helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/inquisitor/old charges = 12 @@ -470,7 +469,6 @@ Contains: desc = "Voices echo from the hardsuit, driving the user insane. This one is pretty battle-worn, but still fearsome." armor = list("melee" = 55, "bullet" = 40, "laser" = 40, "energy" = 40, "bomb" = 40, "bio" = 80, "rad" = 80, "fire" = 60, "acid" = 60) slowdown = 0.8 - obj_flags = IMMUTABLE_SLOW //rest in peace rusty joints. helmettype = /obj/item/clothing/head/helmet/space/hardsuit/ert/paranormal/inquisitor/old charges = 6 diff --git a/code/modules/clothing/suits/wiz_robe.dm b/code/modules/clothing/suits/wiz_robe.dm index e392a6b2d1..047dc7b7a3 100644 --- a/code/modules/clothing/suits/wiz_robe.dm +++ b/code/modules/clothing/suits/wiz_robe.dm @@ -165,31 +165,134 @@ var/robe_charge = TRUE actions_types = list(/datum/action/item_action/stickmen) +/obj/item/clothing/suit/wizrobe/paper/item_action_slot_check(slot, mob/user, datum/action/A) + if(A.type == /datum/action/item_action/stickmen && slot != SLOT_WEAR_SUIT) + return FALSE + return ..() -/obj/item/clothing/suit/wizrobe/paper/ui_action_click(mob/user, action) - stickmen() +//Stickmemes. VV-friendly. +/datum/action/item_action/stickmen + name = "Summon Stick Minions" + desc = "Allows you to summon faithful stickmen allies to aide you in battle." + icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' + button_icon_state = "art_summon" + var/ready = TRUE + var/list/summoned_stickmen = list() + var/summoned_mob_path = /mob/living/simple_animal/hostile/stickman //Must be an hostile animal path. + var/max_stickmen = 8 + var/cooldown = 3 SECONDS + var/list/book_of_grudges = list() + +/datum/action/item_action/stickmen/New(Target) + ..() + if(isitem(Target)) + RegisterSignal(Target, COMSIG_PARENT_EXAMINE, .proc/give_infos) + +/datum/action/item_action/stickmen/Destroy() + for(var/A in summoned_stickmen) + var/mob/living/simple_animal/hostile/S = A + if(S.client) + to_chat(S, "A dizzying sensation strikes you as the comglomerate of pencil lines you call \ + your body crumbles under the pressure of an invisible eraser, soon to join bilions discarded sketches. \ + It seems whatever was keeping you in this realm has come to an end, like all things.") + animate(S, alpha = 0, time = 5 SECONDS) + QDEL_IN(S, 5 SECONDS) + return ..() + +/datum/action/item_action/stickmen/proc/give_infos(atom/source, mob/user, list/examine_list) + examine_list += "Making sure you are properly wearing or holding it, \ + point at whatever you want to rally your minions to its position." + examine_list += "While on harm intent, pointed mobs (minus you and the minions) \ + will also be marked as foes for your minions to attack for the next 2 minutes." + +/datum/action/item_action/stickmen/Grant(mob/M) + . = ..() + if(owner) + RegisterSignal(M, COMSIG_MOB_POINTED, .proc/rally) + if(book_of_grudges[M]) //Stop attacking your new master. + book_of_grudges -= M + for(var/A in summoned_stickmen) + var/mob/living/simple_animal/hostile/S = A + if(!S.mind) + S.LoseTarget() -/obj/item/clothing/suit/wizrobe/paper/verb/stickmen() - set category = "Object" - set name = "Summon Stick Minions" - set src in usr - if(!isliving(usr)) +/datum/action/item_action/stickmen/Remove(mob/M) + . = ..() + UnregisterSignal(M, COMSIG_MOB_POINTED) + +/datum/action/item_action/stickmen/Trigger() + . = ..() + if(!.) return - if(!robe_charge) - to_chat(usr, "\The robe's internal magic supply is still recharging!") + if(!ready) + to_chat(owner, "[src]'s internal magic supply is still recharging!") + return FALSE + var/summon = TRUE + if(length(summoned_stickmen) >= max_stickmen) + var/mob/living/simple_animal/hostile/S = popleft(summoned_stickmen) + if(!S.client) + qdel(S) + else + S.forceMove(owner.drop_location()) + S.revive(TRUE) + summoned_stickmen[S] = TRUE + summon = FALSE + + owner.say("Rise, my creation! Off your page into this realm!", forced = "stickman summoning") + playsound(owner, 'sound/magic/summon_magic.ogg', 50, 1, 1) + if(summon) + var/mob/living/simple_animal/hostile/S = new summoned_mob_path (get_turf(usr)) + S.faction = owner.faction + S.foes = book_of_grudges + RegisterSignal(S, COMSIG_PARENT_QDELETING, .proc/remove_from_list) + ready = FALSE + addtimer(CALLBACK(src, .proc/ready_again), cooldown) + +/datum/action/item_action/stickmen/proc/remove_from_list(datum/source, forced) + summoned_stickmen -= source + +/datum/action/item_action/stickmen/proc/ready_again() + ready = TRUE + if(owner) + to_chat(owner, "[src] hums, its internal magic supply restored.") + +/** + * Rallies your army of stickmen to whichever target the user is pointing. + * Should the user be on harm intent and the target be a living mob that's not the user or a fellow stickman, + * said target will be added to a list of foes which the stickmen will gladly dispose regardless of faction. + * This is designed so stickmen will move toward whatever you point at even when you don't want to, that's the downside. + */ +/datum/action/item_action/stickmen/proc/rally(mob/source, atom/A) + var/turf/T = get_turf(A) + var/list/surrounding_turfs = block(locate(T.x - 1, T.y - 1, T.z), locate(T.x + 1, T.y + 1, T.z)) + if(!surrounding_turfs.len) return + if(source.a_intent == INTENT_HARM && A != source && !summoned_stickmen[A]) + var/mob/living/L + if(isliving(A)) //Gettem boys! + L = A + else if(ismecha(A)) + var/obj/mecha/M = A + L = M.occupant + if(L && L.stat != DEAD && !HAS_TRAIT(L, TRAIT_DEATHCOMA)) //Taking revenge on the deads would be proposterous. + addtimer(CALLBACK(src, .proc/clear_grudge, L), 2 MINUTES, TIMER_OVERRIDE|TIMER_UNIQUE) + if(!book_of_grudges[L]) + RegisterSignal(L, list(COMSIG_PARENT_QDELETING, COMSIG_MOB_DEATH), .proc/grudge_settled) + book_of_grudges[L] = TRUE + for(var/k in summoned_stickmen) //Shamelessly copied from the blob rally power + var/mob/living/simple_animal/hostile/S = k + if(!S.mind && isturf(S.loc) && get_dist(S, T) <= 10) + S.LoseTarget() + S.Goto(pick(surrounding_turfs), S.move_to_delay) - usr.say("Rise, my creation! Off your page into this realm!", forced = "stickman summoning") - playsound(src.loc, 'sound/magic/summon_magic.ogg', 50, 1, 1) - var/mob/living/M = new /mob/living/simple_animal/hostile/stickman(get_turf(usr)) - var/list/factions = usr.faction - M.faction = factions - src.robe_charge = FALSE - sleep(30) - src.robe_charge = TRUE - to_chat(usr, "\The robe hums, its internal magic supply restored.") +/datum/action/item_action/stickmen/proc/clear_grudge(mob/living/L) + if(!QDELETED(L)) + book_of_grudges -= L +/datum/action/item_action/stickmen/proc/grudge_settled(mob/living/L) + UnregisterSignal(L, list(COMSIG_PARENT_QDELETING, COMSIG_MOB_DEATH)) + book_of_grudges -= L //Shielded Armour diff --git a/code/modules/keybindings/keybind/combat.dm b/code/modules/keybindings/keybind/combat.dm index 1c68297c27..73739215b8 100644 --- a/code/modules/keybindings/keybind/combat.dm +++ b/code/modules/keybindings/keybind/combat.dm @@ -5,12 +5,8 @@ category = CATEGORY_COMBAT description = "Toggles whether or not you're in combat mode." -/datum/keybinding/living/toggle_combat_mode/can_use(client/user) - return iscarbon(user.mob) // for now, only carbons should be using combat mode, although all livings have combat mode implemented. - /datum/keybinding/living/toggle_combat_mode/down(client/user) - var/mob/living/carbon/C = user.mob - C.user_toggle_intentional_combat_mode() + SEND_SIGNAL(user.mob, COMSIG_TOGGLE_COMBAT_MODE) return TRUE /datum/keybinding/living/active_block diff --git a/code/modules/mapping/mapping_helpers/network_builder/_network_builder.dm b/code/modules/mapping/mapping_helpers/network_builder/_network_builder.dm index 78a835cffa..69a75148dd 100644 --- a/code/modules/mapping/mapping_helpers/network_builder/_network_builder.dm +++ b/code/modules/mapping/mapping_helpers/network_builder/_network_builder.dm @@ -12,7 +12,6 @@ /obj/effect/mapping_helpers/network_builder/Initialize(mapload) . = ..() - to_chat(world, "DEBUG: Initializing [COORD(src)]") var/conflict = check_duplicates() if(conflict) stack_trace("WARNING: [type] network building helper found check_duplicates() conflict [conflict] in its location.!") @@ -27,7 +26,6 @@ /// How this works: On LateInitialize, detect all directions that this should be applicable to, and do what it needs to do, and then inform all network builders in said directions that it's been around since it won't be around afterwards. /obj/effect/mapping_helpers/network_builder/LateInitialize() - to_chat(world, "DEBUG: LateInitializing [COORD(src)]") scan_directions() build_network() if(!custom_spawned) diff --git a/code/modules/mining/equipment/lazarus_injector.dm b/code/modules/mining/equipment/lazarus_injector.dm index f8b155cb9f..db826fdb49 100644 --- a/code/modules/mining/equipment/lazarus_injector.dm +++ b/code/modules/mining/equipment/lazarus_injector.dm @@ -33,7 +33,7 @@ if(malfunctioning) H.faction |= list("lazarus", "[REF(user)]") H.robust_searching = 1 - H.friends += user + H.friends[user]++ H.attack_same = 1 log_game("[key_name(user)] has revived hostile mob [key_name(target)] with a malfunctioning lazarus injector") else diff --git a/code/modules/mining/equipment/mining_tools.dm b/code/modules/mining/equipment/mining_tools.dm index ce76ad04fc..50a3dec9dd 100644 --- a/code/modules/mining/equipment/mining_tools.dm +++ b/code/modules/mining/equipment/mining_tools.dm @@ -168,3 +168,17 @@ throwforce = 7 custom_materials = list(/datum/material/iron=50) w_class = WEIGHT_CLASS_SMALL + +/obj/item/shovel/serrated + name = "serrated bone shovel" + desc = "A wicked tool that cleaves through dirt just as easily as it does flesh. The design was styled after ancient lavaland tribal designs." + icon_state = "shovel_bone" + item_state = "shovel_bone" + lefthand_file = 'icons/mob/inhands/equipment/mining_lefthand.dmi' + righthand_file = 'icons/mob/inhands/equipment/mining_righthand.dmi' + force = 15 + throwforce = 12 + w_class = WEIGHT_CLASS_NORMAL + toolspeed = 0.7 + attack_verb = list("slashed", "impaled", "stabbed", "sliced") + sharpness = IS_SHARP diff --git a/code/modules/mining/equipment/survival_pod.dm b/code/modules/mining/equipment/survival_pod.dm index bbab74689c..ab0356aa66 100644 --- a/code/modules/mining/equipment/survival_pod.dm +++ b/code/modules/mining/equipment/survival_pod.dm @@ -270,6 +270,7 @@ desc = "A sign of relief for weary miners, and a warning for would-be competitors to Nanotrasen's mining claims." icon = 'icons/turf/walls/survival_pod_walls.dmi' icon_state = "ntpod" + buildable_sign = FALSE /obj/structure/sign/mining/survival name = "shelter sign" diff --git a/code/modules/mob/living/carbon/alien/larva/life.dm b/code/modules/mob/living/carbon/alien/larva/life.dm index 00d929a1e0..a4da38c4da 100644 --- a/code/modules/mob/living/carbon/alien/larva/life.dm +++ b/code/modules/mob/living/carbon/alien/larva/life.dm @@ -24,12 +24,12 @@ if(!eye_blind) blind_eyes(1) update_mobility() - else - if(stat == UNCONSCIOUS) - stat = CONSCIOUS - if(!(combat_flags & COMBAT_FLAG_HARD_STAMCRIT)) - set_resting(FALSE, TRUE) + else if(stat == UNCONSCIOUS) + stat = CONSCIOUS + if(!(combat_flags & COMBAT_FLAG_HARD_STAMCRIT)) + set_resting(FALSE, TRUE) + if(eye_blind <= 1) adjust_blindness(-1) - update_mobility() + update_mobility() update_damage_hud() update_health_hud() diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index a307433660..e4ec902654 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -442,14 +442,14 @@ //dropItemToGround(I) CIT CHANGE - makes it so the item doesn't drop if the modifier rolls above 100 - var/modifier = 0 + var/modifier = 50 if(HAS_TRAIT(src, TRAIT_CLUMSY)) modifier -= 40 //Clumsy people are more likely to hit themselves -Honk! //CIT CHANGES START HERE - else if(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) - modifier += 50 + else if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) + modifier -= 50 if(modifier < 100) dropItemToGround(I) @@ -827,16 +827,17 @@ return if(IsUnconscious() || IsSleeping() || getOxyLoss() > 50 || (HAS_TRAIT(src, TRAIT_DEATHCOMA)) || (health <= HEALTH_THRESHOLD_FULLCRIT && !HAS_TRAIT(src, TRAIT_NOHARDCRIT))) stat = UNCONSCIOUS - disable_intentional_combat_mode(FALSE, FALSE) + SEND_SIGNAL(src, COMSIG_DISABLE_COMBAT_MODE) if(!eye_blind) blind_eyes(1) else if(health <= crit_threshold && !HAS_TRAIT(src, TRAIT_NOSOFTCRIT)) stat = SOFT_CRIT - disable_intentional_combat_mode(FALSE, FALSE) + SEND_SIGNAL(src, COMSIG_DISABLE_COMBAT_MODE) else stat = CONSCIOUS - adjust_blindness(-1) + if(eye_blind <= 1) + adjust_blindness(-1) update_mobility() update_damage_hud() update_health_hud() @@ -1122,10 +1123,6 @@ if(mood.sanity < SANITY_UNSTABLE) return TRUE -/mob/living/carbon/transfer_ckey(mob/new_mob, send_signal = TRUE) - disable_intentional_combat_mode(TRUE, FALSE) - return ..() - /mob/living/carbon/can_see_reagents() . = ..() if(.) //No need to run through all of this if it's already true. diff --git a/code/modules/mob/living/carbon/carbon_combat.dm b/code/modules/mob/living/carbon/carbon_combat.dm deleted file mode 100644 index f43d850401..0000000000 --- a/code/modules/mob/living/carbon/carbon_combat.dm +++ /dev/null @@ -1,6 +0,0 @@ -/mob/living/carbon/enable_intentional_combat_mode() - . = ..() - if(.) - if(voremode) - toggle_vore_mode() - diff --git a/code/modules/mob/living/carbon/death.dm b/code/modules/mob/living/carbon/death.dm index 4cf82bb0b4..c3e849efa6 100644 --- a/code/modules/mob/living/carbon/death.dm +++ b/code/modules/mob/living/carbon/death.dm @@ -8,8 +8,6 @@ if(!gibbed) emote("deathgasp") - disable_intentional_combat_mode(TRUE, FALSE) - . = ..() for(var/T in get_traumas()) @@ -62,7 +60,3 @@ var/obj/item/bodypart/BP = X BP.drop_limb() BP.throw_at(get_edge_target_turf(src,pick(GLOB.alldirs)),rand(1,3),5) - -/mob/living/carbon/ghostize(can_reenter_corpse = TRUE, special = FALSE, penalize = FALSE, voluntary = FALSE) - disable_intentional_combat_mode(TRUE, FALSE) - return ..() diff --git a/code/modules/mob/living/carbon/examine.dm b/code/modules/mob/living/carbon/examine.dm index 1ee3369701..8dbfba47b1 100644 --- a/code/modules/mob/living/carbon/examine.dm +++ b/code/modules/mob/living/carbon/examine.dm @@ -90,7 +90,7 @@ if(digitalcamo) . += "[t_He] [t_is] moving [t_his] body in an unnatural and blatantly unsimian manner." - if(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) + if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) . += "[t_He] [t_is] visibly tense[CHECK_MOBILITY(src, MOBILITY_STAND) ? "." : ", and [t_is] standing in combative stance."]" var/trait_exam = common_trait_examine() diff --git a/code/modules/mob/living/carbon/human/human.dm b/code/modules/mob/living/carbon/human/human.dm index 007bca3518..de703b8ad4 100644 --- a/code/modules/mob/living/carbon/human/human.dm +++ b/code/modules/mob/living/carbon/human/human.dm @@ -39,6 +39,7 @@ . = ..() if(!CONFIG_GET(flag/disable_human_mood)) AddComponent(/datum/component/mood) + AddComponent(/datum/component/combat_mode) AddElement(/datum/element/flavor_text/carbon, _name = "Flavor Text", _save_key = "flavor_text") AddElement(/datum/element/flavor_text, "", "Temporary Flavor Text", "This should be used only for things pertaining to the current round!") AddElement(/datum/element/flavor_text, _name = "OOC Notes", _addendum = "Put information on ERP/vore/lewd-related preferences here. THIS SHOULD NOT CONTAIN REGULAR FLAVORTEXT!!", _always_show = TRUE, _save_key = "ooc_notes", _examine_no_preview = TRUE) diff --git a/code/modules/mob/living/carbon/human/human_movement.dm b/code/modules/mob/living/carbon/human/human_movement.dm index 733f792109..63ca3f372e 100644 --- a/code/modules/mob/living/carbon/human/human_movement.dm +++ b/code/modules/mob/living/carbon/human/human_movement.dm @@ -16,8 +16,6 @@ if(!SSI) SSI = CONFIG_GET_ENTRY(number/movedelay/sprint_speed_increase) . -= SSI.config_entry_value - if(wrongdirmovedelay) - . += 1 if (m_intent == MOVE_INTENT_WALK && HAS_TRAIT(src, TRAIT_SPEEDY_STEP)) . -= 1.5 diff --git a/code/modules/mob/living/carbon/human/species.dm b/code/modules/mob/living/carbon/human/species.dm index 6f022bdfec..946ecca64b 100644 --- a/code/modules/mob/living/carbon/human/species.dm +++ b/code/modules/mob/living/carbon/human/species.dm @@ -1473,11 +1473,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) var/punchedbrute = target.getBruteLoss() //CITADEL CHANGES - makes resting and disabled combat mode reduce punch damage, makes being out of combat mode result in you taking more damage - if(!(target.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + if(!SEND_SIGNAL(target, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) damage *= 1.5 if(!CHECK_MOBILITY(user, MOBILITY_STAND)) damage *= 0.5 - if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) damage *= 0.25 //END OF CITADEL CHANGES @@ -1625,11 +1625,11 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) log_combat(user, target, "disarmed out of grab from") return var/randn = rand(1, 100) - if(!(target.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) // CITADEL CHANGE + if(SEND_SIGNAL(target, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) // CITADEL CHANGE randn += -10 //CITADEL CHANGE - being out of combat mode makes it easier for you to get disarmed if(!CHECK_MOBILITY(user, MOBILITY_STAND)) //CITADEL CHANGE randn += 100 //CITADEL CHANGE - No kosher disarming if you're resting - if(!(target.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) //CITADEL CHANGE + if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) //CITADEL CHANGE randn += 25 //CITADEL CHANGE - Makes it harder to disarm outside of combat mode if(user.pulling == target) randn -= 20 //If you have the time to get someone in a grab, you should have a greater chance at snatching the thing in their hand. Will be made completely obsolete by the grab rework but i've got a poor track record for releasing big projects on time so w/e i guess @@ -1830,7 +1830,7 @@ GLOBAL_LIST_EMPTY(roundstart_race_names) if(IS_STAMCRIT(user)) to_chat(user, "You're too exhausted for that.") return - if(!(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) to_chat(user, "You need combat mode to be active to that!") return if(user.IsKnockdown() || user.IsParalyzed() || user.IsStun()) diff --git a/code/modules/mob/living/carbon/human/species_types/dwarves.dm b/code/modules/mob/living/carbon/human/species_types/dwarves.dm index dfeff24141..bc5f198b4d 100644 --- a/code/modules/mob/living/carbon/human/species_types/dwarves.dm +++ b/code/modules/mob/living/carbon/human/species_types/dwarves.dm @@ -6,8 +6,8 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) // name = "Dwarf" id = "dwarf" //Also called Homo sapiens pumilionis default_color = "FFFFFF" - species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS,NO_UNDERWEAR,TRAIT_DWARF) - inherent_traits = list() + species_traits = list(EYECOLOR,HAIR,FACEHAIR,LIPS) + inherent_traits = list(TRAIT_DWARF,TRAIT_SNOB) limbs_id = "human" use_skintones = USE_SKINTONES_GRAYSCALE_CUSTOM say_mod = "bellows" //high energy, EXTRA BIOLOGICAL FUEL @@ -87,9 +87,7 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) // var/heal_rate = 0.5 //The rate they heal damages over 400 alcohol stored. Default is 0.5 so we times 3 since 3 seconds. var/alcohol_rate = 0.25 //The rate the alcohol ticks down per each iteration of dwarf_eth_ticker completing. //These count in on_life ticks which should be 2 seconds per every increment of 1 in a perfect world. - var/dwarf_filth_ticker = 0 //Currently set =< 4, that means this will fire the proc around every 4-8 seconds. var/dwarf_eth_ticker = 0 //Currently set =< 1, that means this will fire the proc around every 2 seconds - var/last_filth_spam var/last_alcohol_spam /obj/item/organ/dwarfgland/prepare_eat() @@ -100,64 +98,10 @@ GLOBAL_LIST_INIT(dwarf_last, world.file2list("strings/names/dwarf_last.txt")) // /obj/item/organ/dwarfgland/on_life() //Primary loop to hook into to start delayed loops for other loops.. . = ..() if(owner && owner.stat != DEAD) - dwarf_cycle_ticker() - -//Handles the delayed tick cycle by just adding on increments per each on_life() tick -/obj/item/organ/dwarfgland/proc/dwarf_cycle_ticker() - dwarf_eth_ticker++ - dwarf_filth_ticker++ - - if(dwarf_filth_ticker >= 4) //Should be around 4-8 seconds since a tick is around 2 seconds. - dwarf_filth_cycle() //On_life will adjust regarding other factors, so we are along for the ride. - dwarf_filth_ticker = 0 //We set the ticker back to 0 to go again. - if(dwarf_eth_ticker >= 1) //Alcohol reagent check should be around 2 seconds, since a tick is around 2 seconds. - dwarf_eth_cycle() - dwarf_eth_ticker = 0 - -//If this still friggin uses too much CPU, I'll make a for view subsystem If I have to. -/obj/item/organ/dwarfgland/proc/dwarf_filth_cycle() - if(!owner?.client || !owner?.mind) - return - //Filth Reactions - Since miasma now exists - var/filth_counter = 0 //Holder for the filth check cycle, basically contains how much filth dwarf sees numerically. - for(var/fuck in owner.fov_view(7)) //hello byond for view loop. - if(istype(fuck, /mob/living/carbon/human)) - var/mob/living/carbon/human/H = fuck - if(H.stat == DEAD || (HAS_TRAIT(H, TRAIT_FAKEDEATH))) - filth_counter += 10 - if(istype(fuck, /obj/effect/decal/cleanable/blood)) - if(istype(fuck, /obj/effect/decal/cleanable/blood/gibs)) - filth_counter += 1 - else - filth_counter += 0.1 - if(istype(fuck,/obj/effect/decal/cleanable/vomit)) //They are disgusted by their own vomit too. - filth_counter += 10 //Dwarves could technically chainstun each other in a vomit tantrum spiral. - switch(filth_counter) - if(11 to 25) - if(last_filth_spam + 40 SECONDS < world.time) - to_chat(owner, "Someone should really clean up in here!") - last_filth_spam = world.time - if(26 to 50) - if(prob(6)) //And then the probability they vomit along with it. - to_chat(owner, "The stench makes you queasy.") - owner.vomit(10) //I think vomit should stay over a disgust adjustment. - if(51 to 75) - if(prob(9)) - to_chat(owner, "By Armok! You won't be able to keep alcohol down at all!") - owner.vomit(20) //Its more funny - if(76 to 100) - if(prob(11)) - to_chat(owner, "You can't live in such FILTH!") - owner.adjustToxLoss(10) //Now they start dying. - owner.vomit(20) - if(101 to INFINITY) //Now they will really start dying - if(last_filth_spam + 12 SECONDS < world.time) - to_chat(owner, " THERES TOO MUCH FILTH, OH GODS THE FILTH!") - last_filth_spam = world.time - if(prob(40)) - owner.adjustToxLoss(15) - owner.vomit(30) - CHECK_TICK //Check_tick right here, its motherfuckin magic. (To me at least) + dwarf_eth_ticker++ + if(dwarf_eth_ticker >= 1) //Alcohol reagent check should be around 2 seconds, since a tick is around 2 seconds. + dwarf_eth_cycle() + dwarf_eth_ticker = 0 //Handles the dwarf alcohol cycle tied to on_life, it ticks in dwarf_cycle_ticker. /obj/item/organ/dwarfgland/proc/dwarf_eth_cycle() diff --git a/code/modules/mob/living/carbon/life.dm b/code/modules/mob/living/carbon/life.dm index e85769ca12..4e5b033688 100644 --- a/code/modules/mob/living/carbon/life.dm +++ b/code/modules/mob/living/carbon/life.dm @@ -523,7 +523,7 @@ GLOBAL_LIST_INIT(ballmer_windows_me_msg, list("Yo man, what if, we like, uh, put //this updates all special effects: stun, sleeping, knockdown, druggy, stuttering, etc.. /mob/living/carbon/handle_status_effects() ..() - if(getStaminaLoss() && !(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) //CIT CHANGE - prevents stamina regen while combat mode is active + if(getStaminaLoss() && !SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) //CIT CHANGE - prevents stamina regen while combat mode is active adjustStaminaLoss(!CHECK_MOBILITY(src, MOBILITY_STAND) ? ((combat_flags & COMBAT_FLAG_HARD_STAMCRIT) ? -7.5 : -6) : -3)//CIT CHANGE - decreases adjuststaminaloss to stop stamina damage from being such a joke if(!(combat_flags & COMBAT_FLAG_HARD_STAMCRIT) && incomingstammult != 1) diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 502ebcbe5d..c1038fbb41 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -322,7 +322,7 @@ set_pull_offsets(M, state) /mob/living/proc/set_pull_offsets(mob/living/M, grab_state = GRAB_PASSIVE) - if(M.buckled || M.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) + if(M.buckled || SEND_SIGNAL(M, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) return //don't make them change direction or offset them if they're buckled into something or in combat mode. var/offset = 0 switch(grab_state) diff --git a/code/modules/mob/living/living_defines.dm b/code/modules/mob/living/living_defines.dm index f8abf94083..282dab79a8 100644 --- a/code/modules/mob/living/living_defines.dm +++ b/code/modules/mob/living/living_defines.dm @@ -122,7 +122,7 @@ //// CITADEL STATION COMBAT //// /// See __DEFINES/combat.dm - var/combat_flags = COMBAT_FLAGS_STAMSYSTEM_EXEMPT + var/combat_flags = COMBAT_FLAGS_SPRINT_EXEMPT /// Next world.time when we will show a visible message on entering combat mode voluntarily again. var/combatmessagecooldown = 0 diff --git a/code/modules/mob/living/silicon/silicon.dm b/code/modules/mob/living/silicon/silicon.dm index a4aeeb2ffc..0d0f7f9c97 100644 --- a/code/modules/mob/living/silicon/silicon.dm +++ b/code/modules/mob/living/silicon/silicon.dm @@ -15,8 +15,6 @@ speech_span = SPAN_ROBOT flags_1 = PREVENT_CONTENTS_EXPLOSION_1 | HEAR_1 vore_flags = NO_VORE - /// Enable sprint system but not stamina - combat_flags = COMBAT_FLAGS_STAMEXEMPT_YESSPRINT var/datum/ai_laws/laws = null//Now... THEY ALL CAN ALL HAVE LAWS var/last_lawchange_announce = 0 diff --git a/code/modules/mob/living/simple_animal/friendly/sloth.dm b/code/modules/mob/living/simple_animal/friendly/sloth.dm index 83fe42a7a4..df416047e2 100644 --- a/code/modules/mob/living/simple_animal/friendly/sloth.dm +++ b/code/modules/mob/living/simple_animal/friendly/sloth.dm @@ -27,7 +27,7 @@ glide_size = 2 footstep_type = FOOTSTEP_MOB_CLAW -/mob/living/simple_animal/pet/fox/ComponentInitialize() +/mob/living/simple_animal/pet/sloth/ComponentInitialize() . = ..() AddElement(/datum/element/mob_holder, "sloth") //finally oranges can be held diff --git a/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm b/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm index b1a4f05e8c..a2fc3aec88 100644 --- a/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm +++ b/code/modules/mob/living/simple_animal/hostile/bosses/boss.dm @@ -23,29 +23,21 @@ for(var/ab in boss_abilities) boss_abilities -= ab var/datum/action/boss/AB = new ab() - AB.boss = src AB.Grant(src) boss_abilities += AB atb.assign_abilities(boss_abilities) - /mob/living/simple_animal/hostile/boss/Destroy() - qdel(atb) - atb = null - for(var/ab in boss_abilities) - var/datum/action/boss/AB = ab - AB.boss = null - AB.Remove(src) - qdel(AB) - boss_abilities.Cut() + QDEL_NULL(atb) + QDEL_LIST(boss_abilities) return ..() - //Action datum for bosses //Override Trigger() as shown below to do things /datum/action/boss check_flags = AB_CHECK_CONSCIOUS //Incase the boss is given a player + required_mobility_flags = NONE var/boss_cost = 100 //Cost of usage for the boss' AI 1-100 var/usage_probability = 100 var/mob/living/simple_animal/hostile/boss/boss @@ -53,23 +45,34 @@ var/needs_target = TRUE //Does the boss need to have a target? (Only matters for the AI) var/say_when_triggered = "" //What does the boss Say() when the ability triggers? +/datum/action/boss/Destroy() + boss = null + return ..() + +/datum/action/boss/Grant(mob/M) + . = ..() + boss = owner + +/datum/action/boss/Remove(mob/M) + . = ..() + boss = null + /datum/action/boss/Trigger() . = ..() - if(.) - if(!istype(boss, boss_type)) - return 0 - if(!boss.atb) - return 0 - if(boss.atb.points < boss_cost) - return 0 - if(!boss.client) - if(needs_target && !boss.target) - return 0 - if(boss) - if(say_when_triggered) - boss.say(say_when_triggered, forced = "boss action") - if(!boss.atb.spend(boss_cost)) - return 0 + if(!.) + return + if(!istype(boss, boss_type)) + return FALSE + if(!boss.atb) + return FALSE + if(boss.atb.points < boss_cost) + return FALSE + if(!boss.client && needs_target && !boss.target) + return FALSE + if(!boss.atb.spend(boss_cost)) + return FALSE + if(say_when_triggered) + boss.say(say_when_triggered, forced = "boss action") //Example: /* @@ -83,7 +86,8 @@ /datum/boss_active_timed_battle var/list/abilities //a list of /datum/action/boss owned by a boss mob var/point_regen_delay = 5 - var/points = 50 //1-100, start with 50 so we can use some abilities but not insta-buttfug somebody + var/max_points = 100 + var/points = 50 //start with 50 so we can use some abilities but not insta-buttfug somebody var/next_point_time = 0 var/chance_to_hold_onto_points = 50 var/highest_cost = 0 @@ -108,22 +112,22 @@ /datum/boss_active_timed_battle/proc/spend(cost) if(cost <= points) points = max(0,points-cost) - return 1 - return 0 + return TRUE + return FALSE /datum/boss_active_timed_battle/proc/refund(cost) - points = min(points+cost, 100) + points = min(points+cost, max_points) /datum/boss_active_timed_battle/process() - if(world.time >= next_point_time) + if(world.time >= next_point_time && points < max_points) next_point_time = world.time + point_regen_delay - points = min(100, ++points) //has to be out of 100 + points = min(max_points, ++points) //has to be out of 100 if(abilities) chance_to_hold_onto_points = highest_cost*0.5 - if(points != 100 && prob(chance_to_hold_onto_points)) + if(points != max_points && prob(chance_to_hold_onto_points)) return //Let's save our points for a better ability (unless we're at max points, in which case we can't save anymore!) if(!boss.client) abilities = shuffle(abilities) @@ -135,5 +139,5 @@ /datum/boss_active_timed_battle/Destroy() abilities = null - SSobj.processing.Remove(src) + STOP_PROCESSING(SSobj, src) return ..() diff --git a/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm b/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm index aef3fb714d..4d45120a59 100644 --- a/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm +++ b/code/modules/mob/living/simple_animal/hostile/bosses/paperwizard.dm @@ -32,25 +32,47 @@ name = "Summon Minions" icon_icon = 'icons/mob/actions/actions_minor_antag.dmi' button_icon_state = "art_summon" - usage_probability = 40 + usage_probability = 20 boss_cost = 30 boss_type = /mob/living/simple_animal/hostile/boss/paper_wizard needs_target = FALSE say_when_triggered = "Rise, my creations! Jump off your pages and into this realm!" - var/static/summoned_minions = 0 + var/list/summoned_minions = list() + var/maximum_stickmen = 6 + var/stickmen_to_summon = 3 /datum/action/boss/wizard_summon_minions/Trigger() - if(summoned_minions <= 6 && ..()) - var/list/minions = list( - /mob/living/simple_animal/hostile/stickman, - /mob/living/simple_animal/hostile/stickman/ranged, - /mob/living/simple_animal/hostile/stickman/dog) - var/list/directions = GLOB.cardinals.Copy() - for(var/i in 1 to 3) - var/minions_chosen = pick_n_take(minions) - new minions_chosen (get_step(boss,pick_n_take(directions)), 1) - summoned_minions += 3; + . =..() + if(!.) + return + var/to_summon = stickmen_to_summon + var/current_len = length(summoned_minions) + if(current_len > maximum_stickmen - stickmen_to_summon) + for(var/a in (maximum_stickmen - stickmen_to_summon) to current_len) + var/mob/living/simple_animal/hostile/stickman/S = popleft(summoned_minions) + if(!S.client) + qdel(S) + else + S.forceMove(boss.drop_location()) + S.revive(TRUE) + summoned_minions += S + to_summon-- + var/static/list/minions = list( + /mob/living/simple_animal/hostile/stickman, + /mob/living/simple_animal/hostile/stickman/ranged, + /mob/living/simple_animal/hostile/stickman/dog) + + var/list/directions = GLOB.cardinals.Copy() + for(var/i in 1 to to_summon) + var/minions_chosen = pick(minions) + var/mob/living/simple_animal/hostile/stickman/S = new minions_chosen (get_step(boss,pick_n_take(directions)), 1) + S.faction = boss.faction + RegisterSignal(S, COMSIG_PARENT_QDELETING, .proc/remove_from_list) + summoned_minions += S + +/datum/action/boss/wizard_summon_minions/proc/remove_from_list(datum/source, forced) + summoned_minions -= source //Mimic Ability //Summons mimics of himself with magical papercraft @@ -66,28 +88,32 @@ say_when_triggered = "" /datum/action/boss/wizard_mimic/Trigger() - if(..()) - var/mob/living/target - if(!boss.client) //AI's target - target = boss.target - else //random mob - var/list/threats = boss.PossibleThreats() - if(threats.len) - target = pick(threats) - if(target) - var/mob/living/simple_animal/hostile/boss/paper_wizard/wiz = boss - var/directions = GLOB.cardinals.Copy() - for(var/i in 1 to 3) - var/mob/living/simple_animal/hostile/boss/paper_wizard/copy/C = new (get_step(target,pick_n_take(directions))) - wiz.copies += C - C.original = wiz - C.say("My craft defines me, you could even say it IS me!") - wiz.say("My craft defines me, you could even say it IS me!") - wiz.forceMove(get_step(target,pick_n_take(directions))) - wiz.minimum_distance = 1 //so he doesn't run away and ruin everything - wiz.retreat_distance = 0 + . = ..() + if(!.) + return + var/mob/living/target + if(!boss.client) //AI's target + target = boss.target + else //random mob + var/list/threats = boss.PossibleThreats() + if(threats.len) + target = pick(threats) else - boss.atb.refund(boss_cost) + to_chat(owner, "There is no potential foe of different faction around to attack") + if(target) + var/mob/living/simple_animal/hostile/boss/paper_wizard/wiz = boss + var/directions = GLOB.cardinals.Copy() + for(var/i in 1 to 3) + var/mob/living/simple_animal/hostile/boss/paper_wizard/copy/C = new (get_step(target,pick_n_take(directions))) + wiz.copies += C + C.original = wiz + C.say("My craft defines me, you could even say it IS me!") + wiz.say("My craft defines me, you could even say it IS me!") + wiz.forceMove(get_step(target,pick_n_take(directions))) + wiz.minimum_distance = 1 //so he doesn't run away and ruin everything + wiz.retreat_distance = 0 + else + boss.atb.refund(boss_cost) /mob/living/simple_animal/hostile/boss/paper_wizard/copy desc = "'Tis a ruse!" diff --git a/code/modules/mob/living/simple_animal/hostile/hostile.dm b/code/modules/mob/living/simple_animal/hostile/hostile.dm index cae8948fdd..e41fa7c896 100644 --- a/code/modules/mob/living/simple_animal/hostile/hostile.dm +++ b/code/modules/mob/living/simple_animal/hostile/hostile.dm @@ -20,6 +20,7 @@ var/casingtype //set ONLY it and NULLIFY projectiletype, if we have projectile IN CASING var/move_to_delay = 3 //delay for the automated movement. var/list/friends = list() + var/list/foes = list() var/list/emote_taunt = list() var/taunt_chance = 0 @@ -62,6 +63,8 @@ /mob/living/simple_animal/hostile/Destroy() targets_from = null + friends = null + foes = null return ..() /mob/living/simple_animal/hostile/Life() @@ -193,7 +196,7 @@ // Please do not add one-off mob AIs here, but override this function for your mob /mob/living/simple_animal/hostile/CanAttack(atom/the_target)//Can we actually attack a possible target? - if(isturf(the_target) || !the_target || the_target.type == /atom/movable/lighting_object) // bail out on invalids + if(!the_target || the_target.type == /atom/movable/lighting_object || isturf(the_target)) // bail out on invalids return FALSE if(ismob(the_target)) //Target is in godmode, ignore it. @@ -208,13 +211,13 @@ if(search_objects < 2) if(isliving(the_target)) var/mob/living/L = the_target - var/faction_check = faction_check_mob(L) + var/faction_check = !foes[L] && faction_check_mob(L) if(robust_searching) if(faction_check && !attack_same) return FALSE - if(L.stat > stat_attack) + if(L.stat > stat_attack || (L.stat == UNCONSCIOUS && stat_attack == UNCONSCIOUS && HAS_TRAIT(L, TRAIT_DEATHCOMA))) return FALSE - if(L in friends) + if(friends[L] > 0 && foes[L] < 1) return FALSE else if((faction_check && !attack_same) || L.stat) diff --git a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm index c2faa002bc..31f925fb2b 100644 --- a/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm +++ b/code/modules/mob/living/simple_animal/hostile/mining_mobs/elites/legionnaire.dm @@ -298,5 +298,5 @@ var/mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion/A = new /mob/living/simple_animal/hostile/asteroid/hivelordbrood/legion(user.loc) A.flags_1 |= (flags_1 & ADMIN_SPAWNED_1) A.GiveTarget(target) - A.friends = user + A.friends[user]++ A.faction = user.faction.Copy() diff --git a/code/modules/mob/living/simple_animal/hostile/stickman.dm b/code/modules/mob/living/simple_animal/hostile/stickman.dm index 2edcc4021a..226af952b1 100644 --- a/code/modules/mob/living/simple_animal/hostile/stickman.dm +++ b/code/modules/mob/living/simple_animal/hostile/stickman.dm @@ -13,7 +13,7 @@ speed = 0 blood_volume = 0 stat_attack = UNCONSCIOUS - robust_searching = 1 + robust_searching = TRUE //This is also required for the paper robe rallying to work. environment_smash = ENVIRONMENT_SMASH_NONE maxHealth = 100 health = 100 @@ -30,8 +30,6 @@ faction = list("hostile","stickman") check_friendly_fire = 1 status_flags = CANPUSH - var/datum/action/boss/wizard_summon_minions/changesummons = /datum/action/boss/wizard_summon_minions - var/summoned_by_wizard = 0 /mob/living/simple_animal/hostile/stickman/ranged ranged = 1 @@ -43,7 +41,6 @@ projectilesound = 'sound/misc/bang.ogg' loot = list(/obj/item/gun/ballistic/automatic/pistol/stickman) - /mob/living/simple_animal/hostile/stickman/dog name = "Angry Stick Dog" desc = "Stickman's best friend, if he could see him at least." @@ -52,12 +49,6 @@ icon_dead = "stickdog_dead" mob_biotypes = MOB_BEAST -/mob/living/simple_animal/hostile/stickman/Initialize(mapload, var/wizard_summoned) +/mob/living/simple_animal/hostile/stickman/Initialize(mapload) . = ..() new /obj/effect/temp_visual/paper_scatter(src) - summoned_by_wizard = wizard_summoned - -/mob/living/simple_animal/hostile/stickman/death() - ..() - if(summoned_by_wizard == 1) - changesummons.summoned_minions -- diff --git a/code/modules/mob/living/status_procs.dm b/code/modules/mob/living/status_procs.dm index 0d41347179..0029300936 100644 --- a/code/modules/mob/living/status_procs.dm +++ b/code/modules/mob/living/status_procs.dm @@ -571,12 +571,13 @@ /mob/living/proc/cure_blind(source) REMOVE_TRAIT(src, TRAIT_BLIND, source) if(!HAS_TRAIT(src, TRAIT_BLIND)) - update_blindness() + if(eye_blind <= 1) //little hack now that we don't actively check for trait and unconsciousness on update_blindness. + adjust_blindness(-1) /mob/living/proc/become_blind(source) if(!HAS_TRAIT(src, TRAIT_BLIND)) // not blind already, add trait then overlay ADD_TRAIT(src, TRAIT_BLIND, source) - update_blindness() + blind_eyes(1) else ADD_TRAIT(src, TRAIT_BLIND, source) diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 4a6da1ad56..4c692e7175 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -128,15 +128,13 @@ * * target (optional) is the other mob involved with the visible message. For example, the attacker in many combat messages. * * target_message (optional) is what the target mob will see e.g. "[src] does something to you!" */ -/atom/proc/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs, mob/target, target_message) +/atom/proc/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, ignored_mobs, mob/target, target_message) var/turf/T = get_turf(src) if(!T) return var/list/hearers = get_hearers_in_view(vision_distance, src) //caches the hearers and then removes ignored mobs. if(!length(hearers)) return - if(!islist(ignored_mobs)) - ignored_mobs = list(ignored_mobs) hearers -= ignored_mobs if(target_message && target && istype(target) && target.client) @@ -150,7 +148,7 @@ msg = blind_message if(msg) target.show_message(msg, MSG_VISUAL,blind_message, MSG_AUDIBLE) - else if(self_message) + if(self_message) hearers -= src for(var/mob/M in hearers) if(!M.client) @@ -185,15 +183,13 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA * * hearing_distance (optional) is the range, how many tiles away the message can be heard. * * ignored_mobs (optional) doesn't show any message to any given mob in the list. */ -/atom/proc/audible_message(message, deaf_message, hearing_distance = DEFAULT_MESSAGE_RANGE, self_message, list/ignored_mobs) +/atom/proc/audible_message(message, deaf_message, hearing_distance = DEFAULT_MESSAGE_RANGE, self_message, ignored_mobs) var/turf/T = get_turf(src) if(!T) return var/list/hearers = get_hearers_in_view(hearing_distance, src) if(!length(hearers)) return - if(!islist(ignored_mobs)) - ignored_mobs = list(ignored_mobs) hearers -= ignored_mobs if(self_message) hearers -= src @@ -377,7 +373,7 @@ mob/visible_message(message, self_message, blind_message, vision_distance = DEFA return FALSE new /obj/effect/temp_visual/point(A,invisibility) - + SEND_SIGNAL(src, COMSIG_MOB_POINTED, A) return TRUE /mob/proc/can_resist() diff --git a/code/modules/mob/mob_defines.dm b/code/modules/mob/mob_defines.dm index 9947c8ca1e..9dcfb4e99a 100644 --- a/code/modules/mob/mob_defines.dm +++ b/code/modules/mob/mob_defines.dm @@ -127,6 +127,13 @@ var/registered_z + var/list/alerts = list() // contains /obj/screen/alert only // On /mob so clientless mobs will throw alerts properly + var/list/screens = list() + var/list/client_colours = list() + var/hud_type = /datum/hud + + var/datum/hSB/sandbox = null + var/mob/audiovisual_redirect //Mob to redirect messages, speech, and sounds to var/siliconaccessareas = list() diff --git a/code/modules/mob/mob_movement.dm b/code/modules/mob/mob_movement.dm index 2bcfd47344..9867da1ed4 100644 --- a/code/modules/mob/mob_movement.dm +++ b/code/modules/mob/mob_movement.dm @@ -101,10 +101,10 @@ mob.throwing.finalize(FALSE) var/atom/movable/AM = L.pulling - if(AM && AM.density && !(L.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && !ismob(AM)) + if(AM && AM.density && !SEND_SIGNAL(L, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE) && !ismob(AM)) L.setDir(turn(L.dir, 180)) - SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_MOVE, src, direction, n, oldloc) + SEND_SIGNAL(mob, COMSIG_MOB_CLIENT_MOVE, src, direction, n, oldloc, add_delay) /// Process_Grab(): checks for grab, attempts to break if so. Return TRUE to prevent movement. /client/proc/Process_Grab() diff --git a/code/modules/mob/status_procs.dm b/code/modules/mob/status_procs.dm index 6be1afb5de..fbef8fd244 100644 --- a/code/modules/mob/status_procs.dm +++ b/code/modules/mob/status_procs.dm @@ -23,9 +23,9 @@ * Sets a mob's blindness to an amount if it was not above it already, similar to how status effects work */ /mob/proc/blind_eyes(amount) - var/old_blind = eye_blind || HAS_TRAIT(src, TRAIT_BLIND) - eye_blind = max(eye_blind, amount) - var/new_blind = eye_blind || HAS_TRAIT(src, TRAIT_BLIND) + var/old_blind = eye_blind + eye_blind = max((!eye_blind && stat == UNCONSCIOUS || HAS_TRAIT(src, TRAIT_BLIND)) ? 1 : eye_blind , amount) + var/new_blind = eye_blind if(old_blind != new_blind) update_blindness() @@ -36,21 +36,21 @@ */ /mob/proc/adjust_blindness(amount) var/old_eye_blind = eye_blind - eye_blind = max(0, eye_blind + amount) - if(!old_eye_blind || !eye_blind && !HAS_TRAIT(src, TRAIT_BLIND)) + eye_blind = max((stat == UNCONSCIOUS || HAS_TRAIT(src, TRAIT_BLIND)) ? 1 : 0, eye_blind + amount) + if(!old_eye_blind || !eye_blind) update_blindness() /** * Force set the blindness of a mob to some level */ /mob/proc/set_blindness(amount) var/old_eye_blind = eye_blind - eye_blind = max(amount, 0) - if(!old_eye_blind || !eye_blind && !HAS_TRAIT(src, TRAIT_BLIND)) + eye_blind = max(amount, (stat == UNCONSCIOUS || HAS_TRAIT(src, TRAIT_BLIND)) ? 1 : 0) + if(!old_eye_blind || !eye_blind) update_blindness() /// proc that adds and removes blindness overlays when necessary /mob/proc/update_blindness() - if(stat == UNCONSCIOUS || HAS_TRAIT(src, TRAIT_BLIND) || eye_blind) // UNCONSCIOUS or has blind trait, or has temporary blindness + if(eye_blind) // UNCONSCIOUS or has blind trait, or has temporary blindness if(stat == CONSCIOUS || stat == SOFT_CRIT) throw_alert("blind", /obj/screen/alert/blind) overlay_fullscreen("blind", /obj/screen/fullscreen/blind) diff --git a/code/modules/paperwork/paper.dm b/code/modules/paperwork/paper.dm index 35a2b3f058..aed3ff5848 100644 --- a/code/modules/paperwork/paper.dm +++ b/code/modules/paperwork/paper.dm @@ -384,3 +384,6 @@ /obj/item/paper/crumpled/bloody icon_state = "scrap_bloodied" + +/obj/item/paper/crumpled/muddy + icon_state = "scrap_mud" diff --git a/code/modules/photography/photos/frame.dm b/code/modules/photography/photos/frame.dm index 11ad81ebf0..9e6f827629 100644 --- a/code/modules/photography/photos/frame.dm +++ b/code/modules/photography/photos/frame.dm @@ -4,7 +4,7 @@ name = "picture frame" desc = "The perfect showcase for your favorite deathtrap memories." icon = 'icons/obj/decals.dmi' - custom_materials = null + custom_materials = list(/datum/material/wood = 2000) flags_1 = 0 icon_state = "frame-empty" result_path = /obj/structure/sign/picture_frame @@ -64,6 +64,7 @@ desc = "Every time you look it makes you laugh." icon = 'icons/obj/decals.dmi' icon_state = "frame-empty" + custom_materials = list(/datum/material/wood = 2000) var/obj/item/photo/framed var/persistence_id var/can_decon = TRUE diff --git a/code/modules/projectiles/gun.dm b/code/modules/projectiles/gun.dm index 0f398b6d3b..ef28c76da9 100644 --- a/code/modules/projectiles/gun.dm +++ b/code/modules/projectiles/gun.dm @@ -80,6 +80,8 @@ /// Just 'slightly' snowflakey way to modify projectile damage for projectiles fired from this gun. var/projectile_damage_multiplier = 1 + var/automatic = 0 //can gun use it, 0 is no, anything above 0 is the delay between clicks in ds + /obj/item/gun/Initialize() . = ..() if(no_pin_required) @@ -213,7 +215,8 @@ var/bonus_spread = 0 var/loop_counter = 0 - bonus_spread += getinaccuracy(user) //CIT CHANGE - adds bonus spread while not aiming + if(user) + bonus_spread += getinaccuracy(user) //CIT CHANGE - adds bonus spread while not aiming if(ishuman(user) && user.a_intent == INTENT_HARM && weapon_weight <= WEAPON_LIGHT) var/mob/living/carbon/human/H = user for(var/obj/item/gun/G in H.held_items) @@ -563,12 +566,7 @@ chambered = null update_icon() -/obj/item/gun/proc/getinaccuracy(mob/living/user) - if(!isliving(user)) - return FALSE - else - var/mob/living/holdingdude = user - if(istype(holdingdude) && (holdingdude.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) - return 0 - else - return ((weapon_weight * 25) * inaccuracy_modifier) +/obj/item/gun/proc/getinaccuracy(mob/user) + if(SEND_SIGNAL(user, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_INACTIVE)) + return ((weapon_weight * 25) * inaccuracy_modifier) + return 0 diff --git a/code/modules/projectiles/guns/misc/beam_rifle.dm b/code/modules/projectiles/guns/misc/beam_rifle.dm index 2af25971f3..bcb074023f 100644 --- a/code/modules/projectiles/guns/misc/beam_rifle.dm +++ b/code/modules/projectiles/guns/misc/beam_rifle.dm @@ -77,7 +77,6 @@ var/static/image/drained_overlay = image(icon = 'icons/obj/guns/energy.dmi', icon_state = "esniper_empty") var/datum/action/item_action/zoom_lock_action/zoom_lock_action - var/mob/listeningTo /obj/item/gun/energy/beam_rifle/debug delay = 0 @@ -178,7 +177,6 @@ STOP_PROCESSING(SSfastprocess, src) set_user(null) QDEL_LIST(current_tracers) - listeningTo = null return ..() /obj/item/gun/energy/beam_rifle/proc/aiming_beam(force_update = FALSE) @@ -260,17 +258,12 @@ if(user == current_user) return stop_aiming(current_user) - if(listeningTo) - UnregisterSignal(listeningTo, COMSIG_MOVABLE_MOVED) - listeningTo = null - if(istype(current_user)) - LAZYREMOVE(current_user.mousemove_intercept_objects, src) + if(current_user) + UnregisterSignal(current_user, COMSIG_MOVABLE_MOVED) current_user = null if(istype(user)) current_user = user - LAZYOR(current_user.mousemove_intercept_objects, src) RegisterSignal(user, COMSIG_MOVABLE_MOVED, .proc/on_mob_move) - listeningTo = user /obj/item/gun/energy/beam_rifle/onMouseDrag(src_object, over_object, src_location, over_location, params, mob) if(aiming) diff --git a/code/modules/reagents/reagent_containers/glass.dm b/code/modules/reagents/reagent_containers/glass.dm index b4e954f147..549f4eb48c 100644 --- a/code/modules/reagents/reagent_containers/glass.dm +++ b/code/modules/reagents/reagent_containers/glass.dm @@ -351,7 +351,7 @@ name = "wooden bucket" desc = "It's a bucket made of wood." icon_state = "bucket_wooden" - custom_materials = null + custom_materials = list(/datum/material/wood = MINERAL_MATERIAL_AMOUNT * 2) slot_flags = NONE item_flags = NO_MAT_REDEMPTION diff --git a/code/modules/ruins/lavalandruin_code/elephantgraveyard.dm b/code/modules/ruins/lavalandruin_code/elephantgraveyard.dm new file mode 100644 index 0000000000..65530031c0 --- /dev/null +++ b/code/modules/ruins/lavalandruin_code/elephantgraveyard.dm @@ -0,0 +1,247 @@ +//******Decoration objects +//***Bone statues and giant skeleton parts. +/obj/structure/statue/bone + anchored = TRUE + max_integrity = 120 + material_drop_type = /obj/item/stack/sheet/bone + impressiveness = 18 // Carved from the bones of a massive creature, it's going to be a specticle to say the least + layer = ABOVE_ALL_MOB_LAYER + +/obj/structure/statue/bone/rib + name = "collosal rib" + desc = "It's staggering to think that something this big could have lived, let alone died." + oreAmount = 4 + icon = 'icons/obj/statuelarge.dmi' + icon_state = "rib" + +/obj/structure/statue/bone/skull + name = "collosal skull" + desc = "The gaping maw of a dead, titanic monster." + oreAmount = 12 + icon = 'icons/obj/statuelarge.dmi' + icon_state = "skull" + +/obj/structure/statue/bone/skull/half + desc = "The gaping maw of a dead, titanic monster. This one is cracked in half." + oreAmount = 6 + icon = 'icons/obj/statuelarge.dmi' + icon_state = "skull-half" + +//***Wasteland floor and rock turfs here. +/turf/open/floor/plating/asteroid/basalt/wasteland //Like a more fun version of living in Arizona. + name = "cracked earth" + icon = 'icons/turf/floors.dmi' + icon_state = "wasteland" + environment_type = "wasteland" + baseturfs = /turf/open/floor/plating/asteroid/basalt/wasteland + digResult = /obj/item/stack/ore/glass/basalt + initial_gas_mix = LAVALAND_DEFAULT_ATMOS + slowdown = 0.5 + floor_variance = 30 + +/turf/open/floor/plating/asteroid/basalt/wasteland/Initialize() + .=..() + if(prob(floor_variance)) + icon_state = "[environment_type][rand(0,6)]" + +/turf/closed/mineral/strong/wasteland + name = "ancient dry rock" + color = "#B5651D" + environment_type = "wasteland" + turf_type = /turf/open/floor/plating/asteroid/basalt/wasteland + baseturfs = /turf/open/floor/plating/asteroid/basalt/wasteland + smooth_icon = 'icons/turf/walls/rock_wall.dmi' + +/turf/closed/mineral/strong/wasteland/drop_ores() + if(prob(10)) + new /obj/item/stack/ore/iron(src, 1) + new /obj/item/stack/ore/glass(src, 1) + new /obj/effect/decal/remains/human/grave(src, 1) + else + new /obj/item/stack/sheet/bone(src, 1) + +//***Oil well puddles. +/obj/structure/sink/oil_well //You're not going to enjoy bathing in this... + name = "oil well" + desc = "A bubbling pool of oil.This would probably be valuable, had bluespace technology not destroyed the need for fossil fuels 200 years ago." + icon = 'icons/obj/watercloset.dmi' + icon_state = "puddle-oil" + dispensedreagent = /datum/reagent/oil + +/obj/structure/sink/oil_well/Initialize() + .=..() + create_reagents(20) + reagents.add_reagent(dispensedreagent, 20) + +/obj/structure/sink/oil_well/attack_hand(mob/M) + flick("puddle-oil-splash",src) + reagents.reaction(M, TOUCH, 20) //Covers target in 20u of oil. + to_chat(M, "You touch the pool of oil, only to get oil all over yourself. It would be wise to wash this off with water.") + +/obj/structure/sink/oil_well/attackby(obj/item/O, mob/user, params) + flick("puddle-oil-splash",src) + if(O.tool_behaviour == TOOL_SHOVEL && !(flags_1&NODECONSTRUCT_1)) //attempt to deconstruct the puddle with a shovel + to_chat(user, "You fill in the oil well with soil.") + O.play_tool_sound(src) + deconstruct() + return 1 + if(istype(O, /obj/item/reagent_containers)) //Refilling bottles with oil + var/obj/item/reagent_containers/RG = O + if(RG.is_refillable()) + if(!RG.reagents.holder_full()) + RG.reagents.add_reagent(dispensedreagent, min(RG.volume - RG.reagents.total_volume, RG.amount_per_transfer_from_this)) + to_chat(user, "You fill [RG] from [src].") + return TRUE + to_chat(user, "\The [RG] is full.") + return FALSE + if(user.a_intent != INTENT_HARM) + to_chat(user, "You won't have any luck getting \the [O] out if you drop it in the oil.") + return 1 + else + return ..() + +/obj/structure/sink/oil_well/drop_materials() + new /obj/effect/decal/cleanable/oil(loc) + +//***Grave mounds. +/obj/structure/closet/crate/grave + name = "burial mound" + desc = "An marked patch of soil, showing signs of a burial long ago. You wouldn't disturb a grave... right?" + icon = 'icons/obj/crates.dmi' + icon_state = "grave" + dense_when_open = TRUE + material_drop = /obj/item/stack/ore/glass/basalt + material_drop_amount = 5 + anchorable = FALSE + anchored = TRUE + locked = TRUE + breakout_time = 900 + cutting_tool = /obj/item/shovel + var/lead_tomb = FALSE + var/first_open = FALSE + +/obj/structure/closet/crate/grave/PopulateContents() //GRAVEROBBING IS NOW A FEATURE + ..() + new /obj/effect/decal/remains/human/grave(src) + switch(rand(1,8)) + if(1) + new /obj/item/coin/gold(src) + new /obj/item/storage/wallet(src) + if(2) + new /obj/item/clothing/glasses/meson(src) + if(3) + new /obj/item/coin/silver(src) + new /obj/item/shovel/spade(src) + if(4) + new /obj/item/storage/book/bible/booze(src) + if(5) + new /obj/item/clothing/neck/stethoscope(src) + new /obj/item/scalpel(src) + new /obj/item/hemostat(src) + + if(6) + new /obj/item/reagent_containers/glass/beaker(src) + new /obj/item/clothing/glasses/science(src) + if(7) + new /obj/item/clothing/glasses/sunglasses(src) + new /obj/item/clothing/mask/cigarette/rollie(src) + +/obj/structure/closet/crate/grave/open(mob/living/user, obj/item/S) + if(!opened) + to_chat(user, "The ground here is too hard to dig up with your bare hands. You'll need a shovel.") + else + to_chat(user, "The grave has already been dug up.") + +/obj/structure/closet/crate/grave/tool_interact(obj/item/S, mob/living/carbon/user) + if(user.a_intent == INTENT_HELP) //checks to attempt to dig the grave, must be done on help intent only. + if(!opened) + if(istype(S,cutting_tool) && S.tool_behaviour == TOOL_SHOVEL) + to_chat(user, "You start start to dig open \the [src] with \the [S]...") + if (do_after(user,20, target = src)) + opened = TRUE + locked = TRUE + dump_contents() + update_icon() + SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "graverobbing", /datum/mood_event/graverobbing) + if(lead_tomb == TRUE && first_open == TRUE) + user.gain_trauma(/datum/brain_trauma/magic/stalker) + to_chat(user, "Oh no, no no no, THEY'RE EVERYWHERE! EVERY ONE OF THEM IS EVERYWHERE!") + first_open = FALSE + return 1 + return 1 + else + to_chat(user, "You can't dig up a grave with \the [S.name].") + return 1 + else + to_chat(user, "The grave has already been dug up.") + return 1 + + else if((user.a_intent != INTENT_HELP) && opened) //checks to attempt to remove the grave entirely. + if(istype(S,cutting_tool) && S.tool_behaviour == TOOL_SHOVEL) + to_chat(user, "You start to remove \the [src] with \the [S].") + if (do_after(user,15, target = src)) + to_chat(user, "You remove \the [src] completely.") + SEND_SIGNAL(user, COMSIG_ADD_MOOD_EVENT, "graverobbing", /datum/mood_event/graverobbing) + deconstruct(TRUE) + return 1 + return + +/obj/structure/closet/crate/grave/bust_open() + ..() + opened = TRUE + update_icon() + dump_contents() + return + +/obj/structure/closet/crate/grave/lead_researcher + name = "ominous burial mound" + desc = "Even in a place filled to the brim with graves, this one shows a level of preperation and planning that fills you with dread." + icon = 'icons/obj/crates.dmi' + icon_state = "grave_lead" + lead_tomb = TRUE + first_open = TRUE + +/obj/structure/closet/crate/grave/lead_researcher/PopulateContents() //ADVANCED GRAVEROBBING + ..() + new /obj/effect/decal/cleanable/blood/gibs/old(src) + new /obj/item/book/granter/crafting_recipe/boneyard_notes(src) + +/obj/effect/decal/remains/human/grave + turf_loc_check = FALSE + +/obj/item/book/granter/crafting_recipe/boneyard_notes + name = "The Complete Works of Lavaland Bone Architecture" + desc = "Pried from the lead Archaeologist's cold, dead hands, this seems to explain how ancient bone architecture was erected long ago." + crafting_recipe_types = list(/datum/crafting_recipe/rib, /datum/crafting_recipe/boneshovel, /datum/crafting_recipe/halfskull, /datum/crafting_recipe/skull) + icon = 'icons/obj/library.dmi' + icon_state = "boneworking_learing" + oneuse = FALSE + remarks = list("Who knew you could bend bones that far back?", "I guess that was much easier before the planet heated up...", "So that's how they made those ruins survive the ashstorms. Neat!", "The page is just filled with insane ramblings about some 'legion' thing.", "But why would they need vinegar to polish the bones? And rags too?", "You spend a few moments cleaning dirt and blood off of the page, yeesh.") + + +//***Fluff items for lore/intrigue +/obj/item/paper/crumpled/muddy/fluff/elephant_graveyard + name = "posted warning" + desc = "It seems to be smudged with mud and... oil?" + info = "TO WHOM IT MAY CONCERN

This area is property of the Nanotrasen Mining Division.

Trespassing in this area is illegal, highly dangerous, and subject to several NDAs.

Please turn back now, under intergalactic law section 48-R." + +/obj/item/paper/crumpled/muddy/fluff/elephant_graveyard/rnd_notes + name = "Research Findings: Day 26" + desc = "Huh, this one page looks like it was torn out of a full book. How odd." + icon_state = "docs_part" + info = "Researcher name: B--*--* J--*s.

Detailed findings:Today the camp site's cond-tion has wor--ene*. The ashst--ms keep blocking us off from le-ving the sit* for m-re supplies, and it's lo-king like we're out of pl*sma to p-wer the ge-erat*r. Can't rea-*y study c-*bon *ating with no li--ts, ya know? Da-*y's been going -*f again and ag-*n a-*ut h*w the company's left us to *ie here, but I j-s* keep tell-ng him to stop che*-in* out these damn graves. We m-y b* archaeologists, but -e sho*ld have t-e dec-**cy to know these grav-s are *-l NEW.

The rest of the page is just semantics about carbon dating methods." + +/obj/item/paper/crumpled/muddy/fluff/elephant_graveyard/mutiny + name = "hastily scribbled note" + desc = "Seems like someone was in a hurry." + info = "Alright, we all know that stuck up son a bitch is just doing this to keep us satisifed. Who the hell does he think he is, taking extra rations? We're OUT OF FOOD, CARL. Tomorrow at noon, we're going to try and take the ship by force. He HAS to be lying about the engine cooling down. He HAS TO BE. I'm tellin ya, with this implant I lifted off that last supply ship, I got the smarts to get us offa this shithole. Keep your knife handy carl." + +/obj/item/paper/fluff/ruins/elephant_graveyard/hypothesis + name = "research document" + desc = "Standard Nanotrasen typeface for important research documents." + info = "Day 9: Tenative Conclusions

While the area appears to be of significant cultural importance to the lizard race, outside of some sparce contact with native wildlife, we're yet to find any exact reasoning for the nature of this phenomenon. It seems that organic life is communally drawn to this planet as though it functions as a final resting place for intelligent life. As per company guidelines, this site shall be given the following classification: 'LZ-0271 - Elephant Graveyard'

Compiled list of Artifact findings (Currently Sent Offsite)
Cultist Blade Fragments: x8
Brass Multiplicative Ore Sample: x105
Syndicate Revolutionary Leader Implant (Broken) x1
Extinct Cortical Borer Tissue Sample x1
Space Carp Fossil x3" + +/obj/item/paper/fluff/ruins/elephant_graveyard/final_message + name = "important looking Note" + desc = "This note is well written, and seems to have been put here so you'd find it." + info = "If you find this... you don't need to know who I am.

You need to leave this place. I dunno what shit they did to me out here, but I don't think I'm going to be making it out of here.

This place... it wears down your psyche. The other researchers out here laughed it off but... They were the first to go.

One by one they started turning on each other. The more they found out, the more they started fighting and arguing...
As I speak now, I had to... I wound up having to put most of my men down. I know what I had to do, and I know there's no way left for me to live with myself.
If anyone ever finds this, just don't touch the graves.

DO NOT. TOUCH. THE GRAVES. Don't be a dumbass, like we all were." diff --git a/code/modules/tgs/LICENSE b/code/modules/tgs/LICENSE new file mode 100644 index 0000000000..221f9e1deb --- /dev/null +++ b/code/modules/tgs/LICENSE @@ -0,0 +1,24 @@ +The MIT License + +Copyright (c) 2017 Jordan Brown + +Permission is hereby granted, free of charge, +to any person obtaining a copy of this software and +associated documentation files (the "Software"), to +deal in the Software without restriction, including +without limitation the rights to use, copy, modify, +merge, publish, distribute, sublicense, and/or sell +copies of the Software, and to permit persons to whom +the Software is furnished to do so, +subject to the following conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, +EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES +OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. +IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR +ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, +TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE +SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. diff --git a/code/modules/tgs/README.md b/code/modules/tgs/README.md new file mode 100644 index 0000000000..445cee41f5 --- /dev/null +++ b/code/modules/tgs/README.md @@ -0,0 +1,13 @@ +# DMAPI Internals + +This folder should be placed on it's own inside a codebase that wishes to use the TGS DMAPI. Warranty void if modified. + +- [includes.dm](./includes.dm) is the file that should be included by DM code, it handles including the rest. +- The [core](./core) folder includes all code not directly part of any API version. +- The other versioned folders contain code for the different DMAPI versions. + - [v3210](./v3210) contains the final TGS3 API. + - [v4](./v4) is the legacy DMAPI 4 (Used in TGS 4.0.X versions). + - [v5](./v5) is the current DMAPI version used by TGS4 >=4.1. +- [LICENSE](./LICENSE) is the MIT license for the DMAPI. + +APIs communicate with TGS in two ways. All versions implement TGS -> DM communication using /world/Topic. DM -> TGS communication, called the bridge method, is different for each version. diff --git a/code/modules/tgs/core/README.md b/code/modules/tgs/core/README.md new file mode 100644 index 0000000000..aa3c7a9c9d --- /dev/null +++ b/code/modules/tgs/core/README.md @@ -0,0 +1,8 @@ +# Core DMAPI functions + +This folder contains all DMAPI code not directly involved in an API. + +- [_definitions.dm](./definitions.dm) contains defines needed across DMAPI internals. +- [core.dm](./core.dm) contains the implementations of the `/world/proc/TgsXXX()` procs. Many map directly to the `/datum/tgs_api` functions. It also contains the /datum selection and setup code. +- [datum.dm](./datum.dm) contains the `/datum/tgs_api` declarations that all APIs must implement. +- [tgs_version.dm](./tgs_version.dm) contains the `/datum/tgs_version` definition \ No newline at end of file diff --git a/code/modules/tgs/core/core.dm b/code/modules/tgs/core/core.dm index a74c9bbab2..f75e7837af 100644 --- a/code/modules/tgs/core/core.dm +++ b/code/modules/tgs/core/core.dm @@ -154,30 +154,3 @@ var/datum/tgs_api/api = TGS_READ_GLOBAL(tgs) if(api) api.SecurityLevel() - -/* -The MIT License - -Copyright (c) 2017 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/code/modules/tgs/core/datum.dm b/code/modules/tgs/core/datum.dm index ccc75fe344..ef6d3a4fe5 100644 --- a/code/modules/tgs/core/datum.dm +++ b/code/modules/tgs/core/datum.dm @@ -55,30 +55,3 @@ TGS_PROTECT_DATUM(/datum/tgs_api) /datum/tgs_api/proc/SecurityLevel() return TGS_UNIMPLEMENTED - -/* -The MIT License - -Copyright (c) 2017 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/code/modules/tgs/includes.dm b/code/modules/tgs/includes.dm index b3c1728f34..c803cf7ac2 100644 --- a/code/modules/tgs/includes.dm +++ b/code/modules/tgs/includes.dm @@ -15,30 +15,3 @@ #include "v5\api.dm" #include "v5\commands.dm" #include "v5\undef.dm" - -/* -The MIT License - -Copyright (c) 2017 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/code/modules/tgs/v3210/README.md b/code/modules/tgs/v3210/README.md new file mode 100644 index 0000000000..f96e7cf3b3 --- /dev/null +++ b/code/modules/tgs/v3210/README.md @@ -0,0 +1,6 @@ +# DMAPI V3 + +This DMAPI implements bridge using file output which TGS monitors for. + +- [api.dm](./api.dm) contains the bulk of the API code. +- [commands.dm](./commands.dm) contains functions relating to `/datum/tgs_chat_command`s. diff --git a/code/modules/tgs/v3210/api.dm b/code/modules/tgs/v3210/api.dm index 0fc0076c8b..e0d00ad15d 100644 --- a/code/modules/tgs/v3210/api.dm +++ b/code/modules/tgs/v3210/api.dm @@ -226,30 +226,3 @@ #undef SERVICE_REQUEST_API_VERSION #undef SERVICE_RETURN_SUCCESS - -/* -The MIT License - -Copyright (c) 2017 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/code/modules/tgs/v3210/commands.dm b/code/modules/tgs/v3210/commands.dm index 5046631981..a1949da444 100644 --- a/code/modules/tgs/v3210/commands.dm +++ b/code/modules/tgs/v3210/commands.dm @@ -19,7 +19,7 @@ TGS_ERROR_LOG("Custom command [command_name] can't be used as it is empty or contains illegal characters!") warned_command_names[command_name] = TRUE continue - + if(command_name_types[command_name]) if(warnings_only) TGS_ERROR_LOG("Custom commands [command_name_types[command_name]] and [stc] have the same name, only [command_name_types[command_name]] will be available!") @@ -44,35 +44,3 @@ user.friendly_name = sender user.mention = sender return stc.Run(user, params) || TRUE - -/* - -#undef SERVICE_JSON_PARAM_HELPTEXT -#undef SERVICE_JSON_PARAM_ADMINONLY -#undef SERVICE_JSON_PARAM_REQUIREDPARAMETERS - -The MIT License - -Copyright (c) 2017 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/code/modules/tgs/v4/README.md b/code/modules/tgs/v4/README.md new file mode 100644 index 0000000000..78191447b2 --- /dev/null +++ b/code/modules/tgs/v4/README.md @@ -0,0 +1,6 @@ +# DMAPI V4 + +This DMAPI implements bridge requests using file output which TGS monitors for. It has a safe mode restriction. + +- [api.dm](./api.dm) contains the bulk of the API code. +- [commands.dm](./commands.dm) contains functions relating to `/datum/tgs_chat_command`s. diff --git a/code/modules/tgs/v4/api.dm b/code/modules/tgs/v4/api.dm index ba18aab688..1dc98f811e 100644 --- a/code/modules/tgs/v4/api.dm +++ b/code/modules/tgs/v4/api.dm @@ -50,6 +50,10 @@ return new /datum/tgs_version("4.0.0.0") /datum/tgs_api/v4/OnWorldNew(minimum_required_security_level) + if(minimum_required_security_level == TGS_SECURITY_ULTRASAFE) + TGS_WARNING_LOG("V4 DMAPI requires safe security!") + minimum_required_security_level = TGS_SECURITY_SAFE + json_path = world.params[TGS4_PARAM_INFO_JSON] if(!json_path) TGS_ERROR_LOG("Missing [TGS4_PARAM_INFO_JSON] world parameter!") @@ -310,30 +314,3 @@ /datum/tgs_api/v4/SecurityLevel() return security_level - -/* -The MIT License - -Copyright (c) 2017 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/code/modules/tgs/v4/commands.dm b/code/modules/tgs/v4/commands.dm index 1d9951bc04..4ca1500167 100644 --- a/code/modules/tgs/v4/commands.dm +++ b/code/modules/tgs/v4/commands.dm @@ -39,31 +39,3 @@ result = "" return result return "Unknown command: [command]!" - -/* - -The MIT License - -Copyright (c) 2017 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/code/modules/tgs/v5/_defines.dm b/code/modules/tgs/v5/_defines.dm index 2baf3e12d7..8fd84e19fa 100644 --- a/code/modules/tgs/v5/_defines.dm +++ b/code/modules/tgs/v5/_defines.dm @@ -12,13 +12,14 @@ #define DMAPI5_BRIDGE_COMMAND_CHAT_SEND 5 #define DMAPI5_PARAMETER_ACCESS_IDENTIFIER "accessIdentifier" +#define DMAPI5_PARAMETER_CUSTOM_COMMANDS "customCommands" + #define DMAPI5_RESPONSE_ERROR_MESSAGE "errorMessage" #define DMAPI5_BRIDGE_PARAMETER_COMMAND_TYPE "commandType" #define DMAPI5_BRIDGE_PARAMETER_CURRENT_PORT "currentPort" #define DMAPI5_BRIDGE_PARAMETER_VERSION "version" #define DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE "chatMessage" -#define DMAPI5_BRIDGE_PARAMETER_CUSTOM_COMMANDS "customCommands" #define DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL "minimumSecurityLevel" #define DMAPI5_BRIDGE_RESPONSE_NEW_PORT "newPort" @@ -95,30 +96,3 @@ #define DMAPI5_CUSTOM_CHAT_COMMAND_NAME "name" #define DMAPI5_CUSTOM_CHAT_COMMAND_HELP_TEXT "helpText" #define DMAPI5_CUSTOM_CHAT_COMMAND_ADMIN_ONLY "adminOnly" - -/* -The MIT License - -Copyright (c) 2020 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/code/modules/tgs/v5/api.dm b/code/modules/tgs/v5/api.dm index eedefb2877..8ca85faf05 100644 --- a/code/modules/tgs/v5/api.dm +++ b/code/modules/tgs/v5/api.dm @@ -16,7 +16,7 @@ var/list/chat_channels /datum/tgs_api/v5/ApiVersion() - return new /datum/tgs_version("5.1.1") + return new /datum/tgs_version("5.2.1") /datum/tgs_api/v5/OnWorldNew(minimum_required_security_level) server_port = world.params[DMAPI5_PARAM_SERVER_PORT] @@ -24,7 +24,7 @@ var/datum/tgs_version/api_version = ApiVersion() version = null - var/list/bridge_response = Bridge(DMAPI5_BRIDGE_COMMAND_STARTUP, list(DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL = minimum_required_security_level, DMAPI5_BRIDGE_PARAMETER_VERSION = api_version.raw_parameter, DMAPI5_BRIDGE_PARAMETER_CUSTOM_COMMANDS = ListCustomCommands())) + var/list/bridge_response = Bridge(DMAPI5_BRIDGE_COMMAND_STARTUP, list(DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL = minimum_required_security_level, DMAPI5_BRIDGE_PARAMETER_VERSION = api_version.raw_parameter, DMAPI5_PARAMETER_CUSTOM_COMMANDS = ListCustomCommands())) if(!istype(bridge_response)) TGS_ERROR_LOG("Failed initial bridge request!") return FALSE @@ -201,17 +201,27 @@ if(DMAPI5_TOPIC_COMMAND_HEARTBEAT) return TopicResponse() if(DMAPI5_TOPIC_COMMAND_WATCHDOG_REATTACH) + var/new_port = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_PORT] + var/error_message = null + if (new_port != null) + if (!isnum(new_port) || !(new_port > 0)) + error_message = "Invalid [DMAPI5_TOPIC_PARAMETER_NEW_PORT]]" + else + server_port = new_port + var/new_version_string = topic_parameters[DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION] if (!istext(new_version_string)) - return TopicResponse("Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION]]") + if(error_message != null) + error_message += ", " + error_message += "Invalid or missing [DMAPI5_TOPIC_PARAMETER_NEW_SERVER_VERSION]]" + else + var/datum/tgs_version/new_version = new(new_version_string) + if (event_handler) + event_handler.HandleEvent(TGS_EVENT_WATCHDOG_REATTACH, new_version) - var/datum/tgs_version/new_version = new(new_version_string) - if (event_handler) - event_handler.HandleEvent(TGS_EVENT_WATCHDOG_REATTACH, new_version) + version = new_version - version = new_version - - return TopicResponse() + return json_encode(list(DMAPI5_RESPONSE_ERROR_MESSAGE = error_message, DMAPI5_PARAMETER_CUSTOM_COMMANDS = ListCustomCommands())) return TopicResponse("Unknown command: [command]") @@ -343,30 +353,3 @@ /datum/tgs_api/v5/SecurityLevel() RequireInitialBridgeResponse() return security_level - -/* -The MIT License - -Copyright (c) 2020 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/code/modules/tgs/v5/commands.dm b/code/modules/tgs/v5/commands.dm index 2775157656..6d31dd3422 100644 --- a/code/modules/tgs/v5/commands.dm +++ b/code/modules/tgs/v5/commands.dm @@ -38,31 +38,3 @@ topic_response[DMAPI5_TOPIC_RESPONSE_COMMAND_RESPONSE_MESSAGE] = text_response return json_encode(topic_response) return TopicResponse("Unknown custom chat command: [command]!") - -/* - -The MIT License - -Copyright (c) 2020 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/code/modules/tgs/v5/undef.dm b/code/modules/tgs/v5/undef.dm index b27e3abe95..34fc481d36 100644 --- a/code/modules/tgs/v5/undef.dm +++ b/code/modules/tgs/v5/undef.dm @@ -12,13 +12,14 @@ #undef DMAPI5_BRIDGE_COMMAND_CHAT_SEND #undef DMAPI5_PARAMETER_ACCESS_IDENTIFIER +#undef DMAPI5_PARAMETER_CUSTOM_COMMANDS + #undef DMAPI5_RESPONSE_ERROR_MESSAGE #undef DMAPI5_BRIDGE_PARAMETER_COMMAND_TYPE #undef DMAPI5_BRIDGE_PARAMETER_CURRENT_PORT #undef DMAPI5_BRIDGE_PARAMETER_VERSION #undef DMAPI5_BRIDGE_PARAMETER_CHAT_MESSAGE -#undef DMAPI5_BRIDGE_PARAMETER_CUSTOM_COMMANDS #undef DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL #undef DMAPI5_BRIDGE_RESPONSE_NEW_PORT @@ -95,30 +96,3 @@ #undef DMAPI5_CUSTOM_CHAT_COMMAND_NAME #undef DMAPI5_CUSTOM_CHAT_COMMAND_HELP_TEXT #undef DMAPI5_CUSTOM_CHAT_COMMAND_ADMIN_ONLY - -/* -The MIT License - -Copyright (c) 2020 Jordan Brown - -Permission is hereby granted, free of charge, -to any person obtaining a copy of this software and -associated documentation files (the "Software"), to -deal in the Software without restriction, including -without limitation the rights to use, copy, modify, -merge, publish, distribute, sublicense, and/or sell -copies of the Software, and to permit persons to whom -the Software is furnished to do so, -subject to the following conditions: - -The above copyright notice and this permission notice -shall be included in all copies or substantial portions of the Software. - -THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, -EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES -OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. -IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, -TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE -SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. -*/ diff --git a/config/lavaRuinBlacklist.txt b/config/lavaRuinBlacklist.txt index 6d2d2633ce..e86cf42ea0 100644 --- a/config/lavaRuinBlacklist.txt +++ b/config/lavaRuinBlacklist.txt @@ -38,4 +38,5 @@ #_maps/RandomRuins/LavaRuins/lavaland_surface_hermit.dmm #_maps/RandomRuins/LavaRuins/lavaland_surface_swarmer_crash.dmm #_maps/RandomRuins/LavaRuins/lavaland_surface_library.dmm -#_maps/RandomRuins/AnywhereRuins/fountain_hall.dmm \ No newline at end of file +#_maps/RandomRuins/AnywhereRuins/fountain_hall.dmm +#_maps/RandomRuins/LavaRuins/lavaland_surface_elephant_graveyard.dmm \ No newline at end of file diff --git a/icons/mob/inhands/equipment/mining_lefthand.dmi b/icons/mob/inhands/equipment/mining_lefthand.dmi index e902690c37..7496aba625 100644 Binary files a/icons/mob/inhands/equipment/mining_lefthand.dmi and b/icons/mob/inhands/equipment/mining_lefthand.dmi differ diff --git a/icons/mob/inhands/equipment/mining_righthand.dmi b/icons/mob/inhands/equipment/mining_righthand.dmi index dacf9be078..de3d11978a 100644 Binary files a/icons/mob/inhands/equipment/mining_righthand.dmi and b/icons/mob/inhands/equipment/mining_righthand.dmi differ diff --git a/icons/obj/bureaucracy.dmi b/icons/obj/bureaucracy.dmi index 4f2238e391..95ae326f1e 100644 Binary files a/icons/obj/bureaucracy.dmi and b/icons/obj/bureaucracy.dmi differ diff --git a/icons/obj/crates.dmi b/icons/obj/crates.dmi index 532324fcf4..a1bc443efb 100644 Binary files a/icons/obj/crates.dmi and b/icons/obj/crates.dmi differ diff --git a/icons/obj/decals.dmi b/icons/obj/decals.dmi index f66767292c..c280ee786f 100644 Binary files a/icons/obj/decals.dmi and b/icons/obj/decals.dmi differ diff --git a/icons/obj/library.dmi b/icons/obj/library.dmi index be12ab5f8b..727d69b1e3 100644 Binary files a/icons/obj/library.dmi and b/icons/obj/library.dmi differ diff --git a/icons/obj/mining.dmi b/icons/obj/mining.dmi index 20ffbdbe06..43bc9c48aa 100644 Binary files a/icons/obj/mining.dmi and b/icons/obj/mining.dmi differ diff --git a/icons/obj/statuelarge.dmi b/icons/obj/statuelarge.dmi index e45afb8db8..e627a883cb 100644 Binary files a/icons/obj/statuelarge.dmi and b/icons/obj/statuelarge.dmi differ diff --git a/icons/obj/watercloset.dmi b/icons/obj/watercloset.dmi index 5670b9e839..4a299f29dd 100644 Binary files a/icons/obj/watercloset.dmi and b/icons/obj/watercloset.dmi differ diff --git a/icons/turf/floors.dmi b/icons/turf/floors.dmi index d24efa0625..477120870b 100644 Binary files a/icons/turf/floors.dmi and b/icons/turf/floors.dmi differ diff --git a/modular_citadel/code/_onclick/hud/screen_objects.dm b/modular_citadel/code/_onclick/hud/screen_objects.dm index a2fa6ee23c..017f7f3485 100644 --- a/modular_citadel/code/_onclick/hud/screen_objects.dm +++ b/modular_citadel/code/_onclick/hud/screen_objects.dm @@ -1,53 +1,22 @@ -/obj/screen/combattoggle - name = "toggle combat mode" - icon = 'modular_citadel/icons/ui/screen_midnight.dmi' - icon_state = "combat_off" - var/mutable_appearance/flashy - -/obj/screen/combattoggle/Click() - if(iscarbon(usr)) - var/mob/living/carbon/C = usr - C.user_toggle_intentional_combat_mode() - -/obj/screen/combattoggle/update_icon_state() - var/mob/living/carbon/user = hud?.mymob - if(!istype(user)) - return - if((user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) - icon_state = "combat" - else if(HAS_TRAIT(user, TRAIT_COMBAT_MODE_LOCKED)) - icon_state = "combat_locked" - else - icon_state = "combat_off" - -/obj/screen/combattoggle/update_overlays() - . = ..() - var/mob/living/carbon/user = hud?.mymob - if(!istype(user) || !user.client) - return - - if((user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE) && user.client.prefs.hud_toggle_flash) - if(!flashy) - flashy = mutable_appearance('icons/mob/screen_gen.dmi', "togglefull_flash") - if(flashy.color != user.client.prefs.hud_toggle_color) - flashy.color = user.client.prefs.hud_toggle_color - . += flashy //TODO - beg lummox jr for the ability to force mutable appearances or images to be created rendering from their first frame of animation rather than being based entirely around the client's frame count - /obj/screen/voretoggle name = "toggle vore mode" icon = 'modular_citadel/icons/ui/screen_midnight.dmi' icon_state = "nom_off" /obj/screen/voretoggle/Click() - if(iscarbon(usr)) - var/mob/living/carbon/C = usr - C.toggle_vore_mode() + if(usr != hud.mymob) + return + var/mob/living/carbon/C = usr + if(SEND_SIGNAL(usr, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_ACTIVE)) + to_chat(usr, "Disable combat mode first.") + return + C.toggle_vore_mode() /obj/screen/voretoggle/update_icon_state() var/mob/living/carbon/user = hud?.mymob if(!istype(user)) return - if(user.voremode && !(user.combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) + if(user.voremode) icon_state = "nom" else icon_state = "nom_off" diff --git a/modular_citadel/code/modules/mob/living/carbon/carbon.dm b/modular_citadel/code/modules/mob/living/carbon/carbon.dm index 8efb41e127..3a683ca2ff 100644 --- a/modular_citadel/code/modules/mob/living/carbon/carbon.dm +++ b/modular_citadel/code/modules/mob/living/carbon/carbon.dm @@ -1,21 +1,16 @@ /mob/living/carbon - var/lastmousedir - var/wrongdirmovedelay - //oh no vore time var/voremode = FALSE /mob/living/carbon/proc/toggle_vore_mode() + if(SEND_SIGNAL(src, COMSIG_COMBAT_MODE_CHECK, COMBAT_MODE_TOGGLED)) + return FALSE //let's not override the main draw of the game these days voremode = !voremode var/obj/screen/voretoggle/T = locate() in hud_used?.static_inventory T?.update_icon_state() - if(combat_flags & COMBAT_FLAG_COMBAT_TOGGLED) - return FALSE //let's not override the main draw of the game these days - SEND_SIGNAL(src, COMSIG_VORE_TOGGLED, src, voremode) return TRUE -/mob/living/carbon/onMouseMove(object, location, control, params) - if(!(combat_flags & COMBAT_FLAG_COMBAT_ACTIVE)) - return - face_atom(object, TRUE) - lastmousedir = dir +/mob/living/carbon/proc/disable_vore_mode() + voremode = FALSE + var/obj/screen/voretoggle/T = locate() in hud_used?.static_inventory + T?.update_icon_state() diff --git a/modular_citadel/code/modules/mob/living/living.dm b/modular_citadel/code/modules/mob/living/living.dm index 3baab2ad86..01867e9dcc 100644 --- a/modular_citadel/code/modules/mob/living/living.dm +++ b/modular_citadel/code/modules/mob/living/living.dm @@ -37,7 +37,7 @@ if(!(combat_flags & COMBAT_FLAG_HARD_STAMCRIT) && total_health >= STAMINA_CRIT && !stat) to_chat(src, "You're too exhausted to keep going...") set_resting(TRUE, FALSE, FALSE) - disable_intentional_combat_mode(TRUE, FALSE) + SEND_SIGNAL(src, COMSIG_DISABLE_COMBAT_MODE) ENABLE_BITFIELD(combat_flags, COMBAT_FLAG_HARD_STAMCRIT) filters += CIT_FILTER_STAMINACRIT update_mobility() diff --git a/tgstation.dme b/tgstation.dme index ab19f17cac..c399ff2a29 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -386,6 +386,7 @@ #include "code\datums\brain_damage\brain_trauma.dm" #include "code\datums\brain_damage\hypnosis.dm" #include "code\datums\brain_damage\imaginary_friend.dm" +#include "code\datums\brain_damage\magic.dm" #include "code\datums\brain_damage\mild.dm" #include "code\datums\brain_damage\phobia.dm" #include "code\datums\brain_damage\severe.dm" @@ -394,12 +395,12 @@ #include "code\datums\components\_component.dm" #include "code\datums\components\anti_magic.dm" #include "code\datums\components\armor_plate.dm" -#include "code\datums\components\art.dm" #include "code\datums\components\bane.dm" #include "code\datums\components\bouncy.dm" #include "code\datums\components\butchering.dm" #include "code\datums\components\caltrop.dm" #include "code\datums\components\chasm.dm" +#include "code\datums\components\combat_mode.dm" #include "code\datums\components\construction.dm" #include "code\datums\components\decal.dm" #include "code\datums\components\dejavu.dm" @@ -528,6 +529,8 @@ #include "code\datums\diseases\advance\symptoms\weight.dm" #include "code\datums\diseases\advance\symptoms\youth.dm" #include "code\datums\elements\_element.dm" +#include "code\datums\elements\art.dm" +#include "code\datums\elements\beauty.dm" #include "code\datums\elements\cleaning.dm" #include "code\datums\elements\dusts_on_catatonia.dm" #include "code\datums\elements\dusts_on_leaving_area.dm" @@ -2316,7 +2319,6 @@ #include "code\modules\mob\living\living_active_parry.dm" #include "code\modules\mob\living\living_block.dm" #include "code\modules\mob\living\living_blocking_parrying.dm" -#include "code\modules\mob\living\living_combat.dm" #include "code\modules\mob\living\living_defense.dm" #include "code\modules\mob\living\living_defines.dm" #include "code\modules\mob\living\living_mobility.dm" @@ -2339,7 +2341,6 @@ #include "code\modules\mob\living\brain\say.dm" #include "code\modules\mob\living\brain\status_procs.dm" #include "code\modules\mob\living\carbon\carbon.dm" -#include "code\modules\mob\living\carbon\carbon_combat.dm" #include "code\modules\mob\living\carbon\carbon_defense.dm" #include "code\modules\mob\living\carbon\carbon_defines.dm" #include "code\modules\mob\living\carbon\carbon_movement.dm" @@ -3102,6 +3103,7 @@ #include "code\modules\ruins\icemoonruin_code\library.dm" #include "code\modules\ruins\lavalandruin_code\alien_nest.dm" #include "code\modules\ruins\lavalandruin_code\biodome_clown_planet.dm" +#include "code\modules\ruins\lavalandruin_code\elephantgraveyard.dm" #include "code\modules\ruins\lavalandruin_code\pizzaparty.dm" #include "code\modules\ruins\lavalandruin_code\puzzle.dm" #include "code\modules\ruins\lavalandruin_code\sloth.dm" diff --git a/tgui-next/packages/tgui/interfaces/AirlockElectronics.js b/tgui-next/packages/tgui/interfaces/AirlockElectronics.js index 680849e649..f42afd1de2 100644 --- a/tgui-next/packages/tgui/interfaces/AirlockElectronics.js +++ b/tgui-next/packages/tgui/interfaces/AirlockElectronics.js @@ -79,7 +79,7 @@ export const AirlockElectronics = props => { />