diff --git a/.github/workflows/detect_translate_conflicts.yml b/.github/workflows/detect_translate_conflicts.yml index 97feee08845520..e8f126ff9beef8 100644 --- a/.github/workflows/detect_translate_conflicts.yml +++ b/.github/workflows/detect_translate_conflicts.yml @@ -19,6 +19,7 @@ jobs: run: | git config --local user.email "action@github.com" git config --local user.name "SS220Manager" + git config --local merge.conflictStyle zdiff3 - name: Try merging continue-on-error: true run: | @@ -28,10 +29,12 @@ jobs: { echo "MERGE_CONFLICTS<" + echo "$file" echo -e "\n\`\`\`diff" git diff --diff-filter=U "$file" | sed -n '/<<<<<<>>>>>>/p' echo -e "\n\`\`\`" + echo "" done echo EOF } >> $GITHUB_ENV @@ -39,15 +42,42 @@ jobs: uses: actions/github-script@v7 with: script: | - const { MERGE_CONFLICTS } = process.env - - if(!MERGE_CONFLICTS) { - return - } - - await github.rest.issues.createComment({ - issue_number: context.issue.number, - owner: context.repo.owner, - repo: context.repo.repo, - body: `This pr causes following conflicts on translate branch:\n ${MERGE_CONFLICTS} ` - }) + const { MERGE_CONFLICTS } = process.env; + + const conflict_message_header = "This PR causes following conflicts on translate branch:\n"; + const issue_body = `${conflict_message_header}${MERGE_CONFLICTS}`; + + const comments = await github.rest.issues.listComments({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + }); + + const action_comment = comments.data.find(comment => comment.body.startsWith(conflict_message_header) && comment.user.login === "github-actions[bot]"); + + if (action_comment) { + const comment_id = action_comment.id; + + if (!MERGE_CONFLICTS) { + await github.rest.issues.deleteComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: comment_id, + }); + return; + } + + await github.rest.issues.updateComment({ + owner: context.repo.owner, + repo: context.repo.repo, + comment_id: comment_id, + body: issue_body, + }); + } else if (MERGE_CONFLICTS) { + await github.rest.issues.createComment({ + owner: context.repo.owner, + repo: context.repo.repo, + issue_number: context.issue.number, + body: issue_body, + }); + } diff --git a/.github/workflows/run_integration_tests.yml b/.github/workflows/run_integration_tests.yml index 7b544fef2a66c2..3485b90d47489e 100644 --- a/.github/workflows/run_integration_tests.yml +++ b/.github/workflows/run_integration_tests.yml @@ -46,9 +46,9 @@ jobs: - name: Install rust-g run: | bash tools/ci/install_rust_g.sh - - name: Install auxlua + - name: Install dreamluau run: | - bash tools/ci/install_auxlua.sh + bash tools/ci/install_dreamluau.sh - name: Configure version run: | echo "BYOND_MAJOR=${{ inputs.major }}" >> $GITHUB_ENV diff --git a/.github/workflows/update_tgs_dmapi.yml b/.github/workflows/update_tgs_dmapi.yml index 15d45b7935f05d..8dfdee90e36a0d 100644 --- a/.github/workflows/update_tgs_dmapi.yml +++ b/.github/workflows/update_tgs_dmapi.yml @@ -28,8 +28,8 @@ jobs: - name: Commit and Push continue-on-error: true run: | - git config user.name tgstation-server - git config user.email tgstation-server@users.noreply.github.com + git config user.name "tgstation-server-ci[bot]" + git config user.email "161980869+tgstation-server-ci[bot]@users.noreply.github.com" git add . git commit -m 'Update TGS DMAPI' git push -f -u origin tgs-dmapi-update diff --git a/.gitignore b/.gitignore index c70ebf608b965b..8ef9946abc9354 100644 --- a/.gitignore +++ b/.gitignore @@ -214,7 +214,7 @@ Temporary Items # Built auxtools libraries and intermediate files aux*.dll libaux*.so -aux*.pdb +*.pdb # byond-tracy, we intentionally do not ship this and do not want to maintain it # https://github.com/mafemergency/byond-tracy/ diff --git a/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_plasma_facility.dmm b/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_plasma_facility.dmm index 96dec4af7207d7..0bfcc133f0c98f 100644 --- a/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_plasma_facility.dmm +++ b/_maps/RandomRuins/IceRuins/icemoon_underground_abandoned_plasma_facility.dmm @@ -25,8 +25,8 @@ /obj/item/clothing/shoes/galoshes{ pixel_y = -5 }, -/obj/item/flashlight/eyelight{ - pixel_y = 11 +/obj/item/flashlight{ + pixel_y = 8 }, /turf/open/floor/plating/icemoon, /area/ruin/plasma_facility/operations) diff --git a/_maps/RandomRuins/SpaceRuins/infested_frigate.dmm b/_maps/RandomRuins/SpaceRuins/infested_frigate.dmm index 64e7be0705b6bb..21b981191aeb32 100644 --- a/_maps/RandomRuins/SpaceRuins/infested_frigate.dmm +++ b/_maps/RandomRuins/SpaceRuins/infested_frigate.dmm @@ -856,7 +856,7 @@ icon_state = "floor5-old" }, /obj/item/ammo_casing/spent, -/obj/item/gun/ballistic/automatic/plastikov, +/obj/item/gun/ballistic/automatic/smartgun, /obj/effect/mob_spawn/corpse/human/syndicatepilot, /turf/open/floor/mineral/plastitanium/red, /area/ruin/space/has_grav/infested_frigate) @@ -2790,7 +2790,7 @@ icon_state = "plastitaniumtiny" }, /mob/living/basic/alien/queen/large{ - loot = list(/obj/effect/gibspawner/xeno,/obj/item/ammo_box/magazine/plastikov9mm,/obj/effect/mob_spawn/corpse/human/syndicatecommando/soft_suit); + loot = list(/obj/effect/gibspawner/xeno,/obj/item/ammo_box/magazine/smartgun,/obj/effect/mob_spawn/corpse/human/syndicatecommando/soft_suit); desc = "What you saw in your dreams last night."; faction = list("syndicate","xenomorph") }, diff --git a/_maps/RandomZLevels/SnowCabin.dmm b/_maps/RandomZLevels/SnowCabin.dmm index 3b5c32345c0e38..bfbc5a18c56a10 100644 --- a/_maps/RandomZLevels/SnowCabin.dmm +++ b/_maps/RandomZLevels/SnowCabin.dmm @@ -598,7 +598,7 @@ /turf/open/floor/iron/freezer, /area/awaymission/cabin) "cH" = ( -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/snowcabin, /obj/structure/cable, /turf/open/floor/wood, /area/awaymission/cabin) @@ -660,7 +660,7 @@ /turf/open/floor/iron/white, /area/awaymission/cabin) "cQ" = ( -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/snowcabin, /obj/structure/cable, /turf/open/floor/carpet, /area/awaymission/cabin) @@ -2904,7 +2904,7 @@ /area/awaymission/cabin/snowforest) "rk" = ( /obj/machinery/light/directional/south, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/snowcabin, /obj/structure/sign/poster/official/report_crimes/directional/south, /obj/structure/cable, /turf/open/floor/carpet, diff --git a/_maps/RandomZLevels/TheBeach.dmm b/_maps/RandomZLevels/TheBeach.dmm index c7a097a02ad17f..64cdcbb6d362e5 100644 --- a/_maps/RandomZLevels/TheBeach.dmm +++ b/_maps/RandomZLevels/TheBeach.dmm @@ -1688,7 +1688,7 @@ "vq" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/mapping_helpers/broken_floor, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/beach, /turf/open/floor/plating, /area/awaymission/beach) "vx" = ( @@ -3586,7 +3586,7 @@ /area/awaymission/beach) "SB" = ( /obj/effect/decal/cleanable/dirt, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/beach, /turf/open/floor/plating, /area/awaymission/beach) "SI" = ( diff --git a/_maps/RandomZLevels/caves.dmm b/_maps/RandomZLevels/caves.dmm index c64aa99d1aab61..a21d64d505b635 100644 --- a/_maps/RandomZLevels/caves.dmm +++ b/_maps/RandomZLevels/caves.dmm @@ -480,7 +480,7 @@ /turf/open/floor/plating, /area/awaymission/caves/research) "cR" = ( -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/caves, /turf/open/floor/plating, /area/awaymission/caves/research) "cS" = ( @@ -610,7 +610,7 @@ "dw" = ( /obj/structure/bed, /obj/item/bedsheet, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/caves, /turf/open/floor/iron, /area/awaymission/caves/bmp_asteroid/level_two) "dx" = ( @@ -653,7 +653,7 @@ "dH" = ( /obj/structure/bed, /obj/item/bedsheet, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/caves, /turf/open/floor/wood, /area/awaymission/caves/northblock) "dI" = ( @@ -705,7 +705,7 @@ /obj/structure/bed, /obj/item/bedsheet, /obj/effect/decal/cleanable/cobweb/cobweb2, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/caves, /turf/open/floor/wood, /area/awaymission/caves/northblock) "ea" = ( @@ -714,7 +714,7 @@ /area/awaymission/caves/northblock) "ed" = ( /obj/structure/bed, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/caves, /turf/open/floor/wood, /area/awaymission/caves/northblock) "ee" = ( @@ -849,7 +849,7 @@ /turf/open/floor/iron, /area/awaymission/caves/listeningpost) "eO" = ( -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/caves, /turf/open/floor/iron, /area/awaymission/caves/listeningpost) "eP" = ( @@ -1584,7 +1584,7 @@ }, /area/awaymission/caves/bmp_asteroid/level_two) "Bs" = ( -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/caves, /turf/open/misc/asteroid/basalt{ initial_gas_mix = "n2=23;o2=14;TEMP=2.7" }, diff --git a/_maps/RandomZLevels/moonoutpost19.dmm b/_maps/RandomZLevels/moonoutpost19.dmm index 3a4e4c8affed69..a8f52784b343ac 100644 --- a/_maps/RandomZLevels/moonoutpost19.dmm +++ b/_maps/RandomZLevels/moonoutpost19.dmm @@ -1903,14 +1903,14 @@ /turf/open/floor/mineral/titanium/yellow, /area/awaymission/moonoutpost19/arrivals) "ms" = ( -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/moonoutpost, /turf/open/floor/mineral/titanium/blue, /area/awaymission/moonoutpost19/arrivals) "mt" = ( /obj/structure/chair{ dir = 8 }, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/moonoutpost, /turf/open/floor/mineral/titanium/blue, /area/awaymission/moonoutpost19/arrivals) "mu" = ( @@ -1955,7 +1955,7 @@ /turf/open/floor/mineral/titanium/yellow, /area/awaymission/moonoutpost19/arrivals) "mI" = ( -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/moonoutpost, /turf/open/floor/mineral/titanium/yellow, /area/awaymission/moonoutpost19/arrivals) "mJ" = ( @@ -1965,7 +1965,7 @@ icon_state = "beacon"; name = "tracking beacon" }, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/moonoutpost, /turf/open/floor/mineral/titanium/yellow, /area/awaymission/moonoutpost19/arrivals) "mK" = ( diff --git a/_maps/RandomZLevels/museum.dmm b/_maps/RandomZLevels/museum.dmm index 2937250b1f9ba5..afd0cd888fdcda 100644 --- a/_maps/RandomZLevels/museum.dmm +++ b/_maps/RandomZLevels/museum.dmm @@ -1426,7 +1426,7 @@ /turf/open/indestructible/plating, /area/awaymission/museum) "lz" = ( -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/museum, /obj/structure/flora/bush/sparsegrass/style_random, /turf/open/floor/grass, /area/awaymission/museum) @@ -3095,7 +3095,7 @@ /turf/open/floor/iron/smooth_large, /area/awaymission/museum) "zd" = ( -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/museum, /turf/open/floor/grass, /area/awaymission/museum) "zg" = ( @@ -4503,7 +4503,7 @@ }, /area/awaymission/museum) "KN" = ( -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/museum, /obj/effect/turf_decal/siding/wood{ dir = 1 }, diff --git a/_maps/RandomZLevels/research.dmm b/_maps/RandomZLevels/research.dmm index 1e84014fa0e1bc..ae1814b7d7096a 100644 --- a/_maps/RandomZLevels/research.dmm +++ b/_maps/RandomZLevels/research.dmm @@ -389,7 +389,7 @@ /turf/open/floor/iron/dark, /area/awaymission/research/interior/gateway) "bR" = ( -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/research, /turf/open/floor/iron/dark, /area/awaymission/research/interior/gateway) "bS" = ( @@ -438,7 +438,7 @@ /turf/open/floor/iron/dark, /area/awaymission/research/interior/gateway) "bZ" = ( -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/research, /obj/effect/turf_decal/stripes/line, /obj/structure/cable, /turf/open/floor/iron/dark, @@ -481,12 +481,12 @@ /area/awaymission/research/interior/gateway) "cj" = ( /obj/structure/window/reinforced/spawner/directional/south, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/research, /turf/open/floor/iron/dark, /area/awaymission/research/interior/gateway) "ck" = ( /obj/machinery/door/window/right/directional/south, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/research, /obj/structure/cable, /turf/open/floor/iron/dark, /area/awaymission/research/interior/gateway) @@ -1761,7 +1761,7 @@ /obj/structure/toilet{ dir = 8 }, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/research, /obj/machinery/light/small/directional/east, /turf/open/floor/iron/freezer, /area/awaymission/research/interior/bathroom) @@ -2007,7 +2007,7 @@ "jU" = ( /obj/structure/bed, /obj/item/bedsheet/blue, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/research, /turf/open/floor/wood, /area/awaymission/research/interior/dorm) "jV" = ( @@ -2505,7 +2505,7 @@ "lT" = ( /obj/structure/bed, /obj/item/bedsheet/patriot, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/research, /turf/open/floor/wood, /area/awaymission/research/interior/dorm) "lX" = ( @@ -2976,7 +2976,7 @@ /area/awaymission/research/interior) "sM" = ( /obj/structure/window/reinforced/spawner/directional/south, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/research, /obj/structure/cable, /turf/open/floor/iron/dark, /area/awaymission/research/interior/gateway) diff --git a/_maps/RandomZLevels/snowdin.dmm b/_maps/RandomZLevels/snowdin.dmm index d66be7f5614ffb..6f565143e790ec 100644 --- a/_maps/RandomZLevels/snowdin.dmm +++ b/_maps/RandomZLevels/snowdin.dmm @@ -181,7 +181,7 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4{ dir = 8 }, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/snowdin, /obj/item/bedsheet/purple, /turf/open/floor/wood, /area/awaymission/snowdin/post/dorm) @@ -213,7 +213,7 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4{ dir = 8 }, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/snowdin, /turf/open/floor/wood, /area/awaymission/snowdin/post/dorm) "aY" = ( @@ -239,7 +239,7 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4{ dir = 8 }, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/snowdin, /obj/item/paper/crumpled/ruins/snowdin/dontdeadopeninside, /obj/item/bedsheet/green, /turf/open/floor/wood, @@ -414,7 +414,7 @@ /turf/open/floor/iron/freezer, /area/awaymission/snowdin/post/kitchen) "bM" = ( -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/snowdin, /obj/effect/decal/cleanable/blood/old, /turf/open/floor/iron/freezer, /area/awaymission/snowdin/post/kitchen) @@ -1092,7 +1092,7 @@ "eh" = ( /obj/structure/bed, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/snowdin, /obj/item/bedsheet/red, /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/wood, @@ -2073,12 +2073,12 @@ /area/awaymission/snowdin/post/gateway) "hR" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/snowdin, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/awaymission/snowdin/post/gateway) "hS" = ( -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/snowdin, /obj/effect/turf_decal/loading_area, /obj/effect/decal/cleanable/dirt, /obj/structure/cable, @@ -2086,7 +2086,7 @@ /area/awaymission/snowdin/post/gateway) "hT" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer4, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/snowdin, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/awaymission/snowdin/post/gateway) @@ -2302,7 +2302,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ dir = 5 }, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/snowdin, /turf/open/floor/iron, /area/awaymission/snowdin/post/gateway) "iB" = ( @@ -2310,7 +2310,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden{ dir = 10 }, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/snowdin, /obj/machinery/holopad, /obj/effect/decal/cleanable/dirt, /obj/structure/cable, @@ -2318,7 +2318,7 @@ /area/awaymission/snowdin/post/gateway) "iC" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer4, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/snowdin, /turf/open/floor/iron, /area/awaymission/snowdin/post/gateway) "iD" = ( @@ -2579,14 +2579,14 @@ /turf/open/floor/iron/white, /area/awaymission/snowdin/post/minipost) "ju" = ( -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/snowdin, /obj/effect/turf_decal/stripes/line, /turf/open/floor/iron, /area/awaymission/snowdin/post/gateway) "jv" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer4, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/snowdin, /obj/effect/turf_decal/stripes/line, /obj/effect/decal/cleanable/dirt, /obj/structure/cable, @@ -2650,7 +2650,7 @@ /obj/structure/chair{ dir = 4 }, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/snowdin, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer4, /turf/open/floor/iron, @@ -3523,7 +3523,7 @@ /obj/structure/chair{ dir = 8 }, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/snowdin, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/awaymission/snowdin/post/garage) @@ -7044,7 +7044,7 @@ }, /area/awaymission/snowdin/cave) "Be" = ( -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/snowdin, /obj/effect/turf_decal/tile/neutral/anticorner/contrasted{ dir = 8 }, @@ -7500,7 +7500,7 @@ /obj/structure/bed{ dir = 4 }, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/snowdin, /obj/item/bedsheet/nanotrasen{ dir = 4 }, diff --git a/_maps/RandomZLevels/undergroundoutpost45.dmm b/_maps/RandomZLevels/undergroundoutpost45.dmm index 7d8b1cd028d46f..16cc8924aae9be 100644 --- a/_maps/RandomZLevels/undergroundoutpost45.dmm +++ b/_maps/RandomZLevels/undergroundoutpost45.dmm @@ -101,14 +101,14 @@ /turf/open/floor/iron/dark, /area/awaymission/undergroundoutpost45/central) "ax" = ( -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/underground, /turf/open/floor/iron, /area/awaymission/undergroundoutpost45/central) "ay" = ( /obj/structure/chair/comfy/beige{ dir = 4 }, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/underground, /turf/open/floor/iron/grimy, /area/awaymission/undergroundoutpost45/central) "az" = ( @@ -118,7 +118,7 @@ icon_state = "beacon"; name = "tracking beacon" }, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/underground, /obj/effect/turf_decal/tile/neutral/half/contrasted{ dir = 4 }, @@ -126,7 +126,7 @@ /area/awaymission/undergroundoutpost45/central) "aB" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/underground, /obj/effect/turf_decal/tile/neutral/half/contrasted{ dir = 4 }, @@ -218,7 +218,7 @@ /turf/open/floor/iron, /area/awaymission/undergroundoutpost45/central) "aT" = ( -/obj/effect/landmark/awaystart, +/obj/effect/landmark/awaystart/underground, /turf/open/floor/iron/grimy, /area/awaymission/undergroundoutpost45/central) "aU" = ( diff --git a/_maps/map_files/Birdshot/birdshot.dmm b/_maps/map_files/Birdshot/birdshot.dmm index 0a770985080d54..00961dbd7f5d63 100644 --- a/_maps/map_files/Birdshot/birdshot.dmm +++ b/_maps/map_files/Birdshot/birdshot.dmm @@ -160,6 +160,10 @@ }, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/visible/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/dark/visible, +/obj/machinery/airlock_controller/incinerator_atmos{ + pixel_x = -40; + pixel_y = -8 + }, /turf/open/floor/engine, /area/station/maintenance/disposal/incinerator) "aem" = ( @@ -205,8 +209,15 @@ /obj/machinery/atmospherics/components/trinary/filter/flipped/layer2{ dir = 4 }, -/obj/structure/extinguisher_cabinet/directional/north, /obj/machinery/light/small/directional/north, +/obj/machinery/button/door/incinerator_vent_atmos_aux{ + pixel_x = 8; + pixel_y = 24 + }, +/obj/machinery/button/door/incinerator_vent_atmos_main{ + pixel_x = 8; + pixel_y = 36 + }, /turf/open/floor/plating, /area/station/maintenance/disposal/incinerator) "aeX" = ( @@ -2661,7 +2672,7 @@ dir = 1 }, /turf/open/floor/iron, -/area/station/holodeck/rec_center) +/area/station/commons/fitness/recreation/entertainment) "baP" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -4399,6 +4410,7 @@ cycle_id = "atmos_airlock_1" }, /obj/machinery/door/firedoor, +/obj/effect/mapping_helpers/airlock/access/all/engineering/atmos, /turf/open/floor/iron, /area/station/engineering/atmos/office) "bJK" = ( @@ -4949,7 +4961,7 @@ dir = 4 }, /turf/open/floor/iron, -/area/station/holodeck/rec_center) +/area/station/commons/fitness/recreation/entertainment) "bWs" = ( /obj/effect/turf_decal/stripes/line{ dir = 6 @@ -4958,8 +4970,9 @@ /turf/open/floor/iron, /area/station/science/xenobiology) "bXb" = ( -/obj/effect/turf_decal/sand/plating, -/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/department/electrical) "bXi" = ( @@ -5135,6 +5148,7 @@ /obj/structure/disposalpipe/segment{ dir = 8 }, +/obj/effect/mapping_helpers/airlock/access/all/engineering/atmos, /turf/open/floor/iron, /area/station/engineering/atmos/office) "cam" = ( @@ -5721,7 +5735,7 @@ dir = 1; name = "Plasma to Pure" }, -/obj/machinery/atmospherics/pipe/bridge_pipe/green{ +/obj/machinery/atmospherics/pipe/bridge_pipe/green/visible{ dir = 4 }, /turf/open/floor/iron, @@ -7336,6 +7350,7 @@ /obj/machinery/door/airlock/engineering/glass{ name = "Engineering Storage" }, +/obj/effect/mapping_helpers/airlock/access/all/engineering/engine_equipment, /turf/open/floor/iron/smooth_half{ dir = 8 }, @@ -7555,7 +7570,7 @@ /obj/structure/chair/stool/bar/directional/south, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, -/area/station/holodeck/rec_center) +/area/station/commons/fitness/recreation/entertainment) "cUH" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 1 @@ -7763,11 +7778,10 @@ dir = 4 }, /obj/effect/turf_decal/tile/neutral/opposingcorners, -/obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, -/area/station/holodeck/rec_center) +/area/station/commons/fitness/recreation/entertainment) "cYt" = ( /obj/structure/cable, /turf/open/floor/plating, @@ -8400,7 +8414,7 @@ /obj/structure/chair/stool/bar/directional/south, /obj/effect/landmark/start/hangover, /turf/open/floor/iron, -/area/station/holodeck/rec_center) +/area/station/commons/fitness/recreation/entertainment) "diI" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/turf_decal/tile/neutral, @@ -9248,6 +9262,7 @@ /area/station/maintenance/starboard/aft) "dzH" = ( /obj/machinery/portable_atmospherics/canister/plasma, +/obj/machinery/atmospherics/pipe/smart/simple/yellow/visible, /turf/open/floor/engine/plasma, /area/station/engineering/atmos) "dAn" = ( @@ -10739,6 +10754,10 @@ /obj/effect/turf_decal/tile/neutral, /turf/open/floor/iron, /area/station/hallway/primary/central/aft) +"efn" = ( +/obj/effect/spawner/random/structure/crate_loot, +/turf/open/floor/plating, +/area/station/maintenance/department/electrical) "efy" = ( /obj/item/kirbyplants/organic/plant21, /obj/machinery/status_display/ai/directional/west, @@ -12439,6 +12458,9 @@ "eKd" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden, /obj/machinery/light/small/directional/west, +/obj/machinery/airlock_sensor/incinerator_atmos{ + pixel_y = -20 + }, /turf/open/floor/engine, /area/station/maintenance/disposal/incinerator) "eKf" = ( @@ -12469,9 +12491,6 @@ /obj/effect/landmark/start/hangover, /turf/open/floor/iron, /area/station/hallway/secondary/entry) -"eKU" = ( -/turf/closed/wall/r_wall/rust, -/area/station/engineering/atmos/pumproom) "eKW" = ( /obj/machinery/door/airlock/maintenance{ name = "Bathroom" @@ -12629,7 +12648,7 @@ /obj/machinery/airalarm/directional/east, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, -/area/station/holodeck/rec_center) +/area/station/commons/fitness/recreation/entertainment) "eOY" = ( /obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ dir = 4 @@ -14389,9 +14408,7 @@ /area/station/science/xenobiology) "fxp" = ( /obj/effect/spawner/structure/window/reinforced/plasma, -/obj/machinery/atmospherics/pipe/smart/simple/orange{ - dir = 1 - }, +/obj/machinery/atmospherics/pipe/smart/simple/orange/visible, /turf/open/floor/plating, /area/station/engineering/supermatter/room) "fxF" = ( @@ -16495,6 +16512,10 @@ /obj/machinery/camera/autoname/directional/west, /turf/open/floor/iron, /area/station/hallway/primary/aft) +"ggr" = ( +/obj/item/pickaxe, +/turf/open/floor/plating, +/area/station/maintenance/department/electrical) "ggw" = ( /obj/effect/turf_decal/stripes/white/end{ dir = 1 @@ -16692,7 +16713,7 @@ }, /obj/effect/turf_decal/tile/neutral/opposingcorners, /turf/open/floor/iron, -/area/station/holodeck/rec_center) +/area/station/commons/fitness/recreation/entertainment) "gjE" = ( /obj/structure/cable, /obj/effect/decal/cleanable/dirt/dust, @@ -18857,7 +18878,7 @@ dir = 4 }, /turf/closed/wall/r_wall, -/area/station/engineering/atmos/pumproom) +/area/station/maintenance/department/engine/atmos) "gUV" = ( /obj/structure/cable, /obj/structure/chair/stool/directional/south{ @@ -19681,7 +19702,7 @@ dir = 4 }, /turf/closed/wall/r_wall, -/area/station/engineering/atmos/pumproom) +/area/station/maintenance/department/engine/atmos) "hhL" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -20162,8 +20183,8 @@ }, /area/station/science/lobby) "hqH" = ( -/obj/structure/reagent_dispensers/watertank, /obj/item/reagent_containers/cup/watering_can/wood, +/obj/structure/table, /turf/open/floor/plating, /area/station/maintenance/starboard/greater) "hqM" = ( @@ -21001,7 +21022,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/landmark/start/hangover, /turf/open/floor/iron, -/area/station/holodeck/rec_center) +/area/station/commons/fitness/recreation/entertainment) "hED" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment, @@ -21075,6 +21096,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden, /turf/closed/wall/r_wall, /area/station/maintenance/disposal/incinerator) +"hGa" = ( +/obj/machinery/camera/directional/east{ + c_tag = "Atmospherics Tank - Mix" + }, +/turf/open/floor/engine/vacuum, +/area/station/engineering/atmos) "hGb" = ( /turf/closed/wall/r_wall, /area/station/science/ordnance/storage) @@ -21884,7 +21911,7 @@ /obj/machinery/atmospherics/pipe/smart/simple/yellow/visible{ dir = 4 }, -/obj/machinery/atmospherics/pipe/bridge_pipe/green, +/obj/machinery/atmospherics/pipe/bridge_pipe/green/visible, /turf/open/floor/iron, /area/station/engineering/atmos) "hWk" = ( @@ -22215,7 +22242,7 @@ dir = 4 }, /turf/open/floor/iron, -/area/station/holodeck/rec_center) +/area/station/commons/fitness/recreation/entertainment) "ibI" = ( /obj/effect/turf_decal/siding/white/corner{ dir = 8 @@ -23321,7 +23348,7 @@ /obj/machinery/atmospherics/pipe/bridge_pipe/yellow/visible{ dir = 4 }, -/obj/machinery/atmospherics/pipe/bridge_pipe/green, +/obj/machinery/atmospherics/pipe/bridge_pipe/green/visible, /turf/open/floor/iron, /area/station/engineering/atmos) "itw" = ( @@ -25639,13 +25666,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/port/greater) -"jbE" = ( -/obj/effect/spawner/structure/window/reinforced/plasma, -/obj/machinery/atmospherics/pipe/smart/simple/purple/visible{ - dir = 4 - }, -/turf/open/floor/plating, -/area/station/engineering/atmos) "jbV" = ( /obj/machinery/photocopier, /turf/open/floor/iron/dark, @@ -26700,6 +26720,17 @@ /obj/structure/cable, /turf/open/floor/iron/dark/small, /area/station/command/heads_quarters/captain/private) +"jvm" = ( +/obj/machinery/door/airlock/engineering/glass/critical{ + heat_proof = 1; + name = "Supermatter Chamber" + }, +/obj/effect/mapping_helpers/airlock/access/any/engineering/general, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 8 + }, +/turf/open/floor/engine, +/area/station/engineering/supermatter) "jvB" = ( /obj/structure/disposalpipe/segment, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ @@ -27837,7 +27868,7 @@ /obj/machinery/atmospherics/components/binary/pump/off{ name = "O2 To Pure" }, -/obj/machinery/atmospherics/pipe/bridge_pipe/green{ +/obj/machinery/atmospherics/pipe/bridge_pipe/green/visible{ dir = 4 }, /turf/open/floor/iron, @@ -28260,7 +28291,7 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/camera/autoname/directional/east, /turf/open/floor/iron, -/area/station/holodeck/rec_center) +/area/station/commons/fitness/recreation/entertainment) "jTD" = ( /obj/machinery/atmospherics/components/trinary/filter/atmos/o2{ dir = 8 @@ -30993,9 +31024,6 @@ /area/station/maintenance/starboard/fore) "kNv" = ( /obj/machinery/air_sensor/mix_tank, -/obj/machinery/camera/directional/east{ - c_tag = "Atmospherics Tank - Mix" - }, /turf/open/floor/engine/vacuum, /area/station/engineering/atmos) "kNx" = ( @@ -32190,6 +32218,10 @@ /obj/item/camera, /turf/open/floor/iron, /area/station/security/prison/workout) +"lhd" = ( +/obj/structure/water_source/puddle, +/turf/open/floor/grass, +/area/station/security/prison/garden) "lhi" = ( /obj/machinery/airalarm/directional/north, /obj/machinery/button/door/directional/north{ @@ -32344,6 +32376,15 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating/rust, /area/station/maintenance/department/engine/atmos) +"ljc" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/plating, +/area/station/maintenance/starboard/fore) "ljg" = ( /obj/effect/turf_decal/weather/snow/corner{ dir = 1 @@ -33234,9 +33275,6 @@ /obj/machinery/camera/autoname/directional/west, /turf/open/floor/iron, /area/station/cargo/miningoffice) -"lwK" = ( -/turf/closed/wall/r_wall/rust, -/area/station/engineering/atmos/storage) "lwO" = ( /obj/machinery/door/airlock/highsecurity{ name = "Engine Room" @@ -33919,7 +33957,6 @@ "lGO" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/sink/directional/west, /turf/open/floor/iron, /area/station/security/prison/garden) "lGT" = ( @@ -36648,13 +36685,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/department/engine) -"mDb" = ( -/obj/effect/turf_decal/sand/plating, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/plating, -/area/station/maintenance/department/electrical) "mDf" = ( /obj/structure/chair/wood{ dir = 8 @@ -37284,10 +37314,6 @@ /obj/structure/broken_flooring/singular/directional/east, /turf/open/floor/plating, /area/station/maintenance/starboard/aft) -"mMF" = ( -/obj/structure/sign/warning/pods/directional/north, -/turf/open/floor/plating, -/area/station/maintenance/department/electrical) "mMN" = ( /obj/structure/chair/office{ dir = 8 @@ -38042,6 +38068,10 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/maintenance/port/lesser) +"nbN" = ( +/obj/effect/spawner/random/structure/girder, +/turf/open/floor/plating, +/area/station/maintenance/department/electrical) "ncb" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/table/wood, @@ -38208,10 +38238,6 @@ }, /turf/open/floor/iron, /area/station/security) -"ngd" = ( -/obj/effect/turf_decal/tile/neutral/opposingcorners, -/turf/open/floor/iron, -/area/station/holodeck/rec_center) "ngq" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -39118,7 +39144,7 @@ }, /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, -/area/station/holodeck/rec_center) +/area/station/commons/fitness/recreation/entertainment) "nuY" = ( /obj/structure/broken_flooring/pile/directional/east, /obj/structure/alien/weeds/node, @@ -39961,9 +39987,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 5 }, -/obj/machinery/atmospherics/pipe/smart/simple/orange{ - dir = 1 - }, +/obj/machinery/atmospherics/pipe/smart/simple/orange/visible, /turf/open/floor/engine, /area/station/engineering/supermatter/room) "nKj" = ( @@ -40915,6 +40939,7 @@ }, /obj/machinery/power/apc/auto_name/directional/west, /obj/structure/cable, +/obj/machinery/light/small/directional/west, /turf/open/floor/iron/dark, /area/station/engineering/atmos/storage) "odh" = ( @@ -43437,6 +43462,10 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/entry) +"oYf" = ( +/obj/machinery/button/ignition/incinerator/atmos, +/turf/closed/wall/r_wall, +/area/station/maintenance/disposal/incinerator) "oYi" = ( /obj/effect/turf_decal/trimline/neutral/line, /obj/effect/turf_decal/trimline/neutral/line{ @@ -44348,6 +44377,7 @@ /area/station/service/chapel) "pnO" = ( /obj/structure/cable, +/obj/machinery/airalarm/directional/south, /turf/open/floor/plating, /area/station/maintenance/disposal/incinerator) "pnQ" = ( @@ -44574,6 +44604,10 @@ /obj/item/kirbyplants/random, /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) +"prd" = ( +/obj/machinery/light/small/directional/west, +/turf/open/floor/iron/smooth_large, +/area/station/engineering/supermatter/room) "prf" = ( /obj/structure/cable, /obj/effect/spawner/structure/window/reinforced, @@ -45899,9 +45933,6 @@ }, /turf/open/floor/wood/parquet, /area/station/service/library) -"pOT" = ( -/turf/closed/wall, -/area/station/holodeck/rec_center) "pOX" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 1 @@ -46147,11 +46178,10 @@ name = "Maintenance" }, /obj/effect/mapping_helpers/airlock/access/any/service/maintenance, -/obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/plating, -/area/station/holodeck/rec_center) +/area/station/commons/fitness/recreation/entertainment) "pTq" = ( /obj/machinery/door/airlock/maintenance{ name = "Crematorium Maintenance" @@ -46177,7 +46207,7 @@ /obj/effect/spawner/random/entertainment/arcade, /obj/effect/decal/cleanable/cobweb/cobweb2, /turf/open/floor/iron, -/area/station/holodeck/rec_center) +/area/station/commons/fitness/recreation/entertainment) "pTZ" = ( /obj/effect/turf_decal/siding/wideplating/dark{ dir = 8 @@ -46497,7 +46527,6 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, -/obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/plating, @@ -46984,7 +47013,7 @@ dir = 1; name = "CO2 to Pure" }, -/obj/machinery/atmospherics/pipe/bridge_pipe/green{ +/obj/machinery/atmospherics/pipe/bridge_pipe/green/visible{ dir = 4 }, /turf/open/floor/iron, @@ -50683,6 +50712,7 @@ name = "Engine Airlock" }, /obj/machinery/door/firedoor, +/obj/effect/mapping_helpers/airlock/access/any/engineering/general, /turf/open/floor/plating, /area/station/engineering/supermatter/room) "ruS" = ( @@ -52948,7 +52978,7 @@ /obj/effect/turf_decal/tile/neutral/opposingcorners, /obj/structure/chair/stool/bar/directional/north, /turf/open/floor/iron, -/area/station/holodeck/rec_center) +/area/station/commons/fitness/recreation/entertainment) "sjl" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -53462,7 +53492,7 @@ /area/station/maintenance/port/greater) "srw" = ( /turf/closed/wall/r_wall/rust, -/area/station/engineering/atmospherics_engine) +/area/station/maintenance/department/electrical) "srx" = ( /obj/machinery/power/port_gen/pacman, /obj/effect/turf_decal/bot{ @@ -53636,7 +53666,7 @@ }, /obj/effect/landmark/start/hangover, /turf/open/floor/iron, -/area/station/holodeck/rec_center) +/area/station/commons/fitness/recreation/entertainment) "sul" = ( /obj/effect/turf_decal/siding{ dir = 1 @@ -54429,6 +54459,10 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron/grimy, /area/station/commons/vacant_room/office) +"sJf" = ( +/obj/structure/water_source/puddle, +/turf/open/misc/asteroid, +/area/station/maintenance/starboard/greater) "sJg" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/general/hidden, /obj/machinery/door/airlock/command{ @@ -56207,11 +56241,9 @@ "tlJ" = ( /obj/effect/turf_decal/tile/neutral/opposingcorners, /obj/item/kirbyplants/random, -/obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/power/apc/auto_name/directional/east, /turf/open/floor/iron, -/area/station/holodeck/rec_center) +/area/station/commons/fitness/recreation/entertainment) "tlX" = ( /obj/structure/cable, /obj/effect/turf_decal/tile/blue/fourcorners, @@ -56535,6 +56567,12 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/wood, /area/station/commons/fitness/recreation) +"tqn" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/light/small/directional/west, +/turf/open/floor/iron/dark, +/area/station/engineering/atmospherics_engine) "tqo" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, @@ -58697,6 +58735,9 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos/project) +"uct" = ( +/turf/open/floor/engine/vacuum, +/area/station/engineering/atmos) "ucy" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/turf_decal/siding/red{ @@ -59975,7 +60016,7 @@ /obj/effect/turf_decal/tile/neutral/opposingcorners, /obj/effect/spawner/random/entertainment/arcade, /turf/open/floor/iron, -/area/station/holodeck/rec_center) +/area/station/commons/fitness/recreation/entertainment) "uwB" = ( /obj/effect/turf_decal/tile/dark_red/half/contrasted{ dir = 4 @@ -60118,19 +60159,6 @@ /obj/machinery/airalarm/directional/west, /turf/open/floor/wood/tile, /area/station/command/bridge) -"uAM" = ( -/obj/machinery/atmospherics/components/unary/thermomachine/freezer{ - dir = 8 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/effect/turf_decal/bot{ - dir = 1 - }, -/obj/structure/closet/firecloset, -/turf/open/floor/engine, -/area/station/engineering/supermatter/room) "uAY" = ( /turf/open/floor/plating, /area/station/maintenance/department/bridge) @@ -61738,10 +61766,6 @@ }, /turf/open/floor/iron/dark, /area/station/security/interrogation) -"vcm" = ( -/obj/item/pickaxe, -/turf/open/misc/asteroid, -/area/station/maintenance/department/electrical) "vcB" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -63923,7 +63947,7 @@ /obj/machinery/door/airlock/engineering{ name = "Engineering Office" }, -/obj/effect/mapping_helpers/airlock/access/any/engineering/general, +/obj/effect/mapping_helpers/airlock/access/all/engineering/engine_equipment, /turf/open/floor/iron/smooth_half{ dir = 8 }, @@ -65457,14 +65481,6 @@ "wfr" = ( /turf/closed/wall/r_wall, /area/station/medical/pharmacy) -"wfB" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/effect/decal/cleanable/dirt/dust, -/obj/effect/spawner/random/structure/steam_vent, -/turf/open/floor/plating, -/area/station/maintenance/department/electrical) "wfG" = ( /obj/structure/disposalpipe/segment, /obj/machinery/firealarm/directional/west, @@ -67714,10 +67730,10 @@ /obj/machinery/atmospherics/components/binary/pump/on{ name = "O2 to Airmix" }, -/obj/machinery/atmospherics/pipe/bridge_pipe/green{ +/obj/machinery/light/no_nightlight/directional/north, +/obj/machinery/atmospherics/pipe/bridge_pipe/green/visible{ dir = 4 }, -/obj/machinery/light/no_nightlight/directional/north, /turf/open/floor/iron, /area/station/engineering/atmos) "wPP" = ( @@ -70301,6 +70317,10 @@ heat_proof = 1; name = "Supermatter Chamber" }, +/obj/effect/mapping_helpers/airlock/access/any/engineering/general, +/obj/effect/mapping_helpers/airlock/cyclelink_helper{ + dir = 4 + }, /turf/open/floor/engine, /area/station/engineering/supermatter) "xAA" = ( @@ -72325,7 +72345,7 @@ /area/station/hallway/primary/starboard) "yei" = ( /obj/machinery/door/airlock/maintenance{ - name = "Transit Tube Station" + name = "Atmospherics Maintenance" }, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/cable, @@ -81902,7 +81922,7 @@ wBo sRf wBo hFO -wBo +oYf mPB wWm nlR @@ -83995,7 +84015,7 @@ kjW fcE ceN cDV -kUN +bNq ybs knv knv @@ -84221,8 +84241,8 @@ wzv wzv fjh dfd -ybO -jbE +pnl +ooo ukP ooo jZl @@ -84233,7 +84253,7 @@ wmq vMI pKW kiP -wmq +tqn dYv jZl feu @@ -84252,7 +84272,7 @@ tKn eWr xcW prP -kUN +bNq ybs knv aJq @@ -84478,7 +84498,7 @@ wzv wzv fjh wzv -ybO +pnl dpH kNv gAy @@ -84509,7 +84529,7 @@ hBi bzF gzM svd -kUN +bNq liX jqd lxP @@ -84735,10 +84755,10 @@ pWm pWm uEH dfd -ybO -ybO -ybO -ybO +pnl +uct +uct +uct jZl bEG rCk @@ -84766,7 +84786,7 @@ isC bPd vDG rry -kUN +bNq olj cmf gBh @@ -84991,11 +85011,11 @@ wzv wzv wzv yil -yil -wfB -kNn -yil -kNn +wzv +pnl +uct +hGa +uct jZl oqq tmK @@ -85023,7 +85043,7 @@ uqg cjS gqS kmL -eKU +ecq olj gBh gBh @@ -85244,15 +85264,15 @@ dDB aWx tdY qcF -wzv +kNn yil xnL yil -pWm -pWm -pWm -mMF -mDb +bXb +pnl +pnl +pnl +pnl srw tXF qaU @@ -85280,7 +85300,7 @@ hMQ tNm nWa iua -kUN +bNq bJK dez gBh @@ -85501,13 +85521,13 @@ pWm pWm pWm pWm -pWm rjo pWm pWm pWm -bvt -bvt +bXb +bXb +bXb bXb yil fTJ @@ -85537,7 +85557,7 @@ kti iwR oQK dFG -kUN +bNq cvJ olj knv @@ -85756,18 +85776,18 @@ dDB dDB tYT aJq -aJq -pWm +gcs ako mmT vtJ acg pWm -bvt -bvt -vcm +efn +wzv +wzv +wzv oii -jZl +pnl sZP wvZ mDS @@ -85794,7 +85814,7 @@ lkN rjw vSt kOH -kUN +bNq cvJ aIk knv @@ -86013,8 +86033,7 @@ dDB dDB tYT aJq -aJq -pWm +gcs arN wOz viE @@ -86022,9 +86041,10 @@ bOa pWm bvt bvt -bvt +nbN +ggr oii -jZl +pnl gmv jrD jrD @@ -86051,7 +86071,7 @@ vuV xLS lfq cHt -kUN +bNq xxt liX knv @@ -86201,7 +86221,7 @@ xjz xjz xjz xjz -dDB +xjz dDB blb blb @@ -86270,8 +86290,7 @@ dDB dDB tYT aJq -aJq -pWm +gcs pWm hDg qMG @@ -86280,17 +86299,18 @@ bvt bvt bvt bvt +bvt yil -jZl +pnl wFZ oLc jDi jDi jDi -jZl +pnl srw -jZl -jZl +pnl +pnl jZl xck cag @@ -86298,17 +86318,17 @@ xck bJH xck cGV -cGV -cGV -lwK -cGV -kUN +bNq +bNq +ecq +bNq +bNq hhr -kUN +bNq gUQ -kUN -kUN -kUN +bNq +bNq +bNq knv tZE knv @@ -86457,7 +86477,7 @@ hJC aHJ wmy tBm -xjz +tBm xjz blb blb @@ -86529,22 +86549,22 @@ dDB tYT aJq bvt -bvt fiw oIf pWm bvt bvt bvt +bvt pWm oii -jZl +pnl jDi jDi jDi jDi jDi -jZl +pnl oCE oCE lYH @@ -86714,7 +86734,7 @@ aWt sis sis sis -tBm +lhd xjz blb dDB @@ -86795,13 +86815,13 @@ bvt bvt pWm yil -jZl +pnl urP kLr wkj tuu kHd -jZl +pnl oCE pWm pWm @@ -87053,11 +87073,11 @@ bvt pWm qjp kNn -jZl -jZl -jZl +pnl +pnl +pnl srw -jZl +pnl tOc oCE pWm @@ -90396,7 +90416,7 @@ szg tpW pUM kMe -kMe +prd fGf ayK izf @@ -91673,7 +91693,7 @@ cBd cBd dyI ozQ -xAx +jvm brA dyI oer @@ -92704,7 +92724,7 @@ buI kjs xUK vni -uAM +nHH lHd nHH xTr @@ -112298,13 +112318,13 @@ cvk nFW uvG siN -ngd +jpp nuV sue -ngd +jpp cUB baO -pOT +pzd gMz rem rQA @@ -112557,11 +112577,11 @@ pTA hEw bWp gjn -ngd +jpp ibF diG baO -pOT +pzd ycQ rem nvB @@ -112810,13 +112830,13 @@ eav eav nFW nFW -pOT -pOT +pzd +pzd tlJ cYp jTC eOX -pOT +pzd xQJ xQJ xQJ @@ -113068,12 +113088,12 @@ tLj wOp fsq iRl -pOT -pOT +pzd +pzd pTk -pOT -pOT -pOT +pzd +pzd +pzd xqs xMO xQJ @@ -113327,7 +113347,7 @@ fLg tHi tfc wOp -mTc +ljc xQJ ejn vJx @@ -113584,7 +113604,7 @@ pot rUq lyq wOp -mTc +ljc xQJ mbV vJx @@ -129061,7 +129081,7 @@ ylD hqH vzv brz -cgM +sJf ylD wyj dYR diff --git a/_maps/map_files/Deltastation/DeltaStation2.dmm b/_maps/map_files/Deltastation/DeltaStation2.dmm index 07982e7dabcee1..8959abab5589d6 100644 --- a/_maps/map_files/Deltastation/DeltaStation2.dmm +++ b/_maps/map_files/Deltastation/DeltaStation2.dmm @@ -10390,14 +10390,12 @@ /area/station/command/corporate_showroom) "czg" = ( /obj/machinery/hydroponics/soil, -/obj/effect/decal/cleanable/dirt, /obj/item/plant_analyzer, /obj/machinery/camera/directional/east{ c_tag = "Permabrig - Garden"; network = list("ss13","prison") }, -/obj/effect/mapping_helpers/burnt_floor, -/turf/open/floor/plating, +/turf/open/misc/sandy_dirt, /area/station/security/prison/garden) "czi" = ( /obj/effect/decal/cleanable/dirt, @@ -19613,10 +19611,8 @@ /area/station/engineering/atmos) "eQx" = ( /obj/machinery/hydroponics/soil, -/obj/effect/decal/cleanable/dirt, /obj/item/shovel/spade, -/obj/effect/mapping_helpers/burnt_floor, -/turf/open/floor/plating, +/turf/open/misc/sandy_dirt, /area/station/security/prison/garden) "eQB" = ( /obj/machinery/door/airlock/public/glass{ @@ -27561,10 +27557,8 @@ "gLT" = ( /obj/machinery/hydroponics/soil, /obj/item/cultivator, -/obj/effect/decal/cleanable/dirt, /obj/structure/sign/warning/electric_shock/directional/west, -/obj/effect/mapping_helpers/burnt_floor, -/turf/open/floor/plating, +/turf/open/misc/sandy_dirt, /area/station/security/prison/garden) "gMd" = ( /obj/structure/window/reinforced/spawner/directional/west, @@ -30877,23 +30871,10 @@ /turf/open/floor/iron, /area/station/commons/vacant_room/commissary) "hHi" = ( -/obj/structure/closet/crate/hydroponics, -/obj/item/paper/guides/jobs/hydroponics, -/obj/item/seeds/onion, -/obj/item/seeds/garlic, -/obj/item/seeds/potato, -/obj/item/seeds/tomato, -/obj/item/seeds/carrot, -/obj/item/seeds/grass, -/obj/item/seeds/ambrosia, -/obj/item/seeds/wheat, -/obj/item/seeds/pumpkin, -/obj/effect/spawner/random/contraband/prison, /obj/structure/window/spawner/directional/south, -/obj/effect/decal/cleanable/dirt, -/obj/item/seeds/tower, /obj/structure/sign/poster/official/random/directional/north, -/turf/open/floor/iron, +/obj/structure/water_source/puddle, +/turf/open/misc/sandy_dirt, /area/station/security/prison/garden) "hHo" = ( /obj/structure/disposalpipe/trunk, @@ -59532,13 +59513,23 @@ /area/station/service/chapel) "oWp" = ( /obj/structure/window/spawner/directional/south, -/obj/structure/sink/directional/south, -/obj/structure/reagent_dispensers/watertank, -/obj/item/reagent_containers/cup/watering_can, /obj/effect/decal/cleanable/dirt, /obj/effect/decal/cleanable/cobweb, /obj/structure/cable, /obj/machinery/power/apc/auto_name/directional/west, +/obj/structure/closet/crate/hydroponics, +/obj/item/seeds/tower, +/obj/effect/spawner/random/contraband/prison, +/obj/item/seeds/pumpkin, +/obj/item/seeds/wheat, +/obj/item/seeds/ambrosia, +/obj/item/seeds/grass, +/obj/item/seeds/carrot, +/obj/item/seeds/tomato, +/obj/item/seeds/potato, +/obj/item/seeds/garlic, +/obj/item/seeds/onion, +/obj/item/paper/guides/jobs/hydroponics, /turf/open/floor/iron, /area/station/security/prison/garden) "oWt" = ( @@ -78609,11 +78600,9 @@ /area/station/command/corporate_showroom) "tGW" = ( /obj/machinery/hydroponics/soil, -/obj/effect/decal/cleanable/dirt, /obj/item/radio/intercom/directional/east, -/obj/effect/mapping_helpers/burnt_floor, /obj/machinery/light/small/directional/east, -/turf/open/floor/plating, +/turf/open/misc/sandy_dirt, /area/station/security/prison/garden) "tHc" = ( /obj/structure/table/wood/fancy, @@ -79874,10 +79863,8 @@ dir = 1 }, /obj/machinery/firealarm/directional/west, -/obj/effect/turf_decal/tile/green{ - dir = 8 - }, -/turf/open/floor/iron, +/obj/structure/water_source/puddle, +/turf/open/misc/sandy_dirt, /area/station/service/hydroponics/garden) "tXe" = ( /obj/effect/turf_decal/loading_area/red{ @@ -84678,6 +84665,7 @@ /obj/machinery/hydroponics/constructable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/effect/turf_decal/tile/green, +/obj/item/reagent_containers/cup/watering_can, /turf/open/floor/iron, /area/station/security/prison/garden) "veD" = ( @@ -90301,10 +90289,8 @@ "wAt" = ( /obj/machinery/hydroponics/soil, /obj/item/cultivator, -/obj/effect/decal/cleanable/dirt, /obj/machinery/airalarm/directional/east, -/obj/effect/mapping_helpers/burnt_floor, -/turf/open/floor/plating, +/turf/open/misc/sandy_dirt, /area/station/security/prison/garden) "wAz" = ( /obj/structure/table/wood, @@ -91828,11 +91814,9 @@ /area/space) "wVy" = ( /obj/machinery/hydroponics/soil, -/obj/effect/decal/cleanable/dirt, /obj/machinery/light/small/directional/west, -/obj/effect/mapping_helpers/burnt_floor, /obj/structure/sign/poster/contraband/ambrosia_vulgaris/directional/west, -/turf/open/floor/plating, +/turf/open/misc/sandy_dirt, /area/station/security/prison/garden) "wVJ" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ diff --git a/_maps/map_files/IceBoxStation/IceBoxStation.dmm b/_maps/map_files/IceBoxStation/IceBoxStation.dmm index 31478a156f20b2..b88647d4934a00 100644 --- a/_maps/map_files/IceBoxStation/IceBoxStation.dmm +++ b/_maps/map_files/IceBoxStation/IceBoxStation.dmm @@ -964,7 +964,7 @@ /obj/structure/cable, /obj/effect/turf_decal/tile/neutral/fourcorners, /obj/machinery/light/small/directional/north, -/obj/machinery/computer/security/telescreen/engine/directional/north, +/obj/machinery/incident_display/delam/directional/north, /turf/open/floor/iron/dark, /area/station/engineering/engine_smes) "apS" = ( @@ -9036,6 +9036,9 @@ /obj/effect/turf_decal/tile/neutral/half/contrasted{ dir = 4 }, +/obj/effect/turf_decal/siding/wood{ + dir = 4 + }, /turf/open/floor/iron, /area/station/service/hydroponics/garden) "cBG" = ( @@ -15758,6 +15761,7 @@ /obj/item/analyzer, /obj/item/pipe_dispenser, /obj/item/flashlight, +/obj/machinery/incident_display/delam/directional/north, /turf/open/floor/engine, /area/station/engineering/supermatter/room) "eEm" = ( @@ -24771,10 +24775,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/visible, /turf/open/floor/plating, /area/station/maintenance/port/aft) -"hto" = ( -/obj/structure/girder, -/turf/closed/wall, -/area/station/maintenance/starboard/aft) "htp" = ( /obj/machinery/door/poddoor/preopen{ id = "xenobio2"; @@ -29665,7 +29665,7 @@ }, /obj/machinery/holopad, /obj/effect/landmark/start/depsec/medical, -/obj/machinery/computer/security/telescreen/cmo/directional/east, +/obj/machinery/computer/security/telescreen/med_sec/directional/east, /turf/open/floor/iron/dark/smooth_large, /area/station/security/checkpoint/medical) "iTJ" = ( @@ -41854,7 +41854,6 @@ /obj/effect/turf_decal/tile/blue/half/contrasted{ dir = 1 }, -/obj/machinery/incident_display/bridge/directional/north, /turf/open/floor/iron, /area/station/hallway/primary/central) "mDw" = ( @@ -43794,6 +43793,7 @@ /obj/structure/cable, /obj/machinery/power/apc/auto_name/directional/south, /obj/item/radio/intercom/directional/west, +/obj/structure/reagent_dispensers/watertank, /turf/open/floor/iron, /area/station/service/hydroponics/garden) "nhT" = ( @@ -49552,6 +49552,10 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/wood, /area/station/maintenance/aft/lesser) +"oNW" = ( +/obj/structure/water_source/puddle, +/turf/open/floor/grass, +/area/station/security/prison/garden) "oNX" = ( /obj/machinery/airalarm/directional/west, /turf/open/floor/iron/dark, @@ -52423,6 +52427,9 @@ /obj/structure/disposalpipe/segment{ dir = 4 }, +/obj/effect/turf_decal/siding/wood{ + dir = 1 + }, /turf/open/floor/iron/dark, /area/station/service/hydroponics/garden) "pGJ" = ( @@ -54284,10 +54291,10 @@ /turf/open/floor/iron, /area/station/command/heads_quarters/qm) "qiT" = ( -/obj/structure/reagent_dispensers/watertank, /obj/effect/turf_decal/tile/green/anticorner/contrasted{ dir = 4 }, +/obj/item/kirbyplants/random, /turf/open/floor/iron/dark, /area/station/service/hydroponics/garden) "qjb" = ( @@ -58115,6 +58122,7 @@ /obj/item/stock_parts/power_store/cell/high/empty, /obj/machinery/cell_charger, /obj/effect/turf_decal/tile/brown/fourcorners, +/obj/item/radio/intercom/directional/west, /turf/open/floor/iron/dark, /area/station/engineering/lobby) "rlS" = ( @@ -63820,7 +63828,7 @@ /turf/open/floor/iron/white, /area/station/medical/chemistry) "sSS" = ( -/obj/item/radio/intercom/directional/north, +/obj/machinery/incident_display/delam/directional/north, /turf/open/floor/iron/dark, /area/station/engineering/lobby) "sTe" = ( @@ -67390,7 +67398,6 @@ /obj/machinery/modular_computer/preset/civilian{ dir = 8 }, -/obj/structure/sign/poster/official/build/directional/north, /turf/open/floor/iron/dark, /area/station/engineering/lobby) "tZR" = ( @@ -73913,7 +73920,6 @@ /turf/open/floor/iron/large, /area/station/command/heads_quarters/ce) "wcz" = ( -/obj/structure/sink/directional/south, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /obj/effect/turf_decal/tile/green/half/contrasted{ dir = 1 @@ -74289,8 +74295,8 @@ /area/station/medical/virology) "wiM" = ( /obj/machinery/computer/station_alert, -/obj/item/radio/intercom/directional/north, /obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/machinery/computer/security/telescreen/engine/directional/north, /turf/open/floor/iron/dark, /area/station/engineering/engine_smes) "wiO" = ( @@ -77700,15 +77706,12 @@ /turf/open/floor/carpet/blue, /area/station/hallway/secondary/entry) "xhg" = ( -/obj/effect/turf_decal/siding/wood{ - dir = 1 - }, /obj/machinery/camera/directional/east{ c_tag = "Garden" }, -/obj/item/kirbyplants/random, /obj/machinery/status_display/ai/directional/east, -/turf/open/floor/iron/dark, +/obj/structure/water_source/puddle, +/turf/open/floor/grass, /area/station/service/hydroponics/garden) "xhk" = ( /turf/open/floor/iron/dark, @@ -79384,9 +79387,14 @@ /turf/open/floor/iron/dark, /area/station/medical/morgue) "xFM" = ( -/obj/machinery/incident_display/delam, -/turf/closed/wall/r_wall, -/area/station/engineering/supermatter/room) +/obj/effect/turf_decal/bot{ + dir = 1 + }, +/obj/machinery/suit_storage_unit/engine, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/item/radio/intercom/directional/west, +/turf/open/floor/iron/dark/textured, +/area/station/engineering/engine_smes) "xFT" = ( /obj/effect/turf_decal/trimline/green/filled/corner, /obj/effect/turf_decal/trimline/blue/filled/warning/corner, @@ -167760,7 +167768,7 @@ jlF jNf dpC cGQ -whr +oNW nmr hVY gjq @@ -168275,7 +168283,7 @@ jNf qIo tau dWK -ozX +whr hVY gjq gjq @@ -240599,7 +240607,7 @@ gTK gTK myX sSJ -xFM +gka eEh fab eDC @@ -240852,7 +240860,7 @@ mNY wiM tMD ehJ -rpF +xFM twt tXB sSJ @@ -259613,7 +259621,7 @@ lXi vzD vzD vzD -hto +vzD jOj vzD daT diff --git a/_maps/map_files/MetaStation/MetaStation.dmm b/_maps/map_files/MetaStation/MetaStation.dmm index 83eb9c4b5e81dd..a719ae4c671149 100644 --- a/_maps/map_files/MetaStation/MetaStation.dmm +++ b/_maps/map_files/MetaStation/MetaStation.dmm @@ -10596,9 +10596,7 @@ }, /obj/effect/turf_decal/tile/red/fourcorners, /obj/machinery/light/small/directional/west, -/obj/machinery/computer/security/telescreen/cmo/directional/west{ - name = "Medbay Monitor" - }, +/obj/machinery/computer/security/telescreen/med_sec/directional/west, /turf/open/floor/iron/dark, /area/station/security/checkpoint/medical) "dQO" = ( @@ -15539,13 +15537,10 @@ /turf/open/floor/plating/airless, /area/station/solars/port/fore) "fzr" = ( -/obj/structure/table, -/obj/effect/turf_decal/stripes/line, -/obj/effect/spawner/random/food_or_drink/seed{ - spawn_all_loot = 1; - spawn_random_offset = 1 - }, -/turf/open/floor/iron, +/obj/structure/window/spawner/directional/south, +/obj/structure/window/spawner/directional/west, +/obj/structure/water_source/puddle, +/turf/open/floor/grass, /area/station/service/hydroponics/garden) "fzE" = ( /obj/structure/sign/warning/vacuum/external/directional/north, @@ -38990,6 +38985,7 @@ /obj/effect/turf_decal/trimline/green/filled/line{ dir = 9 }, +/obj/structure/cable, /turf/open/floor/iron, /area/station/security/prison/garden) "nNw" = ( @@ -39528,6 +39524,10 @@ /obj/structure/table, /obj/structure/extinguisher_cabinet/directional/west, /obj/effect/turf_decal/stripes/line, +/obj/effect/spawner/random/food_or_drink/seed{ + spawn_all_loot = 1; + spawn_random_offset = 1 + }, /turf/open/floor/iron, /area/station/service/hydroponics/garden) "nYU" = ( @@ -40409,7 +40409,6 @@ /obj/machinery/hydroponics/soil, /obj/item/cultivator, /obj/effect/decal/cleanable/dirt, -/obj/structure/cable, /turf/open/floor/grass, /area/station/security/prison/garden) "opG" = ( @@ -50759,8 +50758,6 @@ /turf/open/floor/iron/white, /area/station/medical/virology) "rVb" = ( -/obj/structure/sink/directional/west, -/obj/item/reagent_containers/cup/watering_can, /obj/effect/turf_decal/trimline/green/filled/line{ dir = 4 }, @@ -51193,7 +51190,6 @@ "sbX" = ( /obj/machinery/hydroponics/soil, /obj/effect/decal/cleanable/dirt, -/obj/structure/cable, /obj/item/plant_analyzer, /turf/open/floor/grass, /area/station/security/prison/garden) @@ -55374,6 +55370,7 @@ /obj/effect/turf_decal/trimline/green/filled/line{ dir = 8 }, +/obj/structure/cable, /turf/open/floor/iron, /area/station/security/prison/garden) "tCF" = ( @@ -63870,6 +63867,12 @@ /obj/structure/reagent_dispensers/fueltank, /turf/open/floor/iron, /area/station/science/robotics/mechbay) +"wsG" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/water_source/puddle, +/obj/item/reagent_containers/cup/watering_can, +/turf/open/floor/grass, +/area/station/security/prison/garden) "wsI" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/structure/cable, @@ -65138,7 +65141,6 @@ /turf/open/floor/iron/white, /area/station/science/robotics/lab) "wRF" = ( -/obj/structure/window/spawner/directional/west, /obj/structure/flora/rock/pile, /turf/open/floor/grass, /area/station/service/hydroponics/garden) @@ -87403,7 +87405,7 @@ aaa lMJ aaa aaa -aaa +cmB cmB cmB cmB @@ -87661,7 +87663,7 @@ lMJ aaa aaa cmB -cmB +wsG opF sbX jTi diff --git a/_maps/map_files/Mining/Lavaland.dmm b/_maps/map_files/Mining/Lavaland.dmm index 7f0a84010e9f03..01234def932898 100644 --- a/_maps/map_files/Mining/Lavaland.dmm +++ b/_maps/map_files/Mining/Lavaland.dmm @@ -3896,11 +3896,11 @@ /area/mine/lounge) "uT" = ( /obj/structure/lattice/catwalk, -/obj/machinery/atmospherics/components/unary/passive_vent/layer2{ +/obj/machinery/atmospherics/components/unary/outlet_injector/layer2{ dir = 1 }, /turf/open/misc/asteroid/basalt/lava_land_surface, -/area/lavaland/surface/outdoors) +/area/mine/maintenance/service) "uU" = ( /turf/closed/mineral/random/labormineral/volcanic, /area/lavaland/surface/outdoors) diff --git a/_maps/map_files/NorthStar/north_star.dmm b/_maps/map_files/NorthStar/north_star.dmm index 4e9080ef499bd7..b4168c7d54d930 100644 --- a/_maps/map_files/NorthStar/north_star.dmm +++ b/_maps/map_files/NorthStar/north_star.dmm @@ -18356,6 +18356,18 @@ /obj/machinery/duct, /turf/open/floor/iron/dark, /area/station/hallway/floor3/fore) +"eJy" = ( +/obj/effect/turf_decal/weather/dirt{ + dir = 8 + }, +/obj/effect/turf_decal/tile/dark_blue, +/obj/effect/turf_decal/weather/dirt{ + dir = 1 + }, +/turf/open/floor/iron/dark/side{ + dir = 8 + }, +/area/station/security/prison/garden) "eJF" = ( /obj/machinery/airalarm/directional/south, /obj/item/kirbyplants/random, @@ -54107,7 +54119,9 @@ /area/station/maintenance/floor1/starboard) "nSz" = ( /obj/effect/decal/cleanable/dirt, -/obj/structure/sink/kitchen/directional/south, +/obj/effect/turf_decal/weather/dirt{ + dir = 8 + }, /turf/open/floor/iron/dark/side{ dir = 5 }, @@ -59391,6 +59405,10 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/pod/light, /area/station/maintenance/floor1/starboard/aft) +"ppf" = ( +/obj/effect/turf_decal/weather/sand/light, +/turf/closed/wall/r_wall, +/area/station/security/execution/education) "ppi" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/table, @@ -64263,15 +64281,9 @@ /turf/open/floor/iron/dark, /area/station/command/teleporter) "qzQ" = ( -/obj/effect/turf_decal/weather/dirt{ - dir = 8 - }, -/obj/item/reagent_containers/cup/watering_can, -/obj/effect/turf_decal/tile/dark_blue, /obj/machinery/newscaster/directional/north, -/turf/open/floor/iron/dark/side{ - dir = 9 - }, +/obj/structure/water_source/puddle, +/turf/open/misc/dirt/jungle, /area/station/security/prison/garden) "qzX" = ( /obj/effect/mapping_helpers/airlock/cyclelink_helper, @@ -68264,6 +68276,7 @@ /obj/effect/mapping_helpers/broken_floor, /obj/effect/turf_decal/tile/dark_blue/opposingcorners, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, +/obj/item/reagent_containers/cup/watering_can, /turf/open/floor/iron/dark/corner{ dir = 4 }, @@ -329837,7 +329850,7 @@ oyh oyh oyh fkA -fkA +ppf wmD fkA kUZ @@ -331381,7 +331394,7 @@ oyh wMF wMF qzQ -pfL +eJy pfL pfL yfr diff --git a/_maps/map_files/tramstation/tramstation.dmm b/_maps/map_files/tramstation/tramstation.dmm index f168e52c6886dc..469e5ec80fb3dd 100644 --- a/_maps/map_files/tramstation/tramstation.dmm +++ b/_maps/map_files/tramstation/tramstation.dmm @@ -8220,6 +8220,7 @@ }, /obj/machinery/vending/modularpc, /obj/structure/table, +/obj/machinery/light/small/directional/north, /turf/open/floor/iron, /area/station/commons/storage/primary) "bNI" = ( @@ -8386,6 +8387,10 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron, /area/station/engineering/atmos) +"bRl" = ( +/obj/structure/water_source/puddle, +/turf/open/misc/asteroid, +/area/station/security/prison/workout) "bRE" = ( /obj/structure/lattice/catwalk, /turf/open/floor/plating/airless, @@ -9748,6 +9753,7 @@ pixel_y = 11 }, /obj/item/stock_parts/power_store/cell/high, +/obj/machinery/light/small/directional/south, /turf/open/floor/iron, /area/station/commons/storage/primary) "cpl" = ( @@ -10802,14 +10808,13 @@ /turf/open/floor/iron, /area/station/security/brig) "cGm" = ( -/obj/effect/turf_decal/bot, -/obj/structure/reagent_dispensers/watertank, /obj/machinery/airalarm/directional/east, /obj/effect/turf_decal/trimline/neutral/line, /obj/effect/turf_decal/trimline/neutral/filled/line{ dir = 4 }, -/turf/open/floor/iron, +/obj/structure/water_source/puddle, +/turf/open/floor/grass, /area/station/service/hydroponics/garden) "cGy" = ( /obj/structure/chair/stool/directional/north, @@ -16419,6 +16424,7 @@ }, /obj/structure/sign/clock/directional/east, /obj/effect/landmark/event_spawn, +/obj/machinery/light/directional/east, /turf/open/floor/iron/smooth, /area/station/commons/storage/primary) "eHr" = ( @@ -46716,7 +46722,6 @@ /area/station/hallway/secondary/exit) "pzw" = ( /obj/effect/turf_decal/bot, -/obj/structure/reagent_dispensers/watertank, /obj/machinery/power/apc/auto_name/directional/east, /obj/effect/turf_decal/trimline/neutral/filled/line{ dir = 4 @@ -47441,10 +47446,10 @@ /turf/open/floor/iron/white, /area/station/science/lower) "pMz" = ( -/obj/structure/table/glass, /obj/effect/turf_decal/trimline/neutral/filled/line{ dir = 5 }, +/obj/structure/reagent_dispensers/watertank, /turf/open/floor/iron, /area/station/service/hydroponics/garden) "pMG" = ( @@ -88123,7 +88128,7 @@ abM aal lPV kPC -lFk +bRl lFk lFk mAB diff --git a/_maps/map_files/wawastation/wawastation.dmm b/_maps/map_files/wawastation/wawastation.dmm index 6cfd1418f7f7fe..fa4ea9e4b32639 100644 --- a/_maps/map_files/wawastation/wawastation.dmm +++ b/_maps/map_files/wawastation/wawastation.dmm @@ -1,4 +1,9 @@ //MAP CONVERTED BY dmm2tgm.py THIS HEADER COMMENT PREVENTS RECONVERSION, DO NOT REMOVE +"aam" = ( +/obj/effect/spawner/structure/window/reinforced/plasma, +/obj/machinery/atmospherics/pipe/smart/simple/yellow/visible, +/turf/open/floor/plating, +/area/station/science/ordnance) "aas" = ( /obj/structure/chair/office/tactical{ dir = 4 @@ -169,6 +174,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/orange/visible, /turf/open/floor/engine, /area/station/engineering/supermatter/room) +"acN" = ( +/obj/structure/table, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/item/holosign_creator/atmos, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "acY" = ( /obj/structure/cable, /obj/structure/railing/corner{ @@ -448,18 +459,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/plating, /area/station/science/xenobiology) -"agM" = ( -/obj/machinery/door/poddoor/shutters/window/preopen{ - name = "Security Shutters"; - id = "xbprotect"; - dir = 8 - }, -/obj/structure/cable, -/obj/machinery/door/firedoor, -/obj/machinery/firealarm/directional/north, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "agO" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/broken_flooring/pile/directional/east, @@ -594,6 +593,18 @@ }, /turf/open/floor/plating, /area/station/science/ordnance) +"aju" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/duct, +/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/hidden, +/obj/effect/turf_decal/tile/blue/fourcorners, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/medical/treatment_center) "ajK" = ( /obj/machinery/door/firedoor, /obj/effect/landmark/navigate_destination/bar, @@ -1040,23 +1051,6 @@ /obj/item/lighter, /turf/open/floor/carpet/red, /area/station/command/heads_quarters/qm) -"aqz" = ( -/obj/effect/turf_decal/caution/stand_clear/red, -/obj/effect/turf_decal/stripes/line, -/obj/machinery/door/poddoor/shutters/window/preopen{ - id = "ordstorage" - }, -/obj/effect/turf_decal/stripes/corner{ - dir = 1 - }, -/turf/open/floor/iron/white, -/area/station/science/ordnance/storage) -"aqG" = ( -/obj/structure/cable, -/obj/effect/turf_decal/siding/purple/corner, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "aqM" = ( /obj/effect/turf_decal/tile/purple/opposingcorners, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ @@ -1157,18 +1151,6 @@ /obj/structure/closet/firecloset, /turf/open/floor/iron/white, /area/station/hallway/secondary/entry) -"atb" = ( -/obj/machinery/atmospherics/components/unary/portables_connector/visible{ - dir = 1 - }, -/obj/effect/turf_decal/box/red, -/obj/structure/disposalpipe/segment{ - dir = 6 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "ath" = ( /obj/machinery/door/window/left/directional/west, /turf/open/floor/grass, @@ -1195,6 +1177,10 @@ /obj/machinery/light/small/directional/south, /turf/open/floor/plating, /area/station/maintenance/aft/upper) +"atT" = ( +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/white, +/area/station/maintenance/department/medical) "atX" = ( /obj/effect/spawner/random/structure/closet_maintenance, /turf/open/floor/plating, @@ -1374,6 +1360,10 @@ /obj/structure/sign/chalkboard_menu, /turf/closed/wall, /area/station/service/cafeteria) +"awy" = ( +/obj/structure/cable, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "awB" = ( /obj/effect/turf_decal/tile/neutral/fourcorners, /obj/structure/table, @@ -1854,6 +1844,17 @@ }, /turf/open/floor/circuit, /area/station/cargo/bitrunning/den) +"aEL" = ( +/obj/machinery/airalarm/directional/east, +/obj/structure/table/reinforced, +/obj/item/stack/sheet/iron/fifty, +/obj/item/storage/toolbox/mechanical, +/obj/item/clothing/head/utility/welding, +/obj/effect/turf_decal/siding/purple{ + dir = 8 + }, +/turf/open/floor/iron, +/area/station/science/robotics/mechbay) "aEP" = ( /obj/effect/mapping_helpers/airlock/access/all/command/captain, /obj/machinery/door/airlock/command{ @@ -1874,6 +1875,15 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/wood/tile, /area/station/service/bar) +"aFb" = ( +/obj/machinery/power/apc/auto_name/directional/south, +/obj/structure/cable, +/obj/effect/mapping_helpers/apc/cell_5k, +/obj/effect/mapping_helpers/apc/full_charge, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "aFp" = ( /obj/machinery/light/directional/south, /obj/structure/dresser, @@ -2318,6 +2328,14 @@ /obj/machinery/airalarm/directional/north, /turf/open/floor/iron/dark, /area/station/security/prison/safe) +"aMf" = ( +/obj/structure/cable, +/obj/effect/turf_decal/siding/purple{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "aMx" = ( /obj/structure/cable, /obj/machinery/camera/autoname/motion/directional/south{ @@ -2394,15 +2412,6 @@ /obj/structure/cable, /turf/open/floor/iron/white, /area/station/science/research) -"aNF" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/lab) "aNH" = ( /obj/machinery/door/airlock/security/glass{ name = "Security Entry"; @@ -2510,15 +2519,6 @@ /obj/effect/spawner/structure/window/plasma, /turf/open/floor/engine, /area/station/medical/chemistry) -"aPG" = ( -/obj/machinery/door/poddoor/shutters/window/preopen{ - id = "ordstorage" - }, -/obj/effect/turf_decal/stripes/line, -/obj/effect/turf_decal/caution/stand_clear/red, -/obj/structure/cable, -/turf/open/floor/iron/white, -/area/station/science/ordnance/storage) "aPI" = ( /obj/machinery/meter, /obj/machinery/atmospherics/pipe/smart/simple/yellow/visible{ @@ -2850,15 +2850,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/dark, /area/station/science/ordnance) -"aXc" = ( -/obj/machinery/power/apc/auto_name/directional/south, -/obj/structure/cable, -/obj/effect/mapping_helpers/apc/cell_5k, -/obj/effect/mapping_helpers/apc/full_charge, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "aXg" = ( /obj/structure/railing{ dir = 10 @@ -3307,17 +3298,6 @@ }, /turf/open/misc/asteroid, /area/station/maintenance/department/science) -"bfq" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/machinery/atmospherics/components/unary/portables_connector/visible{ - dir = 1 - }, -/obj/effect/turf_decal/box/red, -/obj/machinery/light/directional/south, -/turf/open/floor/iron/dark/smooth_large, -/area/station/science/ordnance) "bfD" = ( /obj/effect/landmark/event_spawn, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -3395,6 +3375,10 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central) +"bhq" = ( +/obj/item/radio/intercom/directional/south, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/ordnance/testlab) "bhv" = ( /obj/structure/window/reinforced/plasma/spawner/directional/south, /obj/machinery/power/energy_accumulator/tesla_coil/anchored, @@ -3624,6 +3608,15 @@ "bmp" = ( /turf/closed/wall, /area/station/service/theater) +"bmr" = ( +/obj/machinery/door/poddoor/shutters/window/preopen{ + id = "ordstorage" + }, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/caution/stand_clear/red, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron/white, +/area/station/science/ordnance/storage) "bmu" = ( /obj/effect/turf_decal/sand/plating, /obj/effect/spawner/random/structure/crate, @@ -3769,10 +3762,6 @@ }, /turf/open/floor/iron, /area/station/security/interrogation) -"bqs" = ( -/obj/structure/lattice/catwalk, -/turf/open/openspace/xenobio, -/area/station/science/xenobiology) "bqz" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/components/unary/portables_connector/visible/layer2, @@ -4609,6 +4598,15 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/hallway/primary/central) +"bEz" = ( +/obj/structure/closet/crate/science, +/obj/item/wrench, +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/firealarm/directional/west, +/obj/effect/spawner/random/maintenance, +/obj/effect/turf_decal/stripes/line, +/turf/open/floor/iron/dark/smooth_large, +/area/station/science/ordnance) "bEW" = ( /obj/structure/table/wood, /obj/effect/spawner/random/decoration/microwave{ @@ -4873,15 +4871,6 @@ /obj/machinery/door/window/right/directional/west, /turf/open/floor/grass, /area/station/service/hydroponics/garden) -"bIP" = ( -/obj/effect/turf_decal/tile/neutral/opposingcorners{ - dir = 1 - }, -/obj/effect/turf_decal/siding/purple{ - dir = 4 - }, -/turf/open/floor/iron/dark, -/area/station/command/heads_quarters/rd) "bJc" = ( /obj/structure/railing/corner, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -5054,6 +5043,21 @@ "bND" = ( /turf/open/floor/iron, /area/station/engineering/atmos) +"bNG" = ( +/obj/machinery/door/airlock/research{ + autoclose = 0; + frequency = 1449; + id_tag = "xeno_airlock_interior"; + name = "Xenobiology Lab Internal Airlock" + }, +/obj/effect/mapping_helpers/airlock/locked, +/obj/structure/cable, +/obj/effect/mapping_helpers/airlock/access/all/science/xenobio, +/obj/machinery/door/firedoor, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "bNI" = ( /obj/structure/showcase/cyborg/old{ dir = 8; @@ -5543,6 +5547,12 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, /area/station/maintenance/department/cargo) +"bXe" = ( +/obj/structure/cable, +/obj/machinery/airalarm/directional/north, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "bXx" = ( /obj/machinery/camera/autoname/directional/south, /obj/machinery/airalarm/directional/south, @@ -5570,10 +5580,6 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos) -"bXM" = ( -/obj/machinery/camera/autoname/directional/west, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/ordnance/testlab) "bYa" = ( /obj/structure/filingcabinet/employment, /turf/open/floor/carpet, @@ -5704,10 +5710,6 @@ }, /turf/open/floor/iron/white, /area/station/science/lobby) -"caH" = ( -/obj/structure/sign/warning/directional/west, -/turf/closed/wall/rust, -/area/station/medical/chemistry/minisat) "caP" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 1 @@ -6308,6 +6310,16 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/department/engine) +"cnd" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/duct, +/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/hidden, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/medical/treatment_center) "cnm" = ( /obj/effect/turf_decal/siding/wood/corner{ dir = 4 @@ -6420,12 +6432,6 @@ dir = 4 }, /area/station/hallway/secondary/exit/departure_lounge) -"cqf" = ( -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/effect/mapping_helpers/broken_floor, -/obj/effect/decal/cleanable/dirt/dust, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "cqm" = ( /obj/structure/cable, /obj/machinery/camera/autoname/directional/south{ @@ -6462,12 +6468,6 @@ }, /turf/open/floor/plating, /area/station/maintenance/disposal) -"cra" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron/white, -/area/station/science/ordnance/testlab) "crb" = ( /obj/machinery/door/poddoor/shutters/window{ id = "armory"; @@ -6609,25 +6609,6 @@ "csW" = ( /turf/open/floor/carpet/executive, /area/station/command/heads_quarters/captain/private) -"ctf" = ( -/obj/effect/mapping_helpers/broken_floor, -/obj/effect/decal/cleanable/dirt/dust, -/obj/structure/table, -/obj/item/reagent_containers/cup/beaker{ - pixel_x = -6; - pixel_y = 4 - }, -/obj/item/reagent_containers/syringe{ - pixel_x = 16; - pixel_y = 1 - }, -/obj/item/reagent_containers/syringe{ - pixel_x = 8; - pixel_y = 10 - }, -/obj/structure/sign/poster/contraband/random/directional/north, -/turf/open/floor/iron/white, -/area/station/maintenance/department/medical) "cti" = ( /obj/effect/turf_decal/stripes/line{ dir = 9 @@ -6881,6 +6862,15 @@ }, /turf/open/floor/iron/dark, /area/station/science/ordnance) +"czC" = ( +/obj/effect/turf_decal/bot, +/obj/machinery/button/door/directional/east{ + name = "shutter control"; + id = "ordauxgarage" + }, +/obj/structure/closet/firecloset, +/turf/open/floor/plating, +/area/station/science/ordnance) "czD" = ( /obj/item/stack/tile/iron/white, /obj/effect/decal/cleanable/dirt/dust, @@ -6928,6 +6918,17 @@ /obj/effect/landmark/start/botanist, /turf/open/floor/iron, /area/station/service/hydroponics) +"cAq" = ( +/obj/structure/cable, +/obj/machinery/button/door/directional/east{ + name = "shutter control"; + id = "xbprotect" + }, +/obj/structure/window/reinforced/spawner/directional/south, +/obj/item/kirbyplants/random, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "cAr" = ( /obj/structure/cable, /obj/machinery/button/door/directional/north{ @@ -7016,17 +7017,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/station/cargo/storage) -"cBB" = ( -/obj/machinery/airalarm/directional/east, -/obj/structure/table/reinforced, -/obj/item/stack/sheet/iron/fifty, -/obj/item/storage/toolbox/mechanical, -/obj/item/clothing/head/utility/welding, -/obj/effect/turf_decal/siding/purple{ - dir = 8 - }, -/turf/open/floor/iron, -/area/station/science/robotics/mechbay) "cBD" = ( /obj/machinery/door/airlock/grunge{ name = "Prison Forestry" @@ -7054,6 +7044,19 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark/small, /area/station/engineering/transit_tube) +"cCr" = ( +/obj/machinery/light/directional/north, +/obj/structure/table, +/obj/item/pen{ + pixel_x = 9; + pixel_y = 4 + }, +/obj/item/hand_labeler{ + pixel_y = 10; + pixel_x = -13 + }, +/turf/open/floor/glass/reinforced, +/area/station/science/xenobiology) "cCv" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/siding/white{ @@ -7342,12 +7345,6 @@ /obj/effect/spawner/random/maintenance, /turf/open/floor/plating, /area/station/maintenance/department/medical) -"cIk" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 9 - }, -/turf/open/floor/iron/white, -/area/station/science/ordnance/storage) "cIx" = ( /obj/machinery/atmospherics/components/unary/outlet_injector/monitored/mix_input{ dir = 4 @@ -7716,15 +7713,6 @@ "cPt" = ( /turf/closed/wall/r_wall, /area/station/science/lab) -"cPu" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/simple/dark/visible{ - dir = 8 - }, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "cPx" = ( /obj/structure/table, /obj/item/hfr_box/corner, @@ -7803,16 +7791,6 @@ }, /turf/open/floor/engine/vacuum, /area/station/science/ordnance/burnchamber) -"cQx" = ( -/obj/structure/table, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/item/pipe_dispenser{ - pixel_x = 3; - pixel_y = 7 - }, -/obj/item/pipe_dispenser, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "cQK" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 4 @@ -7990,6 +7968,13 @@ /obj/machinery/rnd/production/protolathe/department/science, /turf/open/floor/iron/white, /area/station/science/lab) +"cUf" = ( +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "cUk" = ( /obj/structure/disposalpipe/segment, /turf/open/floor/iron/white, @@ -8070,6 +8055,15 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron, /area/station/engineering/main) +"cVs" = ( +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Xenobiology Maintenance" + }, +/obj/effect/mapping_helpers/airlock/access/all/science/xenobio, +/obj/structure/cable, +/obj/structure/disposalpipe/segment, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "cVL" = ( /obj/structure/closet/firecloset, /turf/open/floor/iron/textured, @@ -8319,6 +8313,12 @@ /obj/effect/turf_decal/sand/plating, /turf/open/floor/plating/reinforced/airless, /area/space/nearstation) +"cZs" = ( +/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ + dir = 8 + }, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "cZE" = ( /turf/open/openspace, /area/station/command/meeting_room) @@ -8351,12 +8351,6 @@ }, /turf/open/floor/catwalk_floor/iron_dark, /area/station/science/robotics/lab) -"daT" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/light/small/broken/directional/north, -/obj/machinery/atmospherics/components/tank/oxygen, -/turf/open/floor/plating, -/area/station/maintenance/department/science) "dba" = ( /obj/structure/cable, /obj/effect/turf_decal/tile/red{ @@ -8423,6 +8417,12 @@ /obj/effect/spawner/random/trash/mess, /turf/open/floor/iron, /area/station/maintenance/department/medical/central) +"dcc" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron/white, +/area/station/science/ordnance/testlab) "dcf" = ( /obj/structure/table/wood, /obj/structure/railing{ @@ -8452,10 +8452,6 @@ }, /turf/open/floor/plating, /area/station/cargo/miningoffice) -"dci" = ( -/obj/effect/turf_decal/tile/blue/fourcorners, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/medical/treatment_center) "dcl" = ( /obj/effect/turf_decal/sand/plating, /obj/item/pickaxe, @@ -8676,16 +8672,6 @@ }, /turf/open/floor/plating, /area/station/medical/storage) -"dgR" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/duct, -/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/hidden, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/medical/treatment_center) "dgS" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -8829,23 +8815,6 @@ /obj/machinery/light/small/dim/directional/west, /turf/open/misc/asteroid, /area/station/hallway/secondary/entry) -"dir" = ( -/obj/machinery/door/airlock/research/glass{ - name = "Chemistry Minisat" - }, -/obj/effect/mapping_helpers/airlock/access/all/medical/chemistry, -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/effect/turf_decal/trimline/yellow/filled/line, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/mapping_helpers/airlock/unres{ - dir = 8 - }, -/turf/open/floor/iron/white, -/area/station/medical/chemistry/minisat) "diz" = ( /obj/structure/cable, /turf/open/floor/plating, @@ -9304,6 +9273,13 @@ }, /turf/open/floor/iron, /area/station/security/interrogation) +"dpA" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/landmark/blobstart, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "dpH" = ( /obj/effect/turf_decal/tile/neutral/half/contrasted{ color = "#000000" @@ -9381,21 +9357,6 @@ /obj/machinery/light/directional/north, /turf/open/floor/iron, /area/station/cargo/storage) -"drx" = ( -/obj/machinery/door_buttons/airlock_controller{ - idExterior = "xeno_airlock_exterior"; - idInterior = "xeno_airlock_interior"; - idSelf = "xeno_airlock_control"; - name = "Access Console"; - pixel_x = -25; - pixel_y = -25; - req_access = list("xenobiology") - }, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "drz" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/machinery/disposal/bin, @@ -9707,17 +9668,6 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/central) -"dxZ" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/pipe/smart/simple/green/visible{ - dir = 6 - }, -/obj/item/flashlight/glowstick/blue{ - start_on = 1; - light_range = 2 - }, -/turf/open/floor/plating, -/area/station/maintenance/department/science) "dyb" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 1 @@ -9870,6 +9820,12 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central) +"dzL" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "dzN" = ( /obj/effect/turf_decal/tile/neutral{ dir = 1 @@ -10019,6 +9975,12 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/science/xenobiology) +"dBn" = ( +/obj/structure/cable, +/obj/effect/turf_decal/tile/dark_blue/half/contrasted, +/obj/machinery/incident_display/bridge/directional/south, +/turf/open/floor/iron, +/area/station/command/bridge) "dBp" = ( /obj/machinery/button/door/directional/west{ req_access = list("atmospherics"); @@ -10298,23 +10260,6 @@ /obj/structure/cable, /turf/open/floor/carpet/executive, /area/station/command/heads_quarters/captain/private) -"dGi" = ( -/obj/machinery/door/poddoor/shutters/window/preopen{ - id = "ordstorage" - }, -/obj/effect/turf_decal/stripes/line, -/obj/machinery/button/door/directional/east{ - req_access = list("ordnance"); - name = "Ordnance Storage Shutter Control"; - id = "ordstorage" - }, -/obj/effect/turf_decal/caution/stand_clear/red, -/obj/effect/turf_decal/stripes/corner{ - dir = 4 - }, -/obj/structure/cable, -/turf/open/floor/iron/white, -/area/station/science/ordnance/storage) "dGq" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 8 @@ -10323,16 +10268,28 @@ /area/station/service/theater) "dGs" = ( /obj/structure/table/reinforced, -/obj/item/storage/pill_bottle/epinephrine, -/obj/item/stack/sheet/mineral/plasma{ - pixel_y = 12 - }, /obj/effect/turf_decal/trimline/yellow/filled/line{ dir = 4 }, /obj/effect/turf_decal/trimline/yellow/filled/mid_joiner{ dir = 4 }, +/obj/item/hand_labeler{ + pixel_x = 3; + pixel_y = 5 + }, +/obj/item/storage/pill_bottle/epinephrine{ + pixel_x = -9; + pixel_y = 1 + }, +/obj/item/stack/sheet/mineral/plasma{ + pixel_y = 14; + pixel_x = 3 + }, +/obj/item/hand_labeler_refill{ + pixel_x = 10; + pixel_y = -2 + }, /turf/open/floor/iron/white/smooth_edge{ dir = 4 }, @@ -10537,14 +10494,6 @@ }, /turf/open/floor/iron, /area/station/commons/locker) -"dJr" = ( -/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ - dir = 1 - }, -/turf/open/floor/iron/white/smooth_half{ - dir = 8 - }, -/area/station/science/xenobiology) "dJJ" = ( /obj/structure/plasticflaps, /obj/machinery/navbeacon{ @@ -10797,17 +10746,6 @@ /obj/effect/turf_decal/tile/red/fourcorners, /turf/open/floor/iron/dark, /area/station/security/checkpoint/medical) -"dPh" = ( -/obj/machinery/atmospherics/components/unary/thermomachine/freezer/layer2{ - dir = 1 - }, -/obj/effect/turf_decal/box/red, -/obj/machinery/light/directional/south, -/obj/machinery/camera/autoname/directional/west{ - network = list("ss13","rd") - }, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "dPk" = ( /obj/machinery/button/elevator/directional/east{ id = "cargo" @@ -11077,7 +11015,7 @@ /obj/effect/turf_decal/stripes/line{ dir = 5 }, -/obj/structure/reagent_dispensers/watertank, +/obj/structure/reagent_dispensers/watertank/high, /turf/open/floor/iron/large, /area/station/engineering/atmos/upper) "dTA" = ( @@ -11296,6 +11234,16 @@ }, /turf/open/floor/iron/dark, /area/station/security/lockers) +"dXH" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/turf_decal/trimline/yellow/filled/corner{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/yellow/filled/corner, +/turf/open/floor/iron/white, +/area/station/maintenance/department/medical) "dXN" = ( /obj/machinery/door/airlock/research{ name = "Robotics Lab Storage" @@ -11369,11 +11317,6 @@ /obj/structure/reagent_dispensers/wall/peppertank/directional/south, /turf/open/floor/iron/dark, /area/station/security/checkpoint/science) -"dYY" = ( -/obj/machinery/portable_atmospherics/canister, -/obj/structure/sign/poster/official/wtf_is_co2/directional/north, -/turf/open/floor/iron/white/smooth_large, -/area/station/science/ordnance/storage) "dYZ" = ( /obj/effect/spawner/random/maintenance/two, /obj/effect/spawner/random/clothing/twentyfive_percent_cyborg_mask, @@ -11427,15 +11370,6 @@ dir = 1 }, /area/station/command/meeting_room) -"dZQ" = ( -/obj/structure/window/spawner/directional/east, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/structure/cable, -/obj/machinery/portable_atmospherics/pump, -/turf/open/floor/iron/dark/smooth_large, -/area/station/science/ordnance) "eam" = ( /obj/structure/chair{ dir = 8 @@ -11463,10 +11397,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/wood, /area/station/command/heads_quarters/qm) -"eaL" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/hidden, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/medical/treatment_center) "eaS" = ( /obj/effect/turf_decal/siding/wood{ dir = 6 @@ -11590,6 +11520,15 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central) +"ebU" = ( +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/lab) "ece" = ( /obj/effect/turf_decal/trimline/yellow/filled/line{ dir = 4 @@ -11730,6 +11669,14 @@ /obj/machinery/light_switch/directional/west, /turf/open/floor/iron/kitchen, /area/station/service/kitchen) +"efF" = ( +/obj/effect/decal/cleanable/dirt, +/obj/effect/turf_decal/bot, +/obj/machinery/atmospherics/components/unary/portables_connector/visible{ + dir = 4 + }, +/turf/open/floor/plating, +/area/station/maintenance/department/science) "efJ" = ( /obj/machinery/atmospherics/pipe/smart/manifold/purple/visible/layer2{ dir = 1 @@ -11758,6 +11705,15 @@ }, /turf/open/floor/iron/dark, /area/station/security/courtroom) +"egt" = ( +/obj/structure/barricade/wooden, +/obj/effect/decal/cleanable/dirt, +/obj/item/flashlight/glowstick/blue{ + start_on = 1; + light_range = 2 + }, +/turf/open/floor/plating, +/area/station/maintenance/department/science) "egv" = ( /obj/effect/turf_decal/siding/wood{ dir = 4 @@ -11847,6 +11803,20 @@ }, /turf/open/floor/iron/white/smooth_large, /area/station/science/xenobiology/hallway) +"eih" = ( +/obj/structure/table, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/item/storage/toolbox/mechanical{ + pixel_x = -2; + pixel_y = 8 + }, +/obj/item/storage/toolbox/mechanical{ + pixel_x = 3; + pixel_y = -2 + }, +/obj/structure/cable, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "ein" = ( /obj/effect/turf_decal/tile/red/half/contrasted, /obj/structure/disposalpipe/segment{ @@ -12243,11 +12213,6 @@ }, /turf/open/floor/iron/white, /area/station/medical/treatment_center) -"epB" = ( -/obj/machinery/portable_atmospherics/canister, -/obj/structure/cable, -/turf/open/floor/iron/white/smooth_large, -/area/station/science/ordnance/storage) "epE" = ( /obj/structure/closet/toolcloset, /obj/effect/turf_decal/trimline/yellow/filled/line{ @@ -12698,14 +12663,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/wood, /area/station/service/library) -"exS" = ( -/obj/structure/cable, -/obj/effect/turf_decal/sand/plating, -/obj/structure/disposalpipe/segment, -/obj/machinery/door/airlock/maintenance_hatch, -/obj/effect/mapping_helpers/airlock/access/any/medical/maintenance, -/turf/open/floor/plating, -/area/station/asteroid) "exT" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -12742,11 +12699,6 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, /area/station/security/prison/work) -"eyx" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/components/tank/oxygen, -/turf/open/floor/plating, -/area/station/maintenance/department/science) "eyN" = ( /obj/structure/table, /obj/item/grenade/chem_grenade/smart_metal_foam{ @@ -12922,6 +12874,16 @@ /obj/machinery/airalarm/directional/north, /turf/open/floor/iron/white, /area/station/security/prison/safe) +"eBw" = ( +/obj/structure/cable, +/obj/machinery/airalarm/directional/north, +/obj/structure/disposalpipe/segment{ + dir = 10 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/lab) "eBD" = ( /obj/item/kirbyplants/random, /obj/structure/railing/corner{ @@ -13023,15 +12985,6 @@ /obj/structure/marker_beacon/yellow, /turf/open/space/openspace, /area/space/nearstation) -"eCJ" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/simple/dark/visible{ - dir = 8 - }, -/obj/machinery/meter, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "eCO" = ( /obj/machinery/shower/directional/west, /obj/effect/turf_decal/stripes/line, @@ -13125,6 +13078,21 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central) +"eEg" = ( +/obj/machinery/door_buttons/airlock_controller{ + idExterior = "xeno_airlock_exterior"; + idInterior = "xeno_airlock_interior"; + idSelf = "xeno_airlock_control"; + name = "Access Console"; + pixel_x = -25; + pixel_y = -25; + req_access = list("xenobiology") + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "eEm" = ( /obj/effect/turf_decal/stripes/corner, /obj/effect/turf_decal/tile/neutral, @@ -13437,14 +13405,6 @@ "eKR" = ( /turf/closed/wall/r_wall, /area/station/command/bridge) -"eLb" = ( -/obj/machinery/door/airlock/command{ - name = "Research Director's Observatory" - }, -/obj/effect/mapping_helpers/airlock/access/all/science/rd, -/obj/machinery/door/firedoor, -/turf/open/floor/plating, -/area/station/science/ordnance/testlab) "eLe" = ( /obj/machinery/power/apc/auto_name/directional/east, /obj/effect/turf_decal/tile/red/half/contrasted{ @@ -13543,15 +13503,6 @@ }, /turf/open/floor/iron/grimy, /area/station/security/detectives_office) -"eNt" = ( -/obj/machinery/portable_atmospherics/canister/oxygen, -/obj/effect/turf_decal/box, -/obj/machinery/atmospherics/components/unary/portables_connector/visible{ - dir = 8; - name = "Oxygen Chamber Injection Port" - }, -/turf/open/floor/iron/white, -/area/station/science/ordnance/storage) "eNS" = ( /obj/effect/turf_decal/tile/red/half/contrasted, /obj/structure/disposalpipe/segment{ @@ -13581,6 +13532,14 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/asteroid) +"eOA" = ( +/obj/structure/table, +/obj/effect/spawner/random/trash/crushed_can{ + pixel_x = 7; + pixel_y = 15 + }, +/turf/open/floor/iron/white, +/area/station/maintenance/department/medical) "eOD" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -13810,12 +13769,6 @@ /obj/item/trash/waffles, /turf/open/floor/iron, /area/station/hallway/primary/central) -"eTG" = ( -/obj/machinery/atmospherics/pipe/smart/manifold/purple/visible{ - dir = 1 - }, -/turf/closed/wall/r_wall, -/area/station/science/ordnance/storage) "eTZ" = ( /obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ dir = 8 @@ -13828,9 +13781,6 @@ /obj/machinery/portable_atmospherics/canister, /turf/open/floor/plating, /area/station/maintenance/department/science) -"eUB" = ( -/turf/open/floor/catwalk_floor/iron_white, -/area/station/medical/treatment_center) "eUD" = ( /obj/effect/turf_decal/plaque{ icon_state = "L12" @@ -15808,11 +15758,6 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron, /area/station/command/corporate_showroom) -"fEW" = ( -/obj/effect/spawner/structure/window/reinforced/plasma, -/obj/structure/cable, -/turf/open/floor/plating, -/area/station/command/heads_quarters/rd) "fFb" = ( /obj/structure/railing{ dir = 1 @@ -16266,13 +16211,6 @@ /obj/machinery/light/dim/directional/east, /turf/open/floor/iron, /area/station/commons/storage/tools) -"fNi" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 9 - }, -/obj/machinery/portable_atmospherics/scrubber/huge/movable, -/turf/open/floor/iron/dark/smooth_large, -/area/station/science/ordnance) "fNk" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /turf/open/floor/iron/dark, @@ -16710,14 +16648,6 @@ }, /turf/open/floor/iron/white, /area/station/science/research) -"fTO" = ( -/obj/machinery/processor/slime, -/obj/effect/turf_decal/bot_red, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/iron/white/textured_large, -/area/station/science/xenobiology) "fTX" = ( /turf/closed/wall/r_wall, /area/station/engineering/atmos) @@ -16806,6 +16736,16 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, /area/station/maintenance/port/greater) +"fVO" = ( +/obj/machinery/door/firedoor/heavy, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/machinery/door/airlock/research{ + name = "Ordnance Auxiliary Storage" + }, +/obj/effect/mapping_helpers/airlock/access/all/science/ordnance, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "fVU" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -16852,6 +16792,14 @@ "fXn" = ( /turf/open/floor/wood/parquet, /area/station/cargo/boutique) +"fXo" = ( +/obj/effect/turf_decal/sand/plating, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/obj/item/pickaxe, +/turf/open/floor/plating, +/area/station/asteroid) "fXt" = ( /obj/effect/spawner/structure/window/reinforced/plasma, /turf/open/floor/engine, @@ -16940,16 +16888,6 @@ /obj/machinery/camera/autoname/directional/west, /turf/open/floor/iron, /area/station/hallway/primary/starboard) -"fYW" = ( -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "fYX" = ( /obj/machinery/power/solar{ id = "foreport"; @@ -16973,6 +16911,15 @@ "fZe" = ( /turf/closed/wall, /area/station/security/detectives_office) +"fZg" = ( +/obj/item/toy/plush/lizard_plushie/green{ + name = "Hauls-The-Crates" + }, +/obj/effect/spawner/random/structure/table_or_rack, +/obj/effect/decal/cleanable/cobweb/cobweb2, +/obj/structure/sign/departments/exodrone/directional/east, +/turf/open/floor/plating, +/area/station/maintenance/department/cargo) "fZl" = ( /obj/effect/turf_decal/tile/blue/fourcorners, /obj/machinery/recharge_station, @@ -17219,14 +17166,6 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/glass/reinforced, /area/station/science/research) -"gdM" = ( -/obj/structure/cable, -/obj/effect/turf_decal/siding/purple{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "gdP" = ( /obj/structure/lattice, /obj/machinery/atmospherics/pipe/smart/simple/green/visible{ @@ -17349,6 +17288,7 @@ /area/station/science/research) "ggl" = ( /obj/machinery/camera/autoname/directional/west, +/obj/structure/water_source/puddle, /turf/open/floor/grass, /area/station/service/hydroponics/garden) "ggu" = ( @@ -17502,6 +17442,14 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/engineering/atmos/pumproom) +"giJ" = ( +/obj/structure/cable, +/obj/machinery/firealarm/directional/east, +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/lab) "giK" = ( /obj/effect/turf_decal/tile/brown/half/contrasted{ dir = 1 @@ -17509,17 +17457,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/cargo/drone_bay) -"gjo" = ( -/obj/structure/cable, -/obj/machinery/button/door/directional/east{ - name = "shutter control"; - id = "xbprotect" - }, -/obj/structure/window/reinforced/spawner/directional/south, -/obj/item/kirbyplants/random, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "gjt" = ( /obj/machinery/pdapainter/medbay, /obj/effect/turf_decal/trimline/dark_blue/filled/line{ @@ -17687,15 +17624,6 @@ /obj/machinery/digital_clock/directional/north, /turf/open/floor/iron/white, /area/station/medical/treatment_center) -"gmb" = ( -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 6 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "gmd" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/door/poddoor/shutters/preopen{ @@ -17782,16 +17710,6 @@ /obj/effect/spawner/random/structure/crate, /turf/open/floor/plating, /area/station/maintenance/department/medical/central) -"gop" = ( -/obj/effect/landmark/blobstart, -/obj/structure/closet/crate/science{ - opened = 1; - icon_state = "scicrateopen" - }, -/obj/effect/decal/cleanable/dirt/dust, -/obj/effect/turf_decal/stripes/line, -/turf/open/floor/iron/dark/smooth_large, -/area/station/science/ordnance) "goB" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/effect/decal/cleanable/blood/tracks, @@ -18123,10 +18041,6 @@ /obj/machinery/airalarm/directional/north, /turf/open/floor/iron, /area/station/cargo/storage) -"guJ" = ( -/obj/item/radio/intercom/chapel/directional/west, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/ordnance/testlab) "guN" = ( /obj/structure/table/glass, /obj/item/folder/white, @@ -18150,6 +18064,18 @@ /obj/effect/decal/cleanable/blood/old, /turf/open/floor/iron/freezer, /area/station/maintenance/department/medical/central) +"gvj" = ( +/obj/machinery/door/poddoor/shutters/window/preopen{ + name = "Security Shutters"; + id = "xbprotect"; + dir = 8 + }, +/obj/structure/cable, +/obj/machinery/door/firedoor, +/obj/machinery/firealarm/directional/north, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "gvk" = ( /obj/structure/cable, /obj/effect/spawner/random/maintenance, @@ -18460,14 +18386,6 @@ /obj/effect/turf_decal/tile/blue/fourcorners, /turf/open/floor/iron/white, /area/station/medical/treatment_center) -"gzF" = ( -/obj/machinery/atmospherics/pipe/smart/simple/dark/visible{ - dir = 8 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "gzL" = ( /obj/machinery/light/small/directional/south, /turf/open/floor/plating, @@ -18505,6 +18423,13 @@ /mob/living/basic/carp/pet/lia, /turf/open/floor/carpet/red, /area/station/command/heads_quarters/hos) +"gAV" = ( +/obj/structure/tank_dispenser, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/item/radio/intercom/directional/north, +/obj/machinery/light_switch/directional/east, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "gAZ" = ( /obj/machinery/atmospherics/components/binary/pump/off{ dir = 8; @@ -18631,6 +18556,17 @@ /obj/effect/turf_decal/tile/yellow/fourcorners, /turf/open/floor/iron, /area/station/engineering/main) +"gCV" = ( +/obj/structure/cable, +/obj/machinery/door/airlock/maintenance_hatch{ + name = "Xenobiology Maintenance" + }, +/obj/effect/mapping_helpers/airlock/access/all/science/xenobio, +/obj/structure/disposalpipe/segment, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "gCY" = ( /obj/structure/cable, /obj/effect/turf_decal/tile/yellow, @@ -18964,6 +18900,13 @@ }, /turf/open/floor/iron/dark, /area/station/maintenance/department/engine) +"gIM" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/lab) "gIO" = ( /obj/structure/table/reinforced/rglass, /obj/item/poster/random_official, @@ -19328,6 +19271,10 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron, /area/station/engineering/lobby) +"gQL" = ( +/obj/structure/sign/warning/directional/west, +/turf/closed/wall/rust, +/area/station/medical/chemistry/minisat) "gQN" = ( /obj/effect/turf_decal/stripes/line, /obj/effect/turf_decal/tile/purple/half/contrasted, @@ -19841,6 +19788,11 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, /area/station/security/checkpoint/science) +"gZF" = ( +/obj/effect/turf_decal/sand/plating, +/obj/machinery/portable_atmospherics/canister, +/turf/open/floor/plating, +/area/station/maintenance/department/science) "gZI" = ( /obj/structure/dresser, /obj/machinery/airalarm/directional/west, @@ -20311,6 +20263,17 @@ /obj/structure/lattice, /turf/open/misc/asteroid/airless, /area/space/nearstation) +"hhd" = ( +/obj/machinery/door/poddoor/shutters{ + id = "ordauxgarage"; + dir = 1 + }, +/obj/effect/turf_decal/sand/plating, +/obj/effect/turf_decal/stripes/asteroid/end{ + dir = 8 + }, +/turf/open/floor/plating, +/area/station/science/ordnance) "hhC" = ( /obj/structure/railing{ dir = 5 @@ -20470,14 +20433,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/wood, /area/station/service/library) -"hld" = ( -/obj/structure/cable, -/obj/machinery/firealarm/directional/east, -/obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/lab) "hle" = ( /obj/machinery/light/directional/south, /obj/structure/table/glass, @@ -20521,16 +20476,6 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /turf/open/floor/iron, /area/station/hallway/primary/central) -"hmd" = ( -/obj/effect/turf_decal/tile/neutral/opposingcorners{ - dir = 1 - }, -/obj/effect/turf_decal/siding/purple{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron/dark, -/area/station/command/heads_quarters/rd) "hmg" = ( /obj/machinery/requests_console/directional/north{ name = "Bar Requests Console"; @@ -21064,16 +21009,6 @@ }, /turf/open/floor/iron, /area/station/security) -"htn" = ( -/obj/machinery/door/airlock/research{ - glass = 1; - name = "Slime Euthanization Chamber"; - opacity = 0 - }, -/obj/effect/turf_decal/tile/blue/fourcorners, -/obj/effect/mapping_helpers/airlock/access/all/science/xenobio, -/turf/open/floor/glass/reinforced, -/area/station/science/xenobiology) "htw" = ( /obj/effect/spawner/random/structure/closet_empty/crate, /obj/effect/spawner/random/maintenance, @@ -21340,6 +21275,12 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron/white, /area/station/medical/storage) +"hyL" = ( +/obj/structure/cable, +/obj/structure/disposalpipe/segment, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/plating, +/area/station/maintenance/department/medical) "hyM" = ( /obj/structure/closet, /obj/item/food/grown/banana, @@ -21511,16 +21452,6 @@ /obj/structure/cable, /turf/open/floor/circuit, /area/station/hallway/primary/central) -"hCB" = ( -/obj/machinery/door/firedoor/heavy, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/machinery/door/airlock/research{ - name = "Ordnance Auxiliary Storage" - }, -/obj/effect/mapping_helpers/airlock/access/all/science/ordnance, -/obj/effect/decal/cleanable/dirt/dust, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "hCJ" = ( /obj/structure/railing{ dir = 8 @@ -21633,15 +21564,6 @@ /obj/effect/landmark/start/mime, /turf/open/floor/carpet, /area/station/service/theater) -"hEw" = ( -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/lab) "hED" = ( /turf/closed/wall/r_wall, /area/station/ai_monitored/security/armory) @@ -21676,6 +21598,14 @@ /obj/machinery/atmospherics/components/tank/plasma, /turf/open/misc/asteroid, /area/station/maintenance/disposal/incinerator) +"hFz" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/structure/cable, +/obj/machinery/light/directional/east, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "hFA" = ( /obj/machinery/light/small/directional/south, /obj/effect/turf_decal/stripes/asteroid/line{ @@ -21987,6 +21917,19 @@ /obj/structure/cable, /turf/open/floor/iron/dark, /area/station/security/execution/education) +"hMf" = ( +/obj/machinery/door/poddoor/shutters/window/preopen{ + name = "Security Shutters"; + id = "xbprotect1"; + dir = 8 + }, +/obj/structure/cable, +/obj/machinery/door/firedoor, +/obj/machinery/firealarm/directional/south, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "hME" = ( /turf/closed/wall, /area/station/security/prison/work) @@ -22020,13 +21963,6 @@ }, /turf/open/floor/iron, /area/station/commons/storage/art) -"hNI" = ( -/obj/machinery/light/directional/north, -/obj/machinery/atmospherics/components/trinary/mixer{ - dir = 4 - }, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "hNN" = ( /obj/effect/turf_decal/trimline/yellow/filled/line{ dir = 8 @@ -22121,15 +22057,6 @@ /obj/machinery/light_switch/directional/north, /turf/open/floor/iron, /area/station/service/hydroponics) -"hPn" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/effect/decal/cleanable/dirt/dust, -/obj/machinery/light/small/directional/south, -/obj/machinery/portable_atmospherics/canister, -/turf/open/floor/iron/dark/smooth_large, -/area/station/science/ordnance) "hPp" = ( /obj/structure/table/glass, /obj/effect/turf_decal/tile/blue/fourcorners, @@ -22399,6 +22326,9 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/carpet/red, /area/station/command/heads_quarters/qm) +"hSB" = ( +/turf/open/floor/catwalk_floor/iron_white, +/area/station/medical/treatment_center) "hSC" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/cable, @@ -22451,10 +22381,6 @@ /obj/structure/extinguisher_cabinet/directional/south, /turf/open/floor/iron/white, /area/station/medical/paramedic) -"hTv" = ( -/obj/structure/railing/corner, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "hTQ" = ( /obj/machinery/atmospherics/components/unary/passive_vent{ dir = 1; @@ -22568,6 +22494,15 @@ "hVB" = ( /turf/open/floor/plating, /area/station/engineering/supermatter/room) +"hVC" = ( +/obj/machinery/atmospherics/pipe/smart/simple/dark/visible{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "hVL" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 8 @@ -22590,11 +22525,6 @@ /obj/machinery/telecomms/hub/preset, /turf/open/floor/circuit/green/telecomms/mainframe, /area/station/tcommsat/server) -"hWl" = ( -/obj/effect/turf_decal/sand/plating, -/obj/structure/broken_flooring/pile, -/turf/open/floor/plating, -/area/station/science/ordnance) "hWt" = ( /obj/effect/turf_decal/box/corners{ dir = 8 @@ -22719,6 +22649,15 @@ /obj/structure/cable, /turf/open/floor/iron/textured_large, /area/station/engineering/storage/tech) +"hYG" = ( +/obj/machinery/atmospherics/pipe/smart/manifold/yellow/visible{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "hYP" = ( /obj/machinery/modular_computer/preset/id{ dir = 1 @@ -22965,6 +22904,11 @@ /obj/effect/turf_decal/sand/plating, /turf/open/floor/plating, /area/station/cargo/miningoffice) +"ief" = ( +/obj/machinery/airalarm/directional/west, +/obj/machinery/portable_atmospherics/canister/oxygen, +/turf/open/floor/iron/white/smooth_large, +/area/station/science/ordnance/storage) "iej" = ( /obj/effect/turf_decal/siding/white{ dir = 1 @@ -23032,14 +22976,6 @@ }, /turf/open/floor/iron/white, /area/station/hallway/secondary/entry) -"ieU" = ( -/obj/structure/cable, -/obj/effect/turf_decal/siding/purple/corner{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "ifc" = ( /obj/effect/turf_decal/trimline/yellow/filled/line, /obj/machinery/firealarm/directional/south, @@ -23056,6 +22992,18 @@ /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, /area/station/medical/storage) +"ifv" = ( +/obj/machinery/atmospherics/components/trinary/mixer{ + dir = 4 + }, +/obj/machinery/camera/autoname/directional/north{ + network = list("ss13","rd") + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "ifE" = ( /obj/machinery/vending/medical, /obj/effect/turf_decal/tile/blue/fourcorners, @@ -23282,11 +23230,6 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating/reinforced, /area/station/maintenance/port/greater) -"ikJ" = ( -/obj/effect/turf_decal/stripes/corner, -/obj/structure/closet/firecloset, -/turf/open/floor/iron/dark/smooth_large, -/area/station/science/ordnance) "ilb" = ( /obj/effect/turf_decal/tile/red/diagonal_edge, /turf/open/floor/iron/dark, @@ -23452,18 +23395,6 @@ }, /turf/open/floor/iron/white, /area/station/medical/treatment_center) -"ioh" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/duct, -/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/hidden, -/obj/effect/turf_decal/tile/blue/fourcorners, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/medical/treatment_center) "iol" = ( /turf/closed/wall/r_wall, /area/station/service/lawoffice) @@ -23487,11 +23418,6 @@ }, /turf/open/floor/iron, /area/station/hallway/secondary/command) -"ioL" = ( -/obj/item/radio/intercom/directional/east, -/obj/machinery/portable_atmospherics/canister/oxygen, -/turf/open/floor/iron/white, -/area/station/science/ordnance/storage) "ioP" = ( /obj/structure/cable/multilayer/multiz, /obj/effect/decal/cleanable/dirt, @@ -23743,6 +23669,10 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron, /area/station/security/office) +"isy" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/hidden, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/medical/treatment_center) "isH" = ( /obj/effect/decal/cleanable/dirt, /obj/structure/disposalpipe/segment{ @@ -23869,14 +23799,6 @@ "ivx" = ( /turf/open/floor/glass/reinforced/airless, /area/station/asteroid) -"ivy" = ( -/obj/machinery/atmospherics/components/unary/portables_connector/visible{ - dir = 8 - }, -/obj/effect/turf_decal/box/red, -/obj/item/radio/intercom/directional/south, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "ivC" = ( /obj/machinery/camera/autoname/directional/north{ network = list("ss13","engine") @@ -24517,11 +24439,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/asteroid) -"iHV" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/cable, -/turf/open/floor/iron/dark, -/area/station/command/heads_quarters/rd) "iHY" = ( /obj/structure/sign/warning/explosives/directional/east, /obj/effect/turf_decal/siding/purple/corner{ @@ -24860,21 +24777,6 @@ /obj/structure/sign/poster/official/random/directional/east, /turf/open/floor/iron, /area/station/hallway/primary/starboard) -"iOk" = ( -/obj/machinery/door/airlock/research{ - autoclose = 0; - frequency = 1449; - id_tag = "xeno_airlock_interior"; - name = "Xenobiology Lab Internal Airlock" - }, -/obj/effect/mapping_helpers/airlock/locked, -/obj/structure/cable, -/obj/effect/mapping_helpers/airlock/access/all/science/xenobio, -/obj/machinery/door/firedoor, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "iOE" = ( /obj/item/pickaxe/mini, /turf/open/misc/asteroid, @@ -24907,6 +24809,17 @@ /obj/machinery/firealarm/directional/north, /turf/open/floor/carpet/executive, /area/station/command/corporate_showroom) +"iPf" = ( +/obj/structure/cable, +/obj/machinery/button/door/directional/east{ + name = "shutter control"; + id = "xbprotect1" + }, +/obj/structure/window/reinforced/spawner/directional/north, +/obj/item/kirbyplants/random, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "iPm" = ( /obj/structure/rack, /obj/effect/turf_decal/trimline/yellow/filled/line, @@ -24967,16 +24880,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/dark, /area/station/command/corporate_showroom) -"iQo" = ( -/obj/structure/table, -/obj/machinery/reagentgrinder{ - pixel_y = 8 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/turf/open/floor/iron/white/textured_large, -/area/station/science/xenobiology) "iQt" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/effect/spawner/random/trash/food_packaging, @@ -25019,6 +24922,14 @@ /obj/item/newspaper, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat/foyer) +"iRy" = ( +/obj/machinery/door/airlock/command{ + name = "Research Director's Observatory" + }, +/obj/effect/mapping_helpers/airlock/access/all/science/rd, +/obj/machinery/door/firedoor, +/turf/open/floor/plating, +/area/station/command/heads_quarters/rd) "iRB" = ( /obj/effect/turf_decal/tile/dark_blue/half/contrasted{ dir = 1 @@ -25270,12 +25181,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/white, /area/station/medical/chemistry/minisat) -"iXB" = ( -/obj/structure/cable, -/obj/effect/turf_decal/siding/purple, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "iXR" = ( /obj/structure/cable, /turf/open/floor/plating, @@ -25590,13 +25495,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/cargo/storage) -"jej" = ( -/obj/structure/cable, -/obj/effect/turf_decal/siding/purple{ - dir = 1 - }, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "jer" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /obj/effect/landmark/event_spawn, @@ -25621,15 +25519,6 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/iron/dark, /area/station/ai_monitored/command/storage/eva) -"jeV" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/turf_decal/trimline/yellow/filled/corner{ - dir = 8 - }, -/turf/open/floor/iron/white, -/area/station/medical/chemistry) "jeY" = ( /obj/structure/railing/corner{ dir = 1 @@ -25661,6 +25550,16 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, /area/station/engineering/atmospherics_engine) +"jfq" = ( +/obj/structure/table, +/obj/effect/turf_decal/trimline/yellow/filled/line{ + dir = 5 + }, +/obj/machinery/camera/autoname/directional/north{ + network = list("ss13","medbay") + }, +/turf/open/floor/iron/white, +/area/station/medical/chemistry) "jfr" = ( /obj/effect/spawner/random/trash/garbage{ spawn_loot_count = 3; @@ -25858,14 +25757,6 @@ /obj/docking_port/stationary/syndicate, /turf/open/space/openspace, /area/space) -"jiP" = ( -/obj/effect/turf_decal/sand/plating, -/obj/structure/disposalpipe/segment{ - dir = 5 - }, -/obj/item/pickaxe, -/turf/open/floor/plating, -/area/station/asteroid) "jjp" = ( /obj/item/reagent_containers/cup/bottle/fake_gbs, /turf/closed/mineral/random/stationside/asteroid/porus{ @@ -26414,6 +26305,12 @@ /obj/structure/reagent_dispensers/watertank, /turf/open/floor/plating, /area/station/maintenance/port/lesser) +"jsf" = ( +/obj/structure/sign/warning/chem_diamond/directional/south, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/spawner/random/structure/girder, +/turf/open/floor/plating, +/area/station/maintenance/department/medical) "jsn" = ( /obj/effect/turf_decal/stripes/corner, /obj/effect/decal/cleanable/dirt/dust, @@ -26458,14 +26355,6 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, /area/station/maintenance/disposal) -"jtp" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 4 - }, -/obj/effect/decal/cleanable/dirt/dust, -/obj/machinery/portable_atmospherics/canister, -/turf/open/floor/iron/dark/smooth_large, -/area/station/science/ordnance) "jtv" = ( /obj/structure/chair/plastic, /obj/effect/decal/cleanable/dirt/dust, @@ -26559,15 +26448,6 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /turf/open/floor/iron, /area/station/engineering/atmos/upper) -"jvp" = ( -/obj/structure/window/spawner/directional/east, -/obj/machinery/power/apc/auto_name/directional/south{ - areastring = "/area/station/science/ordnance/burnchamber" - }, -/obj/structure/cable, -/obj/machinery/portable_atmospherics/pump, -/turf/open/floor/iron/dark/smooth_large, -/area/station/science/ordnance) "jvt" = ( /obj/structure/closet/secure_closet/chemical, /obj/effect/turf_decal/stripes/line{ @@ -27042,6 +26922,12 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/wood, /area/station/medical/psychology) +"jCP" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/hallway/secondary/entry) "jCT" = ( /obj/structure/cable, /obj/effect/turf_decal/siding/purple{ @@ -27189,17 +27075,6 @@ }, /turf/open/floor/engine, /area/station/medical/chemistry) -"jEw" = ( -/obj/effect/mapping_helpers/broken_floor, -/obj/structure/closet/crate/science{ - opened = 1; - icon_state = "scicrateopen" - }, -/obj/item/tank, -/obj/effect/decal/cleanable/dirt/dust, -/obj/effect/turf_decal/stripes/line, -/turf/open/floor/iron/dark/smooth_large, -/area/station/science/ordnance) "jED" = ( /obj/machinery/camera/autoname/directional/east, /turf/open/floor/iron/freezer, @@ -27638,6 +27513,13 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/cargo/warehouse/upper) +"jLY" = ( +/obj/machinery/atmospherics/pipe/smart/simple/yellow/visible{ + dir = 1 + }, +/obj/machinery/meter, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "jMa" = ( /obj/machinery/light/dim/directional/south, /obj/machinery/atmospherics/pipe/smart/simple/scrubbers/visible{ @@ -28325,6 +28207,12 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/station/maintenance/department/cargo) +"jZv" = ( +/obj/machinery/power/apc/auto_name/directional/west, +/obj/structure/cable, +/obj/machinery/portable_atmospherics/canister/oxygen, +/turf/open/floor/iron/white/smooth_large, +/area/station/science/ordnance/storage) "jZx" = ( /obj/structure/closet/emcloset, /turf/open/floor/iron/textured, @@ -28429,9 +28317,6 @@ }, /turf/open/floor/iron, /area/station/security/breakroom) -"kbc" = ( -/turf/open/floor/iron/dark, -/area/station/command/heads_quarters/rd) "kbg" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, @@ -28679,19 +28564,6 @@ /obj/effect/turf_decal/tile/blue/opposingcorners, /turf/open/floor/iron, /area/station/service/hydroponics) -"keb" = ( -/obj/machinery/door/firedoor, -/obj/machinery/door/airlock/research/glass{ - name = "Secure Pen" - }, -/obj/effect/mapping_helpers/airlock/access/all/science/xenobio, -/obj/structure/cable, -/obj/machinery/door/poddoor/preopen{ - id = "Xenolab"; - name = "Test Chamber Blast Door" - }, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "ked" = ( /obj/structure/cable, /turf/open/floor/wood, @@ -29561,10 +29433,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/engineering/atmos) -"krO" = ( -/obj/structure/cable, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "krP" = ( /turf/closed/wall/r_wall, /area/station/command/teleporter) @@ -29688,6 +29556,14 @@ }, /turf/open/floor/iron, /area/station/engineering/main) +"ktI" = ( +/obj/machinery/light/dim/directional/east, +/obj/effect/turf_decal/tile/dark_blue/half/contrasted{ + dir = 4 + }, +/obj/structure/fireaxecabinet/directional/east, +/turf/open/floor/iron, +/area/station/command/bridge) "ktL" = ( /turf/open/floor/iron, /area/station/engineering/atmos/upper) @@ -29732,6 +29608,10 @@ }, /turf/open/floor/plating, /area/station/science/genetics) +"kvd" = ( +/obj/structure/lattice/catwalk, +/turf/open/openspace/xenobio, +/area/station/science/xenobiology) "kvj" = ( /obj/machinery/light/directional/north, /obj/structure/table, @@ -29765,6 +29645,10 @@ /obj/item/reagent_containers/cup/rag, /turf/open/floor/plating, /area/station/maintenance/central/greater) +"kvW" = ( +/obj/effect/turf_decal/tile/blue/fourcorners, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/medical/treatment_center) "kvX" = ( /obj/effect/turf_decal/sand/plating, /obj/effect/spawner/random/trash/mess, @@ -30058,14 +29942,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/plating, /area/station/maintenance/port/lesser) -"kAI" = ( -/obj/machinery/door/airlock/maintenance_hatch, -/obj/effect/mapping_helpers/airlock/access/all/science/ordnance, -/obj/machinery/atmospherics/pipe/smart/simple/green/visible{ - dir = 1 - }, -/turf/open/floor/plating, -/area/station/science/ordnance/testlab) "kAW" = ( /obj/effect/mapping_helpers/broken_floor, /obj/effect/decal/cleanable/dirt/dust, @@ -30168,16 +30044,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/dark, /area/station/service/chapel/funeral) -"kCh" = ( -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment{ - dir = 9 - }, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "kCn" = ( /obj/effect/turf_decal/trimline/yellow/filled/line{ dir = 1 @@ -30333,16 +30199,6 @@ }, /turf/open/floor/iron/freezer, /area/station/commons/toilet/restrooms) -"kEM" = ( -/obj/effect/turf_decal/box/corners{ - dir = 4 - }, -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "kFi" = ( /obj/effect/turf_decal/tile/neutral{ dir = 8 @@ -30609,6 +30465,15 @@ /obj/effect/spawner/random/decoration/statue, /turf/open/floor/plating/airless, /area/space/nearstation) +"kJW" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/turf/open/floor/plating, +/area/station/maintenance/department/medical) "kKc" = ( /obj/structure/cable, /obj/effect/turf_decal/trimline/blue/filled/line{ @@ -30692,6 +30557,16 @@ luminosity = 2 }, /area/station/science/ordnance/bomb) +"kMl" = ( +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/components/unary/portables_connector/visible{ + dir = 1 + }, +/obj/effect/turf_decal/box/red, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "kMr" = ( /obj/structure/transport/linear/public, /obj/machinery/elevator_control_panel/directional/north{ @@ -31000,16 +30875,6 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron, /area/station/construction/mining/aux_base) -"kSc" = ( -/obj/structure/table, -/obj/effect/turf_decal/trimline/yellow/filled/line{ - dir = 5 - }, -/obj/machinery/camera/autoname/directional/north{ - network = list("ss13","medbay") - }, -/turf/open/floor/iron/white, -/area/station/medical/chemistry) "kSm" = ( /obj/machinery/computer/libraryconsole/bookmanagement, /obj/structure/table, @@ -31223,15 +31088,6 @@ "kUX" = ( /turf/closed/wall/r_wall, /area/station/engineering/atmospherics_engine) -"kVh" = ( -/obj/structure/closet/crate/freezer, -/obj/item/food/icecreamsandwich, -/obj/effect/turf_decal/trimline/yellow/filled/line{ - dir = 9 - }, -/obj/structure/sign/departments/chemistry/directional/west, -/turf/open/floor/iron/white, -/area/station/medical/chemistry) "kVF" = ( /obj/effect/turf_decal/siding/wood{ dir = 4 @@ -31411,20 +31267,6 @@ /obj/structure/sign/poster/official/random/directional/west, /turf/open/floor/iron, /area/station/hallway/primary/central) -"kZf" = ( -/obj/structure/table/reinforced, -/obj/item/stack/sheet/plasteel{ - amount = 15 - }, -/obj/item/assembly/prox_sensor{ - pixel_x = 5; - pixel_y = 7 - }, -/obj/structure/fireaxecabinet/mechremoval/directional/east, -/obj/item/stack/sheet/glass/fifty, -/obj/item/stack/sheet/iron/fifty, -/turf/open/floor/iron/dark/textured, -/area/station/science/robotics/lab) "kZg" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -31483,6 +31325,16 @@ /obj/machinery/door/firedoor, /turf/open/floor/iron, /area/station/service/hydroponics) +"kZW" = ( +/obj/machinery/door/airlock/research{ + glass = 1; + name = "Slime Euthanization Chamber"; + opacity = 0 + }, +/obj/effect/turf_decal/tile/blue/fourcorners, +/obj/effect/mapping_helpers/airlock/access/all/science/xenobio, +/turf/open/floor/glass/reinforced, +/area/station/science/xenobiology) "laf" = ( /obj/effect/spawner/random/structure/chair_comfy{ dir = 4 @@ -31519,6 +31371,11 @@ /obj/effect/landmark/start/lawyer, /turf/open/floor/iron/dark, /area/station/security/office) +"laD" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "laF" = ( /obj/structure/closet{ name = "evidence closet 1" @@ -31605,21 +31462,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/dark, /area/station/science/ordnance) -"lcj" = ( -/obj/item/stack/sheet/glass, -/obj/item/stack/sheet/iron/fifty, -/obj/item/clothing/glasses/welding, -/obj/item/disk/tech_disk{ - pixel_y = 6 - }, -/obj/item/reagent_containers/dropper, -/obj/structure/table, -/obj/machinery/requests_console/auto_name/directional/north, -/obj/effect/mapping_helpers/requests_console/supplies, -/obj/effect/mapping_helpers/requests_console/ore_update, -/obj/effect/mapping_helpers/requests_console/assistance, -/turf/open/floor/iron/white, -/area/station/science/lab) "lcv" = ( /obj/machinery/camera/autoname/directional/south, /turf/open/floor/glass/reinforced, @@ -31636,6 +31478,23 @@ /obj/effect/decal/cleanable/cobweb/cobweb2, /turf/open/floor/plating, /area/station/science/xenobiology) +"ldf" = ( +/obj/machinery/door/airlock/research/glass{ + name = "Chemistry Minisat" + }, +/obj/effect/mapping_helpers/airlock/access/all/medical/chemistry, +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/effect/turf_decal/trimline/yellow/filled/line, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 8 + }, +/turf/open/floor/iron/white, +/area/station/medical/chemistry/minisat) "ldo" = ( /obj/effect/turf_decal/sand/plating, /obj/effect/turf_decal/stripes/asteroid/line{ @@ -31677,12 +31536,6 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos/pumproom) -"leZ" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/hallway/secondary/entry) "lfd" = ( /obj/machinery/door/airlock/external/glass, /obj/effect/mapping_helpers/airlock/access/all/engineering/external, @@ -32409,10 +32262,6 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, /area/station/maintenance/department/medical/central) -"luh" = ( -/obj/machinery/light/small/directional/north, -/turf/open/floor/engine/o2, -/area/station/science/ordnance) "luq" = ( /obj/effect/turf_decal/stripes{ dir = 4 @@ -32796,6 +32645,12 @@ }, /turf/open/floor/iron/white/textured_large, /area/station/maintenance/department/medical/central) +"lAt" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "lAy" = ( /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron, @@ -32856,11 +32711,6 @@ /obj/structure/chair/sofa/bench/left, /turf/open/floor/iron/white/textured_large, /area/station/science/research) -"lBZ" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "lCk" = ( /obj/effect/turf_decal/siding/dark_blue{ dir = 1 @@ -32920,18 +32770,6 @@ /obj/effect/spawner/random/maintenance/two, /turf/open/floor/iron, /area/station/maintenance/central/greater) -"lCS" = ( -/obj/structure/table, -/obj/item/paper_bin{ - pixel_x = -5; - pixel_y = 6 - }, -/obj/item/pen{ - pixel_x = 9; - pixel_y = 4 - }, -/turf/open/floor/glass/reinforced, -/area/station/science/xenobiology) "lCY" = ( /obj/effect/spawner/random/maintenance/two, /obj/effect/spawner/random/structure/closet_empty/crate, @@ -33081,14 +32919,6 @@ "lFG" = ( /turf/open/floor/glass, /area/station/command/meeting_room) -"lFI" = ( -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/item/radio/intercom/directional/north, -/obj/machinery/light_switch/directional/east, -/obj/machinery/disposal/bin, -/obj/structure/disposalpipe/trunk, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "lFJ" = ( /obj/effect/decal/cleanable/blood/old, /obj/item/flashlight/flare/candle, @@ -33290,6 +33120,17 @@ /obj/machinery/vending/boozeomat/all_access, /turf/open/floor/plating, /area/station/maintenance/central/greater) +"lJo" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/duct, +/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/hidden, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/medical/treatment_center) "lJq" = ( /obj/effect/spawner/structure/window/reinforced, /turf/open/floor/plating, @@ -33444,6 +33285,16 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/carpet/blue, /area/station/command/heads_quarters/cmo) +"lMC" = ( +/obj/machinery/meter, +/obj/machinery/atmospherics/pipe/smart/simple/dark/visible{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "lMI" = ( /obj/effect/spawner/random/structure/closet_maintenance, /turf/open/floor/plating, @@ -33850,13 +33701,6 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/plating, /area/station/maintenance/department/bridge) -"lUy" = ( -/obj/structure/cable, -/obj/effect/landmark/navigate_destination/dockarrival, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/hallway/secondary/entry) "lUF" = ( /obj/structure/transport/linear/public, /obj/machinery/elevator_control_panel{ @@ -34391,6 +34235,16 @@ /obj/machinery/light/dim/directional/south, /turf/open/floor/wood, /area/station/service/library) +"mfw" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/turf_decal/trimline/yellow/filled/line, +/obj/effect/turf_decal/trimline/yellow/filled/corner{ + dir = 1 + }, +/turf/open/floor/iron/white, +/area/station/medical/chemistry) "mfA" = ( /obj/machinery/exoscanner, /obj/effect/turf_decal/siding/wideplating_new/dark/end{ @@ -34402,6 +34256,13 @@ /obj/effect/baseturf_helper/reinforced_plating/ceiling, /turf/open/floor/iron/dark, /area/station/science/ordnance) +"mfP" = ( +/obj/machinery/atmospherics/components/tank/air/layer4, +/obj/effect/turf_decal/tile/green/half/contrasted{ + dir = 1 + }, +/turf/open/floor/iron/white, +/area/station/medical/virology) "mgn" = ( /obj/docking_port/stationary{ dir = 8; @@ -34584,15 +34445,20 @@ }, /turf/open/floor/engine/vacuum, /area/station/science/ordnance/burnchamber) -"miR" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/disposalpipe/segment{ - dir = 9 +"miU" = ( +/obj/structure/table/reinforced, +/obj/item/stack/sheet/plasteel{ + amount = 15 }, -/turf/open/floor/plating, -/area/station/maintenance/department/medical) +/obj/item/assembly/prox_sensor{ + pixel_x = 5; + pixel_y = 7 + }, +/obj/structure/fireaxecabinet/mechremoval/directional/east, +/obj/item/stack/sheet/glass/fifty, +/obj/item/stack/sheet/iron/fifty, +/turf/open/floor/iron/dark/textured, +/area/station/science/robotics/lab) "miV" = ( /obj/effect/spawner/random/trash/mess, /turf/open/floor/plating, @@ -34647,6 +34513,24 @@ /obj/effect/landmark/blobstart, /turf/open/floor/iron, /area/station/engineering/atmos) +"mjU" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/disposalpipe/segment, +/obj/machinery/door/airlock/maintenance_hatch, +/obj/effect/mapping_helpers/airlock/access/any/medical/maintenance, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 1 + }, +/turf/open/floor/plating, +/area/station/maintenance/department/medical) +"mjY" = ( +/obj/structure/cable, +/obj/effect/turf_decal/siding/purple, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "mjZ" = ( /obj/machinery/atmospherics/components/binary/pump, /turf/open/floor/iron, @@ -34702,6 +34586,11 @@ /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, /turf/open/floor/iron, /area/station/command/gateway) +"mkV" = ( +/obj/machinery/power/apc/auto_name/directional/west, +/obj/structure/cable, +/turf/open/floor/iron/white, +/area/station/science/ordnance/testlab) "mkX" = ( /obj/structure/lattice/catwalk, /obj/structure/railing{ @@ -35011,20 +34900,15 @@ /obj/effect/spawner/random/structure/steam_vent, /turf/open/floor/plating, /area/station/maintenance/central/greater) -"mqb" = ( -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) -"mqn" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 5 +"mqc" = ( +/obj/structure/closet/crate/freezer, +/obj/item/food/icecreamsandwich, +/obj/effect/turf_decal/trimline/yellow/filled/line{ + dir = 9 }, -/obj/structure/cable, +/obj/structure/sign/departments/chemistry/directional/west, /turf/open/floor/iron/white, -/area/station/science/ordnance/storage) +/area/station/medical/chemistry) "mqz" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/power/apc/auto_name/directional/east, @@ -35589,6 +35473,15 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, /area/station/maintenance/department/engine) +"mAC" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/machinery/camera/autoname/directional/north{ + network = list("ss13","rd") + }, +/obj/machinery/disposal/bin, +/obj/structure/disposalpipe/trunk, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "mAF" = ( /obj/effect/turf_decal/sand/plating, /obj/effect/mapping_helpers/airlock/access/all/engineering/general, @@ -36069,6 +35962,15 @@ /obj/machinery/atmospherics/pipe/layer_manifold/yellow/visible, /turf/open/floor/plating, /area/station/engineering/atmos) +"mJD" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/effect/turf_decal/trimline/yellow/filled/corner{ + dir = 8 + }, +/turf/open/floor/iron/white, +/area/station/medical/chemistry) "mJG" = ( /obj/structure/cable, /obj/structure/disposalpipe/segment{ @@ -36246,6 +36148,14 @@ /obj/effect/spawner/random/trash/food_packaging, /turf/open/floor/iron, /area/station/hallway/primary/central) +"mMe" = ( +/obj/structure/cable, +/obj/effect/turf_decal/siding/purple/corner{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "mMp" = ( /obj/machinery/door/airlock/highsecurity, /obj/effect/mapping_helpers/airlock/autoname, @@ -36487,17 +36397,6 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/wood, /area/station/commons/lounge) -"mRC" = ( -/obj/structure/cable, -/obj/machinery/door/airlock/maintenance_hatch{ - name = "Xenobiology Maintenance" - }, -/obj/effect/mapping_helpers/airlock/access/all/science/xenobio, -/obj/structure/disposalpipe/segment, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "mRI" = ( /obj/effect/mob_spawn/corpse/human/clown, /turf/open/misc/asteroid, @@ -36506,6 +36405,16 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron, /area/station/engineering/main) +"mSe" = ( +/obj/machinery/atmospherics/pipe/smart/simple/dark/visible{ + dir = 10 + }, +/obj/structure/railing/corner, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "mSf" = ( /obj/machinery/mass_driver{ dir = 1; @@ -36521,14 +36430,6 @@ /obj/item/clothing/head/fedora, /turf/open/floor/wood, /area/station/commons/lounge) -"mSG" = ( -/obj/machinery/atmospherics/pipe/smart/simple/yellow/visible{ - dir = 1 - }, -/obj/machinery/meter, -/obj/structure/cable, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "mSK" = ( /turf/open/floor/iron/white, /area/station/commons/fitness/recreation) @@ -36544,6 +36445,18 @@ }, /turf/open/floor/engine, /area/station/science/explab) +"mTg" = ( +/obj/effect/turf_decal/caution/stand_clear/red, +/obj/effect/turf_decal/stripes/line, +/obj/machinery/door/poddoor/shutters/window/preopen{ + id = "ordstorage" + }, +/obj/structure/cable, +/obj/effect/turf_decal/stripes/corner{ + dir = 1 + }, +/turf/open/floor/iron/white, +/area/station/science/ordnance/storage) "mTs" = ( /obj/machinery/holopad, /obj/effect/landmark/event_spawn, @@ -36599,6 +36512,18 @@ "mUs" = ( /turf/open/floor/iron/white, /area/station/medical/storage) +"mUA" = ( +/obj/machinery/light/small/dim/directional/west, +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/turf_decal/trimline/yellow/filled/corner{ + dir = 8 + }, +/obj/structure/chair{ + dir = 4 + }, +/turf/open/floor/iron/white, +/area/station/maintenance/department/medical) "mUC" = ( /obj/effect/turf_decal/trimline/yellow/filled/line{ dir = 1 @@ -36807,19 +36732,6 @@ }, /turf/open/floor/carpet/red, /area/station/command/heads_quarters/qm) -"mYh" = ( -/obj/machinery/door/poddoor/shutters/window/preopen{ - name = "Security Shutters"; - id = "xbprotect1"; - dir = 8 - }, -/obj/structure/cable, -/obj/machinery/door/firedoor, -/obj/machinery/firealarm/directional/south, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "mYs" = ( /obj/machinery/door/airlock/public/glass{ name = "Gateway Chamber" @@ -37148,6 +37060,11 @@ }, /turf/closed/wall, /area/station/service/bar) +"ndE" = ( +/obj/machinery/door/airlock/maintenance_hatch, +/obj/effect/mapping_helpers/airlock/access/all/science/ordnance, +/turf/open/floor/plating, +/area/station/science/ordnance/testlab) "ndI" = ( /obj/structure/table, /obj/item/hand_labeler, @@ -37193,6 +37110,20 @@ /obj/machinery/digital_clock/directional/west, /turf/open/floor/iron/white, /area/station/medical/paramedic) +"neb" = ( +/obj/structure/table, +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/item/pipe_dispenser{ + pixel_x = 3; + pixel_y = 7 + }, +/obj/item/pipe_dispenser, +/obj/machinery/power/apc/auto_name/directional/south{ + areastring = "/area/station/science/ordnance/burnchamber" + }, +/obj/structure/cable, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "nee" = ( /turf/open/floor/iron/dark/corner{ dir = 4 @@ -37636,12 +37567,6 @@ /obj/structure/disposalpipe/segment, /turf/open/floor/iron/white, /area/station/medical/medbay/central) -"nlx" = ( -/obj/structure/cable, -/obj/structure/disposalpipe/segment, -/obj/effect/decal/cleanable/dirt/dust, -/turf/open/floor/plating, -/area/station/maintenance/department/medical) "nlI" = ( /obj/effect/landmark/start/depsec/engineering, /obj/effect/turf_decal/trimline/red/filled/line{ @@ -37915,6 +37840,12 @@ }, /turf/open/floor/iron/white, /area/station/security/medical) +"nqi" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "nql" = ( /obj/effect/turf_decal/tile/red{ dir = 1 @@ -38473,6 +38404,9 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat/foyer) +"nCm" = ( +/turf/open/openspace/xenobio, +/area/station/science/xenobiology) "nCo" = ( /obj/machinery/atmospherics/pipe/smart/simple/dark/visible, /obj/structure/cable, @@ -38656,13 +38590,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/security/detectives_office) -"nGb" = ( -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/structure/table, -/obj/item/holosign_creator/atmos, -/obj/machinery/light/directional/east, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "nGd" = ( /obj/effect/turf_decal/tile/red/half/contrasted{ dir = 4 @@ -38690,6 +38617,16 @@ }, /turf/open/floor/iron, /area/station/security/prison) +"nGV" = ( +/obj/machinery/atmospherics/pipe/smart/manifold/purple/visible{ + dir = 8 + }, +/obj/structure/disposalpipe/trunk/multiz{ + dir = 1 + }, +/obj/item/radio/intercom/directional/west, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "nHj" = ( /obj/structure/cable, /turf/open/floor/catwalk_floor/iron, @@ -38735,17 +38672,6 @@ /obj/machinery/camera/autoname/directional/south, /turf/open/floor/iron, /area/station/hallway/primary/fore) -"nIa" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/duct, -/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/hidden, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/medical/treatment_center) "nIb" = ( /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, @@ -38794,6 +38720,14 @@ }, /turf/open/floor/wood/parquet, /area/station/cargo/boutique) +"nJD" = ( +/obj/structure/cable, +/obj/effect/turf_decal/sand/plating, +/obj/structure/disposalpipe/segment, +/obj/machinery/door/airlock/maintenance_hatch, +/obj/effect/mapping_helpers/airlock/access/any/medical/maintenance, +/turf/open/floor/plating, +/area/station/asteroid) "nJF" = ( /obj/structure/table/reinforced, /obj/machinery/door/window/left/directional/east{ @@ -39074,13 +39008,6 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/engine, /area/station/engineering/atmospherics_engine) -"nNF" = ( -/obj/machinery/power/apc/auto_name/directional/west, -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron/white, -/area/station/science/ordnance/testlab) "nNK" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 1 @@ -39133,6 +39060,10 @@ /obj/effect/turf_decal/tile/dark_blue, /turf/open/floor/iron, /area/station/command/bridge) +"nPw" = ( +/obj/structure/water_source/puddle, +/turf/open/floor/grass, +/area/station/security/prison/garden) "nPM" = ( /obj/effect/turf_decal/trimline/yellow/filled/line{ dir = 4 @@ -39287,13 +39218,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/hallway/primary/central) -"nTZ" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ - dir = 8 - }, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "nUi" = ( /obj/structure/table/reinforced/rglass, /obj/item/clipboard, @@ -39307,17 +39231,6 @@ /obj/item/emergency_bed, /turf/open/floor/iron/white, /area/station/maintenance/aft/upper) -"nUN" = ( -/obj/machinery/camera/autoname/directional/north{ - network = list("ss13","rd") - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/components/trinary/mixer{ - dir = 4 - }, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "nUS" = ( /obj/effect/decal/cleanable/dirt, /obj/machinery/atmospherics/components/unary/vent_scrubber/on{ @@ -39340,6 +39253,16 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/dark, /area/station/science/xenobiology) +"nVm" = ( +/obj/machinery/computer/camera_advanced/xenobio{ + dir = 1 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/item/storage/box/monkeycubes, +/turf/open/floor/iron/white/textured_large, +/area/station/science/xenobiology) "nVp" = ( /obj/effect/turf_decal/tile/red/half/contrasted{ dir = 8 @@ -39533,6 +39456,13 @@ dir = 8 }, /area/station/engineering/atmos/storage/gas) +"nZW" = ( +/obj/structure/barricade/wooden, +/obj/machinery/atmospherics/components/binary/pump/on/green/visible{ + dir = 8 + }, +/turf/open/floor/plating, +/area/station/maintenance/department/science) "nZY" = ( /obj/effect/mapping_helpers/broken_floor, /obj/structure/reagent_dispensers/watertank, @@ -39546,6 +39476,26 @@ /obj/machinery/digital_clock/directional/south, /turf/open/floor/iron/dark/textured, /area/station/science/robotics/lab) +"oag" = ( +/obj/structure/table, +/obj/item/paper_bin{ + pixel_x = -4; + pixel_y = 6 + }, +/obj/item/pen{ + pixel_x = -4; + pixel_y = 5 + }, +/obj/item/storage/box/beakers{ + pixel_x = 24; + pixel_y = 6 + }, +/obj/item/storage/box/syringes{ + pixel_x = 11; + pixel_y = 4 + }, +/turf/open/floor/glass/reinforced, +/area/station/science/xenobiology) "oas" = ( /obj/structure/table, /obj/item/phone{ @@ -39557,16 +39507,6 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos/upper) -"oaz" = ( -/obj/machinery/light/directional/north, -/obj/structure/table, -/obj/item/hand_labeler{ - pixel_y = 10; - pixel_x = -13 - }, -/obj/item/folder, -/turf/open/floor/glass/reinforced, -/area/station/science/xenobiology) "oaF" = ( /obj/effect/spawner/structure/window/hollow/reinforced/middle{ dir = 4 @@ -39833,6 +39773,17 @@ /obj/machinery/firealarm/directional/east, /turf/open/floor/glass, /area/station/command/meeting_room) +"ofG" = ( +/obj/machinery/atmospherics/components/unary/thermomachine/freezer/layer2{ + dir = 1 + }, +/obj/effect/turf_decal/box/red, +/obj/machinery/light/directional/south, +/obj/machinery/camera/autoname/directional/west{ + network = list("ss13","rd") + }, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "ofL" = ( /obj/effect/spawner/random/structure/crate, /obj/effect/turf_decal/stripes/line, @@ -39912,6 +39863,19 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/plating, /area/station/security/prison/work) +"oia" = ( +/obj/machinery/door/firedoor, +/obj/machinery/door/airlock/research/glass{ + name = "Secure Pen" + }, +/obj/effect/mapping_helpers/airlock/access/all/science/xenobio, +/obj/structure/cable, +/obj/machinery/door/poddoor/preopen{ + id = "Xenolab"; + name = "Test Chamber Blast Door" + }, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "oix" = ( /turf/open/floor/iron/white, /area/station/science/ordnance/testlab) @@ -39948,6 +39912,11 @@ }, /turf/open/floor/iron/textured, /area/station/cargo/drone_bay) +"ojS" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/hidden, +/obj/effect/turf_decal/tile/blue/fourcorners, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/medical/treatment_center) "oka" = ( /obj/effect/turf_decal/siding/purple{ dir = 1 @@ -39970,6 +39939,22 @@ }, /turf/open/floor/wood, /area/station/service/lawoffice) +"okf" = ( +/obj/machinery/light/directional/south, +/obj/structure/table, +/obj/item/clothing/mask/gas{ + pixel_x = 8 + }, +/obj/item/clothing/mask/gas{ + pixel_y = 5; + pixel_x = 16 + }, +/obj/item/clothing/mask/gas{ + pixel_x = 12; + pixel_y = 2 + }, +/turf/open/floor/glass/reinforced, +/area/station/science/xenobiology) "okg" = ( /obj/machinery/holopad, /obj/effect/landmark/event_spawn, @@ -40067,16 +40052,6 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos) -"olY" = ( -/obj/machinery/portable_atmospherics/canister/oxygen, -/obj/machinery/airalarm/directional/north, -/obj/effect/turf_decal/box, -/obj/machinery/atmospherics/components/unary/portables_connector/visible{ - dir = 8; - name = "Oxygen Chamber Injection Port" - }, -/turf/open/floor/iron/white/smooth_large, -/area/station/science/ordnance/storage) "omv" = ( /obj/structure/rack, /obj/effect/spawner/random/clothing/backpack, @@ -40372,9 +40347,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/department/cargo) -"orY" = ( -/turf/open/openspace/xenobio, -/area/station/science/xenobiology) "osd" = ( /obj/structure/cable, /obj/effect/turf_decal/trimline/blue/filled/line{ @@ -40439,11 +40411,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/catwalk_floor/iron_dark, /area/station/ai_monitored/turret_protected/aisat_interior) -"osT" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/hidden, -/obj/effect/turf_decal/tile/blue/fourcorners, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/medical/treatment_center) "osX" = ( /obj/effect/decal/cleanable/dirt, /turf/open/floor/plating, @@ -40464,6 +40431,13 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, /area/station/maintenance/department/bridge) +"otJ" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 9 + }, +/obj/structure/cable, +/turf/open/floor/iron/white, +/area/station/science/ordnance/storage) "otY" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/effect/spawner/random/structure/closet_empty/crate, @@ -40689,26 +40663,6 @@ /obj/effect/mapping_helpers/broken_floor, /turf/open/floor/wood/tile, /area/station/service/bar) -"oxW" = ( -/obj/machinery/door/airlock/research{ - name = "Ordnance Lab" - }, -/obj/effect/mapping_helpers/airlock/access/all/science/ordnance, -/obj/structure/cable, -/obj/machinery/door/firedoor/heavy, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/ordnance) -"oyd" = ( -/obj/effect/turf_decal/bot, -/obj/machinery/button/door/directional/east{ - name = "shutter control"; - id = "ordauxgarage" - }, -/obj/structure/tank_dispenser, -/turf/open/floor/plating, -/area/station/science/ordnance) "oyq" = ( /obj/machinery/light/cold/directional/west, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -41067,6 +41021,15 @@ /obj/effect/spawner/random/maintenance, /turf/open/floor/plating, /area/station/maintenance/port/greater) +"oEP" = ( +/obj/structure/window/spawner/directional/east, +/obj/machinery/portable_atmospherics/pump, +/obj/effect/turf_decal/stripes/line{ + dir = 9 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron/dark/smooth_large, +/area/station/science/ordnance) "oEZ" = ( /obj/machinery/atmospherics/pipe/bridge_pipe/yellow/visible, /obj/machinery/atmospherics/pipe/bridge_pipe/green/visible{ @@ -41579,12 +41542,6 @@ /obj/machinery/camera/autoname/directional/south, /turf/open/floor/iron/dark, /area/station/command/bridge) -"oOP" = ( -/obj/structure/cable, -/obj/effect/turf_decal/tile/dark_blue/half/contrasted, -/obj/machinery/incident_display/bridge/directional/south, -/turf/open/floor/iron, -/area/station/command/bridge) "oOR" = ( /obj/structure/hedge, /obj/effect/turf_decal/siding/green{ @@ -41864,14 +41821,6 @@ /obj/structure/chair/sofa/bench/right, /turf/open/floor/iron, /area/station/hallway/primary/central) -"oTP" = ( -/obj/effect/turf_decal/stripes/corner{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/portable_atmospherics/scrubber, -/turf/open/floor/iron/dark/smooth_large, -/area/station/science/ordnance) "oTW" = ( /obj/structure/closet/secure_closet/quartermaster, /obj/machinery/light/small/directional/east, @@ -42008,6 +41957,11 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/circuit/green, /area/station/ai_monitored/turret_protected/ai_upload) +"oVS" = ( +/obj/structure/cable, +/obj/effect/turf_decal/siding/purple, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "oVV" = ( /obj/machinery/camera/directional/east{ c_tag = "Xenobiology Lab - Secure Pen"; @@ -42598,11 +42552,6 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron, /area/station/security/detectives_office) -"pgI" = ( -/obj/structure/barricade/wooden, -/obj/effect/decal/cleanable/dirt, -/turf/open/floor/plating, -/area/station/maintenance/department/science) "pgJ" = ( /obj/structure/table/reinforced, /obj/effect/turf_decal/tile/red/fourcorners, @@ -42745,17 +42694,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/cargo/storage) -"piH" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/duct, -/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/hidden, -/obj/effect/turf_decal/tile/blue/fourcorners, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/medical/treatment_center) "piS" = ( /obj/structure/girder/displaced, /obj/effect/turf_decal/sand/plating, @@ -42814,13 +42752,6 @@ dir = 8 }, /area/station/service/theater) -"pjK" = ( -/obj/machinery/portable_atmospherics/canister/oxygen, -/obj/machinery/light_switch/directional/east, -/obj/structure/cable, -/obj/machinery/power/apc/auto_name/directional/north, -/turf/open/floor/iron/white/smooth_large, -/area/station/science/ordnance/storage) "pjN" = ( /obj/structure/transit_tube/horizontal{ dir = 2 @@ -42985,6 +42916,17 @@ /obj/machinery/firealarm/directional/south, /turf/open/floor/iron/dark, /area/station/medical/treatment_center) +"pmp" = ( +/obj/machinery/door/airlock/research/glass{ + name = "Chemistry Minisat" + }, +/obj/effect/mapping_helpers/airlock/access/all/medical/chemistry, +/obj/effect/mapping_helpers/airlock/unres{ + dir = 8 + }, +/obj/effect/landmark/navigate_destination/chemfactory, +/turf/open/floor/iron/white, +/area/station/medical/chemistry/minisat) "pmC" = ( /obj/effect/turf_decal/tile/neutral, /turf/open/floor/iron/dark, @@ -43323,6 +43265,13 @@ }, /turf/open/floor/engine, /area/station/engineering/supermatter/room) +"psQ" = ( +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/turf_decal/stripes/line, +/obj/machinery/portable_atmospherics/pipe_scrubber, +/turf/open/floor/iron/dark/smooth_large, +/area/station/science/ordnance) "psT" = ( /obj/effect/turf_decal/stripes/line{ dir = 8 @@ -43598,16 +43547,6 @@ /obj/effect/decal/cleanable/blood/tracks, /turf/open/floor/plating/airless, /area/station/maintenance/department/medical/central) -"pxU" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/turf_decal/trimline/yellow/filled/corner{ - dir = 4 - }, -/obj/effect/turf_decal/trimline/yellow/filled/corner, -/turf/open/floor/iron/white, -/area/station/maintenance/department/medical) "pxY" = ( /obj/structure/reagent_dispensers/fueltank, /obj/effect/decal/cleanable/dirt, @@ -43947,10 +43886,6 @@ }, /turf/open/floor/iron/white/smooth_large, /area/station/medical/chemistry) -"pDr" = ( -/obj/effect/decal/cleanable/dirt/dust, -/turf/open/floor/iron/white, -/area/station/maintenance/department/medical) "pDs" = ( /obj/structure/chair, /obj/machinery/light/small/directional/north, @@ -44023,16 +43958,6 @@ }, /turf/open/floor/iron/textured, /area/station/engineering/storage/tech) -"pEq" = ( -/obj/machinery/atmospherics/pipe/smart/manifold/purple/visible{ - dir = 8 - }, -/obj/structure/disposalpipe/trunk/multiz{ - dir = 1 - }, -/obj/structure/extinguisher_cabinet/directional/west, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "pEH" = ( /turf/closed/wall/rock/porous, /area/station/cargo/miningoffice) @@ -44223,6 +44148,16 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/cargo/warehouse/upper) +"pIk" = ( +/obj/structure/closet/crate/science{ + opened = 1; + icon_state = "scicrateopen" + }, +/obj/effect/decal/cleanable/dirt/dust, +/obj/effect/turf_decal/stripes/line, +/obj/item/tank, +/turf/open/floor/iron/dark/smooth_large, +/area/station/science/ordnance) "pIp" = ( /obj/structure/railing{ dir = 4 @@ -44303,6 +44238,21 @@ }, /turf/open/floor/iron/white, /area/station/science/lobby) +"pJU" = ( +/obj/item/stack/sheet/glass, +/obj/item/stack/sheet/iron/fifty, +/obj/item/clothing/glasses/welding, +/obj/item/disk/tech_disk{ + pixel_y = 6 + }, +/obj/item/reagent_containers/dropper, +/obj/structure/table, +/obj/machinery/requests_console/auto_name/directional/north, +/obj/effect/mapping_helpers/requests_console/supplies, +/obj/effect/mapping_helpers/requests_console/ore_update, +/obj/effect/mapping_helpers/requests_console/assistance, +/turf/open/floor/iron/white, +/area/station/science/lab) "pKb" = ( /obj/effect/spawner/random/trash/cigbutt{ spawn_random_offset = 4; @@ -45515,12 +45465,6 @@ "qfB" = ( /turf/closed/wall, /area/station/medical/pharmacy) -"qfE" = ( -/obj/machinery/air_sensor/oxygen_tank{ - chamber_id = "o2ordance" - }, -/turf/open/floor/engine/o2, -/area/station/science/ordnance) "qfJ" = ( /obj/structure/sign/poster/random/directional/north, /obj/structure/table/wood/fancy/orange, @@ -45757,6 +45701,12 @@ /obj/structure/window/spawner/directional/north, /turf/open/misc/grass, /area/station/ai_monitored/turret_protected/aisat/foyer) +"qjs" = ( +/obj/machinery/camera/autoname/directional/south{ + network = list("ss13","rd") + }, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/ordnance/testlab) "qjw" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, @@ -46242,6 +46192,13 @@ /obj/machinery/air_sensor/nitrous_tank, /turf/open/floor/engine/n2o, /area/station/engineering/atmos) +"qsj" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/atmospherics/components/tank/oxygen{ + dir = 8 + }, +/turf/open/floor/plating, +/area/station/maintenance/department/science) "qsu" = ( /obj/machinery/light/directional/north, /obj/machinery/rnd/production/protolathe/department/engineering, @@ -46723,6 +46680,18 @@ }, /turf/open/floor/carpet, /area/station/medical/psychology) +"qDM" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/obj/machinery/atmospherics/components/unary/portables_connector/visible{ + dir = 1 + }, +/obj/machinery/portable_atmospherics/canister, +/obj/effect/turf_decal/box/red, +/obj/machinery/light/directional/south, +/turf/open/floor/iron/dark/smooth_large, +/area/station/science/ordnance) "qDP" = ( /obj/structure/lattice/catwalk, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -46856,20 +46825,21 @@ /obj/effect/turf_decal/delivery, /turf/open/floor/iron, /area/station/ai_monitored/command/storage/eva) -"qGr" = ( -/obj/machinery/door/poddoor/shutters/window/preopen{ - id = "ordstorage" - }, -/obj/effect/turf_decal/stripes/line, -/obj/structure/cable, -/obj/effect/turf_decal/caution/stand_clear/red, -/turf/open/floor/iron/white, -/area/station/science/ordnance/storage) "qGB" = ( /obj/machinery/ticket_machine/directional/north, /obj/structure/chair/sofa/bench, /turf/open/floor/iron/white, /area/station/medical/exam_room) +"qGD" = ( +/obj/structure/table, +/obj/machinery/reagentgrinder{ + pixel_y = 8 + }, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/iron/white/textured_large, +/area/station/science/xenobiology) "qGN" = ( /obj/structure/table/wood, /obj/effect/spawner/random/entertainment/deck, @@ -46993,16 +46963,6 @@ /obj/effect/mapping_helpers/burnt_floor, /turf/open/floor/plating, /area/station/maintenance/central/greater) -"qIQ" = ( -/obj/structure/chair/office{ - dir = 8 - }, -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 5 - }, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/lab) "qIS" = ( /obj/machinery/cryo_cell, /obj/structure/window/reinforced/spawner/directional/west, @@ -47542,6 +47502,14 @@ /obj/effect/decal/cleanable/glass, /turf/open/floor/plating, /area/station/maintenance/department/engine) +"qUi" = ( +/obj/machinery/processor/slime, +/obj/effect/turf_decal/bot_red, +/obj/effect/turf_decal/stripes/line{ + dir = 1 + }, +/turf/open/floor/iron/white/textured_large, +/area/station/science/xenobiology) "qUl" = ( /obj/effect/turf_decal/tile/neutral, /obj/structure/table, @@ -47584,13 +47552,6 @@ dir = 1 }, /area/station/engineering/atmos) -"qVB" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "qVD" = ( /obj/structure/railing, /obj/structure/table, @@ -47721,14 +47682,11 @@ }, /turf/open/floor/iron, /area/station/hallway/primary/central) -"qXg" = ( -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +"qXj" = ( +/obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/components/binary/valve/digital{ - dir = 8 - }, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "qXm" = ( /turf/open/floor/iron/showroomfloor, /area/station/engineering/main) @@ -47745,23 +47703,17 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white, /area/station/science/lobby) -"qXA" = ( -/obj/machinery/atmospherics/pipe/smart/simple/yellow/visible{ - dir = 5 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 6 - }, -/obj/machinery/computer/atmos_control/oxygen_tank{ - atmos_chambers = list(o2ordance="Oxygen Supply") - }, -/turf/open/floor/iron/dark/smooth_large, -/area/station/science/ordnance) "qXB" = ( /obj/structure/rack, /obj/effect/spawner/random/techstorage/security_all, /turf/open/floor/iron/textured, /area/station/engineering/storage/tech) +"qXE" = ( +/obj/machinery/portable_atmospherics/canister/oxygen, +/obj/structure/sign/poster/official/wtf_is_co2/directional/north, +/obj/machinery/light_switch/directional/east, +/turf/open/floor/iron/white/smooth_large, +/area/station/science/ordnance/storage) "qXK" = ( /obj/effect/turf_decal/tile/red, /obj/effect/landmark/event_spawn, @@ -48086,6 +48038,11 @@ /obj/machinery/firealarm/directional/south, /turf/open/floor/iron, /area/station/security/mechbay) +"rcH" = ( +/obj/effect/decal/cleanable/dirt, +/obj/item/wrench, +/turf/open/floor/plating, +/area/station/maintenance/department/science) "rcP" = ( /obj/effect/turf_decal/stripes/asteroid/corner, /turf/open/misc/asteroid, @@ -48139,11 +48096,6 @@ /obj/machinery/telecomms/processor/preset_one, /turf/open/floor/circuit/green/telecomms/mainframe, /area/station/tcommsat/server) -"rdM" = ( -/obj/effect/spawner/structure/window/reinforced/plasma, -/obj/machinery/atmospherics/pipe/smart/simple/yellow/visible, -/turf/open/floor/plating, -/area/station/science/ordnance) "rdP" = ( /obj/machinery/chem_dispenser, /obj/machinery/newscaster/directional/east, @@ -48275,14 +48227,6 @@ /obj/effect/spawner/random/vending/snackvend, /turf/open/floor/iron/dark/smooth_large, /area/station/hallway/primary/central) -"rfA" = ( -/obj/machinery/atmospherics/pipe/smart/simple/dark/visible{ - dir = 10 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "rfQ" = ( /obj/effect/turf_decal/tile/brown/half/contrasted{ dir = 1 @@ -48699,18 +48643,6 @@ }, /turf/open/floor/iron/dark, /area/station/science/ordnance) -"rkK" = ( -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/components/unary/portables_connector/visible{ - dir = 1 - }, -/obj/effect/turf_decal/box/red, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "rkL" = ( /obj/structure/table, /obj/structure/window/spawner/directional/east, @@ -49161,14 +49093,6 @@ /obj/effect/turf_decal/tile/blue/half/contrasted, /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) -"rtq" = ( -/obj/effect/turf_decal/stripes/line{ - dir = 9 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/portable_atmospherics/scrubber, -/turf/open/floor/iron/dark/smooth_large, -/area/station/science/ordnance) "rts" = ( /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ dir = 1 @@ -49316,15 +49240,6 @@ /obj/item/piggy_bank/vault, /turf/open/floor/iron/dark, /area/station/ai_monitored/command/nuke_storage) -"rwA" = ( -/obj/machinery/door/poddoor/shutters/window/preopen{ - id = "ordstorage" - }, -/obj/effect/turf_decal/stripes/line, -/obj/effect/turf_decal/caution/stand_clear/red, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/iron/white, -/area/station/science/ordnance/storage) "rwD" = ( /obj/structure/cable, /obj/effect/turf_decal/siding/wood/corner{ @@ -49657,11 +49572,6 @@ }, /turf/open/floor/engine/n2o, /area/station/engineering/atmos) -"rBq" = ( -/obj/structure/cable, -/obj/effect/turf_decal/siding/purple, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "rBt" = ( /obj/effect/turf_decal/stripes/line{ dir = 1 @@ -49753,6 +49663,17 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white, /area/station/medical/treatment_center) +"rCD" = ( +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/duct, +/obj/machinery/atmospherics/pipe/smart/manifold4w/cyan/hidden, +/obj/effect/turf_decal/tile/blue/fourcorners, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/medical/treatment_center) "rCL" = ( /obj/effect/turf_decal/stripes/line{ dir = 9 @@ -49918,16 +49839,6 @@ /obj/effect/mapping_helpers/airlock/access/all/engineering/external, /turf/open/floor/plating, /area/station/cargo/storage) -"rEV" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/effect/turf_decal/trimline/yellow/filled/line, -/obj/effect/turf_decal/trimline/yellow/filled/corner{ - dir = 1 - }, -/turf/open/floor/iron/white, -/area/station/medical/chemistry) "rFb" = ( /obj/effect/turf_decal/trimline/green/filled/line{ dir = 9 @@ -50162,12 +50073,6 @@ }, /turf/open/floor/iron, /area/station/engineering/main) -"rJv" = ( -/obj/structure/sign/warning/chem_diamond/directional/south, -/obj/effect/decal/cleanable/dirt/dust, -/obj/effect/spawner/random/structure/girder, -/turf/open/floor/plating, -/area/station/maintenance/department/medical) "rJy" = ( /obj/machinery/portable_atmospherics/canister/air, /obj/effect/turf_decal/bot, @@ -50372,6 +50277,12 @@ /obj/item/holosign_creator/robot_seat/restaurant, /turf/open/floor/iron/kitchen, /area/station/service/kitchen) +"rPh" = ( +/obj/effect/turf_decal/sand/plating, +/obj/machinery/light/small/directional/south, +/obj/structure/broken_flooring/pile, +/turf/open/floor/plating, +/area/station/science/ordnance) "rPi" = ( /obj/structure/flora/bush/flowers_br/style_random, /obj/structure/window/spawner/directional/west, @@ -50415,6 +50326,30 @@ }, /turf/open/floor/iron/textured_large, /area/station/hallway/primary/central) +"rPT" = ( +/obj/effect/mapping_helpers/broken_floor, +/obj/effect/decal/cleanable/dirt/dust, +/obj/structure/table, +/obj/item/reagent_containers/cup/beaker{ + pixel_x = -6; + pixel_y = 4 + }, +/obj/item/reagent_containers/syringe{ + pixel_x = 16; + pixel_y = 1 + }, +/obj/item/reagent_containers/syringe{ + pixel_x = 8; + pixel_y = 10 + }, +/obj/structure/sign/poster/contraband/random/directional/north, +/turf/open/floor/iron/white, +/area/station/maintenance/department/medical) +"rPV" = ( +/obj/effect/turf_decal/tile/purple/fourcorners, +/obj/machinery/light/small/directional/north, +/turf/open/floor/iron, +/area/station/science/ordnance) "rQb" = ( /obj/effect/turf_decal/siding/thinplating_new/end, /obj/effect/decal/cleanable/dirt/dust, @@ -50571,14 +50506,6 @@ dir = 1 }, /area/station/engineering/atmos) -"rSB" = ( -/obj/machinery/atmospherics/pipe/smart/manifold/yellow/visible{ - dir = 1 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "rSF" = ( /obj/effect/turf_decal/siding, /obj/structure/table, @@ -50876,7 +50803,7 @@ /turf/open/floor/iron, /area/station/cargo/storage) "rWI" = ( -/obj/structure/reagent_dispensers/watertank, +/obj/structure/reagent_dispensers/watertank/high, /obj/effect/turf_decal/bot{ dir = 1 }, @@ -50924,6 +50851,14 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/command/heads_quarters/qm) +"rXf" = ( +/obj/structure/table, +/obj/item/paper_bin{ + pixel_x = -5; + pixel_y = 6 + }, +/turf/open/floor/glass/reinforced, +/area/station/science/xenobiology) "rXg" = ( /obj/structure/spirit_board, /obj/item/storage/box/bodybags{ @@ -51139,6 +51074,14 @@ /obj/machinery/holopad, /turf/open/floor/iron, /area/station/service/hydroponics) +"rZE" = ( +/obj/machinery/portable_atmospherics/pump, +/obj/effect/turf_decal/stripes/line{ + dir = 4 + }, +/obj/effect/decal/cleanable/dirt/dust, +/turf/open/floor/iron/dark/smooth_large, +/area/station/science/ordnance) "rZJ" = ( /obj/effect/turf_decal/siding/thinplating_new, /obj/effect/decal/cleanable/dirt/dust, @@ -51285,6 +51228,12 @@ /obj/structure/lattice/catwalk, /turf/open/openspace, /area/station/science/xenobiology) +"sbS" = ( +/obj/structure/cable, +/obj/effect/turf_decal/siding/purple/corner, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "sbU" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/effect/spawner/random/structure/crate, @@ -51366,6 +51315,12 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/security/execution/transfer) +"sdB" = ( +/obj/effect/decal/cleanable/dirt, +/obj/machinery/light/small/broken/directional/north, +/obj/machinery/portable_atmospherics/canister, +/turf/open/floor/plating, +/area/station/maintenance/department/science) "sdW" = ( /obj/structure/railing{ dir = 9 @@ -51640,14 +51595,6 @@ /obj/effect/landmark/blobstart, /turf/open/floor/iron/dark, /area/station/security/lockers) -"siU" = ( -/obj/structure/rack, -/obj/effect/spawner/random/maintenance, -/obj/effect/turf_decal/trimline/yellow/filled/corner, -/obj/effect/decal/cleanable/dirt/dust, -/obj/machinery/light/small/dim/directional/north, -/turf/open/floor/iron/white, -/area/station/maintenance/department/medical) "siX" = ( /obj/machinery/atmospherics/pipe/smart/manifold/scrubbers/visible, /obj/machinery/meter/monitored/waste_loop, @@ -51711,6 +51658,12 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/maintenance/disposal/incinerator) +"sjT" = ( +/obj/effect/turf_decal/tile/brown/fourcorners, +/obj/structure/railing, +/obj/machinery/door/firedoor/border_only, +/turf/open/floor/iron, +/area/station/cargo/storage) "sjW" = ( /obj/machinery/atmospherics/pipe/bridge_pipe/yellow/visible{ dir = 4 @@ -51884,6 +51837,15 @@ /obj/structure/cable, /turf/open/floor/iron, /area/station/hallway/primary/starboard) +"smH" = ( +/obj/machinery/atmospherics/components/binary/valve/digital{ + dir = 8 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "smM" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -52069,20 +52031,6 @@ /obj/effect/spawner/random/trash/bucket, /turf/open/floor/plating, /area/station/maintenance/department/medical/central) -"spU" = ( -/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/medical/chemistry, -/obj/effect/turf_decal/trimline/yellow/filled/line, -/obj/effect/turf_decal/trimline/yellow/filled/line{ - dir = 1 - }, -/obj/machinery/door/airlock/research/glass{ - name = "Chemistry Minisat" - }, -/turf/open/floor/iron/white, -/area/station/medical/chemistry) "sqb" = ( /obj/structure/cable, /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2, @@ -52280,18 +52228,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/white, /area/station/ai_monitored/turret_protected/ai_upload_foyer) -"stk" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/structure/disposalpipe/segment, -/obj/machinery/door/airlock/maintenance_hatch, -/obj/effect/mapping_helpers/airlock/access/any/medical/maintenance, -/obj/effect/mapping_helpers/airlock/unres{ - dir = 1 - }, -/turf/open/floor/plating, -/area/station/maintenance/department/medical) "stp" = ( /obj/structure/railing{ dir = 1 @@ -52355,6 +52291,14 @@ }, /turf/open/floor/engine/xenobio, /area/station/science/xenobiology) +"suo" = ( +/obj/machinery/door/poddoor/shutters/window/preopen{ + id = "ordstorage" + }, +/obj/effect/turf_decal/stripes/line, +/obj/effect/turf_decal/caution/stand_clear/red, +/turf/open/floor/iron/white, +/area/station/science/ordnance/storage) "suq" = ( /obj/effect/landmark/start/station_engineer, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -52444,17 +52388,6 @@ /obj/effect/turf_decal/trimline/blue/filled/line, /turf/open/floor/iron/white, /area/station/medical/medbay/central) -"svE" = ( -/obj/structure/table, -/obj/item/storage/box/syringes{ - pixel_x = -8; - pixel_y = 11 - }, -/obj/item/storage/box/beakers{ - pixel_x = 4 - }, -/turf/open/floor/glass/reinforced, -/area/station/science/xenobiology) "svK" = ( /obj/structure/cable, /obj/effect/decal/cleanable/dirt, @@ -53081,6 +53014,42 @@ }, /turf/open/floor/iron/white/textured_large, /area/station/science/research) +"sHo" = ( +/obj/structure/table, +/obj/item/stack/sheet/iron/fifty{ + pixel_x = 3; + pixel_y = 6 + }, +/obj/item/construction/plumbing{ + pixel_x = 34; + pixel_y = 6 + }, +/obj/item/stack/ducts/fifty{ + pixel_x = 26; + pixel_y = 2 + }, +/obj/item/stack/ducts/fifty{ + pixel_x = 25; + pixel_y = 1 + }, +/obj/item/stack/ducts/fifty{ + pixel_x = 24; + pixel_y = -1 + }, +/obj/item/stack/ducts/fifty{ + pixel_x = 23; + pixel_y = -3 + }, +/obj/item/stack/ducts/fifty{ + pixel_x = 23; + pixel_y = -5 + }, +/obj/effect/turf_decal/trimline/yellow/filled/line{ + dir = 1 + }, +/obj/machinery/light/small/dim/directional/north, +/turf/open/floor/iron/white, +/area/station/medical/chemistry) "sHz" = ( /obj/effect/turf_decal/stripes/line{ dir = 4 @@ -53566,14 +53535,6 @@ }, /turf/open/floor/iron/dark/smooth_large, /area/station/science/xenobiology) -"sQU" = ( -/obj/machinery/light/directional/south, -/obj/structure/table, -/obj/item/clothing/mask/gas, -/obj/item/clothing/mask/gas, -/obj/item/clothing/mask/gas, -/turf/open/floor/glass/reinforced, -/area/station/science/xenobiology) "sRj" = ( /obj/structure/sign/poster/official/random/directional/east, /obj/effect/turf_decal/siding/purple{ @@ -54017,12 +53978,6 @@ }, /turf/open/floor/iron/white, /area/station/medical/paramedic) -"sZr" = ( -/obj/machinery/atmospherics/pipe/smart/simple/purple/visible{ - dir = 5 - }, -/turf/closed/wall/r_wall, -/area/station/science/ordnance/storage) "sZs" = ( /obj/effect/landmark/event_spawn, /obj/effect/turf_decal/siding/wood, @@ -54581,19 +54536,6 @@ /obj/structure/cable, /turf/open/floor/plating, /area/station/maintenance/department/medical/central) -"tky" = ( -/obj/structure/table, -/obj/effect/turf_decal/tile/neutral/fourcorners, -/obj/item/storage/toolbox/mechanical{ - pixel_x = -2; - pixel_y = 8 - }, -/obj/item/storage/toolbox/mechanical{ - pixel_x = 3; - pixel_y = -2 - }, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "tkD" = ( /obj/effect/turf_decal/trimline/yellow/filled/warning, /obj/structure/railing, @@ -54902,13 +54844,11 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/wood, /area/station/maintenance/central/lesser) -"tqf" = ( -/obj/machinery/atmospherics/components/unary/outlet_injector/monitored/oxygen_input{ - dir = 4; - chamber_id = "o2ordance" - }, -/turf/open/floor/engine/o2, -/area/station/science/ordnance) +"tpN" = ( +/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/co2, +/obj/effect/turf_decal/tile/blue/fourcorners, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/medical/treatment_center) "tqk" = ( /obj/machinery/conveyor{ id = "garbage"; @@ -55062,6 +55002,15 @@ /obj/effect/landmark/start/prisoner, /turf/open/floor/iron, /area/station/security/prison) +"tsm" = ( +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "tsq" = ( /obj/structure/chair/sofa/bench/right{ dir = 1 @@ -55192,6 +55141,20 @@ /obj/effect/turf_decal/tile/yellow, /turf/open/floor/iron, /area/station/hallway/primary/starboard) +"tuL" = ( +/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/medical/chemistry, +/obj/effect/turf_decal/trimline/yellow/filled/line, +/obj/effect/turf_decal/trimline/yellow/filled/line{ + dir = 1 + }, +/obj/machinery/door/airlock/research/glass{ + name = "Chemistry Minisat" + }, +/turf/open/floor/iron/white, +/area/station/medical/chemistry) "tuR" = ( /obj/machinery/door/firedoor/border_only, /obj/structure/railing, @@ -55237,24 +55200,12 @@ }, /turf/open/floor/wood/parquet, /area/station/service/theater) -"tvt" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "tvB" = ( /obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ dir = 1 }, /turf/open/floor/iron/dark, /area/station/science/ordnance) -"tvQ" = ( -/obj/structure/chair/sofa/bench, -/obj/effect/landmark/start/prisoner, -/obj/structure/cable, -/turf/open/floor/iron, -/area/station/security/prison) "twf" = ( /obj/machinery/door/poddoor/shutters/radiation/preopen{ id = "soup"; @@ -55591,14 +55542,6 @@ /obj/machinery/light_switch/directional/south, /turf/open/floor/iron/textured, /area/station/cargo/miningoffice) -"tCz" = ( -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 4 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/lab) "tCE" = ( /obj/effect/turf_decal/tile/neutral, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -55702,11 +55645,6 @@ }, /turf/open/floor/iron/dark/airless, /area/station/science/ordnance) -"tEm" = ( -/obj/effect/turf_decal/tile/purple/fourcorners, -/obj/machinery/light/small/directional/north, -/turf/open/floor/iron, -/area/station/command/heads_quarters/rd) "tEn" = ( /obj/structure/cable, /obj/effect/turf_decal/tile/blue{ @@ -55940,24 +55878,11 @@ dir = 8 }, /area/station/command/meeting_room) -"tId" = ( -/obj/machinery/atmospherics/components/unary/vent_pump/siphon/monitored/oxygen_output{ - chamber_id = "o2ordance" - }, -/turf/open/floor/engine/o2, -/area/station/science/ordnance) "tIr" = ( /obj/effect/spawner/structure/window/reinforced, /obj/structure/cable, /turf/open/floor/plating, /area/station/security/warden) -"tIs" = ( -/obj/structure/cable, -/obj/structure/disposalpipe/segment{ - dir = 5 - }, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "tIE" = ( /obj/effect/landmark/secequipment, /obj/effect/turf_decal/tile/red/anticorner/contrasted{ @@ -56068,10 +55993,6 @@ }, /turf/open/floor/iron, /area/station/maintenance/solars/starboard/fore) -"tKD" = ( -/obj/effect/spawner/structure/window/reinforced/plasma, -/turf/open/floor/plating, -/area/station/science/ordnance) "tKX" = ( /obj/structure/table/reinforced, /obj/item/storage/toolbox/mechanical{ @@ -56426,11 +56347,6 @@ /obj/structure/sign/poster/random/directional/north, /turf/open/openspace, /area/station/science/research) -"tPE" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "tPJ" = ( /obj/machinery/light_switch/directional/west, /obj/structure/disposalpipe/segment, @@ -56566,6 +56482,13 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/iron, /area/station/security/brig/entrance) +"tRZ" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 9 + }, +/obj/machinery/portable_atmospherics/scrubber, +/turf/open/floor/iron/dark/smooth_large, +/area/station/science/ordnance) "tSc" = ( /obj/machinery/light/directional/north, /turf/open/floor/iron, @@ -56676,18 +56599,6 @@ }, /turf/open/floor/iron/dark, /area/station/security/warden) -"tUr" = ( -/obj/machinery/light/small/dim/directional/west, -/obj/effect/mapping_helpers/broken_floor, -/obj/effect/decal/cleanable/dirt/dust, -/obj/effect/turf_decal/trimline/yellow/filled/corner{ - dir = 8 - }, -/obj/structure/chair{ - dir = 4 - }, -/turf/open/floor/iron/white, -/area/station/maintenance/department/medical) "tUD" = ( /obj/structure/cable, /turf/open/floor/iron/dark/side{ @@ -56980,12 +56891,6 @@ }, /turf/open/floor/iron/white, /area/station/medical/surgery/theatre) -"tZR" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "tZW" = ( /obj/machinery/camera/autoname/directional/south, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -57023,6 +56928,17 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/plating, /area/station/maintenance/department/science) +"uaw" = ( +/obj/effect/turf_decal/tile/neutral/opposingcorners{ + dir = 1 + }, +/obj/effect/turf_decal/siding/purple{ + dir = 4 + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/iron/dark, +/area/station/command/heads_quarters/rd) "uay" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/white/line{ @@ -57593,16 +57509,6 @@ }, /turf/open/floor/plating, /area/station/medical/pharmacy) -"uke" = ( -/obj/machinery/computer/camera_advanced/xenobio{ - dir = 1 - }, -/obj/effect/turf_decal/stripes/line{ - dir = 1 - }, -/obj/item/storage/box/monkeycubes, -/turf/open/floor/iron/white/textured_large, -/area/station/science/xenobiology) "ukl" = ( /obj/machinery/door/airlock/external{ name = "Solar Maintenance" @@ -57849,11 +57755,6 @@ /obj/machinery/atmospherics/components/binary/valve, /turf/open/floor/plating, /area/station/maintenance/department/medical/central) -"uoP" = ( -/obj/machinery/atmospherics/components/trinary/filter/atmos/flipped/co2, -/obj/effect/turf_decal/tile/blue/fourcorners, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/medical/treatment_center) "uoY" = ( /obj/structure/cable, /obj/effect/turf_decal/trimline/purple/filled/arrow_ccw, @@ -58360,6 +58261,15 @@ }, /turf/open/floor/iron/dark/corner, /area/station/engineering/atmos) +"uya" = ( +/obj/effect/turf_decal/box/corners{ + dir = 4 + }, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "uyc" = ( /obj/machinery/light/cold/directional/west, /obj/effect/turf_decal/tile/neutral/fourcorners, @@ -58566,6 +58476,16 @@ /obj/effect/turf_decal/sand/plating, /turf/open/floor/plating/airless, /area/station/asteroid) +"uBU" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 9 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "uCj" = ( /obj/effect/turf_decal/tile/blue/opposingcorners, /obj/effect/turf_decal/tile/red/opposingcorners{ @@ -58819,15 +58739,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron, /area/station/security/prison) -"uGx" = ( -/obj/item/toy/plush/lizard_plushie/green{ - name = "Hauls-The-Crates" - }, -/obj/effect/spawner/random/structure/table_or_rack, -/obj/effect/decal/cleanable/cobweb/cobweb2, -/obj/structure/sign/departments/exodrone/directional/east, -/turf/open/floor/plating, -/area/station/maintenance/department/cargo) "uGS" = ( /obj/structure/chair/office/tactical{ dir = 8 @@ -58950,9 +58861,7 @@ "uJq" = ( /obj/machinery/computer/records/medical, /obj/effect/turf_decal/tile/red/fourcorners, -/obj/machinery/computer/security/telescreen/cmo/directional/north{ - name = "Medbay Monitor" - }, +/obj/machinery/computer/security/telescreen/med_sec/directional/north, /turf/open/floor/iron/dark, /area/station/security/checkpoint/medical) "uJt" = ( @@ -59042,6 +58951,13 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron, /area/station/engineering/gravity_generator) +"uLi" = ( +/obj/structure/cable, +/obj/effect/landmark/navigate_destination/dockarrival, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/hallway/secondary/entry) "uLj" = ( /obj/machinery/door/poddoor/shutters/window{ id = "gateshutter"; @@ -59690,17 +59606,6 @@ dir = 1 }, /area/station/command/heads_quarters/qm) -"uWI" = ( -/obj/machinery/door/airlock/research/glass{ - name = "Chemistry Minisat" - }, -/obj/effect/mapping_helpers/airlock/access/all/medical/chemistry, -/obj/effect/mapping_helpers/airlock/unres{ - dir = 8 - }, -/obj/effect/landmark/navigate_destination/chemfactory, -/turf/open/floor/iron/white, -/area/station/medical/chemistry/minisat) "uWX" = ( /obj/effect/turf_decal/tile/yellow{ dir = 8 @@ -60095,12 +60000,6 @@ }, /turf/open/floor/iron/large, /area/station/service/hydroponics/garden) -"veF" = ( -/obj/effect/turf_decal/tile/brown/fourcorners, -/obj/structure/railing, -/obj/machinery/door/firedoor/border_only, -/turf/open/floor/iron, -/area/station/cargo/storage) "veW" = ( /obj/structure/extinguisher_cabinet/directional/north, /turf/closed/wall, @@ -60457,10 +60356,6 @@ /obj/machinery/light/directional/south, /turf/open/openspace, /area/station/security/warden) -"vlz" = ( -/obj/structure/cable, -/turf/open/floor/iron/dark, -/area/station/science/ordnance) "vlD" = ( /obj/structure/table/wood, /obj/machinery/light_switch/directional/north, @@ -60531,6 +60426,12 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/station/construction/mining/aux_base) +"vmH" = ( +/obj/effect/decal/cleanable/dirt, +/obj/structure/fluff/broken_canister_frame, +/obj/structure/sign/poster/random/directional/west, +/turf/open/floor/plating, +/area/station/maintenance/department/science) "vnb" = ( /obj/machinery/door/poddoor/incinerator_atmos_aux, /turf/open/floor/engine/airless, @@ -61217,6 +61118,15 @@ dir = 8 }, /area/station/science/xenobiology) +"vBN" = ( +/obj/structure/window/spawner/directional/east, +/obj/effect/turf_decal/stripes/corner{ + dir = 1 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/portable_atmospherics/scrubber, +/turf/open/floor/iron/dark/smooth_large, +/area/station/science/ordnance) "vBV" = ( /obj/structure/disposalpipe/segment{ dir = 4 @@ -61450,6 +61360,12 @@ }, /turf/open/floor/iron/white, /area/station/medical/medbay/lobby) +"vFL" = ( +/obj/effect/turf_decal/stripes/line{ + dir = 5 + }, +/turf/open/floor/iron/white, +/area/station/science/ordnance/storage) "vFM" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -62062,14 +61978,6 @@ "vQB" = ( /turf/closed/wall, /area/station/cargo/boutique) -"vQP" = ( -/obj/machinery/light/dim/directional/east, -/obj/effect/turf_decal/tile/dark_blue/half/contrasted{ - dir = 4 - }, -/obj/structure/fireaxecabinet/directional/east, -/turf/open/floor/iron, -/area/station/command/bridge) "vQT" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, @@ -62270,6 +62178,16 @@ }, /turf/open/floor/iron/solarpanel/airless, /area/station/solars/port) +"vUk" = ( +/obj/machinery/atmospherics/components/trinary/mixer{ + dir = 4 + }, +/obj/machinery/light/directional/north, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/structure/cable, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "vUn" = ( /obj/structure/cable, /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, @@ -62290,6 +62208,11 @@ }, /turf/open/floor/iron, /area/station/engineering/atmos/storage/gas) +"vUJ" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "vUO" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/showroomfloor, @@ -62513,13 +62436,6 @@ /obj/structure/sign/poster/official/random/directional/north, /turf/open/floor/iron/dark, /area/station/commons/locker) -"vZu" = ( -/obj/machinery/atmospherics/components/tank/air/layer4, -/obj/effect/turf_decal/tile/green/half/contrasted{ - dir = 1 - }, -/turf/open/floor/iron/white, -/area/station/medical/virology) "vZF" = ( /obj/structure/dresser, /obj/effect/decal/cleanable/dirt, @@ -62785,12 +62701,6 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, /area/station/maintenance/department/medical/central) -"wea" = ( -/obj/structure/cable, -/obj/machinery/airalarm/directional/north, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "weg" = ( /obj/effect/turf_decal/tile/brown/anticorner/contrasted{ dir = 1 @@ -63161,6 +63071,19 @@ /obj/machinery/light/small/directional/east, /turf/open/floor/iron/textured_large, /area/station/service/hydroponics/garden) +"wlO" = ( +/obj/machinery/atmospherics/components/unary/portables_connector/visible{ + dir = 1 + }, +/obj/effect/turf_decal/box/red, +/obj/structure/disposalpipe/segment{ + dir = 6 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/cable, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "wlR" = ( /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden, /turf/open/floor/plating, @@ -63531,6 +63454,14 @@ /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4, /turf/open/floor/iron/dark, /area/station/command/heads_quarters/rd) +"wtu" = ( +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/lab) "wtw" = ( /obj/structure/extinguisher_cabinet/directional/south, /obj/machinery/atmospherics/components/unary/vent_pump/on/layer4{ @@ -63635,6 +63566,12 @@ /obj/effect/mapping_helpers/mail_sorting/service/hydroponics, /turf/open/floor/wood/tile, /area/station/service/bar) +"wvs" = ( +/obj/structure/chair/sofa/bench, +/obj/effect/landmark/start/prisoner, +/obj/structure/cable, +/turf/open/floor/iron, +/area/station/security/prison) "wvt" = ( /obj/machinery/door/airlock/maintenance_hatch, /obj/effect/mapping_helpers/airlock/access/any/supply/maintenance, @@ -63748,16 +63685,6 @@ }, /turf/open/floor/carpet/executive, /area/station/command/meeting_room) -"wxP" = ( -/obj/structure/cable, -/obj/machinery/airalarm/directional/north, -/obj/structure/disposalpipe/segment{ - dir = 10 - }, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/lab) "wxQ" = ( /obj/machinery/computer/operating{ dir = 8 @@ -64128,6 +64055,16 @@ }, /turf/open/floor/iron/dark, /area/station/ai_monitored/turret_protected/aisat/teleporter) +"wDb" = ( +/obj/structure/chair/office{ + dir = 8 + }, +/obj/structure/cable, +/obj/structure/disposalpipe/segment{ + dir = 5 + }, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/lab) "wDe" = ( /obj/effect/turf_decal/siding/white{ dir = 1 @@ -64294,6 +64231,15 @@ /obj/effect/landmark/event_spawn, /turf/open/floor/iron/dark, /area/station/command/gateway) +"wFb" = ( +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/structure/disposalpipe/segment{ + dir = 4 + }, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/lab) "wFw" = ( /obj/structure/cable, /obj/structure/closet/emcloset, @@ -64500,6 +64446,10 @@ "wKO" = ( /turf/open/floor/glass, /area/station/maintenance/department/medical) +"wKR" = ( +/obj/machinery/portable_atmospherics/canister, +/turf/open/floor/iron/white/smooth_large, +/area/station/science/ordnance/storage) "wKT" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/smart/simple/green/visible{ @@ -64758,42 +64708,6 @@ /obj/machinery/gravity_generator/main, /turf/open/floor/iron/dark, /area/station/engineering/gravity_generator) -"wOJ" = ( -/obj/structure/table, -/obj/item/stack/sheet/iron/fifty{ - pixel_x = 3; - pixel_y = 6 - }, -/obj/item/construction/plumbing{ - pixel_x = 34; - pixel_y = 6 - }, -/obj/item/stack/ducts/fifty{ - pixel_x = 26; - pixel_y = 2 - }, -/obj/item/stack/ducts/fifty{ - pixel_x = 25; - pixel_y = 1 - }, -/obj/item/stack/ducts/fifty{ - pixel_x = 24; - pixel_y = -1 - }, -/obj/item/stack/ducts/fifty{ - pixel_x = 23; - pixel_y = -3 - }, -/obj/item/stack/ducts/fifty{ - pixel_x = 23; - pixel_y = -5 - }, -/obj/effect/turf_decal/trimline/yellow/filled/line{ - dir = 1 - }, -/obj/machinery/light/small/dim/directional/north, -/turf/open/floor/iron/white, -/area/station/medical/chemistry) "wOK" = ( /obj/structure/chair/comfy/brown{ dir = 8; @@ -64819,15 +64733,6 @@ /obj/effect/landmark/atmospheric_sanity/ignore_area, /turf/closed/wall/r_wall, /area/station/ai_monitored/turret_protected/ai_upload_foyer) -"wPP" = ( -/obj/machinery/door/airlock/maintenance_hatch{ - name = "Xenobiology Maintenance" - }, -/obj/effect/mapping_helpers/airlock/access/all/science/xenobio, -/obj/structure/cable, -/obj/structure/disposalpipe/segment, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "wPU" = ( /obj/machinery/light/small/directional/west, /turf/open/misc/asteroid, @@ -64915,6 +64820,13 @@ }, /turf/open/floor/iron, /area/station/security/brig/entrance) +"wRL" = ( +/obj/effect/turf_decal/tile/neutral/fourcorners, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "wRN" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/atmospherics/pipe/smart/simple/cyan/visible{ @@ -65660,17 +65572,6 @@ "xeS" = ( /turf/open/floor/iron, /area/station/commons/storage/primary) -"xeT" = ( -/obj/structure/cable, -/obj/machinery/button/door/directional/east{ - name = "shutter control"; - id = "xbprotect1" - }, -/obj/structure/window/reinforced/spawner/directional/north, -/obj/item/kirbyplants/random, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/xenobiology) "xeW" = ( /obj/effect/turf_decal/tile/brown{ dir = 8 @@ -65738,13 +65639,6 @@ /obj/machinery/photobooth, /turf/open/floor/iron, /area/station/hallway/secondary/command) -"xgc" = ( -/obj/structure/cable, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/disposalpipe/segment, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/science/lab) "xgn" = ( /obj/structure/mannequin/skeleton{ starting_items = list() @@ -66208,16 +66102,6 @@ /obj/effect/decal/cleanable/dirt/dust, /turf/open/floor/plating, /area/station/maintenance/department/cargo) -"xpb" = ( -/obj/effect/turf_decal/stripes/line, -/obj/machinery/door/poddoor/shutters/window/preopen{ - id = "ordstorage" - }, -/obj/effect/turf_decal/caution/stand_clear/red, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/obj/structure/cable, -/turf/open/floor/iron/white, -/area/station/science/ordnance/storage) "xpn" = ( /obj/effect/decal/cleanable/dirt, /obj/effect/turf_decal/stripes/white/line{ @@ -66285,13 +66169,6 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/iron/white, /area/station/medical/chemistry/minisat) -"xqG" = ( -/obj/structure/cable, -/obj/effect/landmark/event_spawn, -/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, -/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, -/turf/open/floor/catwalk_floor/iron_white, -/area/station/hallway/secondary/entry) "xqO" = ( /obj/docking_port/stationary/escape_pod{ dir = 8 @@ -66380,14 +66257,6 @@ }, /turf/open/floor/wood, /area/station/commons/lounge) -"xrY" = ( -/obj/effect/decal/cleanable/dirt, -/obj/machinery/atmospherics/components/unary/portables_connector/visible{ - dir = 1 - }, -/obj/effect/turf_decal/box/red, -/turf/open/floor/plating, -/area/station/maintenance/department/science) "xsj" = ( /obj/machinery/netpod, /obj/structure/cable, @@ -66570,6 +66439,22 @@ /obj/machinery/atmospherics/pipe/bridge_pipe/green/visible, /turf/open/floor/iron, /area/station/engineering/atmos) +"xvo" = ( +/obj/machinery/door/poddoor/shutters/window/preopen{ + id = "ordstorage" + }, +/obj/effect/turf_decal/stripes/line, +/obj/machinery/button/door/directional/east{ + req_access = list("ordnance"); + name = "Ordnance Storage Shutter Control"; + id = "ordstorage" + }, +/obj/effect/turf_decal/caution/stand_clear/red, +/obj/effect/turf_decal/stripes/corner{ + dir = 4 + }, +/turf/open/floor/iron/white, +/area/station/science/ordnance/storage) "xvr" = ( /obj/machinery/computer/prisoner/management{ dir = 1 @@ -66700,6 +66585,11 @@ /obj/effect/decal/cleanable/dirt, /turf/open/floor/iron, /area/station/engineering/atmos) +"xxN" = ( +/obj/machinery/light/small/dim/directional/north, +/obj/machinery/atmospherics/components/unary/passive_vent, +/turf/open/floor/engine/o2, +/area/station/science/ordnance) "xxO" = ( /obj/structure/window/reinforced/spawner/directional/north, /obj/structure/flora/bush/fullgrass/style_random, @@ -66724,6 +66614,15 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, /turf/open/floor/wood, /area/station/service/library) +"xxY" = ( +/obj/machinery/atmospherics/pipe/smart/simple/dark/visible{ + dir = 8 + }, +/obj/structure/cable, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "xyG" = ( /obj/effect/decal/cleanable/dirt/dust, /obj/machinery/power/apc/auto_name/directional/south, @@ -66963,6 +66862,13 @@ /obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, /turf/open/floor/iron/white, /area/station/science/explab) +"xCs" = ( +/obj/structure/cable, +/obj/effect/turf_decal/siding/purple{ + dir = 1 + }, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/xenobiology) "xCw" = ( /obj/effect/turf_decal/siding/purple, /obj/structure/chair/sofa/bench, @@ -67313,6 +67219,15 @@ }, /turf/open/floor/circuit, /area/station/ai_monitored/turret_protected/ai_upload) +"xJK" = ( +/obj/effect/turf_decal/stripes/line, +/obj/machinery/door/poddoor/shutters/window/preopen{ + id = "ordstorage" + }, +/obj/effect/turf_decal/caution/stand_clear/red, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/iron/white, +/area/station/science/ordnance/storage) "xJQ" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 4 @@ -67324,6 +67239,14 @@ }, /turf/open/floor/iron/white, /area/station/medical/exam_room) +"xJR" = ( +/obj/machinery/portable_atmospherics/canister, +/obj/machinery/atmospherics/components/unary/portables_connector/visible{ + dir = 8 + }, +/obj/effect/turf_decal/box/red, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "xJT" = ( /obj/effect/turf_decal/tile/yellow/half/contrasted{ dir = 8 @@ -67548,6 +67471,17 @@ }, /turf/open/floor/wood/tile, /area/station/service/bar) +"xOB" = ( +/obj/machinery/door/airlock/research{ + name = "Ordnance Lab" + }, +/obj/effect/mapping_helpers/airlock/access/all/science/ordnance, +/obj/structure/cable, +/obj/machinery/door/firedoor/heavy, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/science/ordnance) "xOC" = ( /obj/effect/turf_decal/tile/dark_blue/half/contrasted, /obj/structure/disposalpipe/segment, @@ -67726,6 +67660,14 @@ /obj/machinery/door/firedoor, /turf/open/floor/iron/dark/textured_half, /area/station/cargo/storage) +"xSW" = ( +/obj/machinery/atmospherics/components/unary/vent_scrubber/on/layer2{ + dir = 1 + }, +/turf/open/floor/iron/white/smooth_half{ + dir = 8 + }, +/area/station/science/xenobiology) "xTa" = ( /obj/effect/spawner/structure/window/reinforced, /obj/machinery/door/poddoor/preopen{ @@ -68041,6 +67983,12 @@ /obj/machinery/firealarm/directional/west, /turf/open/floor/iron/dark, /area/station/service/bar) +"xYE" = ( +/obj/machinery/atmospherics/pipe/smart/simple/yellow/visible{ + dir = 5 + }, +/turf/open/floor/iron/dark, +/area/station/science/ordnance) "xYG" = ( /obj/effect/turf_decal/trimline/blue/filled/line{ dir = 4 @@ -68133,6 +68081,11 @@ /obj/effect/turf_decal/tile/neutral/fourcorners, /turf/open/floor/iron/dark, /area/station/science/ordnance/testlab) +"yaH" = ( +/obj/item/radio/intercom/directional/east, +/obj/machinery/portable_atmospherics/canister/oxygen, +/turf/open/floor/iron/white/smooth_large, +/area/station/science/ordnance/storage) "yaM" = ( /obj/effect/turf_decal/siding/wood, /obj/effect/decal/cleanable/dirt, @@ -68366,14 +68319,13 @@ }, /turf/open/floor/plating/airless, /area/space/nearstation) -"yew" = ( -/obj/structure/table, -/obj/effect/spawner/random/trash/crushed_can{ - pixel_x = 7; - pixel_y = 15 - }, -/turf/open/floor/iron/white, -/area/station/maintenance/department/medical) +"yeK" = ( +/obj/structure/cable, +/obj/effect/landmark/event_spawn, +/obj/machinery/atmospherics/pipe/smart/manifold4w/supply/hidden/layer4, +/obj/machinery/atmospherics/pipe/smart/manifold4w/scrubbers/hidden/layer2, +/turf/open/floor/catwalk_floor/iron_white, +/area/station/hallway/secondary/entry) "yeO" = ( /obj/machinery/door/firedoor/border_only{ dir = 8 @@ -68446,6 +68398,14 @@ /obj/structure/cable, /turf/open/floor/wood, /area/station/commons/lounge) +"ygt" = ( +/obj/structure/rack, +/obj/effect/spawner/random/maintenance, +/obj/effect/turf_decal/trimline/yellow/filled/corner, +/obj/effect/decal/cleanable/dirt/dust, +/obj/machinery/light/small/dim/directional/north, +/turf/open/floor/iron/white, +/area/station/maintenance/department/medical) "ygw" = ( /turf/closed/wall/r_wall, /area/station/security/detectives_office) @@ -81771,7 +81731,7 @@ jtd bPP gUa mxq -uGx +fZg bVs ycz bVs @@ -82327,9 +82287,9 @@ phV kFT kFT qIS -osT -uoP -ioh +ojS +tpN +aju gzw dKw amK @@ -82506,7 +82466,7 @@ iUF dUc xrb xrb -dEG +nPw dEG iqf cKn @@ -82584,9 +82544,9 @@ hQK dPg fvo jPO -osT -dci -piH +ojS +kvW +rCD xaC dKw dKw @@ -82841,9 +82801,9 @@ sGt ltj fvo pwn -eaL -eUB -dgR +isy +hSB +cnd uPg bui yit @@ -83098,9 +83058,9 @@ bhZ pgJ fvo lcM -eaL -eaL -nIa +isy +isy +lJo crz bui yit @@ -84310,7 +84270,7 @@ hME hME tSc wUe -tvQ +wvs imQ rhY tsk @@ -96658,7 +96618,7 @@ hSi sRM kZA gkQ -oOP +dBn eKR eKR juw @@ -97171,7 +97131,7 @@ jTd rkz lrc eHa -vQP +ktI ita hOb cwq @@ -103874,7 +103834,7 @@ tdk hkc swi dHy -cBB +aEL trL nMP xOU @@ -104122,7 +104082,7 @@ wWY eZN cPt alA -qIQ +wDb irJ rBI cPt @@ -104378,8 +104338,8 @@ vfJ xbu gMK cPt -lcj -tCz +pJU +wtu dfr mKF cPt @@ -104399,7 +104359,7 @@ qnQ xcb wCO tld -kZf +miU azv azv azv @@ -104636,7 +104596,7 @@ eIV gMK cPt voQ -tCz +wtu urh ooy cPt @@ -104893,7 +104853,7 @@ gLw jmY cPt kKJ -hEw +ebU xWb cUe cPt @@ -105150,7 +105110,7 @@ rXG raz cPt toV -hEw +ebU irJ cPt cPt @@ -105407,7 +105367,7 @@ oBP raz wtr rrq -aNF +wFb irJ jRN jyQ @@ -105664,9 +105624,9 @@ oBP vfJ cPt cPt -wxP -xgc -hld +eBw +gIM +giJ ugh aZs jDP @@ -105916,7 +105876,7 @@ fYe vxX vxX vfJ -xAd +gZF oBP xAd kHG @@ -108493,7 +108453,7 @@ foX aku ouA jJe -gOY +ilp gOY gOY gOY @@ -108750,15 +108710,15 @@ foX aku aku ilp +ilp gOY -luh -tId -rdM -qXA +xxN +aam +xYE boy gql abh -pEq +nGV uPL sSN nal @@ -109007,13 +108967,13 @@ rji foX ilp ilp +jTB +jTB +jTB gOY -tqf -qfE -tKD -hNI -atb -qVB +vUk +wlO +nqi iOH fQr gOY @@ -109263,14 +109223,14 @@ uOo aku aku ilp -ilp jTB -eTG -sZr +jTB +ief +jZv gOY -nUN -rkK -nTZ +ifv +kMl +cZs urY czh uPL @@ -109521,15 +109481,15 @@ aku ilp ilp jTB -jTB -olY -eNt -gOY -rSB +jGd +eBH +otJ +mTg +hYG bwj -mSG +jLY rSh -ivy +xJR gOY wOn gOY @@ -109778,18 +109738,18 @@ aku ilp ilp jTB -jGd -eBH -cIk -aqz -qXg +dkr +hbH +naU +bmr +smH lCw -vlz +fDz fDz fDz bPc efJ -dPh +ofG gOY cxg cxg @@ -110035,13 +109995,13 @@ uro rji ilp jTB -dkr -hbH -naU -rwA -eCJ +sqJ +wiT +rBt +suo +lMC aMG -vlz +fDz xTs fDz fDz @@ -110292,13 +110252,13 @@ aku ilp ilp jTB -sqJ -wiT -rBt -aPG -cPu -mqb -vlz +dEn +lIn +tra +suo +xxY +aMG +fDz fDz mfC fDz @@ -110549,19 +110509,19 @@ aku ilp ilp jTB -dEn -lIn -tra -qGr -gzF -kEM +gbV +jqY +rus +xJK +hVC +uya fDz fDz fDz oWy fDz dyd -bfq +qDM gOY cxg vxX @@ -110806,11 +110766,11 @@ aku ilp ilp jTB -gbV -jqY -rus -xpb -rfA +wKR +wKR +vFL +xvo +mSe nCo tGW tGW @@ -111063,14 +111023,14 @@ aku ieo ilp jTB -dYY -epB -mqn -dGi -hTv +jTB +qXE +yaH +gOY +aks tTK tvB -fNi +tRZ nkM vxZ dyS @@ -111309,7 +111269,7 @@ cLf cLf cLf cLf -fYe +vxX vxX ilp pkw @@ -111319,15 +111279,15 @@ uOo aku vfR ilp +ilp +jTB jTB jTB -pjK -ioL gOY -aks +gOY tTK -rtq -oTP +oEP +vBN xfQ cAG xXF @@ -111576,15 +111536,15 @@ uOo aku aku fbN -rji -jTB -jTB -jTB -gOY +gsW +gsW +rZE +rZE gOY -tTK -dZQ -jvp +iJZ +lcd +eih +neb nkM vxZ pZK @@ -111833,15 +111793,15 @@ uOo aku aku pkw -gsW -ikJ -jtp -hPn -gOY -iJZ +hhd +bEz +laD +laD +fVO +cmn lcd -tky -cQx +cmn +acN efL cQu wgI @@ -112091,12 +112051,12 @@ aku aku aku ajs -gop -cqf -hWl -hCB -cmn -fYW +pIk +dpA +rPh +gOY +mAC +uBU cut rcR efL @@ -112348,13 +112308,13 @@ aku aku aku vjB -jEw +psQ cmn -oyd +czC gOY -lFI -kCh -nGb +gAV +hFz +wRL icz efL nbS @@ -112610,8 +112570,8 @@ grm gsW gOY gOY -oxW gOY +xOB gOY nkM nkM @@ -112866,9 +112826,9 @@ aku xAd upd upd -kAI -cra -nNF +ndE +mkV +dcc uvx mna gXw @@ -113121,8 +113081,8 @@ aku aku vfR vfJ -pgI -vfJ +upd +efF moe jxe aaR @@ -113378,8 +113338,8 @@ tsz lJq obA vfJ -dxZ -xrY +egt +nZW moe tLh dlE @@ -113634,9 +113594,9 @@ ouk uYH aQm obA +vmH upd bnb -upd moe rHG bpW @@ -113891,9 +113851,9 @@ lJq jBM lJq obA -daT -eyx -eyx +sdB +rcH +qsj moe mJU bpW @@ -144509,7 +144469,7 @@ vxX mUQ kLL cts -caH +gQL lCA pux eYP @@ -146052,8 +146012,8 @@ vxX iJm uKm eYP -uWI -dir +pmp +ldf eYP fnh qoN @@ -146308,7 +146268,7 @@ vxX vxX vxX uKm -tUr +mUA iLo lYg oHC @@ -146565,10 +146525,10 @@ unk vxX vxX oTe -ctf -pDr +rPT +atT cMK -rJv +jsf fnh kGS fnh @@ -146820,13 +146780,13 @@ ibx ibx unk hvw -jiP +fXo uKm -yew +eOA jSE hgS jHQ -stk +mjU jHQ bhV jHQ @@ -147078,9 +147038,9 @@ ibx fvF duU hmA -exS -nlx -miR +nJD +hyL +kJW kYT kYT kYT @@ -147315,7 +147275,7 @@ sdc ilr gDQ qWY -veF +sjT oZQ oZQ oZQ @@ -147336,8 +147296,8 @@ unk ibx vxX unk -siU -pxU +ygt +dXH kYT bUZ vzG @@ -147594,7 +147554,7 @@ ibx vxX bGk bGk -spU +tuL bGk rRy cOb @@ -147850,8 +147810,8 @@ vxX taj vxX bGk -kVh -rEV +mqc +mfw bGk bGk ncR @@ -148107,8 +148067,8 @@ ibx ibx vxX bGk -wOJ -jeV +sHo +mJD tGR hNN pLA @@ -148364,7 +148324,7 @@ ibx vxX vxX bGk -kSc +jfq dhj dhj xmy @@ -152492,7 +152452,7 @@ wYY tSn xas xhJ -vZu +mfP xOF dgS kzI @@ -154776,25 +154736,25 @@ wjI wjI uXD cYC -leZ -leZ -leZ -leZ -leZ -leZ -leZ -leZ -leZ -leZ -leZ -leZ -leZ -leZ -leZ -leZ -leZ -leZ -leZ +jCP +jCP +jCP +jCP +jCP +jCP +jCP +jCP +jCP +jCP +jCP +jCP +jCP +jCP +jCP +jCP +jCP +jCP +jCP dFc uXD uXD @@ -155033,7 +154993,7 @@ uXD uXD uXD uGW -leZ +jCP rCL sTB kAc @@ -155051,7 +155011,7 @@ kAc kAc sTB vAo -leZ +jCP sZF pLP pLP @@ -155290,7 +155250,7 @@ aLN aLN uXD jYf -leZ +jCP vVC sxV sxV @@ -155308,7 +155268,7 @@ sxV sxV sxV mJV -leZ +jCP sZF pLP pLP @@ -155547,7 +155507,7 @@ aLN aLN ntQ hPS -leZ +jCP sby sxV sxV @@ -155565,7 +155525,7 @@ sxV sxV sxV hrI -xqG +yeK wDr uXD uXD @@ -155804,7 +155764,7 @@ aLN aLN hVN hPS -leZ +jCP sby sxV sxV @@ -155822,7 +155782,7 @@ sxV sxV sxV hrI -leZ +jCP lGP rzJ gMk @@ -156061,7 +156021,7 @@ aLN jhc jYG hPS -leZ +jCP sby sxV sxV @@ -156079,7 +156039,7 @@ sxV sxV idV hrI -leZ +jCP khL uXD uet @@ -156318,7 +156278,7 @@ aLN aLN vzi hPS -leZ +jCP sby sxV sxV @@ -156336,7 +156296,7 @@ sxV sxV sxV hrI -leZ +jCP lGP rzJ gMk @@ -156575,7 +156535,7 @@ aLN aLN uXD hPS -leZ +jCP sby sxV sxV @@ -156593,7 +156553,7 @@ sxV sxV sxV hrI -leZ +jCP qgy uXD uXD @@ -156832,7 +156792,7 @@ aLN aLN uXD cDl -leZ +jCP vVC sxV sxV @@ -156850,7 +156810,7 @@ sxV sxV sxV mJV -leZ +jCP sZF pLP pLP @@ -157089,7 +157049,7 @@ jJb jJb jJb ata -leZ +jCP hbb xkO nhm @@ -157107,7 +157067,7 @@ nhm nhm xkO lCp -leZ +jCP sZF pLP pLP @@ -157346,25 +157306,25 @@ dRq bfN uhi bOr -leZ -leZ -leZ -leZ -leZ -leZ -leZ -leZ -leZ -lUy -leZ -leZ -leZ -leZ -leZ -leZ -leZ -leZ -leZ +jCP +jCP +jCP +jCP +jCP +jCP +jCP +jCP +jCP +uLi +jCP +jCP +jCP +jCP +jCP +jCP +jCP +jCP +jCP wLu uXD uXD @@ -176604,7 +176564,7 @@ raz raz nzk fpY -fEW +clQ ssg vtN ylR @@ -176860,8 +176820,8 @@ iSz uba vfJ nzk -fpY -clQ +rPV +wYI elT elT elT @@ -177117,14 +177077,14 @@ vmk uba pBN nzk -tEm -wYI -kbc -kbc -kbc -kbc -iHV -iHV +hEi +hEi +wFI +mmU +ibE +wts +uaw +uaw tcx qJN uHQ @@ -177375,13 +177335,13 @@ wtI vfJ vfJ hEi -hEi -wFI -mmU -ibE -wts -hmd -bIP +myW +myW +fsZ +jfB +sab +sab +jzM iFN kHf xkL @@ -177632,13 +177592,13 @@ bfp vfJ mNZ hEi -myW -myW -fsZ -jfB +mlm +rsI +gmH +iVp sab sab -jzM +sdn iFN aXl fyJ @@ -177889,13 +177849,13 @@ lVB vfJ mNZ hEi -mlm -rsI +hUH +dfk gmH -iVp -sab -sab -sdn +rXS +tOL +fPv +iAM iFN mZn oND @@ -178146,13 +178106,13 @@ mNZ mNZ mNZ hEi -hUH -dfk -gmH -rXS -tOL -fPv -iAM +hEi +hEi +hEi +hEi +hEi +hEi +iRy iFN rEv vjQ @@ -178402,14 +178362,14 @@ mNZ mNZ mNZ mNZ -kxB -kxB -kxB -kxB -kxB -kxB -moe -eLb +mNZ +mNZ +ivx +ivx +ivx +ivx +wkG +bhq iFN iFN iFN @@ -178662,11 +178622,11 @@ mNZ mNZ mNZ ivx +moe wkG -jYT -guJ -bXM -rIJ +wkG +wkG +qjs moe vxX vxX @@ -178921,9 +178881,9 @@ mNZ gEA wkG jYT -wkG -wkG -wkG +jYT +jYT +rIJ moe vxX vxX @@ -179179,9 +179139,9 @@ ivx wkG jYT wkG -ivx -ivx -ivx +wkG +wkG +moe vxX vxX vxX @@ -183819,7 +183779,7 @@ gQq klu xEs xEs -iOk +bNG xEs xEs qRY @@ -184076,7 +184036,7 @@ gQq sbR gQq arS -drx +eEg qad gQq abm @@ -184333,7 +184293,7 @@ gQq sbR gQq ibl -tZR +dzL qad gQq abm @@ -184590,7 +184550,7 @@ gQq sbR gQq ibl -tZR +dzL qad gQq abm @@ -184847,7 +184807,7 @@ ubn gYI ybO xgq -tZR +dzL ueJ ybO gYI @@ -185099,17 +185059,17 @@ wBd rWL jQS jQS -wea -tPE -tPE -tvt -tvt -tZR -tvt -tvt -tZR -tZR -aXc +bXe +qXj +qXj +lAt +lAt +dzL +lAt +lAt +dzL +dzL +aFb jQS jQS geB @@ -185356,17 +185316,17 @@ wBd hAL jQS ojC -tPE +qXj lKY lKY -lBZ +vUJ nRj nem ciV -tPE +qXj lKY lKY -tZR +dzL kkD jQS cku @@ -185613,17 +185573,17 @@ jQS hAL jQS qWt -tPE +qXj lKY hQH -gjo +cAq csf oIh pPY -xeT +iPf gCP lKY -tZR +dzL hLA jQS cku @@ -185870,7 +185830,7 @@ wBd hAL jQS jQS -agM +gvj gMy gwx jQS @@ -185880,7 +185840,7 @@ wmO jQS xDf gtE -mYh +hMf jQS jQS cku @@ -186125,11 +186085,11 @@ oJt wAT ezg agA -wPP -tIs -tPE +cVs +cUf +qXj lKY -fTO +qUi wmO ybO ybO @@ -186137,9 +186097,9 @@ ybO wmO rmi lKY -tZR -gmb -mRC +dzL +tsm +gCV awC vbV wAT @@ -186384,9 +186344,9 @@ wBd rWL jQS uVe -tPE +qXj avA -uke +nVm wmO ybO ybO @@ -186394,7 +186354,7 @@ ybO wmO xGG uBm -lBZ +vUJ rWp jQS hAL @@ -186641,9 +186601,9 @@ jQS hye jQS qZX -tPE +qXj lKY -iQo +qGD wmO ybO ybO @@ -186651,7 +186611,7 @@ ybO wmO bLI lKY -lBZ +vUJ gDl jQS hye @@ -186898,17 +186858,17 @@ jQS jQS jQS iXn -ieU +mMe cWL tMz jQS wmO -htn +kZW jgA jQS tMz ybo -aqG +sbS lVq jQS jQS @@ -187153,11 +187113,11 @@ hhX hhX fZF jQS -lCS +rXf jEt -gdM +aMf rdn -dJr +xSW wnA wnA wnA @@ -187165,9 +187125,9 @@ wnA viT bUl cNh -iXB +mjY jEt -svE +oag jQS fZF hhX @@ -187410,21 +187370,21 @@ hhX hhX fZF jQS -oaz +cCr fXW -jej -krO -krO -krO -krO -krO -krO -krO -krO -krO -rBq +xCs +awy +awy +awy +awy +awy +awy +awy +awy +awy +oVS mCT -sQU +okf jQS fZF hhX @@ -187674,7 +187634,7 @@ cWc wnA wnA jfD -krO +awy olE wnA wnA @@ -187931,7 +187891,7 @@ jQS bGL vBD rxC -krO +awy jpe wnA trg @@ -188188,7 +188148,7 @@ jQS tbU byC tbU -keb +oia tbU byC tbU @@ -188442,13 +188402,13 @@ hhX hhX fZF jQS -orY -orY -orY -bqs -orY -orY -orY +nCm +nCm +nCm +kvd +nCm +nCm +nCm jQS fZF hhX @@ -188699,13 +188659,13 @@ hhX hhX fZF jQS -orY -orY -orY -bqs -orY -orY -orY +nCm +nCm +nCm +kvd +nCm +nCm +nCm jQS fZF hhX @@ -188956,13 +188916,13 @@ hhX hhX fZF jQS -orY -orY -orY -orY -orY -orY -orY +nCm +nCm +nCm +nCm +nCm +nCm +nCm jQS fZF hhX @@ -189213,13 +189173,13 @@ hhX hhX fZF jQS -orY -orY -orY -orY -orY -orY -orY +nCm +nCm +nCm +nCm +nCm +nCm +nCm jQS fZF hhX @@ -189471,11 +189431,11 @@ hhX fZF jQS jQS -orY -orY -orY -orY -orY +nCm +nCm +nCm +nCm +nCm jQS jQS fZF diff --git a/_maps/safehouses/bathroom.dmm b/_maps/safehouses/bathroom.dmm index 76712d6193c440..69ad0b25e9520e 100644 --- a/_maps/safehouses/bathroom.dmm +++ b/_maps/safehouses/bathroom.dmm @@ -27,7 +27,7 @@ dir = 4 }, /obj/machinery/light/small/blacklight/directional/east, -/turf/open/floor/bitrunning_transport, +/turf/open/indestructible/bitrunning_transport, /area/virtual_domain/safehouse) "v" = ( /obj/machinery/light/small/blacklight/directional/east, @@ -68,7 +68,7 @@ /obj/effect/turf_decal/loading_area{ dir = 4 }, -/turf/open/floor/bitrunning_transport, +/turf/open/indestructible/bitrunning_transport, /area/virtual_domain/safehouse) "M" = ( /obj/effect/decal/cleanable/dirt, diff --git a/_maps/safehouses/den.dmm b/_maps/safehouses/den.dmm index 15debc7e284e66..9b0b37f5351507 100644 --- a/_maps/safehouses/den.dmm +++ b/_maps/safehouses/den.dmm @@ -18,7 +18,7 @@ /obj/effect/turf_decal/loading_area{ dir = 4 }, -/turf/open/floor/bitrunning_transport, +/turf/open/indestructible/bitrunning_transport, /area/virtual_domain/safehouse) "e" = ( /obj/structure/table/reinforced/plastitaniumglass, @@ -59,7 +59,7 @@ /obj/effect/turf_decal/loading_area{ dir = 4 }, -/turf/open/floor/bitrunning_transport, +/turf/open/indestructible/bitrunning_transport, /area/virtual_domain/safehouse) "z" = ( /obj/effect/turf_decal/trimline/yellow/corner{ diff --git a/_maps/safehouses/dig.dmm b/_maps/safehouses/dig.dmm index 73f0d247dfbe49..aa26f980d60891 100644 --- a/_maps/safehouses/dig.dmm +++ b/_maps/safehouses/dig.dmm @@ -20,7 +20,7 @@ dir = 8 }, /obj/effect/landmark/bitrunning/cache_goal_turf, -/turf/open/floor/bitrunning_transport, +/turf/open/indestructible/bitrunning_transport, /area/virtual_domain/safehouse) "i" = ( /obj/effect/turf_decal/siding/yellow{ @@ -98,7 +98,7 @@ /obj/effect/turf_decal/loading_area, /obj/effect/turf_decal/box/corners, /obj/effect/landmark/bitrunning/cache_goal_turf, -/turf/open/floor/bitrunning_transport, +/turf/open/indestructible/bitrunning_transport, /area/virtual_domain/safehouse) "T" = ( /obj/effect/landmark/bitrunning/hololadder_spawn, diff --git a/_maps/safehouses/ice.dmm b/_maps/safehouses/ice.dmm index 96d689339ab870..f9716de71032f0 100644 --- a/_maps/safehouses/ice.dmm +++ b/_maps/safehouses/ice.dmm @@ -60,7 +60,7 @@ /obj/effect/turf_decal/loading_area{ dir = 4 }, -/turf/open/floor/bitrunning_transport, +/turf/open/indestructible/bitrunning_transport, /area/virtual_domain/safehouse) "p" = ( /obj/structure/railing, @@ -69,7 +69,7 @@ /obj/effect/turf_decal/loading_area{ dir = 4 }, -/turf/open/floor/bitrunning_transport, +/turf/open/indestructible/bitrunning_transport, /area/virtual_domain/safehouse) "u" = ( /obj/effect/decal/cleanable/dirt/dust, diff --git a/_maps/safehouses/lavaland_boss.dmm b/_maps/safehouses/lavaland_boss.dmm index 7331a5b79d7a0c..56141803990a58 100644 --- a/_maps/safehouses/lavaland_boss.dmm +++ b/_maps/safehouses/lavaland_boss.dmm @@ -63,7 +63,7 @@ /obj/machinery/light/directional/east, /obj/structure/railing, /obj/effect/landmark/bitrunning/cache_goal_turf, -/turf/open/floor/bitrunning_transport, +/turf/open/indestructible/bitrunning_transport, /area/virtual_domain/safehouse) "A" = ( /obj/effect/turf_decal/trimline/brown/filled/line{ diff --git a/_maps/safehouses/mine.dmm b/_maps/safehouses/mine.dmm index 904c3c5378e8a6..4bf99ab14f3ace 100644 --- a/_maps/safehouses/mine.dmm +++ b/_maps/safehouses/mine.dmm @@ -26,7 +26,7 @@ }, /obj/machinery/light/directional/east, /obj/effect/landmark/bitrunning/cache_goal_turf, -/turf/open/floor/bitrunning_transport, +/turf/open/indestructible/bitrunning_transport, /area/virtual_domain/safehouse) "B" = ( /obj/effect/turf_decal/trimline/brown/filled/line{ @@ -52,7 +52,7 @@ }, /obj/structure/railing, /obj/effect/landmark/bitrunning/cache_goal_turf, -/turf/open/floor/bitrunning_transport, +/turf/open/indestructible/bitrunning_transport, /area/virtual_domain/safehouse) "H" = ( /obj/machinery/door/airlock/external/glass{ diff --git a/_maps/safehouses/shuttle.dmm b/_maps/safehouses/shuttle.dmm index 75fe975258c51f..19f0c4b73aacc2 100644 --- a/_maps/safehouses/shuttle.dmm +++ b/_maps/safehouses/shuttle.dmm @@ -16,7 +16,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/landmark/bitrunning/cache_goal_turf, /obj/effect/turf_decal/loading_area, -/turf/open/floor/bitrunning_transport, +/turf/open/indestructible/bitrunning_transport, /area/virtual_domain/safehouse) "i" = ( /obj/effect/turf_decal/stripes/line{ @@ -41,7 +41,7 @@ /obj/machinery/light/small/directional/south, /obj/effect/landmark/bitrunning/cache_goal_turf, /obj/effect/turf_decal/loading_area, -/turf/open/floor/bitrunning_transport, +/turf/open/indestructible/bitrunning_transport, /area/virtual_domain/safehouse) "m" = ( /obj/modular_map_connector, diff --git a/_maps/safehouses/shuttle_space.dmm b/_maps/safehouses/shuttle_space.dmm index 0029f5b0a6e7d6..2f4071a8347553 100644 --- a/_maps/safehouses/shuttle_space.dmm +++ b/_maps/safehouses/shuttle_space.dmm @@ -67,7 +67,7 @@ /obj/effect/decal/cleanable/dirt, /obj/effect/landmark/bitrunning/cache_goal_turf, /obj/effect/turf_decal/loading_area, -/turf/open/floor/bitrunning_transport, +/turf/open/indestructible/bitrunning_transport, /area/virtual_domain/safehouse) "z" = ( /obj/effect/turf_decal/stripes/line{ @@ -98,7 +98,7 @@ /obj/machinery/light/small/directional/south, /obj/effect/landmark/bitrunning/cache_goal_turf, /obj/effect/turf_decal/loading_area, -/turf/open/floor/bitrunning_transport, +/turf/open/indestructible/bitrunning_transport, /area/virtual_domain/safehouse) "E" = ( /obj/effect/turf_decal/stripes/line{ diff --git a/_maps/safehouses/wood.dmm b/_maps/safehouses/wood.dmm index 05fbb97f915fb3..5faa33faa41819 100644 --- a/_maps/safehouses/wood.dmm +++ b/_maps/safehouses/wood.dmm @@ -19,7 +19,7 @@ /obj/effect/turf_decal/loading_area{ dir = 4 }, -/turf/open/floor/bitrunning_transport, +/turf/open/indestructible/bitrunning_transport, /area/virtual_domain/safehouse) "v" = ( /obj/machinery/light/small/directional/east, @@ -50,7 +50,7 @@ /obj/effect/turf_decal/loading_area{ dir = 4 }, -/turf/open/floor/bitrunning_transport, +/turf/open/indestructible/bitrunning_transport, /area/virtual_domain/safehouse) "T" = ( /obj/effect/landmark/bitrunning/hololadder_spawn, diff --git a/_maps/virtual_domains/clown_planet.dmm b/_maps/virtual_domains/clown_planet.dmm index 1973dacfb889b2..37e00bd45fcbfc 100644 --- a/_maps/virtual_domains/clown_planet.dmm +++ b/_maps/virtual_domains/clown_planet.dmm @@ -759,7 +759,9 @@ /turf/open/indestructible/white, /area/lavaland/surface/outdoors/virtual_domain) "WT" = ( -/obj/machinery/door/airlock/bananium, +/obj/machinery/door/airlock/bananium{ + use_power = 0 + }, /turf/open/floor/carpet, /area/lavaland/surface/outdoors/virtual_domain) "WX" = ( diff --git a/_maps/virtual_domains/island_brawl.dmm b/_maps/virtual_domains/island_brawl.dmm index fa04316b9b626f..c9010062f54b17 100644 --- a/_maps/virtual_domains/island_brawl.dmm +++ b/_maps/virtual_domains/island_brawl.dmm @@ -2540,7 +2540,7 @@ /area/virtual_domain) "GD" = ( /obj/effect/landmark/bitrunning/permanent_exit, -/turf/open/floor/bitrunning_transport, +/turf/open/indestructible/bitrunning_transport, /area/virtual_domain/protected_space/fullbright) "GI" = ( /turf/open/floor/iron/dark/textured_large, diff --git a/auxlua.dll b/auxlua.dll deleted file mode 100644 index 4f712c26d82ee3..00000000000000 Binary files a/auxlua.dll and /dev/null differ diff --git a/code/__DEFINES/DNA.dm b/code/__DEFINES/DNA.dm index bdda4d295c2418..4756b80f027378 100644 --- a/code/__DEFINES/DNA.dm +++ b/code/__DEFINES/DNA.dm @@ -60,9 +60,15 @@ #define DNA_MOTH_MARKINGS_BLOCK 13 #define DNA_MUSHROOM_CAPS_BLOCK 14 #define DNA_POD_HAIR_BLOCK 15 -#define DNA_MONKEY_TAIL_BLOCK 16 -#define DNA_FEATURE_BLOCKS 16 +// Hey! Listen up if you're here because you're adding a species feature! +// +// You don't need to add a DNA block for EVERY species feature! +// You ONLY need DNA blocks if you intend to allow players to change it via GENETICS! +// (Which means having a DNA block for a feature tied to a mob without DNA is entirely pointless.) + +/// Total amount of DNA blocks, must be equal to the highest DNA block number +#define DNA_FEATURE_BLOCKS 15 #define DNA_SEQUENCE_LENGTH 4 #define DNA_MUTATION_BLOCKS 8 @@ -86,6 +92,8 @@ #define ORGAN_SLOT_MONSTER_CORE "monstercore" #define ORGAN_SLOT_RIGHT_ARM_AUG "r_arm_device" #define ORGAN_SLOT_LEFT_ARM_AUG "l_arm_device" //This one ignores alphabetical order cause the arms should be together +#define ORGAN_SLOT_RIGHT_ARM_MUSCLE "r_arm_muscle" +#define ORGAN_SLOT_LEFT_ARM_MUSCLE "l_arm_muscle" //same as above #define ORGAN_SLOT_SPINE "spine" #define ORGAN_SLOT_STOMACH "stomach" #define ORGAN_SLOT_STOMACH_AID "stomach_aid" @@ -137,6 +145,8 @@ GLOBAL_LIST_INIT(organ_process_order, list( ORGAN_SLOT_APPENDIX, ORGAN_SLOT_RIGHT_ARM_AUG, ORGAN_SLOT_LEFT_ARM_AUG, + ORGAN_SLOT_LEFT_ARM_MUSCLE, + ORGAN_SLOT_RIGHT_ARM_MUSCLE, ORGAN_SLOT_STOMACH, ORGAN_SLOT_STOMACH_AID, ORGAN_SLOT_BREATHING_TUBE, diff --git a/code/__DEFINES/_flags.dm b/code/__DEFINES/_flags.dm index 55e706ce06d036..cbc17654078bf0 100644 --- a/code/__DEFINES/_flags.dm +++ b/code/__DEFINES/_flags.dm @@ -11,6 +11,8 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define DF_USE_TAG (1<<0) #define DF_VAR_EDITED (1<<1) #define DF_ISPROCESSING (1<<2) +/// Placed on datums that have a static, constant reference. Primarily only used for turfs. +#define DF_STATIC_OBJECT (1<<3) //FLAGS BITMASK // scroll down before changing the numbers on these @@ -136,6 +138,8 @@ GLOBAL_LIST_INIT(bitflags, list(1, 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 204 #define VIRTUAL_SAFE_AREA (1<<16) /// This area does not allow the Binary channel #define BINARY_JAMMING (1<<17) +/// This area prevents Bag of Holding rifts from being opened. +#define NO_BOH (1<<18) /* These defines are used specifically with the atom/pass_flags bitmask diff --git a/code/__DEFINES/ai/ai_blackboard.dm b/code/__DEFINES/ai/ai_blackboard.dm index 97ec38c1c3c056..4374288b07c5bb 100644 --- a/code/__DEFINES/ai/ai_blackboard.dm +++ b/code/__DEFINES/ai/ai_blackboard.dm @@ -24,6 +24,8 @@ ///the list of interactions we can have with the owner #define BB_INTERACTIONS_WITH_OWNER "BB_interactions_with_owner" +///The trait checked by ai_behavior/find_potential_targets/prioritize_trait to return a target with a trait over the rest. +#define BB_TARGET_PRIORITY_TRAIT "target_priority_trait" /// Store a single or list of emotes at this key #define BB_EMOTE_KEY "BB_emotes" diff --git a/code/__DEFINES/ai/monsters.dm b/code/__DEFINES/ai/monsters.dm index 76fd6c798d53eb..fb6952eb08491f 100644 --- a/code/__DEFINES/ai/monsters.dm +++ b/code/__DEFINES/ai/monsters.dm @@ -70,8 +70,12 @@ #define BB_LOBSTROSITY_TARGET_LIMB "BB_lobstrosity_target_limb" /// We increment this counter every time we try to move while dragging an arm and if we go too long we'll give up trying to get out of line of sight and just eat the fingers #define BB_LOBSTROSITY_FINGER_LUST "BB_lobstrosity_finger_lust" +/// Does this carp still target lying mobs even if they aren't stunned, and flee from sary fishermen? #define BB_LOBSTROSITY_NAIVE_HUNTER "BB_lobstrosity_naive_hunter" +/// Does this carp run from scary fishermen? +#define BB_CARPS_FEAR_FISHERMAN "BB_carp_fear_fisherman" + // eyeball keys ///the death glare ability #define BB_GLARE_ABILITY "BB_glare_ability" diff --git a/code/__DEFINES/basic_mobs.dm b/code/__DEFINES/basic_mobs.dm index ae74872cd73028..e519fb25240beb 100644 --- a/code/__DEFINES/basic_mobs.dm +++ b/code/__DEFINES/basic_mobs.dm @@ -70,5 +70,3 @@ GLOBAL_VAR_INIT(gutlunch_count, 0) #define BB_RAPTOR_TROUGH_TARGET "raptor_trough_target" #define MAX_RAPTOR_POP 64 - - diff --git a/code/__DEFINES/colors.dm b/code/__DEFINES/colors.dm index 72159bde0540e4..5a95d4f77d7d21 100644 --- a/code/__DEFINES/colors.dm +++ b/code/__DEFINES/colors.dm @@ -435,3 +435,8 @@ GLOBAL_LIST_INIT(cable_colors, list( )) #define HUSK_COLOR_TONE rgb(96, 88, 80) + +#define CM_COLOR_SAT_MIN 0.6 +#define CM_COLOR_SAT_MAX 0.7 +#define CM_COLOR_LUM_MIN 0.65 +#define CM_COLOR_LUM_MAX 0.75 diff --git a/code/__DEFINES/dcs/signals/signals_fish.dm b/code/__DEFINES/dcs/signals/signals_fish.dm index 8f7483d94164a0..2fbf99446ab941 100644 --- a/code/__DEFINES/dcs/signals/signals_fish.dm +++ b/code/__DEFINES/dcs/signals/signals_fish.dm @@ -46,3 +46,9 @@ /// From /obj/item/fish_analyzer/proc/analyze_status: (fish, user) #define COMSIG_FISH_ANALYZER_ANALYZE_STATUS "fish_analyzer_analyze_status" + +/// From /datum/component/fish_growth/on_fish_life: (seconds_per_tick) +#define COMSIG_FISH_BEFORE_GROWING "fish_before_growing" + #define COMPONENT_DONT_GROW (1 << 0) +/// From /datum/component/fish_growth/finish_growing: (result) +#define COMSIG_FISH_FINISH_GROWING "fish_finish_growing" diff --git a/code/__DEFINES/dcs/signals/signals_blackmarket.dm b/code/__DEFINES/dcs/signals/signals_market.dm similarity index 100% rename from code/__DEFINES/dcs/signals/signals_blackmarket.dm rename to code/__DEFINES/dcs/signals/signals_market.dm diff --git a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm index 8be5b1fdb64aa2..dfbfe68ad52cd9 100644 --- a/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm +++ b/code/__DEFINES/dcs/signals/signals_mob/signals_mob_main.dm @@ -243,5 +243,8 @@ /// from /mob/proc/slip(): (knockdown_amonut, obj/slipped_on, lube_flags [mobs.dm], paralyze, force_drop) #define COMSIG_MOB_SLIPPED "mob_slipped" +/// From the base of /datum/component/callouts/proc/callout_picker(mob/user, atom/clicked_atom): (datum/callout_option/callout, atom/target) +#define COMSIG_MOB_CREATED_CALLOUT "mob_created_callout" + /// from /mob/proc/key_down(): (key, client/client, full_key) #define COMSIG_MOB_KEYDOWN "mob_key_down" diff --git a/code/__DEFINES/interaction_flags.dm b/code/__DEFINES/interaction_flags.dm index 615fe5c4cbda20..fd66cee5bb93e3 100644 --- a/code/__DEFINES/interaction_flags.dm +++ b/code/__DEFINES/interaction_flags.dm @@ -26,6 +26,8 @@ #define INTERACT_ATOM_MOUSEDROP_IGNORE_USABILITY (1<<12) /// Bypass all adjacency and other checks for mouse drop #define INTERACT_ATOM_MOUSEDROP_IGNORE_CHECKS (INTERACT_ATOM_MOUSEDROP_IGNORE_ADJACENT | INTERACT_ATOM_MOUSEDROP_IGNORE_USABILITY) +/// calls try_interact() on attack_paw() and returns that. +#define INTERACT_ATOM_ATTACK_PAW (1<<13) /// attempt pickup on attack_hand for items #define INTERACT_ITEM_ATTACK_HAND_PICKUP (1<<0) diff --git a/code/__DEFINES/inventory.dm b/code/__DEFINES/inventory.dm index f915b0f66a7c51..63054e533b1bf0 100644 --- a/code/__DEFINES/inventory.dm +++ b/code/__DEFINES/inventory.dm @@ -106,6 +106,8 @@ DEFINE_BITFIELD(no_equip_flags, list( #define HIDESNOUT (1<<12) ///hides mutant/moth wings, does not apply to functional wings #define HIDEMUTWINGS (1<<13) +///hides belts and riggings +#define HIDEBELT (1<<14) //bitflags for clothing coverage - also used for limbs #define HEAD (1<<0) diff --git a/code/__DEFINES/maps.dm b/code/__DEFINES/maps.dm index c76ba609113556..3c87195e99076c 100644 --- a/code/__DEFINES/maps.dm +++ b/code/__DEFINES/maps.dm @@ -222,3 +222,13 @@ Always compile, always use that verb, and always make sure that it works for wha /// Checks the job changes in the map config for the passed change key. #define CHECK_MAP_JOB_CHANGE(job, change) SSmapping.config.job_changes?[job]?[change] + +///Identifiers for away mission spawnpoints +#define AWAYSTART_BEACH "AWAYSTART_BEACH" +#define AWAYSTART_MUSEUM "AWAYSTART_MUSEUM" +#define AWAYSTART_RESEARCH "AWAYSTART_RESEARCH" +#define AWAYSTART_CAVES "AWAYSTART_CAVES" +#define AWAYSTART_MOONOUTPOST "AWAYSTART_MOONOUTPOST" +#define AWAYSTART_SNOWCABIN "AWAYSTART_SNOWCABIN" +#define AWAYSTART_SNOWDIN "AWAYSTART_SNOWDIN" +#define AWAYSTART_UNDERGROUND "AWAYSTART_UNDERGROUND" diff --git a/code/__DEFINES/blackmarket.dm b/code/__DEFINES/market.dm similarity index 100% rename from code/__DEFINES/blackmarket.dm rename to code/__DEFINES/market.dm diff --git a/code/__DEFINES/mining.dm b/code/__DEFINES/mining.dm index 5b612b4b7bcaca..d0fa97062b1a20 100644 --- a/code/__DEFINES/mining.dm +++ b/code/__DEFINES/mining.dm @@ -9,6 +9,7 @@ #define MAX_BOULDERS_PER_VENT 10 /// Time multiplier #define INATE_BOULDER_SPEED_MULTIPLIER 3 + // Vent type /// Large vents, giving large boulders. #define LARGE_VENT_TYPE "large" @@ -17,6 +18,14 @@ /// Small vents, giving small boulders. #define SMALL_VENT_TYPE "small" +// Timers for the ore vents to perform wave defense. +/// Duration for wave defense for a small vent. +#define WAVE_DURATION_SMALL 60 SECONDS +/// Duration for wave defense for a medium vent. +#define WAVE_DURATION_MEDIUM 90 SECONDS +/// Duration for wave defense for a large vent. +#define WAVE_DURATION_LARGE 150 SECONDS + /// Proximity to a vent that a wall ore needs to be for 5 ore to be mined. #define VENT_PROX_VERY_HIGH 3 /// Proximity to a vent that a wall ore needs to be for 4 ore to be mined. diff --git a/code/__DEFINES/projectiles.dm b/code/__DEFINES/projectiles.dm index ed4c66b799c590..28b7b6f3d1be56 100644 --- a/code/__DEFINES/projectiles.dm +++ b/code/__DEFINES/projectiles.dm @@ -14,8 +14,10 @@ #define CALIBER_A7MM "a7mm" /// The caliber used by the [security auto-rifle][/obj/item/gun/ballistic/automatic/wt550]. #define CALIBER_46X30MM "4.6x30mm" -/// The caliber used by the Nanotrasen Saber SMG, PP-95 SMG and Type U3 Uzi. Also used as the default caliber for pistols but only the stechkin APS machine pistol doesn't override it. +/// The caliber used by the Nanotrasen Saber SMG and Type U3 Uzi. Also used as the default caliber for pistols but only the stechkin APS machine pistol doesn't override it. #define CALIBER_9MM "9mm" +/// The caliber used by smart SMG ammunition +#define CALIBER_160SMART ".160 Smart" /// The caliber used as the default for ballistic guns. Only not overridden for the [surplus rifle][/obj/item/gun/ballistic/automatic/surplus]. #define CALIBER_10MM "10mm" /// The caliber used by most revolver variants. diff --git a/code/__DEFINES/tgs.dm b/code/__DEFINES/tgs.dm index e2c89df90e9bfd..17464b44dae81d 100644 --- a/code/__DEFINES/tgs.dm +++ b/code/__DEFINES/tgs.dm @@ -1,6 +1,6 @@ // tgstation-server DMAPI -#define TGS_DMAPI_VERSION "7.1.2" +#define TGS_DMAPI_VERSION "7.1.3" // All functions and datums outside this document are subject to change with any version and should not be relied on. diff --git a/code/__DEFINES/traits/declarations.dm b/code/__DEFINES/traits/declarations.dm index 5293298457b086..294d32ddc3b0f3 100644 --- a/code/__DEFINES/traits/declarations.dm +++ b/code/__DEFINES/traits/declarations.dm @@ -225,6 +225,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_REVEAL_FISH "reveal_fish" ///This trait gets you a list of fishes that can be caught when examining a fishing spot. #define TRAIT_EXAMINE_FISHING_SPOT "examine_fishing_spot" +///lobstrosities and carps will prioritize/flee from those that have this trait (given by the skill-locked hat) +#define TRAIT_SCARY_FISHERMAN "scary_fisherman" ///Trait given to turfs or objects that can be fished from #define TRAIT_FISHING_SPOT "fishing_spot" ///Trait given to mobs that can fish without a rod @@ -747,6 +749,8 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai #define TRAIT_GREAT_QUALITY_BAIT "great_quality_bait" /// Baits with this trait will ignore bait preferences and related fish traits. #define TRAIT_OMNI_BAIT "omni_bait" +/// The bait won't be consumed when used +#define TRAIT_BAIT_UNCONSUMABLE "bait_unconsumabe" /// Plants that were mutated as a result of passive instability, not a mutation threshold. #define TRAIT_PLANT_WILDMUTATE "wildmutation" /// If you hit an APC with exposed internals with this item it will try to shock you @@ -1123,6 +1127,9 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai ///Trait given to limb by /mob/living/basic/living_limb_flesh #define TRAIT_IGNORED_BY_LIVING_FLESH "livingflesh_ignored" +///Trait given to organs that have been inside a living being previously +#define TRAIT_USED_ORGAN "used_organ" + /// Trait given while using /datum/action/cooldown/mob_cooldown/wing_buffet #define TRAIT_WING_BUFFET "wing_buffet" /// Trait given while tired after using /datum/action/cooldown/mob_cooldown/wing_buffet @@ -1214,11 +1221,13 @@ Remember to update _globalvars/traits.dm if you're adding/removing/renaming trai ///Trait given to a turf that should not be allowed to be terraformed, such as turfs holding ore vents. #define TRAIT_NO_TERRAFORM "no_terraform" +///Mobs with these trait do not get italicized/quiet speech when speaking in low pressure +#define TRAIT_SPEECH_BOOSTER "speech_booster" + /// Given to a mob that can throw to make them not able to throw #define TRAIT_NO_THROWING "no_throwing" ///Trait which allows mobs to parry mining mob projectiles #define TRAIT_MINING_PARRYING "mining_parrying" - // END TRAIT DEFINES diff --git a/code/__DEFINES/uplink.dm b/code/__DEFINES/uplink.dm index 67df6fc0e62957..929b558dfec475 100644 --- a/code/__DEFINES/uplink.dm +++ b/code/__DEFINES/uplink.dm @@ -36,9 +36,12 @@ /// Typepath used for uplink items which don't actually produce an item (essentially just a placeholder) /// Future todo: Make this not necessary / make uplink items support item-less items natively -#define ABSTRACT_UPLINK_ITEM /obj/effect/gibspawner/generic +#define ABSTRACT_UPLINK_ITEM /obj/item/loot_table_maker /// Lower threshold for which an uplink items's TC cost is considered "low" for spy bounties picking rewards #define SPY_LOWER_COST_THRESHOLD 5 /// Upper threshold for which an uplink items's TC cost is considered "high" for spy bounties picking rewards #define SPY_UPPER_COST_THRESHOLD 12 + +/// Minimal cost for an item to be eligible for a discount +#define TRAITOR_DISCOUNT_MIN_PRICE 4 diff --git a/code/__HELPERS/_auxtools_api.dm b/code/__HELPERS/_auxtools_api.dm index 0117ded4c51951..a907be8ecf8fb1 100644 --- a/code/__HELPERS/_auxtools_api.dm +++ b/code/__HELPERS/_auxtools_api.dm @@ -1,38 +1,3 @@ -#define AUXTOOLS_FULL_INIT 2 -#define AUXTOOLS_PARTIAL_INIT 1 - -GLOBAL_LIST_EMPTY(auxtools_initialized) -GLOBAL_PROTECT(auxtools_initialized) - -#define AUXTOOLS_CHECK(LIB)\ - if (!CONFIG_GET(flag/auxtools_enabled)) {\ - CRASH("Auxtools is not enabled in config!");\ - }\ - if (GLOB.auxtools_initialized[LIB] != AUXTOOLS_FULL_INIT) {\ - if (fexists(LIB)) {\ - var/string = call_ext(LIB,"auxtools_init")();\ - if(findtext(string, "SUCCESS")) {\ - GLOB.auxtools_initialized[LIB] = AUXTOOLS_FULL_INIT;\ - } else {\ - CRASH(string);\ - }\ - } else {\ - CRASH("No file named [LIB] found!")\ - }\ - }\ - -#define AUXTOOLS_SHUTDOWN(LIB)\ - if (GLOB.auxtools_initialized[LIB] == AUXTOOLS_FULL_INIT && fexists(LIB)){\ - call_ext(LIB,"auxtools_shutdown")();\ - GLOB.auxtools_initialized[LIB] = AUXTOOLS_PARTIAL_INIT;\ - }\ - -#define AUXTOOLS_FULL_SHUTDOWN(LIB)\ - if (GLOB.auxtools_initialized[LIB] && fexists(LIB)){\ - call_ext(LIB,"auxtools_full_shutdown")();\ - GLOB.auxtools_initialized[LIB] = FALSE;\ - } - /proc/auxtools_stack_trace(msg) CRASH(msg) diff --git a/code/__HELPERS/_dreamluau.dm b/code/__HELPERS/_dreamluau.dm new file mode 100644 index 00000000000000..196774d6a88e8e --- /dev/null +++ b/code/__HELPERS/_dreamluau.dm @@ -0,0 +1,297 @@ +/* This comment bypasses grep checks */ /var/__dreamluau + +#define DREAMLUAU (world.system_type == MS_WINDOWS ? "dreamluau.dll" : (__dreamluau || (__dreamluau = __detect_auxtools("dreamluau")))) + +#define DREAMLUAU_CALL(func) call_ext(DREAMLUAU, "byond:[#func]") + +/** + * All of the following functions will return a string if the underlying rust code returns an error or a wrapped panic. + * The return values specified for each function are what they will return if successful. + */ + +/** + * As of 515.1631, byondapi does not provide direct access to `usr`. + * Use this function to pass `usr` into the dreamluau binary so that luau scripts can retrieve it. + * + * @return null on success + */ +#define DREAMLUAU_SET_USR DREAMLUAU_CALL(set_usr)(usr) + + +/** + * Sets the execution limit, in milliseconds. + * + * @param limit the new execution limit + * + * @return null on success + */ +#define DREAMLUAU_SET_EXECUTION_LIMIT_MILLIS(limit) DREAMLUAU_CALL(set_execution_limit_millis)((limit)) + +/** + * Sets the execution limit, in seconds. + * + * @param limit the new execution limit + * + * @return null on success + */ +#define DREAMLUAU_SET_EXECUTION_LIMIT_SECS(limit) DREAMLUAU_CALL(set_execution_limit_secs)((limit)) + +/** + * Clears the execution limit, allowing scripts to run as long as they need to. + * + * WARNING: This allows infinite loops to block Dream Daemon indefinitely, with no safety checks. + * Do not use this if you have no reason for scripts to run arbitrarily long. + * + * @return null on success + */ +#define DREAMLUAU_CLEAR_EXECUTION_LIMIT DREAMLUAU_CALL(clear_execution_limit) + +//Wrapper setters/clearers + +/** + * Set the wrapper for instancing new datums with `dm.new`. + * Clears it if the argument is null. + * If unset, the object will be instantiated using the default `new` instruction. + * + * The wrapper must be a proc with the signature `(type as path, list/arguments)`. + * + * @param wrapper the path to the proc to use as the new wrapper + * + * @return null on success + */ +#define DREAMLUAU_SET_NEW_WRAPPER(wrapper) DREAMLUAU_CALL(set_new_wrapper)((wrapper)) + +/** + * Set the wrapper for reading the vars of an object. + * Clears it if the argument is null. + * If unset, the var will be read directly, without any safety checks. + * + * The wrapper must be a proc with the signature `(target, var)`. + * + * @param wrapper the path to the proc to use as the new wrapper + * + * @return null on success + */ +#define DREAMLUAU_SET_VAR_GET_WRAPPER(wrapper) DREAMLUAU_CALL(set_var_get_wrapper)((wrapper)) + +/** + * Set the wrapper for writing the vars of an object. + * Clears it if the argument is null. + * If unset, the var will be modified directly, without any safety checks. + * + * The wrapper must be a proc with the signature `(target, var, value)`. + * + * @param wrapper the path to the proc to use as the new wrapper + * + * @return null on success + */ +#define DREAMLUAU_SET_VAR_SET_WRAPPER(wrapper) DREAMLUAU_CALL(set_var_set_wrapper)((wrapper)) + +/** + * Set the wrapper for calling a proc on an object. + * Clears it if the argument is null. + * If unset, the proc will be called directly, without any safety checks. + * + * The wrapper must be a proc with the signature `(target, procname as text, list/arguments)`. + * + * @param wrapper the path to the proc to use as the new wrapper + * + * @return null on success + */ +#define DREAMLUAU_SET_OBJECT_CALL_WRAPPER(wrapper) DREAMLUAU_CALL(set_object_call_wrapper)((wrapper)) + +/** + * Set the wrapper for calling a global proc. + * Clears it if the argument is null. + * If unset, the proc will be called directly, without any safety checks. + * + * The wrapper must be a proc with the signature `(procname as text, list/arguments)`. + * + * @param wrapper the path to the proc to use as the new wrapper + * + * @return null on success + */ +#define DREAMLUAU_SET_GLOBAL_CALL_WRAPPER(wrapper) DREAMLUAU_CALL(set_global_call_wrapper)((wrapper)) + +/** + * Set the wrapper for printing with the `print` function. + * Clears it if the argument is null. + * If unset, `print` will raise an error. + * + * The wrapper must be a proc with the signature `(list/arguments)`. + * + * @param wrapper the path to the proc to use as the new wrapper + * + * @return null on success + */ +#define DREAMLUAU_SET_PRINT_WRAPPER(wrapper) DREAMLUAU_CALL(set_print_wrapper)((wrapper)) + + + +/** + * Create a new luau state. + * + * @return a handle to the created state. + */ +#define DREAMLUAU_NEW_STATE DREAMLUAU_CALL(new_state) + +/** + * Some of the following functions return values that cannot be cleanly converted from luau to DM. + * To account for this, these functions also return a list of variant specifiers, equivalent to + * an array of objects of the type described beloe: + * ``` + * type Variants = { + * key?: "error"|Array + * value?: "error"|Array + * } + * ``` + */ + +/** + * The following 4 functions execute luau code and return + * an associative list containing information about the result. + * This list has the following params. + * + * - "status": either "finished", "sleep", "yield", or "error" + * - "return_values": if "status" is "finished" or "yield", contains a list of the return values + * - "variants": a list of variant specifiers for the "return_values" param + * - "message": if "status" is "error", contains the error message + * - "name": the name of the executed code, according to the `what` field of `debug.getinfo` + */ + +/** + * Load and execute a luau script. + * + * @param state the handle to the state + * @param code the source code of the script to run + * @param name an optional name to give to the script, for debugging purposes + * + * @return an associative list containing result information as specified above + */ +#define DREAMLUAU_LOAD DREAMLUAU_CALL(load) + +/** + * Awaken the thread at the front of the specified state's sleeping thread queue. + * + * @param state the handle to the state + * + * @return an associative list containing result information as specified above + */ +#define DREAMLUAU_AWAKEN(state) DREAMLUAU_CALL(awaken)((state)) + +/** + * Resume one of the state's yielded threads. + * + * @param state the handle to the state + * @param index the index of the thread in the state's yielded threads list + * @param ...arguments arguments that will be returned by the `coroutine.yield` that yielded the thread + * + * @return an associative list containing result information as specified above + */ +#define DREAMLUAU_RESUME DREAMLUAU_CALL(resume) + +/** + * Call a function accessible from the global table. + * + * @param state the handle to the state + * @param function a list of nested indices from the global table to the specified function + * @param ...arguments arguments to pass to the function + * + * @return an associative list containing result information as specified above + */ +#define DREAMLUAU_CALL_FUNCTION DREAMLUAU_CALL(call_function) + +// State information collection functions + +/** + * Obtain a copy of the state's global table, converted to DM. + * + * @param state the handle to the state + * + * @return an associative list with the follwing entries: + * - "values": The actual values of the global table + * - "variants": Variant specifiers for "values" + */ +#define DREAMLUAU_GET_GLOBALS(state) DREAMLUAU_CALL(get_globals)((state)) + +/** + * List the names of all sleeping or yielded threads for the state. + * + * @param state the handle to the state + * + * @return an associative list with the following entries: + * - "sleeps": A list of sleeping threads + * - "yields": A list of yielded threads + */ +#define DREAMLUAU_LIST_THREADS(state) DREAMLUAU_CALL(list_threads)((state)) + +// Cleanup functions + +/** + * Run garbage collection on the state. + * + * This may be necessary to prevent hanging references, as some + * hard references may persist in unreachable luau objects that + * would be collected after a garbage collection cycle or two. + * + * @param state the handle to the state + * + * @return null on success + */ +#define DREAMLUAU_COLLECT_GARBAGE(state) DREAMLUAU_CALL(collect_garbage)((state)) + +/** + * Remove a sleeping thread from the sleep queue, without executing it. + * + * @param state the handle to the state + * @param thread the index in the sleep queue to the target thread + * + * @return null on success + */ +#define DREAMLUAU_KILL_SLEEPING_THREAD(state, thread) DREAMLUAU_CALL(kill_sleeping_thread)((state), (thread)) + +/** + * Remove a yielded thread from the yield table, without executing it. + * + * @param state the handle to the state + * @param thread the index in the yield table to the target thread + * + * @return null on success + */ +#define DREAMLUAU_KILL_YIELDED_THREAD(state, thread) DREAMLUAU_CALL(kill_yielded_thread)((state), (thread)) + +/** + * Delete a state. The state's handle will be freed for any new states created afterwards. + * + * @param state the handle to the state + * + * @return null on success + */ +#define DREAMLUAU_KILL_STATE(state) DREAMLUAU_CALL(kill_state)((state)) + +/** + * Retrieve lua traceback info, containing every lua stack frame between the lua entrypoint and the re-entry to dm code. + * + * @param level the level of lua execution to get the traceback for, + * with 1 being the lua code that executed the dm code that called this function, + * 2 being the lua code that executed the dm code that executed the lua code + * that executed the dm code that called this function, etc. + * + * @return the callstack of the specified lua level if valid, null if invalid + */ +#define DREAMLUAU_GET_TRACEBACK(index) DREAMLUAU_CALL(get_traceback)((index)) + +/** + * Luau userdata corresponding to a ref-counted DM type counts as a hard reference for BYOND's garbage collector. + * If you need to delete a DM object, and you cannot be certain that there are no references to it in any luau state, + * call this function before deleting that object to disassociate it from any userdata in any luau state. + * + * Hard deleting an object without clearing userdata corresponding to it leaves the userdata to become associated with + * the next DM object to receive the old object's reference ID, which may be undesirable behavior. + * + * @param object the object to disassociate from userdata. + * + * @return null on success + */ +#define DREAMLUAU_CLEAR_REF_USERDATA(object) DREAMLUAU_CALL(clear_ref_userdata)((object)) + diff --git a/code/__HELPERS/_lists.dm b/code/__HELPERS/_lists.dm index 157a17012a883b..f8a0dc6d7d5519 100644 --- a/code/__HELPERS/_lists.dm +++ b/code/__HELPERS/_lists.dm @@ -978,53 +978,57 @@ else return element -/// Returns a copy of the list where any element that is a datum or the world is converted into a ref -/proc/refify_list(list/target_list, list/visited, path_accumulator = "list") +/** + * Intermediate step for preparing lists to be passed into the lua editor tgui. + * Resolves weakrefs, converts some values without a standard textual representation to text, + * and can handle self-referential lists and potential duplicate output keys. + */ +/proc/prepare_lua_editor_list(list/target_list, list/visited) if(!visited) visited = list() var/list/ret = list() - visited[target_list] = path_accumulator + visited[target_list] = ret + var/list/duplicate_keys = list() for(var/i in 1 to target_list.len) var/key = target_list[i] var/new_key = key if(isweakref(key)) var/datum/weakref/ref = key - var/resolved = ref.resolve() - if(resolved) - new_key = "[resolved] [REF(resolved)]" - else - new_key = "null weakref [REF(key)]" - else if(isdatum(key)) - new_key = "[key] [REF(key)]" + new_key = ref.resolve() || "null weakref" else if(key == world) - new_key = "world [REF(world)]" + new_key = world.name + else if(ref(key) == "\[0xe000001\]") + new_key = "global" else if(islist(key)) - if(visited.Find(key)) + if(visited[key]) new_key = visited[key] else - new_key = refify_list(key, visited, path_accumulator + "\[[i]\]") + new_key = prepare_lua_editor_list(key, visited) var/value - if(istext(key) || islist(key) || ispath(key) || isdatum(key) || key == world) + if(!isnull(key) && !isnum(key)) value = target_list[key] if(isweakref(value)) var/datum/weakref/ref = value - var/resolved = ref.resolve() - if(resolved) - value = "[resolved] [REF(resolved)]" - else - value = "null weakref [REF(key)]" - else if(isdatum(value)) - value = "[value] [REF(value)]" - else if(value == world) - value = "world [REF(world)]" + value = ref.resolve() || "null weakref" + if(value == world) + value = "world" + else if(ref(value) == "\[0xe000001\]") + value = "global" else if(islist(value)) - if(visited.Find(value)) + if(visited[value]) value = visited[value] else - value = refify_list(value, visited, path_accumulator + "\[[key]\]") - var/list/to_add = list(new_key) - if(value) - to_add[new_key] = value + value = prepare_lua_editor_list(value, visited) + var/list/to_add = list() + if(!isnull(value)) + var/final_key = new_key + while(duplicate_keys[final_key]) + duplicate_keys[new_key]++ + final_key = "[new_key] ([duplicate_keys[new_key]])" + duplicate_keys[final_key] = 1 + to_add[final_key] = value + else + to_add += list(new_key) ret += to_add if(i < target_list.len) CHECK_TICK @@ -1033,29 +1037,31 @@ /** * Converts a list into a list of assoc lists of the form ("key" = key, "value" = value) * so that list keys that are themselves lists can be fully json-encoded + * and that unique objects with the same string representation do not + * produce duplicate keys that are clobbered by the standard JavaScript JSON.parse function */ -/proc/kvpify_list(list/target_list, depth = INFINITY, list/visited, path_accumulator = "list") +/proc/kvpify_list(list/target_list, depth = INFINITY, list/visited) if(!visited) visited = list() var/list/ret = list() - visited[target_list] = path_accumulator + visited[target_list] = ret for(var/i in 1 to target_list.len) var/key = target_list[i] var/new_key = key if(islist(key) && depth) - if(visited.Find(key)) + if(visited[key]) new_key = visited[key] else - new_key = kvpify_list(key, depth-1, visited, path_accumulator + "\[[i]\]") + new_key = kvpify_list(key, depth-1, visited) var/value - if(istext(key) || islist(key) || ispath(key) || isdatum(key) || key == world) + if(!isnull(key) && !isnum(key)) value = target_list[key] if(islist(value) && depth) - if(visited.Find(value)) + if(visited[value]) value = visited[value] else - value = kvpify_list(value, depth-1, visited, path_accumulator + "\[[key]\]") - if(value) + value = kvpify_list(value, depth-1, visited) + if(!isnull(value)) ret += list(list("key" = new_key, "value" = value)) else ret += list(list("key" = i, "value" = new_key)) @@ -1065,12 +1071,12 @@ /// Compares 2 lists, returns TRUE if they are the same /proc/deep_compare_list(list/list_1, list/list_2) - if(!islist(list_1) || !islist(list_2)) - return FALSE - if(list_1 == list_2) return TRUE + if(!islist(list_1) || !islist(list_2)) + return FALSE + if(list_1.len != list_2.len) return FALSE @@ -1093,11 +1099,11 @@ return TRUE /// Returns a copy of the list where any element that is a datum is converted into a weakref -/proc/weakrefify_list(list/target_list, list/visited, path_accumulator = "list") +/proc/weakrefify_list(list/target_list, list/visited) if(!visited) visited = list() var/list/ret = list() - visited[target_list] = path_accumulator + visited[target_list] = ret for(var/i in 1 to target_list.len) var/key = target_list[i] var/new_key = key @@ -1107,62 +1113,19 @@ if(visited.Find(key)) new_key = visited[key] else - new_key = weakrefify_list(key, visited, path_accumulator + "\[[i]\]") + new_key = weakrefify_list(key, visited) var/value - if(istext(key) || islist(key) || ispath(key) || isdatum(key) || key == world) + if(!isnull(key) && !isnum(key)) value = target_list[key] if(isdatum(value)) value = WEAKREF(value) else if(islist(value)) - if(visited.Find(value)) + if(visited[value]) value = visited[value] else - value = weakrefify_list(value, visited, path_accumulator + "\[[key]\]") - var/list/to_add = list(new_key) - if(value) - to_add[new_key] = value - ret += to_add - if(i < target_list.len) - CHECK_TICK - return ret - -/// Returns a copy of a list where text values (except assoc-keys and string representations of lua-only values) are -/// wrapped in quotes and existing quote marks are escaped, -/// and nulls are replaced with the string "null" -/proc/encode_text_and_nulls(list/target_list, list/visited) - var/static/regex/lua_reference_regex - if(!lua_reference_regex) - lua_reference_regex = regex(@"^((function)|(table)|(thread)|(userdata)): 0x[0-9a-fA-F]+$") - if(!visited) - visited = list() - var/list/ret = list() - visited[target_list] = TRUE - for(var/i in 1 to target_list.len) - var/key = target_list[i] - var/new_key = key - if(istext(key) && !target_list[key] && !lua_reference_regex.Find(key)) - new_key = "\"[replacetext(key, "\"", "\\\"")]\"" - else if(islist(key)) - var/found_index = visited.Find(key) - if(found_index) - new_key = visited[found_index] - else - new_key = encode_text_and_nulls(key, visited) - else if(isnull(key)) - new_key = "null" - var/value - if(istext(key) || islist(key) || ispath(key) || isdatum(key) || key == world) - value = target_list[key] - if(istext(value) && !lua_reference_regex.Find(value)) - value = "\"[replacetext(value, "\"", "\\\"")]\"" - else if(islist(value)) - var/found_index = visited.Find(value) - if(found_index) - value = visited[found_index] - else - value = encode_text_and_nulls(value, visited) + value = weakrefify_list(value, visited) var/list/to_add = list(new_key) - if(value) + if(!isnull(value)) to_add[new_key] = value ret += to_add if(i < target_list.len) @@ -1188,3 +1151,155 @@ if("x" in coords) return locate(coords["x"], coords["y"], coords["z"]) return locate(coords[1], coords[2], coords[3]) + +/** + * Given a list and a list of its variant hints, appends variants that aren't explicitly required by dreamluau, + * but are required by the lua editor tgui. + */ +/proc/add_lua_editor_variants(list/values, list/variants, list/visited, path = "") + if(!islist(visited)) + visited = list() + visited[values] = "\[\]" + if(!islist(values) || !islist(variants)) + return + if(values.len != variants.len) + CRASH("values and variants must be the same length") + for(var/i in 1 to variants.len) + var/pair = variants[i] + var/pair_modified = FALSE + if(isnull(pair)) + pair = list("key", "value") + var/key = values[i] + if(islist(key)) + if(visited[key]) + pair["key"] = list("cycle", visited[key]) + else + var/list/key_variants = pair["key"] + var/new_path = path + "\[[i], \"key\"\]," + visited[key] = new_path + add_lua_editor_variants(key, key_variants, visited, new_path) + visited -= key + pair["key"] = list("list", key_variants) + pair_modified = TRUE + else if(isdatum(key) || key == world || ref(key) == "\[0xe000001\]") + pair["key"] = list("ref", ref(key)) + pair_modified = TRUE + var/value + if(!isnull(key) && !isnum(key)) + value = values[key] + if(islist(value)) + if(visited[value]) + pair["value"] = list("cycle", visited[value]) + else + var/list/value_variants = pair["value"] + var/new_path = path + "\[[i], \"value\"\]," + visited[value] = new_path + add_lua_editor_variants(value, value_variants, visited, new_path) + visited -= value + pair["value"] = list("list", value_variants) + pair_modified = TRUE + else if(isdatum(value) || value == world || ref(value) == "\[0xe000001\]") + pair["value"] = list("ref", ref(value)) + pair_modified = TRUE + if(pair_modified && pair != variants[i]) + variants[i] = pair + if(i < variants.len) + CHECK_TICK + +/proc/add_lua_return_value_variants(list/values, list/variants) + if(!islist(values) || !islist(variants)) + return + if(values.len != variants.len) + CRASH("values and variants must be the same length") + for(var/i in 1 to values.len) + var/value = values[i] + if(islist(value)) + add_lua_editor_variants(value, variants[i]) + else if(isdatum(value) || value == world || ref(value) == "\[0xe000001\]") + variants[i] = list("ref", ref(value)) + +/proc/deep_copy_without_cycles(list/values, list/visited) + if(!islist(visited)) + visited = list() + if(!islist(values)) + return values + var/list/ret = list() + var/cycle_count = 0 + visited[values] = TRUE + for(var/i in 1 to values.len) + var/key = values[i] + var/out_key = key + if(islist(key)) + if(visited[key]) + do + out_key = "\[cyclical reference[cycle_count ? " (i)" : ""]\]" + cycle_count++ + while(values.Find(out_key)) + else + visited[key] = TRUE + out_key = deep_copy_without_cycles(key, visited) + visited -= key + var/value + if(!isnull(key) && !isnum(key)) + value = values[key] + var/out_value = value + if(islist(value)) + if(visited[value]) + out_value = "\[cyclical reference\]" + else + visited[value] = TRUE + out_value = deep_copy_without_cycles(value, visited) + visited -= value + var/list/to_add = list(out_key) + if(!isnull(out_value)) + to_add[out_key] = out_value + ret += to_add + if(i < values.len) + CHECK_TICK + return ret + +/** + * Given a list and a list of its variant hints, removes any list key/values that are represent lua values that could not be directly converted to DM. + */ +/proc/remove_non_dm_variants(list/return_values, list/variants, list/visited) + if(!islist(visited)) + visited = list() + if(!islist(return_values) || !islist(variants) || visited[return_values]) + return + visited[return_values] = TRUE + if(return_values.len != variants.len) + CRASH("return_values and variants must be the same length") + for(var/i in 1 to variants.len) + var/pair = variants[i] + if(!islist(variants)) + continue + var/key = return_values[i] + if(pair["key"]) + if(!islist(pair["key"])) + return_values[i] = null + continue + remove_non_dm_variants(key, pair["key"], visited) + if(pair["value"]) + if(!islist(pair["value"])) + return_values[key] = null + continue + remove_non_dm_variants(return_values[key], pair["value"], visited) + +/proc/compare_lua_logs(list/log_1, list/log_2) + if(log_1 == log_2) + return TRUE + for(var/field in list("status", "name", "message", "chunk")) + if(log_1[field] != log_2[field]) + return FALSE + switch(log_1["status"]) + if("finished", "yield") + return deep_compare_list( + recursive_list_resolve(log_1["return_values"]), + recursive_list_resolve(log_2["return_values"]) + ) && deep_compare_list(log_1["variants"], log_2["variants"]) + if("runtime") + return log_1["file"] == log_2["file"]\ + && log_1["line"] == log_2["line"]\ + && deep_compare_list(log_1["stack"], log_2["stack"]) + else + return TRUE diff --git a/code/__HELPERS/colors.dm b/code/__HELPERS/colors.dm index 9c70cef798eacd..3a20e5ad60c092 100644 --- a/code/__HELPERS/colors.dm +++ b/code/__HELPERS/colors.dm @@ -101,5 +101,50 @@ return output +/** + * Gets a color for a name, will return the same color for a given string consistently within a round.atom + * + * Note that this proc aims to produce pastel-ish colors using the HSL colorspace. These seem to be favorable for displaying on the map. + * + * Arguments: + * * name - The name to generate a color for + * * sat_shift - A value between 0 and 1 that will be multiplied against the saturation + * * lum_shift - A value between 0 and 1 that will be multiplied against the luminescence + */ +/proc/colorize_string(name, sat_shift = 1, lum_shift = 1) + // seed to help randomness + var/static/rseed = rand(1,26) + + // get hsl using the selected 6 characters of the md5 hash + var/hash = copytext(md5(name + GLOB.round_id), rseed, rseed + 6) + var/h = hex2num(copytext(hash, 1, 3)) * (360 / 255) + var/s = (hex2num(copytext(hash, 3, 5)) >> 2) * ((CM_COLOR_SAT_MAX - CM_COLOR_SAT_MIN) / 63) + CM_COLOR_SAT_MIN + var/l = (hex2num(copytext(hash, 5, 7)) >> 2) * ((CM_COLOR_LUM_MAX - CM_COLOR_LUM_MIN) / 63) + CM_COLOR_LUM_MIN + + // adjust for shifts + s = clamp(s * sat_shift, 0, 1) + l = clamp(l * lum_shift, 0, 1) + + // convert to rgb + var/h_int = round(h/60) // mapping each section of H to 60 degree sections + var/c = (1 - abs(2 * l - 1)) * s + var/x = c * (1 - abs((h / 60) % 2 - 1)) + var/m = l - c * 0.5 + x = (x + m) * 255 + c = (c + m) * 255 + m *= 255 + switch(h_int) + if(0) + return "#[num2hex(c, 2)][num2hex(x, 2)][num2hex(m, 2)]" + if(1) + return "#[num2hex(x, 2)][num2hex(c, 2)][num2hex(m, 2)]" + if(2) + return "#[num2hex(m, 2)][num2hex(c, 2)][num2hex(x, 2)]" + if(3) + return "#[num2hex(m, 2)][num2hex(x, 2)][num2hex(c, 2)]" + if(4) + return "#[num2hex(x, 2)][num2hex(m, 2)][num2hex(c, 2)]" + if(5) + return "#[num2hex(c, 2)][num2hex(m, 2)][num2hex(x, 2)]" #define RANDOM_COLOUR (rgb(rand(0,255),rand(0,255),rand(0,255))) diff --git a/code/__HELPERS/game.dm b/code/__HELPERS/game.dm index aa953760bce714..ce48e593980b50 100644 --- a/code/__HELPERS/game.dm +++ b/code/__HELPERS/game.dm @@ -214,16 +214,16 @@ if(istype(atom_to_find, type)) return atom_to_find - while(!istype(atom_to_find.loc, type)) + while(!istype(atom_to_find, type)) if(!atom_to_find.loc) return atom_to_find = atom_to_find.loc else if(isatom(type)) atom_to_find = target - if(atom_to_find.loc == type) + if(atom_to_find == type) return atom_to_find - while(atom_to_find.loc != type) + while(atom_to_find != type) if(!atom_to_find.loc) return atom_to_find = atom_to_find.loc diff --git a/code/__HELPERS/matrices.dm b/code/__HELPERS/matrices.dm index 68b94fc2fe654a..8a5534e3827b82 100644 --- a/code/__HELPERS/matrices.dm +++ b/code/__HELPERS/matrices.dm @@ -40,8 +40,7 @@ decompose_matrix.rotation = arctan(cossine, sine) * flip_sign /matrix/proc/TurnTo(old_angle, new_angle) - . = new_angle - old_angle - Turn(.) //BYOND handles cases such as -270, 360, 540 etc. DOES NOT HANDLE 180 TURNS WELL, THEY TWEEN AND LOOK LIKE SHIT + return Turn(new_angle - old_angle) //BYOND handles cases such as -270, 360, 540 etc. DOES NOT HANDLE 180 TURNS WELL, THEY TWEEN AND LOOK LIKE SHIT /** * Shear the transform on either or both axes. diff --git a/code/__HELPERS/spawns.dm b/code/__HELPERS/spawns.dm index 2c93e4ba19e56d..c72c5a555de5a7 100644 --- a/code/__HELPERS/spawns.dm +++ b/code/__HELPERS/spawns.dm @@ -29,7 +29,13 @@ if(!ispath(path)) path.forceMove(pod) else - path = new path(pod) + var/amount_to_spawn = paths_to_spawn[path] || 1 + if(!isnum(amount_to_spawn)) + stack_trace("amount to spawn for path \"[path]\" is not a number, defaulting to 1") + amount_to_spawn = 1 + + for(var/item_number in 1 to amount_to_spawn) + new path(pod) //remove non var edits from specifications specifications -= "target" diff --git a/code/__HELPERS/text.dm b/code/__HELPERS/text.dm index b8e0113696ad22..feea67939f836f 100644 --- a/code/__HELPERS/text.dm +++ b/code/__HELPERS/text.dm @@ -121,7 +121,7 @@ if(isnull(user_input)) // User pressed cancel return if(no_trim) - return copytext(html_encode(user_input), 1, max_length) + return copytext_char(html_encode(user_input), 1, max_length) else return trim(html_encode(user_input), max_length) //trim is "outside" because html_encode can expand single symbols into multiple symbols (such as turning < into <) @@ -140,7 +140,7 @@ if(isnull(user_input)) // User pressed cancel return if(no_trim) - return copytext(html_encode(user_input), 1, max_length) + return copytext_char(html_encode(user_input), 1, max_length) else return trim(html_encode(user_input), max_length) @@ -368,7 +368,7 @@ */ /proc/truncate(text, max_length) if(length(text) > max_length) - return copytext(text, 1, max_length) + return copytext_char(text, 1, max_length) return text //Returns a string with reserved characters and spaces before the first word and after the last word removed. @@ -1228,6 +1228,13 @@ GLOBAL_LIST_INIT(binary, list("0","1")) var/input_length = LAZYLEN(ending) return !!findtext(input_text, ending, -input_length) +/// Returns TRUE if the input_text starts with any of the beginnings +/proc/starts_with_any(input_text, list/beginnings) + for(var/beginning in beginnings) + if(!!findtext(input_text, beginning, 1, LAZYLEN(beginning)+1)) + return TRUE + return FALSE + /// Generate a grawlix string of length of the text argument. /proc/grawlix(text) var/grawlix = "" diff --git a/code/_globalvars/bitfields.dm b/code/_globalvars/bitfields.dm index ea1b16d71cef86..27c0d27ec2e92b 100644 --- a/code/_globalvars/bitfields.dm +++ b/code/_globalvars/bitfields.dm @@ -64,6 +64,7 @@ DEFINE_BITFIELD(area_flags, list( "UNIQUE_AREA" = UNIQUE_AREA, "VALID_TERRITORY" = VALID_TERRITORY, "XENOBIOLOGY_COMPATIBLE" = XENOBIOLOGY_COMPATIBLE, + "NO_BOH" = NO_BOH, )) DEFINE_BITFIELD(turf_flags, list( @@ -199,6 +200,7 @@ DEFINE_BITFIELD(flags_inv, list( "HIDEHEADGEAR" = HIDEHEADGEAR, "HIDEJUMPSUIT" = HIDEJUMPSUIT, "HIDEMASK" = HIDEMASK, + "HIDEBELT" = HIDEBELT, "HIDENECK" = HIDENECK, "HIDESHOES" = HIDESHOES, "HIDESNOUT" = HIDESNOUT, diff --git a/code/_globalvars/lists/ambience.dm b/code/_globalvars/lists/ambience.dm index 6dd4935817fea9..12a389cf081f84 100644 --- a/code/_globalvars/lists/ambience.dm +++ b/code/_globalvars/lists/ambience.dm @@ -127,6 +127,11 @@ GLOBAL_LIST_INIT(maint_ambience,list( 'sound/ambience/ambimaint5.ogg', 'sound/ambience/ambimaint6.ogg', 'sound/ambience/ambimaint7.ogg', + 'sound/ambience/ambimaint8.ogg', + 'sound/ambience/ambimaint9.ogg', + 'sound/ambience/ambimaint10.ogg', + 'sound/ambience/ambimaint11.ogg', + 'sound/ambience/ambimaint12.ogg', 'sound/ambience/ambitech2.ogg', 'sound/voice/lowHiss1.ogg', 'sound/voice/lowHiss2.ogg', diff --git a/code/_globalvars/traits/_traits.dm b/code/_globalvars/traits/_traits.dm index d187593220ca02..dcda2365c4b0f8 100644 --- a/code/_globalvars/traits/_traits.dm +++ b/code/_globalvars/traits/_traits.dm @@ -60,6 +60,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_ODD_CUSTOMIZABLE_FOOD_INGREDIENT" = TRAIT_ODD_CUSTOMIZABLE_FOOD_INGREDIENT, "TRAIT_ON_HIT_EFFECT" = TRAIT_ON_HIT_EFFECT, "TRAIT_RUNECHAT_HIDDEN" = TRAIT_RUNECHAT_HIDDEN, + "TRAIT_SCARY_FISHERMAN" = TRAIT_SCARY_FISHERMAN, "TRAIT_SECLUDED_LOCATION" = TRAIT_SECLUDED_LOCATION, "TRAIT_SNOWSTORM_IMMUNE" = TRAIT_SNOWSTORM_IMMUNE, "TRAIT_TELEKINESIS_CONTROLLED" = TRAIT_TELEKINESIS_CONTROLLED, @@ -212,7 +213,6 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_ECHOLOCATION_RECEIVER" = TRAIT_ECHOLOCATION_RECEIVER, "TRAIT_ELDRITCH_PAINTING_EXAMINE" = TRAIT_ELDRITCH_PAINTING_EXAMINE, "TRAIT_ELITE_CHALLENGER" = TRAIT_ELITE_CHALLENGER, - "TRAIT_EMOTEMUTE " = TRAIT_EMOTEMUTE, "TRAIT_EMOTEMUTE" = TRAIT_EMOTEMUTE, "TRAIT_EMPATH" = TRAIT_EMPATH, "TRAIT_ENTRAILS_READER" = TRAIT_ENTRAILS_READER, @@ -529,10 +529,12 @@ GLOBAL_LIST_INIT(traits_by_type, list( "TRAIT_XENO_IMMUNE" = TRAIT_XENO_IMMUNE, "TRAIT_XRAY_HEARING" = TRAIT_XRAY_HEARING, "TRAIT_XRAY_VISION" = TRAIT_XRAY_VISION, + "TRAIT_SPEECH_BOOSTER" = TRAIT_SPEECH_BOOSTER, "TRAIT_MINING_PARRYING" = TRAIT_MINING_PARRYING, ), /obj/item = list( "TRAIT_APC_SHOCKING" = TRAIT_APC_SHOCKING, + "TRAIT_BAIT_UNCONSUMABLE" = TRAIT_BAIT_UNCONSUMABLE, "TRAIT_BAKEABLE" = TRAIT_BAKEABLE, "TRAIT_BASIC_QUALITY_BAIT" = TRAIT_BASIC_QUALITY_BAIT, "TRAIT_BLIND_TOOL" = TRAIT_BLIND_TOOL, @@ -609,6 +611,7 @@ GLOBAL_LIST_INIT(traits_by_type, list( ), /obj/item/organ = list( "TRAIT_LIVING_HEART" = TRAIT_LIVING_HEART, + "TRAIT_USED_ORGAN" = TRAIT_USED_ORGAN, ), /obj/item/organ/internal/liver = list( "TRAIT_BALLMER_SCIENTIST" = TRAIT_BALLMER_SCIENTIST, diff --git a/code/_globalvars/traits/admin_tooling.dm b/code/_globalvars/traits/admin_tooling.dm index 7ff9dad994ec01..98c3fd6ab1fca5 100644 --- a/code/_globalvars/traits/admin_tooling.dm +++ b/code/_globalvars/traits/admin_tooling.dm @@ -18,6 +18,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_MOVE_VENTCRAWLING" = TRAIT_MOVE_VENTCRAWLING, "TRAIT_MOVE_UPSIDE_DOWN" = TRAIT_MOVE_UPSIDE_DOWN, "TRAIT_RUNECHAT_HIDDEN" = TRAIT_RUNECHAT_HIDDEN, + "TRAIT_SCARY_FISHERMAN" = TRAIT_SCARY_FISHERMAN, "TRAIT_SNOWSTORM_IMMUNE" = TRAIT_SNOWSTORM_IMMUNE, "TRAIT_VOIDSTORM_IMMUNE" = TRAIT_VOIDSTORM_IMMUNE, "TRAIT_WEATHER_IMMUNE" = TRAIT_WEATHER_IMMUNE, @@ -29,14 +30,21 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_AGENDER" = TRAIT_AGENDER, "TRAIT_AGEUSIA" = TRAIT_AGEUSIA, "TRAIT_ALCOHOL_TOLERANCE" = TRAIT_ALCOHOL_TOLERANCE, + "TRAIT_ALLOW_HERETIC_CASTING" = TRAIT_ALLOW_HERETIC_CASTING, + "TRAIT_ALWAYS_NO_ACCESS" = TRAIT_ALWAYS_NO_ACCESS, + "TRAIT_ALWAYS_WANTED" = TRAIT_ALWAYS_WANTED, "TRAIT_ANOSMIA" = TRAIT_ANOSMIA, + "TRAIT_ANTENNAE" = TRAIT_ANTENNAE, "TRAIT_ANTIMAGIC" = TRAIT_ANTIMAGIC, + "TRAIT_ANTIMAGIC_NO_SELFBLOCK" = TRAIT_ANTIMAGIC_NO_SELFBLOCK, "TRAIT_ANXIOUS" = TRAIT_ANXIOUS, "TRAIT_BADDNA" = TRAIT_BADDNA, "TRAIT_BADTOUCH" = TRAIT_BADTOUCH, "TRAIT_BALD" = TRAIT_BALD, + "TRAIT_BALLOON_SUTRA" = TRAIT_BALLOON_SUTRA, "TRAIT_BATON_RESISTANCE" = TRAIT_BATON_RESISTANCE, "TRAIT_BEAST_EMPATHY" = TRAIT_BEAST_EMPATHY, + "TRAIT_BLOB_ALLY" = TRAIT_BLOB_ALLY, "TRAIT_BLOCK_SHUTTLE_MOVEMENT" = TRAIT_BLOCK_SHUTTLE_MOVEMENT, "TRAIT_BLOOD_CLANS" = TRAIT_BLOOD_CLANS, "TRAIT_BLOODSHOT_EYES" = TRAIT_BLOODSHOT_EYES, @@ -45,20 +53,27 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_BOOZE_SLIDER" = TRAIT_BOOZE_SLIDER, "TRAIT_BYPASS_MEASURES" = TRAIT_BYPASS_MEASURES, "TRAIT_CAN_HOLD_ITEMS" = TRAIT_CAN_HOLD_ITEMS, + "TRAIT_CAN_STRIP" = TRAIT_CAN_STRIP, + "TRAIT_CAN_USE_NUKE" = TRAIT_CAN_USE_NUKE, "TRAIT_CANNOT_BE_UNBUCKLED" = TRAIT_CANNOT_BE_UNBUCKLED, "TRAIT_CANNOT_OPEN_PRESENTS" = TRAIT_CANNOT_OPEN_PRESENTS, + "TRAIT_CATLIKE_GRACE" = TRAIT_CATLIKE_GRACE, "TRAIT_CHASM_DESTROYED" = TRAIT_CHASM_DESTROYED, "TRAIT_CHUNKYFINGERS_IGNORE_BATON" = TRAIT_CHUNKYFINGERS_IGNORE_BATON, "TRAIT_CHUNKYFINGERS" = TRAIT_CHUNKYFINGERS, + "TRAIT_CLEANBOT_WHISPERER" = TRAIT_CLEANBOT_WHISPERER, + "TRAIT_CLIFF_WALKER" = TRAIT_CLIFF_WALKER, "TRAIT_CLOWN_ENJOYER" = TRAIT_CLOWN_ENJOYER, "TRAIT_CLUMSY" = TRAIT_CLUMSY, "TRAIT_COMMISSIONED" = TRAIT_COMMISSIONED, + "TRAIT_CORPSELOCKED" = TRAIT_CORPSELOCKED, "TRAIT_CRITICAL_CONDITION" = TRAIT_CRITICAL_CONDITION, "TRAIT_CULT_HALO" = TRAIT_CULT_HALO, "TRAIT_DEAF" = TRAIT_DEAF, "TRAIT_DEATHCOMA" = TRAIT_DEATHCOMA, "TRAIT_DEFIB_BLACKLISTED" = TRAIT_DEFIB_BLACKLISTED, "TRAIT_DEPRESSION" = TRAIT_DEPRESSION, + "TRAIT_DETECT_STORM" = TRAIT_DETECT_STORM, "TRAIT_DIAGNOSTIC_HUD" = TRAIT_DIAGNOSTIC_HUD, "TRAIT_BOT_PATH_HUD" = TRAIT_BOT_PATH_HUD, "TRAIT_DISCOORDINATED_TOOL_USER" = TRAIT_DISCOORDINATED_TOOL_USER, @@ -70,42 +85,59 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_DWARF" = TRAIT_DWARF, "TRAIT_EASILY_WOUNDED" = TRAIT_EASILY_WOUNDED, "TRAIT_EASYDISMEMBER" = TRAIT_EASYDISMEMBER, - "TRAIT_EMOTEMUTE " = TRAIT_EMOTEMUTE, + "TRAIT_EMOTEMUTE" = TRAIT_EMOTEMUTE, "TRAIT_EMPATH" = TRAIT_EMPATH, + "TRAIT_ENTRAILS_READER" = TRAIT_ENTRAILS_READER, + "TRAIT_EXAMINE_FISHING_SPOT" = TRAIT_EXAMINE_FISHING_SPOT, "TRAIT_EXAMINE_FITNESS" = TRAIT_EXAMINE_FITNESS, "TRAIT_EXPANDED_FOV" = TRAIT_EXPANDED_FOV, "TRAIT_EXPERT_FISHER" = TRAIT_EXPERT_FISHER, + "TRAIT_EXTROVERT" = TRAIT_EXTROVERT, "TRAIT_FAKEDEATH" = TRAIT_FAKEDEATH, + "TRAIT_FASTMED" = TRAIT_FASTMED, "TRAIT_FAST_CUFFING" = TRAIT_FAST_CUFFING, + "TRAIT_FAST_TYING" = TRAIT_FAST_TYING, "TRAIT_FAT" = TRAIT_FAT, "TRAIT_FEARLESS" = TRAIT_FEARLESS, "TRAIT_FENCE_CLIMBER" = TRAIT_FENCE_CLIMBER, "TRAIT_FIST_MINING" = TRAIT_FIST_MINING, "TRAIT_FIXED_HAIRCOLOR" = TRAIT_FIXED_HAIRCOLOR, "TRAIT_FIXED_MUTANT_COLORS" = TRAIT_FIXED_MUTANT_COLORS, + "TRAIT_FLESH_DESIRE" = TRAIT_FLESH_DESIRE, "TRAIT_FLOORED" = TRAIT_FLOORED, + "TRAIT_FORBID_MINING_SHUTTLE_CONSOLE_OUTSIDE_STATION" = TRAIT_FORBID_MINING_SHUTTLE_CONSOLE_OUTSIDE_STATION, "TRAIT_FORCED_STANDING" = TRAIT_FORCED_STANDING, "TRAIT_FREERUNNING" = TRAIT_FREERUNNING, + "TRAIT_FREE_FLOAT_MOVEMENT" = TRAIT_FREE_FLOAT_MOVEMENT, + "TRAIT_FREE_HYPERSPACE_MOVEMENT" = TRAIT_FREE_HYPERSPACE_MOVEMENT, + "TRAIT_FREE_HYPERSPACE_SOFTCORDON_MOVEMENT" = TRAIT_FREE_HYPERSPACE_SOFTCORDON_MOVEMENT, "TRAIT_FRIENDLY" = TRAIT_FRIENDLY, "TRAIT_GAMER" = TRAIT_GAMER, "TRAIT_GAMERGOD" = TRAIT_GAMERGOD, + "TRAIT_GARLIC_BREATH" = TRAIT_GARLIC_BREATH, "TRAIT_GENELESS" = TRAIT_GENELESS, "TRAIT_GIANT" = TRAIT_GIANT, "TRAIT_GOOD_HEARING" = TRAIT_GOOD_HEARING, "TRAIT_GRABWEAKNESS" = TRAIT_GRABWEAKNESS, "TRAIT_GREENTEXT_CURSED" = TRAIT_GREENTEXT_CURSED, "TRAIT_GUNFLIP" = TRAIT_GUNFLIP, + "TRAIT_GUN_NATURAL" = TRAIT_GUN_NATURAL, "TRAIT_HANDS_BLOCKED" = TRAIT_HANDS_BLOCKED, "TRAIT_HARDLY_WOUNDED" = TRAIT_HARDLY_WOUNDED, + "TRAIT_HATED_BY_DOGS" = TRAIT_HATED_BY_DOGS, + "TRAIT_HEAVY_DRINKER" = TRAIT_HEAVY_DRINKER, "TRAIT_HEAVY_SLEEPER" = TRAIT_HEAVY_SLEEPER, "TRAIT_HIDE_EXTERNAL_ORGANS" = TRAIT_HIDE_EXTERNAL_ORGANS, + "TRAIT_HIGH_VALUE_RANSOM" = TRAIT_HIGH_VALUE_RANSOM, "TRAIT_HOLY" = TRAIT_HOLY, "TRAIT_HUSK" = TRAIT_HUSK, + "TRAIT_ID_APPRAISER" = TRAIT_ID_APPRAISER, "TRAIT_IGNORE_ELEVATION" = TRAIT_IGNORE_ELEVATION, "TRAIT_IGNORESLOWDOWN" = TRAIT_IGNORESLOWDOWN, "TRAIT_ILLITERATE" = TRAIT_ILLITERATE, "TRAIT_IMMOBILIZED" = TRAIT_IMMOBILIZED, "TRAIT_INCAPACITATED" = TRAIT_INCAPACITATED, + "TRAIT_INTROVERT" = TRAIT_INTROVERT, "TRAIT_INVISIBLE_MAN" = TRAIT_INVISIBLE_MAN, "TRAIT_IWASBATONED" = TRAIT_IWASBATONED, "TRAIT_JOLLY" = TRAIT_JOLLY, @@ -113,23 +145,28 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_KNOCKEDOUT" = TRAIT_KNOCKEDOUT, "TRAIT_KNOW_ENGI_WIRES" = TRAIT_KNOW_ENGI_WIRES, "TRAIT_KNOW_ROBO_WIRES" = TRAIT_KNOW_ROBO_WIRES, + "TRAIT_LIGHTBULB_REMOVER" = TRAIT_LIGHTBULB_REMOVER, "TRAIT_LIGHT_DRINKER" = TRAIT_LIGHT_DRINKER, "TRAIT_LIGHT_STEP" = TRAIT_LIGHT_STEP, "TRAIT_LIGHTBULB_REMOVER" = TRAIT_LIGHTBULB_REMOVER, "TRAIT_LIMBATTACHMENT" = TRAIT_LIMBATTACHMENT, "TRAIT_LITERATE" = TRAIT_LITERATE, "TRAIT_LIVERLESS_METABOLISM" = TRAIT_LIVERLESS_METABOLISM, + "TRAIT_MADNESS_IMMUNE" = TRAIT_MADNESS_IMMUNE, "TRAIT_MAGICALLY_GIFTED" = TRAIT_MAGICALLY_GIFTED, + "TRAIT_MARTIAL_ARTS_IMMUNE" = TRAIT_MARTIAL_ARTS_IMMUNE, "TRAIT_MEDICAL_HUD" = TRAIT_MEDICAL_HUD, "TRAIT_MIME_FAN" = TRAIT_MIME_FAN, "TRAIT_MIMING" = TRAIT_MIMING, "TRAIT_MINDSHIELD" = TRAIT_MINDSHIELD, "TRAIT_MOB_HIDE_HAPPINESS" = TRAIT_MOB_HIDE_HAPPINESS, "TRAIT_MORBID" = TRAIT_MORBID, + "TRAIT_MULTIZ_SUIT_SENSORS" = TRAIT_MULTIZ_SUIT_SENSORS, "TRAIT_MUSICIAN" = TRAIT_MUSICIAN, "TRAIT_MUTANT_COLORS" = TRAIT_MUTANT_COLORS, "TRAIT_MUTE" = TRAIT_MUTE, "TRAIT_NAIVE" = TRAIT_NAIVE, + "TRAIT_NEGATES_GRAVITY" = TRAIT_NEGATES_GRAVITY, "TRAIT_NEVER_WOUNDED" = TRAIT_NEVER_WOUNDED, "TRAIT_NICE_SHOT" = TRAIT_NICE_SHOT, "TRAIT_NIGHT_VISION" = TRAIT_NIGHT_VISION, @@ -138,13 +175,18 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_NO_DNA_COPY" = TRAIT_NO_DNA_COPY, "TRAIT_NO_EXTINGUISH" = TRAIT_NO_EXTINGUISH, "TRAIT_NO_GLIDE" = TRAIT_NO_GLIDE, + "TRAIT_NO_GUN_AKIMBO" = TRAIT_NO_GUN_AKIMBO, + "TRAIT_NO_MINDSWAP" = TRAIT_NO_MINDSWAP, + "TRAIT_NO_MIRROR_REFLECTION" = TRAIT_NO_MIRROR_REFLECTION, "TRAIT_NO_PLASMA_TRANSFORM" = TRAIT_NO_PLASMA_TRANSFORM, "TRAIT_NO_SLIP_ALL" = TRAIT_NO_SLIP_ALL, "TRAIT_NO_SLIP_ICE" = TRAIT_NO_SLIP_ICE, "TRAIT_NO_SLIP_SLIDE" = TRAIT_NO_SLIP_SLIDE, "TRAIT_NO_SLIP_WATER" = TRAIT_NO_SLIP_WATER, "TRAIT_NO_SOUL" = TRAIT_NO_SOUL, + "TRAIT_NO_STAGGER" = TRAIT_NO_STAGGER, "TRAIT_NO_TRANSFORM" = TRAIT_NO_TRANSFORM, + "TRAIT_NO_TWOHANDING" = TRAIT_NO_TWOHANDING, "TRAIT_NO_UNDERWEAR" = TRAIT_NO_UNDERWEAR, "TRAIT_NO_ZOMBIFY" = TRAIT_NO_ZOMBIFY, "TRAIT_NOBLOOD" = TRAIT_NOBLOOD, @@ -153,7 +195,10 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_NOCRITOVERLAY" = TRAIT_NOCRITOVERLAY, "TRAIT_NODEATH" = TRAIT_NODEATH, "TRAIT_NODISMEMBER" = TRAIT_NODISMEMBER, + "TRAIT_NOFAT" = TRAIT_NOFAT, + "TRAIT_NOFEAR_HOLDUPS" = TRAIT_NOFEAR_HOLDUPS, "TRAIT_NOFIRE" = TRAIT_NOFIRE, + "TRAIT_NOFIRE_SPREAD" = TRAIT_NOFIRE_SPREAD, "TRAIT_NOFLASH" = TRAIT_NOFLASH, "TRAIT_NOGUNS" = TRAIT_NOGUNS, "TRAIT_TOSS_GUN_HARD" = TRAIT_TOSS_GUN_HARD, @@ -162,7 +207,9 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_NOLIMBDISABLE" = TRAIT_NOLIMBDISABLE, "TRAIT_NOMOBSWAP" = TRAIT_NOMOBSWAP, "TRAIT_NOSOFTCRIT" = TRAIT_NOSOFTCRIT, + "TRAIT_OFF_BALANCE_TACKLER" = TRAIT_OFF_BALANCE_TACKLER, "TRAIT_OIL_FRIED" = TRAIT_OIL_FRIED, + "TRAIT_OVERDOSEIMMUNE" = TRAIT_OVERDOSEIMMUNE, "TRAIT_OVERWATCH_IMMUNE" = TRAIT_OVERWATCH_IMMUNE, "TRAIT_PACIFISM" = TRAIT_PACIFISM, "TRAIT_HIPPOCRATIC_OATH" = TRAIT_HIPPOCRATIC_OATH, @@ -174,6 +221,7 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_PASSTABLE" = TRAIT_PASSTABLE, "TRAIT_PASSWINDOW" = TRAIT_PASSWINDOW, "TRAIT_PERFECT_ATTACKER" = TRAIT_PERFECT_ATTACKER, + "TRAIT_PERMANENTLY_MORTAL" = TRAIT_PERMANENTLY_MORTAL, "TRAIT_PHOTOGRAPHER" = TRAIT_PHOTOGRAPHER, "TRAIT_PIERCEIMMUNE" = TRAIT_PIERCEIMMUNE, "TRAIT_PLANT_SAFE" = TRAIT_PLANT_SAFE, @@ -184,16 +232,22 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_PROSOPAGNOSIA" = TRAIT_PROSOPAGNOSIA, "TRAIT_PULL_BLOCKED" = TRAIT_PULL_BLOCKED, "TRAIT_PUSHIMMUNE" = TRAIT_PUSHIMMUNE, + "TRAIT_QUICK_BUILD" = TRAIT_QUICK_BUILD, "TRAIT_QUICK_CARRY" = TRAIT_QUICK_CARRY, "TRAIT_QUICKER_CARRY" = TRAIT_QUICKER_CARRY, "TRAIT_RADIMMUNE" = TRAIT_RADIMMUNE, + "TRAIT_REMOTE_TASTING" = TRAIT_REMOTE_TASTING, "TRAIT_RESISTCOLD" = TRAIT_RESISTCOLD, "TRAIT_RESISTHEAT" = TRAIT_RESISTHEAT, "TRAIT_RESISTHEATHANDS" = TRAIT_RESISTHEATHANDS, "TRAIT_RESISTHIGHPRESSURE" = TRAIT_RESISTHIGHPRESSURE, "TRAIT_RESISTLOWPRESSURE" = TRAIT_RESISTLOWPRESSURE, "TRAIT_RESTRAINED" = TRAIT_RESTRAINED, + "TRAIT_REVEAL_FISH" = TRAIT_REVEAL_FISH, + "TRAIT_ROCK_STONER" = TRAIT_ROCK_STONER, + "TRAIT_ROD_SUPLEX" = TRAIT_ROD_SUPLEX, "TRAIT_ROUGHRIDER" = TRAIT_ROUGHRIDER, + "TRAIT_SABRAGE_PRO" = TRAIT_SABRAGE_PRO, "TRAIT_SECURITY_HUD" = TRAIT_SECURITY_HUD, "TRAIT_SELF_AWARE" = TRAIT_SELF_AWARE, "TRAIT_SETTLER" = TRAIT_SETTLER, @@ -208,23 +262,28 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_SLOW_FLIP" = TRAIT_SLOW_FLIP, "TRAIT_SMOKER" = TRAIT_SMOKER, "TRAIT_SNOB" = TRAIT_SNOB, + "TRAIT_SOFTSPOKEN" = TRAIT_SOFTSPOKEN, "TRAIT_SOOTHED_THROAT" = TRAIT_SOOTHED_THROAT, "TRAIT_SPACEWALK" = TRAIT_SPACEWALK, "TRAIT_SPECIAL_TRAUMA_BOOST" = TRAIT_SPECIAL_TRAUMA_BOOST, "TRAIT_SPIRITUAL" = TRAIT_SPIRITUAL, "TRAIT_STABLEHEART" = TRAIT_STABLEHEART, "TRAIT_STABLELIVER" = TRAIT_STABLELIVER, + "TRAIT_STRENGTH" = TRAIT_STRENGTH, "TRAIT_STRONG_GRABBER" = TRAIT_STRONG_GRABBER, "TRAIT_STRONG_STOMACH" = TRAIT_STRONG_STOMACH, "TRAIT_STUBBY_BODY" = TRAIT_STUBBY_BODY, "TRAIT_STUNIMMUNE" = TRAIT_STUNIMMUNE, "TRAIT_STURDY_FRAME" = TRAIT_STURDY_FRAME, + "TRAIT_SUPERMATTER_SOOTHER" = TRAIT_SUPERMATTER_SOOTHER, "TRAIT_SURGEON" = TRAIT_SURGEON, "TRAIT_SURGICALLY_ANALYZED" = TRAIT_SURGICALLY_ANALYZED, "TRAIT_TAGGER" = TRAIT_TAGGER, "TRAIT_TENTACLE_IMMUNE" = TRAIT_TENTACLE_IMMUNE, "TRAIT_TESLA_SHOCKIMMUNE" = TRAIT_TESLA_SHOCKIMMUNE, "TRAIT_THERMAL_VISION" = TRAIT_THERMAL_VISION, + "TRAIT_THROWINGARM" = TRAIT_THROWINGARM, + "TRAIT_TIME_STOP_IMMUNE" = TRAIT_TIME_STOP_IMMUNE, "TRAIT_TOXIMMUNE" = TRAIT_TOXIMMUNE, "TRAIT_TOXINLOVER" = TRAIT_TOXINLOVER, "TRAIT_TRAIT_MEDIBOTCOMINGTHROUGH" = TRAIT_MEDIBOTCOMINGTHROUGH, @@ -240,7 +299,10 @@ GLOBAL_LIST_INIT(admin_visible_traits, list( "TRAIT_UNSTABLE" = TRAIT_UNSTABLE, "TRAIT_USED_DNA_VAULT" = TRAIT_USED_DNA_VAULT, "TRAIT_USES_SKINTONES" = TRAIT_USES_SKINTONES, + "TRAIT_VENTCRAWLER_ALWAYS" = TRAIT_VENTCRAWLER_ALWAYS, + "TRAIT_VENTCRAWLER_NUDE" = TRAIT_VENTCRAWLER_NUDE, "TRAIT_VIRUSIMMUNE" = TRAIT_VIRUSIMMUNE, + "TRAIT_VIRUS_RESISTANCE" = TRAIT_VIRUS_RESISTANCE, "TRAIT_VORACIOUS" = TRAIT_VORACIOUS, "TRAIT_WOUND_LICKER" = TRAIT_WOUND_LICKER, "TRAIT_WEAK_SOUL" = TRAIT_WEAK_SOUL, diff --git a/code/_onclick/hud/radial.dm b/code/_onclick/hud/radial.dm index 6c7377c3825436..3bd370120b3a42 100644 --- a/code/_onclick/hud/radial.dm +++ b/code/_onclick/hud/radial.dm @@ -7,6 +7,7 @@ GLOBAL_LIST_EMPTY(radial_menus) icon = 'icons/hud/radial.dmi' plane = ABOVE_HUD_PLANE vis_flags = VIS_INHERIT_PLANE + var/click_on_hover = FALSE var/datum/radial_menu/parent /atom/movable/screen/radial/proc/set_parent(new_value) @@ -39,6 +40,8 @@ GLOBAL_LIST_EMPTY(radial_menus) icon_state = "[parent.radial_slice_icon]_focus" if(tooltips) openToolTip(usr, src, params, title = name) + if (click_on_hover && !isnull(usr) && !isnull(parent)) + Click(location, control, params) /atom/movable/screen/radial/slice/MouseExited(location, control, params) . = ..() @@ -146,7 +149,7 @@ GLOBAL_LIST_EMPTY(radial_menus) starting_angle = 180 ending_angle = 45 -/datum/radial_menu/proc/setup_menu(use_tooltips, set_page = 1) +/datum/radial_menu/proc/setup_menu(use_tooltips, set_page = 1, click_on_hover = FALSE) if(ending_angle > starting_angle) zone = ending_angle - starting_angle else @@ -183,18 +186,26 @@ GLOBAL_LIST_EMPTY(radial_menus) page_data[page] = current pages = page current_page = clamp(set_page, 1, pages) - update_screen_objects(anim = entry_animation) + update_screen_objects(entry_animation, click_on_hover) -/datum/radial_menu/proc/update_screen_objects(anim = FALSE) +/datum/radial_menu/proc/update_screen_objects(anim = FALSE, click_on_hover = FALSE) var/list/page_choices = page_data[current_page] var/angle_per_element = round(zone / page_choices.len) for(var/i in 1 to elements.len) - var/atom/movable/screen/radial/E = elements[i] + var/atom/movable/screen/radial/element = elements[i] var/angle = WRAP(starting_angle + (i - 1) * angle_per_element,0,360) if(i > page_choices.len) - HideElement(E) + HideElement(element) + element.click_on_hover = FALSE else - SetElement(E,page_choices[i],angle,anim = anim,anim_order = i) + SetElement(element,page_choices[i],angle,anim = anim,anim_order = i) + // Only activate click on hover after the animation plays + if (!click_on_hover) + continue + if (anim) + addtimer(VARSET_CALLBACK(element, click_on_hover, TRUE), i * 0.5) + else + element.click_on_hover = TRUE /datum/radial_menu/proc/HideElement(atom/movable/screen/radial/slice/E) E.cut_overlays() @@ -272,7 +283,7 @@ GLOBAL_LIST_EMPTY(radial_menus) /datum/radial_menu/proc/get_next_id() return "c_[choices.len]" -/datum/radial_menu/proc/set_choices(list/new_choices, use_tooltips, set_page = 1) +/datum/radial_menu/proc/set_choices(list/new_choices, use_tooltips, click_on_hover = FALSE, set_page = 1) if(choices.len) Reset() for(var/E in new_choices) @@ -286,7 +297,7 @@ GLOBAL_LIST_EMPTY(radial_menus) if (istype(new_choices[E], /datum/radial_menu_choice)) choice_datums[id] = new_choices[E] - setup_menu(use_tooltips, set_page) + setup_menu(use_tooltips, set_page, click_on_hover) /datum/radial_menu/proc/extract_image(to_extract_from) if (istype(to_extract_from, /datum/radial_menu_choice)) @@ -306,14 +317,14 @@ GLOBAL_LIST_EMPTY(radial_menus) current_page = WRAP(current_page + 1,1,pages+1) update_screen_objects() -/datum/radial_menu/proc/show_to(mob/M) +/datum/radial_menu/proc/show_to(mob/M, offset_x = 0, offset_y = 0) if(current_user) hide() if(!M.client || !anchor) return current_user = M.client //Blank - menu_holder = image(icon='icons/effects/effects.dmi',loc=anchor,icon_state="nothing", layer = RADIAL_BACKGROUND_LAYER) + menu_holder = image(icon='icons/effects/effects.dmi',loc=anchor,icon_state="nothing", layer = RADIAL_BACKGROUND_LAYER, pixel_x = offset_x, pixel_y = offset_y) SET_PLANE_EXPLICIT(menu_holder, ABOVE_HUD_PLANE, M) menu_holder.appearance_flags |= KEEP_APART|RESET_ALPHA|RESET_COLOR|RESET_TRANSFORM menu_holder.vis_contents += elements + close_button @@ -345,7 +356,7 @@ GLOBAL_LIST_EMPTY(radial_menus) Choices should be a list where list keys are movables or text used for element names and return value and list values are movables/icons/images used for element icons */ -/proc/show_radial_menu(mob/user, atom/anchor, list/choices, uniqueid, radius, datum/callback/custom_check, require_near = FALSE, tooltips = FALSE, no_repeat_close = FALSE, radial_slice_icon = "radial_slice", autopick_single_option = TRUE) +/proc/show_radial_menu(mob/user, atom/anchor, list/choices, uniqueid, radius, datum/callback/custom_check, require_near = FALSE, tooltips = FALSE, no_repeat_close = FALSE, radial_slice_icon = "radial_slice", autopick_single_option = TRUE, entry_animation = TRUE, click_on_hover = FALSE, user_space = FALSE) if(!user || !anchor || !length(choices)) return @@ -362,16 +373,24 @@ GLOBAL_LIST_EMPTY(radial_menus) return var/datum/radial_menu/menu = new + menu.entry_animation = entry_animation GLOB.radial_menus[uniqueid] = menu if(radius) menu.radius = radius if(istype(custom_check)) menu.custom_check_callback = custom_check - menu.anchor = anchor + menu.anchor = user_space ? user : anchor menu.radial_slice_icon = radial_slice_icon menu.check_screen_border(user) //Do what's needed to make it look good near borders or on hud - menu.set_choices(choices, tooltips) - menu.show_to(user) + menu.set_choices(choices, tooltips, click_on_hover) + var/offset_x = 0 + var/offset_y = 0 + if (user_space) + var/turf/user_turf = get_turf(user) + var/turf/anchor_turf = get_turf(anchor) + offset_x = (anchor_turf.x - user_turf.x) * world.icon_size + anchor.pixel_x - user.pixel_x + offset_y = (anchor_turf.y - user_turf.y) * world.icon_size + anchor.pixel_y - user.pixel_y + menu.show_to(user, offset_x, offset_y) menu.wait(user, anchor, require_near) var/answer = menu.selected_choice qdel(menu) diff --git a/code/_onclick/hud/screen_objects.dm b/code/_onclick/hud/screen_objects.dm index 315efe48778106..d0f64262549360 100644 --- a/code/_onclick/hud/screen_objects.dm +++ b/code/_onclick/hud/screen_objects.dm @@ -482,8 +482,26 @@ return TRUE +/atom/movable/screen/storage/cell + +/atom/movable/screen/storage/cell/mouse_drop_receive(atom/target, mob/living/user, params) + var/datum/storage/storage = master_ref?.resolve() + + if (isnull(storage) || !istype(user) || storage != user.active_storage) + return + + if (!user.can_perform_action(storage.parent, FORBID_TELEKINESIS_REACH)) + return + + if (target.loc != storage.real_location) + return + + /// Due to items in storage ignoring transparency for click hitboxes, this only can happen if we drag onto a free cell - aka after all current contents + storage.real_location.contents -= target + storage.real_location.contents += target + storage.refresh_views() + /atom/movable/screen/storage/corner - name = "storage" icon_state = "storage_corner_topleft" /atom/movable/screen/storage/corner/top_right diff --git a/code/_onclick/other_mobs.dm b/code/_onclick/other_mobs.dm index 0dd8ee0a582f69..2f1465ac4ffe2e 100644 --- a/code/_onclick/other_mobs.dm +++ b/code/_onclick/other_mobs.dm @@ -200,7 +200,8 @@ /atom/proc/attack_paw(mob/user, list/modifiers) if(SEND_SIGNAL(src, COMSIG_ATOM_ATTACK_PAW, user, modifiers) & COMPONENT_CANCEL_ATTACK_CHAIN) return TRUE - return FALSE + if(interaction_flags_atom & INTERACT_ATOM_ATTACK_PAW) + . = _try_interact(user) /* diff --git a/code/controllers/configuration/entries/game_options.dm b/code/controllers/configuration/entries/game_options.dm index 05489241c6a0be..72df7ceeb9777f 100644 --- a/code/controllers/configuration/entries/game_options.dm +++ b/code/controllers/configuration/entries/game_options.dm @@ -266,7 +266,7 @@ /datum/config_entry/flag/roundstart_away //Will random away mission be loaded. /datum/config_entry/number/gateway_delay //How long the gateway takes before it activates. Default is half an hour. Only matters if roundstart_away is enabled. - default = 18000 + default = 30 MINUTES integer = FALSE min_val = 0 @@ -275,6 +275,16 @@ min_val = 0 max_val = 100 +///An override to gateway_delay for specific maps or start points +/datum/config_entry/keyed_list/gateway_delays_by_id + default = list( + AWAYSTART_BEACH = 5 MINUTES, //Chill RP zone + AWAYSTART_MUSEUM = 12 MINUTES, //Chill place with some cool puzzles and effects. + ) + key_mode = KEY_MODE_TEXT + value_mode = VALUE_MODE_NUM + lowercase_key = FALSE //The macros are written the exact same way as their values, only without the quotation marks. + /datum/config_entry/flag/ghost_interaction /datum/config_entry/flag/near_death_experience //If carbons can hear ghosts when unconscious and very close to death diff --git a/code/controllers/subsystem/dynamic/dynamic.dm b/code/controllers/subsystem/dynamic/dynamic.dm index ed0ebec7aeae9a..a45644813afc4e 100644 --- a/code/controllers/subsystem/dynamic/dynamic.dm +++ b/code/controllers/subsystem/dynamic/dynamic.dm @@ -1019,7 +1019,7 @@ SUBSYSTEM_DEF(dynamic) #define MAXIMUM_DYN_DISTANCE 5 /** - * Returns the comulative distribution of threat centre and width, and a random location of -0.5 to 0.5 + * Returns the comulative distribution of threat centre and width, and a random location of -5 to 5 * plus or minus the otherwise unattainable lower and upper percentiles. All multiplied by the maximum * threat and then rounded to the nearest interval. * rand() calls without arguments returns a value between 0 and 1, allowing for smaller intervals. diff --git a/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm b/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm index 7d91ca6b565ce9..93967281594803 100644 --- a/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm +++ b/code/controllers/subsystem/dynamic/dynamic_rulesets_midround.dm @@ -964,13 +964,15 @@ cost = 5 minimum_players = 40 repeatable = TRUE + signup_item_path = /obj/item/cosmic_skull ruleset_lazy_templates = list(LAZY_TEMPLATE_KEY_VOIDWALKER_VOID) /// The space turf we find in acceptable(), cached for ease var/space_turf /datum/dynamic_ruleset/midround/from_ghosts/voidwalker/acceptable(population = 0, threat_level = 0) space_turf = find_space_spawn() - if(!space_turf) + // Space only antag and will die on planetary gravity. + if(SSmapping.is_planetary() || !space_turf) return FALSE return ..() diff --git a/code/controllers/subsystem/garbage.dm b/code/controllers/subsystem/garbage.dm index 706b4e51d690f3..ad1b9e4132fed8 100644 --- a/code/controllers/subsystem/garbage.dm +++ b/code/controllers/subsystem/garbage.dm @@ -346,6 +346,7 @@ SUBSYSTEM_DEF(garbage) /// Datums passed to this will be given a chance to clean up references to allow the GC to collect them. /proc/qdel(datum/to_delete, force = FALSE) if(!istype(to_delete)) + DREAMLUAU_CLEAR_REF_USERDATA(to_delete) del(to_delete) return diff --git a/code/controllers/subsystem/job.dm b/code/controllers/subsystem/job.dm index 697beaee19b39e..b1629237dc6bf7 100644 --- a/code/controllers/subsystem/job.dm +++ b/code/controllers/subsystem/job.dm @@ -741,9 +741,11 @@ SUBSYSTEM_DEF(job) if(!spawn_turf) SendToLateJoin(living_mob) else - var/obj/structure/closet/supplypod/centcompod/toLaunch = new() - living_mob.forceMove(toLaunch) - new /obj/effect/pod_landingzone(spawn_turf, toLaunch) + podspawn(list( + "target" = spawn_turf, + "path" = /obj/structure/closet/supplypod/centcompod, + "spawn" = living_mob + )) /// Returns a list of minds of all heads of staff who are alive /datum/controller/subsystem/job/proc/get_living_heads() diff --git a/code/controllers/subsystem/lighting.dm b/code/controllers/subsystem/lighting.dm index 59ff294e959a21..24d871d2f09c4b 100644 --- a/code/controllers/subsystem/lighting.dm +++ b/code/controllers/subsystem/lighting.dm @@ -26,6 +26,19 @@ SUBSYSTEM_DEF(lighting) return SS_INIT_SUCCESS + +/datum/controller/subsystem/lighting/proc/create_all_lighting_objects() + for(var/area/area as anything in GLOB.areas) + if(!area.static_lighting) + continue + for (var/list/zlevel_turfs as anything in area.get_zlevel_turf_lists()) + for(var/turf/area_turf as anything in zlevel_turfs) + if(area_turf.space_lit) + continue + new /datum/lighting_object(area_turf) + CHECK_TICK + CHECK_TICK + /datum/controller/subsystem/lighting/fire(resumed, init_tick_checks) MC_SPLIT_TICK_INIT(3) if(!init_tick_checks) diff --git a/code/controllers/subsystem/lua.dm b/code/controllers/subsystem/lua.dm index 1ab88a01746b7c..99df8cf3354903 100644 --- a/code/controllers/subsystem/lua.dm +++ b/code/controllers/subsystem/lua.dm @@ -2,7 +2,6 @@ SUBSYSTEM_DEF(lua) name = "Lua Scripting" runlevels = RUNLEVEL_LOBBY | RUNLEVELS_DEFAULT wait = 0.1 SECONDS - flags = SS_OK_TO_FAIL_INIT /// A list of all lua states var/list/datum/lua_state/states = list() @@ -18,31 +17,19 @@ SUBSYSTEM_DEF(lua) var/list/current_run = list() var/list/current_states_run = list() - /// Protects return values from getting GCed before getting converted to lua values - /// Gets cleared every tick. - var/list/gc_guard = list() + var/list/needs_gc_cycle = list() /datum/controller/subsystem/lua/Initialize() - if(!CONFIG_GET(flag/auxtools_enabled)) - warning("SSlua requires auxtools to be enabled to run.") - return SS_INIT_NO_NEED - - try - // Initialize the auxtools library - AUXTOOLS_CHECK(AUXLUA) - - // Set the wrappers for setting vars and calling procs - __lua_set_set_var_wrapper("/proc/wrap_lua_set_var") - __lua_set_datum_proc_call_wrapper("/proc/wrap_lua_datum_proc_call") - __lua_set_global_proc_call_wrapper("/proc/wrap_lua_global_proc_call") - __lua_set_print_wrapper("/proc/wrap_lua_print") - return SS_INIT_SUCCESS - catch(var/exception/e) - // Something went wrong, best not allow the subsystem to run - var/crash_message = "Error initializing SSlua: [e.name]" - initialization_failure_message = crash_message - warning(crash_message) - return SS_INIT_FAILURE + DREAMLUAU_SET_EXECUTION_LIMIT_SECS(5) + // Set wrappers to ensure that lua scripts are subject to the same safety restrictions as other admin tooling + DREAMLUAU_SET_NEW_WRAPPER("/proc/_new") + DREAMLUAU_SET_VAR_GET_WRAPPER("/proc/wrap_lua_get_var") + DREAMLUAU_SET_VAR_SET_WRAPPER("/proc/wrap_lua_set_var") + DREAMLUAU_SET_OBJECT_CALL_WRAPPER("/proc/wrap_lua_datum_proc_call") + DREAMLUAU_SET_GLOBAL_CALL_WRAPPER("/proc/wrap_lua_global_proc_call") + // Set the print wrapper, as otherwise, the print function is meaningless + DREAMLUAU_SET_PRINT_WRAPPER("/proc/wrap_lua_print") + return SS_INIT_SUCCESS /datum/controller/subsystem/lua/OnConfigLoad() // Read the paths from the config file @@ -52,9 +39,6 @@ SUBSYSTEM_DEF(lua) lua_path += path world.SetConfig("env", "LUAU_PATH", jointext(lua_path, ";")) -/datum/controller/subsystem/lua/Shutdown() - AUXTOOLS_FULL_SHUTDOWN(AUXLUA) - /datum/controller/subsystem/lua/proc/queue_resume(datum/lua_state/state, index, arguments) if(!initialized) return @@ -64,36 +48,33 @@ SUBSYSTEM_DEF(lua) arguments = list() else if(!islist(arguments)) arguments = list(arguments) + else + var/list/args_list = arguments + arguments = args_list.Copy() resumes += list(list("state" = state, "index" = index, "arguments" = arguments)) -/datum/controller/subsystem/lua/proc/kill_task(datum/lua_state/state, list/task_info) +/datum/controller/subsystem/lua/proc/kill_task(datum/lua_state/state, is_sleep, index) if(!istype(state)) return - if(!islist(task_info)) - return - if(!(istext(task_info["name"]) && istext(task_info["status"]) && isnum(task_info["index"]))) - return - switch(task_info["status"]) - if("sleep") - var/task_index = task_info["index"] - var/state_index = 1 - - // Get the nth sleep in the sleep list corresponding to the target state - for(var/i in 1 to length(sleeps)) - var/datum/lua_state/sleeping_state = sleeps[i] - if(sleeping_state == state) - if(state_index == task_index) - sleeps.Cut(i, i+1) - break - state_index++ - if("yield") - // Remove the resumt from the resumt list - for(var/i in 1 to length(resumes)) - var/resume = resumes[i] - if(resume["state"] == state && resume["index"] == task_info["index"]) - resumes.Cut(i, i+1) + if(is_sleep) + var/state_index = 1 + + // Get the nth sleep in the sleep list corresponding to the target state + for(var/i in 1 to length(sleeps)) + var/datum/lua_state/sleeping_state = sleeps[i] + if(sleeping_state == state) + if(state_index == index) + sleeps.Cut(i, i+1) break - state.kill_task(task_info) + state_index++ + else + // Remove the resumt from the resumt list + for(var/i in 1 to length(resumes)) + var/resume = resumes[i] + if(resume["state"] == state && resume["index"] == index) + resumes.Cut(i, i+1) + break + state.kill_task(is_sleep, index) /datum/controller/subsystem/lua/fire(resumed) // Each fire of SSlua awakens every sleeping task in the order they slept, @@ -104,7 +85,6 @@ SUBSYSTEM_DEF(lua) sleeps.Cut() resumes.Cut() - gc_guard.Cut() var/list/current_sleeps = current_run["sleeps"] var/list/affected_states = list() while(length(current_sleeps)) @@ -147,6 +127,32 @@ SUBSYSTEM_DEF(lua) if(MC_TICK_CHECK) break + while(length(needs_gc_cycle)) + var/datum/lua_state/state = needs_gc_cycle[needs_gc_cycle.len] + needs_gc_cycle.len-- + state.collect_garbage() + // Update every lua editor TGUI open for each state that had a task awakened or resumed for(var/datum/lua_state/state in affected_states) INVOKE_ASYNC(state, TYPE_PROC_REF(/datum/lua_state, update_editors)) + +/datum/controller/subsystem/lua/proc/log_involved_runtime(exception/runtime, list/desclines, list/lua_stacks) + var/list/json_data = list("status" = "runtime", "file" = runtime.file, "line" = runtime.line, "message" = runtime.name, "stack" = list()) + var/level = 1 + for(var/line in desclines) + line = copytext(line, 3) + if(starts_with_any(line, list( + "/datum/lua_state (/datum/lua_state): load script", + "/datum/lua_state (/datum/lua_state): call function", + "/datum/lua_state (/datum/lua_state): awaken", + "/datum/lua_state (/datum/lua_state): resume" + ))) + json_data["stack"] += lua_stacks[level] + level++ + json_data["stack"] += line + for(var/datum/weakref/state_ref as anything in GLOB.lua_state_stack) + var/datum/lua_state/state = state_ref.resolve() + if(!state) + continue + state.log_result(json_data) + return diff --git a/code/controllers/subsystem/blackmarket.dm b/code/controllers/subsystem/market.dm similarity index 65% rename from code/controllers/subsystem/blackmarket.dm rename to code/controllers/subsystem/market.dm index 5c88177583b2f2..0c134d56915703 100644 --- a/code/controllers/subsystem/blackmarket.dm +++ b/code/controllers/subsystem/market.dm @@ -1,5 +1,5 @@ -SUBSYSTEM_DEF(blackmarket) - name = "Blackmarket" +SUBSYSTEM_DEF(market) + name = "Market" flags = SS_BACKGROUND init_order = INIT_ORDER_DEFAULT @@ -18,27 +18,27 @@ SUBSYSTEM_DEF(blackmarket) /// Currently queued purchases. var/list/queued_purchases = list() -/datum/controller/subsystem/blackmarket/Initialize() +/datum/controller/subsystem/market/Initialize() for(var/market in subtypesof(/datum/market)) markets[market] += new market - for(var/datum/market_item/item as anything in subtypesof(/datum/market_item)) - if(!initial(item.item)) - continue - if(!prob(initial(item.availability_prob))) - continue - - var/datum/market_item/item_instance = new item() - for(var/potential_market in item_instance.markets) - if(!markets[potential_market]) - stack_trace("SSblackmarket: Item [item_instance] available in market that does not exist.") - continue - // If this fails the market item will just be GC'd - markets[potential_market].add_item(item_instance) + for(var/path in subtypesof(/datum/market_item)) + initialize_item(path) return SS_INIT_SUCCESS -/datum/controller/subsystem/blackmarket/fire(resumed) +/datum/controller/subsystem/market/proc/initialize_item(datum/market_item/path, list/market_whitelist) + if(!path::item || !prob(path::availability_prob)) + return + var/datum/market_item/item_instance = new path() + for(var/potential_market in item_instance.markets) + if(!markets[potential_market]) + stack_trace("SSmarket: Item [item_instance] available in market that does not exist.") + continue + if(isnull(market_whitelist) || (potential_market in market_whitelist)) + markets[potential_market].add_item(item_instance) + +/datum/controller/subsystem/market/fire(resumed) while(length(queued_purchases)) var/datum/market_purchase/purchase = queued_purchases[1] queued_purchases.Cut(1,2) @@ -55,9 +55,9 @@ SUBSYSTEM_DEF(blackmarket) // The time left of the shortest cooldown amongst all telepads. var/lowest_timeleft = INFINITY for(var/obj/machinery/ltsrbt/pad as anything in telepads) - if(!COOLDOWN_FINISHED(pad, recharge_cooldown)) - var/timeleft = COOLDOWN_TIMELEFT(pad, recharge_cooldown) - if(timeleft < lowest_timeleft) + if(!COOLDOWN_FINISHED(pad, recharge_cooldown) || (pad.machine_stat & NOPOWER)) + var/timeleft = pad.machine_stat & NOPOWER ? INFINITY - 1 : COOLDOWN_TIMELEFT(pad, recharge_cooldown) + if(timeleft <= lowest_timeleft) lowest_cd_pad = pad lowest_timeleft = timeleft continue @@ -79,7 +79,7 @@ SUBSYSTEM_DEF(blackmarket) to_chat(buyer, span_notice("[purchase.uplink] flashes a message noting that the order is being teleported to [get_area(targetturf)] in 60 seconds.")) // do_teleport does not want to teleport items from nullspace, so it just forceMoves and does sparks. - addtimer(CALLBACK(src, TYPE_PROC_REF(/datum/controller/subsystem/blackmarket, fake_teleport), purchase, targetturf), 60 SECONDS) + addtimer(CALLBACK(src, TYPE_PROC_REF(/datum/controller/subsystem/market, fake_teleport), purchase, targetturf), 60 SECONDS) // Get the current location of the uplink if it exists, then throws the item from space at the station from a random direction. if(SHIPPING_METHOD_LAUNCH) @@ -95,9 +95,11 @@ SUBSYSTEM_DEF(blackmarket) qdel(purchase) if(SHIPPING_METHOD_SUPPLYPOD) - var/obj/structure/closet/supplypod/back_to_station/pod = new() - purchase.entry.spawn_item(pod, purchase) - new /obj/effect/pod_landingzone(get_turf(purchase.uplink), pod) + var/obj/structure/closet/supplypod/spawned_pod = podspawn(list( + "target" = get_turf(purchase.uplink), + "path" = /obj/structure/closet/supplypod/back_to_station, + )) + purchase.entry.spawn_item(spawned_pod, purchase) to_chat(buyer, span_notice("[purchase.uplink] flashes a message noting the order is being launched at your location. Right here, right now!")) qdel(purchase) @@ -106,7 +108,7 @@ SUBSYSTEM_DEF(blackmarket) break /// Used to make a teleportation effect as do_teleport does not like moving items from nullspace. -/datum/controller/subsystem/blackmarket/proc/fake_teleport(datum/market_purchase/purchase, turf/target) +/datum/controller/subsystem/market/proc/fake_teleport(datum/market_purchase/purchase, turf/target) // Oopsie, whoopsie, the item is gone. So long, and thanks for all the money. if(QDELETED(purchase)) return @@ -119,9 +121,31 @@ SUBSYSTEM_DEF(blackmarket) qdel(purchase) /// Used to add /datum/market_purchase to queued_purchases var. Returns TRUE when queued. -/datum/controller/subsystem/blackmarket/proc/queue_item(datum/market_purchase/purchase) +/datum/controller/subsystem/market/proc/queue_item(datum/market_purchase/purchase) if((purchase.method == SHIPPING_METHOD_LTSRBT && !telepads.len) || isnull(purchase.uplink)) qdel(purchase) return FALSE queued_purchases += purchase return TRUE + +///A proc that restocks one or more markets, or all if the market_whitelist is null. +/datum/controller/subsystem/market/proc/restock(list/market_whitelist) + var/market_name = "Markets" + if(market_whitelist && !islist(market_whitelist)) + var/datum/market/market_path = market_whitelist + market_name = market_path::name + market_whitelist = list(market_path) + + var/list/existing_types = list() + for(var/path in markets) + if(isnull(market_whitelist) || (path in market_whitelist)) + markets[path].restock(existing_types) + + for(var/datum/market_item/path as anything in (subtypesof(/datum/market_item) - existing_types)) + if(!path::restockable) + continue + initialize_item(path, market_whitelist) + + for(var/obj/machinery/ltsrbt/pad as anything in telepads) + pad.say("[market_name] restocked!") + playsound(src, 'sound/effects/cashregister.ogg', 40, FALSE) diff --git a/code/controllers/subsystem/minor_mapping.dm b/code/controllers/subsystem/minor_mapping.dm index 6acbbc1894e252..4aed29be350b6b 100644 --- a/code/controllers/subsystem/minor_mapping.dm +++ b/code/controllers/subsystem/minor_mapping.dm @@ -49,6 +49,8 @@ SUBSYSTEM_DEF(minor_mapping) ///List of areas where satchels should not be placed. var/list/blacklisted_area_types = list( /area/station/holodeck, + /area/space/nearstation, + /area/station/solars, ) while(turfs.len && satchel_amount > 0) diff --git a/code/controllers/subsystem/polling.dm b/code/controllers/subsystem/polling.dm index cbbcca59fa6e2a..fa219cd3da9f06 100644 --- a/code/controllers/subsystem/polling.dm +++ b/code/controllers/subsystem/polling.dm @@ -206,6 +206,12 @@ SUBSYSTEM_DEF(polling) return for(var/mob/dead/observer/ghost_player in GLOB.player_list) candidates += ghost_player + +#ifdef TESTING + for(var/mob/dude in GLOB.player_list) + candidates |= dude +#endif + return poll_candidates(question, role, check_jobban, poll_time, ignore_category, flashwindow, candidates, alert_pic, jump_target, role_name_text, custom_response_messages, start_signed_up, amount_to_pick, chat_text_border_icon, announce_chosen) /datum/controller/subsystem/polling/proc/poll_ghosts_for_target( diff --git a/code/controllers/subsystem/sprite_accessories.dm b/code/controllers/subsystem/sprite_accessories.dm index f381df80df6da3..21bafd5330c97d 100644 --- a/code/controllers/subsystem/sprite_accessories.dm +++ b/code/controllers/subsystem/sprite_accessories.dm @@ -87,23 +87,23 @@ SUBSYSTEM_DEF(accessories) // just 'accessories' for brevity socks_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/socks)[DEFAULT_SPRITE_LIST] - lizard_markings_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/lizard_markings)[DEFAULT_SPRITE_LIST] + lizard_markings_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/lizard_markings, add_blank = TRUE)[DEFAULT_SPRITE_LIST] tails_list_human = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/human, add_blank = TRUE)[DEFAULT_SPRITE_LIST] - tails_list_lizard = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/lizard, add_blank = TRUE)[DEFAULT_SPRITE_LIST] - tails_list_monkey = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/monkey, add_blank = TRUE)[DEFAULT_SPRITE_LIST] + tails_list_lizard = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/lizard)[DEFAULT_SPRITE_LIST] + tails_list_monkey = init_sprite_accessory_subtypes(/datum/sprite_accessory/tails/monkey)[DEFAULT_SPRITE_LIST] snouts_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/snouts)[DEFAULT_SPRITE_LIST] - horns_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/horns)[DEFAULT_SPRITE_LIST] - ears_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/ears)[DEFAULT_SPRITE_LIST] - wings_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/wings)[DEFAULT_SPRITE_LIST] + horns_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/horns, add_blank = TRUE)[DEFAULT_SPRITE_LIST] + ears_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/ears, add_blank = TRUE)[DEFAULT_SPRITE_LIST] + wings_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/wings, add_blank = TRUE)[DEFAULT_SPRITE_LIST] wings_open_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/wings_open)[DEFAULT_SPRITE_LIST] - frills_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/frills)[DEFAULT_SPRITE_LIST] - spines_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/spines)[DEFAULT_SPRITE_LIST] - tail_spines_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/tail_spines)[DEFAULT_SPRITE_LIST] + frills_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/frills, add_blank = TRUE)[DEFAULT_SPRITE_LIST] + spines_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/spines, add_blank = TRUE)[DEFAULT_SPRITE_LIST] + tail_spines_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/tail_spines, add_blank = TRUE)[DEFAULT_SPRITE_LIST] legs_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/legs)[DEFAULT_SPRITE_LIST] caps_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/caps)[DEFAULT_SPRITE_LIST] moth_wings_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/moth_wings)[DEFAULT_SPRITE_LIST] moth_antennae_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/moth_antennae)[DEFAULT_SPRITE_LIST] - moth_markings_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/moth_markings)[DEFAULT_SPRITE_LIST] + moth_markings_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/moth_markings, add_blank = TRUE)[DEFAULT_SPRITE_LIST] pod_hair_list = init_sprite_accessory_subtypes(/datum/sprite_accessory/pod_hair)[DEFAULT_SPRITE_LIST] /// This proc just intializes all /datum/sprite_accessory/hair_gradient into an list indexed by gradient-style name diff --git a/code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm index 4cf04039e8535a..7673551a65319b 100644 --- a/code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm +++ b/code/datums/ai/basic_mobs/basic_ai_behaviors/targeting.dm @@ -152,3 +152,15 @@ GLOBAL_LIST_INIT(target_interested_atoms, typecacheof(list(/mob, /obj/machinery/ /// Returns the desired final target from the filtered list of targets /datum/ai_behavior/find_potential_targets/proc/pick_final_target(datum/ai_controller/controller, list/filtered_targets) return pick(filtered_targets) + +/// Targets with the trait specified by the BB_TARGET_PRIORITY_TRAIT blackboard key will be prioritized over the rest. +/datum/ai_behavior/find_potential_targets/prioritize_trait + +/datum/ai_behavior/find_potential_targets/prioritize_trait/pick_final_target(datum/ai_controller/controller, list/filtered_targets) + var/priority_targets = list() + for(var/atom/target as anything in filtered_targets) + if(HAS_TRAIT(target, controller.blackboard[BB_TARGET_PRIORITY_TRAIT])) + priority_targets += target + if(length(priority_targets)) + return pick(priority_targets) + return ..() diff --git a/code/datums/ai/basic_mobs/basic_subtrees/find_targets_prioritize_traits.dm b/code/datums/ai/basic_mobs/basic_subtrees/find_targets_prioritize_traits.dm new file mode 100644 index 00000000000000..6c83469960ad3e --- /dev/null +++ b/code/datums/ai/basic_mobs/basic_subtrees/find_targets_prioritize_traits.dm @@ -0,0 +1,6 @@ +/// Find something with a specific trait to run from +/datum/ai_planning_subtree/find_target_prioritize_traits + +/datum/ai_planning_subtree/find_target_prioritize_traits/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + . = ..() + controller.queue_behavior(/datum/ai_behavior/find_potential_targets/prioritize_trait, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETING_STRATEGY, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION, BB_TARGET_PRIORITY_TRAIT) diff --git a/code/datums/ai/basic_mobs/basic_subtrees/flee_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/flee_target.dm index 4a2f5b476c7590..3ed8b2df2b26df 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/flee_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/flee_target.dm @@ -10,7 +10,7 @@ /datum/ai_planning_subtree/flee_target/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) . = ..() var/atom/flee_from = controller.blackboard[target_key] - if (controller.blackboard[BB_BASIC_MOB_STOP_FLEEING] || QDELETED(flee_from)) + if(!should_flee(controller, flee_from)) return var/flee_distance = controller.blackboard[BB_BASIC_MOB_FLEE_DISTANCE] || DEFAULT_BASIC_FLEE_DISTANCE if (get_dist(controller.pawn, flee_from) >= flee_distance) @@ -19,8 +19,21 @@ controller.queue_behavior(flee_behaviour, target_key, hiding_place_key) return SUBTREE_RETURN_FINISH_PLANNING //we gotta get out of here. +/datum/ai_planning_subtree/flee_target/proc/should_flee(datum/ai_controller/controller, atom/flee_from) + if (controller.blackboard[BB_BASIC_MOB_STOP_FLEEING] || QDELETED(flee_from)) + return FALSE + return TRUE + /// Try to escape from your current target, without performing any other actions. /// Reads from some fleeing-specific targeting keys rather than the current mob target. /datum/ai_planning_subtree/flee_target/from_flee_key target_key = BB_BASIC_MOB_FLEE_TARGET hiding_place_key = BB_BASIC_MOB_FLEE_TARGET_HIDING_LOCATION + +/// A subtype that forces the mob to flee from targets with the scary fisherman trait anyway. +/datum/ai_planning_subtree/flee_target/from_fisherman + +/datum/ai_planning_subtree/flee_target/from_fisherman/should_flee(datum/ai_controller/controller, atom/flee_from) + if (!QDELETED(flee_from) && HAS_TRAIT(flee_from, TRAIT_SCARY_FISHERMAN)) + return TRUE + return ..() diff --git a/code/datums/ai/basic_mobs/basic_subtrees/simple_attack_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/simple_attack_target.dm index 5b1f5ffbff9ed5..f764568d4ba744 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/simple_attack_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/simple_attack_target.dm @@ -22,3 +22,12 @@ return controller.queue_behavior(ranged_attack_behavior, BB_BASIC_MOB_CURRENT_TARGET, BB_TARGETING_STRATEGY, BB_BASIC_MOB_CURRENT_TARGET_HIDING_LOCATION) return SUBTREE_RETURN_FINISH_PLANNING //we are going into battle...no distractions. + +/datum/ai_planning_subtree/basic_melee_attack_subtree/no_fisherman + +/datum/ai_planning_subtree/basic_melee_attack_subtree/no_fisherman/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + var/atom/movable/target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] + if(QDELETED(target)) + return ..() + if(!HAS_TRAIT(target, TRAIT_SCARY_FISHERMAN)) + return ..() diff --git a/code/datums/ai/basic_mobs/basic_subtrees/simple_find_target.dm b/code/datums/ai/basic_mobs/basic_subtrees/simple_find_target.dm index 1c7d8de9120ba3..42608730f98911 100644 --- a/code/datums/ai/basic_mobs/basic_subtrees/simple_find_target.dm +++ b/code/datums/ai/basic_mobs/basic_subtrees/simple_find_target.dm @@ -12,4 +12,3 @@ if(watcher.stat != DEAD) return return ..() - diff --git a/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm b/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm index 18ce58ffc4debb..3115e3ad62ea28 100644 --- a/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm +++ b/code/datums/bodypart_overlays/mutant_bodypart_overlay.dm @@ -28,13 +28,16 @@ sprite_datum = get_random_appearance() ///Grab a random appearance datum (thats not locked) -/datum/bodypart_overlay/mutant/proc/get_random_appearance() +/datum/bodypart_overlay/mutant/proc/get_random_appearance() as /datum/sprite_accessory + RETURN_TYPE(/datum/sprite_accessory) var/list/valid_restyles = list() var/list/feature_list = get_global_feature_list() for(var/accessory in feature_list) var/datum/sprite_accessory/accessory_datum = feature_list[accessory] if(initial(accessory_datum.locked)) //locked is for stuff that shouldn't appear here continue + if(!initial(accessory_datum.natural_spawn)) + continue valid_restyles += accessory_datum return pick(valid_restyles) diff --git a/code/datums/callback.dm b/code/datums/callback.dm index 35103fbc901f3e..c2941c9202986d 100644 --- a/code/datums/callback.dm +++ b/code/datums/callback.dm @@ -111,7 +111,7 @@ else calling_arguments = args if(datum_flags & DF_VAR_EDITED) - if(usr != GLOB.AdminProcCallHandler && !usr?.client?.ckey) //This happens when a timer or the MC invokes a callback + if(usr != GLOB.AdminProcCallHandler && !(usr && usr?.client?.ckey)) //This happens when a timer or the MC invokes a callback return HandleUserlessProcCall(usr, object, delegate, calling_arguments) return WrapAdminProcCall(object, delegate, calling_arguments) if (object == GLOBAL_PROC) @@ -148,7 +148,7 @@ else calling_arguments = args if(datum_flags & DF_VAR_EDITED) - if(usr != GLOB.AdminProcCallHandler && !usr?.client?.ckey) //This happens when a timer or the MC invokes a callback + if(usr != GLOB.AdminProcCallHandler && !(usr && usr?.client?.ckey)) //This happens when a timer or the MC invokes a callback return HandleUserlessProcCall(usr, object, delegate, calling_arguments) return WrapAdminProcCall(object, delegate, calling_arguments) if (object == GLOBAL_PROC) diff --git a/code/datums/chatmessage.dm b/code/datums/chatmessage.dm index d300fcc371349b..998c10a3b9b442 100644 --- a/code/datums/chatmessage.dm +++ b/code/datums/chatmessage.dm @@ -324,59 +324,6 @@ else new /datum/chatmessage(raw_message, speaker, src, message_language, spans) -// Tweak these defines to change the available color ranges -#define CM_COLOR_SAT_MIN 0.6 -#define CM_COLOR_SAT_MAX 0.7 -#define CM_COLOR_LUM_MIN 0.65 -#define CM_COLOR_LUM_MAX 0.75 - -/** - * Gets a color for a name, will return the same color for a given string consistently within a round.atom - * - * Note that this proc aims to produce pastel-ish colors using the HSL colorspace. These seem to be favorable for displaying on the map. - * - * Arguments: - * * name - The name to generate a color for - * * sat_shift - A value between 0 and 1 that will be multiplied against the saturation - * * lum_shift - A value between 0 and 1 that will be multiplied against the luminescence - */ -/datum/chatmessage/proc/colorize_string(name, sat_shift = 1, lum_shift = 1) - // seed to help randomness - var/static/rseed = rand(1,26) - - // get hsl using the selected 6 characters of the md5 hash - var/hash = copytext(md5(name + GLOB.round_id), rseed, rseed + 6) - var/h = hex2num(copytext(hash, 1, 3)) * (360 / 255) - var/s = (hex2num(copytext(hash, 3, 5)) >> 2) * ((CM_COLOR_SAT_MAX - CM_COLOR_SAT_MIN) / 63) + CM_COLOR_SAT_MIN - var/l = (hex2num(copytext(hash, 5, 7)) >> 2) * ((CM_COLOR_LUM_MAX - CM_COLOR_LUM_MIN) / 63) + CM_COLOR_LUM_MIN - - // adjust for shifts - s *= clamp(sat_shift, 0, 1) - l *= clamp(lum_shift, 0, 1) - - // convert to rgb - var/h_int = round(h/60) // mapping each section of H to 60 degree sections - var/c = (1 - abs(2 * l - 1)) * s - var/x = c * (1 - abs((h / 60) % 2 - 1)) - var/m = l - c * 0.5 - x = (x + m) * 255 - c = (c + m) * 255 - m *= 255 - switch(h_int) - if(0) - return "#[num2hex(c, 2)][num2hex(x, 2)][num2hex(m, 2)]" - if(1) - return "#[num2hex(x, 2)][num2hex(c, 2)][num2hex(m, 2)]" - if(2) - return "#[num2hex(m, 2)][num2hex(c, 2)][num2hex(x, 2)]" - if(3) - return "#[num2hex(m, 2)][num2hex(x, 2)][num2hex(c, 2)]" - if(4) - return "#[num2hex(x, 2)][num2hex(m, 2)][num2hex(c, 2)]" - if(5) - return "#[num2hex(c, 2)][num2hex(m, 2)][num2hex(x, 2)]" - - #undef CHAT_LAYER_MAX_Z #undef CHAT_LAYER_Z_STEP #undef CHAT_MESSAGE_APPROX_LHEIGHT @@ -388,7 +335,3 @@ #undef CHAT_MESSAGE_LIFESPAN #undef CHAT_MESSAGE_SPAWN_TIME #undef CHAT_MESSAGE_WIDTH -#undef CM_COLOR_LUM_MAX -#undef CM_COLOR_LUM_MIN -#undef CM_COLOR_SAT_MAX -#undef CM_COLOR_SAT_MIN diff --git a/code/datums/components/callouts.dm b/code/datums/components/callouts.dm new file mode 100644 index 00000000000000..98d489cc915a97 --- /dev/null +++ b/code/datums/components/callouts.dm @@ -0,0 +1,177 @@ +#define CALLOUT_TIME (5 SECONDS) +#define CALLOUT_COOLDOWN 3 SECONDS + +/// Component that allows its owner/owner's wearer to use callouts system - their pointing is replaced with a fancy radial which allows them to summon glowing markers +/datum/component/callouts + /// If parent is clothing, slot on which this component activates + var/item_slot + /// If we are currently active + var/active = TRUE + /// Current user of this component + var/mob/cur_user + /// Whenever the user should shout the voiceline + var/voiceline = FALSE + /// If voiceline is true, what prefix the user should use + var/radio_prefix = null + /// List of all callout options + var/static/list/callout_options = typecacheof(subtypesof(/datum/callout_option)) + /// Text displayed when parent is examined + var/examine_text = null + /// Cooldown for callouts + COOLDOWN_DECLARE(callout_cooldown) + +/datum/component/callouts/Initialize(item_slot = null, voiceline = FALSE, radio_prefix = null, examine_text = null) + if (!isitem(parent) && !ismob(parent)) + return COMPONENT_INCOMPATIBLE + src.item_slot = item_slot + src.voiceline = voiceline + src.radio_prefix = radio_prefix + src.examine_text = examine_text + + if (ismob(parent)) + cur_user = parent + return + + var/atom/atom_parent = parent + + if (!ismob(atom_parent.loc)) + return + + var/mob/user = atom_parent.loc + if (!isnull(item_slot) && user.get_item_by_slot(item_slot) != parent) + return + + RegisterSignal(atom_parent.loc, COMSIG_MOB_CLICKON, PROC_REF(on_click)) + cur_user = atom_parent.loc + +/datum/component/callouts/Destroy(force) + cur_user = null + . = ..() + +/datum/component/callouts/RegisterWithParent() + RegisterSignal(parent, COMSIG_MOB_CLICKON, PROC_REF(on_click)) + RegisterSignal(parent, COMSIG_ITEM_EQUIPPED, PROC_REF(on_equipped)) + RegisterSignal(parent, COMSIG_ITEM_DROPPED, PROC_REF(on_dropped)) + RegisterSignal(parent, COMSIG_ATOM_EXAMINE, PROC_REF(on_examines)) + RegisterSignal(parent, COMSIG_CLICK_CTRL, PROC_REF(on_ctrl_click)) + +/datum/component/callouts/UnregisterFromParent() + UnregisterSignal(parent, list(COMSIG_MOB_CLICKON, COMSIG_ITEM_EQUIPPED, COMSIG_ITEM_DROPPED, COMSIG_ATOM_EXAMINE, COMSIG_CLICK_CTRL)) + +/datum/component/callouts/proc/on_ctrl_click(datum/source, mob/living/user) + SIGNAL_HANDLER + + if(!isitem(parent)) + return + + var/obj/item/item_parent = parent + active = !active + item_parent.balloon_alert(user, active ? "callouts enabled" : "callouts disabled") + +/datum/component/callouts/proc/on_equipped(datum/source, mob/equipper, slot) + SIGNAL_HANDLER + + if (item_slot & slot) + RegisterSignal(equipper, COMSIG_MOB_CLICKON, PROC_REF(on_click)) + cur_user = equipper + else if (cur_user == equipper) + UnregisterSignal(cur_user, COMSIG_MOB_CLICKON, PROC_REF(on_click)) + cur_user = null + +/datum/component/callouts/proc/on_dropped(datum/source, mob/user) + SIGNAL_HANDLER + + if (cur_user == user) + UnregisterSignal(cur_user, COMSIG_MOB_CLICKON, PROC_REF(on_click)) + cur_user = null + +/datum/component/callouts/proc/on_examines(mob/source, mob/user, list/examine_list) + SIGNAL_HANDLER + if (!isnull(examine_text)) + examine_list += examine_text + +/datum/component/callouts/proc/on_click(mob/user, atom/clicked_atom, list/modifiers) + SIGNAL_HANDLER + + if (!LAZYACCESS(modifiers, SHIFT_CLICK) || !LAZYACCESS(modifiers, MIDDLE_CLICK)) + return + + if (!active) + return + + if (!COOLDOWN_FINISHED(src, callout_cooldown)) + clicked_atom.balloon_alert(user, "callout is on cooldown!") + return COMSIG_MOB_CANCEL_CLICKON + + INVOKE_ASYNC(src, PROC_REF(callout_picker), user, clicked_atom) + return COMSIG_MOB_CANCEL_CLICKON + +/datum/component/callouts/proc/callout_picker(mob/user, atom/clicked_atom) + var/list/callout_items = list() + for(var/datum/callout_option/callout_option as anything in callout_options) + callout_items[callout_option] = image(icon = 'icons/hud/radial.dmi', icon_state = callout_option::icon_state) + + var/datum/callout_option/selection = show_radial_menu(user, get_turf(clicked_atom), callout_items, entry_animation = FALSE, click_on_hover = TRUE, user_space = TRUE) + if (!selection) + return + + COOLDOWN_START(src, callout_cooldown, CALLOUT_COOLDOWN) + new /obj/effect/temp_visual/callout(get_turf(user), user, selection, clicked_atom) + SEND_SIGNAL(user, COMSIG_MOB_CREATED_CALLOUT, selection, clicked_atom) + if (voiceline) + user.say((!isnull(radio_prefix) ? radio_prefix : "") + selection::voiceline, forced = src) + +/obj/effect/temp_visual/callout + name = "callout" + icon = 'icons/effects/callouts.dmi' + icon_state = "point" + plane = ABOVE_LIGHTING_PLANE + duration = CALLOUT_TIME + +/obj/effect/temp_visual/callout/Initialize(mapload, mob/creator, datum/callout_option/callout, atom/target) + . = ..() + if (isnull(creator)) + return + icon_state = callout::icon_state + color = colorize_string(creator.GetVoice(), 2, 0.9) + update_appearance() + var/turf/target_loc = get_turf(target) + animate(src, pixel_x = (target_loc.x - loc.x) * world.icon_size + target.pixel_x, pixel_y = (target_loc.y - loc.y) * world.icon_size + target.pixel_y, time = 0.2 SECONDS, easing = EASE_OUT) + +/datum/callout_option + var/name = "ERROR" + var/icon_state = "point" + var/voiceline = "Something has gone wrong!" + +/datum/callout_option/point + name = "Point" + icon_state = "point" + voiceline = "Here!" + +/datum/callout_option/danger + name = "Danger" + icon_state = "danger" + voiceline = "Danger there!" + +/datum/callout_option/guard + name = "Guard" + icon_state = "guard" + voiceline = "Hold this position!" + +/datum/callout_option/attack + name = "Attack" + icon_state = "attack" + voiceline = "Attack there!" + +/datum/callout_option/mine + name = "Mine" + icon_state = "mine" + voiceline = "Dig here!" + +/datum/callout_option/move + name = "Move" + icon_state = "move" + voiceline = "Reposition there!" + +#undef CALLOUT_TIME +#undef CALLOUT_COOLDOWN diff --git a/code/datums/components/crafting/equipment.dm b/code/datums/components/crafting/equipment.dm index eeea4205a4d290..75b257156084e6 100644 --- a/code/datums/components/crafting/equipment.dm +++ b/code/datums/components/crafting/equipment.dm @@ -23,6 +23,17 @@ time = 4 SECONDS category = CAT_EQUIPMENT +/datum/crafting_recipe/improvisedshield + name = "Moonflower Shield" + result = /obj/item/shield/buckler/moonflower + reqs = list( + /obj/item/seeds/sunflower/moonflower = 3, + /obj/item/grown/log/steel = 3, + ) + time = 4 SECONDS + category = CAT_EQUIPMENT + + /datum/crafting_recipe/radiogloves name = "Radio Gloves" result = /obj/item/clothing/gloves/radio diff --git a/code/datums/components/crafting/melee_weapon.dm b/code/datums/components/crafting/melee_weapon.dm index 594ff7aefd3876..018d99d8703523 100644 --- a/code/datums/components/crafting/melee_weapon.dm +++ b/code/datums/components/crafting/melee_weapon.dm @@ -191,3 +191,13 @@ ) time = 10 SECONDS category = CAT_WEAPON_MELEE + +/datum/crafting_recipe/bambostaff + name = "Bamboo Bo Staff" + result = /obj/item/bambostaff + reqs = list( + /obj/item/stack/sheet/mineral/bamboo = 4, + /obj/item/grown/log/steel = 2, + ) + time = 8 SECONDS + category = CAT_WEAPON_MELEE diff --git a/code/datums/components/crafting/misc.dm b/code/datums/components/crafting/misc.dm index 606cf1fc292620..52c66253e824b5 100644 --- a/code/datums/components/crafting/misc.dm +++ b/code/datums/components/crafting/misc.dm @@ -35,6 +35,17 @@ tool_paths = list(/obj/item/stamp/head/captain) category = CAT_MISC +/datum/crafting_recipe/clipboard + name = "Clipboard" + result = /obj/item/clipboard + time = 3 SECONDS + reqs = list( + /obj/item/stack/sheet/mineral/wood = 1, + /obj/item/stack/rods = 1, + ) + tool_behaviors = list(TOOL_WIRECUTTER) + category = CAT_MISC + /datum/crafting_recipe/cardboard_id name = "Cardboard ID Card" tool_behaviors = list(TOOL_WIRECUTTER) diff --git a/code/datums/components/crafting/tailoring.dm b/code/datums/components/crafting/tailoring.dm index 2bcec49aeb5045..3c498f74416bd5 100644 --- a/code/datums/components/crafting/tailoring.dm +++ b/code/datums/components/crafting/tailoring.dm @@ -6,6 +6,61 @@ time = 5 SECONDS category = CAT_CLOTHING +/datum/crafting_recipe/durathread_robe + name = "Durathread Robe" + result = /obj/item/clothing/suit/wizrobe/durathread + reqs = list( + /obj/item/stack/sheet/durathread = 3, + /obj/item/stack/sheet/leather = 6, + ) + time = 5 SECONDS + category = CAT_CLOTHING + +/datum/crafting_recipe/durathread_robe_fire + name = "Durathread Pyromancer Robe" + result = /obj/item/clothing/suit/wizrobe/durathread/fire + reqs = list(/obj/item/clothing/suit/wizrobe/durathread = 1, + /obj/item/grown/novaflower = 1, + /obj/item/seeds/chili = 3) + time = 2 SECONDS + category = CAT_CLOTHING + +/datum/crafting_recipe/durathread_robe_ice + name = "Durathread Ice-o-mancer Robe" + result = /obj/item/clothing/suit/wizrobe/durathread/ice + reqs = list(/obj/item/clothing/suit/wizrobe/durathread = 1, + /obj/item/seeds/chili/ice = 1, + /obj/item/food/grown/herbs = 3) + time = 2 SECONDS + category = CAT_CLOTHING + +/datum/crafting_recipe/durathread_robe_electric + name = "Durathread Electromancer Robe" + result = /obj/item/clothing/suit/wizrobe/durathread/electric + reqs = list(/obj/item/clothing/suit/wizrobe/durathread = 1, + /obj/item/food/grown/mushroom/jupitercup = 1, + /obj/item/food/grown/sunflower = 3) + time = 2 SECONDS + category = CAT_CLOTHING + +/datum/crafting_recipe/durathread_robe_earth + name = "Durathread Geomancer Robe" + result = /obj/item/clothing/suit/wizrobe/durathread/earth + reqs = list(/obj/item/clothing/suit/wizrobe/durathread = 1, + /obj/item/food/grown/cahnroot = 1, + /obj/item/food/grown/potato = 3) + time = 2 SECONDS + category = CAT_CLOTHING + +/datum/crafting_recipe/durathread_robe_necro + name = "Durathread Necromancer Robe" + result = /obj/item/clothing/suit/wizrobe/durathread/necro + reqs = list(/obj/item/clothing/suit/wizrobe/durathread = 1, + /obj/item/food/grown/cannabis/death = 2, + /obj/item/food/grown/mushroom/angel = 2) + time = 2 SECONDS + category = CAT_CLOTHING + /datum/crafting_recipe/durathread_helmet name = "Durathread Helmet" result = /obj/item/clothing/head/helmet/durathread @@ -14,6 +69,62 @@ time = 4 SECONDS category = CAT_CLOTHING +/datum/crafting_recipe/watermelon_armour + name = "Watermelon Armour" + result = /obj/item/clothing/suit/armor/durability/watermelon + reqs = list(/obj/item/clothing/head/helmet/durability/watermelon = 3, + /obj/item/stack/sheet/durathread = 1) + time = 4 SECONDS + category = CAT_CLOTHING + +/datum/crafting_recipe/watermelon_armour_fr + name = "Watermelon Armour" + result = /obj/item/clothing/suit/armor/durability/watermelon/fire_resist + reqs = list(/obj/item/clothing/head/helmet/durability/watermelon/fire_resist = 3, + /obj/item/stack/sheet/durathread = 1) + time = 4 SECONDS + category = CAT_CLOTHING + +/datum/crafting_recipe/holymelon_armour + name = "Holymelon Armour" + result = /obj/item/clothing/suit/armor/durability/holymelon + reqs = list(/obj/item/clothing/head/helmet/durability/holymelon = 3, + /obj/item/stack/sheet/durathread = 1) + time = 4 SECONDS + category = CAT_CLOTHING + +/datum/crafting_recipe/holymelonmelon_armour_fr + name = "Holymelon Armour" + result = /obj/item/clothing/suit/armor/durability/holymelon/fire_resist + reqs = list(/obj/item/clothing/head/helmet/durability/holymelon/fire_resist = 3, + /obj/item/stack/sheet/durathread = 1) + time = 4 SECONDS + category = CAT_CLOTHING + +/datum/crafting_recipe/barrelmelon_armour + name = "Barrelmelon Armour" + result = /obj/item/clothing/suit/armor/durability/barrelmelon + reqs = list(/obj/item/clothing/head/helmet/durability/barrelmelon = 3, + /obj/item/stack/sheet/durathread = 1) + time = 4 SECONDS + category = CAT_CLOTHING + +/datum/crafting_recipe/barrelmelon_armour_fr + name = "Barrelmelon Armour" + result = /obj/item/clothing/suit/armor/durability/barrelmelon/fire_resist + reqs = list(/obj/item/clothing/head/helmet/durability/barrelmelon/fire_resist = 3, + /obj/item/stack/sheet/durathread = 1) + time = 4 SECONDS + category = CAT_CLOTHING + +/datum/crafting_recipe/grass_sheath + name = "Grass Sabre Sheath" + result = /obj/item/storage/belt/grass_sabre + reqs = list(/obj/item/food/grown/grass = 4, + /obj/item/food/grown/grass/fairy = 2) + time = 4 SECONDS + category = CAT_CONTAINERS + /datum/crafting_recipe/fannypack name = "Fannypack" result = /obj/item/storage/belt/fannypack diff --git a/code/datums/components/crafting/weapon_ammo.dm b/code/datums/components/crafting/weapon_ammo.dm index 2ba01802e7cdd4..9a3448bc803a36 100644 --- a/code/datums/components/crafting/weapon_ammo.dm +++ b/code/datums/components/crafting/weapon_ammo.dm @@ -127,6 +127,28 @@ category = CAT_WEAPON_AMMO crafting_flags = CRAFT_CHECK_DENSITY | CRAFT_MUST_BE_LEARNED +/datum/crafting_recipe/sticky_arrow + name = "Sticky arrow" + result = /obj/item/ammo_casing/arrow/sticky + reqs = list( + /obj/item/ammo_casing/arrow = 1, + /obj/item/food/honeycomb = 3, + ) + time = 5 SECONDS + category = CAT_WEAPON_AMMO + crafting_flags = CRAFT_CHECK_DENSITY + +/datum/crafting_recipe/poison_arrow + name = "Poison arrow" + result = /obj/item/ammo_casing/arrow/poison + reqs = list( + /obj/item/ammo_casing/arrow = 1, + /obj/item/food/grown/berries/poison = 5, + ) + time = 5 SECONDS + category = CAT_WEAPON_AMMO + crafting_flags = CRAFT_CHECK_DENSITY + /datum/crafting_recipe/plastic_arrow name = "Plastic Arrow" result = /obj/item/ammo_casing/arrow/plastic diff --git a/code/datums/components/echolocation.dm b/code/datums/components/echolocation.dm index 020c47ad875e1b..51ab89a2be5642 100644 --- a/code/datums/components/echolocation.dm +++ b/code/datums/components/echolocation.dm @@ -32,7 +32,7 @@ /// Cooldown for the echolocation. COOLDOWN_DECLARE(cooldown_last) -/datum/component/echolocation/Initialize(echo_range, cooldown_time, image_expiry_time, fade_in_time, fade_out_time, images_are_static, blocking_trait, echo_group, echo_icon = "echo", color_path) +/datum/component/echolocation/Initialize(echo_range, cooldown_time, image_expiry_time, fade_in_time, fade_out_time, images_are_static, blocking_trait, echo_group, echo_icon, color_path) . = ..() var/mob/living/echolocator = parent if(!istype(echolocator)) diff --git a/code/datums/components/fish_growth.dm b/code/datums/components/fish_growth.dm new file mode 100644 index 00000000000000..bc7c8a9869e44b --- /dev/null +++ b/code/datums/components/fish_growth.dm @@ -0,0 +1,57 @@ +///A simple component that manages raising things from aquarium fish. +/datum/component/fish_growth + dupe_mode = COMPONENT_DUPE_SELECTIVE + ///the type of the movable that's spawned when the fish grows up. + var/result_type + ///The progress, from 0 to 100 + var/maturation + ///How much maturation is gained per tick + var/growth_rate + ///Is the result moved on the nearest drop location? + var/use_drop_loc + ///Is the parent deleted once the result is spawned? + var/del_on_grow + +/datum/component/fish_growth/Initialize(result_type, growth_rate, use_drop_loc = TRUE, del_on_grow = TRUE) + . = ..() + if(!isfish(parent)) + return COMPONENT_INCOMPATIBLE + RegisterSignal(parent, COMSIG_FISH_LIFE, PROC_REF(on_fish_life)) + src.result_type = result_type + src.growth_rate = growth_rate + src.use_drop_loc = use_drop_loc + src.del_on_grow = del_on_grow + +/datum/component/fish_growth/CheckDupeComponent(result_type, growth_rate, use_drop_loc = TRUE, del_on_grow = TRUE) + if(result_type == src.result_type) + src.growth_rate = growth_rate + return TRUE //copy the growth rate and kill the new component + return FALSE + +/datum/component/fish_growth/proc/on_fish_life(obj/item/fish/source, seconds_per_tick) + SIGNAL_HANDLER + if(SEND_SIGNAL(source, COMSIG_FISH_BEFORE_GROWING, seconds_per_tick) & COMPONENT_DONT_GROW) + return + maturation += growth_rate * seconds_per_tick + if(maturation >= 100) + finish_growing(source) + +/datum/component/fish_growth/proc/finish_growing(obj/item/fish/source) + var/atom/location = use_drop_loc ? source.drop_location() : source.loc + var/atom/movable/result = new result_type (location) + if(location != source.loc) + result.visible_message(span_boldnotice("\A [result] jumps out of [source.loc]!")) + playsound(result, 'sound/effects/fish_splash.ogg', 60) + if(isbasicmob(result)) + for(var/trait_type in source.fish_traits) + var/datum/fish_trait/trait = GLOB.fish_traits[trait_type] + trait.apply_to_mob(result) + + addtimer(CALLBACK(result, TYPE_PROC_REF(/mob/living/basic, hop_on_nearby_turf)), 0.1 SECONDS) + + SEND_SIGNAL(source, COMSIG_FISH_FINISH_GROWING, result) + + if(del_on_grow) + qdel(parent) + else + maturation = 0 diff --git a/code/datums/components/heart_eater.dm b/code/datums/components/heart_eater.dm index 5b73c40c9549e6..507090b9452b09 100644 --- a/code/datums/components/heart_eater.dm +++ b/code/datums/components/heart_eater.dm @@ -68,6 +68,9 @@ var/obj/item/organ/internal/heart/previous_heart = last_heart_we_ate?.resolve() if(we_ate_heart == previous_heart) return + if (!HAS_TRAIT(we_ate_heart, TRAIT_USED_ORGAN)) + to_chat(eater, span_warning("This heart is utterly lifeless, you won't receive any boons from consuming it!")) + return bites_taken = 0 last_heart_we_ate = WEAKREF(we_ate_heart) diff --git a/code/datums/components/pet_commands/pet_command.dm b/code/datums/components/pet_commands/pet_command.dm index 6ae249d2340aa5..a8db88d3a44ef7 100644 --- a/code/datums/components/pet_commands/pet_command.dm +++ b/code/datums/components/pet_commands/pet_command.dm @@ -18,6 +18,8 @@ var/radial_icon_state /// Speech strings to listen out for var/list/speech_commands = list() + /// Callout that triggers this command + var/callout_type /// Shown above the mob's head when it hears you var/command_feedback /// How close a mob needs to be to a target to respond to a command @@ -31,10 +33,11 @@ /datum/pet_command/proc/add_new_friend(mob/living/tamer) RegisterSignal(tamer, COMSIG_MOB_SAY, PROC_REF(respond_to_command)) RegisterSignal(tamer, COMSIG_MOB_AUTOMUTE_CHECK, PROC_REF(waive_automute)) + RegisterSignal(tamer, COMSIG_MOB_CREATED_CALLOUT, PROC_REF(respond_to_callout)) /// Stop listening to a guy /datum/pet_command/proc/remove_friend(mob/living/unfriended) - UnregisterSignal(unfriended, list(COMSIG_MOB_SAY, COMSIG_MOB_AUTOMUTE_CHECK)) + UnregisterSignal(unfriended, list(COMSIG_MOB_SAY, COMSIG_MOB_AUTOMUTE_CHECK, COMSIG_MOB_CREATED_CALLOUT)) /// Stop the automute from triggering for commands (unless the spoken text is suspiciously longer than the command) /datum/pet_command/proc/waive_automute(mob/living/speaker, client/client, last_message, mute_type) @@ -59,6 +62,34 @@ try_activate_command(speaker) +/// Respond to a callout +/datum/pet_command/proc/respond_to_callout(mob/living/caller, datum/callout_option/callout, atom/target) + SIGNAL_HANDLER + + if (isnull(callout_type) || !ispath(callout, callout_type)) + return + + var/mob/living/parent = weak_parent.resolve() + if (!parent) + return + + if (!valid_callout_target(caller, callout, target)) + var/found_new_target = FALSE + for (var/atom/new_target in range(2, target)) + if (valid_callout_target(caller, callout, new_target)) + target = new_target + found_new_target = TRUE + + if (!found_new_target) + return + + if (try_activate_command(caller)) + look_for_target(parent, target) + +/// Does this callout with this target trigger this command? +/datum/pet_command/proc/valid_callout_target(mob/living/caller, datum/callout_option/callout, atom/target) + return TRUE + /** * Returns true if we find any of our spoken commands in the text. * if check_verbosity is true, skip the match if there spoken_text is way longer than the match @@ -76,14 +107,35 @@ /datum/pet_command/proc/try_activate_command(mob/living/commander) var/mob/living/parent = weak_parent.resolve() if (!parent) - return + return FALSE if (!parent.ai_controller) // We stopped having a brain at some point - return + return FALSE if (IS_DEAD_OR_INCAP(parent)) // Probably can't hear them if we're dead - return + return FALSE if (parent.ai_controller.blackboard[BB_ACTIVE_PET_COMMAND] == src) // We're already doing it - return + return FALSE set_command_active(parent, commander) + return TRUE + +/// Target the pointed atom for actions +/datum/pet_command/proc/look_for_target(mob/living/friend, atom/pointed_atom) + var/mob/living/parent = weak_parent.resolve() + if (!parent) + return FALSE + if (!parent.ai_controller) + return FALSE + if (IS_DEAD_OR_INCAP(parent)) + return FALSE + if (parent.ai_controller.blackboard[BB_ACTIVE_PET_COMMAND] != src) // We're not listening right now + return FALSE + if (parent.ai_controller.blackboard[BB_CURRENT_PET_TARGET] == pointed_atom) // That's already our target + return FALSE + if (!can_see(parent, pointed_atom, sense_radius)) + return FALSE + + parent.ai_controller.CancelActions() + set_command_target(parent, pointed_atom) + return TRUE /// Activate the command, extend to add visible messages and the like /datum/pet_command/proc/set_command_active(mob/living/parent, mob/living/commander) @@ -134,33 +186,22 @@ /datum/pet_command/point_targeting/add_new_friend(mob/living/tamer) . = ..() - RegisterSignal(tamer, COMSIG_MOB_POINTED, PROC_REF(look_for_target)) + RegisterSignal(tamer, COMSIG_MOB_POINTED, PROC_REF(on_point)) /datum/pet_command/point_targeting/remove_friend(mob/living/unfriended) . = ..() UnregisterSignal(unfriended, COMSIG_MOB_POINTED) /// Target the pointed atom for actions -/datum/pet_command/point_targeting/proc/look_for_target(mob/living/friend, atom/pointed_atom) +/datum/pet_command/point_targeting/proc/on_point(mob/living/friend, atom/pointed_atom) SIGNAL_HANDLER var/mob/living/parent = weak_parent.resolve() if (!parent) return FALSE - if (!parent.ai_controller) - return FALSE - if (IS_DEAD_OR_INCAP(parent)) - return FALSE - if (parent.ai_controller.blackboard[BB_ACTIVE_PET_COMMAND] != src) // We're not listening right now - return FALSE - if (parent.ai_controller.blackboard[BB_CURRENT_PET_TARGET] == pointed_atom) // That's already our target - return FALSE - if (!can_see(parent, pointed_atom, sense_radius)) - return FALSE parent.ai_controller.CancelActions() - // Deciding if they can actually do anything with this target is the behaviour's job - if(set_command_target(parent, pointed_atom)) - // These are usually hostile actions so should have a record in chat - parent.visible_message(span_warning("[parent] follows [friend]'s gesture towards [pointed_atom][pointed_reaction ? " [pointed_reaction]" : ""]!")) - return TRUE + if (look_for_target(friend, pointed_atom) && set_command_target(parent, pointed_atom)) + parent.visible_message(span_warning("[parent] follows [friend]'s gesture towards [pointed_atom] [pointed_reaction]!")) + return TRUE + return FALSE diff --git a/code/datums/components/pet_commands/pet_commands_basic.dm b/code/datums/components/pet_commands/pet_commands_basic.dm index ad48bba0ffd07a..9f4dda9cca3948 100644 --- a/code/datums/components/pet_commands/pet_commands_basic.dm +++ b/code/datums/components/pet_commands/pet_commands_basic.dm @@ -41,6 +41,7 @@ radial_icon = 'icons/testing/turf_analysis.dmi' radial_icon_state = "red_arrow" speech_commands = list("heel", "follow") + callout_type = /datum/callout_option/move ///the behavior we use to follow var/follow_behavior = /datum/ai_behavior/pet_follow_friend @@ -124,6 +125,7 @@ radial_icon = 'icons/effects/effects.dmi' radial_icon_state = "bite" + callout_type = /datum/callout_option/attack speech_commands = list("attack", "sic", "kill") command_feedback = "growl" pointed_reaction = "and growls" @@ -220,6 +222,7 @@ command_name = "Protect owner" command_desc = "Your pet will run to your aid." hidden = TRUE + callout_type = /datum/callout_option/guard ///the range our owner needs to be in for us to protect him var/protect_range = 9 ///the behavior we will use when he is attacked @@ -250,6 +253,9 @@ . = ..() set_command_target(parent, victim) +/datum/pet_command/protect_owner/valid_callout_target(mob/living/caller, datum/callout_option/callout, atom/target) + return target == caller || get_dist(caller, target) <= 1 + /datum/pet_command/protect_owner/proc/set_attacking_target(atom/source, mob/living/attacker) SIGNAL_HANDLER diff --git a/code/datums/components/profound_fisher.dm b/code/datums/components/profound_fisher.dm index 1bc10b8ac303b7..4485115db06e6b 100644 --- a/code/datums/components/profound_fisher.dm +++ b/code/datums/components/profound_fisher.dm @@ -58,5 +58,6 @@ /obj/item/fishing_rod/mob_fisher display_fishing_line = FALSE line = /obj/item/fishing_line/reinforced + bait = /obj/item/food/bait/doughball/synthetic/unconsumable diff --git a/code/datums/components/spirit_holding.dm b/code/datums/components/spirit_holding.dm index 2f0588c6c22a2a..b510fde3523a42 100644 --- a/code/datums/components/spirit_holding.dm +++ b/code/datums/components/spirit_holding.dm @@ -7,9 +7,9 @@ ///bool on if this component is currently polling for observers to inhabit the item var/attempting_awakening = FALSE /// Allows renaming the bound item - var/allow_renaming + var/allow_renaming = TRUE /// Allows channeling - var/allow_channeling + var/allow_channeling = TRUE /// Allows exorcism var/allow_exorcism ///mob contained in the item. @@ -92,7 +92,7 @@ to_chat(ghost, span_userdanger("The new vessel for your spirit has been destroyed! You remain an unbound ghost.")) return - bind_the_soule(ghost, awakener) + bind_the_soule(ghost.mind, awakener) attempting_awakening = FALSE @@ -119,11 +119,13 @@ * Arguments: * * awakener: user who interacted with the blade */ -/datum/component/spirit_holding/proc/custom_name(mob/awakener) +/datum/component/spirit_holding/proc/custom_name(mob/awakener, iteration = 1) + if(iteration > 5) + return "indecision" // The spirit of indecision var/chosen_name = sanitize_name(tgui_input_text(bound_spirit, "What are you named?", "Spectral Nomenclature", max_length = MAX_NAME_LEN)) if(!chosen_name) // with the way that sanitize_name works, it'll actually send the error message to the awakener as well. - to_chat(awakener, span_warning("Your blade did not select a valid name! Please wait as they try again.")) // more verbose than what sanitize_name might pass in its error message - return custom_name(awakener) + to_chat(awakener, span_warning("Your blade did not select a valid name! Please wait as they try again.")) // more verbose than what sanitize_name might pass in it's error message + return custom_name(awakener, iteration++) return chosen_name ///signal fired from a mob moving inside the parent diff --git a/code/datums/components/uplink.dm b/code/datums/components/uplink.dm index a5ff46964bf6fa..d64022d22b8721 100644 --- a/code/datums/components/uplink.dm +++ b/code/datums/components/uplink.dm @@ -227,9 +227,12 @@ for(var/datum/uplink_item/item as anything in uplink_handler.extra_purchasable) if(item.stock_key in stock_list) extra_purchasable_stock[REF(item)] = stock_list[item.stock_key] + var/atom/actual_item = item.item extra_purchasable += list(list( "id" = item.type, "name" = item.name, + "icon" = actual_item.icon, + "icon_state" = actual_item.icon_state, "cost" = item.cost, "desc" = item.desc, "category" = item.category ? initial(item.category.name) : null, @@ -288,6 +291,13 @@ return item = SStraitor.uplink_items_by_type[item_path] uplink_handler.purchase_item(ui.user, item, parent) + if("buy_raw_tc") + if (uplink_handler.telecrystals <= 0) + return + var/desired_amount = tgui_input_number(ui.user, "How many raw telecrystals to buy?", "Buy Raw TC", default = uplink_handler.telecrystals, max_value = uplink_handler.telecrystals) + if(!desired_amount || desired_amount < 1) + return + uplink_handler.purchase_raw_tc(ui.user, desired_amount, parent) if("lock") if(!lockable) return TRUE diff --git a/code/datums/components/vacuum.dm b/code/datums/components/vacuum.dm index c471dc13a16bcf..0bf7888ff47e3b 100644 --- a/code/datums/components/vacuum.dm +++ b/code/datums/components/vacuum.dm @@ -53,7 +53,7 @@ if (!isitem(potential_item)) continue var/obj/item/item = potential_item - if (vacuum_bag?.attackby(item)) + if (vacuum_bag.atom_storage.attempt_insert(item)) sucked = TRUE // track that we successfully sucked up something // if we did indeed suck up something, play a funny noise diff --git a/code/datums/datum.dm b/code/datums/datum.dm index f4fd0190b2ab91..59a1d54571d3cb 100644 --- a/code/datums/datum.dm +++ b/code/datums/datum.dm @@ -111,6 +111,9 @@ tag = null datum_flags &= ~DF_USE_TAG //In case something tries to REF us weak_reference = null //ensure prompt GCing of weakref. + if(!(datum_flags & DF_STATIC_OBJECT)) + DREAMLUAU_CLEAR_REF_USERDATA(vars) // vars ceases existing when src does, so we need to clear any lua refs to it that exist. + DREAMLUAU_CLEAR_REF_USERDATA(src) if(_active_timers) var/list/timers = _active_timers diff --git a/code/datums/diseases/advance/symptoms/oxygen.dm b/code/datums/diseases/advance/symptoms/oxygen.dm index a7ea3bd181a790..79f0646a5c4b35 100644 --- a/code/datums/diseases/advance/symptoms/oxygen.dm +++ b/code/datums/diseases/advance/symptoms/oxygen.dm @@ -14,7 +14,7 @@ stage_speed = -3 transmittable = -4 level = 6 - base_message_chance = 5 + base_message_chance = 3 symptom_delay_min = 1 symptom_delay_max = 1 required_organ = ORGAN_SLOT_LUNGS @@ -40,6 +40,8 @@ if(4, 5) infected_mob.losebreath = max(0, infected_mob.losebreath - 4) infected_mob.adjustOxyLoss(-7) + if(prob(base_message_chance)) + to_chat(infected_mob, span_notice("You realize you haven't been breathing.")) if(regenerate_blood && infected_mob.blood_volume < BLOOD_VOLUME_NORMAL) infected_mob.blood_volume += 1 else @@ -54,9 +56,12 @@ var/mob/living/carbon/infected_mob = advanced_disease.affected_mob if(advanced_disease.stage >= 4) ADD_TRAIT(infected_mob, TRAIT_NOBREATH, DISEASE_TRAIT) - to_chat(infected_mob, span_notice(pick("You realize you haven't been breathing.", "You don't feel the need to breathe."))) + if(advanced_disease.stage == 4) + to_chat(infected_mob, span_notice("You don't feel the need to breathe anymore.")) else REMOVE_TRAIT(infected_mob, TRAIT_NOBREATH, DISEASE_TRAIT) + if(advanced_disease.stage_peaked && advanced_disease.stage == 3) + to_chat(infected_mob, span_notice("You feel the need to breathe again.")) return TRUE /datum/symptom/oxygen/End(datum/disease/advance/advanced_disease) diff --git a/code/datums/dna.dm b/code/datums/dna.dm index 1bc504ab1b725c..df92d57c59b4c7 100644 --- a/code/datums/dna.dm +++ b/code/datums/dna.dm @@ -216,8 +216,6 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) L[DNA_TAIL_BLOCK] = construct_block(SSaccessories.tails_list_human.Find(features["tail_cat"]), length(SSaccessories.tails_list_human)) if(features["tail_lizard"]) L[DNA_LIZARD_TAIL_BLOCK] = construct_block(SSaccessories.tails_list_lizard.Find(features["tail_lizard"]), length(SSaccessories.tails_list_lizard)) - if(features["tail_monkey"]) - L[DNA_MONKEY_TAIL_BLOCK] = construct_block(SSaccessories.tails_list_monkey.Find(features["tail_monkey"]), length(SSaccessories.tails_list_monkey)) if(features["snout"]) L[DNA_SNOUT_BLOCK] = construct_block(SSaccessories.snouts_list.Find(features["snout"]), length(SSaccessories.snouts_list)) if(features["horns"]) @@ -362,8 +360,6 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) set_uni_feature_block(blocknumber, construct_block(SSaccessories.tails_list_human.Find(features["tail_cat"]), length(SSaccessories.tails_list_human))) if(DNA_LIZARD_TAIL_BLOCK) set_uni_feature_block(blocknumber, construct_block(SSaccessories.tails_list_lizard.Find(features["tail_lizard"]), length(SSaccessories.tails_list_lizard))) - if(DNA_MONKEY_TAIL_BLOCK) - set_uni_feature_block(blocknumber, construct_block(SSaccessories.tails_list_monkey.Find(features["tail_monkey"]), length(SSaccessories.tails_list_monkey))) if(DNA_SNOUT_BLOCK) set_uni_feature_block(blocknumber, construct_block(SSaccessories.snouts_list.Find(features["snout"]), length(SSaccessories.snouts_list))) if(DNA_HORNS_BLOCK) @@ -669,8 +665,6 @@ GLOBAL_LIST_INIT(total_uf_len_by_block, populate_total_uf_len_by_block()) dna.features["tail_cat"] = SSaccessories.tails_list_human[deconstruct_block(get_uni_feature_block(features, DNA_TAIL_BLOCK), length(SSaccessories.tails_list_human))] if(dna.features["tail_lizard"]) dna.features["tail_lizard"] = SSaccessories.tails_list_lizard[deconstruct_block(get_uni_feature_block(features, DNA_LIZARD_TAIL_BLOCK), length(SSaccessories.tails_list_lizard))] - if(dna.features["tail_monkey"]) - dna.features["tail_monkey"] = SSaccessories.tails_list_monkey[deconstruct_block(get_uni_feature_block(features, DNA_MONKEY_TAIL_BLOCK), length(SSaccessories.tails_list_monkey))] if(dna.features["ears"]) dna.features["ears"] = SSaccessories.ears_list[deconstruct_block(get_uni_feature_block(features, DNA_EARS_BLOCK), length(SSaccessories.ears_list))] if(dna.features["moth_wings"]) diff --git a/code/datums/dog_fashion.dm b/code/datums/dog_fashion.dm index c2154736cc0f05..7aa7f120e75098 100644 --- a/code/datums/dog_fashion.dm +++ b/code/datums/dog_fashion.dm @@ -243,3 +243,18 @@ obj_icon_state = "eyepatch" emote_hear = list("sighs gruffly.", "groans.") emote_see = list("considers their own mortality.", "stares bleakly into the middle distance.", "ponders the horrors of warfare.") + +/datum/dog_fashion/head/watermelon + name = "Watermelon Warrior %REAL_NAME%" + desc = "5% safer than normal and ready to take on advantage!" + obj_icon_state = "watermelon" + +/datum/dog_fashion/head/holymelon + name = "Holymelon Paladin %REAL_NAME%" + desc = "Extraterrestial powers beware, %NAME% is here to smite you down!" + obj_icon_state = "holymelon" + +/datum/dog_fashion/head/barrelmelon + name = "Barrelmelon Berserk %REAL_NAME%" + desc = "Either the sturdiness of the helmet gave %REAL_NAME% a confidence boost, or its bit tight on their head..." + obj_icon_state = "barrelmelon" diff --git a/code/datums/elements/door_pryer.dm b/code/datums/elements/door_pryer.dm index b7f213b3856f6d..9f01e8be2b6ab9 100644 --- a/code/datums/elements/door_pryer.dm +++ b/code/datums/elements/door_pryer.dm @@ -35,12 +35,13 @@ attacker.balloon_alert(attacker, "busy!") return COMPONENT_CANCEL_ATTACK_CHAIN - if (airlock_target.locked || airlock_target.welded || airlock_target.seal) - if (!attacker.combat_mode) - airlock_target.balloon_alert(attacker, "it's sealed!") - return COMPONENT_CANCEL_ATTACK_CHAIN + if (attacker.combat_mode) return // Attack the door + if (airlock_target.locked || airlock_target.welded || airlock_target.seal) + airlock_target.balloon_alert(attacker, "it's sealed!") + return COMPONENT_CANCEL_ATTACK_CHAIN + INVOKE_ASYNC(src, PROC_REF(open_door), attacker, airlock_target) return COMPONENT_CANCEL_ATTACK_CHAIN diff --git a/code/datums/elements/pet_collar.dm b/code/datums/elements/pet_collar.dm new file mode 100644 index 00000000000000..5c49de2eceb5bd --- /dev/null +++ b/code/datums/elements/pet_collar.dm @@ -0,0 +1,95 @@ +/datum/element/wears_collar + element_flags = ELEMENT_BESPOKE + argument_hash_start_idx = 2 + ///our icon's pathfile + var/collar_icon + ///our collar's icon state + var/collar_icon_state + ///iconstate of our collar while resting + var/collar_resting_icon_state + +/datum/element/wears_collar/Attach(datum/target, collar_icon = 'icons/mob/simple/pets.dmi', collar_resting_icon_state = FALSE, collar_icon_state) + . = ..() + + if(!isliving(target)) + return ELEMENT_INCOMPATIBLE + + src.collar_icon = collar_icon + src.collar_icon_state = collar_icon_state + src.collar_resting_icon_state = collar_resting_icon_state + + RegisterSignal(target, COMSIG_ATOM_ATTACKBY, PROC_REF(attach_collar)) + RegisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_overlays_updated)) + RegisterSignal(target, COMSIG_ATOM_EXITED, PROC_REF(on_content_exit)) + RegisterSignal(target, COMSIG_ATOM_ENTERED, PROC_REF(on_content_enter)) + RegisterSignal(target, COMSIG_LIVING_RESTING, PROC_REF(on_rest)) + RegisterSignal(target, COMSIG_MOB_STATCHANGE, PROC_REF(on_stat_change)) + +/datum/element/wears_collar/Detach(datum/target) + . = ..() + UnregisterSignal(target, list( + COMSIG_ATOM_ATTACKBY, + COMSIG_ATOM_UPDATE_OVERLAYS, + COMSIG_ATOM_EXITED, + COMSIG_ATOM_ENTERED, + COMSIG_LIVING_RESTING, + COMSIG_MOB_STATCHANGE, + )) + +/datum/element/wears_collar/proc/on_stat_change(mob/living/source) + SIGNAL_HANDLER + + if(collar_icon_state) + source.update_icon(UPDATE_OVERLAYS) + +/datum/element/wears_collar/proc/on_content_exit(mob/living/source, atom/moved) + SIGNAL_HANDLER + + if(!istype(moved, /obj/item/clothing/neck/petcollar)) + return + source.fully_replace_character_name(null, source::name) + if(collar_icon_state) + source.update_appearance() + +/datum/element/wears_collar/proc/on_content_enter(mob/living/source, obj/item/clothing/neck/petcollar/new_collar) + SIGNAL_HANDLER + + if(!istype(new_collar)) + return + + source.fully_replace_character_name(null, "\proper [new_collar.tagname]") + if(collar_icon_state) + source.update_appearance() + +/datum/element/wears_collar/proc/attach_collar(atom/source, atom/movable/attacking_item, atom/user, params) + SIGNAL_HANDLER + + if(!istype(attacking_item, /obj/item/clothing/neck/petcollar)) + return NONE + if(locate(/obj/item/clothing/neck/petcollar) in source) + user.balloon_alert(source, "already wearing a collar!") + return NONE + attacking_item.forceMove(source) + return COMPONENT_NO_AFTERATTACK + +/datum/element/wears_collar/proc/on_overlays_updated(mob/living/source, list/overlays) + SIGNAL_HANDLER + + if(!locate(/obj/item/clothing/neck/petcollar) in source) + return + + var/icon_tag = "" + + if(source.stat == DEAD || HAS_TRAIT(source, TRAIT_FAKEDEATH)) + icon_tag = "_dead" + else if(collar_resting_icon_state && source.resting) + icon_tag = "_rest" + + overlays += mutable_appearance(collar_icon, "[collar_icon_state][icon_tag]collar") + overlays += mutable_appearance(collar_icon, "[collar_icon_state][icon_tag]tag") + + +/datum/element/wears_collar/proc/on_rest(atom/movable/source) + SIGNAL_HANDLER + + source.update_icon(UPDATE_OVERLAYS) diff --git a/code/datums/elements/pet_cult.dm b/code/datums/elements/pet_cult.dm new file mode 100644 index 00000000000000..36941e7b74299f --- /dev/null +++ b/code/datums/elements/pet_cult.dm @@ -0,0 +1,127 @@ +#define PET_CULT_ATTACK_UPPER 15 +#define PET_CULT_HEALTH 50 + +/datum/element/cultist_pet + element_flags = ELEMENT_BESPOKE + argument_hash_start_idx = 2 + ///our pet cult icon's pathfile + var/pet_cult_icon + ///our pet cult icon state + var/pet_cult_icon_state + +/datum/element/cultist_pet/Attach(datum/target, pet_cult_icon = 'icons/mob/simple/pets.dmi', pet_cult_icon_state) + . = ..() + + if(!isliving(target)) + return ELEMENT_INCOMPATIBLE + + src.pet_cult_icon = pet_cult_icon + src.pet_cult_icon_state = pet_cult_icon_state + + RegisterSignal(target, COMSIG_LIVING_CULT_SACRIFICED, PROC_REF(become_cultist)) + RegisterSignal(target, COMSIG_MOB_CLIENT_LOGIN, PROC_REF(on_login)) + RegisterSignal(target, COMSIG_ATOM_UPDATE_ICON_STATE, PROC_REF(on_icon_state_updated)) + RegisterSignal(target, COMSIG_ATOM_UPDATE_OVERLAYS, PROC_REF(on_overlays_updated)) + +/datum/element/cultist_pet/Detach(datum/target) + . = ..() + UnregisterSignal(target, list( + COMSIG_MOB_LOGIN, + COMSIG_LIVING_CULT_SACRIFICED, + COMSIG_ATOM_UPDATE_ICON_STATE, + COMSIG_ATOM_UPDATE_OVERLAYS, + )) + +/datum/element/cultist_pet/proc/on_overlays_updated(mob/living/basic/source, list/overlays) + SIGNAL_HANDLER + + if(isnull(source.mind) && (FACTION_CULT in source.faction)) //cult indicator we show for non sentient pets + var/image/cult_indicator = image(icon = 'icons/mob/simple/pets.dmi', icon_state = "pet_cult_indicator", layer = ABOVE_GAME_PLANE) + overlays += cult_indicator + +/datum/element/cultist_pet/proc/on_icon_state_updated(mob/living/basic/source) + SIGNAL_HANDLER + + if(pet_cult_icon_state && (FACTION_CULT in source.faction)) + source.icon_state = pet_cult_icon_state + source.icon_living = pet_cult_icon_state + +///turn into terrifying beasts +/datum/element/cultist_pet/proc/become_cultist(mob/living/basic/source, list/invokers, datum/team) + SIGNAL_HANDLER + + if(source.stat == DEAD) + return + + if(FACTION_CULT in source.faction) + return STOP_SACRIFICE + + source.mind?.add_antag_datum(/datum/antagonist/cult, team) + qdel(source.GetComponent(/datum/component/obeys_commands)) //if we obey commands previously, forget about them + source.melee_damage_lower = max(PET_CULT_ATTACK_UPPER - 5, source::melee_damage_lower) + source.melee_damage_upper = max(PET_CULT_ATTACK_UPPER, source::melee_damage_upper) + source.maxHealth = max(PET_CULT_HEALTH, source::maxHealth) + source.fully_heal() + + source.faction = list(FACTION_CULT) //we only serve the cult + + if(isnull(pet_cult_icon_state)) + source.add_atom_colour(RUNE_COLOR_MEDIUMRED, FIXED_COLOUR_PRIORITY) + + var/static/list/cult_appetite = list( + /obj/item/organ, + /obj/effect/decal/cleanable/blood, + ) + + var/static/list/death_loot = list( + /obj/effect/gibspawner/generic, + /obj/item/soulstone, + ) + + source.AddElement(/datum/element/basic_eating, heal_amt = 15, food_types = cult_appetite) + source.AddElement(/datum/element/death_drops, death_loot) + + source.basic_mob_flags &= DEL_ON_DEATH + qdel(source.ai_controller) + source.ai_controller = new /datum/ai_controller/basic_controller/pet_cult(source) + var/datum/action/cooldown/spell/conjure/revive_rune/rune_ability = new(source) + rune_ability.Grant(source) + source.ai_controller.set_blackboard_key(BB_RUNE_ABILITY, rune_ability) + source.ai_controller.set_blackboard_key(BB_CULT_TEAM, team) + + var/static/list/new_pet_commands = list( + /datum/pet_command/point_targeting/attack, + /datum/pet_command/follow, + /datum/pet_command/free, + /datum/pet_command/idle, + /datum/pet_command/untargeted_ability/draw_rune, + ) + source.AddComponent(/datum/component/obeys_commands, new_pet_commands) + RegisterSignal(source, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(activate_rune)) + source.update_appearance() + return STOP_SACRIFICE + + +/datum/element/cultist_pet/proc/activate_rune(datum/source, atom/target) + SIGNAL_HANDLER + + if(!istype(target, /obj/effect/rune/raise_dead)) //we can only revive people... + return NONE + + INVOKE_ASYNC(target, TYPE_PROC_REF(/atom, attack_hand), source) + return COMPONENT_CANCEL_ATTACK_CHAIN + +/datum/element/cultist_pet/proc/on_login(mob/living/source) + SIGNAL_HANDLER + + if(!(FACTION_CULT in source.faction)) + return + var/datum/team/cult_team = source.ai_controller.blackboard[BB_CULT_TEAM] + if(isnull(cult_team)) + return + source.mind.add_antag_datum(/datum/antagonist/cult, cult_team) + source.update_appearance(UPDATE_OVERLAYS) + + +#undef PET_CULT_ATTACK_UPPER +#undef PET_CULT_HEALTH diff --git a/code/datums/emotes.dm b/code/datums/emotes.dm index 331e11afa4893b..8d77c6fc6bdbbf 100644 --- a/code/datums/emotes.dm +++ b/code/datums/emotes.dm @@ -60,6 +60,8 @@ var/can_message_change = FALSE /// How long is the cooldown on the audio of the emote, if it has one? var/audio_cooldown = 2 SECONDS + /// Does this emote's sound ignore walls? + var/sound_wall_ignore = FALSE /datum/emote/New() switch(mob_type_allowed_typecache) @@ -100,7 +102,7 @@ var/tmp_sound = get_sound(user) if(tmp_sound && should_play_sound(user, intentional) && TIMER_COOLDOWN_FINISHED(user, type)) TIMER_COOLDOWN_START(user, type, audio_cooldown) - playsound(user, tmp_sound, 50, vary) + playsound(source = user,soundin = tmp_sound,vol = 50, vary = vary, ignore_walls = sound_wall_ignore) var/is_important = emote_type & EMOTE_IMPORTANT var/is_visual = emote_type & EMOTE_VISIBLE diff --git a/code/datums/greyscale/json_configs/meter.json b/code/datums/greyscale/json_configs/meter.json index 73cfb73995955f..344500c2a9dcc0 100644 --- a/code/datums/greyscale/json_configs/meter.json +++ b/code/datums/greyscale/json_configs/meter.json @@ -2,26 +2,26 @@ "meter": [ { "type": "icon_state", - "icon_state": "pressure_off", + "icon_state": "meter_base", "blend_mode": "overlay" }, { "type": "icon_state", - "icon_state": "meter_base", + "icon_state": "pressure_off", "blend_mode": "overlay" } ], "meter0": [ { "type": "icon_state", - "icon_state": "pressure0", - "blend_mode": "overlay", - "color_ids": [ 1 ] + "icon_state": "meter_base", + "blend_mode": "overlay" }, { "type": "icon_state", - "icon_state": "meter_base", - "blend_mode": "overlay" + "icon_state": "pressure0", + "blend_mode": "overlay", + "color_ids": [ 1 ] }, { "type": "icon_state", @@ -32,14 +32,14 @@ "meter1_1": [ { "type": "icon_state", - "icon_state": "pressure1_1", - "blend_mode": "overlay", - "color_ids": [ 1 ] + "icon_state": "meter_base", + "blend_mode": "overlay" }, { "type": "icon_state", - "icon_state": "meter_base", - "blend_mode": "overlay" + "icon_state": "pressure1_1", + "blend_mode": "overlay", + "color_ids": [ 1 ] }, { "type": "icon_state", @@ -50,14 +50,14 @@ "meter1_2": [ { "type": "icon_state", - "icon_state": "pressure1_2", - "blend_mode": "overlay", - "color_ids": [ 1 ] + "icon_state": "meter_base", + "blend_mode": "overlay" }, { "type": "icon_state", - "icon_state": "meter_base", - "blend_mode": "overlay" + "icon_state": "pressure1_2", + "blend_mode": "overlay", + "color_ids": [ 1 ] }, { "type": "icon_state", @@ -68,14 +68,14 @@ "meter1_3": [ { "type": "icon_state", - "icon_state": "pressure1_3", - "blend_mode": "overlay", - "color_ids": [ 1 ] + "icon_state": "meter_base", + "blend_mode": "overlay" }, { "type": "icon_state", - "icon_state": "meter_base", - "blend_mode": "overlay" + "icon_state": "pressure1_3", + "blend_mode": "overlay", + "color_ids": [ 1 ] }, { "type": "icon_state", @@ -86,14 +86,14 @@ "meter1_4": [ { "type": "icon_state", - "icon_state": "pressure1_4", - "blend_mode": "overlay", - "color_ids": [ 1 ] + "icon_state": "meter_base", + "blend_mode": "overlay" }, { "type": "icon_state", - "icon_state": "meter_base", - "blend_mode": "overlay" + "icon_state": "pressure1_4", + "blend_mode": "overlay", + "color_ids": [ 1 ] }, { "type": "icon_state", @@ -104,14 +104,14 @@ "meter1_5": [ { "type": "icon_state", - "icon_state": "pressure1_5", - "blend_mode": "overlay", - "color_ids": [ 1 ] + "icon_state": "meter_base", + "blend_mode": "overlay" }, { "type": "icon_state", - "icon_state": "meter_base", - "blend_mode": "overlay" + "icon_state": "pressure1_5", + "blend_mode": "overlay", + "color_ids": [ 1 ] }, { "type": "icon_state", @@ -122,14 +122,14 @@ "meter1_6": [ { "type": "icon_state", - "icon_state": "pressure1_6", - "blend_mode": "overlay", - "color_ids": [ 1 ] + "icon_state": "meter_base", + "blend_mode": "overlay" }, { "type": "icon_state", - "icon_state": "meter_base", - "blend_mode": "overlay" + "icon_state": "pressure1_6", + "blend_mode": "overlay", + "color_ids": [ 1 ] }, { "type": "icon_state", @@ -140,14 +140,14 @@ "meter2_1": [ { "type": "icon_state", - "icon_state": "pressure2_1", - "blend_mode": "overlay", - "color_ids": [ 1 ] + "icon_state": "meter_base", + "blend_mode": "overlay" }, { "type": "icon_state", - "icon_state": "meter_base", - "blend_mode": "overlay" + "icon_state": "pressure2_1", + "blend_mode": "overlay", + "color_ids": [ 1 ] }, { "type": "icon_state", @@ -158,14 +158,14 @@ "meter2_2": [ { "type": "icon_state", - "icon_state": "pressure2_2", - "blend_mode": "overlay", - "color_ids": [ 1 ] + "icon_state": "meter_base", + "blend_mode": "overlay" }, { "type": "icon_state", - "icon_state": "meter_base", - "blend_mode": "overlay" + "icon_state": "pressure2_2", + "blend_mode": "overlay", + "color_ids": [ 1 ] }, { "type": "icon_state", @@ -176,14 +176,14 @@ "meter2_3": [ { "type": "icon_state", - "icon_state": "pressure2_3", - "blend_mode": "overlay", - "color_ids": [ 1 ] + "icon_state": "meter_base", + "blend_mode": "overlay" }, { "type": "icon_state", - "icon_state": "meter_base", - "blend_mode": "overlay" + "icon_state": "pressure2_3", + "blend_mode": "overlay", + "color_ids": [ 1 ] }, { "type": "icon_state", @@ -194,14 +194,14 @@ "meter2_4": [ { "type": "icon_state", - "icon_state": "pressure2_4", - "blend_mode": "overlay", - "color_ids": [ 1 ] + "icon_state": "meter_base", + "blend_mode": "overlay" }, { "type": "icon_state", - "icon_state": "meter_base", - "blend_mode": "overlay" + "icon_state": "pressure2_4", + "blend_mode": "overlay", + "color_ids": [ 1 ] }, { "type": "icon_state", @@ -212,14 +212,14 @@ "meter2_5": [ { "type": "icon_state", - "icon_state": "pressure2_5", - "blend_mode": "overlay", - "color_ids": [ 1 ] + "icon_state": "meter_base", + "blend_mode": "overlay" }, { "type": "icon_state", - "icon_state": "meter_base", - "blend_mode": "overlay" + "icon_state": "pressure2_5", + "blend_mode": "overlay", + "color_ids": [ 1 ] }, { "type": "icon_state", @@ -230,14 +230,14 @@ "meter2_6": [ { "type": "icon_state", - "icon_state": "pressure2_6", - "blend_mode": "overlay", - "color_ids": [ 1 ] + "icon_state": "meter_base", + "blend_mode": "overlay" }, { "type": "icon_state", - "icon_state": "meter_base", - "blend_mode": "overlay" + "icon_state": "pressure2_6", + "blend_mode": "overlay", + "color_ids": [ 1 ] }, { "type": "icon_state", @@ -248,14 +248,14 @@ "meter3_1": [ { "type": "icon_state", - "icon_state": "pressure3_1", - "blend_mode": "overlay", - "color_ids": [ 1 ] + "icon_state": "meter_base", + "blend_mode": "overlay" }, { "type": "icon_state", - "icon_state": "meter_base", - "blend_mode": "overlay" + "icon_state": "pressure3_1", + "blend_mode": "overlay", + "color_ids": [ 1 ] }, { "type": "icon_state", @@ -266,14 +266,14 @@ "meter3_2": [ { "type": "icon_state", - "icon_state": "pressure3_2", - "blend_mode": "overlay", - "color_ids": [ 1 ] + "icon_state": "meter_base", + "blend_mode": "overlay" }, { "type": "icon_state", - "icon_state": "meter_base", - "blend_mode": "overlay" + "icon_state": "pressure3_2", + "blend_mode": "overlay", + "color_ids": [ 1 ] }, { "type": "icon_state", @@ -284,14 +284,14 @@ "meter3_3": [ { "type": "icon_state", - "icon_state": "pressure3_3", - "blend_mode": "overlay", - "color_ids": [ 1 ] + "icon_state": "meter_base", + "blend_mode": "overlay" }, { "type": "icon_state", - "icon_state": "meter_base", - "blend_mode": "overlay" + "icon_state": "pressure3_3", + "blend_mode": "overlay", + "color_ids": [ 1 ] }, { "type": "icon_state", @@ -302,14 +302,14 @@ "meter3_4": [ { "type": "icon_state", - "icon_state": "pressure3_4", - "blend_mode": "overlay", - "color_ids": [ 1 ] + "icon_state": "meter_base", + "blend_mode": "overlay" }, { "type": "icon_state", - "icon_state": "meter_base", - "blend_mode": "overlay" + "icon_state": "pressure3_4", + "blend_mode": "overlay", + "color_ids": [ 1 ] }, { "type": "icon_state", @@ -320,14 +320,14 @@ "meter3_5": [ { "type": "icon_state", - "icon_state": "pressure3_5", - "blend_mode": "overlay", - "color_ids": [ 1 ] + "icon_state": "meter_base", + "blend_mode": "overlay" }, { "type": "icon_state", - "icon_state": "meter_base", - "blend_mode": "overlay" + "icon_state": "pressure3_5", + "blend_mode": "overlay", + "color_ids": [ 1 ] }, { "type": "icon_state", @@ -338,14 +338,14 @@ "meter3_6": [ { "type": "icon_state", - "icon_state": "pressure3_6", - "blend_mode": "overlay", - "color_ids": [ 1 ] + "icon_state": "meter_base", + "blend_mode": "overlay" }, { "type": "icon_state", - "icon_state": "meter_base", - "blend_mode": "overlay" + "icon_state": "pressure3_6", + "blend_mode": "overlay", + "color_ids": [ 1 ] }, { "type": "icon_state", @@ -356,14 +356,14 @@ "meter4": [ { "type": "icon_state", - "icon_state": "pressure4", - "blend_mode": "overlay", - "color_ids": [ 1 ] + "icon_state": "meter_base", + "blend_mode": "overlay" }, { "type": "icon_state", - "icon_state": "meter_base", - "blend_mode": "overlay" + "icon_state": "pressure4", + "blend_mode": "overlay", + "color_ids": [ 1 ] }, { "type": "icon_state", diff --git a/code/datums/pod_style.dm b/code/datums/pod_style.dm index d680175cbb1840..483f46209eda08 100644 --- a/code/datums/pod_style.dm +++ b/code/datums/pod_style.dm @@ -56,7 +56,7 @@ glow_color = "blue" id = "deathsquad" -/datum/pod_style/advanced +/datum/pod_style/cultist name = "bloody supply pod" ui_name = "Cultist" desc = "A Nanotrasen supply pod covered in scratch-marks, blood, and strange runes." diff --git a/code/datums/skills/fishing.dm b/code/datums/skills/fishing.dm index cfd14a4ce3ba6b..fac1855c98dbc9 100644 --- a/code/datums/skills/fishing.dm +++ b/code/datums/skills/fishing.dm @@ -6,7 +6,7 @@ name = "Fishing" title = "Angler" desc = "How empty and alone you are on this barren Earth." - modifiers = list(SKILL_VALUE_MODIFIER = list(1, 1, 0, -1, -2, -4, -6)) + modifiers = list(SKILL_VALUE_MODIFIER = list(1, 0, -1, -3, -5, -7, -10)) skill_item_path = /obj/item/clothing/head/soft/fishing_hat /datum/skill/fishing/New() diff --git a/code/datums/sprite_accessories.dm b/code/datums/sprite_accessories.dm index eccb2161c73bb9..a37926405f9c08 100644 --- a/code/datums/sprite_accessories.dm +++ b/code/datums/sprite_accessories.dm @@ -51,7 +51,7 @@ var/natural_spawn = TRUE /datum/sprite_accessory/blank - name = "None" + name = SPRITE_ACCESSORY_NONE icon_state = "None" ////////////////////// @@ -835,7 +835,7 @@ var/gradient_category = GRADIENT_APPLIES_TO_HAIR|GRADIENT_APPLIES_TO_FACIAL_HAIR /datum/sprite_accessory/gradient/none - name = "None" + name = SPRITE_ACCESSORY_NONE icon_state = "none" /datum/sprite_accessory/gradient/full @@ -1726,10 +1726,6 @@ /datum/sprite_accessory/lizard_markings icon = 'icons/mob/human/species/lizard/lizard_markings.dmi' -/datum/sprite_accessory/lizard_markings/none - name = "None" - icon_state = "none" - /datum/sprite_accessory/lizard_markings/dtiger name = "Dark Tiger Body" icon_state = "dtiger" @@ -1754,6 +1750,11 @@ icon = 'icons/mob/human/species/lizard/lizard_tails.dmi' spine_key = SPINE_KEY_LIZARD +/datum/sprite_accessory/tails/lizard/none + name = SPRITE_ACCESSORY_NONE + icon_state = "none" + natural_spawn = FALSE + /datum/sprite_accessory/tails/lizard/smooth name = "Smooth" icon_state = "smooth" @@ -1781,6 +1782,13 @@ icon_state = "default" color_src = HAIR_COLOR +/datum/sprite_accessory/tails/monkey + +/datum/sprite_accessory/tails/monkey/none + name = SPRITE_ACCESSORY_NONE + icon_state = "none" + natural_spawn = FALSE + /datum/sprite_accessory/tails/monkey/default name = "Monkey" icon = 'icons/mob/human/species/monkey/monkey_tail.dmi' @@ -1855,10 +1863,6 @@ icon = 'icons/mob/human/species/lizard/lizard_misc.dmi' em_block = TRUE -/datum/sprite_accessory/horns/none - name = "None" - icon_state = "none" - /datum/sprite_accessory/horns/simple name = "Simple" icon_state = "simple" @@ -1883,10 +1887,6 @@ icon = 'icons/mob/human/cat_features.dmi' em_block = TRUE -/datum/sprite_accessory/ears/none - name = "None" - icon_state = "none" - /datum/sprite_accessory/ears/cat name = "Cat" icon_state = "cat" @@ -1921,10 +1921,6 @@ color_src = HAIR_COLOR locked = TRUE -/datum/sprite_accessory/wings/none - name = "None" - icon_state = "none" - /datum/sprite_accessory/wings icon = 'icons/mob/human/species/wings.dmi' em_block = TRUE @@ -2068,10 +2064,6 @@ /datum/sprite_accessory/frills icon = 'icons/mob/human/species/lizard/lizard_misc.dmi' -/datum/sprite_accessory/frills/none - name = "None" - icon_state = "none" - /datum/sprite_accessory/frills/simple name = "Simple" icon_state = "simple" @@ -2092,14 +2084,6 @@ icon = 'icons/mob/human/species/lizard/lizard_spines.dmi' em_block = TRUE -/datum/sprite_accessory/spines/none - name = "None" - icon_state = "none" - -/datum/sprite_accessory/tail_spines/none - name = "None" - icon_state = "none" - /datum/sprite_accessory/spines/short name = "Short" icon_state = "short" @@ -2360,10 +2344,6 @@ icon = 'icons/mob/human/species/moth/moth_markings.dmi' color_src = null -/datum/sprite_accessory/moth_markings/none - name = "None" - icon_state = "none" - /datum/sprite_accessory/moth_markings/reddish name = "Reddish" icon_state = "reddish" diff --git a/code/datums/station_traits/positive_traits.dm b/code/datums/station_traits/positive_traits.dm index 1af74533775fad..945fbe06934bc6 100644 --- a/code/datums/station_traits/positive_traits.dm +++ b/code/datums/station_traits/positive_traits.dm @@ -20,15 +20,23 @@ COOLDOWN_START(src, party_cooldown, rand(PARTY_COOLDOWN_LENGTH_MIN, PARTY_COOLDOWN_LENGTH_MAX)) - var/area/area_to_spawn_in = pick(GLOB.bar_areas) - var/turf/T = pick(area_to_spawn_in.contents) - - var/obj/structure/closet/supplypod/centcompod/toLaunch = new() - var/obj/item/pizzabox/pizza_to_spawn = pick(list(/obj/item/pizzabox/margherita, /obj/item/pizzabox/mushroom, /obj/item/pizzabox/meat, /obj/item/pizzabox/vegetable, /obj/item/pizzabox/pineapple)) - new pizza_to_spawn(toLaunch) - for(var/i in 1 to 6) - new /obj/item/reagent_containers/cup/glass/bottle/beer(toLaunch) - new /obj/effect/pod_landingzone(T, toLaunch) + var/pizza_type_to_spawn = pick(list( + /obj/item/pizzabox/margherita, + /obj/item/pizzabox/mushroom, + /obj/item/pizzabox/meat, + /obj/item/pizzabox/vegetable, + /obj/item/pizzabox/pineapple + )) + + var/area/bar_area = pick(GLOB.bar_areas) + podspawn(list( + "target" = pick(bar_area.contents), + "path" = /obj/structure/closet/supplypod/centcompod, + "spawn" = list( + pizza_type_to_spawn, + /obj/item/reagent_containers/cup/glass/bottle/beer = 6 + ) + )) #undef PARTY_COOLDOWN_LENGTH_MIN #undef PARTY_COOLDOWN_LENGTH_MAX diff --git a/code/datums/storage/storage.dm b/code/datums/storage/storage.dm index a01bb21a451e40..7cdb9d406152bf 100644 --- a/code/datums/storage/storage.dm +++ b/code/datums/storage/storage.dm @@ -449,11 +449,38 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) SEND_SIGNAL(parent, COMSIG_ATOM_STORED_ITEM, to_insert, user, force) SEND_SIGNAL(src, COMSIG_STORAGE_STORED_ITEM, to_insert, user, force) + RegisterSignal(to_insert, COMSIG_MOUSEDROPPED_ONTO, PROC_REF(mousedrop_receive)) to_insert.forceMove(real_location) item_insertion_feedback(user, to_insert, override) parent.update_appearance() return TRUE +/// Since items inside storages ignore transparency for QOL reasons, we're tracking when things are dropped onto them instead of our UI elements +/datum/storage/proc/mousedrop_receive(atom/dropped_onto, atom/movable/target, mob/user, params) + SIGNAL_HANDLER + + if (src != user.active_storage) + return + + if (!user.can_perform_action(parent, FORBID_TELEKINESIS_REACH)) + return + + if (target.loc != real_location) // what even + UnregisterSignal(target, COMSIG_MOUSEDROPPED_ONTO) + return + + if(numerical_stacking) + return + + var/drop_index = real_location.contents.Find(dropped_onto) + real_location.contents -= target + // Use an empty list if we're dropping onto the last item + var/list/to_move = real_location.contents.len >= drop_index ? real_location.contents.Copy(drop_index) : list() + real_location.contents -= to_move + real_location.contents += target + real_location.contents += to_move + refresh_views() + /** * Inserts every item in a given list, with a progress bar * @@ -544,6 +571,7 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) refresh_views() parent.update_appearance() + UnregisterSignal(thing, COMSIG_MOUSEDROPPED_ONTO) SEND_SIGNAL(parent, COMSIG_ATOM_REMOVED_ITEM, thing, remove_to_loc, silent) SEND_SIGNAL(src, COMSIG_STORAGE_REMOVED_ITEM, thing, remove_to_loc, silent) return TRUE @@ -719,7 +747,7 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) parent.add_fingerprint(user) return COMPONENT_CANCEL_MOUSEDROP_ONTO - else if(ismob(over_object)) + if(ismob(over_object)) if(over_object != user || !user.can_perform_action(parent, FORBID_TELEKINESIS_REACH | ALLOW_RESTING)) return @@ -727,13 +755,24 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) INVOKE_ASYNC(src, PROC_REF(open_storage), user) return COMPONENT_CANCEL_MOUSEDROP_ONTO - else if(!istype(over_object, /atom/movable/screen)) - if(!user.can_perform_action(over_object, FORBID_TELEKINESIS_REACH)) - return + if(istype(over_object, /atom/movable/screen)) + return - parent.add_fingerprint(user) - INVOKE_ASYNC(src, PROC_REF(dump_content_at), over_object, user) - return COMPONENT_CANCEL_MOUSEDROP_ONTO + if(!user.can_perform_action(over_object, FORBID_TELEKINESIS_REACH)) + return + + parent.add_fingerprint(user) + + var/atom/dump_loc = over_object.get_dumping_location() + if(isnull(dump_loc)) + return + + /// Don't dump *onto* objects in the same storage as ourselves + if (over_object.loc == parent.loc && !isnull(parent.loc.atom_storage) && isnull(over_object.atom_storage)) + return + + INVOKE_ASYNC(src, PROC_REF(dump_content_at), over_object, dump_loc, user) + return COMPONENT_CANCEL_MOUSEDROP_ONTO /** * Dumps all of our contents at a specific location. @@ -741,7 +780,7 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) * @param atom/dest_object where to dump to * @param mob/user the user who is dumping the contents */ -/datum/storage/proc/dump_content_at(atom/dest_object, mob/user) +/datum/storage/proc/dump_content_at(atom/dest_object, dump_loc, mob/user) if(locked) user.balloon_alert(user, "closed!") return @@ -764,10 +803,6 @@ GLOBAL_LIST_EMPTY(cached_storage_typecaches) SEND_SIGNAL(src, COMSIG_STORAGE_DUMP_POST_TRANSFER, dest_object, user) return - var/atom/dump_loc = dest_object.get_dumping_location() - if(isnull(dump_loc)) - return - // Storage to loc transfer requires a do_after to_chat(user, span_notice("You start dumping out the contents of [parent] onto [dest_object]...")) if(!do_after(user, 2 SECONDS, target = dest_object)) diff --git a/code/datums/storage/storage_interface.dm b/code/datums/storage/storage_interface.dm index cd28b9eb3f7a19..c0cab0dd7952ca 100644 --- a/code/datums/storage/storage_interface.dm +++ b/code/datums/storage/storage_interface.dm @@ -2,7 +2,7 @@ /datum/storage_interface /// UI elements for this theme var/atom/movable/screen/close/closer - var/atom/movable/screen/storage/cells + var/atom/movable/screen/storage/cell/cells var/atom/movable/screen/storage/corner/corner_top_left var/atom/movable/screen/storage/corner/top_right/corner_top_right var/atom/movable/screen/storage/corner/bottom_left/corner_bottom_left diff --git a/code/datums/storage/subtypes/bag_of_holding.dm b/code/datums/storage/subtypes/bag_of_holding.dm index aa812f5d1e0072..4028d4f789c6bf 100644 --- a/code/datums/storage/subtypes/bag_of_holding.dm +++ b/code/datums/storage/subtypes/bag_of_holding.dm @@ -16,6 +16,7 @@ return ..() /datum/storage/bag_of_holding/proc/recursive_insertion(obj/item/to_insert, mob/living/user) + var/area/bag_area = get_area(user) var/safety = tgui_alert(user, "Doing this will have extremely dire consequences for the station and its crew. Be sure you know what you're doing.", "Put in [to_insert.name]?", list("Proceed", "Abort")) if(safety != "Proceed" \ || QDELETED(to_insert) \ @@ -24,6 +25,7 @@ || QDELETED(user) \ || !user.can_perform_action(parent, NEED_DEXTERITY) \ || !can_insert(to_insert, user) \ + || (bag_area.area_flags & NO_BOH) \ ) return diff --git a/code/game/atom/_atom.dm b/code/game/atom/_atom.dm index 8b29ba9e048e77..c025428a17b6e4 100644 --- a/code/game/atom/_atom.dm +++ b/code/game/atom/_atom.dm @@ -186,6 +186,13 @@ if(smoothing_flags & SMOOTH_QUEUED) SSicon_smooth.remove_from_queues(src) + // These lists cease existing when src does, so we need to clear any lua refs to them that exist. + if(!(datum_flags & DF_STATIC_OBJECT)) + DREAMLUAU_CLEAR_REF_USERDATA(contents) + DREAMLUAU_CLEAR_REF_USERDATA(filters) + DREAMLUAU_CLEAR_REF_USERDATA(overlays) + DREAMLUAU_CLEAR_REF_USERDATA(underlays) + return ..() /atom/proc/handle_ricochet(obj/projectile/ricocheting_projectile) @@ -940,13 +947,18 @@ //We inline a MAPTEXT() here, because there's no good way to statically add to a string like this new_maptext = "[name][extra_context]" - INVOKE_ASYNC(src, PROC_REF(set_hover_maptext), client, active_hud, new_maptext) + if (length(name) * 10 > active_hud.screentip_text.maptext_width) + INVOKE_ASYNC(src, PROC_REF(set_hover_maptext), client, active_hud, new_maptext) + return + + active_hud.screentip_text.maptext = new_maptext + active_hud.screentip_text.maptext_y = 10 - (extra_lines > 0 ? 11 + 9 * (extra_lines - 1): 0) /atom/proc/set_hover_maptext(client/client, datum/hud/active_hud, new_maptext) var/map_height WXH_TO_HEIGHT(client.MeasureText(new_maptext, null, active_hud.screentip_text.maptext_width), map_height) active_hud.screentip_text.maptext = new_maptext - active_hud.screentip_text.maptext_y = 22 - map_height + active_hud.screentip_text.maptext_y = 26 - map_height /** * This proc is used for telling whether something can pass by this atom in a given direction, for use by the pathfinding system. diff --git a/code/game/atoms_movable.dm b/code/game/atoms_movable.dm index ae987cb668f155..046478c9b366a5 100644 --- a/code/game/atoms_movable.dm +++ b/code/game/atoms_movable.dm @@ -231,6 +231,10 @@ LAZYNULL(client_mobs_in_contents) + // These lists cease existing when src does, so we need to clear any lua refs to them that exist. + DREAMLUAU_CLEAR_REF_USERDATA(vis_contents) + DREAMLUAU_CLEAR_REF_USERDATA(vis_locs) + . = ..() for(var/movable_content in contents) diff --git a/code/game/machinery/_machinery.dm b/code/game/machinery/_machinery.dm index 423a2a16b55c3b..45a75f06133dd6 100644 --- a/code/game/machinery/_machinery.dm +++ b/code/game/machinery/_machinery.dm @@ -286,6 +286,7 @@ ///Early process for machines added to SSmachines.processing_early to prioritize power draw /obj/machinery/proc/process_early() + set waitfor = FALSE return PROCESS_KILL /obj/machinery/process()//If you dont use process or power why are you here @@ -293,9 +294,11 @@ ///Late process for machines added to SSmachines.processing_late to gather accurate recordings /obj/machinery/proc/process_late() + set waitfor = FALSE return PROCESS_KILL /obj/machinery/proc/process_atmos()//If you dont use process why are you here + set waitfor = FALSE return PROCESS_KILL ///Called when we want to change the value of the machine_stat variable. Holds bitflags. diff --git a/code/game/machinery/computer/operating_computer.dm b/code/game/machinery/computer/operating_computer.dm index d67cea367e9a6b..43a18c7081f30c 100644 --- a/code/game/machinery/computer/operating_computer.dm +++ b/code/game/machinery/computer/operating_computer.dm @@ -143,11 +143,13 @@ var/chems_needed = surgery_step.get_chem_list() var/alternative_step var/alt_chems_needed = "" + var/alt_chems_present = FALSE if(surgery_step.repeatable) var/datum/surgery_step/next_step = procedure.get_surgery_next_step() if(next_step) alternative_step = capitalize(next_step.name) alt_chems_needed = next_step.get_chem_list() + alt_chems_present = next_step.chem_check(patient) else alternative_step = "Finish operation" data["procedures"] += list(list( @@ -155,7 +157,9 @@ "next_step" = capitalize(surgery_step.name), "chems_needed" = chems_needed, "alternative_step" = alternative_step, - "alt_chems_needed" = alt_chems_needed + "alt_chems_needed" = alt_chems_needed, + "chems_present" = surgery_step.chem_check(patient), + "alt_chems_present" = alt_chems_present )) return data diff --git a/code/game/machinery/computer/telescreen.dm b/code/game/machinery/computer/telescreen.dm index c421ca0c90308f..deca4ec8245e17 100644 --- a/code/game/machinery/computer/telescreen.dm +++ b/code/game/machinery/computer/telescreen.dm @@ -185,11 +185,23 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/ce, 32) frame_type = /obj/item/wallframe/telescreen/cmo /obj/item/wallframe/telescreen/cmo - name = "\improper Chief Engineer'stelescreen frame" + name = "\improper Chief Medical Officer's telescreen frame" result_path = /obj/machinery/computer/security/telescreen/cmo MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/cmo, 32) +/obj/machinery/computer/security/telescreen/med_sec + name = "\improper medical telescreen" + desc = "A telescreen with access to the medbay's camera network." + network = list(CAMERANET_NETWORK_MEDBAY) + frame_type = /obj/item/wallframe/telescreen/med_sec + +/obj/item/wallframe/telescreen/med_sec + name = "\improper medical telescreen frame" + result_path = /obj/machinery/computer/security/telescreen/med_sec + +MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/computer/security/telescreen/med_sec, 32) + /obj/machinery/computer/security/telescreen/vault name = "vault monitor" desc = "A telescreen that connects to the vault's camera network." diff --git a/code/game/machinery/doors/airlock.dm b/code/game/machinery/doors/airlock.dm index dcb8622f1db3b5..7188ba7c8353a9 100644 --- a/code/game/machinery/doors/airlock.dm +++ b/code/game/machinery/doors/airlock.dm @@ -1462,9 +1462,9 @@ return if(!density) //Already open return ..() + if(user.combat_mode) + return ..() if(locked || welded || seal) //Extremely generic, as aliens only understand the basics of how airlocks work. - if(user.combat_mode) - return ..() to_chat(user, span_warning("[src] refuses to budge!")) return add_fingerprint(user) diff --git a/code/game/machinery/doors/firedoor.dm b/code/game/machinery/doors/firedoor.dm index dd274b30531697..84df989ba0ea38 100644 --- a/code/game/machinery/doors/firedoor.dm +++ b/code/game/machinery/doors/firedoor.dm @@ -431,6 +431,10 @@ ignore_alarms = FALSE if(!alarm_type || active) // If we have no alarm type, or are already active, go away return + // Do we even care about temperature? + for(var/area/place in affecting_areas) + if(!place.fire_detect) // If any area is set to disable detection + return // Otherwise, reactivate ourselves start_activation_process(alarm_type) diff --git a/code/game/machinery/firealarm.dm b/code/game/machinery/firealarm.dm index a852ea019c697b..3fc4dcf219adb8 100644 --- a/code/game/machinery/firealarm.dm +++ b/code/game/machinery/firealarm.dm @@ -477,6 +477,9 @@ my_area.fire_detect = !my_area.fire_detect for(var/obj/machinery/firealarm/fire_panel in my_area.firealarms) fire_panel.update_icon() + // Used to force all the firelocks to update, if the zone is not manually activated + if (my_area.fault_status != AREA_FAULT_MANUAL) + reset() // Don't send user to prevent double balloon_alert() and the action is already logged in this proc. if (user) balloon_alert(user, "thermal sensors [my_area.fire_detect ? "enabled" : "disabled"]") user.log_message("[ my_area.fire_detect ? "enabled" : "disabled" ] firelock sensors using [src].", LOG_GAME) diff --git a/code/game/machinery/igniter.dm b/code/game/machinery/igniter.dm index 3fa7d25767f2f7..887c04ebedee0f 100644 --- a/code/game/machinery/igniter.dm +++ b/code/game/machinery/igniter.dm @@ -137,6 +137,7 @@ icon = 'icons/obj/wallmounts.dmi' icon_state = "migniter" result_path = /obj/machinery/sparker + custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT) pixel_shift = 26 /obj/machinery/sparker diff --git a/code/game/machinery/lightswitch.dm b/code/game/machinery/lightswitch.dm index 04883800f31eff..c8d0249fca02dc 100644 --- a/code/game/machinery/lightswitch.dm +++ b/code/game/machinery/lightswitch.dm @@ -119,6 +119,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/light_switch, 26) icon = 'icons/obj/machines/wallmounts.dmi' icon_state = "light-nopower" result_path = /obj/machinery/light_switch + custom_materials = list(/datum/material/iron = SHEET_MATERIAL_AMOUNT) pixel_shift = 26 /obj/item/circuit_component/light_switch diff --git a/code/game/machinery/pipe/construction.dm b/code/game/machinery/pipe/construction.dm index 80289a201be986..ef18dc6b068aef 100644 --- a/code/game/machinery/pipe/construction.dm +++ b/code/game/machinery/pipe/construction.dm @@ -36,9 +36,11 @@ Buildable meters icon_state_preview = "junction" pipe_type = /obj/machinery/atmospherics/pipe/heat_exchanging/junction /obj/item/pipe/directional/vent + name = "air vent fitting" icon_state_preview = "uvent" pipe_type = /obj/machinery/atmospherics/components/unary/vent_pump /obj/item/pipe/directional/scrubber + name = "air scrubber fitting" icon_state_preview = "scrubber" pipe_type = /obj/machinery/atmospherics/components/unary/vent_scrubber /obj/item/pipe/directional/connector @@ -78,6 +80,7 @@ Buildable meters RPD_type = PIPE_TRIN_M var/flipped = FALSE /obj/item/pipe/trinary/flippable/filter + name = "gas filter fitting" icon_state_preview = "filter" pipe_type = /obj/machinery/atmospherics/components/trinary/filter /obj/item/pipe/trinary/flippable/mixer diff --git a/code/game/machinery/recycler.dm b/code/game/machinery/recycler.dm index ce1b82a83b4083..8ce9265917d638 100644 --- a/code/game/machinery/recycler.dm +++ b/code/game/machinery/recycler.dm @@ -133,33 +133,55 @@ qdel(morsel) return - var/list/to_eat = (issilicon(morsel) ? list(morsel) : morsel.get_all_contents()) //eating borg contents leads to many bad things + var/list/atom/to_eat = list(morsel) var/living_detected = FALSE //technically includes silicons as well but eh var/list/nom = list() var/list/crunchy_nom = list() //Mobs have to be handled differently so they get a different list instead of checking them multiple times. + var/not_eaten = 0 - for(var/thing in to_eat) - var/obj/as_object = thing - if(istype(as_object)) - if(as_object.resistance_flags & INDESTRUCTIBLE) - if(!isturf(as_object.loc) && !isliving(as_object.loc)) - as_object.forceMove(loc) // so you still cant shove it in a locker - continue - var/obj/item/bodypart/head/as_head = thing - var/obj/item/mmi/as_mmi = thing - if(istype(thing, /obj/item/organ/internal/brain) || (istype(as_head) && locate(/obj/item/organ/internal/brain) in as_head) || (istype(as_mmi) && as_mmi.brain) || istype(thing, /obj/item/dullahan_relay)) - living_detected = TRUE - if(isitem(as_object)) - var/obj/item/as_item = as_object - if(as_item.item_flags & ABSTRACT) //also catches organs and bodyparts *stares* - continue - nom += thing - else if(isliving(thing)) + while (to_eat.len) + var/atom/movable/thing = to_eat[1] + to_eat -= thing + + if (thing.flags_1 & HOLOGRAM_1) + qdel(thing) + continue + + if (thing.resistance_flags & INDESTRUCTIBLE) + if (!isturf(thing.loc) && !isliving(thing.loc)) + thing.forceMove(loc) + not_eaten += 1 + continue + + if (isliving(thing)) living_detected = TRUE crunchy_nom += thing + if (!issilicon(thing)) + to_eat |= thing.contents + continue + + if (!isobj(thing)) + not_eaten += 1 + continue + + if (isitem(thing)) + var/obj/item/as_item = thing + if (as_item.item_flags & ABSTRACT) + not_eaten += 1 + continue + + if (istype(thing, /obj/item/organ/internal/brain) || istype(thing, /obj/item/dullahan_relay)) + living_detected = TRUE + + if (istype(thing, /obj/item/mmi)) + var/obj/item/mmi/mmi = thing + if (!isnull(mmi.brain)) + living_detected = TRUE + + nom += thing + to_eat |= thing.contents - var/not_eaten = to_eat.len - nom.len - crunchy_nom.len if(living_detected) // First, check if we have any living beings detected. if(obj_flags & EMAGGED) for(var/CRUNCH in crunchy_nom) // Eat them and keep going because we don't care about safety. diff --git a/code/game/machinery/roulette_machine.dm b/code/game/machinery/roulette_machine.dm index fc443c247f1d8e..2a8dc8bb49b22a 100644 --- a/code/game/machinery/roulette_machine.dm +++ b/code/game/machinery/roulette_machine.dm @@ -451,11 +451,12 @@ addtimer(CALLBACK(src, PROC_REF(launch_payload)), 4 SECONDS) /obj/item/roulette_wheel_beacon/proc/launch_payload() - var/obj/structure/closet/supplypod/centcompod/toLaunch = new() - - new /obj/machinery/roulette(toLaunch) - - new /obj/effect/pod_landingzone(drop_location(), toLaunch) + podspawn(list( + "target" = drop_location(), + "path" = /obj/structure/closet/supplypod/centcompod, + "spawn" = /obj/machinery/roulette + )) + qdel(src) #undef ROULETTE_DOZ_COL_PAYOUT diff --git a/code/game/machinery/scanner_gate.dm b/code/game/machinery/scanner_gate.dm index 2024e35f91fa3b..fd99f3ccfb8a3e 100644 --- a/code/game/machinery/scanner_gate.dm +++ b/code/game/machinery/scanner_gate.dm @@ -96,13 +96,13 @@ return CONTEXTUAL_SCREENTIP_SET -/obj/machinery/scanner_gate/proc/on_entered(datum/source, atom/movable/AM) +/obj/machinery/scanner_gate/proc/on_entered(datum/source, atom/movable/thing) SIGNAL_HANDLER - INVOKE_ASYNC(src, PROC_REF(auto_scan), AM) + INVOKE_ASYNC(src, PROC_REF(auto_scan), thing) -/obj/machinery/scanner_gate/proc/auto_scan(atom/movable/AM) - if(!(machine_stat & (BROKEN|NOPOWER)) && isliving(AM) & (!panel_open)) - perform_scan(AM) +/obj/machinery/scanner_gate/proc/auto_scan(atom/movable/thing) + if(!(machine_stat & (BROKEN|NOPOWER)) && anchored && !panel_open) + perform_scan(thing) /obj/machinery/scanner_gate/proc/set_scanline(type, duration) cut_overlays() @@ -124,8 +124,8 @@ return ITEM_INTERACT_SUCCESS return NONE -/obj/machinery/scanner_gate/attackby(obj/item/W, mob/user, params) - var/obj/item/card/id/card = W.GetID() +/obj/machinery/scanner_gate/attackby(obj/item/attacking_item, mob/user, params) + var/obj/item/card/id/card = attacking_item.GetID() if(card) if(locked) if(allowed(user)) @@ -133,16 +133,16 @@ req_access = list() to_chat(user, span_notice("You unlock [src].")) else if(!(obj_flags & EMAGGED)) - to_chat(user, span_notice("You lock [src] with [W].")) - var/list/access = W.GetAccess() + to_chat(user, span_notice("You lock [src] with [attacking_item].")) + var/list/access = attacking_item.GetAccess() req_access = access locked = TRUE else - to_chat(user, span_warning("You try to lock [src] with [W], but nothing happens.")) + to_chat(user, span_warning("You try to lock [src] with [attacking_item], but nothing happens.")) else - if(!locked && default_deconstruction_screwdriver(user, "[initial(icon_state)]_open", initial(icon_state), W)) + if(!locked && default_deconstruction_screwdriver(user, "[initial(icon_state)]_open", initial(icon_state), attacking_item)) return - if(panel_open && is_wire_tool(W)) + if(panel_open && is_wire_tool(attacking_item)) wires.interact(user) return ..() @@ -173,7 +173,7 @@ balloon_alert(user, "id checker disabled") return TRUE -/obj/machinery/scanner_gate/proc/perform_scan(mob/living/M) +/obj/machinery/scanner_gate/proc/perform_scan(atom/movable/thing) var/beep = FALSE var/color = null var/detected_thing = null @@ -181,26 +181,28 @@ if(SCANGATE_NONE) return if(SCANGATE_WANTED) - if(ishuman(M)) + if(ishuman(thing)) detected_thing = "Warrant" - var/mob/living/carbon/human/H = M - var/perpname = H.get_face_name(H.get_id_name()) + var/mob/living/carbon/human/scanned_human = thing + var/perpname = scanned_human.get_face_name(scanned_human.get_id_name()) var/datum/record/crew/target = find_record(perpname) if(!target || (target.wanted_status == WANTED_ARREST)) beep = TRUE if(SCANGATE_MINDSHIELD) detected_thing = "Mindshield" - if(HAS_TRAIT(M, TRAIT_MINDSHIELD)) - beep = TRUE + if(ishuman(thing)) + var/mob/living/carbon/human/scanned_human = thing + if(HAS_TRAIT(scanned_human, TRAIT_MINDSHIELD)) + beep = TRUE if(SCANGATE_DISEASE) detected_thing = "[disease_threshold] infection" - if(iscarbon(M)) - var/mob/living/carbon/C = M - if(get_disease_severity_value(C.check_virus()) >= get_disease_severity_value(disease_threshold)) + if(iscarbon(thing)) + var/mob/living/carbon/scanned_carbon = thing + if(get_disease_severity_value(scanned_carbon.check_virus()) >= get_disease_severity_value(disease_threshold)) beep = TRUE if(SCANGATE_SPECIES) - if(ishuman(M)) - var/mob/living/carbon/human/H = M + if(ishuman(thing)) + var/mob/living/carbon/human/scanned_human = thing var/datum/species/scan_species = /datum/species/human switch(detect_species) if(SCANGATE_LIZARD) @@ -230,29 +232,42 @@ if(SCANGATE_ZOMBIE) detected_thing = "Zombie" scan_species = /datum/species/zombie - if(is_species(H, scan_species)) + if(is_species(scanned_human, scan_species)) beep = TRUE if(detect_species == SCANGATE_ZOMBIE) //Can detect dormant zombies detected_thing = "Romerol infection" - if(H.get_organ_slot(ORGAN_SLOT_ZOMBIE)) + if(scanned_human.get_organ_slot(ORGAN_SLOT_ZOMBIE)) beep = TRUE if(SCANGATE_GUNS) - for(var/I in M.get_contents()) - detected_thing = "Weapons" - if(isgun(I)) - beep = TRUE - break + detected_thing = "Weapons" + if(isgun(thing)) + beep = TRUE + else if(ishuman(thing)) + var/mob/living/carbon/human/scanned_human = thing + var/obj/item/card/id/idcard = scanned_human.get_idcard(hand_first = FALSE) + for(var/obj/item/scanned_item in scanned_human.get_all_contents_skipping_traits(TRAIT_CONTRABAND_BLOCKER)) + if(isgun(scanned_item)) + if((!HAS_TRAIT(scanned_human, TRAIT_MINDSHIELD)) && (isnull(idcard) || !(ACCESS_WEAPONS in idcard.access))) // mindshield or ID card with weapons access, like bartender + beep = TRUE + break + say("[detected_thing] detection bypassed.") + break + else + for(var/obj/item/content in thing.get_all_contents_skipping_traits(TRAIT_CONTRABAND_BLOCKER)) + if(isgun(content)) + beep = TRUE + break if(SCANGATE_NUTRITION) - if(ishuman(M)) - var/mob/living/carbon/human/H = M - if(H.nutrition <= detect_nutrition && detect_nutrition == NUTRITION_LEVEL_STARVING) + if(ishuman(thing)) + var/mob/living/carbon/human/scanned_human = thing + if(scanned_human.nutrition <= detect_nutrition && detect_nutrition == NUTRITION_LEVEL_STARVING) beep = TRUE detected_thing = "Starvation" - if(H.nutrition >= detect_nutrition && detect_nutrition == NUTRITION_LEVEL_FAT) + if(scanned_human.nutrition >= detect_nutrition && detect_nutrition == NUTRITION_LEVEL_FAT) beep = TRUE detected_thing = "Obesity" if(SCANGATE_CONTRABAND) - for(var/obj/item/content in M.get_all_contents_skipping_traits(TRAIT_CONTRABAND_BLOCKER)) + for(var/obj/item/content in thing.get_all_contents_skipping_traits(TRAIT_CONTRABAND_BLOCKER)) detected_thing = "Contraband" if(content.is_contraband()) beep = TRUE @@ -268,18 +283,18 @@ if(beep) alarm_beep(detected_thing) - SEND_SIGNAL(src, COMSIG_SCANGATE_PASS_TRIGGER, M) + SEND_SIGNAL(src, COMSIG_SCANGATE_PASS_TRIGGER, thing) if(!ignore_signals) color = wires.get_color_of_wire(WIRE_ACCEPT) var/obj/item/assembly/assembly = wires.get_attached(color) assembly?.activate() else - SEND_SIGNAL(src, COMSIG_SCANGATE_PASS_NO_TRIGGER, M) + SEND_SIGNAL(src, COMSIG_SCANGATE_PASS_NO_TRIGGER, thing) if(!ignore_signals) color = wires.get_color_of_wire(WIRE_DENY) var/obj/item/assembly/assembly = wires.get_attached(color) assembly?.activate() - set_scanline("scanning", 10) + set_scanline("scanning", 1 SECONDS) use_energy(active_power_usage) @@ -291,7 +306,7 @@ say("[detected_thing][reverse ? " not " : " "]detected!!") COOLDOWN_START(src, next_beep, 2 SECONDS) - playsound(src, 'sound/machines/scanbuzz.ogg', 100, FALSE) + playsound(source = src, soundin = 'sound/machines/scanbuzz.ogg', vol = 30, vary = FALSE, extrarange = MEDIUM_RANGE_SOUND_EXTRARANGE, falloff_distance = 4) set_scanline("alarm", 2 SECONDS) /obj/machinery/scanner_gate/can_interact(mob/user) diff --git a/code/game/machinery/telecomms/broadcasting.dm b/code/game/machinery/telecomms/broadcasting.dm index 5887c776675068..2c31dcbd989555 100644 --- a/code/game/machinery/telecomms/broadcasting.dm +++ b/code/game/machinery/telecomms/broadcasting.dm @@ -78,7 +78,7 @@ datum/language/language, // the language of the message message, // the text content of the message spans, // the list of spans applied to the message - list/message_mods // the list of modification applied to the message. Whispering, singing, ect + list/message_mods, // the list of modification applied to the message. Whispering, singing, ect ) src.source = source src.frequency = frequency @@ -92,7 +92,7 @@ "compression" = rand(COMPRESSION_VOCAL_SIGNAL_MIN, COMPRESSION_VOCAL_SIGNAL_MAX), "language" = lang_instance.name, "spans" = spans, - "mods" = message_mods + "mods" = message_mods, ) levels = SSmapping.get_connected_levels(get_turf(source)) diff --git a/code/game/objects/effects/anomalies/anomalies_dimensional_themes.dm b/code/game/objects/effects/anomalies/anomalies_dimensional_themes.dm index 6832b07d12568a..a9d2e0bcaa0c4c 100644 --- a/code/game/objects/effects/anomalies/anomalies_dimensional_themes.dm +++ b/code/game/objects/effects/anomalies/anomalies_dimensional_themes.dm @@ -449,3 +449,23 @@ /obj/structure/table = list(/obj/structure/table/greyscale = 9, /obj/structure/table/abductor = 1), /obj/structure/toilet = list(/obj/structure/toilet/greyscale = 1), ) + +/datum/dimension_theme/bronze + name = "Bronze" + icon = 'icons/obj/weapons/spear.dmi' + icon_state = "ratvarian_spear" + material = /datum/material/bronze + replace_walls = /turf/closed/wall/mineral/bronze + replace_floors = list(/turf/open/floor/bronze = 1, /turf/open/floor/bronze/flat = 1, /turf/open/floor/bronze/filled = 1) + replace_objs = list( + /obj/structure/girder = list(/obj/structure/girder/bronze = 1), + /obj/structure/window/fulltile = list(/obj/structure/window/bronze/fulltile = 1), + /obj/structure/window = list(/obj/structure/window/bronze = 1), + /obj/structure/statue = list(/obj/structure/statue/bronze/marx = 1), // karl marx was a servant of ratvar + /obj/structure/table = list(/obj/structure/table/bronze = 1), + /obj/structure/toilet = list(/obj/structure/toilet/greyscale = 1), + /obj/structure/chair = list(/obj/structure/chair/bronze = 1), + /obj/item/reagent_containers/cup/glass/trophy = list(/obj/item/reagent_containers/cup/glass/trophy/bronze_cup = 1), + /obj/machinery/door/airlock = list(/obj/machinery/door/airlock/bronze = 1), + ) + sound = 'sound/magic/clockwork/fellowship_armory.ogg' diff --git a/code/game/objects/effects/particles/fire.dm b/code/game/objects/effects/particles/fire.dm index 9d90d0d29c29a4..9904685807364b 100644 --- a/code/game/objects/effects/particles/fire.dm +++ b/code/game/objects/effects/particles/fire.dm @@ -33,3 +33,21 @@ drift = generator(GEN_VECTOR, list(-0.1,0), list(0.1,0.025), UNIFORM_RAND) spin = generator(GEN_NUM, list(-15,15), NORMAL_RAND) scale = generator(GEN_VECTOR, list(0.5,0.5), list(2,2), NORMAL_RAND) + +/particles/embers/spark + count = 3 + spawning = 2 + gradient = list("#FBAF4D", "#FCE6B6", "#FFFFFF") + lifespan = 1.5 SECONDS + fade = 1 SECONDS + fadein = 0.1 SECONDS + grow = -0.1 + velocity = generator(GEN_CIRCLE, 3, 3, SQUARE_RAND) + position = generator(GEN_SPHERE, 0, 0, LINEAR_RAND) + scale = generator(GEN_VECTOR, list(0.5, 0.5), list(1,1), NORMAL_RAND) + drift = list(0) + +/particles/embers/spark/severe + count = 10 + spawning = 5 + gradient = list("#FCE6B6", "#FFFFFF") diff --git a/code/game/objects/effects/particles/smoke.dm b/code/game/objects/effects/particles/smoke.dm index 27249c65a683e2..776c90534a957b 100644 --- a/code/game/objects/effects/particles/smoke.dm +++ b/code/game/objects/effects/particles/smoke.dm @@ -84,3 +84,16 @@ grow = 0.05 spin = 2 color = "#fcffff77" + +/particles/smoke/cyborg + count = 5 + spawning = 1 + lifespan = 1 SECONDS + fade = 1.8 SECONDS + position = list(0, 0, 0) + scale = list(0.5, 0.5) + grow = 0.1 + +/particles/smoke/cyborg/heavy_damage + lifespan = 0.8 SECONDS + fade = 0.8 SECONDS diff --git a/code/game/objects/items/clown_items.dm b/code/game/objects/items/clown_items.dm index 3d817d24ccf2b4..32a81d1f75f9cd 100644 --- a/code/game/objects/items/clown_items.dm +++ b/code/game/objects/items/clown_items.dm @@ -89,6 +89,13 @@ worn_icon_state = "soapsyndie" cleanspeed = 0.5 SECONDS //faster than mops so it's useful for traitors who want to clean crime scenes +/obj/item/soap/drone + name = "\improper integrated soap module" + inhand_icon_state = "soapnt" + worn_icon_state = "soapnt" + cleanspeed = 0.5 SECONDS //can be changed if someone isn't happy + uses = INFINITY + /obj/item/soap/omega name = "\improper Omega soap" desc = "The most advanced soap known to mankind. The beginning of the end for germs." diff --git a/code/game/objects/items/crayons.dm b/code/game/objects/items/crayons.dm index 9bc86d0c7f96b3..a879571e2b0aaa 100644 --- a/code/game/objects/items/crayons.dm +++ b/code/game/objects/items/crayons.dm @@ -189,7 +189,7 @@ ) /// List of selectable large options var/static/list/graffiti_large_h = list( - "furrypride" = CRAYON_COST_LARGE, + //"furrypride" = CRAYON_COST_LARGE, // BANDASTATION REMOVAL "paint" = CRAYON_COST_LARGE, "secborg" = CRAYON_COST_LARGE, "yiffhell" = CRAYON_COST_LARGE, @@ -860,7 +860,7 @@ if(carbon_target.client) carbon_target.set_eye_blur_if_lower(6 SECONDS) carbon_target.adjust_temp_blindness(2 SECONDS) - if(carbon_target.get_eye_protection() <= 0) // no eye protection? ARGH IT BURNS. Warning: don't add a stun here. It's a roundstart item with some quirks. + if(carbon_target.get_eye_protection() <= 0 || carbon_target.is_eyes_covered()) // no eye protection? ARGH IT BURNS. Warning: don't add a stun here. It's a roundstart item with some quirks. added redundancy because gas masks don't give you eye protection carbon_target.adjust_jitter(1 SECONDS) carbon_target.adjust_eye_blur(0.5 SECONDS) flash_color(carbon_target, flash_color=paint_color, flash_time=40) diff --git a/code/game/objects/items/defib.dm b/code/game/objects/items/defib.dm index eb3317d5909f0b..02934d1a03eaa6 100644 --- a/code/game/objects/items/defib.dm +++ b/code/game/objects/items/defib.dm @@ -147,7 +147,6 @@ if(!cell || !cell_removable) return FALSE - cell.update_appearance() cell.forceMove(get_turf(src)) balloon_alert(user, "removed [cell]") cell = null diff --git a/code/game/objects/items/devices/flashlight.dm b/code/game/objects/items/devices/flashlight.dm index e684c1b4959e57..968a2f11f4d4ce 100644 --- a/code/game/objects/items/devices/flashlight.dm +++ b/code/game/objects/items/devices/flashlight.dm @@ -959,14 +959,10 @@ var/dark_light_range = 2.5 ///Variable to preserve old lighting behavior in flashlights, to handle darkness. var/dark_light_power = -3 - var/on = FALSE /obj/item/flashlight/flashdark/update_brightness() . = ..() - if(on) - set_light(dark_light_range, dark_light_power) - else - set_light(0) + set_light(dark_light_range, dark_light_power) //type and subtypes spawned and used to give some eyes lights, /obj/item/flashlight/eyelight diff --git a/code/game/objects/items/devices/radio/headset.dm b/code/game/objects/items/devices/radio/headset.dm index 1f2cd37a5ccef4..edf24b0d942d44 100644 --- a/code/game/objects/items/devices/radio/headset.dm +++ b/code/game/objects/items/devices/radio/headset.dm @@ -299,7 +299,7 @@ GLOBAL_LIST_INIT(channel_tokens, list( /obj/item/radio/headset/headset_cargo/mining name = "mining radio headset" - desc = "Headset used by shaft miners." + desc = "Headset used by shaft miners. It has a mining network uplink which allows the user to quickly transmit commands to their comrades and amplifies their voice in low-pressure environments." icon_state = "mine_headset" worn_icon_state = "mine_headset" // "puts the antenna down" while the headset is off @@ -307,6 +307,19 @@ GLOBAL_LIST_INIT(channel_tokens, list( overlay_mic_idle = "headset_up" keyslot = /obj/item/encryptionkey/headset_mining +/obj/item/radio/headset/headset_cargo/mining/Initialize(mapload) + . = ..() + AddComponent(/datum/component/callouts, ITEM_SLOT_EARS, examine_text = span_info("Use ctrl-click to enable or disable callouts.")) + +/obj/item/radio/headset/headset_cargo/mining/equipped(mob/living/carbon/human/user, slot) + . = ..() + if(slot & ITEM_SLOT_EARS) + ADD_TRAIT(user, TRAIT_SPEECH_BOOSTER, CLOTHING_TRAIT) + +/obj/item/radio/headset/headset_cargo/mining/dropped(mob/living/carbon/human/user) + . = ..() + REMOVE_TRAIT(user, TRAIT_SPEECH_BOOSTER, CLOTHING_TRAIT) + /obj/item/radio/headset/headset_srv name = "service radio headset" desc = "Headset used by the service staff, tasked with keeping the station full, happy and clean." diff --git a/code/game/objects/items/devices/radio/radio.dm b/code/game/objects/items/devices/radio/radio.dm index d515929c197ccb..121f0bba965b32 100644 --- a/code/game/objects/items/devices/radio/radio.dm +++ b/code/game/objects/items/devices/radio/radio.dm @@ -351,6 +351,12 @@ signal.broadcast() return + + if(isliving(talking_movable)) + var/mob/living/talking_living = talking_movable + if(talking_living.client?.prefs.read_preference(/datum/preference/toggle/radio_noise)) + SEND_SOUND(talking_living, 'sound/misc/radio_talk.ogg') + // All radios make an attempt to use the subspace system first signal.send_to_receivers() @@ -422,6 +428,18 @@ SEND_SIGNAL(src, COMSIG_RADIO_RECEIVE_MESSAGE, data) flick_overlay_view(overlay_speaker_active, 5 SECONDS) + if(!isliving(loc)) + return + + var/mob/living/holder = loc + if(!holder.client?.prefs.read_preference(/datum/preference/toggle/radio_noise)) + return + + var/list/spans = data["spans"] + SEND_SOUND(holder, 'sound/misc/radio_receive.ogg') + if(SPAN_COMMAND in spans) + SEND_SOUND(holder, 'sound/misc/radio_important.ogg') + /obj/item/radio/ui_state(mob/user) return GLOB.inventory_state diff --git a/code/game/objects/items/food/bait.dm b/code/game/objects/items/food/bait.dm index 047a8a7cd58ce7..41b50c181f287a 100644 --- a/code/game/objects/items/food/bait.dm +++ b/code/game/objects/items/food/bait.dm @@ -66,3 +66,9 @@ /obj/item/food/bait/doughball/synthetic/Initialize(mapload) . = ..() ADD_TRAIT(src, TRAIT_OMNI_BAIT, INNATE_TRAIT) + +/obj/item/food/bait/doughball/syntethic/unconsumable + +/obj/item/food/bait/doughball/synthetic/unconsumable/Initialize(mapload) + . = ..() + ADD_TRAIT(src, TRAIT_BAIT_UNCONSUMABLE, INNATE_TRAIT) diff --git a/code/game/objects/items/food/misc.dm b/code/game/objects/items/food/misc.dm index 31ac87c0ff690b..26852066bae282 100644 --- a/code/game/objects/items/food/misc.dm +++ b/code/game/objects/items/food/misc.dm @@ -16,6 +16,87 @@ juice_typepath = /datum/reagent/consumable/watermelonjuice w_class = WEIGHT_CLASS_SMALL +/obj/item/food/watermelonmush + name = "watermelon mush" + desc = "A plop of watery goodness." + icon = 'icons/obj/service/hydroponics/harvest.dmi' + icon_state = "watermelonpulp" + food_reagents = list( + /datum/reagent/water = 2, + /datum/reagent/consumable/nutriment/vitamin = 0.1, + /datum/reagent/consumable/nutriment = 0.5, + ) + tastes = list("watermelon" = 1) + foodtypes = FRUIT + food_flags = FOOD_FINGER_FOOD + juice_typepath = /datum/reagent/consumable/watermelonjuice + w_class = WEIGHT_CLASS_SMALL + +/obj/item/food/holymelonslice + name = "holymelon slice" + desc = "A slice of holy goodness." + icon = 'icons/obj/service/hydroponics/harvest.dmi' + icon_state = "holymelonslice" + food_reagents = list( + /datum/reagent/water/holywater = 0.5, + /datum/reagent/consumable/nutriment/vitamin = 0.2, + /datum/reagent/consumable/nutriment = 1, + ) + tastes = list("holymelon" = 1) + foodtypes = FRUIT + food_flags = FOOD_FINGER_FOOD + juice_typepath = /datum/reagent/water/holywater + w_class = WEIGHT_CLASS_SMALL + +/obj/item/food/holymelonmush + name = "holymelon mush" + desc = "A plop of holy goodness." + icon = 'icons/obj/service/hydroponics/harvest.dmi' + icon_state = "holymelonpulp" + food_reagents = list( + /datum/reagent/water/holywater = 1, + /datum/reagent/consumable/nutriment/vitamin = 0.1, + /datum/reagent/consumable/nutriment = 0.5, + ) + tastes = list("holymelon" = 1) + foodtypes = FRUIT + food_flags = FOOD_FINGER_FOOD + juice_typepath = /datum/reagent/water/holywater + w_class = WEIGHT_CLASS_SMALL + +/obj/item/food/barrelmelonslice + name = "barrelmelon slice" + desc = "A slice of beery goodness." + icon = 'icons/obj/service/hydroponics/harvest.dmi' + icon_state = "barrelmelonslice" + food_reagents = list( + /datum/reagent/consumable/ethanol/beer = 1, + /datum/reagent/consumable/nutriment/vitamin = 0.2, + /datum/reagent/consumable/nutriment = 1, + ) + tastes = list("beer" = 1) + foodtypes = FRUIT + food_flags = FOOD_FINGER_FOOD + juice_typepath = /datum/reagent/consumable/ethanol/beer + w_class = WEIGHT_CLASS_SMALL + +/obj/item/food/barrelmelonmush + name = "barrelmelon mush" + desc = "A plop of beery goodness." + icon = 'icons/obj/service/hydroponics/harvest.dmi' + icon_state = "barrelmelonpulp" + food_reagents = list( + /datum/reagent/consumable/ethanol/beer = 2, + /datum/reagent/consumable/nutriment/vitamin = 0.1, + /datum/reagent/consumable/nutriment = 0.5, + ) + tastes = list("beer" = 1) + foodtypes = FRUIT + food_flags = FOOD_FINGER_FOOD + juice_typepath = /datum/reagent/consumable/ethanol/beer + w_class = WEIGHT_CLASS_SMALL + + /obj/item/food/appleslice name = "apple slice" desc = "The perfect after-school snack." diff --git a/code/game/objects/items/grenades/_grenade.dm b/code/game/objects/items/grenades/_grenade.dm index 6c84b5cf46eea7..bb9d275fb00b8e 100644 --- a/code/game/objects/items/grenades/_grenade.dm +++ b/code/game/objects/items/grenades/_grenade.dm @@ -17,6 +17,8 @@ obj_flags = CONDUCTS_ELECTRICITY slot_flags = ITEM_SLOT_BELT max_integrity = 40 + pickup_sound = 'sound/items/grenade_pick_up.ogg' + drop_sound = 'sound/items/grenade_drop.ogg' /// Bitfields which prevent the grenade from detonating if set. Includes ([GRENADE_DUD]|[GRENADE_USED]) var/dud_flags = NONE ///Is this grenade currently armed? diff --git a/code/game/objects/items/handcuffs.dm b/code/game/objects/items/handcuffs.dm index c5a68260abade4..dfcd6031d8729b 100644 --- a/code/game/objects/items/handcuffs.dm +++ b/code/game/objects/items/handcuffs.dm @@ -48,6 +48,8 @@ breakouttime = 1 MINUTES armor_type = /datum/armor/restraints_handcuffs custom_price = PAYCHECK_COMMAND * 0.35 + pickup_sound = 'sound/items/handcuffs_pick_up.ogg' + drop_sound = 'sound/items/handcuffs_drop.ogg' ///How long it takes to handcuff someone var/handcuff_time = 4 SECONDS @@ -55,6 +57,8 @@ var/handcuff_time_mod = 1 ///Sound that plays when starting to put handcuffs on someone var/cuffsound = 'sound/weapons/handcuffs.ogg' + ///Sound that plays when restrain is successful + var/cuffsuccesssound = 'sound/items/handcuff_finish.ogg' ///If set, handcuffs will be destroyed on application and leave behind whatever this is set to. var/trashtype = null /// How strong the cuffs are. Weak cuffs can be broken with wirecutters or boxcutters. @@ -120,6 +124,7 @@ return apply_cuffs(victim, user, dispense = iscyborg(user)) + playsound(loc, cuffsuccesssound, 30, TRUE, -2) victim.visible_message( span_notice("[user] handcuffs [victim]."), diff --git a/code/game/objects/items/knives.dm b/code/game/objects/items/knives.dm index 1a16b08eb866b5..848058a6a279ea 100644 --- a/code/game/objects/items/knives.dm +++ b/code/game/objects/items/knives.dm @@ -166,6 +166,19 @@ force = 15 throwforce = 15 +/obj/item/knife/combat/root + name = "cahn'root dagger" + icon = 'icons/obj/weapons/stabby.dmi' + icon_state = "rootdagger" + worn_icon_state = "root_dagger" + lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' + inhand_icon_state = "rootshiv" + embed_type = /datum/embed_data/combat_knife/weak + desc = "A root dagger, deceptively sharp. Perfect to hide and stab someone with, or make a couple and throw them at enemies." + force = 15 + throwforce = 15 + /obj/item/knife/combat/bone name = "bone dagger" inhand_icon_state = "bone_dagger" @@ -177,7 +190,6 @@ desc = "A sharpened bone. The bare minimum in survival." embed_type = /datum/embed_data/combat_knife/weak obj_flags = parent_type::obj_flags & ~CONDUCTS_ELECTRICITY - slot_flags = NONE force = 15 throwforce = 15 custom_materials = null @@ -189,7 +201,9 @@ name = "cyborg knife" icon = 'icons/obj/items_cyborg.dmi' icon_state = "knife_cyborg" + worn_icon_state = "knife_cyborg" //error sprite - this shouldn't have been dropped desc = "A cyborg-mounted plasteel knife. Extremely sharp and durable." + slot_flags = NONE //you can't put this in your mouth /obj/item/knife/shiv name = "glass shiv" @@ -279,3 +293,18 @@ /obj/item/knife/shiv/carrot/suicide_act(mob/living/carbon/user) user.visible_message(span_suicide("[user] forcefully drives \the [src] into [user.p_their()] eye! It looks like [user.p_theyre()] trying to commit suicide!")) return BRUTELOSS + +/obj/item/knife/shiv/parsnip + name = "parsnip shiv" + icon_state = "parsnipshiv" + inhand_icon_state = "parsnipshiv" + desc = "Truly putting 'snip' in the 'parsnip', and it's not sub-par either!" + custom_materials = null + +/obj/item/knife/shiv/root + name = "cahn'root shiv" + icon_state = "rootshiv" + inhand_icon_state = "rootshiv" + desc = "A root sharpened into a shiv. A root source of someone's stab wounds soon, most likely." + custom_materials = null + diff --git a/code/game/objects/items/melee/baton.dm b/code/game/objects/items/melee/baton.dm index 253a40be69d54f..4af5c4c923e75b 100644 --- a/code/game/objects/items/melee/baton.dm +++ b/code/game/objects/items/melee/baton.dm @@ -318,6 +318,8 @@ bare_wound_bonus = 5 clumsy_knockdown_time = 15 SECONDS active = FALSE + pickup_sound = 'sound/items/stun_baton_pick_up.ogg' + drop_sound = 'sound/items/stun_baton_drop.ogg' /// The sound effecte played when our baton is extended. var/on_sound = 'sound/weapons/batonextend.ogg' @@ -436,6 +438,8 @@ light_on = FALSE light_color = LIGHT_COLOR_ORANGE light_power = 0.5 + pickup_sound = 'sound/items/stun_baton_pick_up.ogg' + drop_sound = 'sound/items/stun_baton_drop.ogg' var/throw_stun_chance = 35 @@ -504,7 +508,6 @@ /obj/item/melee/baton/security/Exited(atom/movable/mov_content) . = ..() if(mov_content == cell) - cell.update_appearance() cell = null active = FALSE update_appearance() diff --git a/code/game/objects/items/melee/misc.dm b/code/game/objects/items/melee/misc.dm index 80b1e66b2e3e9d..855484c3066d44 100644 --- a/code/game/objects/items/melee/misc.dm +++ b/code/game/objects/items/melee/misc.dm @@ -164,6 +164,47 @@ user.death(FALSE) REMOVE_TRAIT(src, TRAIT_NODROP, SABRE_SUICIDE_TRAIT) + +/obj/item/melee/parsnip_sabre + name = "parsnip sabre" + desc = "A weird, yet elegant weapon. Suprisingly sharp for something made from a parsnip." + icon = 'icons/obj/weapons/sword.dmi' + icon_state = "parsnip_sabre" + inhand_icon_state = "parsnip_sabre" + lefthand_file = 'icons/mob/inhands/weapons/swords_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/swords_righthand.dmi' + force = 15 + throwforce = 10 + demolition_mod = 0.3 + w_class = WEIGHT_CLASS_BULKY + block_chance = 40 + armour_penetration = 40 + sharpness = SHARP_EDGED + attack_verb_continuous = list("slashes", "cuts") + attack_verb_simple = list("slash", "cut") + block_sound = 'sound/weapons/parry.ogg' + hitsound = 'sound/weapons/rapierhit.ogg' + custom_materials = null + wound_bonus = 5 + bare_wound_bonus = 15 + +/obj/item/melee/sabre/Initialize(mapload) + . = ..() + AddComponent(/datum/component/jousting) + +/obj/item/melee/parsnip_sabre/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) + if(attack_type == PROJECTILE_ATTACK || attack_type == LEAP_ATTACK) + final_block_chance = 0 //Don't bring a sword to a gunfight, and also you aren't going to really block someone full body tackling you with a sword + return ..() + +/obj/item/melee/parsnip_sabre/on_exit_storage(datum/storage/container) + . = ..() + playsound(container.parent, 'sound/items/unsheath.ogg', 25, TRUE) + +/obj/item/melee/parsnip_sabre/on_enter_storage(datum/storage/container) + . = ..() + playsound(container.parent, 'sound/items/sheath.ogg', 25, TRUE) + /obj/item/melee/beesword name = "The Stinger" desc = "Taken from a giant bee and folded over one thousand times in pure honey. Can sting through anything." diff --git a/code/game/objects/items/nitrium_crystals.dm b/code/game/objects/items/nitrium_crystals.dm deleted file mode 100644 index 828f437ade2fd1..00000000000000 --- a/code/game/objects/items/nitrium_crystals.dm +++ /dev/null @@ -1,18 +0,0 @@ -/obj/item/nitrium_crystal - desc = "A weird brown crystal, it smokes when broken" - name = "nitrium crystal" - icon = 'icons/obj/pipes_n_cables/atmos.dmi' - icon_state = "nitrium_crystal" - var/cloud_size = 1 - -/obj/item/nitrium_crystal/attack_self(mob/user) - . = ..() - var/datum/effect_system/fluid_spread/smoke/chem/smoke = new - var/turf/location = get_turf(src) - create_reagents(5) - reagents.add_reagent(/datum/reagent/nitrium_low_metabolization, 3) - reagents.add_reagent(/datum/reagent/nitrium_high_metabolization, 2) - smoke.attach(location) - smoke.set_up(cloud_size, holder = src, location = location, carry = reagents, silent = TRUE) - smoke.start() - qdel(src) diff --git a/code/game/objects/items/robot/items/storage.dm b/code/game/objects/items/robot/items/storage.dm index 2d91128adb68d6..3e030a9bd8f23d 100644 --- a/code/game/objects/items/robot/items/storage.dm +++ b/code/game/objects/items/robot/items/storage.dm @@ -41,6 +41,11 @@ stored.forceMove(get_turf(usr)) return +/obj/item/borg/apparatus/get_proxy_attacker_for(atom/target, mob/user) + if(stored) // Use the stored item if available + return stored + return ..() + /** * Attack_self will pass for the stored item. */ @@ -57,10 +62,6 @@ return CLICK_ACTION_SUCCESS /obj/item/borg/apparatus/pre_attack(atom/atom, mob/living/user, params) - if(stored) - stored.melee_attack_chain(user, atom, params) - return TRUE - if(istype(atom.loc, /mob/living/silicon/robot) || istype(atom.loc, /obj/item/robot_model) || HAS_TRAIT(atom, TRAIT_NODROP)) return ..() // Borgs should not be grabbing their own modules @@ -132,7 +133,6 @@ else . += "Nothing." - . += span_notice(" Right-clicking will splash the beaker on the ground.") . += span_notice(" Alt-click will drop the currently stored beaker. ") /obj/item/borg/apparatus/beaker/update_overlays() @@ -151,15 +151,6 @@ arm.pixel_y = arm.pixel_y - 5 . += arm -/// Secondary attack spills the content of the beaker. -/obj/item/borg/apparatus/beaker/pre_attack_secondary(atom/target, mob/living/silicon/robot/user) - var/obj/item/reagent_containers/stored_beaker = stored - if(!stored_beaker) - return ..() - stored_beaker.SplashReagents(drop_location(user)) - loc.visible_message(span_notice("[user] spills the contents of [stored_beaker] all over the ground.")) - return ..() - /obj/item/borg/apparatus/beaker/extra name = "secondary beaker storage apparatus" desc = "A supplementary beaker storage apparatus." diff --git a/code/game/objects/items/shields.dm b/code/game/objects/items/shields.dm index 1553f0e9c8f29f..c980fe0dbb3596 100644 --- a/code/game/objects/items/shields.dm +++ b/code/game/objects/items/shields.dm @@ -99,6 +99,15 @@ max_integrity = 55 w_class = WEIGHT_CLASS_NORMAL +/obj/item/shield/buckler/moonflower + name = "moonflower buckler" + desc = "A buckler made from a steel-cap reinforced moonflower." + icon_state = "moonflower_buckler" + inhand_icon_state = "moonflower_buckler" + block_chance = 40 + max_integrity = 40 + w_class = WEIGHT_CLASS_NORMAL + /obj/item/shield/kite name = "kite shield" desc = "Protect your internal organs with this almond shaped shield." @@ -140,6 +149,8 @@ shield_break_sound = 'sound/effects/glassbr3.ogg' shield_break_leftover = /obj/item/shard armor_type = /datum/armor/item_shield/riot + pickup_sound = 'sound/items/plastic_shield_pick_up.ogg' + drop_sound = 'sound/items/plastic_shield_drop.ogg' /obj/item/shield/riot/Initialize(mapload) . = ..() diff --git a/code/game/objects/items/spear.dm b/code/game/objects/items/spear.dm index 96fbde554b79e2..53e307e31d6e05 100644 --- a/code/game/objects/items/spear.dm +++ b/code/game/objects/items/spear.dm @@ -221,7 +221,7 @@ icon_state = "military_spear0" base_icon_state = "military_spear0" icon_prefix = "military_spear" - name = "military Javelin" + name = "military javelin" desc = "A stick with a seemingly blunt spearhead on its end. Looks like it might break bones easily." attack_verb_continuous = list("attacks", "pokes", "jabs") attack_verb_simple = list("attack", "poke", "jab") diff --git a/code/game/objects/items/stacks/rods.dm b/code/game/objects/items/stacks/rods.dm index 6314c16c8449c6..69dbe87cd5cc9c 100644 --- a/code/game/objects/items/stacks/rods.dm +++ b/code/game/objects/items/stacks/rods.dm @@ -41,6 +41,7 @@ GLOBAL_LIST_INIT(rod_recipes, list ( \ merge_type = /obj/item/stack/rods pickup_sound = 'sound/items/iron_rod_pick_up.ogg' drop_sound = 'sound/items/metal_drop.ogg' + sound_vary = TRUE /datum/embed_data/rods embed_chance = 50 diff --git a/code/game/objects/items/stacks/sheets/leather.dm b/code/game/objects/items/stacks/sheets/leather.dm index f02a2af11f8355..1f13ec34a764cd 100644 --- a/code/game/objects/items/stacks/sheets/leather.dm +++ b/code/game/objects/items/stacks/sheets/leather.dm @@ -5,9 +5,8 @@ inhand_icon_state = null novariants = TRUE merge_type = /obj/item/stack/sheet/animalhide - - pickup_sound = null - drop_sound = null + pickup_sound = 'sound/items/skin_pick_up.ogg' + drop_sound = 'sound/items/skin_drop.ogg' /obj/item/stack/sheet/animalhide/human name = "human skin" @@ -194,6 +193,8 @@ GLOBAL_LIST_INIT(carp_recipes, list ( \ icon_state = "sheet-leather" inhand_icon_state = null merge_type = /obj/item/stack/sheet/leather + pickup_sound = 'sound/items/skin_pick_up.ogg' + drop_sound = 'sound/items/skin_drop.ogg' GLOBAL_LIST_INIT(leather_recipes, list ( \ new/datum/stack_recipe("wallet", /obj/item/storage/wallet, 1, crafting_flags = NONE, category = CAT_CONTAINERS), \ diff --git a/code/game/objects/items/stacks/sheets/sheet_types.dm b/code/game/objects/items/stacks/sheets/sheet_types.dm index 8cf393b3e065c1..425a6249845509 100644 --- a/code/game/objects/items/stacks/sheets/sheet_types.dm +++ b/code/game/objects/items/stacks/sheets/sheet_types.dm @@ -680,6 +680,8 @@ GLOBAL_LIST_INIT(cardboard_recipes, list ( \ merge_type = /obj/item/stack/sheet/cardboard grind_results = list(/datum/reagent/cellulose = 10) material_type = /datum/material/cardboard + pickup_sound = 'sound/items/cardboard_pick_up.ogg' + drop_sound = 'sound/items/cardboard_drop.ogg' /obj/item/stack/sheet/cardboard/Initialize(mapload, new_amount, merge, list/mat_override, mat_amt) . = ..() diff --git a/code/game/objects/items/storage/belt.dm b/code/game/objects/items/storage/belt.dm index 1bf97712ec566e..bd1f52a832349a 100644 --- a/code/game/objects/items/storage/belt.dm +++ b/code/game/objects/items/storage/belt.dm @@ -373,6 +373,9 @@ /obj/item/restraints/handcuffs, /obj/item/restraints/legcuffs/bola, )) + atom_storage.open_sound = 'sound/items/holster.ogg' + atom_storage.open_sound_vary = TRUE + atom_storage.rustle_sound = FALSE /obj/item/storage/belt/security/full/PopulateContents() new /obj/item/reagent_containers/spray/pepper(src) @@ -855,6 +858,50 @@ new /obj/item/melee/sabre(src) update_appearance() +/obj/item/storage/belt/grass_sabre + name = "sabre sheath" + desc = "An simple grass sheath designed to hold a sabre of... some sort. Actual metal one might be too sharp, though..." + icon_state = "grass_sheath" + inhand_icon_state = "grass_sheath" + worn_icon_state = "grass_sheath" + w_class = WEIGHT_CLASS_BULKY + interaction_flags_click = parent_type::interaction_flags_click | NEED_DEXTERITY | NEED_HANDS + +/obj/item/storage/belt/grass_sabre/Initialize(mapload) + . = ..() + AddElement(/datum/element/update_icon_updates_onmob) + + atom_storage.max_slots = 1 + atom_storage.rustle_sound = FALSE + atom_storage.max_specific_storage = WEIGHT_CLASS_BULKY + atom_storage.set_holdable(/obj/item/melee/parsnip_sabre) + atom_storage.click_alt_open = FALSE + +/obj/item/storage/belt/grass_sabre/examine(mob/user) + . = ..() + if(length(contents)) + . += span_notice("Alt-click it to quickly draw the blade.") + +/obj/item/storage/belt/grass_sabre/click_alt(mob/user) + if(length(contents)) + var/obj/item/I = contents[1] + user.visible_message(span_notice("[user] takes [I] out of [src]."), span_notice("You take [I] out of [src].")) + user.put_in_hands(I) + update_appearance() + else + balloon_alert(user, "it's empty!") + return CLICK_ACTION_SUCCESS + +/obj/item/storage/belt/grass_sabre/update_icon_state() + icon_state = initial(inhand_icon_state) + inhand_icon_state = initial(inhand_icon_state) + worn_icon_state = initial(worn_icon_state) + if(contents.len) + icon_state += "-sabre" + inhand_icon_state += "-sabre" + worn_icon_state += "-sabre" + return ..() + /obj/item/storage/belt/plant name = "botanical belt" desc = "A sturdy leather belt used to hold most hydroponics supplies." diff --git a/code/game/objects/items/storage/boxes/job_boxes.dm b/code/game/objects/items/storage/boxes/job_boxes.dm index ea9189cc5f2b00..a8ced4fdad48e0 100644 --- a/code/game/objects/items/storage/boxes/job_boxes.dm +++ b/code/game/objects/items/storage/boxes/job_boxes.dm @@ -43,7 +43,7 @@ if(HAS_TRAIT(SSstation, STATION_TRAIT_RADIOACTIVE_NEBULA)) new /obj/item/storage/pill_bottle/potassiodide(src) - if(SSmapping.is_planetary() && LAZYLEN(SSmapping.multiz_levels)) + if(length(SSmapping.levels_by_trait(ZTRAIT_STATION)) > 1) new /obj/item/climbing_hook/emergency(src) /obj/item/storage/box/survival/radio/PopulateContents() diff --git a/code/game/objects/items/storage/holsters.dm b/code/game/objects/items/storage/holsters.dm index afb7b0f750b26a..f8dee3afdc7f41 100644 --- a/code/game/objects/items/storage/holsters.dm +++ b/code/game/objects/items/storage/holsters.dm @@ -33,6 +33,8 @@ /obj/item/gun/energy/laser/captain, /obj/item/gun/energy/e_gun/hos, )) + atom_storage.open_sound = 'sound/items/holster.ogg' + atom_storage.open_sound_vary = TRUE /obj/item/storage/belt/holster/energy name = "energy shoulder holsters" diff --git a/code/game/objects/items/storage/medkit.dm b/code/game/objects/items/storage/medkit.dm index c3c97c790fdf3f..bee7fdd524f3de 100644 --- a/code/game/objects/items/storage/medkit.dm +++ b/code/game/objects/items/storage/medkit.dm @@ -18,6 +18,9 @@ righthand_file = 'icons/mob/inhands/equipment/medical_righthand.dmi' throw_speed = 3 throw_range = 7 + drop_sound = 'sound/items/medkit_drop.ogg' + pickup_sound = 'sound/items/medkit_pick_up.ogg' + sound_vary = TRUE var/empty = FALSE /// Defines damage type of the medkit. General ones stay null. Used for medibot healing bonuses var/damagetype_healed @@ -79,6 +82,8 @@ /obj/item/storage/medkit/Initialize(mapload) . = ..() atom_storage.max_specific_storage = WEIGHT_CLASS_SMALL + atom_storage.open_sound = 'sound/items/medkit_open.ogg' + atom_storage.open_sound_vary = TRUE /obj/item/storage/medkit/regular icon_state = "medkit" diff --git a/code/game/objects/items/storage/toolbox.dm b/code/game/objects/items/storage/toolbox.dm index 7c5bc74e075502..905f2e40f47a7e 100644 --- a/code/game/objects/items/storage/toolbox.dm +++ b/code/game/objects/items/storage/toolbox.dm @@ -348,6 +348,11 @@ weapon_to_spawn = /obj/item/gun/ballistic/automatic/c20r extra_to_spawn = /obj/item/ammo_box/magazine/smgm45 +/obj/item/storage/toolbox/guncase/smartgun + name = "adielle smartgun case" + weapon_to_spawn = /obj/item/gun/ballistic/automatic/smartgun + extra_to_spawn = /obj/item/ammo_box/magazine/smartgun + /obj/item/storage/toolbox/guncase/clandestine name = "clandestine gun case" weapon_to_spawn = /obj/item/gun/ballistic/automatic/pistol/clandestine @@ -442,12 +447,6 @@ weapon_to_spawn = /obj/effect/spawner/random/sakhno extra_to_spawn = /obj/effect/spawner/random/sakhno/ammo -/obj/item/storage/toolbox/guncase/soviet/plastikov - name = "ancient surplus gun case" - desc = "A gun case. Has the symbol of the Third Soviet Union stamped on the side." - weapon_to_spawn = /obj/item/gun/ballistic/automatic/plastikov - extra_to_spawn = /obj/item/food/rationpack //sorry comrade, cannot get you more ammo, here, have lunch - /obj/item/storage/toolbox/guncase/monkeycase name = "monkey gun case" desc = "Everything a monkey needs to truly go ape-shit. There's a paw-shaped hand scanner lock on the front of the case." diff --git a/code/game/objects/items/tanks/tanks.dm b/code/game/objects/items/tanks/tanks.dm index ee1f314c92addf..d89794f420917e 100644 --- a/code/game/objects/items/tanks/tanks.dm +++ b/code/game/objects/items/tanks/tanks.dm @@ -22,6 +22,9 @@ slot_flags = ITEM_SLOT_BACK worn_icon = 'icons/mob/clothing/back.dmi' //since these can also get thrown into suit storage slots. if something goes on the belt, set this to null. hitsound = 'sound/weapons/smash.ogg' + pickup_sound = 'sound/items/gas_tank_pick_up.ogg' + drop_sound = 'sound/items/gas_tank_drop.ogg' + sound_vary = TRUE pressure_resistance = ONE_ATMOSPHERE * 5 force = 5 throwforce = 10 diff --git a/code/game/objects/items/tools/crowbar.dm b/code/game/objects/items/tools/crowbar.dm index c6b0d52cdc1c34..20e3846adefabf 100644 --- a/code/game/objects/items/tools/crowbar.dm +++ b/code/game/objects/items/tools/crowbar.dm @@ -191,7 +191,7 @@ desc = "A hydraulic prying tool, simple but powerful." icon = 'icons/obj/items_cyborg.dmi' icon_state = "toolkit_engiborg_crowbar" - worn_icon_state = "crowbar" + worn_icon_state = "toolkit_engiborg_crowbar" //error sprite - this shouldn't have been dropped usesound = 'sound/items/jaws_pry.ogg' force = 10 toolspeed = 0.5 diff --git a/code/game/objects/items/tools/weldingtool.dm b/code/game/objects/items/tools/weldingtool.dm index b2b0109c04c882..fb40a70cbeea0e 100644 --- a/code/game/objects/items/tools/weldingtool.dm +++ b/code/game/objects/items/tools/weldingtool.dm @@ -145,22 +145,30 @@ if(user.combat_mode) return NONE + return try_heal_loop(interacting_with, user) + +/obj/item/weldingtool/proc/try_heal_loop(atom/interacting_with, mob/living/user, repeating = FALSE) var/mob/living/carbon/human/attacked_humanoid = interacting_with var/obj/item/bodypart/affecting = attacked_humanoid.get_bodypart(check_zone(user.zone_selected)) if(isnull(affecting) || !IS_ROBOTIC_LIMB(affecting)) return NONE - var/use_delay = 0 + if (!affecting.get_damage()) + return + user.visible_message(span_notice("[user] starts to fix some of the dents on [attacked_humanoid == user ? user.p_their() : "[attacked_humanoid]'s"] [affecting.name]."), + span_notice("You start fixing some of the dents on [attacked_humanoid == user ? "your" : "[attacked_humanoid]'s"] [affecting.name].")) + var/use_delay = repeating ? 1 SECONDS : 0 if(user == attacked_humanoid) - user.visible_message(span_notice("[user] starts to fix some of the dents on [attacked_humanoid]'s [affecting.name]."), - span_notice("You start fixing some of the dents on [attacked_humanoid == user ? "your" : "[attacked_humanoid]'s"] [affecting.name].")) use_delay = 5 SECONDS if(!use_tool(attacked_humanoid, user, use_delay, volume=50, amount=1)) return ITEM_INTERACT_BLOCKING - attacked_humanoid.item_heal(user, brute_heal = 15, burn_heal = 0, heal_message_brute = "dents", heal_message_burn = "burnt wires", required_bodytype = BODYTYPE_ROBOTIC) + if (!attacked_humanoid.item_heal(user, brute_heal = 15, burn_heal = 0, heal_message_brute = "dents", heal_message_burn = "burnt wires", required_bodytype = BODYTYPE_ROBOTIC)) + return ITEM_INTERACT_BLOCKING + + INVOKE_ASYNC(src, PROC_REF(try_heal_loop), interacting_with, user, TRUE) return ITEM_INTERACT_SUCCESS /obj/item/weldingtool/afterattack(atom/target, mob/user, click_parameters) diff --git a/code/game/objects/items/weaponry.dm b/code/game/objects/items/weaponry.dm index fbe11fe933d1b8..0d3e3f60d4abf0 100644 --- a/code/game/objects/items/weaponry.dm +++ b/code/game/objects/items/weaponry.dm @@ -505,6 +505,37 @@ for further reading, please see: https://github.com/tgstation/tgstation/pull/301 user.visible_message(span_suicide("[user] is strangling [user.p_them()]self with [src]'s cord! It looks like [user.p_theyre()] trying to commit suicide!")) return OXYLOSS +/obj/item/bambostaff + name = "Bamboo Staff" + desc = "A long bamboo-made staff with steel-capped ends. It is rumoured that initiates of Spider Clan train with such before getting to learn how to use a katana." + force = 10 + block_chance = 45 + block_sound = 'sound/weapons/genhit.ogg' + slot_flags = ITEM_SLOT_BACK + w_class = WEIGHT_CLASS_BULKY + hitsound = SFX_SWING_HIT + attack_verb_continuous = list("smashes", "slams", "whacks", "thwacks") + attack_verb_simple = list("smash", "slam", "whack", "thwack") + icon = 'icons/obj/weapons/staff.dmi' + icon_state = "bambostaff0" + base_icon_state = "bambostaff" + inhand_icon_state = "bambostaff0" + worn_icon_state = "bambostaff0" + lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi' + righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi' + +/obj/item/bambostaff/Initialize(mapload) + . = ..() + AddComponent(/datum/component/two_handed, \ + force_unwielded = 10, \ + force_wielded = 14, \ + icon_wielded = "[base_icon_state]1", \ + ) + +/obj/item/bambostaff/update_icon_state() + icon_state = "[base_icon_state]0" + return ..() + /obj/item/cane name = "cane" desc = "A cane used by a true gentleman. Or a clown." diff --git a/code/game/objects/objs.dm b/code/game/objects/objs.dm index ce1b48985bb675..f12479c66a444a 100644 --- a/code/game/objects/objs.dm +++ b/code/game/objects/objs.dm @@ -12,7 +12,7 @@ /// Icon to use as a 32x32 preview in crafting menus and such var/icon_preview var/icon_state_preview - /// The vertical pixel offset applied when the object is anchored on a tile with table + /// The vertical pixel_z offset applied when the object is anchored on a tile with table /// Ignored when set to 0 - to avoid shifting directional wall-mounted objects above tables var/anchored_tabletop_offset = 0 @@ -278,7 +278,14 @@ GLOBAL_LIST_EMPTY(objects_by_id_tag) return FALSE return TRUE -/// Adjusts the vertical pixel offset when the object is anchored on a tile with table +/// Adjusts the vertical pixel_z offset when the object is anchored on a tile with table /obj/proc/check_on_table() - if(anchored_tabletop_offset != 0 && !istype(src, /obj/structure/table) && locate(/obj/structure/table) in loc) - pixel_y = anchored ? anchored_tabletop_offset : initial(pixel_y) + if(anchored_tabletop_offset == 0) + return + if(istype(src, /obj/structure/table)) + return + + if(anchored && locate(/obj/structure/table) in loc) + pixel_z = anchored_tabletop_offset + else + pixel_z = initial(pixel_z) diff --git a/code/game/objects/structures/lavaland/ore_vent.dm b/code/game/objects/structures/lavaland/ore_vent.dm index 024276198ab512..f9214b989b95c7 100644 --- a/code/game/objects/structures/lavaland/ore_vent.dm +++ b/code/game/objects/structures/lavaland/ore_vent.dm @@ -39,6 +39,7 @@ MEDIUM_VENT_TYPE = 5, SMALL_VENT_TYPE = 7, ) + var/wave_timer = WAVE_DURATION_SMALL /// What string do we use to warn the player about the excavation event? var/excavation_warning = "Are you ready to excavate this ore vent?" @@ -219,6 +220,9 @@ node.arrive(src) RegisterSignal(node, COMSIG_QDELETING, PROC_REF(handle_wave_conclusion)) RegisterSignal(node, COMSIG_MOVABLE_MOVED, PROC_REF(handle_wave_conclusion)) + addtimer(CALLBACK(node, TYPE_PROC_REF(/atom, update_appearance)), wave_timer * 0.25) + addtimer(CALLBACK(node, TYPE_PROC_REF(/atom, update_appearance)), wave_timer * 0.5) + addtimer(CALLBACK(node, TYPE_PROC_REF(/atom, update_appearance)), wave_timer * 0.75) particles = new /particles/smoke/ash() for(var/i in 1 to 5) // Clears the surroundings of the ore vent before starting wave defense. for(var/turf/closed/mineral/rock in oview(i)) @@ -247,11 +251,6 @@ spawn_distance = 4, \ spawn_distance_exclude = 3, \ ) - var/wave_timer = 60 SECONDS - if(boulder_size == BOULDER_SIZE_MEDIUM) - wave_timer = 90 SECONDS - else if(boulder_size == BOULDER_SIZE_LARGE) - wave_timer = 150 SECONDS COOLDOWN_START(src, wave_cooldown, wave_timer) addtimer(CALLBACK(src, PROC_REF(handle_wave_conclusion)), wave_timer) icon_state = icon_state_tapped @@ -290,6 +289,7 @@ icon_state = icon_state_tapped update_appearance(UPDATE_ICON_STATE) qdel(GetComponent(/datum/component/gps)) + UnregisterSignal(node, COMSIG_QDELETING) else visible_message(span_danger("\the [src] creaks and groans as the mining attempt fails, and the vent closes back up.")) icon_state = initial(icon_state) @@ -474,18 +474,22 @@ switch(string_boulder_size) if(LARGE_VENT_TYPE) boulder_size = BOULDER_SIZE_LARGE + wave_timer = WAVE_DURATION_LARGE if(mapload) GLOB.ore_vent_sizes["large"] += 1 if(MEDIUM_VENT_TYPE) boulder_size = BOULDER_SIZE_MEDIUM + wave_timer = WAVE_DURATION_MEDIUM if(mapload) GLOB.ore_vent_sizes["medium"] += 1 if(SMALL_VENT_TYPE) boulder_size = BOULDER_SIZE_SMALL + wave_timer = WAVE_DURATION_SMALL if(mapload) GLOB.ore_vent_sizes["small"] += 1 else boulder_size = BOULDER_SIZE_SMALL //Might as well set a default value + wave_timer = WAVE_DURATION_SMALL name = initial(name) diff --git a/code/game/objects/structures/tables_racks.dm b/code/game/objects/structures/tables_racks.dm index 72c974b00252d5..8dc8d82ff5f7de 100644 --- a/code/game/objects/structures/tables_racks.dm +++ b/code/game/objects/structures/tables_racks.dm @@ -316,9 +316,11 @@ return NONE if(!user.transferItemToLoc(tool, drop_location(), silent = FALSE)) return ITEM_INTERACT_BLOCKING - //Clamp it so that the icon never moves more than 16 pixels in either direction (thus leaving the table turf) - tool.pixel_x = clamp(text2num(LAZYACCESS(modifiers, ICON_X)) - 16, -(world.icon_size/2), world.icon_size/2) - tool.pixel_y = clamp(text2num(LAZYACCESS(modifiers, ICON_Y)) - 16, -(world.icon_size/2), world.icon_size/2) + // Items are centered by default, but we move them if click ICON_X and ICON_Y are available + if(LAZYACCESS(modifiers, ICON_X) && LAZYACCESS(modifiers, ICON_Y)) + // Clamp it so that the icon never moves more than 16 pixels in either direction (thus leaving the table turf) + tool.pixel_x = clamp(text2num(LAZYACCESS(modifiers, ICON_X)) - 16, -(world.icon_size*0.5), world.icon_size*0.5) + tool.pixel_y = clamp(text2num(LAZYACCESS(modifiers, ICON_Y)) - 16, -(world.icon_size*0.5), world.icon_size*0.5) AfterPutItemOnTable(tool, user) return ITEM_INTERACT_SUCCESS @@ -354,6 +356,7 @@ if((shove_flags & SHOVE_KNOCKDOWN_BLOCKED) || !(shove_flags & SHOVE_BLOCKED)) return target.Knockdown(SHOVE_KNOCKDOWN_TABLE) + target.apply_status_effect(/datum/status_effect/next_shove_stuns) target.visible_message(span_danger("[shover.name] shoves [target.name] onto \the [src]!"), span_userdanger("You're shoved onto \the [src] by [shover.name]!"), span_hear("You hear aggressive shuffling followed by a loud thud!"), COMBAT_MESSAGE_RANGE, shover) to_chat(shover, span_danger("You shove [target.name] onto \the [src]!")) diff --git a/code/game/objects/structures/water_structures/water_source.dm b/code/game/objects/structures/water_structures/water_source.dm index b7ad26a65ea7e1..e06cd8c6771efd 100644 --- a/code/game/objects/structures/water_structures/water_source.dm +++ b/code/game/objects/structures/water_structures/water_source.dm @@ -137,6 +137,15 @@ base_icon_state = "puddle" resistance_flags = UNACIDABLE +/obj/structure/water_source/puddle/Initialize(mapload) + . = ..() + register_context() + +/obj/structure/water_source/puddle/add_context(atom/source, list/context, obj/item/held_item, mob/user) + . = ..() + if(isnull(held_item)) + context[SCREENTIP_CONTEXT_RMB] = "Scoop Tadpoles" + //ATTACK HAND IGNORING PARENT RETURN VALUE /obj/structure/water_source/puddle/attack_hand(mob/user, list/modifiers) icon_state = "[base_icon_state]-splash" @@ -147,3 +156,20 @@ icon_state = "[base_icon_state]-splash" . = ..() icon_state = base_icon_state + +/obj/structure/water_source/puddle/attack_hand_secondary(mob/living/carbon/human/user, list/modifiers) + . = ..() + if(. == SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN) + return + if(DOING_INTERACTION_WITH_TARGET(user, src)) + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN + icon_state = "[base_icon_state]-splash" + balloon_alert(user, "scooping tadpoles...") + if(do_after(user, src, 5 SECONDS)) + playsound(loc, 'sound/effects/slosh.ogg', 15, TRUE) + balloon_alert(user, "got a tadpole") + var/obj/item/fish/tadpole/tadpole = new(loc) + tadpole.randomize_size_and_weight() + user.put_in_hands(tadpole) + icon_state = base_icon_state + return SECONDARY_ATTACK_CANCEL_ATTACK_CHAIN diff --git a/code/game/turfs/open/floor/misc_floor.dm b/code/game/turfs/open/floor/misc_floor.dm index 7c4428c4823ec5..a3915e14cabb82 100644 --- a/code/game/turfs/open/floor/misc_floor.dm +++ b/code/game/turfs/open/floor/misc_floor.dm @@ -17,12 +17,17 @@ /turf/open/floor/circuit/Initialize(mapload) SSmapping.nuke_tiles += src RegisterSignal(loc, COMSIG_AREA_POWER_CHANGE, PROC_REF(handle_powerchange)) - handle_powerchange(loc) + var/area/cur_area = get_area(src) + if (!isnull(cur_area)) + handle_powerchange(cur_area, TRUE) . = ..() /turf/open/floor/circuit/Destroy() SSmapping.nuke_tiles -= src UnregisterSignal(loc, COMSIG_AREA_POWER_CHANGE) + var/area/cur_area = get_area(src) + if(on && !isnull(cur_area)) + cur_area.removeStaticPower(CIRCUIT_FLOOR_POWERUSE, AREA_USAGE_STATIC_LIGHT) return ..() /turf/open/floor/circuit/update_appearance(updates) @@ -47,7 +52,7 @@ handle_powerchange(new_area) /// Enables/disables our lighting based off our source area -/turf/open/floor/circuit/proc/handle_powerchange(area/source) +/turf/open/floor/circuit/proc/handle_powerchange(area/source, mapload = FALSE) SIGNAL_HANDLER var/old_on = on if(always_off) @@ -59,7 +64,7 @@ if(on) source.addStaticPower(CIRCUIT_FLOOR_POWERUSE, AREA_USAGE_STATIC_LIGHT) - else + else if (!mapload) source.removeStaticPower(CIRCUIT_FLOOR_POWERUSE, AREA_USAGE_STATIC_LIGHT) update_appearance() diff --git a/code/game/turfs/turf.dm b/code/game/turfs/turf.dm index 10165f869174f4..b0493ce0a8ad4c 100644 --- a/code/game/turfs/turf.dm +++ b/code/game/turfs/turf.dm @@ -3,6 +3,7 @@ GLOBAL_LIST_EMPTY(station_turfs) /// Any floor or wall. What makes up the station and the rest of the map. /turf icon = 'icons/turf/floors.dmi' + datum_flags = DF_STATIC_OBJECT vis_flags = VIS_INHERIT_ID // Important for interaction with and visualization of openspace. luminosity = 1 light_height = LIGHTING_HEIGHT_FLOOR diff --git a/code/game/world.dm b/code/game/world.dm index 9e57dbba343c53..b7de61e8c93e59 100644 --- a/code/game/world.dm +++ b/code/game/world.dm @@ -339,7 +339,6 @@ GLOBAL_VAR(restart_counter) #endif /world/proc/auxcleanup() - AUXTOOLS_FULL_SHUTDOWN(AUXLUA) var/debug_server = world.GetConfig("env", "AUXTOOLS_DEBUG_DLL") if (debug_server) call_ext(debug_server, "auxtools_shutdown")() @@ -472,6 +471,7 @@ GLOBAL_VAR(restart_counter) /world/proc/on_tickrate_change() SStimer?.reset_buckets() + DREAMLUAU_SET_EXECUTION_LIMIT_MILLIS(tick_lag * 100) /world/proc/init_byond_tracy() var/library diff --git a/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm b/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm index bc74347475ae98..1305e5a660d6e5 100644 --- a/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm +++ b/code/modules/admin/verbs/SDQL2/SDQL_2_wrappers.dm @@ -51,6 +51,9 @@ /proc/_get_step(Ref, Dir) return get_step(Ref, Dir) +/proc/_hascall(object, procname) + return hascall(object, procname) + /proc/_hearers(Depth = world.view, Center = usr) return hearers(Depth, Center) diff --git a/code/modules/admin/verbs/lua/README.md b/code/modules/admin/verbs/lua/README.md index 707184d4d772b7..9b9bfbe05f93ff 100644 --- a/code/modules/admin/verbs/lua/README.md +++ b/code/modules/admin/verbs/lua/README.md @@ -1,150 +1,225 @@ -# Auxlua +# Objects ---- +Datums, lists, typepaths, static appearances, and some other objects are represented in Luau as userdata. Certain operations can be performed on these types of objects. -## Datums +## Common metamethods -DM datums are treated as lua userdata, and can be stored in fields. Due to fundamental limitations in lua, userdata is inherently truthy. Since datum userdata can correspond to a deleted datum, which would evaluate to `null` in DM, the function [`datum:is_null()`](#datumisnull) is provided to offer a truthiness test consistent with DM. +The following metamethods are defined for all objects. -Keep in mind that BYOND can't see that a datum is referenced in a lua field, and will garbage collect it if it is not referenced anywhere in DM. +### \_\_tostring(): string -### datum:get_var(var) +Returns the string representation of the object. This uses BYOND's internal string conversion function. -Equivalent to DM's `datum.var` +### \_\_eq(other: any): boolean -### datum:set_var(var, value) +Compare the equality of two objects. While passing the same object into luau twice will return two references to the same userdata, some DM projects may override the equality operator using an `__operator==` proc definition. -Equivalent to DM's `datum.var = value` +## Datum-like Objects -### datum:call_proc(procName, ...) +Datum-like objects include datums themselves, clients (if they have not been redefined to be children of `/datum`), static appearances, and the world. -Equivalent to DM's `datum.procName(...)` +### \_\_index(index: string): any -### datum:is_null() +Access the member specified by `index`. -This function is used to evaluate the truthiness of a DM var. The lua statement `if datum:is_null() then` is equivalent to the DM statement `if(datum)`. +If `index` is a valid var for the object, the index operation will return that var's value. +If the var getting wrapper proc is set, the operation will instead call that proc with the arguments `(object, index)`. -### datum.vars +For objects other than static appearances, if `index` is a valid proc for the object, the operation will return a wrapper for that proc that can be invoked using call syntax (e.g. `object:proc(...arguments)`). If the object proc calling wrapper is set, calling the returned function will instead call the wrapper proc with the arguments `(object, proc, {...arguments})`. Note that vars will be shadowed by procs with the same name. To work around this, use the `dm.get_var` function. -Returns a userdatum that allows you to access and modifiy the vars of a DM datum by index. `datum.vars.foo` is equivalent to `datum:get_var("foo")`, while `datum.vars.foo = bar` is equivalent to `datum:set_var("foo", bar)` +### \_\_newindex(index: string, value: any): () ---- +Set the var specified by `index` to `value`, if that var exists on the object. + +If the var setting wrapper proc is set, the operation will instead call that proc with the arguments `(object, index, value)`. ## Lists -In order to allow lists to be modified in-place across the DM-to-lua language barrier, lists are treated as userdata. Whenever running code that expects a DM value, auxlua will attempt to convert tables into lists. +Lists are syntactically similar to tables, with one crucial difference. +Unlike tables, numeric indices must be non-zero integers within the bounds of the list. + +### \_\_index(index: any): any + +Read the list at `index`. This works both for numeric indices and assoc keys. +Vars lists cannot be directly read this way if the var getting wrapper proc is set. + +### \_\_newindex(index: any, value: any): any + +Write `value` to the list at `index`. This works both for writing numeric indices and assoc keys. +Vars lists cannot be directly written this way if the var setting wrapper proc is set. + +### \_\_len(): integer + +Returns the length of the list, similarly to the `length` builtin in DM. + +### Iteration + +Lists support Luau's generalized iteration. Iteration this way returns pairs of numeric indices and list values. +For example, the statement `for _, v in L do` is logically equivalent to the DM statement `for(var/v in L)`. + +# Global Fields and Modules + +In addition to the full extent of Luau's standard library modules, some extra functions and modules have been added. + +## Global-Level Fields + +### sleep(): () + +Yields the active thread, without worrying about passing data into or out of the state. + +Threads yielded this way are placed at the end of a queue. Call the `awaken` hook function from DM to execute the thread at the front of the queue. + +### loadstring(code: string): function + +Luau does not inherently include the `loadstring` function common to a number of other versions of lua. This is an effective reimplementation of `loadstring`. + +### print(...any): () + +Calls the print wrapper with the passed in arguments. +Raises an error if no print wrapper is set, as that means there is nothing to print with. + +### \_state_id: integer + +The handle to the underlying luau state in the dreamluau binary. + +## \_exec + +The `_exec` module includes volatile fields related to the current execution context. + +### \_next_yield_index: integer + +When yielding a thread with `coroutine.yield`, it will be inserted into an internal table at the first open integer index. +This field corresponds to that first open integer index. + +### \_limit: integer? + +If set, the execution limit, rounded to the nearest millisecond. + +### \_time: integer + +The length of successive time luau code has been executed, including recursive calls to DM and back into luau, rounded to the nearest millisecond. + +## dm -List references are subject to the same limitations as datum userdata, but you are less likely to encounter these limitations for regular lists. +The `dm` module includes fields and functions for basic interaction with DM. -Some lists (`vars`, `contents`, `overlays`, `underlays`, `vis_contents`, and `vis_locs`) are inherently attached to datums, and as such, their corresponding userdata contains a weak reference to the containing datum. Use [`list:is_null`](#listisnull) to validate these types of lists. +### world: userdata -### list.len +A static reference to the DM `world`. -Equivalent to DM's `list.len` +### global_vars: userdata -### list:get(index) +A static reference that functions like the DM keyword `global`. This can be indexed to read/write global vars. -Equivalent to DM's `list[index]` +### global_procs: table -### list:set(index, value) +A table that can be indexed by string for functions that wrap global procs. -Equivalent to DM's `list[index] = value` +Due to BYOND limitations, attempting to index an invalid proc returns a function logically equivalent to a no-op. -### list:add(value) +### get_var(object: userdata, var: string): function -Equivalent to DM's `list.Add(value)` +Reads the var `var` on `object`. This function can be used to get vars that are shadowed by procs declared with the same name. -### list:remove(value) +### new(path: string, ...any): userdata -Equivalent to DM's `list.Remove(value)` +Creates an instance of the object specified by `path`, with `...` as its arguments. +If the "new" wrapper is set, that proc will be called instead, with the arguments `(path, {...})`. -### list:to_table() +### is_valid_ref(ref: any): boolean -Converts a DM list into a lua table. +Returns true if the value passed in corresponds to a valid reference-counted DM object. -### list:of_type(type_path) +### usr: userdata? -Will extract only values of type `type_path`. +Corresponds to the DM var `usr`. -### list:is_null() +## list -A similar truthiness test to [`datum:is_null()`](#datumisnull). This function only has the possibility of returning `false` for lists that are inherently attached to a datum (`vars`, `contents`, `overlays`, `underlays`, `vis_contents`, and `vis_locs`). +The `list` module contains wrappers for the builtin list procs, along with several other utility functions for working with lists. -### list.entries +### add(list: userdata, ...any): () -Returns a userdatum that allows you to access and modifiy the entries of the list by index. `list.entries.foo` is equivalent to `list:get("foo")`, while `list.entries.foo = bar` is equivalent to `list:set("foo", bar)` +Logically equivalent to the DM statement `list.Add(...)`. ---- +### copy(list: userdata, start?: integer, end?: integer): userdata -## The dm table +Logically equivalent to the DM statement `list.Copy(start, end)`. -The `dm` table consists of the basic hooks into the DM language. +### cut(list: userdata, start?: integer, end?: integer): userdata -### dm.state_id +Logically equivalent to the DM statement `list.Cut(start, end)`. -The address of the lua state in memory. This is a copy of the internal value used by auxlua to locate the lua state in a global hash map. `state_id` is a registry value that is indirectly obtained using the `dm` table's `__index` metamethod. +### find(list: userdata, item: any, start?: integer, end?: integer): integer -### dm.global_proc(proc, ...) -Calls the global proc `/proc/[proc]` with `...` as its arguments. +Logically equivalent to the DM statement `list.Find(item, start, end)`. -### dm.world -A reference to DM's `world`, in the form of datum userdata. This reference is always valid, since `world` always exists. +### insert(list: userdata, index: integer, ...any): integer -Due to limitations inherent in the wrapper functions used on tgstation, `world:set_var` and `world:call_proc` will raise an error. +Logically equivalent to the DM statement `list.Insert(item, ...)`. -### dm.global_vars -A reference to DM's `global`, in the form of datum userdata. Subject to the same limitations as `dm.world` +### join(list: userdata, glue: string, start?: integer, end?: integer): string -### dm.usr -A weak reference to DM's `usr`. As a rule of thumb, this is a reference to the mob of the client who triggered the chain of procs leading to the execution of Lua code. The following is a list of what `usr` is for the most common ways of executing Lua code: -- For resumes and awakens, which are generally executed by the MC, `usr` is (most likely) null. -- `SS13.wait` queues a resume, which gets executed by the MC. Therefore, `usr` is null after `SS13.wait` finishes. -- For chunk loads, `usr` is generally the current mob of the admin that loaded that chunk. -- For function calls done from the Lua editor, `usr` is the current mob of the admin calling the function. -- `SS13.register_signal` creates a `/datum/callback` that gets executed by the `SEND_SIGNAL` macro for the corresponding signal. As such, `usr` is the mob that triggered the chain of procs leading to the invocation of `SEND_SIGNAL`. +Logically equivalent to the statement `list.Join(glue, start, end)`. ---- +### remove(list: userdata, ...any): integer -## Execution Limit +Logically equivalent to the DM statement `list.Remove(...)`. -In order to prevent freezing the server with infinite loops, auxlua enforces an execution limit, defaulting to 100ms. When a single lua state has been executing for longer than this limit, it will eventually stop and produce an error. +### remove_all(list: userdata, ...any): integer -To avoid exceeding the execution limit, call `sleep()` or `coroutine.yield()` before the execution limit is reached. +Logically equivalent to the DM statement `list.RemoveAll(...)`. -### over_exec_usage(fraction = 0.95) +### splice(list: userdata, start?: integer, end?: integer, ...any): () -This function returns whether the current run of the Lua VM has executed for longer than the specified fraction of the execution limit. You can use this function to branch to a call to `sleep()` or `coroutine.yield()` to maximize the amount of work done in a single run of the Lua VM. If nil, `fraction` will default to 0.95, otherwise, it will be clamped to the range \[0, 1\]. +Logically equivalent to the DM statement `list.Splice(start, end, ...)`. ---- +### swap(list: userdata, index_1: integer, index_2: integer): () -## Task management -The Lua Scripting subsystem manages the execution of tasks for each Lua state. A single fire of the subsystem behaves as follows: -- All tasks that slept since the last fire are resumed in the order they slept. -- For each queued resume, the corresponding task is resumed. +Logically equivalent to the DM statement `list.Swap(index_1, index_2)`. -### sleep() -Yields the current thread, scheduling it to be resumed during the next fire of SSlua. Use this function to prevent your Lua code from exceeding its allowed execution duration. Under the hood, `sleep` performs the following: +### to_table(list: userdata, deep?: boolean): table -- Sets the [`sleep_flag`](#sleep_flag) -- Calls `coroutine.yield()` -- Clears the sleep flag when determining whether the task slept or yielded -- Ignores the return values of `coroutine.yield()` once resumed +Creates a table that is a copy of `list`. If `deep` is true, `to_table` will be called on any lists inside that list. ---- +### from_table(table: table): userdata -## The SS13 package +Creates a list that is a copy of `table`. This is not strictly necessary, as tables are automatically converted to lists when passed back into DM, using the same internal logic as `from_table`. + +### filter(list: userdata, path: string): userdata + +Returns a copy of `list`, containing only elements that are objects descended from `path`. + +## pointer + +The `pointer` module contains utility functions for interacting with pointers. +Keep in mind that passing DM pointers into luau and manipulating them in this way can bypass wrapper procs. + +### read(pointer: userdata): any + +Gets the underlying data the pointer references. + +### write(pointer: userdata, value: any): () + +Writes `value` to the underlying data the pointer references. + +### unwrap(possible_pointer: any): any + +If `possible_pointer` is a pointer, reads it. Otherwise, it is returned as-is. + +# The SS13 package The `SS13` package contains various helper functions that use code specific to tgstation. -### SS13.state +## SS13.state A reference to the state datum (`/datum/lua_state`) handling this Lua state. -### SS13.get_runner_ckey() +## SS13.get_runner_ckey() The ckey of the user who ran the lua script in the current context. Can be unreliable if accessed after sleeping. -### SS13.get_runner_client() +## SS13.get_runner_client() Returns the client of the user who ran the lua script in the current context. Can be unreliable if accessed after sleeping. -### SS13.global_proc +## SS13.global_proc A wrapper for the magic string used to tell `WrapAdminProcCall` to call a global proc. For instance, `/datum/callback` must be instantiated with `SS13.global_proc` as its first argument to specify that it will be invoking a global proc. The following example declares a callback which will execute the global proc `to_chat`: @@ -152,25 +227,18 @@ The following example declares a callback which will execute the global proc `to local callback = SS13.new("/datum/callback", SS13.global_proc, "to_chat", dm.world, "Hello World") ``` -### SS13.istype(thing, type) +## SS13.istype(thing, type) Equivalent to the DM statement `istype(thing, text2path(type))`. -### SS13.new(type, ...) -Instantiates a datum of type `type` with `...` as the arguments passed to `/proc/_new` -The following example spawns a singularity at the caller's current turf: -```lua -SS13.new("/obj/singularity", dm.global_proc("_get_step", dm.usr, 0)) -``` - -### SS13.new_untracked(type, ...) -Works exactly like SS13.new but it does not store the value to the lua state's `references` list variable. This means that the variable could end up deleted if nothing holds a reference to it. +## SS13.new(type, ...) +An alias for `dm.new` -### SS13.is_valid(datum) +## SS13.is_valid(datum) Can be used to determine if the datum passed is not nil, not undefined and not qdel'd all in one. A helper function that allows you to check the validity from only one function. Example usage: ```lua local datum = SS13.new("/datum") -dm.global_proc("qdel", datum) +dm.global_procs.qdel(datum) print(SS13.is_valid(datum)) -- false local null = nil @@ -180,13 +248,13 @@ local datum = SS13.new("/datum") print(SS13.is_valid(datum)) -- true ``` -### SS13.type(string) -Converts a string into a type. Equivalent to doing `dm.global_proc("_text2path", "/path/to/type")` +## SS13.type(string) +Converts a string into a typepath. Equivalent to doing `dm.global_proc("_text2path", "/path/to/type")` -### SS13.qdel(datum) +## SS13.qdel(datum) Deletes a datum. You shouldn't try to reference it after calling this function. Equivalent to doing `dm.global_proc("qdel", datum)` -### SS13.await(thing_to_call, proc_to_call, ...) +## SS13.await(thing_to_call, proc_to_call, ...) Calls `proc_to_call` on `thing_to_call`, with `...` as its arguments, and sleeps until that proc returns. Returns two return values - the first is the return value of the proc, and the second is the message of any runtime exception thrown by the called proc. The following example calls and awaits the return of `poll_ghost_candidates`: @@ -194,59 +262,59 @@ The following example calls and awaits the return of `poll_ghost_candidates`: local ghosts, runtime = SS13.await(SS13.global_proc, "poll_ghost_candidates", "Would you like to be considered for something?") ``` -### SS13.wait(time, timer) +## SS13.wait(time, timer) Waits for a number of **seconds** specified with the `time` argument. You can optionally specify a timer subsystem using the `timer` argument. Internally, this function creates a timer that will resume the current task after `time` seconds, then yields the current task by calling `coroutine.yield` with no arguments and ignores the return values. If the task is prematurely resumed, the timer will be safely deleted. -### SS13.register_signal(datum, signal, func, make_easy_clear_function) +## SS13.register_signal(datum, signal, func) Registers the Lua function `func` as a handler for `signal` on `datum`. Like with signal handlers written in DM, Lua signal handlers should not sleep (either by calling `sleep` or `coroutine.yield`). -If `make_easy_clear_function` is truthy, a member function taking no arguments will be created in the `SS13` table to easily unregister the signal handler. - -This function returns the `/datum/callback` created to call `func` from DM. +This function returns whether the signal registration was successful. The following example defines a function which will register a signal that makes `target` make a honking sound any time it moves: ```lua function honk(target) SS13.register_signal(target, "movable_moved", function(source) - dm.global_proc("playsound", target, "sound/items/bikehorn.ogg", 100, true) + dm.global_procs.playsound(target, "sound/items/bikehorn.ogg", 100, true) end) end ``` -### SS13.unregister_signal(datum, signal, callback) -Unregister a signal previously registered using `SS13.register_signal`. `callback` should be a `datum/callback` previously returned by `SS13.register_signal`. If `callback` is not specified, **ALL** signal handlers registered on `datum` for `signal` will be unregistered. +NOTE: if `func` is an anonymous function declared inside the call to `SS13.register_signal`, it cannot be referenced in order to unregister that signal with `SS13.unregister_signal` -### SS13.set_timeout(time, func) +## SS13.unregister_signal(datum, signal, func) +Unregister a signal previously registered using `SS13.register_signal`. `func` must be a function for which a handler for the specified signal has already been registered. If `func` is `nil`, all handlers for that signal will be unregistered. + +## SS13.set_timeout(time, func) Creates a timer which will execute `func` after `time` **seconds**. `func` should not expect to be passed any arguments, as it will not be passed any. Unlike `SS13.wait`, `SS13.set_timeout` does not yield or sleep the current task, making it suitable for use in signal handlers for `SS13.register_signal` The following example will output a message to chat after 5 seconds: ```lua SS13.set_timeout(5, function() - dm.global_proc("to_chat", dm.world, "Hello World!") + dm.global_procs.to_chat(dm.world, "Hello World!") end) ``` -### SS13.start_loop(time, amount, func) +## SS13.start_loop(time, amount, func) Creates a timer which will execute `func` after `time` **seconds**. `func` should not expect to be passed any arguments, as it will not be passed any. Works exactly the same as `SS13.set_timeout` except it will loop the timer `amount` times. If `amount` is set to -1, it will loop indefinitely. Returns a number value, which represents the timer's id. Can be stopped with `SS13.end_loop` Returns a number, the timer id, which is needed to stop indefinite timers. The following example will output a message to chat every 5 seconds, repeating 10 times: ```lua SS13.start_loop(5, 10, function() - dm.global_proc("to_chat", dm.world, "Hello World!") + dm.global_procs.to_chat(dm.world, "Hello World!") end) ``` The following example will output a message to chat every 5 seconds, until `SS13.end_loop(timerid)` is called: ```lua local timerid = SS13.start_loop(5, -1, function() - dm.global_proc("to_chat", dm.world, "Hello World!") + dm.global_proc.to_chat(dm.world, "Hello World!") end) ``` -### SS13.end_loop(id) +## SS13.end_loop(id) Prematurely ends a loop that hasn't ended yet, created with `SS13.start_loop`. Silently fails if there is no started loop with the specified id. The following example will output a message to chat every 5 seconds and delete it after it has repeated 20 times: ```lua @@ -254,7 +322,7 @@ local repeated_amount = 0 -- timerid won't be in the looping function's scope if declared before the function is declared. local timerid timerid = SS13.start_loop(5, -1, function() - dm.global_proc("to_chat", dm.world, "Hello World!") + dm.global_procs.to_chat(dm.world, "Hello World!") repeated_amount += 1 if repeated_amount >= 20 then SS13.end_loop(timerid) @@ -262,35 +330,6 @@ timerid = SS13.start_loop(5, -1, function() end) ``` -### SS13.stop_all_loops() +## SS13.stop_all_loops() Stops all current running loops that haven't ended yet. Useful in case you accidentally left a indefinite loop running without storing the id anywhere. - -### SS13.stop_tracking(datum) -Stops tracking a datum that was created via `SS13.new` so that it can be garbage collected and deleted without having to qdel. Should be used for things like callbacks and other such datums where the reference to the variable is no longer needed. - ---- - -## Internal globals - -Auxlua defines several registry values for each state. Note that there is no way to access registry values from lua code. - -### sleep_flag - -This flag is used to designate that a yielding task should be put in the sleep queue instead of the yield table. Once auxlua determines that a task should sleep, `sleep_flag` is cleared. - -### sleep_queue - -A sequence of threads, each corresponding to a task that has slept. When calling `/proc/__lua_awaken`, auxlua will dequeue the first thread from the sequence and resume it. - -### yield_table - -A table of threads, each corresponding to a coroutine that has yielded. When calling `/proc/__lua_resume`, auxlua will look for a thread at the index specified in the `index` argument, and resume it with the arguments specified in the `arguments` argument. - -### task_info - -A table of key-value-pairs, where the keys are threads, and the values are tables consisting of the following fields: - -- name: A string containing the name of the task -- status: A string, either "sleep" or "yield" -- index: The task's index in `sleep_queue` or `yield_table` diff --git a/code/modules/admin/verbs/lua/_hooks.dm b/code/modules/admin/verbs/lua/_hooks.dm deleted file mode 100644 index a092947e06ec9c..00000000000000 --- a/code/modules/admin/verbs/lua/_hooks.dm +++ /dev/null @@ -1,239 +0,0 @@ -/datum - var/__auxtools_weakref_id //used by auxtools for weak references - -/** - * Sets a global proc to call in place of just outright setting a datum's var to a given value - * - * The proc will be called with the arguments (datum/datum_to_modify, var_name, value) - * - * required wrapper text the name of the proc to use as the wrapper - */ -/proc/__lua_set_set_var_wrapper(wrapper) - CRASH("auxlua not loaded") - -/** - * Sets a global proc to call in place of just outright calling a given proc on a datum - * - * The proc will be called with the arguments (datum/thing_to_call, proc_to_call, list/arguments) - * - * required wrapper text the name of the proc to use as the wrapper - */ -/proc/__lua_set_datum_proc_call_wrapper(wrapper) - CRASH("auxlua not loaded") - -/** - * Sets a global proc to call in place of just outright calling a given global proc - * - * The proc will be called with the arguments (proc_to_call, list/arguments) - * - * required wrapper text the name of the proc to use as the wrapper - */ -/proc/__lua_set_global_proc_call_wrapper(wrapper) - CRASH("auxlua not loaded") - -/** - * Sets a global proc as a wrapper for lua's print function - * - * The proc will be called with the arguments (state_id, list/arguments) - * - * required wrapper text the name of the proc to use as the wrapper - */ -/proc/__lua_set_print_wrapper(wrapper) - CRASH("auxlua not loaded") - -/** - * Sets the maximum amount of time a lua chunk or function can execute without sleeping or yielding. - * Chunks/functions that exceed this duration will produce an error. - * - * required limit number the execution limit, in milliseconds - */ -/proc/__lua_set_execution_limit(limit) - CRASH("auxlua not loaded") - -/** - * Creates a new lua state. - * - * return text a pointer to the created state. - */ -/proc/__lua_new_state() - CRASH("auxlua not loaded") - -/** - * Loads a chunk of lua source code and executes it - * - * required state text a pointer to the state - * in which to execute the code - * required script text the lua source code to execute - * optional name text a name to give to the chunk - * - * return list|text a list of lua return information - * or an error message if the state was corrupted - * - * Lua return information is formatted as followed: - * - ["status"]: How the chunk or function stopped code execution - * - "sleeping": The chunk or function called dm.sleep, - * placing it in the sleep queue. Items in the sleep - * queue can be resumed using /proc/__lua_awaken - * - "yielded": The chunk or function called coroutine.yield, - * placing it in the yield table. Items in the yield - * table can can be resumed by passing their index - * to /proc/__lua_resume - * - "finished": The chunk or function finished - * - "errored": The chunk or function produced an error - * - "bad return": The chunk or function yielded or finished, - * but its return value could not be converted to DM values - * - ["param"]: Depends on status. - * - "sleeping": null - * - "yielded" or "finished": The return/yield value(s) - * - "errored" or "bad return": The error message - * - ["yield_index"]: The index in the yield table where the - * chunk or function is located, for calls to __lua_resume - * - ["name"]: The name of the chunk or function, for logging - */ -/proc/__lua_load(state, script, name) - CRASH("auxlua not loaded") - -/** - * Calls a lua function - * - * required state text a pointer to the state - * in which to call the function - * required function text the name of the function to call - * optional arguments list arguments to pass to the function - * - * return list|text a list of lua return information - * or an error message if the state was corrupted - * - * Lua return information is formatted as followed: - * - ["status"]: How the chunk or function stopped code execution - * - "sleeping": The chunk or function called dm.sleep, - * placing it in the sleep queue. Items in the sleep - * queue can be resumed using /proc/__lua_awaken - * - "yielded": The chunk or function called coroutine.yield, - * placing it in the yield table. Items in the yield - * table can can be resumed by passing their index - * to /proc/__lua_resume - * - "finished": The chunk or function finished - * - "errored": The chunk or function produced an error - * - "bad return": The chunk or function yielded or finished, - * but its return value could not be converted to DM values - * - ["param"]: Depends on status. - * - "sleeping": null - * - "yielded" or "finished": The return/yield value(s) - * - "errored" or "bad return": The error message - * - ["yield_index"]: The index in the yield table where the - * chunk or function is located, for calls to __lua_resume - * - ["name"]: The name of the chunk or function, for logging - */ -/proc/__lua_call(state, function, arguments) - CRASH("auxlua not loaded") - -/** - * Dequeues the task at the front of the sleep queue and resumes it - * - * required state text a pointer to the state in which - * to resume a task - * - * return list|text|null a list of lua return information, - * an error message if the state is corrupted, - * or null if the sleep queue is empty - * - * Lua return information is formatted as followed: - * - ["status"]: How the chunk or function stopped code execution - * - "sleeping": The chunk or function called dm.sleep, - * placing it in the sleep queue. Items in the sleep - * queue can be resumed using /proc/__lua_awaken - * - "yielded": The chunk or function called coroutine.yield, - * placing it in the yield table. Items in the yield - * table can can be resumed by passing their index - * to /proc/__lua_resume - * - "finished": The chunk or function finished - * - "errored": The chunk or function produced an error - * - "bad return": The chunk or function yielded or finished, - * but its return value could not be converted to DM values - * - ["param"]: Depends on status. - * - "sleeping": null - * - "yielded" or "finished": The return/yield value(s) - * - "errored" or "bad return": The error message - * - ["yield_index"]: The index in the yield table where the - * chunk or function is located, for calls to __lua_resume - * - ["name"]: The name of the chunk or function, for logging - */ -/proc/__lua_awaken(state) - CRASH("auxlua not loaded") - -/** - * Removes the task at the specified index from the yield table - * and resumes it - * - * required state text a pointer to the state in which to - * resume a task - * required index number the index in the yield table of the - * task to resume - * optional arguments list the arguments to resume the task with - * - * return list|text|null a list of lua return information, - * an error message if the state is corrupted, - * or null if there is no task at the specified index - * - * Lua return information is formatted as followed: - * - ["status"]: How the chunk or function stopped code execution - * - "sleeping": The chunk or function called dm.sleep, - * placing it in the sleep queue. Items in the sleep - * queue can be resumed using /proc/__lua_awaken - * - "yielded": The chunk or function called coroutine.yield, - * placing it in the yield table. Items in the yield - * table can can be resumed by passing their index - * to /proc/__lua_resume - * - "finished": The chunk or function finished - * - "errored": The chunk or function produced an error - * - "bad return": The chunk or function yielded or finished, - * but its return value could not be converted to DM values - * - ["param"]: Depends on status. - * - "sleeping": null - * - "yielded" or "finished": The return/yield value(s) - * - "errored" or "bad return": The error message - * - ["yield_index"]: The index in the yield table where the - * chunk or function is located, for calls to __lua_resume - * - ["name"]: The name of the chunk or function, for logging - */ -/proc/__lua_resume(state, index, arguments) - CRASH("auxlua not loaded") - -/** - * Get the variables within a state's environment. - * Values not convertible to DM values are substituted - * for their types as text - * - * required state text a pointer to the state - * to get the variables from - * - * return list the variables of the state's environment - */ -/proc/__lua_get_globals(state) - CRASH("auxlua not loaded") - -/** - * Get a list of all tasks currently in progress within a state - * - * required state text a pointer to the state - * to get the tasks from - * - * return list a list of the state's tasks, formatted as follows: - * - name: The name of the task - * - status: Whether the task is sleeping or yielding - * - index: The index of the task in the sleep queue - * or yield table, whichever is applicable - */ -/proc/__lua_get_tasks(state) - CRASH("auxlua not loaded") - -/** - * Kills a task in progress - * - * required state text a pointer to the state - * in which to kill a task - * required info list the task info - */ -/proc/__lua_kill_task(state, info) - CRASH("auxlua not loaded") diff --git a/code/modules/admin/verbs/lua/_wrappers.dm b/code/modules/admin/verbs/lua/_wrappers.dm index 8e05453d29d5d2..d516f064f847fa 100644 --- a/code/modules/admin/verbs/lua/_wrappers.dm +++ b/code/modules/admin/verbs/lua/_wrappers.dm @@ -1,3 +1,12 @@ +/proc/wrap_lua_get_var(datum/thing, var_name) + SHOULD_NOT_SLEEP(TRUE) + if(thing == world) + return world.vars[var_name] + if(ref(thing) == "\[0xe000001\]") //This weird fucking thing is like global.vars, but it's not a list and vars is not a valid index for it and I really don't fucking know. + return global.vars[var_name] + if(thing.can_vv_get(var_name)) + return thing.vars[var_name] + /proc/wrap_lua_set_var(datum/thing_to_set, var_name, value) SHOULD_NOT_SLEEP(TRUE) thing_to_set.vv_edit_var(var_name, value) @@ -11,8 +20,6 @@ ret = WrapAdminProcCall(thing_to_call, proc_name, arguments) else ret = HandleUserlessProcCall("lua", thing_to_call, proc_name, arguments) - if(isdatum(ret)) - SSlua.gc_guard += ret return ret /proc/wrap_lua_global_proc_call(proc_name, list/arguments) @@ -24,8 +31,6 @@ ret = WrapAdminProcCall(GLOBAL_PROC, proc_name, arguments) else ret = HandleUserlessProcCall("lua", GLOBAL_PROC, proc_name, arguments) - if(isdatum(ret)) - SSlua.gc_guard += ret return ret /proc/wrap_lua_print(state_id, list/arguments) @@ -38,6 +43,6 @@ if(!target_state) return var/print_message = jointext(arguments, "\t") - var/result = list("status" = "print", "param" = print_message) + var/result = list("status" = "print", "message" = print_message) INVOKE_ASYNC(target_state, TYPE_PROC_REF(/datum/lua_state, log_result), result, TRUE) log_lua("[target_state]: [print_message]") diff --git a/code/modules/admin/verbs/lua/helpers.dm b/code/modules/admin/verbs/lua/helpers.dm index 66b7c835e9ab15..c3072f15e74cda 100644 --- a/code/modules/admin/verbs/lua/helpers.dm +++ b/code/modules/admin/verbs/lua/helpers.dm @@ -3,27 +3,27 @@ #define PROMISE_REJECTED 2 /** - * Auxtools hooks act as "set waitfor = 0" procs. This means that whenever - * a proc directly called from auxtools sleeps, the hook returns with whatever + * Byondapi hooks act as "set waitfor = 0" procs. This means that whenever + * a proc directly called from an external library sleeps, the hook returns with whatever * the called proc had as its return value at the moment it slept. This may not * be desired behavior, so this datum exists to wrap these procs. * * Some procs that don't sleep could take longer than the execution limit would * allow for. We can wrap these in a promise as well. */ -/datum/auxtools_promise +/datum/promise var/datum/callback/callback var/return_value var/runtime_message var/status = PROMISE_PENDING -/datum/auxtools_promise/New(...) +/datum/promise/New(...) + if(!usr) + usr = GLOB.lua_usr callback = CALLBACK(arglist(args)) - perform() + INVOKE_ASYNC(src, PROC_REF(perform)) -/datum/auxtools_promise/proc/perform() - set waitfor = 0 - sleep() //In case we have to call a super-expensive non-sleeping proc (like getFlatIcon) +/datum/promise/proc/perform() try return_value = callback.Invoke() status = PROMISE_RESOLVED diff --git a/code/modules/admin/verbs/lua/lua_editor.dm b/code/modules/admin/verbs/lua/lua_editor.dm index d4a4bc2ee50b7b..a28ae8b40f19bf 100644 --- a/code/modules/admin/verbs/lua/lua_editor.dm +++ b/code/modules/admin/verbs/lua/lua_editor.dm @@ -16,6 +16,12 @@ /// If set, we will force the editor to look at this chunk var/force_view_chunk + /// If set, we will force the script input to be this + var/force_input + + /// If set, the latest code execution performed from the editor raised an error, and this is the message from that error + var/last_error + /datum/lua_editor/New(state, _quick_log_index) . = ..() if(state) @@ -37,37 +43,52 @@ /datum/lua_editor/ui_state(mob/user) return GLOB.debug_state -/datum/lua_editor/ui_static_data(mob/user) - var/list/data = list() - data["documentation"] = file2text('code/modules/admin/verbs/lua/README.md') - data["auxtools_enabled"] = CONFIG_GET(flag/auxtools_enabled) - data["ss_lua_init"] = SSlua.initialized - return data - /datum/lua_editor/ui_data(mob/user) var/list/data = list() - if(!CONFIG_GET(flag/auxtools_enabled) || !SSlua.initialized) + data["ss_lua_init"] = SSlua.initialized + if(!SSlua.initialized) return data data["noStateYet"] = !current_state data["showGlobalTable"] = show_global_table if(current_state) if(current_state.log) - data["stateLog"] = kvpify_list(refify_list(current_state.log.Copy((page*50)+1, min((page+1)*50+1, current_state.log.len+1)))) + var/list/logs = current_state.log.Copy((page*50)+1, min((page+1)*50+1, current_state.log.len+1)) + for(var/i in 1 to logs.len) + var/list/log = logs[i] + log = log.Copy() + if(log["return_values"]) + log["return_values"] = kvpify_list(prepare_lua_editor_list(deep_copy_without_cycles(log["return_values"]))) + logs[i] = log + data["stateLog"] = logs data["page"] = page data["pageCount"] = CEILING(current_state.log.len/50, 1) data["tasks"] = current_state.get_tasks() if(show_global_table) current_state.get_globals() - data["globals"] = kvpify_list(refify_list(current_state.globals)) - data["states"] = SSlua.states - data["callArguments"] = kvpify_list(refify_list(arguments)) + var/list/values = current_state.globals["values"] + values = deep_copy_without_cycles(values) + values = prepare_lua_editor_list(values) + values = kvpify_list(values) + var/list/variants = current_state.globals["variants"] + data["globals"] = list("values" = values, "variants" = variants) + if(last_error) + data["lastError"] = last_error + last_error = null + data["supressRuntimes"] = current_state.supress_runtimes + data["states"] = list() + for(var/datum/lua_state/state as anything in SSlua.states) + data["states"] += state.display_name + data["callArguments"] = kvpify_list(prepare_lua_editor_list(deep_copy_without_cycles(arguments))) if(force_modal) data["forceModal"] = force_modal force_modal = null if(force_view_chunk) data["forceViewChunk"] = force_view_chunk force_view_chunk = null + if(force_input) + data["force_input"] = force_input + force_input = null return data /datum/lua_editor/proc/traverse_list(list/path, list/root, traversal_depth_offset = 0) @@ -99,6 +120,15 @@ else return root +/datum/lua_editor/proc/run_code(code) + var/ckey = usr.ckey + current_state.ckey_last_runner = ckey + var/result = current_state.load_script(code) + var/index_with_result = current_state.log_result(result) + if(result["status"] == "error") + last_error = result["message"] + message_admins("[key_name(usr)] executed [length(code)] bytes of lua code. [ADMIN_LUAVIEW_CHUNK(current_state, index_with_result)]") + /datum/lua_editor/ui_act(action, list/params) . = ..() if(.) @@ -116,6 +146,8 @@ if(!length(state_name)) return TRUE var/datum/lua_state/new_state = new(state_name) + if(QDELETED(new_state)) + return SSlua.states += new_state LAZYREMOVEASSOC(SSlua.editors, text_ref(current_state), src) current_state = new_state @@ -130,11 +162,14 @@ page = 0 return TRUE if("runCode") - var/code = params["code"] - current_state.ckey_last_runner = usr.ckey - var/result = current_state.load_script(code) - var/index_with_result = current_state.log_result(result) - message_admins("[key_name(usr)] executed [length(code)] bytes of lua code. [ADMIN_LUAVIEW_CHUNK(current_state, index_with_result)]") + run_code(params["code"]) + return TRUE + if("runFile") + var/code_file = input(usr, "Select a script to run.", "Lua") as file|null + if(!code_file) + return TRUE + var/code = file2text(code_file) + run_code(code) return TRUE if("moveArgUp") var/list/path = params["path"] @@ -168,49 +203,54 @@ return TRUE if("callFunction") var/list/recursive_indices = params["indices"] - var/list/current_list = kvpify_list(current_state.globals) + var/list/current_list = kvpify_list(current_state.globals["values"]) + var/list/current_variants = current_state.globals["variants"] var/function = list() while(LAZYLEN(recursive_indices)) var/index = popleft(recursive_indices) var/list/element = current_list[index] var/key = element["key"] var/value = element["value"] - if(!(istext(key) || isnum(key))) - to_chat(usr, span_warning("invalid key \[[key]] for function call (expected text or num)")) + var/list/variant_pair = current_variants[index] + var/key_variant = variant_pair["key"] + if(key_variant == "function" || key_variant == "thread" || key_variant == "userdata" || key_variant == "error_as_value") + to_chat(usr, span_warning("invalid table key \[[key]] for function call (expected text, num, path, list, or ref, got [key_variant])")) return function += key if(islist(value)) current_list = value + current_variants = variant_pair["value"] else - var/regex/function_regex = regex("^function: 0x\[0-9a-fA-F]+$") - if(function_regex.Find(value)) - break - to_chat(usr, span_warning("invalid path element \[[value]] for function call (expected list or text matching [function_regex])")) - return + if(variant_pair["value"] != "function") + to_chat(usr, span_warning("invalid value \[[value]] for function call (expected list or function)")) + return var/result = current_state.call_function(arglist(list(function) + arguments)) current_state.log_result(result) + if(result["status"] == "error") + last_error = result["message"] arguments.Cut() - return TRUE + return if("resumeTask") var/task_index = params["index"] SSlua.queue_resume(current_state, task_index, arguments) arguments.Cut() return TRUE if("killTask") - var/task_info = params["info"] - SSlua.kill_task(current_state, task_info) + var/is_sleep = params["is_sleep"] + var/index = params["index"] + SSlua.kill_task(current_state, is_sleep, index) return TRUE if("vvReturnValue") var/log_entry_index = params["entryIndex"] var/list/log_entry = current_state.log[log_entry_index] - var/thing_to_debug = traverse_list(params["tableIndices"], log_entry["param"]) + var/thing_to_debug = traverse_list(params["indices"], log_entry["return_values"]) if(isweakref(thing_to_debug)) var/datum/weakref/ref = thing_to_debug thing_to_debug = ref.resolve() INVOKE_ASYNC(usr.client, TYPE_PROC_REF(/client, debug_variables), thing_to_debug) return FALSE if("vvGlobal") - var/thing_to_debug = traverse_list(params["indices"], current_state.globals) + var/thing_to_debug = traverse_list(params["indices"], current_state.globals["values"]) if(isweakref(thing_to_debug)) var/datum/weakref/ref = thing_to_debug thing_to_debug = ref.resolve() @@ -222,12 +262,18 @@ if("toggleShowGlobalTable") show_global_table = !show_global_table return TRUE + if("toggleSupressRuntimes") + current_state.supress_runtimes = !current_state.supress_runtimes + return TRUE if("nextPage") page = min(page+1, CEILING(current_state.log.len/50, 1)-1) return TRUE if("previousPage") page = max(page-1, 0) return TRUE + if("nukeLog") + current_state.log.Cut() + return TRUE /datum/lua_editor/ui_close(mob/user) . = ..() diff --git a/code/modules/admin/verbs/lua/lua_state.dm b/code/modules/admin/verbs/lua/lua_state.dm index bf2bcbd5a90030..577b0e365c2d8c 100644 --- a/code/modules/admin/verbs/lua/lua_state.dm +++ b/code/modules/admin/verbs/lua/lua_state.dm @@ -1,15 +1,15 @@ #define MAX_LOG_REPEAT_LOOKBACK 5 -GLOBAL_VAR_INIT(IsLuaCall, FALSE) -GLOBAL_PROTECT(IsLuaCall) - GLOBAL_DATUM(lua_usr, /mob) GLOBAL_PROTECT(lua_usr) +GLOBAL_LIST_EMPTY_TYPED(lua_state_stack, /datum/weakref) +GLOBAL_PROTECT(lua_state_stack) + /datum/lua_state - var/name + var/display_name - /// The internal ID of the lua state stored in auxlua's global map + /// The internal ID of the lua state stored in dreamluau's state list var/internal_id /// A log of every return, yield, and error for each chunk execution and function call @@ -18,15 +18,15 @@ GLOBAL_PROTECT(lua_usr) /// A list of all the variables in the state's environment var/list/globals = list() - /// A list in which to store datums and lists instantiated in lua, ensuring that they don't get garbage collected - var/list/references = list() - /// Ckey of the last user who ran a script on this lua state. var/ckey_last_runner = "" /// Whether the timer.lua script has been included into this lua context state. var/timer_enabled = FALSE + /// Whether to supress logging BYOND runtimes for this state. + var/supress_runtimes = FALSE + /// Callbacks that need to be ran on next tick var/list/functions_to_execute = list() @@ -39,55 +39,67 @@ GLOBAL_PROTECT(lua_usr) if(SSlua.initialized != TRUE) qdel(src) return - name = _name - internal_id = __lua_new_state() + display_name = _name + internal_id = DREAMLUAU_NEW_STATE() + if(!isnum(internal_id)) + stack_trace(internal_id) + qdel(src) /datum/lua_state/proc/check_if_slept(result) - if(result["status"] == "sleeping") + if(result["status"] == "sleep") SSlua.sleeps += src /datum/lua_state/proc/log_result(result, verbose = TRUE) if(!islist(result)) return - if(!verbose && result["status"] != "errored" && result["status"] != "bad return" \ - && !(result["name"] == "input" && (result["status"] == "finished" || length(result["param"])))) + var/status = result["status"] + if(!verbose && status != "error" && status != "panic" && status != "runtime" && !(result["name"] == "input" && (status == "finished" || length(result["return_values"])))) + return + if(status == "runtime" && supress_runtimes) return var/append_to_log = TRUE var/index_of_log if(log.len) for(var/index in log.len to max(log.len - MAX_LOG_REPEAT_LOOKBACK, 1) step -1) var/list/entry = log[index] - if(entry["status"] == result["status"] \ - && entry["chunk"] == result["chunk"] \ - && entry["name"] == result["name"] \ - && ((entry["param"] == result["param"]) || deep_compare_list(entry["param"], result["param"]))) - if(!entry["repeats"]) - entry["repeats"] = 0 - index_of_log = index - entry["repeats"]++ - append_to_log = FALSE - break + if(!compare_lua_logs(entry, result)) + continue + if(!entry["repeats"]) + entry["repeats"] = 0 + index_of_log = index + entry["repeats"]++ + append_to_log = FALSE + break if(append_to_log) - if(islist(result["param"])) - result["param"] = weakrefify_list(encode_text_and_nulls(result["param"])) + if(islist(result["return_values"])) + add_lua_return_value_variants(result["return_values"], result["variants"]) + result["return_values"] = weakrefify_list(result["return_values"]) log += list(result) index_of_log = log.len INVOKE_ASYNC(src, TYPE_PROC_REF(/datum/lua_state, update_editors)) return index_of_log +/datum/lua_state/proc/parse_error(message, name) + if(copytext(message, 1, 7) == "PANIC:") + return list("status" = "panic", "message" = copytext(message, 7), "name" = name) + else + return list("status" = "error", "message" = message, "name" = name) + /datum/lua_state/proc/load_script(script) - GLOB.IsLuaCall = TRUE var/tmp_usr = GLOB.lua_usr GLOB.lua_usr = usr - var/result = __lua_load(internal_id, script) - GLOB.IsLuaCall = FALSE + DREAMLUAU_SET_USR + GLOB.lua_state_stack += WEAKREF(src) + var/result = DREAMLUAU_LOAD(internal_id, script, "input") + SSlua.needs_gc_cycle |= src + pop(GLOB.lua_state_stack) GLOB.lua_usr = tmp_usr // Internal errors unrelated to the code being executed are returned as text rather than lists if(isnull(result)) - result = list("status" = "errored", "param" = "__lua_load returned null (it may have runtimed - check the runtime logs)", "name" = "input") + result = list("status" = "error", "message" = "load returned null (it may have runtimed - check the runtime logs)", "name" = "input") if(istext(result)) - result = list("status" = "errored", "param" = result, "name" = "input") + result = parse_error(result, "input") result["chunk"] = script check_if_slept(result) @@ -109,67 +121,106 @@ GLOBAL_PROTECT(lua_usr) if(islist(function)) var/list/new_function_path = list() for(var/path_element in function) - new_function_path += path_element + if(isweakref(path_element)) + var/datum/weakref/weak_ref = path_element + var/resolved = weak_ref.hard_resolve() + if(!resolved) + return list("status" = "error", "message" = "Weakref in function path ([weak_ref] [text_ref(weak_ref)]) resolved to null.", "name" = jointext(function, ".")) + new_function_path += resolved + else + new_function_path += path_element function = new_function_path + else + function = list(function) var/tmp_usr = GLOB.lua_usr GLOB.lua_usr = usr - GLOB.IsLuaCall = TRUE - var/result = __lua_call(internal_id, function, call_args) - GLOB.IsLuaCall = FALSE + DREAMLUAU_SET_USR + GLOB.lua_state_stack += WEAKREF(src) + var/result = DREAMLUAU_CALL_FUNCTION(internal_id, function, call_args) + SSlua.needs_gc_cycle |= src + pop(GLOB.lua_state_stack) GLOB.lua_usr = tmp_usr if(isnull(result)) - result = list("status" = "errored", "param" = "__lua_call returned null (it may have runtimed - check the runtime logs)", "name" = islist(function) ? jointext(function, ".") : function) + result = list("status" = "error", "message" = "call_function returned null (it may have runtimed - check the runtime logs)", "name" = jointext(function, ".")) if(istext(result)) - result = list("status" = "errored", "param" = result, "name" = islist(function) ? jointext(function, ".") : function) + result = parse_error(result, jointext(function, ".")) check_if_slept(result) return result /datum/lua_state/proc/call_function_return_first(function, ...) + SHOULD_NOT_SLEEP(TRUE) // This function is meant to be used for signal handlers. var/list/result = call_function(arglist(args)) - log_result(result, verbose = FALSE) + INVOKE_ASYNC(src, PROC_REF(log_result), deep_copy_list(result), /*verbose = */FALSE) if(length(result)) - if(islist(result["param"]) && length(result["param"])) - return result["param"][1] + if(islist(result["return_values"]) && length(result["return_values"])) + var/return_value = result["return_values"][1] + var/variant = (islist(result["variants"]) && length(result["variants"])) && result["variants"][1] + if(islist(return_value) && islist(variant)) + remove_non_dm_variants(return_value, variant) + return return_value /datum/lua_state/proc/awaken() - GLOB.IsLuaCall = TRUE - var/result = __lua_awaken(internal_id) - GLOB.IsLuaCall = FALSE + DREAMLUAU_SET_USR + GLOB.lua_state_stack += WEAKREF(src) + var/result = DREAMLUAU_AWAKEN(internal_id) + SSlua.needs_gc_cycle |= src + pop(GLOB.lua_state_stack) if(isnull(result)) - result = list("status" = "errored", "param" = "__lua_awaken returned null (it may have runtimed - check the runtime logs)", "name" = "An attempted awaken") + result = list("status" = "error", "message" = "awaken returned null (it may have runtimed - check the runtime logs)", "name" = "An attempted awaken") if(istext(result)) - result = list("status" = "errored", "param" = result, "name" = "An attempted awaken") + result = parse_error(result, "An attempted awaken") check_if_slept(result) return result /// Prefer calling SSlua.queue_resume over directly calling this /datum/lua_state/proc/resume(index, ...) var/call_args = length(args) > 1 ? args.Copy(2) : list() - var/msg = "[key_name(usr)] resumed a lua coroutine with arguments: [english_list(call_args)]" - log_lua(msg) - GLOB.IsLuaCall = TRUE - var/result = __lua_resume(internal_id, index, call_args) - GLOB.IsLuaCall = FALSE + DREAMLUAU_SET_USR + GLOB.lua_state_stack += WEAKREF(src) + var/result = DREAMLUAU_RESUME(internal_id, index, call_args) + SSlua.needs_gc_cycle |= src + pop(GLOB.lua_state_stack) if(isnull(result)) - result = list("status" = "errored", "param" = "__lua_resume returned null (it may have runtimed - check the runtime logs)", "name" = "An attempted resume") + result = list("status" = "error", "param" = "resume returned null (it may have runtimed - check the runtime logs)", "name" = "An attempted resume") if(istext(result)) - result = list("status" = "errored", "param" = result, "name" = "An attempted resume") + result = parse_error(result, "An attempted resumt") check_if_slept(result) return result /datum/lua_state/proc/get_globals() - globals = weakrefify_list(encode_text_and_nulls(__lua_get_globals(internal_id))) + var/result = DREAMLUAU_GET_GLOBALS(internal_id) + if(isnull(result)) + CRASH("get_globals returned null") + if(istext(result)) + CRASH(result) + var/list/new_globals = result + var/list/values = new_globals["values"] + var/list/variants = new_globals["variants"] + add_lua_editor_variants(values, variants) + globals = list("values" = weakrefify_list(values), "variants" = variants) /datum/lua_state/proc/get_tasks() - return __lua_get_tasks(internal_id) + var/result = DREAMLUAU_LIST_THREADS(internal_id) + if(isnull(result)) + CRASH("list_threads returned null") + if(istext(result)) + CRASH(result) + return result + +/datum/lua_state/proc/kill_task(is_sleep, index) + var/result = is_sleep ? DREAMLUAU_KILL_SLEEPING_THREAD(internal_id, index) : DREAMLUAU_KILL_YIELDED_THREAD(internal_id, index) + SSlua.needs_gc_cycle |= src + return result -/datum/lua_state/proc/kill_task(task_info) - __lua_kill_task(internal_id, task_info) +/datum/lua_state/proc/collect_garbage() + var/result = DREAMLUAU_COLLECT_GARBAGE(internal_id) + if(!isnull(result)) + CRASH(result) /datum/lua_state/proc/update_editors() var/list/editor_list = LAZYACCESS(SSlua.editors, text_ref(src)) @@ -177,18 +228,4 @@ GLOBAL_PROTECT(lua_usr) for(var/datum/lua_editor/editor as anything in editor_list) SStgui.update_uis(editor) -/// Called by lua scripts when they add an atom to var/list/references so that it gets cleared up on delete. -/datum/lua_state/proc/clear_on_delete(datum/to_clear) - RegisterSignal(to_clear, COMSIG_QDELETING, PROC_REF(on_delete)) - -/// Called by lua scripts when an atom they've added should soft delete and this state should stop tracking it. -/// Needs to unregister all signals. -/datum/lua_state/proc/let_soft_delete(datum/to_clear) - UnregisterSignal(to_clear, COMSIG_QDELETING, PROC_REF(on_delete)) - references -= to_clear - -/datum/lua_state/proc/on_delete(datum/to_clear) - SIGNAL_HANDLER - references -= to_clear - #undef MAX_LOG_REPEAT_LOOKBACK diff --git a/code/modules/antagonists/clown_ops/clown_weapons.dm b/code/modules/antagonists/clown_ops/clown_weapons.dm index 130b6c9af5f1b2..1e566b7d1975e1 100644 --- a/code/modules/antagonists/clown_ops/clown_weapons.dm +++ b/code/modules/antagonists/clown_ops/clown_weapons.dm @@ -192,7 +192,7 @@ //BOMBANANA /obj/item/seeds/banana/bombanana - name = "pack of bombanana seeds" + name = "bombanana seed pack" desc = "They're seeds that grow into bombanana trees. When grown, give to the clown." plantname = "Bombanana Tree" product = /obj/item/food/grown/banana/bombanana diff --git a/code/modules/antagonists/heretic/heretic_knowledge.dm b/code/modules/antagonists/heretic/heretic_knowledge.dm index 16c8bde219c8ef..6cab0922800009 100644 --- a/code/modules/antagonists/heretic/heretic_knowledge.dm +++ b/code/modules/antagonists/heretic/heretic_knowledge.dm @@ -640,7 +640,6 @@ /obj/item/restraints/handcuffs/cable/zipties, /obj/item/circular_saw, /obj/item/scalpel, - /obj/item/binoculars, /obj/item/clothing/gloves/color/yellow, /obj/item/melee/baton/security, /obj/item/clothing/glasses/sunglasses, diff --git a/code/modules/antagonists/heretic/knowledge/ash_lore.dm b/code/modules/antagonists/heretic/knowledge/ash_lore.dm index b74569f1a14478..957a78a27269cd 100644 --- a/code/modules/antagonists/heretic/knowledge/ash_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/ash_lore.dm @@ -1,7 +1,5 @@ /** * # The path of Ash. - * Spell names are in this language: OLD NORDIC - * Both are related: Nordic Mythology-Yggdrassil-Ash Tree Genus-Ash * * Goes as follows: * @@ -233,7 +231,7 @@ text = "[generate_heretic_text()] Fear the blaze, for the Ashlord, [user.real_name] has ascended! The flames shall consume all! [generate_heretic_text()]", title = "[generate_heretic_text()]", sound = 'sound/ambience/antag/heretic/ascend_ash.ogg', - color_override = "white", + color_override = "pink", ) var/datum/action/cooldown/spell/fire_sworn/circle_spell = new(user.mind) diff --git a/code/modules/antagonists/heretic/knowledge/blade_lore.dm b/code/modules/antagonists/heretic/knowledge/blade_lore.dm index 357e789416d1dd..de79151739f4b5 100644 --- a/code/modules/antagonists/heretic/knowledge/blade_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/blade_lore.dm @@ -1,7 +1,5 @@ /** * # The path of Blades. Stab stab. - * Spell names are in this language: ARAMAIC - * Both are related: Aramaic-Damascus-Blade * * Goes as follows: * diff --git a/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm b/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm index 8a94aada74a67a..a3e7576132036c 100644 --- a/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/cosmic_lore.dm @@ -1,7 +1,5 @@ /** * # The path of Cosmos. - * Spell names are in this language: SUMERIAN - * Both are related: Sumerian-Original-Primordial-Cosmic * * Goes as follows: * @@ -285,7 +283,7 @@ text = "[generate_heretic_text()] A Star Gazer has arrived into the station, [user.real_name] has ascended! This station is the domain of the Cosmos! [generate_heretic_text()]", title = "[generate_heretic_text()]", sound = 'sound/ambience/antag/heretic/ascend_cosmic.ogg', - color_override = "purple", + color_override = "pink", ) var/mob/living/basic/heretic_summon/star_gazer/star_gazer_mob = new /mob/living/basic/heretic_summon/star_gazer(loc) star_gazer_mob.maxHealth = INFINITY diff --git a/code/modules/antagonists/heretic/knowledge/flesh_lore.dm b/code/modules/antagonists/heretic/knowledge/flesh_lore.dm index e0b82651bc9d6f..a1786189d99c07 100644 --- a/code/modules/antagonists/heretic/knowledge/flesh_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/flesh_lore.dm @@ -5,8 +5,6 @@ /** * # The path of Flesh. - * Spell names are in this language: LATIN - * Both are related: Latin-Rome-Hedonism-Flesh * * Goes as follows: * @@ -332,7 +330,7 @@ text = "[generate_heretic_text()] Ever coiling vortex. Reality unfolded. ARMS OUTREACHED, THE LORD OF THE NIGHT, [user.real_name] has ascended! Fear the ever twisting hand! [generate_heretic_text()]", title = "[generate_heretic_text()]", sound = 'sound/ambience/antag/heretic/ascend_flesh.ogg', - color_override = "red", + color_override = "pink", ) var/datum/action/cooldown/spell/shapeshift/shed_human_form/worm_spell = new(user.mind) diff --git a/code/modules/antagonists/heretic/knowledge/lock_lore.dm b/code/modules/antagonists/heretic/knowledge/lock_lore.dm index b238d6dd3c7f3a..17e73cb162c175 100644 --- a/code/modules/antagonists/heretic/knowledge/lock_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/lock_lore.dm @@ -1,7 +1,5 @@ /** * # The path of Lock. - * Spell names are in this language: EGYPTIAN - * Both are related: Egyptian-Mysteries-Secrets-Lock * * Goes as follows: * @@ -243,7 +241,7 @@ text = "Delta-class dimensional anomaly detec[generate_heretic_text()] Reality rended, torn. Gates open, doors open, [user.real_name] has ascended! Fear the tide! [generate_heretic_text()]", title = "[generate_heretic_text()]", sound = 'sound/ambience/antag/heretic/ascend_knock.ogg', - color_override = "yellow", + color_override = "pink", ) // buffs diff --git a/code/modules/antagonists/heretic/knowledge/moon_lore.dm b/code/modules/antagonists/heretic/knowledge/moon_lore.dm index 5ba55b64058cb5..917944d30fe951 100644 --- a/code/modules/antagonists/heretic/knowledge/moon_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/moon_lore.dm @@ -1,7 +1,5 @@ /** * # The path of Moon. - * Spell names are in this language: ANCIENT HEBREW - * Both are related: Ancient Hebrew-Moon Mysticism-Moon * * Goes as follows: * @@ -211,7 +209,7 @@ The truth shall finally devour the lie! [generate_heretic_text()]", title = "[generate_heretic_text()]", sound = 'sound/ambience/antag/heretic/ascend_moon.ogg', - color_override = "blue", + color_override = "pink", ) ADD_TRAIT(user, TRAIT_MADNESS_IMMUNE, REF(src)) diff --git a/code/modules/antagonists/heretic/knowledge/rust_lore.dm b/code/modules/antagonists/heretic/knowledge/rust_lore.dm index fe0d03ec18f50e..3a081c8d295fbb 100644 --- a/code/modules/antagonists/heretic/knowledge/rust_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/rust_lore.dm @@ -1,6 +1,5 @@ /** * # The path of Rust. - * Spell names are in this language: OLD SLAVIC * * Goes as follows: * @@ -257,7 +256,7 @@ text = "[generate_heretic_text()] Fear the decay, for the Rustbringer, [user.real_name] has ascended! None shall escape the corrosion! [generate_heretic_text()]", title = "[generate_heretic_text()]", sound = 'sound/ambience/antag/heretic/ascend_rust.ogg', - color_override = "brown", + color_override = "pink", ) trigger(loc) RegisterSignal(user, COMSIG_MOVABLE_MOVED, PROC_REF(on_move)) diff --git a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_map.dm b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_map.dm index bc6cb750b219a1..2952eb1daed8c6 100644 --- a/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_map.dm +++ b/code/modules/antagonists/heretic/knowledge/sacrifice_knowledge/sacrifice_map.dm @@ -87,7 +87,7 @@ GLOBAL_LIST_EMPTY(heretic_sacrifice_landmarks) has_gravity = STANDARD_GRAVITY ambience_index = AMBIENCE_SPOOKY sound_environment = SOUND_ENVIRONMENT_CAVE - area_flags = UNIQUE_AREA | NOTELEPORT | HIDDEN_AREA | BLOCK_SUICIDE + area_flags = UNIQUE_AREA | NOTELEPORT | HIDDEN_AREA | BLOCK_SUICIDE | NO_BOH /area/centcom/heretic_sacrifice/Initialize(mapload) if(!ambientsounds) diff --git a/code/modules/antagonists/heretic/knowledge/starting_lore.dm b/code/modules/antagonists/heretic/knowledge/starting_lore.dm index 7cb3b82a39ac21..4e5e2910e0ef9a 100644 --- a/code/modules/antagonists/heretic/knowledge/starting_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/starting_lore.dm @@ -1,5 +1,4 @@ // Heretic starting knowledge. -// Default heretic language is Ancient Greek, because, uh, they're like ancient and shit. /// Global list of all heretic knowledge that have route = PATH_START. List of PATHS. GLOBAL_LIST_INIT(heretic_start_knowledge, initialize_starting_knowledge()) diff --git a/code/modules/antagonists/heretic/knowledge/void_lore.dm b/code/modules/antagonists/heretic/knowledge/void_lore.dm index 482de8184401b6..11031a51aca960 100644 --- a/code/modules/antagonists/heretic/knowledge/void_lore.dm +++ b/code/modules/antagonists/heretic/knowledge/void_lore.dm @@ -1,7 +1,5 @@ /** * # The path of VOID. - * Spell names are in this language: PALI - * Both are related: Pali-Buddhism-Nothingness-Void * * Goes as follows: * @@ -221,7 +219,7 @@ text = "[generate_heretic_text()] The nobleman of void [user.real_name] has arrived, stepping along the Waltz that ends worlds! [generate_heretic_text()]", title = "[generate_heretic_text()]", sound = 'sound/ambience/antag/heretic/ascend_void.ogg', - color_override = "blue", + color_override = "pink", ) ADD_TRAIT(user, TRAIT_RESISTLOWPRESSURE, MAGIC_TRAIT) diff --git a/code/modules/antagonists/heretic/magic/aggressive_spread.dm b/code/modules/antagonists/heretic/magic/aggressive_spread.dm index 0c14550f0b2690..dfb4a94847406c 100644 --- a/code/modules/antagonists/heretic/magic/aggressive_spread.dm +++ b/code/modules/antagonists/heretic/magic/aggressive_spread.dm @@ -10,8 +10,8 @@ school = SCHOOL_FORBIDDEN cooldown_time = 30 SECONDS - invocation = "Agresiv'noe rasprostra-neniye!" - invocation_type = INVOCATION_SHOUT + invocation = "A'GRSV SPR'D" + invocation_type = INVOCATION_WHISPER spell_requirements = NONE aoe_radius = 2 diff --git a/code/modules/antagonists/heretic/magic/apetravulnera.dm b/code/modules/antagonists/heretic/magic/apetravulnera.dm index eedef71f4b6c8f..e80d08911848cb 100644 --- a/code/modules/antagonists/heretic/magic/apetravulnera.dm +++ b/code/modules/antagonists/heretic/magic/apetravulnera.dm @@ -10,8 +10,8 @@ school = SCHOOL_FORBIDDEN cooldown_time = 45 SECONDS - invocation = "Shea' shen-eh!" - invocation_type = INVOCATION_SHOUT + invocation = "AP'TRA VULN'RA!" + invocation_type = INVOCATION_WHISPER spell_requirements = NONE cast_range = 4 diff --git a/code/modules/antagonists/heretic/magic/ash_ascension.dm b/code/modules/antagonists/heretic/magic/ash_ascension.dm index 70422a7c48a377..8b564198a61eba 100644 --- a/code/modules/antagonists/heretic/magic/ash_ascension.dm +++ b/code/modules/antagonists/heretic/magic/ash_ascension.dm @@ -10,7 +10,7 @@ school = SCHOOL_FORBIDDEN cooldown_time = 70 SECONDS - invocation = "EID'R-ELDR!!!" + invocation = "FL'MS" invocation_type = INVOCATION_WHISPER spell_requirements = NONE @@ -72,8 +72,8 @@ school = SCHOOL_FORBIDDEN cooldown_time = 30 SECONDS - invocation = "ILLA-LASARA'FOSS!!!" - invocation_type = INVOCATION_SHOUT + invocation = "C'SC'DE" + invocation_type = INVOCATION_WHISPER spell_requirements = NONE /// The radius the flames will go around the caster. @@ -112,7 +112,7 @@ school = SCHOOL_FORBIDDEN cooldown_time = 300 - invocation = "Eld'sky!" + invocation = "F'RE" invocation_type = INVOCATION_WHISPER spell_requirements = NONE diff --git a/code/modules/antagonists/heretic/magic/ash_jaunt.dm b/code/modules/antagonists/heretic/magic/ash_jaunt.dm index 4f8c59d635145a..41242063a90988 100644 --- a/code/modules/antagonists/heretic/magic/ash_jaunt.dm +++ b/code/modules/antagonists/heretic/magic/ash_jaunt.dm @@ -10,7 +10,7 @@ school = SCHOOL_FORBIDDEN cooldown_time = 15 SECONDS - invocation = "Askgraar' goetur!" + invocation = "ASH'N P'SSG'" invocation_type = INVOCATION_WHISPER spell_requirements = NONE diff --git a/code/modules/antagonists/heretic/magic/blood_cleave.dm b/code/modules/antagonists/heretic/magic/blood_cleave.dm index b3370a3ccc6146..d5317f23e344bf 100644 --- a/code/modules/antagonists/heretic/magic/blood_cleave.dm +++ b/code/modules/antagonists/heretic/magic/blood_cleave.dm @@ -10,7 +10,7 @@ school = SCHOOL_FORBIDDEN cooldown_time = 45 SECONDS - invocation = "Fer're!" + invocation = "CL'VE!" invocation_type = INVOCATION_WHISPER spell_requirements = NONE diff --git a/code/modules/antagonists/heretic/magic/blood_siphon.dm b/code/modules/antagonists/heretic/magic/blood_siphon.dm index 6280353a072a56..1e3d6258826d4b 100644 --- a/code/modules/antagonists/heretic/magic/blood_siphon.dm +++ b/code/modules/antagonists/heretic/magic/blood_siphon.dm @@ -11,7 +11,7 @@ school = SCHOOL_FORBIDDEN cooldown_time = 15 SECONDS - invocation = "Sanguis suctio!" + invocation = "FL'MS O'ET'RN'ITY." invocation_type = INVOCATION_WHISPER spell_requirements = NONE diff --git a/code/modules/antagonists/heretic/magic/burglar_finesse.dm b/code/modules/antagonists/heretic/magic/burglar_finesse.dm index c5264119bb48e4..a90acb8495f149 100644 --- a/code/modules/antagonists/heretic/magic/burglar_finesse.dm +++ b/code/modules/antagonists/heretic/magic/burglar_finesse.dm @@ -9,7 +9,7 @@ school = SCHOOL_FORBIDDEN cooldown_time = 40 SECONDS - invocation = "Khenem" + invocation = "Y'O'K!" invocation_type = INVOCATION_WHISPER spell_requirements = NONE diff --git a/code/modules/antagonists/heretic/magic/cosmic_expansion.dm b/code/modules/antagonists/heretic/magic/cosmic_expansion.dm index 6869dc0df51c02..3fb197d392cb08 100644 --- a/code/modules/antagonists/heretic/magic/cosmic_expansion.dm +++ b/code/modules/antagonists/heretic/magic/cosmic_expansion.dm @@ -11,7 +11,7 @@ school = SCHOOL_FORBIDDEN cooldown_time = 45 SECONDS - invocation = "An'gar baltil!" + invocation = "C'SM'S 'XP'ND" invocation_type = INVOCATION_SHOUT spell_requirements = NONE diff --git a/code/modules/antagonists/heretic/magic/cosmic_runes.dm b/code/modules/antagonists/heretic/magic/cosmic_runes.dm index e07aa4fbe8b8a3..207b60ae9393ad 100644 --- a/code/modules/antagonists/heretic/magic/cosmic_runes.dm +++ b/code/modules/antagonists/heretic/magic/cosmic_runes.dm @@ -11,7 +11,7 @@ school = SCHOOL_FORBIDDEN cooldown_time = 15 SECONDS - invocation = "Is'zara-runen" + invocation = "ST'R R'N'" invocation_type = INVOCATION_WHISPER spell_requirements = NONE diff --git a/code/modules/antagonists/heretic/magic/eldritch_blind.dm b/code/modules/antagonists/heretic/magic/eldritch_blind.dm index 413ff4fe678105..8df20503821b08 100644 --- a/code/modules/antagonists/heretic/magic/eldritch_blind.dm +++ b/code/modules/antagonists/heretic/magic/eldritch_blind.dm @@ -5,7 +5,7 @@ overlay_icon_state = "bg_heretic_border" school = SCHOOL_FORBIDDEN - invocation = "Caecus" + invocation = "E'E'S" spell_requirements = NONE cast_range = 10 diff --git a/code/modules/antagonists/heretic/magic/eldritch_emplosion.dm b/code/modules/antagonists/heretic/magic/eldritch_emplosion.dm index 4028f80f84ceac..c68ed07c81f8c6 100644 --- a/code/modules/antagonists/heretic/magic/eldritch_emplosion.dm +++ b/code/modules/antagonists/heretic/magic/eldritch_emplosion.dm @@ -8,7 +8,7 @@ school = SCHOOL_FORBIDDEN cooldown_time = 30 SECONDS - invocation = "Pulsus Energiae" + invocation = "E'P" invocation_type = INVOCATION_WHISPER spell_requirements = NONE diff --git a/code/modules/antagonists/heretic/magic/eldritch_shapeshift.dm b/code/modules/antagonists/heretic/magic/eldritch_shapeshift.dm index bde032a3b39fdf..e598f1f9215b93 100644 --- a/code/modules/antagonists/heretic/magic/eldritch_shapeshift.dm +++ b/code/modules/antagonists/heretic/magic/eldritch_shapeshift.dm @@ -7,7 +7,7 @@ overlay_icon_state = "bg_heretic_border" school = SCHOOL_FORBIDDEN - invocation = "Forma" + invocation = "SH'PE" invocation_type = INVOCATION_WHISPER spell_requirements = NONE diff --git a/code/modules/antagonists/heretic/magic/fire_blast.dm b/code/modules/antagonists/heretic/magic/fire_blast.dm index 8c6d632be9f2de..4c17ca5ffc0dea 100644 --- a/code/modules/antagonists/heretic/magic/fire_blast.dm +++ b/code/modules/antagonists/heretic/magic/fire_blast.dm @@ -12,7 +12,7 @@ school = SCHOOL_FORBIDDEN cooldown_time = 45 SECONDS - invocation = "Eld'fjall!" + invocation = "V'LC'N!" invocation_type = INVOCATION_SHOUT spell_requirements = NONE channel_time = 5 SECONDS diff --git a/code/modules/antagonists/heretic/magic/flesh_ascension.dm b/code/modules/antagonists/heretic/magic/flesh_ascension.dm index add0704a8d61af..a2d792080e0584 100644 --- a/code/modules/antagonists/heretic/magic/flesh_ascension.dm +++ b/code/modules/antagonists/heretic/magic/flesh_ascension.dm @@ -9,7 +9,7 @@ school = SCHOOL_FORBIDDEN - invocation = "REALITAS EXSERPAT!!" + invocation = "REALITY UNCOIL!" invocation_type = INVOCATION_SHOUT spell_requirements = NONE diff --git a/code/modules/antagonists/heretic/magic/flesh_surgery.dm b/code/modules/antagonists/heretic/magic/flesh_surgery.dm index a486b986cd81e0..ff474f063198fc 100644 --- a/code/modules/antagonists/heretic/magic/flesh_surgery.dm +++ b/code/modules/antagonists/heretic/magic/flesh_surgery.dm @@ -11,8 +11,8 @@ school = SCHOOL_FORBIDDEN cooldown_time = 20 SECONDS - invocation = "Carnis chirurgia" - invocation_type = INVOCATION_WHISPER + invocation = "CL'M M'N!" // "CLAIM MINE", but also almost "KALI MA" + invocation_type = INVOCATION_SHOUT spell_requirements = NONE hand_path = /obj/item/melee/touch_attack/flesh_surgery diff --git a/code/modules/antagonists/heretic/magic/furious_steel.dm b/code/modules/antagonists/heretic/magic/furious_steel.dm index 36c7c07608bcbb..0ab882a9289e11 100644 --- a/code/modules/antagonists/heretic/magic/furious_steel.dm +++ b/code/modules/antagonists/heretic/magic/furious_steel.dm @@ -11,7 +11,7 @@ school = SCHOOL_FORBIDDEN cooldown_time = 60 SECONDS - invocation = "Ham'sana-qasep!" + invocation = "F'LSH'NG S'LV'R!" invocation_type = INVOCATION_SHOUT spell_requirements = NONE diff --git a/code/modules/antagonists/heretic/magic/manse_link.dm b/code/modules/antagonists/heretic/magic/manse_link.dm index e077c6db2b45f4..06fd4dd9863f43 100644 --- a/code/modules/antagonists/heretic/magic/manse_link.dm +++ b/code/modules/antagonists/heretic/magic/manse_link.dm @@ -11,7 +11,7 @@ school = SCHOOL_FORBIDDEN cooldown_time = 20 SECONDS - invocation = "Diaperaste' to-myalo!" + invocation = "PI'RC' TH' M'ND." invocation_type = INVOCATION_SHOUT spell_requirements = NONE antimagic_flags = MAGIC_RESISTANCE|MAGIC_RESISTANCE_MIND diff --git a/code/modules/antagonists/heretic/magic/mansus_grasp.dm b/code/modules/antagonists/heretic/magic/mansus_grasp.dm index 803bdd3d218e5f..43dde25374f89a 100644 --- a/code/modules/antagonists/heretic/magic/mansus_grasp.dm +++ b/code/modules/antagonists/heretic/magic/mansus_grasp.dm @@ -10,7 +10,7 @@ school = SCHOOL_EVOCATION cooldown_time = 10 SECONDS - invocation = "Ad verum per aspera!" + invocation = "R'CH T'H TR'TH!" invocation_type = INVOCATION_SHOUT // Mimes can cast it. Chaplains can cast it. Anyone can cast it, so long as they have a hand. spell_requirements = SPELL_CASTABLE_WITHOUT_INVOCATION diff --git a/code/modules/antagonists/heretic/magic/mind_gate.dm b/code/modules/antagonists/heretic/magic/mind_gate.dm index aa6b8ef20af4dc..c5a6e74452a615 100644 --- a/code/modules/antagonists/heretic/magic/mind_gate.dm +++ b/code/modules/antagonists/heretic/magic/mind_gate.dm @@ -11,7 +11,7 @@ school = SCHOOL_FORBIDDEN cooldown_time = 20 SECONDS - invocation = "Sha'ar ha-da'at" + invocation = "Op' 'oY 'Mi'd" invocation_type = INVOCATION_WHISPER spell_requirements = NONE cast_range = 6 diff --git a/code/modules/antagonists/heretic/magic/moon_parade.dm b/code/modules/antagonists/heretic/magic/moon_parade.dm index 4919500e351de2..3b7f1d007cd6e1 100644 --- a/code/modules/antagonists/heretic/magic/moon_parade.dm +++ b/code/modules/antagonists/heretic/magic/moon_parade.dm @@ -11,7 +11,7 @@ school = SCHOOL_FORBIDDEN cooldown_time = 30 SECONDS - invocation = "Tsiyun' levani!" + invocation = "L'N'R P'RAD" invocation_type = INVOCATION_SHOUT spell_requirements = NONE diff --git a/code/modules/antagonists/heretic/magic/moon_ringleader.dm b/code/modules/antagonists/heretic/magic/moon_ringleader.dm index e62c34bb990bbf..3c0b1d2aedb52c 100644 --- a/code/modules/antagonists/heretic/magic/moon_ringleader.dm +++ b/code/modules/antagonists/heretic/magic/moon_ringleader.dm @@ -12,7 +12,7 @@ school = SCHOOL_FORBIDDEN cooldown_time = 1 MINUTES - invocation = "Manahel-qomem!" + invocation = "R''S 'E" invocation_type = INVOCATION_SHOUT spell_requirements = NONE diff --git a/code/modules/antagonists/heretic/magic/moon_smile.dm b/code/modules/antagonists/heretic/magic/moon_smile.dm index 236fd257e385d2..35f2d77e3e6b6b 100644 --- a/code/modules/antagonists/heretic/magic/moon_smile.dm +++ b/code/modules/antagonists/heretic/magic/moon_smile.dm @@ -12,7 +12,7 @@ school = SCHOOL_FORBIDDEN cooldown_time = 20 SECONDS - invocation = "Hiyuk-levana!" + invocation = "Mo'N S'M'LE" invocation_type = INVOCATION_SHOUT spell_requirements = NONE cast_range = 6 diff --git a/code/modules/antagonists/heretic/magic/nightwatcher_rebirth.dm b/code/modules/antagonists/heretic/magic/nightwatcher_rebirth.dm index 8a9b60644b6b73..4e37f5db17fed5 100644 --- a/code/modules/antagonists/heretic/magic/nightwatcher_rebirth.dm +++ b/code/modules/antagonists/heretic/magic/nightwatcher_rebirth.dm @@ -11,7 +11,7 @@ school = SCHOOL_FORBIDDEN cooldown_time = 1 MINUTES - invocation = "Dyrth-a Vaktry'ggjandi" + invocation = "GL'RY T' TH' N'GHT'W'TCH'ER" invocation_type = INVOCATION_WHISPER spell_requirements = SPELL_REQUIRES_HUMAN diff --git a/code/modules/antagonists/heretic/magic/realignment.dm b/code/modules/antagonists/heretic/magic/realignment.dm index dbce0fe0940dd9..d3ddc03fbbef3a 100644 --- a/code/modules/antagonists/heretic/magic/realignment.dm +++ b/code/modules/antagonists/heretic/magic/realignment.dm @@ -14,8 +14,8 @@ cooldown_reduction_per_rank = -6 SECONDS // we're not a wizard spell but we use the levelling mechanic spell_max_level = 10 // we can get up to / over a minute duration cd time - invocation = "Rasut" - invocation_type = INVOCATION_WHISPER + invocation = "R'S'T." + invocation_type = INVOCATION_SHOUT spell_requirements = NONE /datum/action/cooldown/spell/realignment/is_valid_target(atom/cast_on) diff --git a/code/modules/antagonists/heretic/magic/rust_wave.dm b/code/modules/antagonists/heretic/magic/rust_wave.dm index 7ecb3fd0ffbba7..0282a32b2b6874 100644 --- a/code/modules/antagonists/heretic/magic/rust_wave.dm +++ b/code/modules/antagonists/heretic/magic/rust_wave.dm @@ -13,8 +13,8 @@ school = SCHOOL_FORBIDDEN cooldown_time = 30 SECONDS - invocation = "Entro'pichniy-plim!" - invocation_type = INVOCATION_SHOUT + invocation = "'NTR'P'C PL'M'" + invocation_type = INVOCATION_WHISPER spell_requirements = NONE cone_levels = 5 @@ -78,8 +78,8 @@ school = SCHOOL_FORBIDDEN cooldown_time = 35 SECONDS - invocation = "Diffunde' verbum!" - invocation_type = INVOCATION_SHOUT + invocation = "SPR'D TH' WO'D" + invocation_type = INVOCATION_WHISPER spell_requirements = NONE projectile_type = /obj/projectile/magic/aoe/rust_wave diff --git a/code/modules/antagonists/heretic/magic/star_blast.dm b/code/modules/antagonists/heretic/magic/star_blast.dm index 294608a03b998a..3eb62b7ada8140 100644 --- a/code/modules/antagonists/heretic/magic/star_blast.dm +++ b/code/modules/antagonists/heretic/magic/star_blast.dm @@ -10,7 +10,7 @@ school = SCHOOL_FORBIDDEN cooldown_time = 20 SECONDS - invocation = "Pi-rig is'zara!" + invocation = "R'T'T' ST'R!" invocation_type = INVOCATION_SHOUT spell_requirements = NONE diff --git a/code/modules/antagonists/heretic/magic/star_touch.dm b/code/modules/antagonists/heretic/magic/star_touch.dm index dff56df4e3f1fa..89c5d02e7d4981 100644 --- a/code/modules/antagonists/heretic/magic/star_touch.dm +++ b/code/modules/antagonists/heretic/magic/star_touch.dm @@ -13,7 +13,7 @@ sound = 'sound/items/welder.ogg' school = SCHOOL_FORBIDDEN cooldown_time = 15 SECONDS - invocation = "An'gar sig!" + invocation = "ST'R 'N'RG'!" invocation_type = INVOCATION_SHOUT spell_requirements = NONE antimagic_flags = MAGIC_RESISTANCE diff --git a/code/modules/antagonists/heretic/magic/void_cold_cone.dm b/code/modules/antagonists/heretic/magic/void_cold_cone.dm index 40dc9612a50f6f..92c45dc10b0100 100644 --- a/code/modules/antagonists/heretic/magic/void_cold_cone.dm +++ b/code/modules/antagonists/heretic/magic/void_cold_cone.dm @@ -11,7 +11,7 @@ school = SCHOOL_FORBIDDEN cooldown_time = 30 SECONDS - invocation = "Sunya'kop!" + invocation = "FR'ZE!" invocation_type = INVOCATION_SHOUT spell_requirements = NONE diff --git a/code/modules/antagonists/heretic/magic/void_phase.dm b/code/modules/antagonists/heretic/magic/void_phase.dm index f3f0864224c4c6..350ca0f29c1008 100644 --- a/code/modules/antagonists/heretic/magic/void_phase.dm +++ b/code/modules/antagonists/heretic/magic/void_phase.dm @@ -12,8 +12,8 @@ school = SCHOOL_FORBIDDEN cooldown_time = 30 SECONDS - invocation = "Sunya'sthiti!" - invocation_type = INVOCATION_SHOUT + invocation = "RE'L'TY PH'S'E." + invocation_type = INVOCATION_WHISPER spell_requirements = NONE cast_range = 9 diff --git a/code/modules/antagonists/heretic/magic/void_pull.dm b/code/modules/antagonists/heretic/magic/void_pull.dm index dc4673b0714ce4..2021bf8a04e4f8 100644 --- a/code/modules/antagonists/heretic/magic/void_pull.dm +++ b/code/modules/antagonists/heretic/magic/void_pull.dm @@ -11,8 +11,8 @@ school = SCHOOL_FORBIDDEN cooldown_time = 40 SECONDS - invocation = "Sunya'apamkti!" - invocation_type = INVOCATION_SHOUT + invocation = "BR'NG F'RTH TH'M T' M'." + invocation_type = INVOCATION_WHISPER spell_requirements = NONE aoe_radius = 7 diff --git a/code/modules/antagonists/heretic/magic/wave_of_desperation.dm b/code/modules/antagonists/heretic/magic/wave_of_desperation.dm index b9502f08967bbf..3b78b56ddc0ba1 100644 --- a/code/modules/antagonists/heretic/magic/wave_of_desperation.dm +++ b/code/modules/antagonists/heretic/magic/wave_of_desperation.dm @@ -11,8 +11,8 @@ school = SCHOOL_FORBIDDEN cooldown_time = 5 MINUTES - invocation = "Kher' Sekh-em waaef'k!" - invocation_type = INVOCATION_SHOUT + invocation = "F'K 'FF." + invocation_type = INVOCATION_WHISPER spell_requirements = NONE aoe_radius = 3 diff --git a/code/modules/antagonists/nukeop/outfits.dm b/code/modules/antagonists/nukeop/outfits.dm index 0d122cff0c0617..4f7b8804f8a8ef 100644 --- a/code/modules/antagonists/nukeop/outfits.dm +++ b/code/modules/antagonists/nukeop/outfits.dm @@ -102,8 +102,8 @@ name = "Syndicate Operative - Reinforcement" tc = 0 backpack_contents = list( - /obj/item/gun/ballistic/automatic/plastikov = 1, - /obj/item/ammo_box/magazine/plastikov9mm = 2, + /obj/item/gun/ballistic/automatic/smartgun = 1, + /obj/item/ammo_box/magazine/smartgun = 2, ) var/faction = "The Syndicate" diff --git a/code/modules/antagonists/spy/spy.dm b/code/modules/antagonists/spy/spy.dm index 8bcc113f089398..2468eb27cad3f5 100644 --- a/code/modules/antagonists/spy/spy.dm +++ b/code/modules/antagonists/spy/spy.dm @@ -8,6 +8,8 @@ hijack_speed = 1 ui_name = "AntagInfoSpy" preview_outfit = /datum/outfit/spy + can_assign_self_objectives = TRUE + default_custom_objective = "Rob the station blind." /// Whether an uplink has been created (successfully or at all) var/uplink_created = FALSE /// String displayed in the antag panel pointing the spy to where their uplink is. diff --git a/code/modules/antagonists/spy/spy_bounty.dm b/code/modules/antagonists/spy/spy_bounty.dm index 28984ce2272bd2..01a1a1baf7b9a0 100644 --- a/code/modules/antagonists/spy/spy_bounty.dm +++ b/code/modules/antagonists/spy/spy_bounty.dm @@ -186,7 +186,7 @@ var/datum/market_item/stolen_good/new_item = new(thing, item_price) - return SSblackmarket.markets[/datum/market/blackmarket].add_item(new_item) + return SSmarket.markets[/datum/market/blackmarket].add_item(new_item) /// Steal an item /datum/spy_bounty/objective_item diff --git a/code/modules/antagonists/traitor/datum_traitor.dm b/code/modules/antagonists/traitor/datum_traitor.dm index 733e22461c7955..bbdfa77eceacdb 100644 --- a/code/modules/antagonists/traitor/datum_traitor.dm +++ b/code/modules/antagonists/traitor/datum_traitor.dm @@ -47,7 +47,8 @@ /// The uplink handler that this traitor belongs to. var/datum/uplink_handler/uplink_handler - var/uplink_sale_count = 3 + var/uplink_sales_min = 4 + var/uplink_sales_max = 6 ///the final objective the traitor has to accomplish, be it escaping, hijacking, or just martyrdom. var/datum/objective/ending_objective @@ -98,14 +99,14 @@ var/list/uplink_items = list() for(var/datum/uplink_item/item as anything in SStraitor.uplink_items) - if(item.item && !item.cant_discount && (item.purchasable_from & uplink_handler.uplink_flag) && item.cost > 1) + if(item.item && !item.cant_discount && (item.purchasable_from & uplink_handler.uplink_flag) && item.cost >= TRAITOR_DISCOUNT_MIN_PRICE) if(!length(item.restricted_roles) && !length(item.restricted_species)) uplink_items += item continue if((uplink_handler.assigned_role in item.restricted_roles) || (uplink_handler.assigned_species in item.restricted_species)) uplink_items += item continue - uplink_handler.extra_purchasable += create_uplink_sales(uplink_sale_count, /datum/uplink_category/discounts, 1, uplink_items) + uplink_handler.extra_purchasable += create_uplink_sales(rand(uplink_sales_min, uplink_sales_max), /datum/uplink_category/discounts, 1, uplink_items) if(give_objectives) forge_traitor_objectives() diff --git a/code/modules/antagonists/traitor/uplink_handler.dm b/code/modules/antagonists/traitor/uplink_handler.dm index f78ddb0247892a..2d27f3c4a0eff4 100644 --- a/code/modules/antagonists/traitor/uplink_handler.dm +++ b/code/modules/antagonists/traitor/uplink_handler.dm @@ -126,6 +126,21 @@ on_update() return TRUE +/datum/uplink_handler/proc/purchase_raw_tc(mob/user, amount, atom/movable/source) + if(shop_locked) + return FALSE + if(telecrystals < amount) + return FALSE + + telecrystals -= amount + var/tcs = new /obj/item/stack/telecrystal(get_turf(user), amount) + user.put_in_hands(tcs) + + log_uplink("[key_name(user)] purchased [amount] raw telecrystals from [source]'s uplink") + on_update() + return TRUE + + /// Generates objectives for this uplink handler /datum/uplink_handler/proc/generate_objectives() var/potential_objectives_left = maximum_potential_objectives - (length(potential_objectives) + length(active_objectives)) diff --git a/code/modules/antagonists/voidwalker/voidwalker_loot.dm b/code/modules/antagonists/voidwalker/voidwalker_loot.dm index 8d3420d0a5278d..73ed9c7cd2207f 100644 --- a/code/modules/antagonists/voidwalker/voidwalker_loot.dm +++ b/code/modules/antagonists/voidwalker/voidwalker_loot.dm @@ -6,6 +6,9 @@ icon = 'icons/obj/weapons/voidwalker_items.dmi' icon_state = "cosmic_skull_charged" + light_on = TRUE + light_color = "#CC00CC" + light_range = 3 /// Icon state for when drained var/drained_icon_state = "cosmic_skull_drained" /// How many uses does it have left? @@ -37,3 +40,4 @@ uses-- if(uses <= 0 ) icon_state = drained_icon_state + light_on = FALSE diff --git a/code/modules/antagonists/voidwalker/voidwalker_status_effects.dm b/code/modules/antagonists/voidwalker/voidwalker_status_effects.dm index 6dc9cdc35ca7bc..7934e757077af0 100644 --- a/code/modules/antagonists/voidwalker/voidwalker_status_effects.dm +++ b/code/modules/antagonists/voidwalker/voidwalker_status_effects.dm @@ -21,11 +21,16 @@ /datum/status_effect/planet_allergy id = "planet_allergy" duration = INFINITE - alert_type = /atom/movable/screen/alert/veryhighgravity + alert_type = /atom/movable/screen/alert/status_effect/veryhighgravity /datum/status_effect/planet_allergy/tick() owner.adjustBruteLoss(1) +/atom/movable/screen/alert/status_effect/veryhighgravity + name = "Crushing Gravity" + desc = "You're getting crushed by high gravity, picking up items and movement will be slowed. You'll also accumulate brute damage!" + icon_state = "paralysis" + /datum/status_effect/void_eatered duration = 10 SECONDS remove_on_fullheal = TRUE diff --git a/code/modules/antagonists/voidwalker/voidwalker_void_eater.dm b/code/modules/antagonists/voidwalker/voidwalker_void_eater.dm index db638c2b948186..9df3eabab3d218 100644 --- a/code/modules/antagonists/voidwalker/voidwalker_void_eater.dm +++ b/code/modules/antagonists/voidwalker/voidwalker_void_eater.dm @@ -31,7 +31,7 @@ AddComponent(/datum/component/temporary_glass_shatterer) -/obj/item/void_eater/pickup(mob/user) +/obj/item/void_eater/equipped(mob/user) . = ..() RegisterSignal(user, COMSIG_VOIDWALKER_SUCCESFUL_KIDNAP, PROC_REF(refresh)) diff --git a/code/modules/antagonists/wizard/grand_ritual/grand_rune.dm b/code/modules/antagonists/wizard/grand_ritual/grand_rune.dm index 79364a80a198a5..15900a6ac0b0a7 100644 --- a/code/modules/antagonists/wizard/grand_ritual/grand_rune.dm +++ b/code/modules/antagonists/wizard/grand_ritual/grand_rune.dm @@ -19,7 +19,7 @@ pixel_y = 16 pixel_z = -48 anchored = TRUE - interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND + interaction_flags_atom = INTERACT_ATOM_ATTACK_HAND | INTERACT_ATOM_ATTACK_PAW resistance_flags = FIRE_PROOF | UNACIDABLE | ACID_PROOF layer = SIGIL_LAYER /// How many prior grand rituals have been completed? diff --git a/code/modules/asset_cache/assets/uplink.dm b/code/modules/asset_cache/assets/uplink.dm index e85ee1b35b5c13..35a907a234dfa3 100644 --- a/code/modules/asset_cache/assets/uplink.dm +++ b/code/modules/asset_cache/assets/uplink.dm @@ -18,10 +18,13 @@ for(var/datum/uplink_item/item_path as anything in subtypesof(/datum/uplink_item)) var/datum/uplink_item/item = new item_path() + var/atom/actual_item = item.item if(item.item) { items += list(list( "id" = item_path, "name" = item.name, + "icon" = actual_item.icon, + "icon_state" = actual_item.icon_state, "cost" = item.cost, "desc" = item.desc, "category" = item.category ? initial(item.category.name) : null, diff --git a/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer_items.dm b/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer_items.dm index 95b548998a1942..26cb3951135192 100644 --- a/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer_items.dm +++ b/code/modules/atmospherics/machinery/components/gas_recipe_machines/crystallizer_items.dm @@ -38,3 +38,22 @@ if(uses <= 0) qdel(src) return ITEM_INTERACT_SUCCESS + +/obj/item/nitrium_crystal + desc = "A weird brown crystal, it smokes when broken" + name = "nitrium crystal" + icon = 'icons/obj/pipes_n_cables/atmos.dmi' + icon_state = "nitrium_crystal" + var/cloud_size = 1 + +/obj/item/nitrium_crystal/attack_self(mob/user) + . = ..() + var/datum/effect_system/fluid_spread/smoke/chem/smoke = new + var/turf/location = get_turf(src) + create_reagents(5) + reagents.add_reagent(/datum/reagent/nitrium_low_metabolization, 3) + reagents.add_reagent(/datum/reagent/nitrium_high_metabolization, 2) + smoke.attach(location) + smoke.set_up(cloud_size, holder = src, location = location, carry = reagents, silent = TRUE) + smoke.start() + qdel(src) diff --git a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm index 25217de538ce17..da6c75d699d087 100644 --- a/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm +++ b/code/modules/atmospherics/machinery/components/trinary_devices/filter.dm @@ -6,7 +6,7 @@ desc = "Very useful for filtering gasses." can_unwrench = TRUE - construction_type = /obj/item/pipe/trinary/flippable + construction_type = /obj/item/pipe/trinary/flippable/filter pipe_state = "filter" ///Rate of transfer of the gases to the outputs diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm index 02f0d20354496b..8a165830cec07b 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_pump.dm @@ -5,7 +5,7 @@ name = "air vent" desc = "Has a valve and pump attached to it." - + construction_type = /obj/item/pipe/directional/vent use_power = IDLE_POWER_USE idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.15 can_unwrench = TRUE diff --git a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm index 20a0b86b41c296..22ee2f6b414a79 100644 --- a/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm +++ b/code/modules/atmospherics/machinery/components/unary_devices/vent_scrubber.dm @@ -3,6 +3,7 @@ name = "air scrubber" desc = "Has a valve and pump attached to it." + construction_type = /obj/item/pipe/directional/scrubber use_power = IDLE_POWER_USE idle_power_usage = BASE_MACHINE_IDLE_CONSUMPTION * 0.1 active_power_usage = BASE_MACHINE_ACTIVE_CONSUMPTION * 0.15 diff --git a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm index 9729c0871451a0..210eb9b0d9e280 100644 --- a/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm +++ b/code/modules/atmospherics/machinery/portable/portable_atmospherics.dm @@ -51,6 +51,10 @@ AddElement(/datum/element/elevation, pixel_shift = 8) register_context() +/obj/machinery/portable_atmospherics/on_construction(mob/user) + . = ..() + set_anchored(FALSE) + /obj/machinery/portable_atmospherics/on_deconstruction(disassembled) if(nob_crystal_inserted) new /obj/item/hypernoblium_crystal(src) diff --git a/code/modules/awaymissions/zlevel.dm b/code/modules/awaymissions/zlevel.dm index 0fdc5093511f2e..b72a6b59dde369 100644 --- a/code/modules/awaymissions/zlevel.dm +++ b/code/modules/awaymissions/zlevel.dm @@ -32,15 +32,51 @@ GLOBAL_LIST_INIT(potentialConfigRandomZlevels, generate_map_list_from_directory( current = D if(!current) current = new + current.name = name current.id = id if(delay) - current.wait = CONFIG_GET(number/gateway_delay) + var/list/waits_by_id = CONFIG_GET(keyed_list/gateway_delays_by_id) + var/wait_to_use = !isnull(waits_by_id[id]) ? waits_by_id[id] : CONFIG_GET(number/gateway_delay) + current.wait = wait_to_use GLOB.gateway_destinations += current current.target_turfs += get_turf(src) + return INITIALIZE_HINT_QDEL /obj/effect/landmark/awaystart/nodelay delay = FALSE +/obj/effect/landmark/awaystart/beach + name = "beach away spawn" + id = AWAYSTART_BEACH + +/obj/effect/landmark/awaystart/museum + name = "buseum away spawn" + id = AWAYSTART_MUSEUM + +/obj/effect/landmark/awaystart/research + name = "research outpost away spawn" + id = AWAYSTART_RESEARCH + +/obj/effect/landmark/awaystart/caves + name = "caves away spawn" + id = AWAYSTART_CAVES + +/obj/effect/landmark/awaystart/moonoutpost + name = "Moon Outpost 19 away spawn" + id = AWAYSTART_MOONOUTPOST + +/obj/effect/landmark/awaystart/snowcabin + name = "snow cabin away spawn" + id = AWAYSTART_SNOWCABIN + +/obj/effect/landmark/awaystart/snowdin + name = "Snowdin away spawn" + id = AWAYSTART_SNOWDIN + +/obj/effect/landmark/awaystart/underground + name = "Underground Outpost 45 away spawn" + id = AWAYSTART_UNDERGROUND + /proc/generateMapList(filename) . = list() filename = "[global.config.directory]/[SANITIZE_FILENAME(filename)]" diff --git a/code/modules/bitrunning/components/avatar_connection.dm b/code/modules/bitrunning/components/avatar_connection.dm index 51263c339319eb..abf3a7809fcda2 100644 --- a/code/modules/bitrunning/components/avatar_connection.dm +++ b/code/modules/bitrunning/components/avatar_connection.dm @@ -20,7 +20,7 @@ help_text, ) - if(!isliving(parent) || !isliving(old_body) || !server.is_operational || !pod.is_operational) + if(!isliving(parent) || !isliving(old_body) || !old_mind || !server.is_operational || !pod.is_operational) return COMPONENT_INCOMPATIBLE var/mob/living/avatar = parent @@ -66,6 +66,9 @@ if(alias && avatar.real_name != alias) avatar.fully_replace_character_name(avatar.real_name, alias) + for(var/skill_type in old_mind.known_skills) + avatar.mind.set_experience(skill_type, old_mind.get_skill_exp(skill_type), silent = TRUE) + avatar.playsound_local(avatar, 'sound/magic/blink.ogg', 25, TRUE) avatar.set_static_vision(2 SECONDS) avatar.set_temp_blindness(1 SECONDS) // I'm in @@ -281,6 +284,10 @@ if(isnull(old_mind) || isnull(old_body)) return + for(var/skill_type in avatar.mind.known_skills) + old_mind.set_experience(skill_type, avatar.mind.get_skill_exp(skill_type), silent = TRUE) + avatar.mind.set_experience(skill_type, 0, silent = TRUE) + ghost.mind = old_mind if(old_body.stat != DEAD) old_mind.transfer_to(old_body, force_key_move = TRUE) diff --git a/code/modules/bitrunning/turfs.dm b/code/modules/bitrunning/turfs.dm index 4c35153311e531..763388b6e0850e 100644 --- a/code/modules/bitrunning/turfs.dm +++ b/code/modules/bitrunning/turfs.dm @@ -1,4 +1,4 @@ -/turf/open/floor/bitrunning_transport +/turf/open/indestructible/bitrunning_transport name = "circuit floor" desc = "Looks complex. You can see the circuits running through the floor." icon_state = "bitrunning" diff --git a/code/modules/cargo/bounties/assistant.dm b/code/modules/cargo/bounties/assistant.dm index d4ef4b6a148e0d..23e578c2ed2dbd 100644 --- a/code/modules/cargo/bounties/assistant.dm +++ b/code/modules/cargo/bounties/assistant.dm @@ -213,7 +213,7 @@ /datum/bounty/item/assistant/fish name = "Fish" description = "We need fish to populate our aquariums with. Fishes that are dead or bought from cargo will only be paid half as much." - reward = CARGO_CRATE_VALUE * 9 + reward = CARGO_CRATE_VALUE * 9.5 required_count = 4 wanted_types = list(/obj/item/fish = TRUE, /obj/item/storage/fish_case = TRUE) ///the penalty for shipping dead/bought fish, which can subtract up to half the reward in total. @@ -249,7 +249,7 @@ ///A subtype of the fish bounty that requires fish with a specific fluid type /datum/bounty/item/assistant/fish/fluid - reward = CARGO_CRATE_VALUE * 11 + reward = CARGO_CRATE_VALUE * 12 ///The required fluid type of the fish for it to be shipped var/fluid_type @@ -261,42 +261,3 @@ /datum/bounty/item/assistant/fish/fluid/can_ship_fish(obj/item/fish/fishie) return compatible_fluid_type(fishie.required_fluid_type, fluid_type) - -///A subtype of the fish bounty that requires specific fish types. The higher their rarity, the better the pay. -/datum/bounty/item/assistant/fish/specific - description = "Our prestigious fish collection is currently lacking a few specific species. Fishes that are dead or bought from cargo will only be paid half as much." - reward = CARGO_CRATE_VALUE * 16 - required_count = 3 - wanted_types = list(/obj/item/storage/fish_case = TRUE) - -/datum/bounty/item/assistant/fish/specific/New() - var/static/list/choosable_fishes - if(isnull(choosable_fishes)) - choosable_fishes = list() - for(var/obj/item/fish/prototype as anything in subtypesof(/obj/item/fish)) - if(initial(prototype.experisci_scannable) && initial(prototype.show_in_catalog)) - choosable_fishes += prototype - - var/list/fishes_copylist = choosable_fishes.Copy() - ///Used to calculate the extra reward - var/total_rarity = 0 - var/list/name_list = list() - var/num_paths = rand(2,3) - for(var/i in 1 to num_paths) - var/obj/item/fish/chosen_path = pick_n_take(fishes_copylist) - wanted_types[chosen_path] = TRUE - name_list += initial(chosen_path.name) - total_rarity += initial(chosen_path.random_case_rarity) / num_paths - name = english_list(name_list) - - switch(total_rarity) - if(FISH_RARITY_NOPE to FISH_RARITY_GOOD_LUCK_FINDING_THIS) - reward += CARGO_CRATE_VALUE * 14 - if(FISH_RARITY_GOOD_LUCK_FINDING_THIS to FISH_RARITY_VERY_RARE) - reward += CARGO_CRATE_VALUE * 6.5 - if(FISH_RARITY_VERY_RARE to FISH_RARITY_RARE) - reward += CARGO_CRATE_VALUE * 3 - if(FISH_RARITY_RARE to FISH_RARITY_BASIC-1) - reward += CARGO_CRATE_VALUE * 1 - - ..() diff --git a/code/modules/cargo/exports/fish.dm b/code/modules/cargo/exports/fish.dm new file mode 100644 index 00000000000000..9c34fd3afcaebc --- /dev/null +++ b/code/modules/cargo/exports/fish.dm @@ -0,0 +1,9 @@ +/datum/export/fish + cost = 30 + unit_name = "fish" + export_types = list(/obj/item/fish) + +/datum/export/fish/get_cost(obj/item/fish/fish, apply_elastic) + var/elastic_cost = ..() + var/elastic_percent = elastic_cost / init_cost + return fish.get_export_price(elastic_cost, elastic_percent) diff --git a/code/modules/cargo/goodies.dm b/code/modules/cargo/goodies.dm index e09c3e2bc958d8..4751b45aae89ba 100644 --- a/code/modules/cargo/goodies.dm +++ b/code/modules/cargo/goodies.dm @@ -311,7 +311,7 @@ /datum/supply_pack/goody/climbing_hook name = "Climbing Hook Single-Pack" - desc = "A less cheap imported climbing hook. Absolutely no use outside of planetary stations." + desc = "A less cheap imported climbing hook. Absolutely no use outside of multi-floor stations." cost = PAYCHECK_CREW * 5 contains = list(/obj/item/climbing_hook) diff --git a/code/modules/cargo/markets/_market.dm b/code/modules/cargo/markets/_market.dm index 0a93469411cdb4..4696d3007a7ae6 100644 --- a/code/modules/cargo/markets/_market.dm +++ b/code/modules/cargo/markets/_market.dm @@ -6,7 +6,7 @@ var/list/shipping // Automatic vars, do not touch these. - /// Items available from this market, populated by SSblackmarket on initialization. Automatically assigned, so don't manually adjust. + /// Items available from this market, populated by SSmarket on initialization. Automatically assigned, so don't manually adjust. var/list/available_items = list() /// Item categories available from this market, only items which are in these categories can be gotten from this market. Automatically assigned, so don't manually adjust. var/list/categories = list() @@ -73,6 +73,20 @@ return FALSE +/** + * A proc that restocks only the EXISTING items of this market. + * If you want to selectively restock markets, call SSmarket.restock(market_or_list_of_markets) instead. + */ +/datum/market/proc/restock(list/existing_items) + for(var/category in available_items) + var/category_list = available_items[category] + for(var/identifier in category_list) + var/datum/market_item/item = category_list[identifier] + existing_items |= item.type + if(!item.restockable || item.stock >= item.stock_max || !prob(item.availability_prob)) + continue + item.stock += rand(1, item.stock_max - item.stock) + /datum/market/blackmarket name = "Black Market" shipping = list( diff --git a/code/modules/cargo/markets/market_item.dm b/code/modules/cargo/markets/market_item.dm index 5e3ce4efb6c079..d7a4dd4c0eef35 100644 --- a/code/modules/cargo/markets/market_item.dm +++ b/code/modules/cargo/markets/market_item.dm @@ -5,7 +5,7 @@ var/desc /// The category this item belongs to, should be already declared in the market that this item is accessible in. var/category - /// "/datum/market"s that this item should be in, used by SSblackmarket on init. + /// "/datum/market"s that this item should be in, used by SSmarket on init. var/list/markets = list(/datum/market/blackmarket) /// Price for the item, if not set creates a price according to the *_min and *_max vars. @@ -27,7 +27,7 @@ var/stock_min = 1 /// Maximum amount that there should be of this item in the market if generated randomly. var/stock_max = 0 - /// Probability for this item to be available. Used by SSblackmarket on init. + /// Probability for this item to be available. Used by SSmarket on init. var/availability_prob ///The identifier for the market item, generated on runtime and used to access them in the market categories. @@ -36,6 +36,9 @@ ///If set, these will override the shipment methods set by the market var/list/shipping_override + /// Can this item be restocked + var/restockable = TRUE + /datum/market_item/New() if(isnull(price)) price = rand(price_min, price_max) @@ -82,7 +85,7 @@ CRASH("Invalid item type for market item [item || "null"]") /** - * Buys the item and makes SSblackmarket handle it. + * Buys the item and makes SSmarket handle it. * * @param uplink The uplink that is buying the item. * @param buyer The mob that is buying the item. @@ -102,8 +105,8 @@ // Alright, the item has been purchased. var/datum/market_purchase/purchase = new(src, uplink, shipping_method, legal_status) - // SSblackmarket takes care of the shipping. - if(SSblackmarket.queue_item(purchase)) + // SSmarket takes care of the shipping. + if(SSmarket.queue_item(purchase)) stock-- buyer.log_message("has succesfully purchased [name] using [shipping_method] for shipping.", LOG_ECON) return TRUE @@ -139,7 +142,7 @@ /datum/market_purchase/Destroy() entry = null uplink = null - SSblackmarket.queued_purchases -= src + SSmarket.queued_purchases -= src return ..() /datum/market_purchase/proc/on_instance_del(datum/source) diff --git a/code/modules/cargo/markets/market_items/hostages.dm b/code/modules/cargo/markets/market_items/hostages.dm index ed5b1f10a7fcfc..702cea907bdebf 100644 --- a/code/modules/cargo/markets/market_items/hostages.dm +++ b/code/modules/cargo/markets/market_items/hostages.dm @@ -5,6 +5,7 @@ stock = 1 availability_prob = 100 shipping_override = list(SHIPPING_METHOD_LTSRBT = 0, SHIPPING_METHOD_SUPPLYPOD = 350) + restockable = FALSE /// temporary reference to the 4 in 7 chances of signaler and electropack. var/obj/item/assembly/signaler/signaler diff --git a/code/modules/cargo/markets/market_items/stolen_goods.dm b/code/modules/cargo/markets/market_items/stolen_goods.dm index 02a72f05d26d1c..cb1932673e0e3f 100644 --- a/code/modules/cargo/markets/market_items/stolen_goods.dm +++ b/code/modules/cargo/markets/market_items/stolen_goods.dm @@ -4,6 +4,7 @@ abstract_path = /datum/market_item/stolen_good stock = 1 availability_prob = 100 + restockable = FALSE /datum/market_item/stolen_good/New(atom/movable/thing, thing_price) ..() diff --git a/code/modules/cargo/markets/market_items/tools.dm b/code/modules/cargo/markets/market_items/tools.dm index 963d7fbaeb0755..0c9969756d30f4 100644 --- a/code/modules/cargo/markets/market_items/tools.dm +++ b/code/modules/cargo/markets/market_items/tools.dm @@ -11,7 +11,7 @@ stock_min = 2 stock_max = 4 price_min = CARGO_CRATE_VALUE * 2.5 - price_max = CARGO_CRATE_VALUE * 3.75 + price_max = CARGO_CRATE_VALUE * 3.25 availability_prob = 100 /datum/market_item/tool/caravan_wrench diff --git a/code/modules/cargo/markets/market_telepad.dm b/code/modules/cargo/markets/market_telepad.dm index 7c5b509a9421de..799395f30d1254 100644 --- a/code/modules/cargo/markets/market_telepad.dm +++ b/code/modules/cargo/markets/market_telepad.dm @@ -1,3 +1,5 @@ +#define DEFAULT_RESTOCK_COST 675 + /obj/item/circuitboard/machine/ltsrbt name = "LTSRBT (Machine Board)" icon_state = "bluespacearray" @@ -13,7 +15,8 @@ name = "Long-To-Short-Range-Bluespace-Transceiver" desc = "The LTSRBT is a compact teleportation machine for receiving and sending items outside the station and inside the station.\nUsing teleportation frequencies stolen from NT it is near undetectable.\nEssential for any illegal market operations on NT stations.\n" icon = 'icons/obj/machines/telecomms.dmi' - icon_state = "exonet_node" + icon_state = "exonet_node_idle" + base_icon_state = "exonet_node" circuit = /obj/item/circuitboard/machine/ltsrbt density = TRUE @@ -35,18 +38,42 @@ var/datum/market_purchase/transmitting /// Queue for purchases that the machine should receive and send. var/list/datum/market_purchase/queue = list() + /** + * Attacking the machinery with enough credits will restock the markets, allowing for more/better items. + * The cost doubles each time this is done. + */ + var/static/restock_cost = DEFAULT_RESTOCK_COST /obj/machinery/ltsrbt/Initialize(mapload) . = ..() - SSblackmarket.telepads += src + register_context() + SSmarket.telepads += src /obj/machinery/ltsrbt/Destroy() - SSblackmarket.telepads -= src + SSmarket.telepads -= src // Bye bye orders. - if(length(SSblackmarket.telepads)) + if(length(SSmarket.telepads)) for(var/datum/market_purchase/P in queue) - SSblackmarket.queue_item(P) + SSmarket.queue_item(P) + . = ..() + +/obj/machinery/ltsrbt/add_context(atom/source, list/context, obj/item/held_item, mob/user) + if(held_item && held_item.get_item_credit_value()) + context[SCREENTIP_CONTEXT_LMB] = "Restock" + return CONTEXTUAL_SCREENTIP_SET + return NONE + +/obj/machinery/ltsrbt/examine(mob/user) . = ..() + if(machine_stat & NOPOWER) + . += span_info("A display reads: \"Current market restock price: [EXAMINE_HINT("[restock_cost] cr")]\".") + +/obj/machinery/ltsrbt/update_icon_state() + . = ..() + if(machine_stat & NOPOWER) + icon_state = "[base_icon_state]_off" + else + icon_state = "[base_icon_state][(receiving || length(queue)) ? "" : "_idle"]" /obj/machinery/ltsrbt/RefreshParts() . = ..() @@ -67,6 +94,7 @@ /obj/machinery/ltsrbt/proc/add_to_queue(datum/market_purchase/purchase) if(!recharge_cooldown && !receiving && !transmitting) receiving = purchase + update_appearance(UPDATE_ICON_STATE) else queue += purchase @@ -80,6 +108,8 @@ if(transmitting == purchase) transmitting = null + update_appearance(UPDATE_ICON_STATE) + /obj/machinery/ltsrbt/process(seconds_per_tick) if(machine_stat & NOPOWER) return @@ -113,3 +143,32 @@ if(length(queue)) receiving = pick_n_take(queue) + +/obj/machinery/ltsrbt/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + var/creds_value = tool.get_item_credit_value() + if(!creds_value) + return NONE + + . = ITEM_INTERACT_SUCCESS + + if(machine_stat & NOPOWER) + return + + if(creds_value < restock_cost) + say("Insufficient credits!") + playsound(src, 'sound/machines/buzz-sigh.ogg', 40, FALSE) + return + + if(istype(tool, /obj/item/holochip)) + var/obj/item/holochip/chip = tool + chip.spend(restock_cost) + else + qdel(tool) + if(creds_value != restock_cost) + var/obj/item/holochip/change = new(creds_value - restock_cost) + user.put_in_hands(change) + + SSmarket.restock() + restock_cost *= 2 + +#undef DEFAULT_RESTOCK_COST diff --git a/code/modules/cargo/markets/market_uplink.dm b/code/modules/cargo/markets/market_uplink.dm index d13f59937b66ca..a324a2f0409be8 100644 --- a/code/modules/cargo/markets/market_uplink.dm +++ b/code/modules/cargo/markets/market_uplink.dm @@ -20,7 +20,7 @@ /obj/item/market_uplink/Initialize(mapload) . = ..() - // We don't want to go through this at mapload because the SSblackmarket isn't initialized yet. + // We don't want to go through this at mapload because the SSmarket isn't initialized yet. if(mapload) return @@ -30,7 +30,7 @@ /obj/item/market_uplink/proc/update_viewing_category() if(accessible_markets.len) viewing_market = accessible_markets[1] - var/list/categories = SSblackmarket.markets[viewing_market].categories + var/list/categories = SSmarket.markets[viewing_market].categories if(categories?.len) viewing_category = categories[1] @@ -45,7 +45,7 @@ /obj/item/market_uplink/ui_data(mob/user) var/list/data = list() - var/datum/market/market = viewing_market ? SSblackmarket.markets[viewing_market] : null + var/datum/market/market = viewing_market ? SSmarket.markets[viewing_market] : null var/obj/item/card/id/id_card if(isliving(user)) var/mob/living/livin = user @@ -86,11 +86,11 @@ /obj/item/market_uplink/ui_static_data(mob/user) var/list/data = list() - data["delivery_method_description"] = SSblackmarket.shipping_method_descriptions - data["ltsrbt_built"] = SSblackmarket.telepads.len + data["delivery_method_description"] = SSmarket.shipping_method_descriptions + data["ltsrbt_built"] = SSmarket.telepads.len data["markets"] = list() for(var/M in accessible_markets) - var/datum/market/BM = SSblackmarket.markets[M] + var/datum/market/BM = SSmarket.markets[M] data["markets"] += list(list( "id" = M, "name" = BM.name @@ -107,7 +107,7 @@ return if(isnull(viewing_market)) return - if(!(params["category"] in SSblackmarket.markets[viewing_market].categories)) + if(!(params["category"] in SSmarket.markets[viewing_market].categories)) return viewing_category = params["category"] . = TRUE @@ -120,7 +120,7 @@ viewing_market = market - var/list/categories = SSblackmarket.markets[viewing_market].categories + var/list/categories = SSmarket.markets[viewing_market].categories if(categories?.len) viewing_category = categories[1] else @@ -142,7 +142,7 @@ if(isnull(selected_item)) buying = FALSE return - var/datum/market/market = SSblackmarket.markets[viewing_market] + var/datum/market/market = SSmarket.markets[viewing_market] market.purchase(selected_item, viewing_category, params["method"], src, usr) buying = FALSE diff --git a/code/modules/cargo/packs/imports.dm b/code/modules/cargo/packs/imports.dm index f270b1da11f396..98fc4d650212c5 100644 --- a/code/modules/cargo/packs/imports.dm +++ b/code/modules/cargo/packs/imports.dm @@ -318,3 +318,20 @@ ) crate_name = "floortile camouflauge crate" crate_type = /obj/structure/closet/crate/secure/weapon + +/** + * The Long To Short Range Bluespace Teleporter, used to deliver (black) market purchases more effiiently + * It can also be used to restock it, if you hit it with enough credits. + */ +/datum/supply_pack/imports/blackmarket_telepad + name = "Black Market LTSRBT" + desc = "Need a faster and better way of transporting your illegal goods from and to the \ + station? Fear not, the Long-To-Short-Range-Bluespace-Transceiver (LTSRBT for short) \ + is here to help. Contains a LTSRBT circuit, two bluespace crystals, and one ansible." + cost = CARGO_CRATE_VALUE * 10 + contraband = TRUE + contains = list( + /obj/item/circuitboard/machine/ltsrbt, + /obj/item/stack/ore/bluespace_crystal/artificial = 2, + /obj/item/stock_parts/subspace/ansible, + ) diff --git a/code/modules/cargo/packs/medical.dm b/code/modules/cargo/packs/medical.dm index c30a698c06f876..0c626223916af5 100644 --- a/code/modules/cargo/packs/medical.dm +++ b/code/modules/cargo/packs/medical.dm @@ -187,6 +187,6 @@ name = "Strong-Arm Implant Set" desc = "A crate containing two implants, which can be surgically implanted to empower the strength of human arms. Warranty void if exposed to electromagnetic pulses." cost = CARGO_CRATE_VALUE * 6 - contains = list(/obj/item/organ/internal/cyberimp/arm/muscle = 2) + contains = list(/obj/item/organ/internal/cyberimp/arm/strongarm = 2) crate_name = "Strong-Arm implant crate" discountable = SUPPLY_PACK_RARE_DISCOUNTABLE diff --git a/code/modules/cargo/supplypod.dm b/code/modules/cargo/supplypod.dm index 86ee482a9109d9..69b9342007c41d 100644 --- a/code/modules/cargo/supplypod.dm +++ b/code/modules/cargo/supplypod.dm @@ -421,18 +421,22 @@ insert(turf_underneath, holder) /obj/structure/closet/supplypod/insert(atom/to_insert, atom/movable/holder) - if(insertion_allowed(to_insert)) - if(isturf(to_insert)) - var/turf/turf_to_insert = to_insert - turfs_in_cargo += turf_to_insert.type - turf_to_insert.ScrapeAway() - else - var/atom/movable/movable_to_insert = to_insert - movable_to_insert.forceMove(holder) - return TRUE - else + if(!insertion_allowed(to_insert)) return FALSE + if(isturf(to_insert)) + var/turf/turf_to_insert = to_insert + turfs_in_cargo += turf_to_insert.type + turf_to_insert.ScrapeAway() + return TRUE + + var/atom/movable/movable_to_insert = to_insert + if (ismob(movable_to_insert)) + var/mob/mob_to_insert = movable_to_insert + if (!isnull(mob_to_insert.buckled)) + mob_to_insert.buckled.unbuckle_mob(mob_to_insert, force = TRUE) + movable_to_insert.forceMove(holder) + /obj/structure/closet/supplypod/insertion_allowed(atom/to_insert) if(to_insert.invisibility == INVISIBILITY_ABSTRACT) return FALSE diff --git a/code/modules/client/client_procs.dm b/code/modules/client/client_procs.dm index e3f74e47c497df..ac3d6af1796221 100644 --- a/code/modules/client/client_procs.dm +++ b/code/modules/client/client_procs.dm @@ -1206,6 +1206,7 @@ GLOBAL_LIST_INIT(blacklisted_builds, list( winset(usr, "mainwindow", "can-resize=true") winset(usr, "mainwindow", "is-maximized=false") winset(usr, "mainwindow", "on-size=attempt_auto_fit_viewport") + attempt_auto_fit_viewport() /client/verb/toggle_status_bar() set name = "Toggle Status Bar" diff --git a/code/modules/client/preferences/sounds.dm b/code/modules/client/preferences/sounds.dm index f1778405665ad2..4a0298132c2683 100644 --- a/code/modules/client/preferences/sounds.dm +++ b/code/modules/client/preferences/sounds.dm @@ -116,3 +116,9 @@ category = PREFERENCE_CATEGORY_GAME_PREFERENCES savefile_key = "sound_elevator" savefile_identifier = PREFERENCE_PLAYER + +/// Controls hearing radio noise +/datum/preference/toggle/radio_noise + category = PREFERENCE_CATEGORY_GAME_PREFERENCES + savefile_key = "sound_radio_noise" + savefile_identifier = PREFERENCE_PLAYER diff --git a/code/modules/clothing/head/hat.dm b/code/modules/clothing/head/hat.dm index 13285257c65530..a8247a55603e25 100644 --- a/code/modules/clothing/head/hat.dm +++ b/code/modules/clothing/head/hat.dm @@ -210,6 +210,14 @@ name = "rice hat" desc = "Welcome to the rice fields, motherfucker." icon_state = "rice_hat" + base_icon_state = "rice_hat" + var/reversed = FALSE + +/obj/item/clothing/head/costume/rice_hat/click_alt(mob/user) + reversed = !reversed + worn_icon_state = "[base_icon_state][reversed ? "_kim" : ""]" + to_chat(user, span_notice("You [reversed ? "lower" : "raise"] the hat.")) + update_appearance() /obj/item/clothing/head/costume/lizard name = "lizardskin cloche hat" diff --git a/code/modules/clothing/head/helmet.dm b/code/modules/clothing/head/helmet.dm index 68921334510384..76c230ca504d2b 100644 --- a/code/modules/clothing/head/helmet.dm +++ b/code/modules/clothing/head/helmet.dm @@ -568,3 +568,106 @@ fire = 50 acid = 50 wound = 30 + +/obj/item/clothing/head/helmet/durability/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) + take_damage(1, BRUTE, 0, 0) + +/obj/item/clothing/head/helmet/durability/watermelon + name = "Watermelon Helmet" + desc = "A helmet cut out from a watermelon. Might take a few hits, but don't expect it whitstand much." + icon_state = "watermelon" + inhand_icon_state = "watermelon" + flags_inv = HIDEEARS + dog_fashion = /datum/dog_fashion/head/watermelon + armor_type = /datum/armor/helmet_watermelon + max_integrity = 15 + +/obj/item/clothing/head/helmet/durability/watermelon/fire_resist + resistance_flags = FIRE_PROOF + armor_type = /datum/armor/helmet_watermelon_fr + +/datum/armor/helmet_watermelon + melee = 15 + bullet = 10 + energy = 10 + bomb = 10 + fire = 0 + acid = 25 + wound = 5 + +/datum/armor/helmet_watermelon_fr + melee = 15 + bullet = 10 + energy = 10 + bomb = 10 + fire = 15 + acid = 30 + wound = 5 + +/obj/item/clothing/head/helmet/durability/holymelon + name = "Holymelon Helmet" + desc = "A helmet from a hollowed out holymelon. Might take a few hits, but don't expect it whitstand much." + icon_state = "holymelon" + inhand_icon_state = "holymelon" + flags_inv = HIDEEARS + dog_fashion = /datum/dog_fashion/head/holymelon + armor_type = /datum/armor/helmet_watermelon + max_integrity = 15 + var/decayed = FALSE + +/obj/item/clothing/head/helmet/durability/holymelon/fire_resist + resistance_flags = FIRE_PROOF + armor_type = /datum/armor/helmet_watermelon_fr + +/obj/item/clothing/head/helmet/durability/holymelon/Initialize(mapload) + . = ..() + if(decayed) + decay() + return + + AddComponent( + /datum/component/anti_magic, \ + antimagic_flags = MAGIC_RESISTANCE_HOLY, \ + inventory_flags = ITEM_SLOT_OCLOTHING, \ + charges = 1, \ + drain_antimagic = CALLBACK(src, PROC_REF(drain_antimagic)), \ + expiration = CALLBACK(src, PROC_REF(decay)) \ + ) + +/obj/item/clothing/head/helmet/durability/holymelon/proc/drain_antimagic(mob/user) + to_chat(user, span_warning("[src] looses a bit of its shimmer and glossiness...")) + +/obj/item/clothing/head/helmet/durability/holymelon/proc/decay() + take_damage(8, BRUTE, 0, 0) + +/obj/item/clothing/head/helmet/durability/barrelmelon + name = "Barrelmelon Helmet" + desc = "A helmet from hollowed out barrelmelon. As sturdy as if made from actual wood, though its rigid structure makes it break up quicker." + icon_state = "barrelmelon" + inhand_icon_state = "barrelmelon" + flags_inv = HIDEEARS + dog_fashion = /datum/dog_fashion/head/barrelmelon + armor_type = /datum/armor/helmet_barrelmelon + max_integrity = 10 + +/obj/item/clothing/head/helmet/durability/barrelmelon/fire_resist + resistance_flags = FIRE_PROOF + armor_type = /datum/armor/helmet_barrelmelon_fr + +/datum/armor/helmet_barrelmelon + melee = 25 + bullet = 20 + energy = 15 + bomb = 10 + fire = 0 + acid = 35 + wound = 10 + +/datum/armor/helmet_barrelmelon_fr + melee = 25 + bullet = 20 + energy = 15 + bomb = 10 + fire = 20 + acid = 40 + wound = 10 diff --git a/code/modules/clothing/head/soft_caps.dm b/code/modules/clothing/head/soft_caps.dm index 3003e9a76ee159..cb0f9033960c38 100644 --- a/code/modules/clothing/head/soft_caps.dm +++ b/code/modules/clothing/head/soft_caps.dm @@ -169,6 +169,7 @@ clothing_flags = SNUG_FIT resistance_flags = INDESTRUCTIBLE | LAVA_PROOF | FIRE_PROOF | UNACIDABLE dog_fashion = null + clothing_traits = list(TRAIT_SCARY_FISHERMAN) //Fish, carps, lobstrosities and frogs fear me. /obj/item/clothing/head/soft/fishing_hat/Initialize(mapload) . = ..() diff --git a/code/modules/clothing/spacesuits/plasmamen.dm b/code/modules/clothing/spacesuits/plasmamen.dm index 63a0dd515c3f67..380cd0cf3fb532 100644 --- a/code/modules/clothing/spacesuits/plasmamen.dm +++ b/code/modules/clothing/spacesuits/plasmamen.dm @@ -118,33 +118,45 @@ . = ..() if(!up) . += visor_icon - -/obj/item/clothing/head/helmet/space/plasmaman/attackby(obj/item/hitting_item, mob/living/user) - . = ..() - if(istype(hitting_item, /obj/item/toy/crayon)) - if(smile == FALSE) - var/obj/item/toy/crayon/CR = hitting_item - to_chat(user, span_notice("You start drawing a smiley face on the helmet's visor..")) - if(do_after(user, 2.5 SECONDS, target = src)) - smile = TRUE - smile_color = CR.paint_color - to_chat(user, "You draw a smiley on the helmet visor.") - update_appearance() - else - to_chat(user, span_warning("Seems like someone already drew something on this helmet's visor!")) - return - if(istype(hitting_item, /obj/item/clothing/head)) - var/obj/item/clothing/hitting_clothing = hitting_item - if(hitting_clothing.clothing_flags & STACKABLE_HELMET_EXEMPT) - to_chat(user, span_notice("You cannot place [hitting_clothing.name] on helmet!")) - return - if(attached_hat) - to_chat(user, span_notice("There's already something placed on helmet!")) - return - attached_hat = hitting_clothing - to_chat(user, span_notice("You placed [hitting_clothing.name] on helmet!")) - hitting_clothing.forceMove(src) + if(smile) + var/mutable_appearance/smiley = mutable_appearance(icon, smile_state) + smiley.color = smile_color + . += smiley + +/obj/item/clothing/head/helmet/space/plasmaman/item_interaction(mob/living/user, obj/item/tool, list/modifiers) + if(istype(tool, /obj/item/toy/crayon)) + if(smile) + to_chat(user, span_warning("Seems like someone already drew something on [src]'s visor!")) + return ITEM_INTERACT_BLOCKING + + var/obj/item/toy/crayon/crayon = tool + to_chat(user, span_notice("You start drawing a smiley face on [src]'s visor...")) + if(!do_after(user, 2.5 SECONDS, target = src)) + return ITEM_INTERACT_BLOCKING + + smile = TRUE + smile_color = crayon.paint_color + to_chat(user, "You draw a smiley on [src] visor.") update_appearance() + return ITEM_INTERACT_SUCCESS + + if(!istype(tool, /obj/item/clothing/head)) + return NONE + + var/obj/item/clothing/hitting_clothing = tool + if(hitting_clothing.clothing_flags & STACKABLE_HELMET_EXEMPT) + to_chat(user, span_notice("You cannot place [hitting_clothing.name] on [src]!")) + return ITEM_INTERACT_BLOCKING + + if(attached_hat) + to_chat(user, span_notice("There's already something placed on [src]!")) + return ITEM_INTERACT_BLOCKING + + attached_hat = hitting_clothing + to_chat(user, span_notice("You placed [hitting_clothing.name] on [src]!")) + hitting_clothing.forceMove(src) + update_appearance() + return ITEM_INTERACT_SUCCESS ///By the by, helmets have the update_icon_updates_onmob element, so we don't have to call mob.update_worn_head() /obj/item/clothing/head/helmet/space/plasmaman/worn_overlays(mutable_appearance/standing, isinhands) diff --git a/code/modules/clothing/suits/armor.dm b/code/modules/clothing/suits/armor.dm index 5036b939b8e4a2..3c7fa506b208d0 100644 --- a/code/modules/clothing/suits/armor.dm +++ b/code/modules/clothing/suits/armor.dm @@ -714,3 +714,113 @@ fire = 50 acid = 50 wound = 30 + +/obj/item/clothing/suit/armor/durability/hit_reaction(mob/living/carbon/human/owner, atom/movable/hitby, attack_text = "the attack", final_block_chance = 0, damage = 0, attack_type = MELEE_ATTACK, damage_type = BRUTE) + take_damage(1, BRUTE, 0, 0) + +/obj/item/clothing/suit/armor/durability/watermelon + name = "watermelon" + desc = "An armour, made from watermelons. Propably won't take too many hits, but at least it looks serious... As serious as worn watermelon can be." + icon_state = "watermelon" + inhand_icon_state = null + body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + armor_type = /datum/armor/watermelon + strip_delay = 60 + equip_delay_other = 40 + clothing_traits = list(TRAIT_BRAWLING_KNOCKDOWN_BLOCKED) + max_integrity = 15 + +/obj/item/clothing/suit/armor/durability/watermelon/fire_resist + resistance_flags = FIRE_PROOF + armor_type = /datum/armor/watermelon_fr + +/datum/armor/watermelon + melee = 15 + bullet = 10 + energy = 10 + bomb = 10 + fire = 0 + acid = 25 + wound = 5 + +/datum/armor/watermelon_fr + melee = 15 + bullet = 10 + energy = 10 + bomb = 10 + fire = 15 + acid = 30 + wound = 5 + +/obj/item/clothing/suit/armor/durability/holymelon + name = "holymelon" + desc = "An armour, made from holymelons. Inspires you to go on some sort of a crusade... Perhaps spreading spinach to children?" + icon_state = "holymelon" + inhand_icon_state = null + body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + armor_type = /datum/armor/watermelon + strip_delay = 60 + equip_delay_other = 40 + clothing_traits = list(TRAIT_BRAWLING_KNOCKDOWN_BLOCKED) + max_integrity = 15 + var/decayed = FALSE + +/obj/item/clothing/suit/armor/durability/holymelon/fire_resist + resistance_flags = FIRE_PROOF + armor_type = /datum/armor/watermelon_fr + +/obj/item/clothing/suit/armor/durability/holymelon/Initialize(mapload) + . = ..() + if(decayed) + decay() + return + + AddComponent( + /datum/component/anti_magic, \ + antimagic_flags = MAGIC_RESISTANCE_HOLY, \ + inventory_flags = ITEM_SLOT_OCLOTHING, \ + charges = 1, \ + drain_antimagic = CALLBACK(src, PROC_REF(drain_antimagic)), \ + expiration = CALLBACK(src, PROC_REF(decay)) \ + ) + +/obj/item/clothing/suit/armor/durability/holymelon/proc/drain_antimagic(mob/user) + to_chat(user, span_warning("[src] looses a bit of its shimmer and glossiness...")) + +/obj/item/clothing/suit/armor/durability/holymelon/proc/decay() + take_damage(8, BRUTE, 0, 0) + + +/obj/item/clothing/suit/armor/durability/barrelmelon + name = "barrelmelon" + desc = "An armour, made from barrelmelons. Reeks of ale, inspiring to courageous deeds. Or, perhaps, a bar brawl." + icon_state = "barrelmelon" + inhand_icon_state = null + body_parts_covered = CHEST|GROIN|LEGS|FEET|ARMS|HANDS + armor_type = /datum/armor/barrelmelon + strip_delay = 60 + equip_delay_other = 40 + clothing_traits = list(TRAIT_BRAWLING_KNOCKDOWN_BLOCKED) + max_integrity = 10 + +/obj/item/clothing/suit/armor/durability/barrelmelon/fire_resist + resistance_flags = FIRE_PROOF + armor_type = /datum/armor/barrelmelon_fr + +/datum/armor/barrelmelon + melee = 25 + bullet = 20 + energy = 15 + bomb = 10 + fire = 0 + acid = 35 + wound = 10 + +/datum/armor/barrelmelon_fr + melee = 25 + bullet = 20 + energy = 15 + bomb = 10 + fire = 20 + acid = 40 + wound = 10 diff --git a/code/modules/clothing/suits/wiz_robe.dm b/code/modules/clothing/suits/wiz_robe.dm index eb1ccb3c51092b..53026e974bf63a 100644 --- a/code/modules/clothing/suits/wiz_robe.dm +++ b/code/modules/clothing/suits/wiz_robe.dm @@ -49,6 +49,17 @@ resistance_flags = FLAMMABLE dog_fashion = /datum/dog_fashion/head/blue_wizard +/obj/item/clothing/head/wizard/chanterelle + name = "chanterelle hat" + desc = "An oversized chanterelle with hollow out space to fit a head in. Kinda looks like wizard's hat." + icon_state = "chanterelle" + inhand_icon_state = "chanterellehat" + armor_type = /datum/armor/none + resistance_flags = FLAMMABLE + +/obj/item/clothing/head/wizard/chanterelle/fr + resistance_flags = FIRE_PROOF + /obj/item/clothing/head/wizard/marisa name = "witch hat" desc = "Strange-looking hat-wear. Makes you want to cast fireballs." @@ -205,6 +216,63 @@ actions_types = list(/datum/action/item_action/stickmen) +/obj/item/clothing/suit/wizrobe/durathread + name = "durathread robe" + desc = "A rather dull durathread robe; not quite as protective as a proper piece of armour, but much stylish." + icon_state = "durathread-fake" + inhand_icon_state = null + armor_type = /datum/armor/robe_durathread + allowed = list( + /obj/item/cultivator, + /obj/item/geneshears, + /obj/item/graft, + /obj/item/hatchet, + /obj/item/plant_analyzer, + /obj/item/reagent_containers/cup/beaker, + /obj/item/reagent_containers/cup/bottle, + /obj/item/reagent_containers/cup/tube, + /obj/item/reagent_containers/spray/pestspray, + /obj/item/reagent_containers/spray/plantbgone, + /obj/item/secateurs, + /obj/item/seeds, + /obj/item/storage/bag/plants, + ) + +/datum/armor/robe_durathread + melee = 15 + bullet = 5 + laser = 25 + energy = 30 + bomb = 10 + fire = 30 + acid = 40 + +/obj/item/clothing/suit/wizrobe/durathread/fire + name = "pyromancer robe" + desc = "A rather dull durathread robe; not quite as protective as an woven armour, but much stylish." + icon_state = "durathread-fire" + +/obj/item/clothing/suit/wizrobe/durathread/ice + name = "pyromancer robe" + desc = "A rather dull durathread robe; not quite as protective as an woven armour, but much stylish." + icon_state = "durathread-ice" + +/obj/item/clothing/suit/wizrobe/durathread/electric + name = "electromancer robe" + desc = "Doesn't actually conduit or isolate from electricity. Though it does have some durability on account of being made from durathread." + icon_state = "durathread-electric" + +/obj/item/clothing/suit/wizrobe/durathread/earth + name = "geomancer robe" + desc = "A rather dull durathread robe; not quite as protective as an woven armour, but much stylish." + icon_state = "durathread-earth" + +/obj/item/clothing/suit/wizrobe/durathread/necro + name = "necromancer robe" + desc = "A rather dull durathread robe; not quite as protective as an woven armour, but much stylish." + icon_state = "durathread-necro" + + /obj/item/clothing/suit/wizrobe/paper/ui_action_click(mob/user, action) stickmen() diff --git a/code/modules/error_handler/error_handler.dm b/code/modules/error_handler/error_handler.dm index a6841d3975444c..1cf617ce4513ef 100644 --- a/code/modules/error_handler/error_handler.dm +++ b/code/modules/error_handler/error_handler.dm @@ -101,6 +101,12 @@ GLOBAL_VAR_INIT(total_runtimes_skipped, 0) // The proceeding mess will almost definitely break if error messages are ever changed var/list/splitlines = splittext(E.desc, "\n") var/list/desclines = list() + var/list/state_stack = GLOB.lua_state_stack + var/is_lua_call = length(state_stack) + var/list/lua_stacks = list() + if(is_lua_call) + for(var/level in 1 to state_stack.len) + lua_stacks += list(splittext(DREAMLUAU_GET_TRACEBACK(level), "\n")) if(LAZYLEN(splitlines) > ERROR_USEFUL_LEN) // If there aren't at least three lines, there's no info for(var/line in splitlines) if(LAZYLEN(line) < 3 || findtext(line, "source file:") || findtext(line, "usr.loc:")) @@ -110,13 +116,14 @@ GLOBAL_VAR_INIT(total_runtimes_skipped, 0) desclines.Add(usrinfo) usrinfo = null continue // Our usr info is better, replace it - if(copytext(line, 1, 3) != " ")//3 == length(" ") + 1 desclines += (" " + line) // Pad any unpadded lines, so they look pretty else desclines += line if(usrinfo) //If this info isn't null, it hasn't been added yet desclines.Add(usrinfo) + if(is_lua_call) + SSlua.log_involved_runtime(E, desclines, lua_stacks) if(silencing) desclines += " (This error will now be silenced for [DisplayTimeText(configured_error_silence_time)])" if(GLOB.error_cache) diff --git a/code/modules/events/disease_outbreak.dm b/code/modules/events/disease_outbreak.dm index 8fcc05f345bfc6..3856bf550b4a36 100644 --- a/code/modules/events/disease_outbreak.dm +++ b/code/modules/events/disease_outbreak.dm @@ -102,7 +102,7 @@ var/list/afflicted = list() /datum/round_event/disease_outbreak/announce(fake) - if(isnull(illness_type)) + if(!illness_type) var/list/virus_candidates = list( /datum/disease/anxiety, /datum/disease/beesease, diff --git a/code/modules/events/supermatter_surge.dm b/code/modules/events/supermatter_surge.dm index 6c790c84f8d7ed..c7fb6f969d82b1 100644 --- a/code/modules/events/supermatter_surge.dm +++ b/code/modules/events/supermatter_surge.dm @@ -91,7 +91,8 @@ end_when = rand(SURGE_DURATION_MIN, SURGE_DURATION_MAX) /datum/round_event/supermatter_surge/announce(fake) - priority_announce("The Crystal Integrity Monitoring System has detected unusual atmospheric properties in the supermatter chamber, energy output from the supermatter crystal has increased significantly. Engineering intervention is required to stabilize the engine.", "Class [surge_class] Supermatter Surge Alert", 'sound/machines/engine_alert3.ogg') + var/class_to_announce = fake ? pick(1, 2, 3, 4) : surge_class + priority_announce("The Crystal Integrity Monitoring System has detected unusual atmospheric properties in the supermatter chamber, energy output from the supermatter crystal has increased significantly. Engineering intervention is required to stabilize the engine.", "Class [class_to_announce] Supermatter Surge Alert", 'sound/machines/engine_alert3.ogg') /datum/round_event/supermatter_surge/start() engine.bullet_energy = surge_class + SURGE_BULLET_ENERGY_ADDITION @@ -99,7 +100,6 @@ sm_gas.heat_power_generation = (surge_class * SURGE_POWER_GENERATION_MODIFIER) - 1 sm_gas.heat_modifier = (surge_class * SURGE_HEAT_MODIFIER) - 1 - /datum/round_event/supermatter_surge/end() engine.bullet_energy = initial(engine.bullet_energy) sm_gas.powerloss_inhibition = initial(sm_gas.powerloss_inhibition) diff --git a/code/modules/fishing/admin.dm b/code/modules/fishing/admin.dm index 0a9cfc9d51dd99..ba5c29a7fd1729 100644 --- a/code/modules/fishing/admin.dm +++ b/code/modules/fishing/admin.dm @@ -48,7 +48,7 @@ ADMIN_VERB(fishing_calculator, R_DEBUG, "Fishing Calculator", "A calculator... f if(hook_type) temporary_rod.set_slot(new hook_type(temporary_rod), ROD_SLOT_HOOK) if(line_type) - temporary_rod.set_slot(new line_type(temporary_rod), ROD_SLOT_HOOK) + temporary_rod.set_slot(new line_type(temporary_rod), ROD_SLOT_LINE) var/result_table = list() var/modified_table = spot.get_modified_fish_table(temporary_rod,user) diff --git a/code/modules/fishing/aquarium/aquarium.dm b/code/modules/fishing/aquarium/aquarium.dm index 97ce717b4c5247..5afbf4b72d9a94 100644 --- a/code/modules/fishing/aquarium/aquarium.dm +++ b/code/modules/fishing/aquarium/aquarium.dm @@ -13,7 +13,7 @@ name = "aquarium" desc = "A vivarium in which aquatic fauna and flora are usually kept and displayed." density = TRUE - anchored = TRUE + anchored = FALSE icon = 'icons/obj/aquarium/tanks.dmi' icon_state = "aquarium_map" @@ -35,13 +35,13 @@ var/last_feeding /// Can fish reproduce in this quarium. - var/allow_breeding = FALSE + var/allow_breeding = TRUE //This is the area where fish can swim var/aquarium_zone_min_px = 2 var/aquarium_zone_max_px = 31 var/aquarium_zone_min_py = 10 - var/aquarium_zone_max_py = 24 + var/aquarium_zone_max_py = 28 var/list/fluid_types = list(AQUARIUM_FLUID_SALTWATER, AQUARIUM_FLUID_FRESHWATER, AQUARIUM_FLUID_SULPHWATEVER, AQUARIUM_FLUID_AIR) @@ -64,7 +64,7 @@ RegisterSignal(src, COMSIG_ATOM_WAS_ATTACKED, PROC_REF(on_attacked)) create_reagents(6, SEALED_CONTAINER) RegisterSignal(reagents, COMSIG_REAGENTS_NEW_REAGENT, PROC_REF(start_autofeed)) - AddComponent(/datum/component/plumbing/aquarium) + AddComponent(/datum/component/plumbing/aquarium, start = anchored) if(current_beauty) AddElement(/datum/element/beauty, current_beauty) ADD_KEEP_TOGETHER(src, INNATE_TRAIT) @@ -390,6 +390,9 @@ #undef AQUARIUM_BORDERS_LAYER #undef AQUARIUM_BELOW_GLASS_LAYER +/obj/structure/aquarium/lawyer + anchored = TRUE + /obj/structure/aquarium/lawyer/Initialize(mapload) . = ..() @@ -400,6 +403,9 @@ reagents.add_reagent(/datum/reagent/consumable/nutriment, 2) +/obj/structure/aquarium/prefilled + anchored = TRUE + /obj/structure/aquarium/prefilled/Initialize(mapload) . = ..() diff --git a/code/modules/fishing/fish/_fish.dm b/code/modules/fishing/fish/_fish.dm index 081f794029041c..19a20a40a816bb 100644 --- a/code/modules/fishing/fish/_fish.dm +++ b/code/modules/fishing/fish/_fish.dm @@ -627,6 +627,14 @@ fish_zap_flags |= (ZAP_GENERATES_POWER | ZAP_MOB_STUN) tesla_zap(source = get_turf(src), zap_range = fish_zap_range, power = fish_zap_power, cutoff = 1 MEGA JOULES, zap_flags = fish_zap_flags) +///Returns the price of this fish, for the fish export. +/obj/item/fish/proc/get_export_price(price, percent) + var/size_weight_exponentation = (size * weight * 0.01)^0.85 + var/calculated_price = price + size_weight_exponentation * percent + if(HAS_TRAIT(src, TRAIT_FISH_FROM_CASE)) //Avoid printing money by simply ordering fish and sending it back. + calculated_price *= 0.05 + return round(calculated_price) + /// Returns random fish, using random_case_rarity probabilities. /proc/random_fish_type(required_fluid) var/static/probability_table diff --git a/code/modules/fishing/fish/fish_evolution.dm b/code/modules/fishing/fish/fish_evolution.dm index c04ef2c30796d2..e6e2f1d9570ac4 100644 --- a/code/modules/fishing/fish/fish_evolution.dm +++ b/code/modules/fishing/fish/fish_evolution.dm @@ -88,7 +88,7 @@ GLOBAL_LIST_INIT(fish_evolutions, init_subtypes_w_path_keys(/datum/fish_evolutio conditions_note = "The fish (and its mate) need to be unusually big both in size and weight." /datum/fish_evolution/mastodon/check_conditions(obj/item/fish/source, obj/item/fish/mate, obj/structure/aquarium/aquarium) - if((source.size < 144 || source.weight < 4000) || (mate && (mate.size < 144 || mate.weight < 4000))) + if((source.size < 120 || source.weight < 3000) || (mate && (mate.size < 120 || mate.weight < 3000))) return FALSE return ..() diff --git a/code/modules/fishing/fish/fish_types.dm b/code/modules/fishing/fish/fish_types.dm index 0dbcb3e97ecd96..ce9f36f0553d65 100644 --- a/code/modules/fishing/fish/fish_types.dm +++ b/code/modules/fishing/fish/fish_types.dm @@ -81,6 +81,55 @@ required_temperature_max = MIN_AQUARIUM_TEMP+30 beauty = FISH_BEAUTY_GOOD +/obj/item/fish/tadpole + name = "tadpole" + desc = "The larval spawn of an amphibian. A very minuscle, round creature with a long tail it uses to swim around." + icon_state = "tadpole" + dedicated_in_aquarium_icon_state = "tadpole small" + average_size = 3 + average_weight = 10 + sprite_width = 3 + sprite_height = 1 + health = 50 + feeding_frequency = 1.5 MINUTES + required_temperature_min = MIN_AQUARIUM_TEMP+15 + required_temperature_max = MIN_AQUARIUM_TEMP+20 + fillet_type = null + fish_traits = list(/datum/fish_trait/no_mating) //They grow into frogs and that's it. + beauty = FISH_BEAUTY_NULL + random_case_rarity = FISH_RARITY_NOPE //Why would you want generic frog tadpoles you get from ponds inside fish cases? + /// Once dead, tadpoles disappear after a dozen seconds, since you can get infinite tadpoles. + var/del_timerid + +/obj/item/fish/tadpole/Initialize(mapload, apply_qualities = TRUE) + . = ..() + AddComponent(/datum/component/fish_growth, /mob/living/basic/frog, 100 / rand(2.5, 3 MINUTES) * 10) + RegisterSignal(src, COMSIG_FISH_BEFORE_GROWING, PROC_REF(growth_checks)) + RegisterSignal(src, COMSIG_FISH_FINISH_GROWING, PROC_REF(on_growth)) + +/obj/item/fish/tadpole/set_status(new_status) + . = ..() + if(status == FISH_DEAD) + del_timerid = QDEL_IN_STOPPABLE(src, 12 SECONDS) + else + deltimer(del_timerid) + +/obj/item/fish/tadpole/proc/growth_checks(datum/source, seconds_per_tick) + SIGNAL_HANDLER + var/hunger = CLAMP01((world.time - last_feeding) / feeding_frequency) + if(hunger >= 0.7) //too hungry to grow + return COMPONENT_DONT_GROW + var/obj/structure/aquarium/aquarium = loc + if(!aquarium.allow_breeding) //the aquarium has breeding disabled + return COMPONENT_DONT_GROW + +/obj/item/fish/tadpole/proc/on_growth(datum/source, mob/living/basic/frog/result) + SIGNAL_HANDLER + playsound(result, result.attack_sound, 50, TRUE) // reeeeeeeeeeeeeee... + +/obj/item/fish/tadpole/get_export_price(price, percent) + return 2 //two credits. Tadpoles aren't really that valueable. + // Saltwater fish below /obj/item/fish/clownfish @@ -252,7 +301,7 @@ sprite_height = 9 sprite_width = 8 stable_population = 4 - feeding_frequency = 15 MINUTES + feeding_frequency = 10 MINUTES random_case_rarity = FISH_RARITY_RARE fillet_type = /obj/item/food/meat/slab/rawcrab required_temperature_min = MIN_AQUARIUM_TEMP+9 @@ -270,14 +319,17 @@ evolution_types = list(/datum/fish_evolution/ice_chrab) compatible_types = list(/obj/item/fish/chasm_crab/ice) beauty = FISH_BEAUTY_GOOD - ///Chasm crabs mature into juveline lobstrositiess with time. This is the progess from 0 to 100 - var/maturation = 0 ///This value represents how much the crab needs aren't being met. Higher values translate to a more likely hostile lobstrosity. var/anger = 0 ///The lobstrosity type this matures into var/lob_type = /mob/living/basic/mining/lobstrosity/juvenile/lava ///at which rate the crab gains maturation - var/growth_rate = 100 / (12 MINUTES) * 10 + var/growth_rate = 100 / (10 MINUTES) * 10 + +/obj/item/fish/chasm_crab/Initialize(mapload, apply_qualities = TRUE) + . = ..() + RegisterSignal(src, COMSIG_FISH_BEFORE_GROWING, PROC_REF(growth_checks)) + RegisterSignal(src, COMSIG_FISH_FINISH_GROWING, PROC_REF(on_growth)) ///A chasm crab growth speed is determined by its initial weight and size, ergo bigger crabs for faster lobstrosities /obj/item/fish/chasm_crab/update_size_and_weight(new_size = average_size, new_weight = average_weight) @@ -298,62 +350,41 @@ else if(weight >= 1500) multiplier += min(0.1 * round((weight - 1000) / 500), 2) - growth_rate = initial(growth_rate) * multiplier - -/obj/item/fish/chasm_crab/process(seconds_per_tick) - . = ..() - grow_up(seconds_per_tick) + AddComponent(/datum/component/fish_growth, lob_type, initial(growth_rate) * multiplier) -///Slowly grow up each process tick (in an aquarium). This is its own proc so that it can be used in the unit test. -/obj/item/fish/chasm_crab/proc/grow_up(seconds_per_tick) +/obj/item/fish/chasm_crab/proc/growth_checks(datum/source, seconds_per_tick) + SIGNAL_HANDLER var/hunger = CLAMP01((world.time - last_feeding) / feeding_frequency) if(health <= initial(health) * 0.6 || hunger >= 0.6) //if too hurt or hungry, don't grow. anger += growth_rate * 2 * seconds_per_tick - return + return COMPONENT_DONT_GROW + + if(hunger >= 0.4) //I'm hungry and angry + anger += growth_rate * 0.6 * seconds_per_tick - if(!isaquarium(loc)) //can't grow outside an aquarium. + if(!isaquarium(loc)) return var/obj/structure/aquarium/aquarium = loc if(!aquarium.allow_breeding) //the aquarium has breeding disabled - return - if(hunger >= 0.4) //I'm hungry and angry - anger += growth_rate * 0.6 * seconds_per_tick + return COMPONENT_DONT_GROW if(!locate(/obj/item/aquarium_prop) in aquarium) //the aquarium deco is quite barren anger += growth_rate * 0.25 * seconds_per_tick var/fish_count = length(aquarium.get_fishes()) if(!ISINRANGE(fish_count, 3, AQUARIUM_MAX_BREEDING_POPULATION * 0.5)) //too lonely or overcrowded anger += growth_rate * 0.3 * seconds_per_tick - if(fish_count <= AQUARIUM_MAX_BREEDING_POPULATION * 0.5) //check if there's enough room to maturate. - maturation += growth_rate * seconds_per_tick - - if(maturation >= 100) - return finish_growing() - -///spawn a juvenile lobstrosity on the aquarium turf -/obj/item/fish/chasm_crab/proc/finish_growing() - var/mob/living/basic/mining/lobstrosity/juvenile/lob = new lob_type(get_turf(src)) - for(var/trait_type in fish_traits) - var/datum/fish_trait/trait = GLOB.fish_traits[trait_type] - trait.apply_to_mob(lob) + if(fish_count > AQUARIUM_MAX_BREEDING_POPULATION * 0.5) //check if there's enough room to maturate. + return COMPONENT_DONT_GROW + +/obj/item/fish/chasm_crab/proc/on_growth(datum/source, mob/living/basic/mining/lobstrosity/juvenile/result) + SIGNAL_HANDLER if(!prob(anger)) - lob.AddElement(/datum/element/ai_retaliate) - qdel(lob.ai_controller) - lob.ai_controller = new /datum/ai_controller/basic_controller/lobstrosity/juvenile/calm(lob) + result.AddElement(/datum/element/ai_retaliate) + qdel(result.ai_controller) + result.ai_controller = new /datum/ai_controller/basic_controller/lobstrosity/juvenile/calm(result) else if(anger < 30) //not really that mad, just a bit unstable. - qdel(lob.ai_controller) - lob.ai_controller = new /datum/ai_controller/basic_controller/lobstrosity/juvenile/capricious(lob) - - animate(lob, pixel_y = 18, time = 0.4 SECONDS, flags = ANIMATION_RELATIVE, easing = CUBIC_EASING|EASE_OUT) - animate(pixel_y = -18, time = 0.4 SECONDS, flags = ANIMATION_RELATIVE, easing = CUBIC_EASING|EASE_IN) - loc.visible_message(span_boldnotice("\A [lob] jumps out of [loc]!")) - playsound(loc, 'sound/effects/fish_splash.ogg', 60) - - ///make sure it moves the next tick so that it properly glides to the next location after jumping off the aquarium. - addtimer(CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(random_step), lob, 1, 100), 0.1 SECONDS) - - qdel(src) - return lob + qdel(result.ai_controller) + result.ai_controller = new /datum/ai_controller/basic_controller/lobstrosity/juvenile/capricious(result) /obj/item/fish/chasm_crab/ice name = "arctic chrab" @@ -402,7 +433,7 @@ sprite_height = 5 stable_population = 12 average_size = 110 - average_weight = 10000 + average_weight = 6000 random_case_rarity = FISH_RARITY_GOOD_LUCK_FINDING_THIS required_temperature_min = MIN_AQUARIUM_TEMP+10 required_temperature_max = MIN_AQUARIUM_TEMP+30 @@ -434,7 +465,7 @@ ) beauty = FISH_BEAUTY_DISGUSTING -/obj/item/fish/ratfish/Initialize(mapload) +/obj/item/fish/ratfish/Initialize(mapload, apply_qualities = TRUE) . = ..() //stable pop reflects the config for how many mice migrate. powerful... stable_population = CONFIG_GET(number/mice_roundstart) @@ -451,7 +482,7 @@ average_size = 20 average_weight = 400 health = 50 - breeding_timeout = 5 MINUTES + breeding_timeout = 2.5 MINUTES fish_traits = list(/datum/fish_trait/parthenogenesis, /datum/fish_trait/no_mating) required_temperature_min = MIN_AQUARIUM_TEMP+10 required_temperature_max = MIN_AQUARIUM_TEMP+40 @@ -566,7 +597,7 @@ fish_traits = list(/datum/fish_trait/no_mating) //just to be sure, these shouldn't reproduce experisci_scannable = FALSE -/obj/item/fish/holo/Initialize(mapload) +/obj/item/fish/holo/Initialize(mapload, apply_qualities = TRUE) . = ..() var/area/station/holodeck/holo_area = get_area(src) if(!istype(holo_area)) @@ -655,7 +686,7 @@ fish_traits = list(/datum/fish_trait/antigrav, /datum/fish_trait/mixotroph) beauty = FISH_BEAUTY_GREAT -/obj/item/fish/starfish/Initialize(mapload) +/obj/item/fish/starfish/Initialize(mapload, apply_qualities = TRUE) . = ..() update_appearance(UPDATE_OVERLAYS) @@ -693,7 +724,7 @@ ///maximum bonus damage when winded up var/maximum_bonus = 25 -/obj/item/fish/lavaloop/Initialize(mapload) +/obj/item/fish/lavaloop/Initialize(mapload, apply_qualities = TRUE) . = ..() ADD_TRAIT(src, TRAIT_BYPASS_RANGED_ARMOR, INNATE_TRAIT) AddComponent(/datum/component/boomerang, throw_range, TRUE) diff --git a/code/modules/fishing/fishing_minigame.dm b/code/modules/fishing/fishing_minigame.dm index 0a6b6b7cc87a96..9c70d474a62d73 100644 --- a/code/modules/fishing/fishing_minigame.dm +++ b/code/modules/fishing/fishing_minigame.dm @@ -20,13 +20,15 @@ /// The minimum velocity required for the bait to bounce #define BAIT_MIN_VELOCITY_BOUNCE 150 /// The extra deceleration of velocity that happens when the bait switches direction -#define BAIT_DECELERATION_MULT 1.5 +#define BAIT_DECELERATION_MULT 1.8 /// Reduce initial completion rate depending on difficulty #define MAX_FISH_COMPLETION_MALUS 15 /// The window of time between biting phase and back to baiting phase #define BITING_TIME_WINDOW 4 SECONDS +/// The multiplier of how much the difficulty negatively impacts the bait height +#define BAIT_HEIGHT_DIFFICULTY_MALUS 1.3 ///Defines to know how the bait is moving on the minigame slider. #define REELING_STATE_IDLE 0 @@ -36,7 +38,7 @@ ///The pixel height of the minigame bar #define MINIGAME_SLIDER_HEIGHT 76 ///The standard pixel height of the bait -#define MINIGAME_BAIT_HEIGHT 24 +#define MINIGAME_BAIT_HEIGHT 27 ///The standard pixel height of the fish (minus a pixel on each direction for the sake of a better looking sprite) #define MINIGAME_FISH_HEIGHT 4 @@ -82,7 +84,7 @@ /// How much space the fish takes on the minigame slider var/fish_height = 50 /// How much space the bait takes on the minigame slider - var/bait_height = 320 + var/bait_height = 360 /// The height in pixels of the bait bar var/bait_pixel_height = MINIGAME_BAIT_HEIGHT /// The height in pixels of the fish @@ -182,14 +184,16 @@ if(rod.hook.fishing_hook_traits & FISHING_HOOK_KILL) special_effects |= FISHING_MINIGAME_RULE_KILL + completion_loss += user.mind?.get_skill_modifier(/datum/skill/fishing, SKILL_VALUE_MODIFIER)/5 + if(special_effects & FISHING_MINIGAME_RULE_KILL && ispath(reward_path,/obj/item/fish)) RegisterSignal(comp.fish_source, COMSIG_FISH_SOURCE_REWARD_DISPENSED, PROC_REF(hurt_fish)) difficulty += comp.fish_source.calculate_difficulty(reward_path, rod, user, src) - difficulty = clamp(round(difficulty), 1, 100) + difficulty = clamp(round(difficulty), FISHING_EASY_DIFFICULTY - 5, 100) if(difficulty > FISHING_EASY_DIFFICULTY) - completion -= round(MAX_FISH_COMPLETION_MALUS * (difficulty/100), 1) + completion -= MAX_FISH_COMPLETION_MALUS * (difficulty * 0.01) if(HAS_MIND_TRAIT(user, TRAIT_REVEAL_FISH)) fish_icon = GLOB.specific_fish_icons[reward_path] || "fish" @@ -211,7 +215,7 @@ else long_jump_chance *= difficulty - bait_height -= difficulty + bait_height -= round(difficulty * BAIT_HEIGHT_DIFFICULTY_MALUS) bait_pixel_height = round(MINIGAME_BAIT_HEIGHT * (bait_height/initial(bait_height)), 1) /datum/fishing_challenge/Destroy(force) @@ -277,11 +281,11 @@ //You need to be holding the rod to use it. if(LAZYACCESS(modifiers, SHIFT_CLICK) || LAZYACCESS(modifiers, CTRL_CLICK) || LAZYACCESS(modifiers, ALT_CLICK)) return - if(!source.get_active_held_item(used_rod) && !HAS_TRAIT(source, TRAIT_PROFOUND_FISHER)) + if(!HAS_TRAIT(source, TRAIT_PROFOUND_FISHER) && source.get_active_held_item() != used_rod) return - if(phase == WAIT_PHASE) //Reset wait + if(phase == WAIT_PHASE) send_alert("miss!") - start_baiting_phase(TRUE) + start_baiting_phase(TRUE) //Add in another 3 to 5 seconds for that blunder. else if(phase == BITING_PHASE) start_minigame_phase() return COMSIG_MOB_CANCEL_CLICKON @@ -329,7 +333,7 @@ if(penalty) wait_time = min(timeleft(next_phase_timer) + rand(3 SECONDS, 5 SECONDS), 30 SECONDS) else - wait_time = rand(1 SECONDS, 30 SECONDS) + wait_time = rand(3 SECONDS, 25 SECONDS) if(special_effects & FISHING_MINIGAME_AUTOREEL && wait_time >= 15 SECONDS) wait_time = max(wait_time - 7.5 SECONDS, 15 SECONDS) deltimer(next_phase_timer) @@ -409,7 +413,6 @@ completion *= 1.2 if(BITING_TIME_WINDOW - 0.5 SECONDS to BITING_TIME_WINDOW) completion *= 1.4 - completion = round(completion, 1) if(!prepare_minigame_hud()) return phase = MINIGAME_PHASE @@ -736,6 +739,8 @@ #undef MINIGAME_BAIT_HEIGHT #undef MINIGAME_FISH_HEIGHT +#undef BAIT_HEIGHT_DIFFICULTY_MALUS + #undef REELING_STATE_IDLE #undef REELING_STATE_UP #undef REELING_STATE_DOWN diff --git a/code/modules/fishing/fishing_rod.dm b/code/modules/fishing/fishing_rod.dm index fc39a905a6fdd2..c36ea48b15c020 100644 --- a/code/modules/fishing/fishing_rod.dm +++ b/code/modules/fishing/fishing_rod.dm @@ -101,7 +101,7 @@ /obj/item/fishing_rod/proc/consume_bait(atom/movable/reward) // catching things that aren't fish or alive mobs doesn't consume baits. - if(isnull(reward) || isnull(bait)) + if(isnull(reward) || isnull(bait) || HAS_TRAIT(bait, TRAIT_BAIT_UNCONSUMABLE)) return if(isliving(reward)) var/mob/living/caught_mob = reward @@ -536,7 +536,7 @@ ui_description = "This rod has an infinite supply of synth-bait. Also doubles as an Experi-Scanner for fish." icon_state = "fishing_rod_science" reel_overlay = "reel_science" - bait = /obj/item/food/bait/doughball/synthetic + bait = /obj/item/food/bait/doughball/synthetic/unconsumable /obj/item/fishing_rod/tech/Initialize(mapload) . = ..() @@ -558,9 +558,6 @@ . = ..() . += span_notice("Alt-Click to access the Experiment Configuration UI") -/obj/item/fishing_rod/tech/consume_bait(atom/movable/reward) - return - /obj/item/fishing_rod/tech/use_slot(slot, mob/user, obj/item/new_item) if(slot == ROD_SLOT_BAIT) return @@ -586,24 +583,21 @@ if(owner.hook) icon_state = owner.hook.icon_state transform = transform.Scale(1, -1) - return ..() + . = ..() + if(!QDELETED(src)) + our_line = owner.create_fishing_line(src) /obj/projectile/fishing_cast/on_hit(atom/target, blocked = 0, pierce_hit) . = ..() if(blocked < 100) + QDEL_NULL(our_line) //we need to delete the old beam datum, otherwise it won't let you fish. owner.hook_hit(target) - qdel(src) - -/obj/projectile/fishing_cast/fire(angle, atom/direct_target) - . = ..() - our_line = owner.create_fishing_line(src) /obj/projectile/fishing_cast/Destroy() - . = ..() QDEL_NULL(our_line) owner?.casting = FALSE - - + owner = null + return ..() /datum/beam/fishing_line // Is the fishing rod held in left side hand diff --git a/code/modules/fishing/sources/_fish_source.dm b/code/modules/fishing/sources/_fish_source.dm index 602975ed75a00b..4a0419f98f55f4 100644 --- a/code/modules/fishing/sources/_fish_source.dm +++ b/code/modules/fishing/sources/_fish_source.dm @@ -57,6 +57,11 @@ GLOBAL_LIST_INIT(specific_fish_icons, zebra_typecacheof(list( var/explosive_malus = FALSE /// If explosive_malus is true, this will be used to keep track of the turfs where an explosion happened for when we'll spawn the loot. var/list/exploded_turfs + /// Mindless mobs that can fish will never pull up items on this list + var/static/list/profound_fisher_blacklist = typecacheof(list( + /mob/living/basic/mining/lobstrosity, + /obj/structure/closet/crate/necropolis/tendril, + )) /datum/fish_source/New() if(!PERFORM_ALL_TESTS(focus_only/fish_sources_tables)) @@ -97,7 +102,7 @@ GLOBAL_LIST_INIT(specific_fish_icons, zebra_typecacheof(list( . += EXPERT_FISHER_DIFFICULTY_MOD // Difficulty modifier added by the fisher's skill level - if(!challenge || !(challenge.special_effects & FISHING_MINIGAME_RULE_NO_EXP)) + if(!(challenge?.special_effects & FISHING_MINIGAME_RULE_NO_EXP)) . += fisherman.mind?.get_skill_modifier(/datum/skill/fishing, SKILL_VALUE_MODIFIER) // Difficulty modifier added by the rod @@ -259,6 +264,9 @@ GLOBAL_LIST(fishing_property_cache) ///Multiplier used to make fishes more common compared to everything else. var/result_multiplier = 1 + + var/list/final_table = fish_table.Copy() + if(bait) if(HAS_TRAIT(bait, TRAIT_GREAT_QUALITY_BAIT)) result_multiplier = 9 @@ -269,10 +277,13 @@ GLOBAL_LIST(fishing_property_cache) else if(HAS_TRAIT(bait, TRAIT_BASIC_QUALITY_BAIT)) result_multiplier = 2 leveling_exponent = 0.1 + final_table -= FISHING_DUD var/list/fish_list_properties = collect_fish_properties() - var/list/final_table = fish_table.Copy() + + if(HAS_TRAIT(fisherman, TRAIT_PROFOUND_FISHER) && !fisherman.client) + final_table -= profound_fisher_blacklist for(var/result in final_table) final_table[result] *= rod.hook?.get_hook_bonus_multiplicative(result) final_table[result] += rod.hook?.get_hook_bonus_additive(result)//Decide on order here so it can be multiplicative diff --git a/code/modules/fishing/sources/source_types.dm b/code/modules/fishing/sources/source_types.dm index 583aa3e3e7ea9d..dd5602b12f99da 100644 --- a/code/modules/fishing/sources/source_types.dm +++ b/code/modules/fishing/sources/source_types.dm @@ -45,6 +45,7 @@ catalog_description = "Beach dimension (Fishing portal generator)" radial_name = "Beach" radial_state = "palm_beach" + overlay_state = "portal_beach" /datum/fish_source/portal/chasm background = "background_lavaland" diff --git a/code/modules/food_and_drinks/machinery/processor.dm b/code/modules/food_and_drinks/machinery/processor.dm index 21d49808beda13..383a7c34e27567 100644 --- a/code/modules/food_and_drinks/machinery/processor.dm +++ b/code/modules/food_and_drinks/machinery/processor.dm @@ -159,7 +159,9 @@ var/duration = (total_time / rating_speed) INVOKE_ASYNC(src, TYPE_PROC_REF(/atom, Shake), 1, 0, duration) - sleep(duration) + addtimer(CALLBACK(src, PROC_REF(complete_processing)), duration) + +/obj/machinery/processor/proc/complete_processing() for(var/atom/movable/content_item in processor_contents) var/datum/food_processor_process/recipe = PROCESSOR_SELECT_RECIPE(content_item) if (!recipe) diff --git a/code/modules/food_and_drinks/machinery/smartfridge.dm b/code/modules/food_and_drinks/machinery/smartfridge.dm index b568eaf97c3f0a..6e115af7df2172 100644 --- a/code/modules/food_and_drinks/machinery/smartfridge.dm +++ b/code/modules/food_and_drinks/machinery/smartfridge.dm @@ -32,6 +32,8 @@ var/welded_down = FALSE /// The sound of item retrieval var/vend_sound = 'sound/machines/machine_vend.ogg' + /// Whether the UI should be set to list view by default + var/default_list_view = FALSE /obj/machinery/smartfridge/Initialize(mapload) . = ..() @@ -369,7 +371,7 @@ var/atom/movable/atom = item if (!QDELETED(atom)) - var/key = "[atom.type]" + var/key = "[atom.type]-[atom.name]" if (listofitems[key]) listofitems[key]["amount"]++ else @@ -383,6 +385,7 @@ .["contents"] = sort_list(listofitems) .["name"] = name .["isdryer"] = FALSE + .["default_list_view"] = default_list_view /obj/machinery/smartfridge/Exited(atom/movable/gone, direction) // Update the UIs in case something inside is removed . = ..() @@ -400,6 +403,7 @@ if("Release") var/amount = text2num(params["amount"]) var/desired = 1 + var/dispensed_amount = 0 if(isAI(living_mob)) to_chat(living_mob, span_warning("[src] does not respect your authority!")) @@ -413,18 +417,18 @@ for(var/obj/item/dispensed_item in src) if(desired <= 0) break - if(istype(dispensed_item, text2path(params["path"]))) + if(params["path"] == "[dispensed_item.type]-[dispensed_item.name]") if(dispensed_item in component_parts) CRASH("Attempted removal of [dispensed_item] component_part from smartfridge via smartfridge interface.") //dispense the item if(!living_mob.put_in_hands(dispensed_item)) dispensed_item.forceMove(drop_location()) adjust_item_drop_location(dispensed_item) - if(vend_sound) - playsound(src, vend_sound, 50, TRUE, extrarange = -3) use_energy(active_power_usage) + dispensed_amount++ desired-- - + if(dispensed_amount && vend_sound) + playsound(src, vend_sound, 50, TRUE, extrarange = -3) if (visible_contents) update_appearance() return @@ -727,6 +731,7 @@ desc = "A refrigerated storage unit for medicine storage." base_build_path = /obj/machinery/smartfridge/chemistry contents_overlay_icon = "chem" + default_list_view = TRUE /obj/machinery/smartfridge/chemistry/accept_check(obj/item/weapon) // not an item or reagent container @@ -777,6 +782,7 @@ desc = "A refrigerated storage unit for volatile sample storage." base_build_path = /obj/machinery/smartfridge/chemistry/virology contents_overlay_icon = "viro" + default_list_view = TRUE /obj/machinery/smartfridge/chemistry/virology/preloaded initial_contents = list( diff --git a/code/modules/hydroponics/grown/aloe.dm b/code/modules/hydroponics/grown/aloe.dm index cfbefce6dba21e..0548098732622d 100644 --- a/code/modules/hydroponics/grown/aloe.dm +++ b/code/modules/hydroponics/grown/aloe.dm @@ -1,7 +1,7 @@ // aloe /obj/item/seeds/aloe - name = "pack of aloe seeds" + name = "aloe seed pack" desc = "These seeds grow into aloe." icon_state = "seed-aloe" species = "aloe" diff --git a/code/modules/hydroponics/grown/ambrosia.dm b/code/modules/hydroponics/grown/ambrosia.dm index 2becc390f39802..92cdc2d62c8c1d 100644 --- a/code/modules/hydroponics/grown/ambrosia.dm +++ b/code/modules/hydroponics/grown/ambrosia.dm @@ -11,7 +11,7 @@ // Ambrosia Vulgaris /obj/item/seeds/ambrosia - name = "pack of ambrosia vulgaris seeds" + name = "ambrosia vulgaris seed pack" desc = "These seeds grow into common ambrosia, a plant grown by and from medicine." icon_state = "seed-ambrosiavulgaris" plant_icon_offset = 0 @@ -36,7 +36,7 @@ // Ambrosia Deus /obj/item/seeds/ambrosia/deus - name = "pack of ambrosia deus seeds" + name = "ambrosia deus seed pack" desc = "These seeds grow into ambrosia deus. Could it be the food of the gods..?" icon_state = "seed-ambrosiadeus" species = "ambrosiadeus" @@ -55,7 +55,7 @@ //Ambrosia Gaia /obj/item/seeds/ambrosia/gaia - name = "pack of ambrosia gaia seeds" + name = "ambrosia gaia seed pack" desc = "These seeds grow into ambrosia gaia, filled with infinite potential." icon_state = "seed-ambrosia_gaia" species = "ambrosia_gaia" diff --git a/code/modules/hydroponics/grown/apple.dm b/code/modules/hydroponics/grown/apple.dm index 0079f63ec90230..c1739cc7dea828 100644 --- a/code/modules/hydroponics/grown/apple.dm +++ b/code/modules/hydroponics/grown/apple.dm @@ -1,6 +1,6 @@ // Apple /obj/item/seeds/apple - name = "pack of apple seeds" + name = "apple seed pack" desc = "These seeds grow into apple trees." icon_state = "seed-apple" species = "apple" @@ -31,7 +31,7 @@ // Gold Apple /obj/item/seeds/apple/gold - name = "pack of golden apple seeds" + name = "golden apple seed pack" desc = "These seeds grow into golden apple trees. Good thing there are no firebirds in space." icon_state = "seed-goldapple" species = "goldapple" diff --git a/code/modules/hydroponics/grown/banana.dm b/code/modules/hydroponics/grown/banana.dm index ab38f6889907ad..6e09ee3497cddd 100644 --- a/code/modules/hydroponics/grown/banana.dm +++ b/code/modules/hydroponics/grown/banana.dm @@ -1,6 +1,6 @@ // Banana /obj/item/seeds/banana - name = "pack of banana seeds" + name = "banana seed pack" desc = "They're seeds that grow into banana trees. When grown, keep away from clown." icon_state = "seed-banana" species = "banana" @@ -91,7 +91,7 @@ // Mimana - invisible sprites are totally a feature! /obj/item/seeds/banana/mime - name = "pack of mimana seeds" + name = "mimana seed pack" desc = "They're seeds that grow into mimana trees. When grown, keep away from mime." icon_state = "seed-mimana" species = "mimana" @@ -119,7 +119,7 @@ // Bluespace Banana /obj/item/seeds/banana/bluespace - name = "pack of bluespace banana seeds" + name = "bluespace banana seed pack" desc = "They're seeds that grow into bluespace banana trees. When grown, keep away from bluespace clown." icon_state = "seed-banana-blue" species = "bluespacebanana" diff --git a/code/modules/hydroponics/grown/beans.dm b/code/modules/hydroponics/grown/beans.dm index 974b19889ecba0..885eb77c0c6958 100644 --- a/code/modules/hydroponics/grown/beans.dm +++ b/code/modules/hydroponics/grown/beans.dm @@ -1,6 +1,6 @@ // Soybeans /obj/item/seeds/soya - name = "pack of soybean seeds" + name = "soybean seed pack" desc = "These seeds grow into soybean plants." icon_state = "seed-soybean" species = "soybean" @@ -30,7 +30,7 @@ // Koibean /obj/item/seeds/soya/koi - name = "pack of koibean seeds" + name = "koibean seed pack" desc = "These seeds grow into koibean plants." icon_state = "seed-koibean" species = "koibean" @@ -63,7 +63,7 @@ //Butterbeans, the beans wid da butta! // Butterbeans! - Squeeze for a single butter slice! /obj/item/seeds/soya/butter - name = "pack of butterbean seeds" + name = "butterbean seed pack" desc = "These seeds grow into butterbean plants." icon_state = "seed-butterbean" species = "butterbean" @@ -94,7 +94,7 @@ // Green Beans /obj/item/seeds/greenbean - name = "pack of green bean seeds" + name = "green bean seed pack" desc = "These seeds grow into green bean plants." icon_state = "seed-greenbean" species = "greenbean" @@ -123,7 +123,7 @@ // Jumping Bean /obj/item/seeds/greenbean/jump - name = "pack of jumping bean seeds" + name = "jumping bean seed pack" desc = "These seeds grow into jumping bean plants." icon_state = "seed-jumpingbean" species = "jumpingbean" diff --git a/code/modules/hydroponics/grown/berries.dm b/code/modules/hydroponics/grown/berries.dm index 317f8ef2ed87fc..10631e4dcb0b6c 100644 --- a/code/modules/hydroponics/grown/berries.dm +++ b/code/modules/hydroponics/grown/berries.dm @@ -1,6 +1,6 @@ // Berries /obj/item/seeds/berry - name = "pack of berry seeds" + name = "berry seed pack" desc = "These seeds grow into berry bushes." icon_state = "seed-berry" species = "berry" @@ -31,7 +31,7 @@ // Poison Berries /obj/item/seeds/berry/poison - name = "pack of poison-berry seeds" + name = "poison-berry seed pack" desc = "These seeds grow into poison-berry bushes." icon_state = "seed-poisonberry" species = "poisonberry" @@ -55,7 +55,7 @@ // Death Berries /obj/item/seeds/berry/death - name = "pack of death-berry seeds" + name = "death-berry seed pack" desc = "These seeds grow into death berries." icon_state = "seed-deathberry" species = "deathberry" @@ -81,7 +81,7 @@ // Glow Berries /obj/item/seeds/berry/glow - name = "pack of glow-berry seeds" + name = "glow-berry seed pack" desc = "These seeds grow into glow-berry bushes." icon_state = "seed-glowberry" species = "glowberry" @@ -108,7 +108,7 @@ // Grapes /obj/item/seeds/grape - name = "pack of grape seeds" + name = "grape seed pack" desc = "These seeds grow into grape vines." icon_state = "seed-grapes" species = "grape" @@ -143,7 +143,7 @@ // Green Grapes /obj/item/seeds/grape/green - name = "pack of green grape seeds" + name = "green grape seed pack" desc = "These seeds grow into green-grape vines." icon_state = "seed-greengrapes" species = "greengrape" @@ -162,7 +162,7 @@ // Toechtauese Berries /obj/item/seeds/toechtauese - name = "pack of töchtaüse berry seeds" + name = "töchtaüse berry seed pack" desc = "These seeds grow into töchtaüse bushes." icon_state = "seed-toechtauese" species = "toechtauese" @@ -190,7 +190,7 @@ distill_reagent = /datum/reagent/toxin/itching_powder /obj/item/seeds/lanternfruit - name = "pack of lanternfruit seeds" + name = "lanternfruit seed pack" desc = "These seeds grow into lanternfruit pods." icon_state = "seed-lanternfruit" species = "lanternfruit" diff --git a/code/modules/hydroponics/grown/cannabis.dm b/code/modules/hydroponics/grown/cannabis.dm index c336f0f4b24566..df2cda24b2d624 100644 --- a/code/modules/hydroponics/grown/cannabis.dm +++ b/code/modules/hydroponics/grown/cannabis.dm @@ -1,6 +1,6 @@ // Cannabis /obj/item/seeds/cannabis - name = "pack of cannabis seeds" + name = "cannabis seed pack" desc = "Taxable." icon_state = "seed-cannabis" plant_icon_offset = 6 @@ -24,7 +24,7 @@ /obj/item/seeds/cannabis/rainbow - name = "pack of rainbow weed seeds" + name = "rainbow weed seed pack" desc = "These seeds grow into rainbow weed. Groovy... and also highly addictive." icon_state = "seed-megacannabis" icon_grow = "megacannabis-grow" @@ -36,7 +36,7 @@ rarity = 40 /obj/item/seeds/cannabis/death - name = "pack of deathweed seeds" + name = "deathweed seed pack" desc = "These seeds grow into deathweed. Not groovy." icon_state = "seed-blackcannabis" icon_grow = "blackcannabis-grow" @@ -48,7 +48,7 @@ rarity = 40 /obj/item/seeds/cannabis/white - name = "pack of lifeweed seeds" + name = "lifeweed seed pack" desc = "I will give unto him that is munchies of the fountain of the cravings of life, freely." icon_state = "seed-whitecannabis" icon_grow = "whitecannabis-grow" @@ -62,7 +62,7 @@ /obj/item/seeds/cannabis/ultimate - name = "pack of omega weed seeds" + name = "omega weed seed pack" desc = "These seeds grow into omega weed." icon_state = "seed-ocannabis" plant_icon_offset = 0 diff --git a/code/modules/hydroponics/grown/cereals.dm b/code/modules/hydroponics/grown/cereals.dm index 744c0dc5b023cf..b304382d2dc471 100644 --- a/code/modules/hydroponics/grown/cereals.dm +++ b/code/modules/hydroponics/grown/cereals.dm @@ -1,6 +1,6 @@ // Wheat /obj/item/seeds/wheat - name = "pack of wheat seeds" + name = "wheat seed pack" desc = "These may, or may not, grow into wheat." icon_state = "seed-wheat" species = "wheat" @@ -30,7 +30,7 @@ // Oat /obj/item/seeds/wheat/oat - name = "pack of oat seeds" + name = "oat seed pack" desc = "These may, or may not, grow into oat." icon_state = "seed-oat" species = "oat" @@ -52,7 +52,7 @@ // Rice /obj/item/seeds/wheat/rice - name = "pack of rice seeds" + name = "rice seed pack" desc = "These may, or may not, grow into rice." icon_state = "seed-rice" species = "rice" @@ -76,7 +76,7 @@ //Meatwheat - grows into synthetic meat /obj/item/seeds/wheat/meat - name = "pack of meatwheat seeds" + name = "meatwheat seed pack" desc = "If you ever wanted to drive a vegetarian to insanity, here's how." icon_state = "seed-meatwheat" species = "meatwheat" diff --git a/code/modules/hydroponics/grown/cherries.dm b/code/modules/hydroponics/grown/cherries.dm index 4ebd42489d96f8..ad35bacf8fe71a 100644 --- a/code/modules/hydroponics/grown/cherries.dm +++ b/code/modules/hydroponics/grown/cherries.dm @@ -1,6 +1,6 @@ // Cherries /obj/item/seeds/cherry - name = "pack of cherry pits" + name = "cherry pit pack" desc = "Careful not to crack a tooth on one... That'd be the pits." icon_state = "seed-cherry" species = "cherry" @@ -34,7 +34,7 @@ // Blue Cherries /obj/item/seeds/cherry/blue - name = "pack of blue cherry pits" + name = "blue cherry pit pack" desc = "The blue kind of cherries." icon_state = "seed-bluecherry" species = "bluecherry" @@ -57,7 +57,7 @@ //Cherry Bulbs /obj/item/seeds/cherry/bulb - name = "pack of cherry bulb pits" + name = "cherry bulb pit pack" desc = "The glowy kind of cherries." icon_state = "seed-cherrybulb" species = "cherrybulb" @@ -82,7 +82,7 @@ //Cherry Bombs /obj/item/seeds/cherry/bomb - name = "pack of cherry bomb pits" + name = "cherry bomb pit pack" desc = "They give you vibes of dread and frustration." icon_state = "seed-cherry_bomb" species = "cherry_bomb" diff --git a/code/modules/hydroponics/grown/chili.dm b/code/modules/hydroponics/grown/chili.dm index 9f6d3bbd08ce0e..1d9aaa8468ebf0 100644 --- a/code/modules/hydroponics/grown/chili.dm +++ b/code/modules/hydroponics/grown/chili.dm @@ -1,6 +1,6 @@ // Chili /obj/item/seeds/chili - name = "pack of chili seeds" + name = "chili seed pack" desc = "These seeds grow into chili plants. HOT! HOT! HOT!" icon_state = "seed-chili" species = "chili" @@ -30,7 +30,7 @@ // Ice Chili /obj/item/seeds/chili/ice - name = "pack of chilly pepper seeds" + name = "chilly pepper seed pack" desc = "These seeds grow into chilly pepper plants." icon_state = "seed-icepepper" species = "chiliice" @@ -56,7 +56,7 @@ // Ghost Chili /obj/item/seeds/chili/ghost - name = "pack of ghost chili seeds" + name = "ghost chili seed pack" desc = "These seeds grow into a chili said to be the hottest in the galaxy." icon_state = "seed-chilighost" species = "chilighost" @@ -83,7 +83,7 @@ // Bell Pepper /obj/item/seeds/chili/bell_pepper - name = "pack of bell pepper seeds" + name = "bell pepper seed pack" desc = "These seeds grow into bell pepper plants. MILD! MILD! MILD!" icon_state = "seed-bell-pepper" species = "bellpepper" diff --git a/code/modules/hydroponics/grown/citrus.dm b/code/modules/hydroponics/grown/citrus.dm index c624722f82392b..6bfc8bc203af53 100644 --- a/code/modules/hydroponics/grown/citrus.dm +++ b/code/modules/hydroponics/grown/citrus.dm @@ -9,7 +9,7 @@ // Lime /obj/item/seeds/lime - name = "pack of lime seeds" + name = "lime seed pack" desc = "These are very sour seeds." icon_state = "seed-lime" species = "lime" @@ -33,7 +33,7 @@ // Orange /obj/item/seeds/orange - name = "pack of orange seeds" + name = "orange seed pack" desc = "Sour seeds." icon_state = "seed-orange" species = "orange" @@ -61,7 +61,7 @@ // Lemon /obj/item/seeds/lemon - name = "pack of lemon seeds" + name = "lemon seed pack" desc = "These are sour seeds." icon_state = "seed-lemon" species = "lemon" @@ -86,7 +86,7 @@ // Combustible lemon /obj/item/seeds/firelemon //combustible lemon is too long so firelemon - name = "pack of combustible lemon seeds" + name = "combustible lemon seed pack" desc = "When life gives you lemons, don't make lemonade. Make life take the lemons back! Get mad! I don't want your damn lemons!" icon_state = "seed-firelemon" species = "firelemon" @@ -112,7 +112,7 @@ //3D Orange /obj/item/seeds/orange_3d - name = "pack of extradimensional orange seeds" + name = "extradimensional orange seed pack" desc = "Polygonal seeds." icon_state = "seed-orange" species = "orange" diff --git a/code/modules/hydroponics/grown/cocoa_vanilla.dm b/code/modules/hydroponics/grown/cocoa_vanilla.dm index 4e9a9810b42804..e4b6c916f7cc99 100644 --- a/code/modules/hydroponics/grown/cocoa_vanilla.dm +++ b/code/modules/hydroponics/grown/cocoa_vanilla.dm @@ -1,6 +1,6 @@ // Cocoa Pod /obj/item/seeds/cocoapod - name = "pack of cocoa pod seeds" + name = "cocoa pod seed pack" desc = "These seeds grow into cacao trees. They look fattening." //SIC: cocoa is the seeds. The trees are spelled cacao. icon_state = "seed-cocoapod" species = "cocoapod" @@ -31,7 +31,7 @@ // Vanilla Pod /obj/item/seeds/cocoapod/vanillapod - name = "pack of vanilla pod seeds" + name = "vanilla pod seed pack" desc = "These seeds grow into vanilla trees. They look fattening." icon_state = "seed-vanillapod" species = "vanillapod" @@ -52,7 +52,7 @@ distill_reagent = /datum/reagent/consumable/vanilla //Takes longer, but you can get even more vanilla from it. /obj/item/seeds/cocoapod/bungotree - name = "pack of bungo tree seeds" + name = "bungo tree seed pack" desc = "These seeds grow into bungo trees. They appear to be heavy and almost perfectly spherical." icon_state = "seed-bungotree" plant_icon_offset = 4 diff --git a/code/modules/hydroponics/grown/corn.dm b/code/modules/hydroponics/grown/corn.dm index d5f9f94e1b2dfd..02f77280c5ab9c 100644 --- a/code/modules/hydroponics/grown/corn.dm +++ b/code/modules/hydroponics/grown/corn.dm @@ -1,6 +1,6 @@ // Corn /obj/item/seeds/corn - name = "pack of corn seeds" + name = "corn seed pack" desc = "I don't mean to sound corny..." icon_state = "seed-corn" species = "corn" @@ -57,7 +57,7 @@ // Snapcorn /obj/item/seeds/corn/snapcorn - name = "pack of snapcorn seeds" + name = "snapcorn seed pack" desc = "Oh snap!" icon_state = "seed-snapcorn" species = "snapcorn" @@ -100,7 +100,7 @@ //Pepper-corn - Heh funny. /obj/item/seeds/corn/pepper - name = "pack of pepper-corn seeds" + name = "pepper-corn seed pack" desc = "If Peter picked a pack of pepper-corn..." icon_state = "seed-peppercorn" species = "peppercorn" diff --git a/code/modules/hydroponics/grown/cotton.dm b/code/modules/hydroponics/grown/cotton.dm index 819d97f321f8de..c2149b7a330061 100644 --- a/code/modules/hydroponics/grown/cotton.dm +++ b/code/modules/hydroponics/grown/cotton.dm @@ -1,5 +1,5 @@ /obj/item/seeds/cotton - name = "pack of cotton seeds" + name = "cotton seed pack" desc = "A pack of seeds that'll grow into a cotton plant. Assistants make good free labor if neccesary." icon_state = "seed-cotton" species = "cotton" @@ -45,7 +45,7 @@ //reinforced mutated variant /obj/item/seeds/cotton/durathread - name = "pack of durathread seeds" + name = "durathread seed pack" desc = "A pack of seeds that'll grow into an extremely durable thread that could easily rival plasteel if woven properly." icon_state = "seed-durathread" species = "durathread" diff --git a/code/modules/hydroponics/grown/cucumber.dm b/code/modules/hydroponics/grown/cucumber.dm index f3712c6a5c90a7..a8487a0cac9bc7 100644 --- a/code/modules/hydroponics/grown/cucumber.dm +++ b/code/modules/hydroponics/grown/cucumber.dm @@ -1,6 +1,6 @@ // CUCUMBERS YEAH /obj/item/seeds/cucumber - name = "pack of cucumber seeds" + name = "cucumber seed pack" desc = "These seeds grow into cucumber plants." icon_state = "seed-cucumber" species = "cucumber" diff --git a/code/modules/hydroponics/grown/eggplant.dm b/code/modules/hydroponics/grown/eggplant.dm index d4b38c3438bdbe..47cbc6d934cd38 100644 --- a/code/modules/hydroponics/grown/eggplant.dm +++ b/code/modules/hydroponics/grown/eggplant.dm @@ -1,6 +1,6 @@ // Eggplant /obj/item/seeds/eggplant - name = "pack of eggplant seeds" + name = "eggplant seed pack" desc = "These seeds grow to produce berries that look nothing like eggs." icon_state = "seed-eggplant" species = "eggplant" @@ -25,7 +25,7 @@ // Egg-Plant /obj/item/seeds/eggplant/eggy - name = "pack of egg-plant seeds" + name = "egg-plant seed pack" desc = "These seeds grow to produce berries that look a lot like eggs." icon_state = "seed-eggy" species = "eggy" diff --git a/code/modules/hydroponics/grown/flowers.dm b/code/modules/hydroponics/grown/flowers.dm index 84b1414335cafa..d4ef53474fc975 100644 --- a/code/modules/hydroponics/grown/flowers.dm +++ b/code/modules/hydroponics/grown/flowers.dm @@ -1,6 +1,6 @@ // Poppy /obj/item/seeds/poppy - name = "pack of poppy seeds" + name = "poppy seed pack" desc = "These seeds grow into poppies." icon_state = "seed-poppy" species = "poppy" @@ -32,7 +32,7 @@ // Lily /obj/item/seeds/poppy/lily - name = "pack of lily seeds" + name = "lily seed pack" desc = "These seeds grow into lilies." icon_state = "seed-lily" species = "lily" @@ -52,7 +52,7 @@ //Spacemans's Trumpet /obj/item/seeds/poppy/lily/trumpet - name = "pack of spaceman's trumpet seeds" + name = "spaceman's trumpet seed pack" desc = "A plant sculped by extensive genetic engineering. The spaceman's trumpet is said to bear no resemblance to its wild ancestors. Inside NT AgriSci circles it is better known as NTPW-0372." icon_state = "seed-trumpet" species = "spacemanstrumpet" @@ -86,7 +86,7 @@ // Geranium /obj/item/seeds/poppy/geranium - name = "pack of geranium seeds" + name = "geranium seed pack" desc = "These seeds grow into geranium." icon_state = "seed-geranium" species = "geranium" @@ -106,7 +106,7 @@ ///Fraxinella seeds. /obj/item/seeds/poppy/geranium/fraxinella - name = "pack of fraxinella seeds" + name = "fraxinella seed pack" desc = "These seeds grow into fraxinella." icon_state = "seed-fraxinella" species = "fraxinella" @@ -130,7 +130,7 @@ // Harebell /obj/item/seeds/harebell - name = "pack of harebell seeds" + name = "harebell seed pack" desc = "These seeds grow into pretty little flowers." icon_state = "seed-harebell" plant_icon_offset = 1 @@ -162,7 +162,7 @@ // Sunflower /obj/item/seeds/sunflower - name = "pack of sunflower seeds" + name = "sunflower seed pack" desc = "These seeds grow into sunflowers." icon_state = "seed-sunflower" species = "sunflower" @@ -203,7 +203,7 @@ // Moonflower /obj/item/seeds/sunflower/moonflower - name = "pack of moonflower seeds" + name = "moonflower seed pack" desc = "These seeds grow into moonflowers." icon_state = "seed-moonflower" lefthand_file = 'icons/mob/inhands/items/food_lefthand.dmi' @@ -231,7 +231,7 @@ // Novaflower /obj/item/seeds/sunflower/novaflower - name = "pack of novaflower seeds" + name = "novaflower seed pack" desc = "These seeds grow into novaflowers." icon_state = "seed-novaflower" species = "novaflower" @@ -266,7 +266,7 @@ // Rose /obj/item/seeds/rose - name = "pack of rose seeds" + name = "rose seed pack" desc = "These seeds grow into roses." icon_state = "seed-rose" species = "rose" @@ -311,7 +311,7 @@ // Carbon Rose /obj/item/seeds/carbon_rose - name = "pack of carbon rose seeds" + name = "carbon rose seed pack" desc = "These seeds grow into carbon roses." icon_state = "seed-carbonrose" species = "carbonrose" diff --git a/code/modules/hydroponics/grown/garlic.dm b/code/modules/hydroponics/grown/garlic.dm index e37d49fa93032f..755d0c2920a3f8 100644 --- a/code/modules/hydroponics/grown/garlic.dm +++ b/code/modules/hydroponics/grown/garlic.dm @@ -1,5 +1,5 @@ /obj/item/seeds/garlic - name = "pack of garlic seeds" + name = "garlic seed pack" desc = "A packet of extremely pungent seeds." icon_state = "seed-garlic" species = "garlic" diff --git a/code/modules/hydroponics/grown/gatfruit.dm b/code/modules/hydroponics/grown/gatfruit.dm index f64b6eb3bd4819..c6de17d6eb684c 100644 --- a/code/modules/hydroponics/grown/gatfruit.dm +++ b/code/modules/hydroponics/grown/gatfruit.dm @@ -1,7 +1,7 @@ // Gatfruit /obj/item/seeds/gatfruit - name = "pack of gatfruit seeds" + name = "gatfruit seed pack" desc = "These seeds grow into .357 revolvers." icon_state = "seed-gatfruit" species = "gatfruit" diff --git a/code/modules/hydroponics/grown/grass_carpet.dm b/code/modules/hydroponics/grown/grass_carpet.dm index 732a6d32b881b7..a5cdc08fb7658f 100644 --- a/code/modules/hydroponics/grown/grass_carpet.dm +++ b/code/modules/hydroponics/grown/grass_carpet.dm @@ -1,6 +1,6 @@ // Grass /obj/item/seeds/grass - name = "pack of grass seeds" + name = "grass seed pack" desc = "These seeds grow into grass. Yummy!" icon_state = "seed-grass" species = "grass" @@ -42,7 +42,7 @@ //Fairygrass /obj/item/seeds/grass/fairy - name = "pack of fairygrass seeds" + name = "fairygrass seed pack" desc = "These seeds grow into a more mystical grass." icon_state = "seed-fairygrass" species = "fairygrass" @@ -65,7 +65,7 @@ // Carpet /obj/item/seeds/grass/carpet - name = "pack of carpet seeds" + name = "carpet seed pack" desc = "These seeds grow into stylish carpet samples." icon_state = "seed-carpet" species = "carpet" diff --git a/code/modules/hydroponics/grown/hedges.dm b/code/modules/hydroponics/grown/hedges.dm index 9127f70f78fd46..d02949bfd98136 100644 --- a/code/modules/hydroponics/grown/hedges.dm +++ b/code/modules/hydroponics/grown/hedges.dm @@ -1,5 +1,5 @@ /obj/item/seeds/shrub - name = "pack of shrub seeds" + name = "shrub seed pack" desc = "These seeds grow into hedge shrubs." icon_state = "seed-shrub" species = "shrub" diff --git a/code/modules/hydroponics/grown/herbs.dm b/code/modules/hydroponics/grown/herbs.dm index b22be06ec6aca6..bc450d6857f188 100644 --- a/code/modules/hydroponics/grown/herbs.dm +++ b/code/modules/hydroponics/grown/herbs.dm @@ -1,6 +1,6 @@ // Herbs /obj/item/seeds/herbs - name = "pack of herb seeds" + name = "herb seed pack" desc = "These seeds grow to produce an assortment of herbs and seasonings." icon_state = "seed-herbs" species = "herbs" diff --git a/code/modules/hydroponics/grown/korta_nut.dm b/code/modules/hydroponics/grown/korta_nut.dm index cfa6c1e5b51f33..457ebff07163ed 100644 --- a/code/modules/hydroponics/grown/korta_nut.dm +++ b/code/modules/hydroponics/grown/korta_nut.dm @@ -1,6 +1,6 @@ //Korta Nut /obj/item/seeds/korta_nut - name = "pack of korta nut seeds" + name = "korta nut seed pack" desc = "These seeds grow into korta nut bushes, native to Tizira." icon_state = "seed-korta" species = "kortanut" @@ -29,7 +29,7 @@ //Sweet Korta Nut /obj/item/seeds/korta_nut/sweet - name = "pack of sweet korta nut seeds" + name = "sweet korta nut seed pack" desc = "These seeds grow into sweet korta nuts, a mutation of the original species that produces a thick syrup that Tizirans use for desserts." icon_state = "seed-sweetkorta" species = "kortanut" diff --git a/code/modules/hydroponics/grown/kronkus.dm b/code/modules/hydroponics/grown/kronkus.dm index 90d264230e7503..b4ba30a5eddbe6 100644 --- a/code/modules/hydroponics/grown/kronkus.dm +++ b/code/modules/hydroponics/grown/kronkus.dm @@ -1,5 +1,5 @@ /obj/item/seeds/kronkus - name = "pack of kronkus seeds" + name = "kronkus seed pack" desc = "A pack of highly illegal kronkus seeds.\nPossession of these seeds carries the death penalty in 7 sectors." icon_state = "seed-kronkus" plant_icon_offset = 6 diff --git a/code/modules/hydroponics/grown/melon.dm b/code/modules/hydroponics/grown/melon.dm index 0e59231141fc43..3aca50ae1be54f 100644 --- a/code/modules/hydroponics/grown/melon.dm +++ b/code/modules/hydroponics/grown/melon.dm @@ -1,6 +1,6 @@ // Watermelon /obj/item/seeds/watermelon - name = "pack of watermelon seeds" + name = "watermelon seed pack" desc = "These seeds grow into watermelon plants." icon_state = "seed-watermelon" species = "watermelon" @@ -27,6 +27,7 @@ name = "watermelon" desc = "It's full of watery goodness." icon_state = "watermelon" + inhand_icon_state = "watermelon" bite_consumption_mod = 2 w_class = WEIGHT_CLASS_NORMAL foodtypes = FRUIT @@ -39,9 +40,41 @@ /obj/item/food/grown/watermelon/make_dryable() return //No drying +/obj/item/food/grown/watermelon/attackby(obj/item/I, mob/user, params) + if(!istype(I, /obj/item/kitchen/spoon)) + return ..() + + var/melon_pulp_count = 1 + if(seed) + melon_pulp_count += round(seed.potency / 25) + + user.balloon_alert(user, "scooped out [melon_pulp_count] pulp(s)") + for(var/i in 1 to melon_pulp_count) + new /obj/item/food/watermelonmush(user.loc) + + /// The piece of armour melon turns into; either chetsplate or helmet + var/obj/item/clothing/melon_armour + /// Chance for the armour to be a chestplate instead of the helmet + var/melon_chestplate_chance = (max(0, seed.potency - 50) / 50) + if (prob(melon_chestplate_chance)) + if(seed.resistance_flags & FIRE_PROOF) + melon_armour = new /obj/item/clothing/suit/armor/durability/watermelon/fire_resist + else + melon_armour = new /obj/item/clothing/suit/armor/durability/watermelon + to_chat(user, span_notice("You hollow the melon into a helmet with [I].")) + else + if(seed.resistance_flags & FIRE_PROOF) + melon_armour = new /obj/item/clothing/head/helmet/durability/watermelon/fire_resist + else + melon_armour = new /obj/item/clothing/head/helmet/durability/watermelon + to_chat(user, span_notice("You hollow the melon into a chestplate with [I].")) + remove_item_from_storage(user) + qdel(src) + user.put_in_hands(melon_armour) + // Holymelon /obj/item/seeds/watermelon/holy - name = "pack of holymelon seeds" + name = "holymelon seed pack" desc = "These seeds grow into holymelon plants." icon_state = "seed-holymelon" species = "holymelon" @@ -66,6 +99,9 @@ wine_power = 70 //Water to wine, baby. wine_flavor = "divinity" +/obj/item/food/grown/holymelon/make_processable() + AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/holymelonslice, 5, 20, screentip_verb = "Slice") + /obj/item/food/grown/holymelon/make_dryable() return //No drying @@ -73,6 +109,39 @@ . = ..() AddComponent(/datum/component/edible, check_liked = CALLBACK(src, PROC_REF(check_holyness))) + +/obj/item/food/grown/holymelon/attackby(obj/item/I, mob/user, params) + if(!istype(I, /obj/item/kitchen/spoon)) + return ..() + + var/holymelon_pulp_count = 1 + if(seed) + holymelon_pulp_count += round(seed.potency / 25) + + user.balloon_alert(user, "scooped out [holymelon_pulp_count] pulp(s)") + for(var/i in 1 to holymelon_pulp_count) + new /obj/item/food/holymelonmush(user.loc) + + /// The piece of armour holymelon turns into; either chetsplate or helmet + var/obj/item/clothing/holymelon_armour + /// Chance for the armour to be a chestplate instead of the helmet + var/holymelon_chestplate_chance = (max(0, seed.potency - 50) / 50) + if (prob(holymelon_chestplate_chance)) + if(seed.resistance_flags & FIRE_PROOF) + holymelon_armour = new /obj/item/clothing/suit/armor/durability/holymelon/fire_resist + else + holymelon_armour = new /obj/item/clothing/suit/armor/durability/holymelon + to_chat(user, span_notice("You hollow the holymelon into a helmet with [I].")) + else + if(seed.resistance_flags & FIRE_PROOF) + holymelon_armour = new /obj/item/clothing/head/helmet/durability/holymelon/fire_resist + else + holymelon_armour = new /obj/item/clothing/head/helmet/durability/holymelon + to_chat(user, span_notice("You hollow the holymelon into a chestplate with [I].")) + remove_item_from_storage(user) + qdel(src) + user.put_in_hands(holymelon_armour) + /* * Callback to be used with the edible component. * Checks whether or not the person eating the holymelon @@ -90,7 +159,7 @@ /// Barrel melon Seeds /obj/item/seeds/watermelon/barrel - name = "pack of barrelmelon seeds" + name = "barrelmelon seed pack" desc = "These seeds grow into barrelmelon plants." icon_state = "seed-barrelmelon" species = "barrelmelon" @@ -108,4 +177,41 @@ name = "barrelmelon" desc = "The nutriments within this melon have been compressed and fermented into rich alcohol." icon_state = "barrelmelon" + inhand_icon_state = "barrelmelon" distill_reagent = /datum/reagent/medicine/antihol //You can call it a integer overflow. + +/obj/item/food/grown/barrelmelon/make_processable() + AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/barrelmelonslice, 5, 20, screentip_verb = "Chop") + +/obj/item/food/grown/barrelmelon/attackby(obj/item/I, mob/user, params) + if(!istype(I, /obj/item/kitchen/spoon)) + return ..() + + var/barrelmelon_pulp_count = 1 + if(seed) + barrelmelon_pulp_count += round(seed.potency / 25) + + user.balloon_alert(user, "scooped out [barrelmelon_pulp_count] pulp(s)") + for(var/i in 1 to barrelmelon_pulp_count) + new /obj/item/food/barrelmelonmush(user.loc) + + /// The piece of armour barrelmelon turns into; either chetsplate or helmet + var/obj/item/clothing/barrelmelon_armour + /// Chance for the armour to be a chestplate instead of the helmet + var/barrelmelon_chestplate_chance = (max(0, seed.potency - 50) / 50) + if (prob(barrelmelon_chestplate_chance)) + if(seed.resistance_flags & FIRE_PROOF) + barrelmelon_armour = new /obj/item/clothing/suit/armor/durability/barrelmelon/fire_resist + else + barrelmelon_armour = new /obj/item/clothing/suit/armor/durability/barrelmelon + to_chat(user, span_notice("You hollow the barrelmelon into a helmet with [I].")) + else + if(seed.resistance_flags & FIRE_PROOF) + barrelmelon_armour = new /obj/item/clothing/head/helmet/durability/barrelmelon/fire_resist + else + barrelmelon_armour = new /obj/item/clothing/head/helmet/durability/barrelmelon + to_chat(user, span_notice("You hollow the barrelmelon into a chestplate with [I].")) + + remove_item_from_storage(user) + qdel(src) + user.put_in_hands(barrelmelon_armour) diff --git a/code/modules/hydroponics/grown/mushrooms.dm b/code/modules/hydroponics/grown/mushrooms.dm index bfc50f0c483b3b..9d1d802916bff4 100644 --- a/code/modules/hydroponics/grown/mushrooms.dm +++ b/code/modules/hydroponics/grown/mushrooms.dm @@ -11,7 +11,7 @@ // Reishi /obj/item/seeds/reishi - name = "pack of reishi mycelium" + name = "reishi mycelium pack" desc = "This mycelium grows into something medicinal and relaxing." icon_state = "mycelium-reishi" species = "reishi" @@ -38,7 +38,7 @@ // Fly Amanita /obj/item/seeds/amanita - name = "pack of fly amanita mycelium" + name = "fly amanita mycelium pack" desc = "This mycelium grows into something horrible." icon_state = "mycelium-amanita" species = "amanita" @@ -65,7 +65,7 @@ // Destroying Angel /obj/item/seeds/angel - name = "pack of destroying angel mycelium" + name = "destroying angel mycelium pack" desc = "This mycelium grows into something devastating." icon_state = "mycelium-angel" species = "angel" @@ -93,7 +93,7 @@ // Liberty Cap /obj/item/seeds/liberty - name = "pack of liberty-cap mycelium" + name = "liberty-cap mycelium pack" desc = "This mycelium grows into liberty-cap mushrooms." icon_state = "mycelium-liberty" species = "liberty" @@ -119,7 +119,7 @@ // Plump Helmet /obj/item/seeds/plump - name = "pack of plump-helmet mycelium" + name = "plump-helmet mycelium pack" desc = "This mycelium grows into helmets... maybe." icon_state = "mycelium-plump" species = "plump" @@ -145,7 +145,7 @@ // Walking Mushroom /obj/item/seeds/plump/walkingmushroom - name = "pack of walking mushroom mycelium" + name = "walking mushroom mycelium pack" desc = "This mycelium will grow into huge stuff!" icon_state = "mycelium-walkingmushroom" species = "walkingmushroom" @@ -171,7 +171,7 @@ // Chanterelle /obj/item/seeds/chanter - name = "pack of chanterelle mycelium" + name = "chanterelle mycelium pack" desc = "This mycelium grows into chanterelle mushrooms." icon_state = "mycelium-chanter" species = "chanter" @@ -197,9 +197,23 @@ desc = "Cantharellus Cibarius: These jolly yellow little shrooms sure look tasty!" icon_state = "chanterelle" +/obj/item/food/grown/mushroom/chanterelle/attackby(obj/item/I, mob/user, params) + if(!istype(I, /obj/item/kitchen/spoon)) + return ..() + if(seed.potency < 95) + return ..() + + to_chat(user, span_notice("You hollow up the chanterelle with [I].")) + remove_item_from_storage(user) + qdel(src) + if(seed.resistance_flags & FIRE_PROOF) + user.put_in_hands(new /obj/item/clothing/head/wizard/chanterelle/fr()) + else + user.put_in_hands(new /obj/item/clothing/head/wizard/chanterelle()) + //Jupiter Cup /obj/item/seeds/chanter/jupitercup - name = "pack of jupiter cup mycelium" + name = "jupiter cup mycelium pack" desc = "This mycelium grows into jupiter cups. Zeus would be envious at the power at your fingertips." icon_state = "mycelium-jupitercup" species = "jupitercup" @@ -224,7 +238,7 @@ // Glowshroom /obj/item/seeds/glowshroom - name = "pack of glowshroom mycelium" + name = "glowshroom mycelium pack" desc = "This mycelium -glows- into mushrooms!" icon_state = "mycelium-glowshroom" species = "glowshroom" @@ -279,7 +293,7 @@ // Glowcap /obj/item/seeds/glowshroom/glowcap - name = "pack of glowcap mycelium" + name = "glowcap mycelium pack" desc = "This mycelium -powers- into mushrooms!" icon_state = "mycelium-glowcap" species = "glowcap" @@ -303,7 +317,7 @@ //Shadowshroom /obj/item/seeds/glowshroom/shadowshroom - name = "pack of shadowshroom mycelium" + name = "shadowshroom mycelium pack" desc = "This mycelium will grow into something shadowy." icon_state = "mycelium-shadowshroom" species = "shadowshroom" @@ -332,7 +346,7 @@ investigate_log("was planted by [key_name(user)] at [AREACOORD(user)]", INVESTIGATE_BOTANY) /obj/item/seeds/odious_puffball - name = "pack of odious pullball spores" + name = "odious pullball spore pack" desc = "These spores reek! Disgusting." icon_state = "seed-odiouspuffball" species = "odiouspuffball" diff --git a/code/modules/hydroponics/grown/olive.dm b/code/modules/hydroponics/grown/olive.dm index 38102cacb24eab..0b2f52c7a5e7bb 100644 --- a/code/modules/hydroponics/grown/olive.dm +++ b/code/modules/hydroponics/grown/olive.dm @@ -1,6 +1,6 @@ // Olive /obj/item/seeds/olive - name = "pack of olive seeds" + name = "olive seed pack" desc = "These seeds grow into olive trees." icon_state = "seed-olive" species = "olive" diff --git a/code/modules/hydroponics/grown/onion.dm b/code/modules/hydroponics/grown/onion.dm index 8f948407a37b85..0d33c3e1f395d7 100644 --- a/code/modules/hydroponics/grown/onion.dm +++ b/code/modules/hydroponics/grown/onion.dm @@ -1,5 +1,5 @@ /obj/item/seeds/onion - name = "pack of onion seeds" + name = "onion seed pack" desc = "These seeds grow into onions." icon_state = "seed-onion" species = "onion" @@ -29,7 +29,7 @@ AddElement(/datum/element/processable, TOOL_KNIFE, /obj/item/food/onion_slice, 2, 15, screentip_verb = "Cut") /obj/item/seeds/onion/red - name = "pack of red onion seeds" + name = "red onion seed pack" desc = "For growing exceptionally potent onions." icon_state = "seed-onionred" species = "onion_red" diff --git a/code/modules/hydroponics/grown/peanut.dm b/code/modules/hydroponics/grown/peanut.dm index 69cf6d9e0568dc..6560ec196c9189 100644 --- a/code/modules/hydroponics/grown/peanut.dm +++ b/code/modules/hydroponics/grown/peanut.dm @@ -1,6 +1,6 @@ // Peanuts! /obj/item/seeds/peanut - name = "pack of peanut seeds" + name = "peanut seed pack" desc = "These seeds grow into peanut plants." icon_state = "seed-peanut" species = "peanut" diff --git a/code/modules/hydroponics/grown/peas.dm b/code/modules/hydroponics/grown/peas.dm index c232ed247c6905..66eaec6ff1d54d 100644 --- a/code/modules/hydroponics/grown/peas.dm +++ b/code/modules/hydroponics/grown/peas.dm @@ -1,6 +1,6 @@ // Finally, peas. Base plant. /obj/item/seeds/peas - name = "pack of pea pods" + name = "pea pod pack" desc = "These seeds grows into vitamin rich peas!" icon_state = "seed-peas" species = "peas" @@ -29,7 +29,7 @@ // Laughin' Peas /obj/item/seeds/peas/laugh - name = "pack of laughin' peas" + name = "laughin' pea pack" desc = "These seeds give off a very soft purple glow.. they should grow into Laughin' Peas." icon_state = "seed-laughpeas" species = "laughpeas" @@ -61,7 +61,7 @@ // World Peas - Peace at last, peace at last... /obj/item/seeds/peas/laugh/peace - name = "pack of world peas" + name = "world pea pack" desc = "These rather large seeds give off a soothing blue glow..." icon_state = "seed-worldpeas" species = "worldpeas" diff --git a/code/modules/hydroponics/grown/pineapple.dm b/code/modules/hydroponics/grown/pineapple.dm index 3c0e462f38855c..5de85e9168f1f5 100644 --- a/code/modules/hydroponics/grown/pineapple.dm +++ b/code/modules/hydroponics/grown/pineapple.dm @@ -1,6 +1,6 @@ // Pineapple! /obj/item/seeds/pineapple - name = "pack of pineapple seeds" + name = "pineapple seed pack" desc = "Oooooooooooooh!" icon_state = "seed-pineapple" species = "pineapple" diff --git a/code/modules/hydroponics/grown/plum.dm b/code/modules/hydroponics/grown/plum.dm index cac12bdb1eb5dc..c11acdf2db5536 100644 --- a/code/modules/hydroponics/grown/plum.dm +++ b/code/modules/hydroponics/grown/plum.dm @@ -1,6 +1,6 @@ // Plum /obj/item/seeds/plum - name = "pack of plum seeds" + name = "plum seed pack" desc = "These seeds grow into plum trees." icon_state = "seed-plum" species = "plum" @@ -28,7 +28,7 @@ // Plumb /obj/item/seeds/plum/plumb - name = "pack of plumb seeds" + name = "plumb seed pack" desc = "These seeds grow into plumb trees." icon_state = "seed-plumb" species = "plumb" diff --git a/code/modules/hydroponics/grown/potato.dm b/code/modules/hydroponics/grown/potato.dm index 837937e41d1280..c57111b86d0c0e 100644 --- a/code/modules/hydroponics/grown/potato.dm +++ b/code/modules/hydroponics/grown/potato.dm @@ -1,6 +1,6 @@ // Potato /obj/item/seeds/potato - name = "pack of potato seeds" + name = "potato seed pack" desc = "Boil 'em! Mash 'em! Stick 'em in a stew!" icon_state = "seed-potato" species = "potato" @@ -50,7 +50,7 @@ // Sweet Potato /obj/item/seeds/potato/sweet - name = "pack of sweet potato seeds" + name = "sweet potato seed pack" desc = "These seeds grow into sweet potato plants." icon_state = "seed-sweetpotato" species = "sweetpotato" diff --git a/code/modules/hydroponics/grown/pumpkin.dm b/code/modules/hydroponics/grown/pumpkin.dm index 11130c153344ab..dce207302c306a 100644 --- a/code/modules/hydroponics/grown/pumpkin.dm +++ b/code/modules/hydroponics/grown/pumpkin.dm @@ -1,6 +1,6 @@ // Pumpkin /obj/item/seeds/pumpkin - name = "pack of pumpkin seeds" + name = "pumpkin seed pack" desc = "These seeds grow into pumpkin vines." icon_state = "seed-pumpkin" plant_icon_offset = 4 @@ -40,7 +40,7 @@ // Blumpkin /obj/item/seeds/pumpkin/blumpkin - name = "pack of blumpkin seeds" + name = "blumpkin seed pack" desc = "These seeds grow into blumpkin vines." icon_state = "seed-blumpkin" species = "blumpkin" diff --git a/code/modules/hydroponics/grown/rainbow_bunch.dm b/code/modules/hydroponics/grown/rainbow_bunch.dm index 4ffad4583c705e..c3d21347bf9539 100644 --- a/code/modules/hydroponics/grown/rainbow_bunch.dm +++ b/code/modules/hydroponics/grown/rainbow_bunch.dm @@ -1,5 +1,5 @@ /obj/item/seeds/rainbow_bunch - name = "pack of rainbow bunch seeds" + name = "rainbow bunch seed pack" desc = "A pack of seeds that'll grow into a beautiful bush of various colored flowers." icon_state = "seed-rainbowbunch" species = "rainbowbunch" diff --git a/code/modules/hydroponics/grown/random.dm b/code/modules/hydroponics/grown/random.dm index 560e3c71e5ce6e..3a97277f0d85cc 100644 --- a/code/modules/hydroponics/grown/random.dm +++ b/code/modules/hydroponics/grown/random.dm @@ -1,7 +1,7 @@ //Random seeds; stats, traits, and plant type are randomized for each seed. /obj/item/seeds/random - name = "pack of strange seeds" + name = "strange seed pack" desc = "Mysterious seeds as strange as their name implies. Spooky." icon_state = "seed-x" species = "?????" diff --git a/code/modules/hydroponics/grown/replicapod.dm b/code/modules/hydroponics/grown/replicapod.dm index f412e146db2066..602b90f4c35676 100644 --- a/code/modules/hydroponics/grown/replicapod.dm +++ b/code/modules/hydroponics/grown/replicapod.dm @@ -2,7 +2,7 @@ // Yes, i'm talking about cabbage, baby! No, just kidding, but cabbages are the precursor to replica pods, so they are here as well. /obj/item/seeds/cabbage - name = "pack of cabbage seeds" + name = "cabbage seed pack" desc = "These seeds grow into cabbages." icon_state = "seed-cabbage" species = "cabbage" @@ -31,7 +31,7 @@ ///The actual replica pods themselves! /obj/item/seeds/replicapod - name = "pack of replica pod seeds" + name = "replica pod seed pack" desc = "These seeds grow into replica pods. They say these are used to harvest humans." icon_state = "seed-replicapod" plant_icon_offset = 2 diff --git a/code/modules/hydroponics/grown/root.dm b/code/modules/hydroponics/grown/root.dm index c272b1e448462c..4393d76a5fa226 100644 --- a/code/modules/hydroponics/grown/root.dm +++ b/code/modules/hydroponics/grown/root.dm @@ -1,6 +1,6 @@ // Carrot /obj/item/seeds/carrot - name = "pack of carrot seeds" + name = "carrot seed pack" desc = "These seeds grow into carrots." icon_state = "seed-carrot" species = "carrot" @@ -12,7 +12,7 @@ instability = 15 growthstages = 3 growing_icon = 'icons/obj/service/hydroponics/growing_vegetables.dmi' - mutatelist = list(/obj/item/seeds/carrot/parsnip) + mutatelist = list(/obj/item/seeds/carrot/parsnip, /obj/item/seeds/carrot/cahnroot) reagents_add = list(/datum/reagent/medicine/oculine = 0.1, /datum/reagent/consumable/nutriment/vitamin = 0.04, /datum/reagent/consumable/nutriment = 0.05) /obj/item/food/grown/carrot @@ -26,24 +26,26 @@ wine_power = 30 /obj/item/food/grown/carrot/attackby(obj/item/I, mob/user, params) - if(I.get_sharpness()) - var/carrot_blade - var/carrot_sword_chance = (max(0, seed.potency - 50) / 50) - if (prob(carrot_sword_chance)) - carrot_blade = new /obj/item/claymore/carrot - to_chat(user, span_notice("You sharpen the carrot into a sword with [I].")) - else - carrot_blade = new /obj/item/knife/shiv/carrot - to_chat(user, span_notice("You sharpen the carrot into a shiv with [I].")) - remove_item_from_storage(user) - qdel(src) - user.put_in_hands(carrot_blade) - else + if(!I.get_sharpness()) return ..() + /// The blade carrot will turn into once sharpened + var/obj/item/carrot_blade + /// Chance for it to become a sword rather than a shiv + var/carrot_sword_chance = (max(0, seed.potency - 50) / 50) + if (prob(carrot_sword_chance)) + carrot_blade = new /obj/item/claymore/carrot + to_chat(user, span_notice("You sharpen the carrot into a sword with [I].")) + else + carrot_blade = new /obj/item/knife/shiv/carrot + to_chat(user, span_notice("You sharpen the carrot into a shiv with [I].")) + remove_item_from_storage(user) + qdel(src) + user.put_in_hands(carrot_blade) + // Parsnip /obj/item/seeds/carrot/parsnip - name = "pack of parsnip seeds" + name = "parsnip seed pack" desc = "These seeds grow into parsnips." icon_state = "seed-parsnip" species = "parsnip" @@ -62,10 +64,73 @@ juice_typepath = /datum/reagent/consumable/parsnipjuice wine_power = 35 +/obj/item/food/grown/parsnip/attackby(obj/item/I, mob/user, params) + if(!I.get_sharpness()) + return ..() + + /// The blade parsnip will turn into once sharpened + var/obj/item/parsnip_blade + /// Chance for it to become a sabre rather than a shiv + var/parsnip_sabre_chance = (max(0, seed.potency - 50) / 50) + if (prob(parsnip_sabre_chance)) + parsnip_blade = new /obj/item/melee/parsnip_sabre + to_chat(user, span_notice("You sharpen the parsnip into a sabre with [I].")) + else + parsnip_blade = new /obj/item/knife/shiv/parsnip + to_chat(user, span_notice("You sharpen the parsnip into a shiv with [I].")) + remove_item_from_storage(user) + qdel(src) + user.put_in_hands(parsnip_blade) + + +// Cahn'root +/obj/item/seeds/carrot/cahnroot + name = "cahn'root seed pack" + desc = "These seeds grow into cahn'roots." + icon_state = "seed-cahn'root" + species = "cahn'root" + plantname = "Cahn'root" + product = /obj/item/food/grown/cahnroot + genes = list(/datum/plant_gene/trait/plant_type/weed_hardy) + endurance = 50 + instability = 10 + icon_dead = "cahn'root-dead" + mutatelist = null + reagents_add = list(/datum/reagent/consumable/nutriment/vitamin = 0.05, /datum/reagent/consumable/nutriment = 0.05, /datum/reagent/cellulose = 0.01, /datum/reagent/consumable/sugar = 0.01) + rarity = 10 + graft_gene = /datum/plant_gene/trait/plant_type/weed_hardy + +/obj/item/food/grown/cahnroot + seed = /obj/item/seeds/carrot/cahnroot + name = "cahn'root" + desc = "Heavily modified version of terran carrot, originally made to survive the scarciest of environments by an enterprising scientist of Moth Flotilla, Cahn'Mang." + icon_state = "cahn'root" + foodtypes = VEGETABLES + juice_typepath = null + tastes = list("sweet dirt" = 1) + distill_reagent = /datum/reagent/consumable/rootbeer + +/obj/item/food/grown/cahnroot/attackby(obj/item/I, mob/user, params) + if(!I.get_sharpness()) + return ..() + + /// The blade cahn'root will turn into once sharpened + var/obj/item/knife/root_blade + /// Chance for it to become a dagger rather than a shiv + var/root_dagger_chance = (max(0, seed.potency - 25) / 50) + if (prob(root_dagger_chance)) + root_blade = new /obj/item/knife/combat/root + to_chat(user, span_notice("You sharpen the cahn'root into a dagger with [I].")) + else + root_blade = new /obj/item/knife/shiv/root + to_chat(user, span_notice("You sharpen the cahn'root into a shiv with [I].")) + remove_item_from_storage(user) + qdel(src) + user.put_in_hands(root_blade) // White-Beet /obj/item/seeds/whitebeet - name = "pack of white-beet seeds" + name = "white-beet seed pack" desc = "These seeds grow into sugary beet producing plants." icon_state = "seed-whitebeet" species = "whitebeet" @@ -91,7 +156,7 @@ // Red Beet /obj/item/seeds/redbeet - name = "pack of redbeet seeds" + name = "redbeet seed pack" desc = "These seeds grow into red beet producing plants." icon_state = "seed-redbeet" species = "redbeet" diff --git a/code/modules/hydroponics/grown/seedling.dm b/code/modules/hydroponics/grown/seedling.dm index 57fd11280b6ede..9ce83acfa9e36d 100644 --- a/code/modules/hydroponics/grown/seedling.dm +++ b/code/modules/hydroponics/grown/seedling.dm @@ -1,5 +1,5 @@ /obj/item/seeds/seedling - name = "pack of seedling seeds" + name = "seedling seed pack" desc = "These seeds grow into a floral assistant which can help look after other plants!" icon_state = "seed-seedling" growing_icon = 'icons/obj/service/hydroponics/growing_fruits.dmi' diff --git a/code/modules/hydroponics/grown/sugarcane.dm b/code/modules/hydroponics/grown/sugarcane.dm index 1c5c55fece08d0..e7845f1e556079 100644 --- a/code/modules/hydroponics/grown/sugarcane.dm +++ b/code/modules/hydroponics/grown/sugarcane.dm @@ -1,7 +1,7 @@ // Sugarcane /obj/item/seeds/sugarcane - name = "pack of sugarcane seeds" + name = "sugarcane seed pack" desc = "These seeds grow into sugarcane." icon_state = "seed-sugarcane" species = "sugarcane" @@ -28,7 +28,7 @@ ///and bamboo! /obj/item/seeds/bamboo - name = "pack of bamboo seeds" + name = "bamboo seed pack" desc = "A plant known for its flexible and resistant logs." icon_state = "seed-bamboo" species = "bamboo" @@ -59,7 +59,7 @@ //Saltcane - Gross, salty shafts! /obj/item/seeds/sugarcane/saltcane - name = "pack of saltcane seeds" + name = "saltcane seed pack" desc = "These seeds grow into saltcane." icon_state = "seed-saltcane" species = "saltcane" diff --git a/code/modules/hydroponics/grown/tea_coffee.dm b/code/modules/hydroponics/grown/tea_coffee.dm index 366dd8b45237ec..26a215be720b44 100644 --- a/code/modules/hydroponics/grown/tea_coffee.dm +++ b/code/modules/hydroponics/grown/tea_coffee.dm @@ -1,6 +1,6 @@ // Tea /obj/item/seeds/tea - name = "pack of tea aspera seeds" + name = "tea aspera seed pack" desc = "These seeds grow into tea plants." icon_state = "seed-teaaspera" species = "teaaspera" @@ -27,7 +27,7 @@ // Tea Astra /obj/item/seeds/tea/astra - name = "pack of tea astra seeds" + name = "tea astra seed pack" icon_state = "seed-teaastra" species = "teaastra" plantname = "Tea Astra Plant" @@ -46,7 +46,7 @@ // Coffee /obj/item/seeds/coffee - name = "pack of coffee arabica seeds" + name = "coffee arabica seed pack" desc = "These seeds grow into coffee arabica bushes." icon_state = "seed-coffeea" species = "coffeea" @@ -75,7 +75,7 @@ // Coffee Robusta /obj/item/seeds/coffee/robusta - name = "pack of coffee robusta seeds" + name = "coffee robusta seed pack" desc = "These seeds grow into coffee robusta bushes." icon_state = "seed-coffeer" species = "coffeer" diff --git a/code/modules/hydroponics/grown/tobacco.dm b/code/modules/hydroponics/grown/tobacco.dm index 87f8253a4d96b5..29e8fba6d6a8b0 100644 --- a/code/modules/hydroponics/grown/tobacco.dm +++ b/code/modules/hydroponics/grown/tobacco.dm @@ -1,6 +1,6 @@ // Tobacco /obj/item/seeds/tobacco - name = "pack of tobacco seeds" + name = "tobacco seed pack" desc = "These seeds grow into tobacco plants." icon_state = "seed-tobacco" species = "tobacco" @@ -24,7 +24,7 @@ // Space Tobacco /obj/item/seeds/tobacco/space - name = "pack of space tobacco seeds" + name = "space tobacco seed pack" desc = "These seeds grow into space tobacco plants." icon_state = "seed-stobacco" species = "stobacco" diff --git a/code/modules/hydroponics/grown/tomato.dm b/code/modules/hydroponics/grown/tomato.dm index e676d822bbf1a8..1459887d6facbd 100644 --- a/code/modules/hydroponics/grown/tomato.dm +++ b/code/modules/hydroponics/grown/tomato.dm @@ -1,6 +1,6 @@ // Tomato /obj/item/seeds/tomato - name = "pack of tomato seeds" + name = "tomato seed pack" desc = "These seeds grow into tomato plants." icon_state = "seed-tomato" species = "tomato" @@ -29,7 +29,7 @@ // Blood Tomato /obj/item/seeds/tomato/blood - name = "pack of blood-tomato seeds" + name = "blood-tomato seed pack" desc = "These seeds grow into blood-tomato plants." icon_state = "seed-bloodtomato" species = "bloodtomato" @@ -52,7 +52,7 @@ // Blue Tomato /obj/item/seeds/tomato/blue - name = "pack of blue-tomato seeds" + name = "blue-tomato seed pack" desc = "These seeds grow into blue-tomato plants." icon_state = "seed-bluetomato" species = "bluetomato" @@ -77,7 +77,7 @@ // Bluespace Tomato /obj/item/seeds/tomato/blue/bluespace - name = "pack of bluespace tomato seeds" + name = "bluespace tomato seed pack" desc = "These seeds grow into bluespace tomato plants." icon_state = "seed-bluespacetomato" species = "bluespacetomato" @@ -101,7 +101,7 @@ // Killer Tomato /obj/item/seeds/tomato/killer - name = "pack of killer-tomato seeds" + name = "killer-tomato seed pack" desc = "These seeds grow into killer-tomato plants." icon_state = "seed-killertomato" species = "killertomato" diff --git a/code/modules/hydroponics/grown/towercap.dm b/code/modules/hydroponics/grown/towercap.dm index 1082b51665ff7c..a09e4e61b4d15b 100644 --- a/code/modules/hydroponics/grown/towercap.dm +++ b/code/modules/hydroponics/grown/towercap.dm @@ -1,5 +1,5 @@ /obj/item/seeds/tower - name = "pack of tower-cap mycelium" + name = "tower-cap mycelium pack" desc = "This mycelium grows into tower-cap mushrooms." icon_state = "mycelium-tower" species = "towercap" @@ -20,7 +20,7 @@ graft_gene = /datum/plant_gene/trait/plant_type/fungal_metabolism /obj/item/seeds/tower/steel - name = "pack of steel-cap mycelium" + name = "steel-cap mycelium pack" desc = "This mycelium grows into steel logs." icon_state = "mycelium-steelcap" species = "steelcap" diff --git a/code/modules/hydroponics/grown/weeds/kudzu.dm b/code/modules/hydroponics/grown/weeds/kudzu.dm index 86b49672705b96..a0a3c9405718c9 100644 --- a/code/modules/hydroponics/grown/weeds/kudzu.dm +++ b/code/modules/hydroponics/grown/weeds/kudzu.dm @@ -1,7 +1,7 @@ // A very special plant, deserving its own file. /obj/item/seeds/kudzu - name = "pack of kudzu seeds" + name = "kudzu seed pack" desc = "These seeds grow into a weed that grows incredibly fast." icon_state = "seed-kudzu" plant_icon_offset = 2 diff --git a/code/modules/hydroponics/grown/weeds/nettle.dm b/code/modules/hydroponics/grown/weeds/nettle.dm index 98868b8d6e748b..33a0f6288912d9 100644 --- a/code/modules/hydroponics/grown/weeds/nettle.dm +++ b/code/modules/hydroponics/grown/weeds/nettle.dm @@ -1,5 +1,5 @@ /obj/item/seeds/nettle - name = "pack of nettle seeds" + name = "nettle seed pack" desc = "These seeds grow into nettles." icon_state = "seed-nettle" plant_icon_offset = 0 @@ -17,7 +17,7 @@ graft_gene = /datum/plant_gene/trait/plant_type/weed_hardy /obj/item/seeds/nettle/death - name = "pack of death-nettle seeds" + name = "death-nettle seed pack" desc = "These seeds grow into death-nettles." icon_state = "seed-deathnettle" species = "deathnettle" diff --git a/code/modules/hydroponics/grown/weeds/starthistle.dm b/code/modules/hydroponics/grown/weeds/starthistle.dm index 74627a31f88e81..af94cf3d985088 100644 --- a/code/modules/hydroponics/grown/weeds/starthistle.dm +++ b/code/modules/hydroponics/grown/weeds/starthistle.dm @@ -1,6 +1,6 @@ // Starthistle /obj/item/seeds/starthistle - name = "pack of starthistle seeds" + name = "starthistle seed pack" desc = "A robust species of weed that often springs up in-between the cracks of spaceship parking lots." icon_state = "seed-starthistle" plant_icon_offset = 3 @@ -33,7 +33,7 @@ // Corpse flower /obj/item/seeds/starthistle/corpse_flower - name = "pack of corpse flower seeds" + name = "corpse flower seed pack" desc = "A species of plant that emits a horrible odor. The odor stops being produced in difficult atmospheric conditions." icon_state = "seed-corpse-flower" species = "corpse-flower" @@ -46,7 +46,7 @@ //Galaxy Thistle /obj/item/seeds/galaxythistle - name = "pack of galaxythistle seeds" + name = "galaxythistle seed pack" desc = "An impressive species of weed that is thought to have evolved from the simple milk thistle. Contains flavolignans that can help repair a damaged liver." icon_state = "seed-galaxythistle" species = "galaxythistle" diff --git a/code/modules/hydroponics/hydroponics.dm b/code/modules/hydroponics/hydroponics.dm index 46865f5bd9b9fe..ed17254fa9b053 100644 --- a/code/modules/hydroponics/hydroponics.dm +++ b/code/modules/hydroponics/hydroponics.dm @@ -798,15 +798,7 @@ if(isnull(particles)) particles = new /particles/pollen() if(myseed.instability >= 20 && prob(70) && length(T.myseed.reagents_add)) - var/list/datum/plant_gene/reagent/possible_reagents = list() - for(var/datum/plant_gene/reagent/reag in T.myseed.genes) - possible_reagents += reag - var/datum/plant_gene/reagent/reagent_gene = pick(possible_reagents) //Let this serve as a lession to delete your WIP comments before merge. - if(reagent_gene.can_add(myseed)) - if(!reagent_gene.try_upgrade_gene(myseed)) - myseed.genes += reagent_gene.Copy() - myseed.reagents_from_genes() - continue + myseed.perform_reagent_pollination(T.myseed) if(!any_adjacent) particles = null diff --git a/code/modules/hydroponics/seeds.dm b/code/modules/hydroponics/seeds.dm index 13a49b35189053..18197c006b51ed 100644 --- a/code/modules/hydroponics/seeds.dm +++ b/code/modules/hydroponics/seeds.dm @@ -616,3 +616,27 @@ /obj/item/grown/get_plant_seed() return seed + +/obj/item/seeds/proc/perform_reagent_pollination(obj/item/seeds/donor) + var/list/datum/plant_gene/reagent/valid_reagents = list() + for(var/datum/plant_gene/reagent/donor_reagent in donor.genes) + var/repeated = FALSE + for(var/datum/plant_gene/reagent/receptor_reagent in genes) + if(donor_reagent.reagent_id == receptor_reagent.reagent_id) + if(receptor_reagent.rate < donor_reagent.rate) + receptor_reagent.rate = donor_reagent.rate + // sucessful pollination/upgrade, we stop here. + reagents_from_genes() + return + else + repeated = TRUE + break + + if(!repeated) + valid_reagents += donor_reagent + + if(length(valid_reagents)) + // pick a valid reagent that our receptor seed don't have and add the gene to it + var/datum/plant_gene/reagent/selected_reagent = pick(valid_reagents) + genes += selected_reagent.Copy() + reagents_from_genes() diff --git a/code/modules/jobs/job_types/assistant/gimmick_assistants.dm b/code/modules/jobs/job_types/assistant/gimmick_assistants.dm index ed2851366153cd..23fd9616ee3cb9 100644 --- a/code/modules/jobs/job_types/assistant/gimmick_assistants.dm +++ b/code/modules/jobs/job_types/assistant/gimmick_assistants.dm @@ -167,6 +167,7 @@ belt = /obj/item/storage/belt/utility/full head = /obj/item/clothing/head/utility/hardhat uniform = /obj/item/clothing/under/color/yellow + l_pocket = /obj/item/modular_computer/pda/assistant outfit_weight = 6 diff --git a/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm b/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm index df658d71dddc2c..b02dee12cf8268 100644 --- a/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm +++ b/code/modules/jobs/job_types/chaplain/chaplain_nullrod.dm @@ -564,7 +564,7 @@ /obj/item/nullrod/bostaff name = "monk's staff" desc = "A long, tall staff made of polished wood. Traditionally used in ancient old-Earth martial arts, it is now used to harass the clown." - force = 15 + force = 14 block_chance = 40 block_sound = 'sound/weapons/genhit.ogg' slot_flags = ITEM_SLOT_BACK @@ -574,11 +574,25 @@ attack_verb_simple = list("smash", "slam", "whack", "thwack") icon = 'icons/obj/weapons/staff.dmi' icon_state = "bostaff0" + base_icon_state = "bostaff" inhand_icon_state = "bostaff0" worn_icon_state = "bostaff0" lefthand_file = 'icons/mob/inhands/weapons/staves_lefthand.dmi' righthand_file = 'icons/mob/inhands/weapons/staves_righthand.dmi' - menu_description = "A staff which provides a medium-low chance of blocking incoming melee attacks and deals a little less damage. Can be worn on the back." + menu_description = "A staff which provides a medium-low chance of blocking incoming melee attacks and deals less damage, unless dual-wielded. Can be worn on the back." + +/obj/item/nullrod/bostaff/Initialize(mapload) + . = ..() + AddComponent(/datum/component/two_handed, \ + force_unwielded = 14, \ + force_wielded = 18, \ + icon_wielded = "[base_icon_state]1", \ + ) + +/obj/item/nullrod/bostaff/update_icon_state() + icon_state = "[base_icon_state]0" + return ..() + // Arrhythmic Knife - Lets your walk without rhythm by varying your walk speed. Can't be put away. diff --git a/code/modules/lighting/lighting_setup.dm b/code/modules/lighting/lighting_setup.dm deleted file mode 100644 index c148530d1cd863..00000000000000 --- a/code/modules/lighting/lighting_setup.dm +++ /dev/null @@ -1,12 +0,0 @@ - -/proc/create_all_lighting_objects() - for(var/area/area as anything in GLOB.areas) - if(!area.static_lighting) - continue - for (var/list/zlevel_turfs as anything in area.get_zlevel_turf_lists()) - for(var/turf/area_turf as anything in zlevel_turfs) - if(area_turf.space_lit) - continue - new /datum/lighting_object(area_turf) - CHECK_TICK - CHECK_TICK diff --git a/code/modules/loadout/categories/pocket.dm b/code/modules/loadout/categories/pocket.dm index e1cddde76e5b9f..fd3f11e112b276 100644 --- a/code/modules/loadout/categories/pocket.dm +++ b/code/modules/loadout/categories/pocket.dm @@ -106,10 +106,6 @@ name = "Plush (Moth)" item_path = /obj/item/toy/plush/moth -/datum/loadout_item/pocket_items/plush/narsie - name = "Plush (Nar'sie)" - item_path = /obj/item/toy/plush/narplush - /datum/loadout_item/pocket_items/plush/nukie name = "Plush (Nukie)" item_path = /obj/item/toy/plush/nukeplushie @@ -122,10 +118,6 @@ name = "Plush (Plasmaman)" item_path = /obj/item/toy/plush/plasmamanplushie -/datum/loadout_item/pocket_items/plush/ratvar - name = "Plush (Ratvar)" - item_path = /obj/item/toy/plush/ratplush - /datum/loadout_item/pocket_items/plush/rouny name = "Plush (Rouny)" item_path = /obj/item/toy/plush/rouny diff --git a/code/modules/lootpanel/contents.dm b/code/modules/lootpanel/contents.dm index 44f4acd47f24c4..2fcd4201d8a7c3 100644 --- a/code/modules/lootpanel/contents.dm +++ b/code/modules/lootpanel/contents.dm @@ -21,6 +21,8 @@ if(!istype(thing)) stack_trace("Non-atom in the contents of [source_turf]!") continue + if(QDELETED(thing)) + continue if(thing.mouse_opacity == MOUSE_OPACITY_TRANSPARENT) continue if(thing.IsObscured()) diff --git a/code/modules/lootpanel/search_object.dm b/code/modules/lootpanel/search_object.dm index 149be76e710647..2cb0bdf85dba96 100644 --- a/code/modules/lootpanel/search_object.dm +++ b/code/modules/lootpanel/search_object.dm @@ -62,6 +62,7 @@ /datum/search_object/Destroy(force) item = null + icon = null return ..() @@ -75,6 +76,9 @@ /datum/search_object/proc/on_item_moved(atom/source) SIGNAL_HANDLER + if(QDELETED(src)) + return + qdel(src) @@ -82,4 +86,4 @@ /datum/search_object/proc/on_turf_change(turf/source, path, list/new_baseturfs, flags, list/post_change_callbacks) SIGNAL_HANDLER - post_change_callbacks += CALLBACK(src, GLOBAL_PROC_REF(qdel), src) + post_change_callbacks += CALLBACK(GLOBAL_PROC, GLOBAL_PROC_REF(qdel), src) diff --git a/code/modules/mafia/roles/roles.dm b/code/modules/mafia/roles/roles.dm index ab1a1cc0e454b7..4cfd7662d843e3 100644 --- a/code/modules/mafia/roles/roles.dm +++ b/code/modules/mafia/roles/roles.dm @@ -189,6 +189,6 @@ team_span = "comradio" the = FALSE result += span_notice("The [span_bold("[name]")] is aligned with [the ? "the " : ""][team_desc]") - result += "\"[desc]\"" + result += "\"[initial(desc)]\"" result += span_notice("[name] wins when they [win_condition]") to_chat(clueless, result.Join("
")) diff --git a/code/modules/mining/lavaland/ash_flora.dm b/code/modules/mining/lavaland/ash_flora.dm index 1e4e444861155f..3a813aebd14a6a 100644 --- a/code/modules/mining/lavaland/ash_flora.dm +++ b/code/modules/mining/lavaland/ash_flora.dm @@ -261,7 +261,7 @@ graft_gene = /datum/plant_gene/trait/fire_resistance /obj/item/seeds/lavaland/cactus - name = "pack of fruiting cactus seeds" + name = "fruiting cactus seed pack" desc = "These seeds grow into fruiting cacti." icon_state = "seed-cactus" species = "cactus" @@ -275,7 +275,7 @@ ///Star Cactus seeds, mutation of lavaland cactus. /obj/item/seeds/star_cactus - name = "pack of star cacti seeds" + name = "star cacti seed pack" desc = "These seeds grow into star cacti." icon_state = "seed-starcactus" species = "starcactus" @@ -303,7 +303,7 @@ distill_reagent = /datum/reagent/consumable/ethanol/tequila /obj/item/seeds/lavaland/polypore - name = "pack of polypore mycelium" + name = "polypore mycelium pack" desc = "This mycelium grows into bracket mushrooms, also known as polypores. Woody and firm, shaft miners often use them for makeshift crafts." icon_state = "mycelium-polypore" species = "polypore" @@ -314,7 +314,7 @@ reagents_add = list(/datum/reagent/consumable/nutriment = 0.04, /datum/reagent/consumable/ethanol = 0.04, /datum/reagent/stabilizing_agent = 0.06, /datum/reagent/consumable/mintextract = 0.02) /obj/item/seeds/lavaland/porcini - name = "pack of porcini mycelium" + name = "porcini mycelium pack" desc = "This mycelium grows into Boletus edulus, also known as porcini. Native to the late Earth, but discovered on Lavaland. Has culinary, medicinal and relaxant effects." icon_state = "mycelium-porcini" species = "porcini" @@ -325,7 +325,7 @@ reagents_add = list(/datum/reagent/consumable/nutriment = 0.06, /datum/reagent/consumable/sugar = 0.06, /datum/reagent/consumable/vitfro = 0.04, /datum/reagent/drug/nicotine = 0.04) /obj/item/seeds/lavaland/inocybe - name = "pack of inocybe mycelium" + name = "inocybe mycelium pack" desc = "This mycelium grows into an inocybe mushroom, a species of Lavaland origin with hallucinatory and toxic effects." icon_state = "mycelium-inocybe" species = "inocybe" @@ -336,7 +336,7 @@ reagents_add = list(/datum/reagent/toxin/mindbreaker = 0.04, /datum/reagent/consumable/entpoly = 0.08, /datum/reagent/drug/mushroomhallucinogen = 0.04) /obj/item/seeds/lavaland/ember - name = "pack of embershroom mycelium" + name = "embershroom mycelium pack" desc = "This mycelium grows into embershrooms, a species of bioluminescent mushrooms native to Lavaland." icon_state = "mycelium-ember" species = "ember" @@ -347,7 +347,7 @@ reagents_add = list(/datum/reagent/consumable/tinlux = 0.04, /datum/reagent/consumable/nutriment/vitamin = 0.02, /datum/reagent/drug/space_drugs = 0.02) /obj/item/seeds/lavaland/seraka - name = "pack of seraka mycelium" + name = "seraka mycelium pack" desc = "This mycelium grows into seraka mushrooms, a species of savoury mushrooms originally native to Tizira used in food and traditional medicine." icon_state = "mycelium-seraka" species = "seraka" @@ -358,7 +358,7 @@ reagents_add = list(/datum/reagent/toxin/mushroom_powder = 0.1, /datum/reagent/medicine/coagulant/seraka_extract = 0.02) /obj/item/seeds/lavaland/fireblossom - name = "pack of fire blossom seeds" + name = "fire blossom seed pack" desc = "These seeds grow into fire blossoms." plantname = "Fire Blossom" icon_state = "seed-fireblossom" diff --git a/code/modules/mob/living/basic/basic.dm b/code/modules/mob/living/basic/basic.dm index 98a771a06a99de..582af27c3161b9 100644 --- a/code/modules/mob/living/basic/basic.dm +++ b/code/modules/mob/living/basic/basic.dm @@ -318,3 +318,9 @@ /mob/living/basic/get_body_temp_cold_damage_limit() return minimum_survivable_temperature + +/mob/living/basic/proc/hop_on_nearby_turf() + var/dir = pick(GLOB.cardinals) + Move(get_step(src, dir), dir) + animate(src, pixel_y = 18, time = 0.4 SECONDS, flags = ANIMATION_RELATIVE, easing = CUBIC_EASING|EASE_OUT) + animate(pixel_y = -18, time = 0.4 SECONDS, flags = ANIMATION_RELATIVE, easing = CUBIC_EASING|EASE_IN) diff --git a/code/modules/mob/living/basic/bots/_bots.dm b/code/modules/mob/living/basic/bots/_bots.dm index 9f2b915944bb45..04b3a7864d21ed 100644 --- a/code/modules/mob/living/basic/bots/_bots.dm +++ b/code/modules/mob/living/basic/bots/_bots.dm @@ -517,7 +517,6 @@ GLOBAL_LIST_INIT(command_strings, list( if(istype(item_to_drop, /obj/item/stock_parts/power_store/cell)) var/obj/item/stock_parts/power_store/cell/dropped_cell = item_to_drop dropped_cell.charge = 0 - dropped_cell.update_appearance() return if(istype(item_to_drop, /obj/item/storage)) diff --git a/code/modules/mob/living/basic/drone/drone_tools.dm b/code/modules/mob/living/basic/drone/drone_tools.dm index 1fa3aa7884b2a7..32ec1bb1528487 100644 --- a/code/modules/mob/living/basic/drone/drone_tools.dm +++ b/code/modules/mob/living/basic/drone/drone_tools.dm @@ -20,10 +20,11 @@ /obj/item/pipe_dispenser, /obj/item/t_scanner, /obj/item/analyzer, + /obj/item/soap/drone, ) atom_storage.max_total_storage = 40 atom_storage.max_specific_storage = WEIGHT_CLASS_NORMAL - atom_storage.max_slots = 9 + atom_storage.max_slots = 10 atom_storage.rustle_sound = FALSE atom_storage.set_holdable(drone_builtins) @@ -39,7 +40,7 @@ builtintools += new /obj/item/pipe_dispenser(src) builtintools += new /obj/item/t_scanner(src) builtintools += new /obj/item/analyzer(src) - + builtintools += new /obj/item/soap/drone(src) for(var/obj/item/tool as anything in builtintools) tool.AddComponent(/datum/component/holderloving, src, TRUE) diff --git a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm index a06ecb9e9b0401..7dcbc4ae325b01 100644 --- a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm +++ b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity.dm @@ -41,8 +41,6 @@ /mob/living/basic/mining/lobstrosity/Initialize(mapload) . = ..() - var/static/list/food_types = list(/obj/item/fish/lavaloop) - ai_controller.set_blackboard_key(BB_BASIC_FOODS, typecacheof(food_types)) AddComponent(/datum/component/profound_fisher) AddElement(/datum/element/mob_grabber) AddElement(/datum/element/footstep, FOOTSTEP_MOB_CLAW) @@ -160,7 +158,7 @@ /mob/living/basic/mining/lobstrosity/juvenile/Initialize(mapload) . = ..() - var/growth_step = 1000/(8 MINUTES) //It should take 8 minutes if you keep the happiness above 40% and at most 14 + var/growth_step = 1000/(7 MINUTES) //It should take 7-ish minutes if you keep the happiness above 40% and at most 12 AddComponent(\ /datum/component/growth_and_differentiation,\ growth_path = grow_type,\ diff --git a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm index 75b64d051203a3..32ec66a62cc37d 100644 --- a/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm +++ b/code/modules/mob/living/basic/lavaland/lobstrosity/lobstrosity_ai.dm @@ -14,6 +14,7 @@ BB_LOBSTROSITY_FINGER_LUST = 0, BB_LOBSTROSITY_NAIVE_HUNTER = FALSE, BB_BASIC_MOB_FLEE_DISTANCE = 8, + BB_TARGET_PRIORITY_TRAIT = TRAIT_SCARY_FISHERMAN, BB_OWNER_SELF_HARM_RESPONSES = SHRIMP_HARM_RESPONSES, ) ai_traits = PAUSE_DURING_DO_AFTER @@ -24,7 +25,7 @@ /datum/ai_planning_subtree/random_speech/insect, /datum/ai_planning_subtree/hoard_fingers, /datum/ai_planning_subtree/pet_planning, - /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/find_target_prioritize_traits, /datum/ai_planning_subtree/targeted_mob_ability/lobster, /datum/ai_planning_subtree/flee_target/lobster, /datum/ai_planning_subtree/attack_obstacle_in_path, @@ -33,6 +34,14 @@ /datum/ai_planning_subtree/find_and_hunt_target/lobster_fishing, /datum/ai_planning_subtree/find_fingers, ) + +/datum/ai_controller/basic_controller/lobstrosity/TryPossessPawn(atom/new_pawn) + . = ..() + if(. & AI_CONTROLLER_INCOMPATIBLE) + return + var/static/list/food_types = typecacheof(list(/obj/item/fish/lavaloop)) + set_blackboard_key(BB_BASIC_FOODS, food_types) + ///Ensure that juveline lobstrosities witll charge at things they can reach. /datum/ai_controller/basic_controller/lobstrosity/juvenile blackboard = list( @@ -43,13 +52,14 @@ BB_LOBSTROSITY_FINGER_LUST = 0, BB_LOBSTROSITY_NAIVE_HUNTER = TRUE, BB_BASIC_MOB_FLEE_DISTANCE = 4, + BB_TARGET_PRIORITY_TRAIT = TRAIT_SCARY_FISHERMAN, BB_OWNER_SELF_HARM_RESPONSES = SHRIMP_HARM_RESPONSES, ) planning_subtrees = list( /datum/ai_planning_subtree/random_speech/insect, /datum/ai_planning_subtree/hoard_fingers, /datum/ai_planning_subtree/pet_planning, - /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/find_target_prioritize_traits, /datum/ai_planning_subtree/targeted_mob_ability/lobster, /datum/ai_planning_subtree/flee_target/lobster, /datum/ai_planning_subtree/attack_obstacle_in_path, @@ -100,14 +110,17 @@ melee_attack_behavior = /datum/ai_behavior/basic_melee_attack/lobster /datum/ai_planning_subtree/basic_melee_attack_subtree/lobster/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) - if(!isliving(controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET])) + var/atom/movable/target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] + if(!isliving(target)) return ..() if (!controller.blackboard[BB_BASIC_MOB_STOP_FLEEING]) return if (!isnull(controller.blackboard[BB_LOBSTROSITY_TARGET_LIMB])) return + if(controller.blackboard[BB_LOBSTROSITY_NAIVE_HUNTER] && HAS_TRAIT(target, TRAIT_SCARY_FISHERMAN)) + return //juvenile lobstrosities fear me. var/mob/living/living_pawn = controller.pawn - if (DOING_INTERACTION_WITH_TARGET(living_pawn, controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET])) + if (DOING_INTERACTION_WITH_TARGET(living_pawn, target)) return return ..() @@ -118,9 +131,14 @@ if (isnull(target) || !istype(target)) return ..() var/is_vulnerable = FALSE - if(controller.blackboard[BB_LOBSTROSITY_NAIVE_HUNTER] && target.body_position == LYING_DOWN) - is_vulnerable = TRUE - else + if(controller.blackboard[BB_LOBSTROSITY_NAIVE_HUNTER]) + if(HAS_TRAIT(target, TRAIT_SCARY_FISHERMAN)) + //Trigger lobstrosity PTSD. Don't clear the target so we can run away. + controller.set_blackboard_key(BB_BASIC_MOB_STOP_FLEEING, FALSE) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_SUCCEEDED + if(target.body_position == LYING_DOWN) + is_vulnerable = TRUE + if(!is_vulnerable) for (var/trait in controller.blackboard[BB_LOBSTROSITY_EXPLOIT_TRAITS]) if (!HAS_TRAIT(target, trait)) continue @@ -137,9 +155,12 @@ flee_behaviour = /datum/ai_behavior/run_away_from_target/lobster /datum/ai_planning_subtree/flee_target/lobster/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + var/atom/movable/target = controller.blackboard[target_key] + if(!QDELETED(target) && controller.blackboard[BB_LOBSTROSITY_NAIVE_HUNTER] && HAS_TRAIT(target, TRAIT_SCARY_FISHERMAN)) + return ..() var/datum/action/cooldown/using_action = controller.blackboard[BB_TARGETED_ACTION] if (using_action?.IsAvailable()) - return + return FALSE return ..() /datum/ai_behavior/run_away_from_target/lobster @@ -147,19 +168,23 @@ /datum/ai_behavior/run_away_from_target/lobster/perform(seconds_per_tick, datum/ai_controller/controller, target_key, hiding_location_key) var/atom/target = controller.blackboard[target_key] - if(isnull(target)) + if(QDELETED(target)) return ..() - if(isliving(target)) - var/mob/living/living_target = target - if(controller.blackboard[BB_LOBSTROSITY_NAIVE_HUNTER] && living_target.body_position == LYING_DOWN) + var/is_naive = controller.blackboard[BB_LOBSTROSITY_NAIVE_HUNTER] + var/is_scary = HAS_TRAIT(target, TRAIT_SCARY_FISHERMAN) + + if(!is_naive || !is_scary) //the lobstrosity isn't naive/young and the target isn't a scary fisherman. + if(isliving(target)) + var/mob/living/living_target = target + if(is_naive && living_target.body_position == LYING_DOWN) + controller.set_blackboard_key(BB_BASIC_MOB_STOP_FLEEING, TRUE) + return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED + for (var/trait in controller.blackboard[BB_LOBSTROSITY_EXPLOIT_TRAITS]) + if (!HAS_TRAIT(target, trait)) + continue controller.set_blackboard_key(BB_BASIC_MOB_STOP_FLEEING, TRUE) return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED - for (var/trait in controller.blackboard[BB_LOBSTROSITY_EXPLOIT_TRAITS]) - if (!HAS_TRAIT(target, trait)) - continue - controller.set_blackboard_key(BB_BASIC_MOB_STOP_FLEEING, TRUE) - return AI_BEHAVIOR_INSTANT | AI_BEHAVIOR_FAILED var/mob/living/us = controller.pawn if (us.pulling == target) @@ -174,7 +199,9 @@ /datum/ai_planning_subtree/targeted_mob_ability/lobster/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) var/atom/target = controller.blackboard[target_key] if(QDELETED(target) || in_range(controller.pawn, target)) - return FALSE + return + if(controller.blackboard[BB_LOBSTROSITY_NAIVE_HUNTER] && HAS_TRAIT(target, TRAIT_SCARY_FISHERMAN)) + return return ..() diff --git a/code/modules/mob/living/basic/lavaland/mining.dm b/code/modules/mob/living/basic/lavaland/mining.dm index ca84e0d1d20c77..37b7dd118f4d96 100644 --- a/code/modules/mob/living/basic/lavaland/mining.dm +++ b/code/modules/mob/living/basic/lavaland/mining.dm @@ -36,6 +36,9 @@ drop_immediately = basic_mob_flags & DEL_ON_DEATH,\ ) RegisterSignal(src, COMSIG_ATOM_WAS_ATTACKED, PROC_REF(check_ashwalker_peace_violation)) + // We add this to ensure that mobs will actually receive the above signal, as some will lack AI + // handling for retaliation and attack special cases + AddElement(/datum/element/relay_attackers) /mob/living/basic/mining/proc/add_ranged_armour(list/vulnerable_projectiles) AddElement(\ diff --git a/code/modules/mob/living/basic/lavaland/node_drone/node_drone.dm b/code/modules/mob/living/basic/lavaland/node_drone/node_drone.dm index b149c6d09728bb..87687c56999635 100644 --- a/code/modules/mob/living/basic/lavaland/node_drone/node_drone.dm +++ b/code/modules/mob/living/basic/lavaland/node_drone/node_drone.dm @@ -74,6 +74,31 @@ if(flying_state == FLY_IN_STATE || flying_state == FLY_OUT_STATE) icon_state = "mining_node_flying" +/mob/living/basic/node_drone/update_overlays() + . = ..() + if(attached_vent) + var/time_remaining = COOLDOWN_TIMELEFT(attached_vent, wave_cooldown) + var/wave_timers + switch(attached_vent?.boulder_size) + if(BOULDER_SIZE_SMALL) + wave_timers = WAVE_DURATION_SMALL + if(BOULDER_SIZE_MEDIUM) + wave_timers = WAVE_DURATION_MEDIUM + if(BOULDER_SIZE_LARGE) + wave_timers = WAVE_DURATION_LARGE + var/remaining_fraction = (time_remaining / wave_timers) + if(remaining_fraction <= 0.3) + . += "node_progress_4" + return + if(remaining_fraction <= 0.55) + . += "node_progress_3" + return + if(remaining_fraction <= 0.80) + . += "node_progress_2" + return + . += "node_progress_1" + return + /mob/living/basic/node_drone/proc/arrive(obj/structure/ore_vent/parent_vent) attached_vent = parent_vent maxHealth = 300 + ((attached_vent.boulder_size/BOULDER_SIZE_SMALL) * 100) diff --git a/code/modules/mob/living/basic/minebots/minebot_ai.dm b/code/modules/mob/living/basic/minebots/minebot_ai.dm index 62aeaf3aa79238..31fed0ec1f32cc 100644 --- a/code/modules/mob/living/basic/minebots/minebot_ai.dm +++ b/code/modules/mob/living/basic/minebots/minebot_ai.dm @@ -284,6 +284,10 @@ radial_icon = 'icons/obj/mining.dmi' radial_icon_state = "pickaxe" speech_commands = list("mine") + callout_type = /datum/callout_option/mine + +/datum/pet_command/automate_mining/valid_callout_target(mob/living/caller, datum/callout_option/callout, atom/target) + return ismineralturf(target) /datum/pet_command/automate_mining/execute_action(datum/ai_controller/controller) controller.set_blackboard_key(BB_AUTOMATED_MINING, TRUE) diff --git a/code/modules/mob/living/basic/pets/cat/cat.dm b/code/modules/mob/living/basic/pets/cat/cat.dm index 400bd9ac9f1733..2bcd715d7f5c87 100644 --- a/code/modules/mob/living/basic/pets/cat/cat.dm +++ b/code/modules/mob/living/basic/pets/cat/cat.dm @@ -24,8 +24,6 @@ response_harm_simple = "kick" mobility_flags = MOBILITY_FLAGS_REST_CAPABLE_DEFAULT gold_core_spawnable = FRIENDLY_SPAWN - collar_icon_state = "cat" - has_collar_resting_icon_state = TRUE can_be_held = TRUE ai_controller = /datum/ai_controller/basic_controller/cat held_state = "cat2" @@ -33,7 +31,8 @@ attack_verb_simple = "claw" attack_sound = 'sound/weapons/slash.ogg' attack_vis_effect = ATTACK_EFFECT_CLAW - cult_icon_state = "cat_cult" + ///icon of the collar we can wear + var/collar_icon_state = "cat" ///can this cat breed? var/can_breed = TRUE ///can hold items? @@ -50,9 +49,13 @@ var/obj/item/held_food ///mutable appearance for held item var/mutable_appearance/held_item_overlay + ///icon state of our cult icon + var/cult_icon_state = "cat_cult" /mob/living/basic/pet/cat/Initialize(mapload) . = ..() + AddElement(/datum/element/cultist_pet, pet_cult_icon_state = cult_icon_state) + AddElement(/datum/element/wears_collar, collar_icon_state = collar_icon_state, collar_resting_icon_state = TRUE) AddElement(/datum/element/ai_retaliate) AddElement(/datum/element/pet_bonus, "purrs!") AddElement(/datum/element/footstep, footstep_type = FOOTSTEP_MOB_CLAW) @@ -147,7 +150,6 @@ icon_living = "breadcat" icon_dead = "breadcat_dead" ai_controller = /datum/ai_controller/basic_controller/cat/bread - collar_icon_state = null held_state = "breadcat" can_interact_with_stove = TRUE butcher_results = list( @@ -156,6 +158,7 @@ /obj/item/organ/external/tail/cat = 1, /obj/item/food/breadslice/plain = 1 ) + collar_icon_state = null /mob/living/basic/pet/cat/breadcat/add_cell_sample() return @@ -167,7 +170,6 @@ icon_state = "original" icon_living = "original" icon_dead = "original_dead" - collar_icon_state = null unique_pet = TRUE held_state = "original" @@ -183,10 +185,10 @@ density = FALSE pass_flags = PASSMOB mob_size = MOB_SIZE_SMALL - collar_icon_state = "kitten" can_breed = FALSE ai_controller = /datum/ai_controller/basic_controller/cat/kitten can_hold_item = FALSE + collar_icon_state = "kitten" /mob/living/basic/pet/cat/kitten/Initialize(mapload) . = ..() diff --git a/code/modules/mob/living/basic/pets/dog/_dog.dm b/code/modules/mob/living/basic/pets/dog/_dog.dm index 5cd970575ec6f9..b1c2c5e486fc1b 100644 --- a/code/modules/mob/living/basic/pets/dog/_dog.dm +++ b/code/modules/mob/living/basic/pets/dog/_dog.dm @@ -44,9 +44,15 @@ /datum/pet_command/point_targeting/fetch, /datum/pet_command/play_dead, ) + ///icon state of the collar we can wear + var/collar_icon_state + ///icon state of our cult icon + var/cult_icon_state /mob/living/basic/pet/dog/Initialize(mapload) . = ..() + AddElement(/datum/element/cultist_pet, pet_cult_icon_state = cult_icon_state) + AddElement(/datum/element/wears_collar, collar_icon_state = collar_icon_state) ADD_TRAIT(src, TRAIT_WOUND_LICKER, INNATE_TRAIT) AddElement(/datum/element/pet_bonus, "woofs happily!") AddElement(/datum/element/footstep, FOOTSTEP_MOB_CLAW) diff --git a/code/modules/mob/living/basic/pets/dog/corgi.dm b/code/modules/mob/living/basic/pets/dog/corgi.dm index 7e13c792d28306..e1f05b33d81fb2 100644 --- a/code/modules/mob/living/basic/pets/dog/corgi.dm +++ b/code/modules/mob/living/basic/pets/dog/corgi.dm @@ -544,9 +544,9 @@ pass_flags = PASSMOB ai_controller = /datum/ai_controller/basic_controller/dog/puppy mob_size = MOB_SIZE_SMALL - collar_icon_state = "puppy" strippable_inventory_slots = list(/datum/strippable_item/pet_collar, /datum/strippable_item/corgi_id) //puppies are too small to handle hats and back slot items can_breed = FALSE + collar_icon_state = "puppy" //PUPPY IAN! SQUEEEEEEEEE~ /mob/living/basic/pet/dog/corgi/puppy/ian diff --git a/code/modules/mob/living/basic/pets/dog/strippable_items.dm b/code/modules/mob/living/basic/pets/dog/strippable_items.dm index 2799ca38b978f1..c92948e2b6ffd8 100644 --- a/code/modules/mob/living/basic/pets/dog/strippable_items.dm +++ b/code/modules/mob/living/basic/pets/dog/strippable_items.dm @@ -38,11 +38,11 @@ GLOBAL_LIST_INIT(strippable_corgi_items, create_strippable_list(list( key = STRIPPABLE_ITEM_PET_COLLAR /datum/strippable_item/pet_collar/get_item(atom/source) - var/mob/living/basic/pet/pet_source = source + var/mob/living/basic/pet_source = source if(!istype(pet_source)) return - return pet_source.collar + return (locate(/obj/item/clothing/neck/petcollar) in source) /datum/strippable_item/pet_collar/try_equip(atom/source, obj/item/equipping, mob/user) . = ..() @@ -56,18 +56,10 @@ GLOBAL_LIST_INIT(strippable_corgi_items, create_strippable_list(list( return TRUE /datum/strippable_item/pet_collar/finish_equip(atom/source, obj/item/equipping, mob/user) - var/mob/living/basic/pet/pet_source = source - if(!istype(pet_source)) - return - - pet_source.add_collar(equipping, user) + user.transferItemToLoc(equipping, source) /datum/strippable_item/pet_collar/finish_unequip(atom/source, mob/user) - var/mob/living/basic/pet/pet_source = source - if(!istype(pet_source)) - return - - var/obj/collar = pet_source.remove_collar(user.drop_location()) + var/obj/item/clothing/neck/petcollar/collar = locate() in source user.put_in_hands(collar) /datum/strippable_item/corgi_back diff --git a/code/modules/mob/living/basic/pets/fox.dm b/code/modules/mob/living/basic/pets/fox.dm index 03ac2be54bedd5..e4e978568a0e62 100644 --- a/code/modules/mob/living/basic/pets/fox.dm +++ b/code/modules/mob/living/basic/pets/fox.dm @@ -31,6 +31,8 @@ /mob/living/basic/pet/fox/Initialize(mapload) . = ..() + AddElement(/datum/element/cultist_pet) + AddElement(/datum/element/wears_collar) AddElement(/datum/element/pet_bonus, "pants and yaps happily!") AddElement(/datum/element/footstep, footstep_type = FOOTSTEP_MOB_CLAW) AddElement(/datum/element/tiny_mob_hunter, MOB_SIZE_SMALL) diff --git a/code/modules/mob/living/basic/pets/penguin.dm b/code/modules/mob/living/basic/pets/penguin.dm index 1bf3adec5574ef..a597bd70cbba44 100644 --- a/code/modules/mob/living/basic/pets/penguin.dm +++ b/code/modules/mob/living/basic/pets/penguin.dm @@ -20,6 +20,8 @@ /mob/living/basic/pet/penguin/Initialize(mapload) . = ..() + AddElement(/datum/element/cultist_pet) + AddElement(/datum/element/wears_collar) AddElement(/datum/element/ai_retaliate) AddElement(/datum/element/ai_flee_while_injured) AddElement(/datum/element/pet_bonus, "honks happily!") diff --git a/code/modules/mob/living/basic/pets/pet.dm b/code/modules/mob/living/basic/pets/pet.dm index de5ad59eb1f0c4..64896a3f2ab472 100644 --- a/code/modules/mob/living/basic/pets/pet.dm +++ b/code/modules/mob/living/basic/pets/pet.dm @@ -3,146 +3,12 @@ mob_size = MOB_SIZE_SMALL mob_biotypes = MOB_ORGANIC|MOB_BEAST blood_volume = BLOOD_VOLUME_NORMAL - /// if the mob is protected from being renamed by collars. var/unique_pet = FALSE - /// If the mob has collar sprites, this is the base of the icon states. - var/collar_icon_state = null - /// We have a seperate _rest collar icon state when the pet is resting. - var/has_collar_resting_icon_state = FALSE - /// Our collar - var/obj/item/clothing/neck/petcollar/collar - ///can we become cultists? - var/can_cult_convert = TRUE - ///whether we have a custom icon state when we get culted - var/cult_icon_state - -/mob/living/basic/pet/Initialize(mapload) - . = ..() - - /// Can set the collar var beforehand to start the pet with a collar. - if(collar) - collar = new(src) - - update_icon(UPDATE_OVERLAYS) - if(can_cult_convert) - RegisterSignal(src, COMSIG_LIVING_CULT_SACRIFICED, PROC_REF(become_cultist)) - -/mob/living/basic/pet/Destroy() - . = ..() - - QDEL_NULL(collar) - -/mob/living/basic/pet/attackby(obj/item/thing, mob/user, params) - if(istype(thing, /obj/item/clothing/neck/petcollar) && !collar) - add_collar(thing, user) - return TRUE - - if(istype(thing, /obj/item/newspaper) && !stat) - user.visible_message(span_notice("[user] baps [name] on the nose with the rolled up [thing].")) - dance_rotate(src) - return TRUE - return ..() - -/mob/living/basic/pet/update_overlays() - . = ..() - - if(isnull(mind) && (FACTION_CULT in faction)) - var/image/cult_indicator = image(icon = 'icons/mob/simple/pets.dmi', icon_state = "pet_cult_indicator", layer = ABOVE_GAME_PLANE) - . += cult_indicator - - if(!collar || !collar_icon_state) - return - - // Determine which status tag to add to the middle of the icon state. - var/dead_tag = (stat == DEAD || HAS_TRAIT(src, TRAIT_FAKEDEATH)) ? "_dead" : null - var/rest_tag = has_collar_resting_icon_state && resting ? "_rest" : null - var/stat_tag = dead_tag || rest_tag || "" - - . += mutable_appearance(icon, "[collar_icon_state][stat_tag]collar") - . += mutable_appearance(icon, "[collar_icon_state][stat_tag]tag") - -/mob/living/basic/pet/update_icon_state() - if(cult_icon_state && (FACTION_CULT in faction)) - icon_state = cult_icon_state - icon_living = cult_icon_state - return ..() - -/mob/living/basic/pet/gib() - remove_collar(drop_location(), update_visuals = FALSE) - return ..() - -/mob/living/basic/pet/revive(full_heal_flags = NONE, excess_healing = 0, force_grab_ghost = FALSE) - . = ..() - if(!.) - return - - update_icon(UPDATE_OVERLAYS) /mob/living/basic/pet/death(gibbed) . = ..() add_memory_in_range(src, 7, /datum/memory/pet_died, deuteragonist = src) //Protagonist is the person memorizing it -/mob/living/basic/pet/Exited(atom/movable/gone, direction) - . = ..() - if(gone != collar) - return - - collar = null - - if(QDELETED(src)) - return - - update_icon(UPDATE_OVERLAYS) - -/mob/living/basic/pet/update_stat() - . = ..() - - update_icon(UPDATE_OVERLAYS) - -/mob/living/basic/pet/set_resting(new_resting, silent, instant) - . = ..() - - if(!has_collar_resting_icon_state) - return - - update_icon(UPDATE_OVERLAYS) - -/** - * Add a collar to the pet. - * - * Arguments: - * * new_collar - the collar. - * * user - the user that did it. - */ -/mob/living/basic/pet/proc/add_collar(obj/item/clothing/neck/petcollar/new_collar, mob/user) - if(QDELETED(new_collar) || collar) - return - if(!user.transferItemToLoc(new_collar, src)) - return - - collar = new_collar - if(collar_icon_state) - update_icon(UPDATE_OVERLAYS) - - to_chat(user, span_notice("You put [new_collar] around [src]'s neck.")) - if(new_collar.tagname && !unique_pet) - fully_replace_character_name(null, "\proper [new_collar.tagname]") - -/** - * Remove the collar from the pet. - */ -/mob/living/basic/pet/proc/remove_collar(atom/new_loc, update_visuals = TRUE) - if(!collar) - return - - var/obj/old_collar = collar - - collar.forceMove(new_loc) - collar = null - - if(collar_icon_state && update_visuals) - update_icon(UPDATE_OVERLAYS) - return old_collar diff --git a/code/modules/mob/living/basic/pets/pet_cult/pet_cult.dm b/code/modules/mob/living/basic/pets/pet_cult/pet_cult.dm deleted file mode 100644 index 438737a1ad2611..00000000000000 --- a/code/modules/mob/living/basic/pets/pet_cult/pet_cult.dm +++ /dev/null @@ -1,85 +0,0 @@ -#define PET_CULT_ATTACK 10 -#define PET_CULT_HEALTH 50 - -///turn into terrifying beasts -/mob/living/basic/pet/proc/become_cultist(datum/source, list/invokers, datum/team) - SIGNAL_HANDLER - - if(stat == DEAD || !can_cult_convert) - return - - if(FACTION_CULT in faction) - return STOP_SACRIFICE - - mind?.add_antag_datum(/datum/antagonist/cult, team) - qdel(GetComponent(/datum/component/obeys_commands)) - melee_damage_lower = max(PET_CULT_ATTACK, initial(melee_damage_lower)) - melee_damage_upper = max(PET_CULT_ATTACK + 5, initial(melee_damage_upper)) - maxHealth = max(PET_CULT_HEALTH, initial(maxHealth)) - fully_heal() - - faction = list(FACTION_CULT) //we only serve the cult - - if(isnull(cult_icon_state)) - add_atom_colour(RUNE_COLOR_MEDIUMRED, FIXED_COLOUR_PRIORITY) - - var/static/list/cult_appetite = list( - /obj/item/organ, - /obj/effect/decal/cleanable/blood, - ) - - var/static/list/death_loot = list( - /obj/effect/gibspawner/generic, - /obj/item/soulstone, - ) - - AddElement(/datum/element/basic_eating, heal_amt = 15, food_types = cult_appetite) - AddElement(/datum/element/death_drops, death_loot) - - basic_mob_flags &= DEL_ON_DEATH - qdel(ai_controller) - ai_controller = new /datum/ai_controller/basic_controller/pet_cult(src) - var/datum/action/cooldown/spell/conjure/revive_rune/rune_ability = new(src) - rune_ability.Grant(src) - ai_controller.set_blackboard_key(BB_RUNE_ABILITY, rune_ability) - ai_controller.set_blackboard_key(BB_CULT_TEAM, team) - - var/static/list/new_pet_commands = list( - /datum/pet_command/point_targeting/attack, - /datum/pet_command/follow, - /datum/pet_command/free, - /datum/pet_command/idle, - /datum/pet_command/untargeted_ability/draw_rune, - ) - AddComponent(/datum/component/obeys_commands, new_pet_commands) - RegisterSignal(src, COMSIG_HOSTILE_PRE_ATTACKINGTARGET, PROC_REF(activate_rune), override = TRUE) - update_appearance() - return STOP_SACRIFICE - - -/mob/living/basic/pet/proc/activate_rune(datum/source, atom/target) - SIGNAL_HANDLER - - if(!istype(target, /obj/effect/rune/raise_dead)) - return NONE - - target.attack_hand(src) - - return COMPONENT_CANCEL_ATTACK_CHAIN - -/mob/living/basic/pet/Login() - . = ..() - if(!. || !client) - return FALSE - - if(!(FACTION_CULT in faction)) - return - var/datum/team/cult_team = locate(/datum/team/cult) in GLOB.antagonist_teams - if(isnull(cult_team)) - return - mind.add_antag_datum(/datum/antagonist/cult, cult_team) - update_appearance(UPDATE_OVERLAYS) - - -#undef PET_CULT_ATTACK -#undef PET_CULT_HEALTH diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm index 71017bd2207a2f..810c45603862b8 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_actions.dm @@ -55,6 +55,12 @@ /// This subtype only exists because if you queue multiple of the same action with different arguments it deletes their stored arguments /datum/ai_behavior/find_potential_targets/nearest/magicarp +/datum/ai_behavior/find_potential_targets/nearest/magicarp/pick_final_target(datum/ai_controller/controller, list/enemies_list) + for(var/atom/atom as anything in enemies_list) + if(HAS_TRAIT(atom, TRAIT_SCARY_FISHERMAN)) + enemies_list -= atom + return ..() + /// Then use it on that target /datum/ai_planning_subtree/targeted_mob_ability/magicarp ability_key = BB_MAGICARP_SPELL diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm index 84b96ae3ce4056..f104d3566b347b 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp_ai_rift_actions.dm @@ -31,6 +31,9 @@ finish_planning = TRUE /datum/ai_planning_subtree/make_carp_rift/panic_teleport/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + var/atom/movable/fleeing_from = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] + if(!QDELETED(fleeing_from) && controller.blackboard[BB_CARPS_FEAR_FISHERMAN] && HAS_TRAIT(fleeing_from, TRAIT_SCARY_FISHERMAN)) + return ..() if (controller.blackboard[BB_BASIC_MOB_STOP_FLEEING]) return return ..() @@ -42,6 +45,12 @@ /datum/ai_planning_subtree/make_carp_rift/aggressive_teleport rift_behaviour = /datum/ai_behavior/make_carp_rift/towards/aggressive +/datum/ai_planning_subtree/make_carp_rift/aggressive_teleport/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) + var/atom/movable/target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] + if(!QDELETED(target) && controller.blackboard[BB_CARPS_FEAR_FISHERMAN] && HAS_TRAIT(target, TRAIT_SCARY_FISHERMAN)) + return + return ..() + /** * # Make carp rift * Make a carp rift somewhere @@ -174,7 +183,7 @@ /datum/ai_planning_subtree/shortcut_to_target_through_carp_rift/SelectBehaviors(datum/ai_controller/controller, seconds_per_tick) var/mob/living/target = controller.blackboard[BB_BASIC_MOB_CURRENT_TARGET] - if (QDELETED(target)) + if (QDELETED(target) || (controller.blackboard[BB_CARPS_FEAR_FISHERMAN] && HAS_TRAIT(target, TRAIT_SCARY_FISHERMAN))) return var/distance_to_target = get_dist(controller.pawn, target) diff --git a/code/modules/mob/living/basic/space_fauna/carp/carp_controllers.dm b/code/modules/mob/living/basic/space_fauna/carp/carp_controllers.dm index 0befb20987c01b..4491ef1149137b 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/carp_controllers.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/carp_controllers.dm @@ -12,24 +12,48 @@ BB_BASIC_MOB_STOP_FLEEING = TRUE, BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/allow_items, BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, + BB_TARGET_PRIORITY_TRAIT = TRAIT_SCARY_FISHERMAN, + BB_CARPS_FEAR_FISHERMAN = TRUE, ) ai_movement = /datum/ai_movement/basic_avoidance idle_behavior = /datum/idle_behavior/idle_random_walk + planning_subtrees = list( + /datum/ai_planning_subtree/pet_planning, + /datum/ai_planning_subtree/simple_find_nearest_target_to_flee, + /datum/ai_planning_subtree/find_target_prioritize_traits, + /datum/ai_planning_subtree/make_carp_rift/panic_teleport, + /datum/ai_planning_subtree/flee_target/from_fisherman, + /datum/ai_planning_subtree/find_food, + /datum/ai_planning_subtree/attack_obstacle_in_path/carp, + /datum/ai_planning_subtree/shortcut_to_target_through_carp_rift, + /datum/ai_planning_subtree/make_carp_rift/aggressive_teleport, + /datum/ai_planning_subtree/basic_melee_attack_subtree/no_fisherman, + /datum/ai_planning_subtree/carp_migration, + ) + +///Megacarps. The only difference is that they don't flee from scary fishermen and prioritize them. +/datum/ai_controller/basic_controller/carp/mega + blackboard = list( + BB_BASIC_MOB_STOP_FLEEING = TRUE, + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic/allow_items, + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, + BB_TARGET_PRIORITY_TRAIT = TRAIT_SCARY_FISHERMAN, + BB_CARPS_FEAR_FISHERMAN = FALSE, + ) planning_subtrees = list( /datum/ai_planning_subtree/pet_planning, /datum/ai_planning_subtree/simple_find_nearest_target_to_flee, /datum/ai_planning_subtree/make_carp_rift/panic_teleport, /datum/ai_planning_subtree/flee_target, /datum/ai_planning_subtree/find_food, - /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/find_target_prioritize_traits, /datum/ai_planning_subtree/attack_obstacle_in_path/carp, /datum/ai_planning_subtree/shortcut_to_target_through_carp_rift, /datum/ai_planning_subtree/make_carp_rift/aggressive_teleport, /datum/ai_planning_subtree/basic_melee_attack_subtree, /datum/ai_planning_subtree/carp_migration, ) - /** * Carp which bites back, but doesn't look for targets. * 'Not hunting targets' includes food (and can rings), because they have been well trained. @@ -39,18 +63,20 @@ BB_BASIC_MOB_STOP_FLEEING = TRUE, BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, + BB_TARGET_PRIORITY_TRAIT = TRAIT_SCARY_FISHERMAN, + BB_CARPS_FEAR_FISHERMAN = TRUE, ) ai_traits = STOP_MOVING_WHEN_PULLED planning_subtrees = list( /datum/ai_planning_subtree/pet_planning, /datum/ai_planning_subtree/find_nearest_thing_which_attacked_me_to_flee, /datum/ai_planning_subtree/make_carp_rift/panic_teleport, - /datum/ai_planning_subtree/flee_target, + /datum/ai_planning_subtree/flee_target/from_fisherman, /datum/ai_planning_subtree/target_retaliate, /datum/ai_planning_subtree/attack_obstacle_in_path/carp, /datum/ai_planning_subtree/shortcut_to_target_through_carp_rift, /datum/ai_planning_subtree/make_carp_rift/aggressive_teleport, - /datum/ai_planning_subtree/basic_melee_attack_subtree, + /datum/ai_planning_subtree/basic_melee_attack_subtree/no_fisherman, ) /** @@ -61,12 +87,12 @@ planning_subtrees = list( /datum/ai_planning_subtree/pet_planning, /datum/ai_planning_subtree/simple_find_nearest_target_to_flee, + /datum/ai_planning_subtree/find_target_prioritize_traits, /datum/ai_planning_subtree/make_carp_rift/panic_teleport, - /datum/ai_planning_subtree/flee_target, + /datum/ai_planning_subtree/flee_target/from_fisherman, /datum/ai_planning_subtree/find_food, /datum/ai_planning_subtree/find_nearest_magicarp_spell_target, /datum/ai_planning_subtree/targeted_mob_ability/magicarp, - /datum/ai_planning_subtree/simple_find_target, /datum/ai_planning_subtree/attack_obstacle_in_path/carp, /datum/ai_planning_subtree/shortcut_to_target_through_carp_rift, /datum/ai_planning_subtree/make_carp_rift/aggressive_teleport, @@ -83,17 +109,19 @@ BB_BASIC_MOB_STOP_FLEEING = TRUE, BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, + BB_TARGET_PRIORITY_TRAIT = TRAIT_SCARY_FISHERMAN, + BB_CARPS_FEAR_FISHERMAN = TRUE, ) ai_traits = STOP_MOVING_WHEN_PULLED planning_subtrees = list( /datum/ai_planning_subtree/pet_planning, /datum/ai_planning_subtree/simple_find_nearest_target_to_flee, /datum/ai_planning_subtree/make_carp_rift/panic_teleport, - /datum/ai_planning_subtree/flee_target, + /datum/ai_planning_subtree/flee_target/from_fisherman, /datum/ai_planning_subtree/find_food, /datum/ai_planning_subtree/attack_obstacle_in_path/carp, /datum/ai_planning_subtree/shortcut_to_target_through_carp_rift, /datum/ai_planning_subtree/make_carp_rift/aggressive_teleport, - /datum/ai_planning_subtree/basic_melee_attack_subtree, + /datum/ai_planning_subtree/basic_melee_attack_subtree/no_fisherman, /datum/ai_planning_subtree/carp_migration, ) diff --git a/code/modules/mob/living/basic/space_fauna/carp/megacarp.dm b/code/modules/mob/living/basic/space_fauna/carp/megacarp.dm index deadeaaa540a60..d82120a37e0346 100644 --- a/code/modules/mob/living/basic/space_fauna/carp/megacarp.dm +++ b/code/modules/mob/living/basic/space_fauna/carp/megacarp.dm @@ -24,6 +24,7 @@ ridable_data = /datum/component/riding/creature/megacarp greyscale_config = /datum/greyscale_config/carp_mega butcher_results = list(/obj/item/food/fishmeat/carp = 2, /obj/item/stack/sheet/animalhide/carp = 3) + ai_controller = /datum/ai_controller/basic_controller/carp/mega /mob/living/basic/carp/mega/Initialize(mapload) . = ..() diff --git a/code/modules/mob/living/basic/vermin/frog.dm b/code/modules/mob/living/basic/vermin/frog.dm index a674169dbd5ce9..3a288918dbdc11 100644 --- a/code/modules/mob/living/basic/vermin/frog.dm +++ b/code/modules/mob/living/basic/vermin/frog.dm @@ -109,6 +109,7 @@ /datum/ai_controller/basic_controller/frog blackboard = list( + BB_BASIC_MOB_STOP_FLEEING = TRUE, //We only flee from scary fishermen. BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, BB_OWNER_SELF_HARM_RESPONSES = list( @@ -122,7 +123,8 @@ planning_subtrees = list( /datum/ai_planning_subtree/target_retaliate, /datum/ai_planning_subtree/random_speech/frog, - /datum/ai_planning_subtree/basic_melee_attack_subtree, + /datum/ai_planning_subtree/basic_melee_attack_subtree/no_fisherman, + /datum/ai_planning_subtree/flee_target/from_fisherman, /datum/ai_planning_subtree/go_for_swim, ) @@ -131,11 +133,18 @@ /datum/ai_planning_subtree/pet_planning, /datum/ai_planning_subtree/random_speech/frog, /datum/ai_planning_subtree/simple_find_target, - /datum/ai_planning_subtree/basic_melee_attack_subtree, + /datum/ai_planning_subtree/basic_melee_attack_subtree/no_fisherman, + /datum/ai_planning_subtree/flee_target/from_fisherman, ) /datum/ai_controller/basic_controller/frog/suicide_frog + blackboard = list( + BB_TARGETING_STRATEGY = /datum/targeting_strategy/basic, + BB_PET_TARGETING_STRATEGY = /datum/targeting_strategy/basic/not_friends, + BB_TARGET_PRIORITY_TRAIT = TRAIT_SCARY_FISHERMAN, //No fear, only hatred. It has nothing to lose + ) + planning_subtrees = list( - /datum/ai_planning_subtree/simple_find_target, + /datum/ai_planning_subtree/find_target_prioritize_traits, /datum/ai_planning_subtree/basic_melee_attack_subtree, ) diff --git a/code/modules/mob/living/carbon/alien/alien_defense.dm b/code/modules/mob/living/carbon/alien/alien_defense.dm index 3717cfcb89a1a9..630171ba2c15da 100644 --- a/code/modules/mob/living/carbon/alien/alien_defense.dm +++ b/code/modules/mob/living/carbon/alien/alien_defense.dm @@ -33,7 +33,6 @@ In all, this is a lot like the monkey code. /N to_chat(user, span_danger("You bite [src]!")) adjustBruteLoss(1) log_combat(user, src, "attacked") - updatehealth() else to_chat(user, span_warning("[name] is too injured for that.")) diff --git a/code/modules/mob/living/carbon/human/_species.dm b/code/modules/mob/living/carbon/human/_species.dm index 1e514ad13cedbb..5e1bdf42826862 100644 --- a/code/modules/mob/living/carbon/human/_species.dm +++ b/code/modules/mob/living/carbon/human/_species.dm @@ -744,7 +744,7 @@ GLOBAL_LIST_EMPTY(features_by_species) sample_overlay = new overlay_path() organs_to_randomize[overlay_path] = sample_overlay - new_features["[sample_overlay.feature_key]"] = pick(sample_overlay.get_global_feature_list()) + new_features["[sample_overlay.feature_key]"] = sample_overlay.get_random_appearance().name return new_features @@ -1514,6 +1514,14 @@ GLOBAL_LIST_EMPTY(features_by_species) /datum/species/proc/get_cry_sound(mob/living/carbon/human/human) return +/// Returns the species' sigh sound. +/datum/species/proc/get_sigh_sound(mob/living/carbon/human/human) + return + +/// Returns the species' sniff sound. +/datum/species/proc/get_sniff_sound(mob/living/carbon/human/human) + return + /// Returns the species' cough sound. /datum/species/proc/get_cough_sound(mob/living/carbon/human/human) return diff --git a/code/modules/mob/living/carbon/human/species_types/felinid.dm b/code/modules/mob/living/carbon/human/species_types/felinid.dm index bd8063b744ee6d..b26bd476b4bc49 100644 --- a/code/modules/mob/living/carbon/human/species_types/felinid.dm +++ b/code/modules/mob/living/carbon/human/species_types/felinid.dm @@ -99,6 +99,17 @@ return 'sound/voice/human/female_sneeze1.ogg' return 'sound/voice/human/male_sneeze1.ogg' +/datum/species/human/felinid/get_sigh_sound(mob/living/carbon/human/felinid) + if(felinid.physique == FEMALE) + return 'sound/voice/human/female_sigh.ogg' + return 'sound/voice/human/male_sigh.ogg' + +/datum/species/human/felinid/get_sniff_sound(mob/living/carbon/human/felinid) + if(felinid.physique == FEMALE) + return 'sound/voice/human/female_sniff.ogg' + return 'sound/voice/human/male_sniff.ogg' + + /proc/mass_purrbation() for(var/mob in GLOB.human_list) diff --git a/code/modules/mob/living/carbon/human/species_types/humans.dm b/code/modules/mob/living/carbon/human/species_types/humans.dm index 98a4518c4fa2ee..ef8140c7d82ef5 100644 --- a/code/modules/mob/living/carbon/human/species_types/humans.dm +++ b/code/modules/mob/living/carbon/human/species_types/humans.dm @@ -79,6 +79,16 @@ 'sound/voice/human/manlaugh2.ogg', ) +/datum/species/human/get_sigh_sound(mob/living/carbon/human/human) + if(human.physique == FEMALE) + return 'sound/voice/human/female_sigh.ogg' + return 'sound/voice/human/male_sigh.ogg' + +/datum/species/human/get_sniff_sound(mob/living/carbon/human/human) + if(human.physique == FEMALE) + return 'sound/voice/human/female_sniff.ogg' + return 'sound/voice/human/male_sniff.ogg' + /datum/species/human/get_species_description() return "Humans are the dominant species in the known galaxy. \ Their kind extend from old Earth to the edges of known space." diff --git a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm index 2a83efbda3e7ee..6b71a234d9b610 100644 --- a/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm +++ b/code/modules/mob/living/carbon/human/species_types/lizardpeople.dm @@ -101,6 +101,16 @@ /datum/species/lizard/get_laugh_sound(mob/living/carbon/human/lizard) return 'sound/voice/lizard/lizard_laugh1.ogg' +/datum/species/lizard/get_sigh_sound(mob/living/carbon/human/lizard) + if(lizard.physique == FEMALE) + return 'sound/voice/human/female_sigh.ogg' + return 'sound/voice/human/male_sigh.ogg' + +/datum/species/lizard/get_sniff_sound(mob/living/carbon/human/lizard) + if(lizard.physique == FEMALE) + return 'sound/voice/human/female_sniff.ogg' + return 'sound/voice/human/male_sniff.ogg' + /datum/species/lizard/get_physical_attributes() return "Lizardpeople can withstand slightly higher temperatures than most species, but they are very vulnerable to the cold \ and can't regulate their body-temperature internally, making the vacuum of space extremely deadly to them." diff --git a/code/modules/mob/living/carbon/human/species_types/mothmen.dm b/code/modules/mob/living/carbon/human/species_types/mothmen.dm index 7b621971e18197..0caa0d996ba1be 100644 --- a/code/modules/mob/living/carbon/human/species_types/mothmen.dm +++ b/code/modules/mob/living/carbon/human/species_types/mothmen.dm @@ -98,6 +98,16 @@ /datum/species/moth/get_laugh_sound(mob/living/carbon/human/moth) return 'sound/voice/moth/moth_laugh1.ogg' +/datum/species/moth/get_sigh_sound(mob/living/carbon/human/moth) + if(moth.physique == FEMALE) + return 'sound/voice/human/female_sigh.ogg' + return 'sound/voice/human/male_sigh.ogg' + +/datum/species/moth/get_sniff_sound(mob/living/carbon/human/moth) + if(moth.physique == FEMALE) + return 'sound/voice/human/female_sniff.ogg' + return 'sound/voice/human/male_sniff.ogg' + /datum/species/moth/get_physical_attributes() return "Moths have large and fluffy wings, which help them navigate the station if gravity is offline by pushing the air around them. \ Due to that, it isn't of much use out in space. Their eyes are very sensitive." diff --git a/code/modules/mob/living/carbon/inventory.dm b/code/modules/mob/living/carbon/inventory.dm index e59a6328aa72ee..5b43bf980c4a14 100644 --- a/code/modules/mob/living/carbon/inventory.dm +++ b/code/modules/mob/living/carbon/inventory.dm @@ -11,6 +11,8 @@ obscured |= ITEM_SLOT_NECK if(hidden_slots & HIDEMASK) obscured |= ITEM_SLOT_MASK + if(hidden_slots & HIDEBELT) + obscured |= ITEM_SLOT_BELT if(hidden_slots & HIDEEYES) obscured |= ITEM_SLOT_EYES if(hidden_slots & HIDEEARS) diff --git a/code/modules/mob/living/emote.dm b/code/modules/mob/living/emote.dm index 418b07ebf26691..62030cf1eba590 100644 --- a/code/modules/mob/living/emote.dm +++ b/code/modules/mob/living/emote.dm @@ -352,6 +352,7 @@ message_mime = "acts out a scream!" emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE mob_type_blacklist_typecache = list(/mob/living/brain, /mob/living/carbon/human) + sound_wall_ignore = TRUE /datum/emote/living/scream/run_emote(mob/user, params, type_override, intentional = FALSE) if(!intentional && HAS_TRAIT(user, TRAIT_ANALGESIA)) @@ -394,6 +395,7 @@ message = "sighs." message_mime = "acts out an exaggerated silent sigh." emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE + vary = TRUE /datum/emote/living/sigh/run_emote(mob/living/user, params, type_override, intentional) . = ..() @@ -402,6 +404,11 @@ var/image/emote_animation = image('icons/mob/human/emote_visuals.dmi', user, "sigh") flick_overlay_global(emote_animation, GLOB.clients, 2.0 SECONDS) +/datum/emote/living/sigh/get_sound(mob/living/carbon/human/user) + if(!istype(user)) + return + return user.dna.species.get_sigh_sound(user) + /datum/emote/living/sit key = "sit" key_third_person = "sits" @@ -423,6 +430,13 @@ message = "sniffs." message_mime = "sniffs silently." emote_type = EMOTE_VISIBLE | EMOTE_AUDIBLE + vary = TRUE + +/datum/emote/living/sniff/get_sound(mob/living/carbon/human/user) + if(!istype(user)) + return + return user.dna.species.get_sniff_sound(user) + /datum/emote/living/snore key = "snore" diff --git a/code/modules/mob/living/living.dm b/code/modules/mob/living/living.dm index 2873dab1a71bc4..70f268c2a454a6 100644 --- a/code/modules/mob/living/living.dm +++ b/code/modules/mob/living/living.dm @@ -169,13 +169,8 @@ if(now_pushing) return TRUE - var/they_can_move = TRUE - var/their_combat_mode = FALSE - if(isliving(M)) var/mob/living/L = M - their_combat_mode = L.combat_mode - they_can_move = L.mobility_flags & MOBILITY_MOVE //Also spread diseases for(var/thing in diseases) var/datum/disease/D = thing @@ -205,22 +200,7 @@ return TRUE if(!M.buckled && !M.has_buckled_mobs()) - var/mob_swap = FALSE - var/too_strong = (M.move_resist > move_force) //can't swap with immovable objects unless they help us - if(!they_can_move) //we have to physically move them - if(!too_strong) - mob_swap = TRUE - else - //You can swap with the person you are dragging on grab intent, and restrained people in most cases - if(M.pulledby == src && !too_strong) - mob_swap = TRUE - else if( - !(HAS_TRAIT(M, TRAIT_NOMOBSWAP) || HAS_TRAIT(src, TRAIT_NOMOBSWAP)) &&\ - ((HAS_TRAIT(M, TRAIT_RESTRAINED) && !too_strong) || !their_combat_mode) &&\ - (HAS_TRAIT(src, TRAIT_RESTRAINED) || !combat_mode) - ) - mob_swap = TRUE - if(mob_swap) + if(can_mobswap_with(M)) //switch our position with M if(loc && !loc.Adjacent(M.loc)) return TRUE @@ -273,6 +253,46 @@ if(prob(I.block_chance*2)) return +/mob/living/proc/can_mobswap_with(mob/other) + if (HAS_TRAIT(other, TRAIT_NOMOBSWAP) || HAS_TRAIT(src, TRAIT_NOMOBSWAP)) + return FALSE + + var/they_can_move = TRUE + var/their_combat_mode = FALSE + + if(isliving(other)) + var/mob/living/other_living = other + their_combat_mode = other_living.combat_mode + they_can_move = other_living.mobility_flags & MOBILITY_MOVE + + var/too_strong = other.move_resist > move_force + + // They cannot move, see if we can push through them + if (!they_can_move) + return !too_strong + + // We are pulling them and can move through + if (other.pulledby == src && !too_strong) + return TRUE + + // If we're in combat mode and not restrained we don't try to pass through people + if (combat_mode && !HAS_TRAIT(src, TRAIT_RESTRAINED)) + return FALSE + + // Nor can we pass through non-restrained people in combat mode (or if they're restrained but still too strong for us) + if (their_combat_mode && (!HAS_TRAIT(other, TRAIT_RESTRAINED) || too_strong)) + return FALSE + + if (isnull(other.client) || isnull(client)) + return TRUE + + // If both of us are trying to move in the same direction, let the fastest one through first + if (client.intended_direction == other.client.intended_direction) + return cached_multiplicative_slowdown < other.cached_multiplicative_slowdown + + // Else, sure, let us pass + return TRUE + /mob/living/get_photo_description(obj/item/camera/camera) var/list/holding = list() var/len = length(held_items) @@ -2663,7 +2683,7 @@ GLOBAL_LIST_EMPTY(fire_appearances) ///The price should be high enough that the contractor can't just buy 'em back with their cut alone. var/datum/market_item/hostage/market_item = new(src, black_market_price || ransom_price) - SSblackmarket.markets[/datum/market/blackmarket].add_item(market_item) + SSmarket.markets[/datum/market/blackmarket].add_item(market_item) if(mind) ADD_TRAIT(mind, TRAIT_HAS_BEEN_KIDNAPPED, TRAIT_GENERIC) diff --git a/code/modules/mob/living/living_say.dm b/code/modules/mob/living/living_say.dm index 1d7f447493e07e..459410d0a026a0 100644 --- a/code/modules/mob/living/living_say.dm +++ b/code/modules/mob/living/living_say.dm @@ -251,7 +251,7 @@ GLOBAL_LIST_INIT(message_modes_stat_limits, list( if(pressure < SOUND_MINIMUM_PRESSURE && !HAS_TRAIT(src, TRAIT_SIGN_LANG)) message_range = 1 - if(pressure < ONE_ATMOSPHERE*0.4) //Thin air, let's italicise the message + if(pressure < ONE_ATMOSPHERE * (HAS_TRAIT(src, TRAIT_SPEECH_BOOSTER) ? 0.1 : 0.4)) //Thin air, let's italicise the message unless we have a loud low pressure speech trait and not in vacuum spans |= SPAN_ITALICS send_speech(message, message_range, src, bubble_type, spans, language, message_mods, tts_message = tts_message, tts_filter = tts_filter)//roughly 58% of living/say()'s total cost diff --git a/code/modules/mob/living/silicon/ai/ai_defense.dm b/code/modules/mob/living/silicon/ai/ai_defense.dm index 7dea684e569418..0c5eb6ec164b2f 100644 --- a/code/modules/mob/living/silicon/ai/ai_defense.dm +++ b/code/modules/mob/living/silicon/ai/ai_defense.dm @@ -14,7 +14,6 @@ /mob/living/silicon/ai/blob_act(obj/structure/blob/B) if (stat != DEAD) adjustBruteLoss(60) - updatehealth() return TRUE return FALSE diff --git a/code/modules/mob/living/silicon/robot/death.dm b/code/modules/mob/living/silicon/robot/death.dm index 3a8cec66efd6fb..5c4384302b8d69 100644 --- a/code/modules/mob/living/silicon/robot/death.dm +++ b/code/modules/mob/living/silicon/robot/death.dm @@ -21,18 +21,30 @@ else logevent("FATAL -- SYSTEM HALT") modularInterface.shutdown_computer() + eye_flash_timer = addtimer(CALLBACK(src, PROC_REF(flash_headlamp)), 2 SECONDS, TIMER_STOPPABLE | TIMER_LOOP) . = ..() locked = FALSE //unlock cover if(!QDELETED(builtInCamera) && builtInCamera.camera_enabled) builtInCamera.toggle_cam(src,0) - toggle_headlamp(TRUE) //So borg lights are disabled when killed. + toggle_headlamp(TRUE) //So borg lights are disabled when killed. drop_all_held_items() // particularly to ensure sight modes are cleared - update_icons() - unbuckle_all_mobs(TRUE) - SSblackbox.ReportDeath(src) + +/mob/living/silicon/robot/proc/flash_headlamp() + if(eye_lights) + eye_lights = null + regenerate_icons() + return + + eye_lights = new() + eye_lights.icon_state = "[model.special_light_key ? "[model.special_light_key]":"[model.cyborg_base_icon]"]_e_r" + eye_lights.color = COLOR_WHITE + SET_PLANE_EXPLICIT(eye_lights, ABOVE_GAME_PLANE, src) + eye_lights.icon = icon + regenerate_icons() + add_overlay(eye_lights) diff --git a/code/modules/mob/living/silicon/robot/robot.dm b/code/modules/mob/living/silicon/robot/robot.dm index 3fcf652cc6abb0..4871370d16c3d0 100644 --- a/code/modules/mob/living/silicon/robot/robot.dm +++ b/code/modules/mob/living/silicon/robot/robot.dm @@ -583,6 +583,7 @@ /mob/living/silicon/robot/updatehealth() ..() + update_damage_particles() if(!model.breakable_modules) return @@ -680,6 +681,9 @@ builtInCamera.toggle_cam(src, 0) if(full_heal_flags & HEAL_ADMIN) locked = TRUE + if(eye_flash_timer) + deltimer(eye_flash_timer) + eye_flash_timer = null src.set_stat(CONSCIOUS) notify_ai(AI_NOTIFICATION_NEW_BORG) toggle_headlamp(FALSE, TRUE) //This will reenable borg headlamps if doomsday is currently going on still. diff --git a/code/modules/mob/living/silicon/robot/robot_defense.dm b/code/modules/mob/living/silicon/robot/robot_defense.dm index 0e4e79f84ce509..16da8d89783af7 100644 --- a/code/modules/mob/living/silicon/robot/robot_defense.dm +++ b/code/modules/mob/living/silicon/robot/robot_defense.dm @@ -186,6 +186,52 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real return ..() +#define LOW_DAMAGE_UPPER_BOUND 1/3 +#define MODERATE_DAMAGE_UPPER_BOUND 2/3 + +/mob/living/silicon/robot/proc/update_damage_particles() + var/brute_percent = bruteloss / maxHealth + var/burn_percent = fireloss / maxHealth + + if (brute_percent > MODERATE_DAMAGE_UPPER_BOUND) + if(!smoke_particles) + smoke_particles = new(src, /particles/smoke/cyborg/heavy_damage, PARTICLE_ATTACH_MOB) + else if(!istype(smoke_particles.particles, /particles/smoke/cyborg/heavy_damage)) //TODO: needs to be darker + QDEL_NULL(smoke_particles) + smoke_particles = new(src, /particles/smoke/cyborg/heavy_damage, PARTICLE_ATTACH_MOB) + + else if (brute_percent > LOW_DAMAGE_UPPER_BOUND) + if(!smoke_particles) + smoke_particles = new(src, /particles/smoke/cyborg, PARTICLE_ATTACH_MOB) + else if(!istype(smoke_particles.particles, /particles/smoke/cyborg)) + QDEL_NULL(smoke_particles) + smoke_particles = new(src, /particles/smoke/cyborg, PARTICLE_ATTACH_MOB) + + else + if(smoke_particles) + QDEL_NULL(smoke_particles) + + if (burn_percent > MODERATE_DAMAGE_UPPER_BOUND) + if(!spark_particles) + spark_particles = new(src, /particles/embers/spark/severe, PARTICLE_ATTACH_MOB) + else if(!istype(spark_particles.particles, /particles/embers/spark/severe)) //TODO: needs to be more dramatic + QDEL_NULL(spark_particles) + spark_particles = new(src, /particles/embers/spark/severe, PARTICLE_ATTACH_MOB) + + else if (burn_percent > LOW_DAMAGE_UPPER_BOUND) + if(!spark_particles) + spark_particles = new(src, /particles/embers/spark, PARTICLE_ATTACH_MOB) + else if(!istype(spark_particles.particles, /particles/embers/spark)) + QDEL_NULL(spark_particles) + spark_particles = new(src, /particles/embers/spark, PARTICLE_ATTACH_MOB) + + else + if(spark_particles) + QDEL_NULL(spark_particles) + +#undef LOW_DAMAGE_UPPER_BOUND +#undef MODERATE_DAMAGE_UPPER_BOUND + /mob/living/silicon/robot/attack_alien(mob/living/carbon/alien/adult/user, list/modifiers) if (LAZYACCESS(modifiers, RIGHT_CLICK)) if(body_position == STANDING_UP) @@ -214,7 +260,6 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real if(!wiresexposed && !issilicon(user)) if(!cell) return - cell.update_appearance() cell.add_fingerprint(user) to_chat(user, span_notice("You remove \the [cell].")) user.put_in_active_hand(cell) @@ -402,7 +447,7 @@ GLOBAL_LIST_INIT(blacklisted_borg_hats, typecacheof(list( //Hats that don't real if(stat != DEAD) adjustBruteLoss(30) else - investigate_log("has been gibbed a blob.", INVESTIGATE_DEATHS) + investigate_log("has been gibbed by a blob.", INVESTIGATE_DEATHS) gib(DROP_ALL_REMAINS) return TRUE diff --git a/code/modules/mob/living/silicon/robot/robot_defines.dm b/code/modules/mob/living/silicon/robot/robot_defines.dm index 33026d70921fbe..e6af597bc60b70 100644 --- a/code/modules/mob/living/silicon/robot/robot_defines.dm +++ b/code/modules/mob/living/silicon/robot/robot_defines.dm @@ -57,6 +57,8 @@ // Overlay for borg eye lights var/mutable_appearance/eye_lights + ///Holds a reference to the timer taking care of blinking lights on dead cyborgs + var/eye_flash_timer = null // Overlay for borg hat var/mutable_appearance/hat_overlay @@ -115,6 +117,10 @@ var/low_power_mode = FALSE ///So they can initialize sparks whenever/N var/datum/effect_system/spark_spread/spark_system + ///Smoke particle holder for brute damage + var/obj/effect/abstract/particle_holder/smoke_particles = null + ///Spark particle holder for burn damage + var/obj/effect/abstract/particle_holder/spark_particles = null ///Jetpack-like effect. var/ionpulse = FALSE diff --git a/code/modules/mob/living/silicon/robot/robot_model.dm b/code/modules/mob/living/silicon/robot/robot_model.dm index c20efda747bfd8..015f23182dca37 100644 --- a/code/modules/mob/living/silicon/robot/robot_model.dm +++ b/code/modules/mob/living/silicon/robot/robot_model.dm @@ -233,6 +233,7 @@ if(!new_model.be_transformed_to(src, forced)) qdel(new_model) return + cyborg.drop_all_held_items() cyborg.model = new_model cyborg.update_module_innate() new_model.rebuild_modules() diff --git a/code/modules/mob/living/silicon/silicon_defense.dm b/code/modules/mob/living/silicon/silicon_defense.dm index b7a669b4a2e620..73d6ac25bdd0fb 100644 --- a/code/modules/mob/living/silicon/silicon_defense.dm +++ b/code/modules/mob/living/silicon/silicon_defense.dm @@ -18,7 +18,6 @@ flash_act(affect_silicon = 1) log_combat(user, src, "attacked") adjustBruteLoss(damage) - updatehealth() else playsound(loc, 'sound/weapons/slashmiss.ogg', 25, TRUE, -1) visible_message(span_danger("[user]'s swipe misses [src]!"), \ diff --git a/code/modules/mob/living/simple_animal/animal_defense.dm b/code/modules/mob/living/simple_animal/animal_defense.dm index 2fea2871c0388b..baaf1b39b3c562 100644 --- a/code/modules/mob/living/simple_animal/animal_defense.dm +++ b/code/modules/mob/living/simple_animal/animal_defense.dm @@ -27,7 +27,6 @@ playsound(loc, attacked_sound, 25, TRUE, -1) apply_damage(harm_intent_damage) log_combat(user, src, "attacked") - updatehealth() return TRUE /mob/living/simple_animal/get_shoving_message(mob/living/shover, obj/item/weapon, shove_flags) diff --git a/code/modules/mob/living/simple_animal/bot/bot.dm b/code/modules/mob/living/simple_animal/bot/bot.dm index c483d371e1aa30..e2bb112e1565e5 100644 --- a/code/modules/mob/living/simple_animal/bot/bot.dm +++ b/code/modules/mob/living/simple_animal/bot/bot.dm @@ -556,7 +556,6 @@ if(istype(item_to_drop, /obj/item/stock_parts/power_store/cell)) var/obj/item/stock_parts/power_store/cell/dropped_cell = item_to_drop dropped_cell.charge = 0 - dropped_cell.update_appearance() else if(istype(item_to_drop, /obj/item/storage)) var/obj/item/storage/storage_to_drop = item_to_drop diff --git a/code/modules/mob/living/simple_animal/bot/mulebot.dm b/code/modules/mob/living/simple_animal/bot/mulebot.dm index 6b9b4aa77faeeb..f3194e88b18629 100644 --- a/code/modules/mob/living/simple_animal/bot/mulebot.dm +++ b/code/modules/mob/living/simple_animal/bot/mulebot.dm @@ -754,7 +754,6 @@ new /obj/item/stack/cable_coil/cut(Tsec) if(cell) cell.forceMove(Tsec) - cell.update_appearance() cell = null new /obj/effect/decal/cleanable/oil(loc) diff --git a/code/modules/mob/living/sneeze.dm b/code/modules/mob/living/sneeze.dm index b2cf76c25a6b05..4c38027fda0d81 100644 --- a/code/modules/mob/living/sneeze.dm +++ b/code/modules/mob/living/sneeze.dm @@ -57,6 +57,7 @@ spread = 40 damage_type = BRUTE damage = 0 + hitsound = null /// Call this when we hit something var/datum/callback/sneezie_callback diff --git a/code/modules/mob/mob_update_icons.dm b/code/modules/mob/mob_update_icons.dm index a355a385d9faaf..b14da72e830619 100644 --- a/code/modules/mob/mob_update_icons.dm +++ b/code/modules/mob/mob_update_icons.dm @@ -54,6 +54,8 @@ update_worn_shoes(update_obscured = FALSE) if(obscured_flags & HIDEMASK) update_worn_mask(update_obscured = FALSE) + if(obscured_flags & HIDEBELT) + update_worn_belt(update_obscured = FALSE) if(obscured_flags & HIDEEARS) update_worn_ears(update_obscured = FALSE) if(obscured_flags & HIDEEYES) diff --git a/code/modules/mod/mod_control.dm b/code/modules/mod/mod_control.dm index 78ff7e9952bd10..cf91aaf482c224 100644 --- a/code/modules/mod/mod_control.dm +++ b/code/modules/mod/mod_control.dm @@ -537,7 +537,7 @@ radial_anchor = get_turf(user.loc) //they're phased out via some module, anchor the radial on the turf so it may still display if (!isnull(anchor_override)) radial_anchor = anchor_override - var/pick = show_radial_menu(user, radial_anchor, items, custom_check = FALSE, require_near = isnull(anchor_override), tooltips = TRUE) + var/pick = show_radial_menu(user, radial_anchor, items, custom_check = FALSE, require_near = isnull(anchor_override), tooltips = TRUE, user_space = !isnull(anchor_override)) if(!pick) return var/module_reference = display_names[pick] diff --git a/code/modules/mod/mod_core.dm b/code/modules/mod/mod_core.dm index 0c13efa1b950c8..5f93427f532775 100644 --- a/code/modules/mod/mod_core.dm +++ b/code/modules/mod/mod_core.dm @@ -173,7 +173,6 @@ /obj/item/mod/core/standard/proc/uninstall_cell() if(!cell) return - cell.update_appearance() cell = null mod.update_charge_alert() diff --git a/code/modules/mod/mod_theme.dm b/code/modules/mod/mod_theme.dm index b3b0df28ed5d7d..394ddea0ecdea0 100644 --- a/code/modules/mod/mod_theme.dm +++ b/code/modules/mod/mod_theme.dm @@ -479,21 +479,21 @@ ), /obj/item/clothing/suit/mod = list( UNSEALED_CLOTHING = THICKMATERIAL, - SEALED_CLOTHING = STOPSPRESSUREDAMAGE, - SEALED_INVISIBILITY = HIDEJUMPSUIT, + SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE, + SEALED_INVISIBILITY = HIDEJUMPSUIT|HIDEBELT, UNSEALED_MESSAGE = CHESTPLATE_UNSEAL_MESSAGE, SEALED_MESSAGE = CHESTPLATE_SEAL_MESSAGE, ), /obj/item/clothing/gloves/mod = list( UNSEALED_CLOTHING = THICKMATERIAL, - SEALED_CLOTHING = STOPSPRESSUREDAMAGE, + SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE, CAN_OVERSLOT = TRUE, UNSEALED_MESSAGE = GAUNTLET_UNSEAL_MESSAGE, SEALED_MESSAGE = GAUNTLET_SEAL_MESSAGE, ), /obj/item/clothing/shoes/mod = list( UNSEALED_CLOTHING = THICKMATERIAL, - SEALED_CLOTHING = STOPSPRESSUREDAMAGE, + SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE, CAN_OVERSLOT = TRUE, UNSEALED_MESSAGE = BOOT_UNSEAL_MESSAGE, SEALED_MESSAGE = BOOT_SEAL_MESSAGE, @@ -502,7 +502,7 @@ "asteroid" = list( /obj/item/clothing/head/mod = list( UNSEALED_CLOTHING = SNUG_FIT|THICKMATERIAL, - SEALED_CLOTHING = STOPSPRESSUREDAMAGE|HEADINTERNALS, + SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE|HEADINTERNALS, UNSEALED_INVISIBILITY = HIDEFACIALHAIR|HIDEEARS|HIDEHAIR|HIDESNOUT, SEALED_INVISIBILITY = HIDEMASK|HIDEEYES|HIDEFACE, SEALED_COVER = HEADCOVERSMOUTH|HEADCOVERSEYES|PEPPERPROOF, @@ -511,21 +511,21 @@ ), /obj/item/clothing/suit/mod = list( UNSEALED_CLOTHING = THICKMATERIAL, - SEALED_CLOTHING = STOPSPRESSUREDAMAGE, - SEALED_INVISIBILITY = HIDEJUMPSUIT, + SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE, + SEALED_INVISIBILITY = HIDEJUMPSUIT|HIDEBELT, UNSEALED_MESSAGE = CHESTPLATE_UNSEAL_MESSAGE, SEALED_MESSAGE = CHESTPLATE_SEAL_MESSAGE, ), /obj/item/clothing/gloves/mod = list( UNSEALED_CLOTHING = THICKMATERIAL, - SEALED_CLOTHING = STOPSPRESSUREDAMAGE, + SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE, CAN_OVERSLOT = TRUE, UNSEALED_MESSAGE = GAUNTLET_UNSEAL_MESSAGE, SEALED_MESSAGE = GAUNTLET_SEAL_MESSAGE, ), /obj/item/clothing/shoes/mod = list( UNSEALED_CLOTHING = THICKMATERIAL, - SEALED_CLOTHING = STOPSPRESSUREDAMAGE, + SEALED_CLOTHING = THICKMATERIAL|STOPSPRESSUREDAMAGE, CAN_OVERSLOT = TRUE, UNSEALED_MESSAGE = BOOT_UNSEAL_MESSAGE, SEALED_MESSAGE = BOOT_SEAL_MESSAGE, @@ -533,7 +533,7 @@ ), ) -/datum/mod_theme/loader/New() +/datum/mod_theme/mining/New() .=..() allowed_suit_storage = GLOB.mining_suit_allowed diff --git a/code/modules/mod/mod_types.dm b/code/modules/mod/mod_types.dm index 5125b70a9a7ad3..db9d150f3438a0 100644 --- a/code/modules/mod/mod_types.dm +++ b/code/modules/mod/mod_types.dm @@ -123,7 +123,7 @@ theme = /datum/mod_theme/mining applied_core = /obj/item/mod/core/plasma applied_modules = list( - /obj/item/mod/module/storage, + /obj/item/mod/module/storage/large_capacity, /obj/item/mod/module/gps, /obj/item/mod/module/orebag, /obj/item/mod/module/clamp, diff --git a/code/modules/mod/modules/modules_general.dm b/code/modules/mod/modules/modules_general.dm index 815cfb0a144bc3..8db88e16ba3127 100644 --- a/code/modules/mod/modules/modules_general.dm +++ b/code/modules/mod/modules/modules_general.dm @@ -174,9 +174,6 @@ required_slots = list(ITEM_SLOT_BACK) /obj/item/mod/module/jump_jet/on_use() - . = ..() - if (!.) - return FALSE if (DOING_INTERACTION(mod.wearer, mod.wearer)) balloon_alert(mod.wearer, "busy!") return @@ -289,7 +286,6 @@ icon_state = "apparatus" complexity = 1 incompatible_modules = list(/obj/item/mod/module/mouthhole) - overlay_state_inactive = "module_apparatus" required_slots = list(ITEM_SLOT_HEAD|ITEM_SLOT_MASK) /// Former flags of the helmet. var/former_helmet_flags = NONE @@ -715,6 +711,7 @@ attached_hat = hat var/obj/item/clothing/helmet = mod.get_part_from_slot(ITEM_SLOT_HEAD) if(istype(helmet)) + helmet.attach_clothing_traits(attached_hat.clothing_traits) former_flags = helmet.flags_cover former_visor_flags = helmet.visor_flags_cover helmet.flags_cover |= attached_hat.flags_cover @@ -737,11 +734,12 @@ balloon_alert(user, "hat removed") else balloon_alert_to_viewers("the hat falls to the floor!") - attached_hat = null var/obj/item/clothing/helmet = mod.get_part_from_slot(ITEM_SLOT_HEAD) if(istype(helmet)) + helmet.detach_clothing_traits(attached_hat) helmet.flags_cover = former_flags helmet.visor_flags_cover = former_visor_flags + attached_hat = null mod.wearer.update_clothing(mod.slot_flags) /obj/item/mod/module/hat_stabilizer/syndicate @@ -863,16 +861,10 @@ return ..() /obj/item/mod/module/recycler/on_activation() - . = ..() - if(!.) - return connector = AddComponent(/datum/component/connect_loc_behalf, mod.wearer, loc_connections) RegisterSignal(mod.wearer, COMSIG_MOVABLE_MOVED, PROC_REF(on_wearer_moved)) /obj/item/mod/module/recycler/on_deactivation(display_message, deleting = FALSE) - . = ..() - if(!.) - return QDEL_NULL(connector) UnregisterSignal(mod.wearer, COMSIG_MOVABLE_MOVED, PROC_REF(on_wearer_moved)) diff --git a/code/modules/mod/modules/modules_ninja.dm b/code/modules/mod/modules/modules_ninja.dm index 518e3683abf722..cfa95fb8a591ee 100644 --- a/code/modules/mod/modules/modules_ninja.dm +++ b/code/modules/mod/modules/modules_ninja.dm @@ -72,15 +72,9 @@ cooldown_time = 3 SECONDS /obj/item/mod/module/stealth/ninja/on_activation() - . = ..() - if(!.) - return ADD_TRAIT(mod.wearer, TRAIT_SILENT_FOOTSTEPS, MOD_TRAIT) /obj/item/mod/module/stealth/ninja/on_deactivation(display_message = TRUE, deleting = FALSE) - . = ..() - if(!.) - return REMOVE_TRAIT(mod.wearer, TRAIT_SILENT_FOOTSTEPS, MOD_TRAIT) ///Camera Vision - Prevents flashes, blocks tracking. diff --git a/code/modules/mod/modules/modules_security.dm b/code/modules/mod/modules/modules_security.dm index 19150b8a4cd67d..752273fa0748cc 100644 --- a/code/modules/mod/modules/modules_security.dm +++ b/code/modules/mod/modules/modules_security.dm @@ -269,7 +269,7 @@ dispense_type = /obj/item/grenade/mirage /obj/item/mod/module/dispenser/mirage/on_use() - var/obj/item/grenade/mirage/grenade = . + var/obj/item/grenade/mirage/grenade = ..() grenade.arm_grenade(mod.wearer) /obj/item/grenade/mirage @@ -331,9 +331,6 @@ RegisterSignal(dampening_field, COMSIG_DAMPENER_RELEASE, PROC_REF(release_projectile)) /obj/item/mod/module/projectile_dampener/on_deactivation(display_message, deleting = FALSE) - . = ..() - if(!.) - return QDEL_NULL(dampening_field) /obj/item/mod/module/projectile_dampener/proc/dampen_projectile(datum/source, obj/projectile/projectile) diff --git a/code/modules/power/apc/apc_main.dm b/code/modules/power/apc/apc_main.dm index 90fe374cf9c0ac..481ccde663b72b 100644 --- a/code/modules/power/apc/apc_main.dm +++ b/code/modules/power/apc/apc_main.dm @@ -308,7 +308,6 @@ /obj/machinery/power/apc/Exited(atom/movable/gone, direction) . = ..() if(gone == cell) - cell.update_appearance() cell = null charging = APC_NOT_CHARGING update_appearance() diff --git a/code/modules/power/apc/apc_tool_act.dm b/code/modules/power/apc/apc_tool_act.dm index 2072ab145614de..8e4d51a703da6b 100644 --- a/code/modules/power/apc/apc_tool_act.dm +++ b/code/modules/power/apc/apc_tool_act.dm @@ -320,7 +320,6 @@ balloon_alert(user, "cell removed") var/turf/user_turf = get_turf(user) cell.forceMove(user_turf) - cell.update_appearance() cell = null charging = APC_NOT_CHARGING update_appearance() diff --git a/code/modules/power/cable.dm b/code/modules/power/cable.dm index a8e20cde8c7a0b..65b4f017229598 100644 --- a/code/modules/power/cable.dm +++ b/code/modules/power/cable.dm @@ -565,22 +565,42 @@ GLOBAL_LIST_INIT(wire_node_generating_types, typecacheof(list(/obj/structure/gri // General procedures /////////////////////////////////// //you can use wires to heal robotics -/obj/item/stack/cable_coil/attack(mob/living/carbon/human/H, mob/user) - if(!istype(H)) - return ..() - var/obj/item/bodypart/affecting = H.get_bodypart(check_zone(user.zone_selected)) - if(affecting && IS_ROBOTIC_LIMB(affecting)) - if(user == H) - user.visible_message(span_notice("[user] starts to fix some of the wires in [H]'s [affecting.name]."), span_notice("You start fixing some of the wires in [H == user ? "your" : "[H]'s"] [affecting.name].")) - if(!do_after(user, 5 SECONDS, H)) - return - if(H.item_heal(user, 0, 15, "dents", "burnt wires", BODYTYPE_ROBOTIC)) - use(1) +/obj/item/stack/cable_coil/interact_with_atom(atom/interacting_with, mob/living/user, list/modifiers) + if(!ishuman(interacting_with)) + return NONE + + if(user.combat_mode) + return NONE + + return try_heal_loop(interacting_with, user) + +/obj/item/stack/cable_coil/proc/try_heal_loop(atom/interacting_with, mob/living/user, repeating = FALSE) + var/mob/living/carbon/human/attacked_humanoid = interacting_with + var/obj/item/bodypart/affecting = attacked_humanoid.get_bodypart(check_zone(user.zone_selected)) + if(isnull(affecting) || !IS_ROBOTIC_LIMB(affecting)) + return NONE + + if (!affecting.get_damage()) return - else - return ..() + user.visible_message(span_notice("[user] starts to fix some of the wires in [attacked_humanoid == user ? user.p_their() : "[attacked_humanoid]'s"] [affecting.name]."), + span_notice("You start fixing some of the wires in [attacked_humanoid == user ? "your" : "[attacked_humanoid]'s"] [affecting.name].")) + + var/use_delay = repeating ? 1 SECONDS : 0 + if(user == attacked_humanoid) + use_delay = 5 SECONDS + + if(!do_after(user, use_delay, attacked_humanoid)) + return ITEM_INTERACT_BLOCKING + + if (!attacked_humanoid.item_heal(user, brute_heal = 0, burn_heal = 15, heal_message_brute = "dents", heal_message_burn = "burnt wires", required_bodytype = BODYTYPE_ROBOTIC)) + return ITEM_INTERACT_BLOCKING + + if (use(1) && amount > 0) + INVOKE_ASYNC(src, PROC_REF(try_heal_loop), interacting_with, user, TRUE) + + return ITEM_INTERACT_SUCCESS /////////////////////////////////////////////// // Cable laying procedures diff --git a/code/modules/power/gravitygenerator.dm b/code/modules/power/gravitygenerator.dm index 1e561c60307927..ecab6e4eee9a1a 100644 --- a/code/modules/power/gravitygenerator.dm +++ b/code/modules/power/gravitygenerator.dm @@ -78,6 +78,7 @@ GLOBAL_LIST_EMPTY(gravity_generators) /obj/machinery/gravity_generator/part/Destroy() atom_break() if(main_part) + main_part.generator_parts -= src UnregisterSignal(main_part, COMSIG_ATOM_UPDATED_ICON) main_part = null return ..() diff --git a/code/modules/power/lighting/light_construct.dm b/code/modules/power/lighting/light_construct.dm index ec09fdc26924f6..902ca9fb0eb3dc 100644 --- a/code/modules/power/lighting/light_construct.dm +++ b/code/modules/power/lighting/light_construct.dm @@ -63,7 +63,6 @@ return user.visible_message(span_notice("[user] removes [cell] from [src]!"), span_notice("You remove [cell].")) user.put_in_hands(cell) - cell.update_appearance() cell = null add_fingerprint(user) diff --git a/code/modules/power/power_store.dm b/code/modules/power/power_store.dm index 688dc70908f36c..8bbaa5bc0fe58e 100644 --- a/code/modules/power/power_store.dm +++ b/code/modules/power/power_store.dm @@ -57,6 +57,13 @@ ) AddElement(/datum/element/connect_loc, loc_connections) + +/obj/item/stock_parts/power_store/Moved(atom/old_loc, movement_dir, forced, list/old_locs, momentum_change = TRUE) + . = ..() + if(!isturf(old_loc)) + update_appearance() + + /** * Signal proc for [COMSIG_ITEM_MAGICALLY_CHARGED] * diff --git a/code/modules/projectiles/ammunition/ballistic/pistol.dm b/code/modules/projectiles/ammunition/ballistic/pistol.dm index a2f55f797bdb5f..bc25970e7c364b 100644 --- a/code/modules/projectiles/ammunition/ballistic/pistol.dm +++ b/code/modules/projectiles/ammunition/ballistic/pistol.dm @@ -26,7 +26,7 @@ desc = "A 10mm reaper bullet casing." projectile_type = /obj/projectile/bullet/c10mm/reaper -// 9mm (Makarov, Stechkin APS, PP-95) +// 9mm (Makarov, Stechkin APS) /obj/item/ammo_casing/c9mm name = "9mm bullet casing" @@ -49,7 +49,6 @@ desc = "A 9mm incendiary bullet casing." projectile_type = /obj/projectile/bullet/incendiary/c9mm - // .50AE (Desert Eagle) /obj/item/ammo_casing/a50ae @@ -57,3 +56,21 @@ desc = "A .50AE bullet casing." caliber = CALIBER_50AE projectile_type = /obj/projectile/bullet/a50ae + +// .160 Smart (Abielle smartgun) + +/obj/item/ammo_casing/c160smart + name = ".160 smart bullet casing" + desc = "A .160 smart bullet with a small charge of booster propellant at the bottom." + icon_state = "smartgun_casing" + caliber = CALIBER_160SMART + projectile_type = /obj/projectile/bullet/c160smart + +/obj/item/ammo_casing/c160smart/Initialize(mapload) + . = ..() + AddElement(/datum/element/caseless) + +/obj/item/ammo_casing/c160smart/ready_proj(atom/target, mob/living/user, quiet, zone_override, atom/fired_from) + . = ..() + if(!isturf(target)) + loaded_projectile.set_homing_target(target) diff --git a/code/modules/projectiles/boxes_magazines/external/smg.dm b/code/modules/projectiles/boxes_magazines/external/smg.dm index 3ebb459ed93197..40837d9ddbc4cf 100644 --- a/code/modules/projectiles/boxes_magazines/external/smg.dm +++ b/code/modules/projectiles/boxes_magazines/external/smg.dm @@ -30,18 +30,16 @@ . = ..() icon_state = "[base_icon_state]-[round(ammo_count(), 4)]" -/obj/item/ammo_box/magazine/plastikov9mm - name = "PP-95 magazine (9mm)" - icon_state = "9x19-50" - base_icon_state = "9x19" - ammo_type = /obj/item/ammo_casing/c9mm - caliber = CALIBER_9MM +/obj/item/ammo_box/magazine/smartgun + name = "Abielle magazine (.160 Smart)" + icon_state = "smartgun" + base_icon_state = "smartgun" + ammo_type = /obj/item/ammo_casing/c160smart + multiple_sprites = AMMO_BOX_FULL_EMPTY + multiple_sprite_use_base = TRUE + caliber = CALIBER_160SMART max_ammo = 50 -/obj/item/ammo_box/magazine/plastikov9mm/update_icon_state() - . = ..() - icon_state = "[base_icon_state]-[ammo_count() ? 50 : 0]" - /obj/item/ammo_box/magazine/uzim9mm name = "uzi magazine (9mm)" icon_state = "uzi9mm-32" diff --git a/code/modules/projectiles/guns/ballistic.dm b/code/modules/projectiles/guns/ballistic.dm index d009cabd1a9a39..8a8b4dbacfcccb 100644 --- a/code/modules/projectiles/guns/ballistic.dm +++ b/code/modules/projectiles/guns/ballistic.dm @@ -5,6 +5,8 @@ name = "projectile gun" icon_state = "debug" w_class = WEIGHT_CLASS_NORMAL + pickup_sound = 'sound/items/gun_pick_up.ogg' + drop_sound = 'sound/items/gun_drop.ogg' ///sound when inserting magazine var/load_sound = 'sound/weapons/gun/general/magazine_insert_full.ogg' diff --git a/code/modules/projectiles/guns/ballistic/automatic.dm b/code/modules/projectiles/guns/ballistic/automatic.dm index b86e2a99389959..a895cbe88e44f0 100644 --- a/code/modules/projectiles/guns/ballistic/automatic.dm +++ b/code/modules/projectiles/guns/ballistic/automatic.dm @@ -86,20 +86,33 @@ /obj/item/gun/ballistic/automatic/wt550/add_bayonet_point() AddComponent(/datum/component/bayonet_attachable, offset_x = 25, offset_y = 12) -/obj/item/gun/ballistic/automatic/plastikov - name = "\improper PP-95 SMG" - desc = "An ancient 9mm submachine gun pattern updated and simplified to lower costs, though perhaps simplified too much." - icon_state = "plastikov" - inhand_icon_state = "plastikov" - accepted_magazine_type = /obj/item/ammo_box/magazine/plastikov9mm - burst_size = 5 - spread = 25 - can_suppress = FALSE +/obj/item/gun/ballistic/automatic/smartgun + name = "\improper Abielle Smart-SMG" + desc = "An old experiment in smart-weapon technology that guides bullets towards the target the gun was aimed at when fired. \ + While the tracking functions worked fine, the gun is prone to insanely wide spread thanks to it's practically non-existant barrel." + icon_state = "smartgun" + inhand_icon_state = "smartgun" + accepted_magazine_type = /obj/item/ammo_box/magazine/smartgun + burst_size = 4 + fire_delay = 1 + spread = 40 + dual_wield_spread = 20 actions_types = list() - projectile_damage_multiplier = 0.35 //It's like 10.5 damage per bullet, it's close enough to 10 shots + bolt_type = BOLT_TYPE_LOCKING + can_suppress = FALSE mag_display = TRUE empty_indicator = TRUE - fire_sound = 'sound/weapons/gun/smg/shot_alt.ogg' + click_on_low_ammo = FALSE + /// List of the possible firing sounds + var/list/firing_sound_list = list( + 'sound/weapons/gun/smartgun/smartgun_shoot_1.ogg', + 'sound/weapons/gun/smartgun/smartgun_shoot_2.ogg', + 'sound/weapons/gun/smartgun/smartgun_shoot_3.ogg', + ) + +/obj/item/gun/ballistic/automatic/smartgun/fire_sounds() + var/picked_fire_sound = pick(firing_sound_list) + playsound(src, picked_fire_sound, fire_sound_volume, vary_fire_sound) /obj/item/gun/ballistic/automatic/mini_uzi name = "\improper Type U3 Uzi" diff --git a/code/modules/projectiles/guns/ballistic/bows/bow_arrows.dm b/code/modules/projectiles/guns/ballistic/bows/bow_arrows.dm index 92c4f19e9b333a..d7a24c9deba474 100644 --- a/code/modules/projectiles/guns/ballistic/bows/bow_arrows.dm +++ b/code/modules/projectiles/guns/ballistic/bows/bow_arrows.dm @@ -45,6 +45,60 @@ jostle_pain_mult = 3 rip_time = 1 SECONDS +/// sticky arrows +/obj/item/ammo_casing/arrow/sticky + name = "sticky arrow" + desc = "A sticky arrow. Not sharp-ended, but ripping it off yourself once hit would be rather difficult and painful." + icon_state = "sticky_arrow" + inhand_icon_state = "sticky_arrow" + base_icon_state = "sticky_arrow" + projectile_type = /obj/projectile/bullet/arrow/sticky + +///sticky arrow projectile +/obj/projectile/bullet/arrow/sticky + name = "sticky arrow" + desc = "Quite the sticky situation..." + icon_state = "sticky_arrow_projectile" + damage = 30 + speed = 0.75 + range = 20 + embed_type = /datum/embed_data/arrow/sticky + +/datum/embed_data/arrow/sticky + embed_chance = 99 + fall_chance = 0 + jostle_chance = 1 + ignore_throwspeed_threshold = TRUE + pain_stam_pct = 0.7 + pain_mult = 3 + jostle_pain_mult = 3 + rip_time = 8 SECONDS + +/// poison arrows +/obj/item/ammo_casing/arrow/poison + name = "poisonous arrow" + desc = "A poisonous arrow." + icon_state = "poison_arrow" + inhand_icon_state = "poison_arrow" + base_icon_state = "poison_arrow" + projectile_type = /obj/projectile/bullet/arrow/poison + +/// poison arrow projctile +/obj/projectile/bullet/arrow/poison + name = "poisonous arrow" + desc = "Better to not get hit with this!" + icon_state = "poison_arrow_projectile" + damage = 40 + embed_type = /datum/embed_data/arrow + +/obj/projectile/bullet/arrow/poison/on_hit(atom/target, blocked, pierce_hit) + . = ..() + if(!ishuman(target)) + return + + target.reagents?.add_reagent(/datum/reagent/toxin/cyanide, 8) + target.reagents?.add_reagent(/datum/reagent/toxin/staminatoxin, 1) + /// holy arrows /obj/item/ammo_casing/arrow/holy name = "holy arrow" diff --git a/code/modules/projectiles/guns/energy.dm b/code/modules/projectiles/guns/energy.dm index 3571e0858c8afc..9c16133e1ea35e 100644 --- a/code/modules/projectiles/guns/energy.dm +++ b/code/modules/projectiles/guns/energy.dm @@ -3,6 +3,8 @@ name = "energy gun" desc = "A basic energy-based gun." icon = 'icons/obj/weapons/guns/energy.dmi' + pickup_sound = 'sound/items/gun_pick_up.ogg' + drop_sound = 'sound/items/gun_drop.ogg' /// What type of power cell this uses var/obj/item/stock_parts/power_store/cell diff --git a/code/modules/projectiles/projectile.dm b/code/modules/projectiles/projectile.dm index 5833a95c567665..c501f15db90e6c 100644 --- a/code/modules/projectiles/projectile.dm +++ b/code/modules/projectiles/projectile.dm @@ -85,7 +85,8 @@ /// `speed` a modest value like 1 and set this to a low value like 0.2. var/pixel_speed_multiplier = 1 - var/Angle = 0 + /// The current angle of the projectile. Initially null, so if the arg is missing from [/fire()], we can calculate it from firer and target as fallback. + var/Angle var/original_angle = 0 //Angle at firing var/nondirectional_sprite = FALSE //Set TRUE to prevent projectiles from having their sprites rotated based on firing angle var/spread = 0 //amount (in degrees) of projectile spread @@ -761,21 +762,19 @@ process_hit(get_turf(direct_target), direct_target) if(QDELETED(src)) return + var/turf/starting = get_turf(src) if(isnum(angle)) set_angle(angle) - if(spread) - set_angle(Angle + ((rand() - 0.5) * spread)) - var/turf/starting = get_turf(src) - if(isnull(Angle)) //Try to resolve through offsets if there's no angle set. + else if(isnull(Angle)) //Try to resolve through offsets if there's no angle set. if(isnull(xo) || isnull(yo)) stack_trace("WARNING: Projectile [type] deleted due to being unable to resolve a target after angle was null!") qdel(src) return var/turf/target = locate(clamp(starting + xo, 1, world.maxx), clamp(starting + yo, 1, world.maxy), starting.z) set_angle(get_angle(src, target)) + if(spread) + set_angle(Angle + (rand() - 0.5) * spread) original_angle = Angle - if(!nondirectional_sprite) - transform = transform.Turn(Angle) trajectory_ignore_forcemove = TRUE forceMove(starting) trajectory_ignore_forcemove = FALSE diff --git a/code/modules/projectiles/projectile/bullets/pistol.dm b/code/modules/projectiles/projectile/bullets/pistol.dm index 6bd355219f9502..63e491e2f290d0 100644 --- a/code/modules/projectiles/projectile/bullets/pistol.dm +++ b/code/modules/projectiles/projectile/bullets/pistol.dm @@ -71,3 +71,25 @@ impact_light_intensity = 5 impact_light_range = 1 impact_light_color_override = LIGHT_COLOR_DIM_YELLOW + +// .160 Smart + +/obj/projectile/bullet/c160smart + name = ".160 smart bullet" + icon_state = "smartgun" + damage = 10 + embed_type = /datum/embed_data/bullet_c160smart + speed = 2 + homing_turn_speed = 5 + homing_inaccuracy_min = 4 + homing_inaccuracy_max = 10 + +/datum/embed_data/bullet_c160smart + embed_chance = 10 + fall_chance = 5 + jostle_chance = 3 + ignore_throwspeed_threshold = TRUE + pain_stam_pct = 0.25 + pain_mult = 3 + jostle_pain_mult = 6 + rip_time = 5 diff --git a/code/modules/reagents/chemistry/machinery/chem_master.dm b/code/modules/reagents/chemistry/machinery/chem_master.dm index 91b921b4f7c720..237dcb862af508 100644 --- a/code/modules/reagents/chemistry/machinery/chem_master.dm +++ b/code/modules/reagents/chemistry/machinery/chem_master.dm @@ -247,11 +247,6 @@ /obj/machinery/chem_master/attack_ai_secondary(mob/user, list/modifiers) return attack_hand_secondary(user, modifiers) -/obj/machinery/chem_master/ui_assets(mob/user) - return list( - get_asset_datum(/datum/asset/spritesheet/chemmaster) - ) - /obj/machinery/chem_master/ui_interact(mob/user, datum/tgui/ui) ui = SStgui.try_update_ui(user, src, ui) if(!ui) @@ -273,9 +268,10 @@ //add containers to this category for(var/obj/item/reagent_containers/container as anything in printable_containers[category]) category_list["containers"] += list(list( - "icon" = sanitize_css_class_name("[container]"), "ref" = REF(container), "name" = initial(container.name), + "icon" = initial(container.icon), + "icon_state" = initial(container.icon_state), "volume" = initial(container.volume), )) diff --git a/code/modules/reagents/reagent_containers/misc.dm b/code/modules/reagents/reagent_containers/misc.dm index d2dc2adfb5f764..8b13ab4a54bebb 100644 --- a/code/modules/reagents/reagent_containers/misc.dm +++ b/code/modules/reagents/reagent_containers/misc.dm @@ -91,7 +91,6 @@ /obj/item/reagent_containers/cup/maunamug/attack_hand(mob/living/user, list/modifiers) if(cell && open) - cell.update_appearance() user.put_in_hands(cell) cell = null to_chat(user, span_notice("You remove the power cell from [src].")) diff --git a/code/modules/reagents/reagent_containers/spray.dm b/code/modules/reagents/reagent_containers/spray.dm index bb426436599c0c..dc54dcd7db44b9 100644 --- a/code/modules/reagents/reagent_containers/spray.dm +++ b/code/modules/reagents/reagent_containers/spray.dm @@ -229,6 +229,8 @@ stream_range = 4 amount_per_transfer_from_this = 5 list_reagents = list(/datum/reagent/consumable/condensedcapsaicin = 50) + pickup_sound = 'sound/items/pepper_spray_pick_up.ogg' + drop_sound = 'sound/items/pepper_spray_drop.ogg' /obj/item/reagent_containers/spray/pepper/empty //for protolathe printing list_reagents = null diff --git a/code/modules/research/designs/medical_designs.dm b/code/modules/research/designs/medical_designs.dm index 23a41da63ec147..5daf936119076e 100644 --- a/code/modules/research/designs/medical_designs.dm +++ b/code/modules/research/designs/medical_designs.dm @@ -403,7 +403,11 @@ desc = "A set of surgical tools hidden behind a concealed panel on the user's arm." id = "ci-surgery" build_type = PROTOLATHE | AWAY_LATHE | MECHFAB - materials = list (/datum/material/iron = SHEET_MATERIAL_AMOUNT*1.25, /datum/material/glass =HALF_SHEET_MATERIAL_AMOUNT * 1.5, /datum/material/silver =HALF_SHEET_MATERIAL_AMOUNT * 1.5) + materials = list ( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 1.25, + /datum/material/glass = HALF_SHEET_MATERIAL_AMOUNT * 1.5, + /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT * 1.5, + ) construction_time = 2 SECONDS build_path = /obj/item/organ/internal/cyberimp/arm/surgery category = list( @@ -416,7 +420,11 @@ desc = "A stripped-down version of engineering cyborg toolset, designed to be installed on subject's arm." id = "ci-toolset" build_type = PROTOLATHE | AWAY_LATHE | MECHFAB - materials = list (/datum/material/iron = SHEET_MATERIAL_AMOUNT*1.25, /datum/material/glass =HALF_SHEET_MATERIAL_AMOUNT * 1.5, /datum/material/silver =HALF_SHEET_MATERIAL_AMOUNT * 1.5) + materials = list ( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 1.25, + /datum/material/glass = HALF_SHEET_MATERIAL_AMOUNT * 1.5, + /datum/material/silver = HALF_SHEET_MATERIAL_AMOUNT * 1.5, + ) construction_time = 2 SECONDS build_path = /obj/item/organ/internal/cyberimp/arm/toolset category = list( diff --git a/code/modules/research/techweb/_techweb.dm b/code/modules/research/techweb/_techweb.dm index a85c4b82c1725c..1a5a387551178e 100644 --- a/code/modules/research/techweb/_techweb.dm +++ b/code/modules/research/techweb/_techweb.dm @@ -332,16 +332,16 @@ return techweb_point_display_generic(research_points) /datum/techweb/proc/enqueue_node(id, mob/user) - var/mob/living/carbon/human/human_user = user - var/is_rd = FALSE - if(human_user.wear_id) - var/list/access = human_user.wear_id.GetAccess() + var/queue_first = FALSE + if(istype(user, /mob/living/carbon/human)) + var/mob/living/carbon/human/human_user = user + var/list/access = human_user.wear_id?.GetAccess() if(ACCESS_RD in access) - is_rd = TRUE + queue_first = TRUE if(id in research_queue_nodes) - if(is_rd) - research_queue_nodes.Remove(id) + if(queue_first) + research_queue_nodes.Remove(id) // Remove to be able to place first else return FALSE @@ -349,7 +349,7 @@ if(research_queue_nodes[node_id] == user) research_queue_nodes.Remove(node_id) - if (is_rd) + if (queue_first) research_queue_nodes.Insert(1, id) research_queue_nodes[id] = user diff --git a/code/modules/research/techweb/_techweb_node.dm b/code/modules/research/techweb/_techweb_node.dm index 9b26ca860d88d5..23ad6fd213dbab 100644 --- a/code/modules/research/techweb/_techweb_node.dm +++ b/code/modules/research/techweb/_techweb_node.dm @@ -90,8 +90,7 @@ var/list/boostlist = host.boosted_nodes[id] for(var/booster in boostlist) if(actual_costs[booster]) - var/delta = max(0, actual_costs[booster] - 250) - actual_costs[booster] -= min(boostlist[booster], delta) + actual_costs[booster] = max(actual_costs[booster] - boostlist[booster], 0) return actual_costs diff --git a/code/modules/research/xenobiology/crossbreeding/consuming.dm b/code/modules/research/xenobiology/crossbreeding/consuming.dm index 5a23d30671f545..be8bba7ec66fa1 100644 --- a/code/modules/research/xenobiology/crossbreeding/consuming.dm +++ b/code/modules/research/xenobiology/crossbreeding/consuming.dm @@ -226,30 +226,40 @@ Consuming extracts: icon_state = "bluespace" taste = "sugar and starlight" -/obj/item/slime_cookie/bluespace/do_effect(mob/living/M, mob/user) - var/list/L = get_area_turfs(get_area(get_turf(M))) +/obj/item/slime_cookie/bluespace/do_effect(mob/living/eater, mob/user) + var/area/eater_area = get_area(eater) + if (eater_area.area_flags & NOTELEPORT) + fail_effect(eater) + return + + var/list/area_turfs = get_area_turfs(get_area(get_turf(eater))) var/turf/target - while (L.len && !target) - var/I = rand(1, L.len) - var/turf/T = L[I] - if (is_centcom_level(T.z)) - L.Cut(I,I+1) + + while (length(area_turfs)) + var/turf/check_turf = pick_n_take(area_turfs) + if (is_centcom_level(check_turf.z)) + continue // Probably already filtered out by NOTELEPORT but let's just be careful + if (check_turf.is_blocked_turf()) continue - if(!T.density) - var/clear = TRUE - for(var/obj/O in T) - if(O.density) - clear = FALSE - break - if(clear) - target = T - if (!target) - L.Cut(I,I+1) - - if(target) - do_teleport(M, target, 0, asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE) - new /obj/effect/particle_effect/sparks(get_turf(M)) - playsound(get_turf(M), SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + target = check_turf + break + + if (isnull(target)) + fail_effect(eater) + return + if (!do_teleport(eater, target, 0, asoundin = 'sound/effects/phasein.ogg', channel = TELEPORT_CHANNEL_BLUESPACE)) + fail_effect(eater) + return + new /obj/effect/particle_effect/sparks(target) + playsound(target, SFX_SPARKS, 50, TRUE, SHORT_RANGE_SOUND_EXTRARANGE) + +/obj/item/slime_cookie/bluespace/proc/fail_effect(mob/living/eater) + eater.visible_message( + message = span_warning("[eater] briefly vanishes... then slams forcefully into the ground"), + self_message = span_warning("You briefly vanish... and are returned forcefully to the ground.") + ) + eater.Knockdown(0.1 SECONDS) + new /obj/effect/particle_effect/sparks(get_turf(eater)) /obj/item/slimecross/consuming/sepia colour = SLIME_TYPE_SEPIA diff --git a/code/modules/research/xenobiology/xenobiology.dm b/code/modules/research/xenobiology/xenobiology.dm index be805ae9da82f3..6ec7fca37e3622 100644 --- a/code/modules/research/xenobiology/xenobiology.dm +++ b/code/modules/research/xenobiology/xenobiology.dm @@ -715,13 +715,10 @@ if(!dumb_mob.compare_sentience_type(sentience_type)) // Will also return false if not a basic or simple mob, which are the only two we want anyway balloon_alert(user, "invalid creature!") return - if(isnull(potion_reason)) - balloon_alert(user, "no reason for offering set!") - return balloon_alert(user, "offering...") being_used = TRUE var/mob/chosen_one = SSpolling.poll_ghosts_for_target( - question = "[span_danger(user.name)] is offering [span_notice(dumb_mob.name)] an intelligence potion! Reason: [span_boldnotice(potion_reason)]", + question = "[span_danger(user.name)] is offering [span_notice(dumb_mob.name)] an intelligence potion![potion_reason ? " Reason: [span_boldnotice(potion_reason)]" : ""]", check_jobban = ROLE_SENTIENCE, poll_time = 20 SECONDS, checked_target = dumb_mob, diff --git a/code/modules/shuttle/supply.dm b/code/modules/shuttle/supply.dm index 01657d2ebb9765..72096f7bb9bfb7 100644 --- a/code/modules/shuttle/supply.dm +++ b/code/modules/shuttle/supply.dm @@ -81,12 +81,11 @@ GLOBAL_LIST_INIT(blacklisted_cargo_types, typecacheof(list( if(!length(stuff_to_send_home)) return FALSE - var/obj/structure/closet/supplypod/centcompod/et_go_home = new() - - for(var/atom/movable/et as anything in stuff_to_send_home) - et.forceMove(et_go_home) - - new /obj/effect/pod_landingzone(get_turf(home), et_go_home) + podspawn(list( + "target" = get_turf(home), + "path" = /obj/structure/closet/supplypod/centcompod, + "spawn" = stuff_to_send_home, + )) return stuff_to_send_home diff --git a/code/modules/surgery/amputation.dm b/code/modules/surgery/amputation.dm index 49793c1ad2de28..16045a760324cd 100644 --- a/code/modules/surgery/amputation.dm +++ b/code/modules/surgery/amputation.dm @@ -27,6 +27,13 @@ /datum/surgery_step/sever_limb/mechanic, //The benefit of being robotic; people can pull you apart in an instant! Wait, that's not a benefit... ) +/datum/surgery/amputation/peg + name = "Detach" + requires_bodypart_type = BODYTYPE_PEG + steps = list( + /datum/surgery_step/sever_limb/peg, //Easy come, easy go + ) + /datum/surgery/amputation/can_start(mob/user, mob/living/patient) if(HAS_TRAIT(patient, TRAIT_NODISMEMBER)) return FALSE @@ -62,6 +69,19 @@ preop_sound = 'sound/items/ratchet.ogg' preop_sound = 'sound/machines/doorclick.ogg' +/datum/surgery_step/sever_limb/peg + name = "detach limb (circular saw)" + implements = list( + TOOL_SAW = 100, + /obj/item/shovel/serrated = 100, + /obj/item/fireaxe = 90, + /obj/item/hatchet = 75, + TOOL_SCALPEL = 25, + ) + time = 30 + preop_sound = 'sound/surgery/saw.ogg' + success_sound = 'sound/items/wood_drop.ogg' + /datum/surgery_step/sever_limb/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) display_results( user, diff --git a/code/modules/surgery/cavity_implant.dm b/code/modules/surgery/cavity_implant.dm index ac8c69610c3504..3ec68f8db88583 100644 --- a/code/modules/surgery/cavity_implant.dm +++ b/code/modules/surgery/cavity_implant.dm @@ -9,6 +9,8 @@ /datum/surgery_step/handle_cavity, /datum/surgery_step/close) +GLOBAL_LIST_INIT(heavy_cavity_implants, typecacheof(list(/obj/item/transfer_valve))) + //handle cavity /datum/surgery_step/handle_cavity name = "implant item" @@ -49,7 +51,7 @@ /datum/surgery_step/handle_cavity/success(mob/user, mob/living/carbon/human/target, target_zone, obj/item/tool, datum/surgery/surgery = FALSE) var/obj/item/bodypart/chest/target_chest = target.get_bodypart(BODY_ZONE_CHEST) if(tool) - if(item_for_cavity || tool.w_class > WEIGHT_CLASS_NORMAL || HAS_TRAIT(tool, TRAIT_NODROP) || isorgan(tool)) + if(item_for_cavity || ((tool.w_class > WEIGHT_CLASS_NORMAL) && !is_type_in_typecache(tool, GLOB.heavy_cavity_implants)) || HAS_TRAIT(tool, TRAIT_NODROP) || isorgan(tool)) to_chat(user, span_warning("You can't seem to fit [tool] in [target]'s [target_zone]!")) return FALSE else diff --git a/code/modules/surgery/organs/external/tails.dm b/code/modules/surgery/organs/external/tails.dm index e4cd3f50a49979..1a52bbe56cd5b4 100644 --- a/code/modules/surgery/organs/external/tails.dm +++ b/code/modules/surgery/organs/external/tails.dm @@ -175,7 +175,7 @@ bodypart_overlay = /datum/bodypart_overlay/mutant/tail/monkey - dna_block = DNA_MONKEY_TAIL_BLOCK + dna_block = null ///Monkey tail bodypart overlay /datum/bodypart_overlay/mutant/tail/monkey diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm b/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm index 5632688cb476b8..4a7dcab80f2596 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_arms.dm @@ -2,7 +2,7 @@ name = "arm-mounted implant" desc = "You shouldn't see this! Adminhelp and report this as an issue on github!" zone = BODY_ZONE_R_ARM - icon_state = "implant-toolkit" + icon_state = "toolkit_generic" w_class = WEIGHT_CLASS_SMALL actions_types = list(/datum/action/item_action/organ_action/toggle) ///A ref for the arm we're taking up. Mostly for the unregister signal upon removal @@ -17,6 +17,10 @@ var/extend_sound = 'sound/mecha/mechmove03.ogg' /// Sound played when retracting var/retract_sound = 'sound/mecha/mechmove03.ogg' + /// Organ slot that the implant occupies for the right arm + var/right_arm_organ_slot = ORGAN_SLOT_RIGHT_ARM_AUG + /// Organ slot that the implant occupies for the left arm + var/left_arm_organ_slot = ORGAN_SLOT_LEFT_ARM_AUG /obj/item/organ/internal/cyberimp/arm/Initialize(mapload) . = ..() @@ -48,9 +52,9 @@ /obj/item/organ/internal/cyberimp/arm/proc/SetSlotFromZone() switch(zone) if(BODY_ZONE_L_ARM) - slot = ORGAN_SLOT_LEFT_ARM_AUG + slot = left_arm_organ_slot if(BODY_ZONE_R_ARM) - slot = ORGAN_SLOT_RIGHT_ARM_AUG + slot = right_arm_organ_slot else CRASH("Invalid zone for [type]") @@ -260,6 +264,7 @@ /obj/item/organ/internal/cyberimp/arm/toolset name = "integrated toolset implant" desc = "A stripped-down version of the engineering cyborg toolset, designed to be installed on subject's arm. Contain advanced versions of every tool." + icon_state = "toolkit_engineering" actions_types = list(/datum/action/item_action/organ_action/toggle/toolkit) items_to_create = list( /obj/item/screwdriver/cyborg, @@ -345,6 +350,7 @@ /obj/item/organ/internal/cyberimp/arm/surgery name = "surgical toolset implant" desc = "A set of surgical tools hidden behind a concealed panel on the user's arm." + icon_state = "toolkit_surgical" actions_types = list(/datum/action/item_action/organ_action/toggle/toolkit) items_to_create = list( /obj/item/retractor/augment, @@ -370,18 +376,24 @@ /obj/item/knife/combat/cyborg, ) -/obj/item/organ/internal/cyberimp/arm/muscle +/obj/item/organ/internal/cyberimp/arm/strongarm name = "\proper Strong-Arm empowered musculature implant" desc = "When implanted, this cybernetic implant will enhance the muscles of the arm to deliver more power-per-action." icon_state = "muscle_implant" zone = BODY_ZONE_R_ARM - slot = ORGAN_SLOT_RIGHT_ARM_AUG + slot = ORGAN_SLOT_RIGHT_ARM_MUSCLE + right_arm_organ_slot = ORGAN_SLOT_RIGHT_ARM_MUSCLE + left_arm_organ_slot = ORGAN_SLOT_LEFT_ARM_MUSCLE actions_types = list() ///The amount of damage the implant adds to our unarmed attacks. var/punch_damage = 5 + ///Biotypes we apply an additional amount of damage too + var/biotype_bonus_targets = MOB_BEAST | MOB_SPECIAL + ///Extra damage dealt to our targeted mobs + var/biotype_bonus_damage = 20 ///IF true, the throw attack will not smash people into walls var/non_harmful_throw = TRUE ///How far away your attack will throw your oponent @@ -392,17 +404,24 @@ var/throw_power_max = 4 ///How long will the implant malfunction if it is EMP'd var/emp_base_duration = 9 SECONDS + ///How long before we get another slam punch; consider that these usually come in pairs of two + var/slam_cooldown_duration = 5 SECONDS + ///Tracks how soon we can perform another slam attack + COOLDOWN_DECLARE(slam_cooldown) -/obj/item/organ/internal/cyberimp/arm/muscle/on_mob_insert(mob/living/carbon/arm_owner) +/obj/item/organ/internal/cyberimp/arm/strongarm/l + zone = BODY_ZONE_L_ARM + +/obj/item/organ/internal/cyberimp/arm/strongarm/on_mob_insert(mob/living/carbon/arm_owner) . = ..() if(ishuman(arm_owner)) //Sorry, only humans RegisterSignal(arm_owner, COMSIG_LIVING_EARLY_UNARMED_ATTACK, PROC_REF(on_attack_hand)) -/obj/item/organ/internal/cyberimp/arm/muscle/on_mob_remove(mob/living/carbon/arm_owner) +/obj/item/organ/internal/cyberimp/arm/strongarm/on_mob_remove(mob/living/carbon/arm_owner) . = ..() UnregisterSignal(arm_owner, COMSIG_LIVING_EARLY_UNARMED_ATTACK) -/obj/item/organ/internal/cyberimp/arm/muscle/emp_act(severity) +/obj/item/organ/internal/cyberimp/arm/strongarm/emp_act(severity) . = ..() if((organ_flags & ORGAN_FAILING) || . & EMP_PROTECT_SELF) return @@ -410,11 +429,11 @@ organ_flags |= ORGAN_FAILING addtimer(CALLBACK(src, PROC_REF(reboot)), 90 / severity) -/obj/item/organ/internal/cyberimp/arm/muscle/proc/reboot() +/obj/item/organ/internal/cyberimp/arm/strongarm/proc/reboot() organ_flags &= ~ORGAN_FAILING owner.balloon_alert(owner, "your arm stops spasming!") -/obj/item/organ/internal/cyberimp/arm/muscle/proc/on_attack_hand(mob/living/carbon/human/source, atom/target, proximity, modifiers) +/obj/item/organ/internal/cyberimp/arm/strongarm/proc/on_attack_hand(mob/living/carbon/human/source, atom/target, proximity, modifiers) SIGNAL_HANDLER if(source.get_active_hand() != hand || !proximity) @@ -425,6 +444,8 @@ return NONE if(HAS_TRAIT(source, TRAIT_HULK)) //NO HULK return NONE + if(!COOLDOWN_FINISHED(src, slam_cooldown)) + return NONE if(!source.can_unarmed_attack()) return COMPONENT_SKIP_ATTACK @@ -454,13 +475,16 @@ var/obj/item/bodypart/attacking_bodypart = hand potential_damage += rand(attacking_bodypart.unarmed_damage_low, attacking_bodypart.unarmed_damage_high) + var/is_correct_biotype = living_target.mob_biotypes & biotype_bonus_targets + if(biotype_bonus_targets && is_correct_biotype) //If we are punching one of our special biotype targets, increase the damage floor by a factor of two. + potential_damage += biotype_bonus_damage + source.do_attack_animation(target, ATTACK_EFFECT_SMASH) playsound(living_target.loc, 'sound/weapons/punch1.ogg', 25, TRUE, -1) var/target_zone = living_target.get_random_valid_zone(source.zone_selected) var/armor_block = living_target.run_armor_check(target_zone, MELEE, armour_penetration = attacking_bodypart.unarmed_effectiveness) - living_target.apply_damage(potential_damage, attacking_bodypart.attack_type, target_zone, armor_block) - living_target.apply_damage(potential_damage*1.5, STAMINA, target_zone, armor_block) + living_target.apply_damage(potential_damage * 2, attacking_bodypart.attack_type, target_zone, armor_block) if(source.body_position != LYING_DOWN) //Throw them if we are standing var/atom/throw_target = get_edge_target_turf(living_target, source.dir) @@ -478,4 +502,6 @@ log_combat(source, target, "[picked_hit_type]ed", "muscle implant") + COOLDOWN_START(src, slam_cooldown, slam_cooldown_duration) + return COMPONENT_CANCEL_ATTACK_CHAIN diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm b/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm index 046c84200d1ebc..060499936d53da 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_chest.dm @@ -1,15 +1,12 @@ /obj/item/organ/internal/cyberimp/chest name = "cybernetic torso implant" desc = "Implants for the organs in your torso." - icon_state = "chest_implant" - implant_overlay = "chest_implant_overlay" zone = BODY_ZONE_CHEST /obj/item/organ/internal/cyberimp/chest/nutriment - name = "Nutriment pump implant" + name = "nutriment pump implant" desc = "This implant will synthesize and pump into your bloodstream a small amount of nutriment when you are starving." - icon_state = "chest_implant" - implant_color = "#00AA00" + icon_state = "nutriment_implant" var/hunger_threshold = NUTRITION_LEVEL_STARVING var/synthesizing = 0 var/poison_amount = 5 @@ -37,18 +34,16 @@ /obj/item/organ/internal/cyberimp/chest/nutriment/plus - name = "Nutriment pump implant PLUS" + name = "nutriment pump implant PLUS" desc = "This implant will synthesize and pump into your bloodstream a small amount of nutriment when you are hungry." - icon_state = "chest_implant" - implant_color = "#006607" + icon_state = "adv_nutriment_implant" hunger_threshold = NUTRITION_LEVEL_HUNGRY poison_amount = 10 /obj/item/organ/internal/cyberimp/chest/reviver - name = "Reviver implant" + name = "reviver implant" desc = "This implant will attempt to revive and heal you if you lose consciousness. For the faint of heart!" - icon_state = "chest_implant" - implant_color = "#AD0000" + icon_state = "reviver_implant" slot = ORGAN_SLOT_HEART_AID var/revive_cost = 0 var/reviving = FALSE @@ -164,7 +159,6 @@ slot = ORGAN_SLOT_THRUSTERS icon_state = "imp_jetpack" base_icon_state = "imp_jetpack" - implant_overlay = null implant_color = null actions_types = list(/datum/action/item_action/organ_action/toggle) w_class = WEIGHT_CLASS_NORMAL @@ -265,7 +259,7 @@ name = "\improper Herculean gravitronic spinal implant" desc = "This gravitronic spinal interface is able to improve the athletics of a user, allowing them greater physical ability. \ Contains a slot which can be upgraded with a gravity anomaly core, improving its performance." - implant_color = "#15704c" + icon_state = "herculean_implant" slot = ORGAN_SLOT_SPINE /// How much faster does the spinal implant improve our lifting speed, workout ability, reducing falling damage and improving climbing and standing speed var/athletics_boost_multiplier = 0.8 @@ -315,5 +309,7 @@ name = "\improper Atlas gravitonic spinal implant" desc = "This gravitronic spinal interface is able to improve the athletics of a user, allowing them greater physical ability. \ This one has been improved through the installation of a gravity anomaly core, allowing for personal gravity manipulation." + icon_state = "herculean_implant_core" + update_appearance() qdel(tool) return ITEM_INTERACT_SUCCESS diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm b/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm index 401e951a8534a2..d4c4b57d75f6b6 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_eyes.dm @@ -2,7 +2,6 @@ name = "cybernetic eye implant" desc = "Implants for your eyes." icon_state = "eye_implant" - implant_overlay = "eye_implant_overlay" slot = ORGAN_SLOT_EYES zone = BODY_ZONE_PRECISE_EYES w_class = WEIGHT_CLASS_TINY @@ -41,21 +40,25 @@ toggled_on = FALSE /obj/item/organ/internal/cyberimp/eyes/hud/medical - name = "Medical HUD implant" + name = "medical HUD implant" desc = "These cybernetic eye implants will display a medical HUD over everything you see." + icon_state = "eye_implant_medical" HUD_traits = list(TRAIT_MEDICAL_HUD) /obj/item/organ/internal/cyberimp/eyes/hud/security - name = "Security HUD implant" + name = "security HUD implant" desc = "These cybernetic eye implants will display a security HUD over everything you see." + icon_state = "eye_implant_security" HUD_traits = list(TRAIT_SECURITY_HUD) /obj/item/organ/internal/cyberimp/eyes/hud/diagnostic - name = "Diagnostic HUD implant" + name = "diagnostic HUD implant" desc = "These cybernetic eye implants will display a diagnostic HUD over everything you see." + icon_state = "eye_implant_diagnostic" HUD_traits = list(TRAIT_DIAGNOSTIC_HUD, TRAIT_BOT_PATH_HUD) /obj/item/organ/internal/cyberimp/eyes/hud/security/syndicate - name = "Contraband Security HUD Implant" + name = "contraband security HUD implant" desc = "A Cybersun Industries brand Security HUD Implant. These illicit cybernetic eye implants will display a security HUD over everything you see." + icon_state = "eye_implant_syndicate" organ_flags = ORGAN_ROBOTIC | ORGAN_HIDDEN diff --git a/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm b/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm index f36c6cfe838b8b..f71e29631b3845 100644 --- a/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm +++ b/code/modules/surgery/organs/internal/cyberimp/augments_internal.dm @@ -22,8 +22,6 @@ /obj/item/organ/internal/cyberimp/brain name = "cybernetic brain implant" desc = "Injectors of extra sub-routines for the brain." - icon_state = "brain_implant" - implant_overlay = "brain_implant_overlay" zone = BODY_ZONE_HEAD w_class = WEIGHT_CLASS_TINY @@ -39,9 +37,9 @@ /obj/item/organ/internal/cyberimp/brain/anti_drop name = "anti-drop implant" desc = "This cybernetic brain implant will allow you to force your hand muscles to contract, preventing item dropping. Twitch ear to toggle." + icon_state = "brain_implant_antidrop" var/active = FALSE var/list/stored_items = list() - implant_color = "#DE7E00" slot = ORGAN_SLOT_BRAIN_ANTIDROP actions_types = list(/datum/action/item_action/organ_action/toggle) @@ -99,9 +97,9 @@ stored_items -= source /obj/item/organ/internal/cyberimp/brain/anti_stun - name = "CNS Rebooter implant" + name = "CNS rebooter implant" desc = "This implant will automatically give you back control over your central nervous system, reducing downtime when stunned." - implant_color = COLOR_YELLOW + icon_state = "brain_implant_rebooter" slot = ORGAN_SLOT_BRAIN_ANTISTUN var/static/list/signalCache = list( diff --git a/code/modules/surgery/organs/internal/heart/_heart.dm b/code/modules/surgery/organs/internal/heart/_heart.dm index f3899cb994648e..b0fac316ad3e35 100644 --- a/code/modules/surgery/organs/internal/heart/_heart.dm +++ b/code/modules/surgery/organs/internal/heart/_heart.dm @@ -165,13 +165,23 @@ icon_state = "heart-c-on" base_icon_state = "heart-c" organ_flags = ORGAN_ROBOTIC - maxHealth = STANDARD_ORGAN_THRESHOLD*0.75 //This also hits defib timer, so a bit higher than its less important counterparts + maxHealth = STANDARD_ORGAN_THRESHOLD * 0.75 //This also hits defib timer, so a bit higher than its less important counterparts failing_desc = "seems to be broken." - var/dose_available = FALSE - var/rid = /datum/reagent/medicine/epinephrine - var/ramount = 10 - var/emp_vulnerability = 80 //Chance of permanent effects if emp-ed. + /// Whether or not we have a stabilization available. This prevents our owner from entering softcrit for an amount of time. + var/stabilization_available = FALSE + + /// How long our stabilization lasts for. + var/stabilization_duration = 10 SECONDS + + /// Whether our heart suppresses bleeders and restores blood automatically. + var/bleed_prevention = FALSE + + /// The probability that our blood replication causes toxin damage. + var/toxification_probability = 20 + + /// Chance of permanent effects if emp-ed. + var/emp_vulnerability = 80 /obj/item/organ/internal/heart/cybernetic/emp_act(severity) . = ..() @@ -197,35 +207,63 @@ /obj/item/organ/internal/heart/cybernetic/on_life(seconds_per_tick, times_fired) . = ..() - if(dose_available && owner.health <= owner.crit_threshold && !owner.reagents.has_reagent(rid)) - used_dose() -/obj/item/organ/internal/heart/cybernetic/proc/used_dose() - owner.reagents.add_reagent(rid, ramount) - dose_available = FALSE + if(organ_flags & ORGAN_EMP) + return + + if(stabilization_available && owner.health <= owner.crit_threshold) + stabilize_heart() + + if(bleed_prevention && ishuman(owner) && owner.blood_volume < BLOOD_VOLUME_NORMAL) + var/mob/living/carbon/human/wounded_owner = owner + wounded_owner.blood_volume += 2 * seconds_per_tick + if(toxification_probability && prob(toxification_probability)) + wounded_owner.adjustToxLoss(1 * seconds_per_tick, updating_health = FALSE) + + var/datum/wound/bloodiest_wound + + for(var/datum/wound/iter_wound as anything in wounded_owner.all_wounds) + if(iter_wound.blood_flow && iter_wound.blood_flow > bloodiest_wound?.blood_flow) + bloodiest_wound = iter_wound + + if(bloodiest_wound) + bloodiest_wound.adjust_blood_flow(-1 * seconds_per_tick) + +/obj/item/organ/internal/heart/cybernetic/proc/stabilize_heart() + ADD_TRAIT(owner, TRAIT_NOSOFTCRIT, ORGAN_TRAIT) + stabilization_available = FALSE + + addtimer(TRAIT_CALLBACK_REMOVE(owner, TRAIT_NOSOFTCRIT, ORGAN_TRAIT), stabilization_duration) + + addtimer(VARSET_CALLBACK(src, stabilization_available, TRUE), 5 MINUTES, TIMER_DELETE_ME) + +// Largely a sanity check +/obj/item/organ/internal/heart/cybernetic/on_mob_remove(mob/living/carbon/heart_owner, special = FALSE) + . = ..() + if(HAS_TRAIT_FROM(heart_owner, TRAIT_NOSOFTCRIT, ORGAN_TRAIT)) + REMOVE_TRAIT(heart_owner, TRAIT_NOSOFTCRIT, ORGAN_TRAIT) /obj/item/organ/internal/heart/cybernetic/tier2 name = "cybernetic heart" - desc = "An electronic device designed to mimic the functions of an organic human heart. Also holds an emergency dose of epinephrine, used automatically after facing severe trauma." + desc = "An electronic device designed to mimic the functions of an organic human heart. In case of lacerations or haemorrhaging, the heart rapidly begins self-replicating \ + artificial blood. However, this can cause toxins to build up in the bloodstream to the imperfect replication process." icon_state = "heart-c-u-on" base_icon_state = "heart-c-u" maxHealth = 1.5 * STANDARD_ORGAN_THRESHOLD - dose_available = TRUE + bleed_prevention = TRUE emp_vulnerability = 40 /obj/item/organ/internal/heart/cybernetic/tier3 name = "upgraded cybernetic heart" - desc = "An electronic device designed to mimic the functions of an organic human heart. Also holds an emergency dose of epinephrine, used automatically after facing severe trauma. This upgraded model can regenerate its dose after use." + desc = "An electronic device designed to mimic the functions of an organic human heart. In case of physical trauma, the heart has temporary failsafes to maintain patient stability \ + and mobility for a brief moment. In addition, the heart is able to safely self-replicate blood without risk of toxin buildup." icon_state = "heart-c-u2-on" base_icon_state = "heart-c-u2" maxHealth = 2 * STANDARD_ORGAN_THRESHOLD - dose_available = TRUE + stabilization_available = TRUE + toxification_probability = 0 emp_vulnerability = 20 -/obj/item/organ/internal/heart/cybernetic/tier3/used_dose() - . = ..() - addtimer(VARSET_CALLBACK(src, dose_available, TRUE), 5 MINUTES) - /obj/item/organ/internal/heart/cybernetic/surplus name = "surplus prosthetic heart" desc = "A fragile mockery of a human heart that resembles a water pump more than an actual heart. \ diff --git a/code/modules/surgery/organs/internal/heart/heart_anomalock.dm b/code/modules/surgery/organs/internal/heart/heart_anomalock.dm index e9da6197ed2739..5cdb27942358b4 100644 --- a/code/modules/surgery/organs/internal/heart/heart_anomalock.dm +++ b/code/modules/surgery/organs/internal/heart/heart_anomalock.dm @@ -7,6 +7,8 @@ name = "Voltaic Combat Cyberheart" desc = "A cutting-edge cyberheart, originally designed for Nanotrasen killsquad usage but later declassified for normal research. Voltaic technology allows the heart to keep the body upright in dire circumstances, alongside redirecting anomalous flux energy to fully shield the user from shocks and electro-magnetic pulses. Requires a refined Flux core as a power source." icon_state = "anomalock_heart" + bleed_prevention = TRUE + toxification_probability = 0 COOLDOWN_DECLARE(survival_cooldown) ///Cooldown for the activation of the organ diff --git a/code/modules/surgery/organs/organ_movement.dm b/code/modules/surgery/organs/organ_movement.dm index 2889cbe07081bf..ff9f753ce18a1a 100644 --- a/code/modules/surgery/organs/organ_movement.dm +++ b/code/modules/surgery/organs/organ_movement.dm @@ -161,6 +161,7 @@ UnregisterSignal(organ_owner, COMSIG_ATOM_EXAMINE) SEND_SIGNAL(src, COMSIG_ORGAN_REMOVED, organ_owner) SEND_SIGNAL(organ_owner, COMSIG_CARBON_LOSE_ORGAN, src, special) + ADD_TRAIT(src, TRAIT_USED_ORGAN, ORGAN_TRAIT) var/list/diseases = organ_owner.get_static_viruses() if(!LAZYLEN(diseases)) diff --git a/code/modules/surgery/revival.dm b/code/modules/surgery/revival.dm index bda1aaaafef7fa..e0111feb522319 100644 --- a/code/modules/surgery/revival.dm +++ b/code/modules/surgery/revival.dm @@ -104,8 +104,7 @@ span_notice("[user] send a powerful shock to [target]'s brain with [tool]..."), ) target.grab_ghost() - target.adjustOxyLoss(-50, 0) - target.updatehealth() + target.adjustOxyLoss(-50) if(iscarbon(target)) var/mob/living/carbon/carbon_target = target carbon_target.set_heartattack(FALSE) diff --git a/code/modules/surgery/surgery_step.dm b/code/modules/surgery/surgery_step.dm index 350bd60fbd1767..336e76b4d70c2f 100644 --- a/code/modules/surgery/surgery_step.dm +++ b/code/modules/surgery/surgery_step.dm @@ -96,6 +96,12 @@ var/fail_prob = 0//100 - fail_prob = success_prob var/advance = FALSE + if(!chem_check(target)) + user.balloon_alert(user, "missing [LOWER_TEXT(get_chem_list())]!") + to_chat(user, span_warning("[target] is missing the [LOWER_TEXT(get_chem_list())] required to perform this surgery step!")) + surgery.step_in_progress = FALSE + return FALSE + if(preop(user, target, target_zone, tool, surgery) == SURGERY_STEP_FAIL) update_surgery_mood(target, SURGERY_STATE_FAILURE) surgery.step_in_progress = FALSE @@ -134,9 +140,7 @@ if(do_after(user, modded_time, target = target, interaction_key = user.has_status_effect(/datum/status_effect/hippocratic_oath) ? target : DOAFTER_SOURCE_SURGERY)) //If we have the hippocratic oath, we can perform one surgery on each target, otherwise we can only do one surgery in total. - var/chem_check_result = chem_check(target) - if((prob(100-fail_prob) || (iscyborg(user) && !silicons_obey_prob)) && chem_check_result && !try_to_fail) - + if((prob(100-fail_prob) || (iscyborg(user) && !silicons_obey_prob)) && !try_to_fail) if(success(user, target, target_zone, tool, surgery)) update_surgery_mood(target, SURGERY_STATE_SUCCESS) play_success_sound(user, target, target_zone, tool, surgery) @@ -146,8 +150,6 @@ play_failure_sound(user, target, target_zone, tool, surgery) update_surgery_mood(target, SURGERY_STATE_FAILURE) advance = TRUE - if(chem_check_result) - return .(user, target, target_zone, tool, surgery, try_to_fail) //automatically re-attempt if failed for reason other than lack of required chemical if(advance && !repeatable) surgery.status++ if(surgery.status > surgery.steps.len) diff --git a/code/modules/tgs/v5/api.dm b/code/modules/tgs/v5/api.dm index 95b8edd3ee5c2e..05d0dee25b3c2e 100644 --- a/code/modules/tgs/v5/api.dm +++ b/code/modules/tgs/v5/api.dm @@ -50,7 +50,9 @@ version = null // we want this to be the TGS version, not the interop version // sleep once to prevent an issue where world.Export on the first tick can hang indefinitely + TGS_DEBUG_LOG("Starting Export bug prevention sleep tick. time:[world.time] sleep_offline:[world.sleep_offline]") sleep(world.tick_lag) + TGS_DEBUG_LOG("Export bug prevention sleep complete") var/list/bridge_response = Bridge(DMAPI5_BRIDGE_COMMAND_STARTUP, list(DMAPI5_BRIDGE_PARAMETER_MINIMUM_SECURITY_LEVEL = minimum_required_security_level, DMAPI5_BRIDGE_PARAMETER_VERSION = api_version.raw_parameter, DMAPI5_PARAMETER_CUSTOM_COMMANDS = ListCustomCommands(), DMAPI5_PARAMETER_TOPIC_PORT = GetTopicPort())) if(!istype(bridge_response)) diff --git a/code/modules/tgui_input/text.dm b/code/modules/tgui_input/text.dm index 4b3e59a6028c77..806696dcf4f444 100644 --- a/code/modules/tgui_input/text.dm +++ b/code/modules/tgui_input/text.dm @@ -140,9 +140,9 @@ switch(action) if("submit") if(max_length) - if(length(params["entry"]) > max_length) + if(length_char(params["entry"]) > max_length) CRASH("[usr] typed a text string longer than the max length") - if(encode && (length(html_encode(params["entry"])) > max_length)) + if(encode && (length_char(html_encode(params["entry"])) > max_length)) to_chat(usr, span_notice("Your message was clipped due to special character usage.")) set_entry(params["entry"]) closed = TRUE diff --git a/code/modules/transport/elevator/elev_controller.dm b/code/modules/transport/elevator/elev_controller.dm index aae79cfe0f14b3..870211ecb56d93 100644 --- a/code/modules/transport/elevator/elev_controller.dm +++ b/code/modules/transport/elevator/elev_controller.dm @@ -122,7 +122,7 @@ MAPPING_DIRECTIONAL_HELPERS(/obj/machinery/button/elevator, 32) return FALSE // We can't call an elevator that's moving. You may say "you totally can do that", but that's not modelled - if(lift.controls_locked == LIFT_PLATFORM_LOCKED) + if(lift.controller_status & CONTROLS_LOCKED) loc.balloon_alert(activator, "elevator is moving!") return FALSE diff --git a/code/modules/transport/elevator/elev_music_zone.dm b/code/modules/transport/elevator/elev_music_zone.dm index 8379e742caea5c..f5b3de8a67cc40 100644 --- a/code/modules/transport/elevator/elev_music_zone.dm +++ b/code/modules/transport/elevator/elev_music_zone.dm @@ -83,6 +83,8 @@ GLOBAL_LIST_EMPTY(elevator_music) /datum/proximity_monitor/advanced/elevator_music_area/field_turf_uncrossed(mob/exited, turf/old_location, turf/new_location) if (!(exited in tracked_mobs)) return + if ((new_location in field_turfs) || (new_location in edge_turfs)) + return qdel(tracked_mobs[exited]) tracked_mobs -= exited UnregisterSignal(exited, COMSIG_QDELETING) diff --git a/code/modules/transport/elevator/elev_panel.dm b/code/modules/transport/elevator/elev_panel.dm index 76b95922dfe66d..0b5e99bdbb059b 100644 --- a/code/modules/transport/elevator/elev_panel.dm +++ b/code/modules/transport/elevator/elev_panel.dm @@ -276,7 +276,7 @@ var/datum/transport_controller/linear/lift = lift_weakref?.resolve() if(lift) data["lift_exists"] = TRUE - data["currently_moving"] = lift.controls_locked == LIFT_PLATFORM_LOCKED + data["currently_moving"] = lift.controller_status & CONTROLS_LOCKED data["currently_moving_to_floor"] = last_move_target data["current_floor"] = lift.transport_modules[1].z @@ -319,7 +319,7 @@ return TRUE // Something is inaccurate, update UI var/datum/transport_controller/linear/lift = lift_weakref?.resolve() - if(!lift || lift.controls_locked == LIFT_PLATFORM_LOCKED) + if(!lift || lift.controller_status & CONTROLS_LOCKED) return TRUE // We shouldn't be moving anything, update UI INVOKE_ASYNC(lift, TYPE_PROC_REF(/datum/transport_controller/linear, move_to_zlevel), desired_z, CALLBACK(src, PROC_REF(check_panel)), usr) diff --git a/code/modules/transport/linear_controller.dm b/code/modules/transport/linear_controller.dm index 80c161c32918d3..1b3ffd30c148f9 100644 --- a/code/modules/transport/linear_controller.dm +++ b/code/modules/transport/linear_controller.dm @@ -1,3 +1,6 @@ +/// If anyone changes the hydraulic sound effect I sure hope they update this... +#define HYDRAULIC_SFX_DURATION (2 SECONDS) + ///coordinate and control movement across linked transport_controllers. allows moving large single multitile platforms and many 1 tile platforms. ///also is capable of linking platforms across linked z levels /datum/transport_controller/linear @@ -10,6 +13,7 @@ /obj/machinery/power/supermatter_crystal, /obj/structure/holosign, /obj/machinery/field, + /obj/structure/fluff/tram_rail, ) ///whether the lift handled by this transport_controller datum is multitile as opposed to nxm platforms per z level @@ -32,9 +36,6 @@ ///bitfield of various transport states var/controller_status = NONE - ///if true, the platform cannot be manually moved. - var/controls_locked = FALSE - /// probability of being thrown hard during an emergency stop var/throw_chance = 17.5 @@ -343,10 +344,8 @@ // Get the lowest or highest platform according to which direction we're moving var/obj/structure/transport/linear/prime_lift = return_closest_platform_to_z(direction == UP ? world.maxz : 0) - // If anyone changes the hydraulic sound effect I sure hope they update this variable... - var/hydraulic_sfx_duration = 2 SECONDS // ...because we use the duration of the sound effect to make it last for roughly the duration of the lift travel - playsound(prime_lift, 'sound/mecha/hydraulic.ogg', 25, vary = TRUE, frequency = clamp(hydraulic_sfx_duration / lift_move_duration, 0.33, 3)) + playsound(prime_lift, 'sound/mecha/hydraulic.ogg', 25, vary = TRUE, frequency = clamp(HYDRAULIC_SFX_DURATION / lift_move_duration, 0.33, 3)) // Move the platform after a timer addtimer(CALLBACK(src, PROC_REF(move_lift_vertically), direction, user), lift_move_duration, TIMER_UNIQUE) @@ -465,6 +464,7 @@ // Close all lift doors update_lift_doors(action = CYCLE_CLOSED) + sleep(1.1 SECONDS) // Approach the desired z-level one step at a time for(var/i in 1 to z_difference) if(!Check_lift_move(direction)) @@ -482,7 +482,7 @@ if(QDELETED(src) || QDELETED(prime_lift)) return - addtimer(CALLBACK(src, PROC_REF(open_lift_doors_callback)), 2 SECONDS) + update_lift_doors(get_zs_we_are_on(), action = CYCLE_OPEN) SEND_SIGNAL(src, COMSIG_LIFT_SET_DIRECTION, 0) controls_lock(FALSE) return TRUE @@ -636,3 +636,5 @@ lift_to_reset.reset_contents(consider_anything_past, foreign_objects, foreign_non_player_mobs, consider_player_mobs) return TRUE + +#undef HYDRAULIC_SFX_DURATION diff --git a/code/modules/transport/transport_module.dm b/code/modules/transport/transport_module.dm index 104601f2f6ca30..af8f4199438db3 100644 --- a/code/modules/transport/transport_module.dm +++ b/code/modules/transport/transport_module.dm @@ -378,19 +378,19 @@ for(var/obj/structure/victim_structure in dest_turf.contents) if(QDELING(victim_structure)) continue - if(!is_type_in_typecache(victim_structure, transport_controller_datum.ignored_smashthroughs) && victim_structure.layer >= LOW_OBJ_LAYER) - - if(victim_structure.anchored && initial(victim_structure.anchored) == TRUE) - visible_message(span_danger("[src] smashes through [victim_structure]!")) - victim_structure.deconstruct(FALSE) - - else - if(!throw_target) - throw_target = get_edge_target_turf(src, turn(travel_direction, pick(45, -45))) - visible_message(span_danger("[src] violently rams [victim_structure] out of the way!")) - victim_structure.anchored = FALSE - victim_structure.take_damage(rand(20, 25) * collision_lethality) - victim_structure.throw_at(throw_target, 200 * collision_lethality, 4 * collision_lethality) + if(!is_type_in_typecache(victim_structure, transport_controller_datum.ignored_smashthroughs)) + if((victim_structure.plane == FLOOR_PLANE && victim_structure.layer > TRAM_RAIL_LAYER) || (victim_structure.plane == GAME_PLANE && victim_structure.layer > LOW_OBJ_LAYER) ) + if(victim_structure.anchored && initial(victim_structure.anchored) == TRUE) + visible_message(span_danger("[src] smashes through [victim_structure]!")) + victim_structure.deconstruct(FALSE) + + else + if(!throw_target) + throw_target = get_edge_target_turf(src, turn(travel_direction, pick(45, -45))) + visible_message(span_danger("[src] violently rams [victim_structure] out of the way!")) + victim_structure.anchored = FALSE + victim_structure.take_damage(rand(20, 25) * collision_lethality) + victim_structure.throw_at(throw_target, 200 * collision_lethality, 4 * collision_lethality) for(var/obj/machinery/victim_machine in dest_turf.contents) if(QDELING(victim_machine)) diff --git a/code/modules/unit_tests/_unit_tests.dm b/code/modules/unit_tests/_unit_tests.dm index 911887cc8b9005..a42c25dc94ee1b 100644 --- a/code/modules/unit_tests/_unit_tests.dm +++ b/code/modules/unit_tests/_unit_tests.dm @@ -102,7 +102,6 @@ #include "bespoke_id.dm" #include "binary_insert.dm" #include "bitrunning.dm" -#include "blackmarket.dm" #include "blindness.dm" #include "bloody_footprints.dm" #include "breath.dm" @@ -183,6 +182,7 @@ #include "mapload_space_verification.dm" #include "mapping.dm" #include "mapping_nearstation_test.dm" +#include "market.dm" #include "mecha_damage.dm" #include "medical_wounds.dm" #include "merge_type.dm" diff --git a/code/modules/unit_tests/blackmarket.dm b/code/modules/unit_tests/blackmarket.dm deleted file mode 100644 index 984e2ea815503b..00000000000000 --- a/code/modules/unit_tests/blackmarket.dm +++ /dev/null @@ -1,23 +0,0 @@ -/// Ensures black market items have acceptable variable values. -/datum/unit_test/blackmarket - -/datum/unit_test/blackmarket/Run() - for(var/datum/market_item/prototype as anything in subtypesof(/datum/market_item)) - if(prototype::abstract_path == prototype) //skip abstract paths - continue - if(!prototype::category) - TEST_FAIL("[prototype] doesn't have a set category (or the abstract path var isn't correctly set)") - continue - if(!prototype::item) - TEST_FAIL("[prototype] doesn't have a set item (or the abstract path var isn't correctly set)") - continue - if(isnull(prototype::price) && prototype::price_max <= prototype::price_min) - TEST_FAIL("[prototype] doesn't have a correctly set random price (price_max should be higher than price_min)") - if(isnull(prototype::stock) && prototype::stock_max < prototype::stock_min) - TEST_FAIL("[prototype] doesn't have a correctly set random stock (stock_max shouldn't be lower than stock_min)") - if(!isnum(prototype::availability_prob)) - TEST_FAIL("[prototype] doesn't have a set availability_prob (must be a number)") - if(!prototype::name) - TEST_FAIL("[prototype] doesn't have a set name") - if(!prototype::desc) - TEST_FAIL("[prototype] doesn't have a set desc") diff --git a/code/modules/unit_tests/fish_unit_tests.dm b/code/modules/unit_tests/fish_unit_tests.dm index 1db534c5e076cb..5cb582ca9694a9 100644 --- a/code/modules/unit_tests/fish_unit_tests.dm +++ b/code/modules/unit_tests/fish_unit_tests.dm @@ -226,10 +226,11 @@ /datum/unit_test/raise_a_chasm_crab/Run() var/obj/structure/aquarium/crab/aquarium = allocate(/obj/structure/aquarium/crab) - var/mob/living/basic/mining/lobstrosity/juvenile/lobster = aquarium.crabbie.grow_up(1) //one stands for a second - TEST_ASSERT(lobster, "The test aquarium's chasm crab didn't grow up into a lobstrosity.[aquarium.crabbie ? " The aquarium crab is still here and at about [aquarium.crabbie.maturation]% maturation" : ""]") - allocated |= lobster //make sure it's allocated and thus properly deleted when the test is over + SEND_SIGNAL(aquarium.crabbie, COMSIG_FISH_LIFE, 1) //give the fish growth component a small push. + var/mob/living/basic/mining/lobstrosity/juvenile/lobster = locate() in aquarium.loc TEST_ASSERT_EQUAL(lobster.loc, get_turf(aquarium), "The lobstrosity didn't spawn on the aquarium's turf") + TEST_ASSERT(QDELETED(aquarium.crabbie), "The test aquarium's chasm crab didn't delete itself.") + allocated |= lobster //make sure it's allocated and thus properly deleted when the test is over //While ideally impossible to have all traits because of incompatible ones, I want to be sure they don't error out. for(var/trait_type in GLOB.fish_traits) var/datum/fish_trait/trait = GLOB.fish_traits[trait_type] diff --git a/code/modules/unit_tests/market.dm b/code/modules/unit_tests/market.dm new file mode 100644 index 00000000000000..022f277d879c0f --- /dev/null +++ b/code/modules/unit_tests/market.dm @@ -0,0 +1,59 @@ +#define CATEGORY_CODERBUS "Coderbus" +/// Ensures market items have acceptable variable values and restocking works. +/datum/unit_test/market + +/datum/unit_test/market/Run() + for(var/datum/market_item/prototype as anything in subtypesof(/datum/market_item)) + if(prototype::abstract_path == prototype) //skip abstract paths + continue + if(!prototype::category) + TEST_FAIL("[prototype] doesn't have a set category (or the abstract path var isn't correctly set)") + continue + if(!prototype::item) + TEST_FAIL("[prototype] doesn't have a set item (or the abstract path var isn't correctly set)") + continue + if(isnull(prototype::price) && prototype::price_max <= prototype::price_min) + TEST_FAIL("[prototype] doesn't have a correctly set random price (price_max should be higher than price_min)") + if(isnull(prototype::stock) && prototype::stock_max < prototype::stock_min) + TEST_FAIL("[prototype] doesn't have a correctly set random stock (stock_max shouldn't be lower than stock_min)") + if(!isnum(prototype::availability_prob)) + TEST_FAIL("[prototype] doesn't have a set availability_prob (must be a number)") + if(!prototype::name) + TEST_FAIL("[prototype] doesn't have a set name") + if(!prototype::desc) + TEST_FAIL("[prototype] doesn't have a set desc") + + + var/datum/market/unit_test/market = SSmarket.markets[/datum/market/unit_test] + TEST_ASSERT(market, "Couldn't find the unit test market") + var/list/category_items = market.available_items[CATEGORY_CODERBUS] + var/datum/market_item/unit_test/item = category_items[category_items[1]] + TEST_ASSERT(item, "Couldn't find the unit test market item") + TEST_ASSERT_EQUAL(item.stock, 1, "The unit test market item is incorrectly stocked. Only one should be in stock") + + var/mob/living/user = allocate(/mob/living) + var/obj/item/holochip/chip = allocate(/obj/item/holochip, run_loc_floor_bottom_left, INFINITY) + var/obj/machinery/ltsrbt/pad = allocate(/obj/machinery/ltsrbt) + + pad.item_interaction(user, chip) + + TEST_ASSERT_EQUAL(item, category_items[category_items[1]], "The unit test market item has been replaced during restock") + TEST_ASSERT_EQUAL(item.stock, 2, "The unit test market item is incorrectly stocked after restock. There should be two in stock") + +/datum/market/unit_test + name = "Unit Test Market" + shipping = list(SHIPPING_METHOD_TELEPORT = 0) + +/datum/market_item/unit_test + name = "Your Own Special Singularity" + desc = "ALL HAIL LORD SINGULOTH!!!" + category = CATEGORY_CODERBUS + markets = list(/datum/market/unit_test) + item = /obj/singularity + price = 42069 + stock_min = 1 + stock = 1 + stock_max = 2 + availability_prob = 100 + +#undef CATEGORY_CODERBUS diff --git a/code/modules/uplink/uplink_devices.dm b/code/modules/uplink/uplink_devices.dm index 596ea9e1ffad41..3c31ddf647f88f 100644 --- a/code/modules/uplink/uplink_devices.dm +++ b/code/modules/uplink/uplink_devices.dm @@ -48,7 +48,7 @@ hidden_uplink.uplink_handler.debug_mode = TRUE /obj/item/uplink/nuclear - uplink_flag = UPLINK_ALL_SYNDIE_OPS + uplink_flag = UPLINK_NUKE_OPS /obj/item/uplink/nuclear/debug name = "debug nuclear uplink" diff --git a/code/modules/uplink/uplink_items.dm b/code/modules/uplink/uplink_items.dm index bf963587ae1ccd..7e501217eb68c6 100644 --- a/code/modules/uplink/uplink_items.dm +++ b/code/modules/uplink/uplink_items.dm @@ -2,9 +2,17 @@ /// Selects a set number of unique items from the uplink, and deducts a percentage discount from them /proc/create_uplink_sales(num, datum/uplink_category/category, limited_stock, list/sale_items) var/list/sales = list() - var/list/sale_items_copy = sale_items.Copy() + var/list/per_category = list() + + for (var/datum/uplink_item/possible_sale as anything in sale_items) + if (!(possible_sale.category in per_category)) + per_category[possible_sale.category] = list() + per_category[possible_sale.category] += possible_sale + for (var/i in 1 to num) - var/datum/uplink_item/taken_item = pick_n_take(sale_items_copy) + var/datum/uplink_category/item_category = pick(per_category) + var/datum/uplink_item/taken_item = pick(per_category[item_category]) + per_category -= item_category var/datum/uplink_item/uplink_item = new taken_item.type() var/discount = uplink_item.get_discount() var/static/list/disclaimer = list( diff --git a/code/modules/uplink/uplink_items/bundle.dm b/code/modules/uplink/uplink_items/bundle.dm index dae6166d49cebd..b6cdc2fd3d6578 100644 --- a/code/modules/uplink/uplink_items/bundle.dm +++ b/code/modules/uplink/uplink_items/bundle.dm @@ -40,18 +40,7 @@ // Don't add telecrystals to the purchase_log since // it's just used to buy more items (including itself!) purchase_log_vis = FALSE - -/datum/uplink_item/bundles_tc/telecrystal/five - name = "5 Raw Telecrystals" - desc = "Five telecrystals in their rawest and purest form; can be utilized on active uplinks to increase their telecrystal count." - item = /obj/item/stack/telecrystal/five - cost = 5 - -/datum/uplink_item/bundles_tc/telecrystal/twenty - name = "20 Raw Telecrystals" - desc = "Twenty telecrystals in their rawest and purest form; can be utilized on active uplinks to increase their telecrystal count." - item = /obj/item/stack/telecrystal/twenty - cost = 20 + purchasable_from = NONE /datum/uplink_item/bundles_tc/bundle_a name = "Syndi-kit Tactical" diff --git a/code/modules/uplink/uplink_items/nukeops.dm b/code/modules/uplink/uplink_items/nukeops.dm index 2a93976992216c..80df9de47cfbca 100644 --- a/code/modules/uplink/uplink_items/nukeops.dm +++ b/code/modules/uplink/uplink_items/nukeops.dm @@ -373,16 +373,18 @@ //Meme weapons: Literally just weapons used as a joke, shouldn't be particularly expensive. /datum/uplink_item/weapon_kits/surplus_smg - name = "Surplus SMG Case (Flukie)" - desc = "A horribly outdated automatic weapon. Why would you want to use this? Comes with...rations." - item = /obj/item/gun/ballistic/automatic/plastikov + name = "Surplus Smart-SMG (Flukie)" + desc = "An outdated smart-SMG with limited stopping power, however it's bullets will gradually track towards whatever \ + the gun was shot at. This does require you to actually aim at the person you are shooting at before firing, but \ + surely a highly trained operative such as yourself can manage that." + item = /obj/item/gun/ballistic/automatic/smartgun cost = 2 purchasable_from = UPLINK_SERIOUS_OPS /datum/uplink_item/ammo_nuclear/surplus_smg - name = "Surplus SMG Magazine (Surplus)" - desc = "A cylindrical magazine designed for the PP-95 SMG." - item = /obj/item/ammo_box/magazine/plastikov9mm + name = "Surplus Smart-SMG Magazine (Smartgun)" + desc = "A large box magazine made for use in the Abielle smart-SMG." + item = /obj/item/ammo_box/magazine/smartgun cost = 1 purchasable_from = UPLINK_SERIOUS_OPS uplink_item_flags = SYNDIE_TRIPS_CONTRABAND diff --git a/code/modules/uplink/uplink_items/suits.dm b/code/modules/uplink/uplink_items/suits.dm index d940d4eb06769c..b66cce4eaece7e 100644 --- a/code/modules/uplink/uplink_items/suits.dm +++ b/code/modules/uplink/uplink_items/suits.dm @@ -79,3 +79,4 @@ purchasable_from = ~UPLINK_ALL_SYNDIE_OPS progression_minimum = 90 MINUTES cost = 16 + cant_discount = TRUE diff --git a/code/modules/vehicles/cars/vim.dm b/code/modules/vehicles/cars/vim.dm index 221c9268febbb8..dfcd604ef144de 100644 --- a/code/modules/vehicles/cars/vim.dm +++ b/code/modules/vehicles/cars/vim.dm @@ -18,6 +18,7 @@ light_power = 1.5 light_on = FALSE engine_sound = 'sound/effects/servostep.ogg' + interaction_flags_mouse_drop = NONE ///Maximum size of a mob trying to enter the mech var/maximum_mob_size = MOB_SIZE_SMALL COOLDOWN_DECLARE(sound_cooldown) diff --git a/code/modules/vehicles/mecha/combat/justice.dm b/code/modules/vehicles/mecha/combat/justice.dm index e99632394a1b78..00b0543dbd8658 100644 --- a/code/modules/vehicles/mecha/combat/justice.dm +++ b/code/modules/vehicles/mecha/combat/justice.dm @@ -170,10 +170,10 @@ . = ..() RegisterSignal(chassis, COMSIG_MECH_SAFETIES_TOGGLE, PROC_REF(on_toggle_safety)) -/// update button icon when toggle safety. +/// update button icon when toggle safety and turns invisibility off. /datum/action/vehicle/sealed/mecha/invisibility/proc/on_toggle_safety() SIGNAL_HANDLER - + invisibility_off() build_all_button_icons(UPDATE_BUTTON_STATUS) /datum/action/vehicle/sealed/mecha/invisibility/Trigger(trigger_flags) diff --git a/code/modules/vehicles/mecha/equipment/mecha_equipment.dm b/code/modules/vehicles/mecha/equipment/mecha_equipment.dm index b32e26be94a4ea..00d0a955d7b871 100644 --- a/code/modules/vehicles/mecha/equipment/mecha_equipment.dm +++ b/code/modules/vehicles/mecha/equipment/mecha_equipment.dm @@ -149,12 +149,12 @@ if(equipment_slot == MECHA_WEAPON) if(attach_right) // We need to check for length in case a mech doesn't support any arm attachments at all - if((mech.equip_by_category[MECHA_R_ARM] == mech.max_equip_by_category[MECHA_R_ARM]) && (!special_attaching_interaction(attach_right, mech, user, checkonly = TRUE))) - to_chat(user, span_warning("\The [mech]'s right arm is full![mech.equip_by_category[MECHA_L_ARM] ? "" : " Try left arm!"]")) + if((!isnull(mech.equip_by_category[MECHA_R_ARM]) || !mech.max_equip_by_category[MECHA_R_ARM]) && (!special_attaching_interaction(attach_right, mech, user, checkonly = TRUE))) + to_chat(user, span_warning("\The [mech]'s right arm is full![mech.equip_by_category[MECHA_L_ARM] || !mech.max_equip_by_category[MECHA_L_ARM] ? "" : " Try left arm!"]")) return FALSE else - if((mech.equip_by_category[MECHA_L_ARM] == mech.max_equip_by_category[MECHA_L_ARM]) && (!special_attaching_interaction(attach_right, mech, user, checkonly = TRUE))) - to_chat(user, span_warning("\The [mech]'s left arm is full![mech.equip_by_category[MECHA_R_ARM] ? "" : " Try right arm!"]")) + if((!isnull(mech.equip_by_category[MECHA_L_ARM]) || !mech.max_equip_by_category[MECHA_L_ARM]) && (!special_attaching_interaction(attach_right, mech, user, checkonly = TRUE))) + to_chat(user, span_warning("\The [mech]'s left arm is full![mech.equip_by_category[MECHA_R_ARM] || !mech.max_equip_by_category[MECHA_R_ARM] ? "" : " Try right arm!"]")) return FALSE return TRUE if(length(mech.equip_by_category[equipment_slot]) == mech.max_equip_by_category[equipment_slot]) diff --git a/code/modules/vehicles/mecha/equipment/tools/work_tools.dm b/code/modules/vehicles/mecha/equipment/tools/work_tools.dm index 35645bf56ba922..34216db38d3cd1 100644 --- a/code/modules/vehicles/mecha/equipment/tools/work_tools.dm +++ b/code/modules/vehicles/mecha/equipment/tools/work_tools.dm @@ -98,7 +98,7 @@ span_notice("[chassis] pushes you aside.")) return ..() - if(iscarbon(victim))//meme clamp here + if(iscarbon(victim) && killer_clamp)//meme clamp here var/mob/living/carbon/carbon_victim = target var/torn_off = FALSE var/obj/item/bodypart/affected = carbon_victim.get_bodypart(BODY_ZONE_L_ARM) @@ -120,7 +120,6 @@ if(isnull(victim)) //get gibbed stoopid return ..() victim.adjustOxyLoss(round(clamp_damage/2)) - victim.updatehealth() victim.visible_message(span_danger("[chassis] squeezes [victim]!"), \ span_userdanger("[chassis] squeezes you!"),\ span_hear("You hear something crack.")) diff --git a/code/modules/vehicles/mecha/mech_fabricator.dm b/code/modules/vehicles/mecha/mech_fabricator.dm index c2d37ee6e83483..b4c292202542e8 100644 --- a/code/modules/vehicles/mecha/mech_fabricator.dm +++ b/code/modules/vehicles/mecha/mech_fabricator.dm @@ -149,8 +149,9 @@ /obj/machinery/mecha_part_fabricator/emag_act(mob/user, obj/item/card/emag/emag_card) if(obj_flags & EMAGGED) return FALSE - if(user.job != JOB_ROBOTICIST) - to_chat(user, span_warning("You clicking and typing but don’t understand what to do with it")) + if(!HAS_TRAIT(user, TRAIT_KNOW_ROBO_WIRES)) + to_chat(user, span_warning("You're unsure about [emag_card ? "where to swipe [emag_card] over" : "how to override"] [src] for any effect. Maybe if you had more knowledge of robotics...")) + return FALSE obj_flags |= EMAGGED for(var/found_illegal_mech_nods in SSresearch.techweb_nodes) @@ -179,6 +180,9 @@ if(design.build_type & MECHFAB) cached_designs |= design + for(var/datum/design/illegal_disign in illegal_local_designs) + cached_designs |= illegal_disign + var/design_delta = cached_designs.len - previous_design_count if(design_delta > 0) diff --git a/code/modules/vehicles/mecha/mech_melee_attack.dm b/code/modules/vehicles/mecha/mech_melee_attack.dm index 6fe64c879fa716..f37d092b83f32b 100644 --- a/code/modules/vehicles/mecha/mech_melee_attack.dm +++ b/code/modules/vehicles/mecha/mech_melee_attack.dm @@ -72,6 +72,22 @@ return return ..() +/obj/vehicle/mech_melee_attack(obj/vehicle/sealed/mecha/mecha_attacker, mob/living/user) + if(!user.combat_mode) + return FALSE + + mecha_attacker.do_attack_animation(src) + switch(mecha_attacker.damtype) + if(BRUTE) + playsound(src, 'sound/weapons/punch4.ogg', 50, TRUE) + if(BURN) + playsound(src, 'sound/items/welder.ogg', 50, TRUE) + else + return + mecha_attacker.visible_message(span_danger("[mecha_attacker] hits [src]!"), span_danger("You hit [src]!"), null, COMBAT_MESSAGE_RANGE) + ..() + return take_damage(mecha_attacker.force, mecha_attacker.damtype, "melee", FALSE, get_dir(src, mecha_attacker)) + /mob/living/mech_melee_attack(obj/vehicle/sealed/mecha/mecha_attacker, mob/living/user) if(istype(user) && !user.combat_mode) step_away(src, mecha_attacker) diff --git a/code/modules/vehicles/mecha/mecha_ai_interaction.dm b/code/modules/vehicles/mecha/mecha_ai_interaction.dm index 3a681cac97db59..cec3d867e2b6ac 100644 --- a/code/modules/vehicles/mecha/mecha_ai_interaction.dm +++ b/code/modules/vehicles/mecha/mecha_ai_interaction.dm @@ -12,7 +12,7 @@ to_chat(user, "[span_userdanger("ASSUME DIRECT CONTROL?")]
") return examine(user) - if(length(return_drivers()) > 0) + if(length(return_occupants()) >= max_occupants) to_chat(user, span_warning("This exosuit has a pilot and cannot be controlled.")) return var/can_control_mech = FALSE @@ -103,6 +103,7 @@ AI.controlled_equipment = src AI.remote_control = src AI.ShutOffDoomsdayDevice() + add_occupant(AI) to_chat(AI, AI.can_dominate_mechs ? span_greenannounce("Takeover of [name] complete! You are now loaded onto the onboard computer. Do not attempt to leave the station sector!") :\ span_notice("You have been uploaded to a mech's onboard computer.")) to_chat(AI, "Use Middle-Mouse or the action button in your HUD to toggle equipment safety. Clicks with safety enabled will pass AI commands.") diff --git a/code/modules/vehicles/motorized_wheelchair.dm b/code/modules/vehicles/motorized_wheelchair.dm index cecf6b815e2492..6a38f65e3bf09f 100644 --- a/code/modules/vehicles/motorized_wheelchair.dm +++ b/code/modules/vehicles/motorized_wheelchair.dm @@ -100,7 +100,6 @@ /obj/vehicle/ridden/wheelchair/motorized/attack_hand(mob/living/user, list/modifiers) if(!power_cell || !panel_open) return ..() - power_cell.update_appearance() to_chat(user, span_notice("You remove [power_cell] from [src].")) user.put_in_hands(power_cell) power_cell = null diff --git a/code/modules/vehicles/pimpin_ride.dm b/code/modules/vehicles/pimpin_ride.dm index 7ef79cb89cf04c..441a1263a3ea00 100644 --- a/code/modules/vehicles/pimpin_ride.dm +++ b/code/modules/vehicles/pimpin_ride.dm @@ -64,7 +64,7 @@ installed_upgrade = null update_appearance() else if(trash_bag && (!is_key(I) || is_key(inserted_key))) // don't put a key in the trash when we need it - trash_bag.attackby(I, user) + trash_bag.atom_storage.attempt_insert(I, user) else return ..() diff --git a/code/modules/vending/autodrobe.dm b/code/modules/vending/autodrobe.dm index 97a2ee4a0576b5..8b9f7045695450 100644 --- a/code/modules/vending/autodrobe.dm +++ b/code/modules/vending/autodrobe.dm @@ -136,7 +136,7 @@ GLOBAL_LIST_INIT(autodrobe_animal_items, list( /obj/item/clothing/mask/animal/horsehead = 3, )) -GLOBAL_LIST_INIT(autodrobe_other_items, list( +GLOBAL_LIST_INIT(autodrobe_service_items, list( /obj/item/clothing/under/costume/buttondown/slacks/service = 3, /obj/item/clothing/under/costume/buttondown/skirt/service = 3, /obj/item/clothing/neck/bowtie = 6, @@ -150,27 +150,23 @@ GLOBAL_LIST_INIT(autodrobe_other_items, list( /obj/item/clothing/neck/maid = 3, /obj/item/clothing/under/rank/civilian/janitor/maid = 3, /obj/item/clothing/accessory/maidapron = 3, +)) + +GLOBAL_LIST_INIT(autodrobe_other_items, list( + /obj/item/clothing/head/wig/random = 6, + /obj/item/clothing/head/flatcap = 3, + /obj/item/clothing/suit/jacket/miljacket = 3, + /obj/item/clothing/shoes/jackboots = 3, + /obj/item/clothing/mask/fakemoustache = 3, + /obj/item/clothing/glasses/cold= 3, + /obj/item/clothing/glasses/heat= 3, + /obj/item/clothing/mask/gas/cyborg = 3, + /obj/item/clothing/mask/joy = 3, /obj/item/clothing/mask/gas/prop = 4, /obj/item/clothing/mask/gas/atmosprop = 3, /obj/item/clothing/mask/animal/small/tribal = 1, )) -GLOBAL_LIST_INIT(autodrobe_service_items, list( - /obj/item/clothing/under/costume/buttondown/slacks/service = 3, - /obj/item/clothing/under/costume/buttondown/skirt/service = 3, - /obj/item/clothing/neck/bowtie = 6, - /obj/item/clothing/accessory/waistcoat = 4, - /obj/item/clothing/under/suit/waiter = 4, - /obj/item/clothing/suit/apron = 3, - /obj/item/clothing/suit/apron/overalls = 3, - /obj/item/clothing/head/costume/maidheadband = 3, - /obj/item/clothing/under/costume/maid = 3, - /obj/item/clothing/gloves/maid = 3, - /obj/item/clothing/neck/maid = 3, - /obj/item/clothing/under/rank/civilian/janitor/maid = 3, - /obj/item/clothing/accessory/maidapron = 3, -)) - GLOBAL_LIST_INIT(autodrobe_premium_items, list( /obj/item/clothing/suit/costume/pirate/captain = 2, /obj/item/clothing/head/costume/pirate/captain = 2, @@ -230,9 +226,11 @@ GLOBAL_VAR_INIT(all_autodrobe_items, (autodrobe_costumes_items +\ req_access = list(ACCESS_THEATRE) product_slogans = "Dress for success!;Suited and booted!;It's show time!;Why leave style up to fate? Use AutoDrobe!" vend_reply = "Thank you for using AutoDrobe!" + /** * Categories are filled in Initialize! */ + refill_canister = /obj/item/vending_refill/autodrobe default_price = PAYCHECK_CREW * 0.8 //Default of 40. extra_price = PAYCHECK_COMMAND diff --git a/code/modules/vending/subtype.dm b/code/modules/vending/subtype.dm index 9b4f212224ea74..3a1a04ff6e764b 100644 --- a/code/modules/vending/subtype.dm +++ b/code/modules/vending/subtype.dm @@ -10,6 +10,7 @@ circuit = null product_slogans = "Spawn \" too annoying? Too lazy to open game panel? This one's for you!;Subtype vendor, for all your debugging woes!" default_price = 0 + onstation = FALSE /// Spawns coders by default var/type_to_vend = /obj/item/food/grown/citrus diff --git a/config/game_options.txt b/config/game_options.txt index ab75284e43ccb2..0f3ba8e9e801ba 100644 --- a/config/game_options.txt +++ b/config/game_options.txt @@ -184,6 +184,10 @@ ROUNDSTART_AWAY ## 600 is one minute. GATEWAY_DELAY 18000 +## Overrides to gateway delay for specific away mission start points. +GATEWAY_DELAYS_BY_ID AWAYSTART_BEACH 6000 +GATEWAY_DELAYS_BY_ID AWAYSTART_MUSEUM 9000 + ## The probability of the gateway mission being a config one CONFIG_GATEWAY_CHANCE 0 diff --git a/dependencies.sh b/dependencies.sh index 772ff347f5e1f0..60753e1411c8d5 100644 --- a/dependencies.sh +++ b/dependencies.sh @@ -22,11 +22,11 @@ export SPACEMAN_DMM_VERSION=suite-1.8 # Python version for mapmerge and other tools export PYTHON_VERSION=3.9.0 -#auxlua repo -export AUXLUA_REPO=tgstation/auxlua +#dreamluau repo +export DREAMLUAU_REPO="tgstation/dreamluau" -#auxlua git tag -export AUXLUA_VERSION=1.4.4 +#dreamluau git tag +export DREAMLUAU_VERSION=0.1.0 #hypnagogic repo export CUTTER_REPO=spacestation13/hypnagogic diff --git a/dreamluau.dll b/dreamluau.dll new file mode 100644 index 00000000000000..7d49f0742d8f80 Binary files /dev/null and b/dreamluau.dll differ diff --git a/html/changelogs/AutoChangeLog-pr-85195.yml b/html/changelogs/AutoChangeLog-pr-85195.yml deleted file mode 100644 index c1715fb80fbcdb..00000000000000 --- a/html/changelogs/AutoChangeLog-pr-85195.yml +++ /dev/null @@ -1,4 +0,0 @@ -author: "Vekter" -delete-after: True -changes: - - spellcheck: "Reworded Voidwalker's objectives to be more descriptive of their actual goals as opposed to just fluff." \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-85290.yml b/html/changelogs/AutoChangeLog-pr-85290.yml new file mode 100644 index 00000000000000..f64fde94ba83b6 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-85290.yml @@ -0,0 +1,4 @@ +author: "Ben10Omintrix" +delete-after: True +changes: + - refactor: "refactors pet collars and cultist pets into elements" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-85473.yml b/html/changelogs/AutoChangeLog-pr-85473.yml new file mode 100644 index 00000000000000..d3f12bf94347da --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-85473.yml @@ -0,0 +1,4 @@ +author: "SmArtKar" +delete-after: True +changes: + - bugfix: "Bitrunning crate capture zones can no longer be destroyed" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-85490.yml b/html/changelogs/AutoChangeLog-pr-85490.yml new file mode 100644 index 00000000000000..c86f16c571394b --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-85490.yml @@ -0,0 +1,4 @@ +author: "Gaxeer" +delete-after: True +changes: + - rscdel: "Remove narsie and ratvar plushies from loadout" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-85537.yml b/html/changelogs/AutoChangeLog-pr-85537.yml new file mode 100644 index 00000000000000..1f219cb2d5de62 --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-85537.yml @@ -0,0 +1,4 @@ +author: "SmArtKar" +delete-after: True +changes: + - code_imp: "Removed multiple cases of unnecessary updatehealth" \ No newline at end of file diff --git a/html/changelogs/AutoChangeLog-pr-85541.yml b/html/changelogs/AutoChangeLog-pr-85541.yml new file mode 100644 index 00000000000000..18374b79f2b44c --- /dev/null +++ b/html/changelogs/AutoChangeLog-pr-85541.yml @@ -0,0 +1,4 @@ +author: "SmArtKar" +delete-after: True +changes: + - bugfix: "Elevator music no longer restarts when you take a step" \ No newline at end of file diff --git a/html/changelogs/archive/2024-07.yml b/html/changelogs/archive/2024-07.yml index fdb3f22db38185..632d897df753ad 100644 --- a/html/changelogs/archive/2024-07.yml +++ b/html/changelogs/archive/2024-07.yml @@ -1275,3 +1275,233 @@ nikothedude: - bugfix: Alexander no longer causes harddels - bugfix: Removed a theoretical infinite block exploit from alexander +2024-07-25: + Ghommie: + - bugfix: Fixed fishing. + MTandi: + - bugfix: Borgs and AI can now use research queue + Vekter: + - spellcheck: Reworded Voidwalker's objectives to be more descriptive of their actual + goals as opposed to just fluff. + necromanceranne: + - balance: Strong-arm implants go on cooldown when activated, but deal more overall + lethal damage on a single blow. + - balance: The strong-arm implant does additional damage to fauna and some other + dangerous mobs. + - qol: You can pair toolset arm implants with the strong-arm implants. + - balance: Quality cybernetic hearts combat bleeds and restore blood, rather than + inject you with epinephrine when you enter crit. This can result in mild toxin + buildup, however. + - balance: Upgraded cybernetic hearts give an extremely brief amount of action when + you enter softcrit (but not hardcrit). + - bugfix: Restores some of the items accidentally lost in the autodrobe. +2024-07-26: + LT3: + - bugfix: Fixed elevator panel allowing conflicting inputs + - bugfix: Fixed elevator sound being out of sync with movement + SmArtKar: + - bugfix: Xenomorphs and door pryer basic mobs can now attack airlocks in combat + mode + - bugfix: Borgs now unequip their equipment upon module change like they should + YesterdaysPromise: + - rscadd: All the melons are now sliceable, and have inhands, instead of just watermelon + and holymelon respectively. + - rscadd: You can now hollow out melons of all kinds with a spoon to make helmets + or chestplates, based on the potency! If you are unlucky, you can tie up three + helmets into a chestplate with durathread using the crafting menu. + - rscadd: You can now make a bo staff out of bamboo and steelcap logs. + - rscadd: You can now make a moonflower buckler out of moonflowers and steelcap + logs. + - rscadd: You can also hollow out chantarelle to make mock-up wizard hat. + - rscadd: Parsnips, as mutation of carrots, become equaly able to be sharpaned, + turning into shivs, or with potency and luck, sabres. + - rscadd: You can now craft a durathread robe, and customize it into different variants + using specific plants in crafting menu. + - rscadd: Carrots gain a new possible mutation; cahn'root, brewable into root beer + and sharpanable into shivs or daggers! + - rscadd: Rice hat, made from bamboo, now has an alternative style, allowing you + to wear it in reverse and be much cooler. + - rscadd: Two new arrow variants appear in the crafting menu; sticky and poisonous + ones! If you want to make arrows at all though, remember to order bow-maker's + crate at cargo. +2024-07-27: + 00-Steven: + - bugfix: Fixes borgs not being able to place apparatus-held items on tables. As + a side-effect, they can now combat mode right click splash containers as normal + instead of having their own right-click floor splash. + Ghommie: + - bugfix: Centcom technicians have been trained to recognize cargo-bought fish. + You will no longer be able to trick the economy system by buying fish and sending + it right back. Also nerfed fish selling price very slightly. + - bugfix: Fixes projectiles facing north if ricocheting, deflected or homing + - rscdel: Removed a janky fish bounty + - rscadd: introduced exporting fish through cargo. + - balance: reduced the average weight of the jumpercable. Conversely, eased up the + requirements for the bone fish evolution. + Ical92: + - bugfix: Tram's Tool Storage now has proper lighting + Jacquerel: + - balance: If a bluespace cookie fails to teleport you then you will trip over. + LT3: + - bugfix: Fixed delam counter stuck in window near Ice Box bridge + - bugfix: Fixed disease outbreak announcement sometimes missing the disease name + - bugfix: False supermatter surge announcements are now identical to real ones + - bugfix: Tram will no longer eat its own rails as it travels + MTandi: + - bugfix: Janicart inserts items into the attached trash bag again (manual and vacuumed) + Melbert: + - qol: All randomly spawned monkeys (and lizardpeople) will spawn with tails. You + can still select to be tailless. + - code_imp: Cleaned up some code relating to species features (like tails, markings, + etc). Report any oddities + SmArtKar: + - image: Updated gas flow meter sprites + Thlumyn: + - bugfix: self-resp viruses don't spam messages as often + afonamos2: + - bugfix: Firelocks will once again respect fire alarm's thermal sensors being disabled. + carlarctg: + - bugfix: Fixed possessed blades being broken + - code_imp: If testing is enabled everyone is polled in ghost polls. + mc-oofert: + - bugfix: wawastation ordnance no longer has a light fixture on a window and looks + objectively slightly better + - bugfix: wawastation engineering water tanks are now highcap +2024-07-28: + 00-Steven: + - bugfix: Clicking on a table in the lootpanel with an item in-hand tries to place + it in the center again. + Axidyuwu: + - bugfix: now Justice invisibility turns off in non combat mode as it supposed to + Deadgebert: + - bugfix: peg limbs can now be amputated + DrDiasyl aka DrTuxedo: + - sound: Hearing and talking into the radio now produces a sound. Heads get a special + sound. + Helg2: + - rscadd: Emergency climbing hooks now spawn in emergency boxes on all of the multi-z + level stations. + JohnFulpWillard: + - bugfix: '[Mafia] The show_help button no longer shows you who the Obsessed''s + target is.' + LT3: + - bugfix: Players now receive a notification when trying to perform surgery steps + that involve chemicals + Rhials: + - bugfix: Monkey wizards can now interact with grand ritual runes. + - bugfix: Clown Ops gear has been returned to being available only to clown ops. + Whoops! + SmArtKar: + - bugfix: People with tooltips enabled no longer lag the server when they move their + mouse. Oops. + - bugfix: Mirage grenade dispensers and ionic jump jets now work + StrangeWeirdKitten: + - bugfix: Voidwalker should not run on planetary maps. + grungussuss: + - bugfix: Med sec telescreens are no longer the same item as the CMO telescreen. + - spellcheck: correcte name for the CMO telescreen mount + - bugfix: birdshot holodeck's lighting has been fixed. + - sound: medkits now have sounds + - sound: gas tanks now have sound + - sound: the default metal sound has been changed + - bugfix: lavaland no longer has roundstart atmos processing because of a passive + vent + - sound: only the scream emote can be heard through walls + - sound: the sneeze projectile no longer makes a sound when making contact. +2024-07-29: + DaCoolBoss: + - spellcheck: military javelin's name is now fully uncapitalised + SmArtKar: + - rscadd: Mining headsets now allow you to make callouts via pointing. You can use + them to communicate with fellow miners or order your army of bots and raptors! + - rscadd: Mining headsets keep your voice loud and clear in low-pressure environments + (not vacuum!) + - qol: If you have auto fit viewport enabled, it will trigger upon entering or exiting + fullscreen + - bugfix: VIM no longer requires hands to enter + - bugfix: Recyclers no longer recycle contents of indestructible items + - bugfix: Grass sheath now holds parsnip sabres like its supposed to + - spellcheck: Fixed up parsnip sabre description grammar + StrangeWeirdKitten: + - rscadd: Cosmic Skull glows purple. + Time-Green: + - bugfix: Fixes void eater not refreshing + - bugfix: Fixes planetary gravity not killing voidwalkers and voideds + Y0SH1M4S73R: + - admin: Admin lua scripting uses a new library that (probably) will not break when + BYOND updates. +2024-07-30: + 13spacemen: + - balance: TTV bombs can be implanted into people's chest once again + AyIong: + - rscadd: Stat Panel now scales like a chat, depends on the font size. Defaults + from the chat font size, but you can separate it. + - refactor: Refactored Stat Panel styles and Byond skin theme applying. Stat Panel + now looks more like a TGUI + Bisar: + - bugfix: All mining mobs now properly listen to the signals sent by attackers and + will respond appropriately. + Gaxeer: + - refactor: replace some copypaste code for pod spawn to use `podspawn` proc instead + - code_imp: modify `podspawn` proc to accept amount of item type to spawn in `spawn` + specification + Ghommie: + - qol: Aquariums start unanchored and don't autoconnect to plumbing. Their reproduction + prevention is also disabled by default. + - balance: Made it a tad easier to control the bait during the minigame. Buffed + the fishing skill. No fishing duds at all when using ANY bait. + - balance: Chasm Chrabs take less time to grow into Lobstrosities but need food + a bit more frequently. + - balance: '"Profound fisher" mobs will have less RNG-dependant time fishing.' + - bugfix: You can now ACTUALLY interact with other things while fishing if the fishing + rod isn't in your active hand. + - config: Added a config for specific gateway delays so locations like the beach + and the museum don't have to take 30 minutes to become available like the rest. + Jackriip: + - refactor: moves the create_all_lighting_objects proc to the lighting subsystem + KazooBard: + - rscadd: The heretic's ritual of knowledge no longer requires binoculars + - rscadd: Clipboards are craftable using a wood plank, an iron rod and wirecutters + Paxilmaniac: + - balance: The nukeops surplus smg, the pp-95, has been reworked into the Abielle + Smart-SMG. It performs nearly identically to the pp-95, however it's projectiles + get a slight homing ability towards whatever you click on. + - sound: New firing sounds for the surplus smg, credit to the m41 sound effects + from tgmc + - image: New sprites for the surplus smg, made by me + SmArtKar: + - bugfix: Fixed mapload circuit floors not drawing power and deconstructing circuit + floors not reducing power load + - bugfix: Projectile dampener, recycler and ninja stealth MOD modules now work properly + - bugfix: You can no longer tear peoples arms off with non-killer clamps + - bugfix: Mechs can no longer equip infinite amount of weapons + - bugfix: Mining MODsuits now can store everything that explorer suits can + Vekter: + - bugfix: Fixes an exploit that allowed players to open a Bag of Holding rift in + the Heretic dimension. + deathrobotpunch: + - qol: drones now have soap in their internal storage! + grungussuss: + - sound: leather, skins and cardboard have their own sound now + - bugfix: smuggler satchels will no longer spawn in space + - sound: added sniff sounds + - sound: added sigh sounds + grungussuss and Kayozz: + - sound: more maintenance ambience has been added + rroqc: + - bugfix: plants no longer select reagent genes they already have while cross pollinating + - code_imp: 'improves reagent cross pollination code + + :cl:' +2024-07-31: + Jacquerel: + - image: Big balls are now much rounder, to more easily slide down into a cannon. + SmArtKar: + - image: All implants have received a fresh coat of paint + rroqc: + - bugfix: 'fix a bug where botany reagents would dissapear from existing plants + + :cl:' + thegrb93: + - bugfix: Fixes getting permanently hot or cold if wearing thermal insulation as + a lizard diff --git a/html/changelogs/archive/2024-08.yml b/html/changelogs/archive/2024-08.yml new file mode 100644 index 00000000000000..0665fba035a2a8 --- /dev/null +++ b/html/changelogs/archive/2024-08.yml @@ -0,0 +1,161 @@ +2024-08-01: + 00-Steven: + - bugfix: You no longer render on top of tall enough objects that get vertically + offset when anchored to a table when standing on the tile directly to the north + of them. Examples are soda and booze dispensers. + - bugfix: Removing the vertical offset some objects get when anchored to a table + can be done by unanchoring it at any point, rather than only on a table. + ArcaneMusic: + - qol: NODE drones summoned to tap a vent within ore vents now display a green status + light to show how much longer they need the vent defended for. + Axidyuwu: + - bugfix: fixes a way of duplicating iron with wallmounted sparklers and light switches + Bisar: + - qol: Machines check their parts during initialization now; this will usually apply + in cases such as a machine in a prefab having been varedited to be upgraded. + - code_imp: All machines check their parts during initialization. + Ghommie: + - rscadd: Added tadpoles, which can be scooped from puddles with right-click. Functionally + they're like most fish, which require an aquarium to survive, and also need + to be fed fairly frequently, however they quickly become frogs after about 3 + minutes of care. + - rscadd: Every station now has a couple puddles. One at the public garden and the + other in prison. + - qol: Changed the name of an aquarium UI button from "Reproduction Prevention" + to "Reproduction and Growth", as it controls both fish breeding and growth. + - rscadd: Carps, frogs and young lobstrosities now fear people wearing fishing hats! + Adults and megacarp favour the 'fight' part of the fear reflex however. + - bugfix: The hat stabilizer module now inherits the clothing traits of the attached + hat. + Helg2: + - bugfix: Emergency climbing hooks now shouldn't spawn on non multi-z stations. + Jackraxxus: + - bugfix: AI mech control beacons and malf AI dominate mech work again. + LT3: + - bugfix: Scanner gate now detects items thrown through it + - bugfix: Scanner gate does not alarm for guns on players with mindshield + - bugfix: Scanner gate does not alarm for guns on players with weapons ID card access + - sound: Reduced volume of scanner gate alarm + MTandi: + - image: Made chem master container icons not blurry + - bugfix: Portable atmos machine circuit boards list correct components + - bugfix: Portable atmos machine circuit boards accept unwrenched fittings + - bugfix: Portable atmos machines are movable on construction + - qol: smart fridge UI now groups items by type+name instead of just type + - qol: smart fridge UI now shows item names next to the images + - qol: smart fridge UI has a list view option (default for chem and viro versions) + - bugfix: fixed smart fridge stacking sounds when dispensing multiple items + - qol: Renamed seed packs to have the plant name at the beginning + Majkl-J: + - bugfix: Fixes the echolocation screen overlay not appearing with default arguments + due to using the wrong icon state + Momo8289: + - bugfix: The charge indicators on power cells now work properly. + - code_imp: Removed some now redundant power cell appearance updates + Rhials: + - qol: Sentience potions can now be used without a provided summon reason. + - rscadd: Spies can now pick their own custom objectives, if they so choose. + Sadboysuss: + - bugfix: The clown planet domain is now completable + - bugfix: rod sounds will now vary in pitch + - bugfix: spray can face spraying will no longer work on light-sensitives with eyewear + and people wearing eye covering masks + - bugfix: birdshot engineering feedback has been applied + SmArtKar: + - bugfix: Bank cards speak once more + - bugfix: Removed a rogue wall grinder on icebox + - bugfix: Silicons and simplemobs can also hear radio chatter now + - bugfix: Heart eater wizard perk no longer works activates on organs that haven't + been used before + - qol: You can now reorder items inside storages by dragging them + - balance: Mining MODsuits are now considered thick clothing and gained expanded + storage. + - image: Mining MODsuits got a slight glowup and hide belts now + - bugfix: Fixed advanced pods showing up as cultist pods + - admin: Subtype vendor no longer requries an ID + - qol: You no longer goofily swap with others trying to move in the same direction + as you if you're not faster than them + - code_imp: Moved mobswap check logic into a separate proc and made it more readable + - balance: Discounts now pick 4-6 items each from a unique category + - balance: Items that cost below 4 TC cannot get discounted anymore + - balance: Elite syndicate MODs for traitors can no longer get discounted + - bugfix: Fixed NT Frontier discounts not applying + Watermelon914: + - admin: Turfs in lua will no longer become invalid on deletion. + - bugfix: Fixes SS13.wait not working when called multiple times before it finishes + waiting. + Xackii: + - bugfix: Justice design no longer disappears + - bugfix: Mechs can attack other mechs in melee + - rscadd: RD can emag mech fabricator(like roboticist). + carlarctg: + - rscdel: Revert "Heretic spell invocations now use one dead language per path" + grungussuss: + - bugfix: the abandoned plasma research facility on icemoon no longer has an item + that shouldn't exist + mc-oofert: + - bugfix: wawastation pharmacy now has a hand labeller + rroqc: + - rscadd: 'durathread robes can now store botany gear + + :cl:' +2024-08-02: + FlufflesTheDog: + - bugfix: Existing gas flow meters have been recalled and replaced due to a faulty + screen connection, and once again convey pressure and temperature + Ghommie: + - qol: Skills are passed down to bitrunning avatars and then back to the original + body. + - bugfix: Stop clientless lobstrosities from fishing other lobstrosities, which + in turn can fish other lobstrosities and so on. + - balance: Stop clientless lobstrosities from fishing the lavaland fishing spot + chest. + Jacquerel: + - admin: Adds some missing traits to the mob trait list in VV + MTandi: + - qol: new uplink UI + - qol: made it possible to buy a custom amount of TC, instead of bundles with fixed + amounts + Majkl-J: + - bugfix: Flashdarks now broduce darkness upon toggling + SmArtKar: + - bugfix: Bamboo staves can now be wielded + - bugfix: Bostaff no longer disappears forever when wielded + - bugfix: Rice hat no longer disappears upon being toggled and can be raised back + up. Toggling sprites is now done by alt-clicking + - qol: Callouts and MODsuit quick module pickers now track user + - qol: Cable coil and welding tool healing now loops similarly to sutures/meshes + - bugfix: Fixed cable coil/welding tool heal message not displaying when healing + someone else + - bugfix: Putting people you're fireman carrying into contractor pods no longer + sends both of you to zelda's shadow realm + Tattle: + - qol: dead cyborgs now blink yellow lights + - qol: damaged cyborgs have smoke particles when they've taken brute damage, and + sparks for burn + Y0SH1M4S73R: + - admin: The layout of the lua editor has been tweaked slightly. + - admin: In the lua editor, you can now toggle whether to log runtimes the viewed + state is involved in. + carlarctg: + - rscadd: Adds a bronze dimensional theme + necromanceranne: + - bugfix: Shoving someone onto a table now causes them to become vulnerable to being + stunned. +2024-08-03: + Watermelon914: + - bugfix: Fixed an infinite TC glitch dupe + Y0SH1M4S73R: + - admin: The "Suppress Runtime Logging" toggle in the lua editor actually does what + it says +2024-08-05: + Ben10Omintrix: + - bugfix: juvenile lobstrosities will now look for food + OrionTheFox: + - image: added and updated belt/suit/mask storage sprites for several knives missing + them + SmArtKar: + - bugfix: Lizards no longer die from cold on icebox despite wearing insulation + - bugfix: Fixed handyman assistants spawning without a PDA + Y0SH1M4S73R: + - bugfix: lua scripting now works on linux diff --git a/html/statbrowser.css b/html/statbrowser.css index dc693f42f756b4..cd1d63bf7c0609 100644 --- a/html/statbrowser.css +++ b/html/statbrowser.css @@ -1,150 +1,125 @@ body { font-family: Verdana, Geneva, Tahoma, sans-serif; - font-size: 12px !important; + font-size: 12px; margin: 0 !important; padding: 0 !important; - overflow-x: hidden; - overflow-y: scroll; -} - -body.dark { - background-color: #131313; - color: #b2c4dd; - scrollbar-base-color: #1c1c1c; - scrollbar-face-color: #3b3b3b; - scrollbar-3dlight-color: #252525; - scrollbar-highlight-color: #252525; - scrollbar-track-color: #1c1c1c; - scrollbar-arrow-color: #929292; - scrollbar-shadow-color: #3b3b3b; -} - -#menu { - background-color: #F0F0F0; - position: fixed; - width: 100%; - z-index: 100; -} - -.dark #menu { - background-color: #202020; -} - -#statcontent { - padding: 7px 7px 7px 7px; + overflow: hidden; } a { - color: black; - text-decoration: none -} - -.dark a { - color: #b2c4dd; + color: #003399; + text-decoration: none; } -a:hover, -.dark a:hover { - text-decoration: underline; +a:hover { + color: #007fff; } -ul { - list-style-type: none; - margin: 0; - padding: 0; - background-color: #333; +h3 { + margin: 0 -0.5em 0.25em; + padding: 1em 0.66em 0.5em; + border-bottom: 0.1667em solid; } -li { - float: left; -} -li a { - display: block; - color: white; - text-align: center; - padding: 14px 16px; - text-decoration: none; +img { + -ms-interpolation-mode: nearest-neighbor; + image-rendering: pixelated; } -li a:hover:not(.active) { - background-color: #111; +.stat-container { + display: flex; + flex-direction: column; + height: 100vh; } -.button-container { - display: inline-flex; - flex-wrap: wrap-reverse; - flex-direction: row; - align-items: flex-start; - overflow-x: hidden; - white-space: pre-wrap; - padding: 0 4px; +#menu { + display: flex; + overflow-x: auto; + overflow-y: hidden; + padding: 0.25em 0.25em 0; + background-color: #ffffff; } .button { - background-color: #dfdfdf; - border: 1px solid #cecece; - border-bottom-width: 2px; - color: rgba(0, 0, 0, 0.7); - padding: 6px 4px 4px; - text-align: center; - text-decoration: none; - font-size: 12px; - margin: 0; + display: inline-table; cursor: pointer; - transition-duration: 100ms; - order: 3; - min-width: 40px; -} - -.dark button { - background-color: #222222; - border-color: #343434; - color: rgba(255, 255, 255, 0.5); + user-select: none; + -ms-user-select: none; /* Remove after Byond 516 */ + text-align: center; + font-size: 1em; + min-width: 2.9em; + padding: 0.5em 0.5em 0.4em; + background-color: transparent; + color: rgba(0, 0, 0, 0.5); + border: 0; + border-bottom: 0.1667em solid transparent; + border-radius: 0.25em 0.25em 0 0; } .button:hover { background-color: #ececec; - transition-duration: 0; -} - -.dark button:hover { - background-color: #2e2e2e; } -.button:active, .button.active { - background-color: #ffffff; + background-color: #dfdfdf; color: black; - border-top-color: #cecece; - border-left-color: #cecece; - border-right-color: #cecece; - border-bottom-color: #ffffff; + border-bottom-color: #000000; +} + +#under-menu { + height: 0.5em; + background-color: #eeeeee; } -.dark .button:active, -.dark .button.active { - background-color: #444444; - color: white; - border-top-color: #343434; - border-left-color: #343434; - border-right-color: #343434; - border-bottom-color: #ffffff; +#statcontent { + flex: 1; + padding: 0.75em 0.5em; + overflow-y: scroll; + overflow-x: hidden; } .grid-container { - margin: -2px; - margin-right: -15px; + margin: 0; } .grid-item { + display: inline-flex; position: relative; - display: inline-block; + user-select: none; + -ms-user-select: none; /* Remove after Byond 516 */ width: 100%; box-sizing: border-box; - overflow: visible; - padding: 3px 2px; text-decoration: none; + background-color: transparent; + color: black; +} + +.grid-item:hover { + color: #003399; + z-index: 1; +} + +.grid-item-text { + display: inline-block; + overflow: hidden; + text-overflow: ellipsis; + box-sizing: border-box; + white-space: nowrap; + width: 100%; + padding: 0.33em 0.5em; + border-radius: 0.25em; +} + +.grid-item-text:hover { + position: absolute; + top: -1.33em; + white-space: normal; + background-color: #ececec; +} + +.grid-item-text:active { + background-color: #dfdfdf; } @media only screen and (min-width: 300px) { @@ -171,57 +146,67 @@ li a:hover:not(.active) { } } -.grid-item:hover { - z-index: 1; +.status-info { + margin: 0 0.33em 0.25em; } -.grid-item:hover .grid-item-text { - width: auto; - text-decoration: underline; +.interview_panel_stats, +.interview_panel_controls { + margin-bottom: 1em; } -.grid-item-text { - display: inline-block; - width: 100%; - background-color: #ffffff; - margin: 0 -6px; - padding: 0 6px; - white-space: nowrap; - overflow: hidden; - text-overflow: ellipsis; - pointer-events: none; +/* Dark theme colors */ +body.dark { + background-color: #131313; + color: #b2c4dd; + scrollbar-base-color: #1c1c1c; + scrollbar-face-color: #3b3b3b; + scrollbar-3dlight-color: #252525; + scrollbar-highlight-color: #252525; + scrollbar-track-color: #1c1c1c; + scrollbar-arrow-color: #929292; + scrollbar-shadow-color: #3b3b3b; +} + +.dark a { + color: #6699ff; +} + +.dark a:hover, +.dark .grid-item:hover { + color: #80bfff; } -.dark .grid-item-text { +.dark #menu { background-color: #131313; } -.link { - display: inline; - background: none; - border: none; - padding: 7px 14px; - color: black; - text-decoration: none; - cursor: pointer; - font-size: 13px; - margin: 2px 2px; +.dark .button { + color: rgba(255, 255, 255, 0.5); } -.dark .link { - color: #abc6ec; +.dark .button:hover { + background-color: #252525; } -.link:hover { - text-decoration: underline; +.dark .button.active { + background-color: #313131; + color: #d4dfec; + border-bottom-color: #d4dfec; } -img { - -ms-interpolation-mode: nearest-neighbor; - image-rendering: pixelated; +.dark #under-menu { + background-color: #202020; +} + +.dark .grid-item{ + color: #b2c4dd; +} + +.dark .grid-item-text:hover { + background-color: #252525; } -.interview_panel_controls, -.interview_panel_stats { - margin-bottom: 10px; +.dark .grid-item-text:active { + background-color: #313131; } diff --git a/html/statbrowser.html b/html/statbrowser.html index 1aea8811d58a08..ffd7425bd26070 100644 --- a/html/statbrowser.html +++ b/html/statbrowser.html @@ -1,3 +1,5 @@ - -
-
+
+ +
+
+
diff --git a/html/statbrowser.js b/html/statbrowser.js index 0d89487af5b39a..f6c188c6edd61b 100644 --- a/html/statbrowser.js +++ b/html/statbrowser.js @@ -32,7 +32,6 @@ var turfname = ""; var imageRetryDelay = 500; var imageRetryLimit = 50; var menu = document.getElementById('menu'); -var under_menu = document.getElementById('under_menu'); var statcontentdiv = document.getElementById('statcontent'); var storedimages = []; var split_admin_tabs = false; @@ -58,23 +57,23 @@ function createStatusTab(name) { if (!verb_tabs.includes(name) && !permanent_tabs.includes(name)) { return; } - var B = document.createElement("BUTTON"); - B.onclick = function () { + var button = document.createElement("DIV"); + button.onclick = function () { tab_change(name); this.blur(); + statcontentdiv.focus(); }; - B.id = name; - B.textContent = name; - B.className = "button"; + button.id = name; + button.textContent = name; + button.className = "button"; //ORDERING ALPHABETICALLY - B.style.order = name.charCodeAt(0); + button.style.order = name.charCodeAt(0); if (name == "Status" || name == "MC") { - B.style.order = name == "Status" ? 1 : 2; + button.style.order = name == "Status" ? 1 : 2; } //END ORDERING - menu.appendChild(B); + menu.appendChild(button); SendTabToByond(name); - under_menu.style.height = menu.clientHeight + 'px'; } function removeStatusTab(name) { @@ -88,7 +87,6 @@ function removeStatusTab(name) { } menu.removeChild(document.getElementById(name)); TakeTabFromByond(name); - under_menu.style.height = menu.clientHeight + 'px'; } function sortVerbs() { @@ -104,10 +102,6 @@ function sortVerbs() { }) } -window.onresize = function () { - under_menu.style.height = menu.clientHeight + 'px'; -} - function addPermanentTab(name) { if (!permanent_tabs.includes(name)) { permanent_tabs.push(name); @@ -361,6 +355,7 @@ function draw_status() { } else { var div = document.createElement("div"); div.textContent = status_tab_parts[i]; + div.className = "status-info"; document.getElementById("statcontent").appendChild(div); } } @@ -717,6 +712,10 @@ function set_theme(which) { } } +function set_font_size(size) { + document.body.style.setProperty('font-size', size); +} + function set_style_sheet(sheet) { if (document.getElementById("goonStyle")) { var currentSheet = document.getElementById("goonStyle"); diff --git a/icons/_nanomaps/Birdshot Station_nanomap_z1.png b/icons/_nanomaps/Birdshot Station_nanomap_z1.png index 991c567cd09fec..fc2fd5ff5fb2b2 100644 Binary files a/icons/_nanomaps/Birdshot Station_nanomap_z1.png and b/icons/_nanomaps/Birdshot Station_nanomap_z1.png differ diff --git a/icons/_nanomaps/Delta Station_nanomap_z1.png b/icons/_nanomaps/Delta Station_nanomap_z1.png index 5e77d6fe6cdd8f..eeb4958012666e 100644 Binary files a/icons/_nanomaps/Delta Station_nanomap_z1.png and b/icons/_nanomaps/Delta Station_nanomap_z1.png differ diff --git a/icons/_nanomaps/Ice Box Station_nanomap_z1.png b/icons/_nanomaps/Ice Box Station_nanomap_z1.png index 24e8ef02065213..00a5741f3ffe6e 100644 Binary files a/icons/_nanomaps/Ice Box Station_nanomap_z1.png and b/icons/_nanomaps/Ice Box Station_nanomap_z1.png differ diff --git a/icons/_nanomaps/Ice Box Station_nanomap_z2.png b/icons/_nanomaps/Ice Box Station_nanomap_z2.png index f7d184081d732b..fa355ee6a7c935 100644 Binary files a/icons/_nanomaps/Ice Box Station_nanomap_z2.png and b/icons/_nanomaps/Ice Box Station_nanomap_z2.png differ diff --git a/icons/_nanomaps/Ice Box Station_nanomap_z3.png b/icons/_nanomaps/Ice Box Station_nanomap_z3.png index efc6e19276c85d..ada28a2d694af3 100644 Binary files a/icons/_nanomaps/Ice Box Station_nanomap_z3.png and b/icons/_nanomaps/Ice Box Station_nanomap_z3.png differ diff --git a/icons/_nanomaps/Meta Station_nanomap_z1.png b/icons/_nanomaps/Meta Station_nanomap_z1.png index ac4a7af4fa80bd..ddd86a25031623 100644 Binary files a/icons/_nanomaps/Meta Station_nanomap_z1.png and b/icons/_nanomaps/Meta Station_nanomap_z1.png differ diff --git a/icons/_nanomaps/NorthStar_nanomap_z2.png b/icons/_nanomaps/NorthStar_nanomap_z2.png index 04bbf32256e2f9..51858a266832a4 100644 Binary files a/icons/_nanomaps/NorthStar_nanomap_z2.png and b/icons/_nanomaps/NorthStar_nanomap_z2.png differ diff --git a/icons/_nanomaps/NorthStar_nanomap_z4.png b/icons/_nanomaps/NorthStar_nanomap_z4.png index 5608cac3defa8f..923f7999f1786c 100644 Binary files a/icons/_nanomaps/NorthStar_nanomap_z4.png and b/icons/_nanomaps/NorthStar_nanomap_z4.png differ diff --git a/icons/_nanomaps/Tramstation_nanomap_z1.png b/icons/_nanomaps/Tramstation_nanomap_z1.png index a823333a26b891..942b6d8eb497ee 100644 Binary files a/icons/_nanomaps/Tramstation_nanomap_z1.png and b/icons/_nanomaps/Tramstation_nanomap_z1.png differ diff --git a/icons/_nanomaps/Tramstation_nanomap_z2.png b/icons/_nanomaps/Tramstation_nanomap_z2.png index 5cc48c959c3375..a3a42b2abb87c7 100644 Binary files a/icons/_nanomaps/Tramstation_nanomap_z2.png and b/icons/_nanomaps/Tramstation_nanomap_z2.png differ diff --git a/icons/effects/callouts.dmi b/icons/effects/callouts.dmi new file mode 100644 index 00000000000000..583f47d52b3478 Binary files /dev/null and b/icons/effects/callouts.dmi differ diff --git a/icons/hud/fishing_hud.dmi b/icons/hud/fishing_hud.dmi index 58c478d071064c..f18ed7c6cfca90 100644 Binary files a/icons/hud/fishing_hud.dmi and b/icons/hud/fishing_hud.dmi differ diff --git a/icons/hud/radial.dmi b/icons/hud/radial.dmi index e4a1693fb573e8..f6e141ab6855a4 100644 Binary files a/icons/hud/radial.dmi and b/icons/hud/radial.dmi differ diff --git a/icons/mob/clothing/back.dmi b/icons/mob/clothing/back.dmi index 0f07c3fe0803f1..a96beb1cfa9364 100644 Binary files a/icons/mob/clothing/back.dmi and b/icons/mob/clothing/back.dmi differ diff --git a/icons/mob/clothing/belt.dmi b/icons/mob/clothing/belt.dmi index a2d318adfb7d1c..724a29de21b0f9 100644 Binary files a/icons/mob/clothing/belt.dmi and b/icons/mob/clothing/belt.dmi differ diff --git a/icons/mob/clothing/belt_mirror.dmi b/icons/mob/clothing/belt_mirror.dmi index 9594f6227730fc..0507a0301944e9 100644 Binary files a/icons/mob/clothing/belt_mirror.dmi and b/icons/mob/clothing/belt_mirror.dmi differ diff --git a/icons/mob/clothing/head/costume.dmi b/icons/mob/clothing/head/costume.dmi index 1de2281271f801..09c11ca0acba3d 100644 Binary files a/icons/mob/clothing/head/costume.dmi and b/icons/mob/clothing/head/costume.dmi differ diff --git a/icons/mob/clothing/head/helmet.dmi b/icons/mob/clothing/head/helmet.dmi index 116f0256a6276d..579f4c53f0f979 100644 Binary files a/icons/mob/clothing/head/helmet.dmi and b/icons/mob/clothing/head/helmet.dmi differ diff --git a/icons/mob/clothing/head/wizard.dmi b/icons/mob/clothing/head/wizard.dmi index 785ed63ca5bde0..cafde2136f7405 100644 Binary files a/icons/mob/clothing/head/wizard.dmi and b/icons/mob/clothing/head/wizard.dmi differ diff --git a/icons/mob/clothing/mask.dmi b/icons/mob/clothing/mask.dmi index 5f577c7e255d96..ac40c153dd7842 100644 Binary files a/icons/mob/clothing/mask.dmi and b/icons/mob/clothing/mask.dmi differ diff --git a/icons/mob/clothing/modsuit/mod_clothing.dmi b/icons/mob/clothing/modsuit/mod_clothing.dmi index 3a567eac4e724b..cb2a472c32ed62 100644 Binary files a/icons/mob/clothing/modsuit/mod_clothing.dmi and b/icons/mob/clothing/modsuit/mod_clothing.dmi differ diff --git a/icons/mob/clothing/modsuit/mod_modules.dmi b/icons/mob/clothing/modsuit/mod_modules.dmi index 3c41dac86b2d46..4f2dc9740d1f70 100644 Binary files a/icons/mob/clothing/modsuit/mod_modules.dmi and b/icons/mob/clothing/modsuit/mod_modules.dmi differ diff --git a/icons/mob/clothing/suits/armor.dmi b/icons/mob/clothing/suits/armor.dmi index eb7a525e4b78f4..ea80204c2cdcc8 100644 Binary files a/icons/mob/clothing/suits/armor.dmi and b/icons/mob/clothing/suits/armor.dmi differ diff --git a/icons/mob/clothing/suits/wizard.dmi b/icons/mob/clothing/suits/wizard.dmi index 454bc1f3cf1e6b..9e8c8224130c02 100644 Binary files a/icons/mob/clothing/suits/wizard.dmi and b/icons/mob/clothing/suits/wizard.dmi differ diff --git a/icons/mob/inhands/clothing/hats_lefthand.dmi b/icons/mob/inhands/clothing/hats_lefthand.dmi index 4fa05fa6cd6911..6ad1f8886c99e1 100644 Binary files a/icons/mob/inhands/clothing/hats_lefthand.dmi and b/icons/mob/inhands/clothing/hats_lefthand.dmi differ diff --git a/icons/mob/inhands/clothing/hats_righthand.dmi b/icons/mob/inhands/clothing/hats_righthand.dmi index dfb0b71ef4bdcb..3aba15568ef882 100644 Binary files a/icons/mob/inhands/clothing/hats_righthand.dmi and b/icons/mob/inhands/clothing/hats_righthand.dmi differ diff --git a/icons/mob/inhands/equipment/belt_lefthand.dmi b/icons/mob/inhands/equipment/belt_lefthand.dmi index 9f306a2777d2fa..d5c4f7c4424b55 100644 Binary files a/icons/mob/inhands/equipment/belt_lefthand.dmi and b/icons/mob/inhands/equipment/belt_lefthand.dmi differ diff --git a/icons/mob/inhands/equipment/belt_righthand.dmi b/icons/mob/inhands/equipment/belt_righthand.dmi index 7b519f7cf69ea6..0e0c7b817eed4b 100644 Binary files a/icons/mob/inhands/equipment/belt_righthand.dmi and b/icons/mob/inhands/equipment/belt_righthand.dmi differ diff --git a/icons/mob/inhands/equipment/shields_lefthand.dmi b/icons/mob/inhands/equipment/shields_lefthand.dmi index 1aa27021b9ede5..a19d5f46245e1f 100644 Binary files a/icons/mob/inhands/equipment/shields_lefthand.dmi and b/icons/mob/inhands/equipment/shields_lefthand.dmi differ diff --git a/icons/mob/inhands/equipment/shields_righthand.dmi b/icons/mob/inhands/equipment/shields_righthand.dmi index 4227ba00792b4c..b4d080345c5363 100644 Binary files a/icons/mob/inhands/equipment/shields_righthand.dmi and b/icons/mob/inhands/equipment/shields_righthand.dmi differ diff --git a/icons/mob/inhands/items/food_lefthand.dmi b/icons/mob/inhands/items/food_lefthand.dmi index 8e2b19c4dd42a3..5dabacf53dbf66 100644 Binary files a/icons/mob/inhands/items/food_lefthand.dmi and b/icons/mob/inhands/items/food_lefthand.dmi differ diff --git a/icons/mob/inhands/items/food_righthand.dmi b/icons/mob/inhands/items/food_righthand.dmi index 12063ad38a8f95..7cd6569508c8ee 100644 Binary files a/icons/mob/inhands/items/food_righthand.dmi and b/icons/mob/inhands/items/food_righthand.dmi differ diff --git a/icons/mob/inhands/items_lefthand.dmi b/icons/mob/inhands/items_lefthand.dmi index 86bd5020f4f326..86396dcaa8c67f 100644 Binary files a/icons/mob/inhands/items_lefthand.dmi and b/icons/mob/inhands/items_lefthand.dmi differ diff --git a/icons/mob/inhands/items_righthand.dmi b/icons/mob/inhands/items_righthand.dmi index a6de8b974644c3..2cbe944aecc529 100644 Binary files a/icons/mob/inhands/items_righthand.dmi and b/icons/mob/inhands/items_righthand.dmi differ diff --git a/icons/mob/inhands/weapons/guns_lefthand.dmi b/icons/mob/inhands/weapons/guns_lefthand.dmi index 9c8d8eec107810..90df2a892f984b 100644 Binary files a/icons/mob/inhands/weapons/guns_lefthand.dmi and b/icons/mob/inhands/weapons/guns_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/guns_righthand.dmi b/icons/mob/inhands/weapons/guns_righthand.dmi index 1525f403312c9a..eebed61656aa4b 100644 Binary files a/icons/mob/inhands/weapons/guns_righthand.dmi and b/icons/mob/inhands/weapons/guns_righthand.dmi differ diff --git a/icons/mob/inhands/weapons/staves_lefthand.dmi b/icons/mob/inhands/weapons/staves_lefthand.dmi index 5e4eb552f2a5cc..917b46ae8938a2 100644 Binary files a/icons/mob/inhands/weapons/staves_lefthand.dmi and b/icons/mob/inhands/weapons/staves_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/staves_righthand.dmi b/icons/mob/inhands/weapons/staves_righthand.dmi index 9de32d8cd9533a..da1765fe800c67 100644 Binary files a/icons/mob/inhands/weapons/staves_righthand.dmi and b/icons/mob/inhands/weapons/staves_righthand.dmi differ diff --git a/icons/mob/inhands/weapons/swords_lefthand.dmi b/icons/mob/inhands/weapons/swords_lefthand.dmi index b9552c754c0829..82c98f057c0ece 100644 Binary files a/icons/mob/inhands/weapons/swords_lefthand.dmi and b/icons/mob/inhands/weapons/swords_lefthand.dmi differ diff --git a/icons/mob/inhands/weapons/swords_righthand.dmi b/icons/mob/inhands/weapons/swords_righthand.dmi index f132e997658cb5..3f6e471e83e2f2 100644 Binary files a/icons/mob/inhands/weapons/swords_righthand.dmi and b/icons/mob/inhands/weapons/swords_righthand.dmi differ diff --git a/icons/mob/silicon/robots.dmi b/icons/mob/silicon/robots.dmi index 5c79a0f95e39bd..c2780ce26abea7 100644 Binary files a/icons/mob/silicon/robots.dmi and b/icons/mob/silicon/robots.dmi differ diff --git a/icons/mob/simple/corgi_head.dmi b/icons/mob/simple/corgi_head.dmi index 2e14a3ed0bb5dd..c07f1227a3de15 100644 Binary files a/icons/mob/simple/corgi_head.dmi and b/icons/mob/simple/corgi_head.dmi differ diff --git a/icons/obj/aquarium/fish.dmi b/icons/obj/aquarium/fish.dmi index ab282e1681be9d..638c8300f304a0 100644 Binary files a/icons/obj/aquarium/fish.dmi and b/icons/obj/aquarium/fish.dmi differ diff --git a/icons/obj/clothing/belts.dmi b/icons/obj/clothing/belts.dmi index 5ccdf2c186f895..14ed534744f6e8 100644 Binary files a/icons/obj/clothing/belts.dmi and b/icons/obj/clothing/belts.dmi differ diff --git a/icons/obj/clothing/head/helmet.dmi b/icons/obj/clothing/head/helmet.dmi index fe52d505e439d0..cc54b2bf92934b 100644 Binary files a/icons/obj/clothing/head/helmet.dmi and b/icons/obj/clothing/head/helmet.dmi differ diff --git a/icons/obj/clothing/head/wizard.dmi b/icons/obj/clothing/head/wizard.dmi index 29595f02fc2add..82ea73b68babd7 100644 Binary files a/icons/obj/clothing/head/wizard.dmi and b/icons/obj/clothing/head/wizard.dmi differ diff --git a/icons/obj/clothing/modsuit/mod_clothing.dmi b/icons/obj/clothing/modsuit/mod_clothing.dmi index 85dd82449709f3..6ab49417aa52fc 100644 Binary files a/icons/obj/clothing/modsuit/mod_clothing.dmi and b/icons/obj/clothing/modsuit/mod_clothing.dmi differ diff --git a/icons/obj/clothing/modsuit/mod_modules.dmi b/icons/obj/clothing/modsuit/mod_modules.dmi index 6ec143a849e1cb..36d95aa61fdbbe 100644 Binary files a/icons/obj/clothing/modsuit/mod_modules.dmi and b/icons/obj/clothing/modsuit/mod_modules.dmi differ diff --git a/icons/obj/clothing/suits/armor.dmi b/icons/obj/clothing/suits/armor.dmi index 0484cf060d0333..b1763f5453ffe0 100644 Binary files a/icons/obj/clothing/suits/armor.dmi and b/icons/obj/clothing/suits/armor.dmi differ diff --git a/icons/obj/clothing/suits/wizard.dmi b/icons/obj/clothing/suits/wizard.dmi index fcfa748d3b317c..94fc99b01b47d9 100644 Binary files a/icons/obj/clothing/suits/wizard.dmi and b/icons/obj/clothing/suits/wizard.dmi differ diff --git a/icons/obj/food/meat.dmi b/icons/obj/food/meat.dmi index 66761ee20298d0..bf0b1df4f4cd2b 100644 Binary files a/icons/obj/food/meat.dmi and b/icons/obj/food/meat.dmi differ diff --git a/icons/obj/machines/telecomms.dmi b/icons/obj/machines/telecomms.dmi index 1af082171ac16b..f1380268c29cf0 100644 Binary files a/icons/obj/machines/telecomms.dmi and b/icons/obj/machines/telecomms.dmi differ diff --git a/icons/obj/medical/organs/organs.dmi b/icons/obj/medical/organs/organs.dmi index fd1f5af2ddefcf..a9366894d7bf39 100644 Binary files a/icons/obj/medical/organs/organs.dmi and b/icons/obj/medical/organs/organs.dmi differ diff --git a/icons/obj/mining.dmi b/icons/obj/mining.dmi index 1f6393a8c51bab..991762dba3d593 100644 Binary files a/icons/obj/mining.dmi and b/icons/obj/mining.dmi differ diff --git a/icons/obj/pipes_n_cables/meter.dmi b/icons/obj/pipes_n_cables/meter.dmi index 2aed35e065f493..fa0d5e3bf4d88b 100644 Binary files a/icons/obj/pipes_n_cables/meter.dmi and b/icons/obj/pipes_n_cables/meter.dmi differ diff --git a/icons/obj/service/hydroponics/growing_vegetables.dmi b/icons/obj/service/hydroponics/growing_vegetables.dmi index 30f02e862e037a..37ddd825a829d2 100644 Binary files a/icons/obj/service/hydroponics/growing_vegetables.dmi and b/icons/obj/service/hydroponics/growing_vegetables.dmi differ diff --git a/icons/obj/service/hydroponics/harvest.dmi b/icons/obj/service/hydroponics/harvest.dmi index b15a34105dec24..dd3cd5865deeb9 100644 Binary files a/icons/obj/service/hydroponics/harvest.dmi and b/icons/obj/service/hydroponics/harvest.dmi differ diff --git a/icons/obj/service/hydroponics/seeds.dmi b/icons/obj/service/hydroponics/seeds.dmi index 4de1a757e1fbc4..c18c361b0ec0a8 100644 Binary files a/icons/obj/service/hydroponics/seeds.dmi and b/icons/obj/service/hydroponics/seeds.dmi differ diff --git a/icons/obj/stack_objects.dmi b/icons/obj/stack_objects.dmi index f13b10bdf4a8ad..489d045968984b 100644 Binary files a/icons/obj/stack_objects.dmi and b/icons/obj/stack_objects.dmi differ diff --git a/icons/obj/weapons/bows/arrows.dmi b/icons/obj/weapons/bows/arrows.dmi index 956a82dd9bf1f4..b19c20187ebfa9 100644 Binary files a/icons/obj/weapons/bows/arrows.dmi and b/icons/obj/weapons/bows/arrows.dmi differ diff --git a/icons/obj/weapons/bows/bows.dmi b/icons/obj/weapons/bows/bows.dmi index 4de9d4fca35ab4..57d42371042664 100644 Binary files a/icons/obj/weapons/bows/bows.dmi and b/icons/obj/weapons/bows/bows.dmi differ diff --git a/icons/obj/weapons/guns/ammo.dmi b/icons/obj/weapons/guns/ammo.dmi index 889d66c18b7f5f..4cd031af7ee8b5 100644 Binary files a/icons/obj/weapons/guns/ammo.dmi and b/icons/obj/weapons/guns/ammo.dmi differ diff --git a/icons/obj/weapons/guns/ballistic.dmi b/icons/obj/weapons/guns/ballistic.dmi index 98d92ff716a0df..824d8b7c0a073b 100644 Binary files a/icons/obj/weapons/guns/ballistic.dmi and b/icons/obj/weapons/guns/ballistic.dmi differ diff --git a/icons/obj/weapons/guns/projectiles.dmi b/icons/obj/weapons/guns/projectiles.dmi index 8c8356a0e51b8f..a6cf89e9b910f5 100644 Binary files a/icons/obj/weapons/guns/projectiles.dmi and b/icons/obj/weapons/guns/projectiles.dmi differ diff --git a/icons/obj/weapons/shields.dmi b/icons/obj/weapons/shields.dmi index 99e9b06aa4000d..eec85e9bea1ac1 100644 Binary files a/icons/obj/weapons/shields.dmi and b/icons/obj/weapons/shields.dmi differ diff --git a/icons/obj/weapons/stabby.dmi b/icons/obj/weapons/stabby.dmi index 24d4e0aef31eb9..be125b5f31d594 100644 Binary files a/icons/obj/weapons/stabby.dmi and b/icons/obj/weapons/stabby.dmi differ diff --git a/icons/obj/weapons/staff.dmi b/icons/obj/weapons/staff.dmi index 2d1460cf7e9829..45c20ae17e5da7 100644 Binary files a/icons/obj/weapons/staff.dmi and b/icons/obj/weapons/staff.dmi differ diff --git a/icons/obj/weapons/sword.dmi b/icons/obj/weapons/sword.dmi index d9a443cfc26998..9464c7b474585b 100644 Binary files a/icons/obj/weapons/sword.dmi and b/icons/obj/weapons/sword.dmi differ diff --git a/lua/SS13_base.lua b/lua/SS13_base.lua index ea04c8c6503dd3..2b0645172ea1cb 100644 --- a/lua/SS13_base.lua +++ b/lua/SS13_base.lua @@ -5,59 +5,38 @@ local SS13 = {} __SS13_signal_handlers = __SS13_signal_handlers or {} -SS13.SSlua = dm.global_vars.vars.SSlua +SS13.SSlua = dm.global_vars.SSlua SS13.global_proc = "some_magic_bullshit" SS13.state = state.state function SS13.get_runner_ckey() - return SS13.state:get_var("ckey_last_runner") + return SS13.state.ckey_last_runner end function SS13.get_runner_client() - return dm.global_vars:get_var("GLOB"):get_var("directory"):get(SS13.get_runner_ckey()) + return dm.global_vars.GLOB.directory[SS13.get_runner_ckey()] end -function SS13.istype(thing, type) - return dm.global_proc("_istype", thing, dm.global_proc("_text2path", type)) == 1 -end - -function SS13.start_tracking(datum) - local references = SS13.state.vars.references - references:add(datum) - SS13.state:call_proc("clear_on_delete", datum) -end +SS13.type = dm.global_procs._text2path -function SS13.new(type, ...) - local datum = SS13.new_untracked(type, ...) - if datum then - SS13.start_tracking(datum) - return datum - end +function SS13.istype(thing, type) + return dm.global_procs._istype(thing, SS13.type(type)) == 1 end -function SS13.type(string_type) - return dm.global_proc("_text2path", string_type) -end +SS13.new = dm.new function SS13.qdel(datum) if SS13.is_valid(datum) then - dm.global_proc("qdel", datum) + dm.global_procs.qdel(datum) return true end return false end -function SS13.new_untracked(type, ...) - return dm.global_proc("_new", type, { ... }) -end - function SS13.is_valid(datum) - if datum and not datum:is_null() and not datum:get_var("gc_destroyed") then - return true - end - return false + return dm.is_valid_ref(datum) and not datum.gc_destroyed end function SS13.await(thing_to_call, proc_to_call, ...) @@ -67,123 +46,107 @@ function SS13.await(thing_to_call, proc_to_call, ...) if thing_to_call == SS13.global_proc then proc_to_call = "/proc/" .. proc_to_call end - local promise = SS13.new("/datum/auxtools_promise", thing_to_call, proc_to_call, ...) - local promise_vars = promise.vars - while promise_vars.status == 0 do + local promise = SS13.new("/datum/promise", thing_to_call, proc_to_call, ...) + while promise.status == 0 do sleep() end - local return_value, runtime_message = promise_vars.return_value, promise_vars.runtime_message - SS13.stop_tracking(promise) - return return_value, runtime_message + return promise.return_value, promise.runtime_message end -function SS13.register_signal(datum, signal, func) - if not SS13.istype(datum, "/datum") then - return +local function signal_handler(data, ...) + local output = 0 + for func, _ in data.functions do + output = bit32.bor(output, func(...)) end - if not SS13.is_valid(datum) then - error("Tried to register a signal on a deleted datum!", 2) - return + return output +end + +local function create_qdeleting_callback(datum) + local callback = SS13.new("/datum/callback", SS13.state, "call_function_return_first") + callback:RegisterSignal(datum, "parent_qdeleting", "Invoke") + local path = { + "__SS13_signal_handlers", + dm.global_procs.WEAKREF(datum), + "parent_qdeleting", + "handler", + } + callback.arguments = { path } + local handler_data = { callback = callback, functions = {} } + handler_data.handler = function(source, ...) + local result = signal_handler(handler_data, source, ...) + for signal, signal_data in __SS13_signal_handlers[source] do + signal_data.callback:UnregisterSignal(source, signal) + end + __SS13_signal_handlers[source] = nil + return result end - local datumWeakRef = dm.global_proc("WEAKREF", datum) - if not __SS13_signal_handlers[datumWeakRef] then - __SS13_signal_handlers[datumWeakRef] = {} + __SS13_signal_handlers[datum]["parent_qdeleting"] = handler_data +end + +function SS13.register_signal(datum, signal, func) + if not type(func) == "function" then + return end - if signal == "_cleanup" then + if not SS13.istype(datum, "/datum") then return end - if not __SS13_signal_handlers[datumWeakRef][signal] then - __SS13_signal_handlers[datumWeakRef][signal] = {} + if not SS13.is_valid(datum) then + error("Tried to register a signal on a deleted datum", 2) end - local callback = SS13.new("/datum/callback", SS13.state, "call_function_return_first") - local callbackWeakRef = dm.global_proc("WEAKREF", callback) - callback:call_proc("RegisterSignal", datum, signal, "Invoke") - local path = { "__SS13_signal_handlers", datumWeakRef, signal, callbackWeakRef, "func" } - callback.vars.arguments = { path } - -- Turfs don't remove their signals on deletion. - if not __SS13_signal_handlers[datumWeakRef]._cleanup and not SS13.istype(datum, "/turf") then - local cleanupCallback = SS13.new("/datum/callback", SS13.state, "call_function_return_first") - local cleanupPath = { "__SS13_signal_handlers", datumWeakRef, "_cleanup"} - cleanupCallback.vars.arguments = { cleanupPath } - cleanupCallback:call_proc("RegisterSignal", datum, "parent_qdeleting", "Invoke") - __SS13_signal_handlers[datumWeakRef]._cleanup = function(datum) - SS13.start_tracking(datumWeakRef) - timer.set_timeout(0, function() - SS13.signal_handler_cleanup(datumWeakRef) - SS13.stop_tracking(cleanupCallback) - SS13.stop_tracking(datumWeakRef) - end) + if not __SS13_signal_handlers[datum] then + __SS13_signal_handlers[datum] = {} + -- Turfs don't remove their signals on deletion. + if not SS13.istype(datum, "/turf") then + create_qdeleting_callback(datum) end end - __SS13_signal_handlers[datumWeakRef][signal][callbackWeakRef] = { func = func, callback = callback } - return callback -end - -function SS13.stop_tracking(datum) - SS13.state:call_proc("let_soft_delete", datum) -end - -function SS13.unregister_signal(datum, signal, callback) - local function clear_handler(handler_info) - if not handler_info then - return - end - if not handler_info.callback then - return + local handler_data = __SS13_signal_handlers[datum][signal] + if not handler_data then + handler_data = { callback = nil, functions = {} } + local callback = SS13.new("/datum/callback", SS13.state, "call_function_return_first") + callback:RegisterSignal(datum, signal, "Invoke") + local path = { + "__SS13_signal_handlers", + dm.global_procs.WEAKREF(datum), + signal, + "handler", + } + callback.arguments = { path } + handler_data.callback = callback + handler_data.handler = function(...) + return signal_handler(handler_data, ...) end - local handler_callback = handler_info.callback - local callbackWeakRef = dm.global_proc("WEAKREF", handler_callback) - if not SS13.istype(datum, "/datum/weakref") then - handler_callback:call_proc("UnregisterSignal", datum, signal) - else - local actualDatum = datum:call_proc("hard_resolve") - if SS13.is_valid(actualDatum) then - handler_callback:call_proc("UnregisterSignal", actualDatum, signal) - end - end - SS13.stop_tracking(handler_callback) + __SS13_signal_handlers[datum][signal] = handler_data end + handler_data.functions[func] = true + return true +end - local datumWeakRef = datum - if not SS13.istype(datum, "/datum/weakref") then - datumWeakRef = dm.global_proc("WEAKREF", datum) - end - if not __SS13_signal_handlers[datumWeakRef] then +function SS13.unregister_signal(datum, signal, func) + if not (func == nil or type(func) == "function") then return end - - if signal == "_cleanup" then + if not __SS13_signal_handlers[datum] then return end - - if not __SS13_signal_handlers[datumWeakRef][signal] then + local handler_data = __SS13_signal_handlers[datum][signal] + if not handler_data then return end - - if not callback then - for handler_key, handler_info in __SS13_signal_handlers[datumWeakRef][signal] do - clear_handler(handler_info) + if func == nil then + if signal == "parent_qdeleting" then + handler_data.functions = {} + else + handler_data.callback:UnregisterSignal(datum, signal) + __SS13_signal_handlers[datum][signal] = nil end - __SS13_signal_handlers[datumWeakRef][signal] = nil else - if not SS13.istype(callback, "/datum/callback") then - return + handler_data.functions[func] = nil + if not (#handler_data.functions or (signal == "parent_qdeleting")) then + handler_data.callback:UnregisterSignal(datum, signal) + __SS13_signal_handlers[datum][signal] = nil end - local callbackWeakRef = dm.global_proc("WEAKREF", callback) - clear_handler(__SS13_signal_handlers[datumWeakRef][signal][callbackWeakRef]) - __SS13_signal_handlers[datumWeakRef][signal][callbackWeakRef] = nil - end -end - -function SS13.signal_handler_cleanup(datumWeakRef) - if not __SS13_signal_handlers[datumWeakRef] then - return - end - - for signal, _ in __SS13_signal_handlers[datumWeakRef] do - SS13.unregister_signal(datumWeakRef, signal) end - __SS13_signal_handlers[datumWeakRef] = nil end return SS13 diff --git a/lua/handler_group.lua b/lua/handler_group.lua index 0246d33c74488c..050551b852969f 100644 --- a/lua/handler_group.lua +++ b/lua/handler_group.lua @@ -1,29 +1,29 @@ -local SS13 = require('SS13') +local SS13 = require("SS13") local HandlerGroup = {} HandlerGroup.__index = HandlerGroup function HandlerGroup.new() return setmetatable({ - registered = {} + registered = {}, }, HandlerGroup) end -- Registers a signal on a datum for this handler group instance. function HandlerGroup:register_signal(datum, signal, func) - local callback = SS13.register_signal(datum, signal, func) - if not callback then + local registered_successfully = SS13.register_signal(datum, signal, func) + if not registered_successfully then return end - table.insert(self.registered, { datum = dm.global_proc("WEAKREF", datum), signal = signal, callback = callback }) + table.insert(self.registered, { datum = datum, signal = signal, func = func }) end -- Clears all the signals that have been registered on this HandlerGroup function HandlerGroup:clear() for _, data in self.registered do - if not data.callback or not data.datum then + if not data.func or not SS13.is_valid(data.datum) then continue end - SS13.unregister_signal(data.datum, data.signal, data.callback) + SS13.unregister_signal(data.datum, data.signal, data.func) end table.clear(self.registered) end @@ -45,5 +45,4 @@ function HandlerGroup.register_once(datum, signal, func) return callback end - return HandlerGroup diff --git a/lua/state.lua b/lua/state.lua index 080ee9f7eb32cb..cba24d64356119 100644 --- a/lua/state.lua +++ b/lua/state.lua @@ -1,7 +1,7 @@ -local SSlua = dm.global_vars:get_var("SSlua") +local SSlua = dm.global_vars.SSlua -for _, state in SSlua:get_var("states") do - if state:get_var("internal_id") == dm.state_id then +for _, state in SSlua.states do + if state.internal_id == _state_id then return { state = state } end end diff --git a/lua/timer.lua b/lua/timer.lua index 8619bbb54a29e4..e79cc8cdca54b8 100644 --- a/lua/timer.lua +++ b/lua/timer.lua @@ -2,19 +2,19 @@ local state = require("state") local Timer = {} -local SSlua = dm.global_vars:get_var("SSlua") +local SSlua = dm.global_vars.SSlua __Timer_timers = __Timer_timers or {} __Timer_callbacks = __Timer_callbacks or {} function __add_internal_timer(func, time, loop) local timer = { loop = loop, - executeTime = time + dm.world:get_var("time") + executeTime = time + dm.world.time, } __Timer_callbacks[tostring(func)] = function() timer.executing = false if loop and timer.terminate ~= true then - timer.executeTime = dm.world:get_var("time") + time + timer.executeTime = dm.world.time + time else __stop_internal_timer(tostring(func)) end @@ -37,22 +37,21 @@ function __stop_internal_timer(func) end __Timer_timer_processing = __Timer_timer_processing or false -state.state:set_var("timer_enabled", 1) +state.state.timer_enabled = 1 __Timer_timer_process = function(seconds_per_tick) if __Timer_timer_processing then return 0 end __Timer_timer_processing = true - local time = dm.world:get_var("time") for func, timeData in __Timer_timers do if timeData.executing == true then continue end - if over_exec_usage(0.85) then + if _exec.time / (dm.world.tick_lag * 100) > 0.85 then sleep() end - if time >= timeData.executeTime then - state.state:get_var("functions_to_execute"):add(func) + if dm.world.time >= timeData.executeTime then + list.add(state.state.functions_to_execute, func) timeData.executing = true end end @@ -61,9 +60,9 @@ __Timer_timer_process = function(seconds_per_tick) end function Timer.wait(time) - local next_yield_index = __next_yield_index + local yieldIndex = _exec.next_yield_index __add_internal_timer(function() - SSlua:call_proc("queue_resume", state.state, next_yield_index) + SSlua:queue_resume(state.state, yieldIndex) end, time * 10, false) coroutine.yield() end diff --git a/modular_bandastation/admin/_admin.dm b/modular_bandastation/admin/_admin.dm new file mode 100644 index 00000000000000..f9230d0005fbeb --- /dev/null +++ b/modular_bandastation/admin/_admin.dm @@ -0,0 +1,4 @@ +/datum/modpack/admin + name = "Административные удобства" + desc = "Всякие вещи для удобства администрации и дебага." + author = "Aylong" diff --git a/modular_bandastation/admin/_admin.dme b/modular_bandastation/admin/_admin.dme new file mode 100644 index 00000000000000..a72aec54b1a55c --- /dev/null +++ b/modular_bandastation/admin/_admin.dme @@ -0,0 +1,3 @@ +#include "_admin.dm" + +#include "code/admin_verbs.dm" diff --git a/modular_bandastation/admin/code/admin_verbs.dm b/modular_bandastation/admin/code/admin_verbs.dm new file mode 100644 index 00000000000000..bf72a51ed3825c --- /dev/null +++ b/modular_bandastation/admin/code/admin_verbs.dm @@ -0,0 +1,30 @@ +ADMIN_VERB_ONLY_CONTEXT_MENU(spawn_debug_outfit, R_SPAWN, "Debug Outfit", mob/admin in world) + if(tgui_alert(admin,"Это заспавнит вас в специальном Debug прикиде, удаляя при этом ваше старое тело если оно было. Вы уверены?", "Debug Outfit", list("Да", "Нет")) != "Да") + return + var/mob/living/carbon/human/admin_body = admin.change_mob_type(/mob/living/carbon/human, delete_old_mob = TRUE) + admin_body.equipOutfit(/datum/outfit/debug) + +ADMIN_VERB_ONLY_CONTEXT_MENU(download_flaticon, R_ADMIN, "Download Icon", atom/thing in world) + var/icon/image = getFlatIcon(thing, no_anim = TRUE) + var/image_width = max(image.Width(), 32) + var/image_height = max(image.Height(), 32) + + var/resize_answer = tgui_alert(usr, "Хотите ли вы изменить размер иконки? Оригинальный размер: [image_width]x[image_height]", "Download Icon", list("Да", "Нет", "Удвоить")) + if(resize_answer != "Нет" && !isnull(resize_answer)) + switch(resize_answer) + if("Да") + var/new_width = tgui_input_number(usr, "Оригинальная ширина: [image_width]px", "Изменение ширины", image_width, 1024, 16) + if(!isnull(new_width)) + image_width = new_width + + var/new_height = tgui_input_number(usr, "Оригинальная высота: [image_height]px", "Изменение высоты", image_height, 1024, 16) + if(!isnull(new_height)) + image_height = new_height + + if("Удвоить") + image_width *= 2 + image_height *= 2 + + image.Scale(image_width, image_height) + + usr << ftp(image, "[thing.name]_[image_width]x[image_height].png") diff --git a/modular_bandastation/balance/_balance.dme b/modular_bandastation/balance/_balance.dme index b1cdc16a011380..9a348afb891c39 100644 --- a/modular_bandastation/balance/_balance.dme +++ b/modular_bandastation/balance/_balance.dme @@ -5,3 +5,4 @@ #include "code/events.dm" #include "code/station_traits.dm" #include "code/supply_packs.dm" +#include "code/crew_manifest.dm" diff --git a/modular_bandastation/balance/code/crew_manifest.dm b/modular_bandastation/balance/code/crew_manifest.dm new file mode 100644 index 00000000000000..268a5e0d81f271 --- /dev/null +++ b/modular_bandastation/balance/code/crew_manifest.dm @@ -0,0 +1,6 @@ +/datum/computer_file/program/crew_manifest + download_access = list() + +/obj/item/modular_computer/pda/install_default_programs() + starting_programs |= /datum/computer_file/program/crew_manifest + . = ..() diff --git a/modular_bandastation/balance/code/events.dm b/modular_bandastation/balance/code/events.dm index 09c4f35392e4df..a86d6b49c59caf 100644 --- a/modular_bandastation/balance/code/events.dm +++ b/modular_bandastation/balance/code/events.dm @@ -13,3 +13,7 @@ var/obj/structure/closet/supplypod/pod = . pod.explosionSize = list(1,2,3,3) return pod + +// Holidays Removal +/datum/holiday/pride_week/shouldCelebrate(dd, mm, yyyy, ddd) + return FALSE diff --git a/modular_bandastation/hair/_hair.dm b/modular_bandastation/hair/_hair.dm new file mode 100644 index 00000000000000..0932a8390130d0 --- /dev/null +++ b/modular_bandastation/hair/_hair.dm @@ -0,0 +1,4 @@ +/datum/modpack/hair + name = "Прически" + desc = "Добавляет новые прически" + author = "Dekupich" diff --git a/modular_bandastation/hair/_hair.dme b/modular_bandastation/hair/_hair.dme new file mode 100644 index 00000000000000..dfed7522c732a2 --- /dev/null +++ b/modular_bandastation/hair/_hair.dme @@ -0,0 +1,3 @@ +#include "_hair.dm" + +#include "code/hair.dm" diff --git a/modular_bandastation/hair/code/hair.dm b/modular_bandastation/hair/code/hair.dm new file mode 100644 index 00000000000000..0197bd1c281c1f --- /dev/null +++ b/modular_bandastation/hair/code/hair.dm @@ -0,0 +1,124 @@ +/datum/sprite_accessory/hair/afropuffleft + name = "Afropuff Left" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_afropuffleft" + +/datum/sprite_accessory/hair/afropuffright + name = "Afropuff Rigt" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_afropuffright" + +/datum/sprite_accessory/hair/baum + name = "Baum" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_baum" + +/datum/sprite_accessory/hair/cotton + name = "Cotton" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_cotton" + +/datum/sprite_accessory/hair/cottonalt + name = "Cotton Alt" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_cottonalt" + +/datum/sprite_accessory/hair/flipped + name = "Flipped" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_flipped" + +/datum/sprite_accessory/hair/froofy + name = "Froofy" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_froofy" + +/datum/sprite_accessory/hair/frontbraids + name = "Long Braids" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_frontbraids" + +/datum/sprite_accessory/hair/glammetal + name = "Glammetal" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_glammetal" + +/datum/sprite_accessory/hair/inari + name = "Inari" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_inari" + +/datum/sprite_accessory/hair/kisaragi + name = "Kisaragi" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_kisaragi" + +/datum/sprite_accessory/hair/longbuns + name = "Long Buns" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_longbuns" + +/datum/sprite_accessory/hair/longstraighttwintails + name = "Long Twintails" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_longstraighttwintails" + +/datum/sprite_accessory/hair/longwavy + name = "Long Wavy" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_longwavy" + +/datum/sprite_accessory/hair/ponytail6 + name = "Ponytail Strict" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_ponytail6" + +/datum/sprite_accessory/hair/quadcurls + name = "Quadcurls" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_quadcurls" + +/datum/sprite_accessory/hair/rockstar + name = "Rockstar" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_rockstar" + +/datum/sprite_accessory/hair/stacy + name = "Stacy" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_stacy" + +/datum/sprite_accessory/hair/shorttassles + name = "Short Tassles" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_shorttassles" + +/datum/sprite_accessory/hair/supernova + name = "Supernova" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_supernova" + +/datum/sprite_accessory/hair/tribum + name = "Tri-bun" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_tribun" + +/datum/sprite_accessory/hair/twintail + name = "Twintails" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_twintail" + +/datum/sprite_accessory/hair/unkempt + name = "Unkempt" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_unkempt" + +/datum/sprite_accessory/hair/verylongtails + name = "Very Long Twintails" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_verylongtails" + +/datum/sprite_accessory/hair/vivi + name = "Vivi" + icon = 'modular_bandastation/hair/icons/human_face.dmi' + icon_state = "hair_vivi" diff --git a/modular_bandastation/hair/icons/human_face.dmi b/modular_bandastation/hair/icons/human_face.dmi new file mode 100644 index 00000000000000..4ef14ec04a80f7 Binary files /dev/null and b/modular_bandastation/hair/icons/human_face.dmi differ diff --git a/modular_bandastation/medical/_medical.dm b/modular_bandastation/medical/_medical.dm new file mode 100644 index 00000000000000..9c7c34e3e9ec70 --- /dev/null +++ b/modular_bandastation/medical/_medical.dm @@ -0,0 +1,4 @@ +/datum/modpack/medical + name = "Medical Extension" + desc = "Расширение медицинской системы" + author = "Svotin" diff --git a/modular_bandastation/medical/_medical.dme b/modular_bandastation/medical/_medical.dme new file mode 100644 index 00000000000000..3783e0393c8c7a --- /dev/null +++ b/modular_bandastation/medical/_medical.dme @@ -0,0 +1,3 @@ +#include "_medical.dm" + +#include "code/surgery/vocal_cords.dm" diff --git a/modular_bandastation/medical/code/surgery/vocal_cords.dm b/modular_bandastation/medical/code/surgery/vocal_cords.dm new file mode 100644 index 00000000000000..58a49bd9d90322 --- /dev/null +++ b/modular_bandastation/medical/code/surgery/vocal_cords.dm @@ -0,0 +1,51 @@ +/datum/surgery/vocal_cords + name = "Операция на голосовых связках" + possible_locs = list(BODY_ZONE_PRECISE_MOUTH) + steps = list( + /datum/surgery_step/incise, + /datum/surgery_step/retract_skin, + /datum/surgery_step/tune_vocal_cords, + /datum/surgery_step/close, + ) + +/datum/surgery_step/tune_vocal_cords + name = "настройка голосовых связок (гемостат)" + implements = list( + TOOL_HEMOSTAT = 100, + TOOL_WIRECUTTER = 50, + /obj/item/kitchen/fork = 35 + ) + preop_sound = 'sound/surgery/hemostat1.ogg' + time = 6.4 SECONDS + +/datum/surgery_step/tune_vocal_cords/preop(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + display_results( + user, + target, + span_notice("Вы начинаете настраивать голосовые связки [target]..."), + span_notice("[user] начинает настраивать голосовые связки [target]."), + span_notice("[user] начинает выполнять операцию на голосовых связках [target].") + ) + +/datum/surgery_step/tune_vocal_cords/success(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery, default_display_results = FALSE) + display_results( + user, + target, + span_notice("Вам удалось настроить голосовые связки [target]."), + span_notice("[user] успешно настраивает голосовые связки [target]!"), + span_notice("[user] завершает операцию на голосовых связках [target]."), + ) + target.change_tts_seed(user, TRUE) + return ..() + +/datum/surgery_step/tune_vocal_cords/failure(mob/user, mob/living/carbon/target, target_zone, obj/item/tool, datum/surgery/surgery) + display_results( + user, + target, + span_warning("Вы случайно вонзаете [tool] в горло [target]!"), + span_warning("[user] случайно вонзает [tool] в горло [target]!"), + span_warning("[user] случайно вонзает [tool] в горло [target]!"), + ) + display_pain(target, "Вы чувствуете острую колющую боль в горле!") + target.apply_damage(20, BRUTE, BODY_ZONE_HEAD, sharpness=TRUE) + return FALSE diff --git a/modular_bandastation/modular_bandastation.dme b/modular_bandastation/modular_bandastation.dme index cf404d7b81641f..c791b1a07def5a 100644 --- a/modular_bandastation/modular_bandastation.dme +++ b/modular_bandastation/modular_bandastation.dme @@ -5,6 +5,7 @@ #include "_helpers220/_helpers220.dme" #include "_signals220/_signals220.dme" #include "_singletons/_singletons.dme" +#include "admin/_admin.dme" #include "aesthetics/_aesthetics.dme" #include "automapper/_automapper.dme" #include "ai_laws/_ai_laws.dme" @@ -22,6 +23,7 @@ #include "keybinding/_keybinding.dme" #include "loadout/_loadout.dme" #include "mapping/_mapping.dme" +#include "medical/_medical.dme" #include "pixel_shift/_pixel_shift.dme" #include "ru_jobs/_ru_jobs.dme" #include "translations/_translations.dme" @@ -33,3 +35,4 @@ #include "species/_species.dme" #include "jukebox/_jukebox.dme" #include "objects/_objects.dme" +#include "hair/_hair.dme" diff --git a/modular_bandastation/objects/_objects.dme b/modular_bandastation/objects/_objects.dme index 5b175bcf4ff5fb..c7d19cdf83e165 100644 --- a/modular_bandastation/objects/_objects.dme +++ b/modular_bandastation/objects/_objects.dme @@ -4,4 +4,16 @@ #include "code/hampters.dm" #include "code/papershredder.dm" #include "code/material_pouch.dm" + #include "code/structures/posters.dm" + +#include "code/clothing/head/hat.dm" +#include "code/clothing/head/soft_caps.dm" +#include "code/clothing/suits/cloaks.dm" +#include "code/clothing/suits/jacket.dm" +#include "code/clothing/suits/wintercoats.dm" +#include "code/clothing/under/jobs/rnd.dm" + +#include "code/vending/vending.dm" + +#include "code/weapons/ranged/awaymission_gun.dm" diff --git a/modular_bandastation/objects/code/clothing/head/hat.dm b/modular_bandastation/objects/code/clothing/head/hat.dm new file mode 100644 index 00000000000000..6e054b75d32076 --- /dev/null +++ b/modular_bandastation/objects/code/clothing/head/hat.dm @@ -0,0 +1,7 @@ +/obj/item/clothing/head/cowboy/roboticist + name = "roboticist's cowboy hat" + desc = "Ковбойская шляпа с малиновой лентой, сочетающая стиль и функциональность. Отличный выбор для тех, кто хочет выделиться на космической станции. На бирке указано: 'Flameholdeir Industries'. Вам точно не хватает револьвера!" + icon = 'modular_bandastation/objects/icons/obj/clothing/head/cowboy.dmi' + worn_icon = 'modular_bandastation/objects/icons/mob/clothing/head/cowboy.dmi' + icon_state = "cowboy_robostics" + worn_icon_state = "cowboy_robostics" diff --git a/modular_bandastation/objects/code/clothing/head/soft_caps.dm b/modular_bandastation/objects/code/clothing/head/soft_caps.dm new file mode 100644 index 00000000000000..f059ccdccbf7f8 --- /dev/null +++ b/modular_bandastation/objects/code/clothing/head/soft_caps.dm @@ -0,0 +1,9 @@ +/obj/item/clothing/head/soft/roboticist_cap + icon = 'modular_bandastation/objects/icons/obj/clothing/head/hats.dmi' + worn_icon = 'modular_bandastation/objects/icons/mob/clothing/head/hats.dmi' + name = "roboticist's cap" + desc = "Элегантная кепка в черных тонах с малиновым козырьком. Идеально дополняет рабочую форму, добавляя стиль. На бирке указано: 'Flameholdeir Industries'. С этой кепкой вы точно никогда не опоздаете." + icon_state = "robocap" + soft_type = "robocap" + soft_suffix = null + dog_fashion = null diff --git a/modular_bandastation/objects/code/clothing/suits/cloaks.dm b/modular_bandastation/objects/code/clothing/suits/cloaks.dm new file mode 100644 index 00000000000000..69b6461b31804f --- /dev/null +++ b/modular_bandastation/objects/code/clothing/suits/cloaks.dm @@ -0,0 +1,18 @@ +/obj/item/clothing/suit/hooded/roboticist_cloak + name = "roboticist's coat" + desc = "Стильный плащ с принтом головы борга на спине. Идеален для тех, кто хочет выделиться и показать свою любовь к робототехнике. На бирке указано: 'Flameholdeir Industries'. Бережно обращайтесь с боргами, пока они не сделали из вас лампочку!" + icon_state = "robotics_coat" + icon = 'modular_bandastation/objects/icons/obj/clothing/suits/rnd.dmi' + worn_icon = 'modular_bandastation/objects/icons/mob/clothing/suits/rnd.dmi' + inhand_icon_state = null + body_parts_covered = CHEST|GROIN|ARMS + hoodtype = /obj/item/clothing/head/hooded/roboticist_cloak + +/obj/item/clothing/head/hooded/roboticist_cloak + name = "roboticist's hood" + icon = 'modular_bandastation/objects/icons/obj/clothing/head/rnd.dmi' + worn_icon = 'modular_bandastation/objects/icons/mob/clothing/head/rnd.dmi' + icon_state = "robotics_hood" + body_parts_covered = HEAD + flags_inv = HIDEHAIR|HIDEEARS + diff --git a/modular_bandastation/objects/code/clothing/suits/jacket.dm b/modular_bandastation/objects/code/clothing/suits/jacket.dm new file mode 100644 index 00000000000000..bdf49af42f51da --- /dev/null +++ b/modular_bandastation/objects/code/clothing/suits/jacket.dm @@ -0,0 +1,6 @@ +/obj/item/clothing/suit/toggle/jacket/roboticist + name = "roboticist's jacket" + desc = "Универсальная куртка из прочного материала, идеально подходит для работы с механическими деталями. Красные полосы на плечах добавляют стильный акцент. Теперь вы не только защищены, но и модны. На бирке указано: 'Flameholdeir Industries'. Будьте стильным, как Адский Бродяга!" + icon_state = "robotics_jacket" + icon = 'modular_bandastation/objects/icons/obj/clothing/suits/jacket.dmi' + worn_icon = 'modular_bandastation/objects/icons/mob/clothing/suits/jacket.dmi' diff --git a/modular_bandastation/objects/code/clothing/suits/wintercoats.dm b/modular_bandastation/objects/code/clothing/suits/wintercoats.dm new file mode 100644 index 00000000000000..19bce1d4d9a9c6 --- /dev/null +++ b/modular_bandastation/objects/code/clothing/suits/wintercoats.dm @@ -0,0 +1,11 @@ +/obj/item/clothing/suit/hooded/wintercoat/science/robotics/alt + name = "roboticist's winter coat" + desc = "Пальто, исключительно для разбирающихся в моде. Для крутых и подкрученных перцев. На бирке указано: 'Flameholdeir Industries'. Поможет даже во время самых длинных, холодных и тёмных времен." + icon_state = "coatrobotics" + icon = 'modular_bandastation/objects/icons/obj/clothing/suits/wintercoat.dmi' + worn_icon = 'modular_bandastation/objects/icons/mob/clothing/suits/wintercoat.dmi' + hoodtype = NONE + inhand_icon_state = null + +/obj/item/clothing/suit/hooded/wintercoat/science/robotics/alt/click_alt(mob/user) + return NONE // Restrict user to zip and unzip coat diff --git a/modular_bandastation/objects/code/clothing/under/jobs/rnd.dm b/modular_bandastation/objects/code/clothing/under/jobs/rnd.dm new file mode 100644 index 00000000000000..efb78170e4255d --- /dev/null +++ b/modular_bandastation/objects/code/clothing/under/jobs/rnd.dm @@ -0,0 +1,35 @@ +/obj/item/clothing/under/rank/rnd/roboticist/alt + name = "standart roboticist jumpsuit" + desc = "Комбинезон робототехника нового образца. Ничего выдающегося, кроме качественного материала. На бирке указано: 'Flameholdeir Industries'. Эстетика в простоте - будьте как Сенатор!" + icon_state = "robotics_alt" + icon = 'modular_bandastation/objects/icons/obj/clothing/under/rnd.dmi' + worn_icon = 'modular_bandastation/objects/icons/mob/clothing/under/rnd.dmi' + +/obj/item/clothing/under/rank/rnd/roboticist/alt/red + name = "red roboticist's jumpsuit" + desc = "Прочный рабочий комбинезон из высококачественных материалов, обеспечивающий защиту и комфорт. Красный свитер из кашемира, мягкий на ощупь. Да, мы тоже думаем, что золотые заклёпки - это огонь. На бирке указано: 'Flameholdeir Industries'. Теперь вы готовы починить всех боргов, как парень с монтировкой, который спасает мир!" + icon_state = "robotics_red" + can_adjust = FALSE + +/obj/item/clothing/under/rank/rnd/roboticist/alt/hoodie + name = "roboticist's hoodie" + desc = "Худи и джоггеры, идущие как единый комбинезон, пояс сделанный из крашенной кожи и золотой пряжки. Выполнены из мягкого и прочного материала, обеспечивая комфорт и свободу движений. Теперь даже борги будут завидовать вашему стилю. На бирке указано: 'Flameholdeir Industries'. В этом костюме вы можете прыгать по крышам, как паркурист-доставщик!" + icon_state = "robotics_hoodie" + body_parts_covered = CHEST|GROIN|ARMS + can_adjust = FALSE + +/obj/item/clothing/under/rank/rnd/roboticist/alt/skirt + name = "standart roboticist's jumpskirt" + desc = "Комбинезон робототехника нового образца с юбкой. Ничего выдающегося, кроме качественного материала. На бирке указано: 'Flameholdeir Industries'. Эстетика в простоте - а кстати, а где моя катана?" + icon_state = "robotics_skirt_alt" + body_parts_covered = CHEST|GROIN|ARMS + dying_key = DYE_REGISTRY_JUMPSKIRT + female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY + supports_variations_flags = CLOTHING_DIGITIGRADE_VARIATION_NO_NEW_ICON + +/obj/item/clothing/under/rank/rnd/roboticist/alt/skirt/red + name = "red roboticist's jumpskirt" + desc = "Прочный рабочий комбинезон из высококачественных материалов, обеспечивающий защиту и комфорт. Красный свитер из кашемира, мягкий на ощупь. Да, мы тоже думаем, что золотые заклёпки - это огонь. На бирке указано: 'Flameholdeir Industries'. Вы сможете заменять протезы рук ВЕЧНОСТЬ и со стилем!" + icon_state = "robotics_skirt_red" + female_sprite_flags = FEMALE_UNIFORM_TOP_ONLY + can_adjust = FALSE diff --git a/modular_bandastation/objects/code/vending/vending.dm b/modular_bandastation/objects/code/vending/vending.dm new file mode 100644 index 00000000000000..3c692d95e632fe --- /dev/null +++ b/modular_bandastation/objects/code/vending/vending.dm @@ -0,0 +1,20 @@ +/obj/machinery/vending/wardrobe/robo_wardrobe + icon = 'modular_bandastation/objects/icons/obj/machines/vending.dmi' + icon_state = "robodrobe" + light_mask = null + +/obj/machinery/vending/wardrobe/robo_wardrobe/build_inventories(start_empty) + products |= list( + /obj/item/clothing/head/beret = 2, + /obj/item/clothing/head/cowboy/roboticist = 2, + /obj/item/clothing/head/soft/roboticist_cap = 2, + /obj/item/clothing/suit/hooded/roboticist_cloak = 2, + /obj/item/clothing/suit/toggle/jacket/roboticist = 2, + /obj/item/clothing/suit/hooded/wintercoat/science/robotics/alt = 2, + /obj/item/clothing/under/rank/rnd/roboticist/alt = 2, + /obj/item/clothing/under/rank/rnd/roboticist/alt/red = 2, + /obj/item/clothing/under/rank/rnd/roboticist/alt/hoodie = 2, + /obj/item/clothing/under/rank/rnd/roboticist/alt/skirt = 2, + /obj/item/clothing/under/rank/rnd/roboticist/alt/skirt/red = 2, + ) + . = ..() diff --git a/modular_bandastation/objects/code/weapons/ranged/awaymission_gun.dm b/modular_bandastation/objects/code/weapons/ranged/awaymission_gun.dm new file mode 100644 index 00000000000000..ca33dfdde926a8 --- /dev/null +++ b/modular_bandastation/objects/code/weapons/ranged/awaymission_gun.dm @@ -0,0 +1,110 @@ +/obj/item/gun/energy/laser/awaymission_aeg + name = "Exploreverse Mk.I" + desc = "Прототип оружия с миниатюрным реактором для исследований в крайне отдаленных секторах. \ + \n Данная модель использует экспериментальную систему обратного восполнения, работающую на принципе огромной аккумуляции энергии, но крайне уязвимую к радиопомехам, которыми кишит сектор станции, попростую не работая там." + icon = 'modular_bandastation/objects/icons/guns.dmi' + lefthand_file = 'modular_bandastation/objects/icons/inhands/guns_lefthand.dmi' + righthand_file = 'modular_bandastation/objects/icons/inhands/guns_righthand.dmi' + icon_state = "laser_gate" + inhand_icon_state = "laser_gate" + ammo_type = list(/obj/item/ammo_casing/energy/lasergun/awaymission_aeg) + can_select = FALSE + selfcharge = TRUE + ammo_x_offset = 0 + can_charge = FALSE + +/obj/item/ammo_casing/energy/lasergun/awaymission_aeg + e_cost = LASER_SHOTS(20, STANDARD_CELL_CHARGE) + +/obj/item/gun/energy/laser/awaymission_aeg/Initialize(mapload) + . = ..() + RegisterSignal(src, COMSIG_MOVABLE_Z_CHANGED, PROC_REF(check_z)) + check_z() + +/obj/item/gun/energy/laser/awaymission_aeg/proc/check_z() + SIGNAL_HANDLER + + if(onAwayMission()) + selfcharge = TRUE + if(ismob(loc)) + to_chat(loc, span_notice("[src.name] активируется, начиная аккумулировать энергию из материи сущего.")) + else + selfcharge = FALSE + cell.change(-STANDARD_BATTERY_CHARGE) + update_appearance() + if(ismob(loc)) + to_chat(loc, span_danger("[src.name] деактивируется, так как он подавляется системами станции.")) + recharge_newshot(no_cyborg_drain = TRUE) + +/obj/item/gun/energy/laser/awaymission_aeg/mk2 + name = "Exploreverse Mk.II" + desc = "Второй прототип оружия с миниатюрным реактором и забавным рычагом для исследований в крайне отдаленных секторах. \ + \nДанная модель оснащена системой ручного восполнения энергии \"Za.E.-8 A.L'sya\", \ + позволяющей в короткие сроки восполнить необходимую электроэнергию с помощью ручного труда и конвертации личной энергии подключенного к системе зарядки. \ + \nТеперь еще более нелепый дизайн с торчащими проводами!" + icon_state = "laser_gate_mk2" + +/obj/item/gun/energy/laser/awaymission_aeg/mk2/attack_self(mob/living/user) + . = ..() + if(!onAwayMission()) + user.balloon_alert(user, "не в гейте!") + return FALSE + + if(cell.charge >= cell.maxcharge) + user.balloon_alert(user, "полностью заряжен!") + return FALSE + + if(user.nutrition <= NUTRITION_LEVEL_STARVING) + user.balloon_alert(user, "недостаточно сил!") + return FALSE + + user.balloon_alert(user, "зарядка...") + playsound(src, 'sound/effects/sparks3.ogg', 10, 1) + do_sparks(1, 1, src) + + if(!do_after(user, 3 SECONDS, target = src)) + return + cell.give(STANDARD_CELL_CHARGE * 0.1) + user.adjust_nutrition(-10) + +/datum/design/exploreverse_mk1 + name = "Exploreverse Mk.I" + desc = "Энергетическое оружие с экспериментальным миниатюрным реактором. Работает только во вратах." + id = "exploreverse_mk1" + build_type = PROTOLATHE | AWAY_LATHE + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 3, + /datum/material/glass = SHEET_MATERIAL_AMOUNT * 0.75, + /datum/material/uranium = SHEET_MATERIAL_AMOUNT * 0.75, + /datum/material/titanium = SHEET_MATERIAL_AMOUNT * 0.25 + ) + build_path = /obj/item/gun/energy/laser/awaymission_aeg + category = list( + RND_CATEGORY_WEAPONS + RND_SUBCATEGORY_WEAPONS_RANGED, + ) + departmental_flags = DEPARTMENT_BITFLAG_CARGO | DEPARTMENT_BITFLAG_SCIENCE +/datum/design/exploreverse_mk2 + name = "Exploreverse Mk.II" + desc = "Энергетическое оружие с экспериментальным миниатюрным реактором и рычагом для ручной зарядки. Работает только во вратах." + id = "exploreverse_mk2" + build_type = PROTOLATHE | AWAY_LATHE + materials = list( + /datum/material/iron = SHEET_MATERIAL_AMOUNT * 4, + /datum/material/glass = SHEET_MATERIAL_AMOUNT, + /datum/material/uranium = SHEET_MATERIAL_AMOUNT, + /datum/material/titanium = SHEET_MATERIAL_AMOUNT * 0.25, + /datum/material/silver = SHEET_MATERIAL_AMOUNT * 0.5 + ) + build_path = /obj/item/gun/energy/laser/awaymission_aeg/mk2 + category = list( + RND_CATEGORY_WEAPONS + RND_SUBCATEGORY_WEAPONS_RANGED, + ) + departmental_flags = DEPARTMENT_BITFLAG_CARGO | DEPARTMENT_BITFLAG_SCIENCE + +/datum/techweb_node/mining/New() + . = ..() + design_ids |= "exploreverse_mk1" + +/datum/techweb_node/plasma_mining/New() + . = ..() + design_ids |= "exploreverse_mk2" diff --git a/modular_bandastation/objects/icons/guns.dmi b/modular_bandastation/objects/icons/guns.dmi new file mode 100644 index 00000000000000..0365ecc759077e Binary files /dev/null and b/modular_bandastation/objects/icons/guns.dmi differ diff --git a/modular_bandastation/objects/icons/inhands/guns_lefthand.dmi b/modular_bandastation/objects/icons/inhands/guns_lefthand.dmi new file mode 100644 index 00000000000000..72d893f8a21ca5 Binary files /dev/null and b/modular_bandastation/objects/icons/inhands/guns_lefthand.dmi differ diff --git a/modular_bandastation/objects/icons/inhands/guns_righthand.dmi b/modular_bandastation/objects/icons/inhands/guns_righthand.dmi new file mode 100644 index 00000000000000..4941c0dbb30f4c Binary files /dev/null and b/modular_bandastation/objects/icons/inhands/guns_righthand.dmi differ diff --git a/modular_bandastation/objects/icons/mob/clothing/head/cowboy.dmi b/modular_bandastation/objects/icons/mob/clothing/head/cowboy.dmi new file mode 100644 index 00000000000000..abd9de1e38b8dd Binary files /dev/null and b/modular_bandastation/objects/icons/mob/clothing/head/cowboy.dmi differ diff --git a/modular_bandastation/objects/icons/mob/clothing/head/hats.dmi b/modular_bandastation/objects/icons/mob/clothing/head/hats.dmi new file mode 100644 index 00000000000000..abfda90672ff85 Binary files /dev/null and b/modular_bandastation/objects/icons/mob/clothing/head/hats.dmi differ diff --git a/modular_bandastation/objects/icons/mob/clothing/head/rnd.dmi b/modular_bandastation/objects/icons/mob/clothing/head/rnd.dmi new file mode 100644 index 00000000000000..2ce9786bd25b0a Binary files /dev/null and b/modular_bandastation/objects/icons/mob/clothing/head/rnd.dmi differ diff --git a/modular_bandastation/objects/icons/mob/clothing/suits/jacket.dmi b/modular_bandastation/objects/icons/mob/clothing/suits/jacket.dmi new file mode 100644 index 00000000000000..0c0fe7fea6ba8a Binary files /dev/null and b/modular_bandastation/objects/icons/mob/clothing/suits/jacket.dmi differ diff --git a/modular_bandastation/objects/icons/mob/clothing/suits/rnd.dmi b/modular_bandastation/objects/icons/mob/clothing/suits/rnd.dmi new file mode 100644 index 00000000000000..5c11f632600598 Binary files /dev/null and b/modular_bandastation/objects/icons/mob/clothing/suits/rnd.dmi differ diff --git a/modular_bandastation/objects/icons/mob/clothing/suits/wintercoat.dmi b/modular_bandastation/objects/icons/mob/clothing/suits/wintercoat.dmi new file mode 100644 index 00000000000000..e718ebd1af9b03 Binary files /dev/null and b/modular_bandastation/objects/icons/mob/clothing/suits/wintercoat.dmi differ diff --git a/modular_bandastation/objects/icons/mob/clothing/under/rnd.dmi b/modular_bandastation/objects/icons/mob/clothing/under/rnd.dmi new file mode 100644 index 00000000000000..21f2e5d9c38892 Binary files /dev/null and b/modular_bandastation/objects/icons/mob/clothing/under/rnd.dmi differ diff --git a/modular_bandastation/objects/icons/obj/clothing/head/cowboy.dmi b/modular_bandastation/objects/icons/obj/clothing/head/cowboy.dmi new file mode 100644 index 00000000000000..3e96432304ad54 Binary files /dev/null and b/modular_bandastation/objects/icons/obj/clothing/head/cowboy.dmi differ diff --git a/modular_bandastation/objects/icons/obj/clothing/head/hats.dmi b/modular_bandastation/objects/icons/obj/clothing/head/hats.dmi new file mode 100644 index 00000000000000..3d11ac3a2bdecb Binary files /dev/null and b/modular_bandastation/objects/icons/obj/clothing/head/hats.dmi differ diff --git a/modular_bandastation/objects/icons/obj/clothing/head/rnd.dmi b/modular_bandastation/objects/icons/obj/clothing/head/rnd.dmi new file mode 100644 index 00000000000000..26182c2da7ebc0 Binary files /dev/null and b/modular_bandastation/objects/icons/obj/clothing/head/rnd.dmi differ diff --git a/modular_bandastation/objects/icons/obj/clothing/suits/jacket.dmi b/modular_bandastation/objects/icons/obj/clothing/suits/jacket.dmi new file mode 100644 index 00000000000000..ebbb532fc6e38b Binary files /dev/null and b/modular_bandastation/objects/icons/obj/clothing/suits/jacket.dmi differ diff --git a/modular_bandastation/objects/icons/obj/clothing/suits/rnd.dmi b/modular_bandastation/objects/icons/obj/clothing/suits/rnd.dmi new file mode 100644 index 00000000000000..160c1632959924 Binary files /dev/null and b/modular_bandastation/objects/icons/obj/clothing/suits/rnd.dmi differ diff --git a/modular_bandastation/objects/icons/obj/clothing/suits/wintercoat.dmi b/modular_bandastation/objects/icons/obj/clothing/suits/wintercoat.dmi new file mode 100644 index 00000000000000..0433e69c0b86e2 Binary files /dev/null and b/modular_bandastation/objects/icons/obj/clothing/suits/wintercoat.dmi differ diff --git a/modular_bandastation/objects/icons/obj/clothing/under/rnd.dmi b/modular_bandastation/objects/icons/obj/clothing/under/rnd.dmi new file mode 100644 index 00000000000000..787174add15876 Binary files /dev/null and b/modular_bandastation/objects/icons/obj/clothing/under/rnd.dmi differ diff --git a/modular_bandastation/objects/icons/obj/machines/vending.dmi b/modular_bandastation/objects/icons/obj/machines/vending.dmi new file mode 100644 index 00000000000000..e4d8d37dc467d3 Binary files /dev/null and b/modular_bandastation/objects/icons/obj/machines/vending.dmi differ diff --git a/sound/ambience/ambimaint10.ogg b/sound/ambience/ambimaint10.ogg new file mode 100644 index 00000000000000..975aae32bff544 Binary files /dev/null and b/sound/ambience/ambimaint10.ogg differ diff --git a/sound/ambience/ambimaint11.ogg b/sound/ambience/ambimaint11.ogg new file mode 100644 index 00000000000000..2723c6008eb3b4 Binary files /dev/null and b/sound/ambience/ambimaint11.ogg differ diff --git a/sound/ambience/ambimaint12.ogg b/sound/ambience/ambimaint12.ogg new file mode 100644 index 00000000000000..2c873e0f5f9966 Binary files /dev/null and b/sound/ambience/ambimaint12.ogg differ diff --git a/sound/ambience/ambimaint8.ogg b/sound/ambience/ambimaint8.ogg new file mode 100644 index 00000000000000..582ec800cbc459 Binary files /dev/null and b/sound/ambience/ambimaint8.ogg differ diff --git a/sound/ambience/ambimaint9.ogg b/sound/ambience/ambimaint9.ogg new file mode 100644 index 00000000000000..c990f954e5f6a2 Binary files /dev/null and b/sound/ambience/ambimaint9.ogg differ diff --git a/sound/ambience/antag/attribution.txt b/sound/ambience/antag/attribution.txt index 6390dd525c4599..8db2b1b8ec2eb1 100644 --- a/sound/ambience/antag/attribution.txt +++ b/sound/ambience/antag/attribution.txt @@ -1,3 +1,11 @@ sound/ambience/antag/abductee.ogg is from "Warp SFX" https://freesound.org/people/Breviceps/sounds/453391 (CC0) sound/ambience/antag/brainwash.ogg is from "nog.wav" https://freesound.org/people/_NOMINAL_/sounds/124602 (CC-BY 3.0) -sound/ambience/antag/hypnosis.ogg is from "Flashback.wav" https://freesound.org/people/Sclolex/sounds/342103 (CC0) \ No newline at end of file +sound/ambience/antag/hypnosis.ogg is from "Flashback.wav" https://freesound.org/people/Sclolex/sounds/342103 (CC0) + +{ +ambimaint8.ogg +ambimaint9.ogg +ambimaint10.ogg +ambimaint11.ogg +ambimaint12.ogg +} made by Kayozz , license: CC-by-SA \ No newline at end of file diff --git a/sound/items/attributions.txt b/sound/items/attributions.txt index 31b573c1058933..9ad1a09d8cb419 100644 --- a/sound/items/attributions.txt +++ b/sound/items/attributions.txt @@ -5,7 +5,7 @@ cig_snuff.ogg lighter_on.ogg lighter_off.ogg zippo_onn.ogg -zippo_off.ogg +zippo_off.ogg } - Taken from https://github.com/BeeStation/BeeStation-Hornet/pull/29 pen_click.ogg from https://freesound.org/people/LexzachGames/sounds/431492/ , license: CC0 @@ -13,7 +13,7 @@ pen_click.ogg from https://freesound.org/people/LexzachGames/sounds/431492/ , li night_vision_on.ogg by Syna-Max -- https://freesound.org/s/60345/ -- License: Attribution NonCommercial 4.0 { -metal_drop.ogg - https://freesound.org/people/13FPanská_Tolar_David/sounds/378682/ , License: CC0 +metal_drop.ogg - https://freesound.org/people/Robinhood76/sounds/85418/ , License: CC BY-NC 4.0 metal_pick_up.ogg - https://freesound.org/people/Hotlavaman/sounds/108673/ , License: CC0 glass_drop.ogg - https://freesound.org/people/Hotlavaman/sounds/108673/ , License: CC0 glass_pick_up.ogg - https://freesound.org/people/tcrocker68/sounds/235602/ , License: CC0 @@ -22,4 +22,37 @@ wood_drop.ogg - https://freesound.org/people/cjosephwalker/sounds/94859/ , Licen irod_rod_pick_up.ogg - https://freesound.org/people/lostphosphene/sounds/258265/ , License: CC BY 4.0 plastic_pick_up.ogg - https://freesound.org/people/Jessica190091/sounds/491304/ , License: CC BY 4.0 plastic_drop.ogg - https://freesound.org/people/martian/sounds/338854/ , License: CC0 -} - edited by sadboysuss \ No newline at end of file +} - edited by sadboysuss + +{ +gun_drop.ogg - FN FAL Rifle Load and Cock 01.mp3 by PNMCarrieRailfan -- https://freesound.org/s/682029/ -- License: Attribution NonCommercial 4.0 +gun_pick_up.ogg - FN FAL Rifle Unload and Cock.mp3 by PNMCarrieRailfan -- https://freesound.org/s/682031/ -- License: Attribution NonCommercial 4.0 +handcuffs_drop.ogg - handcuffs.ogg by kimuracarter -- https://freesound.org/s/528749/ -- License: Attribution 3.0 +handcuffs_pick_up.ogg - handcuffs.ogg by kimuracarter -- https://freesound.org/s/528749/ -- License: Attribution 3.0 +plastic_shield_drop.ogg - made by sadboysuss -- License: CC-by-SA +plastic_shield_pick_up.ogg - made by sadboysuss -- License: CC-by-SA +stun_baton_drop.ogg - Fn P90 Submachine Gun 5.7Mm. Mechan; Empty Mag Inserted Into And Pulled Out Slow And Various 02 by PNMCarrieRailfan -- https://freesound.org/s/682041/ -- License: Attribution NonCommercial 4.0 +stun_baton_pick_up.ogg - Fn P90 Submachine Gun 5.7Mm. Mechan; Empty Mag Inserted Into And Pulled Out Slow And Various 02 by PNMCarrieRailfan -- https://freesound.org/s/682041/ -- License: Attribution NonCommercial 4.0 +pepper_spray_drop.ogg - Spray Paint Shake Slow Five.wav by cbakos -- https://freesound.org/s/200376/ -- License: Creative Commons 0 +pepper_spray_pick_up.ogg - Spray Paint Shake Slow Five.wav by cbakos -- https://freesound.org/s/200376/ -- License: Creative Commons 0 +grenade_drop.ogg - made by sadboysuss -- License: CC-by-SA +grenade_pick_up.ogg - made by sadboysuss -- License: CC-by-SA +} - edited by sadboysuss + +{ +skin_drop.ogg - https://freesound.org/people/Crinkem/sounds/501015/ , License: CC4 +skin_pick_up.ogg - https://freesound.org/people/Crinkem/sounds/501015/ , License CC3 +cardboard_drop and cardboard_pick_up - https://freesound.org/people/newagesoup/sounds/364736/ , License CC0 +} + +{ + medkit_open.ogg - https://freesound.org/people/Jandre160108/sounds/365866/ , License: CC BY-NC 4.0 + medkit_drop.ogg - https://freesound.org/people/Jandre160108/sounds/365866/ , License: CC BY-NC 4.0 + medkit_pick_up.ogg - https://freesound.org/people/blouhond/sounds/440710/ , License: CC BY 4.0 +} - edited by sadboysuss + +{ +gas_tank_drop.ogg +gas_tank_pick_up.ogg +} - https://freesound.org/people/Globofonia/sounds/698346/ , License CC0 +edited by grungussuss diff --git a/sound/items/cardboard_drop.ogg b/sound/items/cardboard_drop.ogg new file mode 100644 index 00000000000000..c1082f2e37d7dc Binary files /dev/null and b/sound/items/cardboard_drop.ogg differ diff --git a/sound/items/cardboard_pick_up.ogg b/sound/items/cardboard_pick_up.ogg new file mode 100644 index 00000000000000..a363c587b375bc Binary files /dev/null and b/sound/items/cardboard_pick_up.ogg differ diff --git a/sound/items/gas_tank_drop.ogg b/sound/items/gas_tank_drop.ogg new file mode 100644 index 00000000000000..e102cb4fe8aad0 Binary files /dev/null and b/sound/items/gas_tank_drop.ogg differ diff --git a/sound/items/gas_tank_pick_up.ogg b/sound/items/gas_tank_pick_up.ogg new file mode 100644 index 00000000000000..41c83645da6094 Binary files /dev/null and b/sound/items/gas_tank_pick_up.ogg differ diff --git a/sound/items/grenade_drop.ogg b/sound/items/grenade_drop.ogg new file mode 100644 index 00000000000000..04627811cd1886 Binary files /dev/null and b/sound/items/grenade_drop.ogg differ diff --git a/sound/items/grenade_pick_up.ogg b/sound/items/grenade_pick_up.ogg new file mode 100644 index 00000000000000..d257659f76182a Binary files /dev/null and b/sound/items/grenade_pick_up.ogg differ diff --git a/sound/items/gun_drop.ogg b/sound/items/gun_drop.ogg new file mode 100644 index 00000000000000..21b83bc91d6115 Binary files /dev/null and b/sound/items/gun_drop.ogg differ diff --git a/sound/items/gun_pick_up.ogg b/sound/items/gun_pick_up.ogg new file mode 100644 index 00000000000000..6bf6b45a16b260 Binary files /dev/null and b/sound/items/gun_pick_up.ogg differ diff --git a/sound/items/handcuff_finish.ogg b/sound/items/handcuff_finish.ogg new file mode 100644 index 00000000000000..92096837835feb Binary files /dev/null and b/sound/items/handcuff_finish.ogg differ diff --git a/sound/items/handcuffs_drop.ogg b/sound/items/handcuffs_drop.ogg new file mode 100644 index 00000000000000..85b7f172e4852f Binary files /dev/null and b/sound/items/handcuffs_drop.ogg differ diff --git a/sound/items/handcuffs_pick_up.ogg b/sound/items/handcuffs_pick_up.ogg new file mode 100644 index 00000000000000..d3fdc3450bd473 Binary files /dev/null and b/sound/items/handcuffs_pick_up.ogg differ diff --git a/sound/items/holster.ogg b/sound/items/holster.ogg new file mode 100644 index 00000000000000..984e7ad4fea38b Binary files /dev/null and b/sound/items/holster.ogg differ diff --git a/sound/items/medkit_drop.ogg b/sound/items/medkit_drop.ogg new file mode 100644 index 00000000000000..227d4a8beb2202 Binary files /dev/null and b/sound/items/medkit_drop.ogg differ diff --git a/sound/items/medkit_open.ogg b/sound/items/medkit_open.ogg new file mode 100644 index 00000000000000..63307783d2f776 Binary files /dev/null and b/sound/items/medkit_open.ogg differ diff --git a/sound/items/medkit_pick_up.ogg b/sound/items/medkit_pick_up.ogg new file mode 100644 index 00000000000000..e13c6848e44dfc Binary files /dev/null and b/sound/items/medkit_pick_up.ogg differ diff --git a/sound/items/metal_drop.ogg b/sound/items/metal_drop.ogg index 48460e8cd37bfe..46488dca29fd32 100644 Binary files a/sound/items/metal_drop.ogg and b/sound/items/metal_drop.ogg differ diff --git a/sound/items/pepper_spray_drop.ogg b/sound/items/pepper_spray_drop.ogg new file mode 100644 index 00000000000000..e071c65d3bce4c Binary files /dev/null and b/sound/items/pepper_spray_drop.ogg differ diff --git a/sound/items/pepper_spray_pick_up.ogg b/sound/items/pepper_spray_pick_up.ogg new file mode 100644 index 00000000000000..a474bbd91b3c77 Binary files /dev/null and b/sound/items/pepper_spray_pick_up.ogg differ diff --git a/sound/items/plastic_shield_drop.ogg b/sound/items/plastic_shield_drop.ogg new file mode 100644 index 00000000000000..4d07b48d481fb0 Binary files /dev/null and b/sound/items/plastic_shield_drop.ogg differ diff --git a/sound/items/plastic_shield_pick_up.ogg b/sound/items/plastic_shield_pick_up.ogg new file mode 100644 index 00000000000000..e18e9617b77ded Binary files /dev/null and b/sound/items/plastic_shield_pick_up.ogg differ diff --git a/sound/items/skin_drop.ogg b/sound/items/skin_drop.ogg new file mode 100644 index 00000000000000..effdd83392bee3 Binary files /dev/null and b/sound/items/skin_drop.ogg differ diff --git a/sound/items/skin_pick_up.ogg b/sound/items/skin_pick_up.ogg new file mode 100644 index 00000000000000..9edf326cd9ef30 Binary files /dev/null and b/sound/items/skin_pick_up.ogg differ diff --git a/sound/items/stun_baton_drop.ogg b/sound/items/stun_baton_drop.ogg new file mode 100644 index 00000000000000..1d5d59e9012bad Binary files /dev/null and b/sound/items/stun_baton_drop.ogg differ diff --git a/sound/items/stun_baton_pick_up.ogg b/sound/items/stun_baton_pick_up.ogg new file mode 100644 index 00000000000000..6b87e531fc43ee Binary files /dev/null and b/sound/items/stun_baton_pick_up.ogg differ diff --git a/sound/misc/license.txt b/sound/misc/license.txt index 69ef29928202ce..761a031d190813 100644 --- a/sound/misc/license.txt +++ b/sound/misc/license.txt @@ -5,4 +5,13 @@ knuckles.ogg by CGEffex. Shortened and cut. https://freesound.org/people/CGEffex/sounds/93981/ airraid.ogg by Jwade722. Shortened and cut. -https://freesound.org/people/Jwade722/sounds/534550/ \ No newline at end of file +https://freesound.org/people/Jwade722/sounds/534550/ + +radio_talk.ogg by cs2975871. Shortened and cut. +https://freesound.org/people/cs2975871/sounds/514185/ + +radio_important.ogg by morganpurkis. +https://freesound.org/people/morganpurkis/sounds/392972/ + +radio_receive.ogg by JovianSounds. Shortened and cut. +https://freesound.org/people/JovianSounds/sounds/524205/ \ No newline at end of file diff --git a/sound/misc/radio_important.ogg b/sound/misc/radio_important.ogg new file mode 100644 index 00000000000000..bb6f769d6129b4 Binary files /dev/null and b/sound/misc/radio_important.ogg differ diff --git a/sound/misc/radio_receive.ogg b/sound/misc/radio_receive.ogg new file mode 100644 index 00000000000000..6b2ee1ba4ef08a Binary files /dev/null and b/sound/misc/radio_receive.ogg differ diff --git a/sound/misc/radio_talk.ogg b/sound/misc/radio_talk.ogg new file mode 100644 index 00000000000000..50d14c897a0efb Binary files /dev/null and b/sound/misc/radio_talk.ogg differ diff --git a/sound/voice/credits.txt b/sound/voice/attribution.txt similarity index 61% rename from sound/voice/credits.txt rename to sound/voice/attribution.txt index b54e6ad5319669..7bfe5c4a9ce146 100644 --- a/sound/voice/credits.txt +++ b/sound/voice/attribution.txt @@ -3,3 +3,10 @@ borg_deathsound.ogg is spliced from two clips, both of which are under the CC At all complianator sounds are licensed under CC-BY-SA by Michael Haugh (supermichael) The male sharp gasps in /sound/voice/human/ are from https://freesound.org/people/bacruz666/sounds/341908/ and https://freesound.org/people/nettoi/sounds/677540/, the female sharp gasps are from https://freesound.org/people/drotzruhn/sounds/405203/ + +{ +human/male_sniff.ogg - https://freesound.org/people/Fluffayfish/sounds/327799/ , License: CC BY-NC 3.0 +human/male_sigh.ogg - https://freesound.org/people/giddster/sounds/336540/ , License: CC0 +human/female_sniff.ogg - https://freesound.org/people/SpliceSound/sounds/218307/ , License: CC0 +human/female_sigh.ogg - https://freesound.org/people/biawinter/sounds/408090/ , License: CC BY-NC 4.0 +} modified by grungussuss \ No newline at end of file diff --git a/sound/voice/human/female_sigh.ogg b/sound/voice/human/female_sigh.ogg new file mode 100644 index 00000000000000..3c338a868baf5b Binary files /dev/null and b/sound/voice/human/female_sigh.ogg differ diff --git a/sound/voice/human/female_sniff.ogg b/sound/voice/human/female_sniff.ogg new file mode 100644 index 00000000000000..edc75248790de0 Binary files /dev/null and b/sound/voice/human/female_sniff.ogg differ diff --git a/sound/voice/human/male_sigh.ogg b/sound/voice/human/male_sigh.ogg new file mode 100644 index 00000000000000..ec61683d68e938 Binary files /dev/null and b/sound/voice/human/male_sigh.ogg differ diff --git a/sound/voice/human/male_sniff.ogg b/sound/voice/human/male_sniff.ogg new file mode 100644 index 00000000000000..b940505c97a8ab Binary files /dev/null and b/sound/voice/human/male_sniff.ogg differ diff --git a/sound/weapons/gun/smartgun/smartgun_shoot_1.ogg b/sound/weapons/gun/smartgun/smartgun_shoot_1.ogg new file mode 100644 index 00000000000000..5d567b7fca6c0b Binary files /dev/null and b/sound/weapons/gun/smartgun/smartgun_shoot_1.ogg differ diff --git a/sound/weapons/gun/smartgun/smartgun_shoot_2.ogg b/sound/weapons/gun/smartgun/smartgun_shoot_2.ogg new file mode 100644 index 00000000000000..9891482865c662 Binary files /dev/null and b/sound/weapons/gun/smartgun/smartgun_shoot_2.ogg differ diff --git a/sound/weapons/gun/smartgun/smartgun_shoot_3.ogg b/sound/weapons/gun/smartgun/smartgun_shoot_3.ogg new file mode 100644 index 00000000000000..89eb9fcc989c4a Binary files /dev/null and b/sound/weapons/gun/smartgun/smartgun_shoot_3.ogg differ diff --git a/tgstation.dme b/tgstation.dme index 36c69ba485137f..f80c5652d8048f 100644 --- a/tgstation.dme +++ b/tgstation.dme @@ -51,7 +51,6 @@ #include "code\__DEFINES\basic_mobs.dm" #include "code\__DEFINES\basketball.dm" #include "code\__DEFINES\bitrunning.dm" -#include "code\__DEFINES\blackmarket.dm" #include "code\__DEFINES\blend_modes.dm" #include "code\__DEFINES\blob_defines.dm" #include "code\__DEFINES\blood.dm" @@ -139,6 +138,7 @@ #include "code\__DEFINES\map_switch.dm" #include "code\__DEFINES\mapping.dm" #include "code\__DEFINES\maps.dm" +#include "code\__DEFINES\market.dm" #include "code\__DEFINES\maths.dm" #include "code\__DEFINES\matrices.dm" #include "code\__DEFINES\MC.dm" @@ -302,7 +302,6 @@ #include "code\__DEFINES\dcs\signals\signals_backpack.dm" #include "code\__DEFINES\dcs\signals\signals_beam.dm" #include "code\__DEFINES\dcs\signals\signals_bitrunning.dm" -#include "code\__DEFINES\dcs\signals\signals_blackmarket.dm" #include "code\__DEFINES\dcs\signals\signals_blob.dm" #include "code\__DEFINES\dcs\signals\signals_bot.dm" #include "code\__DEFINES\dcs\signals\signals_camera.dm" @@ -332,6 +331,7 @@ #include "code\__DEFINES\dcs\signals\signals_leash.dm" #include "code\__DEFINES\dcs\signals\signals_lift.dm" #include "code\__DEFINES\dcs\signals\signals_light_eater.dm" +#include "code\__DEFINES\dcs\signals\signals_market.dm" #include "code\__DEFINES\dcs\signals\signals_material_container.dm" #include "code\__DEFINES\dcs\signals\signals_medical.dm" #include "code\__DEFINES\dcs\signals\signals_mind.dm" @@ -397,6 +397,7 @@ #include "code\__DEFINES\traits\macros.dm" #include "code\__DEFINES\traits\sources.dm" #include "code\__HELPERS\_auxtools_api.dm" +#include "code\__HELPERS\_dreamluau.dm" #include "code\__HELPERS\_lists.dm" #include "code\__HELPERS\_planes.dm" #include "code\__HELPERS\_string_lists.dm" @@ -633,7 +634,6 @@ #include "code\controllers\subsystem\ban_cache.dm" #include "code\controllers\subsystem\bitrunning.dm" #include "code\controllers\subsystem\blackbox.dm" -#include "code\controllers\subsystem\blackmarket.dm" #include "code\controllers\subsystem\chat.dm" #include "code\controllers\subsystem\circuit_component.dm" #include "code\controllers\subsystem\dbcore.dm" @@ -658,6 +658,7 @@ #include "code\controllers\subsystem\lua.dm" #include "code\controllers\subsystem\machines.dm" #include "code\controllers\subsystem\mapping.dm" +#include "code\controllers\subsystem\market.dm" #include "code\controllers\subsystem\materials.dm" #include "code\controllers\subsystem\minor_mapping.dm" #include "code\controllers\subsystem\mobs.dm" @@ -912,6 +913,7 @@ #include "code\datums\ai\basic_mobs\basic_subtrees\find_food.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\find_paper_and_write.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\find_parent.dm" +#include "code\datums\ai\basic_mobs\basic_subtrees\find_targets_prioritize_traits.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\flee_target.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\go_for_swim.dm" #include "code\datums\ai\basic_mobs\basic_subtrees\maintain_distance.dm" @@ -1051,6 +1053,7 @@ #include "code\datums\components\bumpattack.dm" #include "code\datums\components\burning.dm" #include "code\datums\components\butchering.dm" +#include "code\datums\components\callouts.dm" #include "code\datums\components\caltrop.dm" #include "code\datums\components\can_flash_from_behind.dm" #include "code\datums\components\chasm.dm" @@ -1099,6 +1102,7 @@ #include "code\datums\components\explode_on_attack.dm" #include "code\datums\components\faction_granter.dm" #include "code\datums\components\fertile_egg.dm" +#include "code\datums\components\fish_growth.dm" #include "code\datums\components\fishing_spot.dm" #include "code\datums\components\focused_attacker.dm" #include "code\datums\components\food_storage.dm" @@ -1507,6 +1511,8 @@ #include "code\datums\elements\organ_set_bonus.dm" #include "code\datums\elements\permanent_fire_overlay.dm" #include "code\datums\elements\pet_bonus.dm" +#include "code\datums\elements\pet_collar.dm" +#include "code\datums\elements\pet_cult.dm" #include "code\datums\elements\plant_backfire.dm" #include "code\datums\elements\point_of_interest.dm" #include "code\datums\elements\poster_tearer.dm" @@ -2355,7 +2361,6 @@ #include "code\game\objects\items\maintenance_loot.dm" #include "code\game\objects\items\manuals.dm" #include "code\game\objects\items\mop.dm" -#include "code\game\objects\items\nitrium_crystals.dm" #include "code\game\objects\items\paint.dm" #include "code\game\objects\items\paiwire.dm" #include "code\game\objects\items\pet_carrier.dm" @@ -2956,7 +2961,6 @@ #include "code\modules\admin\verbs\shuttlepanel.dm" #include "code\modules\admin\verbs\spawnobjasmob.dm" #include "code\modules\admin\verbs\special_verbs.dm" -#include "code\modules\admin\verbs\lua\_hooks.dm" #include "code\modules\admin\verbs\lua\_wrappers.dm" #include "code\modules\admin\verbs\lua\helpers.dm" #include "code\modules\admin\verbs\lua\lua_editor.dm" @@ -3667,6 +3671,7 @@ #include "code\modules\cargo\exports\anomaly.dm" #include "code\modules\cargo\exports\antiques.dm" #include "code\modules\cargo\exports\civilain_bounty.dm" +#include "code\modules\cargo\exports\fish.dm" #include "code\modules\cargo\exports\food_and_drink.dm" #include "code\modules\cargo\exports\gear.dm" #include "code\modules\cargo\exports\large_objects.dm" @@ -4465,7 +4470,6 @@ #include "code\modules\lighting\lighting_atom.dm" #include "code\modules\lighting\lighting_corner.dm" #include "code\modules\lighting\lighting_object.dm" -#include "code\modules\lighting\lighting_setup.dm" #include "code\modules\lighting\lighting_source.dm" #include "code\modules\lighting\lighting_turf.dm" #include "code\modules\lighting\static_lighting_area.dm" @@ -4911,7 +4915,6 @@ #include "code\modules\mob\living\basic\pets\parrot\parrot_ai\parrot_hoarding.dm" #include "code\modules\mob\living\basic\pets\parrot\parrot_ai\parrot_perching.dm" #include "code\modules\mob\living\basic\pets\parrot\parrot_ai\parroting_action.dm" -#include "code\modules\mob\living\basic\pets\pet_cult\pet_cult.dm" #include "code\modules\mob\living\basic\pets\pet_cult\pet_cult_abilities.dm" #include "code\modules\mob\living\basic\pets\pet_cult\pet_cult_ai.dm" #include "code\modules\mob\living\basic\ruin_defender\cybersun_aicore.dm" diff --git a/tgui/packages/tgui-panel/chat/ChatPageSettings.jsx b/tgui/packages/tgui-panel/chat/ChatPageSettings.jsx index 4bd0383d7d759d..ba577a1e5ef2f8 100644 --- a/tgui/packages/tgui-panel/chat/ChatPageSettings.jsx +++ b/tgui/packages/tgui-panel/chat/ChatPageSettings.jsx @@ -30,7 +30,23 @@ export const ChatPageSettings = (props) => { return (
- + {!!!page.isMain && ( + + - ) : ( - '' - )} - - - - {!page.isMain ? ( - - Reorder Chat:  - - - - ) : ( - '' )} diff --git a/tgui/packages/tgui-panel/settings/SettingsGeneral.tsx b/tgui/packages/tgui-panel/settings/SettingsGeneral.tsx index 8203f0313951de..3599f24e707031 100644 --- a/tgui/packages/tgui-panel/settings/SettingsGeneral.tsx +++ b/tgui/packages/tgui-panel/settings/SettingsGeneral.tsx @@ -8,8 +8,8 @@ import { Divider, Input, LabeledList, - NumberInput, Section, + Slider, Stack, } from 'tgui/components'; @@ -20,10 +20,11 @@ import { FONTS } from './constants'; import { selectSettings } from './selectors'; export function SettingsGeneral(props) { - const { theme, fontFamily, fontSize, lineHeight } = + const { theme, fontFamily, fontSize, lineHeight, statLinked, statFontSize } = useSelector(selectSettings); const dispatch = useDispatch(); const [freeFont, setFreeFont] = useState(false); + const [statFont, setStatFont] = useState(false); return (
@@ -109,35 +110,66 @@ export function SettingsGeneral(props) { )} - - toFixed(value)} - onChange={(value) => - dispatch( - updateSettings({ - fontSize: value, - }), - ) - } - /> + + + + toFixed(value)} + onChange={(e, value) => + dispatch( + updateSettings({ + [statFont ? 'statFontSize' : 'fontSize']: value, + }), + ) + } + /> + + + + + {!!statFont && ( + +
diff --git a/tgui/packages/tgui/interfaces/Aquarium.tsx b/tgui/packages/tgui/interfaces/Aquarium.tsx index caa0c65d75f65f..6f29920fc0bf38 100644 --- a/tgui/packages/tgui/interfaces/Aquarium.tsx +++ b/tgui/packages/tgui/interfaces/Aquarium.tsx @@ -71,10 +71,10 @@ export const Aquarium = (props) => { ))} - + diff --git a/tgui/packages/tgui/interfaces/LuaEditor/CallModal.jsx b/tgui/packages/tgui/interfaces/LuaEditor/CallModal.tsx similarity index 58% rename from tgui/packages/tgui/interfaces/LuaEditor/CallModal.jsx rename to tgui/packages/tgui/interfaces/LuaEditor/CallModal.tsx index 73c505fba1c777..2681d7fb5f42de 100644 --- a/tgui/packages/tgui/interfaces/LuaEditor/CallModal.jsx +++ b/tgui/packages/tgui/interfaces/LuaEditor/CallModal.tsx @@ -1,12 +1,20 @@ -import { useBackend, useLocalState } from '../../backend'; +import { Dispatch, SetStateAction } from 'react'; + +import { useBackend } from '../../backend'; import { Button, Modal, Section } from '../../components'; import { ListMapper } from './ListMapper'; +import { CallInfo, LuaEditorData, LuaEditorModal } from './types'; + +type CallModalProps = { + setModal: Dispatch>; + toCall: CallInfo; + setToCall: Dispatch>; +}; -export const CallModal = (props) => { - const { act, data } = useBackend(); +export const CallModal = (props: CallModalProps) => { + const { act, data } = useBackend(); const { callArguments } = data; - const [, setModal] = useLocalState('modal'); - const [toCall, setToCall] = useLocalState('toCallTaskInfo'); + const { setModal, toCall, setToCall } = props; const { type, params } = toCall; return ( { color="red" icon="window-close" onClick={() => { - setModal(null); - setToCall(null); + setModal(undefined); + setToCall(undefined); act('clearArgs'); }} > @@ -35,8 +43,8 @@ export const CallModal = (props) => { - ); - } else if (UnconvertibleLuaValueRegex.test(thing)) { - return {thing.charAt(0).toUpperCase() + thing.substring(1)}; - } else if (RefRegex.test(thing)) { - return ( - - ); - } else if (thing === null) { - return Nil; - } else { - return thing; - } - } else { - return {thing}; - } - }; - - const ListMapperInner = (element, i) => { - const { key, value } = element; - const basePath = path ? path : []; - let keyPath = [...basePath, { index: i + 1, type: 'key' }]; - let valuePath = [...basePath, { index: i + 1, type: 'value' }]; - let entryPath = [...basePath, { index: i + 1, type: 'entry' }]; - - if (key === null && skipNulls) { - return; - } - - /* - * Finding a function only accessible as a table's key is too awkward to - * deal with for now - */ - let keyNode = ThingNode(key, keyPath, { callType: null }); - - /* - * Likewise, since table, thread, and userdata equality is tested by - * reference rather than value, we can't find functions whose keys - * within the table are tables, threads, or userdata - */ - const uniquelyIndexable = - (typeof key === 'string' && - !(UnconvertibleLuaValueRegex.test(key) || RefRegex.test(key))) || - typeof key === 'number'; - let valueNode = ThingNode(value, valuePath, { - callType: uniquelyIndexable && callType, - }); - return ( - - - - ); - } - return ( - <> - {i > 0 && } - - {message} - - {repeats && ( - - x{repeats + 1} - - )} - - ); - }); -}; diff --git a/tgui/packages/tgui/interfaces/LuaEditor/Log.tsx b/tgui/packages/tgui/interfaces/LuaEditor/Log.tsx new file mode 100644 index 00000000000000..be0730a350df11 --- /dev/null +++ b/tgui/packages/tgui/interfaces/LuaEditor/Log.tsx @@ -0,0 +1,224 @@ +import { Dispatch, SetStateAction } from 'react'; + +import { useBackend } from '../../backend'; +import { + Box, + Button, + Collapsible, + Divider, + LabeledList, + Stack, +} from '../../components'; +import { logger } from '../../logging'; +import { ListMapper } from './ListMapper'; +import { LuaEditorData, LuaEditorModal } from './types'; + +const parsePanic = (name, panic_json) => { + const panic_info = JSON.parse(panic_json); + const { + message, + location: { file, line }, + backtrace, + } = panic_info; + return ( + <> + + {name} panicked at {file}:{line}: {message} + + + + {backtrace + ?.filter( + (frame) => frame.file !== undefined && frame.line !== undefined, + ) + ?.map(({ name, file, line }, i) => ( + <> + {i > 0 && } + + + {name} + + {file}:{line} + + + + + ))} + + + + ); +}; + +type LogProps = { + setViewedChunk: Dispatch>; + setModal: Dispatch>; +}; + +export const Log = (props: LogProps) => { + const { act, data } = useBackend(); + const { stateLog } = data; + const { setViewedChunk, setModal } = props; + return stateLog.map((element, i) => { + const { status, repeats } = element; + let output; + let messageColor; + switch (status) { + case 'sleep': { + const { chunk, name } = element; + if (chunk) { + messageColor = 'blue'; + output = ( + <> + {name} slept. + + ); + } + break; + } + case 'yield': { + const { name, return_values, variants } = element; + output = ( + <> + {name} yielded + {return_values.length + ? ` ${return_values.length} value${ + return_values.length > 1 ? 's' : '' + }` + : ''} + . + {return_values.length ? ( + + act('vvReturnValue', { + entryIndex: i + 1, + indices: path, + }) + } + /> + ) : ( +
+ )} + + ); + messageColor = 'yellow'; + break; + } + case 'finished': { + const { name, return_values, variants } = element; + output = ( + <> + {name} returned + {return_values.length + ? ` ${return_values.length} value${ + return_values.length > 1 ? 's' : '' + }` + : ''} + . + {return_values.length ? ( + + + act('vvReturnValue', { + entryIndex: i + 1, + tableIndices: path, + }) + } + /> + + ) : ( +
+ )} + + ); + messageColor = 'green'; + break; + } + case 'error': { + const { message } = element; + output = message; + messageColor = 'red'; + break; + } + case 'panic': { + const { name, message } = element; + output = parsePanic(name, message); + break; + } + case 'runtime': { + const { file, line, message, stack } = element; + output = ( + <> + Runtime at {file}:{line}: {message} + { + return { key: null, value: frame }; + })} + name="Stack Trace" + collapsible + /> + + ); + messageColor = 'red'; + break; + } + case 'print': { + const { message } = element; + output = message; + break; + } + default: + logger.warn(`unknown log status ${status}`); + } + if (output === undefined) { + return; + } + const { chunk } = element; + if (chunk) { + output = ( + <> + {output} + + + ); + } + return ( + <> + {i > 0 && } + + {output} + + {repeats && ( + + x{repeats + 1} + + )} + + ); + }); +}; diff --git a/tgui/packages/tgui/interfaces/LuaEditor/StateSelectModal.jsx b/tgui/packages/tgui/interfaces/LuaEditor/StateSelectModal.tsx similarity index 64% rename from tgui/packages/tgui/interfaces/LuaEditor/StateSelectModal.jsx rename to tgui/packages/tgui/interfaces/LuaEditor/StateSelectModal.tsx index 3ac6373611e1a2..4ff3deeb09bfe1 100644 --- a/tgui/packages/tgui/interfaces/LuaEditor/StateSelectModal.jsx +++ b/tgui/packages/tgui/interfaces/LuaEditor/StateSelectModal.tsx @@ -1,16 +1,20 @@ -import { useBackend, useLocalState } from '../../backend'; +import { useState } from 'react'; + +import { useBackend } from '../../backend'; import { Button, Input, Modal, Section, Stack } from '../../components'; +import { LuaEditorData, LuaEditorModal } from './types'; + +type StateSelectModalProps = { + setModal: (modal: LuaEditorModal) => void; +}; -export const StateSelectModal = (props) => { - const { act, data } = useBackend(); - const [, setModal] = useLocalState('modal', 'states'); - const [input, setInput] = useLocalState('newStateName', ''); +export const StateSelectModal = (props: StateSelectModalProps) => { + const { act, data } = useBackend(); + const { setModal } = props; + const [input, setInput] = useState(); const { states } = data; return ( - +
{ color="red" icon="window-close" onClick={() => { - setModal(null); + setModal(undefined); }} > Cancel @@ -30,7 +34,7 @@ export const StateSelectModal = (props) => { ))} - + { @@ -36,16 +35,16 @@ export const TaskManager = (props) => {
- +
- {yields.map((info, i) => ( - + {yields.map(({ index, name }, i) => ( + - {noStateYet ? ( - -

Please select or create a lua state to get started.

-
- ) : ( - - -
- - - - } - > -