202 Commits
v2.0.7 ... dev

Author SHA1 Message Date
ZioPao
bd532dc013 fix: relayed amputations 2026-01-31 17:32:28 +01:00
ZioPao
1d21c0d51c fix: relay wear amputation 2026-01-31 17:21:10 +01:00
ZioPao
e129b325e4 fix: wearing amputation in MP 42.13 2026-01-27 23:01:56 +01:00
ZioPao
df9f559078 fix: working amputations in mp 2026-01-27 01:33:54 +01:00
ZioPao
1fb3899a5a chore: stuff to move around for 42.13 2026-01-15 22:37:13 +01:00
ZioPao
457f89b064 fix: error while amputating 2026-01-15 22:37:06 +01:00
ZioPao
27d79c5802 chore: removed old b41 tasks 2026-01-08 01:56:20 +01:00
ZioPao
92a0b9ef18 fix: encoding UA again 2026-01-08 01:53:02 +01:00
Vinellon
494b4b576f fix encoding for translate files 2026-01-08 01:43:35 +01:00
ZioPao
76fcb1ac97 Merge branch 'dev-42.13' of https://github.com/ZioPao/The-Only-Cure into dev-42.13-merge 2026-01-08 01:39:40 +01:00
ZioPao
fba1b2e643 fix: wip changes for traits and infection healing 2026-01-08 01:26:17 +01:00
ZioPao
2cf7df16b3 refactor: changes to StaticData and registries 2026-01-08 01:25:53 +01:00
ZioPao
898e8ec653 refactor: restored new bodylocs 2026-01-08 01:23:53 +01:00
guiriguy
943e3a8f3c Refactor prosthetic limb string constants
Updated string constants for prosthetic limbs and body locations.
2025-12-18 22:51:51 +01:00
guiriguy
442af10b7a Update Registries.lua 2025-12-18 22:51:27 +01:00
guiriguy
c9d6236b89 Refactor BodyLocations.lua for improved management
Refactored BodyLocations.lua to streamline body location management and improve functionality.
2025-12-18 22:51:06 +01:00
guiriguy
e884985fe3 Refactor player courage and temperature checks 2025-12-18 22:50:28 +01:00
guiriguy
38fe71bc72 Refactor ProsthesisHandler for B42 compatibility 2025-12-18 22:48:17 +01:00
guiriguy
b650b2a590 Refactor tourniquet check and update patient stats 2025-12-18 22:48:00 +01:00
guiriguy
da7621c0f0 Refactor LocalPlayerController to use TOC registries 2025-12-18 22:47:31 +01:00
guiriguy
acd2e9c547 Refactor TOC registries for traits and body locations 2025-12-18 22:46:57 +01:00
ZioPao
27d9b3a513 fix: bodyloc check for tourniquets 2025-12-16 01:02:51 +01:00
ZioPao
aa61a3390c fix: wrong dir for Translate 2025-12-16 00:56:06 +01:00
ZioPao
b84c2a593d fix: items bodylocs 2025-12-16 00:56:00 +01:00
ZioPao
cdf0473065 fix: Type to ItemType in items ZedScripts 2025-12-16 00:51:23 +01:00
ZioPao
40da330b41 fix: trait init in LocalPlayerController 2025-12-16 00:51:05 +01:00
ZioPao
20fa1bd05e refactor: removed compat with b41 entirely 2025-12-16 00:34:40 +01:00
ZioPao
3f888e7f22 fix: bodyloc for b42 mp 2025-12-14 10:39:28 +01:00
Vinellon
d84554ff07 fix encoding for translate files 2025-11-17 19:37:38 +03:00
Pao
ec87d128e4 Merge pull request #217 from ZioPao/dev
v2.2.2
2025-11-15 21:38:24 +01:00
ZioPao
be4588fc43 chore: bump to mod version - 2.2.2 2025-10-12 17:45:09 +02:00
ZioPao
4bafb3a15c fix: went back to previous look for amputations 2025-10-12 17:16:52 +02:00
ZioPao
fd056aea1e fix: amputation items not hiding anymore 2025-10-09 22:32:41 +02:00
ZioPao
100abab2aa fix: workshop.txt 2025-10-05 16:17:55 +02:00
ZioPao
789b0635e0 fix: workshop.txt for b42 2025-10-05 16:08:56 +02:00
ZioPao
d6d9ba7028 Bump to mod version 2025-10-05 16:03:21 +02:00
ZioPao
a182fb07e5 chore: updates to workshop files for b42 2025-10-04 18:55:48 +02:00
ZioPao
528a43247a add: better wound textures 2025-10-04 16:38:50 +02:00
ZioPao
b281ce7d12 add: gen_amp_textures 2025-10-04 16:38:25 +02:00
ZioPao
9db3a1c944 fix: better masks for amputations 2025-10-04 15:40:10 +02:00
ZioPao
a74e33134d fix: switched to multiple body locs to fix some old issues and prepare for better visuals overhaul 2025-10-04 02:32:48 +02:00
ZioPao
1caf4a4b49 fix: fix for cheat prevention with both hands feasibility to false 2025-09-30 01:01:41 +02:00
ZioPao
5f71cebdc0 fix: override for both hands interaction for b42 and cheat prevention 2025-09-30 00:58:37 +02:00
ZioPao
4714bd7b82 fix: recipes 2025-09-30 00:53:15 +02:00
ZioPao
4d20cc2559 fix: baseline recipes for b42 2025-09-29 02:03:00 +02:00
ZioPao
5ec0ec1a9b fix: 42.12 new bodyloc 2025-09-29 01:31:18 +02:00
ZioPao
89a28e846a refactor: cleaning 2025-09-29 01:04:08 +02:00
ZioPao
a511ac777a refactor: reorganized settings for cd 2025-07-14 02:46:43 +02:00
ZioPao
04c7172d82 refactor: removed old code 2025-07-14 01:15:39 +02:00
ZioPao
522c49b40c chore: cleaning and setting up stuff 2025-04-17 18:23:18 +02:00
Pao
b5266cd7cd Merge pull request #200 from ZioPao/dev
v2.1.7
2025-04-17 16:18:41 +02:00
ZioPao
8c8aa8351b mod version 2025-04-17 15:53:49 +02:00
ZioPao
3eeb9d1000 fix: hotfix to IgnoredActions 2025-04-17 15:46:22 +02:00
ZioPao
c60a2c56ec fix: fixed (once and for all, hopefully) hotbar handling 2025-04-17 12:54:50 +02:00
ZioPao
69025c8262 fix: disabled ISDetachItemHotbar override, broken and unneccesary 2025-04-17 12:52:23 +02:00
ZioPao
80e9391db5 fix: fixed ignored actions that should ignore toc calculations 2025-04-17 12:42:35 +02:00
ZioPao
d7bdee1d26 fix: broken skipTOC check for timed actions 2025-04-17 12:18:27 +02:00
ZioPao
8234abd5e2 refactor: changed check for version 2025-04-17 11:26:58 +02:00
ZioPao
9011579f08 chore: changes to structure 2025-04-17 11:01:03 +02:00
ZioPao
be6466976c add: added known incompatibilies to mod.info for B42 2025-04-17 11:00:46 +02:00
ZioPao
9ab584d977 chore: fix to some stupid config issues 2025-04-17 03:38:02 +02:00
ZioPao
b0d3520173 fix: #174 2025-04-15 03:07:20 +02:00
ZioPao
bbd36f7dc2 chore: changes to vscode config and updated gitignore for symink 2025-04-15 03:02:38 +02:00
ZioPao
3fc37f56d6 refactor: cleaning dev stuff 2025-04-13 03:21:34 +02:00
ZioPao
d5fd735de8 refactor: cleaning code 2025-04-13 03:21:06 +02:00
ZioPao
253c5717a9 refactor: removed unused code 2025-04-13 03:16:06 +02:00
ZioPao
d850691053 Chore: changes to vscode config 2025-04-13 03:08:49 +02:00
ZioPao
f728520f9e Chore: fixed config for umbrella 2025-04-12 15:16:02 +02:00
ZioPao
67f51ca845 Change: unified perks into one single parent, added translations for perk tooltips (b42) 2025-04-03 00:37:18 +02:00
ZioPao
e07af54d27 Fix: moved UI files for b42 to correct location 2025-04-03 00:16:21 +02:00
ZioPao
6e47f945c5 Add: #180 2025-04-03 00:00:53 +02:00
ZioPao
644376cea0 Fix: #186 2025-04-02 23:57:17 +02:00
ZioPao
6a3fa76e00 Fix: added more checks in DataController to prevent issues, thanks PhysiksTV 2025-04-02 18:12:45 +02:00
ZioPao
6e674959ab UI: Fixed color for Health panel female covers (b41 only) 2025-04-02 02:04:44 +02:00
ZioPao
d52f3f6bf2 UI: Moved specific b42 health panel files to 42 folder, restored old files for b41 2025-04-02 01:59:58 +02:00
ZioPao
5acab111f2 git: Modified gitignore 2025-04-02 01:57:35 +02:00
ZioPao
61f505fa8e Dev: modified tasks and settings (vscode) 2025-04-02 01:36:37 +02:00
ZioPao
6abd89cea7 UI: Fixed male Health Panel 2025-04-02 01:32:30 +02:00
ZioPao
768a0dbdab UI: Better test pattern for Health Panel debugging 2025-04-02 01:16:51 +02:00
ZioPao
d96c26d099 UI: fixed health panel for Female chars 2025-04-02 00:42:58 +02:00
ZioPao
f93c0503f8 Fix unequip prosthesis for b42 2025-03-31 22:46:12 +02:00
ZioPao
671bf133e3 Fixes for overriden methods, compat with b41 2025-03-31 22:22:17 +02:00
ZioPao
1e754895a0 Re-added lua timers 2025-03-31 20:56:23 +02:00
ZioPao
9a11047e3c Fix to Traits 2025-03-31 19:57:38 +02:00
ZioPao
db6f315f89 Readded translations, finalized folder struct 2025-03-31 19:57:27 +02:00
ZioPao
729e3b62e7 Reverted common for B41 2025-03-31 06:45:44 +02:00
ZioPao
7c8cfb0fcc Added mod.info for b41 2025-03-31 06:43:19 +02:00
ZioPao
bb19da2b4b Removed icon and poster from versioned folder, added dynamically 2025-03-31 02:47:26 +02:00
ZioPao
471608f9ba minVersion=42.6 2025-03-31 02:40:13 +02:00
ZioPao
71b854efe2 Moved everything to common. 2025-03-31 02:36:15 +02:00
ZioPao
e919c8c01b Bump to mod version and changed folder for specific game version 2025-03-31 02:17:40 +02:00
ZioPao
b6b61b872f Bump to mod version 2025-03-31 02:15:49 +02:00
ZioPao
58d5c8e13d Moved TR translation to correct folder 2025-03-31 02:00:19 +02:00
ZioPao
cc5e67aceb Moved Translations to common folder, merged pgmbru changes manually 2025-03-31 01:59:27 +02:00
ZioPao
f77a357dab Updated to current unstable version and fixed Healthpanel again 2025-03-31 01:46:49 +02:00
Pao
499db8cd78 Merge pull request #193 from ZioPao/dev-b42
Dev b42
2025-03-31 00:40:24 +02:00
Pao
ffce5fac2e Merge pull request #182 from VVentos0/main
Turkish Translation Added
2025-02-26 01:51:43 +01:00
VVentos0
81842f7020 Turkish Translate Added
I made Turkish Translate for your mod. This Translate only for B41 because the encode is ANSI (Windows-1254)

If you going to update your mod to B42 .txt files should be UTF-08 I'll post B42 files too. Please don't forget to add B42 Translation after B42 Update <3
2025-01-11 10:17:03 +03:00
ZioPao
d846b853ff Fix for ISHealthPanel 2025-01-04 21:21:05 +01:00
ZioPao
0f4117cd34 moved common files 2025-01-04 21:07:34 +01:00
ZioPao
736d527a13 Fix instanceItem, oops 2025-01-04 21:00:39 +01:00
ZioPao
1ded7f976c Replaced InventoryItemFactory with instanceItem 2025-01-04 20:46:11 +01:00
ZioPao
6635cc19b2 moved folders 2025-01-04 20:44:12 +01:00
ZioPao
5d8e60a2e4 Updated tasks for b42 dev 2025-01-04 20:25:22 +01:00
Pao
5515b6bd4f Merge pull request #157 from ZioPao/dev
v2.1.5
2024-10-22 01:12:27 +02:00
ZioPao
ba267cb900 I should stop trying to fix stuff while I'm falling asleep 2024-10-22 01:09:41 +02:00
Pao
90ca2edbce Merge pull request #155 from ZioPao/dev
v2.1.5
2024-10-22 00:11:35 +02:00
ZioPao
00d5d83ea2 Bump to mod version 2024-10-22 00:10:49 +02:00
ZioPao
849c17051a Fixed broken checks for admin menu 2024-10-22 00:10:40 +02:00
Pao
0071d2ac3f Merge pull request #148 from ZioPao/dev
v2.1.4
2024-10-19 18:42:08 +02:00
ZioPao
68605ddb35 Bump to mod version 2024-10-19 18:37:02 +02:00
Pao
371134faa7 Merge pull request #144 from ZioPao/dev
v2.1.3
2024-10-17 23:52:07 +02:00
ZioPao
132ce24328 Added confirmation for amputations 2024-10-17 23:50:51 +02:00
ZioPao
4af127196c removed useless require 2024-10-17 23:22:08 +02:00
ZioPao
39bccaf895 Disabled other stuff 2024-10-12 19:51:21 +02:00
ZioPao
54c5958715 Disabled some non-functioning overrides 2024-10-12 19:17:46 +02:00
Pao
6b79ebf003 Merge pull request #139 from pllq/main
Ukrainian translation
2024-10-12 18:51:22 +02:00
ZioPao
75d5cb180d Fix to familiarity timing bug 2024-10-12 18:48:52 +02:00
pllq
245f81be26 updated Sandbox_UA.txt
added new translation for ukrainian langauge in Sandbox_UA.txt
2024-10-05 00:11:41 +03:00
pllq
1f950e0663 Delete media/lua/shared/Translate/UA/Sandbox_UA.txt
deleted old Sandbox_UA.txt
2024-10-05 00:11:05 +03:00
pllq
aecb5448ea translation for the UI file
added translation for the UI file
2024-10-05 00:09:44 +03:00
Pao
c02ac7dacc Merge pull request #123 from ZioPao/main
backmerge to dev since i'm an idiot part 2
2024-08-23 04:50:16 +02:00
ZioPao
332e02d9fd Fix to force reinit breaking actions in SP 2024-08-23 04:48:15 +02:00
ZioPao
a2b3db6793 Fix to unequip 2024-08-23 04:48:03 +02:00
Pao
6883c81322 Merge pull request #121 from ZioPao/dev
v2.1.3
2024-08-23 03:04:44 +02:00
ZioPao
600c55f5f8 Bump to mod version 2024-08-23 03:03:01 +02:00
ZioPao
bf20aec94f Fixed admin commands in sp 2024-08-23 02:53:04 +02:00
Pao
26c269e8ba Update README.md 2024-08-21 22:21:19 +02:00
ZioPao
db42feed35 Added exceptions for various equipping actions 2024-08-21 17:23:12 +02:00
ZioPao
10f97cffa1 Fixed picking up broken glass with item in off hand 2024-08-21 13:21:09 +02:00
ZioPao
22e6621300 Removed unused param 2024-08-21 12:36:04 +02:00
ZioPao
4d2b62e4a1 Error check for OnProsthesisEquipped 2024-08-21 01:55:59 +02:00
Pao
dd0d48cd08 Merge pull request #114 from ZioPao/dev
v2.1.2
2024-08-17 19:27:58 +02:00
ZioPao
2de512b447 Bump mod version 2024-08-17 19:26:41 +02:00
ZioPao
1765d82ad9 Implemented Forced Amputation and some additional safety checks 2024-08-17 19:15:58 +02:00
ZioPao
c52cca09f1 Merge branch 'dev' of https://github.com/ZioPao/The-Only-Cure into dev 2024-08-17 18:26:14 +02:00
ZioPao
545d5c7573 Implemented random limb side for Zombie Amputations 2024-08-17 18:26:13 +02:00
ZioPao
99d0847caa Updated workshop.txt 2024-08-17 16:51:37 +02:00
Pao
3b7fe2ec58 Merge pull request #113 from ZioPao/dev
v2.1.1
2024-08-17 16:48:59 +02:00
Pao
92fc80095d Merge pull request #109 from Pgmbru/Pgmbru-patch-FR
Pgmbru patch fr
2024-08-17 16:48:09 +02:00
ZioPao
751e36cba7 Fixed zombie amputations not enabling 2024-08-17 16:47:28 +02:00
Pgmbru
487e616801 Update Sandbox_FR.txt
Add Translate + Update Sandbox_FR
2024-08-12 03:04:07 +01:00
Pao
d5915cd287 Merge pull request #105 from ZioPao/dev
v2.1
2024-08-11 16:15:53 +02:00
ZioPao
d1f63ab55f Removed broken linter 2024-08-11 16:15:38 +02:00
ZioPao
857515576e Disabled zombies amputations by default 2024-08-11 16:14:05 +02:00
ZioPao
69c6177be5 Test linter 2024-08-11 13:32:28 +02:00
Pgmbru
38fa63324c Add Translate FR 2024-08-06 00:05:11 +01:00
ZioPao
940f5486aa Added toggle for Zombie amputations 2024-07-15 12:19:11 +02:00
ZioPao
11622795e1 Working zombies amputations once again 2024-07-15 12:15:35 +02:00
ZioPao
cb7603feea Bump to mod.info (2.1) 2024-07-15 10:59:40 +02:00
ZioPao
7b5e8e15d5 Added failsafe for iMeds compat 2024-07-15 10:59:15 +02:00
ZioPao
9a74710c1e Added preliminary compatibility with iMeds 2024-07-15 10:54:34 +02:00
ZioPao
3f7bf56be2 Added translation credits 2024-07-13 19:33:07 +02:00
Pao
501c2fbabd Merge pull request #93 from ZioPao/dev
v2.0.15
2024-07-13 19:30:30 +02:00
ZioPao
3dad820014 Fixed cicatrization force-applying with traits 2024-07-13 19:27:55 +02:00
ZioPao
2f82021b5d Fixed bandage\stitches action after amputation applying to wrong body part 2024-07-13 19:13:18 +02:00
ZioPao
a3287bb2bc Fixed suture needle causing an error 2024-07-13 19:07:17 +02:00
ZioPao
6c82f1a96f Add logs for traits 2024-07-13 18:57:16 +02:00
ZioPao
f2446c0781 Added script to automatically bump version 2024-07-13 18:57:10 +02:00
ZioPao
4d6ee68054 bump to mod.info 2024-07-13 17:27:48 +02:00
ZioPao
854238ef98 Merge branch 'dev' of https://github.com/ZioPao/The-Only-Cure into dev 2024-07-13 17:26:06 +02:00
ZioPao
2b41745a05 Added Korean translation 2024-07-13 17:26:04 +02:00
Pao
c2e15151a6 Merge pull request #84 from pllq/main
Added Ukrainian localization
2024-06-09 23:28:33 +02:00
pllq
b25f52a40d Add files via upload
Ukrainian localization for the TOC mod
2024-06-09 23:54:59 +03:00
Pao
145ec33620 Merge pull request #80 from ZioPao/dev
v2.0.14
2024-06-04 09:53:14 +02:00
ZioPao
307e19fd52 Fixed bug with saws 2024-06-04 09:48:17 +02:00
Pao
9eb9ea0263 Merge pull request #79 from ZioPao/dev
v2.0.13
2024-06-03 21:59:48 +02:00
ZioPao
f8fc8e7f60 Merge branch 'dev' of https://github.com/ZioPao/The-Only-Cure into dev 2024-06-03 21:59:15 +02:00
ZioPao
3d1cfba85c bump to mod.info 2024-06-03 21:59:13 +02:00
Pao
1f6fc63f46 Merge pull request #78 from Rinary1/main
RU Translate For This Mod
2024-06-03 21:57:45 +02:00
Rinary
3931c0ed4d Add files via upload 2024-06-03 20:29:43 +03:00
Pao
74eb7763cf Merge pull request #75 from ZioPao/dev
v2.0.12
2024-05-31 10:53:56 +02:00
ZioPao
e0e65c022f bump to mod.info 2024-05-31 10:52:24 +02:00
ZioPao
574526aca0 Fix: traits handling 2024-05-31 10:50:51 +02:00
ZioPao
29f21decb4 hotfix to traits 2024-05-31 10:37:39 +02:00
ZioPao
b70dd619a4 Disabled insensitive trait for now 2024-05-28 10:01:03 +02:00
Pao
0d5814dad1 Merge pull request #72 from ZioPao/dev
v2.0.11
2024-05-15 13:14:52 +02:00
ZioPao
5f64ead354 Fixed disabling of Interact Key 2024-05-15 13:13:27 +02:00
ZioPao
80c8b22faa lock for HandleDamage not disengaging in some cases 2024-05-15 11:52:45 +02:00
ZioPao
696edc1f1d Fixed wrong skin color for amputations 2024-05-15 11:47:28 +02:00
ZioPao
a1336c8d2e Destroying the instance will break stuff 2024-05-15 11:38:08 +02:00
Pao
1187f1a1b6 Merge pull request #60 from ZioPao/dev
disabled useless log
2024-05-09 14:52:00 +02:00
ZioPao
dc921e4c04 disabled useless log 2024-05-09 14:50:48 +02:00
Pao
bff6a2d4d6 Merge pull request #59 from ZioPao/dev
v2.0.10
2024-05-09 14:47:52 +02:00
ZioPao
36c3418a3e bump to mod version 2024-05-09 14:47:28 +02:00
ZioPao
a7e32bc69b Fix to HandleDamage breaking when getIsIgnoredPartInfected==true 2024-05-09 14:46:31 +02:00
Pao
139ad5828a Merge pull request #55 from ZioPao/dev
v2.0.9
2024-05-07 17:14:53 +02:00
ZioPao
1636ca7e13 bump to mod version 2024-05-07 17:13:56 +02:00
ZioPao
46a8ddc207 Added some tests 2024-05-07 17:13:27 +02:00
ZioPao
26e0324f4a Fixed bug related to BodyLocations that would break equipping prosthesis 2024-05-07 17:04:32 +02:00
ZioPao
c1faeeaabf Potential fix to bleeding issue 2024-05-07 16:58:55 +02:00
Pao
a93c8a56bb Merge pull request #51 from ZioPao/dev
v2.0.8
2024-05-06 22:07:00 +02:00
ZioPao
b33cee7271 hotfix 2024-05-06 22:06:26 +02:00
Pao
6e68e12b60 Merge pull request #49 from ZioPao/dev
v2.0.7
2024-05-06 17:15:27 +02:00
Pao
99dbaea143 Update issue templates 2024-05-06 10:15:31 +02:00
Pao
a09a1520a1 Update issue templates 2024-05-06 01:28:35 +02:00
Pao
6458988cc8 Merge pull request #45 from ZioPao/dev
v2.0.6
2024-05-05 18:05:06 +02:00
Pao
ba4f161122 Merge pull request #44 from ZioPao/dev
v2.0.5
2024-05-05 17:02:45 +02:00
Pao
df8591b1ef Merge pull request #42 from ZioPao/dev
Added ProstFamiliarity in adjustMaxTime function
2024-05-05 13:57:31 +02:00
Pao
91a6eb7763 Merge pull request #41 from ZioPao/dev
v2.0.4
2024-05-05 13:52:02 +02:00
Pao
1a754f4012 Merge pull request #38 from ZioPao/dev
bump to modversion
2024-05-05 01:01:35 +02:00
Pao
74bb34bbc8 Merge pull request #37 from ZioPao/dev
v2.0.3
2024-05-05 00:50:22 +02:00
364 changed files with 2541 additions and 2266 deletions

