diff --git a/.github/workflows/ci_suite.yml b/.github/workflows/ci_suite.yml index e9dd9bd5f3f7..b758c4d58a62 100644 --- a/.github/workflows/ci_suite.yml +++ b/.github/workflows/ci_suite.yml @@ -189,31 +189,20 @@ jobs: name: Integration Tests needs: collect_data - strategy: - fail-fast: false - matrix: - map: ${{ fromJSON(needs.collect_data.outputs.maps).paths }} - - uses: ./.github/workflows/run_integration_tests.yml + uses: ./.github/workflows/perform_regular_version_tests.yml with: - map: ${{ matrix.map }} + maps: ${{ needs.collect_data.outputs.maps }} max_required_byond_client: ${{needs.collect_data.outputs.max_required_byond_client}} run_alternate_tests: if: needs.collect_data.outputs.alternate_tests != '[]' name: Alternate Tests needs: collect_data - strategy: - fail-fast: false - matrix: - setup: ${{ fromJSON(needs.collect_data.outputs.alternate_tests) }} - uses: ./.github/workflows/run_integration_tests.yml + uses: ./.github/workflows/perform_alternate_version_tests.yml with: - map: ${{ matrix.setup.map }} - major: ${{ matrix.setup.major }} - minor: ${{ matrix.setup.minor }} - max_required_byond_client: ${{ matrix.setup.max_client_version || needs.collect_data.outputs.max_required_byond_client }} + alternate_tests: ${{ needs.collect_data.outputs.alternate_tests }} + default_max_required_byond_client: ${{ needs.collect_data.outputs.max_required_byond_client }} compare_screenshots: if: needs.collect_data.outputs.alternate_tests == '[]' || needs.run_alternate_tests.result == 'success' diff --git a/.github/workflows/perform_alternate_version_tests.yml b/.github/workflows/perform_alternate_version_tests.yml new file mode 100644 index 000000000000..de2abfe3e81e --- /dev/null +++ b/.github/workflows/perform_alternate_version_tests.yml @@ -0,0 +1,25 @@ +name: Run Alternate BYOND Version Tests +on: + workflow_call: + inputs: + alternate_tests: + required: true + type: string + default_max_required_byond_client: + required: true + type: string + +jobs: + run: + uses: ./.github/workflows/run_integration_tests.yml + + strategy: + fail-fast: false + matrix: + setup: ${{ fromJSON(inputs.alternate_tests) }} + + with: + map: ${{ matrix.setup.map }} + major: ${{ matrix.setup.major }} + minor: ${{ matrix.setup.minor }} + max_required_byond_client: ${{ matrix.setup.max_client_version || inputs.default_max_required_byond_client }} diff --git a/.github/workflows/perform_regular_version_tests.yml b/.github/workflows/perform_regular_version_tests.yml new file mode 100644 index 000000000000..bc515d850025 --- /dev/null +++ b/.github/workflows/perform_regular_version_tests.yml @@ -0,0 +1,23 @@ +name: Run Regular BYOND Version Tests +on: + workflow_call: + inputs: + maps: + required: true + type: string + max_required_byond_client: + required: true + type: string + +jobs: + run: + uses: ./.github/workflows/run_integration_tests.yml + + strategy: + fail-fast: false + matrix: + map: ${{ fromJSON(inputs.maps).paths }} + + with: + map: ${{ matrix.map }} + max_required_byond_client: ${{ inputs.max_required_byond_client }} diff --git a/.github/workflows/run_integration_tests.yml b/.github/workflows/run_integration_tests.yml index e5d75f303b39..70af0eeadd0e 100644 --- a/.github/workflows/run_integration_tests.yml +++ b/.github/workflows/run_integration_tests.yml @@ -19,6 +19,12 @@ on: jobs: run_integration_tests: + # If `inputs.major` is specified, this will output `Run Tests (major.minor; map; max)`. + # For example, `Run Tests (515.1627; runtimestation; 515)`. + # + # Otherwise, it will output `Run Tests (map; max)`. + # For example, `Run Tests (runtimestation; 515)`. + name: Run Tests (${{ inputs.major && format('{0}.{1}; ', inputs.major, inputs.minor) || '' }}${{ inputs.map }}; ${{ inputs.max_required_byond_client }}) runs-on: ubuntu-latest timeout-minutes: 30 # Monkestation edit: Our CI takes nearly twice as long, so the timeout is twice as long services: diff --git a/_maps/RandomRuins/SpaceRuins/deepstorage.dmm b/_maps/RandomRuins/SpaceRuins/deepstorage.dmm index ba03c88fc2e8..f4104f9f4305 100644 --- a/_maps/RandomRuins/SpaceRuins/deepstorage.dmm +++ b/_maps/RandomRuins/SpaceRuins/deepstorage.dmm @@ -2259,6 +2259,7 @@ /obj/item/clothing/head/bio_hood/interdyne, /obj/item/clothing/head/bio_hood/interdyne, /obj/item/clothing/head/bio_hood/interdyne, +/obj/item/construction/plumbing/research, /turf/open/floor/iron/white/textured, /area/ruin/space/has_grav/deepstorage/xenobiology) "gu" = ( @@ -2637,7 +2638,6 @@ /obj/effect/turf_decal/stripes{ dir = 8 }, -/obj/machinery/duct, /turf/open/floor/iron/white/textured, /area/ruin/space/has_grav/deepstorage/xenobiology) "kB" = ( @@ -2646,6 +2646,7 @@ }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/light/directional/south, +/obj/machinery/duct, /turf/open/floor/iron/white/textured, /area/ruin/space/has_grav/deepstorage/xenobiology) "kE" = ( @@ -2795,6 +2796,7 @@ }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/cable, +/obj/machinery/duct, /turf/open/floor/iron/white/textured, /area/ruin/space/has_grav/deepstorage/xenobiology) "sy" = ( @@ -2852,7 +2854,6 @@ /obj/effect/turf_decal/stripes{ dir = 4 }, -/obj/machinery/duct, /turf/open/floor/iron/white/textured, /area/ruin/space/has_grav/deepstorage/xenobiology) "vs" = ( @@ -2908,8 +2909,8 @@ /obj/item/stack/sheet/mineral/plasma/twenty, /obj/item/stack/sheet/mineral/plasma/twenty, /obj/item/stack/sheet/mineral/plasma/twenty, -/obj/item/disk/vacuum_upgrade, -/obj/item/disk/vacuum_upgrade, +/obj/item/disk/vacuum_upgrade/biomass, +/obj/item/disk/vacuum_upgrade/biomass, /turf/open/floor/iron/white/textured, /area/ruin/space/has_grav/deepstorage/xenobiology) "wI" = ( @@ -2988,6 +2989,7 @@ /area/ruin/space/has_grav/deepstorage/xenobiology) "An" = ( /obj/structure/extinguisher_cabinet/directional/south, +/obj/machinery/duct, /turf/open/floor/iron/white/textured, /area/ruin/space/has_grav/deepstorage/xenobiology) "Az" = ( diff --git a/_maps/map_files/Blueshift/Blueshift.dmm b/_maps/map_files/Blueshift/Blueshift.dmm index a95cb5b9546a..1497beddc1b5 100644 --- a/_maps/map_files/Blueshift/Blueshift.dmm +++ b/_maps/map_files/Blueshift/Blueshift.dmm @@ -525,6 +525,9 @@ /obj/effect/turf_decal/tile/brown/half/contrasted{ dir = 4 }, +/obj/structure/table/reinforced, +/obj/machinery/recharger, +/obj/item/restraints/handcuffs/cable/orange, /turf/open/floor/iron/dark/side{ dir = 8 }, @@ -20925,7 +20928,7 @@ /obj/effect/mapping_helpers/airlock/cyclelink_helper_multi{ cycle_id = "tcomms-internal" }, -/obj/effect/mapping_helpers/airlock/access/all/engineering/construction, +/obj/effect/mapping_helpers/airlock/access/all/engineering/tcoms, /turf/open/floor/iron, /area/station/tcommsat/computer) "dYM" = ( @@ -21416,11 +21419,11 @@ /obj/machinery/door/airlock/engineering/glass{ name = "Shared Engineering Storage" }, -/obj/effect/mapping_helpers/airlock/access/all/engineering/general, /obj/structure/disposalpipe/segment, /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/mapping_helpers/airlock/access/all/engineering/construction, /turf/open/floor/iron, /area/station/engineering/storage_shared) "eeY" = ( @@ -34005,7 +34008,6 @@ /obj/machinery/door/airlock/engineering/glass{ name = "Engineering Break Room" }, -/obj/effect/mapping_helpers/airlock/access/all/engineering/general, /obj/effect/mapping_helpers/airlock/cyclelink_helper{ dir = 1 }, @@ -34013,6 +34015,7 @@ /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/mapping_helpers/airlock/access/all/engineering/construction, /turf/open/floor/iron, /area/station/engineering/lobby) "gBa" = ( @@ -34417,10 +34420,9 @@ cycle_id = "tcomms-internal" }, /obj/machinery/door/firedoor/heavy, -/obj/effect/mapping_helpers/airlock/access/any/engineering/tcoms, -/obj/effect/mapping_helpers/airlock/access/any/command/general, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/mapping_helpers/airlock/access/all/engineering/tcoms, /turf/open/floor/iron, /area/station/tcommsat/computer) "gFA" = ( @@ -36719,11 +36721,11 @@ /obj/machinery/door/airlock/engineering/glass{ name = "Shared Engineering Storage" }, -/obj/effect/mapping_helpers/airlock/access/all/engineering/general, /obj/structure/disposalpipe/segment, /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/mapping_helpers/airlock/access/all/engineering/construction, /turf/open/floor/iron, /area/station/engineering/storage_shared) "hdL" = ( @@ -43966,7 +43968,6 @@ /obj/machinery/door/airlock/command/glass{ name = "Secure Tools Storage" }, -/obj/effect/mapping_helpers/airlock/access/all/command/general, /obj/machinery/door/firedoor, /obj/machinery/door/poddoor/preopen{ id = "Secure Tool"; @@ -43975,6 +43976,7 @@ /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/mapping_helpers/airlock/access/all/command/minisat, /turf/open/floor/iron, /area/station/engineering/transit_tube) "iyE" = ( @@ -49746,13 +49748,13 @@ /obj/machinery/door/airlock/engineering/glass{ name = "Engineering Foyer" }, -/obj/effect/mapping_helpers/airlock/access/all/engineering/general, /obj/effect/mapping_helpers/airlock/cyclelink_helper, /obj/structure/disposalpipe/segment, /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/landmark/navigate_destination, +/obj/effect/mapping_helpers/airlock/access/all/engineering/construction, /turf/open/floor/iron, /area/station/engineering/lobby) "jGA" = ( @@ -55673,11 +55675,10 @@ /obj/machinery/door/airlock/hatch{ name = "MiniSat Space Access Airlock" }, -/obj/effect/mapping_helpers/airlock/access/any/command/general, -/obj/effect/mapping_helpers/airlock/access/any/engineering/construction, /obj/effect/mapping_helpers/airlock/cyclelink_helper_multi{ cycle_id = "AIsatAirlock" }, +/obj/effect/mapping_helpers/airlock/access/all/command/minisat, /turf/open/floor/plating, /area/station/ai_monitored/aisat/exterior) "kKN" = ( @@ -61507,9 +61508,9 @@ name = "Telecoms Cooling" }, /obj/machinery/door/firedoor, -/obj/effect/mapping_helpers/airlock/access/all/engineering/construction, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/mapping_helpers/airlock/access/all/engineering/tcoms, /turf/open/floor/iron/dark, /area/station/tcommsat/computer) "lTC" = ( @@ -61528,6 +61529,11 @@ /area/station/engineering/atmos) "lTH" = ( /obj/effect/turf_decal/bot, +/mob/living/basic/pet/poppy, +/obj/structure/bed/dogbed{ + anchored = 1; + name = "Poppy's bed" + }, /turf/open/floor/iron/dark, /area/station/engineering/supermatter/room) "lTN" = ( @@ -65234,7 +65240,7 @@ /obj/effect/turf_decal/tile/purple{ dir = 8 }, -/obj/structure/table/reinforced, +/obj/machinery/computer/security, /turf/open/floor/iron/dark/side{ dir = 1 }, @@ -66574,7 +66580,6 @@ /obj/structure/extinguisher_cabinet/directional/west, /mob/living/basic/pet/potty, /obj/structure/sink/directional/east, -/obj/machinery/duct, /turf/open/floor/iron, /area/station/common/night_club/changing_room) "mTN" = ( @@ -70043,6 +70048,19 @@ /obj/machinery/airalarm/directional/east, /turf/open/floor/iron/white, /area/station/medical/coldroom) +"nEX" = ( +/obj/machinery/door/airlock/hatch{ + name = "MiniSat Space Access Airlock" + }, +/obj/effect/mapping_helpers/airlock/cyclelink_helper_multi{ + cycle_id = "AIsatAirlock" + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/mapping_helpers/airlock/access/all/command/minisat, +/turf/open/floor/plating, +/area/station/ai_monitored/aisat/exterior) "nFc" = ( /obj/machinery/door/firedoor/border_only{ dir = 4 @@ -72741,9 +72759,9 @@ /area/station/maintenance/department/crew_quarters/bar) "ofN" = ( /obj/machinery/newscaster/directional/west, -/obj/structure/table/reinforced, -/obj/machinery/recharger, -/obj/item/restraints/handcuffs/cable/orange, +/obj/machinery/computer/security{ + dir = 1 + }, /turf/open/floor/iron/dark, /area/station/security/checkpoint/supply) "ofS" = ( @@ -78236,9 +78254,11 @@ /turf/open/floor/iron, /area/station/security/prison/workout) "phZ" = ( -/obj/structure/filingcabinet, /obj/effect/turf_decal/bot, /obj/item/radio/intercom/directional/west, +/obj/machinery/computer/security{ + dir = 4 + }, /turf/open/floor/iron/dark, /area/station/security/checkpoint/engineering) "pic" = ( @@ -85416,7 +85436,9 @@ /area/station/service/forge) "qCz" = ( /obj/machinery/firealarm/directional/west, -/obj/structure/table/reinforced, +/obj/machinery/computer/security{ + dir = 4 + }, /turf/open/floor/iron/dark, /area/station/security/checkpoint/medical) "qCC" = ( @@ -89063,8 +89085,7 @@ name = "MiniSat Antechamber" }, /obj/structure/cable, -/obj/effect/mapping_helpers/airlock/access/any/command/general, -/obj/effect/mapping_helpers/airlock/access/any/engineering/construction, +/obj/effect/mapping_helpers/airlock/access/all/command/minisat, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat_interior) "rml" = ( @@ -95798,7 +95819,6 @@ /turf/open/floor/plating, /area/station/engineering/atmos/upper) "sCJ" = ( -/obj/structure/table/reinforced, /obj/item/book/manual/wiki/security_space_law, /obj/item/radio, /obj/structure/cable, @@ -95806,6 +95826,7 @@ /obj/effect/turf_decal/tile/brown/half/contrasted{ dir = 4 }, +/obj/structure/table/reinforced, /turf/open/floor/iron/dark/side{ dir = 8 }, @@ -97095,7 +97116,6 @@ /turf/open/floor/plating/airless, /area/space/nearstation) "sOT" = ( -/obj/effect/mapping_helpers/airlock/access/any/engineering/construction, /obj/effect/mapping_helpers/airlock/cyclelink_helper_multi{ cycle_id = "AISATFOYER" }, @@ -97105,6 +97125,7 @@ }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/mapping_helpers/airlock/access/all/engineering/construction, /turf/open/floor/plating, /area/station/engineering/transit_tube) "sOV" = ( @@ -102934,8 +102955,7 @@ /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/mapping_helpers/airlock/access/any/command/general, -/obj/effect/mapping_helpers/airlock/access/any/engineering/construction, +/obj/effect/mapping_helpers/airlock/access/all/command/minisat, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat_interior) "tTy" = ( @@ -106243,8 +106263,7 @@ /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/mapping_helpers/airlock/access/any/command/general, -/obj/effect/mapping_helpers/airlock/access/any/engineering/construction, +/obj/effect/mapping_helpers/airlock/access/all/command/minisat, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat_interior) "uAR" = ( @@ -107573,20 +107592,6 @@ /obj/machinery/ntnet_relay, /turf/open/floor/circuit/telecomms/mainframe, /area/station/tcommsat/server) -"uOa" = ( -/obj/machinery/door/airlock/hatch{ - name = "MiniSat Space Access Airlock" - }, -/obj/effect/mapping_helpers/airlock/access/any/command/general, -/obj/effect/mapping_helpers/airlock/access/any/engineering/construction, -/obj/effect/mapping_helpers/airlock/cyclelink_helper_multi{ - cycle_id = "AIsatAirlock" - }, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/plating, -/area/station/ai_monitored/aisat/exterior) "uOh" = ( /obj/structure/cable, /turf/open/floor/iron/dark/side, @@ -107744,10 +107749,10 @@ /obj/effect/mapping_helpers/airlock/cyclelink_helper_multi{ cycle_id = "tcomms-internal" }, -/obj/effect/mapping_helpers/airlock/access/all/engineering/construction, /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/mapping_helpers/airlock/access/all/engineering/tcoms, /turf/open/floor/iron, /area/station/tcommsat/computer) "uQb" = ( @@ -109309,8 +109314,7 @@ /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/mapping_helpers/airlock/access/any/command/general, -/obj/effect/mapping_helpers/airlock/access/any/engineering/construction, +/obj/effect/mapping_helpers/airlock/access/all/command/ai_upload, /turf/open/floor/engine, /area/station/ai_monitored/turret_protected/aisat_interior) "vfS" = ( @@ -109880,10 +109884,10 @@ name = "MiniSat Transit Tube Access" }, /obj/structure/cable, -/obj/effect/mapping_helpers/airlock/access/all/command/minisat, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/landmark/navigate_destination, +/obj/effect/mapping_helpers/airlock/access/all/command/minisat, /turf/open/floor/iron, /area/station/engineering/transit_tube) "vkG" = ( @@ -117184,9 +117188,7 @@ }, /area/station/security/execution/transfer) "wCw" = ( -/obj/machinery/camera/directional/south{ - c_tag = "Courtroom - Holding Cell" - }, +/obj/machinery/camera/directional/north, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/dark, /area/station/security/courtroom) @@ -119931,8 +119933,7 @@ /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/mapping_helpers/airlock/access/any/command/general, -/obj/effect/mapping_helpers/airlock/access/any/engineering/construction, +/obj/effect/mapping_helpers/airlock/access/all/command/minisat, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat_interior) "xeY" = ( @@ -120119,9 +120120,9 @@ name = "MiniSat Access" }, /obj/structure/cable, -/obj/effect/mapping_helpers/airlock/access/all/command/minisat, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/effect/mapping_helpers/airlock/access/all/engineering/construction, /turf/open/floor/iron, /area/station/engineering/transit_tube) "xgS" = ( @@ -120989,11 +120990,11 @@ }, /obj/machinery/door/firedoor, /obj/effect/landmark/navigate_destination, -/obj/effect/mapping_helpers/airlock/access/all/engineering/construction, /obj/structure/disposalpipe/segment, /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/mapping_helpers/airlock/access/all/engineering/tcoms, /turf/open/floor/iron, /area/station/tcommsat/computer) "xqe" = ( @@ -121528,8 +121529,8 @@ /obj/effect/mapping_helpers/airlock/cyclelink_helper_multi{ cycle_id = "tcomms-internal" }, -/obj/effect/mapping_helpers/airlock/access/all/engineering/construction, /obj/structure/cable, +/obj/effect/mapping_helpers/airlock/access/all/engineering/tcoms, /turf/open/floor/iron, /area/station/tcommsat/computer) "xuJ" = ( @@ -220903,7 +220904,7 @@ gLc gLc gLc tQB -uOa +nEX mcW kKI xya @@ -221417,7 +221418,7 @@ gLc gLc gLc tQB -uOa +nEX mPm kKI hKn diff --git a/_maps/map_files/BoxStation/BoxStation.dmm b/_maps/map_files/BoxStation/BoxStation.dmm index 68e4b5935c3f..5a1300bf4906 100644 --- a/_maps/map_files/BoxStation/BoxStation.dmm +++ b/_maps/map_files/BoxStation/BoxStation.dmm @@ -1650,6 +1650,7 @@ /obj/structure/cable, /obj/machinery/holopad, /obj/machinery/duct, +/mob/living/basic/bot/cleanbot/medbay, /turf/open/floor/iron/white/smooth_large, /area/station/medical/storage) "aBj" = ( @@ -60852,14 +60853,12 @@ /area/station/engineering/break_room) "tQC" = ( /obj/effect/turf_decal/trimline/yellow/filled/warning, -/obj/structure/disposalpipe/sorting/mail/flip{ - dir = 1 - }, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/cable, /obj/machinery/duct, /obj/effect/mapping_helpers/mail_sorting/engineering/general, +/obj/structure/disposalpipe/sorting/mail, /turf/open/floor/iron/dark/side, /area/station/engineering/break_room) "tQD" = ( diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index b231ec1a3dd2..b472196814c8 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -17763,6 +17763,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/spawner/random/engineering/tracking_beacon, /obj/effect/turf_decal/tile/blue/fourcorners, +/mob/living/basic/bot/cleanbot/medbay, /turf/open/floor/iron, /area/station/medical/storage) "eiK" = ( @@ -34948,6 +34949,11 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/effect/decal/cleanable/dirt, /obj/machinery/light/small/directional/north, +/obj/structure/bed/dogbed{ + anchored = 1; + name = "Poppy's bed" + }, +/mob/living/basic/pet/poppy, /turf/open/floor/iron, /area/station/engineering/supermatter/room) "ikx" = ( diff --git a/_maps/map_files/Graveyard/Graveyard.dmm b/_maps/map_files/Graveyard/Graveyard.dmm index 656dc0e33c9a..0846e2c50b33 100644 --- a/_maps/map_files/Graveyard/Graveyard.dmm +++ b/_maps/map_files/Graveyard/Graveyard.dmm @@ -17052,7 +17052,6 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 1 }, -/obj/machinery/duct, /turf/open/floor/iron/grimy, /area/ruin/syndicate_lava_base) "gEx" = ( @@ -25736,8 +25735,6 @@ /obj/structure/cable/multilayer/connected, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable/layer3, -/obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/port/fore) "kbt" = ( @@ -27229,6 +27226,11 @@ /obj/effect/spawner/random/trash/cigbutt, /turf/open/floor/plating, /area/station/maintenance/starboard/central) +"kFj" = ( +/obj/machinery/duct, +/obj/machinery/light/floor/has_bulb, +/turf/open/floor/iron/white, +/area/station/science/xenobiology) "kFp" = ( /obj/machinery/atmospherics/pipe/smart/manifold/purple/visible{ dir = 1 @@ -27805,7 +27807,6 @@ /area/station/maintenance/aft) "kQn" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/duct, /obj/structure/sink/directional/east, /turf/open/floor/iron/white, /area/graveyard/bunker/medical) @@ -50815,7 +50816,6 @@ req_access = list("xenobiology"); pixel_x = -24 }, -/obj/machinery/light/floor/has_bulb, /turf/open/floor/iron/white, /area/station/science/xenobiology) "tNd" = ( @@ -122384,7 +122384,7 @@ dKV emY raD jvq -lLz +kFj lLz pmj sQT diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index 9553433c5639..88eb84cb29eb 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -44232,6 +44232,11 @@ /area/station/security/prison/safe) "nXl" = ( /obj/effect/turf_decal/bot, +/mob/living/basic/pet/poppy, +/obj/structure/bed/dogbed{ + anchored = 1; + name = "Poppy's bed" + }, /turf/open/floor/iron/dark, /area/station/engineering/supermatter/room) "nXn" = ( @@ -68339,6 +68344,7 @@ dir = 8 }, /obj/effect/landmark/event_spawn, +/mob/living/basic/bot/cleanbot/medbay, /turf/open/floor/iron/white, /area/station/medical/storage) "vQQ" = ( diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index f8ceb07fca11..bf56aa214935 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -975,7 +975,7 @@ /turf/open/floor/iron/grimy, /area/station/tcommsat/computer) "arW" = ( -/obj/machinery/light/floor, +/obj/machinery/light/floor/has_bulb, /turf/open/floor/wood, /area/station/commons/lounge) "ase" = ( @@ -10067,7 +10067,7 @@ /obj/effect/turf_decal/siding/wood{ dir = 1 }, -/obj/machinery/light/floor, +/obj/machinery/light/floor/has_bulb, /turf/open/floor/wood/large, /area/station/commons/lounge) "dJK" = ( @@ -16326,7 +16326,7 @@ /obj/effect/turf_decal/siding/wood{ dir = 1 }, -/obj/machinery/light/floor, +/obj/machinery/light/floor/has_bulb, /turf/open/floor/wood/large, /area/station/commons/lounge) "fTE" = ( @@ -34062,7 +34062,6 @@ req_access = list("xenobiology"); pixel_x = -24 }, -/obj/machinery/light/floor/has_bulb, /turf/open/floor/iron/white, /area/station/science/xenobiology) "lOZ" = ( @@ -38402,7 +38401,7 @@ /area/station/security/office) "nlu" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/light/floor, +/obj/machinery/light/floor/has_bulb, /turf/open/floor/wood, /area/station/commons/lounge) "nlL" = ( @@ -38933,7 +38932,7 @@ /obj/effect/turf_decal/siding/wood{ dir = 1 }, -/obj/machinery/light/floor, +/obj/machinery/light/floor/has_bulb, /turf/open/floor/wood, /area/station/commons/lounge) "ntk" = ( @@ -43662,6 +43661,11 @@ }, /turf/open/floor/iron/white, /area/station/medical/chemistry) +"pbB" = ( +/obj/machinery/duct, +/obj/machinery/light/floor/has_bulb, +/turf/open/floor/iron/white, +/area/station/science/xenobiology) "pbL" = ( /obj/machinery/door/firedoor, /turf/open/floor/iron/white/side, @@ -58794,7 +58798,7 @@ /area/station/security/prison/mess) "umP" = ( /obj/structure/window/spawner/directional/west, -/obj/machinery/light/floor, +/obj/machinery/light/floor/has_bulb, /turf/open/floor/carpet, /area/station/service/theater) "umS" = ( @@ -118451,7 +118455,7 @@ mtu vHm fHs ycv -kCw +pbB kCw gRY xCA diff --git a/_maps/map_files/Theseus/Theseus.dmm b/_maps/map_files/Theseus/Theseus.dmm index 903ce6488894..fc976b3b6858 100644 --- a/_maps/map_files/Theseus/Theseus.dmm +++ b/_maps/map_files/Theseus/Theseus.dmm @@ -459,7 +459,6 @@ /obj/item/radio/radio_mic{ pixel_y = 7 }, -/obj/machinery/light/floor/has_bulb/warm, /obj/structure/cable, /turf/open/floor/carpet/green, /area/station/service/library/upper) @@ -2325,6 +2324,7 @@ }, /obj/structure/sink/directional/south, /obj/effect/turf_decal/bot, +/obj/machinery/light/floor/has_bulb, /turf/open/floor/iron/white/textured_edge{ dir = 1 }, @@ -4253,7 +4253,6 @@ /obj/effect/mapping_helpers/airlock/cyclelink_helper, /obj/effect/mapping_helpers/airlock/access/all/service/theatre, /obj/structure/cable, -/obj/machinery/light/floor/has_bulb, /obj/machinery/door/firedoor, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -4428,7 +4427,6 @@ "bqt" = ( /obj/structure/table/reinforced, /obj/effect/turf_decal/tile/gray/fourcorners, -/obj/machinery/light/floor/red, /obj/item/storage/pill_bottle/lsdpsych{ pixel_y = 12; name = "Emesis Diazepam" @@ -8301,6 +8299,7 @@ "cxX" = ( /obj/effect/landmark/event_spawn, /obj/structure/disposalpipe/segment, +/obj/machinery/light/floor/has_bulb, /turf/open/floor/iron/grimy, /area/station/service/library) "cya" = ( @@ -8591,7 +8590,6 @@ /area/station/engineering/break_room) "cBi" = ( /obj/structure/bookcase/random/reference, -/obj/machinery/light/floor/has_bulb, /turf/open/floor/wood, /area/station/service/library) "cBm" = ( @@ -12365,6 +12363,7 @@ /area/station/hallway/primary/starboard) "dIf" = ( /obj/structure/cable, +/obj/machinery/light/floor/has_bulb, /turf/open/floor/carpet, /area/station/service/cafeteria) "dIl" = ( @@ -13003,7 +13002,6 @@ /obj/item/reagent_containers/condiment/saltshaker{ pixel_x = -3 }, -/obj/machinery/light/floor/has_bulb, /obj/machinery/door/firedoor, /turf/open/floor/carpet, /area/station/service/bar) @@ -19913,7 +19911,6 @@ dir = 1 }, /obj/effect/mapping_helpers/airlock/access/all/security/brig, -/obj/machinery/light/floor/has_bulb, /turf/open/floor/plating, /area/station/security/processing) "fXf" = ( @@ -20226,6 +20223,11 @@ }, /turf/open/floor/engine, /area/station/science/xenobiology) +"gbR" = ( +/obj/structure/cable, +/obj/machinery/light/floor/has_bulb/warm, +/turf/open/floor/carpet/green, +/area/station/service/library/upper) "gbV" = ( /obj/effect/turf_decal/tile/yellow/half{ dir = 1 @@ -22330,11 +22332,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/station/hallway/primary/central/fore) -"gJm" = ( -/obj/structure/bookcase/random/nonfiction, -/obj/machinery/light/floor/has_bulb, -/turf/open/floor/iron/grimy, -/area/station/service/library) "gJn" = ( /obj/structure/lattice/catwalk, /obj/item/bodypart/arm/right, @@ -23812,7 +23809,6 @@ /turf/open/floor/plating, /area/station/command/heads_quarters/hos) "heQ" = ( -/obj/machinery/duct, /obj/structure/reagent_dispensers/plumbed, /turf/open/floor/plating, /area/station/maintenance/solars/port/fore) @@ -25223,6 +25219,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/disposalpipe/segment, +/obj/machinery/light/floor/has_bulb, /turf/open/floor/carpet, /area/station/service/cafeteria) "hAQ" = ( @@ -26240,7 +26237,6 @@ /obj/structure/mirror/directional/north{ pixel_y = 30 }, -/obj/machinery/duct, /turf/open/floor/iron/showroomfloor, /area/station/commons/dorms) "hRr" = ( @@ -26309,7 +26305,6 @@ /obj/effect/mapping_helpers/airlock/access/all/service/theatre, /obj/structure/cable, /obj/effect/landmark/navigate_destination/common/theatrebackstage, -/obj/machinery/light/floor/has_bulb, /obj/machinery/door/firedoor, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -32981,7 +32976,6 @@ /obj/item/surgical_drapes, /obj/effect/decal/cleanable/blood, /obj/effect/landmark/start/hangover, -/obj/machinery/light/floor/has_bulb, /obj/structure/drain/big, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -34007,7 +34001,6 @@ /obj/structure/table/optable, /obj/item/surgical_drapes, /obj/effect/landmark/start/hangover, -/obj/machinery/light/floor/has_bulb, /obj/structure/drain/big, /turf/open/floor/iron/dark, /area/station/medical/treatment_center) @@ -38707,6 +38700,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 8 }, +/obj/machinery/light/floor/has_bulb, /turf/open/floor/plating, /area/station/security/processing) "ltX" = ( @@ -47030,6 +47024,10 @@ "nTC" = ( /turf/open/floor/iron, /area/station/security/office) +"nTD" = ( +/obj/machinery/light/floor/has_bulb, +/turf/open/floor/iron/grimy, +/area/station/service/library) "nTE" = ( /obj/machinery/computer/warrant, /obj/effect/turf_decal/bot, @@ -51853,7 +51851,6 @@ /area/station/security/checkpoint/escape) "prO" = ( /obj/structure/bookcase/random/nonfiction, -/obj/machinery/light/floor/has_bulb, /obj/structure/disposalpipe/segment{ dir = 4 }, @@ -54540,7 +54537,6 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 8 }, -/obj/machinery/duct, /turf/open/floor/iron/showroomfloor, /area/station/commons) "qhb" = ( @@ -55981,6 +55977,13 @@ /obj/machinery/door/firedoor, /turf/open/floor/carpet, /area/station/service/bar) +"qBj" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/light/floor/has_bulb, +/turf/open/floor/iron/dark, +/area/station/service/theater) "qBx" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/structure/cable, @@ -58824,6 +58827,7 @@ /obj/effect/turf_decal/caution/stand_clear{ dir = 4 }, +/obj/machinery/light/floor/has_bulb, /turf/open/floor/plating, /area/station/security/processing) "rrO" = ( @@ -58889,6 +58893,7 @@ /area/station/service/library) "rsF" = ( /obj/machinery/iv_drip, +/obj/machinery/light/floor/has_bulb, /turf/open/floor/iron/dark, /area/station/medical/treatment_center) "rsL" = ( @@ -66348,7 +66353,6 @@ dir = 8 }, /obj/structure/sink/directional/south, -/obj/machinery/duct, /turf/open/floor/iron/white/textured, /area/station/security/medical) "tAh" = ( @@ -68831,6 +68835,7 @@ /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/light/floor/has_bulb, /turf/open/floor/wood, /area/station/service/theater) "ukt" = ( @@ -78112,7 +78117,6 @@ /obj/machinery/door/airlock/external{ name = "Gulag Shuttle Airlock" }, -/obj/machinery/light/floor/has_bulb, /turf/open/floor/plating, /area/station/security/processing) "wTF" = ( @@ -81835,6 +81839,7 @@ /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/light/floor/has_bulb, /turf/open/floor/eighties/red{ icon = 'goon/icons/turf/floors.dmi'; icon_state = "clown_carpet" @@ -88742,7 +88747,7 @@ fel mux saq ikP -iRD +gbR azt agO mux @@ -109408,7 +109413,7 @@ uGY gck prO bwX -gJm +bwX gck umk tyv @@ -110178,7 +110183,7 @@ svf ifR iMW fwA -iLO +nTD aaT ttd vnu @@ -121446,10 +121451,10 @@ bTD ofY ukm bli +qBj rJj rJj -rJj -rJj +qBj hSn xYR vjd diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index e3e238f4627c..0eb60baf8bab 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -13742,6 +13742,10 @@ "dkO" = ( /turf/open/floor/iron, /area/station/security/brig) +"dkU" = ( +/mob/living/basic/bot/cleanbot/medbay, +/turf/open/floor/iron/dark, +/area/station/medical/treatment_center) "dlb" = ( /obj/machinery/bluespace_beacon, /obj/effect/turf_decal/trimline/yellow/filled/warning, @@ -44027,6 +44031,15 @@ /obj/effect/turf_decal/sand/plating, /turf/open/floor/catwalk_floor, /area/station/solars/starboard/fore) +"mJO" = ( +/obj/structure/table, +/obj/machinery/duct, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/item/radio/intercom/prison, +/turf/open/floor/iron, +/area/station/security/prison) "mKe" = ( /obj/machinery/door/airlock/external{ name = "Solar Maintenance" @@ -70907,7 +70920,6 @@ /area/station/maintenance/starboard/central) "vcp" = ( /obj/structure/curtain, -/obj/machinery/shower/directional/north, /obj/machinery/duct, /turf/open/floor/iron/freezer, /area/station/commons/toilet) @@ -80671,12 +80683,13 @@ /area/station/commons/fitness/recreation) "yho" = ( /obj/structure/table, -/obj/item/radio/intercom/prison, /obj/machinery/duct, -/obj/machinery/light/floor/has_bulb, /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/item/flashlight/lamp{ + pixel_y = 7 + }, /turf/open/floor/iron, /area/station/security/prison) "yhN" = ( @@ -99413,7 +99426,7 @@ cVl fdr tPb yho -oiF +mJO fdr fdr cCD @@ -178627,7 +178640,7 @@ ecW dXo lTc lrQ -xOn +dkU gHp dHv xSZ diff --git a/_maps/~monkestation/RandomEngines/BoxStation/supermatter.dmm b/_maps/~monkestation/RandomEngines/BoxStation/supermatter.dmm index ef45726f6dc0..dfeff3080f4f 100644 --- a/_maps/~monkestation/RandomEngines/BoxStation/supermatter.dmm +++ b/_maps/~monkestation/RandomEngines/BoxStation/supermatter.dmm @@ -173,6 +173,15 @@ /obj/machinery/firealarm/directional/south, /turf/open/floor/engine, /area/station/engineering/supermatter/room) +"eO" = ( +/obj/effect/turf_decal/bot, +/mob/living/basic/pet/poppy, +/obj/structure/bed/dogbed{ + anchored = 1; + name = "Poppy's bed" + }, +/turf/open/floor/iron/dark/smooth_large, +/area/station/engineering/supermatter/room) "fc" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/green/visible, /turf/closed/wall/r_wall, @@ -1992,7 +2001,7 @@ Qi TL IC hr -YW +eO HS ze EI diff --git a/_maps/~monkestation/RandomEngines/MetaStation/supermatter.dmm b/_maps/~monkestation/RandomEngines/MetaStation/supermatter.dmm index 709c3188563d..8090eab80404 100644 --- a/_maps/~monkestation/RandomEngines/MetaStation/supermatter.dmm +++ b/_maps/~monkestation/RandomEngines/MetaStation/supermatter.dmm @@ -818,6 +818,17 @@ /obj/effect/spawner/structure/window/reinforced/plasma, /turf/open/floor/plating, /area/station/engineering/supermatter) +"NK" = ( +/obj/effect/turf_decal/bot{ + dir = 1 + }, +/mob/living/basic/pet/poppy, +/obj/structure/bed/dogbed{ + anchored = 1; + name = "Poppy's bed" + }, +/turf/open/floor/iron/dark, +/area/station/engineering/supermatter/room) "NN" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/visible, @@ -1205,7 +1216,7 @@ wE yn SK Qn -nu +NK nu UI GH diff --git a/_maps/~monkestation/RandomEngines/TramStation/supermatter.dmm b/_maps/~monkestation/RandomEngines/TramStation/supermatter.dmm index 1ee0b187e9ad..479d17a6e334 100644 --- a/_maps/~monkestation/RandomEngines/TramStation/supermatter.dmm +++ b/_maps/~monkestation/RandomEngines/TramStation/supermatter.dmm @@ -93,7 +93,6 @@ dir = 10; network = list("ss13","engine","engineering") }, -/obj/machinery/incident_display/delam/directional/south, /turf/open/floor/engine, /area/station/engineering/supermatter) "fo" = ( @@ -314,6 +313,7 @@ /obj/machinery/atmospherics/components/binary/pump{ name = "Gas to Chamber" }, +/obj/machinery/incident_display/delam/directional/south, /turf/open/floor/engine, /area/station/engineering/supermatter) "lv" = ( @@ -806,6 +806,11 @@ /area/station/engineering/supermatter/room) "Fs" = ( /obj/effect/turf_decal/bot, +/obj/structure/bed/dogbed{ + anchored = 1; + name = "Poppy's bed" + }, +/mob/living/basic/pet/poppy, /turf/open/floor/engine, /area/station/engineering/supermatter/room) "FF" = ( diff --git a/code/__DEFINES/~monkestation/dcs/signals/signals_global.dm b/code/__DEFINES/~monkestation/dcs/signals/signals_global.dm index d090af76972c..7505478a365c 100644 --- a/code/__DEFINES/~monkestation/dcs/signals/signals_global.dm +++ b/code/__DEFINES/~monkestation/dcs/signals/signals_global.dm @@ -1,2 +1,4 @@ /// Sent whenever a new goldeneye key is spawned: (obj/item/goldeneye_key) #define COMSIG_GLOB_GOLDENEYE_KEY_CREATED "!goldeneye_key_created" +/// Sent whenever a camera network broadcast is started/stopped/updated: (camera_net, is_show_active, announcement) +#define COMSIG_GLOB_NETWORK_BROADCAST_UPDATED "!network_broadcast_updated" diff --git a/code/__DEFINES/~monkestation/hud.dm b/code/__DEFINES/~monkestation/hud.dm new file mode 100644 index 000000000000..d423dd120691 --- /dev/null +++ b/code/__DEFINES/~monkestation/hud.dm @@ -0,0 +1 @@ +#define ui_more_under_health_and_to_the_left "EAST-2:14,CENTER-5:29" diff --git a/code/controllers/configuration/entries/monkestation.dm b/code/controllers/configuration/entries/monkestation.dm index c49237131fec..988fae0853c4 100644 --- a/code/controllers/configuration/entries/monkestation.dm +++ b/code/controllers/configuration/entries/monkestation.dm @@ -62,3 +62,13 @@ . = ..() if(.) config_entry_value *= 600 // documented as minutes + +/datum/config_entry/flag/plexora_enabled + +/datum/config_entry/string/plexora_url + default = "http://127.0.0.1:1330" + +/datum/config_entry/string/plexora_url/ValidateAndSet(str_val) + if(!findtext(str_val, GLOB.is_http_protocol)) + return FALSE + return ..() diff --git a/code/datums/martial/cqc.dm b/code/datums/martial/cqc.dm index e982f6488de0..bd81b07a38e5 100644 --- a/code/datums/martial/cqc.dm +++ b/code/datums/martial/cqc.dm @@ -32,17 +32,16 @@ return // monkestation edit: improved messaging cqc_user.visible_message( - span_danger("[cqc_user] twists [attacker]'s arm, sending their [attack_weapon] back towards them!"), - span_userdanger("Making sure to avoid [attacker]'s [attack_weapon], you twist their arm to send it right back at them!"), + span_danger("[cqc_user] twists [attacker]'s arm, sending [attacker.p_their()] [attack_weapon] back towards [attacker.p_them()]!"), + span_userdanger("Making sure to avoid [attacker]'s [attack_weapon], you twist [attacker.p_their()] arm to send it right back at [attacker.p_them()]!"), ignored_mobs = list(attacker), ) to_chat(attacker, span_userdanger("[cqc_user] swiftly grabs and twists your arm, hitting you with your own [attack_weapon]!"), type = MESSAGE_TYPE_COMBAT) // monkestation end var/obj/item/melee/touch_attack/touch_weapon = attack_weapon var/datum/action/cooldown/spell/touch/touch_spell = touch_weapon.spell_which_made_us?.resolve() - if(!touch_spell) - return - INVOKE_ASYNC(touch_spell, TYPE_PROC_REF(/datum/action/cooldown/spell/touch, do_hand_hit), touch_weapon, attacker, attacker) + if(touch_spell) + INVOKE_ASYNC(touch_spell, TYPE_PROC_REF(/datum/action/cooldown/spell/touch, do_hand_hit), touch_weapon, attacker, attacker) return COMPONENT_NO_AFTERATTACK /datum/martial_art/cqc/reset_streak(mob/living/new_target) @@ -242,7 +241,7 @@ if(prob(65)) if(!defender.stat || !defender.IsParalyzed() || !restraining_mob) held_item = defender.get_active_held_item() - defender.visible_message(span_danger("[attacker] strikes [defender]'s jaw with their hand!"), \ + defender.visible_message(span_danger("[attacker] strikes [defender]'s jaw with [attacker.p_their()] hand!"), \ span_userdanger("Your jaw is struck by [attacker], you feel disoriented!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), COMBAT_MESSAGE_RANGE, attacker) to_chat(attacker, span_danger("You strike [defender]'s jaw, leaving [defender.p_them()] disoriented!")) playsound(get_turf(defender), 'sound/weapons/cqchit1.ogg', 50, TRUE, -1) diff --git a/code/datums/martial/sleeping_carp.dm b/code/datums/martial/sleeping_carp.dm index 56bd900fdf8d..4279e8d08dc4 100644 --- a/code/datums/martial/sleeping_carp.dm +++ b/code/datums/martial/sleeping_carp.dm @@ -13,7 +13,7 @@ var/deflect_cooldown = 3 SECONDS //monke edit start var/deflect_stamcost = 15 //how much stamina it costs per bullet deflected var/log_name = "Sleeping Carp" - var/damage = 0 + var/damage = 20 var/kick_speed = 0 //how fast you get punted into the stratosphere on launchkick var/wounding = 0 //whether or not you get wounded by the attack var/zone_message = "" //string for where the attack is targetting @@ -52,31 +52,41 @@ return FALSE ///Gnashing Teeth: Harm Harm, consistent 20 force punch on every second harm punch -/datum/martial_art/the_sleeping_carp/proc/strongPunch(mob/living/attacker, mob/living/defender) - damage = 20 - wounding = 0 +/datum/martial_art/the_sleeping_carp/proc/strongPunch(mob/living/attacker, mob/living/defender, set_damage = TRUE) + if(set_damage) + damage = 20 + wounding = 0 ///this var is so that the strong punch is always aiming for the body part the user is targeting and not trying to apply to the chest before deviating var/obj/item/bodypart/affecting = defender.get_bodypart(defender.get_random_valid_zone(attacker.zone_selected)) attacker.do_attack_animation(defender, ATTACK_EFFECT_PUNCH) var/atk_verb = pick("precisely kick", "brutally chop", "cleanly hit", "viciously slam") - defender.visible_message(span_danger("[attacker] [atk_verb]s [defender]!"), \ - span_userdanger("[attacker] [atk_verb]s you!"), null, null, attacker) + defender.visible_message( + span_danger("[attacker] [atk_verb]s [defender]!"), + span_userdanger("[attacker] [atk_verb]s you!"), + ignored_mobs = attacker + ) to_chat(attacker, span_danger("You [atk_verb] [defender]!")) playsound(defender, 'sound/weapons/punch1.ogg', vol = 25, vary = TRUE, extrarange = -1) log_combat(attacker, defender, "strong punched ([log_name])") //monke edit defender.apply_damage(damage, attacker.get_attack_type(), affecting, wound_bonus = wounding) - return ///Crashing Wave Kick: Harm Disarm combo, throws people seven tiles backwards -/datum/martial_art/the_sleeping_carp/proc/launchKick(mob/living/attacker, mob/living/defender) - damage = 15 //monke edit start - kick_speed = 4 - wounding = CANT_WOUND - zone_message = "chest" - zone = BODY_ZONE_CHEST +/datum/martial_art/the_sleeping_carp/proc/launchKick(mob/living/attacker, mob/living/defender, set_damage = TRUE) + //monke edit start + if(set_damage) + damage = 15 + kick_speed = 4 + wounding = CANT_WOUND + zone_message = "chest" + zone = BODY_ZONE_CHEST attacker.do_attack_animation(defender, ATTACK_EFFECT_KICK) - defender.visible_message(span_warning("[attacker] kicks [defender] square in the [zone_message], sending them flying!"), \ - span_userdanger("You are kicked square in the [zone_message] by [attacker], sending you flying!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), COMBAT_MESSAGE_RANGE, attacker) + defender.visible_message( + span_warning("[attacker] kicks [defender] square in the [zone_message], sending [defender.p_them()] flying!"), + span_userdanger("You are kicked square in the [zone_message] by [attacker], sending you flying!"), + span_hear("You hear a sickening sound of flesh hitting flesh!"), + vision_distance = COMBAT_MESSAGE_RANGE, + ignored_mobs = attacker, + ) playsound(get_turf(attacker), 'sound/effects/hit_kick.ogg', vol = 50, vary = TRUE, extrarange = -1) var/atom/throw_target = get_edge_target_turf(defender, attacker.dir) defender.throw_at(throw_target, 7, kick_speed, attacker) @@ -85,24 +95,30 @@ return ///Keelhaul: Disarm Disarm combo, knocks people down and deals substantial stamina damage, and also discombobulates them. Knocks objects out of their hands if they're already on the ground. -/datum/martial_art/the_sleeping_carp/proc/dropKick(mob/living/attacker, mob/living/defender) - stamina_damage = 100 //monke edit start +/datum/martial_art/the_sleeping_carp/proc/dropKick(mob/living/attacker, mob/living/defender, set_damage = TRUE) + //monke edit start + if(set_damage) + stamina_damage = 100 attacker.do_attack_animation(defender, ATTACK_EFFECT_KICK) playsound(get_turf(attacker), 'sound/effects/hit_kick.ogg', vol = 50, vary = TRUE, extrarange = -1) if(defender.body_position == STANDING_UP) defender.Knockdown(2 SECONDS) defender.visible_message( - span_warning("[attacker] kicks [defender] in the head, sending them face first into the floor!"), + span_warning("[attacker] kicks [defender] in the head, sending [defender.p_them()] face first into the floor!"), span_userdanger("You are kicked in the head by [attacker], sending you crashing to the floor!"), - span_hear("You hear a sickening sound of flesh hitting flesh!"), COMBAT_MESSAGE_RANGE, attacker - ) + span_hear("You hear a sickening sound of flesh hitting flesh!"), + vision_distance = COMBAT_MESSAGE_RANGE, + ignored_mobs = attacker, + ) else defender.drop_all_held_items() defender.visible_message( span_warning("[attacker] kicks [defender] in the head!"), span_userdanger("You are kicked in the head by [attacker]!"), - span_hear("You hear a sickening sound of flesh hitting flesh!"), COMBAT_MESSAGE_RANGE, attacker - ) + span_hear("You hear a sickening sound of flesh hitting flesh!"), + vision_distance = COMBAT_MESSAGE_RANGE, + ignored_mobs = attacker, + ) defender.stamina.adjust(stamina_damage) defender.adjust_dizzy_up_to(10 SECONDS, 10 SECONDS) defender.adjust_temp_blindness_up_to(2 SECONDS, 10 SECONDS) @@ -121,7 +137,7 @@ playsound(defender, 'sound/weapons/punch1.ogg', vol = 25, vary = TRUE, extrarange = -1) if(defender.stat != DEAD && !defender.IsUnconscious() && defender.stamina.current <= 50) //We put our target to sleep. defender.visible_message( - span_danger("[attacker] carefully pinch a nerve in [defender]'s neck, knocking them out cold"), + span_danger("[attacker] carefully pinch a nerve in [defender]'s neck, knocking [defender.p_them()] out cold"), span_userdanger("[attacker] pinches something in your neck, and you fall unconscious!"), ) grab_log_description = "grabbed and nerve pinched" @@ -143,9 +159,9 @@ span_danger("[attacker] snaps the neck of [defender]!"), span_userdanger("Your neck is snapped by [attacker]!"), span_hear("You hear a sickening snap!"), - ignored_mobs = attacker + ignored_mobs = attacker, ) - to_chat(attacker, span_danger("In a swift motion, you snap the neck of [defender]!")) + to_chat(attacker, span_danger("In a swift motion, you snap the neck of [defender]!"), type = MESSAGE_TYPE_COMBAT) log_combat(attacker, defender, "snapped neck") defender.apply_damage(100, BRUTE, BODY_ZONE_HEAD, wound_bonus=CANT_WOUND) if(!HAS_TRAIT(defender, TRAIT_NODEATH)) @@ -164,7 +180,7 @@ span_danger("[attacker] [atk_verb]s [defender]!"), span_userdanger("[attacker] [atk_verb]s you!"), null, null, attacker ) - to_chat(attacker, span_danger("You [atk_verb] [defender]!")) + to_chat(attacker, span_danger("You [atk_verb] [defender]!"), type = MESSAGE_TYPE_COMBAT) defender.apply_damage(rand(10,15), attacker.get_attack_type(), affecting, wound_bonus = CANT_WOUND) playsound(defender, 'sound/weapons/punch1.ogg', 25, TRUE, -1) @@ -186,12 +202,12 @@ return ..() -/datum/martial_art/the_sleeping_carp/proc/can_deflect(mob/living/carp_user) +/datum/martial_art/the_sleeping_carp/proc/can_deflect(mob/living/carp_user, check_intent = TRUE) if(!COOLDOWN_FINISHED(src, block_cooldown)) //monke edit return FALSE if(!can_use(carp_user)) return FALSE - if(!(carp_user.istate & ISTATE_HARM)) // monke edit: istates/intents + if(check_intent && !(carp_user.istate & ISTATE_HARM)) // monke edit: istates/intents return FALSE if(carp_user.incapacitated(IGNORE_GRAB)) //NO STUN return FALSE @@ -222,10 +238,11 @@ return COMPONENT_BULLET_PIERCED ///Signal from getting attacked with an item, for a special interaction with touch spells -/datum/martial_art/the_sleeping_carp/proc/on_attackby(mob/living/carbon/human/carp_user, obj/item/attack_weapon, mob/attacker, params) //no signal handler or this proc will explode - if(!istype(attack_weapon, /obj/item/melee/touch_attack) || !can_deflect(carp_user)) +/datum/martial_art/the_sleeping_carp/proc/on_attackby(mob/living/carbon/human/carp_user, obj/item/melee/touch_attack/touch_weapon, mob/attacker, params) + SIGNAL_HANDLER + + if(!istype(touch_weapon) || !can_deflect(carp_user, check_intent = !touch_weapon.dangerous)) return - var/obj/item/melee/touch_attack/touch_weapon = attack_weapon var/datum/action/cooldown/spell/touch/touch_spell = touch_weapon.spell_which_made_us?.resolve() // monkestation edit: flavor tweaks if(!counter) @@ -239,15 +256,15 @@ playsound(carp_user, 'monkestation/sound/effects/miss.ogg', vol = 50, vary = TRUE, extrarange = SHORT_RANGE_SOUND_EXTRARANGE) else carp_user.visible_message( - span_danger("[carp_user] twists [attacker]'s arm, sending their [attack_weapon] back towards them!"), - span_userdanger("Making sure to avoid [attacker]'s [attack_weapon], you twist their arm to send it right back at them!"), - ignored_mobs = list(attacker), - ) - to_chat(attacker, span_userdanger("[carp_user] swiftly grabs and twists your arm, hitting you with your own [attack_weapon]!"), type = MESSAGE_TYPE_COMBAT) - carp_user.say(message = "PATHETIC!", language = /datum/language/common, ignore_spam = TRUE, forced = src) - if(!touch_spell) - return - INVOKE_ASYNC(touch_spell, TYPE_PROC_REF(/datum/action/cooldown/spell/touch, do_hand_hit), touch_weapon, attacker, attacker) + span_danger("[carp_user] twists [attacker]'s arm, sending [attacker.p_their()] [touch_weapon] back towards [attacker.p_them()]!"), + span_userdanger("Making sure to avoid [attacker]'s [touch_weapon], you twist [attacker.p_their()] arm to send it right back at [attacker.p_them()]!"), + ignored_mobs = list(attacker), + ) + to_chat(attacker, span_userdanger("[carp_user] swiftly grabs and twists your arm, hitting you with your own [touch_weapon]!"), type = MESSAGE_TYPE_COMBAT) + INVOKE_ASYNC(carp_user, TYPE_PROC_REF(/atom/movable, say), message = "PATHETIC!", language = /datum/language/common, ignore_spam = TRUE, forced = src) + if(touch_spell) + INVOKE_ASYNC(touch_spell, TYPE_PROC_REF(/datum/action/cooldown/spell/touch, do_hand_hit), touch_weapon, attacker, attacker) + attacker.changeNext_move(CLICK_CD_MELEE) // monkestation end return COMPONENT_NO_AFTERATTACK diff --git a/code/datums/quirks/_quirk.dm b/code/datums/quirks/_quirk.dm index b470ad4d4f48..e685c0236934 100644 --- a/code/datums/quirks/_quirk.dm +++ b/code/datums/quirks/_quirk.dm @@ -33,10 +33,18 @@ /// The base weight for the each quirk's mail goodies list to be selected is 5 /// then the item selected is determined by pick(selected_quirk.mail_goodies) var/list/mail_goodies = list() //Monkestation Edit BLOOD_DATUM: Why? this is already a list all this does is mess confuse us. - /// The minimum stat where this quirk can process (if it has QUIRK_PROCESSES) - var/minimum_process_stat = HARD_CRIT + /// The maximum stat below which this quirk can process (if it has QUIRK_PROCESSES), and above which it stops. + var/maximum_process_stat = HARD_CRIT /// A list of additional signals to register with update_process() var/list/process_update_signals + /// A list of traits that should stop this quirk from processing. + /// Signals for adding and removing this trait will automatically be added to `process_update_signals`. + var/list/no_process_traits + +/datum/quirk/New() + . = ..() + for(var/trait in no_process_traits) + LAZYADD(process_update_signals, list(SIGNAL_ADDTRAIT(trait), SIGNAL_REMOVETRAIT(trait))) /datum/quirk/Destroy() if(quirk_holder) @@ -81,7 +89,8 @@ add(client_source) if(quirk_flags & QUIRK_PROCESSES) - RegisterSignal(quirk_holder, COMSIG_MOB_STATCHANGE, PROC_REF(on_stat_changed)) + if(!isnull(maximum_process_stat)) + RegisterSignal(quirk_holder, COMSIG_MOB_STATCHANGE, PROC_REF(on_stat_changed)) if(process_update_signals) RegisterSignals(quirk_holder, process_update_signals, PROC_REF(update_process)) if(should_process()) @@ -161,7 +170,16 @@ /datum/quirk/proc/should_process() SHOULD_CALL_PARENT(TRUE) SHOULD_BE_PURE(TRUE) - return (quirk_flags & QUIRK_PROCESSES) && !QDELETED(quirk_holder) && quirk_holder.stat <= minimum_process_stat + if(QDELETED(quirk_holder)) + return FALSE + if(!(quirk_flags & QUIRK_PROCESSES)) + return FALSE + if(!isnull(maximum_process_stat) && quirk_holder.stat >= maximum_process_stat) + return FALSE + for(var/trait in no_process_traits) + if(HAS_TRAIT(quirk_holder, trait)) + return FALSE + return TRUE /// Checks to see if the quirk should be processing, and starts/stops it. /datum/quirk/proc/update_process() diff --git a/code/datums/quirks/negative_quirks/allergic.dm b/code/datums/quirks/negative_quirks/allergic.dm index 371c5d691c38..86999706ba8f 100644 --- a/code/datums/quirks/negative_quirks/allergic.dm +++ b/code/datums/quirks/negative_quirks/allergic.dm @@ -9,10 +9,7 @@ hardcore_value = 3 quirk_flags = QUIRK_HUMAN_ONLY | QUIRK_PROCESSES mail_goodies = list(/obj/item/reagent_containers/hypospray/medipen) // epinephrine medipen stops allergic reactions - process_update_signals = list( - SIGNAL_ADDTRAIT(TRAIT_STASIS), - SIGNAL_REMOVETRAIT(TRAIT_STASIS), - ) + no_process_traits = list(TRAIT_STASIS) var/list/allergies = list() var/list/blacklist = list( /datum/reagent/medicine/c2, @@ -64,6 +61,3 @@ if(SPT_PROB(10, seconds_per_tick)) carbon_quirk_holder.vomit() carbon_quirk_holder.adjustOrganLoss(pick(ORGAN_SLOT_BRAIN,ORGAN_SLOT_APPENDIX,ORGAN_SLOT_LUNGS,ORGAN_SLOT_HEART,ORGAN_SLOT_LIVER,ORGAN_SLOT_STOMACH),10) - -/datum/quirk/item_quirk/allergic/should_process() - return iscarbon(quirk_holder) && ..() && !HAS_TRAIT(quirk_holder, TRAIT_STASIS) diff --git a/code/datums/quirks/negative_quirks/brain_problems.dm b/code/datums/quirks/negative_quirks/brain_problems.dm index 2f9165f20961..2f6d24c461a2 100644 --- a/code/datums/quirks/negative_quirks/brain_problems.dm +++ b/code/datums/quirks/negative_quirks/brain_problems.dm @@ -14,10 +14,7 @@ hardcore_value = 12 quirk_flags = QUIRK_HUMAN_ONLY | QUIRK_PROCESSES | QUIRK_DONT_CLONE // monkestation edit: QUIRK_DONT_CLONE (the cloner isn't gonna clone ur tumor lol) mail_goodies = list(/obj/item/storage/pill_bottle/mannitol/braintumor) - process_update_signals = list( - SIGNAL_ADDTRAIT(TRAIT_TUMOR_SUPPRESSED), - SIGNAL_REMOVETRAIT(TRAIT_TUMOR_SUPPRESSED), - ) + no_process_traits = list(TRAIT_TUMOR_SUPPRESSED) /datum/quirk/item_quirk/brainproblems/add_unique(client/client_source) give_item_to_holder( @@ -33,6 +30,3 @@ /datum/quirk/item_quirk/brainproblems/process(seconds_per_tick) quirk_holder.adjustOrganLoss(ORGAN_SLOT_BRAIN, 0.2 * seconds_per_tick) - -/datum/quirk/item_quirk/brainproblems/should_process() - return ..() && !HAS_TRAIT(quirk_holder, TRAIT_TUMOR_SUPPRESSED) diff --git a/code/datums/quirks/negative_quirks/claustrophobia.dm b/code/datums/quirks/negative_quirks/claustrophobia.dm index c84b8770bbbf..1861abf8ec4e 100644 --- a/code/datums/quirks/negative_quirks/claustrophobia.dm +++ b/code/datums/quirks/negative_quirks/claustrophobia.dm @@ -6,12 +6,9 @@ medical_record_text = "Patient demonstrates a fear of tight spaces." hardcore_value = 5 quirk_flags = QUIRK_HUMAN_ONLY | QUIRK_PROCESSES - minimum_process_stat = CONSCIOUS + maximum_process_stat = SOFT_CRIT mail_goodies = list(/obj/item/reagent_containers/syringe/convermol) // to help breathing - process_update_signals = list( - SIGNAL_ADDTRAIT(TRAIT_FEARLESS), - SIGNAL_REMOVETRAIT(TRAIT_FEARLESS), - ) + no_process_traits = list(TRAIT_FEARLESS) /datum/quirk/claustrophobia/remove() quirk_holder.clear_mood_event("claustrophobia") @@ -36,9 +33,6 @@ else to_chat(quirk_holder, span_warning("You feel trapped! Must escape... can't breathe...")) -/datum/quirk/claustrophobia/should_process() - return ..() && !HAS_TRAIT(quirk_holder, TRAIT_FEARLESS) - ///investigates whether possible_saint_nick possesses a high level of christmas cheer /datum/quirk/claustrophobia/proc/evaluate_jolly_levels(mob/living/carbon/human/possible_saint_nick) if(!istype(possible_saint_nick)) diff --git a/code/datums/quirks/negative_quirks/junkie.dm b/code/datums/quirks/negative_quirks/junkie.dm index 539cd953c516..6ac9ac705011 100644 --- a/code/datums/quirks/negative_quirks/junkie.dm +++ b/code/datums/quirks/negative_quirks/junkie.dm @@ -8,10 +8,7 @@ hardcore_value = 4 quirk_flags = QUIRK_HUMAN_ONLY | QUIRK_PROCESSES | QUIRK_DONT_CLONE mail_goodies = list(/obj/effect/spawner/random/contraband/narcotics) - process_update_signals = list( - SIGNAL_ADDTRAIT(TRAIT_LIVERLESS_METABOLISM), - SIGNAL_REMOVETRAIT(TRAIT_LIVERLESS_METABOLISM), - ) + no_process_traits = list(TRAIT_LIVERLESS_METABOLISM) var/drug_list = list(/datum/reagent/drug/blastoff, /datum/reagent/drug/krokodil, /datum/reagent/medicine/painkiller/morphine, /datum/reagent/drug/happiness, /datum/reagent/drug/methamphetamine) //List of possible IDs var/datum/reagent/reagent_type //!If this is defined, reagent_id will be unused and the defined reagent type will be instead. var/datum/reagent/reagent_instance //! actual instanced version of the reagent @@ -86,9 +83,6 @@ for(var/addiction in reagent_instance.addiction_types) human_holder.last_mind?.add_addiction_points(addiction, 1000) ///Max that shit out -/datum/quirk/item_quirk/junkie/should_process() - return ..() && !HAS_TRAIT(quirk_holder, TRAIT_LIVERLESS_METABOLISM) - /datum/quirk/item_quirk/junkie/smoker name = "Smoker" desc = "Sometimes you just really want a smoke. Probably not great for your lungs." diff --git a/code/datums/quirks/positive_quirks/drunk_healing.dm b/code/datums/quirks/positive_quirks/drunk_healing.dm index cb9572896cb1..a565c78cc9b4 100644 --- a/code/datums/quirks/positive_quirks/drunk_healing.dm +++ b/code/datums/quirks/positive_quirks/drunk_healing.dm @@ -7,7 +7,7 @@ lose_text = span_danger("You no longer feel like drinking would ease your pain.") medical_record_text = "Patient has unusually efficient liver metabolism and can slowly regenerate wounds by drinking alcoholic beverages." quirk_flags = QUIRK_HUMAN_ONLY | QUIRK_PROCESSES - minimum_process_stat = DEAD // it processed before while dead, so I'm keeping it that way + maximum_process_stat = DEAD // it processed before while dead, so I'm keeping it that way mail_goodies = list(/obj/effect/spawner/random/food_or_drink/booze) /datum/quirk/drunkhealing/process(seconds_per_tick) diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index 4c14051481c3..939115953f8b 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -213,7 +213,7 @@ move_packet = null if(spatial_grid_key) - SSspatial_grid.force_remove_from_cell(src) + SSspatial_grid.force_remove_from_grid(src) LAZYNULL(client_mobs_in_contents) diff --git a/code/game/machinery/computer/telescreen.dm b/code/game/machinery/computer/telescreen.dm index ac49361fa2da..21531e8f5295 100644 --- a/code/game/machinery/computer/telescreen.dm +++ b/code/game/machinery/computer/telescreen.dm @@ -58,17 +58,19 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai /obj/machinery/computer/security/telescreen/entertainment/Initialize(mapload) . = ..() RegisterSignal(src, COMSIG_CLICK, PROC_REF(BigClick)) + RegisterSignal(SSdcs, COMSIG_GLOB_NETWORK_BROADCAST_UPDATED, PROC_REF(on_network_broadcast_updated)) // monkestation edit: convert to signal handler speakers = new(src) /obj/machinery/computer/security/telescreen/entertainment/Destroy() - . = ..() + UnregisterSignal(SSdcs, COMSIG_GLOB_NETWORK_BROADCAST_UPDATED) // monkestation edit: convert to signal handler QDEL_NULL(speakers) + return ..() // Bypass clickchain to allow humans to use the telescreen from a distance /obj/machinery/computer/security/telescreen/entertainment/proc/BigClick() SIGNAL_HANDLER - if(!network.len) + if(!length(network)) balloon_alert(usr, "nothing on TV!") return @@ -84,7 +86,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai say(announcement) /// Adds a camera network ID to the entertainment monitor, and turns off the monitor if network list is empty -/obj/machinery/computer/security/telescreen/entertainment/proc/update_shows(is_show_active, tv_show_id, announcement) +/obj/machinery/computer/security/telescreen/entertainment/proc/on_network_broadcast_updated(datum/source, tv_show_id, is_show_active, announcement) // monkestation edit: convert to signal handler + SIGNAL_HANDLER if(!network) return @@ -93,7 +96,8 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai else network -= tv_show_id - notify(network.len, announcement) + INVOKE_ASYNC(src, TYPE_PROC_REF(/datum, update_static_data_for_all_viewers)) // monkestation edit: ensure static data is always updated + notify(length(network), announcement) /** * Adds a camera network to all entertainment monitors. @@ -102,12 +106,15 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai * * announcement - Optional, what announcement to make when the show starts. */ /proc/start_broadcasting_network(camera_net, announcement) + SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NETWORK_BROADCAST_UPDATED, camera_net, TRUE, announcement) +/* monkestation edit: convert to global signal for(var/obj/machinery/computer/security/telescreen/entertainment/tv as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/computer/security/telescreen/entertainment)) tv.update_shows( is_show_active = TRUE, tv_show_id = camera_net, announcement = announcement, ) +monkestation end */ /** * Removes a camera network from all entertainment monitors. @@ -116,12 +123,15 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai * * announcement - Optional, what announcement to make when the show ends. */ /proc/stop_broadcasting_network(camera_net, announcement) + SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NETWORK_BROADCAST_UPDATED, camera_net, FALSE, announcement) +/* monkestation edit: convert to global signal for(var/obj/machinery/computer/security/telescreen/entertainment/tv as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/computer/security/telescreen/entertainment)) tv.update_shows( is_show_active = FALSE, tv_show_id = camera_net, announcement = announcement, ) +monkestation end */ /** * Sets the camera network status on all entertainment monitors. @@ -135,12 +145,15 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/entertai * Likewise, there's no way to differentiate off -> on and on -> off, unless you handle that yourself. */ /proc/set_network_broadcast_status(camera_net, is_show_active, announcement) + SEND_GLOBAL_SIGNAL(COMSIG_GLOB_NETWORK_BROADCAST_UPDATED, camera_net, is_show_active, announcement) +/* monkestation edit: convert to global signal for(var/obj/machinery/computer/security/telescreen/entertainment/tv as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/computer/security/telescreen/entertainment)) tv.update_shows( is_show_active = is_show_active, tv_show_id = camera_net, announcement = announcement, ) +monkestation end */ /obj/machinery/computer/security/telescreen/rd name = "\improper Research Director's telescreen" diff --git a/code/game/objects/items/devices/broadcast_camera.dm b/code/game/objects/items/devices/broadcast_camera.dm index 83dbfe7c1559..488450e8ad8b 100644 --- a/code/game/objects/items/devices/broadcast_camera.dm +++ b/code/game/objects/items/devices/broadcast_camera.dm @@ -35,7 +35,6 @@ /obj/item/broadcast_camera/Initialize(mapload) . = ..() - AddElement(/datum/element/empprotection, EMP_PROTECT_ALL) /obj/item/broadcast_camera/Destroy(force) @@ -47,21 +46,22 @@ icon_state = "[base_icon_state][active]" return ..() -/obj/item/broadcast_camera/attack_self(mob/user, modifiers) +/obj/item/broadcast_camera/attack_self(mob/living/user, modifiers) . = ..() active = !active if(active) on_activating() else + user.remove_status_effect(/datum/status_effect/streamer, internal_camera) on_deactivating() /obj/item/broadcast_camera/attack_self_secondary(mob/user, modifiers) . = ..() - broadcast_name = tgui_input_text(user = user, title = "Broadcast Name", message = "What will be the name of your broadcast?", default = "[broadcast_name]", max_length = MAX_CHARTER_LEN) + broadcast_name = tgui_input_text(user = user, title = "Broadcast Name", message = "What will be the name of your broadcast?", default = "[broadcast_name]", max_length = MAX_CHARTER_LEN, encode = FALSE) /obj/item/broadcast_camera/examine(mob/user) . = ..() - . += span_notice("Broadcast name is [broadcast_name]") + . += span_notice("Broadcast name is [html_encode(broadcast_name)]") . += span_notice("The microphone is [active_microphone ? "On" : "Off"]") /obj/item/broadcast_camera/on_enter_storage(datum/storage/master_storage) @@ -69,25 +69,29 @@ if(active) on_deactivating() -/obj/item/broadcast_camera/dropped(mob/user, silent) +/obj/item/broadcast_camera/dropped(mob/living/user, silent) . = ..() if(active) + user?.remove_status_effect(/datum/status_effect/streamer, internal_camera) on_deactivating() /// When activating the camera /obj/item/broadcast_camera/proc/on_activating() - if(!iscarbon(loc)) + if(!isliving(loc)) + return + /// The mob who wielded the camera, allegedly + var/mob/living/wielder = loc + if(!wielder.is_holding(src)) return active = TRUE update_icon_state() - /// The carbon who wielded the camera, allegedly - var/mob/living/carbon/wielding_carbon = loc // INTERNAL CAMERA - internal_camera = new(wielding_carbon) // Cameras for some reason do not work inside of obj's + internal_camera = new(wielder) // Cameras for some reason do not work inside of obj's internal_camera.internal_light = FALSE internal_camera.network = camera_networks internal_camera.c_tag = "LIVE: [broadcast_name]" + wielder.apply_status_effect(/datum/status_effect/streamer, internal_camera, CALLBACK(src, PROC_REF(ensure_still_active))) start_broadcasting_network(camera_networks, "[broadcast_name] is now LIVE!") // INTERNAL RADIO @@ -112,6 +116,16 @@ playsound(source = src, soundin = 'sound/machines/terminal_prompt_deny.ogg', vol = 20, vary = FALSE, ignore_walls = FALSE) balloon_alert_to_viewers("offline") +/obj/item/broadcast_camera/proc/ensure_still_active() + if(!active) + return FALSE + if(!isliving(loc)) + return FALSE + var/mob/living/wielder = loc + if(!wielder.is_holding(src)) + return FALSE + return TRUE + /obj/item/broadcast_camera/AltClick(mob/user) if(!user.can_perform_action(src, NEED_DEXTERITY|FORBID_TELEKINESIS_REACH)) return diff --git a/code/modules/admin/holder2.dm b/code/modules/admin/holder2.dm index 94fde875336c..dd2fcc1fea98 100644 --- a/code/modules/admin/holder2.dm +++ b/code/modules/admin/holder2.dm @@ -75,7 +75,6 @@ GLOBAL_PROTECT(href_token) activate() else deactivate() - plane_debug = new(src) /datum/admins/Destroy() if(IsAdminAdvancedProcCall()) @@ -96,7 +95,7 @@ GLOBAL_PROTECT(href_token) deadmined = FALSE if(owner) rementor(owner) - QDEL_NULL(plane_debug) + plane_debug = new(src) if (GLOB.directory[target]) associate(GLOB.directory[target]) //find the client for a ckey if they are connected and associate them with us @@ -109,6 +108,7 @@ GLOBAL_PROTECT(href_token) return GLOB.deadmins[target] = src GLOB.admin_datums -= target + QDEL_NULL(plane_debug) if(owner) dementor(owner) diff --git a/code/modules/food_and_drinks/machinery/smartfridge.dm b/code/modules/food_and_drinks/machinery/smartfridge.dm index eacf09e02f6b..80c5ca3fc694 100644 --- a/code/modules/food_and_drinks/machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/machinery/smartfridge.dm @@ -521,8 +521,8 @@ /obj/machinery/smartfridge/chemistry/virology/preloaded initial_contents = list( /obj/item/reagent_containers/syringe/antiviral = 4, - /obj/item/reagent_containers/cup/bottle/cold = 1, - /obj/item/reagent_containers/cup/bottle/flu_virion = 1, + // /obj/item/reagent_containers/cup/bottle/cold = 1, + // /obj/item/reagent_containers/cup/bottle/flu_virion = 1, Monkestation removal, Old viro code /obj/item/reagent_containers/cup/bottle/mutagen = 1, /obj/item/reagent_containers/cup/bottle/sugar = 1, /obj/item/reagent_containers/cup/bottle/plasma = 1, diff --git a/code/modules/mob/living/carbon/carbon.dm b/code/modules/mob/living/carbon/carbon.dm index e665c4bf3ee8..9b69ce808959 100644 --- a/code/modules/mob/living/carbon/carbon.dm +++ b/code/modules/mob/living/carbon/carbon.dm @@ -192,7 +192,7 @@ if (!bulky && prob(50)) return visible_message(span_danger("[src] looses [src.p_their()] balance."), \ - span_danger("You loose your balance.")) + span_danger("You lose your balance.")) Knockdown(2 SECONDS) //MONKESTATION EDIT END diff --git a/code/modules/mob/living/carbon/death.dm b/code/modules/mob/living/carbon/death.dm index 45fc9ba947da..18f0ab2c210b 100644 --- a/code/modules/mob/living/carbon/death.dm +++ b/code/modules/mob/living/carbon/death.dm @@ -51,7 +51,7 @@ var/org_zone = check_zone(organ.zone) //both groin and chest organs. if(org_zone != BODY_ZONE_CHEST) continue - organs.Remove(organ) + organ.Remove(src) organ.forceMove(Tsec) organ.fly_away(Tsec, horizontal_multiplier = 2, vertical_multiplier = 1.2) else @@ -62,7 +62,7 @@ if(no_organs && !istype(organ, /obj/item/organ/internal/brain)) qdel(organ) continue - organs.Remove(organ) + organ.Remove(src) organ.forceMove(Tsec) organ.fly_away(Tsec, horizontal_multiplier = 2, vertical_multiplier = 1.2) diff --git a/code/modules/mob/living/simple_animal/bot/secbot.dm b/code/modules/mob/living/simple_animal/bot/secbot.dm index d3b2bb374ff6..274a1c708248 100644 --- a/code/modules/mob/living/simple_animal/bot/secbot.dm +++ b/code/modules/mob/living/simple_animal/bot/secbot.dm @@ -51,6 +51,8 @@ ///The department the secbot will deposit collected money into var/payment_department = ACCOUNT_SEC + var/stamina_damage = 95 //3 hit stam crit from full, but they most likely wont be due to running a bit + /mob/living/simple_animal/bot/secbot/beepsky name = "Commander Beep O'sky" desc = "It's Commander Beep O'sky! Officially the superior officer of all bots on station, Beepsky remains as humble and dedicated to the law as the day he was first fabricated." @@ -321,7 +323,7 @@ back_to_idle() /mob/living/simple_animal/bot/secbot/proc/stun_attack(mob/living/carbon/current_target, harm = FALSE) - var/judgement_criteria = judgement_criteria() + //var/judgement_criteria = judgement_criteria() playsound(src, 'sound/weapons/egloves.ogg', 50, TRUE, -1) icon_state = "[initial(icon_state)]-c" addtimer(CALLBACK(src, TYPE_PROC_REF(/atom, update_appearance)), 0.2 SECONDS) @@ -329,15 +331,17 @@ if(harm) weapon.attack(current_target, src) + + // monkestation start: check shields and baton resistance, deal stamina damage if(ishuman(current_target)) - current_target.set_stutter(10 SECONDS) - current_target.Paralyze(100) var/mob/living/carbon/human/human_target = current_target - threat = human_target.assess_threat(judgement_criteria, weaponcheck = CALLBACK(src, PROC_REF(check_for_weapons))) + if(human_target.check_shields(src, 0, "\the [name]", MELEE_ATTACK)) + return + if(HAS_TRAIT(current_target, TRAIT_BATON_RESISTANCE)) + current_target.stamina.adjust_to(-stamina_damage, current_target.stamina.maximum * 0.29) else - current_target.Paralyze(100) - current_target.set_stutter(10 SECONDS) - threat = current_target.assess_threat(judgement_criteria, weaponcheck = CALLBACK(src, PROC_REF(check_for_weapons))) + current_target.stamina.adjust(-stamina_damage) + // monkestation end log_combat(src, current_target, "stunned") if(security_mode_flags & SECBOT_DECLARE_ARRESTS) diff --git a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm index c9c55baabd26..6218c46124bd 100644 --- a/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm +++ b/code/modules/mob/living/simple_animal/hostile/megafauna/drake.dm @@ -183,7 +183,7 @@ return FALSE return ..() -/mob/living/simple_animal/hostile/megafauna/dragon/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs, visible_message_flags = NONE) +/mob/living/simple_animal/hostile/megafauna/dragon/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs, visible_message_flags = NONE, atom/push_appearance) if(swooping & SWOOP_INVULNERABLE) //to suppress attack messages without overriding every single proc that could send a message saying we got hit return return ..() diff --git a/code/modules/mob/mob.dm b/code/modules/mob/mob.dm index 978be4255fca..131cac527030 100644 --- a/code/modules/mob/mob.dm +++ b/code/modules/mob/mob.dm @@ -265,12 +265,16 @@ * * blind_message (optional) is what blind people will hear e.g. "You hear something!" * * vision_distance (optional) define how many tiles away the message can be seen. * * ignored_mob (optional) doesn't show any message to a given mob if TRUE. + * * push_appearance(optional) pushes an atom's appearance to all viewing mobs, for use with */ -/atom/proc/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs, visible_message_flags = NONE) +/atom/proc/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs, visible_message_flags = NONE, atom/push_appearance) var/turf/T = get_turf(src) if(!T) return + if(!isnull(push_appearance) && !isatom(push_appearance)) + stack_trace("push_appearance must be an atom, but got [push_appearance] instead") + if(!islist(ignored_mobs)) ignored_mobs = list(ignored_mobs) var/list/hearers = get_hearers_in_view(vision_distance, src) //caches the hearers and then removes ignored mobs. @@ -304,6 +308,9 @@ if(!msg) continue + if(push_appearance) + M << output(push_appearance, "push_appearance_placeholder_id") + if(visible_message_flags & EMOTE_MESSAGE && runechat_prefs_check(M, visible_message_flags) && !M.is_blind()) M.create_chat_message(src, raw_message = raw_msg, runechat_flags = visible_message_flags) @@ -311,7 +318,7 @@ ///Adds the functionality to self_message. -/mob/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs, visible_message_flags = NONE) +/mob/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs, visible_message_flags = NONE, atom/push_appearance) . = ..() if(self_message) show_message(self_message, MSG_VISUAL, blind_message, MSG_AUDIBLE) diff --git a/code/modules/modular_computers/computers/item/computer.dm b/code/modules/modular_computers/computers/item/computer.dm index 01ede1c17be9..c4750484ea2f 100644 --- a/code/modules/modular_computers/computers/item/computer.dm +++ b/code/modules/modular_computers/computers/item/computer.dm @@ -496,11 +496,11 @@ * The program calling this proc. * The message that the program wishes to display. */ -/obj/item/modular_computer/proc/alert_call(datum/computer_file/program/origin, alerttext, sound = 'sound/machines/twobeep_high.ogg') - if(!origin || !origin.alert_able || origin.alert_silenced || !alerttext) //Yeah, we're checking alert_able. No, you don't get to make alerts that the user can't silence. +/obj/item/modular_computer/proc/alert_call(datum/computer_file/program/origin, alerttext, sound = 'sound/machines/twobeep_high.ogg', vision_distance = DEFAULT_MESSAGE_RANGE) + if(QDELETED(loc) || QDELETED(origin) || !origin.alert_able || origin.alert_silenced || !alerttext) //Yeah, we're checking alert_able. No, you don't get to make alerts that the user can't silence. return FALSE playsound(src, sound, 50, TRUE) - loc.visible_message(span_notice("[icon2html(src)] [span_notice("The [src] displays a [origin.filedesc] notification: [alerttext]")]")) + loc.visible_message(span_notice(" \The [src] displays a [origin.filedesc] notification: [alerttext]"), vision_distance = vision_distance, push_appearance = src) /obj/item/modular_computer/proc/ring(ringtone, list/balloon_alertees) // bring bring if(HAS_TRAIT(SSstation, STATION_TRAIT_PDA_GLITCHED)) diff --git a/code/modules/modular_computers/computers/item/computer_ui.dm b/code/modules/modular_computers/computers/item/computer_ui.dm index 4146588d7d93..8ea9c28dc699 100644 --- a/code/modules/modular_computers/computers/item/computer_ui.dm +++ b/code/modules/modular_computers/computers/item/computer_ui.dm @@ -39,14 +39,12 @@ // Operates TGUI /obj/item/modular_computer/ui_interact(mob/user, datum/tgui/ui) if(!enabled || !user.can_read(src, READING_CHECK_LITERACY) || !use_power()) - if(ui) - ui.close() + ui?.close() return // Robots don't really need to see the screen, their wireless connection works as long as computer is on. if(!screen_on && !issilicon(user)) - if(ui) - ui.close() + ui?.close() return if(honkvirus_amount > 0) // EXTRA annoying, huh! @@ -56,6 +54,8 @@ ui = SStgui.try_update_ui(user, src, ui) if(!ui) update_tablet_open_uis(user) + else if(active_program?.always_update_ui) + active_program.ui_interact(user, ui) /obj/item/modular_computer/ui_assets(mob/user) var/list/data = list() diff --git a/code/modules/modular_computers/computers/item/pda.dm b/code/modules/modular_computers/computers/item/pda.dm index 9560738ecafd..e6d731213aa1 100644 --- a/code/modules/modular_computers/computers/item/pda.dm +++ b/code/modules/modular_computers/computers/item/pda.dm @@ -36,7 +36,10 @@ /datum/computer_file/program/messenger, /datum/computer_file/program/nt_pay, /datum/computer_file/program/notepad, - /datum/computer_file/program/crew_manifest // monke edit: install crew manifest by default + // monkestation edit: install crew manifest and spess.tv by default + /datum/computer_file/program/crew_manifest, + /datum/computer_file/program/secureye/spesstv, + // monkestation end ) ///List of items that can be stored in a PDA var/static/list/contained_item = list( diff --git a/code/modules/modular_computers/computers/item/role_tablet_presets.dm b/code/modules/modular_computers/computers/item/role_tablet_presets.dm index 0e1ddcc72b2e..c45f41998800 100644 --- a/code/modules/modular_computers/computers/item/role_tablet_presets.dm +++ b/code/modules/modular_computers/computers/item/role_tablet_presets.dm @@ -102,6 +102,7 @@ /datum/computer_file/program/robocontrol, /datum/computer_file/program/budgetorders, /datum/computer_file/program/signal_commander, + /datum/computer_file/program/scipaper_program, ) /obj/item/modular_computer/pda/heads/quartermaster @@ -187,6 +188,8 @@ starting_programs = list( /datum/computer_file/program/atmosscan, /datum/computer_file/program/signal_commander, + /datum/computer_file/program/science, + /datum/computer_file/program/scipaper_program, ) /obj/item/modular_computer/pda/roboticist diff --git a/code/modules/modular_computers/file_system/program.dm b/code/modules/modular_computers/file_system/program.dm index 59ef183f6d66..65336cf0e43b 100644 --- a/code/modules/modular_computers/file_system/program.dm +++ b/code/modules/modular_computers/file_system/program.dm @@ -43,6 +43,8 @@ var/detomatix_resistance = NONE ///Boolean on whether or not only one copy of the app can exist. This means it deletes itself when cloned elsewhere. var/unique_copy = FALSE + ///Boolean on whether the UI should *always* be updated while active. + var/always_update_ui = FALSE /datum/computer_file/program/clone() var/datum/computer_file/program/temp = ..() diff --git a/code/modules/modular_computers/file_system/programs/secureye.dm b/code/modules/modular_computers/file_system/programs/secureye.dm index 1fd00e163345..14e50869aa75 100644 --- a/code/modules/modular_computers/file_system/programs/secureye.dm +++ b/code/modules/modular_computers/file_system/programs/secureye.dm @@ -13,6 +13,7 @@ size = 5 tgui_id = "NtosSecurEye" program_icon = "eye" + always_update_ui = TRUE ///Boolean on whether or not the app will make noise when flipping around the channels. var/spying = FALSE diff --git a/code/modules/pai/card.dm b/code/modules/pai/card.dm index 3e11c0b7bcb8..91f2222641dd 100644 --- a/code/modules/pai/card.dm +++ b/code/modules/pai/card.dm @@ -14,8 +14,8 @@ /// Spam alert prevention var/alert_cooldown - /// The emotion icon displayed. - var/emotion_icon = "off" + /// The icon displayed on the card's screen. + var/datum/pai_screen_image/screen_image = /datum/pai_screen_image/off /// Any pAI personalities inserted var/mob/living/silicon/pai/pai /// Prevents a crew member from hitting "request pAI" repeatedly @@ -60,7 +60,7 @@ /obj/item/pai_card/handle_atom_del(atom/thing) if(thing == pai) //double check /mob/living/silicon/pai/Destroy() if you change these. pai = null - emotion_icon = initial(emotion_icon) + screen_image = initial(screen_image) update_appearance() return ..() @@ -76,13 +76,13 @@ /obj/item/pai_card/update_overlays() . = ..() - . += "pai-[emotion_icon]" + . += image(icon = screen_image.icon, icon_state = screen_image.icon_state) if(pai?.hacking_cable) . += "[initial(icon_state)]-connector" /obj/item/pai_card/vv_edit_var(vname, vval) . = ..() - if(vname == NAMEOF(src, emotion_icon)) + if(vname == NAMEOF(src, screen_image)) update_appearance() /obj/item/pai_card/ui_interact(mob/user, datum/tgui/ui) @@ -268,7 +268,7 @@ if(pai) return FALSE pai = downloaded - emotion_icon = "null" + screen_image = /datum/pai_screen_image/neutral update_appearance() playsound(src, 'sound/effects/pai_boot.ogg', 50, TRUE, -1) audible_message("[src] plays a cheerful startup noise!") diff --git a/code/modules/pai/datums/screen_icon.dm b/code/modules/pai/datums/screen_icon.dm new file mode 100644 index 000000000000..2115b8ea0d61 --- /dev/null +++ b/code/modules/pai/datums/screen_icon.dm @@ -0,0 +1,67 @@ +// Datums describing an icon that is overlaid on a pAI card, to make its screen show something. The +// player can select between any of these at any time. These are usually faces, but can +// realistically be anything (similar to an AI's display). + +/datum/pai_screen_image + // The name to show in the radial menu. + var/name + // The icon and icon state that is applied to the pAI device when this screen image is selected. + var/icon/icon = 'icons/obj/aicards.dmi' + var/icon_state + // The FontAwesome icon to use next to the "Display" button in the pAI's tgui interface window. + var/interface_icon + +/datum/pai_screen_image/angry + name = "Angry" + icon_state = "pai-angry" + interface_icon = "angry" + +/datum/pai_screen_image/cat + name = "Cat" + icon_state = "pai-cat" + interface_icon = "cat" + +/datum/pai_screen_image/extremely_happy + name = "Extremely Happy" + icon_state = "pai-extremely-happy" + interface_icon = "grin-beam" + +/datum/pai_screen_image/face + name = "Face" + icon_state = "pai-face" + interface_icon = "grin-alt" + +/datum/pai_screen_image/happy + name = "Happy" + icon_state = "pai-happy" + interface_icon = "smile" + +/datum/pai_screen_image/laugh + name = "Laugh" + icon_state = "pai-laugh" + interface_icon = "grin-tears" + +/datum/pai_screen_image/neutral + name = "Neutral" + icon_state = "pai-null" + interface_icon = "meh" + +/datum/pai_screen_image/off + name = "None" + icon_state = "pai-off" + interface_icon = "meh-blank" + +/datum/pai_screen_image/sad + name = "Sad" + icon_state = "pai-sad" + interface_icon = "sad-cry" + +/datum/pai_screen_image/sunglasses + name = "Sunglasses" + icon_state = "pai-sunglasses" + interface_icon = "sun" + +/datum/pai_screen_image/what + name = "What" + icon_state = "pai-what" + interface_icon = "frown-open" diff --git a/code/modules/pai/death.dm b/code/modules/pai/death.dm index 469f1757d47a..b819e16bfce8 100644 --- a/code/modules/pai/death.dm +++ b/code/modules/pai/death.dm @@ -13,7 +13,7 @@ if (!QDELETED(card) && loc != card) card.forceMove(drop_location()) card.pai = null - card.emotion_icon = initial(card.emotion_icon) + card.screen_image = initial(card.screen_image) card.update_appearance() qdel(src) diff --git a/code/modules/pai/pai.dm b/code/modules/pai/pai.dm index 35229887c86b..278d642b6ae8 100644 --- a/code/modules/pai/pai.dm +++ b/code/modules/pai/pai.dm @@ -124,20 +124,6 @@ "puppy" = FALSE, "spider" = FALSE, ) - /// List of all available card overlays. - var/static/list/possible_overlays = list( - "null", - "angry", - "cat", - "extremely-happy", - "face", - "happy", - "laugh", - "off", - "sad", - "sunglasses", - "what" - ) /mob/living/silicon/pai/add_sensors() //pAIs have to buy their HUDs return diff --git a/code/modules/pai/software.dm b/code/modules/pai/software.dm index f5b69dd03264..a8c34ca60b89 100644 --- a/code/modules/pai/software.dm +++ b/code/modules/pai/software.dm @@ -8,7 +8,7 @@ /mob/living/silicon/pai/ui_data(mob/user) var/list/data = list() data["door_jack"] = hacking_cable - data["image"] = card.emotion_icon + data["screen_image_interface_icon"] = card.screen_image.interface_icon data["installed"] = installed_software data["ram"] = ram return data @@ -135,16 +135,16 @@ */ /mob/living/silicon/pai/proc/change_image() var/list/possible_choices = list() - for(var/face_option in possible_overlays) + for(var/datum/pai_screen_image/screen_option as anything in subtypesof(/datum/pai_screen_image)) var/datum/radial_menu_choice/choice = new - choice.name = face_option - choice.image = image(icon = card.icon, icon_state = "pai-[face_option]") - possible_choices[face_option] += choice + choice.name = screen_option.name + choice.image = image(icon = screen_option.icon, icon_state = screen_option.icon_state) + possible_choices[screen_option] += choice var/atom/anchor = get_atom_on_turf(src) var/new_image = show_radial_menu(src, anchor, possible_choices, custom_check = CALLBACK(src, PROC_REF(check_menu), anchor), radius = 40, require_near = TRUE) if(isnull(new_image)) return FALSE - card.emotion_icon = new_image + card.screen_image = new_image card.update_appearance() return TRUE diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index 214ad78425be..c6e3fbe78d72 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -121,6 +121,7 @@ #include "egg_glands.dm" #include "emoting.dm" #include "fish_unit_tests.dm" +#include "floor_lights.dm" #include "focus_only_tests.dm" #include "food_edibility_check.dm" #include "full_heal.dm" diff --git a/code/modules/unit_tests/floor_lights.dm b/code/modules/unit_tests/floor_lights.dm new file mode 100644 index 000000000000..1caa5fdce08b --- /dev/null +++ b/code/modules/unit_tests/floor_lights.dm @@ -0,0 +1,21 @@ +/// This test ensures that floor lights aren't mapped underneath any sort of solid object that would obscure it. +/datum/unit_test/floor_lights + +/datum/unit_test/floor_lights/Run() + var/static/list/obscuring_typecache = typecacheof(list( + /obj/structure/table, + /obj/structure/bookcase, + /obj/machinery/computer, + /obj/machinery/vending, + )) + + for(var/obj/machinery/light/floor/light as anything in SSmachines.get_machines_by_type_and_subtypes(/obj/machinery/light/floor)) + var/turf/light_turf = light.loc + if(!isturf(light_turf) || !is_station_level(light_turf.z)) // only check lights on-station + continue + if(!istype(light, /obj/machinery/light/floor/has_bulb)) + TEST_FAIL("[light] ([light.type]) does not start with a bulb at [AREACOORD(light_turf)], this is likely a mistake") + continue + for(var/obj/thing in light_turf) + if(thing.density && (is_type_in_typecache(thing, obscuring_typecache) || ((thing.flags_1 & PREVENT_CLICK_UNDER_1) && thing.layer > light.layer))) + TEST_FAIL("[light] ([light.type]) obscured by [thing] ([thing.type]) at [AREACOORD(light_turf)]") diff --git a/code/modules/unit_tests/unit_test.dm b/code/modules/unit_tests/unit_test.dm index 2f7bcf439cb8..1877abe8ddf5 100644 --- a/code/modules/unit_tests/unit_test.dm +++ b/code/modules/unit_tests/unit_test.dm @@ -256,6 +256,7 @@ GLOBAL_VAR_INIT(focused_tests, focused_tests()) /turf/closed/mineral/random/regrowth, /obj/effect/abstract/signboard_holder, // monkestation addition: shouldn't exist outside of signboards /obj/effect/transmission_beam, // monkestation addition: relies on the existence of a PTL + /obj/item/radio/entertainment/speakers/pda, // monkestation addition: should never exist outside of a modular computer ) //Say it with me now, type template ignore += typesof(/obj/effect/mapping_helpers) @@ -353,9 +354,12 @@ GLOBAL_VAR_INIT(focused_tests, focused_tests()) var/list/test_results = list() + //Hell code, we're bound to end the round somehow so let's stop if from ending while we work + SSticker.delay_end = TRUE for(var/unit_path in tests_to_run) CHECK_TICK //We check tick first because the unit test we run last may be so expensive that checking tick will lock up this loop forever RunUnitTest(unit_path, test_results) + SSticker.delay_end = FALSE var/file_name = "data/unit_tests.json" fdel(file_name) diff --git a/config/config.txt b/config/config.txt index 464b95aa5078..1078e1d6e593 100644 --- a/config/config.txt +++ b/config/config.txt @@ -8,6 +8,7 @@ $include resources.txt $include interviews.txt $include lua.txt $include auxtools.txt +$include plexora.txt # You can use the @ character at the beginning of a config option to lock it from being edited in-game # Example usage: diff --git a/config/plexora.json b/config/plexora.json deleted file mode 100644 index cac6b9114fca..000000000000 --- a/config/plexora.json +++ /dev/null @@ -1,5 +0,0 @@ -{ - "enabled": true, - "ip": "127.0.0.1", - "port": 1330 -} diff --git a/config/plexora.txt b/config/plexora.txt new file mode 100644 index 000000000000..b7ceb1904d69 --- /dev/null +++ b/config/plexora.txt @@ -0,0 +1,5 @@ +# Uncomment this to enable Plexora. You probably won't need this, this is really only used by the main Monkestation server. +#PLEXORA_ENABLED + +# The base URL for the Plexora instance. +PLEXORA_URL http://127.0.0.1:1330 diff --git a/html/changelogs/AutoChangeLog-pr-5134.yml b/html/changelogs/AutoChangeLog-pr-5134.yml deleted file mode 100644 index b47eec56d913..000000000000 --- a/html/changelogs/AutoChangeLog-pr-5134.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Absolucy" -delete-after: True -changes: - - bugfix: "Fixed various minor errors." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-5142.yml b/html/changelogs/AutoChangeLog-pr-5142.yml deleted file mode 100644 index f4a02ca4e6b8..000000000000 --- a/html/changelogs/AutoChangeLog-pr-5142.yml +++ /dev/null @@ -1,5 +0,0 @@ -author: "Absolucy" -delete-after: True -changes: - - bugfix: "Scrollbars are now properly themed on BYOND 516." - - bugfix: "Fixed not being able to scroll properly through techfabs/lathes on BYOND 516." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-5152.yml b/html/changelogs/AutoChangeLog-pr-5152.yml new file mode 100644 index 000000000000..2de52e72a17e --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-5152.yml @@ -0,0 +1,4 @@ +author: "Ancient_Engineer, Killermankey, Camroid" +delete-after: True +changes: + - rscadd: "New and improved mentor cloak I'd advise against trying to steal it (:" \ No newline at end of file diff --git a/html/changelogs/archive/2025-01.yml b/html/changelogs/archive/2025-01.yml index ea07313dc880..42c165832845 100644 --- a/html/changelogs/archive/2025-01.yml +++ b/html/changelogs/archive/2025-01.yml @@ -627,6 +627,12 @@ - qol: The corrupt appendix and lungs now have a cooldown, to prevent stunlocks or rapidly filling entire rooms with plasma if you're super unlucky. - bugfix: Fixed some minor map issues. + - bugfix: Fixed a few floor lights that were obscured by dense objects. + - bugfix: Fixed crew transfer votes being spammed if nobody votes on them. + - bugfix: Scrollbars are now properly themed on BYOND 516. + - bugfix: Fixed not being able to scroll properly through techfabs/lathes on BYOND + 516. + - bugfix: Fixed various minor errors. BingusSS13: - qol: Updates The Derelict / KS13 / Drone Station / Russian Station's engineering to look like it's original map's engineering. @@ -651,6 +657,9 @@ - balance: Minimum players required for a Disease/plague outbreak are all increased - balance: 'Fake virus''s will now share starting conditions with Disease: Classic rather than Plague rats.' + - bugfix: Engineering is properly accessed by Construction access. + - bugfix: Tcomms is properly accessed with TComms access. + - bugfix: AI sat is properly accessed by minisat access MrBagHead: - qol: Renamed "Midround Heretics" event to "Forbidden Calling (Heretics)" for consistency. Shoddd: @@ -662,3 +671,23 @@ - bugfix: fixed donator tokens being buggy (hopefully) - rscadd: Syndicate Depot's Operatives are reminded of escalation requirements when faxing or teleporting stuff to the station. + - bugfix: Donator Tokens. + - bugfix: Tokens now backup appropriately after being spent. +2025-01-31: + Gw0sty: + - rscadd: Added security camera consoles to blueshift outposts. + - rscadd: Rockroach disks finally lost their copyright and are now purchasable on + the slime market. + - rscdel: Removed old rhinovirus and cold bottles from viro fridges + - bugfix: Boxstation no longer has ooze suckers that link to its neighbour pens + - bugfix: Deepstation engineers stopped cutting corners, and completed the ooze + network, and gave proper upgrade disks, and a plumbing device + - bugfix: Colour mutation syringes no longer pretend to be No Ooze syringes in the + market + - bugfix: Tram station's super matter will no longer have a delam counter hanging + off the wall. + - bugfix: Blueshift no longer has a dedicated camera for looking at a wall. + - bugfix: Xenobiology has finally figured out what the hell a possum is. Thus are + printable by vacuum backpacks + - bugfix: Semi-organic bugs will be unlocked on red slimes, instead of dark purple + slimes diff --git a/html/changelogs/archive/2025-02.yml b/html/changelogs/archive/2025-02.yml new file mode 100644 index 000000000000..a8bbb2dd5e07 --- /dev/null +++ b/html/changelogs/archive/2025-02.yml @@ -0,0 +1,47 @@ +2025-02-01: + Absolucy: + - bugfix: Awakened Dragon's attacks now do the intended amount of damage. + - bugfix: Awakened Dragon and Tunnel Arts now have fully consistent counter/dodge + effects with the blood cult stun hand. + - bugfix: When a touch attack gets dodged by a martial arts user, the attacker will + properly have their click cooldown set. + - balance: Sleeping Carp, Awakened Dragon, and Tunnel Arts will now dodge/counter + touch attacks regardless of combat mode if they're considered a "dangerous" + attack (pretty much everything except genetics shock touch) + - balance: Tunnel Arts' illusionary warriors now move at the same speed as normal + humans, rather than the typical slower rate than most simplemobs do. + - qol: Categorized many martial arts-related chat messages as being combat-related + in chat tabs. + - rscadd: PDAs can now tune into the broadcast camera's streams, with the pre-installed + Spess.tv app! + - refactor: Refactored some stuff about how camera broadcasts work. + - bugfix: Mark of Rust can no longer damage indestructible items. + - bugfix: Fixed the chat reliability subsystem being completely useless (hopefully). + - balance: Securitrons/Beepsky now only deal stamina damage instead of instantly + hardstunning someone. + - balance: Having baton resistance now also provides resistance against beepsky. + - balance: Beepsky can now be blocked/parried with shields and such. + Absolucy, SyncIt21: + - bugfix: Quirks now properly process again. + Gw0sty: + - rscadd: Added cures to the various transformation diseases + - balance: Lowered the maximum trigger chance of transformation symptoms. + - bugfix: Boxstation engineering disposals will no longer explode. + RikuTheKiller: + - spellcheck: You no longer loosen your balance, instead you lose it when throwing + a bulky item. + TheColorCyan: + - rscadd: Added NT frontier and NT Science Hub to Scientist PDAs + - rscadd: Added NT frontier to RD PDAs + ThePooba: + - bugfix: Fixed ships being unabled to be recalled after completing your first ship + on blueshift + - bugfix: box station shipbreaker hut wont run out of power now +2025-02-03: + Gw0sty: + - rscadd: Added Dr. Scrubs to remaining maps + - rscadd: Added Poppy the safety inspector into the remaining SM maps + - bugfix: Fixed a missing airlock helping on minisat. + Wernerses: + - balance: reduced minimum apid honey require to make beehives from 150 to 70 + - balance: reduced beehive cooldown from 25 minutes to 5 minutes. diff --git a/monkestation/code/controllers/subsystem/autotransfer.dm b/monkestation/code/controllers/subsystem/autotransfer.dm index e136b3aca303..cbe8968a2f81 100644 --- a/monkestation/code/controllers/subsystem/autotransfer.dm +++ b/monkestation/code/controllers/subsystem/autotransfer.dm @@ -14,9 +14,20 @@ SUBSYSTEM_DEF(autotransfer) SSticker.OnRoundstart(CALLBACK(src, PROC_REF(crew_transfer_setup))) return SS_INIT_SUCCESS +/datum/controller/subsystem/autotransfer/Recover() + next_transfer_vote = SSautotransfer.next_transfer_vote + /datum/controller/subsystem/autotransfer/fire() if(can_run_transfer_vote()) SSvote.initiate_vote(/datum/vote/shuttle_call, "automatic shuttle vote", forced = TRUE) + start_subsequent_vote_cooldown() + +/datum/controller/subsystem/autotransfer/proc/start_subsequent_vote_cooldown() + var/subsequent_transfer_vote_time = CONFIG_GET(number/subsequent_transfer_vote_time) + if(subsequent_transfer_vote_time) + COOLDOWN_START(src, next_transfer_vote, subsequent_transfer_vote_time + CONFIG_GET(number/vote_period)) + else + next_transfer_vote = 0 /datum/controller/subsystem/autotransfer/proc/can_run_transfer_vote() . = TRUE @@ -50,8 +61,3 @@ SUBSYSTEM_DEF(autotransfer) /datum/controller/subsystem/autotransfer/proc/crew_transfer_continue() SSgamemode.point_gain_multipliers[EVENT_TRACK_ROLESET]++ - var/subsequent_transfer_vote_time = CONFIG_GET(number/subsequent_transfer_vote_time) - if(!subsequent_transfer_vote_time) - next_transfer_vote = 0 - return - COOLDOWN_START(src, next_transfer_vote, subsequent_transfer_vote_time) diff --git a/monkestation/code/controllers/subsystem/plexora.dm b/monkestation/code/controllers/subsystem/plexora.dm index 38c9f7ae9219..72f2d993c50a 100644 --- a/monkestation/code/controllers/subsystem/plexora.dm +++ b/monkestation/code/controllers/subsystem/plexora.dm @@ -20,8 +20,8 @@ INVOKE_ASYNC(SSplexora, TYPE_PROC_REF(/datum/controller/subsystem/plexora, topic_listener_response), input["emitter_token"], returning); \ return; \ }; - #define AUTH_HEADER ("Basic " + CONFIG_GET(string/comms_key)) +#define OLD_PLEXORA_CONFIG "config/plexora.json" SUBSYSTEM_DEF(plexora) name = "Plexora" @@ -36,11 +36,9 @@ SUBSYSTEM_DEF(plexora) // MUST INCREMENT BY ONE FOR EVERY CHANGE MADE TO PLEXORA var/version_increment_counter = 2 - var/configuration_path = "config/plexora.json" var/plexora_is_alive = FALSE var/vanderlin_available = FALSE - var/http_root = "" - var/http_port = 0 + var/base_url = "" var/enabled = TRUE var/tripped_bad_version = FALSE var/list/default_headers @@ -49,16 +47,7 @@ SUBSYSTEM_DEF(plexora) var/hrp_available = FALSE /datum/controller/subsystem/plexora/Initialize() - if (!aneri_file_read(configuration_path)) - stack_trace("SSplexora has no configuration file! (missing: [configuration_path])") - enabled = FALSE - flags |= SS_NO_FIRE - return SS_INIT_FAILURE - - // Get config - var/list/config = json_decode(aneri_file_read(configuration_path)) - - if (!config["enabled"]) + if(!CONFIG_GET(flag/plexora_enabled) && !load_old_plexora_config()) enabled = FALSE flags |= SS_NO_FIRE return SS_INIT_NO_NEED @@ -70,8 +59,7 @@ SUBSYSTEM_DEF(plexora) flags |= SS_NO_FIRE return SS_INIT_FAILURE - http_root = config["ip"] - http_port = config["port"] + base_url = CONFIG_GET(string/plexora_url) default_headers = list( "Content-Type" = "application/json", @@ -92,19 +80,30 @@ SUBSYSTEM_DEF(plexora) flags |= SS_NO_INIT // Make extra sure we don't initialize twice. initialized = SSplexora.initialized plexora_is_alive = SSplexora.plexora_is_alive - http_root = SSplexora.http_root - http_port = SSplexora.http_port + base_url = SSplexora.base_url enabled = SSplexora.enabled tripped_bad_version = SSplexora.tripped_bad_version default_headers = SSplexora.default_headers if(initialized && !enabled) flags |= SS_NO_FIRE +// compat thing so that it'll load plexora.json if it's still used +/datum/controller/subsystem/plexora/proc/load_old_plexora_config() + if(!aneri_file_exists(OLD_PLEXORA_CONFIG)) + return FALSE + var/list/old_config = json_decode(aneri_file_read(OLD_PLEXORA_CONFIG)) + if(!old_config["enabled"]) + return FALSE + stack_trace("Falling back to [OLD_PLEXORA_CONFIG], you should really migrate to the PLEXORA_ENABLED and PLEXORA_URL config entries!") + CONFIG_SET(flag/plexora_enabled, TRUE) + CONFIG_SET(string/plexora_url, "http://[old_config["ip"]]:[old_config["port"]]") + return TRUE + /datum/controller/subsystem/plexora/proc/is_plexora_alive() . = FALSE if(!enabled) return - var/datum/http_request/request = new(RUSTG_HTTP_METHOD_GET, "http://[http_root]:[http_port]/alive") + var/datum/http_request/request = new(RUSTG_HTTP_METHOD_GET, "[base_url]/alive") request.begin_async() UNTIL_OR_TIMEOUT(request.is_complete(), 10 SECONDS) var/datum/http_response/response = request.into_response() @@ -134,7 +133,7 @@ SUBSYSTEM_DEF(plexora) http_request( RUSTG_HTTP_METHOD_POST, - "http://[http_root]:[http_port]/status", + "[base_url]/status", json_encode(status), default_headers ).begin_async() @@ -211,7 +210,7 @@ SUBSYSTEM_DEF(plexora) "id" = id ) - var/datum/http_request/request = new(RUSTG_HTTP_METHOD_GET, "http://[http_root]:[http_port]/byondserver_alive", json_encode(body), default_headers) + var/datum/http_request/request = new(RUSTG_HTTP_METHOD_GET, "[base_url]/byondserver_alive", json_encode(body), default_headers) request.begin_async() UNTIL_OR_TIMEOUT(request.is_complete(), 5 SECONDS) var/datum/http_response/response = request.into_response() @@ -362,7 +361,7 @@ SUBSYSTEM_DEF(plexora) var/datum/http_request/request = new( RUSTG_HTTP_METHOD_POST, - "http://[http_root]:[http_port]/[path]", + "[base_url]/[path]", json_encode(body), default_headers, "tmp/response.json" @@ -979,5 +978,6 @@ SUBSYSTEM_DEF(plexora) html = "Mentor PM: [key_name_mentor(sender, honked_client, FALSE, FALSE)]->[key_name_mentor(recipient, honked_client, FALSE, FALSE)]: [message]", confidential = TRUE) +#undef OLD_PLEXORA_CONFIG #undef AUTH_HEADER #undef TOPIC_EMITTER diff --git a/monkestation/code/datums/meta_tokens.dm b/monkestation/code/datums/meta_tokens.dm index 7f91794f9a07..a3180b6c3fd9 100644 --- a/monkestation/code/datums/meta_tokens.dm +++ b/monkestation/code/datums/meta_tokens.dm @@ -44,6 +44,8 @@ GLOBAL_LIST_INIT(patreon_etoken_values, list( var/antag_timeout /// The timer for the event token timeout var/event_timeout + /// The month we last used a donator token on + var/token_month = 0 /datum/meta_token_holder/New(client/creator) . = ..() @@ -72,6 +74,7 @@ GLOBAL_LIST_INIT(patreon_etoken_values, list( event_tokens = saved_tokens["event_tokens"] event_token_month = saved_tokens["event_token_month"] donator_token = saved_tokens["donator"] + token_month = saved_tokens["donator_token_month"] total_antag_tokens = total_low_threat_tokens + total_medium_threat_tokens + total_high_threat_tokens @@ -90,6 +93,7 @@ GLOBAL_LIST_INIT(patreon_etoken_values, list( "event_tokens" = event_tokens, "event_token_month" = event_token_month, "donator" = donator_token, + "donator_token_month" = token_month, ) backup_tokens() owner.prefs.save_preferences() @@ -101,20 +105,18 @@ GLOBAL_LIST_INIT(patreon_etoken_values, list( return FALSE var/month_number = text2num(time2text(world.time, "MM")) - if(owner.prefs.token_month == 0) - owner.prefs.token_month = month_number - if(owner.prefs.token_month != month_number) + if(token_month != month_number) if(patreon.has_access(ACCESS_NUKIE_RANK)) ///if nukie rank, get coins AND token owner.prefs.adjust_metacoins(owner?.ckey, 10000, "Monthly Monkecoin rations.", TRUE, FALSE, FALSE) donator_token++ - owner.prefs.token_month = month_number ///update per-person month counter + token_month = month_number ///update per-person month counter convert_tokens_to_list() return TRUE else - owner.prefs.token_month = month_number + token_month = month_number convert_tokens_to_list() return FALSE @@ -122,8 +124,8 @@ GLOBAL_LIST_INIT(patreon_etoken_values, list( if(use_donor) if(donator_token) donator_token-- - logger.Log(LOG_CATEGORY_META, "[owner], used donator token on [owner.prefs.token_month].") - owner.prefs.save_preferences() + logger.Log(LOG_CATEGORY_META, "[owner], used donator token on [token_month].") + convert_tokens_to_list() return switch(tier) diff --git a/monkestation/code/game/machinery/computer/camera.dm b/monkestation/code/game/machinery/computer/camera.dm new file mode 100644 index 000000000000..4df9a6f64ead --- /dev/null +++ b/monkestation/code/game/machinery/computer/camera.dm @@ -0,0 +1,6 @@ +/obj/machinery/camera/proc/count_spesstv_viewers() + . = 0 + var/list/spesstv_viewers = GLOB.spesstv_viewers // just in case this ends up being a hot proc + for(var/key in spesstv_viewers) + if(spesstv_viewers[key] == c_tag) + .++ diff --git a/monkestation/code/game/machinery/computer/telescreen.dm b/monkestation/code/game/machinery/computer/telescreen.dm new file mode 100644 index 000000000000..c44fe9e435ff --- /dev/null +++ b/monkestation/code/game/machinery/computer/telescreen.dm @@ -0,0 +1,17 @@ +/obj/machinery/computer/security/telescreen/entertainment/update_active_camera_screen() + . = ..() + update_spesstv_watcher_list(REF(src), active_camera) + +/obj/machinery/computer/security/telescreen/entertainment/Destroy() + LAZYREMOVE(GLOB.spesstv_viewers, REF(src)) + return ..() + +/obj/machinery/computer/security/telescreen/entertainment/atom_break(damage_flag) + . = ..() + if(.) + LAZYREMOVE(GLOB.spesstv_viewers, REF(src)) + +/obj/machinery/computer/security/telescreen/entertainment/power_change() + . = ..() + if(!powered()) + LAZYREMOVE(GLOB.spesstv_viewers, REF(src)) diff --git a/monkestation/code/game/objects/items/devices/broadcast_camera.dm b/monkestation/code/game/objects/items/devices/broadcast_camera.dm new file mode 100644 index 000000000000..eca97528a612 --- /dev/null +++ b/monkestation/code/game/objects/items/devices/broadcast_camera.dm @@ -0,0 +1,79 @@ +/datum/status_effect/streamer + id = "streamer" + alert_type = null + processing_speed = STATUS_EFFECT_NORMAL_PROCESS + /// How many people are currently watching the stream. + var/viewers = 0 + /// The camera being used to stream. + var/obj/machinery/camera/camera + /// Simple screen element used to hold the maptext for the viewer counter. + var/atom/movable/screen/stream_viewers/viewer_display + /// Callback to see if the stream is still valid. + var/datum/callback/extra_checks + +/datum/status_effect/streamer/Destroy() + extra_checks = null + camera = null + QDEL_NULL(viewer_display) + return ..() + +/datum/status_effect/streamer/on_creation(mob/living/new_owner, obj/machinery/camera/camera, datum/callback/extra_checks) + src.camera = camera + src.extra_checks = extra_checks + return ..() + +/datum/status_effect/streamer/on_apply() + if(QDELETED(camera)) + return FALSE + else if(!istype(camera)) + CRASH("Invalid camera ([camera]) passed to [type] (expected an /obj/machinery/camera)") + if(extra_checks && !extra_checks.Invoke(src)) + return FALSE + give_hud() + RegisterSignal(owner, COMSIG_MOB_LOGIN, PROC_REF(give_hud)) + RegisterSignal(owner, COMSIG_MOB_GET_STATUS_TAB_ITEMS, PROC_REF(get_status_tab_item)) + RegisterSignal(camera, COMSIG_QDELETING, PROC_REF(hamburger_time)) + return TRUE + +/datum/status_effect/streamer/on_remove() + . = ..() + UnregisterSignal(owner, list(COMSIG_MOB_LOGIN, COMSIG_MOB_GET_STATUS_TAB_ITEMS)) + UnregisterSignal(camera, COMSIG_QDELETING) + if(!isnull(viewer_display)) + owner.client?.screen -= viewer_display + +/datum/status_effect/streamer/before_remove(source) + if(!isnull(source) && !QDELETED(camera) && source == camera) + return FALSE + return ..() + +/datum/status_effect/streamer/tick(seconds_per_tick, times_fired) + if(extra_checks && !extra_checks.Invoke(src)) + qdel(src) + return + viewers = camera.count_spesstv_viewers() + viewer_display?.update_maptext(camera.count_spesstv_viewers()) + +/datum/status_effect/streamer/proc/give_hud() + SIGNAL_HANDLER + if(QDELETED(viewer_display)) + viewer_display = new + viewers = camera.count_spesstv_viewers() + viewer_display.update_maptext(viewers) + owner.client?.screen |= viewer_display + +/datum/status_effect/streamer/proc/get_status_tab_item(mob/living/source, list/items) + SIGNAL_HANDLER + items += "Stream Viewers: [viewers]" + +/datum/status_effect/streamer/proc/hamburger_time() + SIGNAL_HANDLER + qdel(src) + +/atom/movable/screen/stream_viewers + screen_loc = ui_more_under_health_and_to_the_left + maptext_width = 84 + maptext_height = 24 + +/atom/movable/screen/stream_viewers/proc/update_maptext(amt) + maptext = "
Viewers: [amt]
" diff --git a/monkestation/code/modules/a_ship_in_need_of_breaking/machines/console.dm b/monkestation/code/modules/a_ship_in_need_of_breaking/machines/console.dm index 77768306fffe..d2d138f08334 100644 --- a/monkestation/code/modules/a_ship_in_need_of_breaking/machines/console.dm +++ b/monkestation/code/modules/a_ship_in_need_of_breaking/machines/console.dm @@ -27,6 +27,8 @@ var/ship_health = 0 ///our initial turf count var/turf_count = 0 + var/ship_part = 0 + var/total_turf = 0 /obj/machinery/computer/shipbreaker/Initialize(mapload) ..() @@ -56,7 +58,7 @@ /obj/machinery/computer/shipbreaker/proc/area_clear_check() for(var/turf/t in linked) - if(!isspaceturf(t)) + if(!isgroundlessturf(t)) spawn_area_clear = FALSE say("FLOORING OR WALL DETECTED") return @@ -108,14 +110,18 @@ /obj/machinery/computer/shipbreaker/proc/setup_health_tracker() for(var/turf/turf in linked) - if(!isspaceturf(turf)) + if(!isgroundlessturf(turf)) turf_count++ RegisterSignal(turf, COMSIG_TURF_CHANGE, PROC_REF(modify_health)) + total_turf = turf_count + ship_part = (100 / turf_count) ship_health = 100 /obj/machinery/computer/shipbreaker/proc/modify_health(turf/source) - ship_health -= (100 / turf_count) + ship_health -= ((total_turf - turf_count) * ship_part) ship_health = max(ship_health, 0) + if(ship_health < 1) + ship_health = 0 /obj/machinery/computer/shipbreaker/proc/damage_ship() diff --git a/monkestation/code/modules/antagonists/cult/blood_magic.dm b/monkestation/code/modules/antagonists/cult/blood_magic.dm index 635c6cce7910..95317060806a 100644 --- a/monkestation/code/modules/antagonists/cult/blood_magic.dm +++ b/monkestation/code/modules/antagonists/cult/blood_magic.dm @@ -77,13 +77,23 @@ // If this is gonna be a snowflake touch spell despite not being an actual touch spell, then we get to have snowflake code to ensure it behaves like it should. /obj/item/melee/blood_magic/stun/proc/snowflake_martial_arts_handler(mob/living/target, mob/living/carbon/user) var/datum/martial_art/martial_art = target?.mind?.martial_art - var/list/static/martial_counters_typecache = typecacheof(list( - /datum/martial_art/cqc, - /datum/martial_art/the_sleeping_carp/awakened_dragon, - )) if(!martial_art?.can_use()) return FALSE - if(is_type_in_typecache(martial_art, martial_counters_typecache)) + var/counter = FALSE + var/dodge = FALSE + if(istype(martial_art, /datum/martial_art/cqc)) + counter = TRUE + else if(istype(martial_art, /datum/martial_art/the_sleeping_carp)) + var/datum/martial_art/the_sleeping_carp/eepy_carp = martial_art + if(eepy_carp.can_deflect(target, check_intent = FALSE)) + if(eepy_carp.counter) + counter = TRUE + INVOKE_ASYNC(target, TYPE_PROC_REF(/atom/movable, say), message = "PATHETIC!", language = /datum/language/common, ignore_spam = TRUE, forced = martial_art) + else + dodge = TRUE + else if(istype(martial_art, /datum/martial_art/the_tunnel_arts)) + dodge = TRUE + if(counter) target.visible_message( span_danger("[target] twists [user]'s arm, sending [user.p_their()] [src] back towards [user.p_them()]!"), span_userdanger("Making sure to avoid [user]'s [src], you twist [user.p_their()] arm to send it right back at [user.p_them()]!"), @@ -92,16 +102,14 @@ to_chat(user, span_userdanger("As you attempt to stun [target] with the spell, [target.p_they()] twist[target.p_s()] your arm and send[target.p_s()] the spell back at you!"), type = MESSAGE_TYPE_COMBAT) effect_weakened(user, silent = TRUE) return TRUE - else if(istype(martial_art, /datum/martial_art/the_sleeping_carp)) - var/datum/martial_art/the_sleeping_carp/eepy_carp = martial_art - if(eepy_carp.can_deflect(target)) - target.visible_message( - span_danger("[target] carefully dodges [user]'s [src]!"), - span_userdanger("You take great care to remain untouched by [user]'s [src]!"), - ignored_mobs = list(user), - ) - to_chat(user, span_userdanger("[target] carefully dodges your [src], remaining completely untouched!"), type = MESSAGE_TYPE_COMBAT) - target.balloon_alert(user, "miss!") - playsound(target, 'monkestation/sound/effects/miss.ogg', vol = 50, vary = TRUE, extrarange = SHORT_RANGE_SOUND_EXTRARANGE) - return TRUE + else if(dodge) + target.visible_message( + span_danger("[target] carefully dodges [user]'s [src]!"), + span_userdanger("You take great care to remain untouched by [user]'s [src]!"), + ignored_mobs = list(user), + ) + to_chat(user, span_userdanger("[target] carefully dodges your [src], remaining completely untouched!"), type = MESSAGE_TYPE_COMBAT) + target.balloon_alert(user, "miss!") + playsound(target, 'monkestation/sound/effects/miss.ogg', vol = 50, vary = TRUE, extrarange = SHORT_RANGE_SOUND_EXTRARANGE) + return TRUE return FALSE diff --git a/monkestation/code/modules/antagonists/heretic/status_effects/mark_effects.dm b/monkestation/code/modules/antagonists/heretic/status_effects/mark_effects.dm index c25405e84c6b..c591d7aadc20 100644 --- a/monkestation/code/modules/antagonists/heretic/status_effects/mark_effects.dm +++ b/monkestation/code/modules/antagonists/heretic/status_effects/mark_effects.dm @@ -22,7 +22,7 @@ if(QDELETED(thing) || prob(50)) continue // ignore abstract items and such - if(thing.item_flags & (ABSTRACT | EXAMINE_SKIP | HAND_ITEM)) + if((thing.item_flags & (ABSTRACT | EXAMINE_SKIP | HAND_ITEM)) || (thing.resistance_flags & INDESTRUCTIBLE)) continue // don't delete people's ID cards if(istype(thing, /obj/item/card/id)) diff --git a/monkestation/code/modules/art_sci_overrides/asteroids/asteroid_magnet.dm b/monkestation/code/modules/art_sci_overrides/asteroids/asteroid_magnet.dm index 5300967aaa12..90e1120e99c4 100644 --- a/monkestation/code/modules/art_sci_overrides/asteroids/asteroid_magnet.dm +++ b/monkestation/code/modules/art_sci_overrides/asteroids/asteroid_magnet.dm @@ -61,7 +61,10 @@ else available_templates[roid] = 100 templates_on_map = list() + return INITIALIZE_HINT_LATELOAD +/obj/machinery/asteroid_magnet/LateInitialize() + . = ..() GenerateMap() /obj/machinery/asteroid_magnet/proc/ping(coords_x, coords_y) diff --git a/monkestation/code/modules/botany/species/apid/hive/ability.dm b/monkestation/code/modules/botany/species/apid/hive/ability.dm index 29da7ae69f03..a8c4836dd252 100644 --- a/monkestation/code/modules/botany/species/apid/hive/ability.dm +++ b/monkestation/code/modules/botany/species/apid/hive/ability.dm @@ -5,8 +5,10 @@ button_icon = 'icons/obj/hydroponics/equipment.dmi' button_icon_state = "beebox" - cooldown_time = 25 MINUTES + cooldown_time = 5 MINUTES spell_requirements = NONE +//MONKESTATION EDIT : Reducing the cooldown from 25 to 10 minutes. +// The time was extremely long before, almost twice as the time to **make** a hive. This is healthier, equating to double of the time of the beehive. var/obj/structure/beebox/hive/created_hive @@ -19,7 +21,7 @@ . = ..() if(is_species(user, /datum/species/apid)) var/datum/species/apid/apid = user.dna.species - if(apid.stored_honey < 150) + if(apid.stored_honey < 70) to_chat(user, span_notice("Not enough stored honey")) addtimer(CALLBACK(src, PROC_REF(reset_spell_cooldown)), 2 SECONDS) return @@ -30,14 +32,16 @@ if(is_species(user, /datum/species/apid)) var/datum/species/apid/apid = user.dna.species - if(apid.stored_honey < 150) + if(apid.stored_honey < 70) addtimer(CALLBACK(src, PROC_REF(reset_spell_cooldown)), 2 SECONDS) return - apid.adjust_honeycount(-150) + apid.adjust_honeycount(-70) created_hive = new(get_turf(user), user.real_name) apid.owned_hive = created_hive created_hive.current_stat = apid.current_stat + //MONKESTATION EDIT : Changed the total requirement from 15 minutes to a reasonable 7. + //The amount of time investment this required only incentivized an isolated style of gameplay, this should be healthier and incentivize the use of beehives earlier for interactions with crewmembers. RegisterSignals(created_hive, list(COMSIG_QDELETING, COMSIG_PREQDELETED), PROC_REF(remove_hive)) diff --git a/monkestation/code/modules/botany/species/apid/hive/hive_object.dm b/monkestation/code/modules/botany/species/apid/hive/hive_object.dm index b0cf51e09701..23ba9278c4c7 100644 --- a/monkestation/code/modules/botany/species/apid/hive/hive_object.dm +++ b/monkestation/code/modules/botany/species/apid/hive/hive_object.dm @@ -100,25 +100,25 @@ GLOBAL_LIST_INIT(hive_exits, list()) RegisterSignal(get_area(src), COMSIG_AREA_ENTERED, PROC_REF(enter_area)) /obj/structure/hive_exit/Destroy() - . = ..() - if(!linked_hive || !get_turf(linked_hive)) - return - var/turf/turf = get_turf(linked_hive) - for(var/atom/movable/listed in atoms_inside) - if(isnull(turf)) - continue - listed.forceMove(turf) - var/area/area = get_area(src) - for(var/atom/movable/movable as anything in area) - if(isturf(movable)) - continue - if(isnull(turf)) - continue - movable.forceMove(turf) + if(linked_hive) + var/turf/turf = get_turf(linked_hive) + for(var/atom/movable/listed in atoms_inside) + if(isnull(turf)) + continue + listed.forceMove(turf) + var/area/area = get_area(src) + for(var/atom/movable/movable as anything in area) + if(isturf(movable)) + continue + if(isnull(turf)) + continue + movable.forceMove(turf) + + linked_hive.linked_exit = null + linked_hive = null GLOB.hive_exits -= src - linked_hive?.linked_exit = null - linked_hive = null + return ..() /obj/structure/hive_exit/attack_hand(mob/living/user, list/modifiers) . = ..() diff --git a/monkestation/code/modules/cassettes/machines/media/jukebox.dm b/monkestation/code/modules/cassettes/machines/media/jukebox.dm index 98edbca0c226..53789eb5514c 100644 --- a/monkestation/code/modules/cassettes/machines/media/jukebox.dm +++ b/monkestation/code/modules/cassettes/machines/media/jukebox.dm @@ -310,7 +310,7 @@ // Just junk to make it sneaky - I wish a lot more stuff was on /obj/machinery/media instead of /jukebox so I could use that. /obj/machinery/media/jukebox/ghost/audible_message(message, deaf_message, hearing_distance = DEFAULT_MESSAGE_RANGE, self_message, audible_message_flags = NONE) return -/obj/machinery/media/jukebox/ghost/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs, visible_message_flags = NONE) +/obj/machinery/media/jukebox/ghost/visible_message(message, self_message, blind_message, vision_distance = DEFAULT_MESSAGE_RANGE, list/ignored_mobs, visible_message_flags = NONE, atom/push_appearance) return /obj/machinery/media/jukebox/ghost/attackby(obj/item/W as obj, mob/user as mob) return diff --git a/monkestation/code/modules/client/preference_savefile.dm b/monkestation/code/modules/client/preference_savefile.dm index 9b01aff3e8c6..409fef38895d 100644 --- a/monkestation/code/modules/client/preference_savefile.dm +++ b/monkestation/code/modules/client/preference_savefile.dm @@ -63,8 +63,6 @@ savefile.set_entry("channel_volume", channel_volume) savefile.set_entry("saved_tokens", saved_tokens) savefile.set_entry("extra_stat_inventory", extra_stat_inventory) - if(token_month) - savefile.set_entry("token_month", token_month) savefile.set_entry("lootboxes_owned", lootboxes_owned) savefile.set_entry("antag_rep", antag_rep) @@ -79,7 +77,6 @@ extra_stat_inventory = savefile.get_entry("extra_stat_inventory", extra_stat_inventory) extra_stat_inventory = SANITIZE_LIST(extra_stat_inventory) - token_month = savefile.get_entry("token_month", token_month) lootboxes_owned = savefile.get_entry("lootboxes_owned", lootboxes_owned) antag_rep = savefile.get_entry("antag_rep", antag_rep) diff --git a/monkestation/code/modules/client/preferences.dm b/monkestation/code/modules/client/preferences.dm index 773a4b31cc59..eb0a32388aa2 100644 --- a/monkestation/code/modules/client/preferences.dm +++ b/monkestation/code/modules/client/preferences.dm @@ -29,6 +29,7 @@ "event_tokens" = 0, "event_token_month" = 0, "donator" = 0, + "donator_token_month" = 0, ) ///amount of metaconis you can earn per shift @@ -36,8 +37,6 @@ ///Alternative job titles stored in preferences. Assoc list, ie. alt_job_titles["Scientist"] = "Cytologist" var/list/alt_job_titles = list() - /// the month we used our last donator token on - var/token_month = 0 /// these are inventory items that require external data to load correctly var/list/extra_stat_inventory = list( "unusual" = list(), diff --git a/monkestation/code/modules/clothing/neck/cloaks.dm b/monkestation/code/modules/clothing/neck/cloaks.dm index 7a0e3e23fb00..a0a776c90956 100644 --- a/monkestation/code/modules/clothing/neck/cloaks.dm +++ b/monkestation/code/modules/clothing/neck/cloaks.dm @@ -152,13 +152,107 @@ /obj/item/clothing/neck/mentorcloak name = "mentor cloak" desc = "Buzz!" - icon = 'monkestation/icons/obj/clothing/necks.dmi' - worn_icon = 'monkestation/icons/obj/clothing/necks.dmi' - icon_state = "mentor" + icon = 'monkestation/icons/obj/clothing/necks/mentor_cloaks.dmi' + worn_icon = 'monkestation/icons/mob/clothing/necks/mentor_cloaks.dmi' + icon_state = "green_cloak" + worn_icon_state = "green_cloak" + var/current_cloak = "green" + var/current_cloak_overlay = "lizar" + var/datum/action/innate/select_cloak_appearance/select_cloak_appearance /obj/item/clothing/neck/mentorcloak/Initialize(mapload) . = ..() - AddComponent(/datum/component/toggle_clothes, "mentor_t") + select_cloak_appearance = new(src) + +/obj/item/clothing/neck/mentorcloak/Destroy(force) + QDEL_NULL(select_cloak_appearance) + return ..() + +/obj/item/clothing/neck/mentorcloak/examine(mob/user) + . = ..() + if(user.mind?.has_antag_datum(/datum/antagonist/changeling)) + . += span_warning("Well you can still feel the displeasure from the cloak it feels like \ + it might just let you wear it") + if(!user.client?.is_mentor()) + . += span_warning("You can feel this cloak dispises you for lacking a high enough level of knowledge") + +/obj/item/clothing/neck/mentorcloak/equipped(mob/living/user, slot) + . = ..() + if(slot & ITEM_SLOT_NECK) + if(user.mind?.has_antag_datum(/datum/antagonist/changeling)) + to_chat(user, span_notice("I'll let you get way with it this time.")) + else if(!user.client?.is_mentor()) + lightningbolt(user) + user.dropItemToGround(src) + to_chat(user, span_userdanger("No mentor cloak for you!")) + return + select_cloak_appearance.Grant(user) + if(slot & ITEM_SLOT_HANDS) + if(user.mind?.has_antag_datum(/datum/antagonist/changeling)) + to_chat(user, span_notice("You feel it's power flow through your body")) + else if(!user.client?.is_mentor()) + user.cause_pain(FULL_BODY, 20, STAMINA) + user.sharp_pain(ARMS, 5, BURN, 20) + user.apply_status_effect(/datum/status_effect/confusion) + user.apply_status_effect(/datum/status_effect/jitter) + user.apply_status_effect(/datum/status_effect/terrified) + user.apply_status_effect(/datum/status_effect/temporary_blindness) + to_chat(user, span_userdanger("You feel a surge of power hit you like a [span_bolddanger("TRUCK")] draining your stamina instantly")) + +/obj/item/clothing/neck/mentorcloak/dropped(mob/living/user) + . = ..() + if(user.get_item_by_slot(ITEM_SLOT_NECK) == src) + select_cloak_appearance.Remove(user) + +/obj/item/clothing/neck/mentorcloak/worn_overlays(mutable_appearance/standing, isinhands) + . = ..() + if(!isinhands && current_cloak_overlay) + . += mutable_appearance('monkestation/icons/mob/clothing/necks/mentor_cloak_overlays.dmi', current_cloak_overlay) + +/datum/action/innate/select_cloak_appearance + name = "Select Cloak Appearance" + desc = "Select the appearance of your mentor cloak" + button_icon = 'monkestation/icons/obj/clothing/necks/mentor_cloaks.dmi' + button_icon_state = "green_cloak" + background_icon_state = "bg_revenant" + overlay_icon_state = "bg_revenant_border" + +/datum/action/innate/select_cloak_appearance/Activate() + . = ..() + var/static/list/possible_cloaks = list( + "black_cloak" = image(icon = 'monkestation/icons/obj/clothing/necks/mentor_cloaks.dmi', icon_state = "black_cloak"), + "blue_cloak" = image(icon = 'monkestation/icons/obj/clothing/necks/mentor_cloaks.dmi', icon_state = "blue_cloak"), + "red_cloak" = image(icon = 'monkestation/icons/obj/clothing/necks/mentor_cloaks.dmi', icon_state = "red_cloak"), + "purple_cloak" = image(icon = 'monkestation/icons/obj/clothing/necks/mentor_cloaks.dmi', icon_state = "purple_cloak"), + "green_cloak" = image(icon = 'monkestation/icons/obj/clothing/necks/mentor_cloaks.dmi', icon_state = "green_cloak"), + "bloak" = image(icon = 'monkestation/icons/obj/clothing/necks/mentor_cloaks.dmi', icon_state = "bloak"), + "flesh_cloak" = image(icon = 'monkestation/icons/obj/clothing/necks/mentor_cloaks.dmi', icon_state = "flesh_cloak") + ) + var/static/list/possible_cloak_overlays = list( + "lizar" = image(icon = 'monkestation/icons/hud/radial_mentor_cloak.dmi', icon_state = "lizar"), + "moff" = image(icon = 'monkestation/icons/hud/radial_mentor_cloak.dmi', icon_state = "moff"), + "sillycones" = image(icon = 'monkestation/icons/hud/radial_mentor_cloak.dmi', icon_state = "sillycones"), + "human" = image(icon = 'monkestation/icons/hud/radial_mentor_cloak.dmi', icon_state = "human"), + "ethereal" = image(icon = 'monkestation/icons/hud/radial_mentor_cloak.dmi', icon_state = "ethereal"), + "plasmeme" = image(icon = 'monkestation/icons/hud/radial_mentor_cloak.dmi', icon_state = "plasmeme"), + "snek" = image(icon = 'monkestation/icons/hud/radial_mentor_cloak.dmi', icon_state = "snek"), + "bee" = image(icon = 'monkestation/icons/hud/radial_mentor_cloak.dmi', icon_state = "bee") + ) + var/picked_cloak = show_radial_menu(owner, owner, possible_cloaks, radius = 50, require_near = TRUE) + if(!picked_cloak) + return + var/picked_cloak_overlay = show_radial_menu(owner, owner, possible_cloak_overlays, radius = 50, require_near = TRUE) + if(!picked_cloak_overlay) + return + var/obj/item/clothing/neck/mentorcloak/mentorcloak = owner.get_item_by_slot(ITEM_SLOT_NECK) + if(!mentorcloak) + return + mentorcloak.current_cloak = picked_cloak + mentorcloak.current_cloak_overlay = picked_cloak_overlay + mentorcloak.icon_state = picked_cloak + mentorcloak.worn_icon_state = picked_cloak + mentorcloak.update_slot_icon() + mentorcloak.update_appearance() /obj/item/clothing/neck/helldivercape name = "helldiver cape" diff --git a/monkestation/code/modules/map_gen_expansions/mushroom/extraction/structures/extractor/hub.dm b/monkestation/code/modules/map_gen_expansions/mushroom/extraction/structures/extractor/hub.dm index 4e2a63b42cab..5e8fc40497fe 100644 --- a/monkestation/code/modules/map_gen_expansions/mushroom/extraction/structures/extractor/hub.dm +++ b/monkestation/code/modules/map_gen_expansions/mushroom/extraction/structures/extractor/hub.dm @@ -30,6 +30,20 @@ TODO LIST: ///The main pipe that owns us as part of our 3x3 machine. var/obj/structure/plasma_extraction_hub/part/pipe/main/pipe_owner +/obj/structure/plasma_extraction_hub/part/Destroy() + pipe_owner = null + return ..() + +/** + * A piece of the extractor itself, that otherwise does not act as a pipe. + */ +/obj/structure/plasma_extraction_hub/part/extractor + +/obj/structure/plasma_extraction_hub/part/extractor/Destroy() + if(pipe_owner) + pipe_owner.extractor_parts -= src + return ..() + /** * Plasma extraction machine pipe * There's 3 of these on each plasma extraction machine, one of which is the owner of the rest. @@ -48,9 +62,11 @@ TODO LIST: AddComponent(/datum/component/pipe_laying, src) /obj/structure/plasma_extraction_hub/part/pipe/Destroy() - . = ..() + if(pipe_owner) + pipe_owner.hub_parts -= src last_pipe = null QDEL_LIST(connected_pipes) + return ..() /** * Called when a pipe with a reference to us is destroyed, diff --git a/monkestation/code/modules/map_gen_expansions/mushroom/extraction/structures/extractor/main.dm b/monkestation/code/modules/map_gen_expansions/mushroom/extraction/structures/extractor/main.dm index 9cd43b2fd394..13dfc4e52c88 100644 --- a/monkestation/code/modules/map_gen_expansions/mushroom/extraction/structures/extractor/main.dm +++ b/monkestation/code/modules/map_gen_expansions/mushroom/extraction/structures/extractor/main.dm @@ -13,7 +13,9 @@ ///This is used to tell recently repaired pipes that they should get back to working. var/drilling = FALSE ///List of all parts connected to the extraction hub, not including ourselves. - var/list/obj/structure/plasma_extraction_hub/hub_parts = list() + var/list/obj/structure/plasma_extraction_hub/part/pipe/hub_parts = list() + ///List of all parts which make up the extractor's sprite. Excludes parts which act as pipes. + var/list/obj/structure/plasma_extraction_hub/part/extractor/extractor_parts = list() /obj/structure/plasma_extraction_hub/part/pipe/main/Initialize(mapload) . = ..() @@ -21,6 +23,7 @@ /obj/structure/plasma_extraction_hub/part/pipe/main/Destroy() QDEL_LIST(hub_parts) + QDEL_LIST(extractor_parts) if(display_panel_ref) QDEL_NULL(display_panel_ref) return ..() @@ -51,7 +54,8 @@ hub_parts += new_part new_part.icon_state = "extractor-middle-left" else - new_part = new/obj/structure/plasma_extraction_hub/part(spawned_turf) + new_part = new/obj/structure/plasma_extraction_hub/part/extractor(spawned_turf) + extractor_parts += new_part switch(count) if(9) new_part.icon_state = "extractor-bottom-left" diff --git a/monkestation/code/datums/martial_arts/awakened_dragon.dm b/monkestation/code/modules/martial_arts/awakened_dragon.dm similarity index 91% rename from monkestation/code/datums/martial_arts/awakened_dragon.dm rename to monkestation/code/modules/martial_arts/awakened_dragon.dm index 08671dbbc4b7..632cae09c605 100644 --- a/monkestation/code/datums/martial_arts/awakened_dragon.dm +++ b/monkestation/code/modules/martial_arts/awakened_dragon.dm @@ -5,6 +5,8 @@ deflect_cooldown = 0 deflect_stamcost = 10 log_name = "Awakened Dragon" + scarp_traits = list(TRAIT_NOGUNS, TRAIT_NEVER_WOUNDED, TRAIT_NODISMEMBER, TRAIT_LIGHT_SLEEPER, TRAIT_THROW_GUNS, TRAIT_BATON_RESISTANCE) + counter = TRUE var/title = null //YOUR TITLE BELOW THE HEAVENS! This is the prefix you use :] var/static/list/character_prefixes = list( "Heavenly Demon", @@ -20,8 +22,6 @@ var/original_name var/titled_name var/list/datum/weakref/all_bodies = list() - scarp_traits = list(TRAIT_NOGUNS, TRAIT_NEVER_WOUNDED, TRAIT_NODISMEMBER, TRAIT_LIGHT_SLEEPER, TRAIT_THROW_GUNS, TRAIT_BATON_RESISTANCE) - counter = TRUE /datum/martial_art/the_sleeping_carp/awakened_dragon/teach(mob/living/carbon/human/target, make_temporary) . = ..() @@ -31,33 +31,31 @@ if(title == null) title = pick(character_prefixes) all_bodies += target - titled_name = "[title] [target.get_face_name(original_name)]" + titled_name = "[title] [original_name]" target.fully_replace_character_name(original_name, titled_name) /datum/martial_art/the_sleeping_carp/awakened_dragon/remove(mob/living/carbon/human/target) . = ..() target.fully_replace_character_name(titled_name, original_name) - -/datum/martial_art/the_sleeping_carp/awakened_dragon/strongPunch(mob/living/attacker, mob/living/defender) - . = ..() +/datum/martial_art/the_sleeping_carp/awakened_dragon/strongPunch(mob/living/attacker, mob/living/defender, set_damage) damage = 40 wounding = 15 + . = ..(attacker, defender, set_damage = FALSE) attacker.say("Crushing Maw!!", forced = /datum/martial_art/the_sleeping_carp/awakened_dragon, ignore_spam = TRUE) - -/datum/martial_art/the_sleeping_carp/awakened_dragon/launchKick(mob/living/attacker, mob/living/defender) - . = ..() +/datum/martial_art/the_sleeping_carp/awakened_dragon/launchKick(mob/living/attacker, mob/living/defender, set_damage) damage = 30 kick_speed = 5 wounding = 5 zone = BODY_ZONE_HEAD zone_message = "head" + . = ..(attacker, defender, set_damage = FALSE) attacker.say("Tsunami Kick of the Heavenly Serpent!!", forced = /datum/martial_art/the_sleeping_carp/awakened_dragon, ignore_spam = TRUE) -/datum/martial_art/the_sleeping_carp/awakened_dragon/dropKick(mob/living/attacker, mob/living/defender) - . = ..() +/datum/martial_art/the_sleeping_carp/awakened_dragon/dropKick(mob/living/attacker, mob/living/defender, set_damage) stamina_damage = 50 + . = ..(attacker, defender, set_damage = FALSE) defender.apply_damage(30, attacker.get_attack_type(), defender.zone_selected, wound_bonus = 10, bare_wound_bonus = 5) attacker.say("Heavenly Dragon Kick!!", forced = /datum/martial_art/the_sleeping_carp/awakened_dragon, ignore_spam = TRUE) diff --git a/monkestation/code/modules/martial_arts/tunnel_arts.dm b/monkestation/code/modules/martial_arts/tunnel_arts.dm index 2b183d7e4cf0..c07a94a4dd73 100644 --- a/monkestation/code/modules/martial_arts/tunnel_arts.dm +++ b/monkestation/code/modules/martial_arts/tunnel_arts.dm @@ -11,10 +11,16 @@ allow_temp_override = FALSE help_verb = /mob/living/proc/tunnel_arts_help display_combos = TRUE - /// List of traits applied to users of this martial art. - var/list/tunnel_traits = list(TRAIT_HARDLY_WOUNDED, TRAIT_NOSOFTCRIT, TRAIT_BATON_RESISTANCE, TRAIT_PERFECT_ATTACKER, TRAIT_NOGUNS) /// Probability of successfully blocking attacks while on throw mode block_chance = 50 + /// List of traits applied to users of this martial art. + var/static/list/tunnel_traits = list( + TRAIT_HARDLY_WOUNDED, + TRAIT_NOSOFTCRIT, + TRAIT_BATON_RESISTANCE, + TRAIT_PERFECT_ATTACKER, + TRAIT_NOGUNS + ) /datum/martial_art/the_tunnel_arts/teach(mob/living/new_holder) . = ..() @@ -48,13 +54,12 @@ var/obj/item/bodypart/affecting = defender.get_bodypart(defender.get_random_valid_zone(attacker.zone_selected)) attacker.do_attack_animation(defender, ATTACK_EFFECT_PUNCH) defender.visible_message( - span_danger("[attacker] uppercuts [defender], sending them skyward!"), + span_danger("[attacker] uppercuts [defender], sending [defender.p_them()] skyward!"), span_userdanger("[attacker] uppercuts you, sending you hurtling through the air!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), - null, - attacker, + ignored_mobs = list(attacker), ) - to_chat(attacker, span_danger("You uppercut [defender]!")) + to_chat(attacker, span_danger("You uppercut [defender]!"), type = MESSAGE_TYPE_COMBAT) playsound(defender, 'sound/weapons/punch1.ogg', 25, TRUE, -1) log_combat(attacker, defender, "god fist (The Tunnel Arts))") defender.apply_damage(20, attacker.get_attack_type(), affecting) @@ -69,13 +74,12 @@ var/obj/item/bodypart/affecting = defender.get_bodypart(defender.get_random_valid_zone(attacker.zone_selected)) attacker.do_attack_animation(defender, ATTACK_EFFECT_PUNCH) defender.visible_message( - span_danger("[attacker] slams their palm into [defender]!"), + span_danger("[attacker] slams [attacker.p_their()] palm into [defender]!"), span_userdanger("[attacker] palm strikes you, rattling you to your very core!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), - null, - attacker, + ignored_mobs = list(attacker), ) - to_chat(attacker, span_danger("You palm strike [defender], corrupting their Chi energy!")) + to_chat(attacker, span_danger("You palm strike [defender], corrupting [defender.p_their()] Chi energy!"), type = MESSAGE_TYPE_COMBAT) playsound(defender, 'sound/weapons/punch1.ogg', 25, TRUE, -1) log_combat(attacker, defender, "god fist (The Tunnel Arts))") defender.apply_damage(30, attacker.get_attack_type(), affecting) @@ -94,10 +98,9 @@ span_danger("[attacker] punches [defender] with a rapid series of blows!"), span_userdanger("[attacker] rapidly punches you!"), span_hear("You hear a sickening sound of flesh hitting flesh!"), - null, - attacker, + ignored_mobs = list(attacker), ) - to_chat(attacker, span_danger("You rapidly punch [defender]!")) + to_chat(attacker, span_danger("You rapidly punch [defender]!"), type = MESSAGE_TYPE_COMBAT) // Borrows this trick from standard holoparsites for(var/sounds in 1 to 4) @@ -109,18 +112,17 @@ if(!defender.mind || defender.stat != CONSCIOUS || prob(50)) return TRUE - var/mob/living/simple_animal/hostile/illusion/khan = new(attacker.loc) + var/mob/living/simple_animal/hostile/illusion/khan_warrior/khan = new(attacker.loc) khan.faction = attacker.faction.Copy() - khan.Copy_Parent(attacker, 100, attacker.health/2.5, 12, 30) + khan.Copy_Parent(attacker, 100, attacker.health / 2.5, 12, 30) khan.GiveTarget(defender) attacker.visible_message( span_danger("[attacker] seems to duplicate before your very eyes!"), span_userdanger("[attacker] seems to duplicate before your eyes!"), span_hear("You hear a multitude of stamping feet!"), - null, - attacker, + ignored_mobs = list(attacker), ) - to_chat(attacker, span_danger("You conjure an illusionary warrior to fight with you!")) + to_chat(attacker, span_danger("You conjure an illusionary warrior to fight with you!"), type = MESSAGE_TYPE_COMBAT) return TRUE /// Echo our punching sounds @@ -153,7 +155,7 @@ span_hear("You hear a sickening snap!"), ignored_mobs = attacker ) - to_chat(attacker, span_danger("In a swift motion, you snap the neck of [defender]!")) + to_chat(attacker, span_danger("In a swift motion, you snap the neck of [defender]!"), type = MESSAGE_TYPE_COMBAT) log_combat(attacker, defender, "snapped neck") defender.apply_damage(100, BRUTE, BODY_ZONE_HEAD, wound_bonus=CANT_WOUND) if(!HAS_TRAIT(defender, TRAIT_NODEATH)) @@ -179,8 +181,8 @@ log_combat(attacker, defender, "disarmed (The Tunnel Arts)") return MARTIAL_ATTACK_INVALID // normal disarm -/datum/martial_art/the_tunnel_arts/proc/check_usability(mob/living/khan_user) - if(!(khan_user.istate & ISTATE_HARM)) // monke edit: istates/intents +/datum/martial_art/the_tunnel_arts/proc/check_usability(mob/living/khan_user, check_intent = TRUE) + if(check_intent && !(khan_user.istate & ISTATE_HARM)) return FALSE if(khan_user.incapacitated(IGNORE_GRAB)) //NO STUN return FALSE @@ -194,12 +196,11 @@ return TRUE ///Signal from getting attacked with an item, for a special interaction with touch spells -/datum/martial_art/the_tunnel_arts/proc/on_attackby(mob/living/khan_user, obj/item/attack_weapon, mob/attacker, params) +/datum/martial_art/the_tunnel_arts/proc/on_attackby(mob/living/khan_user, obj/item/melee/touch_attack/touch_weapon, mob/attacker, params) SIGNAL_HANDLER - if(!istype(attack_weapon, /obj/item/melee/touch_attack) || !check_usability(khan_user)) + if(!istype(touch_weapon) || !check_usability(khan_user, check_intent = !touch_weapon.dangerous)) return - var/obj/item/melee/touch_attack/touch_weapon = attack_weapon khan_user.visible_message( span_danger("[khan_user] carefully dodges [attacker]'s [touch_weapon]!"), span_userdanger("You take great care to remain untouched by [attacker]'s [touch_weapon]!"), @@ -207,6 +208,7 @@ ) to_chat(attacker, span_userdanger("[khan_user] carefully dodges your [touch_weapon], remaining completely untouched!"), type = MESSAGE_TYPE_COMBAT) khan_user.balloon_alert(attacker, "miss!") + attacker.changeNext_move(CLICK_CD_MELEE) playsound(khan_user, 'monkestation/sound/effects/miss.ogg', vol = 50, vary = TRUE, extrarange = SHORT_RANGE_SOUND_EXTRARANGE) return COMPONENT_NO_AFTERATTACK @@ -216,12 +218,15 @@ set desc = "Remember the martial techniques of Maint Khan, who brought to the Spinward Sector the knowledge of the Tunnel Arts." set category = "The Tunnel Arts" - to_chat(usr, "You retreat inward and recall the teachings of the Tunnel Arts...\n\ + to_chat(src, "You retreat inward and recall the teachings of the Tunnel Arts...\n\ [span_notice("One Thousand Fists")]: Punch Punch. Deal additional damage every second (consecutive) punch, and potentially conjure forth an illusionary Khan Warrior.\n\ [span_notice("Chaos Reigns")]: Shove Punch. Launch your opponent away from you and corrupt their Chi energy, causing them to flail madly in their confused state!\n\ [span_notice("Space Wind God Fist")]: Punch Shove. Send the target spinning helplessly through the air with this vicious uppercut.\n\ While in throw mode (and not stunned, not a hulk, and not in a mech), you can block various attacks against you in melee with your bare hands!") +/mob/living/simple_animal/hostile/illusion/khan_warrior + speed = 0 + #undef SPACE_WIND_GOD_FIST_COMBO #undef CHAOS_REIGNS_COMBO #undef ONE_THOUSAND_FISTS_COMBO diff --git a/monkestation/code/modules/modular_computers/file_system/programs/spesstv.dm b/monkestation/code/modules/modular_computers/file_system/programs/spesstv.dm new file mode 100644 index 000000000000..e757ad3f3b1a --- /dev/null +++ b/monkestation/code/modules/modular_computers/file_system/programs/spesstv.dm @@ -0,0 +1,98 @@ +#define STREAM_ALERT_COOLDOWN (5 SECONDS) +/// Global lazylist containing who's watching what spesstv streams. +GLOBAL_LIST(spesstv_viewers) + +/datum/computer_file/program/secureye/spesstv + filename = "spesstv" + filedesc = "Spess.tv" + extended_desc = "This program allows users to tune into public streams." + transfer_access = list() + usage_flags = PROGRAM_ALL + size = 0 + program_icon = FA_ICON_VIDEO + alert_able = TRUE + network = list() + /// The radio used to listen to the entertainment channel. + var/obj/item/radio/entertainment/speakers/pda/radio + /// Coolwdown for stream alerts. + COOLDOWN_DECLARE(alert_cooldown) + +/datum/computer_file/program/secureye/spesstv/New() + . = ..() + RegisterSignal(SSdcs, COMSIG_GLOB_NETWORK_BROADCAST_UPDATED, PROC_REF(on_network_broadcast_updated)) + +/datum/computer_file/program/secureye/spesstv/Destroy() + LAZYREMOVE(GLOB.spesstv_viewers, REF(src)) + UnregisterSignal(SSdcs, COMSIG_GLOB_NETWORK_BROADCAST_UPDATED) + QDEL_NULL(radio) + return ..() + +/datum/computer_file/program/secureye/spesstv/on_start(mob/living/user) + . = ..() + if(. && QDELETED(radio) && !QDELETED(computer)) + radio = new(computer) + +/datum/computer_file/program/secureye/spesstv/kill_program(mob/user) + . = ..() + if(.) + LAZYREMOVE(GLOB.spesstv_viewers, REF(src)) + QDEL_NULL(radio) + +/datum/computer_file/program/secureye/spesstv/background_program() + . = ..() + if(.) + LAZYREMOVE(GLOB.spesstv_viewers, REF(src)) + +/datum/computer_file/program/secureye/spesstv/update_active_camera_screen() + . = ..() + update_spesstv_watcher_list(REF(src), camera_ref) + +/datum/computer_file/program/secureye/spesstv/proc/on_network_broadcast_updated(datum/source, tv_show_id, is_show_active, announcement) + SIGNAL_HANDLER + if(is_show_active) + network |= tv_show_id + alert_pending = TRUE + else + network -= tv_show_id + if(!length(network)) + alert_pending = FALSE + LAZYREMOVE(GLOB.spesstv_viewers, REF(src)) + if(!QDELETED(computer)) + if(announcement && COOLDOWN_FINISHED(src, alert_cooldown)) + computer.alert_call(src, announcement, vision_distance = 2) + COOLDOWN_START(src, alert_cooldown, STREAM_ALERT_COOLDOWN) + INVOKE_ASYNC(computer, TYPE_PROC_REF(/datum, update_static_data_for_all_viewers)) + +/obj/item/radio/entertainment/speakers/pda + canhear_range = 0 + +/obj/item/radio/entertainment/speakers/pda/Initialize(mapload) + . = ..() + if(!istype(loc, /obj/item/modular_computer)) + stack_trace("[type] spawned outside of a modular computer!") + return INITIALIZE_HINT_QDEL + RegisterSignal(loc, COMSIG_QDELETING, PROC_REF(on_loc_destroyed)) + +/obj/item/radio/entertainment/speakers/pda/Destroy() + if(!isnull(loc)) + UnregisterSignal(loc, COMSIG_QDELETING) + return ..() + +/obj/item/radio/entertainment/speakers/pda/proc/on_loc_destroyed(datum/source) + SIGNAL_HANDLER + if(!QDELETED(src)) + qdel(src) + +/obj/item/radio/entertainment/speakers/pda/emp_act(severity) + return + +/proc/update_spesstv_watcher_list(key, obj/machinery/camera/active_camera) + if(istype(active_camera, /datum/weakref)) + var/datum/weakref/camera_ref = active_camera + active_camera = camera_ref.resolve() + if(QDELETED(active_camera) || !active_camera.can_use()) + LAZYREMOVE(GLOB.spesstv_viewers, key) + else + LAZYSET(GLOB.spesstv_viewers, key, active_camera.c_tag) + +#undef STREAM_ALERT_COOLDOWN diff --git a/monkestation/code/modules/slimecore/machines/biomass_recycler.dm b/monkestation/code/modules/slimecore/machines/biomass_recycler.dm index b735aed76d93..b6db24849f4a 100644 --- a/monkestation/code/modules/slimecore/machines/biomass_recycler.dm +++ b/monkestation/code/modules/slimecore/machines/biomass_recycler.dm @@ -181,3 +181,8 @@ GLOBAL_LIST_INIT(biomass_unlocks, list()) name = "\"Rockroach\" biomass recycler upgrade disk" printable_types = list(/mob/living/basic/cockroach/rockroach = 0.4) vacuum_printable_types = list(/mob/living/basic/cockroach/rockroach = 0.4) + +/datum/slime_store_item/rockroach + name = "\"Rockroach\" biomass recycler upgrade disk" + desc = "An upgrade disk for the biomass recycler that allows for the printing of Rockroaches." + item_path = /obj/item/disk/biomass_upgrade/rockroach diff --git a/monkestation/code/modules/slimecore/machines/extract_requestor.dm b/monkestation/code/modules/slimecore/machines/extract_requestor.dm index 09f927c4d29c..351c6b71c245 100644 --- a/monkestation/code/modules/slimecore/machines/extract_requestor.dm +++ b/monkestation/code/modules/slimecore/machines/extract_requestor.dm @@ -29,6 +29,12 @@ name_to_path |= list("[new_extract.name]" = new_extract.type) qdel(new_extract) +/obj/machinery/slime_extract_requestor/Destroy() + if(console?.request_pad == src) + console.request_pad = null + console = null + return ..() + /obj/machinery/slime_extract_requestor/attack_hand(mob/living/user, list/modifiers) . = ..() if(!console) diff --git a/monkestation/code/modules/slimecore/machines/slime_market.dm b/monkestation/code/modules/slimecore/machines/slime_market.dm index c74b67983d1f..8af2adee7f37 100644 --- a/monkestation/code/modules/slimecore/machines/slime_market.dm +++ b/monkestation/code/modules/slimecore/machines/slime_market.dm @@ -26,6 +26,13 @@ . = ..() link_console() +/obj/machinery/slime_market_pad/Destroy() + var/consoles_market_pad = console?.market_pad + if(consoles_market_pad == src) + console.market_pad = null + console = null + return ..() + /obj/machinery/slime_market_pad/AltClick(mob/user) . = ..() if(!.) diff --git a/monkestation/code/modules/slimecore/machines/slime_market_computer.dm b/monkestation/code/modules/slimecore/machines/slime_market_computer.dm index a3394c7a0105..923ad0c944de 100644 --- a/monkestation/code/modules/slimecore/machines/slime_market_computer.dm +++ b/monkestation/code/modules/slimecore/machines/slime_market_computer.dm @@ -24,7 +24,6 @@ GLOBAL_DATUM(default_slime_market, /obj/machinery/computer/slime_market) link_market_pad() /obj/machinery/computer/slime_market/Destroy() - . = ..() if(GLOB.default_slime_market == src) GLOB.default_slime_market = null @@ -35,6 +34,7 @@ GLOBAL_DATUM(default_slime_market, /obj/machinery/computer/slime_market) request_pad = null market_pad = null + return ..() /obj/machinery/computer/slime_market/proc/link_market_pad() if(market_pad) diff --git a/monkestation/code/modules/slimecore/machines/slime_store/mutators.dm b/monkestation/code/modules/slimecore/machines/slime_store/mutators.dm index 2efd6938d7cb..eda9abcb5774 100644 --- a/monkestation/code/modules/slimecore/machines/slime_store/mutators.dm +++ b/monkestation/code/modules/slimecore/machines/slime_store/mutators.dm @@ -36,7 +36,7 @@ /datum/slime_store_item/random_color_mutator name = "Random Color Mutation Syringe" - desc = "Adds the No Ooze Slime mutation to a single slime." + desc = "Mutates a single slime into a possible mutation." item_path = /obj/item/slime_mutation_syringe/random_color cost = 3000 diff --git a/monkestation/code/modules/slimecore/slime_color_mutations/colors.dm b/monkestation/code/modules/slimecore/slime_color_mutations/colors.dm index 97c9f1e167d2..f41a57563d1b 100644 --- a/monkestation/code/modules/slimecore/slime_color_mutations/colors.dm +++ b/monkestation/code/modules/slimecore/slime_color_mutations/colors.dm @@ -135,7 +135,7 @@ /datum/slime_mutation_data/oil, ) -/datum/slime_color/darkpurple/on_first_unlock() +/datum/slime_color/red/on_first_unlock() GLOB.biomass_unlocks |= list(/mob/living/basic/xenofauna/dron = 1) /datum/slime_color/yellow diff --git a/monkestation/code/modules/spells/spell_types/touch/_touch.dm b/monkestation/code/modules/spells/spell_types/touch/_touch.dm new file mode 100644 index 000000000000..e5b3f8957ced --- /dev/null +++ b/monkestation/code/modules/spells/spell_types/touch/_touch.dm @@ -0,0 +1,7 @@ +/obj/item/melee/touch_attack + /// If this touch attack is "dangerous" - this is used for martial arts bypassing intent checks. + /// This should only be FALSE for benign / non-antag attacks, to prevent metagaming by randomly shock touching people to see if they have martial arts. + var/dangerous = TRUE + +/obj/item/melee/touch_attack/shock + dangerous = FALSE diff --git a/monkestation/code/modules/virology/disease/premades/transformations.dm b/monkestation/code/modules/virology/disease/premades/transformations.dm index ce075632cff3..2540ce0894fe 100644 --- a/monkestation/code/modules/virology/disease/premades/transformations.dm +++ b/monkestation/code/modules/virology/disease/premades/transformations.dm @@ -10,10 +10,16 @@ spread_flags = DISEASE_SPREAD_BLOOD robustness = 75 + infectionchance = 0 infectionchance_base = 0 stage_variance = 0 +/datum/disease/acute/premade/gondola/activate(mob/living/mob, starved, seconds_per_tick) + . = ..() + if(mob.has_reagent(/datum/reagent/consumable/condensedcapsaicin, 1)) //Pepperspray can ruin anyones peaceful existancce. + cure() + /datum/disease/acute/premade/gondola/digital category = DISEASE_GONDOLA_DIGITAL @@ -37,6 +43,11 @@ infectionchance_base = 0 stage_variance = 0 +/datum/disease/acute/premade/xeno/activate(mob/living/mob, starved, seconds_per_tick) + . = ..() + if(mob.has_reagent(/datum/reagent/phlogiston, 1)) //Fire + cure() + /datum/disease/acute/premade/corgi name = "Puppification" form = "Puppy Cells" @@ -53,6 +64,11 @@ infectionchance_base = 0 stage_variance = 0 +/datum/disease/acute/premade/corgi/activate(mob/living/mob, starved, seconds_per_tick) + . = ..() + if(mob.has_reagent(/datum/reagent/consumable/coco, 1)) //Feed Ian chocolatebars + cure() + /datum/disease/acute/premade/slime name = "Slime Syndrome" form = "Simplified Cells" @@ -69,6 +85,11 @@ infectionchance_base = 0 stage_variance = 0 +/datum/disease/acute/premade/slime/activate(mob/living/mob, starved, seconds_per_tick) + . = ..() + if(mob.has_reagent(/datum/reagent/water, 1)) //Water is effective against slimes + cure() + /datum/disease/acute/premade/morph name = "Gluttony" form = "Hungering Cells" @@ -85,6 +106,11 @@ infectionchance_base = 0 stage_variance = 0 +/datum/disease/acute/premade/morph/activate(mob/living/mob, starved, seconds_per_tick) + . = ..() + if(mob.has_reagent(/datum/reagent/toxin/lipolicide, 1)) //Empties the hunger + cure() + /datum/disease/acute/premade/robot name = "Nanite Conversion" form = "Nanites" @@ -100,3 +126,8 @@ infectionchance = 0 infectionchance_base = 0 stage_variance = 0 + +/datum/disease/acute/premade/robot/activate(mob/living/mob, starved, seconds_per_tick) + . = ..() + if(mob.has_reagent(/datum/reagent/medicine/system_cleaner, 1)) + cure() diff --git a/monkestation/code/modules/virology/disease/symtoms/restricted/stage1.dm b/monkestation/code/modules/virology/disease/symtoms/restricted/stage1.dm index ec042ea47445..d9e82ca75112 100644 --- a/monkestation/code/modules/virology/disease/symtoms/restricted/stage1.dm +++ b/monkestation/code/modules/virology/disease/symtoms/restricted/stage1.dm @@ -6,7 +6,7 @@ stage = 1 badness = EFFECT_DANGER_HARMFUL severity = 3 - max_chance = 10 + max_chance = 5 var/new_form = /mob/living/carbon/human var/bantype var/transformed_antag_datum //Do we add a specific antag datum once the transformation is complete? @@ -75,32 +75,39 @@ name = "Robotic Transformation" new_form = /mob/living/silicon/robot bantype = JOB_CYBORG + desc = "Restructures the subject cells into a Cyborg. Cure: Synthetic Cleaner" /datum/symptom/transformation/xeno name = "Xenomorph Transformation" new_form = /mob/living/carbon/alien/adult/hunter bantype = ROLE_ALIEN transformed_antag_datum = /datum/antagonist/xeno + desc = "Restructures the subject cells into a premative xeno hunter. Cure: Phlogisto" /datum/symptom/transformation/slime name = "Advanced Mutation Transformation" new_form = /mob/living/basic/slime + desc = "Restructures the subject cells into a slime. Cure: Water" /datum/symptom/transformation/corgi name = "The Barkening" new_form = /mob/living/basic/pet/dog/corgi + desc = "Restructures the subject cells into a corgi. Cure: Coco Powder" /datum/symptom/transformation/morph name = "Gluttony's Blessing" new_form = /mob/living/basic/morph transformed_antag_datum = /datum/antagonist/morph + desc = "Restructures the subject cells into a morph. Cure: Lipolicide" /datum/symptom/transformation/gondola name = "Gondola Transformation" - max_chance = 50 + max_chance = 10 new_form = /mob/living/simple_animal/pet/gondola + desc = "Restructures the subject cells into a gondola. Cure: Condensed Capsaicin" /datum/symptom/transformation/gondola/digital + max_chance = 50 new_form = /mob/living/simple_animal/pet/gondola/virtual_domain /datum/symptom/anxiety diff --git a/monkestation/icons/hud/radial_mentor_cloak.dmi b/monkestation/icons/hud/radial_mentor_cloak.dmi new file mode 100644 index 000000000000..14912b7d217c Binary files /dev/null and b/monkestation/icons/hud/radial_mentor_cloak.dmi differ diff --git a/monkestation/icons/mob/clothing/necks/mentor_cloak_overlays.dmi b/monkestation/icons/mob/clothing/necks/mentor_cloak_overlays.dmi new file mode 100644 index 000000000000..ca6ea37a65bb Binary files /dev/null and b/monkestation/icons/mob/clothing/necks/mentor_cloak_overlays.dmi differ diff --git a/monkestation/icons/mob/clothing/necks/mentor_cloaks.dmi b/monkestation/icons/mob/clothing/necks/mentor_cloaks.dmi new file mode 100644 index 000000000000..db33d5c8fefc Binary files /dev/null and b/monkestation/icons/mob/clothing/necks/mentor_cloaks.dmi differ diff --git a/monkestation/icons/obj/clothing/necks.dmi b/monkestation/icons/obj/clothing/necks.dmi index 1954c253de30..c5c42b1cd5c5 100644 Binary files a/monkestation/icons/obj/clothing/necks.dmi and b/monkestation/icons/obj/clothing/necks.dmi differ diff --git a/monkestation/icons/obj/clothing/necks/mentor_cloaks.dmi b/monkestation/icons/obj/clothing/necks/mentor_cloaks.dmi new file mode 100644 index 000000000000..6d9be3924610 Binary files /dev/null and b/monkestation/icons/obj/clothing/necks/mentor_cloaks.dmi differ diff --git a/tgstation.dme b/tgstation.dme index c88cac7aef4c..0f558949e872 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -431,6 +431,7 @@ #include "code\__DEFINES\~monkestation\hacking.dm" #include "code\__DEFINES\~monkestation\helpers.dm" #include "code\__DEFINES\~monkestation\holomaps.dm" +#include "code\__DEFINES\~monkestation\hud.dm" #include "code\__DEFINES\~monkestation\interaction_particles.dm" #include "code\__DEFINES\~monkestation\ipcs.dm" #include "code\__DEFINES\~monkestation\is_helpers.dm" @@ -4999,6 +5000,7 @@ #include "code\modules\pai\say.dm" #include "code\modules\pai\shell.dm" #include "code\modules\pai\software.dm" +#include "code\modules\pai\datums\screen_icon.dm" #include "code\modules\paperwork\carbonpaper.dm" #include "code\modules\paperwork\clipboard.dm" #include "code\modules\paperwork\contract.dm" @@ -6007,7 +6009,6 @@ #include "monkestation\code\datums\keybinding\communication.dm" #include "monkestation\code\datums\keybinding\living.dm" #include "monkestation\code\datums\looping_sounds\weather.dm" -#include "monkestation\code\datums\martial_arts\awakened_dragon.dm" #include "monkestation\code\datums\memory\key_memories.dm" #include "monkestation\code\datums\mind\_mind.dm" #include "monkestation\code\datums\mocking\client.dm" @@ -6077,8 +6078,10 @@ #include "monkestation\code\game\machinery\player_hologram.dm" #include "monkestation\code\game\machinery\prize_vendor.dm" #include "monkestation\code\game\machinery\suit_storage_unit.dm" +#include "monkestation\code\game\machinery\computer\camera.dm" #include "monkestation\code\game\machinery\computer\cloning.dm" #include "monkestation\code\game\machinery\computer\crew.dm" +#include "monkestation\code\game\machinery\computer\telescreen.dm" #include "monkestation\code\game\machinery\computer\orders\order_veggies.dm" #include "monkestation\code\game\machinery\doors\airlock.dm" #include "monkestation\code\game\machinery\doors\firedoor.dm" @@ -6140,6 +6143,7 @@ #include "monkestation\code\game\objects\items\circuitboards\computer_circuitboards.dm" #include "monkestation\code\game\objects\items\circuitboards\holy_weapons.dm" #include "monkestation\code\game\objects\items\circuitboards\machine_circuitboards.dm" +#include "monkestation\code\game\objects\items\devices\broadcast_camera.dm" #include "monkestation\code\game\objects\items\devices\compression_kit.dm" #include "monkestation\code\game\objects\items\devices\gps.dm" #include "monkestation\code\game\objects\items\devices\pocket_heater.dm" @@ -7528,6 +7532,7 @@ #include "monkestation\code\modules\mapping\access_helpers.dm" #include "monkestation\code\modules\mapping\mapping_helpers.dm" #include "monkestation\code\modules\maptext\maptext_image_helper.dm" +#include "monkestation\code\modules\martial_arts\awakened_dragon.dm" #include "monkestation\code\modules\martial_arts\tribal_claw.dm" #include "monkestation\code\modules\martial_arts\tunnel_arts.dm" #include "monkestation\code\modules\martial_arts\granters\tribal_claw_gr.dm" @@ -7731,6 +7736,7 @@ #include "monkestation\code\modules\modular_computers\computers\item\role_tablet_presets.dm" #include "monkestation\code\modules\modular_computers\file_system\programs\crewmanifest.dm" #include "monkestation\code\modules\modular_computers\file_system\programs\lifeline.dm" +#include "monkestation\code\modules\modular_computers\file_system\programs\spesstv.dm" #include "monkestation\code\modules\modular_guns\__base_attachment.dm" #include "monkestation\code\modules\modular_guns\__base_modular_gun.dm" #include "monkestation\code\modules\modular_guns\attachment_datums\__base_attachment_datum.dm" @@ -8231,6 +8237,7 @@ #include "monkestation\code\modules\spells\spell_types\conjure_item\summon_mjollnir.dm" #include "monkestation\code\modules\spells\spell_types\pointed\fire_ball.dm" #include "monkestation\code\modules\spells\spell_types\pointed\smite.dm" +#include "monkestation\code\modules\spells\spell_types\touch\_touch.dm" #include "monkestation\code\modules\store\admin\admin_coin_modification.dm" #include "monkestation\code\modules\store\atm\_atm.dm" #include "monkestation\code\modules\store\pre_round\_pre_round_store.dm" diff --git a/tgui/packages/tgui-panel/chat/middleware.js b/tgui/packages/tgui-panel/chat/middleware.js index 4dccee80d08d..64dc5a4f1381 100644 --- a/tgui/packages/tgui-panel/chat/middleware.js +++ b/tgui/packages/tgui-panel/chat/middleware.js @@ -134,13 +134,14 @@ export const chatMiddleware = (store) => { requesting < sequence; requesting++ ) { - requested_sequences.push(requesting); + sequences_requested.push(requesting); Byond.sendMessage('chat/resend', requesting); } } } chatRenderer.processBatch([payload_obj.content]); + sequences.push(sequence); return; } if (type === loadChat.type) { diff --git a/tgui/packages/tgui/interfaces/PaiInterface/System.tsx b/tgui/packages/tgui/interfaces/PaiInterface/System.tsx index adad34996b0f..d11e3c2cadc8 100644 --- a/tgui/packages/tgui/interfaces/PaiInterface/System.tsx +++ b/tgui/packages/tgui/interfaces/PaiInterface/System.tsx @@ -1,6 +1,5 @@ import { useBackend } from 'tgui/backend'; import { Box, Button, LabeledList, Section, Stack } from 'tgui/components'; -import { ICON_MAP } from './constants'; import { PaiData } from './types'; export const SystemDisplay = (props) => { @@ -64,7 +63,7 @@ const SystemWallpaper = (props) => { */ const SystemInfo = (props) => { const { act, data } = useBackend(); - const { image, master_dna, master_name } = data; + const { screen_image_interface_icon, master_dna, master_name } = data; return (
{ Verify