Compare commits
231 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
bd532dc013 | ||
|
|
1d21c0d51c | ||
|
|
e129b325e4 | ||
|
|
df9f559078 | ||
|
|
1fb3899a5a | ||
|
|
457f89b064 | ||
|
|
27d79c5802 | ||
|
|
92a0b9ef18 | ||
|
|
494b4b576f | ||
|
|
76fcb1ac97 | ||
|
|
fba1b2e643 | ||
|
|
2cf7df16b3 | ||
|
|
898e8ec653 | ||
|
|
943e3a8f3c | ||
|
|
442af10b7a | ||
|
|
c9d6236b89 | ||
|
|
e884985fe3 | ||
|
|
38fe71bc72 | ||
|
|
b650b2a590 | ||
|
|
da7621c0f0 | ||
|
|
acd2e9c547 | ||
|
|
27d9b3a513 | ||
|
|
aa61a3390c | ||
|
|
b84c2a593d | ||
|
|
cdf0473065 | ||
|
|
40da330b41 | ||
|
|
20fa1bd05e | ||
|
|
3f888e7f22 | ||
|
|
d84554ff07 | ||
|
|
ec87d128e4 | ||
|
|
be4588fc43 | ||
|
|
4bafb3a15c | ||
|
|
fd056aea1e | ||
|
|
100abab2aa | ||
|
|
789b0635e0 | ||
|
|
d6d9ba7028 | ||
|
|
a182fb07e5 | ||
|
|
528a43247a | ||
|
|
b281ce7d12 | ||
|
|
9db3a1c944 | ||
|
|
a74e33134d | ||
|
|
1caf4a4b49 | ||
|
|
5f71cebdc0 | ||
|
|
4714bd7b82 | ||
|
|
4d20cc2559 | ||
|
|
5ec0ec1a9b | ||
|
|
89a28e846a | ||
|
|
a511ac777a | ||
|
|
04c7172d82 | ||
|
|
522c49b40c | ||
|
|
b5266cd7cd | ||
|
|
8c8aa8351b | ||
|
|
3eeb9d1000 | ||
|
|
c60a2c56ec | ||
|
|
69025c8262 | ||
|
|
80e9391db5 | ||
|
|
d7bdee1d26 | ||
|
|
8234abd5e2 | ||
|
|
9011579f08 | ||
|
|
be6466976c | ||
|
|
9ab584d977 | ||
|
|
b0d3520173 | ||
|
|
bbd36f7dc2 | ||
|
|
3fc37f56d6 | ||
|
|
d5fd735de8 | ||
|
|
253c5717a9 | ||
|
|
d850691053 | ||
|
|
f728520f9e | ||
|
|
67f51ca845 | ||
|
|
e07af54d27 | ||
|
|
6e47f945c5 | ||
|
|
644376cea0 | ||
|
|
6a3fa76e00 | ||
|
|
6e674959ab | ||
|
|
d52f3f6bf2 | ||
|
|
5acab111f2 | ||
|
|
61f505fa8e | ||
|
|
6abd89cea7 | ||
|
|
768a0dbdab | ||
|
|
d96c26d099 | ||
|
|
f93c0503f8 | ||
|
|
671bf133e3 | ||
|
|
1e754895a0 | ||
|
|
9a11047e3c | ||
|
|
db6f315f89 | ||
|
|
729e3b62e7 | ||
|
|
7c8cfb0fcc | ||
|
|
bb19da2b4b | ||
|
|
471608f9ba | ||
|
|
71b854efe2 | ||
|
|
e919c8c01b | ||
|
|
b6b61b872f | ||
|
|
58d5c8e13d | ||
|
|
cc5e67aceb | ||
|
|
f77a357dab | ||
|
|
499db8cd78 | ||
|
|
ffce5fac2e | ||
|
|
81842f7020 | ||
|
|
d846b853ff | ||
|
|
0f4117cd34 | ||
|
|
736d527a13 | ||
|
|
1ded7f976c | ||
|
|
6635cc19b2 | ||
|
|
5d8e60a2e4 | ||
|
|
5515b6bd4f | ||
|
|
ba267cb900 | ||
|
|
90ca2edbce | ||
|
|
00d5d83ea2 | ||
|
|
849c17051a | ||
|
|
0071d2ac3f | ||
|
|
68605ddb35 | ||
|
|
371134faa7 | ||
|
|
132ce24328 | ||
|
|
4af127196c | ||
|
|
39bccaf895 | ||
|
|
54c5958715 | ||
|
|
6b79ebf003 | ||
|
|
75d5cb180d | ||
|
|
245f81be26 | ||
|
|
1f950e0663 | ||
|
|
aecb5448ea | ||
|
|
c02ac7dacc | ||
|
|
332e02d9fd | ||
|
|
a2b3db6793 | ||
|
|
6883c81322 | ||
|
|
600c55f5f8 | ||
|
|
bf20aec94f | ||
|
|
26c269e8ba | ||
|
|
db42feed35 | ||
|
|
10f97cffa1 | ||
|
|
22e6621300 | ||
|
|
4d2b62e4a1 | ||
|
|
dd0d48cd08 | ||
|
|
2de512b447 | ||
|
|
1765d82ad9 | ||
|
|
c52cca09f1 | ||
|
|
545d5c7573 | ||
|
|
99d0847caa | ||
|
|
3b7fe2ec58 | ||
|
|
92fc80095d | ||
|
|
751e36cba7 | ||
|
|
487e616801 | ||
|
|
d5915cd287 | ||
|
|
d1f63ab55f | ||
|
|
857515576e | ||
|
|
69c6177be5 | ||
|
|
38fa63324c | ||
|
|
940f5486aa | ||
|
|
11622795e1 | ||
|
|
cb7603feea | ||
|
|
7b5e8e15d5 | ||
|
|
9a74710c1e | ||
|
|
3f7bf56be2 | ||
|
|
501c2fbabd | ||
|
|
3dad820014 | ||
|
|
2f82021b5d | ||
|
|
a3287bb2bc | ||
|
|
6c82f1a96f | ||
|
|
f2446c0781 | ||
|
|
4d6ee68054 | ||
|
|
854238ef98 | ||
|
|
2b41745a05 | ||
|
|
c2e15151a6 | ||
|
|
b25f52a40d | ||
|
|
145ec33620 | ||
|
|
307e19fd52 | ||
|
|
9eb9ea0263 | ||
|
|
f8fc8e7f60 | ||
|
|
3d1cfba85c | ||
|
|
1f6fc63f46 | ||
|
|
3931c0ed4d | ||
|
|
74eb7763cf | ||
|
|
e0e65c022f | ||
|
|
574526aca0 | ||
|
|
29f21decb4 | ||
|
|
b70dd619a4 | ||
|
|
0d5814dad1 | ||
|
|
5f64ead354 | ||
|
|
80c8b22faa | ||
|
|
696edc1f1d | ||
|
|
a1336c8d2e | ||
|
|
1187f1a1b6 | ||
|
|
dc921e4c04 | ||
|
|
bff6a2d4d6 | ||
|
|
36c3418a3e | ||
|
|
a7e32bc69b | ||
|
|
139ad5828a | ||
|
|
1636ca7e13 | ||
|
|
46a8ddc207 | ||
|
|
26e0324f4a | ||
|
|
c1faeeaabf | ||
|
|
a93c8a56bb | ||
|
|
b33cee7271 | ||
|
|
6e68e12b60 | ||
|
|
013f852e7e | ||
|
|
99dbaea143 | ||
|
|
a09a1520a1 | ||
|
|
a7a064119d | ||
|
|
6458988cc8 | ||
|
|
9b1876b235 | ||
|
|
0d9ee4203c | ||
|
|
2ea03601f5 | ||
|
|
3d4a54418c | ||
|
|
ba4f161122 | ||
|
|
17718cbbca | ||
|
|
f9ad597d2b | ||
|
|
c8b6a8c5ed | ||
|
|
df8591b1ef | ||
|
|
9478e0faa1 | ||
|
|
91a6eb7763 | ||
|
|
d512f0ba81 | ||
|
|
31995965f9 | ||
|
|
d35840d825 | ||
|
|
e270b4f73b | ||
|
|
1a754f4012 | ||
|
|
4757d9dfa8 | ||
|
|
74bb34bbc8 | ||
|
|
1b235ebaa4 | ||
|
|
44d486dfeb | ||
|
|
5cc982188a | ||
|
|
aadbe02df4 | ||
|
|
20bed84910 | ||
|
|
fc3113f243 | ||
|
|
be368738ba | ||
|
|
4209f690a8 | ||
|
|
a3a2614124 | ||
|
|
50f6db9344 | ||
|
|
17d554d269 | ||
|
|
1bef713de5 | ||
|
|
beee6f409c | ||
|
|
540f510eb0 |
24
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal file
24
.github/ISSUE_TEMPLATE/bug_report.md
vendored
Normal 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
3
.gitignore
vendored
@@ -1 +1,2 @@
|
||||
.vscode
|
||||
dev_stuff/gen_amp_textures/.venv
|
||||
dev_stuff/gen_amp_textures/output
|
||||
32
.vscode/settings.json
vendored
32
.vscode/settings.json
vendored
@@ -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
111
.vscode/tasks.json
vendored
@@ -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"
|
||||
// ]
|
||||
// }
|
||||
]
|
||||
}
|
||||
@@ -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 -->
|
||||
@@ -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>
|
||||
39
42/media/clothing/clothingItems/Amputation_Hand_L.xml
Normal file
39
42/media/clothing/clothingItems/Amputation_Hand_L.xml
Normal 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>
|
||||
37
42/media/clothing/clothingItems/Amputation_Hand_R.xml
Normal file
37
42/media/clothing/clothingItems/Amputation_Hand_R.xml
Normal 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>
|
||||
@@ -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>
|
||||
@@ -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>
|
||||
@@ -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()
|
||||
sendClientCommand(CommandsData.modules.TOC_RELAY, CommandsData.server.Relay.RelayExecuteInitialization,
|
||||
{ patientNum = clickedPlayerNum })
|
||||
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)
|
||||
|
||||
@@ -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
|
||||
@@ -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"
|
||||
79
42/media/lua/client/TOC/Compat.lua
Normal file
79
42/media/lua/client/TOC/Compat.lua
Normal 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
|
||||
@@ -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
|
||||
@@ -86,21 +86,29 @@ function DataController:setup(key)
|
||||
}
|
||||
end
|
||||
|
||||
-- Add it to global mod data
|
||||
-- Add it to client global mod data
|
||||
ModData.add(key, self.tocData)
|
||||
|
||||
-- Sync with the server
|
||||
self:apply()
|
||||
|
||||
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)
|
||||
end
|
||||
|
||||
---@param key string
|
||||
function DataController:loadLocalData(key)
|
||||
function DataController:tryLoadLocalData(key)
|
||||
self.tocData = ModData.get(key)
|
||||
|
||||
--TOC_DEBUG.printTable(self.tocData)
|
||||
@@ -220,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
|
||||
@@ -330,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
|
||||
|
||||
@@ -368,11 +369,14 @@ end
|
||||
function DataController.ReceiveData(key, data)
|
||||
-- During startup the game can return Bob as the player username, adding a useless ModData table
|
||||
if key == "TOC_Bob" then return end
|
||||
if not luautils.stringStarts(key, StaticData.MOD_NAME .. "_") then return end
|
||||
|
||||
|
||||
TOC_DEBUG.print("ReceiveData for " .. key)
|
||||
if data == {} or data == nil then
|
||||
error("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)
|
||||
@@ -387,22 +391,25 @@ function DataController.ReceiveData(key, data)
|
||||
-- TODO Add update from server scenario
|
||||
|
||||
if handler.isResetForced then
|
||||
TOC_DEBUG.print("Forced reset")
|
||||
handler:setup(key)
|
||||
elseif data then
|
||||
if data.isUpdateFromServer then
|
||||
TOC_DEBUG.print("Update from the server")
|
||||
end
|
||||
elseif data and data.limbs then
|
||||
-- Let's validate that the data structure is actually valid to prevent issues
|
||||
handler:applyOnlineData(data)
|
||||
elseif username == getPlayer():getUsername() then
|
||||
handler:loadLocalData(key)
|
||||
TOC_DEBUG.print("Trying to load local data or no data is available")
|
||||
handler:tryLoadLocalData(key)
|
||||
end
|
||||
|
||||
|
||||
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
|
||||
@@ -434,7 +441,7 @@ Events.OnReceiveGlobalModData.Add(DataController.ReceiveData)
|
||||
--- SP Only initialization
|
||||
---@param key string
|
||||
function DataController:initSinglePlayer(key)
|
||||
self:loadLocalData(key)
|
||||
self:tryLoadLocalData(key)
|
||||
if self.tocData == nil or self.isResetForced then
|
||||
self:setup(key)
|
||||
end
|
||||
@@ -462,4 +469,12 @@ function DataController.GetInstance(username)
|
||||
end
|
||||
end
|
||||
|
||||
|
||||
function DataController.DestroyInstance(username)
|
||||
if DataController.instances[username] ~= nil then
|
||||
DataController.instances[username] = nil
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return DataController
|
||||
@@ -5,74 +5,167 @@ 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
|
||||
|
||||
local function CheckHandFeasibility(limbName)
|
||||
function LimitActionsController.CheckLimbFeasibility(limbName)
|
||||
local dcInst = DataController.GetInstance()
|
||||
return not dcInst:getIsCut(limbName) or dcInst:getIsProstEquipped(limbName)
|
||||
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
|
||||
|
||||
|
||||
--* Time to perform actions overrides *--
|
||||
|
||||
-- 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)
|
||||
local dcInst = DataController.GetInstance()
|
||||
|
||||
local isFeasible = not dcInst:getIsCut(limbName) or dcInst:getIsProstEquipped(limbName)
|
||||
TOC_DEBUG.print("isFeasible: " .. tostring(isFeasible))
|
||||
return isFeasible
|
||||
end
|
||||
|
||||
|
||||
--* 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())
|
||||
|
||||
for k, _ in pairs(amputatedLimbs) do
|
||||
local limbName = k
|
||||
--if dcInst:getIsCut(limbName) then
|
||||
local perk = Perks["Side_" .. CommonMethods.GetSide(limbName)]
|
||||
local perkLevel = pl:getPerkLevel(perk)
|
||||
local perkAmp = Perks["Side_" .. CommonMethods.GetSide(limbName)]
|
||||
local perkLevel = pl:getPerkLevel(perkAmp)
|
||||
|
||||
if dcInst:getIsProstEquipped(limbName) then
|
||||
-- TODO We should separate this in multiple perks, since this is gonna be a generic familiarity and could make no actual sense
|
||||
local perkProst = Perks["ProstFamiliarity"]
|
||||
perkLevel = perkLevel + pl:getPerkLevel(perkProst)
|
||||
end
|
||||
|
||||
local perkLevelScaled
|
||||
if perkLevel ~= 0 then perkLevelScaled = perkLevel / 10 else perkLevelScaled = 0 end
|
||||
time = time * (StaticData.LIMBS_TIME_MULTIPLIER_IND_NUM[limbName] - perkLevelScaled)
|
||||
--end
|
||||
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("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
|
||||
-- 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], 1) -- TODO Make it dynamic
|
||||
|
||||
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
|
||||
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")
|
||||
--TOC_DEBUG.print("Trying for bleed, player met the criteria")
|
||||
LocalPlayerController.TryRandomBleed(self.character, limbName)
|
||||
end
|
||||
end
|
||||
@@ -89,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)
|
||||
@@ -97,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
|
||||
@@ -105,8 +202,8 @@ 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
|
||||
local getMethodFirst = nil
|
||||
@@ -130,6 +227,10 @@ function ISEquipWeaponAction:performWithAmputation(dcInst)
|
||||
setMethodSecond = self.character.setSecondaryHandItem
|
||||
end
|
||||
|
||||
local isFirstValid = CheckHandFeasibility(hand)
|
||||
local isSecondValid = CheckHandFeasibility(otherHand)
|
||||
|
||||
|
||||
if not self.twoHands then
|
||||
if getMethodFirst(self.character) and getMethodFirst(self.character):isRequiresEquippedBothHands() then
|
||||
setMethodFirst(self.character, nil)
|
||||
@@ -145,10 +246,10 @@ function ISEquipWeaponAction:performWithAmputation(dcInst)
|
||||
setMethodSecond(self.character, nil)
|
||||
-- TODO We should use the CachedData indexable instead of dcInst
|
||||
|
||||
if not dcInst:getIsCut(hand) then
|
||||
if isFirstValid then
|
||||
setMethodSecond(self.character, self.item)
|
||||
-- Check other HAND!
|
||||
elseif not dcInst:getIsCut(otherHand) then
|
||||
elseif isSecondValid then
|
||||
setMethodFirst(self.character, self.item)
|
||||
end
|
||||
end
|
||||
@@ -156,13 +257,10 @@ function ISEquipWeaponAction:performWithAmputation(dcInst)
|
||||
setMethodFirst(self.character, nil)
|
||||
setMethodSecond(self.character, nil)
|
||||
|
||||
|
||||
local isFirstValid = CheckHandFeasibility(hand)
|
||||
local isSecondValid = CheckHandFeasibility(otherHand)
|
||||
-- TOC_DEBUG.print("First Hand: " .. tostring(hand))
|
||||
-- TOC_DEBUG.print("Prost Group: " .. tostring(prostGroup))
|
||||
-- --TOC_DEBUG.print("Prost Group: " .. tostring(prostGroup))
|
||||
-- TOC_DEBUG.print("Other Hand: " .. tostring(otherHand))
|
||||
-- TOC_DEBUG.print("Other Prost Group: " .. tostring(otherProstGroup))
|
||||
-- --TOC_DEBUG.print("Other Prost Group: " .. tostring(otherProstGroup))
|
||||
|
||||
-- TOC_DEBUG.print("isPrimaryHandValid: " .. tostring(isFirstValid))
|
||||
-- TOC_DEBUG.print("isSecondaryHandValid: " .. tostring(isSecondValid))
|
||||
@@ -183,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)
|
||||
@@ -248,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 :((")
|
||||
@@ -262,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
|
||||
@@ -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
|
||||
@@ -35,8 +40,7 @@ function LocalPlayerController.InitializePlayer(isForced)
|
||||
|
||||
-- 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
|
||||
|
||||
@@ -44,21 +48,37 @@ function LocalPlayerController.InitializePlayer(isForced)
|
||||
SetHealthPanelTOC()
|
||||
end
|
||||
|
||||
|
||||
|
||||
---Handles the traits
|
||||
---@param playerObj IsoPlayer
|
||||
function LocalPlayerController.ManageTraits(playerObj)
|
||||
local AmputationHandler = require("Handlers/TOC_AmputationHandler")
|
||||
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
|
||||
-- Once we find one, we should be done.
|
||||
local tempHandler = AmputationHandler:new(v)
|
||||
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 *--
|
||||
@@ -75,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)
|
||||
@@ -92,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()
|
||||
@@ -121,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
|
||||
|
||||
@@ -135,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
|
||||
@@ -155,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
|
||||
@@ -167,18 +198,17 @@ 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
|
||||
|
||||
for i = 1, #StaticData.IGNORED_BODYLOCS_BPT do
|
||||
local bodyPartType = StaticData.IGNORED_BODYLOCS_BPT[i]
|
||||
local bodyPart = bd:getBodyPart(bodyPartType)
|
||||
if bodyPart and (bodyPart:bitten() or bodyPart:IsInfected()) then
|
||||
dcInst:setIsIgnoredPartInfected(true)
|
||||
modDataNeedsUpdate = true
|
||||
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)
|
||||
if bodyPart and (bodyPart:bitten() or bodyPart:IsInfected()) then
|
||||
dcInst:setIsIgnoredPartInfected(true)
|
||||
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
|
||||
@@ -187,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
|
||||
@@ -257,14 +283,11 @@ function LocalPlayerController.UpdateAmputations()
|
||||
cicTime = cicTime - cicDec
|
||||
|
||||
|
||||
dcInst:setCicatrizationTime(limbName, cicTime)
|
||||
TOC_DEBUG.print("New cicatrization time: " .. tostring(cicTime))
|
||||
if cicTime <= 0 then
|
||||
TOC_DEBUG.print(tostring(limbName) .. " is cicatrized")
|
||||
dcInst:setIsCicatrized(limbName, true)
|
||||
-- Set visual
|
||||
local ItemsController = require("TOC/Controllers/ItemsController")
|
||||
ItemsController.Player.OverrideAmputationItemVisuals(pl, limbName, true)
|
||||
LocalPlayerController.HandleSetCicatrization(dcInst, pl, limbName)
|
||||
else
|
||||
dcInst:setCicatrizationTime(limbName, cicTime)
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -285,6 +308,24 @@ function LocalPlayerController.ToggleUpdateAmputations()
|
||||
CommonMethods.SafeStartEvent("EveryHours", LocalPlayerController.UpdateAmputations)
|
||||
end
|
||||
|
||||
|
||||
--* Cicatrization and cicatrization visuals *--
|
||||
|
||||
---Set the boolean and cicTime in DCINST and the visuals for the amputated limb
|
||||
---@param dcInst DataController
|
||||
---@param playerObj IsoPlayer
|
||||
---@param limbName string
|
||||
function LocalPlayerController.HandleSetCicatrization(dcInst, playerObj, limbName)
|
||||
TOC_DEBUG.print("Setting cicatrization to " .. tostring(limbName))
|
||||
dcInst:setIsCicatrized(limbName, true)
|
||||
dcInst:setCicatrizationTime(limbName, 0)
|
||||
|
||||
-- -- 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
|
||||
|
||||
|
||||
@@ -334,10 +375,20 @@ function LocalPlayerController.DropItemsAfterAmputation(limbName)
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
-- TODO Consider 2 handed weapons too
|
||||
|
||||
-- equipped items too
|
||||
if side == "R" then
|
||||
pl:setPrimaryHandItem(nil)
|
||||
elseif side == "L" then
|
||||
pl:setSecondaryHandItem(nil)
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
Events.OnAmputatedLimb.Add(LocalPlayerController.DropItemsAfterAmputation)
|
||||
|
||||
Events.OnProsthesisUnequipped.Add(LocalPlayerController.DropItemsAfterAmputation)
|
||||
|
||||
|
||||
|
||||
@@ -64,18 +64,20 @@ 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
|
||||
|
||||
wrappedFunc(obj)
|
||||
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
|
||||
|
||||
|
||||
@@ -92,18 +94,21 @@ 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()
|
||||
TourniquetController.WrapClothingAction(self, og_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()
|
||||
TourniquetController.WrapClothingAction(self, og_ISUnequipAction_perform)
|
||||
return TourniquetController.WrapClothingAction(self, og_ISUnequipAction_perform)
|
||||
end
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
--* Setup Events *--
|
||||
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
|
||||
@@ -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
|
||||
@@ -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 = {}
|
||||
|
||||
@@ -111,6 +108,8 @@ end
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
--* Hand feasibility caching *--
|
||||
CachedDataHandler.handFeasibility = {}
|
||||
|
||||
@@ -118,30 +117,55 @@ 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
|
||||
getCore():addKeyBinding(interactStr, Keyboard.KEY_NONE)
|
||||
|
||||
end
|
||||
else
|
||||
TOC_DEBUG.print("Re-enabling interact key")
|
||||
--TOC_DEBUG.print("Re-enabling interact key")
|
||||
--TOC_DEBUG.print("Cached current key for interact: " .. tostring(CachedDataHandler.interactKey))
|
||||
|
||||
if not CachedDataHandler.interactKey then CachedDataHandler.interactKey = getCore():getKey(interactStr) end
|
||||
getCore():addKeyBinding(interactStr, 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
|
||||
|
||||
@@ -150,3 +174,4 @@ function CachedDataHandler.GetBothHandsFeasibility()
|
||||
end
|
||||
|
||||
return CachedDataHandler
|
||||
|
||||
@@ -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
|
||||
@@ -70,7 +68,6 @@ function ProsthesisHandler.CheckIfEquippable(fullType)
|
||||
return false
|
||||
end
|
||||
|
||||
|
||||
---Handle equipping or unequipping prosthetics
|
||||
---@param item InventoryItem
|
||||
---@param isEquipping boolean
|
||||
@@ -85,22 +82,15 @@ 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
|
||||
|
||||
local fullType = item:getFullType() -- use fulltype for side
|
||||
local fullType = item:getFullType() -- use fulltype for side
|
||||
if isEquippable then
|
||||
isEquippable = ProsthesisHandler.CheckIfEquippable(fullType)
|
||||
else
|
||||
@@ -111,73 +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(self.item, 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
|
||||
@@ -6,39 +6,11 @@ require("TOC/Events")
|
||||
|
||||
---@class Main
|
||||
local Main = {
|
||||
_version = 2.0
|
||||
_version = "2.3"
|
||||
}
|
||||
|
||||
---Setups the custom traits
|
||||
function Main.SetupTraits()
|
||||
-- Perks.Left_Hand is defined in perks.txt
|
||||
|
||||
local traitsTable = {
|
||||
[1] = TraitFactory.addTrait("Amputee_Hand", getText("UI_trait_Amputee_Hand"), -8, getText("UI_trait_Amputee_Hand_desc"), false, false),
|
||||
[2] = TraitFactory.addTrait("Amputee_LowerArm", getText("UI_trait_Amputee_LowerArm"), -10, getText("UI_trait_Amputee_LowerArm_desc"), false, false),
|
||||
[3] = TraitFactory.addTrait("Amputee_UpperArm", getText("UI_trait_Amputee_UpperArm"), -20, getText("UI_trait_Amputee_UpperArm_desc"), false, false)
|
||||
}
|
||||
|
||||
for i=1, #traitsTable do
|
||||
|
||||
---@type Trait
|
||||
local t = traitsTable[i]
|
||||
---@diagnostic disable-next-line: undefined-field
|
||||
t:addXPBoost(Perks.Left_Hand, 4)
|
||||
t:addXPBoost(Perks.Fitness, -1)
|
||||
t:addXPBoost(Perks.Strength, -1)
|
||||
end
|
||||
|
||||
TraitFactory.addTrait("Insensitive", getText("UI_trait_Insensitive"), 6, getText("UI_trait_Insensitive_desc"), false, false)
|
||||
|
||||
TraitFactory.setMutualExclusive("Amputee_Hand", "Amputee_LowerArm")
|
||||
TraitFactory.setMutualExclusive("Amputee_Hand", "Amputee_UpperArm")
|
||||
TraitFactory.setMutualExclusive("Amputee_LowerArm", "Amputee_UpperArm")
|
||||
end
|
||||
|
||||
function Main.Start()
|
||||
TOC_DEBUG.print("running Start method")
|
||||
Main.SetupTraits()
|
||||
TOC_DEBUG.print("Starting The Only Cure version " .. tostring(Main._version))
|
||||
Main.SetupEvents()
|
||||
end
|
||||
|
||||
@@ -47,6 +19,7 @@ function Main.SetupEvents()
|
||||
Events.OnReceivedTocData.Add(CachedDataHandler.CalculateCacheableValues)
|
||||
end
|
||||
|
||||
|
||||
function Main.InitializePlayer()
|
||||
---Looop until we've successfully initialized the mod
|
||||
local function TryToInitialize()
|
||||
@@ -63,16 +36,15 @@ function Main.InitializePlayer()
|
||||
CommonMethods.SafeStartEvent("OnTick", TryToInitialize)
|
||||
end
|
||||
|
||||
---Clean the TOC table for that SP player, to prevent from clogging it up
|
||||
---Clean the TOC table for that SP player, to prevent it from clogging ModData up
|
||||
---@param player IsoPlayer
|
||||
function Main.WipeData(player)
|
||||
TOC_DEBUG.print("Wiping data after death")
|
||||
local key = CommandsData.GetKey(player:getUsername())
|
||||
local username = player:getUsername()
|
||||
TOC_DEBUG.print("Wiping data after death: " .. username)
|
||||
local key = CommandsData.GetKey(username)
|
||||
|
||||
--ModData.remove(key)
|
||||
|
||||
|
||||
|
||||
if not isClient() then
|
||||
-- For SP, it's enough just removing the data this way
|
||||
ModData.remove(key)
|
||||
@@ -81,7 +53,15 @@ function Main.WipeData(player)
|
||||
-- at the next character by passing an empty mod data
|
||||
ModData.add(key, {})
|
||||
ModData.transmit(key)
|
||||
|
||||
end
|
||||
|
||||
|
||||
-- Let's wipe the instance too just to be sure
|
||||
-- TODO This can break things I guess
|
||||
--local DataController = require("TOC/Controllers/DataController")
|
||||
--DataController.DestroyInstance(username)
|
||||
|
||||
end
|
||||
|
||||
--* Events *--
|
||||
@@ -11,7 +11,6 @@ local StaticData = require("TOC/StaticData")
|
||||
TestFramework.registerTestModule("LocalPlayerController", "Setup", function()
|
||||
local Tests = {}
|
||||
function Tests.InitializePlayer()
|
||||
local pl = getPlayer()
|
||||
LocalPlayerController.InitializePlayer(true)
|
||||
end
|
||||
return Tests
|
||||
@@ -146,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
|
||||
@@ -153,6 +160,37 @@ TestFramework.registerTestModule("Various", "Player", function()
|
||||
return Tests
|
||||
end)
|
||||
|
||||
TestFramework.registerTestModule("Various", "Visuals", function()
|
||||
local Tests = {}
|
||||
|
||||
function Tests.AddBloodLeftForearm()
|
||||
local playerObj = getPlayer()
|
||||
local limbName = "ForeArm_L"
|
||||
local fullType = StaticData.AMPUTATION_CLOTHING_ITEM_BASE .. limbName
|
||||
|
||||
|
||||
local item = playerObj:getInventory():FindAndReturn(fullType)
|
||||
if instanceof(item, "Clothing") then
|
||||
|
||||
---@cast item Clothing
|
||||
|
||||
print("Found limb to add blood onto")
|
||||
item:setBloodLevel(100)
|
||||
local coveredParts = BloodClothingType.getCoveredParts(item:getBloodClothingType())
|
||||
if coveredParts then
|
||||
for j=0,coveredParts:size()-1 do
|
||||
item:setBlood(coveredParts:get(j), 100)
|
||||
item:setDirt(coveredParts:get(j), 100)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
playerObj:resetModelNextFrame()
|
||||
end
|
||||
|
||||
return Tests
|
||||
end)
|
||||
|
||||
|
||||
--------------------------------------------------------------------------------------
|
||||
@@ -1,5 +1,6 @@
|
||||
require "TimedActions/ISBaseTimedAction"
|
||||
local DataController = require("TOC/Controllers/DataController")
|
||||
local LocalPlayerController = require("TOC/Controllers/LocalPlayerController")
|
||||
---------------
|
||||
|
||||
---@class CauterizeAction : ISBaseTimedAction
|
||||
@@ -72,11 +73,14 @@ function CauterizeAction:perform()
|
||||
|
||||
local dcInst = DataController.GetInstance()
|
||||
dcInst:setCicatrizationTime(self.limbName, 0)
|
||||
dcInst:setIsCicatrized(self.limbName, true)
|
||||
dcInst:setIsCauterized(self.limbName, true)
|
||||
|
||||
-- we don't care about the depended limbs, since they're alread "cicatrized"
|
||||
-- Set isCicatrized and the visuals in one go, since this action is gonna be run only on a single client
|
||||
LocalPlayerController.HandleSetCicatrization(dcInst, self.character, self.limbName)
|
||||
|
||||
-- TODO Add specific visuals for cauterization
|
||||
|
||||
-- we don't care about the depended limbs, since they're alread "cicatrized"
|
||||
dcInst:apply()
|
||||
|
||||
ISBaseTimedAction.perform(self)
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
139
42/media/lua/client/TOC/TimedActions/IgnoredActions.lua
Normal file
139
42/media/lua/client/TOC/TimedActions/IgnoredActions.lua
Normal 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
|
||||
@@ -0,0 +1,80 @@
|
||||
local CachedDataHandler = require("TOC/Handlers/CachedDataHandler")
|
||||
local StaticData = require("TOC/StaticData")
|
||||
|
||||
-- Since amputations are actually clothing items, we need to override ISWashYourself to account for that
|
||||
|
||||
-- TODO Clean this up
|
||||
|
||||
local og_ISWashYourself_perform = ISWashYourself.perform
|
||||
function ISWashYourself:perform()
|
||||
|
||||
TOC_DEBUG.print("ISWashYourself override")
|
||||
|
||||
---@type IsoPlayer
|
||||
local pl = self.character
|
||||
local plInv = pl:getInventory()
|
||||
-- Search for amputations and clean them here
|
||||
local amputatedLimbs = CachedDataHandler.GetAmputatedLimbs(pl:getUsername())
|
||||
for limbName, _ in pairs(amputatedLimbs) do
|
||||
|
||||
TOC_DEBUG.print("Checking if " .. limbName .. " is in inventory and washing it")
|
||||
|
||||
-- get clothing item
|
||||
local foundItem = plInv:FindAndReturn(StaticData.AMPUTATION_CLOTHING_ITEM_BASE .. limbName)
|
||||
if foundItem and instanceof(foundItem, "Clothing") then
|
||||
|
||||
TOC_DEBUG.print("Washing " .. limbName)
|
||||
|
||||
---@cast foundItem Clothing
|
||||
foundItem:setWetness(100)
|
||||
foundItem:setBloodLevel(0)
|
||||
foundItem:setDirtyness(0) -- TODO Integrate with other dirtyness
|
||||
|
||||
local coveredParts = BloodClothingType.getCoveredParts(foundItem:getBloodClothingType())
|
||||
for j=0, coveredParts:size() - 1 do
|
||||
foundItem:setBlood(coveredParts:get(j), 0)
|
||||
foundItem:setDirt(coveredParts:get(j), 0)
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
|
||||
og_ISWashYourself_perform(self)
|
||||
|
||||
|
||||
end
|
||||
|
||||
|
||||
local og_ISWashYourself_GetRequiredWater = ISWashYourself.GetRequiredWater
|
||||
|
||||
|
||||
---@param character IsoPlayer
|
||||
---@return integer
|
||||
function ISWashYourself.GetRequiredWater(character)
|
||||
|
||||
local units = og_ISWashYourself_GetRequiredWater(character)
|
||||
local amputatedLimbs = CachedDataHandler.GetAmputatedLimbs(character:getUsername())
|
||||
local plInv = character:getInventory()
|
||||
for limbName, _ in pairs(amputatedLimbs) do
|
||||
|
||||
TOC_DEBUG.print("Checking if " .. limbName .. " is in inventory and washing it")
|
||||
|
||||
-- get clothing item
|
||||
local item = plInv:FindAndReturn(StaticData.AMPUTATION_CLOTHING_ITEM_BASE .. limbName)
|
||||
if item and instanceof(item, "Clothing") then
|
||||
local coveredParts = BloodClothingType.getCoveredParts(item:getBloodClothingType())
|
||||
if coveredParts then
|
||||
for i=1,coveredParts:size() do
|
||||
local part = coveredParts:get(i-1)
|
||||
if item:getBlood(part) > 0 then
|
||||
units = units + 1
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
end
|
||||
|
||||
return units
|
||||
end
|
||||
116
42/media/lua/client/TOC/UI/ConfirmationPanel.lua
Normal file
116
42/media/lua/client/TOC/UI/ConfirmationPanel.lua
Normal 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
|
||||
@@ -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
|
||||
@@ -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,24 +76,32 @@ end
|
||||
---@param stitchesItem InventoryItem?
|
||||
---@param bandageItem InventoryItem?
|
||||
local function PerformAction(surgeon, patient, limbName, sawItem, stitchesItem, bandageItem)
|
||||
-- get saw in hand
|
||||
-- todo primary or secondary depending on amputation status of surgeon
|
||||
ISTimedActionQueue.add(ISEquipWeaponAction:new(surgeon, sawItem, 50, true, false))
|
||||
|
||||
local lHandItem = surgeon:getSecondaryHandItem()
|
||||
if lHandItem then
|
||||
ISTimedActionQueue.add(ISUnequipAction:new(surgeon, lHandItem, 50))
|
||||
end
|
||||
|
||||
|
||||
ISTimedActionQueue.add(CutLimbAction:new(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))
|
||||
|
||||
local lHandItem = surgeon:getSecondaryHandItem()
|
||||
if lHandItem then
|
||||
ISTimedActionQueue.add(ISUnequipAction:new(surgeon, lHandItem, 50))
|
||||
end
|
||||
|
||||
|
||||
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
|
||||
@@ -33,15 +33,17 @@ function BaseHandler:checkItems()
|
||||
local containers = ISInventoryPaneContextMenu.getContainers(self:getDoctor())
|
||||
local done = {}
|
||||
local childContainers = {}
|
||||
for i=1,containers:size() do
|
||||
local container = containers:get(i-1)
|
||||
done[container] = true
|
||||
table.wipe(childContainers)
|
||||
self:checkContainerItems(container, childContainers)
|
||||
for _,container2 in ipairs(childContainers) do
|
||||
if not done[container2] then
|
||||
done[container2] = true
|
||||
self:checkContainerItems(container2, nil)
|
||||
if containers ~= nil then
|
||||
for i=1, containers:size() do
|
||||
local container = containers:get(i-1)
|
||||
done[container] = true
|
||||
table.wipe(childContainers)
|
||||
self:checkContainerItems(container, childContainers)
|
||||
for _,container2 in ipairs(childContainers) do
|
||||
if not done[container2] then
|
||||
done[container2] = true
|
||||
self:checkContainerItems(container2, nil)
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -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
|
||||
@@ -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
|
||||
157
42/media/lua/client/TOC/Zombies/ZombiesAmputation.lua
Normal file
157
42/media/lua/client/TOC/Zombies/ZombiesAmputation.lua
Normal 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)
|
||||
@@ -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)
|
||||
@@ -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,12 +24,13 @@ 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
|
||||
|
||||
ModData.add(key, table) -- Add it to the server mod data
|
||||
ServerDataHandler.modData[key] = table
|
||||
|
||||
|
||||
-- Check integrity of table. if it doesn't contains toc data, it means that we received a reset
|
||||
if table.limbs == nil then return end
|
||||
|
||||
-- Since this could be triggered by a different client than the one referenced in the key, we're gonna
|
||||
-- apply the changes back to the key client again to be sure that everything is in sync
|
||||
local username = CommandsData.GetUsername(key)
|
||||
44
42/media/lua/server/TOC/ServerItemsCommands.lua
Normal file
44
42/media/lua/server/TOC/ServerItemsCommands.lua
Normal 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)
|
||||
@@ -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
|
||||
|
||||
-------------------------
|
||||
|
||||
109
42/media/lua/shared/TOC/BodyLocations.lua
Normal file
109
42/media/lua/shared/TOC/BodyLocations.lua
Normal 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)
|
||||
@@ -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}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -13,10 +13,12 @@ end
|
||||
---Print debug
|
||||
---@param string string
|
||||
function TOC_DEBUG.print(string)
|
||||
--if isDebugEnabled() then
|
||||
local runningFile = TOC_DEBUG.getRunningFile()
|
||||
print("[TOC]" .. "[" .. runningFile .. "] " .. tostring(string))
|
||||
--end
|
||||
if isDebugEnabled() then
|
||||
local runningFile = TOC_DEBUG.getRunningFile()
|
||||
print("[TOC]" .. "[" .. runningFile .. "] " .. tostring(string))
|
||||
else
|
||||
print(string)
|
||||
end
|
||||
end
|
||||
|
||||
---Horrendous but I don't really care about performance for this
|
||||
31
42/media/lua/shared/TOC/OverridenMethodsArchive.lua
Normal file
31
42/media/lua/shared/TOC/OverridenMethodsArchive.lua
Normal 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
|
||||
1
42/media/lua/shared/TOC/Registries.lua
Normal file
1
42/media/lua/shared/TOC/Registries.lua
Normal file
@@ -0,0 +1 @@
|
||||
return _TOCRegistries
|
||||
@@ -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 }
|
||||
---@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
|
||||
}
|
||||
|
||||
|
||||
@@ -232,9 +230,9 @@ end
|
||||
|
||||
-- Link a trait to a specific body part
|
||||
StaticData.TRAITS_BP = {
|
||||
AmputeeHand = "Hand_L",
|
||||
AmputeeLowerArm = "ForeArm_L",
|
||||
AmputeeUpeerArm = "UpperArm_L"
|
||||
Amputee_Hand = "Hand_L",
|
||||
Amputee_ForeArm = "ForeArm_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(),
|
||||
@@ -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",
|
||||
@@ -1,8 +1,8 @@
|
||||
UI_DE = {
|
||||
UI_trait_Amputee_Hand = "Amputierte linke Hand",
|
||||
UI_trait_Amputee_Hand_desc = "",
|
||||
UI_trait_Amputee_LowerArm = "Amputierter linker Unterarm",
|
||||
UI_trait_Amputee_LowerArm_desc = "",
|
||||
UI_trait_Amputee_ForeArm = "Amputierter linker Unterarm",
|
||||
UI_trait_Amputee_ForeArm_desc = "",
|
||||
UI_trait_Amputee_UpperArm = "Amputierter linker Oberarm",
|
||||
UI_trait_Amputee_UpperArm_desc = "",
|
||||
UI_trait_Insensitive = "Unempfindlich",
|
||||
@@ -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?"
|
||||
|
||||
}
|
||||
@@ -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",
|
||||
|
||||
}
|
||||
@@ -2,8 +2,8 @@ UI_EN = {
|
||||
UI_trait_Amputee_Hand = "Amputated Left Hand",
|
||||
UI_trait_Amputee_Hand_desc = "",
|
||||
|
||||
UI_trait_Amputee_LowerArm = "Amputated Left Forearm",
|
||||
UI_trait_Amputee_LowerArm_desc = "",
|
||||
UI_trait_Amputee_ForeArm = "Amputated Left Forearm",
|
||||
UI_trait_Amputee_ForeArm_desc = "",
|
||||
|
||||
UI_trait_Amputee_UpperArm = "Amputated Left Upper arm",
|
||||
UI_trait_Amputee_UpperArm_desc = "",
|
||||
29
42/media/lua/shared/Translate/FR/ContextMenu_FR.txt
Normal file
29
42/media/lua/shared/Translate/FR/ContextMenu_FR.txt
Normal 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",
|
||||
}
|
||||
21
42/media/lua/shared/Translate/FR/IG_UI_FR.txt
Normal file
21
42/media/lua/shared/Translate/FR/IG_UI_FR.txt
Normal 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",
|
||||
|
||||
}
|
||||
11
42/media/lua/shared/Translate/FR/ItemName_FR.txt
Normal file
11
42/media/lua/shared/Translate/FR/ItemName_FR.txt
Normal 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",
|
||||
}
|
||||
5
42/media/lua/shared/Translate/FR/Recipes_FR.txt
Normal file
5
42/media/lua/shared/Translate/FR/Recipes_FR.txt
Normal 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",
|
||||
|
||||
}
|
||||
10
42/media/lua/shared/Translate/FR/Sandbox_FR.txt
Normal file
10
42/media/lua/shared/Translate/FR/Sandbox_FR.txt
Normal 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",
|
||||
|
||||
}
|
||||
10
42/media/lua/shared/Translate/FR/Tooltip_FR.txt
Normal file
10
42/media/lua/shared/Translate/FR/Tooltip_FR.txt
Normal 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",
|
||||
|
||||
}
|
||||
16
42/media/lua/shared/Translate/FR/UI_FR.txt
Normal file
16
42/media/lua/shared/Translate/FR/UI_FR.txt
Normal 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..."
|
||||
|
||||
}
|
||||
33
42/media/lua/shared/Translate/IT/ContextMenu_IT.txt
Normal file
33
42/media/lua/shared/Translate/IT/ContextMenu_IT.txt
Normal file
@@ -0,0 +1,33 @@
|
||||
ContextMenu_IT = {
|
||||
ContextMenu_Amputate = "Amputa",
|
||||
ContextMenu_Amputate_Bandage = "Amputa e fascia",
|
||||
ContextMenu_Amputate_Stitch = "Amputa e metti i punti",
|
||||
ContextMenu_Amputate_Stitch_Bandage = "Amputate, metti i punti e fascia",
|
||||
|
||||
ContextMenu_Cauterize = "Cauterizza",
|
||||
|
||||
ContextMenu_Limb_Hand_L = "Mano Sinistra",
|
||||
ContextMenu_Limb_ForeArm_L = "Avambraccio Sinistro",
|
||||
ContextMenu_Limb_UpperArm_L = "Braccio Superiore Sinistro",
|
||||
ContextMenu_Limb_Hand_R = "Mano Destra",
|
||||
ContextMenu_Limb_ForeArm_R = "Avambraccio Destro",
|
||||
ContextMenu_Limb_UpperArm_R = "Braccio Superiore Destro",
|
||||
|
||||
ContextMenu_InstallProstRight = "Installa protesi sul braccio destro",
|
||||
ContextMenu_InstallProstLeft = "Installa protesi sul braccio sinistro",
|
||||
|
||||
ContextMenu_PutTourniquetArmLeft = "Metti laccio emostatico sul braccio sinistro",
|
||||
ContextMenu_PutTourniquetLegL = "Metti laccio emostatico sulla gamba sinistra",
|
||||
ContextMenu_PutTourniquetArmRight = "Metti laccio emostatico sul braccio destro",
|
||||
ContextMenu_PutTourniquetLegR = "Metti laccio emostatico sulla gamba destra",
|
||||
|
||||
|
||||
ContextMenu_CleanWound = "Pulisci ferita",
|
||||
|
||||
|
||||
|
||||
ContextMenu_Admin_TOC = "TOC",
|
||||
ContextMenu_Admin_ResetTOC = "Reset Amputations",
|
||||
ContextMenu_Admin_ForceAmputation = "Force Amputation",
|
||||
|
||||
}
|
||||
21
42/media/lua/shared/Translate/IT/IG_UI_IT.txt
Normal file
21
42/media/lua/shared/Translate/IT/IG_UI_IT.txt
Normal file
@@ -0,0 +1,21 @@
|
||||
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",
|
||||
IGUI_perks_Prosthesis = "Protesi",
|
||||
IGUI_perks_ProstFamiliarity= "Familiarità",
|
||||
|
||||
IGUI_ItemCat_Prosthesis = "Protesi",
|
||||
IGUI_ItemCat_Surgery = "Operazioni mediche",
|
||||
IGUI_ItemCat_Amputation = "Amputazione"
|
||||
|
||||
IGUI_HealthPanel_Cicatrization = "Cicatrizzazione",
|
||||
IGUI_HealthPanel_Cicatrized = "Cicatrizzata",
|
||||
IGUI_HealthPanel_Cauterized = "Cauterizzata",
|
||||
IGUI_HealthPanel_WoundDirtyness = "Sporcizia della ferita",
|
||||
IGUI_HealthPanel_ProstEquipped = "Protesi installata",
|
||||
|
||||
}
|
||||
11
42/media/lua/shared/Translate/IT/ItemName_IT.txt
Normal file
11
42/media/lua/shared/Translate/IT/ItemName_IT.txt
Normal file
@@ -0,0 +1,11 @@
|
||||
ItemName_IT = {
|
||||
|
||||
ItemName_TOC.Surg_Arm_Tourniquet_L = "Laccio emostatico",
|
||||
ItemName_TOC.Surg_Arm_Tourniquet_R = "Laccio emostatico",
|
||||
|
||||
ItemName_TOC.Prost_NormalArm_L = "Braccio Prostetico",
|
||||
ItemName_TOC.Prost_NormalArm_R = "Braccio Prostetico",
|
||||
|
||||
ItemName_TOC.Prost_HookArm_L = "Braccio prostetico - Uncino",
|
||||
ItemName_TOC.Prost_HookArm_R = "Braccio prostetico - Uncino",
|
||||
}
|
||||
4
42/media/lua/shared/Translate/IT/Recipes_IT.txt
Normal file
4
42/media/lua/shared/Translate/IT/Recipes_IT.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
Recipes_IT = {
|
||||
Recipe_Craft_Prosthetic_Arm = "Costruisci un braccio prostetico",
|
||||
Recipe_Craft_Prosthetic_Hook = "Costruisci un braccio prostetico con uncino",
|
||||
}
|
||||
7
42/media/lua/shared/Translate/IT/Sandbox_IT.txt
Normal file
7
42/media/lua/shared/Translate/IT/Sandbox_IT.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
Sandbox_IT = {
|
||||
Sandbox_TOC = "The Only Cure",
|
||||
Sandbox_TOC_CicatrizationSpeed = "Velocità cicatrizzazione",
|
||||
Sandbox_TOC_WoundDirtynessMultiplier = "Moltiplicatore sporcizia ferita",
|
||||
Sandbox_TOC_SurgeonAbilityImportance = "Importanza abilità medico",
|
||||
|
||||
}
|
||||
10
42/media/lua/shared/Translate/IT/Tooltip_IT.txt
Normal file
10
42/media/lua/shared/Translate/IT/Tooltip_IT.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
Tooltip_IT = {
|
||||
|
||||
Tooltip_Surgery_CantCauterize = "Non puoi cauterizzare la ferita",
|
||||
|
||||
Tooltip_Surgery_And = " e "
|
||||
Tooltip_Surgery_TempTooLow = "La temperatura è troppo bassa",
|
||||
Tooltip_Surgery_Coward = "Non sei abbastanza coraggioso",
|
||||
Tooltip_Surgery_LimbNotFree = "Devi rimuovere la protesi",
|
||||
|
||||
}
|
||||
16
42/media/lua/shared/Translate/IT/UI_IT.txt
Normal file
16
42/media/lua/shared/Translate/IT/UI_IT.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
UI_IT = {
|
||||
UI_trait_Amputee_Hand = "Mano Sinistra Amputata",
|
||||
UI_trait_Amputee_Hand_desc = "",
|
||||
|
||||
UI_trait_Amputee_ForeArm = "Avambraccio Sinistro Amputato",
|
||||
UI_trait_Amputee_ForeArm_desc = "",
|
||||
|
||||
UI_trait_Amputee_UpperArm = "Parte superiore del Braccio Sinistro Amputato",
|
||||
UI_trait_Amputee_UpperArm_desc = "",
|
||||
|
||||
UI_trait_Insensitive = "Insensibile",
|
||||
UI_trait_Insensitive_desc = "",
|
||||
|
||||
|
||||
UI_Say_CantEquip = "Non posso equipaggiarlo..."
|
||||
}
|
||||
BIN
42/media/lua/shared/Translate/KO/ContextMenu_KO.txt
Normal file
BIN
42/media/lua/shared/Translate/KO/ContextMenu_KO.txt
Normal file
Binary file not shown.
BIN
42/media/lua/shared/Translate/KO/IG_UI_KO.txt
Normal file
BIN
42/media/lua/shared/Translate/KO/IG_UI_KO.txt
Normal file
Binary file not shown.
BIN
42/media/lua/shared/Translate/KO/ItemName_KO.txt
Normal file
BIN
42/media/lua/shared/Translate/KO/ItemName_KO.txt
Normal file
Binary file not shown.
BIN
42/media/lua/shared/Translate/KO/Recipes_KO.txt
Normal file
BIN
42/media/lua/shared/Translate/KO/Recipes_KO.txt
Normal file
Binary file not shown.
BIN
42/media/lua/shared/Translate/KO/Sandbox_KO.txt
Normal file
BIN
42/media/lua/shared/Translate/KO/Sandbox_KO.txt
Normal file
Binary file not shown.
BIN
42/media/lua/shared/Translate/KO/Tooltip_KO.txt
Normal file
BIN
42/media/lua/shared/Translate/KO/Tooltip_KO.txt
Normal file
Binary file not shown.
BIN
42/media/lua/shared/Translate/KO/UI_KO.txt
Normal file
BIN
42/media/lua/shared/Translate/KO/UI_KO.txt
Normal file
Binary file not shown.
33
42/media/lua/shared/Translate/RU/ContextMenu_RU.txt
Normal file
33
42/media/lua/shared/Translate/RU/ContextMenu_RU.txt
Normal 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 = "Моментально ампутировать",
|
||||
|
||||
}
|
||||
18
42/media/lua/shared/Translate/RU/IG_UI_RU.txt
Normal file
18
42/media/lua/shared/Translate/RU/IG_UI_RU.txt
Normal 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 = "Протез экипирован",
|
||||
|
||||
}
|
||||
11
42/media/lua/shared/Translate/RU/ItemName_RU.txt
Normal file
11
42/media/lua/shared/Translate/RU/ItemName_RU.txt
Normal 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 = "Протез руки - Крюк",
|
||||
}
|
||||
4
42/media/lua/shared/Translate/RU/Recipes_RU.txt
Normal file
4
42/media/lua/shared/Translate/RU/Recipes_RU.txt
Normal file
@@ -0,0 +1,4 @@
|
||||
Recipes_RU = {
|
||||
Recipe_Craft_Prosthetic_Arm = "Изготовить протез руки",
|
||||
Recipe_Craft_Prosthetic_Hook = "Изготовить протез ввиде крючка",
|
||||
}
|
||||
7
42/media/lua/shared/Translate/RU/Sandbox_RU.txt
Normal file
7
42/media/lua/shared/Translate/RU/Sandbox_RU.txt
Normal file
@@ -0,0 +1,7 @@
|
||||
Sandbox_RU = {
|
||||
Sandbox_TOC = "Спасенье в Отсечении",
|
||||
Sandbox_TOC_CicatrizationSpeed = "Скорость заживления",
|
||||
Sandbox_TOC_WoundDirtynessMultiplier = "Множитель загрязнения ран",
|
||||
Sandbox_TOC_SurgeonAbilityImportance = "Значимость способностей врача-хирурга",
|
||||
|
||||
}
|
||||
10
42/media/lua/shared/Translate/RU/Tooltip_RU.txt
Normal file
10
42/media/lua/shared/Translate/RU/Tooltip_RU.txt
Normal file
@@ -0,0 +1,10 @@
|
||||
Tooltip_RU = {
|
||||
|
||||
Tooltip_Surgery_CantCauterize = "Нельзя прижигать рану",
|
||||
|
||||
Tooltip_Surgery_And = " и "
|
||||
Tooltip_Surgery_TempTooLow = "Температура все еще слишком низкая",
|
||||
Tooltip_Surgery_Coward = "У тебя не хватит смелости сделать это",
|
||||
Tooltip_Surgery_LimbNotFree = "Сначала нужно снять протез",
|
||||
|
||||
}
|
||||
16
42/media/lua/shared/Translate/RU/UI_RU.txt
Normal file
16
42/media/lua/shared/Translate/RU/UI_RU.txt
Normal 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 = "Я не могу его так экипировать..."
|
||||
}
|
||||
31
42/media/lua/shared/Translate/TR/ContextMenu_TR.txt
Normal file
31
42/media/lua/shared/Translate/TR/ContextMenu_TR.txt
Normal 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
Reference in New Issue
Block a user