24
.github/ISSUE_TEMPLATE/bug_report.md vendored Normal file
View File

@@ -0,0 +1,24 @@
---
name: Bug report
about: Create a report to help us improve
title: ''
labels: ''
assignees: ZioPao
---
**Describe the bug**
A clear and concise description of what the bug is.
**To Reproduce**
Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**Logs**
Please upload your game logs too. Server logs are useful too.
**Additional context**
Add any other context about the problem here.

3
.gitignore vendored
View File

@@ -1 +1,2 @@
.vscode
dev_stuff/gen_amp_textures/.venv
dev_stuff/gen_amp_textures/output

32
.vscode/settings.json vendored
View File

@@ -1,11 +1,27 @@
{
"todo-tree.tree.scanMode": "workspace",
"zomboid_user_folder": "C:/Users/picch/Zomboid",
"zomboid_folder": "E:\\Steam\\steamapps\\common\\ProjectZomboid",
"zomboid_server_folder": "E:\\Steam\\steamapps\\common\\Project Zomboid Dedicated Server",
"Lua.diagnostics.globals": [
"ModOptions",
"zombie",
"_"
"Lua.workspace.library": [
"${addons}/umbrella-unstable/module/library"
],
"Lua.runtime.version": "Lua 5.1",
"Lua.runtime.path": [
"?.lua",
"?/init.lua",
"server/?.lua"
],
"Lua.completion.requireSeparator": "/",
"Lua.runtime.builtin": {
"debug": "disable",
"io": "disable",
"package": "disable"
},
"Lua.workspace.checkThirdParty": false,
"Lua.workspace.ignoreDir": [
".vscode",
"dev_stuff",
"workshop_files"
],
"Lua.diagnostics.globals": [
"FHSwapHandsAction",
"timer"
]
}

111
.vscode/tasks.json vendored
View File

@@ -6,42 +6,82 @@
{
"label": "Create Workshop folder",
"type": "shell",
"options": {"statusbar": {"label": "$(combine) Assemble Mod"}},
"command": "python ${config:zomboid_user_folder}/PaosCrap/make_workshop_pack.py picch ${workspaceFolderBasename}",
"options": {"statusbar": {"label": "$(combine) Assemble Mod - B42"}},
"command": "python ${config:zomboid_user_folder}/PaosCrap/make_workshop_pack.py \"42\" \"picch\" \"${workspaceFolderBasename}\" \"\"",
},
{
"label": "Create Workshop folder",
"type": "shell",
"options": {"statusbar": {"label": "$(combine) Assemble Mod (Test)"}},
"command": "python ${config:zomboid_user_folder}/PaosCrap/make_workshop_pack.py \"picch\" \"${workspaceFolderBasename}\" \"test\"",
},
{
"label": "Run Zomboid Debug No Steam",
"label": "Bump Mod Version",
"type": "shell",
"options": {"statusbar": {"label": "$(arrow-up) Bump Mod Version"}},
"command": "python ${config:zomboid_user_folder}/PaosCrap/bump_version.py common/media/lua/client/TOC/Main.lua",
},
{
"label": "Run Zomboid Debug No Steam (42)",
"type": "shell",
"presentation": {
"group": "groupZomboid"
},
"command": "\"${config:zomboid_folder}\\ProjectZomboid64 - nosteam-debug.bat\"",
"options": {"statusbar": {"label": "$(run) Zomboid client"}},
"command": "\"${config:zomboid_folder_b42}\\ProjectZomboid64_Debug_NoSteam.bat\"",
"options": {"statusbar": {"label": "$(run) Zomboid client (42)"}},
"problemMatcher": [
"$eslint-stylish"
]
},
{
"label": "Run Zomboid Debug No Steam 2",
"type": "shell",
"command": "\"${config:zomboid_folder}\\ProjectZomboid64 - nosteam-debug.bat\"",
"options": {"statusbar": {"hide": true}},
},
{
"label": "Run Zomboid Debug No Steam (42) - 2nd Instance",
"type": "shell",
"presentation": {
"group": "groupZomboid"
},
"command": "\"${config:zomboid_folder_b42}\\ProjectZomboid64_Debug_NoSteam.bat\"",
"options": {"statusbar": {"label": "$(run) Zomboid client (42) - 2nd Instance"}},
"problemMatcher": [
"$eslint-stylish"
]
},
{
"label": "Run two instances of Zomboid Debug No Steam",
"options": {"statusbar": {"label": "$(run-all) Two Zomboid Clients"}},
"presentation": {
"reveal": "always",
"panel": "new"
},
"dependsOn": [
"Run Zomboid Debug No Steam", "Run Zomboid Debug No Steam 2"],
"problemMatcher": []
},
// {
// "label": "Run Zomboid Debug No Steam",
// "type": "shell",
// "presentation": {
// "group": "groupZomboid"
// },
// "command": "\"${config:zomboid_folder}\\ProjectZomboid64 - nosteam-debug.bat\"",
// "options": {"statusbar": {"label": "$(run) Zomboid client"}},
// "problemMatcher": [
// "$eslint-stylish"
// ]
// },
// {
// "label": "Run Zomboid Debug No Steam 2",
// "type": "shell",
// "command": "\"${config:zomboid_folder}\\ProjectZomboid64 - nosteam-debug.bat\"",
// "options": {"statusbar": {"hide": true}},
// "problemMatcher": [
// "$eslint-stylish"
// ]
// },
// {
// "label": "Run two instances of Zomboid Debug No Steam",
// "options": {"statusbar": {"label": "$(run-all) Two Zomboid Clients"}},
// "presentation": {
// "reveal": "always",
// "panel": "new"
// },
// "dependsOn": [
// "Run Zomboid Debug No Steam", "Run Zomboid Debug No Steam 2"],
// "problemMatcher": []
// },
{
"label": "Run Zomboid Test Server",
"options": {"statusbar": {"label": "$(run) Zomboid Server (TOC)"}},
@@ -51,14 +91,23 @@
"$eslint-stylish"
]
},
{
"label": "Run Zomboid Test Server 2",
"options": {"statusbar": {"label": "$(run) Zomboid Server (TOC+FH+BH)"}},
"type": "shell",
"command":"\"${config:zomboid_server_folder}\\StartServer64_nosteam_custom.bat\" TOC_FH_BH",
"problemMatcher": [
"$eslint-stylish"
]
}
// {
// "label": "Run Zomboid Test Server 2",
// "options": {"statusbar": {"label": "$(run) Zomboid Server (TOC+FH+BH)"}},
// "type": "shell",
// "command":"\"${config:zomboid_server_folder}\\StartServer64_nosteam_custom.bat\" TOC_FH_BH",
// "problemMatcher": [
// "$eslint-stylish"
// ]
// },
// {
// "label": "Run Zomboid Test Server 3",
// "options": {"statusbar": {"label": "$(run) Zomboid Server (TOC+FH+BH+iMedsFixed)"}},
// "type": "shell",
// "command":"\"${config:zomboid_server_folder}\\StartServer64_nosteam_custom.bat\" TOC_FH_BH_imeds",
// "problemMatcher": [
// "$eslint-stylish"
// ]
// }
]
}

View File

@@ -7,9 +7,10 @@
<m_AllowRandomHue>false</m_AllowRandomHue>
<m_AllowRandomTint>false</m_AllowRandomTint>
<m_Masks>3</m_Masks>
<m_Masks>4</m_Masks>
<m_Masks>3</m_Masks>
<!-- <m_UnderlayMasksFolder>media/textures/Amputations/Masks</m_UnderlayMasksFolder> -->
<!-- HUMAN -->

View File

@@ -10,6 +10,8 @@
<m_Masks>5</m_Masks>
<m_Masks>6</m_Masks>
<!-- <m_UnderlayMasksFolder>media/textures/Amputations/Masks</m_UnderlayMasksFolder> -->
<!-- HUMAN -->
<textureChoices>Amputations\Human\Forearm\skin01_b</textureChoices>
<textureChoices>Amputations\Human\Forearm\skin02_b</textureChoices>

View File

@@ -0,0 +1,39 @@
<?xml version="1.0" encoding="utf-8"?>
<clothingItem>
<m_MaleModel>Amputation\Amputation_Left_Hand_Male</m_MaleModel>
<m_FemaleModel>Amputation\Amputation_Left_Hand_Female</m_FemaleModel>
<m_GUID>2de93af2-b7a8-4c04-84d1-28d92cce8a0f</m_GUID>
<m_Static>false</m_Static>
<m_AllowRandomHue>false</m_AllowRandomHue>
<m_AllowRandomTint>false</m_AllowRandomTint>
<m_Masks>4</m_Masks>
<!-- <m_MasksFolder>none</m_MasksFolder> -->
<!-- HUMAN -->
<textureChoices>Amputations\Human\Hand\skin01_b</textureChoices>
<textureChoices>Amputations\Human\Hand\skin02_b</textureChoices>
<textureChoices>Amputations\Human\Hand\skin03_b</textureChoices>
<textureChoices>Amputations\Human\Hand\skin04_b</textureChoices>
<textureChoices>Amputations\Human\Hand\skin05_b</textureChoices>
<textureChoices>Amputations\Human\Hand\skin01_hairy_b</textureChoices>
<textureChoices>Amputations\Human\Hand\skin02_hairy_b</textureChoices>
<textureChoices>Amputations\Human\Hand\skin03_hairy_b</textureChoices>
<textureChoices>Amputations\Human\Hand\skin04_hairy_b</textureChoices>
<textureChoices>Amputations\Human\Hand\skin05_hairy_b</textureChoices>
<!-- HUMAN AFTER CICATRIZATION -->
<textureChoices>Body\MaleBody01</textureChoices>
<textureChoices>Body\MaleBody02</textureChoices>
<textureChoices>Body\MaleBody03</textureChoices>
<textureChoices>Body\MaleBody04</textureChoices>
<textureChoices>Body\MaleBody05</textureChoices>
<textureChoices>Body\MaleBody01a</textureChoices>
<textureChoices>Body\MaleBody02a</textureChoices>
<textureChoices>Body\MaleBody03a</textureChoices>
<textureChoices>Body\MaleBody04</textureChoices>
<textureChoices>Body\MaleBody05a</textureChoices>
</clothingItem>

View File

@@ -0,0 +1,37 @@
<clothingItem>
<m_MaleModel>Amputation\Amputation_Right_Hand_Male</m_MaleModel>
<m_FemaleModel>Amputation\Amputation_Right_Hand_Female</m_FemaleModel>
<m_GUID>f114e53a-b92e-4639-8d8c-2b43ab981885</m_GUID>
<m_Static>false</m_Static>
<m_AllowRandomHue>false</m_AllowRandomHue>
<m_AllowRandomTint>false</m_AllowRandomTint>
<m_Masks>6</m_Masks>
<!-- <m_MasksFolder>none</m_MasksFolder> -->
<!-- HUMAN -->
<textureChoices>Amputations\Human\Hand\skin01_b</textureChoices>
<textureChoices>Amputations\Human\Hand\skin02_b</textureChoices>
<textureChoices>Amputations\Human\Hand\skin03_b</textureChoices>
<textureChoices>Amputations\Human\Hand\skin04_b</textureChoices>
<textureChoices>Amputations\Human\Hand\skin05_b</textureChoices>
<textureChoices>Amputations\Human\Hand\skin01_hairy_b</textureChoices>
<textureChoices>Amputations\Human\Hand\skin02_hairy_b</textureChoices>
<textureChoices>Amputations\Human\Hand\skin03_hairy_b</textureChoices>
<textureChoices>Amputations\Human\Hand\skin04_hairy_b</textureChoices>
<textureChoices>Amputations\Human\Hand\skin05_hairy_b</textureChoices>
<!-- HUMAN AFTER CICATRIZATION -->
<textureChoices>Body\MaleBody01</textureChoices>
<textureChoices>Body\MaleBody02</textureChoices>
<textureChoices>Body\MaleBody03</textureChoices>
<textureChoices>Body\MaleBody04</textureChoices>
<textureChoices>Body\MaleBody05</textureChoices>
<textureChoices>Body\MaleBody01a</textureChoices>
<textureChoices>Body\MaleBody02a</textureChoices>
<textureChoices>Body\MaleBody03a</textureChoices>
<textureChoices>Body\MaleBody04</textureChoices>
<textureChoices>Body\MaleBody05a</textureChoices>
</clothingItem>

View File

@@ -9,6 +9,8 @@
<m_Masks>3</m_Masks>
<m_Masks>4</m_Masks>
<!-- <m_UnderlayMasksFolder>media/textures/Amputations/Masks</m_UnderlayMasksFolder> -->
<!-- HUMAN -->
<textureChoices>Amputations\Human\Upperarm\skin01_b</textureChoices>
<textureChoices>Amputations\Human\Upperarm\skin02_b</textureChoices>

View File

@@ -8,6 +8,7 @@
<m_AllowRandomTint>false</m_AllowRandomTint>
<m_Masks>5</m_Masks>
<m_Masks>6</m_Masks>
<!-- <m_UnderlayMasksFolder>media/textures/Amputations/Masks</m_UnderlayMasksFolder> -->
<!-- HUMAN -->
<textureChoices>Amputations\Human\Upperarm\skin01_b</textureChoices>

View File

