forked from SpaceStation14-Shenanigans/Monolith
Compare commits
913 Commits
57mm
...
hot-loop-hell
| Author | SHA1 | Date | |
|---|---|---|---|
| eebcb303f0 | |||
| 2ccf6d95b6 | |||
| 1b953cf4cb | |||
| 9ddc145cc1 | |||
| 8e59b16718 | |||
| bbaeab61b5 | |||
| 97e11f66d1 | |||
| 80ae6a33a5 | |||
| 4a3178b4e2 | |||
| 36faba3835 | |||
| 2c6fe74bca | |||
| 3ce24a6dea | |||
| ff40a7c9ce | |||
| f66007ed82 | |||
| 116b6b5201 | |||
| eceaa24095 | |||
| 51e43c0218 | |||
| d11a891bed | |||
| 53222c7db0 | |||
| f875a93d99 | |||
| 58e585fafb | |||
| 4b371b6f08 | |||
| 61bbc0b04d | |||
| 17376acb2b | |||
| 2a91d09f34 | |||
| 425732c52b | |||
| f2d130f925 | |||
| 5423c7111e | |||
| dce3a56655 | |||
| b4fe165b53 | |||
| 5c883e42d7 | |||
| f99ef195df | |||
| a5d51193cb | |||
| b8cfff831f | |||
| 84b077432d | |||
| 901f1dad81 | |||
| 9b0c66171a | |||
| 8f354a91f8 | |||
| f9dad2c68a | |||
| 730f0758b9 | |||
| 8956b8693a | |||
| 8ec089e18a | |||
| 1415ce6c0c | |||
| 94fcc2457a | |||
| cee68ab5f9 | |||
| 4c6401cf0f | |||
| b1580d2dc0 | |||
| 9cb45515cf | |||
| 6835481c97 | |||
| 236fcf75c5 | |||
| 04a7bb42b5 | |||
| fd6c0569d1 | |||
| 4028405a5a | |||
| 919dc543e0 | |||
| 83b4f9a5d7 | |||
| cbe7f6c3f5 | |||
| 9c9ad7248c | |||
| dfbe98cbbb | |||
| 1dae5d84f5 | |||
| 07c99c87d7 | |||
| 7944589905 | |||
| 690299e366 | |||
| cbef529e94 | |||
| c3f506e6aa | |||
| dc7e3a8b0f | |||
| 00f103890e | |||
| 2b979960ad | |||
| c83930bf2f | |||
| 8287d6a9bc | |||
| 5085871129 | |||
| 17aed77cc0 | |||
| 090b0d49db | |||
| 4099cf5c5f | |||
| 662670d3eb | |||
| ae3ad17500 | |||
| 780bac284c | |||
| 0ec333ebed | |||
| 33552b44a2 | |||
| 87ab827f04 | |||
| a7761b1742 | |||
| 3cdf4cf142 | |||
| ffa0efdb7c | |||
| 2cdb0021ea | |||
| cc94e52caa | |||
| 98e512fbba | |||
| d66474366c | |||
| 30a736ec45 | |||
| 49035ada5c | |||
| 36a752851c | |||
| fcfb8feff6 | |||
| cee5f2a57e | |||
| 6cfedd70f2 | |||
| 57d41c69b2 | |||
| 94dd84d1fd | |||
| e9229f2946 | |||
| d70855f08d | |||
| e7b11673dd | |||
| 7d19340a0a | |||
| 217a647528 | |||
| 9b8604c8e9 | |||
| 50a6912312 | |||
| daf3801a89 | |||
| ebdc1c9f50 | |||
| 5c73fa2e64 | |||
| 5abadca6eb | |||
| 7dbd1fc4ee | |||
| 69a088ab1c | |||
| 11bd89ab29 | |||
| 1c4707ef20 | |||
| e13dd8e284 | |||
| c37fdece10 | |||
| 368f9f66eb | |||
| bb804fb4eb | |||
| 687d0baf38 | |||
| 01c3731dd6 | |||
| 07b89a7ddd | |||
| a12713d824 | |||
| 827ac02e14 | |||
| 643e335430 | |||
| 9fd9c8e0d3 | |||
| 751236b093 | |||
| 546ded6a0f | |||
| 93477eb322 | |||
| 65d50d7b46 | |||
| ceec2eda2f | |||
| 1058c5e8c1 | |||
| aea7d67573 | |||
| 4f26f02318 | |||
| 905757742d | |||
| 9ea1fe9d58 | |||
| 788f30a40d | |||
| 6f6eeef1d2 | |||
| fe335ba114 | |||
| b7c39e31ca | |||
| 7dfbc4441e | |||
| 6ffca1c96d | |||
| f7394c02a3 | |||
| 8afd0a1ac0 | |||
| 51d1122dc2 | |||
| 343c6dd98c | |||
| 17795e629d | |||
| a906504c18 | |||
| e9bd143612 | |||
| 3f9487e507 | |||
| dfb81dd5c4 | |||
| d1218ad15b | |||
| 5d82605e4c | |||
| ff856ddcbc | |||
| c14df33b47 | |||
| aa3aef3786 | |||
| 12ff1257f7 | |||
| 878fe89966 | |||
| bfcad4b309 | |||
| 89b7db6957 | |||
| 6c402241db | |||
| c228375dc1 | |||
| 1be5bc68d5 | |||
| 1122d4d30f | |||
| bc0cd37fb6 | |||
| 182c63c87e | |||
| a16b01982a | |||
| 260e34054d | |||
| 73b055c6cb | |||
| dea71210b0 | |||
| 17289457c0 | |||
| 94d3092c33 | |||
| 66c9bd6455 | |||
| 154f242bb8 | |||
| 1e6bd607fc | |||
| dd467907ec | |||
| 9a8c753491 | |||
| d354f90036 | |||
| a33eb842f7 | |||
| d7ea4b55c4 | |||
| a40ece4b7c | |||
| 0b8062b471 | |||
| dadcdfc692 | |||
| e4177484ca | |||
| 5629674bbb | |||
| 253eb267d2 | |||
| 0650ef5f24 | |||
| cf19d8ed54 | |||
| ff66ed37dd | |||
| e7f615461d | |||
| 4ef14f0dce | |||
| 3296e8d2cd | |||
| 8b78b737cd | |||
| 3f7bfcb78e | |||
| fb1103c457 | |||
| af2d45dd55 | |||
| 560e64c13c | |||
| 5054665057 | |||
| 5fd442171f | |||
| 8894d4e5ff | |||
| eef28959e2 | |||
| 4ea83d389a | |||
| 02f74c26e9 | |||
| c0ea5adf5d | |||
| 6daf9f02e6 | |||
| afabe747f2 | |||
| 699232f653 | |||
| 262aa8cd4b | |||
| bcb9440046 | |||
| 93bd8b8356 | |||
| d14dd88149 | |||
| f520ddf911 | |||
| c2ea1eaf94 | |||
| fc105b61fc | |||
| 271c4e7efc | |||
| a4138f4b11 | |||
| ff74cf3ae1 | |||
| 663425a050 | |||
| b4e4a284bc | |||
| 3a8ac92ef8 | |||
| d3d3ab531e | |||
| 71cf5f42c7 | |||
| fce9e95910 | |||
| ee337596d6 | |||
| a2b3ddecdf | |||
| 0939533dc1 | |||
| 42f6f53be9 | |||
| 2651c00cfd | |||
| a462d09fb9 | |||
| ce617c185e | |||
| 131c5e79a5 | |||
| 86c9a843b1 | |||
| dd910f1550 | |||
| cd8d59c095 | |||
| 20bc7af2a4 | |||
| 65ea89b673 | |||
| 44445f3d2a | |||
| 648cc99aff | |||
| e8c2b72aa0 | |||
| 7d85dbca00 | |||
| 85e0cb1c76 | |||
| 3c32d2f6f5 | |||
| 9d8d0b9016 | |||
| 02e72a4c1d | |||
| 5fac554802 | |||
| bc62bf3700 | |||
| accb1404b0 | |||
| 326440aa22 | |||
| b4fe4ab5e7 | |||
| 8ff52fcd7b | |||
| e8a620e044 | |||
| 9ea80d6405 | |||
| abec847ca3 | |||
| 36214087e9 | |||
| 2b4f4f2ba0 | |||
| 258bc12f16 | |||
| d73cf7aeaf | |||
| b1e200408d | |||
| 95227750d9 | |||
| 34f71b59b9 | |||
| 547420d4bc | |||
| 510434fb65 | |||
| 862ce8352c | |||
| 552ab5718a | |||
| 2bacec206b | |||
| bd8ae0ec9b | |||
| 6ba17c6e1b | |||
| 50d7de7818 | |||
| 02348e780e | |||
| 80cc460d69 | |||
| e95a87a1d8 | |||
| 78ecd13c0a | |||
| 9eb4c8333c | |||
| 882b1acae7 | |||
| df39f7bd6d | |||
| c68d329dd2 | |||
| 5a2341407b | |||
| b4b49016d9 | |||
| 53a40c6c3c | |||
| fbf93d50be | |||
| 68144857e8 | |||
| 820a70c695 | |||
| bff7436490 | |||
| 2b76b0a55a | |||
| fa61e959fb | |||
| b427f087b0 | |||
| 7a8b90339f | |||
| cecc52bff9 | |||
| 378592a0ba | |||
| 89dff2ec03 | |||
| 4faad89b0c | |||
| 8f8b94862a | |||
| 7c29b33d27 | |||
| 8180e5d436 | |||
| e081dd59c6 | |||
| 295ef88a95 | |||
| 39292553b3 | |||
| 2652423c4d | |||
| fb836a0ee7 | |||
| 7a63aba489 | |||
| 7ec10d578c | |||
| 91f4eb7b51 | |||
| e552e2498f | |||
| ef34f255bf | |||
| 0f3390aba8 | |||
| 25033ae9c1 | |||
| d32fd9dd0a | |||
| 728c10974e | |||
| 50c5891b4e | |||
| 51818f6dc3 | |||
| dcaefa16d7 | |||
| 15936634b1 | |||
| 574bb25522 | |||
| 1125715a3f | |||
| 9e3a270988 | |||
| bf1a02bfcb | |||
| 57c59e3684 | |||
| 0e31d3885f | |||
| 27b05a3b75 | |||
| f99e36e101 | |||
| 5a17e7781f | |||
| 98f8d334a1 | |||
| c9bba3367d | |||
| 4ac8f937fb | |||
| 9648f54fc3 | |||
| 33e0bf8293 | |||
| 81ed57e9fb | |||
| 0943abba3e | |||
| 886752cd7a | |||
| f8ba24d3f1 | |||
| 1765c7d506 | |||
| 16f40a5289 | |||
| b80fb6d554 | |||
| e1932935fe | |||
| 5aa06e8fc0 | |||
| 914c5529ec | |||
| f406be9a5d | |||
| 002ba09258 | |||
| f89e18df88 | |||
| a7dcf1afea | |||
| 670785fd48 | |||
| 654a657788 | |||
| 52137b967a | |||
| 8e0bff68cb | |||
| af99be86ed | |||
| 3ed4f7cc1a | |||
| e72a06c19d | |||
| 6619538fb9 | |||
| 005950f2a0 | |||
| 468be1435c | |||
| 685422209e | |||
| ae58c4d021 | |||
| 464975916d | |||
| 2f39b9edce | |||
| a18831a0c5 | |||
| 42dcb56e22 | |||
| 3eeb83a16e | |||
| abf8bd7218 | |||
| c6de815de4 | |||
| 53b02b5830 | |||
| 40d2f70e08 | |||
| 1791e631f7 | |||
| f79b69a3f6 | |||
| b8d5ca7022 | |||
| f37ef8c994 | |||
| b4ae011b87 | |||
| 0adcb3c8a4 | |||
| ad1a263596 | |||
| 591a6ba333 | |||
| ebf2e56159 | |||
| c6b36bf126 | |||
| 2cd30797ac | |||
| 2aad60a3d7 | |||
| f561fcb45e | |||
| a68c0d48ba | |||
| ec2c5a521d | |||
| 39efe6f747 | |||
| 0816b4457c | |||
| 6c87da3dc3 | |||
| 05d4b2eebd | |||
| 6ee1e7d8f3 | |||
| f097148d99 | |||
| ef2ce6565d | |||
| 98ad67497b | |||
| 67644068b6 | |||
| 1b64380dbb | |||
| 465006f16b | |||
| e1ec12fb3e | |||
| d62e3a42d0 | |||
| 02be1ef282 | |||
| 85c4a0c9ec | |||
| baeb53ee82 | |||
| 933dc75c33 | |||
| fc45f016ee | |||
| 6a719f7c39 | |||
| d83db373fe | |||
| ccec7894c6 | |||
| 3319b5f0d3 | |||
| 81d9ae37e3 | |||
| 1990f2a272 | |||
| 3665639420 | |||
| 20e2ceb0db | |||
| 84a116fd27 | |||
| c3c402d380 | |||
| 92e8677e82 | |||
| 65365135e3 | |||
| 62e372c9d2 | |||
| 4279c1977d | |||
| 6406a7cf4f | |||
| 806e22e8b4 | |||
| c2934d0bd7 | |||
| 5316f1fdd9 | |||
| 66fed8d2a2 | |||
| 28e3584a67 | |||
| 78c94ddbc4 | |||
| cef95a03bf | |||
| bd3a35ee64 | |||
| 0b50c919e4 | |||
| afcf994545 | |||
| 5aaee26a09 | |||
| fb3c49bd09 | |||
| 2c381cbcd0 | |||
| f4e3ac2478 | |||
| 31de4af5e2 | |||
| 5e67e63032 | |||
| f3919fafc1 | |||
| 974b78863b | |||
| 1654bd5cf8 | |||
| d353667f97 | |||
| 47116d8ba7 | |||
| 9bd6d5f3f2 | |||
| 1dc696deb6 | |||
| f2df23dc81 | |||
| 76d6ea96e0 | |||
| 93ba265e00 | |||
| 16f73ec031 | |||
| 9d3b0778b3 | |||
| 32b15951e2 | |||
| 7a0f0d04c5 | |||
| bcce8e67a3 | |||
| 5afcdd9379 | |||
| 01c7ea464a | |||
| 55f6108312 | |||
| 8be27c1658 | |||
| 4df38cc9cc | |||
| 8c0d2a50df | |||
| 2d8105de13 | |||
| 01bb73bf56 | |||
| fb09b866f2 | |||
| 0458a500ff | |||
| 4334b07093 | |||
| ad2dd99a9b | |||
| f11c83a96e | |||
| 36d1740829 | |||
| 1e201bb8d2 | |||
| c7a34dfc22 | |||
| e366c4d7cc | |||
| bc0151e540 | |||
| b2307660de | |||
| 5d5f6b4654 | |||
| 165f9950b5 | |||
| ef9858936d | |||
| d0a95f5d8b | |||
| ee386b0633 | |||
| de38cc18ef | |||
| ca928bdc83 | |||
| cee6ce9566 | |||
| 984a2c9b71 | |||
| 548e9eccb6 | |||
| cd817abd2c | |||
| f276df8fe9 | |||
| dd323be01d | |||
| 0cf9b35f08 | |||
| 114a09f290 | |||
| dc4b50e71e | |||
| c405c32c89 | |||
| 34ff30a736 | |||
| c8e162baa1 | |||
| ffcbc32c43 | |||
| 351b225102 | |||
| 496432881e | |||
| 9fd2a7b5af | |||
| 8972408ec1 | |||
| 5798b57788 | |||
| ec88162ac0 | |||
| 3992aa846f | |||
| 4b62f35f10 | |||
| cc1c91f39f | |||
| c5241854ce | |||
| d02895a50f | |||
| c41d005cf4 | |||
| 013f57a73d | |||
| c3f687a493 | |||
| f837710be1 | |||
| 7b00d623e0 | |||
| dafbb5f3d8 | |||
| d4487d9a5a | |||
| 7b9f602c55 | |||
| 97509dd3b6 | |||
| 55c2a03ea4 | |||
| 543c19645f | |||
| da8b19dd05 | |||
| 4fc44d3a9c | |||
| 55688cc9e0 | |||
| 5357469644 | |||
| 6040135534 | |||
| 52649a871e | |||
| fef33511d8 | |||
| fec5bfce0a | |||
| 11f82f95d3 | |||
| 3dbad97455 | |||
| a193ab828e | |||
| c75083140d | |||
| 106f9b6d28 | |||
| fe24fc22bc | |||
| 85c9636003 | |||
| a1d2f4dcbc | |||
| 3381fe165c | |||
| a913c35b21 | |||
| 0706b759d4 | |||
| 73a91c0b0a | |||
| 9e390680bd | |||
| d3d391f5a0 | |||
| a6506c7f46 | |||
| 958421b6c9 | |||
| c513938ed9 | |||
| a6431c9bab | |||
| f3390a81cc | |||
| 6ba80381cc | |||
| ef095aec88 | |||
| d02738089c | |||
| b9f0de8576 | |||
| 5a6d4b74b1 | |||
| 1ac13bf597 | |||
| 90ee912816 | |||
| 27665829e6 | |||
| e1459b0d43 | |||
| 395d334dd7 | |||
| 75e166e9b3 | |||
| d987cfe88d | |||
| a942f3e7b1 | |||
| 4108933834 | |||
| 6af6f3b386 | |||
| 9a590069d2 | |||
| a60321f201 | |||
| dfabb71045 | |||
| ce034c3f19 | |||
| 79c9dee112 | |||
| 6a048def33 | |||
| e41ef48441 | |||
| 27e7b2f70a | |||
| 2bd317dadb | |||
| 1145822797 | |||
| 27dca32ef3 | |||
| 4bdad8f6ee | |||
| 38ebc2699c | |||
| 82f75ff37f | |||
| c84cde54cb | |||
| f0c6624762 | |||
| 277ad91140 | |||
| b9419b25a1 | |||
| e1a5488f14 | |||
| d9b46ca6dc | |||
| a672e9bd28 | |||
| 2a5fe8fe6a | |||
| e069f2ba9d | |||
| db3675b3e8 | |||
| 79bf0fec68 | |||
| 41b3fb9113 | |||
| 7cd749dfa6 | |||
| eb44deeeda | |||
| 7035e752a9 | |||
| 2fdd1cd573 | |||
| 6c4101e0c0 | |||
| 5f90433697 | |||
| 9f54374593 | |||
| 5272291275 | |||
| 4a0f4cec3a | |||
| 5d68716090 | |||
| a4b1a5317c | |||
| ee48853724 | |||
| a8651f6457 | |||
| 47378ac726 | |||
| 9ca8d4a82a | |||
| f8e940c5f5 | |||
| 89b73cdc76 | |||
| 881ee08f91 | |||
| 19d869bda1 | |||
| 964b5768fd | |||
| 925933bbcb | |||
| 277086116a | |||
| 54412b25e4 | |||
| b75be35a1d | |||
| 1d184cfd27 | |||
| ea8ce6d5b5 | |||
| a9a05d0da3 | |||
| e2c193f7c7 | |||
| 060a7565c5 | |||
| 2d94504508 | |||
| 9ec05018b0 | |||
| 9574d6fe1f | |||
| 937131c2a4 | |||
| f2cd5a6f3a | |||
| 7749344876 | |||
| cda0c1f802 | |||
| ad37c2895a | |||
| 7ceedb6014 | |||
| a8c0d92351 | |||
| 1ead85c1c5 | |||
| 135335f7c9 | |||
| c1a5f4d8c5 | |||
| 9f204d62d1 | |||
| 7ef79b3fda | |||
| 3f0670b985 | |||
| c7060a0dc3 | |||
| 6a48576e4e | |||
| e4412cfbb6 | |||
| a119933e1a | |||
| 7602c54c29 | |||
| f58931c915 | |||
| 686d6c8c37 | |||
| e8850079f0 | |||
| 9cfdbd75e0 | |||
| 100800d09c | |||
| 863cd54169 | |||
| b4bd44a589 | |||
| 8ab20f7058 | |||
| 29e20df5b0 | |||
| e7b1f19944 | |||
| 615cc446e0 | |||
| 4e794d6a42 | |||
| 63ac33ebce | |||
| d5d89acbb4 | |||
| 1cee621041 | |||
| 9dbf4629a0 | |||
| 67e804698e | |||
| b63dd431e8 | |||
| 849b094574 | |||
| 2dcf189143 | |||
| 9e4a84a3b2 | |||
| e69a387839 | |||
| 3f50e9e035 | |||
| 6b1977d0f9 | |||
| b9c02cd366 | |||
| f35f5e264d | |||
| 60c6741960 | |||
| 94812b996b | |||
| b291b1cfd6 | |||
| 96902972d5 | |||
| 45bce4ed33 | |||
| 9347f67507 | |||
| e3635d4c91 | |||
| a40b954978 | |||
| adb4296d38 | |||
| a48a235bf6 | |||
| 176055630f | |||
| ff6bf1c131 | |||
| 1be801abf4 | |||
| 0f25271add | |||
| 24bc95450a | |||
| 77ebbdad20 | |||
| 44a6d7eca6 | |||
| eb5c8ac4e9 | |||
| 188070b757 | |||
| 3f97487c0b | |||
| c7de9b660a | |||
| 4b44b891d3 | |||
| b895b2ba42 | |||
| 8a6b39a560 | |||
| ad7633023b | |||
| 8777215b34 | |||
| 4007b079f8 | |||
| 79067884e1 | |||
| ae72c4b217 | |||
| 12485a5ce2 | |||
| 53b74938fd | |||
| 42c12489e3 | |||
| 3c31450ab3 | |||
| 273ca2cd2c | |||
| 64a800ab06 | |||
| 1fec90e647 | |||
| 389b1a39fe | |||
| 8ef3e658b4 | |||
| b6623e107b | |||
| 136225a067 | |||
| 7e88f38fa9 | |||
| 5abbb4beb3 | |||
| cdcb4454b0 | |||
| 4185d83e64 | |||
| 8f921ed705 | |||
| 9a454d9b9a | |||
| 6d5e1cb119 | |||
| 44b443bdf9 | |||
| 696736da06 | |||
| 926c4fab49 | |||
| a80e0db8a0 | |||
| c4954e4bd2 | |||
| 981017a9b4 | |||
| 84b90912f9 | |||
| 78d90096a2 | |||
| a9a5f194f5 | |||
| bc85b73fee | |||
| 0f316130e4 | |||
| 275ecb8e01 | |||
| a3ee39de70 | |||
| 9d38f200d7 | |||
| 8350c4d544 | |||
| e4d67e8d33 | |||
| 278d73dd78 | |||
| 3ab8f43ea3 | |||
| 0bd1b0800e | |||
| c0a10d659a | |||
| bf89ec2037 | |||
| 77811a2d7f | |||
| fa7b973bb3 | |||
| b686b65058 | |||
| 361c0111ca | |||
| c62943f2e0 | |||
| 701883e108 | |||
| b68630257f | |||
| 7072751108 | |||
| 469c42f2a4 | |||
| dd8070316f | |||
| 6e0dbdd1e7 | |||
| ef47aad488 | |||
| 7f00a4c13a | |||
| a651e15ab5 | |||
| f089bf5a29 | |||
| 785e6abe69 | |||
| 6c0061a2d3 | |||
| c3e008866a | |||
| 8245850cb0 | |||
| 5da958f7a9 | |||
| 27513e7a28 | |||
| c39c6ca2f5 | |||
| 319b12b138 | |||
| 21ba67d599 | |||
| 454f33ad43 | |||
| ad9093094c | |||
| 09c7bf422b | |||
| d24a85c6d8 | |||
| 8709244f6f | |||
| 856093613e | |||
| 6b1aabb8f5 | |||
| 2939e6b9bc | |||
| 9476e003c2 | |||
| 6e220606fb | |||
| a56db3da27 | |||
| f7960e90ab | |||
| 313e4f1db6 | |||
| d9721a8328 | |||
| 8100503e6a | |||
| a0f3d8193b | |||
| cacbaec4cf | |||
| d5e213abd9 | |||
| eacac0b2e3 | |||
| b3e51ba5a9 | |||
| d54cc99491 | |||
| 51797e0933 | |||
| 9d97920e55 | |||
| 68da6b039c | |||
| 9a8c9b76e2 | |||
| 5d0fe0a94b | |||
| 88c1e7fd1d | |||
| 3f594f2387 | |||
| b19ec1eb9f | |||
| f76e2bb807 | |||
| ee02f8afdd | |||
| 0a4753edae | |||
| d0ceadf130 | |||
| 05c046d055 | |||
| b1aa743a40 | |||
| 5125fc084e | |||
| 2fa487e4b3 | |||
| d63c42b0ee | |||
| da16de09a5 | |||
| 58fa85d648 | |||
| 3ce7df2433 | |||
| a11952bdd2 | |||
| 22c29f0a46 | |||
| 39358d68cd | |||
| 52cd9ad5c5 | |||
| 3b272d0572 | |||
| fa47f767a3 | |||
| 94d15b0fcf | |||
| 9b20d3aee4 | |||
| 13a4c7eb63 | |||
| a364ff074b | |||
| 6c33c74260 | |||
| e03bc781c8 | |||
| a76089a1d8 | |||
| 14c3ca4ed6 | |||
| 6378076a5d | |||
| e01cb2be78 | |||
| a2cbcddd12 | |||
| 70b903467e | |||
| fdb9954a22 | |||
| 01e622b43d | |||
| 1154e94757 | |||
| d95e82922d | |||
| 24e77e2fc4 | |||
| f15d0e74c9 | |||
| 1107c9c288 | |||
| 57c5287e02 | |||
| 838a56a68a | |||
| 8134e4733e | |||
| b7fc2cc7e7 | |||
| b5618452d5 | |||
| 3c697015a6 | |||
| 5be002dbc2 | |||
| e8989e1fc3 | |||
| a5fcf434ec | |||
| 8ee21957a3 | |||
| 88c6b190b5 | |||
| e490f5216c | |||
| 4da4b3b01a | |||
| f457d5c33c | |||
| f2726120f6 | |||
| 04a3fc2949 | |||
| 3e38958cab | |||
| 0642406657 | |||
| c62bade639 | |||
| 1365399931 | |||
| b02070a3c0 | |||
| 94a7413968 | |||
| c984c461c7 | |||
| e102989c28 | |||
| f8b1355bbb | |||
| 52e11f7a59 | |||
| 5e152a2875 | |||
| 3f40d8f59f | |||
| 56727c248c | |||
| 56dbf295c2 | |||
| 1f5f3d38d5 | |||
| 86f70184d7 | |||
| 3a1f36ea15 | |||
| 036870c2d0 | |||
| 108864d7ed | |||
| 4a21e19afe | |||
| 1d53b774b4 | |||
| 6f3508f497 | |||
| faf89dc740 | |||
| 2e2c0e2a97 | |||
| 424c5001a1 | |||
| e845a6f77c | |||
| e6e9346979 | |||
| 30a6e47d6f | |||
| 298ed43ee5 | |||
| c992c56fa3 | |||
| fe071126d5 | |||
| 86d46357bd | |||
| 32ab30233f | |||
| afb33ea720 | |||
| d83e97be76 | |||
| 77323026ae | |||
| f9d115f708 | |||
| 0fffae63af | |||
| 4848763feb | |||
| b52fea4920 | |||
| ca50c40b3b | |||
| 5d8b66f491 | |||
| 0e717b1cd6 | |||
| 3da48f94d1 | |||
| 92eaee9dc0 | |||
| 9945dcc5fa | |||
| e91ee50973 | |||
| abf7764557 | |||
| b5d0ce7866 | |||
| f9f4c37b03 | |||
| 0d340bbae9 | |||
| 81a1371eb4 | |||
| 2825f0f400 | |||
| c218faac8d | |||
| 1fb4bca1b3 | |||
| 846fb711a6 | |||
| c943010bc1 | |||
| c497df354b | |||
| f692d16b1a | |||
| 885c2feec3 | |||
| ab4e4daa48 | |||
| 8743651e1b | |||
| ccff51b77b | |||
| 52915390bb | |||
| 09150f5a7d | |||
| 9ea3e34f49 | |||
| 1ca09e96d3 | |||
| 44aac3d94b | |||
| 75f18469aa | |||
| 956658b305 | |||
| 297262017b | |||
| 7536925649 | |||
| d463794da7 | |||
| ee903e3735 | |||
| 3f9e35f900 | |||
| 90b2bd34e2 | |||
| 0fe194c209 | |||
| 3cbfc5055c | |||
| c4d5fa6813 | |||
| 41e8348d96 | |||
| f715d4c00b | |||
| 685d12c35f | |||
| 1182332c0d | |||
| 9ce9d7258d | |||
| 23489aaadd | |||
| b36192bf3b | |||
| 417cd92c4b | |||
| 7561cdfb92 | |||
| dfe9c65221 | |||
| 7f852a8cb8 | |||
| 6895525e91 | |||
| dc230618e3 | |||
| d5530fb5ee | |||
| 1a6bd945c5 | |||
| 69c0484989 | |||
| c7f86e6b6f | |||
| 8cb67fbbe2 | |||
| 4c7d77502c | |||
| 7b6ebef36f | |||
| 974cb92dc5 |
+1
-1
@@ -348,7 +348,7 @@ resharper_csharp_qualified_using_at_nested_scope = false
|
||||
resharper_csharp_prefer_qualified_reference = false
|
||||
resharper_csharp_allow_alias = false
|
||||
|
||||
[*.{csproj,xml,yml,yaml,dll.config,msbuildproj,targets,props,json}]
|
||||
[*.{csproj,xml,yml,yaml,dll.config,msbuildproj,targets,props,json,slnx}]
|
||||
indent_size = 2
|
||||
|
||||
[nuget.config]
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
<!-- Guidelines: https://docs.spacestation14.io/en/getting-started/pr-guideline -->
|
||||
|
||||
## About the PR
|
||||
<!-- What did you change? -->
|
||||
@@ -7,23 +6,23 @@
|
||||
## Why / Balance
|
||||
<!-- Discuss how this would affect game balance or explain why it was changed. Link any relevant discussions or issues. -->
|
||||
|
||||
## How to test
|
||||
<!-- Describe the way it can be tested -->
|
||||
|
||||
## Media
|
||||
<!-- Attach media if the PR makes ingame changes (clothing, items, features, etc).
|
||||
Small fixes/refactors are exempt. Media may be used in SS14 progress reports with credit. -->
|
||||
|
||||
## Requirements
|
||||
<!-- Confirm the following by placing an X in the brackets [X]: -->
|
||||
- [ ] I have read and am following the [Pull Request and Changelog Guidelines](https://docs.spacestation14.com/en/general-development/codebase-info/pull-request-guidelines.html).
|
||||
- [ ] I have read relevant guidelines/documentation to this PR found on [our devwiki](https://monolith-station.github.io/mono-docs/).
|
||||
- [ ] I have added media to this PR or it does not require an ingame showcase.
|
||||
- [ ] I can confirm this PR contains no AI-generated content, and did not use any AI-generated content.
|
||||
- [ ] I can confirm this PR contains either no AI-generated content, or AI-generated content that meets our guidelines.
|
||||
<!-- You should understand that not following the above may get your PR closed at maintainer’s discretion -->
|
||||
<!-- When using AI, make sure you are already proficient in creating whatever content you are attempting to generate and that you already have experience contributing to SS14. This means using AI to enhance your preexisting workflow, not vibecoding. -->
|
||||
|
||||
## How to test
|
||||
<!-- Describe the way it can be tested -->
|
||||
|
||||
## Breaking changes
|
||||
<!-- List any breaking changes, including namespaces, public class/method/field changes, prototype renames; and provide instructions for fixing them.
|
||||
This will be posted in #codebase-changes. -->
|
||||
<!-- List any breaking changes, including namespaces, public class/method/field changes, prototype renames; and provide instructions for fixing them. -->
|
||||
|
||||
**Changelog**
|
||||
<!-- Add a Changelog entry to make players aware of new features or changes that could affect gameplay.
|
||||
|
||||
@@ -11,7 +11,7 @@ jobs:
|
||||
name: Run Benchmarks
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3.6.0
|
||||
- uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- name: Get Engine version
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Master
|
||||
uses: actions/checkout@v3.6.0
|
||||
uses: actions/checkout@v4.2.2
|
||||
|
||||
- name: Setup Submodule
|
||||
run: |
|
||||
@@ -38,9 +38,9 @@ jobs:
|
||||
git submodule update --init --recursive
|
||||
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v3.2.0
|
||||
uses: actions/setup-dotnet@v4.1.0
|
||||
with:
|
||||
dotnet-version: 9.0.x
|
||||
dotnet-version: 10.0.x
|
||||
|
||||
- name: Install dependencies
|
||||
run: dotnet restore
|
||||
|
||||
@@ -23,7 +23,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Master
|
||||
uses: actions/checkout@v3.6.0
|
||||
uses: actions/checkout@v4.2.2
|
||||
|
||||
- name: Setup Submodule
|
||||
run: |
|
||||
@@ -38,9 +38,9 @@ jobs:
|
||||
git submodule update --init --recursive
|
||||
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v3.2.0
|
||||
uses: actions/setup-dotnet@v4.1.0
|
||||
with:
|
||||
dotnet-version: 9.0.x
|
||||
dotnet-version: 10.0.x
|
||||
|
||||
- name: Install dependencies
|
||||
run: dotnet restore
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: PR Changelogs
|
||||
concurrency: commit_action
|
||||
concurrency: commit_action-${{ github.event.pull_request.base.ref }} # Mono
|
||||
on:
|
||||
pull_request_target:
|
||||
types: [closed]
|
||||
@@ -16,11 +16,11 @@ jobs:
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Checkout Master
|
||||
- name: Checkout Base Branch # Mono
|
||||
uses: actions/checkout@v3
|
||||
with:
|
||||
token: ${{ secrets.BOT_TOKEN }}
|
||||
ref: "${{ vars.CHANGELOG_BRANCH }}"
|
||||
ref: "${{ github.event.pull_request.base.ref }}" # Mono
|
||||
|
||||
- name: Setup Git
|
||||
run: |
|
||||
@@ -47,9 +47,9 @@ jobs:
|
||||
|
||||
- name: Commit Changelog
|
||||
run: |
|
||||
git pull origin main
|
||||
git pull origin "${{ github.event.pull_request.base.ref }}"
|
||||
git add "${{ env.CHANGELOG_DIR }}"
|
||||
git commit -m "Automated Changelog (#${{ env.PR_NUMBER }})"
|
||||
git push
|
||||
git push origin "${{ github.event.pull_request.base.ref }}"
|
||||
shell: bash
|
||||
continue-on-error: true
|
||||
|
||||
@@ -14,6 +14,6 @@ jobs:
|
||||
if: github.event.pull_request.draft == false
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3.6.0
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- name: Check for CRLF
|
||||
run: Tools/check_crlf.py
|
||||
|
||||
@@ -10,18 +10,18 @@ jobs:
|
||||
if: ${{github.head_ref == 'master' || github.head_ref == 'main' || github.head_ref == 'develop'}}
|
||||
|
||||
steps:
|
||||
# - uses: superbrothers/close-pull-request@v3
|
||||
# with:
|
||||
# comment: "Thank you for contributing to the Space Station 14 repository. Unfortunately, it looks like you submitted your pull request from the master branch. We suggest you follow [our git usage documentation](https://docs.spacestation14.com/en/general-development/setup/git-for-the-ss14-developer.html) \n\n You can move your current work from the master branch to another branch by doing `git branch <branch_name` and resetting the master branch."
|
||||
- uses: superbrothers/close-pull-request@v3
|
||||
with:
|
||||
comment: "Thank you for contributing to the Monolith repository. Unfortunately, it looks like you submitted your pull request from the master branch. We suggest you follow [our git usage documentation](https://docs.spacestation14.com/en/general-development/setup/git-for-the-ss14-developer.html) \n\n You can move your current work from the master branch to another branch by doing `git branch <branch_name` and resetting the master branch."
|
||||
|
||||
# If you prefer to just comment on the pr and not close it, uncomment the bellow and comment the above
|
||||
|
||||
- uses: actions/github-script@v7
|
||||
with:
|
||||
script: |
|
||||
github.rest.issues.createComment({
|
||||
issue_number: ${{ github.event.number }},
|
||||
owner: context.repo.owner,
|
||||
repo: context.repo.repo,
|
||||
body: "Thank you for contributing to the Space Station 14 repository. Unfortunately, it looks like you submitted your pull request from the master branch. We suggest you follow [our git usage documentation](https://docs.spacestation14.com/en/general-development/setup/git-for-the-ss14-developer.html) \n\n You can move your current work from the master branch to another branch by doing `git branch <branch_name` and resetting the master branch. \n\n This pr won't be automatically closed. However, a maintainer may close it for this reason."
|
||||
})
|
||||
#- uses: actions/github-script@v7
|
||||
# with:
|
||||
# script: |
|
||||
# github.rest.issues.createComment({
|
||||
# issue_number: ${{ github.event.number }},
|
||||
# owner: context.repo.owner,
|
||||
# repo: context.repo.repo,
|
||||
# body: "Thank you for contributing to the Monolith repository. Unfortunately, it looks like you submitted your pull request from the master branch. We suggest you follow [our git usage documentation](https://docs.spacestation14.com/en/general-development/setup/git-for-the-ss14-developer.html) \n\n You can move your current work from the master branch to another branch by doing `git branch <branch_name>` and resetting the master branch. \n\n This pr won't be automatically closed. However, a maintainer may close it for this reason."
|
||||
# })
|
||||
|
||||
@@ -20,7 +20,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Master
|
||||
uses: actions/checkout@v3.6.0
|
||||
uses: actions/checkout@v4.2.2
|
||||
|
||||
- name: Setup Submodule
|
||||
run: |
|
||||
@@ -35,9 +35,9 @@ jobs:
|
||||
git submodule update --init --recursive
|
||||
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v3.2.0
|
||||
uses: actions/setup-dotnet@v4.1.0
|
||||
with:
|
||||
dotnet-version: 9.0.x
|
||||
dotnet-version: 10.0.x
|
||||
|
||||
- name: Install Dependencies
|
||||
run: dotnet restore
|
||||
|
||||
@@ -13,13 +13,13 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3.6.0
|
||||
- uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v3.2.0
|
||||
uses: actions/setup-dotnet@v4.1.0
|
||||
with:
|
||||
dotnet-version: 9.0.x
|
||||
dotnet-version: 10.0.x
|
||||
|
||||
- name: Get Engine Tag
|
||||
run: |
|
||||
|
||||
@@ -15,13 +15,13 @@ jobs:
|
||||
- name: Install dependencies
|
||||
run: sudo apt-get install -y python3-paramiko python3-lxml
|
||||
|
||||
- uses: actions/checkout@v3.6.0
|
||||
- uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
submodules: 'recursive'
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v3.2.0
|
||||
uses: actions/setup-dotnet@v4.1.0
|
||||
with:
|
||||
dotnet-version: 9.0.x
|
||||
dotnet-version: 10.0.x
|
||||
|
||||
- name: Get Engine Tag
|
||||
run: |
|
||||
|
||||
@@ -15,7 +15,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3.6.0
|
||||
uses: actions/checkout@v4.2.2
|
||||
|
||||
- name: Get changed files
|
||||
id: files
|
||||
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: Checkout Master
|
||||
uses: actions/checkout@v3.6.0
|
||||
uses: actions/checkout@v4.2.2
|
||||
|
||||
- name: Setup Submodule
|
||||
run: |
|
||||
@@ -53,9 +53,9 @@ jobs:
|
||||
git submodule update --init --recursive
|
||||
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v3.2.0
|
||||
uses: actions/setup-dotnet@v4.1.0
|
||||
with:
|
||||
dotnet-version: 9.0.x
|
||||
dotnet-version: 10.0.x
|
||||
|
||||
- name: Install dependencies
|
||||
run: dotnet restore
|
||||
|
||||
@@ -13,7 +13,7 @@ jobs:
|
||||
if: github.repository == 'Monolith-Station/Monolith' # Mono: space-wizards/space-station-14 > Monolith-Station/Monolith
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v3.6.0
|
||||
- uses: actions/checkout@v4.2.2
|
||||
with:
|
||||
ref: main
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
name: Validate RSIs
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3.6.0
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- name: Setup Submodule
|
||||
run: git submodule update --init
|
||||
- name: Pull engine updates
|
||||
|
||||
@@ -17,7 +17,7 @@ jobs:
|
||||
if: github.event.pull_request.draft == false
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3.6.0
|
||||
- uses: actions/checkout@v4.2.2
|
||||
- name: Setup submodule
|
||||
run: |
|
||||
git submodule update --init --recursive
|
||||
@@ -28,9 +28,9 @@ jobs:
|
||||
cd RobustToolbox/
|
||||
git submodule update --init --recursive
|
||||
- name: Setup .NET Core
|
||||
uses: actions/setup-dotnet@v3.2.0
|
||||
uses: actions/setup-dotnet@v4.1.0
|
||||
with:
|
||||
dotnet-version: 9.0.x
|
||||
dotnet-version: 10.0.x
|
||||
- name: Install dependencies
|
||||
run: dotnet restore
|
||||
- name: Build
|
||||
|
||||
@@ -1,3 +1,6 @@
|
||||
# MSbuild binlog files
|
||||
*.binlog
|
||||
|
||||
## Ignore Visual Studio temporary files, build results, and
|
||||
## files generated by popular Visual Studio add-ons.
|
||||
|
||||
|
||||
Vendored
+53
-7
@@ -13,6 +13,26 @@
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false
|
||||
},
|
||||
{
|
||||
"name": "Client - Tools",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build - Tools",
|
||||
"program": "${workspaceFolder}/bin/Content.Client/Content.Client.dll",
|
||||
"args": [],
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false
|
||||
},
|
||||
{
|
||||
"name": "Client - Release",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build - Release",
|
||||
"program": "${workspaceFolder}/bin/Content.Client/Content.Client.dll",
|
||||
"args": [],
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false
|
||||
},
|
||||
{
|
||||
"name": "Client (Compatibility renderer)",
|
||||
"type": "coreclr",
|
||||
@@ -31,6 +51,26 @@
|
||||
"console": "integratedTerminal",
|
||||
"stopAtEntry": false
|
||||
},
|
||||
{
|
||||
"name": "Server - Tools",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build - Tools",
|
||||
"program": "${workspaceFolder}/bin/Content.Server/Content.Server.dll",
|
||||
"args": [""],
|
||||
"console": "integratedTerminal",
|
||||
"stopAtEntry": false
|
||||
},
|
||||
{
|
||||
"name": "Server - Release",
|
||||
"type": "coreclr",
|
||||
"request": "launch",
|
||||
"preLaunchTask": "build - Release",
|
||||
"program": "${workspaceFolder}/bin/Content.Server/Content.Server.dll",
|
||||
"args": [""],
|
||||
"console": "integratedTerminal",
|
||||
"stopAtEntry": false
|
||||
},
|
||||
{
|
||||
"name": "YAML Linter",
|
||||
"type": "coreclr",
|
||||
@@ -40,7 +80,7 @@
|
||||
"cwd": "${workspaceFolder}/Content.YAMLLinter",
|
||||
"console": "internalConsole",
|
||||
"stopAtEntry": false
|
||||
}
|
||||
},
|
||||
],
|
||||
"compounds": [
|
||||
{
|
||||
@@ -51,14 +91,21 @@
|
||||
],
|
||||
"preLaunchTask": "build"
|
||||
},
|
||||
// Frontier begin
|
||||
{
|
||||
"name": "Server/Client (Release)",
|
||||
"name": "Server/Client - Tools",
|
||||
"configurations": [
|
||||
"Server",
|
||||
"Client"
|
||||
"Server - Tools",
|
||||
"Client - Tools"
|
||||
],
|
||||
"preLaunchTask": "build-release"
|
||||
"preLaunchTask": "build - Tools"
|
||||
},
|
||||
{
|
||||
"name": "Server/Client - Release",
|
||||
"configurations": [
|
||||
"Server - Release",
|
||||
"Client - Release"
|
||||
],
|
||||
"preLaunchTask": "build - Release"
|
||||
},
|
||||
{
|
||||
"name": "Server/Client (No Build)",
|
||||
@@ -67,6 +114,5 @@
|
||||
"Client"
|
||||
]
|
||||
}
|
||||
// Frontier end
|
||||
]
|
||||
}
|
||||
|
||||
Vendored
+26
-6
@@ -21,26 +21,46 @@
|
||||
},
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
// Frontier begin
|
||||
{
|
||||
"label": "build-release",
|
||||
"label": "build - Tools",
|
||||
"command": "dotnet",
|
||||
"type": "shell",
|
||||
"args": [
|
||||
"build",
|
||||
"--configuration=Release", // Build in release mode. Note: --, not /. /configuration doesn't work, because Microsoft.
|
||||
"--configuration",
|
||||
"Tools",
|
||||
"/property:GenerateFullPaths=true", // Ask dotnet build to generate full paths for file names.
|
||||
"/consoleloggerparameters:NoSummary" // Do not generate summary otherwise it leads to duplicate errors in Problems panel
|
||||
"/consoleloggerparameters:'ForceNoAlign;NoSummary'", // Do not generate summary otherwise it leads to duplicate errors in Problems panel
|
||||
],
|
||||
"group": {
|
||||
"kind": "build"
|
||||
"kind": "build",
|
||||
"isDefault": false
|
||||
},
|
||||
"presentation": {
|
||||
"reveal": "silent"
|
||||
},
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
{
|
||||
"label": "build - Release",
|
||||
"command": "dotnet",
|
||||
"type": "shell",
|
||||
"args": [
|
||||
"build",
|
||||
"--configuration",
|
||||
"Release",
|
||||
"/property:GenerateFullPaths=true", // Ask dotnet build to generate full paths for file names.
|
||||
"/consoleloggerparameters:'ForceNoAlign;NoSummary'", // Do not generate summary otherwise it leads to duplicate errors in Problems panel
|
||||
],
|
||||
"group": {
|
||||
"kind": "build",
|
||||
"isDefault": false
|
||||
},
|
||||
"presentation": {
|
||||
"reveal": "silent"
|
||||
},
|
||||
"problemMatcher": "$msCompile"
|
||||
},
|
||||
// Frontier end
|
||||
{
|
||||
"label": "build-yaml-linter",
|
||||
"command": "dotnet",
|
||||
|
||||
@@ -8,7 +8,7 @@ import shutil
|
||||
from pathlib import Path
|
||||
from typing import List
|
||||
|
||||
SOLUTION_PATH = Path("..") / "SpaceStation14.sln"
|
||||
SOLUTION_PATH = Path("..") / "SpaceStation14.slnx"
|
||||
# If this doesn't match the saved version we overwrite them all.
|
||||
CURRENT_HOOKS_VERSION = "2"
|
||||
QUIET = len(sys.argv) == 2 and sys.argv[1] == "--quiet"
|
||||
|
||||
@@ -1,17 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<Import Project="..\RobustToolbox\MSBuild\Robust.Properties.targets" />
|
||||
<PropertyGroup>
|
||||
<!-- Work around https://github.com/dotnet/project-system/issues/4314 -->
|
||||
<TargetFramework>$(TargetFramework)</TargetFramework>
|
||||
<OutputPath>..\bin\Content.Benchmarks\</OutputPath>
|
||||
<IsPackable>false</IsPackable>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<OutputType>Exe</OutputType>
|
||||
<AllowUnsafeBlocks>true</AllowUnsafeBlocks>
|
||||
<LangVersion>12</LangVersion>
|
||||
<IsTestingPlatformApplication>false</IsTestingPlatformApplication>
|
||||
<Nullable>disable</Nullable>
|
||||
</PropertyGroup>
|
||||
<Import Project="../MSBuild/Content.props" />
|
||||
<ItemGroup>
|
||||
<PackageReference Include="BenchmarkDotNet" />
|
||||
|
||||
<!-- pin transitive deps -->
|
||||
<PackageReference Include="System.Management" />
|
||||
<PackageReference Include="Microsoft.CodeAnalysis.CSharp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Content.Client\Content.Client.csproj" />
|
||||
@@ -19,10 +22,12 @@
|
||||
<ProjectReference Include="..\Content.Shared\Content.Shared.csproj" />
|
||||
<ProjectReference Include="..\Content.Tests\Content.Tests.csproj" />
|
||||
<ProjectReference Include="..\Content.IntegrationTests\Content.IntegrationTests.csproj" />
|
||||
<ProjectReference Include="..\RobustToolbox\Robust.Benchmarks\Robust.Benchmarks.csproj" />
|
||||
<ProjectReference Include="..\RobustToolbox\Robust.Client\Robust.Client.csproj" />
|
||||
<ProjectReference Include="..\RobustToolbox\Robust.Server\Robust.Server.csproj" />
|
||||
<ProjectReference Include="..\RobustToolbox\Robust.Shared.Maths\Robust.Shared.Maths.csproj" />
|
||||
<ProjectReference Include="..\RobustToolbox\Robust.Shared\Robust.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\RobustToolbox\Imports\Lidgren.props" />
|
||||
<Import Project="..\RobustToolbox\Imports\Client.props" />
|
||||
<Import Project="..\RobustToolbox\Imports\Server.props" />
|
||||
<Import Project="..\RobustToolbox\Imports\Shared.props" />
|
||||
<Import Project="..\RobustToolbox\Imports\Benchmarks.props" />
|
||||
<Import Project="..\RobustToolbox\Imports\Testing.props" />
|
||||
</Project>
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
// Global usings for Content.Benchmarks
|
||||
|
||||
global using Robust.UnitTesting.Pool;
|
||||
@@ -51,6 +51,8 @@ internal sealed class AdminNameOverlay : Overlay
|
||||
|
||||
//TODO make this adjustable via GUI
|
||||
var classic = _config.GetCVar(CCVars.AdminOverlayClassic);
|
||||
var playTime = _config.GetCVar(CCVars.AdminOverlayPlaytime);
|
||||
var startingJob = _config.GetCVar(CCVars.AdminOverlayStartingJob);
|
||||
|
||||
foreach (var playerInfo in _system.PlayerList)
|
||||
{
|
||||
@@ -77,25 +79,50 @@ internal sealed class AdminNameOverlay : Overlay
|
||||
}
|
||||
|
||||
var uiScale = _userInterfaceManager.RootControl.UIScale;
|
||||
var lineoffset = new Vector2(0f, 11f) * uiScale;
|
||||
var lineoffset = new Vector2(0f, 14f) * uiScale;
|
||||
var screenCoordinates = _eyeManager.WorldToScreen(aabb.Center +
|
||||
new Angle(-_eyeManager.CurrentEye.Rotation).RotateVec(
|
||||
aabb.TopRight - aabb.Center)) + new Vector2(1f, 7f);
|
||||
var balance = playerInfo.Balance == int.MinValue ? "NO BALANCE" : BankSystemExtensions.ToCurrencyString(playerInfo.Balance); // Frontier
|
||||
|
||||
var currentOffset = Vector2.Zero;
|
||||
|
||||
args.ScreenHandle.DrawString(_font, screenCoordinates + currentOffset, playerInfo.CharacterName, uiScale, playerInfo.Connected ? Color.Aquamarine : Color.White);
|
||||
currentOffset += lineoffset;
|
||||
|
||||
args.ScreenHandle.DrawString(_font, screenCoordinates + currentOffset, playerInfo.Username, uiScale, playerInfo.Connected ? Color.Yellow : Color.White);
|
||||
currentOffset += lineoffset;
|
||||
|
||||
var balance = playerInfo.Balance == int.MinValue
|
||||
? "NO BALANCE"
|
||||
: BankSystemExtensions.ToCurrencyString(playerInfo.Balance);
|
||||
args.ScreenHandle.DrawString(_font, screenCoordinates + currentOffset, $"Balance: {balance}", uiScale, playerInfo.Connected ? Color.Aquamarine : Color.White);
|
||||
currentOffset += lineoffset;
|
||||
|
||||
if (!string.IsNullOrEmpty(playerInfo.PlaytimeString) && playTime)
|
||||
{
|
||||
args.ScreenHandle.DrawString(_font, screenCoordinates + currentOffset, playerInfo.PlaytimeString, uiScale, playerInfo.Connected ? Color.Orange : Color.White);
|
||||
currentOffset += lineoffset;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(playerInfo.StartingJob) && startingJob)
|
||||
{
|
||||
args.ScreenHandle.DrawString(_font, screenCoordinates + currentOffset, Loc.GetString(playerInfo.StartingJob), uiScale, playerInfo.Connected ? Color.GreenYellow : Color.White);
|
||||
currentOffset += lineoffset;
|
||||
}
|
||||
|
||||
if (classic && playerInfo.Antag)
|
||||
{
|
||||
args.ScreenHandle.DrawString(_font, screenCoordinates + (lineoffset * 3), _antagLabelClassic, uiScale, _antagColorClassic); // Frontier: 2<3
|
||||
args.ScreenHandle.DrawString(_font, screenCoordinates + currentOffset, _antagLabelClassic, uiScale, Color.OrangeRed);
|
||||
currentOffset += lineoffset;
|
||||
}
|
||||
else if (!classic && _filter.Contains(playerInfo.RoleProto))
|
||||
{
|
||||
var label = Loc.GetString(playerInfo.RoleProto.Name).ToUpper();
|
||||
var color = playerInfo.RoleProto.Color;
|
||||
|
||||
args.ScreenHandle.DrawString(_font, screenCoordinates + (lineoffset * 3), label, uiScale, color); // Frontier: 2<3
|
||||
args.ScreenHandle.DrawString(_font, screenCoordinates + currentOffset, label, uiScale, color);
|
||||
currentOffset += lineoffset;
|
||||
}
|
||||
args.ScreenHandle.DrawString(_font, screenCoordinates+lineoffset, playerInfo.Username, uiScale, playerInfo.Connected ? Color.Yellow : Color.White);
|
||||
args.ScreenHandle.DrawString(_font, screenCoordinates, playerInfo.CharacterName, uiScale, playerInfo.Connected ? Color.Aquamarine : Color.White);
|
||||
args.ScreenHandle.DrawString(_font, screenCoordinates + lineoffset * 2, $"Balance: {balance}", uiScale, playerInfo.Connected ? Color.Aquamarine : Color.White); // Frontier
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
<Control
|
||||
xmlns="https://spacestation14.io"
|
||||
xmlns:viewport="clr-namespace:Content.Client.Viewport"
|
||||
MouseFilter="Stop">
|
||||
<PanelContainer StyleClasses="BackgroundDark" Name="AdminCameraWindowRoot" Access="Public">
|
||||
<BoxContainer Orientation="Vertical" Access="Public">
|
||||
<!-- Camera -->
|
||||
<Control VerticalExpand="True" Name="CameraViewBox">
|
||||
<viewport:ScalingViewport Name="CameraView"
|
||||
MinSize="100 100"
|
||||
MouseFilter="Ignore" />
|
||||
</Control>
|
||||
<!-- Controller buttons -->
|
||||
<BoxContainer Orientation="Horizontal" Margin="5 5 5 5">
|
||||
<Button StyleClasses="OpenRight" Name="FollowButton" HorizontalExpand="True" Access="Public" Text="{Loc 'admin-camera-window-follow'}" />
|
||||
<Button StyleClasses="OpenLeft" Name="PopControl" HorizontalExpand="True" Access="Public" Text="{Loc 'admin-camera-window-pop-out'}" />
|
||||
</BoxContainer>
|
||||
</BoxContainer>
|
||||
</PanelContainer>
|
||||
</Control>
|
||||
@@ -0,0 +1,101 @@
|
||||
using System.Numerics;
|
||||
using Content.Client.Eye;
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.Timing;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Timing;
|
||||
|
||||
namespace Content.Client.Administration.UI.AdminCamera;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class AdminCameraControl : Control
|
||||
{
|
||||
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||
[Dependency] private readonly IClientGameTiming _timing = default!;
|
||||
|
||||
public event Action? OnFollow;
|
||||
public event Action? OnPopoutControl;
|
||||
|
||||
private readonly EyeLerpingSystem _eyeLerpingSystem;
|
||||
private readonly FixedEye _defaultEye = new();
|
||||
private AdminCameraEuiState? _nextState;
|
||||
|
||||
private const float MinimumZoom = 0.1f;
|
||||
private const float MaximumZoom = 2.0f;
|
||||
|
||||
public EntityUid? CurrentCamera;
|
||||
public float Zoom = 1.0f;
|
||||
|
||||
public bool IsPoppedOut;
|
||||
|
||||
public AdminCameraControl()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
_eyeLerpingSystem = _entManager.System<EyeLerpingSystem>();
|
||||
|
||||
CameraView.Eye = _defaultEye;
|
||||
|
||||
FollowButton.OnPressed += _ => OnFollow?.Invoke();
|
||||
PopControl.OnPressed += _ => OnPopoutControl?.Invoke();
|
||||
CameraView.OnResized += OnResized;
|
||||
}
|
||||
|
||||
private new void OnResized()
|
||||
{
|
||||
var width = Math.Max(CameraView.PixelWidth, (int)Math.Floor(CameraView.MinWidth));
|
||||
var height = Math.Max(CameraView.PixelHeight, (int)Math.Floor(CameraView.MinHeight));
|
||||
|
||||
CameraView.ViewportSize = new Vector2i(width, height);
|
||||
}
|
||||
|
||||
protected override void MouseWheel(GUIMouseWheelEventArgs args)
|
||||
{
|
||||
base.MouseWheel(args);
|
||||
|
||||
if (CameraView.Eye == null)
|
||||
return;
|
||||
|
||||
Zoom = Math.Clamp(Zoom - args.Delta.Y * 0.15f * Zoom, MinimumZoom, MaximumZoom);
|
||||
CameraView.Eye.Zoom = new Vector2(Zoom, Zoom);
|
||||
args.Handle();
|
||||
}
|
||||
|
||||
public void SetState(AdminCameraEuiState state)
|
||||
{
|
||||
_nextState = state;
|
||||
}
|
||||
|
||||
// I know that this is awful, but I copied this from the solution editor anyways.
|
||||
// This is needed because EUIs update before the gamestate is applied, which means it will fail to get the uid from the net entity.
|
||||
// The suggestion from the comment in the solution editor saying to use a BUI is not ideal either:
|
||||
// - We would need to bind the UI to an entity, but with how BUIs currently work we cannot open it in the same tick as we spawn that entity on the server.
|
||||
// - We want the UI opened by the user session, not by their currently attached entity. Otherwise it would close in cases where admins move from one entity to another, for example when ghosting.
|
||||
protected override void FrameUpdate(FrameEventArgs args)
|
||||
{
|
||||
if (_nextState == null || _timing.LastRealTick < _nextState.Tick) // make sure the last gamestate has been applied
|
||||
return;
|
||||
|
||||
if (!_entManager.TryGetEntity(_nextState.Camera, out var cameraUid))
|
||||
return;
|
||||
|
||||
if (CurrentCamera == null)
|
||||
{
|
||||
_eyeLerpingSystem.AddEye(cameraUid.Value);
|
||||
CurrentCamera = cameraUid;
|
||||
}
|
||||
else if (CurrentCamera != cameraUid)
|
||||
{
|
||||
_eyeLerpingSystem.RemoveEye(CurrentCamera.Value);
|
||||
_eyeLerpingSystem.AddEye(cameraUid.Value);
|
||||
CurrentCamera = cameraUid;
|
||||
}
|
||||
|
||||
if (_entManager.TryGetComponent<EyeComponent>(CurrentCamera, out var eye))
|
||||
CameraView.Eye = eye.Eye ?? _defaultEye;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,117 @@
|
||||
using System.Numerics;
|
||||
using Content.Client.Eui;
|
||||
using Content.Shared.Administration;
|
||||
using Content.Shared.Eui;
|
||||
using JetBrains.Annotations;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
|
||||
namespace Content.Client.Administration.UI.AdminCamera;
|
||||
|
||||
/// <summary>
|
||||
/// Admin Eui for opening a viewport window to observe entities.
|
||||
/// Use the "Open Camera" admin verb or the "camera" command to open.
|
||||
/// </summary>
|
||||
[UsedImplicitly]
|
||||
public sealed partial class AdminCameraEui : BaseEui
|
||||
{
|
||||
private readonly AdminCameraWindow _window;
|
||||
private readonly AdminCameraControl _control;
|
||||
|
||||
// If not null the camera is in "popped out" mode and is in an external window.
|
||||
private OSWindow? _OSWindow;
|
||||
|
||||
// The last location the window was located at in game.
|
||||
// Is used for getting knowing where to "pop in" external windows.
|
||||
private Vector2 _lastLocation;
|
||||
|
||||
public AdminCameraEui()
|
||||
{
|
||||
_window = new AdminCameraWindow();
|
||||
_control = new AdminCameraControl();
|
||||
|
||||
_window.Contents.AddChild(_control);
|
||||
|
||||
_control.OnFollow += () => SendMessage(new AdminCameraFollowMessage());
|
||||
_window.OnClose += () =>
|
||||
{
|
||||
if (!_control.IsPoppedOut)
|
||||
SendMessage(new CloseEuiMessage());
|
||||
};
|
||||
|
||||
_control.OnPopoutControl += () =>
|
||||
{
|
||||
if (_control.IsPoppedOut)
|
||||
PopIn();
|
||||
else
|
||||
PopOut();
|
||||
};
|
||||
}
|
||||
|
||||
// Pop the window out into an external OS window
|
||||
private void PopOut()
|
||||
{
|
||||
_lastLocation = _window.Position;
|
||||
|
||||
// TODO: When there is a way to have a minimum window size, enforce something!
|
||||
_OSWindow = new OSWindow
|
||||
{
|
||||
SetSize = _window.Size,
|
||||
Title = _window.Title ?? Loc.GetString("admin-camera-window-title-placeholder"),
|
||||
};
|
||||
|
||||
_OSWindow.Show();
|
||||
|
||||
if (_OSWindow.Root == null)
|
||||
return;
|
||||
|
||||
_control.Orphan();
|
||||
_OSWindow.Root.AddChild(_control);
|
||||
|
||||
_OSWindow.Closed += () =>
|
||||
{
|
||||
if (_control.IsPoppedOut)
|
||||
SendMessage(new CloseEuiMessage());
|
||||
};
|
||||
|
||||
_control.IsPoppedOut = true;
|
||||
_control.PopControl.Text = Loc.GetString("admin-camera-window-pop-in");
|
||||
|
||||
_window.Close();
|
||||
}
|
||||
|
||||
// Pop the window back into the in game window.
|
||||
private void PopIn()
|
||||
{
|
||||
_control.Orphan();
|
||||
_window.Contents.AddChild(_control);
|
||||
|
||||
_window.Open(_lastLocation);
|
||||
|
||||
_control.IsPoppedOut = false;
|
||||
_control.PopControl.Text = Loc.GetString("admin-camera-window-pop-out");
|
||||
|
||||
_OSWindow?.Close();
|
||||
_OSWindow = null;
|
||||
}
|
||||
|
||||
public override void Opened()
|
||||
{
|
||||
base.Opened();
|
||||
_window.OpenCentered();
|
||||
}
|
||||
|
||||
public override void Closed()
|
||||
{
|
||||
base.Closed();
|
||||
_window.Close();
|
||||
}
|
||||
|
||||
public override void HandleState(EuiStateBase baseState)
|
||||
{
|
||||
if (baseState is not AdminCameraEuiState state)
|
||||
return;
|
||||
|
||||
_window.SetState(state);
|
||||
_control.SetState(state);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,6 @@
|
||||
<DefaultWindow xmlns="https://spacestation14.io"
|
||||
Title="{Loc admin-camera-window-title-placeholder}"
|
||||
SetSize="425 550"
|
||||
MinSize="200 225"
|
||||
Name="Window">
|
||||
</DefaultWindow>
|
||||
@@ -0,0 +1,23 @@
|
||||
using Content.Shared.Administration;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface.CustomControls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
|
||||
namespace Content.Client.Administration.UI.AdminCamera;
|
||||
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class AdminCameraWindow : DefaultWindow
|
||||
{
|
||||
public AdminCameraWindow()
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
|
||||
ContentsContainer.Margin = new Thickness(5, 0, 5, 0);
|
||||
}
|
||||
|
||||
public void SetState(AdminCameraEuiState state)
|
||||
{
|
||||
Title = Loc.GetString("admin-camera-window-title", ("name", state.Name));
|
||||
}
|
||||
}
|
||||
@@ -30,6 +30,7 @@
|
||||
<Button Name="FreezeAndMuteToggleButton" Text="{Loc player-panel-freeze-and-mute}" Disabled="True"/>
|
||||
<Button Name="BanButton" Text="{Loc player-panel-ban}" Disabled="True"/>
|
||||
<controls:ConfirmButton Name="RejuvenateButton" Text="{Loc player-panel-rejuvenate}" Disabled="True"/>
|
||||
<Button Name="CameraButton" Text="{Loc player-panel-camera}" Disabled="True"/>
|
||||
</GridContainer>
|
||||
<Button Name="JobWhitelistsButton" Text="{Loc player-panel-job-whitelists}" SetWidth="136" SetHeight="27" Disabled="True"/> <!-- DeltaV: Job whitelists -->
|
||||
</BoxContainer>
|
||||
|
||||
@@ -19,6 +19,7 @@ public sealed partial class PlayerPanel : FancyWindow
|
||||
public event Action<NetUserId?>? OnOpenBans;
|
||||
public event Action<NetUserId?>? OnAhelp;
|
||||
public event Action<string?>? OnKick;
|
||||
public event Action<string?>? OnCamera;
|
||||
public event Action<NetUserId?>? OnOpenBanPanel;
|
||||
public event Action<NetUserId?, bool>? OnWhitelistToggle;
|
||||
public event Action? OnFreezeAndMuteToggle;
|
||||
@@ -40,6 +41,7 @@ public sealed partial class PlayerPanel : FancyWindow
|
||||
UsernameCopyButton.OnPressed += _ => OnUsernameCopy?.Invoke(PlayerName.Text ?? "");
|
||||
BanButton.OnPressed += _ => OnOpenBanPanel?.Invoke(TargetPlayer);
|
||||
KickButton.OnPressed += _ => OnKick?.Invoke(TargetUsername);
|
||||
CameraButton.OnPressed += _ => OnCamera?.Invoke(TargetUsername);
|
||||
NotesButton.OnPressed += _ => OnOpenNotes?.Invoke(TargetPlayer);
|
||||
ShowBansButton.OnPressed += _ => OnOpenBans?.Invoke(TargetPlayer);
|
||||
AhelpButton.OnPressed += _ => OnAhelp?.Invoke(TargetPlayer);
|
||||
@@ -132,5 +134,6 @@ public sealed partial class PlayerPanel : FancyWindow
|
||||
RejuvenateButton.Disabled = !_adminManager.HasFlag(AdminFlags.Debug);
|
||||
DeleteButton.Disabled = !_adminManager.HasFlag(AdminFlags.Debug);
|
||||
JobWhitelistsButton.Disabled = !_adminManager.HasFlag(AdminFlags.Whitelist); // DeltaV
|
||||
CameraButton.Disabled = !_adminManager.CanCommand("camera");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,6 +25,7 @@ public sealed class PlayerPanelEui : BaseEui
|
||||
PlayerPanel.OnOpenNotes += id => _console.ExecuteCommand($"adminnotes \"{id}\"");
|
||||
// Kick command does not support GUIDs
|
||||
PlayerPanel.OnKick += username => _console.ExecuteCommand($"kick \"{username}\"");
|
||||
PlayerPanel.OnCamera += username => _console.ExecuteCommand($"camera \"{username}\"");
|
||||
PlayerPanel.OnOpenBanPanel += id => _console.ExecuteCommand($"banpanel \"{id}\"");
|
||||
PlayerPanel.OnOpenBans += id => _console.ExecuteCommand($"banlist \"{id}\"");
|
||||
PlayerPanel.OnAhelp += id => _console.ExecuteCommand($"openahelp \"{id}\"");
|
||||
|
||||
@@ -8,6 +8,8 @@ namespace Content.Client.AlertLevel;
|
||||
|
||||
public sealed class AlertLevelDisplaySystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -21,26 +23,26 @@ public sealed class AlertLevelDisplaySystem : EntitySystem
|
||||
{
|
||||
return;
|
||||
}
|
||||
var layer = args.Sprite.LayerMapReserveBlank(AlertLevelDisplay.Layer);
|
||||
var layer = _sprite.LayerMapReserve((uid, args.Sprite), AlertLevelDisplay.Layer);
|
||||
|
||||
if (args.AppearanceData.TryGetValue(AlertLevelDisplay.Powered, out var poweredObject))
|
||||
{
|
||||
args.Sprite.LayerSetVisible(layer, poweredObject is true);
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), layer, poweredObject is true);
|
||||
}
|
||||
|
||||
if (!args.AppearanceData.TryGetValue(AlertLevelDisplay.CurrentLevel, out var level))
|
||||
{
|
||||
args.Sprite.LayerSetState(layer, alertLevelDisplay.AlertVisuals.Values.First());
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), layer, alertLevelDisplay.AlertVisuals.Values.First());
|
||||
return;
|
||||
}
|
||||
|
||||
if (alertLevelDisplay.AlertVisuals.TryGetValue((string) level, out var visual))
|
||||
if (alertLevelDisplay.AlertVisuals.TryGetValue((string)level, out var visual))
|
||||
{
|
||||
args.Sprite.LayerSetState(layer, visual);
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), layer, visual);
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Sprite.LayerSetState(layer, alertLevelDisplay.AlertVisuals.Values.First());
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), layer, alertLevelDisplay.AlertVisuals.Values.First());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,253 @@
|
||||
using Content.Client.Atmos.EntitySystems;
|
||||
using Content.Shared.Atmos;
|
||||
using Content.Shared.Atmos.Components;
|
||||
using Content.Shared.Atmos.EntitySystems;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Map.Components;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Content.Client.Atmos.Overlays;
|
||||
|
||||
/// <summary>
|
||||
/// Renders a thermal heatmap overlay for gas tiles, used for equipment like thermal glasses.
|
||||
/// /// </summary>
|
||||
public sealed class GasTileDangerousTemperatureOverlay : Overlay
|
||||
{
|
||||
public override bool RequestScreenTexture { get; set; } = false;
|
||||
|
||||
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly IClyde _clyde = default!;
|
||||
|
||||
private GasTileOverlaySystem? _gasTileOverlay;
|
||||
private readonly SharedTransformSystem _xformSys;
|
||||
private EntityQuery<GasTileOverlayComponent> _overlayQuery;
|
||||
|
||||
private IRenderTexture? _temperatureTarget;
|
||||
|
||||
// Cache used to transform ThermalByte into Color for overlay
|
||||
private readonly Color[] _colorCache = new Color[256];
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV;
|
||||
|
||||
public GasTileDangerousTemperatureOverlay()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
_xformSys = _entManager.System<SharedTransformSystem>();
|
||||
|
||||
_overlayQuery = _entManager.GetEntityQuery<GasTileOverlayComponent>();
|
||||
|
||||
for (byte i = 0; i <= ThermalByte.TempResolution; i++)
|
||||
{
|
||||
_colorCache[i] = PreCalculateColor(i);
|
||||
}
|
||||
|
||||
_colorCache[ThermalByte.StateVacuum] = Color.Teal;
|
||||
_colorCache[ThermalByte.StateVacuum].A = 0.6f;
|
||||
_colorCache[ThermalByte.AtmosImpossible] = Color.Transparent;
|
||||
|
||||
#if DEBUG // This shouldn't happend so tell me if you see this LimeGreen on the screen
|
||||
_colorCache[ThermalByte.ReservedFuture0] = Color.LimeGreen;
|
||||
_colorCache[ThermalByte.ReservedFuture1] = Color.LimeGreen;
|
||||
_colorCache[ThermalByte.ReservedFuture2] = Color.LimeGreen;
|
||||
#else
|
||||
_colorCache[ThermalByte.ReservedFuture0] = Color.Transparent;
|
||||
_colorCache[ThermalByte.ReservedFuture1] = Color.Transparent;
|
||||
_colorCache[ThermalByte.ReservedFuture2] = Color.Transparent;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Used for Calculating onscreen color from ThermalByte core value
|
||||
/// /// </summary>
|
||||
private static Color PreCalculateColor(byte byteTemp)
|
||||
{
|
||||
// Color Thresholds in Kelvin
|
||||
// -150 C
|
||||
const float deepFreezeK = 123.15f;
|
||||
// -50 C
|
||||
const float freezeStartK = 223.15f;
|
||||
// 0 C
|
||||
const float waterFreezeK = 273.15f;
|
||||
// 50 C
|
||||
const float heatStartK = 323.15f;
|
||||
// 100 C
|
||||
const float waterBoilK = 373.15f;
|
||||
// 300 C
|
||||
const float superHeatK = 573.15f;
|
||||
|
||||
var tempK = byteTemp * ThermalByte.TempDegreeResolution;
|
||||
|
||||
// Neutral Zone Check (0C to 50C)
|
||||
// If between 273.15K and 323.15K, it's transparent.
|
||||
if (tempK >= waterFreezeK && tempK < heatStartK)
|
||||
{
|
||||
return Color.Transparent;
|
||||
}
|
||||
|
||||
Color resultingColor;
|
||||
|
||||
switch (tempK)
|
||||
{
|
||||
case < deepFreezeK:
|
||||
resultingColor = Color.FromHex("#330066");
|
||||
resultingColor.A = 0.7f;
|
||||
break;
|
||||
case < freezeStartK:
|
||||
// Interpolate Deep Purple -> Blue
|
||||
// Range: 123.15 to 223.15 (Span: 100)
|
||||
resultingColor = Color.InterpolateBetween(
|
||||
Color.FromHex("#330066"),
|
||||
Color.Blue,
|
||||
(tempK - deepFreezeK) * 0.01f);
|
||||
resultingColor.A = 0.6f;
|
||||
break;
|
||||
case < waterFreezeK:
|
||||
// Interpolate Blue -> Transparent
|
||||
// Range: 223.15 to 273.15 (Span: 50)
|
||||
|
||||
resultingColor = Color.InterpolateBetween(
|
||||
new Color(Color.Blue.R, Color.Blue.G, Color.Blue.B, 0.6f),
|
||||
new Color(Color.Blue.R, Color.Blue.G, Color.Blue.B, 0.2f),
|
||||
(tempK - freezeStartK) * 0.02f);
|
||||
break;
|
||||
case < waterBoilK:
|
||||
// Interpolate Transparent -> Yellow
|
||||
// Range: 323.15 to 373.15 (Span: 50)
|
||||
|
||||
resultingColor = Color.InterpolateBetween(
|
||||
new Color(Color.Yellow.R, Color.Yellow.G, Color.Yellow.B, 0.2f),
|
||||
new Color(Color.Yellow.R, Color.Yellow.G, Color.Yellow.B, 0.6f),
|
||||
(tempK - heatStartK) * 0.02f);
|
||||
break;
|
||||
case < superHeatK:
|
||||
// Interpolate Yellow -> Red
|
||||
// Range: 373.15 to 573.15 (Span: 200)
|
||||
resultingColor = Color.InterpolateBetween(
|
||||
Color.Yellow,
|
||||
Color.Red,
|
||||
(tempK - waterBoilK) * 0.005f);
|
||||
resultingColor.A = 0.6f;
|
||||
break;
|
||||
default:
|
||||
resultingColor = Color.DarkRed;
|
||||
resultingColor.A = 0.7f;
|
||||
break;
|
||||
}
|
||||
|
||||
return resultingColor;
|
||||
}
|
||||
|
||||
protected override bool BeforeDraw(in OverlayDrawArgs args)
|
||||
{
|
||||
if (args.MapId == MapId.Nullspace)
|
||||
return false;
|
||||
|
||||
_gasTileOverlay ??= _entManager.System<GasTileOverlaySystem>();
|
||||
if (_gasTileOverlay == null)
|
||||
return false;
|
||||
|
||||
var target = args.Viewport.RenderTarget;
|
||||
|
||||
if (_temperatureTarget?.Texture.Size != target.Size)
|
||||
{
|
||||
_temperatureTarget?.Dispose();
|
||||
_temperatureTarget = _clyde.CreateRenderTarget(
|
||||
target.Size,
|
||||
new RenderTargetFormatParameters(RenderTargetColorFormat.Rgba8Srgb),
|
||||
name: nameof(GasTileDangerousTemperatureOverlay));
|
||||
}
|
||||
|
||||
var drawHandle = args.WorldHandle;
|
||||
var worldBounds = args.WorldBounds;
|
||||
var worldAABB = args.WorldAABB;
|
||||
var mapId = args.MapId;
|
||||
var worldToViewportLocal = args.Viewport.GetWorldToLocalMatrix();
|
||||
|
||||
var anyGasDrawn = false;
|
||||
List<Entity<MapGridComponent>> grids = new();
|
||||
|
||||
drawHandle.RenderInRenderTarget(_temperatureTarget,
|
||||
() =>
|
||||
{
|
||||
grids.Clear();
|
||||
_mapManager.FindGridsIntersecting(mapId, worldAABB, ref grids);
|
||||
|
||||
foreach (var grid in grids)
|
||||
{
|
||||
if (!_overlayQuery.TryGetComponent(grid.Owner, out var comp))
|
||||
continue;
|
||||
|
||||
var gridTileSizeVec = grid.Comp.TileSizeVector;
|
||||
var gridTileCenterVec = grid.Comp.TileSizeHalfVector;
|
||||
var gridEntToWorld = _xformSys.GetWorldMatrix(grid.Owner);
|
||||
var gridEntToViewportLocal = gridEntToWorld * worldToViewportLocal;
|
||||
|
||||
drawHandle.SetTransform(gridEntToViewportLocal);
|
||||
|
||||
var worldToGridLocal = _xformSys.GetInvWorldMatrix(grid.Owner);
|
||||
var floatBounds = worldToGridLocal.TransformBox(worldBounds).Enlarged(grid.Comp.TileSize);
|
||||
|
||||
var localBounds = new Box2i(
|
||||
(int)MathF.Floor(floatBounds.Left),
|
||||
(int)MathF.Floor(floatBounds.Bottom),
|
||||
(int)MathF.Ceiling(floatBounds.Right),
|
||||
(int)MathF.Ceiling(floatBounds.Top));
|
||||
|
||||
foreach (var chunk in comp.Chunks.Values)
|
||||
{
|
||||
var enumerator = new GasChunkEnumerator(chunk);
|
||||
while (enumerator.MoveNext(out var tileGas))
|
||||
{
|
||||
var tilePosition = chunk.Origin + (enumerator.X, enumerator.Y);
|
||||
if (!localBounds.Contains(tilePosition))
|
||||
continue;
|
||||
|
||||
var gasColor = _colorCache[tileGas.ByteGasTemperature.Value];
|
||||
|
||||
if (gasColor.A <= 0f)
|
||||
continue;
|
||||
|
||||
anyGasDrawn = true;
|
||||
|
||||
drawHandle.DrawRect(
|
||||
Box2.CenteredAround(tilePosition + gridTileCenterVec, gridTileSizeVec),
|
||||
gasColor
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
new Color(0, 0, 0, 0));
|
||||
|
||||
drawHandle.SetTransform(Matrix3x2.Identity);
|
||||
|
||||
if (!anyGasDrawn)
|
||||
{
|
||||
_temperatureTarget?.Dispose();
|
||||
_temperatureTarget = null;
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
if (_temperatureTarget is null)
|
||||
return;
|
||||
|
||||
args.WorldHandle.DrawTextureRect(_temperatureTarget.Texture, args.WorldBounds);
|
||||
args.WorldHandle.SetTransform(Matrix3x2.Identity);
|
||||
}
|
||||
|
||||
protected override void DisposeBehavior()
|
||||
{
|
||||
_temperatureTarget?.Dispose();
|
||||
_temperatureTarget = null;
|
||||
base.DisposeBehavior();
|
||||
}
|
||||
}
|
||||
@@ -36,8 +36,6 @@ public sealed partial class ContentAudioSystem
|
||||
[Dependency] private readonly IStateManager _state = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly CombatModeSystem _combatModeSystem = default!; //CLIENT ONE. WHY ARE THERE 3???
|
||||
[Dependency] private readonly IPrototypeManager _protMan = default!;
|
||||
[Dependency] private readonly SpaceBiomeSystem _spaceBiome = default!;
|
||||
|
||||
//options menu ---
|
||||
private static float _volumeSliderAmbient;
|
||||
|
||||
@@ -12,6 +12,7 @@ public sealed class JukeboxSystem : SharedJukeboxSystem
|
||||
[Dependency] private readonly AnimationPlayerSystem _animationPlayer = default!;
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearanceSystem = default!;
|
||||
[Dependency] private readonly SharedUserInterfaceSystem _uiSystem = default!;
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -64,7 +65,7 @@ public sealed class JukeboxSystem : SharedJukeboxSystem
|
||||
visualState = JukeboxVisualState.On;
|
||||
}
|
||||
|
||||
UpdateAppearance(uid, visualState, component, sprite);
|
||||
UpdateAppearance((uid, sprite), visualState, component);
|
||||
}
|
||||
|
||||
private void OnAppearanceChange(EntityUid uid, JukeboxComponent component, ref AppearanceChangeEvent args)
|
||||
@@ -78,25 +79,25 @@ public sealed class JukeboxSystem : SharedJukeboxSystem
|
||||
visualState = JukeboxVisualState.On;
|
||||
}
|
||||
|
||||
UpdateAppearance(uid, visualState, component, args.Sprite);
|
||||
UpdateAppearance((uid, args.Sprite), visualState, component);
|
||||
}
|
||||
|
||||
private void UpdateAppearance(EntityUid uid, JukeboxVisualState visualState, JukeboxComponent component, SpriteComponent sprite)
|
||||
private void UpdateAppearance(Entity<SpriteComponent> entity, JukeboxVisualState visualState, JukeboxComponent component)
|
||||
{
|
||||
SetLayerState(JukeboxVisualLayers.Base, component.OffState, sprite);
|
||||
SetLayerState(JukeboxVisualLayers.Base, component.OffState, entity);
|
||||
|
||||
switch (visualState)
|
||||
{
|
||||
case JukeboxVisualState.On:
|
||||
SetLayerState(JukeboxVisualLayers.Base, component.OnState, sprite);
|
||||
SetLayerState(JukeboxVisualLayers.Base, component.OnState, entity);
|
||||
break;
|
||||
|
||||
case JukeboxVisualState.Off:
|
||||
SetLayerState(JukeboxVisualLayers.Base, component.OffState, sprite);
|
||||
SetLayerState(JukeboxVisualLayers.Base, component.OffState, entity);
|
||||
break;
|
||||
|
||||
case JukeboxVisualState.Select:
|
||||
PlayAnimation(uid, JukeboxVisualLayers.Base, component.SelectState, 1.0f, sprite);
|
||||
PlayAnimation(entity.Owner, JukeboxVisualLayers.Base, component.SelectState, 1.0f, entity);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -109,7 +110,7 @@ public sealed class JukeboxSystem : SharedJukeboxSystem
|
||||
if (!_animationPlayer.HasRunningAnimation(uid, state))
|
||||
{
|
||||
var animation = GetAnimation(layer, state, animationTime);
|
||||
sprite.LayerSetVisible(layer, true);
|
||||
_sprite.LayerSetVisible((uid, sprite), layer, true);
|
||||
_animationPlayer.Play(uid, animation, state);
|
||||
}
|
||||
}
|
||||
@@ -133,13 +134,13 @@ public sealed class JukeboxSystem : SharedJukeboxSystem
|
||||
};
|
||||
}
|
||||
|
||||
private void SetLayerState(JukeboxVisualLayers layer, string? state, SpriteComponent sprite)
|
||||
private void SetLayerState(JukeboxVisualLayers layer, string? state, Entity<SpriteComponent> sprite)
|
||||
{
|
||||
if (string.IsNullOrEmpty(state))
|
||||
return;
|
||||
|
||||
sprite.LayerSetVisible(layer, true);
|
||||
sprite.LayerSetAutoAnimated(layer, true);
|
||||
sprite.LayerSetState(layer, state);
|
||||
_sprite.LayerSetVisible(sprite.AsNullable(), layer, true);
|
||||
_sprite.LayerSetAutoAnimated(sprite.AsNullable(), layer, true);
|
||||
_sprite.LayerSetRsiState(sprite.AsNullable(), layer, state);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
using Content.Client.Botany.Components;
|
||||
using Content.Shared.Botany;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client.Botany;
|
||||
|
||||
public sealed class PlantHolderVisualizerSystem : VisualizerSystem<PlantHolderVisualsComponent>
|
||||
{
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
@@ -17,8 +20,8 @@ public sealed class PlantHolderVisualizerSystem : VisualizerSystem<PlantHolderVi
|
||||
if (!TryComp<SpriteComponent>(uid, out var sprite))
|
||||
return;
|
||||
|
||||
sprite.LayerMapReserveBlank(PlantHolderLayers.Plant);
|
||||
sprite.LayerSetVisible(PlantHolderLayers.Plant, false);
|
||||
_sprite.LayerMapReserve((uid, sprite), PlantHolderLayers.Plant);
|
||||
_sprite.LayerSetVisible((uid, sprite), PlantHolderLayers.Plant, false);
|
||||
}
|
||||
|
||||
protected override void OnAppearanceChange(EntityUid uid, PlantHolderVisualsComponent component, ref AppearanceChangeEvent args)
|
||||
@@ -31,12 +34,12 @@ public sealed class PlantHolderVisualizerSystem : VisualizerSystem<PlantHolderVi
|
||||
{
|
||||
var valid = !string.IsNullOrWhiteSpace(state);
|
||||
|
||||
args.Sprite.LayerSetVisible(PlantHolderLayers.Plant, valid);
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), PlantHolderLayers.Plant, valid);
|
||||
|
||||
if (valid)
|
||||
{
|
||||
args.Sprite.LayerSetRSI(PlantHolderLayers.Plant, rsi);
|
||||
args.Sprite.LayerSetState(PlantHolderLayers.Plant, state);
|
||||
_sprite.LayerSetRsi((uid, args.Sprite), PlantHolderLayers.Plant, new ResPath(rsi));
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), PlantHolderLayers.Plant, state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ internal sealed class BuckleSystem : SharedBuckleSystem
|
||||
[Dependency] private readonly RotationVisualizerSystem _rotationVisualizerSystem = default!;
|
||||
[Dependency] private readonly IEyeManager _eye = default!;
|
||||
[Dependency] private readonly SharedTransformSystem _xformSystem = default!;
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -73,11 +74,11 @@ internal sealed class BuckleSystem : SharedBuckleSystem
|
||||
{
|
||||
// This will only assign if empty, it won't get overwritten by new depth on multiple calls, which do happen easily
|
||||
buckle.OriginalDrawDepth ??= buckledSprite.DrawDepth;
|
||||
buckledSprite.DrawDepth = strapSprite.DrawDepth - 1;
|
||||
_sprite.SetDrawDepth((buckledEntity, buckledSprite), strapSprite.DrawDepth - 1);
|
||||
}
|
||||
else if (buckle.OriginalDrawDepth.HasValue)
|
||||
{
|
||||
buckledSprite.DrawDepth = buckle.OriginalDrawDepth.Value;
|
||||
_sprite.SetDrawDepth((buckledEntity, buckledSprite), buckle.OriginalDrawDepth.Value);
|
||||
buckle.OriginalDrawDepth = null;
|
||||
}
|
||||
}
|
||||
@@ -101,7 +102,7 @@ internal sealed class BuckleSystem : SharedBuckleSystem
|
||||
return;
|
||||
|
||||
ent.Comp.OriginalDrawDepth ??= buckledSprite.DrawDepth;
|
||||
buckledSprite.DrawDepth = strapSprite.DrawDepth - 1;
|
||||
_sprite.SetDrawDepth((ent.Owner, buckledSprite), strapSprite.DrawDepth - 1);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -115,7 +116,7 @@ internal sealed class BuckleSystem : SharedBuckleSystem
|
||||
if (!ent.Comp.OriginalDrawDepth.HasValue)
|
||||
return;
|
||||
|
||||
buckledSprite.DrawDepth = ent.Comp.OriginalDrawDepth.Value;
|
||||
_sprite.SetDrawDepth((ent.Owner, buckledSprite), ent.Comp.OriginalDrawDepth.Value);
|
||||
ent.Comp.OriginalDrawDepth = null;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,7 +8,6 @@ using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
using Serilog;
|
||||
|
||||
namespace Content.Client.Cargo.UI;
|
||||
|
||||
|
||||
@@ -32,6 +32,10 @@ public sealed class CharacterInfoSystem : EntitySystem
|
||||
private void OnCharacterInfoEvent(CharacterInfoEvent msg, EntitySessionEventArgs args)
|
||||
{
|
||||
var entity = GetEntity(msg.NetEntity);
|
||||
// Mono - fix
|
||||
if (TerminatingOrDeleted(entity))
|
||||
return;
|
||||
|
||||
var data = new CharacterData(entity, msg.JobTitle, msg.Objectives, msg.Briefing, Name(entity));
|
||||
|
||||
OnCharacterUpdate?.Invoke(data);
|
||||
|
||||
@@ -9,13 +9,13 @@
|
||||
<!-- Main -->
|
||||
<ui:RadialContainer Name="Main" VerticalExpand="True" HorizontalExpand="True" InitialRadius="100" ReserveSpaceForHiddenChildren="False">
|
||||
<ui:RadialMenuTextureButtonWithSector SetSize="64 64" ToolTip="{Loc 'emote-menu-category-general'}" TargetLayer="General" Visible="False">
|
||||
<TextureRect VerticalAlignment="Center" HorizontalAlignment="Center" TextureScale="2 2" TexturePath="/Textures/Clothing/Head/Soft/mimesoft.rsi/icon.png"/>
|
||||
<TextureRect VerticalAlignment="Center" HorizontalAlignment="Center" TextureScale="2 2" Name="GeneralCategoryTexture"/>
|
||||
</ui:RadialMenuTextureButtonWithSector>
|
||||
<ui:RadialMenuTextureButtonWithSector SetSize="64 64" ToolTip="{Loc 'emote-menu-category-vocal'}" TargetLayer="Vocal" Visible="False">
|
||||
<TextureRect VerticalAlignment="Center" HorizontalAlignment="Center" TextureScale="2 2" TexturePath="/Textures/Interface/Emotes/vocal.png"/>
|
||||
</ui:RadialMenuTextureButtonWithSector>
|
||||
<ui:RadialMenuTextureButtonWithSector SetSize="64 64" ToolTip="{Loc 'emote-menu-category-hands'}" TargetLayer="Hands" Visible="False">
|
||||
<TextureRect VerticalAlignment="Center" HorizontalAlignment="Center" TextureScale="2 2" TexturePath="/Textures/Clothing/Hands/Gloves/latex.rsi/icon.png"/>
|
||||
<TextureRect VerticalAlignment="Center" HorizontalAlignment="Center" TextureScale="2 2" Name="HandsCategoryTexture"/>
|
||||
</ui:RadialMenuTextureButtonWithSector>
|
||||
</ui:RadialContainer>
|
||||
|
||||
|
||||
@@ -5,10 +5,12 @@ using Content.Shared.Speech;
|
||||
using Content.Shared.Whitelist;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client.Chat.UI;
|
||||
|
||||
@@ -86,6 +88,9 @@ public sealed partial class EmotesMenu : RadialMenu
|
||||
continue;
|
||||
AddEmoteClickAction(container);
|
||||
}
|
||||
|
||||
GeneralCategoryTexture.Texture = spriteSystem.Frame0(new SpriteSpecifier.Rsi(new ResPath("/Textures/Clothing/Head/Soft/mimesoft.rsi"), "icon"));
|
||||
HandsCategoryTexture.Texture = spriteSystem.Frame0(new SpriteSpecifier.Rsi(new ResPath("/Textures/Clothing/Hands/Gloves/latex.rsi"), "icon"));
|
||||
}
|
||||
|
||||
private void AddEmoteClickAction(RadialContainer container)
|
||||
|
||||
@@ -6,7 +6,6 @@ using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
using Robust.Client.UserInterface.XAML;
|
||||
using Robust.Client.Utility;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
using System.Linq;
|
||||
@@ -14,6 +13,7 @@ using System.Numerics;
|
||||
using Content.Shared.FixedPoint;
|
||||
using Robust.Client.Graphics;
|
||||
using static Robust.Client.UserInterface.Controls.BoxContainer;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
namespace Content.Client.Chemistry.UI
|
||||
{
|
||||
@@ -24,6 +24,8 @@ namespace Content.Client.Chemistry.UI
|
||||
public sealed partial class ChemMasterWindow : FancyWindow
|
||||
{
|
||||
[Dependency] private readonly IPrototypeManager _prototypeManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entityManager = default!;
|
||||
private readonly SpriteSystem _sprite;
|
||||
public event Action<BaseButton.ButtonEventArgs, ReagentButton>? OnReagentButtonPressed;
|
||||
public readonly Button[] PillTypeButtons;
|
||||
|
||||
@@ -37,6 +39,7 @@ namespace Content.Client.Chemistry.UI
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
IoCManager.InjectDependencies(this);
|
||||
_sprite = _entityManager.System<SpriteSystem>();
|
||||
|
||||
// Pill type selection buttons, in total there are 20 pills.
|
||||
// Pill rsi file should have states named as pill1, pill2, and so on.
|
||||
@@ -67,9 +70,9 @@ namespace Content.Client.Chemistry.UI
|
||||
|
||||
// Generate buttons textures
|
||||
var specifier = new SpriteSpecifier.Rsi(resourcePath, "pill" + (i + 1));
|
||||
TextureRect pillTypeTexture = new TextureRect
|
||||
var pillTypeTexture = new TextureRect
|
||||
{
|
||||
Texture = specifier.Frame0(),
|
||||
Texture = _sprite.Frame0(specifier),
|
||||
TextureScale = new Vector2(1.75f, 1.75f),
|
||||
Stretch = TextureRect.StretchMode.KeepCentered,
|
||||
};
|
||||
@@ -249,7 +252,7 @@ namespace Content.Client.Chemistry.UI
|
||||
ChemMasterSortingType.Latest => Loc.GetString("chem-master-window-sort-type-latest"),
|
||||
_ => Loc.GetString("chem-master-window-sort-type-none")
|
||||
};
|
||||
|
||||
|
||||
OutputBufferDraw.Pressed = state.DrawSource == ChemMasterDrawSource.Internal;
|
||||
OutputBeakerDraw.Pressed = state.DrawSource == ChemMasterDrawSource.External;
|
||||
|
||||
@@ -434,7 +437,7 @@ namespace Content.Client.Chemistry.UI
|
||||
get => LabelLineEdit.Text;
|
||||
set => LabelLineEdit.Text = value;
|
||||
}
|
||||
|
||||
|
||||
private void SetBufferText(FixedPoint2? volume, string text)
|
||||
{
|
||||
BufferCurrentVolume.Text = $" {volume ?? FixedPoint2.Zero}u";
|
||||
|
||||
@@ -50,7 +50,7 @@ public sealed class SolutionContainerVisualsSystem : VisualizerSystem<SolutionCo
|
||||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (!args.Sprite.LayerMapTryGet(component.Layer, out var fillLayer))
|
||||
if (!SpriteSystem.LayerMapTryGet((uid, args.Sprite), component.Layer, out var fillLayer, false))
|
||||
return;
|
||||
|
||||
var maxFillLevels = component.MaxFillLevels;
|
||||
@@ -68,9 +68,9 @@ public sealed class SolutionContainerVisualsSystem : VisualizerSystem<SolutionCo
|
||||
}
|
||||
if (component.Metamorphic)
|
||||
{
|
||||
if (args.Sprite.LayerMapTryGet(component.BaseLayer, out var baseLayer))
|
||||
if (SpriteSystem.LayerMapTryGet((uid, args.Sprite), component.BaseLayer, out var baseLayer, false))
|
||||
{
|
||||
var hasOverlay = args.Sprite.LayerMapTryGet(component.OverlayLayer, out var overlayLayer);
|
||||
var hasOverlay = SpriteSystem.LayerMapTryGet((uid, args.Sprite), component.OverlayLayer, out var overlayLayer, false);
|
||||
|
||||
if (AppearanceSystem.TryGetData<string>(uid, SolutionContainerVisuals.BaseOverride,
|
||||
out var baseOverride,
|
||||
@@ -80,35 +80,35 @@ public sealed class SolutionContainerVisualsSystem : VisualizerSystem<SolutionCo
|
||||
|
||||
if (reagentProto?.MetamorphicSprite is { } sprite)
|
||||
{
|
||||
args.Sprite.LayerSetSprite(baseLayer, sprite);
|
||||
SpriteSystem.LayerSetSprite((uid, args.Sprite), baseLayer, sprite);
|
||||
if (reagentProto.MetamorphicMaxFillLevels > 0)
|
||||
{
|
||||
args.Sprite.LayerSetVisible(fillLayer, true);
|
||||
SpriteSystem.LayerSetVisible((uid, args.Sprite), fillLayer, true);
|
||||
maxFillLevels = reagentProto.MetamorphicMaxFillLevels;
|
||||
fillBaseName = reagentProto.MetamorphicFillBaseName;
|
||||
changeColor = reagentProto.MetamorphicChangeColor;
|
||||
fillSprite = sprite;
|
||||
}
|
||||
else
|
||||
args.Sprite.LayerSetVisible(fillLayer, false);
|
||||
SpriteSystem.LayerSetVisible((uid, args.Sprite), fillLayer, false);
|
||||
|
||||
if (hasOverlay)
|
||||
args.Sprite.LayerSetVisible(overlayLayer, false);
|
||||
SpriteSystem.LayerSetVisible((uid, args.Sprite), overlayLayer, false);
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Sprite.LayerSetVisible(fillLayer, true);
|
||||
SpriteSystem.LayerSetVisible((uid, args.Sprite), fillLayer, true);
|
||||
if (hasOverlay)
|
||||
args.Sprite.LayerSetVisible(overlayLayer, true);
|
||||
SpriteSystem.LayerSetVisible((uid, args.Sprite), overlayLayer, true);
|
||||
if (component.MetamorphicDefaultSprite != null)
|
||||
args.Sprite.LayerSetSprite(baseLayer, component.MetamorphicDefaultSprite);
|
||||
SpriteSystem.LayerSetSprite((uid, args.Sprite), baseLayer, component.MetamorphicDefaultSprite);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Sprite.LayerSetVisible(fillLayer, true);
|
||||
SpriteSystem.LayerSetVisible((uid, args.Sprite), fillLayer, true);
|
||||
}
|
||||
|
||||
var closestFillSprite = ContentHelpers.RoundToLevels(fraction, 1, maxFillLevels + 1);
|
||||
@@ -120,25 +120,25 @@ public sealed class SolutionContainerVisualsSystem : VisualizerSystem<SolutionCo
|
||||
|
||||
var stateName = fillBaseName + closestFillSprite;
|
||||
if (fillSprite != null)
|
||||
args.Sprite.LayerSetSprite(fillLayer, fillSprite);
|
||||
args.Sprite.LayerSetState(fillLayer, stateName);
|
||||
SpriteSystem.LayerSetSprite((uid, args.Sprite), fillLayer, fillSprite);
|
||||
SpriteSystem.LayerSetRsiState((uid, args.Sprite), fillLayer, stateName);
|
||||
|
||||
if (changeColor && AppearanceSystem.TryGetData<Color>(uid, SolutionContainerVisuals.Color, out var color, args.Component))
|
||||
args.Sprite.LayerSetColor(fillLayer, color);
|
||||
SpriteSystem.LayerSetColor((uid, args.Sprite), fillLayer, color);
|
||||
else
|
||||
args.Sprite.LayerSetColor(fillLayer, Color.White);
|
||||
SpriteSystem.LayerSetColor((uid, args.Sprite), fillLayer, Color.White);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (component.EmptySpriteName == null)
|
||||
args.Sprite.LayerSetVisible(fillLayer, false);
|
||||
SpriteSystem.LayerSetVisible((uid, args.Sprite), fillLayer, false);
|
||||
else
|
||||
{
|
||||
args.Sprite.LayerSetState(fillLayer, component.EmptySpriteName);
|
||||
SpriteSystem.LayerSetRsiState((uid, args.Sprite), fillLayer, component.EmptySpriteName);
|
||||
if (changeColor)
|
||||
args.Sprite.LayerSetColor(fillLayer, component.EmptySpriteColor);
|
||||
SpriteSystem.LayerSetColor((uid, args.Sprite), fillLayer, component.EmptySpriteColor);
|
||||
else
|
||||
args.Sprite.LayerSetColor(fillLayer, Color.White);
|
||||
SpriteSystem.LayerSetColor((uid, args.Sprite), fillLayer, Color.White);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,26 +1,24 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
<PropertyGroup>
|
||||
<!-- Work around https://github.com/dotnet/project-system/issues/4314 -->
|
||||
<TargetFramework>$(TargetFramework)</TargetFramework>
|
||||
<LangVersion>12</LangVersion>
|
||||
<IsPackable>false</IsPackable>
|
||||
<AppendTargetFrameworkToOutputPath>false</AppendTargetFrameworkToOutputPath>
|
||||
<OutputPath>..\bin\Content.Client\</OutputPath>
|
||||
<OutputType Condition="'$(FullRelease)' != 'True'">Exe</OutputType>
|
||||
<WarningsAsErrors>nullable</WarningsAsErrors>
|
||||
<Nullable>enable</Nullable>
|
||||
<Configurations>Debug;Release;Tools;DebugOpt</Configurations>
|
||||
<Platforms>AnyCPU</Platforms>
|
||||
<WarningsAsErrors>RA0032;nullable</WarningsAsErrors>
|
||||
</PropertyGroup>
|
||||
<Import Project="../MSBuild/Content.props" />
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Nett" />
|
||||
<PackageReference Include="JetBrains.Annotations" PrivateAssets="All" />
|
||||
<PackageReference Include="SixLabors.ImageSharp" />
|
||||
<PackageReference Include="Pidgin" />
|
||||
<PackageReference Include="Robust.Shared.AuthLib" />
|
||||
</ItemGroup>
|
||||
|
||||
<Import Project="..\RobustToolbox\Imports\Lidgren.props" />
|
||||
<Import Project="..\RobustToolbox\Imports\Client.props" />
|
||||
<Import Project="..\RobustToolbox\Imports\Shared.props" />
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\RobustToolbox\Lidgren.Network\Lidgren.Network.csproj" />
|
||||
<ProjectReference Include="..\RobustToolbox\Robust.Shared.Maths\Robust.Shared.Maths.csproj" />
|
||||
<ProjectReference Include="..\RobustToolbox\Robust.Shared\Robust.Shared.csproj" />
|
||||
<ProjectReference Include="..\RobustToolbox\Robust.Client\Robust.Client.csproj" />
|
||||
<ProjectReference Include="..\Content.Shared\Content.Shared.csproj" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Robust.Client.Graphics;
|
||||
using System.Numerics;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
@@ -34,7 +35,7 @@ namespace Content.Client.Cooldown
|
||||
if (Progress >= 0f)
|
||||
{
|
||||
var hue = (5f / 18f) * lerp;
|
||||
color = Color.FromHsv((hue, 0.75f, 0.75f, 0.50f));
|
||||
color = Color.FromHsv(new Vector4(hue, 0.75f, 0.75f, 0.50f));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -4,12 +4,14 @@ using Content.Shared.Cuffs.Components;
|
||||
using Content.Shared.Humanoid;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client.Cuffs;
|
||||
|
||||
public sealed class CuffableSystem : SharedCuffableSystem
|
||||
{
|
||||
[Dependency] private readonly ActionBlockerSystem _actionBlocker = default!;
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -22,7 +24,7 @@ public sealed class CuffableSystem : SharedCuffableSystem
|
||||
private void OnCuffableShutdown(EntityUid uid, CuffableComponent component, ComponentShutdown args)
|
||||
{
|
||||
if (TryComp<SpriteComponent>(uid, out var sprite))
|
||||
sprite.LayerSetVisible(HumanoidVisualLayers.Handcuffs, false);
|
||||
_sprite.LayerSetVisible((uid, sprite), HumanoidVisualLayers.Handcuffs, false);
|
||||
}
|
||||
|
||||
private void OnCuffableHandleState(EntityUid uid, CuffableComponent component, ref ComponentHandleState args)
|
||||
@@ -39,22 +41,22 @@ public sealed class CuffableSystem : SharedCuffableSystem
|
||||
if (!TryComp<SpriteComponent>(uid, out var sprite))
|
||||
return;
|
||||
var cuffed = cuffState.NumHandsCuffed > 0;
|
||||
sprite.LayerSetVisible(HumanoidVisualLayers.Handcuffs, cuffed);
|
||||
_sprite.LayerSetVisible((uid, sprite), HumanoidVisualLayers.Handcuffs, cuffed);
|
||||
|
||||
// if they are not cuffed, that means that we didn't get a valid color,
|
||||
// iconstate, or RSI. that also means we don't need to update the sprites.
|
||||
if (!cuffed)
|
||||
return;
|
||||
sprite.LayerSetColor(HumanoidVisualLayers.Handcuffs, cuffState.Color!.Value);
|
||||
_sprite.LayerSetColor((uid, sprite), HumanoidVisualLayers.Handcuffs, cuffState.Color!.Value);
|
||||
|
||||
if (!Equals(component.CurrentRSI, cuffState.RSI) && cuffState.RSI != null) // we don't want to keep loading the same RSI
|
||||
{
|
||||
component.CurrentRSI = cuffState.RSI;
|
||||
sprite.LayerSetState(HumanoidVisualLayers.Handcuffs, cuffState.IconState, component.CurrentRSI);
|
||||
_sprite.LayerSetRsi((uid, sprite), _sprite.LayerMapGet((uid, sprite), HumanoidVisualLayers.Handcuffs), new ResPath(component.CurrentRSI), cuffState.IconState);
|
||||
}
|
||||
else
|
||||
{
|
||||
sprite.LayerSetState(HumanoidVisualLayers.Handcuffs, cuffState.IconState);
|
||||
_sprite.LayerSetRsiState((uid, sprite), HumanoidVisualLayers.Handcuffs, cuffState.IconState);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using Content.Shared.Disposal;
|
||||
using System.Numerics;
|
||||
using Content.Shared.Disposal;
|
||||
using Content.Shared.Disposal.Unit;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
|
||||
@@ -11,6 +11,7 @@ public sealed class DoorSystem : SharedDoorSystem
|
||||
{
|
||||
[Dependency] private readonly AnimationPlayerSystem _animationSystem = default!;
|
||||
[Dependency] private readonly IResourceCache _resourceCache = default!;
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -85,7 +86,7 @@ public sealed class DoorSystem : SharedDoorSystem
|
||||
state = DoorState.Closed;
|
||||
|
||||
if (AppearanceSystem.TryGetData<string>(entity, DoorVisuals.BaseRSI, out var baseRsi, args.Component))
|
||||
UpdateSpriteLayers(args.Sprite, baseRsi);
|
||||
UpdateSpriteLayers((entity.Owner, args.Sprite), baseRsi);
|
||||
|
||||
if (_animationSystem.HasRunningAnimation(entity, DoorComponent.AnimationKey))
|
||||
_animationSystem.Stop(entity.Owner, DoorComponent.AnimationKey);
|
||||
@@ -95,21 +96,21 @@ public sealed class DoorSystem : SharedDoorSystem
|
||||
|
||||
private void UpdateAppearanceForDoorState(Entity<DoorComponent> entity, SpriteComponent sprite, DoorState state)
|
||||
{
|
||||
sprite.DrawDepth = state is DoorState.Open ? entity.Comp.OpenDrawDepth : entity.Comp.ClosedDrawDepth;
|
||||
_sprite.SetDrawDepth((entity.Owner, sprite), state is DoorState.Open ? entity.Comp.OpenDrawDepth : entity.Comp.ClosedDrawDepth);
|
||||
|
||||
switch (state)
|
||||
{
|
||||
case DoorState.Open:
|
||||
foreach (var (layer, layerState) in entity.Comp.OpenSpriteStates)
|
||||
{
|
||||
sprite.LayerSetState(layer, layerState);
|
||||
_sprite.LayerSetRsiState((entity.Owner, sprite), layer, layerState);
|
||||
}
|
||||
|
||||
return;
|
||||
case DoorState.Closed:
|
||||
foreach (var (layer, layerState) in entity.Comp.ClosedSpriteStates)
|
||||
{
|
||||
sprite.LayerSetState(layer, layerState);
|
||||
_sprite.LayerSetRsiState((entity.Owner, sprite), layer, layerState);
|
||||
}
|
||||
|
||||
return;
|
||||
@@ -138,7 +139,7 @@ public sealed class DoorSystem : SharedDoorSystem
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateSpriteLayers(SpriteComponent sprite, string baseRsi)
|
||||
private void UpdateSpriteLayers(Entity<SpriteComponent> sprite, string baseRsi)
|
||||
{
|
||||
if (!_resourceCache.TryGetResource<RSIResource>(SpriteSpecifierSerializer.TextureRoot / baseRsi, out var res))
|
||||
{
|
||||
@@ -146,6 +147,6 @@ public sealed class DoorSystem : SharedDoorSystem
|
||||
return;
|
||||
}
|
||||
|
||||
sprite.BaseRSI = res.RSI;
|
||||
_sprite.SetBaseRsi(sprite.AsNullable(), res.RSI);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ namespace Content.Client.Electrocution;
|
||||
public sealed class ElectrocutionHUDVisualizerSystem : VisualizerSystem<ElectrocutionHUDVisualsComponent>
|
||||
{
|
||||
[Dependency] private readonly IPlayerManager _playerMan = default!;
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -53,15 +54,12 @@ public sealed class ElectrocutionHUDVisualizerSystem : VisualizerSystem<Electroc
|
||||
private void ShowHUD()
|
||||
{
|
||||
var electrifiedQuery = AllEntityQuery<ElectrocutionHUDVisualsComponent, AppearanceComponent, SpriteComponent>();
|
||||
while (electrifiedQuery.MoveNext(out var uid, out var _, out var appearanceComp, out var spriteComp))
|
||||
while (electrifiedQuery.MoveNext(out var uid, out _, out var appearanceComp, out var spriteComp))
|
||||
{
|
||||
if (!AppearanceSystem.TryGetData<bool>(uid, ElectrifiedVisuals.IsElectrified, out var electrified, appearanceComp))
|
||||
continue;
|
||||
|
||||
if (electrified)
|
||||
spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, true);
|
||||
else
|
||||
spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, false);
|
||||
_sprite.LayerSetVisible((uid, spriteComp), ElectrifiedLayers.HUD, electrified);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -70,10 +68,9 @@ public sealed class ElectrocutionHUDVisualizerSystem : VisualizerSystem<Electroc
|
||||
private void RemoveHUD()
|
||||
{
|
||||
var electrifiedQuery = AllEntityQuery<ElectrocutionHUDVisualsComponent, AppearanceComponent, SpriteComponent>();
|
||||
while (electrifiedQuery.MoveNext(out var uid, out var _, out var appearanceComp, out var spriteComp))
|
||||
while (electrifiedQuery.MoveNext(out var uid, out _, out _, out var spriteComp))
|
||||
{
|
||||
|
||||
spriteComp.LayerSetVisible(ElectrifiedLayers.HUD, false);
|
||||
_sprite.LayerSetVisible((uid, spriteComp), ElectrifiedLayers.HUD, false);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -87,9 +84,6 @@ public sealed class ElectrocutionHUDVisualizerSystem : VisualizerSystem<Electroc
|
||||
return;
|
||||
|
||||
var player = _playerMan.LocalEntity;
|
||||
if (electrified && HasComp<ShowElectrocutionHUDComponent>(player))
|
||||
args.Sprite.LayerSetVisible(ElectrifiedLayers.HUD, true);
|
||||
else
|
||||
args.Sprite.LayerSetVisible(ElectrifiedLayers.HUD, false);
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), ElectrifiedLayers.HUD, electrified && HasComp<ShowElectrocutionHUDComponent>(player));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,12 +1,14 @@
|
||||
using Content.Shared.Ensnaring;
|
||||
using Content.Shared.Ensnaring.Components;
|
||||
using Robust.Client.GameObjects;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client.Ensnaring;
|
||||
|
||||
public sealed class EnsnareableSystem : SharedEnsnareableSystem
|
||||
{
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -19,25 +21,25 @@ public sealed class EnsnareableSystem : SharedEnsnareableSystem
|
||||
{
|
||||
base.OnEnsnareInit(ent, ref args);
|
||||
|
||||
if(!TryComp<SpriteComponent>(ent.Owner, out var sprite))
|
||||
if (!TryComp<SpriteComponent>(ent.Owner, out var sprite))
|
||||
return;
|
||||
|
||||
// TODO remove this, this should just be in yaml.
|
||||
sprite.LayerMapReserveBlank(EnsnaredVisualLayers.Ensnared);
|
||||
_sprite.LayerMapReserve((ent.Owner, sprite), EnsnaredVisualLayers.Ensnared);
|
||||
}
|
||||
|
||||
private void OnAppearanceChange(EntityUid uid, EnsnareableComponent component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (args.Sprite == null || !args.Sprite.LayerMapTryGet(EnsnaredVisualLayers.Ensnared, out var layer))
|
||||
if (args.Sprite == null || !_sprite.LayerMapTryGet((uid, args.Sprite), EnsnaredVisualLayers.Ensnared, out var layer, false))
|
||||
return;
|
||||
|
||||
if (_appearance.TryGetData<bool>(uid, EnsnareableVisuals.IsEnsnared, out var isEnsnared, args.Component))
|
||||
{
|
||||
if (component.Sprite != null)
|
||||
{
|
||||
args.Sprite.LayerSetRSI(layer, component.Sprite);
|
||||
args.Sprite.LayerSetState(layer, component.State);
|
||||
args.Sprite.LayerSetVisible(layer, isEnsnared);
|
||||
_sprite.LayerSetRsi((uid, args.Sprite), layer, new ResPath(component.Sprite));
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), layer, component.State);
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), layer, isEnsnared);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,7 @@ using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Replays;
|
||||
using Robust.Shared.Timing;
|
||||
using Content.Client._NF.Emp.Overlays; // Frontier
|
||||
using Content.Client._Mono.Company; // Mono
|
||||
|
||||
namespace Content.Client.Entry
|
||||
{
|
||||
@@ -75,6 +76,7 @@ namespace Content.Client.Entry
|
||||
[Dependency] private readonly DebugMonitorManager _debugMonitorManager = default!;
|
||||
[Dependency] private readonly TitleWindowManager _titleWindowManager = default!;
|
||||
[Dependency] private readonly IEntitySystemManager _entitySystemManager = default!;
|
||||
[Dependency] private readonly CompanyManager _companyManager = default!; // Mono
|
||||
|
||||
public override void Init()
|
||||
{
|
||||
@@ -137,6 +139,7 @@ namespace Content.Client.Entry
|
||||
_extendedDisconnectInformation.Initialize();
|
||||
_jobRequirements.Initialize();
|
||||
_playbackMan.Initialize();
|
||||
_companyManager.Initialize();
|
||||
|
||||
//AUTOSCALING default Setup!
|
||||
_configManager.SetCVar("interface.resolutionAutoScaleUpperCutoffX", 1080);
|
||||
|
||||
@@ -10,6 +10,7 @@ namespace Content.Client.Fluids;
|
||||
public sealed class PuddleSystem : SharedPuddleSystem
|
||||
{
|
||||
[Dependency] private readonly IconSmoothSystem _smooth = default!;
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -27,7 +28,7 @@ public sealed class PuddleSystem : SharedPuddleSystem
|
||||
|
||||
if (args.AppearanceData.TryGetValue(PuddleVisuals.CurrentVolume, out var volumeObj))
|
||||
{
|
||||
volume = (float) volumeObj;
|
||||
volume = (float)volumeObj;
|
||||
}
|
||||
|
||||
// Update smoothing and sprite based on volume.
|
||||
@@ -35,19 +36,19 @@ public sealed class PuddleSystem : SharedPuddleSystem
|
||||
{
|
||||
if (volume < LowThreshold)
|
||||
{
|
||||
args.Sprite.LayerSetState(0, $"{smooth.StateBase}a");
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), 0, $"{smooth.StateBase}a");
|
||||
_smooth.SetEnabled(uid, false, smooth);
|
||||
}
|
||||
else if (volume < MediumThreshold)
|
||||
{
|
||||
args.Sprite.LayerSetState(0, $"{smooth.StateBase}b");
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), 0, $"{smooth.StateBase}b");
|
||||
_smooth.SetEnabled(uid, false, smooth);
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!smooth.Enabled)
|
||||
{
|
||||
args.Sprite.LayerSetState(0, $"{smooth.StateBase}0");
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), 0, $"{smooth.StateBase}0");
|
||||
_smooth.SetEnabled(uid, true, smooth);
|
||||
_smooth.DirtyNeighbours(uid);
|
||||
}
|
||||
@@ -58,12 +59,12 @@ public sealed class PuddleSystem : SharedPuddleSystem
|
||||
|
||||
if (args.AppearanceData.TryGetValue(PuddleVisuals.SolutionColor, out var colorObj))
|
||||
{
|
||||
var color = (Color) colorObj;
|
||||
args.Sprite.Color = color * baseColor;
|
||||
var color = (Color)colorObj;
|
||||
_sprite.SetColor((uid, args.Sprite), color * baseColor);
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Sprite.Color *= baseColor;
|
||||
_sprite.SetColor((uid, args.Sprite), args.Sprite.Color * baseColor);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
using Robust.Client.Graphics;
|
||||
|
||||
namespace Content.Client.Graphics;
|
||||
|
||||
/// <summary>
|
||||
/// A cache for <see cref="Overlay"/>s to store per-viewport render resources, such as render targets.
|
||||
/// </summary>
|
||||
/// <typeparam name="T">The type of data stored in the cache.</typeparam>
|
||||
public sealed class OverlayResourceCache<T> : IDisposable where T : class, IDisposable
|
||||
{
|
||||
private readonly Dictionary<long, CacheEntry> _cache = new();
|
||||
|
||||
/// <summary>
|
||||
/// Get the data for a specific viewport, creating a new entry if necessary.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The cached data may be cleared at any time if <see cref="IClydeViewport.ClearCachedResources"/> gets invoked.
|
||||
/// </remarks>
|
||||
/// <param name="viewport">The viewport for which to retrieve cached data.</param>
|
||||
/// <param name="factory">A delegate used to create the cached data, if necessary.</param>
|
||||
public T GetForViewport(IClydeViewport viewport, Func<IClydeViewport, T> factory)
|
||||
{
|
||||
return GetForViewport(viewport, out _, factory);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Get the data for a specific viewport, creating a new entry if necessary.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// The cached data may be cleared at any time if <see cref="IClydeViewport.ClearCachedResources"/> gets invoked.
|
||||
/// </remarks>
|
||||
/// <param name="viewport">The viewport for which to retrieve cached data.</param>
|
||||
/// <param name="wasCached">True if the data was pulled from cache, false if it was created anew.</param>
|
||||
/// <param name="factory">A delegate used to create the cached data, if necessary.</param>
|
||||
public T GetForViewport(IClydeViewport viewport, out bool wasCached, Func<IClydeViewport, T> factory)
|
||||
{
|
||||
if (_cache.TryGetValue(viewport.Id, out var entry))
|
||||
{
|
||||
wasCached = true;
|
||||
return entry.Data;
|
||||
}
|
||||
|
||||
wasCached = false;
|
||||
|
||||
entry = new CacheEntry
|
||||
{
|
||||
Data = factory(viewport),
|
||||
Viewport = new WeakReference<IClydeViewport>(viewport),
|
||||
};
|
||||
_cache.Add(viewport.Id, entry);
|
||||
|
||||
viewport.ClearCachedResources += ViewportOnClearCachedResources;
|
||||
|
||||
return entry.Data;
|
||||
}
|
||||
|
||||
private void ViewportOnClearCachedResources(ClearCachedViewportResourcesEvent ev)
|
||||
{
|
||||
if (!_cache.Remove(ev.ViewportId, out var entry))
|
||||
{
|
||||
// I think this could theoretically happen if you manually dispose the cache *after* a leaked viewport got
|
||||
// GC'd, but before its ClearCachedResources got invoked.
|
||||
return;
|
||||
}
|
||||
|
||||
entry.Data.Dispose();
|
||||
|
||||
if (ev.Viewport != null)
|
||||
ev.Viewport.ClearCachedResources -= ViewportOnClearCachedResources;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
foreach (var entry in _cache)
|
||||
{
|
||||
if (entry.Value.Viewport.TryGetTarget(out var viewport))
|
||||
viewport.ClearCachedResources -= ViewportOnClearCachedResources;
|
||||
|
||||
entry.Value.Data.Dispose();
|
||||
}
|
||||
|
||||
_cache.Clear();
|
||||
}
|
||||
|
||||
private struct CacheEntry
|
||||
{
|
||||
public T Data;
|
||||
public WeakReference<IClydeViewport> Viewport;
|
||||
}
|
||||
}
|
||||
@@ -36,39 +36,37 @@ public sealed partial class DocumentParsingManager
|
||||
.Assert(_tagControlParsers.ContainsKey, tag => $"unknown tag: {tag}")
|
||||
.Bind(tag => _tagControlParsers[tag]);
|
||||
|
||||
// Frontier: comment parser
|
||||
Parser<char, Unit> whitespaceAndCommentParser = SkipWhitespaces.Then(Try(String("<!--").Then(Parser<char>.Any.SkipUntil(Try(String("-->"))))).SkipMany());
|
||||
var whitespaceAndCommentParser = SkipWhitespaces.Then(Try(String("<!--").Then(Parser<char>.Any.SkipUntil(Try(String("-->"))))).SkipMany());
|
||||
|
||||
_controlParser = OneOf(_tagParser, TryHeaderControl, TryListControl, TextControlParser)
|
||||
.Before(whitespaceAndCommentParser);
|
||||
// End Frontier
|
||||
|
||||
foreach (var typ in _reflectionManager.GetAllChildren<IDocumentTag>())
|
||||
{
|
||||
_tagControlParsers.Add(typ.Name, CreateTagControlParser(typ.Name, typ, _sandboxHelper));
|
||||
}
|
||||
|
||||
ControlParser = whitespaceAndCommentParser.Then(_controlParser.Many()); // Frontier: SkipWhitespaces<whitespaceAndCommentParser
|
||||
ControlParser = whitespaceAndCommentParser.Then(_controlParser.Many());
|
||||
|
||||
_sawmill = Logger.GetSawmill("Guidebook");
|
||||
}
|
||||
|
||||
public bool TryAddMarkup(Control control, ProtoId<GuideEntryPrototype> entryId, bool log = true)
|
||||
public bool TryAddMarkup(Control control, ProtoId<GuideEntryPrototype> entryId)
|
||||
{
|
||||
if (!_prototype.TryIndex(entryId, out var entry))
|
||||
if (!_prototype.Resolve(entryId, out var entry))
|
||||
return false;
|
||||
|
||||
using var file = _resourceManager.ContentFileReadText(entry.Text);
|
||||
return TryAddMarkup(control, file.ReadToEnd(), log);
|
||||
return TryAddMarkup(control, file.ReadToEnd());
|
||||
}
|
||||
|
||||
public bool TryAddMarkup(Control control, GuideEntry entry, bool log = true)
|
||||
public bool TryAddMarkup(Control control, GuideEntry entry)
|
||||
{
|
||||
using var file = _resourceManager.ContentFileReadText(entry.Text);
|
||||
return TryAddMarkup(control, file.ReadToEnd(), log);
|
||||
return TryAddMarkup(control, file.ReadToEnd());
|
||||
}
|
||||
|
||||
public bool TryAddMarkup(Control control, string text, bool log = true)
|
||||
public bool TryAddMarkup(Control control, string text)
|
||||
{
|
||||
try
|
||||
{
|
||||
|
||||
@@ -83,7 +83,7 @@ public sealed partial class DocumentParsingManager
|
||||
}
|
||||
|
||||
msg.Pop();
|
||||
rt.SetMessage(msg);
|
||||
rt.SetMessage(msg, tagsAllowed: null);
|
||||
return rt;
|
||||
},
|
||||
TextParser)
|
||||
|
||||
@@ -19,6 +19,7 @@ using Robust.Shared.Containers;
|
||||
using Robust.Shared.GameStates;
|
||||
using Robust.Shared.Player;
|
||||
using Robust.Shared.Timing;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client.Hands.Systems
|
||||
{
|
||||
@@ -30,6 +31,7 @@ namespace Content.Client.Hands.Systems
|
||||
|
||||
[Dependency] private readonly SharedContainerSystem _containerSystem = default!;
|
||||
[Dependency] private readonly StrippableSystem _stripSys = default!;
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
[Dependency] private readonly ExamineSystem _examine = default!;
|
||||
[Dependency] private readonly DisplacementMapSystem _displacement = default!;
|
||||
|
||||
@@ -330,7 +332,7 @@ namespace Content.Client.Hands.Systems
|
||||
{
|
||||
foreach (var key in revealedLayers)
|
||||
{
|
||||
sprite.RemoveLayer(key);
|
||||
_sprite.RemoveLayer((uid, sprite), key);
|
||||
}
|
||||
|
||||
revealedLayers.Clear();
|
||||
@@ -366,7 +368,7 @@ namespace Content.Client.Hands.Systems
|
||||
continue;
|
||||
}
|
||||
|
||||
var index = sprite.LayerMapReserveBlank(key);
|
||||
var index = _sprite.LayerMapReserve((uid, sprite), key);
|
||||
|
||||
// In case no RSI is given, use the item's base RSI as a default. This cuts down on a lot of unnecessary yaml entries.
|
||||
if (layerData.RsiPath == null
|
||||
@@ -374,12 +376,12 @@ namespace Content.Client.Hands.Systems
|
||||
&& sprite[index].Rsi == null)
|
||||
{
|
||||
if (TryComp<ItemComponent>(held, out var itemComponent) && itemComponent.RsiPath != null)
|
||||
sprite.LayerSetRSI(index, itemComponent.RsiPath);
|
||||
_sprite.LayerSetRsi((uid, sprite), index, new ResPath(itemComponent.RsiPath));
|
||||
else if (TryComp(held, out SpriteComponent? clothingSprite))
|
||||
sprite.LayerSetRSI(index, clothingSprite.BaseRSI);
|
||||
_sprite.LayerSetRsi((uid, sprite), index, clothingSprite.BaseRSI);
|
||||
}
|
||||
|
||||
sprite.LayerSetData(index, layerData);
|
||||
_sprite.LayerSetData((uid, sprite), index, layerData);
|
||||
|
||||
//Add displacement maps
|
||||
if (handComp.HandDisplacement is not null)
|
||||
|
||||
@@ -5,6 +5,7 @@ using Robust.Client.Graphics;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Timing;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using DrawDepth = Content.Shared.DrawDepth.DrawDepth;
|
||||
|
||||
namespace Content.Client.Holopad;
|
||||
|
||||
@@ -18,7 +18,7 @@ public sealed partial class InfoSection : BoxContainer
|
||||
{
|
||||
TitleLabel.Text = title;
|
||||
if (markup)
|
||||
Content.SetMessage(FormattedMessage.FromMarkupOrThrow(text.Trim()));
|
||||
Content.SetMessage(FormattedMessage.FromMarkupOrThrow(text.Trim()), tagsAllowed: null);
|
||||
else
|
||||
Content.SetMessage(text);
|
||||
}
|
||||
|
||||
@@ -24,7 +24,7 @@ namespace Content.Client.Info
|
||||
}
|
||||
public void SetInfoBlob(string markup)
|
||||
{
|
||||
_richTextLabel.SetMessage(FormattedMessage.FromMarkupOrThrow(markup));
|
||||
_richTextLabel.SetMessage(FormattedMessage.FromMarkupOrThrow(markup), tagsAllowed: null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -24,6 +24,7 @@ using Content.Shared.Administration.Managers;
|
||||
using Content.Shared.Chat;
|
||||
using Content.Shared.Players.PlayTimeTracking;
|
||||
using Content.Shared.Players.RateLimiting;
|
||||
using Content.Client._Mono.Company; // Mono
|
||||
|
||||
namespace Content.Client.IoC
|
||||
{
|
||||
@@ -60,6 +61,7 @@ namespace Content.Client.IoC
|
||||
collection.Register<PlayerRateLimitManager>();
|
||||
collection.Register<SharedPlayerRateLimitManager, PlayerRateLimitManager>();
|
||||
collection.Register<TitleWindowManager>();
|
||||
collection.Register<CompanyManager>(); // Mono
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ public sealed class AfterLightTargetOverlay : Overlay
|
||||
return;
|
||||
|
||||
var lightOverlay = _overlay.GetOverlay<BeforeLightTargetOverlay>();
|
||||
var lightRes = lightOverlay.GetCachedForViewport(args.Viewport);
|
||||
var bounds = args.WorldBounds;
|
||||
|
||||
// at 1-1 render scale it's mostly fine but at 4x4 it's way too fkn big
|
||||
@@ -38,7 +39,7 @@ public sealed class AfterLightTargetOverlay : Overlay
|
||||
|
||||
var localMatrix =
|
||||
viewport.LightRenderTarget.GetWorldToLocalMatrix(viewport.Eye, newScale);
|
||||
var diff = (lightOverlay.EnlargedLightTarget.Size - viewport.LightRenderTarget.Size);
|
||||
var diff = (lightRes.EnlargedLightTarget.Size - viewport.LightRenderTarget.Size);
|
||||
var halfDiff = diff / 2;
|
||||
|
||||
// Pixels -> Metres -> Half distance.
|
||||
@@ -53,7 +54,7 @@ public sealed class AfterLightTargetOverlay : Overlay
|
||||
viewport.LightRenderTarget.Size.Y + halfDiff.Y);
|
||||
|
||||
worldHandle.SetTransform(localMatrix);
|
||||
worldHandle.DrawTextureRectRegion(lightOverlay.EnlargedLightTarget.Texture, bounds, subRegion: subRegion);
|
||||
worldHandle.DrawTextureRectRegion(lightRes.EnlargedLightTarget.Texture, bounds, subRegion: subRegion);
|
||||
}, Color.Transparent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,140 @@
|
||||
using System.Numerics;
|
||||
using Content.Shared.CCVar;
|
||||
using Content.Shared.Maps;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Configuration;
|
||||
using Robust.Shared.Enums;
|
||||
using Robust.Shared.Map;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
|
||||
namespace Content.Client.Light;
|
||||
|
||||
/// <summary>
|
||||
/// Applies ambient-occlusion to the viewport.
|
||||
/// </summary>
|
||||
public sealed class AmbientOcclusionOverlay : Overlay
|
||||
{
|
||||
[Dependency] private readonly IClyde _clyde = default!;
|
||||
[Dependency] private readonly IConfigurationManager _cfgManager = default!;
|
||||
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||
[Dependency] private readonly IMapManager _mapManager = default!;
|
||||
[Dependency] private readonly IPrototypeManager _proto = default!;
|
||||
[Dependency] private readonly ITileDefinitionManager _tileDefManager = default!;
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowEntities;
|
||||
|
||||
private IRenderTexture? _aoTarget;
|
||||
|
||||
// Couldn't figure out a way to avoid this so if you can then please do.
|
||||
private IRenderTexture? _aoStencilTarget;
|
||||
|
||||
public AmbientOcclusionOverlay()
|
||||
{
|
||||
IoCManager.InjectDependencies(this);
|
||||
ZIndex = AfterLightTargetOverlay.ContentZIndex + 1;
|
||||
}
|
||||
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
/*
|
||||
* tl;dr
|
||||
* - we draw a black square on each "ambient occlusion" entity.
|
||||
* - we blur this.
|
||||
* - We apply it to the viewport.
|
||||
*
|
||||
* We do this while ignoring lighting because it will wash out the actual effect.
|
||||
* In 3D ambient occlusion is more complicated due top having to calculate normals but in 2D
|
||||
* we don't have a concept of depth / corners necessarily.
|
||||
*/
|
||||
|
||||
var viewport = args.Viewport;
|
||||
var mapId = args.MapId;
|
||||
var worldBounds = args.WorldBounds;
|
||||
var worldHandle = args.WorldHandle;
|
||||
var color = Color.FromHex(_cfgManager.GetCVar(CCVars.AmbientOcclusionColor));
|
||||
var distance = _cfgManager.GetCVar(CCVars.AmbientOcclusionDistance);
|
||||
//var color = Color.Red;
|
||||
var target = viewport.RenderTarget;
|
||||
var lightScale = target.Size / (Vector2) viewport.Size;
|
||||
var scale = viewport.RenderScale / (Vector2.One / lightScale);
|
||||
var maps = _entManager.System<SharedMapSystem>();
|
||||
var lookups = _entManager.System<EntityLookupSystem>();
|
||||
var query = _entManager.System<OccluderSystem>();
|
||||
var xformSystem = _entManager.System<SharedTransformSystem>();
|
||||
var invMatrix = args.Viewport.GetWorldToLocalMatrix();
|
||||
|
||||
if (_aoTarget?.Texture.Size != target.Size)
|
||||
{
|
||||
_aoTarget?.Dispose();
|
||||
_aoTarget = _clyde.CreateRenderTarget(target.Size, new RenderTargetFormatParameters(RenderTargetColorFormat.Rgba8Srgb), name: "ambient-occlusion-target");
|
||||
}
|
||||
|
||||
if (_aoStencilTarget?.Texture.Size != target.Size)
|
||||
{
|
||||
_aoStencilTarget?.Dispose();
|
||||
_aoStencilTarget = _clyde.CreateRenderTarget(target.Size, new RenderTargetFormatParameters(RenderTargetColorFormat.Rgba8Srgb), name: "ambient-occlusion-stencil-target");
|
||||
}
|
||||
|
||||
// Draw the texture data to the texture.
|
||||
args.WorldHandle.RenderInRenderTarget(_aoTarget,
|
||||
() =>
|
||||
{
|
||||
worldHandle.UseShader(_proto.Index<ShaderPrototype>("unshaded").Instance());
|
||||
var invMatrix = _aoTarget.GetWorldToLocalMatrix(viewport.Eye!, scale);
|
||||
|
||||
foreach (var entry in query.QueryAabb(mapId, worldBounds))
|
||||
{
|
||||
DebugTools.Assert(entry.Component.Enabled);
|
||||
var matrix = xformSystem.GetWorldMatrix(entry.Transform);
|
||||
var localMatrix = Matrix3x2.Multiply(matrix, invMatrix);
|
||||
|
||||
worldHandle.SetTransform(localMatrix);
|
||||
// 4 pixels
|
||||
worldHandle.DrawRect(Box2.UnitCentered.Enlarged(distance / EyeManager.PixelsPerMeter), Color.White);
|
||||
}
|
||||
}, Color.Transparent);
|
||||
|
||||
_clyde.BlurRenderTarget(viewport, _aoTarget, _aoTarget, viewport.Eye!, 14f);
|
||||
|
||||
// Need to do stencilling after blur as it will nuke it.
|
||||
// Draw stencil for the grid so we don't draw in space.
|
||||
args.WorldHandle.RenderInRenderTarget(_aoStencilTarget,
|
||||
() =>
|
||||
{
|
||||
// Don't want lighting affecting it.
|
||||
worldHandle.UseShader(_proto.Index<ShaderPrototype>("unshaded").Instance());
|
||||
|
||||
foreach (var grid in _mapManager.FindGridsIntersecting(mapId, worldBounds))
|
||||
{
|
||||
var transform = xformSystem.GetWorldMatrix(grid.Owner);
|
||||
var worldToTextureMatrix = Matrix3x2.Multiply(transform, invMatrix);
|
||||
var tiles = maps.GetTilesEnumerator(grid.Owner, grid, worldBounds);
|
||||
worldHandle.SetTransform(worldToTextureMatrix);
|
||||
while (tiles.MoveNext(out var tileRef))
|
||||
{
|
||||
if (tileRef.IsSpace(_tileDefManager))
|
||||
continue;
|
||||
|
||||
var bounds = lookups.GetLocalBounds(tileRef, grid.TileSize);
|
||||
worldHandle.DrawRect(bounds, Color.White);
|
||||
}
|
||||
}
|
||||
|
||||
}, Color.Transparent);
|
||||
|
||||
// Draw the stencil texture to depth buffer.
|
||||
worldHandle.UseShader(_proto.Index<ShaderPrototype>("StencilMask").Instance());
|
||||
worldHandle.DrawTextureRect(_aoStencilTarget!.Texture, worldBounds);
|
||||
|
||||
// Draw the Blurred AO texture finally.
|
||||
worldHandle.UseShader(_proto.Index<ShaderPrototype>("StencilEqualDraw").Instance());
|
||||
worldHandle.DrawTextureRect(_aoTarget!.Texture, worldBounds, color);
|
||||
|
||||
worldHandle.UseShader(_proto.Index<ShaderPrototype>("StencilClear").Instance());
|
||||
worldHandle.DrawRect(worldBounds, Color.White);
|
||||
|
||||
args.WorldHandle.SetTransform(Matrix3x2.Identity);
|
||||
args.WorldHandle.UseShader(null);
|
||||
}
|
||||
}
|
||||
@@ -1,4 +1,4 @@
|
||||
using System.Numerics;
|
||||
using Content.Client.Graphics;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Enums;
|
||||
|
||||
@@ -13,7 +13,8 @@ public sealed class BeforeLightTargetOverlay : Overlay
|
||||
|
||||
[Dependency] private readonly IClyde _clyde = default!;
|
||||
|
||||
public IRenderTexture EnlargedLightTarget = default!;
|
||||
private readonly OverlayResourceCache<CachedResources> _resources = new();
|
||||
|
||||
public Box2Rotated EnlargedBounds;
|
||||
|
||||
/// <summary>
|
||||
@@ -36,16 +37,42 @@ public sealed class BeforeLightTargetOverlay : Overlay
|
||||
var size = args.Viewport.LightRenderTarget.Size + (int) (_skirting * EyeManager.PixelsPerMeter);
|
||||
EnlargedBounds = args.WorldBounds.Enlarged(_skirting / 2f);
|
||||
|
||||
var res = _resources.GetForViewport(args.Viewport, static _ => new CachedResources());
|
||||
|
||||
// This just exists to copy the lightrendertarget and write back to it.
|
||||
if (EnlargedLightTarget?.Size != size)
|
||||
if (res.EnlargedLightTarget?.Size != size)
|
||||
{
|
||||
EnlargedLightTarget = _clyde
|
||||
res.EnlargedLightTarget = _clyde
|
||||
.CreateRenderTarget(size, new RenderTargetFormatParameters(RenderTargetColorFormat.Rgba8Srgb), name: "enlarged-light-copy");
|
||||
}
|
||||
|
||||
args.WorldHandle.RenderInRenderTarget(EnlargedLightTarget,
|
||||
args.WorldHandle.RenderInRenderTarget(res.EnlargedLightTarget,
|
||||
() =>
|
||||
{
|
||||
}, _clyde.GetClearColor(args.MapUid));
|
||||
}
|
||||
|
||||
internal CachedResources GetCachedForViewport(IClydeViewport viewport)
|
||||
{
|
||||
return _resources.GetForViewport(viewport,
|
||||
static _ => throw new InvalidOperationException(
|
||||
"Expected BeforeLightTargetOverlay to have created its resources"));
|
||||
}
|
||||
|
||||
protected override void DisposeBehavior()
|
||||
{
|
||||
_resources.Dispose();
|
||||
|
||||
base.DisposeBehavior();
|
||||
}
|
||||
|
||||
internal sealed class CachedResources : IDisposable
|
||||
{
|
||||
public IRenderTexture EnlargedLightTarget = default!;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
EnlargedLightTarget?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,8 @@ namespace Content.Client.Light.EntitySystems;
|
||||
|
||||
public sealed class EmergencyLightSystem : VisualizerSystem<EmergencyLightComponent>
|
||||
{
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
protected override void OnAppearanceChange(EntityUid uid, EmergencyLightComponent comp, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (args.Sprite == null)
|
||||
@@ -14,13 +16,13 @@ public sealed class EmergencyLightSystem : VisualizerSystem<EmergencyLightCompon
|
||||
if (!AppearanceSystem.TryGetData<bool>(uid, EmergencyLightVisuals.On, out var on, args.Component))
|
||||
on = false;
|
||||
|
||||
args.Sprite.LayerSetVisible(EmergencyLightVisualLayers.LightOff, !on);
|
||||
args.Sprite.LayerSetVisible(EmergencyLightVisualLayers.LightOn, on);
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), EmergencyLightVisualLayers.LightOff, !on);
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), EmergencyLightVisualLayers.LightOn, on);
|
||||
|
||||
if (AppearanceSystem.TryGetData<Color>(uid, EmergencyLightVisuals.Color, out var color, args.Component))
|
||||
{
|
||||
args.Sprite.LayerSetColor(EmergencyLightVisualLayers.LightOn, color);
|
||||
args.Sprite.LayerSetColor(EmergencyLightVisualLayers.LightOff, color);
|
||||
_sprite.LayerSetColor((uid, args.Sprite), EmergencyLightVisualLayers.LightOn, color);
|
||||
_sprite.LayerSetColor((uid, args.Sprite), EmergencyLightVisualLayers.LightOff, color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,6 +5,8 @@ namespace Content.Client.Light.Visualizers;
|
||||
|
||||
public sealed class LightBulbSystem : VisualizerSystem<LightBulbComponent>
|
||||
{
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
protected override void OnAppearanceChange(EntityUid uid, LightBulbComponent comp, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (args.Sprite == null)
|
||||
@@ -16,13 +18,13 @@ public sealed class LightBulbSystem : VisualizerSystem<LightBulbComponent>
|
||||
switch (state)
|
||||
{
|
||||
case LightBulbState.Normal:
|
||||
args.Sprite.LayerSetState(LightBulbVisualLayers.Base, comp.NormalSpriteState);
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), LightBulbVisualLayers.Base, comp.NormalSpriteState);
|
||||
break;
|
||||
case LightBulbState.Broken:
|
||||
args.Sprite.LayerSetState(LightBulbVisualLayers.Base, comp.BrokenSpriteState);
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), LightBulbVisualLayers.Base, comp.BrokenSpriteState);
|
||||
break;
|
||||
case LightBulbState.Burned:
|
||||
args.Sprite.LayerSetState(LightBulbVisualLayers.Base, comp.BurnedSpriteState);
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), LightBulbVisualLayers.Base, comp.BurnedSpriteState);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@@ -30,7 +32,7 @@ public sealed class LightBulbSystem : VisualizerSystem<LightBulbComponent>
|
||||
// also update sprites color
|
||||
if (AppearanceSystem.TryGetData<Color>(uid, LightBulbVisuals.Color, out var color, args.Component))
|
||||
{
|
||||
args.Sprite.Color = color;
|
||||
_sprite.SetColor((uid, args.Sprite), color);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,17 +1,51 @@
|
||||
using Content.Shared.CCVar;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Configuration;
|
||||
|
||||
namespace Content.Client.Light.EntitySystems;
|
||||
|
||||
public sealed class PlanetLightSystem : EntitySystem
|
||||
{
|
||||
[Dependency] private readonly IConfigurationManager _cfgManager = default!;
|
||||
[Dependency] private readonly IOverlayManager _overlayMan = default!;
|
||||
|
||||
/// <summary>
|
||||
/// Enables / disables the ambient occlusion overlay.
|
||||
/// </summary>
|
||||
public bool AmbientOcclusion
|
||||
{
|
||||
get => _ambientOcclusion;
|
||||
set
|
||||
{
|
||||
if (_ambientOcclusion == value)
|
||||
return;
|
||||
|
||||
_ambientOcclusion = value;
|
||||
|
||||
if (value)
|
||||
{
|
||||
_overlayMan.AddOverlay(new AmbientOcclusionOverlay());
|
||||
}
|
||||
else
|
||||
{
|
||||
_overlayMan.RemoveOverlay<AmbientOcclusionOverlay>();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private bool _ambientOcclusion;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
SubscribeLocalEvent<GetClearColorEvent>(OnClearColor);
|
||||
|
||||
_cfgManager.OnValueChanged(CCVars.AmbientOcclusion, val =>
|
||||
{
|
||||
AmbientOcclusion = val;
|
||||
}, true);
|
||||
|
||||
_overlayMan.AddOverlay(new BeforeLightTargetOverlay());
|
||||
_overlayMan.AddOverlay(new RoofOverlay(EntityManager));
|
||||
_overlayMan.AddOverlay(new TileEmissionOverlay(EntityManager));
|
||||
|
||||
@@ -44,7 +44,7 @@ public sealed class HandheldLightSystem : SharedHandheldLightSystem
|
||||
return;
|
||||
}
|
||||
|
||||
if (!_appearance.TryGetData<bool>(uid, ToggleableLightVisuals.Enabled, out var enabled, args.Component))
|
||||
if (!_appearance.TryGetData<bool>(uid, ToggleableVisuals.Enabled, out var enabled, args.Component))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using Content.Client.Graphics;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Enums;
|
||||
|
||||
@@ -15,7 +16,7 @@ public sealed class LightBlurOverlay : Overlay
|
||||
|
||||
public const int ContentZIndex = TileEmissionOverlay.ContentZIndex + 1;
|
||||
|
||||
private IRenderTarget? _blurTarget;
|
||||
private readonly OverlayResourceCache<CachedResources> _resources = new();
|
||||
|
||||
public LightBlurOverlay()
|
||||
{
|
||||
@@ -29,16 +30,36 @@ public sealed class LightBlurOverlay : Overlay
|
||||
return;
|
||||
|
||||
var beforeOverlay = _overlay.GetOverlay<BeforeLightTargetOverlay>();
|
||||
var size = beforeOverlay.EnlargedLightTarget.Size;
|
||||
var beforeLightRes = beforeOverlay.GetCachedForViewport(args.Viewport);
|
||||
var res = _resources.GetForViewport(args.Viewport, static _ => new CachedResources());
|
||||
|
||||
if (_blurTarget?.Size != size)
|
||||
var size = beforeLightRes.EnlargedLightTarget.Size;
|
||||
|
||||
if (res.BlurTarget?.Size != size)
|
||||
{
|
||||
_blurTarget = _clyde
|
||||
res.BlurTarget = _clyde
|
||||
.CreateRenderTarget(size, new RenderTargetFormatParameters(RenderTargetColorFormat.Rgba8Srgb), name: "enlarged-light-blur");
|
||||
}
|
||||
|
||||
var target = beforeOverlay.EnlargedLightTarget;
|
||||
var target = beforeLightRes.EnlargedLightTarget;
|
||||
// Yeah that's all this does keep walkin.
|
||||
_clyde.BlurRenderTarget(args.Viewport, target, _blurTarget, args.Viewport.Eye, 14f * 5f);
|
||||
_clyde.BlurRenderTarget(args.Viewport, target, res.BlurTarget, args.Viewport.Eye, 14f * 5f);
|
||||
}
|
||||
|
||||
protected override void DisposeBehavior()
|
||||
{
|
||||
_resources.Dispose();
|
||||
|
||||
base.DisposeBehavior();
|
||||
}
|
||||
|
||||
private sealed class CachedResources : IDisposable
|
||||
{
|
||||
public IRenderTarget? BlurTarget;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
BlurTarget?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Content.Client.Items.Systems;
|
||||
using Content.Shared.Clothing;
|
||||
using Content.Shared.Hands;
|
||||
|
||||
@@ -43,7 +43,7 @@ public sealed class RoofOverlay : Overlay
|
||||
|
||||
protected override void Draw(in OverlayDrawArgs args)
|
||||
{
|
||||
if (args.Viewport.Eye == null)
|
||||
if (args.Viewport.Eye == null || !_entManager.HasComponent<MapLightComponent>(args.MapUid))
|
||||
return;
|
||||
|
||||
var viewport = args.Viewport;
|
||||
@@ -52,37 +52,23 @@ public sealed class RoofOverlay : Overlay
|
||||
var worldHandle = args.WorldHandle;
|
||||
var lightoverlay = _overlay.GetOverlay<BeforeLightTargetOverlay>();
|
||||
var bounds = lightoverlay.EnlargedBounds;
|
||||
var target = lightoverlay.EnlargedLightTarget;
|
||||
var target = lightoverlay.GetCachedForViewport(viewport).EnlargedLightTarget;
|
||||
|
||||
_grids.Clear();
|
||||
_mapManager.FindGridsIntersecting(args.MapId, bounds, ref _grids);
|
||||
|
||||
for (var i = _grids.Count - 1; i >= 0; i--)
|
||||
{
|
||||
var grid = _grids[i];
|
||||
|
||||
if (_entManager.HasComponent<RoofComponent>(grid.Owner))
|
||||
continue;
|
||||
|
||||
_grids.RemoveAt(i);
|
||||
}
|
||||
|
||||
if (_grids.Count == 0)
|
||||
return;
|
||||
|
||||
_mapManager.FindGridsIntersecting(args.MapId, bounds, ref _grids, approx: true, includeMap: true);
|
||||
var lightScale = viewport.LightRenderTarget.Size / (Vector2) viewport.Size;
|
||||
var scale = viewport.RenderScale / (Vector2.One / lightScale);
|
||||
|
||||
worldHandle.RenderInRenderTarget(target,
|
||||
() =>
|
||||
{
|
||||
var invMatrix = target.GetWorldToLocalMatrix(eye, scale);
|
||||
|
||||
foreach (var grid in _grids)
|
||||
{
|
||||
if (!_entManager.TryGetComponent(grid.Owner, out RoofComponent? roof))
|
||||
continue;
|
||||
|
||||
var invMatrix = target.GetWorldToLocalMatrix(eye, scale);
|
||||
|
||||
var gridMatrix = _xformSystem.GetWorldMatrix(grid.Owner);
|
||||
var matty = Matrix3x2.Multiply(gridMatrix, invMatrix);
|
||||
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Numerics;
|
||||
using Content.Client.Graphics;
|
||||
using Content.Shared.Light.Components;
|
||||
using Robust.Client.Graphics;
|
||||
using Robust.Shared.Enums;
|
||||
@@ -11,6 +12,8 @@ namespace Content.Client.Light;
|
||||
|
||||
public sealed class SunShadowOverlay : Overlay
|
||||
{
|
||||
private static readonly ProtoId<ShaderPrototype> MixShader = "Mix";
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.BeforeLighting;
|
||||
|
||||
[Dependency] private readonly IClyde _clyde = default!;
|
||||
@@ -22,8 +25,7 @@ public sealed class SunShadowOverlay : Overlay
|
||||
|
||||
private readonly HashSet<Entity<SunShadowCastComponent>> _shadows = new();
|
||||
|
||||
private IRenderTexture? _blurTarget;
|
||||
private IRenderTexture? _target;
|
||||
private readonly OverlayResourceCache<CachedResources> _resources = new();
|
||||
|
||||
public SunShadowOverlay()
|
||||
{
|
||||
@@ -53,16 +55,18 @@ public sealed class SunShadowOverlay : Overlay
|
||||
var worldBounds = args.WorldBounds;
|
||||
var targetSize = viewport.LightRenderTarget.Size;
|
||||
|
||||
if (_target?.Size != targetSize)
|
||||
var res = _resources.GetForViewport(args.Viewport, static _ => new CachedResources());
|
||||
|
||||
if (res.Target?.Size != targetSize)
|
||||
{
|
||||
_target = _clyde
|
||||
res.Target = _clyde
|
||||
.CreateRenderTarget(targetSize,
|
||||
new RenderTargetFormatParameters(RenderTargetColorFormat.Rgba8Srgb),
|
||||
name: "sun-shadow-target");
|
||||
|
||||
if (_blurTarget?.Size != targetSize)
|
||||
if (res.BlurTarget?.Size != targetSize)
|
||||
{
|
||||
_blurTarget = _clyde
|
||||
res.BlurTarget = _clyde
|
||||
.CreateRenderTarget(targetSize, new RenderTargetFormatParameters(RenderTargetColorFormat.Rgba8Srgb), name: "sun-shadow-blur");
|
||||
}
|
||||
}
|
||||
@@ -91,11 +95,11 @@ public sealed class SunShadowOverlay : Overlay
|
||||
_shadows.Clear();
|
||||
|
||||
// Draw shadow polys to stencil
|
||||
args.WorldHandle.RenderInRenderTarget(_target,
|
||||
args.WorldHandle.RenderInRenderTarget(res.Target,
|
||||
() =>
|
||||
{
|
||||
var invMatrix =
|
||||
_target.GetWorldToLocalMatrix(eye, scale);
|
||||
res.Target.GetWorldToLocalMatrix(eye, scale);
|
||||
var indices = new Vector2[PhysicsConstants.MaxPolygonVertices * 2];
|
||||
|
||||
// Go through shadows in range.
|
||||
@@ -114,7 +118,9 @@ public sealed class SunShadowOverlay : Overlay
|
||||
foreach (var ent in _shadows)
|
||||
{
|
||||
var xform = _entManager.GetComponent<TransformComponent>(ent.Owner);
|
||||
var worldMatrix = _xformSys.GetWorldMatrix(xform);
|
||||
var (worldPos, worldRot) = _xformSys.GetWorldPositionRotation(xform);
|
||||
// Need no rotation on matrix as sun shadow direction doesn't care.
|
||||
var worldMatrix = Matrix3x2.CreateTranslation(worldPos);
|
||||
var renderMatrix = Matrix3x2.Multiply(worldMatrix, invMatrix);
|
||||
var pointCount = ent.Comp.Points.Length;
|
||||
|
||||
@@ -122,6 +128,10 @@ public sealed class SunShadowOverlay : Overlay
|
||||
|
||||
for (var i = 0; i < pointCount; i++)
|
||||
{
|
||||
// Update point based on entity rotation.
|
||||
indices[i] = worldRot.RotateVec(indices[i]);
|
||||
|
||||
// Add the offset point by the sun shadow direction.
|
||||
indices[pointCount + i] = indices[i] + direction;
|
||||
}
|
||||
|
||||
@@ -134,7 +144,7 @@ public sealed class SunShadowOverlay : Overlay
|
||||
Color.Transparent);
|
||||
|
||||
// Slightly blur it just to avoid aliasing issues on the later viewport-wide blur.
|
||||
_clyde.BlurRenderTarget(viewport, _target, _target, eye, 1f);
|
||||
_clyde.BlurRenderTarget(viewport, res.Target, res.BlurTarget!, eye, 1f);
|
||||
|
||||
// Draw stencil (see roofoverlay).
|
||||
args.WorldHandle.RenderInRenderTarget(viewport.LightRenderTarget,
|
||||
@@ -144,11 +154,30 @@ public sealed class SunShadowOverlay : Overlay
|
||||
viewport.LightRenderTarget.GetWorldToLocalMatrix(eye, scale);
|
||||
worldHandle.SetTransform(invMatrix);
|
||||
|
||||
var maskShader = _protoManager.Index<ShaderPrototype>("Mix").Instance();
|
||||
var maskShader = _protoManager.Index(MixShader).Instance();
|
||||
worldHandle.UseShader(maskShader);
|
||||
|
||||
worldHandle.DrawTextureRect(_target.Texture, worldBounds, Color.Black.WithAlpha(alpha));
|
||||
worldHandle.DrawTextureRect(res.Target.Texture, worldBounds, Color.Black.WithAlpha(alpha));
|
||||
}, null);
|
||||
}
|
||||
}
|
||||
|
||||
protected override void DisposeBehavior()
|
||||
{
|
||||
_resources.Dispose();
|
||||
|
||||
base.DisposeBehavior();
|
||||
}
|
||||
|
||||
private sealed class CachedResources : IDisposable
|
||||
{
|
||||
public IRenderTexture? BlurTarget;
|
||||
public IRenderTexture? Target;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
BlurTarget?.Dispose();
|
||||
Target?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ public sealed class TileEmissionOverlay : Overlay
|
||||
var worldHandle = args.WorldHandle;
|
||||
var lightoverlay = _overlay.GetOverlay<BeforeLightTargetOverlay>();
|
||||
var bounds = lightoverlay.EnlargedBounds;
|
||||
var target = lightoverlay.EnlargedLightTarget;
|
||||
var target = lightoverlay.GetCachedForViewport(args.Viewport).EnlargedLightTarget;
|
||||
var viewport = args.Viewport;
|
||||
_grids.Clear();
|
||||
_mapManager.FindGridsIntersecting(mapId, bounds, ref _grids, approx: true);
|
||||
|
||||
@@ -12,6 +12,7 @@ public sealed class PoweredLightVisualizerSystem : VisualizerSystem<PoweredLight
|
||||
{
|
||||
[Dependency] private readonly IRobustRandom _random = default!;
|
||||
[Dependency] private readonly SharedAudioSystem _audio = default!;
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -28,16 +29,16 @@ public sealed class PoweredLightVisualizerSystem : VisualizerSystem<PoweredLight
|
||||
return;
|
||||
|
||||
if (comp.SpriteStateMap.TryGetValue(state, out var spriteState))
|
||||
args.Sprite.LayerSetState(PoweredLightLayers.Base, spriteState);
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), PoweredLightLayers.Base, spriteState);
|
||||
|
||||
if (args.Sprite.LayerExists(PoweredLightLayers.Glow))
|
||||
if (_sprite.LayerExists((uid, args.Sprite), PoweredLightLayers.Glow))
|
||||
{
|
||||
if (TryComp<PointLightComponent>(uid, out var light))
|
||||
{
|
||||
args.Sprite.LayerSetColor(PoweredLightLayers.Glow, light.Color);
|
||||
_sprite.LayerSetColor((uid, args.Sprite), PoweredLightLayers.Glow, light.Color);
|
||||
}
|
||||
|
||||
args.Sprite.LayerSetVisible(PoweredLightLayers.Glow, state == PoweredLightState.On);
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), PoweredLightLayers.Glow, state == PoweredLightState.On);
|
||||
}
|
||||
|
||||
SetBlinkingAnimation(
|
||||
@@ -55,8 +56,7 @@ public sealed class PoweredLightVisualizerSystem : VisualizerSystem<PoweredLight
|
||||
{
|
||||
if (args.Key != PoweredLightVisualsComponent.BlinkingAnimationKey)
|
||||
return;
|
||||
|
||||
if(!comp.IsBlinking)
|
||||
if (!comp.IsBlinking)
|
||||
return;
|
||||
|
||||
AnimationSystem.Play(uid, Comp<AnimationPlayerComponent>(uid), BlinkingAnimation(comp), PoweredLightVisualsComponent.BlinkingAnimationKey);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Linq;
|
||||
using Content.Client._Mono.Company; // Mono
|
||||
using Content.Client._Mono.MonoCoins;
|
||||
using Content.Client.Guidebook;
|
||||
using Content.Client.Humanoid;
|
||||
@@ -41,6 +42,7 @@ public sealed class LobbyUIController : UIController, IOnStateEntered<LobbyState
|
||||
[Dependency] private readonly IStateManager _stateManager = default!;
|
||||
[Dependency] private readonly JobRequirementsManager _requirements = default!;
|
||||
[Dependency] private readonly MarkingManager _markings = default!;
|
||||
[Dependency] private readonly CompanyManager _companyManager = default!; // Mono
|
||||
[UISystemDependency] private readonly HumanoidAppearanceSystem _humanoid = default!;
|
||||
[UISystemDependency] private readonly ClientInventorySystem _inventory = default!;
|
||||
[UISystemDependency] private readonly StationSpawningSystem _spawn = default!;
|
||||
@@ -350,7 +352,8 @@ public sealed class LobbyUIController : UIController, IOnStateEntered<LobbyState
|
||||
_prototypeManager,
|
||||
_resourceCache,
|
||||
_requirements,
|
||||
_markings);
|
||||
_markings,
|
||||
_companyManager); // Mono
|
||||
|
||||
_profileEditor.OnOpenGuidebook += _guide.OpenHelp;
|
||||
|
||||
|
||||
@@ -35,6 +35,7 @@ using Robust.Shared.Enums;
|
||||
using Robust.Shared.Prototypes;
|
||||
using Robust.Shared.Utility;
|
||||
using Direction = Robust.Shared.Maths.Direction;
|
||||
using Content.Client._Mono.Company;
|
||||
|
||||
namespace Content.Client.Lobby.UI
|
||||
{
|
||||
@@ -52,6 +53,7 @@ namespace Content.Client.Lobby.UI
|
||||
private readonly JobRequirementsManager _requirements;
|
||||
private readonly LobbyUIController _controller;
|
||||
private readonly EntityWhitelistSystem _whitelist; // Frontier
|
||||
private readonly CompanyManager _companyManager; // Mono
|
||||
|
||||
private FlavorText.FlavorText? _flavorText;
|
||||
private TextEdit? _flavorTextEdit;
|
||||
@@ -116,7 +118,8 @@ namespace Content.Client.Lobby.UI
|
||||
IPrototypeManager prototypeManager,
|
||||
IResourceManager resManager,
|
||||
JobRequirementsManager requirements,
|
||||
MarkingManager markings)
|
||||
MarkingManager markings,
|
||||
CompanyManager manager) // Mono
|
||||
{
|
||||
RobustXamlLoader.Load(this);
|
||||
_sawmill = logManager.GetSawmill("profile.editor");
|
||||
@@ -127,6 +130,7 @@ namespace Content.Client.Lobby.UI
|
||||
_prototypeManager = prototypeManager;
|
||||
_markingManager = markings;
|
||||
_preferencesManager = preferencesManager;
|
||||
_companyManager = manager; // Mono
|
||||
_resManager = resManager;
|
||||
_requirements = requirements;
|
||||
_controller = UserInterfaceManager.GetUIController<LobbyUIController>();
|
||||
@@ -446,12 +450,9 @@ namespace Content.Client.Lobby.UI
|
||||
// Clear any existing items
|
||||
CompanyButton.Clear();
|
||||
|
||||
var username = _playerManager.LocalPlayer?.Session?.Name; //Lua modified - company login support
|
||||
|
||||
// Add all companies from prototypes - use consistent sorting with UpdateCompanyControls
|
||||
var companies = _prototypeManager.EnumeratePrototypes<CompanyPrototype>()
|
||||
//.Where(c => !c.Disabled) // Filter out disabled companies
|
||||
.Where(c => !c.Disabled || (username != null && c.Logins.Contains(username))) //Lua modified - company login support
|
||||
.Where(c => !c.Disabled && _companyManager.IsAllowed(c.ID))
|
||||
.ToList();
|
||||
companies.Sort((a, b) => string.Compare(a.Name, b.Name, StringComparison.Ordinal));
|
||||
|
||||
@@ -1451,7 +1452,7 @@ namespace Content.Client.Lobby.UI
|
||||
|
||||
_loadoutWindow = new LoadoutWindow(Profile, roleLoadout, roleLoadoutProto, _playerManager.LocalSession, collection)
|
||||
{
|
||||
Title = jobProto?.ID + "-loadout",
|
||||
Title = jobProto?.LocalizedName + " loadout", // Mono - replace the "-" with a space in "-loadout", change to LocalizedName from ID
|
||||
};
|
||||
|
||||
// Refresh the buttons etc.
|
||||
@@ -2194,11 +2195,8 @@ namespace Content.Client.Lobby.UI
|
||||
if (Profile is null)
|
||||
return;
|
||||
|
||||
var username = _playerManager.LocalPlayer?.Session?.Name; //Lua modified - company login support
|
||||
|
||||
var companies = _prototypeManager.EnumeratePrototypes<CompanyPrototype>()
|
||||
//.Where(c => !c.Disabled) // Filter out disabled companies
|
||||
.Where(c => !c.Disabled || (username != null && c.Logins.Contains(username))) //Lua modified - company login support
|
||||
.Where(c => !c.Disabled && _companyManager.IsAllowed(c.ID))
|
||||
.ToList();
|
||||
companies.Sort((a, b) => string.Compare(a.Name, b.Name, StringComparison.Ordinal));
|
||||
|
||||
|
||||
@@ -1,6 +1,4 @@
|
||||
using System.Numerics;
|
||||
using Content.Client.UserInterface.Controls;
|
||||
using Prometheus;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface;
|
||||
using Robust.Client.UserInterface.Controls;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System.Numerics;
|
||||
using Content.Shared.Nyanotrasen.Kitchen.UI;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
<Control xmlns="https://spacestation14.io">
|
||||
<BoxContainer Orientation="Vertical">
|
||||
<Label Name="TitleLabel" Access="Public" />
|
||||
<Label Name="ExampleLabel" Access="Public" />
|
||||
<ColorSelectorSliders Name="Slider" Access="Public" HorizontalExpand="True" />
|
||||
</BoxContainer>
|
||||
</Control>
|
||||
@@ -0,0 +1,31 @@
|
||||
using Content.Client.Options.UI;
|
||||
using Robust.Client.AutoGenerated;
|
||||
using Robust.Client.UserInterface;
|
||||
|
||||
namespace Content.Client.Options.UI;
|
||||
|
||||
/// <summary>
|
||||
/// Standard UI control used for color sliders in the options menu. Intended for use with <see cref="OptionsTabControlRow"/>.
|
||||
/// </summary>
|
||||
/// <seealso cref="OptionsTabControlRow.AddOptionColorSlider"/>
|
||||
[GenerateTypedNameReferences]
|
||||
public sealed partial class OptionColorSlider : Control
|
||||
{
|
||||
/// <summary>
|
||||
/// The text describing what this slider affects.
|
||||
/// </summary>
|
||||
public string? Title
|
||||
{
|
||||
get => TitleLabel.Text;
|
||||
set => TitleLabel.Text = value;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The example text showing the current color of the slider.
|
||||
/// </summary>
|
||||
public string? Example
|
||||
{
|
||||
get => ExampleLabel.Text;
|
||||
set => ExampleLabel.Text = value;
|
||||
}
|
||||
}
|
||||
@@ -143,6 +143,19 @@ public sealed partial class OptionsTabControlRow : Control
|
||||
return AddOption(new OptionSliderIntCVar(this, _cfg, cVar, slider, min, max, format ?? FormatInt));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a color slider option, backed by a simple string CVar.
|
||||
/// </summary>
|
||||
/// <param name="cVar">The CVar represented by the slider.</param>
|
||||
/// <param name="slider">The UI control for the option.</param>
|
||||
/// <returns>The option instance backing the added option.</returns>
|
||||
public OptionColorSliderCVar AddOptionColorSlider(
|
||||
CVarDef<string> cVar,
|
||||
OptionColorSlider slider)
|
||||
{
|
||||
return AddOption(new OptionColorSliderCVar(this, _cfg, cVar, slider));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Add a drop-down option, backed by a CVar.
|
||||
/// </summary>
|
||||
@@ -518,6 +531,54 @@ public sealed class OptionSliderFloatCVar : BaseOptionCVar<float>
|
||||
}
|
||||
}
|
||||
|
||||
public sealed class OptionColorSliderCVar : BaseOptionCVar<string>
|
||||
{
|
||||
private readonly OptionColorSlider _slider;
|
||||
|
||||
protected override string Value
|
||||
{
|
||||
get => _slider.Slider.Color.ToHex();
|
||||
set
|
||||
{
|
||||
_slider.Slider.Color = Color.FromHex(value);
|
||||
UpdateLabelColor();
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of this type.
|
||||
/// </summary>
|
||||
/// <remarks>
|
||||
/// <para>
|
||||
/// It is generally more convenient to call overloads on <see cref="OptionsTabControlRow"/>
|
||||
/// such as <see cref="OptionsTabControlRow.AddOptionPercentSlider"/> instead of instantiating this type directly.
|
||||
/// </para>
|
||||
/// </remarks>
|
||||
/// <param name="controller">The control row that owns this option.</param>
|
||||
/// <param name="cfg">The configuration manager to get and set values from.</param>
|
||||
/// <param name="cVar">The CVar that is being controlled by this option.</param>
|
||||
/// <param name="slider">The UI control for the option.</param>
|
||||
public OptionColorSliderCVar(
|
||||
OptionsTabControlRow controller,
|
||||
IConfigurationManager cfg,
|
||||
CVarDef<string> cVar,
|
||||
OptionColorSlider slider) : base(controller, cfg, cVar)
|
||||
{
|
||||
_slider = slider;
|
||||
|
||||
slider.Slider.OnColorChanged += _ =>
|
||||
{
|
||||
ValueChanged();
|
||||
UpdateLabelColor();
|
||||
};
|
||||
}
|
||||
|
||||
private void UpdateLabelColor()
|
||||
{
|
||||
_slider.ExampleLabel.FontColorOverride = Color.FromHex(Value);
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Implementation of a CVar option that simply corresponds with an integer <see cref="OptionSlider"/>.
|
||||
/// </summary>
|
||||
|
||||
@@ -12,6 +12,10 @@
|
||||
<ui:OptionSlider Name="SpeechBubbleTextOpacitySlider" Title="{Loc 'ui-options-speech-bubble-text-opacity'}" />
|
||||
<ui:OptionSlider Name="SpeechBubbleSpeakerOpacitySlider" Title="{Loc 'ui-options-speech-bubble-speaker-opacity'}" />
|
||||
<ui:OptionSlider Name="SpeechBubbleBackgroundOpacitySlider" Title="{Loc 'ui-options-speech-bubble-background-opacity'}" />
|
||||
<CheckBox Name="AutoFillHighlightsCheckBox" Text="{Loc 'ui-options-auto-fill-highlights'}" />
|
||||
<ui:OptionColorSlider Name="HighlightsColorSlider"
|
||||
Title="{Loc 'ui-options-highlights-color'}"
|
||||
Example="{Loc 'ui-options-highlights-color-example'}"/>
|
||||
</BoxContainer>
|
||||
</ScrollContainer>
|
||||
<ui:OptionsTabControlRow Name="Control" Access="Public" />
|
||||
|
||||
@@ -20,6 +20,8 @@ public sealed partial class AccessibilityTab : Control
|
||||
Control.AddOptionPercentSlider(CCVars.SpeechBubbleTextOpacity, SpeechBubbleTextOpacitySlider);
|
||||
Control.AddOptionPercentSlider(CCVars.SpeechBubbleSpeakerOpacity, SpeechBubbleSpeakerOpacitySlider);
|
||||
Control.AddOptionPercentSlider(CCVars.SpeechBubbleBackgroundOpacity, SpeechBubbleBackgroundOpacitySlider);
|
||||
Control.AddOptionCheckBox(CCVars.ChatAutoFillHighlights, AutoFillHighlightsCheckBox);
|
||||
Control.AddOptionColorSlider(CCVars.ChatHighlightsColor, HighlightsColorSlider);
|
||||
|
||||
Control.Initialize();
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<ui:OptionDropDown Name="DropDownLightingQuality" Title="{Loc 'ui-options-lighting-label'}" />
|
||||
<CheckBox Name="ViewportLowResCheckBox" Text="{Loc 'ui-options-vp-low-res'}" />
|
||||
<CheckBox Name="ParallaxLowQualityCheckBox" Text="{Loc 'ui-options-parallax-low-quality'}" />
|
||||
<CheckBox Name="AmbientOcclusionCheckBox" Text="{Loc 'ui-options-ambient-occlusion'}" />
|
||||
|
||||
<!-- Interface -->
|
||||
<Label Text="{Loc 'ui-options-interface-label'}" StyleClasses="LabelKeyText"/>
|
||||
|
||||
@@ -20,6 +20,7 @@ public sealed partial class GraphicsTab : Control
|
||||
RobustXamlLoader.Load(this);
|
||||
|
||||
Control.AddOptionCheckBox(CVars.DisplayVSync, VSyncCheckBox);
|
||||
Control.AddOptionCheckBox(CCVars.AmbientOcclusion, AmbientOcclusionCheckBox);
|
||||
Control.AddOption(new OptionFullscreen(Control, _cfg, FullscreenCheckBox));
|
||||
Control.AddOption(new OptionLightingQuality(Control, _cfg, DropDownLightingQuality));
|
||||
|
||||
|
||||
@@ -7,7 +7,11 @@ namespace Content.Client.Overlays;
|
||||
|
||||
public sealed partial class StencilOverlay
|
||||
{
|
||||
private void DrawRestrictedRange(in OverlayDrawArgs args, RestrictedRangeComponent rangeComp, Matrix3x2 invMatrix)
|
||||
private void DrawRestrictedRange(
|
||||
in OverlayDrawArgs args,
|
||||
CachedResources res,
|
||||
RestrictedRangeComponent rangeComp,
|
||||
Matrix3x2 invMatrix)
|
||||
{
|
||||
var worldHandle = args.WorldHandle;
|
||||
var renderScale = args.Viewport.RenderScale.X;
|
||||
@@ -38,20 +42,20 @@ public sealed partial class StencilOverlay
|
||||
// Cut out the irrelevant bits via stencil
|
||||
// This is why we don't just use parallax; we might want specific tiles to get drawn over
|
||||
// particularly for planet maps or stations.
|
||||
worldHandle.RenderInRenderTarget(_blep!, () =>
|
||||
worldHandle.RenderInRenderTarget(res.Blep!, () =>
|
||||
{
|
||||
worldHandle.UseShader(_shader);
|
||||
worldHandle.DrawRect(localAABB, Color.White);
|
||||
}, Color.Transparent);
|
||||
|
||||
worldHandle.SetTransform(Matrix3x2.Identity);
|
||||
worldHandle.UseShader(_protoManager.Index<ShaderPrototype>("StencilMask").Instance());
|
||||
worldHandle.DrawTextureRect(_blep!.Texture, worldBounds);
|
||||
worldHandle.UseShader(_protoManager.Index(StencilMask).Instance());
|
||||
worldHandle.DrawTextureRect(res.Blep!.Texture, worldBounds);
|
||||
var curTime = _timing.RealTime;
|
||||
var sprite = _sprite.GetFrame(new SpriteSpecifier.Texture(new ResPath("/Textures/Parallaxes/noise.png")), curTime);
|
||||
|
||||
// Draw the rain
|
||||
worldHandle.UseShader(_protoManager.Index<ShaderPrototype>("StencilDraw").Instance());
|
||||
worldHandle.UseShader(_protoManager.Index(StencilDraw).Instance());
|
||||
_parallax.DrawParallax(worldHandle, worldAABB, sprite, curTime, position, new Vector2(0.5f, 0f));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,12 @@ public sealed partial class StencilOverlay
|
||||
{
|
||||
private List<Entity<MapGridComponent>> _grids = new();
|
||||
|
||||
private void DrawWeather(in OverlayDrawArgs args, WeatherPrototype weatherProto, float alpha, Matrix3x2 invMatrix)
|
||||
private void DrawWeather(
|
||||
in OverlayDrawArgs args,
|
||||
CachedResources res,
|
||||
WeatherPrototype weatherProto,
|
||||
float alpha,
|
||||
Matrix3x2 invMatrix)
|
||||
{
|
||||
var worldHandle = args.WorldHandle;
|
||||
var mapId = args.MapId;
|
||||
@@ -22,7 +27,7 @@ public sealed partial class StencilOverlay
|
||||
// Cut out the irrelevant bits via stencil
|
||||
// This is why we don't just use parallax; we might want specific tiles to get drawn over
|
||||
// particularly for planet maps or stations.
|
||||
worldHandle.RenderInRenderTarget(_blep!, () =>
|
||||
worldHandle.RenderInRenderTarget(res.Blep!, () =>
|
||||
{
|
||||
var xformQuery = _entManager.GetEntityQuery<TransformComponent>();
|
||||
_grids.Clear();
|
||||
@@ -55,13 +60,13 @@ public sealed partial class StencilOverlay
|
||||
}, Color.Transparent);
|
||||
|
||||
worldHandle.SetTransform(Matrix3x2.Identity);
|
||||
worldHandle.UseShader(_protoManager.Index<ShaderPrototype>("StencilMask").Instance());
|
||||
worldHandle.DrawTextureRect(_blep!.Texture, worldBounds);
|
||||
worldHandle.UseShader(_protoManager.Index(StencilMask).Instance());
|
||||
worldHandle.DrawTextureRect(res.Blep!.Texture, worldBounds);
|
||||
var curTime = _timing.RealTime;
|
||||
var sprite = _sprite.GetFrame(weatherProto.Sprite, curTime);
|
||||
|
||||
// Draw the rain
|
||||
worldHandle.UseShader(_protoManager.Index<ShaderPrototype>("StencilDraw").Instance());
|
||||
worldHandle.UseShader(_protoManager.Index(StencilDraw).Instance());
|
||||
_parallax.DrawParallax(worldHandle, worldAABB, sprite, curTime, position, Vector2.Zero, modulate: (weatherProto.Color ?? Color.White).WithAlpha(alpha));
|
||||
|
||||
worldHandle.SetTransform(Matrix3x2.Identity);
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Numerics;
|
||||
using Content.Client.Graphics;
|
||||
using Content.Client.Parallax;
|
||||
using Content.Client.Weather;
|
||||
using Content.Shared.Salvage;
|
||||
@@ -17,6 +18,9 @@ namespace Content.Client.Overlays;
|
||||
/// </summary>
|
||||
public sealed partial class StencilOverlay : Overlay
|
||||
{
|
||||
private static readonly ProtoId<ShaderPrototype> StencilMask = "StencilMask";
|
||||
private static readonly ProtoId<ShaderPrototype> StencilDraw = "StencilDraw";
|
||||
|
||||
[Dependency] private readonly IClyde _clyde = default!;
|
||||
[Dependency] private readonly IEntityManager _entManager = default!;
|
||||
[Dependency] private readonly IGameTiming _timing = default!;
|
||||
@@ -30,7 +34,7 @@ public sealed partial class StencilOverlay : Overlay
|
||||
|
||||
public override OverlaySpace Space => OverlaySpace.WorldSpaceBelowFOV;
|
||||
|
||||
private IRenderTexture? _blep;
|
||||
private readonly OverlayResourceCache<CachedResources> _resources = new();
|
||||
|
||||
private readonly ShaderInstance _shader;
|
||||
|
||||
@@ -51,10 +55,12 @@ public sealed partial class StencilOverlay : Overlay
|
||||
var mapUid = _mapManager.GetMapEntityId(args.MapId);
|
||||
var invMatrix = args.Viewport.GetWorldToLocalMatrix();
|
||||
|
||||
if (_blep?.Texture.Size != args.Viewport.Size)
|
||||
var res = _resources.GetForViewport(args.Viewport, static _ => new CachedResources());
|
||||
|
||||
if (res.Blep?.Texture.Size != args.Viewport.Size)
|
||||
{
|
||||
_blep?.Dispose();
|
||||
_blep = _clyde.CreateRenderTarget(args.Viewport.Size, new RenderTargetFormatParameters(RenderTargetColorFormat.Rgba8Srgb), name: "weather-stencil");
|
||||
res.Blep?.Dispose();
|
||||
res.Blep = _clyde.CreateRenderTarget(args.Viewport.Size, new RenderTargetFormatParameters(RenderTargetColorFormat.Rgba8Srgb), name: "weather-stencil");
|
||||
}
|
||||
|
||||
if (_entManager.TryGetComponent<WeatherComponent>(mapUid, out var comp))
|
||||
@@ -65,16 +71,33 @@ public sealed partial class StencilOverlay : Overlay
|
||||
continue;
|
||||
|
||||
var alpha = _weather.GetPercent(weather, mapUid);
|
||||
DrawWeather(args, weatherProto, alpha, invMatrix);
|
||||
DrawWeather(args, res, weatherProto, alpha, invMatrix);
|
||||
}
|
||||
}
|
||||
|
||||
if (_entManager.TryGetComponent<RestrictedRangeComponent>(mapUid, out var restrictedRangeComponent))
|
||||
{
|
||||
DrawRestrictedRange(args, restrictedRangeComponent, invMatrix);
|
||||
DrawRestrictedRange(args, res, restrictedRangeComponent, invMatrix);
|
||||
}
|
||||
|
||||
args.WorldHandle.UseShader(null);
|
||||
args.WorldHandle.SetTransform(Matrix3x2.Identity);
|
||||
}
|
||||
|
||||
protected override void DisposeBehavior()
|
||||
{
|
||||
_resources.Dispose();
|
||||
|
||||
base.DisposeBehavior();
|
||||
}
|
||||
|
||||
private sealed class CachedResources : IDisposable
|
||||
{
|
||||
public IRenderTexture? Blep;
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
Blep?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,34 @@
|
||||
using Content.Client.Atmos.Overlays;
|
||||
using Content.Shared.Inventory.Events;
|
||||
using Content.Shared.Overlays;
|
||||
using Robust.Client.Graphics;
|
||||
|
||||
namespace Content.Client.Overlays;
|
||||
|
||||
public sealed partial class ThermalSightOverlaySystem : EquipmentHudSystem<ThermalSightComponent>
|
||||
{
|
||||
[Dependency] private readonly IOverlayManager _overlayMan = default!;
|
||||
|
||||
private GasTileDangerousTemperatureOverlay _temperatureOverlay = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
base.Initialize();
|
||||
|
||||
_temperatureOverlay = new();
|
||||
}
|
||||
|
||||
protected override void UpdateInternal(RefreshEquipmentHudEvent<ThermalSightComponent> component)
|
||||
{
|
||||
base.UpdateInternal(component);
|
||||
|
||||
_overlayMan.AddOverlay(_temperatureOverlay);
|
||||
}
|
||||
|
||||
protected override void DeactivateInternal()
|
||||
{
|
||||
base.DeactivateInternal();
|
||||
|
||||
_overlayMan.RemoveOverlay(_temperatureOverlay);
|
||||
}
|
||||
}
|
||||
@@ -6,18 +6,28 @@ namespace Content.Client.Paper.UI;
|
||||
|
||||
public sealed class PaperVisualizerSystem : VisualizerSystem<PaperVisualsComponent>
|
||||
{
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
protected override void OnAppearanceChange(EntityUid uid, PaperVisualsComponent component, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (AppearanceSystem.TryGetData<PaperStatus>(uid, PaperVisuals.Status , out var writingStatus, args.Component))
|
||||
args.Sprite.LayerSetVisible(PaperVisualLayers.Writing, writingStatus == PaperStatus.Written);
|
||||
if (AppearanceSystem.TryGetData<PaperStatus>(uid, PaperVisuals.Status, out var writingStatus, args.Component))
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), PaperVisualLayers.Writing, writingStatus == PaperStatus.Written);
|
||||
|
||||
if (AppearanceSystem.TryGetData<string>(uid, PaperVisuals.Stamp, out var stampState, args.Component))
|
||||
{
|
||||
args.Sprite.LayerSetState(PaperVisualLayers.Stamp, stampState);
|
||||
args.Sprite.LayerSetVisible(PaperVisualLayers.Stamp, true);
|
||||
if (stampState != string.Empty)
|
||||
{
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), PaperVisualLayers.Stamp, stampState);
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), PaperVisualLayers.Stamp, true);
|
||||
}
|
||||
else
|
||||
{
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), PaperVisualLayers.Stamp, false);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -98,10 +98,13 @@ public sealed class ParallaxManager : IParallaxManager
|
||||
}
|
||||
else
|
||||
{
|
||||
layers = await Task.WhenAll(
|
||||
// Explicitly allocate params array to avoid sandbox violation since C# 14.
|
||||
var tasks = new[]
|
||||
{
|
||||
LoadParallaxLayers(parallaxPrototype.Layers, loadedLayers, cancel),
|
||||
LoadParallaxLayers(parallaxPrototype.LayersLQ, loadedLayers, cancel)
|
||||
);
|
||||
LoadParallaxLayers(parallaxPrototype.LayersLQ, loadedLayers, cancel),
|
||||
};
|
||||
layers = await Task.WhenAll(tasks);
|
||||
}
|
||||
|
||||
cancel.ThrowIfCancellationRequested();
|
||||
|
||||
@@ -1,4 +1,3 @@
|
||||
using System.Linq;
|
||||
using Content.Shared.Singularity.Components;
|
||||
using Robust.Client.GameObjects;
|
||||
|
||||
@@ -6,12 +5,14 @@ namespace Content.Client.ParticleAccelerator;
|
||||
|
||||
public sealed class ParticleAcceleratorPartVisualizerSystem : VisualizerSystem<ParticleAcceleratorPartVisualsComponent>
|
||||
{
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
protected override void OnAppearanceChange(EntityUid uid, ParticleAcceleratorPartVisualsComponent comp, ref AppearanceChangeEvent args)
|
||||
{
|
||||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (!args.Sprite.LayerMapTryGet(ParticleAcceleratorVisualLayers.Unlit, out var index))
|
||||
if (!_sprite.LayerMapTryGet((uid, args.Sprite), ParticleAcceleratorVisualLayers.Unlit, out var index, false))
|
||||
return;
|
||||
|
||||
if (!AppearanceSystem.TryGetData<ParticleAcceleratorVisualState>(uid, ParticleAcceleratorVisuals.VisualState, out var state, args.Component))
|
||||
@@ -21,12 +22,12 @@ public sealed class ParticleAcceleratorPartVisualizerSystem : VisualizerSystem<P
|
||||
|
||||
if (state != ParticleAcceleratorVisualState.Unpowered)
|
||||
{
|
||||
args.Sprite.LayerSetVisible(index, true);
|
||||
args.Sprite.LayerSetState(index, comp.StateBase + comp.StatesSuffixes[state]);
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), index, true);
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), index, comp.StateBase + comp.StatesSuffixes[state]);
|
||||
}
|
||||
else
|
||||
{
|
||||
args.Sprite.LayerSetVisible(index, false);
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), index, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,6 +11,7 @@ using Robust.Shared.GameObjects;
|
||||
using Robust.Shared.Localization;
|
||||
using Robust.Shared.Maths;
|
||||
using FancyWindow = Content.Client.UserInterface.Controls.FancyWindow;
|
||||
using System.Numerics;
|
||||
|
||||
namespace Content.Client.Power.APC.UI
|
||||
{
|
||||
|
||||
@@ -6,7 +6,6 @@ using Robust.Shared.Utility;
|
||||
using System.Diagnostics.CodeAnalysis;
|
||||
using System.Linq;
|
||||
using System.Numerics;
|
||||
using Vector4 = Robust.Shared.Maths.Vector4;
|
||||
|
||||
namespace Content.Client.Power;
|
||||
|
||||
|
||||
@@ -9,6 +9,7 @@ namespace Content.Client.PowerCell;
|
||||
public sealed class PowerCellSystem : SharedPowerCellSystem
|
||||
{
|
||||
[Dependency] private readonly SharedAppearanceSystem _appearance = default!;
|
||||
[Dependency] private readonly SpriteSystem _sprite = default!;
|
||||
|
||||
public override void Initialize()
|
||||
{
|
||||
@@ -44,19 +45,19 @@ public sealed class PowerCellSystem : SharedPowerCellSystem
|
||||
if (args.Sprite == null)
|
||||
return;
|
||||
|
||||
if (!args.Sprite.TryGetLayer((int) PowerCellVisualLayers.Unshaded, out var unshadedLayer))
|
||||
if (!_sprite.LayerExists((uid, args.Sprite), PowerCellVisualLayers.Unshaded))
|
||||
return;
|
||||
|
||||
if (_appearance.TryGetData<byte>(uid, PowerCellVisuals.ChargeLevel, out var level, args.Component))
|
||||
{
|
||||
if (level == 0)
|
||||
{
|
||||
unshadedLayer.Visible = false;
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), PowerCellVisualLayers.Unshaded, false);
|
||||
return;
|
||||
}
|
||||
|
||||
unshadedLayer.Visible = true;
|
||||
args.Sprite.LayerSetState(PowerCellVisualLayers.Unshaded, $"o{level}");
|
||||
_sprite.LayerSetVisible((uid, args.Sprite), PowerCellVisualLayers.Unshaded, false);
|
||||
_sprite.LayerSetRsiState((uid, args.Sprite), PowerCellVisualLayers.Unshaded, $"o{level}");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -12,9 +12,16 @@
|
||||
|
||||
<!-- Entry layer (shows main categories) -->
|
||||
<ui:RadialContainer Name="Main" VerticalExpand="True" HorizontalExpand="True" InitialRadius="100" ReserveSpaceForHiddenChildren="False">
|
||||
|
||||
<ui:RadialMenuTextureButtonWithSector SetSize="64 64" ToolTip="{Loc 'rcd-component-walls-and-flooring'}" TargetLayer="WallsAndFlooring" Visible="False">
|
||||
<TextureRect VerticalAlignment="Center" HorizontalAlignment="Center" TextureScale="2 2" TexturePath="/Textures/Interface/Radial/RCD/walls_and_flooring.png"/>
|
||||
</ui:RadialMenuTextureButtonWithSector>
|
||||
<ui:RadialMenuTextureButtonWithSector SetSize="64 64" ToolTip="{Loc 'rcd-component-latticetiles'}" TargetLayer="LatticeTiles" Visible="False"> <!-- Mono -->
|
||||
<TextureRect VerticalAlignment="Center" HorizontalAlignment="Center" TextureScale="2 2" TexturePath="/Textures/Interface/Radial/RCD/lattice.png"/>
|
||||
</ui:RadialMenuTextureButtonWithSector>
|
||||
<ui:RadialMenuTextureButtonWithSector SetSize="64 64" ToolTip="{Loc 'rcd-component-platingtiles'}" TargetLayer="PlatingTiles" Visible="False"> <!-- Mono -->
|
||||
<TextureRect VerticalAlignment="Center" HorizontalAlignment="Center" TextureScale="2 2" TexturePath="/Textures/Interface/Radial/RCD/plating.png"/>
|
||||
</ui:RadialMenuTextureButtonWithSector>
|
||||
<ui:RadialMenuTextureButtonWithSector SetSize="64 64" ToolTip="{Loc 'rcd-component-windows-and-grilles'}" TargetLayer="WindowsAndGrilles" Visible="False">
|
||||
<TextureRect VerticalAlignment="Center" HorizontalAlignment="Center" TextureScale="2 2" TexturePath="/Textures/Interface/Radial/RCD/windows_and_grilles.png"/>
|
||||
</ui:RadialMenuTextureButtonWithSector>
|
||||
@@ -27,11 +34,18 @@
|
||||
<ui:RadialMenuTextureButtonWithSector SetSize="64 64" ToolTip="{Loc 'rcd-component-lighting'}" TargetLayer="Lighting" Visible="False">
|
||||
<TextureRect VerticalAlignment="Center" HorizontalAlignment="Center" TextureScale="2 2" TexturePath="/Textures/Interface/Radial/RCD/lighting.png"/>
|
||||
</ui:RadialMenuTextureButtonWithSector>
|
||||
|
||||
</ui:RadialContainer>
|
||||
|
||||
<!-- Walls and flooring -->
|
||||
<ui:RadialContainer Name="WallsAndFlooring" VerticalExpand="True" HorizontalExpand="True" InitialRadius="100"/>
|
||||
|
||||
<!-- Lattices Mono -->
|
||||
<ui:RadialContainer Name="LatticeTiles" VerticalExpand="True" HorizontalExpand="True" InitialRadius="100"/>
|
||||
|
||||
<!-- Plating Mono -->
|
||||
<ui:RadialContainer Name="PlatingTiles" VerticalExpand="True" HorizontalExpand="True" InitialRadius="100"/>
|
||||
|
||||
<!-- Windows and grilles -->
|
||||
<ui:RadialContainer Name="WindowsAndGrilles" VerticalExpand="True" HorizontalExpand="True" InitialRadius="100"/>
|
||||
|
||||
|
||||
@@ -77,6 +77,16 @@ public sealed partial class RoboticsConsoleWindow : FancyWindow
|
||||
if (_selected is {} selected && !_cyborgs.ContainsKey(selected))
|
||||
_selected = null;
|
||||
|
||||
// Corvax-Next-AiRemoteControl-Start
|
||||
var isAiControllable = false;
|
||||
|
||||
if (_selected != null)
|
||||
{
|
||||
_cyborgs.TryGetValue(_selected, out var data);
|
||||
isAiControllable = data.IsAiControllable;
|
||||
}
|
||||
// Corvax-Next-AiRemoteControl-End
|
||||
|
||||
var hasCyborgs = _cyborgs.Count > 0;
|
||||
NoCyborgs.Visible = !hasCyborgs;
|
||||
CyborgsContainer.Visible = hasCyborgs;
|
||||
|
||||
@@ -6,6 +6,9 @@ using Robust.Client.UserInterface;
|
||||
using Robust.Shared.Log;
|
||||
using Robust.Shared.Map;
|
||||
|
||||
// Mono
|
||||
using Content.Shared._Mono.Shuttles;
|
||||
|
||||
namespace Content.Client.Shuttles.BUI;
|
||||
|
||||
[UsedImplicitly]
|
||||
@@ -25,6 +28,7 @@ public sealed partial class ShuttleConsoleBoundUserInterface : BoundUserInterfac
|
||||
|
||||
_window.RequestFTL += OnFTLRequest;
|
||||
_window.RequestBeaconFTL += OnFTLBeaconRequest;
|
||||
_window.RequestAutopilot += OnAutopilotRequest; // Mono
|
||||
_window.DockRequest += OnDockRequest;
|
||||
_window.UndockRequest += OnUndockRequest;
|
||||
_window.UndockAllRequest += OnUndockAllRequest;
|
||||
@@ -78,6 +82,16 @@ public sealed partial class ShuttleConsoleBoundUserInterface : BoundUserInterfac
|
||||
});
|
||||
}
|
||||
|
||||
// Mono
|
||||
private void OnAutopilotRequest(MapCoordinates obj, Angle angle)
|
||||
{
|
||||
SendMessage(new ShuttleConsoleAutopilotPositionMessage()
|
||||
{
|
||||
Coordinates = obj,
|
||||
Angle = angle,
|
||||
});
|
||||
}
|
||||
|
||||
protected override void Dispose(bool disposing)
|
||||
{
|
||||
base.Dispose(disposing);
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using Content.Shared.Shuttles.Systems;
|
||||
using Content.Shared.Shuttles.Components;
|
||||
using Content.Shared.Access.Components;
|
||||
using Content.Shared.UserInterface;
|
||||
|
||||
namespace Content.Client.Shuttles.Systems;
|
||||
|
||||
@@ -17,4 +18,17 @@ public sealed class ShuttleConsoleLockSystem : SharedShuttleConsoleLockSystem
|
||||
// Prediction only
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Client extension of OnUIOpenAttempt. Prevents UI flashing open on client.
|
||||
/// </summary>
|
||||
protected override void OnUIOpenAttempt(EntityUid uid,
|
||||
ShuttleConsoleLockComponent component,
|
||||
ActivatableUIOpenAttemptEvent args)
|
||||
{
|
||||
base.OnUIOpenAttempt(uid, component, args);
|
||||
|
||||
if(Timing.IsFirstTimePredicted && args.Cancelled)
|
||||
Popup.PopupEntity(Loc.GetString("shuttle-console-locked"), uid, args.User);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -138,6 +138,293 @@ public partial class BaseShuttleControl : MapGridControl
|
||||
}
|
||||
// End Frontier Corvax
|
||||
|
||||
// Mono
|
||||
protected void DrawAzimuthScale(DrawingHandleScreen handle, Angle rotation)
|
||||
{
|
||||
const int azimuthMinorTickStepDegrees = 10;
|
||||
const int azimuthMajorTickInterval = 3;
|
||||
const int azimuthCardinalTickInterval = 9;
|
||||
const float edgeInset = 10f;
|
||||
const float tickInset = 4f;
|
||||
const float minorTickLength = 5f;
|
||||
const float majorTickLength = 9f;
|
||||
const float cardinalTickLength = 12f;
|
||||
const float labelPadding = 3f;
|
||||
const float labelOffset = tickInset + cardinalTickLength + labelPadding;
|
||||
const float regularLabelScale = 0.62f;
|
||||
const float cardinalLabelScale = 0.72f;
|
||||
|
||||
var origin = MidPointVector;
|
||||
var viewportSize = new Vector2(PixelWidth, PixelHeight);
|
||||
|
||||
var subtleGray = Color.FromHex("#676767");
|
||||
var northAccent = Color.FromHex("#7F7442");
|
||||
var eastAccent = Color.FromHex("#456273");
|
||||
var baseTickColor = subtleGray.WithAlpha(0.34f);
|
||||
var majorTickColor = subtleGray.WithAlpha(0.5f);
|
||||
var cardinalTickColor = subtleGray.WithAlpha(0.68f);
|
||||
var regularLabelColor = subtleGray.WithAlpha(0.76f);
|
||||
var cardinalLabelColor = subtleGray.WithAlpha(0.9f);
|
||||
var labelShadowColor = Color.Black.WithAlpha(0.36f);
|
||||
|
||||
for (var step = 0; step < 360 / azimuthMinorTickStepDegrees; step++)
|
||||
{
|
||||
var degrees = step * azimuthMinorTickStepDegrees;
|
||||
var direction = GetAzimuthDirection(rotation, degrees);
|
||||
var isCardinal = step % azimuthCardinalTickInterval == 0;
|
||||
var isMajor = step % azimuthMajorTickInterval == 0;
|
||||
var isNorth = degrees == 0;
|
||||
var isEast = degrees == 90;
|
||||
var tickLength = isCardinal
|
||||
? cardinalTickLength
|
||||
: isMajor
|
||||
? majorTickLength
|
||||
: minorTickLength;
|
||||
|
||||
if (!TryGetViewportEdgePoint(origin, direction, viewportSize, edgeInset, out var edgePoint, out var inwardNormal))
|
||||
continue;
|
||||
|
||||
var outer = edgePoint + inwardNormal * tickInset;
|
||||
var inner = outer + inwardNormal * tickLength;
|
||||
var tickColor = isNorth
|
||||
? northAccent.WithAlpha(0.58f)
|
||||
: isEast
|
||||
? eastAccent.WithAlpha(0.58f)
|
||||
: isCardinal
|
||||
? cardinalTickColor
|
||||
: isMajor
|
||||
? majorTickColor
|
||||
: baseTickColor;
|
||||
handle.DrawLine(outer, inner, tickColor);
|
||||
if (isNorth)
|
||||
{
|
||||
var sideOffset = new Vector2(-inwardNormal.Y, inwardNormal.X) * 0.35f;
|
||||
handle.DrawLine(outer + sideOffset, inner + sideOffset, tickColor.WithAlpha(0.46f));
|
||||
}
|
||||
|
||||
if (!isMajor)
|
||||
continue;
|
||||
|
||||
var label = degrees.ToString();
|
||||
var labelScale = isCardinal ? cardinalLabelScale : regularLabelScale;
|
||||
var labelColor = isEast
|
||||
? eastAccent.WithAlpha(0.76f)
|
||||
: isCardinal
|
||||
? cardinalLabelColor
|
||||
: regularLabelColor;
|
||||
var labelSize = handle.GetDimensions(Font, label, labelScale);
|
||||
var labelPosition = GetEdgeLabelPosition(edgePoint, inwardNormal, labelSize, viewportSize, labelOffset);
|
||||
handle.DrawString(Font, labelPosition + new Vector2(1f, 1f), label, labelScale, labelShadowColor);
|
||||
handle.DrawString(Font, labelPosition, label, labelScale, labelColor);
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawAzimuthRing(DrawingHandleScreen handle, Angle rotation)
|
||||
{
|
||||
const int azimuthMinorTickStepDegrees = 10;
|
||||
const int azimuthMajorTickInterval = 3;
|
||||
const int azimuthCardinalTickInterval = 9;
|
||||
const float ringInset = 16f;
|
||||
const float minorTickLength = 5f;
|
||||
const float majorTickLength = 9f;
|
||||
const float cardinalTickLength = 12f;
|
||||
const float labelPadding = 5f;
|
||||
const float regularLabelScale = 0.62f;
|
||||
const float cardinalLabelScale = 0.72f;
|
||||
|
||||
var origin = MidPointVector;
|
||||
var radius = MathF.Max(8f, SizeFull * 0.5f - ringInset);
|
||||
|
||||
var subtleGray = Color.FromHex("#676767");
|
||||
var northAccent = Color.FromHex("#7F7442");
|
||||
var eastAccent = Color.FromHex("#456273");
|
||||
var baseTickColor = subtleGray.WithAlpha(0.34f);
|
||||
var majorTickColor = subtleGray.WithAlpha(0.5f);
|
||||
var cardinalTickColor = subtleGray.WithAlpha(0.68f);
|
||||
var regularLabelColor = subtleGray.WithAlpha(0.76f);
|
||||
var cardinalLabelColor = subtleGray.WithAlpha(0.9f);
|
||||
var labelShadowColor = Color.Black.WithAlpha(0.36f);
|
||||
|
||||
handle.DrawCircle(origin, radius, subtleGray.WithAlpha(0.12f), false);
|
||||
|
||||
for (var step = 0; step < 360 / azimuthMinorTickStepDegrees; step++)
|
||||
{
|
||||
var degrees = step * azimuthMinorTickStepDegrees;
|
||||
var direction = GetAzimuthDirection(rotation, degrees);
|
||||
var isCardinal = step % azimuthCardinalTickInterval == 0;
|
||||
var isMajor = step % azimuthMajorTickInterval == 0;
|
||||
var isNorth = degrees == 0;
|
||||
var isEast = degrees == 90;
|
||||
var tickLength = isCardinal
|
||||
? cardinalTickLength
|
||||
: isMajor
|
||||
? majorTickLength
|
||||
: minorTickLength;
|
||||
|
||||
var outer = origin + direction * radius;
|
||||
var inner = origin + direction * (radius - tickLength);
|
||||
var tickColor = isNorth
|
||||
? northAccent.WithAlpha(0.58f)
|
||||
: isEast
|
||||
? eastAccent.WithAlpha(0.58f)
|
||||
: isCardinal
|
||||
? cardinalTickColor
|
||||
: isMajor
|
||||
? majorTickColor
|
||||
: baseTickColor;
|
||||
handle.DrawLine(outer, inner, tickColor);
|
||||
if (isNorth)
|
||||
{
|
||||
var sideOffset = new Vector2(-direction.Y, direction.X) * 0.35f;
|
||||
handle.DrawLine(outer + sideOffset, inner + sideOffset, tickColor.WithAlpha(0.46f));
|
||||
}
|
||||
|
||||
if (!isMajor)
|
||||
continue;
|
||||
|
||||
var label = degrees.ToString();
|
||||
var labelScale = isCardinal ? cardinalLabelScale : regularLabelScale;
|
||||
var labelColor = isEast
|
||||
? eastAccent.WithAlpha(0.76f)
|
||||
: isCardinal
|
||||
? cardinalLabelColor
|
||||
: regularLabelColor;
|
||||
var labelSize = handle.GetDimensions(Font, label, labelScale);
|
||||
var labelPosition = origin + direction * (radius - tickLength - labelPadding) - labelSize * 0.5f;
|
||||
handle.DrawString(Font, labelPosition + new Vector2(1f, 1f), label, labelScale, labelShadowColor);
|
||||
handle.DrawString(Font, labelPosition, label, labelScale, labelColor);
|
||||
}
|
||||
}
|
||||
|
||||
protected void DrawCompassOverlay(DrawingHandleScreen handle, Angle heading)
|
||||
{
|
||||
var compassCenter = new Vector2(44f, 44f);
|
||||
const float compassRadius = 24f;
|
||||
var ringColor = Color.White.WithAlpha(0.08f);
|
||||
var northColor = Color.FromHex("#776C43");
|
||||
var eastColor = Color.FromHex("#4C6572");
|
||||
handle.DrawCircle(compassCenter, compassRadius, ringColor, false);
|
||||
handle.DrawCircle(compassCenter, 2.5f, ringColor.WithAlpha(0.48f), true);
|
||||
|
||||
DrawCompassNeedle(handle, compassCenter, compassRadius, GetAzimuthDirection(heading, 0f), "N", northColor);
|
||||
DrawCompassNeedle(handle, compassCenter, compassRadius * 0.82f, GetAzimuthDirection(heading, 90f), "E", eastColor);
|
||||
}
|
||||
|
||||
private void DrawCompassNeedle(
|
||||
DrawingHandleScreen handle,
|
||||
Vector2 compassCenter,
|
||||
float radius,
|
||||
Vector2 direction,
|
||||
string label,
|
||||
Color color)
|
||||
{
|
||||
var tip = compassCenter + direction * radius;
|
||||
var tail = compassCenter - direction * (radius * 0.35f);
|
||||
DrawArrowLine(handle, tail, tip, color.WithAlpha(0.58f), 6f);
|
||||
|
||||
var labelSize = handle.GetDimensions(Font, label, 0.9f);
|
||||
var labelPosition = tip + direction * 6f - new Vector2(labelSize.X * 0.5f, labelSize.Y * 0.5f);
|
||||
handle.DrawString(Font, labelPosition, label, 0.9f, color.WithAlpha(0.7f));
|
||||
}
|
||||
|
||||
private static void DrawArrowLine(
|
||||
DrawingHandleScreen handle,
|
||||
Vector2 start,
|
||||
Vector2 end,
|
||||
Color color,
|
||||
float headLength)
|
||||
{
|
||||
var direction = end - start;
|
||||
if (direction.LengthSquared() <= 0.001f)
|
||||
return;
|
||||
|
||||
direction = Vector2.Normalize(direction);
|
||||
var left = new Vector2(-direction.Y, direction.X);
|
||||
handle.DrawLine(start, end, color);
|
||||
handle.DrawLine(end, end - direction * headLength + left * (headLength * 0.45f), color);
|
||||
handle.DrawLine(end, end - direction * headLength - left * (headLength * 0.45f), color);
|
||||
}
|
||||
|
||||
private static bool TryGetViewportEdgePoint(
|
||||
Vector2 origin,
|
||||
Vector2 direction,
|
||||
Vector2 viewportSize,
|
||||
float inset,
|
||||
out Vector2 edgePoint,
|
||||
out Vector2 inwardNormal)
|
||||
{
|
||||
edgePoint = default;
|
||||
inwardNormal = default;
|
||||
|
||||
if (direction.LengthSquared() <= 0.001f)
|
||||
return false;
|
||||
|
||||
direction = Vector2.Normalize(direction);
|
||||
var min = new Vector2(inset, inset);
|
||||
var max = viewportSize - min;
|
||||
if (max.X <= min.X || max.Y <= min.Y)
|
||||
return false;
|
||||
|
||||
var tx = direction.X > 0f
|
||||
? (max.X - origin.X) / direction.X
|
||||
: direction.X < 0f
|
||||
? (min.X - origin.X) / direction.X
|
||||
: float.PositiveInfinity;
|
||||
var ty = direction.Y > 0f
|
||||
? (max.Y - origin.Y) / direction.Y
|
||||
: direction.Y < 0f
|
||||
? (min.Y - origin.Y) / direction.Y
|
||||
: float.PositiveInfinity;
|
||||
|
||||
var t = Math.Min(tx, ty);
|
||||
if (!float.IsFinite(t) || t <= 0f)
|
||||
return false;
|
||||
|
||||
edgePoint = origin + direction * t;
|
||||
|
||||
if (tx < ty)
|
||||
inwardNormal = direction.X > 0f ? -Vector2.UnitX : Vector2.UnitX;
|
||||
else
|
||||
inwardNormal = direction.Y > 0f ? -Vector2.UnitY : Vector2.UnitY;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static Vector2 GetEdgeLabelPosition(
|
||||
Vector2 edgePoint,
|
||||
Vector2 inwardNormal,
|
||||
Vector2 labelSize,
|
||||
Vector2 viewportSize,
|
||||
float offset)
|
||||
{
|
||||
var anchor = edgePoint + inwardNormal * offset;
|
||||
Vector2 requested;
|
||||
if (Math.Abs(inwardNormal.X) > Math.Abs(inwardNormal.Y))
|
||||
{
|
||||
requested = inwardNormal.X > 0f
|
||||
? new Vector2(anchor.X, anchor.Y - labelSize.Y * 0.5f)
|
||||
: new Vector2(anchor.X - labelSize.X, anchor.Y - labelSize.Y * 0.5f);
|
||||
}
|
||||
else
|
||||
{
|
||||
requested = inwardNormal.Y > 0f
|
||||
? new Vector2(anchor.X - labelSize.X * 0.5f, anchor.Y)
|
||||
: new Vector2(anchor.X - labelSize.X * 0.5f, anchor.Y - labelSize.Y);
|
||||
}
|
||||
|
||||
var minPosition = new Vector2(offset, offset);
|
||||
var maxPosition = viewportSize - labelSize - minPosition;
|
||||
return Vector2.Clamp(requested, minPosition, maxPosition);
|
||||
}
|
||||
|
||||
private static Vector2 GetAzimuthDirection(Angle baseAngle, float azimuthDegrees)
|
||||
{
|
||||
var angle = baseAngle + Angle.FromDegrees(azimuthDegrees);
|
||||
var radians = (float) angle.Theta - MathF.PI / 2f;
|
||||
return new Vector2(MathF.Cos(radians), MathF.Sin(radians));
|
||||
}
|
||||
// End Mono
|
||||
|
||||
protected void DrawGrid(DrawingHandleScreen handle, Matrix3x2 gridToView, Entity<MapGridComponent> grid, Color color, float alpha = 0.01f)
|
||||
{
|
||||
var rator = Maps.GetAllTilesEnumerator(grid.Owner, grid.Comp);
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
Orientation="Vertical">
|
||||
<!-- FTL Lock Section -->
|
||||
<controls1:StripeBack MinSize="48 48">
|
||||
<controls:Label Text="{controls:Loc 'FTL Lock'}" HorizontalAlignment="Center"/>
|
||||
<controls:Label Text="{controls:Loc 'shuttle-console-ftl-lock'}" HorizontalAlignment="Center"/>
|
||||
</controls1:StripeBack>
|
||||
<controls:PanelContainer VerticalExpand="True" HorizontalExpand="True" Margin="4 4 4 4">
|
||||
<controls:PanelContainer.PanelOverride>
|
||||
@@ -36,12 +36,12 @@
|
||||
</controls:PanelContainer.PanelOverride>
|
||||
<controls:BoxContainer Orientation="Horizontal" HorizontalAlignment="Stretch" Margin="5 5 5 5">
|
||||
<controls:Button Name="FTLLockEnabledButton"
|
||||
Text="{controls:Loc 'Enabled'}"
|
||||
Text="{controls:Loc 'shuttle-console-ftl-lock-enabled'}"
|
||||
ToggleMode="True"
|
||||
HorizontalExpand="True"
|
||||
StyleClasses="OpenRight"/>
|
||||
<controls:Button Name="FTLLockDisabledButton"
|
||||
Text="{controls:Loc 'Disabled'}"
|
||||
Text="{controls:Loc 'shuttle-console-ftl-lock-disabled'}"
|
||||
ToggleMode="True"
|
||||
HorizontalExpand="True"
|
||||
StyleClasses="OpenLeft"/>
|
||||
@@ -50,7 +50,7 @@
|
||||
|
||||
<!-- Docks Section -->
|
||||
<controls1:StripeBack MinSize="48 48">
|
||||
<controls:Label Text="{controls:Loc 'Docks'}" HorizontalAlignment="Center"/>
|
||||
<controls:Label Text="{controls:Loc 'shuttle-console-docks-label'}" HorizontalAlignment="Center"/>
|
||||
</controls1:StripeBack>
|
||||
<controls:PanelContainer VerticalExpand="True" HorizontalExpand="True" Margin="4 4 4 4">
|
||||
<controls:PanelContainer.PanelOverride>
|
||||
@@ -62,7 +62,7 @@
|
||||
<graphics:StyleBoxFlat BorderThickness="2" BorderColor="#333333" BackgroundColor="#121212"/>
|
||||
</controls:PanelContainer.PanelOverride>
|
||||
<controls:Button Name="UndockAllButton"
|
||||
Text="{controls:Loc 'Undock All'}"
|
||||
Text="{controls:Loc 'shuttle-console-undock-all'}"
|
||||
Margin="5 5 5 5"
|
||||
StyleClasses="ButtonSquare"/>
|
||||
</controls:PanelContainer>
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user