@@ -1,4 +1,5 @@
local CommandsData = require("TOC/CommandsData")
local ClientRelayCommands = require("TOC/ClientRelayCommands")
local StaticData = require("TOC/StaticData")
local DataController = require("TOC/Controllers/DataController")
-------------------
@@ -7,7 +8,7 @@ local DataController = require("TOC/Controllers/DataController")
---@param context ISContextMenu
---@param worldobjects table
local function AddAdminTocOptions(playerNum, context, worldobjects)
if not isAdmin() then return end
if not(isClient() and isAdmin() or isDebugEnabled()) then return end
local players = {}
for _, v in ipairs(worldobjects) do
@@ -30,6 +31,7 @@ local function AddAdminTocOptions(playerNum, context, worldobjects)
end
-- ugly This whole section should be done better
for _, pl in pairs(players) do
---@cast pl IsoPlayer
@@ -40,10 +42,36 @@ local function AddAdminTocOptions(playerNum, context, worldobjects)
context:addSubMenu(option, subMenu)
subMenu:addOption(getText("ContextMenu_Admin_ResetTOC"), nil, function()
if isClient() then
sendClientCommand(CommandsData.modules.TOC_RELAY, CommandsData.server.Relay.RelayExecuteInitialization,
{ patientNum = clickedPlayerNum })
else
ClientRelayCommands.ReceiveExecuteInitialization()
end
end)
-- Force amputation
local forceAmpOption = subMenu:addOption(getText("ContextMenu_Admin_ForceAmputation"), nil, nil)
local forceAmpSubMenu = ISContextMenu:getNew(subMenu)
context:addSubMenu(forceAmpOption, forceAmpSubMenu)
for i = 1, #StaticData.LIMBS_STR do
local limbName = StaticData.LIMBS_STR[i]
local limbTranslatedName = getText("ContextMenu_Limb_" .. limbName)
forceAmpSubMenu:addOption(limbTranslatedName, nil, function()
if isClient() then
sendClientCommand(CommandsData.modules.TOC_RELAY, CommandsData.server.Relay.RelayForcedAmputation,
{ patientNum = clickedPlayerNum, limbName = limbName })
else
ClientRelayCommands.ReceiveExecuteAmputationAction({surgeonNum=clickedPlayerNum, limbName=limbName, damagePlayer=false})
end
end)
end
end
end
Events.OnFillWorldObjectContextMenu.Add(AddAdminTocOptions)

View File

@@ -1,5 +1,6 @@
local CommandsData = require("TOC/CommandsData")
local AmputationHandler = require("TOC/Handlers/AmputationHandler")
local DataController = require("TOC/Controllers/DataController")
--------------------------------------------
local ClientRelayCommands = {}
@@ -11,7 +12,7 @@ local ClientRelayCommands = {}
local function InitAmputationHandler(limbName, surgeonNum)
-- TODO Pretty unclean
local surgeonPl = getSpecificPlayer(surgeonNum)
local surgeonPl = getSpecificPlayer(surgeonNum) -- fix broken, getOnlineID not working anymore
local handler = AmputationHandler:new(limbName, surgeonPl)
return handler
end
@@ -25,8 +26,14 @@ end
---Creates a new handler and execute the amputation function on this client
---@param args receiveExecuteAmputationActionParams
function ClientRelayCommands.ReceiveExecuteAmputationAction(args)
-- Check if player already doesn't have that limb or it's a dependant limb.
-- Mostly a check for admin forced amputations more than anything else, since this case is handled in the GUI already.
local dcInst = DataController.GetInstance()
if dcInst:getIsCut(args.limbName) then return end
local handler = InitAmputationHandler(args.limbName, args.surgeonNum)
handler:execute(true)
handler:execute(args.damagePlayer)
end
@@ -39,6 +46,14 @@ function ClientRelayCommands.ReceiveApplyFromServer()
end
--* WEAR AMPUTATION ITEM *--
function ClientRelayCommands.ReceiveWearAmputation(args)
local itemName = args.itemName
local clothingItem = getPlayer():getInventory():FindAndReturn(itemName)
getPlayer():setWornItem(clothingItem:getBodyLocation(), clothingItem)
end
--* TRIGGERED BY ADMINS *--
function ClientRelayCommands.ReceiveExecuteInitialization()
@@ -46,6 +61,15 @@ function ClientRelayCommands.ReceiveExecuteInitialization()
LocalPlayerController.InitializePlayer(true)
end
---Creates a new handler and execute the amputation function on this client
---@param args receiveForcedCicatrizationParams
function ClientRelayCommands.ReceiveForcedCicatrization(args)
local dcInst = DataController.GetInstance()
--dcInst:setCicatrizationTime(args.limbName, 1)
dcInst:setIsCicatrized(args.limbName, true)
dcInst:apply()
end
-------------------------
local function OnServerRelayCommand(module, command, args)
@@ -56,3 +80,6 @@ local function OnServerRelayCommand(module, command, args)
end
Events.OnServerCommand.Add(OnServerRelayCommand)
-- TODO temporary
return ClientRelayCommands

View File

@@ -26,7 +26,7 @@ end
---Returns full name for the side, to be used with BodyLocations
---@param side string
---@return string
---@return string?
function CommonMethods.GetSideFull(side)
if side == 'R' then
return "Right"

View File

@@ -0,0 +1,79 @@
---@class Compat
---@field handlers table<string, {fun : function, isActive : boolean}>
local Compat = {
handlers = {}
}
--- Brutal hands has a TOC_COMPAT but its check is wrong and uses an old API.
function Compat.BrutalHandwork()
BrutalHands = BrutalHands or {}
BrutalHands.TOC = require("TOC/API")
end
--- Was handled inside old TOC
function Compat.FancyHandwork()
require("TimedActions/FHSwapHandsAction")
local og_FHSwapHandsAction_isValid = FHSwapHandsAction.isValid
function FHSwapHandsAction:isValid()
local tocApi = require("TOC/API")
if tocApi.hasBothHands(self.character) then
return og_FHSwapHandsAction_isValid(self)
else
return false
end
end
end
function Compat.iMeds()
require("Component/Interface/Service/ContextMenu/Menu/HealthPanel/HealthPanelMenuInitializer")
-- placeholder, in case we need to do something more drastic with it.
end
------------------------------
Compat.handlers = {
["BrutalHandwork"] = {
fun = Compat.BrutalHandwork,
isActive = false},
["FancyHandwork"] = {
fun = Compat.FancyHandwork,
isActive = false},
-- either or
['iMeds'] = {
fun = Compat.iMeds,
isActive = false},
['iMedsFixed'] = {
fun = Compat.iMeds,
isActive = false}
-- TODO Check if FirstAidOverhaul can be made compatible
}
function Compat.RunModCompatibility()
local activatedMods = getActivatedMods()
TOC_DEBUG.print("Checking for mods compatibility")
for k, modCompatHandler in pairs(Compat.handlers) do
if activatedMods:contains(k) then
TOC_DEBUG.print("Found " .. k .. ", running compatibility handler")
modCompatHandler.fun()
modCompatHandler.isActive = true
end
end
end
Events.OnGameStart.Add(Compat.RunModCompatibility)
return Compat

View File

@@ -5,7 +5,7 @@ local StaticData = require("TOC/StaticData")
----------------
--- An instance will be abbreviated with dcInst
-- https://github.com/ZioPao/The-Only-Cure/issues/187
--- Handle all TOC mod data related stuff
---@class DataController
@@ -57,7 +57,6 @@ function DataController:setup(key)
---@type tocModDataType
self.tocData = {
-- Generic stuff that does not belong anywhere else
isInitializing = true,
isIgnoredPartInfected = false,
isAnyLimbCut = false,
limbs = {},
@@ -93,15 +92,16 @@ function DataController:setup(key)
-- Sync with the server
self:apply()
-- -- Disable lock
-- self.tocData.isInitializing = false
-- ModData.add(key, self.tocData)
triggerEvent("OnSetupTocData")
end
---In case of desync between the table on ModData and the table here
---@param tocData tocModDataType
function DataController:applyOnlineData(tocData)
if not tocData or not tocData.limbs then
TOC_DEBUG.print("Received invalid tocData")
return
end
local key = CommandsData.GetKey(self.username)
ModData.add(key, tocData)
self.tocData = ModData.get(key)
@@ -228,12 +228,8 @@ end
---@param limbName string
---@return boolean
function DataController:getIsCut(limbName)
if not self.isDataReady then return false end
if self.tocData.limbs[limbName] then
return self.tocData.limbs[limbName].isCut
else
return false
end
if not self.isDataReady or not self.tocData or not self.tocData.limbs then return false end
return self.tocData.limbs[limbName] and self.tocData.limbs[limbName].isCut or false
end
---Get isVisible
@@ -338,14 +334,11 @@ end
---@param cicatrizationTime integer?
function DataController:setLimbParams(limbName, ampStatus, cicatrizationTime)
local limbData = self.tocData.limbs[limbName]
if ampStatus.isCut ~= nil then limbData.isCut = ampStatus.isCut end
if ampStatus.isInfected ~= nil then limbData.isInfected = ampStatus.isInfected end
if ampStatus.isOperated ~= nil then limbData.isOperated = ampStatus.isOperated end
if ampStatus.isCicatrized ~= nil then limbData.isCicatrized = ampStatus.isCicatrized end
if ampStatus.isCauterized ~= nil then limbData.isCauterized = ampStatus.isCauterized end
if ampStatus.woundDirtyness ~= nil then limbData.woundDirtyness = ampStatus.woundDirtyness end
if ampStatus.isVisible ~= nil then limbData.isVisible = ampStatus.isVisible end
for k, v in pairs(ampStatus) do
if v ~= nil then
limbData[k] = v
end
end
if cicatrizationTime ~= nil then limbData.cicatrizationTime = cicatrizationTime end
end
@@ -381,9 +374,9 @@ function DataController.ReceiveData(key, data)
TOC_DEBUG.print("ReceiveData for " .. key)
if data == nil or data.limbs == nil then
TOC_DEBUG.print("Data is nil, new character or something is wrong")
end
-- if data == nil or data.limbs == nil then
-- TOC_DEBUG.print("Data is nil, new character or something is wrong")
-- end
-- Get DataController instance if there was none for that user and reapply the correct ModData table as a reference
local username = key:sub(5)
@@ -402,12 +395,9 @@ function DataController.ReceiveData(key, data)
handler:setup(key)
elseif data and data.limbs then
-- Let's validate that the data structure is actually valid to prevent issues
if data.isUpdateFromServer then
TOC_DEBUG.print("Update from the server")
end
handler:applyOnlineData(data)
elseif username == getPlayer():getUsername() then
TOC_DEBUG.print("loading local data")
TOC_DEBUG.print("Trying to load local data or no data is available")
handler:tryLoadLocalData(key)
end
@@ -415,8 +405,11 @@ function DataController.ReceiveData(key, data)
handler:setIsResetForced(false)
handler:setIsDataReady(true)
--TOC_DEBUG.print("Finished ReceiveData, triggering OnReceivedTocData")
triggerEvent("OnReceivedTocData", handler.username)
-- TODO We need an event to track if initialization has been finalized
-- if username == getPlayer():getUsername() and not handler.isResetForced then

View File

@@ -5,14 +5,51 @@ local CachedDataHandler = require("TOC/Handlers/CachedDataHandler")
local CommonMethods = require("TOC/CommonMethods")
local StaticData = require("TOC/StaticData")
local OverridenMethodsArchive = require("TOC/OverridenMethodsArchive")
-----------------
---@class LimitActionsController
local LimitActionsController = {}
--* TIMED ACTIONS *--
-- We want to be able to modify how long actions are gonna take,
-- depending on amputation status and kind of action. Also, when the
-- player has not completely cicatrized their own wounds, and try to do any action with
-- a prosthesis on, that can trigger random bleeds.
--* DISABLE WEARING CERTAIN ITEMS WHEN NO LIMB
function LimitActionsController.CheckLimbFeasibility(limbName)
local dcInst = DataController.GetInstance()
local isFeasible = not dcInst:getIsCut(limbName) or dcInst:getIsProstEquipped(limbName)
--TOC_DEBUG.print("isFeasible="..tostring(isFeasible))
return isFeasible
end
---@param obj any
---@param wrappedFunc function
---@param item InventoryItem
---@return boolean
function LimitActionsController.WrapClothingAction(obj, wrappedFunc, item)
local isEquippable = wrappedFunc(obj)
if not isEquippable then return isEquippable end
local itemBodyLoc = item:getBodyLocation()
local limbToCheck = StaticData.AFFECTED_BODYLOCS_TO_LIMBS_IND_STR[itemBodyLoc]
if LimitActionsController.CheckLimbFeasibility(limbToCheck) then return isEquippable else return false end
end
-- We need to override when the player changes key binds manually to be sure that TOC changes are re-applied
local og_MainOptions_apply = MainOptions.apply
function MainOptions:apply(closeAfter)
og_MainOptions_apply(self, closeAfter)
CachedDataHandler.OverrideBothHandsFeasibility()
end
--------------------------------------------
--* TIMED ACTIONS
--* We want to be able to modify how long actions are gonna take,
--* depending on amputation status and kind of action. Also, when the
--* player has not completely cicatrized their own wounds, and try to do any action with
--* a prosthesis on, that can trigger random bleeds.
local function CheckHandFeasibility(limbName)
TOC_DEBUG.print("Checking hand feasibility: " .. limbName)
@@ -24,20 +61,25 @@ local function CheckHandFeasibility(limbName)
end
--* Time to perform actions overrides *--
--* Time to perform actions overrides
local og_ISBaseTimedAction_adjustMaxTime = ISBaseTimedAction.adjustMaxTime
--- Adjust time
---@diagnostic disable-next-line: duplicate-set-field
function ISBaseTimedAction:adjustMaxTime(maxTime)
local time = og_ISBaseTimedAction_adjustMaxTime(self, maxTime)
--TOC_DEBUG.print("Running override for adjustMaxTime")
-- Exceptions handling, if we find that parameter then we just use the original time
local queue = ISTimedActionQueue.getTimedActionQueue(getPlayer())
if queue and queue.current and queue.current.skipTOC then return time end
local actionsQueue = ISTimedActionQueue.getTimedActionQueue(getPlayer())
if actionsQueue and actionsQueue.current and actionsQueue.current.skipTOC then
TOC_DEBUG.print("Should skip TOC stuff")
return time
end
-- Action is valid, check if we have any cut limb and then modify maxTime
local dcInst = DataController.GetInstance()
if time ~= -1 and dcInst and dcInst:getIsAnyLimbCut() then
--TOC_DEBUG.print("Overriding adjustMaxTime")
local pl = getPlayer()
local amputatedLimbs = CachedDataHandler.GetAmputatedLimbs(pl:getUsername())
@@ -54,45 +96,78 @@ function ISBaseTimedAction:adjustMaxTime(maxTime)
local perkLevelScaled
if perkLevel ~= 0 then perkLevelScaled = perkLevel / 10 else perkLevelScaled = 0 end
time = time * (StaticData.LIMBS_TIME_MULTIPLIER_IND_NUM[limbName] - perkLevelScaled)
TOC_DEBUG.print("Perk Level: " .. tostring(perkLevel))
TOC_DEBUG.print("OG time: " .. tostring(time))
-- Modified Time shouldn't EVER be lower compared to the og one.
local modifiedTime = time * (StaticData.LIMBS_TIME_MULTIPLIER_IND_NUM[limbName] - perkLevelScaled)
if modifiedTime >= time then
time = modifiedTime
end
--TOC_DEBUG.print("Modified time: " .. tostring(time))
end
end
--TOC_DEBUG.print("New time with amputations: " .. tostring(time))
return time
end
--* Random bleeding during cicatrization + Perks leveling override *--
--* Random bleeding during cicatrization + Perks leveling override
local og_ISBaseTimedAction_perform = ISBaseTimedAction.perform
--- After each action, level up perks
---@diagnostic disable-next-line: duplicate-set-field
function ISBaseTimedAction:perform()
og_ISBaseTimedAction_perform(self)
TOC_DEBUG.print("Running ISBaseTimedAction.perform override")
TOC_DEBUG.print("max time: " .. tostring(self.maxTime))
--TOC_DEBUG.print("Running ISBaseTimedAction.perform override")
--TOC_DEBUG.print("max time: " .. tostring(self.maxTime))
local dcInst = DataController.GetInstance()
if not dcInst:getIsAnyLimbCut() then return end
if not dcInst:getIsAnyLimbCut() or self.noExp then return end
--* LEVELING
-- First check level of perks. if already at max, skip
local amputatedLimbs = CachedDataHandler.GetAmputatedLimbs(LocalPlayerController.username)
local xp = self.maxTime/100
local xp = self.maxTime / 100
-- TODO Exp should be added while doing the action, not after it's done
-- Prevent xp from being negative and decreasing perks
if xp < 0 then xp = 0 end
for k, _ in pairs(amputatedLimbs) do
local limbName = k
-- We're checking for only "visible" amputations to prevent from having bleeds everywhere
if dcInst:getIsCut(limbName) and dcInst:getIsVisible(limbName) then
local side = CommonMethods.GetSide(limbName)
LocalPlayerController.playerObj:getXp():AddXP(Perks["Side_" .. side], xp)
if not dcInst:getIsCicatrized(limbName) and dcInst:getIsProstEquipped(limbName) then
TOC_DEBUG.print("Trying for bleed, player met the criteria")
LocalPlayerController.TryRandomBleed(self.character, limbName)
local ampPerk = Perks["Side_" .. side]
local ampPerkLevel = LocalPlayerController.playerObj:getPerkLevel(ampPerk)
if ampPerkLevel < 10 then
--TOC_DEBUG.print("Levelling")
LocalPlayerController.playerObj:getXp():AddXP(ampPerk, xp)
end
-- Level up prosthesis perk
if dcInst:getIsProstEquipped(limbName) then
LocalPlayerController.playerObj:getXp():AddXP(Perks["ProstFamiliarity"], xp)
local prostPerk = Perks["ProstFamiliarity"]
local prostPerkLevel = LocalPlayerController.playerObj:getPerkLevel(prostPerk)
if prostPerkLevel < 10 then
LocalPlayerController.playerObj:getXp():AddXP(prostPerk, xp)
end
end
-- Bleeding when not cicatrized
if not dcInst:getIsCicatrized(limbName) and dcInst:getIsProstEquipped(limbName) then
--TOC_DEBUG.print("Trying for bleed, player met the criteria")
LocalPlayerController.TryRandomBleed(self.character, limbName)
end
end
end
end
@@ -107,7 +182,7 @@ end
--* Equipping items overrides *--
local og_ISEquipWeaponAction_isValid = ISEquipWeaponAction.isValid
---Add a condition to check the feasibility of having 2 handed weapons or if both arms are cut off
---@return boolean
---@return boolean?
---@diagnostic disable-next-line: duplicate-set-field
function ISEquipWeaponAction:isValid()
local isValid = og_ISEquipWeaponAction_isValid(self)
@@ -115,6 +190,10 @@ function ISEquipWeaponAction:isValid()
local isPrimaryHandValid = CachedDataHandler.GetHandFeasibility(StaticData.SIDES_IND_STR.R)
local isSecondaryHandValid = CachedDataHandler.GetHandFeasibility(StaticData.SIDES_IND_STR.L)
-- Both hands are cut off, so it's impossible to equip in any way
--TOC_DEBUG.print("isPrimaryHandValid : " .. tostring(isPrimaryHandValid))
--TOC_DEBUG.print("isSecondaryHandValid : " .. tostring(isSecondaryHandValid))
if not isPrimaryHandValid and not isSecondaryHandValid then
isValid = false
end
@@ -123,9 +202,7 @@ function ISEquipWeaponAction:isValid()
end
---A recreation of the original method, but with amputations in mind
---@param dcInst DataController
function ISEquipWeaponAction:performWithAmputation(dcInst)
function ISEquipWeaponAction:performWithAmputation()
TOC_DEBUG.print("running ISEquipWeaponAction performWithAmputation")
local hand = nil
local otherHand = nil
@@ -204,12 +281,15 @@ local og_ISEquipWeaponAction_perform = ISEquipWeaponAction.perform
function ISEquipWeaponAction:perform()
og_ISEquipWeaponAction_perform(self)
-- TODO Can we do it earlier?
--if self.character == getPlayer() then
local dcInst = DataController.GetInstance(self.character:getUsername())
-- Just check it any limb has been cut. If not, we can just return from here
if dcInst:getIsAnyLimbCut() == true then
self:performWithAmputation(dcInst)
if dcInst:getIsAnyLimbCut() then
self:performWithAmputation()
end
--end
end
function ISInventoryPaneContextMenu.doEquipOption(context, playerObj, isWeapon, items, player)
@@ -269,6 +349,29 @@ function ISWorldObjectContextMenu.createMenu(player, worldobjects, x, y, test)
---@type ISContextMenu
local ogContext = og_ISWorldObjectContextMenu_createMenu(player, worldobjects, x, y, test)
-- goddamn it, zomboid devs. ogContext could be a boolean...
-- TBH, I don't really care about gamepad support, but all this method can break stuff. Let's just disable thisfor gamepad users.
if type(ogContext) == "boolean" or type(ogContext) == "string" then
return ogContext
end
-- The vanilla game doesn't count an item in the off hand as "equipped" for picking up glass. Let's fix that here
local brokenGlassOption = ogContext:getOptionFromName(getText("ContextMenu_RemoveBrokenGlass"))
if brokenGlassOption then
local playerObj = getSpecificPlayer(player)
if (CachedDataHandler.GetHandFeasibility(StaticData.SIDES_IND_STR.R) and playerObj:getPrimaryHandItem()) or
(CachedDataHandler.GetHandFeasibility(StaticData.SIDES_IND_STR.L) and playerObj:getSecondaryHandItem())
then
brokenGlassOption.notAvailable = false
brokenGlassOption.toolTip = nil -- This is active only when you can't do the action.
end
end
-- check if no hands, disable various interactions
if not CachedDataHandler.GetBothHandsFeasibility() then
TOC_DEBUG.print("NO hands :((")
@@ -283,43 +386,30 @@ function ISWorldObjectContextMenu.createMenu(player, worldobjects, x, y, test)
return ogContext
end
--* DISABLE WEARING CERTAIN ITEMS WHEN NO LIMB
local function CheckLimbFeasibility(limbName)
local dcInst = DataController.GetInstance()
local isFeasible = not dcInst:getIsCut(limbName) or dcInst:getIsProstEquipped(limbName)
--TOC_DEBUG.print("isFeasible="..tostring(isFeasible))
return isFeasible
end
---@param obj any
---@param wrappedFunc function
---@param item InventoryItem
---@return boolean
local function WrapClothingAction(obj, wrappedFunc, item)
local isEquippable = wrappedFunc(obj)
if not isEquippable then return isEquippable end
local itemBodyLoc = item:getBodyLocation()
local limbToCheck = StaticData.AFFECTED_BODYLOCS_TO_LIMBS_IND_STR[itemBodyLoc]
if CheckLimbFeasibility(limbToCheck) then return isEquippable else return false end
end
---@diagnostic disable-next-line: duplicate-set-field
local og_ISWearClothing_isValid = ISWearClothing.isValid
function ISWearClothing:isValid()
return WrapClothingAction(self, og_ISWearClothing_isValid, self.item)
return LimitActionsController.WrapClothingAction(self, og_ISWearClothing_isValid, self.item)
end
local og_ISClothingExtraAction_isValid = ISClothingExtraAction.isValid
local og_ISClothingExtraAction_isValid = OverridenMethodsArchive.Save("ISClothingExtraAction_isValid", ISClothingExtraAction.isValid)
---@diagnostic disable-next-line: duplicate-set-field
function ISClothingExtraAction:isValid()
return WrapClothingAction(self, og_ISClothingExtraAction_isValid, InventoryItemFactory.CreateItem(self.extra))
return LimitActionsController.WrapClothingAction(self, og_ISClothingExtraAction_isValid, instanceItem(self.extra))
end
--* Book exception for exp
local og_ISReadABook_perform = ISReadABook.perform
function ISReadABook:perform()
self.noExp = true
og_ISReadABook_perform(self)
end
return LimitActionsController

View File

@@ -1,11 +1,16 @@
local DataController = require("TOC/Controllers/DataController")
local CommonMethods = require("TOC/CommonMethods")
local CachedDataHandler = require("TOC/Handlers/CachedDataHandler")
local CommandsData = require("TOC/CommandsData")
local StaticData = require("TOC/StaticData")
require("TOC/Events")
local TOC = require("TOC/Registries")
-----------
-- Handle ONLY stuff for the local client
---@class LocalPlayerController
@@ -33,13 +38,9 @@ function LocalPlayerController.InitializePlayer(isForced)
Events.OnAmputatedLimb.Add(LocalPlayerController.ToggleUpdateAmputations)
LocalPlayerController.ToggleUpdateAmputations()
-- Manage their traits
LocalPlayerController.ManageTraits(playerObj)
-- Since isForced is used to reset an existing player data, we're gonna clean their ISHealthPanel table too
if isForced then
local ItemsController = require("TOC/Controllers/ItemsController")
ItemsController.Player.DeleteAllOldAmputationItems(playerObj)
sendClientCommand(CommandsData.modules.TOC_ITEMS, "DeleteAllOldAmputationItems", {playerNum = playerObj:getOnlineID()})
CachedDataHandler.Setup(username)
end
@@ -47,24 +48,37 @@ function LocalPlayerController.InitializePlayer(isForced)
SetHealthPanelTOC()
end
---Handles the traits
---@param playerObj IsoPlayer
function LocalPlayerController.ManageTraits(playerObj)
function LocalPlayerController.ManageTraits()
-- Local player
local playerObj = getPlayer()
local AmputationHandler = require("TOC/Handlers/AmputationHandler")
for k, v in pairs(StaticData.TRAITS_BP) do
if playerObj:HasTrait(k) then
if playerObj:hasTrait(TOC.traits[k]) then
-- Once we find one, we should be done since they're exclusive
TOC_DEBUG.print("Player has amputation trait " .. k .. ", executing it")
local tempHandler = AmputationHandler:new(v, playerObj)
tempHandler:execute(false) -- No damage
tempHandler:close()
-- The wound should be already cicatrized
local dcInst = DataController.GetInstance()
LocalPlayerController.HandleSetCicatrization(DataController.GetInstance(), playerObj, v)
dcInst:apply()
return
end
end
end
-- We need to manage traits when we're done setupping everything
-- It shouldn't be done every single time we initialize the player, fetching data, etc.
Events.OnSetupTocData.Add(LocalPlayerController.ManageTraits)
----------------------------------------------------------
--* Health *--
@@ -81,7 +95,8 @@ function LocalPlayerController.HealArea(bodyPart)
bodyPart:setBleedingTime(0)
bodyPart:SetBitten(false)
bodyPart:setBiteTime(0)
--bodyPart:setBiteTime(0)
bodyPart:SetInfected(false)
bodyPart:setCut(false)
bodyPart:setCutTime(0)
@@ -98,14 +113,14 @@ end
---@param bodyPart BodyPart
---@param limbName string
---@param dcInst DataController
function LocalPlayerController.HealZombieInfection(bodyDamage, bodyPart, limbName, dcInst)
function LocalPlayerController.HealZombieInfection(bodyDamage, limbName, dcInst)
-- FIX Different in B42.13, to be set with stats?
if bodyDamage:isInfected() == false then return end
bodyDamage:setInfected(false)
bodyDamage:setInfectionMortalityDuration(-1)
bodyDamage:setInfectionTime(-1)
bodyDamage:setInfectionLevel(-1)
bodyPart:SetInfected(false)
--bodyPart:SetInfected(false)
dcInst:setIsInfected(limbName, false)
dcInst:apply()
@@ -127,8 +142,14 @@ function LocalPlayerController.TryRandomBleed(character, limbName)
if chance > normCicTime then
TOC_DEBUG.print("Triggered bleeding from non cicatrized wound")
local adjacentBodyPartType = BodyPartType[StaticData.LIMBS_ADJACENT_IND_STR[limbName]]
character:getBodyDamage():getBodyPart(adjacentBodyPartType):setBleeding(true)
character:getBodyDamage():getBodyPart(adjacentBodyPartType):setBleedingTime(20)
-- we need to check if the wound is already bleeding before doing anything else to prevent issues with bandages
local bp = character:getBodyDamage():getBodyPart(adjacentBodyPartType)
bp:setBleedingTime(20) -- TODO Should depend on cicatrization instead of a fixed time
-- ADD Could break bandages if bleeding is too much?
--character:getBodyDamage():getBodyPart(adjacentBodyPartType):setBleeding(true)
end
end
@@ -141,9 +162,13 @@ LocalPlayerController.hasBeenDamaged = false
---Check if the player has in infected body part or if they have been hit in a cut area
---@param character IsoPlayer|IsoGameCharacter
function LocalPlayerController.HandleDamage(character)
-- TOC_DEBUG.print("Player got hit!")
--TOC_DEBUG.print("Player got hit!")
-- TOC_DEBUG.print(damageType)
if character ~= getPlayer() then return end
if character ~= getPlayer() then
-- Disable lock before doing anything else
LocalPlayerController.hasBeenDamaged = false
return
end
local bd = character:getBodyDamage()
local dcInst = DataController.GetInstance()
local modDataNeedsUpdate = false
@@ -161,7 +186,7 @@ function LocalPlayerController.HandleDamage(character)
-- Special case for bites\zombie infections
if bodyPart:IsInfected() then
TOC_DEBUG.print("Healed from zombie infection - " .. limbName)
LocalPlayerController.HealZombieInfection(bd, bodyPart, limbName, dcInst)
LocalPlayerController.HealZombieInfection(bd, limbName, dcInst)
end
else
if (bodyPart:bitten() or bodyPart:IsInfected()) and not dcInst:getIsInfected(limbName) then
@@ -173,8 +198,7 @@ function LocalPlayerController.HandleDamage(character)
-- Check other body parts that are not included in the mod, if there's a bite there then the player is fucked
-- We can skip this loop if the player has been infected. The one before we kinda need it to handle correctly the bites in case the player wanna cut stuff off anyway
if dcInst:getIsIgnoredPartInfected() then return end
if not dcInst:getIsIgnoredPartInfected() then
for i = 1, #StaticData.IGNORED_BODYLOCS_BPT do
local bodyPartType = StaticData.IGNORED_BODYLOCS_BPT[i]
local bodyPart = bd:getBodyPart(bodyPartType)
@@ -183,8 +207,8 @@ function LocalPlayerController.HandleDamage(character)
modDataNeedsUpdate = true
end
end
end
-- TODO in theory should sync modData, but it's gonna be expensive as fuck. Figure it out
if modDataNeedsUpdate then
dcInst:apply()
end
@@ -193,17 +217,13 @@ function LocalPlayerController.HandleDamage(character)
LocalPlayerController.hasBeenDamaged = false
end
---Setup HandleDamage, triggered by OnPlayerGetDamage
---Setup HandleDamage, triggered by OnPlayerGetDamage. To prevent a spam caused by this awful event, we use a bool lock
---@param character IsoPlayer|IsoGameCharacter
---@param damageType string
---@param damageAmount number
function LocalPlayerController.OnGetDamage(character, damageType, damageAmount)
-- TODO Check if other players in the online triggers this
if LocalPlayerController.hasBeenDamaged == false then
-- Start checks
-- TODO Add a timer before we can re-enable this bool?
LocalPlayerController.hasBeenDamaged = true
LocalPlayerController.HandleDamage(character)
end
@@ -296,13 +316,14 @@ end
---@param playerObj IsoPlayer
---@param limbName string
function LocalPlayerController.HandleSetCicatrization(dcInst, playerObj, limbName)
TOC_DEBUG.print(tostring(limbName) .. " is cicatrized")
TOC_DEBUG.print("Setting cicatrization to " .. tostring(limbName))
dcInst:setIsCicatrized(limbName, true)
dcInst:setCicatrizationTime(limbName, 0)
-- Set visuals for the amputation
local ItemsController = require("TOC/Controllers/ItemsController")
ItemsController.Player.OverrideAmputationItemVisuals(playerObj, limbName, true)
-- -- Set visuals for the amputation
sendClientCommand(CommandsData.modules.TOC_ITEMS, "OverrideAmputationItemVisuals",
{playerNum = playerObj:getOnlineID(), limbName = limbName, isCicatrized = true})
end
--* Object drop handling when amputation occurs

View File

@@ -64,18 +64,18 @@ end
---@param obj any self
---@param wrappedFunc function
function TourniquetController.WrapClothingAction(obj, wrappedFunc)
local isTourniquet = TourniquetController.IsItemTourniquet(obj.item:getFullType())
local group
if isTourniquet then
group = BodyLocations.getGroup("Human")
group:setMultiItem(TourniquetController.bodyLoc, false)
end
-- local isTourniquet = TourniquetController.IsItemTourniquet(obj.item:getFullType())
-- local group
-- if isTourniquet then
-- group = BodyLocations.getGroup("Human")
-- group:setMultiItem(TourniquetController.bodyLoc, false)
-- end
local ogValue = wrappedFunc(obj)
if isTourniquet then
group:setMultiItem(TourniquetController.bodyLoc, true)
end
-- if isTourniquet then
-- group:setMultiItem(TourniquetController.bodyLoc, true)
-- end
return ogValue -- Needed for isValid
end
@@ -94,16 +94,19 @@ end
local og_ISClothingExtraAction_perform = ISClothingExtraAction.perform
---@diagnostic disable-next-line: duplicate-set-field
function ISClothingExtraAction:perform()
TourniquetController.WrapClothingAction(self, og_ISClothingExtraAction_perform)
end
local og_ISWearClothing_isValid = ISWearClothing.isValid
---@diagnostic disable-next-line: duplicate-set-field
function ISWearClothing:isValid()
return TourniquetController.WrapClothingAction(self, og_ISWearClothing_isValid)
end
local og_ISUnequipAction_perform = ISUnequipAction.perform
---@diagnostic disable-next-line: duplicate-set-field
function ISUnequipAction:perform()
return TourniquetController.WrapClothingAction(self, og_ISUnequipAction_perform)
end

View File

@@ -2,3 +2,4 @@
LuaEventManager.AddEvent("OnAmputatedLimb") --Triggered when a limb has been amputated
LuaEventManager.AddEvent("OnProsthesisUnequipped")
LuaEventManager.AddEvent("OnReceivedTocData") -- Triggered when TOC data is ready
LuaEventManager.AddEvent("OnSetupTocData") -- Triggered when TOC has been setupped

View File

@@ -1,5 +1,8 @@
-- TODO Move this to server side for 42.13
local DataController = require("TOC/Controllers/DataController")
local ItemsController = require("TOC/Controllers/ItemsController")
local CommandsData = require("TOC/CommandsData")
local CachedDataHandler = require("TOC/Handlers/CachedDataHandler")
local LocalPlayerController = require("TOC/Controllers/LocalPlayerController")
local StaticData = require("TOC/StaticData")
@@ -89,9 +92,12 @@ end
---@param stitchesItem InventoryItem
---@return ISStitch
function AmputationHandler.PrepareStitchesAction(prevAction, limbName, surgeonPl, patientPl, stitchesItem)
local bptEnum = StaticData.LIMBS_TO_BODYLOCS_IND_BPT[limbName]
local bd = patientPl:getBodyDamage()
local bodyPart = bd:getBodyPart(bptEnum)
-- we need the adjacent one, not the actual one
local adjacentLimb = StaticData.LIMBS_ADJACENT_IND_STR[limbName]
local bodyPart = bd:getBodyPart(BodyPartType[adjacentLimb])
local stitchesAction = ISStitch:new(surgeonPl, patientPl, stitchesItem, bodyPart, true)
ISTimedActionQueue.addAfter(prevAction, stitchesAction)
@@ -106,9 +112,11 @@ end
---@param bandageItem InventoryItem
---@return ISApplyBandage
function AmputationHandler.PrepareBandagesAction(prevAction, limbName, surgeonPl, patientPl, bandageItem)
local bptEnum = StaticData.LIMBS_TO_BODYLOCS_IND_BPT[limbName]
local bd = patientPl:getBodyDamage()
local bodyPart = bd:getBodyPart(bptEnum)
-- we need the adjacent one, not the actual one
local adjacentLimb = StaticData.LIMBS_ADJACENT_IND_STR[limbName]
local bodyPart = bd:getBodyPart(BodyPartType[adjacentLimb])
local bandageAction = ISApplyBandage:new(surgeonPl, patientPl, bandageItem, bodyPart, true)
ISTimedActionQueue.addAfter(prevAction, bandageAction)
@@ -147,11 +155,13 @@ function AmputationHandler:damageAfterAmputation(surgeonFactor)
bodyPart:setBleedingTime(baseDamage - surgeonFactor)
bodyPart:setDeepWounded(true)
bodyPart:setDeepWoundTime(baseDamage - surgeonFactor)
patientStats:setEndurance(surgeonFactor)
patientStats:setStress(baseDamage - surgeonFactor)
patientStats:set(CharacterStat.ENDURANCE, surgeonFactor)
patientStats:set(CharacterStat.STRESS, baseDamage - surgeonFactor)
end
---Execute the amputation
--- Execute the amputation. This method doesn't check if the upper limb has been amputated or not, so if
--- somehow the method gets triggered and we're trying to cut off a part that doesn't really exist anymore,
--- it will still be executed. This is by design, additional checks must be made BEFORE running the AmputationHandler
---@param damagePlayer boolean
function AmputationHandler:execute(damagePlayer)
local surgeonFactor = self.surgeonPl:getPerkLevel(Perks.Doctor) * SandboxVars.TOC.SurgeonAbilityImportance
@@ -167,8 +177,13 @@ function AmputationHandler:execute(damagePlayer)
LocalPlayerController.HealArea(bodyPart)
-- Give the player the correct amputation item
ItemsController.Player.DeleteOldAmputationItem(self.patientPl, self.limbName)
ItemsController.Player.SpawnAmputationItem(self.patientPl, self.limbName)
-- FIX This can be done in a single step instead of this crap
sendClientCommand(CommandsData.modules.TOC_ITEMS, "DeleteOldAmputationItem",
{playerNum = self.patientPl:getOnlineID(), limbName = self.limbName})
sendClientCommand(CommandsData.modules.TOC_ITEMS, "SpawnAmputationItem",
{playerNum = self.patientPl:getOnlineID(), limbName = self.limbName})
-- Add it to the list of cut limbs on this local client
local username = self.patientPl:getUsername()
@@ -183,8 +198,13 @@ function AmputationHandler:execute(damagePlayer)
-- Cache highest amputation and hand feasibility
CachedDataHandler.CalculateCacheableValues(username)
-- TODO Test this again for 42.13
-- If the part was actually infected, heal the player, if they were in time (infectionLevel < 20)
if bd:getInfectionLevel() < 20 and bodyPart:IsInfected() and not dcInst:getIsIgnoredPartInfected() then
local infectionLevel = self.patientPl:getStats():get(CharacterStat.ZOMBIE_INFECTION)
if infectionLevel < 20 and bodyPart:IsInfected() and not dcInst:getIsIgnoredPartInfected() then
LocalPlayerController.HealZombieInfection(bd, bodyPart, self.limbName, dcInst)
end
@@ -196,7 +216,7 @@ function AmputationHandler:execute(damagePlayer)
triggerEvent("OnAmputatedLimb", self.limbName)
end
---Deletes the instance
---Delete the instance
function AmputationHandler:close()
AmputationHandler.instance = nil
end

View File

@@ -22,16 +22,13 @@ end
---Will calculate all the values that we need
function CachedDataHandler.CalculateCacheableValues(username)
CachedDataHandler.CalculateHighestAmputatedLimbs(username)
-- FIX This should be run ONLY on the actual client, never on other clients. Just a placeholder fix for now
if getPlayer():getUsername() == username then
CachedDataHandler.CalculateBothHandsFeasibility()
CachedDataHandler.OverrideBothHandsFeasibility()
end
end
--* Amputated Limbs caching *--
CachedDataHandler.amputatedLimbs = {}
@@ -120,31 +117,56 @@ CachedDataHandler.handFeasibility = {}
function CachedDataHandler.CalculateHandFeasibility(limbName)
local dcInst = DataController.GetInstance()
local side = CommonMethods.GetSide(limbName)
-- TODO if we re run this too early, it might break everything after a forced re-init
CachedDataHandler.handFeasibility[side] = not dcInst:getIsCut(limbName) or dcInst:getIsProstEquipped(limbName)
TOC_DEBUG.print("Calculated hand feasibility: " .. tostring(side))
end
---@param side string Either "L" or "R"
---@return boolean
function CachedDataHandler.GetHandFeasibility(side)
-- FIX horrendous workaround, but with a forced init we run the caching too early and it breaks this, setting it to nil.
if CachedDataHandler.handFeasibility[side] == nil then
CachedDataHandler.OverrideBothHandsFeasibility()
end
return CachedDataHandler.handFeasibility[side]
end
function CachedDataHandler.CalculateBothHandsFeasibility()
function CachedDataHandler.OverrideBothHandsFeasibility()
CachedDataHandler.CalculateHandFeasibility("Hand_L")
CachedDataHandler.CalculateHandFeasibility("Hand_R")
local interactStr = "Interact"
if CachedDataHandler.interactKey == nil or CachedDataHandler.interactKey == 0 then
CachedDataHandler.interactKey = getCore():getKey(interactStr)
end
if not CachedDataHandler.GetBothHandsFeasibility() then
TOC_DEBUG.print("Disabling interact key")
TOC_DEBUG.print("Cached current key for interact: " .. tostring(CachedDataHandler.interactKey))
-- Cache the current key
CachedDataHandler.interactKey = getCore():getKey(interactStr)
getCore():addKeyBinding(interactStr, Keyboard.KEY_NONE)
if StaticData.COMPAT_42 then
getCore():addKeyBinding(interactStr, Keyboard.KEY_NONE, 0, false, false, false)
else
TOC_DEBUG.print("Re-enabling interact key")
getCore():addKeyBinding(interactStr, Keyboard.KEY_NONE)
if not CachedDataHandler.interactKey then CachedDataHandler.interactKey = getCore():getKey(interactStr) end
end
else
--TOC_DEBUG.print("Re-enabling interact key")
--TOC_DEBUG.print("Cached current key for interact: " .. tostring(CachedDataHandler.interactKey))
if StaticData.COMPAT_42 then
getCore():addKeyBinding(interactStr, CachedDataHandler.interactKey, 0, false, false, false)
else
getCore():addKeyBinding(interactStr, CachedDataHandler.interactKey)
end
end
end
function CachedDataHandler.GetBothHandsFeasibility()
@@ -152,3 +174,4 @@ function CachedDataHandler.GetBothHandsFeasibility()
end
return CachedDataHandler

View File

@@ -2,26 +2,27 @@ local CommonMethods = require("TOC/CommonMethods")
local StaticData = require("TOC/StaticData")
local DataController = require("TOC/Controllers/DataController")
local CachedDataHandler = require("TOC/Handlers/CachedDataHandler")
local OverridenMethodsArchive = require("TOC/OverridenMethodsArchive")
-------------------------
---@class ProsthesisHandler
local ProsthesisHandler = {}
local bodyLocArmProst = StaticData.MOD_BODYLOCS_BASE_IND_STR.TOC_ArmProst
local bodyLocLegProst = StaticData.MOD_BODYLOCS_BASE_IND_STR.TOC_LegProst
local bodylocArmProstBaseline = "toc:toc_armprost"
--local bodyLocLegProst = "TOC_LegProst"
---Check if the following item is a prosthesis or not
---@param item InventoryItem?
---@return boolean
function ProsthesisHandler.CheckIfProst(item)
-- TODO Won't be correct when prost for legs are gonna be in
--TOC_DEBUG.print("Checking if item is prost")
if item == nil then
--TOC_DEBUG.print("Not prost")
TOC_DEBUG.print("Not prost")
return false
end
return item:getBodyLocation():contains(bodyLocArmProst)
return item:getBodyLocation():toString():contains(bodylocArmProstBaseline)
end
---Get the grouping for the prosthesis
@@ -31,13 +32,10 @@ function ProsthesisHandler.GetGroup(item)
local fullType = item:getFullType()
local side = CommonMethods.GetSide(fullType)
local bodyLocation = item:getBodyLocation()
local position
if bodyLocation == bodyLocArmProst then
if bodyLocation:toString():contains(bodylocArmProstBaseline) then
position = "Top_"
elseif bodyLocation == bodyLocLegProst then
position = "Bottom_"
else
TOC_DEBUG.print("Something is wrong, no position in this item")
position = nil
@@ -84,18 +82,11 @@ function ProsthesisHandler.SearchAndSetupProsthesis(item, isEquipping)
dcInst:apply()
-- Calculates hands feasibility once again
CachedDataHandler.CalculateBothHandsFeasibility()
CachedDataHandler.OverrideBothHandsFeasibility()
return true
end
-------------------------
--* Overrides *--
---@param item InventoryItem
---@param isEquippable boolean
---@return unknown
local function HandleProsthesisValidation(item, isEquippable)
function ProsthesisHandler.Validate(item, isEquippable)
local isProst = ProsthesisHandler.CheckIfProst(item)
if not isProst then return isEquippable end
@@ -110,77 +101,89 @@ local function HandleProsthesisValidation(item, isEquippable)
end
---@diagnostic disable-next-line: duplicate-set-field
-------------------------
--* Overrides *--
local og_ISWearClothing_isValid = ISWearClothing.isValid
---@diagnostic disable-next-line: duplicate-set-field
function ISWearClothing:isValid()
local isEquippable = og_ISWearClothing_isValid(self)
return HandleProsthesisValidation(self.item, isEquippable)
return ProsthesisHandler.Validate(self.item, isEquippable)
end
local og_ISWearClothing_perform = ISWearClothing.perform
---@diagnostic disable-next-line: duplicate-set-field
function ISWearClothing:perform()
ProsthesisHandler.SearchAndSetupProsthesis(self.item, true)
og_ISWearClothing_perform(self)
end
local og_ISClothingExtraAction_isValid = ISClothingExtraAction.isValid
local og_ISClothingExtraAction_isValid = OverridenMethodsArchive.Save("ISClothingExtraAction_isValid", ISClothingExtraAction.isValid)
---@diagnostic disable-next-line: duplicate-set-field
function ISClothingExtraAction:isValid()
local isEquippable = og_ISClothingExtraAction_isValid(self)
-- self.extra is a string, not the item
-- B42 Compatibility to add
local testItem = InventoryItemFactory.CreateItem(self.extra)
return HandleProsthesisValidation(testItem, isEquippable)
return ProsthesisHandler.Validate(testItem, isEquippable)
end
--[[
local og_ISClothingExtraAction_perform = OverridenMethodsArchive.Save("ISClothingExtraAction_perform", ISClothingExtraAction.perform)
---@diagnostic disable-next-line: duplicate-set-field
function ISClothingExtraAction:perform()
-- B42 Compatibility to add
local extraItem = InventoryItemFactory.CreateItem(self.extra)
ProsthesisHandler.SearchAndSetupProsthesis(extraItem, true)
og_ISClothingExtraAction_perform(self)
end
local og_ISUnequipAction_perform = ISUnequipAction.perform
---@diagnostic disable-next-line: duplicate-set-field
function ISUnequipAction:perform()
--[[
Horrendous workaround
To unequp items, the java side uses WornItems.setItem, which has
a check for multiItem. Basically, if it's active, it won't actually remove the item,
fucking things up. So, to be 100% sure that we're removing the items, we're gonna
disable and re-enable the multi-item bool for the Unequip Action.
]]
]]
local og_ISClothingExtraAction_perform = ISClothingExtraAction.perform
function ISClothingExtraAction:perform()
local extraItem = InventoryItemFactory.CreateItem(self.extra)
local isProst = ProsthesisHandler.SearchAndSetupProsthesis(extraItem, true)
local group
if isProst then
group = BodyLocations.getGroup("Human")
group:setMultiItem("TOC_ArmProst", false)
end
og_ISClothingExtraAction_perform(self)
if isProst then
group:setMultiItem("TOC_ArmProst", true)
end
end
local og_ISUnequipAction_perform = ISUnequipAction.perform
function ISUnequipAction:perform()
local isProst = ProsthesisHandler.SearchAndSetupProsthesis(self.item, false)
local group
if isProst then
group = BodyLocations.getGroup("Human")
group:setMultiItem("TOC_ArmProst", false)
end
-- local group
-- if isProst then
-- group = BodyLocations.getGroup("Human")
-- group:setMultiItem("TOC_ArmProst", false)
-- end
og_ISUnequipAction_perform(self)
if isProst then
group:setMultiItem("TOC_ArmProst", true)
-- group:setMultiItem("TOC_ArmProst", true)
-- we need to fetch the limbname associated to the prosthesis
local side = CommonMethods.GetSide(self.item:getFullType())
local highestAmputatedLimbs = CachedDataHandler.GetHighestAmputatedLimbs(getPlayer():getUsername())
if highestAmputatedLimbs then
local hal = highestAmputatedLimbs[side]
if hal then
-- This could break if amputated limbs aren't cached for some reason
triggerEvent("OnProsthesisUnequipped", hal)
end
end
end
end
return ProsthesisHandler

View File

@@ -6,7 +6,7 @@ require("TOC/Events")
---@class Main
local Main = {
_version = "2.0.7"
_version = "2.3"
}
function Main.Start()
@@ -58,8 +58,9 @@ function Main.WipeData(player)
-- Let's wipe the instance too just to be sure
local DataController = require("TOC/Controllers/DataController")
DataController.DestroyInstance(username)
-- TODO This can break things I guess
--local DataController = require("TOC/Controllers/DataController")
--DataController.DestroyInstance(username)
end

View File

@@ -145,6 +145,14 @@ end)
TestFramework.registerTestModule("Various", "Player", function()
local Tests = {}
function Tests.BleedTest()
local pl = getPlayer()
--pl:getBodyDamage():getBodyPart(BodyPartType.ForeArm_R):setBleeding(true)
pl:getBodyDamage():getBodyPart(BodyPartType.ForeArm_R):setBleedingTime(20)
end
function Tests.Kill()
getPlayer():Kill(getPlayer())
end
@@ -152,7 +160,6 @@ TestFramework.registerTestModule("Various", "Player", function()
return Tests
end)
TestFramework.registerTestModule("Various", "Visuals", function()
local Tests = {}

View File

@@ -7,6 +7,9 @@ local CommonMethods = require("TOC/CommonMethods")
---@field otherPlayer IsoPlayer
---@field bandage InventoryItem
---@field bodyPart any
---@field doctorLevel number
---@field bandagedPlayerX number
---@field bandagedPlayerY number
local CleanWoundAction = ISBaseTimedAction:derive("CleanWoundAction")
---@param doctor IsoPlayer
@@ -33,7 +36,7 @@ function CleanWoundAction:new(doctor, otherPlayer, bandage, bodyPart)
if doctor:isTimedActionInstant() then
o.maxTime = 1
end
if doctor:getAccessLevel() ~= "None" then
if doctor:getAccessLevel() ~= "None" then -- B42 Deprecated
o.doctorLevel = 10
end
return o
@@ -84,7 +87,7 @@ function CleanWoundAction:perform()
TOC_DEBUG.print("CleanWound for " .. self.otherPlayer:getUsername())
if self.character:HasTrait("Hemophobic") then
if self.character:hasTrait("Hemophobic") then
self.character:getStats():setPanic(self.character:getStats():getPanic() + 15)
end

View File

@@ -24,9 +24,7 @@ local CutLimbAction = ISBaseTimedAction:derive("CutLimbAction")
---@param bandageItem InventoryItem?
---@return CutLimbAction
function CutLimbAction:new(surgeon, patient, limbName, item, stitchesItem, bandageItem)
local o = {}
setmetatable(o, self)
self.__index = self
local o = ISBaseTimedAction.new(self, surgeon)
-- We need to follow ISBaseTimedAction. self.character is gonna be the surgeon
o.character = surgeon
@@ -43,12 +41,21 @@ function CutLimbAction:new(surgeon, patient, limbName, item, stitchesItem, banda
o.stopOnWalk = true
o.stopOnRun = true
o.maxTime = 1000 - (surgeon:getPerkLevel(Perks.Doctor) * 50)
if o.character:isTimedActionInstant() then o.maxTime = 1 end
o.maxTime = o:getDuration()
return o
end
function CutLimbAction:getDuration()
if self.character:isTimedActionInstant() then
return 1
else
local baseTime = 1000
local perkLevel = self.character:getPerkLevel(Perks.Doctor)
return baseTime - (perkLevel * 50)
end
end
function CutLimbAction:isValid()
return not ISHealthPanel.DidPatientMove(self.character,self.patient, self.patientX, self.patientY)
end
@@ -89,6 +96,16 @@ function CutLimbAction:start()
end
-- function CutLimbAction:serverStart()
-- emulateAnimEvent(self.netAction, 200, "")
-- end
-- function CutLimbAction:animEvent(event, parameter)
-- end
function CutLimbAction:waitToStart()
if self.character == self.patient then
return false
@@ -117,22 +134,30 @@ function CutLimbAction:stop()
end
function CutLimbAction:perform()
-- Stop the sound
self:stopSound()
if self.patient == self.character then
TOC_DEBUG.print("patient and surgeon are the same, executing on the client")
local handler = AmputationHandler:new(self.limbName)
handler:execute(true)
else
TOC_DEBUG.print("patient and surgeon not the same, sending relay to server")
-- Other player
---@type relayExecuteAmputationActionParams
local params = {patientNum = self.patient:getOnlineID(), limbName = self.limbName}
sendClientCommand(CommandsData.modules.TOC_RELAY, CommandsData.server.Relay.RelayExecuteAmputationAction, params )
end
ISBaseTimedAction.perform(self)
end
function CutLimbAction:complete()
-- TODO AmputationHandler runs client side, by doing this this would run on the server. AM I missing something?
local handler = AmputationHandler:new(self.limbName, self.character)
handler:execute(true)
end
-- function CutLimbAction:perform()
-- -- Stop the sound
-- if self.patient == self.character then
-- TOC_DEBUG.print("patient and surgeon are the same, executing on the client")
-- local handler = AmputationHandler:new(self.limbName)
-- handler:execute(true)
-- else
-- TOC_DEBUG.print("patient and surgeon not the same, sending relay to server")
-- -- Other player
-- ---@type relayExecuteAmputationActionParams
-- local params = {patientNum = self.patient:getOnlineID(), limbName = self.limbName}
-- sendClientCommand(CommandsData.modules.TOC_RELAY, CommandsData.server.Relay.RelayExecuteAmputationAction, params )
-- end
-- end
return CutLimbAction

View File

@@ -0,0 +1,139 @@
-- TODO This section must be overhauled
local DataController = require("TOC/Controllers/DataController")
local StaticData = require("TOC/StaticData")
---@diagnostic disable: duplicate-set-field
-- Bunch of actions shouldn't be modified by the adjusted time
-----------------------------------------------
---* Some actions have specific maxTime calculations and we must account for that
---ISAttachItemHotbar
---ISDetachItemHotbar
---ISEquipWeaponAction
---ISUnequipAction
--- We're forced to re-run this crap to fix it
---@param action ISBaseTimedAction
local function OverrideAction(action, maxTime)
-- TODO Add forced debuff instead of just relying on the vanilla values?
action.skipTOC = true
action.maxTime = maxTime
action.animSpeed = 1.0
end
local og_ISAttachItemHotbar_new = ISAttachItemHotbar.new
function ISAttachItemHotbar:new(character, item, slot, slotIndex, slotDef)
local action = og_ISAttachItemHotbar_new(self, character, item, slot, slotIndex, slotDef)
OverrideAction(action, 30) -- Default time for this action
return action
end
local og_ISDetachItemHotbar_new = ISDetachItemHotbar.new
function ISDetachItemHotbar:new(character, item)
local action = og_ISDetachItemHotbar_new(self, character, item)
OverrideAction(action, 25) -- Default time for this action
return action
end
local og_ISEquipWeaponAction_new = ISEquipWeaponAction.new
function ISEquipWeaponAction:new(character, item, time, primary, twoHands)
local action = og_ISEquipWeaponAction_new(self, character, item, time, primary, twoHands)
TOC_DEBUG.print("Override ISEquipWeaponAction New")
-- check if right arm is cut off or not. if it is, penality shall apply
-- if we got here, the action is valid, so we know that we have a prosthesis.
local dcInst = DataController.GetInstance()
-- Brutal Handwork should be considered. Use the twohands thing
if not (dcInst:getIsAnyLimbCut() and twoHands) then
OverrideAction(action, time)
end
return action
end
local og_ISUnequipAction_new = ISUnequipAction.new
function ISUnequipAction:new(character, item, time)
local action = og_ISUnequipAction_new(self, character, item, time)
---@cast item InventoryItem
-- TODO Consider other cases where unequipping something should skip TOC.
if instanceof(item, 'HandWeapon') then
OverrideAction(action, time)
end
return action
end
------------------------------------------------------
--- Normal cases
local og_ISEatFoodAction_new = ISEatFoodAction.new
function ISEatFoodAction:new(character, item, percentage)
local action = og_ISEatFoodAction_new(self, character, item, percentage)
--TOC_DEBUG.print("Override ISEatFoodAction")
action.skipTOC = true
return action
end
local og_ISReadABook_new = ISReadABook.new
function ISReadABook:new(character, item, time)
local action = og_ISReadABook_new(self, character, item, time)
--TOC_DEBUG.print("Override ISReadABook")
action.skipTOC = true
return action
end
local og_ISTakePillAction_new = ISTakePillAction.new
function ISTakePillAction:new(character, item, time)
local action = og_ISTakePillAction_new(self, character, item, time)
--TOC_DEBUG.print("Override ISTakePillAction")
action.skipTOC = true
return action
end
local og_ISTakeWaterAction_new = ISTakeWaterAction.new
function ISTakeWaterAction:new(character, item, waterUnit, waterObject, time, oldItem)
local action = og_ISTakeWaterAction_new(self, character, item, waterUnit, waterObject, time, oldItem)
--TOC_DEBUG.print("Override ISTakeWaterAction")
action.skipTOC = true
return action
end
local og_ISDrinkFromBottle_new = ISDrinkFromBottle.new
function ISDrinkFromBottle:new(character, item, uses)
local action = og_ISDrinkFromBottle_new(self, character, item, uses)
--TOC_DEBUG.print("Override ISDrinkFromBottle")
action.skipTOC = true
return action
end
if StaticData.COMPAT_42 == false then
-- TODO confirm that this doesn't exist anymore in B42
-- B42 nenen
local og_ISFinalizeDealAction_new = ISFinalizeDealAction.new
function ISFinalizeDealAction:new(player, otherPlayer, itemsToGive, itemsToReceive, time)
local action = og_ISFinalizeDealAction_new(self, player, otherPlayer, itemsToGive, itemsToReceive, time)
--TOC_DEBUG.print("Override ISFinalizeDealAction")
action.skipTOC = true
return action
end
end
local og_ISCampingInfoAction_new = ISCampingInfoAction.new
function ISCampingInfoAction:new(character, campfireObject, campfire)
local action = og_ISCampingInfoAction_new(self, character, campfireObject, campfire)
--TOC_DEBUG.print("Override ISCampingInfoAction")
action.skipTOC = true
return action
end

View File

@@ -0,0 +1,116 @@
---@class ConfirmationPanel : ISPanel
local ConfirmationPanel = ISPanel:derive("ConfirmationPanel")
---Starts a new confirmation panel
---@param x number
---@param y number
---@param width number
---@param height number
---@param alertText string
---@param onConfirmFunc function
---@return ConfirmationPanel
function ConfirmationPanel:new(x, y, width, height, alertText, parentPanel, onConfirmFunc)
local o = ISPanel:new(x, y, width, height)
setmetatable(o, self)
self.__index = self
o:initialise()
o.alertText = alertText
o.onConfirmFunc = onConfirmFunc
o.parentPanel = parentPanel
ConfirmationPanel.instance = o
---@cast o ConfirmationPanel
return o
end
function ConfirmationPanel:createChildren()
ISPanel.createChildren(self)
self.borderColor = { r = 1, g = 0, b = 0, a = 1 }
self.textPanel = ISRichTextPanel:new(0, 0, self.width, self.height)
self.textPanel:initialise()
self:addChild(self.textPanel)
self.textPanel.defaultFont = UIFont.Medium
self.textPanel.anchorTop = true
self.textPanel.anchorLeft = false
self.textPanel.anchorBottom = true
self.textPanel.anchorRight = false
self.textPanel.marginLeft = 0
self.textPanel.marginTop = 10
self.textPanel.marginRight = 0
self.textPanel.marginBottom = 0
self.textPanel.autosetheight = false
self.textPanel.background = false
self.textPanel:setText(self.alertText)
self.textPanel:paginate()
local yPadding = 10
local xPadding = self:getWidth() / 4
local btnWidth = 100
local btnHeight = 25
local yButton = self:getHeight() - yPadding - btnHeight
self.btnYes = ISButton:new(xPadding, yButton, btnWidth, btnHeight, getText("IGUI_Yes"), self, self.onClick)
self.btnYes.internal = "YES"
self.btnYes:initialise()
self.btnYes.borderColor = { r = 1, g = 0, b = 0, a = 1 }
self.btnYes:setEnable(true)
self:addChild(self.btnYes)
self.btnNo = ISButton:new(self:getWidth() - xPadding - btnWidth, yButton, btnWidth, btnHeight, getText("IGUI_No"), self,
self.onClick)
self.btnNo.internal = "NO"
self.btnNo:initialise()
self.btnNo:setEnable(true)
self:addChild(self.btnNo)
end
function ConfirmationPanel:onClick(btn)
if btn.internal == 'YES' then
self.onConfirmFunc(self.parentPanel)
self:close()
elseif btn.internal == 'NO' then
self:close()
end
end
-------------------------
---@param alertText string
---@param x any
---@param y any
---@param parentPanel any
---@param onConfirmFunc any
---@return ConfirmationPanel
function ConfirmationPanel.Open(alertText, x, y, parentPanel, onConfirmFunc)
local width = 500
local height = 120
local screenWidth = getCore():getScreenWidth()
local screenHeight = getCore():getScreenHeight()
-- Check for oversize
if x+width > screenWidth then
x = screenWidth - width
end
if y+height > screenHeight then
y = screenHeight - height
end
local panel = ConfirmationPanel:new(x, y, width, height, alertText, parentPanel, onConfirmFunc)
panel:initialise()
panel:addToUIManager()
panel:bringToTop()
return panel
end
function ConfirmationPanel.Close()
ConfirmationPanel.instance:close()
end
return ConfirmationPanel

View File

@@ -1,7 +1,7 @@
local StaticData = require("TOC/StaticData")
local CommandsData = require("TOC/CommandsData")
local DataController = require("TOC/Controllers/DataController")
local CachedDataHandler = require("TOC/Handlers/CachedDataHandler")
local Compat = require("TOC/Compat")
local CutLimbInteractionHandler = require("TOC/UI/Interactions/CutLimbInteractionHandler")
local WoundCleaningInteractionHandler = require("TOC/UI/Interactions/WoundCleaningInteractionHandler")
@@ -10,7 +10,22 @@ local WoundCleaningInteractionHandler = require("TOC/UI/Interactions/WoundCleani
local isReady = false
local xMod, yMod
if StaticData.COMPAT_42 then
-- B42 For some reason (I didn't investigate), when applying stuff to the health panel there is an un-accounted shift in B42.
xMod = 5
yMod = 13
else
xMod = 0
yMod = 0
end
function SetHealthPanelTOC()
-- depending on compatibility
isReady = true
end
@@ -98,14 +113,14 @@ function ISHealthPanel:tryDrawAmputation(highestAmputations, side, username)
local sexPl = self.character:isFemale() and "Female" or "Male"
texture = StaticData.HEALTH_PANEL_TEXTURES[sexPl][limbName]
end
self:drawTexture(texture, self.healthPanel.x, self.healthPanel.y, 1, redColor, 0, 0)
-- B42, for some reason the positioning of the texture changed. Realigned it manually with those fixed values
self:drawTexture(texture, self.healthPanel.x - xMod, self.healthPanel.y - yMod, 1, redColor, 0, 0)
end
function ISHealthPanel:tryDrawProsthesis(highestAmputations, side, username)
local dc = DataController.GetInstance(username) -- TODO CACHE PROSTHESIS!!! Don't use DC here
local limbName = highestAmputations[side]
if limbName and dc:getIsProstEquipped(limbName) then
self:drawTexture(StaticData.HEALTH_PANEL_TEXTURES.ProstArm[side], self.healthPanel.x, self.healthPanel.y, 1, 1, 1, 1)
self:drawTexture(StaticData.HEALTH_PANEL_TEXTURES.ProstArm[side], self.healthPanel.x - xMod, self.healthPanel.y - yMod, 1, 1, 1, 1)
end
end
@@ -128,26 +143,6 @@ function ISHealthPanel:render()
end
local og_ISHealthPanel_update = ISHealthPanel.update
function ISHealthPanel:update()
og_ISHealthPanel_update(self)
-- TODO Listen for changes on other player side instead of looping this
-- FIX Re-enable it, just for test
if self.character then
local locPlUsername = getPlayer():getUsername()
local remPlUsername = self.character:getUsername()
if locPlUsername ~= remPlUsername and self:isReallyVisible() then
-- Request update for TOC DATA
local key = CommandsData.GetKey(remPlUsername)
--ModData.request(key)
end
end
end
-- We need to override this to force the alpha to 1
local og_ISCharacterInfoWindow_render = ISCharacterInfoWindow.prerender
function ISCharacterInfoWindow:prerender()
@@ -252,10 +247,10 @@ end
local og_ISHealthPanel_getDamagedParts = ISHealthPanel.getDamagedParts
function ISHealthPanel:getDamagedParts()
-- TODO Overriding it is a lot easier, but ew
if isReady then
-- check for imeds or if TOC is ready to display its stuff on the health panel
if isReady == false or Compat.handlers['iMeds'].isActive or Compat.handlers['iMedsFixed'].isActive then
return og_ISHealthPanel_getDamagedParts(self)
elseif isReady then
local result = {}
local bodyParts = self:getPatient():getBodyDamage():getBodyParts()
if isClient() and not self:getPatient():isLocalPlayer() then
@@ -274,8 +269,5 @@ function ISHealthPanel:getDamagedParts()
end
end
return result
else
return og_ISHealthPanel_getDamagedParts(self)
end
end

View File

@@ -1,11 +1,12 @@
local BaseHandler = require("TOC/UI/Interactions/HealthPanelBaseHandler")
local StaticData = require("TOC/StaticData")
local DataController = require("TOC/Controllers/DataController")
local ConfirmationPanel = require("TOC/UI/ConfirmationPanel")
local CutLimbAction = require("TOC/TimedActions/CutLimbAction")
---------------------
-- TODO Add interaction to cut and bandage!
--* Various functions to help during these pesky checks
@@ -13,7 +14,8 @@ local CutLimbAction = require("TOC/TimedActions/CutLimbAction")
---Check if the item type corresponds to a compatible saw
---@param itemType string
local function CheckIfSaw(itemType)
return itemType:contains(StaticData.SAWS_TYPES_IND_STR.saw) or itemType:contains(StaticData.SAWS_TYPES_IND_STR.gardenSaw)
return itemType == StaticData.SAWS_TYPES_IND_STR.saw
or itemType == StaticData.SAWS_TYPES_IND_STR.gardenSaw
end
---Return a compatible bandage
@@ -37,9 +39,8 @@ local function GetStitchesConsumableItem(player)
-- Suture needle has priority
local sutureNeedle = plInv:FindAndReturn("Base.SutureNeedle")
---@cast sutureNeedle DrainableComboItem
if sutureNeedle and sutureNeedle:getUsedDelta() > 0 then
if sutureNeedle then
return sutureNeedle
else
-- Didn't find the suture one, so let's search for the normal one + thread
@@ -61,6 +62,12 @@ local function GetStitchesConsumableItem(player)
end
local textConfirmAmp = getText("IGUI_Confirmation_Amputate")
local textAmp = getText("ContextMenu_Amputate")
local textAmpBandage = getText("ContextMenu_Amputate_Bandage")
local textAmpStitch = getText("ContextMenu_Amputate_Stitch")
local textAmpStitchBandage = getText("ContextMenu_Amputate_Stitch_Bandage")
---Add the action to the queue
---@param limbName string
---@param surgeon IsoPlayer
@@ -69,6 +76,14 @@ end
---@param stitchesItem InventoryItem?
---@param bandageItem InventoryItem?
local function PerformAction(surgeon, patient, limbName, sawItem, stitchesItem, bandageItem)
local x = (getCore():getScreenWidth() - 500) / 2
local y = getCore():getScreenHeight() / 2
ConfirmationPanel.Open(textConfirmAmp, x, y, nil, function()
-- get saw in hand
-- todo primary or secondary depending on amputation status of surgeon
ISTimedActionQueue.add(ISEquipWeaponAction:new(surgeon, sawItem, 50, true, false))
@@ -80,13 +95,13 @@ local function PerformAction(surgeon, patient, limbName, sawItem, stitchesItem,
ISTimedActionQueue.add(CutLimbAction:new(surgeon, patient, limbName, sawItem, stitchesItem, bandageItem))
end)
end
local textAmp = getText("ContextMenu_Amputate")
local textAmpBandage = getText("ContextMenu_Amputate_Bandage")
local textAmpStitch = getText("ContextMenu_Amputate_Stitch")
local textAmpStitchBandage = getText("ContextMenu_Amputate_Stitch_Bandage")
---Adds the actions to the inventory context menu
---@param player IsoPlayer
@@ -214,6 +229,18 @@ function CutLimbInteractionHandler:checkItem(item)
end
end
---@param x number
---@param y number
---@param type any
function CutLimbInteractionHandler:openConfirmation(x, y, type)
ConfirmationPanel.Open(textConfirmAmp, x, y, nil, function()
self.onMenuOptionSelected(self, type)
end)
end
---@param context ISContextMenu
function CutLimbInteractionHandler:addToMenu(context)
--TOC_DEBUG.print("CutLimbInteractionHandler addToMenu")
@@ -221,8 +248,12 @@ function CutLimbInteractionHandler:addToMenu(context)
local patientUsername = self:getPatient():getUsername()
if #types > 0 and StaticData.LIMBS_TO_BODYLOCS_IND_BPT[self.limbName] and not DataController.GetInstance(patientUsername):getIsCut(self.limbName) then
TOC_DEBUG.print("addToMenu, types > 0")
local x = (getCore():getScreenWidth() - 500) / 2
local y = getCore():getScreenHeight() / 2
for i=1, #types do
context:addOption(getText("ContextMenu_Amputate"), self, self.onMenuOptionSelected, types[i])
context:addOption(getText("ContextMenu_Amputate"), self, self.openConfirmation, x, y, types[i])
end
end
end

View File

@@ -33,7 +33,8 @@ function BaseHandler:checkItems()
local containers = ISInventoryPaneContextMenu.getContainers(self:getDoctor())
local done = {}
local childContainers = {}
for i=1,containers:size() do
if containers ~= nil then
for i=1, containers:size() do
local container = containers:get(i-1)
done[container] = true
table.wipe(childContainers)
@@ -45,6 +46,7 @@ function BaseHandler:checkItems()
end
end
end
end
end
function BaseHandler:checkContainerItems(container, childContainers)
@@ -101,7 +103,7 @@ function BaseHandler:getItemOfTag(items, type)
end
function BaseHandler:getAllItemsOfType(items, type)
local items = {}
items = {}
for _,item in ipairs(items) do
if item:getFullType() == type then
table.insert(items, item)
@@ -118,7 +120,7 @@ function BaseHandler:toPlayerInventory(item, previousAction)
if item:getContainer() ~= self:getDoctor():getInventory() then
local action = ISInventoryTransferAction:new(self:getDoctor(), item, item:getContainer(), self:getDoctor():getInventory())
ISTimedActionQueue.addAfter(previousAction, action)
-- FIXME: ISHealthPanel.actions never gets cleared
-- FIX: ISHealthPanel.actions never gets cleared
self.panel.actions = self.panel.actions or {}
self.panel.actions[action] = self.bodyPart
return action

View File

@@ -68,9 +68,10 @@ local function AddStoveContextMenu(playerNum, context, worldObjects, test)
-- Notifications, in case the player can't do the action
local isPlayerCourageous = pl:HasTrait("Brave") or pl:getPerkLevel(Perks.Strength) > 5
local isTempHighEnough = stoveObj:getCurrentTemperature() >= 250
local isPlayerCourageous = pl:hasTrait(CharacterTrait.BRAVE) or pl:hasTrait(CharacterTrait.DESENSITIZED) or pl:getPerkLevel(Perks.Strength) > 5
local isTempHighEnough = stoveObj:getCurrentTemperature()-1 >= 2.50
local isLimbFree = not dcInst:getIsProstEquipped(limbName)
TOC_DEBUG.print(stoveObj:getCurrentTemperature())
option.notAvailable = not(isPlayerCourageous and isTempHighEnough and isLimbFree)
if not isTempHighEnough then

View File

@@ -0,0 +1,157 @@
require "lua_timers"
local ItemsController = require("TOC/Controllers/ItemsController")
local StaticData = require("TOC/StaticData")
local CommandsData = require("TOC/CommandsData")
-------------------------------
---@param zombie IsoZombie|IsoGameCharacter|IsoMovingObject|IsoObject
---@return integer trueID
local function GetZombieID(zombie)
-- Big love to Chuck and Sir Doggy Jvla for this code
---@diagnostic disable-next-line: param-type-mismatch
local pID = zombie:getPersistentOutfitID()
local bits = string.split(string.reverse(Long.toUnsignedString(pID, 2)), "")
while #bits < 16 do bits[#bits + 1] = 0 end
-- trueID
bits[16] = 0
local trueID = Long.parseUnsignedLong(string.reverse(table.concat(bits, "")), 2)
return trueID
end
-------------------------------
---@param item InventoryItem
local function PredicateAmputationItems(item)
return item:getType():contains("Amputation_")
end
---@param item InventoryItem
local function PredicateAmputationItemLeft(item)
return item:getType():contains("Amputation_") and item:getType():contains("_L")
end
---@param item InventoryItem
local function PredicateAmputationItemRight(item)
return item:getType():contains("Amputation_") and item:getType():contains("_R")
end
---@param zombie IsoZombie
local function SpawnAmputation(zombie, side)
local index = ZombRand(1, #StaticData.PARTS_STR)
local limb = StaticData.PARTS_STR[index] .. "_" .. side
local amputationFullType = StaticData.AMPUTATION_CLOTHING_ITEM_BASE .. limb
ItemsController.Zombie.SpawnAmputationItem(zombie, amputationFullType)
-- Add reference and transmit it to server
local pID = GetZombieID(zombie)
local zombieKey = CommandsData.GetZombieKey()
local zombiesMD = ModData.getOrCreate(zombieKey)
if zombiesMD[pID] == nil then zombiesMD[pID] = {} end
zombiesMD[pID][side] = amputationFullType
ModData.add(zombieKey, zombiesMD)
ModData.transmit(zombieKey)
end
-------------------------------
local bloodAmount = 10
---@param player IsoGameCharacter
---@param zombie IsoZombie
---@param handWeapon HandWeapon
local function HandleZombiesAmputations(player, zombie, handWeapon, damage)
if not SandboxVars.TOC.EnableZombieAmputations then return end
if not instanceof(zombie, "IsoZombie") or not instanceof(player, "IsoPlayer") then return end
if player ~= getPlayer() then return end
-- Check type of weapon. No hands, only knifes or such
local weaponCategories = handWeapon:getScriptItem():getCategories()
if not (weaponCategories:contains("Axe") or weaponCategories:contains("LongBlade")) then return end
local isCrit = player:isCriticalHit()
local randomChance = ZombRand(0, 100) > (100 - SandboxVars.TOC.ZombieAmputationDamageChance)
if (damage > SandboxVars.TOC.ZombieAmputationDamageThreshold and randomChance) or isCrit then
TOC_DEBUG.print("Amputating zombie limbs - damage: " .. tostring(damage))
local zombieInv = zombie:getInventory()
-- Check left or right
local randSide = ZombRand(2) -- Random side
local preferredSide = randSide == 0 and "L" or "R"
local alternateSide = preferredSide == "L" and "R" or "L"
local predicatePreferred = preferredSide == "L" and PredicateAmputationItemLeft or PredicateAmputationItemRight
local predicateAlternate = alternateSide == "L" and PredicateAmputationItemLeft or PredicateAmputationItemRight
if not zombieInv:containsEval(predicatePreferred) then
SpawnAmputation(zombie, preferredSide)
elseif not zombieInv:containsEval(predicateAlternate) then
SpawnAmputation(zombie, alternateSide)
end
TOC_DEBUG.print("Amputating zombie limbs - damage: " .. tostring(damage) .. ", preferred limb side: " .. preferredSide)
-- add blood splat every couple of seconds for a while
addBloodSplat(getCell():getGridSquare(zombie:getX(), zombie:getY(), zombie:getZ()), bloodAmount)
local timerName = tostring(GetZombieID(zombie)) .. "_timer"
timer:Create(timerName, 1, 10, function()
addBloodSplat(getCell():getGridSquare(zombie:getX(), zombie:getY(), zombie:getZ()), bloodAmount)
end)
end
end
Events.OnWeaponHitCharacter.Add(HandleZombiesAmputations)
-----------------------------
local localOnlyZombiesMD
local function SetupZombiesModData()
if not SandboxVars.TOC.EnableZombieAmputations then return end
local zombieKey = CommandsData.GetZombieKey()
localOnlyZombiesMD = ModData.getOrCreate(zombieKey)
end
Events.OnInitGlobalModData.Add(SetupZombiesModData)
---@param zombie IsoZombie
local function ReapplyAmputation(zombie)
if not SandboxVars.TOC.EnableZombieAmputations then return end
local pID = GetZombieID(zombie)
if localOnlyZombiesMD[pID] ~= nil then
-- check if zombie has amputation
local zombiesAmpData = localOnlyZombiesMD[pID]
local zombieInv = zombie:getInventory()
local foundItem = zombieInv:containsEvalRecurse(PredicateAmputationItems)
if foundItem then
return
else
local leftAmp = zombiesAmpData['L']
if leftAmp then
ItemsController.Zombie.SpawnAmputationItem(zombie, leftAmp)
end
local rightAmp = zombiesAmpData['R']
if rightAmp then
ItemsController.Zombie.SpawnAmputationItem(zombie, rightAmp)
end
-- Removes reference, local only
localOnlyZombiesMD[pID] = nil
end
end
end
Events.OnZombieUpdate.Add(ReapplyAmputation)

View File

@@ -1,5 +1,9 @@
-- TODO Should be server side in 42.13
local StaticData = require("TOC/StaticData")
local CommonMethods = require("TOC/CommonMethods")
local CommandsData = require("TOC/CommandsData")
---------------------------
--- Submodule to handle spawning the correct items after certain actions (ie: cutting a hand). LOCAL ONLY!
@@ -20,7 +24,8 @@ function ItemsController.Player.GetAmputationTexturesIndex(playerObj, isCicatriz
local textureString = playerObj:getHumanVisual():getSkinTexture()
local isHairy = textureString:sub(-1) == "a"
local matchedIndex = tonumber(textureString:match("%d$")) or 0
local matchedIndex = tonumber(textureString:match("%d%d")) -- it must always be at least 1
TOC_DEBUG.print("Texture string: " .. tostring(textureString))
if isHairy then
matchedIndex = matchedIndex + 5
@@ -30,7 +35,7 @@ function ItemsController.Player.GetAmputationTexturesIndex(playerObj, isCicatriz
matchedIndex = matchedIndex + (isHairy and 5 or 10) -- We add 5 is it's the texture, else 10
end
TOC_DEBUG.print("isCicatrized= " .. tostring(isCicatrized))
TOC_DEBUG.print("isCicatrized = " .. tostring(isCicatrized))
TOC_DEBUG.print("Amputation Texture Index: " .. tostring(matchedIndex))
return matchedIndex - 1
end
@@ -46,6 +51,8 @@ function ItemsController.Player.RemoveClothingItem(playerObj, clothingItem)
---@diagnostic disable-next-line: param-type-mismatch
playerObj:getInventory():Remove(clothingItem) -- Umbrella is wrong, can be an InventoryItem too
sendRemoveItemFromContainer(playerObj:getInventory(), clothingItem)
TOC_DEBUG.print("found and deleted" .. tostring(clothingItem))
-- Reset model
@@ -77,23 +84,22 @@ end
---Deletes all the old amputation items, used for resets
---@param playerObj IsoPlayer
function ItemsController.Player.DeleteAllOldAmputationItems(playerObj)
-- TODO Fix visual bug
-- This part is a workaround for a pretty shitty implementation on the java side. Check ProsthesisHandler for more infos
local group = BodyLocations.getGroup("Human")
group:setMultiItem("TOC_Arm", false)
group:setMultiItem("TOC_ArmProst", false)
-- local group = BodyLocations.getGroup("Human")
-- group:setMultiItem("TOC_Arm", false)
-- group:setMultiItem("TOC_ArmProst", false)
for i = 1, #StaticData.LIMBS_STR do
local limbName = StaticData.LIMBS_STR[i]
-- TODO Won't work with dedicated clothingItems for multi amps
local clothItemName = StaticData.AMPUTATION_CLOTHING_ITEM_BASE .. limbName
local clothItem = playerObj:getInventory():FindAndReturn(clothItemName)
---@cast clothItem InventoryItem
ItemsController.Player.RemoveClothingItem(playerObj, clothItem)
end
-- Reset model just in case
playerObj:resetModel()
group:setMultiItem("TOC_Arm", true)
group:setMultiItem("TOC_ArmProst", true)
end
---Spawns and equips the correct amputation item to the player.
@@ -101,12 +107,15 @@ end
---@param limbName string
function ItemsController.Player.SpawnAmputationItem(playerObj, limbName)
TOC_DEBUG.print("clothing name " .. StaticData.AMPUTATION_CLOTHING_ITEM_BASE .. limbName)
local clothingItem = playerObj:getInventory():AddItem(StaticData.AMPUTATION_CLOTHING_ITEM_BASE .. limbName)
local itemName = StaticData.AMPUTATION_CLOTHING_ITEM_BASE .. limbName
local clothingItem = playerObj:getInventory():AddItem(itemName)
local texId = ItemsController.Player.GetAmputationTexturesIndex(playerObj, false)
---@cast clothingItem InventoryItem
clothingItem:getVisual():setTextureChoice(texId) -- it counts from 0, so we have to subtract 1
playerObj:setWornItem(clothingItem:getBodyLocation(), clothingItem)
sendAddItemToContainer(playerObj:getInventory(), clothingItem)
sendServerCommand(playerObj, CommandsData.modules.TOC_RELAY, CommandsData.client.Relay.ReceiveWearAmputation, {itemName = itemName, texId = texId})
end
---Search through worn items and modifies a specific amputation item
@@ -154,6 +163,9 @@ function ItemsController.Zombie.SpawnAmputationItem(zombie, amputationFullType)
-- Spawn the item too in the inventory to keep track of stuff this way. It's gonna get deleted when we reload the game
local zombieInv = zombie:getInventory()
zombieInv:AddItem(amputationFullType)
-- TODO Remove objects in that part of the body to prevent items floating in mid air
end
function ItemsController.Zombie.GetAmputationTexturesIndex(zombie)

View File

@@ -3,14 +3,9 @@ local StaticData = require("TOC/StaticData")
local CommandsData = require("TOC/CommandsData")
------------------------
local ServerDataHandler = {}
ServerDataHandler.modData = {}
---Get the server mod data table containing that player TOC data
---@param key string
---@return tocModDataType
@@ -29,8 +24,6 @@ function ServerDataHandler.AddTable(key, table)
--TOC_DEBUG.printTable(table)
-- Set that the data has been modified and it's updated on the server
table.isUpdateFromServer = true -- FIX this is useless as of now
ModData.add(key, table) -- Add it to the server mod data
ServerDataHandler.modData[key] = table

View File

@@ -0,0 +1,44 @@
require ("TOC/Debug")
local CommandsData = require("TOC/CommandsData")
local ItemsController = require("TOC/Controllers/ItemsController")
--------------------------------------------
local ServerItemsCommands = {}
function ServerItemsCommands.SpawnAmputationItem(_, args)
local playerObj = getPlayerByOnlineID(args.playerNum)
local limbName = args.limbName
ItemsController.Player.SpawnAmputationItem(playerObj, limbName)
end
function ServerItemsCommands.DeleteOldAmputationItem(_, args)
local patientPl = getPlayerByOnlineID(args.playerNum)
local limbName = args.limbName
ItemsController.Player.DeleteOldAmputationItem(patientPl, limbName)
end
function ServerItemsCommands.DeleteAllOldAmputationItems(_, args)
local playerObj = getPlayerByOnlineID(args.playerNum)
ItemsController.Player.DeleteAllOldAmputationItems(playerObj)
end
function ServerItemsCommands.OverrideAmputationItemVisuals(_, args)
local playerObj = getPlayerByOnlineID(args.playerNum)
local limbName = args.limbName
local isCicatrized = args.isCicatrized
ItemsController.Player.OverrideAmputationItemVisuals(playerObj, limbName, isCicatrized)
end
--------------------------------------------------------------------
local function OnClientItemsCommands(module, command, playerObj, args)
if module == CommandsData.modules.TOC_ITEMS and ServerItemsCommands[command] then
TOC_DEBUG.print("Received ItemsController command - " .. tostring(command))
ServerItemsCommands[command](playerObj, args)
end
end
Events.OnClientCommand.Add(OnClientItemsCommands)

View File

@@ -21,10 +21,10 @@ end
---@param args relayExecuteAmputationActionParams
function ServerRelayCommands.RelayExecuteAmputationAction(surgeonPl, args)
local patientPl = getPlayerByOnlineID(args.patientNum)
local surgeonNum = surgeonPl:getOnlineID()
local surgeonNum = surgeonPl:getPlayerNum()
---@type receiveDamageDuringAmputationParams
local params = {surgeonNum = surgeonNum, limbName = args.limbName}
local params = {surgeonNum = surgeonNum, limbName = args.limbName, damagePlayer = true}
sendServerCommand(patientPl, CommandsData.modules.TOC_RELAY, CommandsData.client.Relay.ReceiveExecuteAmputationAction, params)
end
@@ -38,7 +38,26 @@ function ServerRelayCommands.RelayExecuteInitialization(adminObj, args)
end
---Relay a forced amputation to another client.
---@param adminObj IsoPlayer
---@param args relayForcedAmputationParams
function ServerRelayCommands.RelayForcedAmputation(adminObj, args)
local patientPl = getPlayerByOnlineID(args.patientNum)
local adminNum = adminObj:getPlayerNum()
---@type receiveDamageDuringAmputationParams
local ampParams = {surgeonNum = adminNum, limbName = args.limbName, damagePlayer = false} -- the only difference between relayExecuteAmputationAction and this is the damage
sendServerCommand(patientPl, CommandsData.modules.TOC_RELAY, CommandsData.client.Relay.ReceiveExecuteAmputationAction, ampParams)
-- Automatic cicatrization
sendServerCommand(patientPl, CommandsData.modules.TOC_RELAY, CommandsData.client.Relay.ReceiveForcedCicatrization, {limbName = args.limbName})
end
function ServerRelayCommands.DeleteAllOldAmputationItems(_, args)
local playerObj = getPlayerByOnlineID(args.playerNum)
local ItemsController = require("TOC/Controllers/ItemsController")
ItemsController.Player.DeleteAllOldAmputationItems(playerObj)
end
-------------------------

View File

@@ -0,0 +1,109 @@
--Based on RabenRabo's bodylocation solution from their mod "Fantasy Bodyparts" and "Fantasy Legs" sub-mod.
--Modified by GanydeBielovzki with permission for batch use for the Frockin' Splendor franchise and spin-offs.
--To copy, further modify or otherwise use this code the original creator and the modifier must be credited.
local function copyBodyLocationProperties(oldGroup, oldLocID, newGroup)
for k = 0, oldGroup:size()-1 do
local otherLocID = oldGroup:getLocationByIndex(k):getId()
if oldGroup:isExclusive(oldLocID, otherLocID)
then
newGroup:setExclusive(oldLocID, otherLocID)
end
if oldGroup:isHideModel(oldLocID, otherLocID)
then
newGroup:setHideModel(oldLocID, otherLocID)
end
if oldGroup:isAltModel(oldLocID, otherLocID)
then
newGroup:setAltModel(oldLocID, otherLocID)
end
end
end
local function addBodyLocationsAt(groupName, locationList)
local results = {}
-- get list (!!actually a view!!) of all groups and copy to array (BodyLocations.reset() will also clear the view)
local allGroupsList = BodyLocations.getAllGroups()
local allGroups = {}
for i = 0, allGroupsList:size()-1 do
allGroups[i + 1] = allGroupsList:get(i)
end
BodyLocations.reset()
-- recreate all groups/bodylocations and insert new bodylocations
for i = 1, #allGroups do
local oldGroup = allGroups[i]
local newGroup = BodyLocations.getGroup(oldGroup:getId())
-- FIRST: Process all original locations AND insert new ones at correct positions
for j = 0, oldGroup:size()-1 do
local oldLoc = oldGroup:getLocationByIndex(j)
local oldLocID = oldLoc:getId()
-- For each location definition, check if it should be inserted here
for _, locDef in ipairs(locationList) do
if oldGroup:getId() == groupName then
local newLocID = type(locDef.name) ~= "string" and locDef.name or
ItemBodyLocation.get(ResourceLocation.of(locDef.name))
local refLocID = type(locDef.reference) ~= "string" and locDef.reference or
ResourceLocation.of(locDef.reference)
local isTargetGroupAndLoc = refLocID == oldLocID
if isTargetGroupAndLoc and locDef.before then
results[locDef.name] = newGroup:getOrCreateLocation(newLocID)
end
end
end
-- Add the original location
newGroup:getOrCreateLocation(oldLocID)
-- Check for "after" insertions
for _, locDef in ipairs(locationList) do
if oldGroup:getId() == groupName then
local newLocID = type(locDef.name) ~= "string" and locDef.name or
ItemBodyLocation.get(ResourceLocation.of(locDef.name))
local refLocID = type(locDef.reference) ~= "string" and locDef.reference or
ResourceLocation.of(locDef.reference)
local isTargetGroupAndLoc = refLocID == oldLocID
if isTargetGroupAndLoc and not locDef.before then
results[locDef.name] = newGroup:getOrCreateLocation(newLocID)
end
end
end
end
-- SECOND: copy bodylocation properties from old groups to new groups
for j = 0, oldGroup:size()-1 do
local oldLocID = oldGroup:getLocationByIndex(j):getId()
newGroup:setMultiItem(oldLocID, oldGroup:isMultiItem(oldLocID))
copyBodyLocationProperties(oldGroup, oldLocID, newGroup)
end
end
return results
end
local results = addBodyLocationsAt("Human", {
{name = "toc:Arm_L", reference = ItemBodyLocation.FULL_TOP, before = false},
{name = "toc:Arm_R", reference = ItemBodyLocation.FULL_TOP, before = false},
{name = "toc:ArmProst_L", reference = ItemBodyLocation.FULL_TOP, before = false},
{name = "toc:ArmProst_R", reference = ItemBodyLocation.FULL_TOP, before = false},
{name = "toc:ArmAccessory_L", reference = ItemBodyLocation.FULL_TOP, before = false},
{name = "toc:ArmAccessory_R", reference = ItemBodyLocation.FULL_TOP, before = false},
})
results['toc:Arm_L']:setMultiItem(true)
results['toc:Arm_R']:setMultiItem(true)
results['toc:ArmProst_L']:setMultiItem(true)
results['toc:ArmProst_R']:setMultiItem(true)
results['toc:ArmAccessory_L']:setMultiItem(true)
results['toc:ArmAccessory_R']:setMultiItem(true)

View File

@@ -5,20 +5,22 @@ local CommandsData = {}
CommandsData.modules = {
TOC_DEBUG = "TOC_DEBUG",
TOC_RELAY = "TOC_RELAY"
TOC_RELAY = "TOC_RELAY",
TOC_ITEMS = "TOC_ITEMS"
}
CommandsData.client = {
Relay = {
ReceiveDamageDuringAmputation = "ReceiveDamageDuringAmputation", ---@alias receiveDamageDuringAmputationParams { limbName : string}
ReceiveExecuteAmputationAction = "ReceiveExecuteAmputationAction", ---@alias receiveExecuteAmputationActionParams {surgeonNum : number, limbName : string}
ReceiveExecuteAmputationAction = "ReceiveExecuteAmputationAction", ---@alias receiveExecuteAmputationActionParams {surgeonNum : number, limbName : string, damagePlayer : boolean}
--* APPLY *--
ReceiveApplyFromServer = "ReceiveApplyFromServer",
ReceiveWearAmputation = "ReceiveWearAmputation",
--* ADMIN ONLY --*
ReceiveExecuteInitialization = "ReceiveExecuteInitialization"
ReceiveExecuteInitialization = "ReceiveExecuteInitialization",
ReceiveForcedCicatrization = "ReceiveForcedCicatrization" ---@alias receiveForcedCicatrizationParams {limbName : string}
}
}
@@ -31,8 +33,10 @@ CommandsData.server = {
Relay = {
RelayDamageDuringAmputation = "RelayDamageDuringAmputation", ---@alias relayDamageDuringAmputationParams {patientNum : number, limbName : string}
RelayExecuteAmputationAction = "RelayExecuteAmputationAction", ---@alias relayExecuteAmputationActionParams {patientNum : number, limbName : string}
--* ADMIN ONLY *--
RelayExecuteInitialization = "RelayExecuteInitialization" ---@alias relayExecuteInitializationParams {patientNum : number}
RelayExecuteInitialization = "RelayExecuteInitialization", ---@alias relayExecuteInitializationParams {patientNum : number}
RelayForcedAmputation = "RelayForcedAmputation" ---@alias relayForcedAmputationParams {patientNum : number, limbName : string}
}
}

View File

@@ -13,10 +13,12 @@ end
---Print debug
---@param string string
function TOC_DEBUG.print(string)
--if isDebugEnabled() then
if isDebugEnabled() then
local runningFile = TOC_DEBUG.getRunningFile()
print("[TOC]" .. "[" .. runningFile .. "] " .. tostring(string))
--end
else
print(string)
end
end
---Horrendous but I don't really care about performance for this

View File

@@ -0,0 +1,31 @@
-- instead of relying on local to save og methods, we save them in a table here that we can use later.
---@class OverridenMethodsArchive
local OverridenMethodsArchive = {}
OverridenMethodsArchive.methods = {}
-- Save an original method, if it wasn't already saved and returns it to be used in common
function OverridenMethodsArchive.Save(methodName, method)
if not OverridenMethodsArchive.methods[methodName] then
OverridenMethodsArchive.methods[methodName] = method
TOC_DEBUG.print("Saved method " .. methodName)
end
return method
end
-- Get the original method
function OverridenMethodsArchive.Get(methodName)
--TOC_DEBUG.print("Getting og method " .. methodName)
--TOC_DEBUG.print("OverridenMethodsArchive.list[methodName] = " .. tostring(OverridenMethodsArchive.methods[methodName]))
--TOC_DEBUG.print(methodName)
--TOC_DEBUG.print(OverridenMethodsArchive.methods[methodName])
return OverridenMethodsArchive.methods[methodName]
end
return OverridenMethodsArchive

View File

@@ -0,0 +1 @@
return _TOCRegistries

View File

@@ -2,10 +2,9 @@
---@alias limbsTable {Hand_L : partDataType, ForeArm_L : partDataType, UpperArm_L : partDataType, Hand_R : partDataType, ForeArm_R : partDataType, UpperArm_R : partDataType }
---@alias prosthesisData {isProstEquipped : boolean, prostFactor : number }
---@alias prosthesesTable {Top_L : prosthesisData, Top_R : prosthesisData } -- TODO add Bottom_L and Bottom_R
---@alias tocModDataType { limbs : limbsTable, prostheses : prosthesesTable, isIgnoredPartInfected : boolean, isAnyLimbCut : boolean, isUpdateFromServer : boolean, isInitializing : boolean}
---@alias tocModDataType { limbs : limbsTable, prostheses : prosthesesTable, isIgnoredPartInfected : boolean, isAnyLimbCut : boolean}
---------------------------
-- _STR = Only strings, no index
-- _IND_STR = indexed Strings
-- _IND_BPT = Indexed BodyPartType
@@ -21,6 +20,10 @@ local StaticData = {}
---Mod name, used to setup Global Mod Data and various stuff
StaticData.MOD_NAME = "TOC"
-- Game version, used to correct some stuff instead of relying on versioned folders
StaticData.COMPAT_42 = luautils.stringStarts(getGameVersion(), "42")
-------------------------
--* Base
@@ -46,12 +49,6 @@ StaticData.PARTS_STR = {
}
StaticData.MOD_BODYLOCS_BASE_IND_STR = {
TOC_ArmProst = "TOC_ArmProst",
TOC_LegProst = "TOC_LegProst",
TOC_Arm = "TOC_Arm",
}
-- No "MAX" here.
StaticData.IGNORED_BODYLOCS_BPT = {
BodyPartType.Foot_L, BodyPartType.Foot_R, BodyPartType.Groin, BodyPartType.Head,
@@ -145,6 +142,7 @@ StaticData.AMP_GROUPS_BASE_IND_STR = {
Bottom = "Bottom"
}
-- FIX This should be aligned with the body locs, no reason anymore to keep it separated
StaticData.AMP_GROUPS_IND_STR = {}
StaticData.AMP_GROUPS_STR = {}
@@ -185,8 +183,8 @@ end
StaticData.TOURNIQUET_BODYLOCS_TO_GROUPS_IND_STR = {
["HandsLeft"] = StaticData.AMP_GROUPS_IND_STR.Top_L,
["HandsRight"] = StaticData.AMP_GROUPS_IND_STR.Top_R
[ItemBodyLocation.HANDS_LEFT] = StaticData.AMP_GROUPS_IND_STR.Top_L,
[ItemBodyLocation.HANDS_RIGHT] = StaticData.AMP_GROUPS_IND_STR.Top_R
}
@@ -234,7 +232,7 @@ end
StaticData.TRAITS_BP = {
Amputee_Hand = "Hand_L",
Amputee_ForeArm = "ForeArm_L",
Amputee_UpperArm = "UpperArm_L"
Amputee_UpperArm = "UpperArm_L",
}
-----------------
@@ -276,8 +274,17 @@ StaticData.AMPUTATION_CLOTHING_ITEM_BASE = "TOC.Amputation_"
------------------
--* Items check
local sawObj = InventoryItemFactory.CreateItem("Base.Saw")
local gardenSawObj = InventoryItemFactory.CreateItem("Base.GardenSaw")
local sawObj
local gardenSawObj
if StaticData.COMPAT_42 then
sawObj = instanceItem("Base.Saw")
gardenSawObj = instanceItem("Base.GardenSaw")
else
sawObj = InventoryItemFactory.CreateItem("Base.Saw")
gardenSawObj = InventoryItemFactory.CreateItem("Base.GardenSaw")
end
StaticData.SAWS_NAMES_IND_STR = {
saw = sawObj:getName(),

View File

@@ -1,4 +1,7 @@
IG_UI_DE = {
IGUI_Yes = "Ja",
IGUI_No = "Nein",
IGUI_perks_Amputations = "Amputationen",
IGUI_perks_Side_R = "Rechte Seite",
IGUI_perks_Side_L = "Linke Seite",

View File

@@ -1,9 +1,14 @@
IG_UI_EN = {
IGUI_Yes = "Yes",
IGUI_No = "No",
IGUI_perks_Amputations = "Amputations",
IGUI_perks_Side_R = "Right Side",
IGUI_perks_Right Side_Description = "Familiarity with amputations on the right side of your body",
IGUI_perks_Side_L = "Left Side",
IGUI_perks_Prosthesis = "Prosthesis",
IGUI_perks_ProstFamiliarity= "Familiarity",
IGUI_perks_Left Side_Description = "Familiarity with amputations on the left side of your body",
IGUI_perks_Prosthesis = "Prosthesis Familiarity",
IGUI_perks_Prosthesis Familiarity_Description = "Familiarity with prosthetic limbs",
IGUI_ItemCat_Prosthesis = "Prosthesis",
IGUI_ItemCat_Surgery = "Surgery",
@@ -15,4 +20,6 @@ IG_UI_EN = {
IGUI_HealthPanel_WoundDirtyness = "Wound Dirtyness",
IGUI_HealthPanel_ProstEquipped = "Prosthesis Equipped",
IGUI_Confirmation_Amputate = " <CENTRE> Do you really want to amputate that limb?"
}

View File

@@ -3,5 +3,8 @@ Sandbox_EN = {
Sandbox_TOC_CicatrizationSpeed = "Cicatrization Speed",
Sandbox_TOC_WoundDirtynessMultiplier = "Wound Dirtyness Multiplier",
Sandbox_TOC_SurgeonAbilityImportance = "Relevance of surgeon doctor ability",
Sandbox_TOC_EnableZombieAmputations = "Enable Zombie amputations",
Sandbox_TOC_ZombieAmputationDamageThreshold = "Zombie amputations damage treshold",
Sandbox_TOC_ZombieAmputationDamageChance = "Zombie amputations damage chance",
}

View File

@@ -0,0 +1,29 @@
ContextMenu_FR = {
ContextMenu_Amputate = "Amputer",
ContextMenu_Amputate_Bandage = "Amputer et bander",
ContextMenu_Amputate_Stitch = "Amputer et suturer",
ContextMenu_Amputate_Stitch_Bandage = "Amputer, suturer et bander",
ContextMenu_Cauterize = "Cautériser",
ContextMenu_Limb_Hand_L = "Main gauche",
ContextMenu_Limb_ForeArm_L = "Avant-bras gauche",
ContextMenu_Limb_UpperArm_L = "Bras supérieur gauche",
ContextMenu_Limb_Hand_R = "Main droite",
ContextMenu_Limb_ForeArm_R = "Avant-bras droit",
ContextMenu_Limb_UpperArm_R = "Bras supérieur droit",
ContextMenu_InstallProstRight = "Installer une prothèse sur le bras droit",
ContextMenu_InstallProstLeft = "Installer une prothèse sur le bras gauche",
ContextMenu_PutTourniquetArmLeft = "Mettre un garrot sur le bras gauche",
ContextMenu_PutTourniquetLegL = "Mettre un garrot sur la jambe gauche",
ContextMenu_PutTourniquetArmRight = "Mettre un garrot sur le bras droit",
ContextMenu_PutTourniquetLegR = "Mettre un garrot sur la jambe droite",
ContextMenu_CleanWound = "Nettoyer la plaie",
ContextMenu_Admin_TOC = "TOC",
ContextMenu_Admin_ResetTOC = "Réinitialiser les amputations",
ContextMenu_Admin_ForceAmputation = "Forcer l'amputation",
}

View File

@@ -0,0 +1,21 @@
IG_UI_FR = {
IGUI_Yes = "Oui",
IGUI_No = "Non",
IGUI_perks_Amputations = "Amputations",
IGUI_perks_Side_R = "Côté droit",
IGUI_perks_Side_L = "Côté gauche",
IGUI_perks_Prosthesis = "Prothèse",
IGUI_perks_ProstFamiliarity = "Familiarité",
IGUI_ItemCat_Prosthesis = "Prothèse",
IGUI_ItemCat_Surgery = "Chirurgie",
IGUI_ItemCat_Amputation = "Amputation",
IGUI_HealthPanel_Cicatrization = "Cicatrisation",
IGUI_HealthPanel_Cicatrized = "Cicatrisé",
IGUI_HealthPanel_Cauterized = "Cautérisé",
IGUI_HealthPanel_WoundDirtyness = "Saleté de la plaie",
IGUI_HealthPanel_ProstEquipped = "Prothèse équipée",
}

View File

@@ -0,0 +1,11 @@
ItemName_FR = {
ItemName_TOC.Surg_Arm_Tourniquet_L = "Garrot",
ItemName_TOC.Surg_Arm_Tourniquet_R = "Garrot",
ItemName_TOC.Prost_NormalArm_L = "Bras prothétique",
ItemName_TOC.Prost_NormalArm_R = "Bras prothétique",
ItemName_TOC.Prost_HookArm_L = "Bras prothétique - Crochet",
ItemName_TOC.Prost_HookArm_R = "Bras prothétique - Crochet",
}

View File

@@ -0,0 +1,5 @@
Recipes_FR = {
Recipe_Craft_Prosthetic_Arm = "Fabriquer un bras prothétique",
Recipe_Craft_Prosthetic_Hook = "Fabriquer un crochet prothétique",
}

View File

@@ -0,0 +1,10 @@
Sandbox_FR = {
Sandbox_TOC = "Le Seul Remède",
Sandbox_TOC_CicatrizationSpeed = "Vitesse de cicatrisation",
Sandbox_TOC_WoundDirtynessMultiplier = "Multiplicateur de saleté de la plaie",
Sandbox_TOC_SurgeonAbilityImportance = "Importance de la compétence du chirurgien",
Sandbox_TOC_EnableZombieAmputations = "Activer les amputations de zombies",
Sandbox_TOC_ZombieAmputationDamageThreshold = "Seuil de dégâts pour amputations de zombies",
Sandbox_TOC_ZombieAmputationDamageChance = "Probabilité d'amputations de zombies",
}

View File

@@ -0,0 +1,10 @@
Tooltip_FR = {
Tooltip_Surgery_CantCauterize = "Vous ne pouvez pas cautériser la plaie",
Tooltip_Surgery_And = " et ",
Tooltip_Surgery_TempTooLow = "La température est encore trop basse",
Tooltip_Surgery_Coward = "Vous n'avez pas le courage de le faire",
Tooltip_Surgery_LimbNotFree = "Vous devez d'abord retirer la prothése",
}

View File

@@ -0,0 +1,16 @@
UI_FR = {
UI_trait_Amputee_Hand = "Main gauche amputée",
UI_trait_Amputee_Hand_desc = "",
UI_trait_Amputee_ForeArm = "Avant-bras gauche amputée",
UI_trait_Amputee_ForeArm_desc = "",
UI_trait_Amputee_UpperArm = "Bras supérieur gauche amputée",
UI_trait_Amputee_UpperArm_desc = "",
UI_trait_Insensitive = "Insensible",
UI_trait_Insensitive_desc = "",
UI_Say_CantEquip = "Je ne peux pas l'équiper comme ça..."
}

View File

@@ -1,4 +1,7 @@
IG_UI_IT = {
IGUI_Yes = "Si",
IGUI_No = "No",
IGUI_perks_Amputations = "Amputazioni",
IGUI_perks_Side_R = "Parte destra",
IGUI_perks_Side_L = "Parte sinistra",

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,33 @@
ContextMenu_RU = {
ContextMenu_Amputate = "Ампутировать",
ContextMenu_Amputate_Bandage = "Ампутировать и перевязать",
ContextMenu_Amputate_Stitch = "Ампутировать и наложить швы",
ContextMenu_Amputate_Stitch_Bandage = "Ампутировать, наложить швы и перевязать",
ContextMenu_Cauterize = "Прижечь",
ContextMenu_Limb_Hand_L = "Левая рука",
ContextMenu_Limb_ForeArm_L = "Левая предплечье",
ContextMenu_Limb_UpperArm_L = "Левое плечо"
ContextMenu_Limb_Hand_R = "Правая рука",
ContextMenu_Limb_ForeArm_R = "Правая предплечье",
ContextMenu_Limb_UpperArm_R = "Правая плечо",
ContextMenu_InstallProstRight = "Установить протез на правую руку",
ContextMenu_InstallProstLeft = "Установить протез на левую руку",
ContextMenu_PutTourniquetArmLeft = "Наложить жгут на левую руку",
ContextMenu_PutTourniquetLegL = "Наложить жгут на левую ногу",
ContextMenu_PutTourniquetArmRight = "Наложить жгут на правую руку",
ContextMenu_PutTourniquetLegR = "Наложить жгут на правую ногу",
ContextMenu_CleanWound = "Очистить рану",
ContextMenu_Admin_TOC = "TOC",
ContextMenu_Admin_ResetTOC = "Сбросить ампутации",
ContextMenu_Admin_ForceAmputation = "Моментально ампутировать",
}

View File

@@ -0,0 +1,18 @@
IG_UI_RU = {
IGUI_perks_Amputations = "Ампутации",
IGUI_perks_Side_R = "Правая сторона",
IGUI_perks_Side_L = "Левая сторона",
IGUI_perks_Prosthesis = "Протез",
IGUI_perks_ProstFamiliarity= "Приспособленность",
IGUI_ItemCat_Prosthesis = "Протез",
IGUI_ItemCat_Surgery = "Хирургия",
IGUI_ItemCat_Amputation = "Ампутация"
IGUI_HealthPanel_Cicatrization = "Заживление",
IGUI_HealthPanel_Cicatrized = "Заживлено",
IGUI_HealthPanel_Cauterized = "Прижженно",
IGUI_HealthPanel_WoundDirtyness = "Загрезнённая рана",
IGUI_HealthPanel_ProstEquipped = "Протез экипирован",
}

View File

@@ -0,0 +1,11 @@
ItemName_RU = {
ItemName_TOC.Surg_Arm_Tourniquet_L = "Жгут",
ItemName_TOC.Surg_Arm_Tourniquet_R = "Жгут",
ItemName_TOC.Prost_NormalArm_L = "Протез руки",
ItemName_TOC.Prost_NormalArm_R = "Протез руки",
ItemName_TOC.Prost_HookArm_L = "Протез руки - Крюк",
ItemName_TOC.Prost_HookArm_R = "Протез руки - Крюк",
}

View File

@@ -0,0 +1,4 @@
Recipes_RU = {
Recipe_Craft_Prosthetic_Arm = "Изготовить протез руки",
Recipe_Craft_Prosthetic_Hook = "Изготовить протез ввиде крючка",
}

View File

@@ -0,0 +1,7 @@
Sandbox_RU = {
Sandbox_TOC = "Спасенье в Отсечении",
Sandbox_TOC_CicatrizationSpeed = "Скорость заживления",
Sandbox_TOC_WoundDirtynessMultiplier = "Множитель загрязнения ран",
Sandbox_TOC_SurgeonAbilityImportance = "Значимость способностей врача-хирурга",
}

View File

@@ -0,0 +1,10 @@
Tooltip_RU = {
Tooltip_Surgery_CantCauterize = "Нельзя прижигать рану",
Tooltip_Surgery_And = " и "
Tooltip_Surgery_TempTooLow = "Температура все еще слишком низкая",
Tooltip_Surgery_Coward = "У тебя не хватит смелости сделать это",
Tooltip_Surgery_LimbNotFree = "Сначала нужно снять протез",
}

View File

@@ -0,0 +1,16 @@
UI_RU = {
UI_trait_Amputee_Hand = "Ампутированная левая рука",
UI_trait_Amputee_Hand_desc = "Вы начинаете с ампутированной левой рукой.",
UI_trait_Amputee_ForeArm = "Ампутированное левое предплечье",
UI_trait_Amputee_ForeArm_desc = "Вы начинаете с ампутированным левым предплечьем.",
UI_trait_Amputee_UpperArm = "Ампутированное левое плечо",
UI_trait_Amputee_UpperArm_desc = "Вы начинаете с ампутированнвм левым плечём.",
UI_trait_Insensitive = "Нечувствительный",
UI_trait_Insensitive_desc = "",
UI_Say_CantEquip = "Я не могу его так экипировать..."
}

View File

@@ -0,0 +1,31 @@
ContextMenu_TR = {
ContextMenu_Amputate = "Ampute Et",
ContextMenu_Amputate_Bandage = "Ampute Et ve Bandajla",
ContextMenu_Amputate_Stitch = "Ampute Et ve Dikiþ At",
ContextMenu_Amputate_Stitch_Bandage = "Ampute Et, Dikiþ At ve Bandajla",
ContextMenu_Cauterize = "Daðla",
ContextMenu_Limb_Hand_L = "Sol El",
ContextMenu_Limb_ForeArm_L = "Sol Ön Kol",
ContextMenu_Limb_UpperArm_L = "Sol Üst Kol",
ContextMenu_Limb_Hand_R = "Sað El",
ContextMenu_Limb_ForeArm_R = "Sað Ön Kol",
ContextMenu_Limb_UpperArm_R = "Sað Üst Kol",
ContextMenu_InstallProstRight = "Sað kola protez tak",
ContextMenu_InstallProstLeft = "Sol kola protez tak",
ContextMenu_PutTourniquetArmLeft = "Sol kola turnike tak",
ContextMenu_PutTourniquetLegL = "Sol bacaðýna turnike tak",
ContextMenu_PutTourniquetArmRight = "Sað kola turnike tak",
ContextMenu_PutTourniquetLegR = "Sað bacaðýna turnike tak",
ContextMenu_CleanWound = "Yarayý Temizle",
ContextMenu_Admin_TOC = "TOC",
ContextMenu_Admin_ResetTOC = "Amputasyonlarý Sýfýrla",
ContextMenu_Admin_ForceAmputation = "Zorla Amputasyon Yap",
}

Some files were not shown because too many files have changed in this diff Show More