31 Commits

Author SHA1 Message Date
ZioPao
bd532dc013 fix: relayed amputations 2026-01-31 17:32:28 +01:00
ZioPao
1d21c0d51c fix: relay wear amputation 2026-01-31 17:21:10 +01:00
ZioPao
e129b325e4 fix: wearing amputation in MP 42.13 2026-01-27 23:01:56 +01:00
ZioPao
df9f559078 fix: working amputations in mp 2026-01-27 01:33:54 +01:00
ZioPao
1fb3899a5a chore: stuff to move around for 42.13 2026-01-15 22:37:13 +01:00
ZioPao
457f89b064 fix: error while amputating 2026-01-15 22:37:06 +01:00
ZioPao
27d79c5802 chore: removed old b41 tasks 2026-01-08 01:56:20 +01:00
ZioPao
92a0b9ef18 fix: encoding UA again 2026-01-08 01:53:02 +01:00
Vinellon
494b4b576f fix encoding for translate files 2026-01-08 01:43:35 +01:00
ZioPao
76fcb1ac97 Merge branch 'dev-42.13' of https://github.com/ZioPao/The-Only-Cure into dev-42.13-merge 2026-01-08 01:39:40 +01:00
ZioPao
fba1b2e643 fix: wip changes for traits and infection healing 2026-01-08 01:26:17 +01:00
ZioPao
2cf7df16b3 refactor: changes to StaticData and registries 2026-01-08 01:25:53 +01:00
ZioPao
898e8ec653 refactor: restored new bodylocs 2026-01-08 01:23:53 +01:00
guiriguy
943e3a8f3c Refactor prosthetic limb string constants
Updated string constants for prosthetic limbs and body locations.
2025-12-18 22:51:51 +01:00
guiriguy
442af10b7a Update Registries.lua 2025-12-18 22:51:27 +01:00
guiriguy
c9d6236b89 Refactor BodyLocations.lua for improved management
Refactored BodyLocations.lua to streamline body location management and improve functionality.
2025-12-18 22:51:06 +01:00
guiriguy
e884985fe3 Refactor player courage and temperature checks 2025-12-18 22:50:28 +01:00
guiriguy
38fe71bc72 Refactor ProsthesisHandler for B42 compatibility 2025-12-18 22:48:17 +01:00
guiriguy
b650b2a590 Refactor tourniquet check and update patient stats 2025-12-18 22:48:00 +01:00
guiriguy
da7621c0f0 Refactor LocalPlayerController to use TOC registries 2025-12-18 22:47:31 +01:00
guiriguy
acd2e9c547 Refactor TOC registries for traits and body locations 2025-12-18 22:46:57 +01:00
ZioPao
27d9b3a513 fix: bodyloc check for tourniquets 2025-12-16 01:02:51 +01:00
ZioPao
aa61a3390c fix: wrong dir for Translate 2025-12-16 00:56:06 +01:00
ZioPao
b84c2a593d fix: items bodylocs 2025-12-16 00:56:00 +01:00
ZioPao
cdf0473065 fix: Type to ItemType in items ZedScripts 2025-12-16 00:51:23 +01:00
ZioPao
40da330b41 fix: trait init in LocalPlayerController 2025-12-16 00:51:05 +01:00
ZioPao
20fa1bd05e refactor: removed compat with b41 entirely 2025-12-16 00:34:40 +01:00
ZioPao
3f888e7f22 fix: bodyloc for b42 mp 2025-12-14 10:39:28 +01:00
Vinellon
d84554ff07 fix encoding for translate files 2025-11-17 19:37:38 +03:00
Pao
ec87d128e4 Merge pull request #217 from ZioPao/dev
v2.2.2
2025-11-15 21:38:24 +01:00
Pao
b5266cd7cd Merge pull request #200 from ZioPao/dev
v2.1.7
2025-04-17 16:18:41 +02:00
324 changed files with 829 additions and 769 deletions

36
.vscode/tasks.json vendored
View File

@@ -9,12 +9,7 @@
"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 - B41"}},
"command": "python ${config:zomboid_user_folder}/PaosCrap/make_workshop_pack.py \"41\" \"picch\" \"${workspaceFolderBasename}\" \"\"",
},
{
"label": "Create Workshop folder",
"type": "shell",
@@ -33,24 +28,27 @@
"presentation": {
"group": "groupZomboid"
},
"command": "\"${config:zomboid_folder_b42}\\ProjectZomboid64 - nosteam-debug 42.bat\"",
"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 (41)",
"label": "Run Zomboid Debug No Steam (42) - 2nd Instance",
"type": "shell",
"presentation": {
"group": "groupZomboid"
},
"command": "\"${config:zomboid_folder_b41}\\ProjectZomboid64 - nosteam-debug.bat\"",
"options": {"statusbar": {"label": "$(run) Zomboid client (41)"}},
"command": "\"${config:zomboid_folder_b42}\\ProjectZomboid64_Debug_NoSteam.bat\"",
"options": {"statusbar": {"label": "$(run) Zomboid client (42) - 2nd Instance"}},
"problemMatcher": [
"$eslint-stylish"
]
},
// {
// "label": "Run Zomboid Debug No Steam",
// "type": "shell",
@@ -84,15 +82,15 @@
// "Run Zomboid Debug No Steam", "Run Zomboid Debug No Steam 2"],
// "problemMatcher": []
// },
// {
// "label": "Run Zomboid Test Server",
// "options": {"statusbar": {"label": "$(run) Zomboid Server (TOC)"}},
// "type": "shell",
// "command":"\"${config:zomboid_server_folder}\\StartServer64_nosteam_custom.bat\" TOC",
// "problemMatcher": [
// "$eslint-stylish"
// ]
// },
{
"label": "Run Zomboid Test Server",
"options": {"statusbar": {"label": "$(run) Zomboid Server (TOC)"}},
"type": "shell",
"command":"\"${config:zomboid_server_folder}\\StartServer64_nosteam_custom.bat\" TOC",
"problemMatcher": [
"$eslint-stylish"
]
},
// {
// "label": "Run Zomboid Test Server 2",
// "options": {"statusbar": {"label": "$(run) Zomboid Server (TOC+FH+BH)"}},

View File

@@ -1,10 +0,0 @@
local LimitActionsController = require("TOC/Controllers/LimitActionsController") -- declared in common
local OverridenMethodsArchive = require("TOC/OverridenMethodsArchive")
local og_ISClothingExtraAction_isValid = OverridenMethodsArchive.Get("ISClothingExtraAction_isValid")
---@diagnostic disable-next-line: duplicate-set-field
function ISClothingExtraAction:isValid()
-- TOC_DEBUG.print("Inside ISClothingExtraAction:isValid 42")
-- TOC_DEBUG.print(OverridenMethodsArchive.Get("ISClothingExtraAction_isValid"))
return LimitActionsController.WrapClothingAction(self, og_ISClothingExtraAction_isValid, instanceItem(self.extra))
end

View File

@@ -1,40 +0,0 @@
local ProsthesisHandler = require("TOC/Handlers/ProsthesisHandler") -- declared in common
local OverridenMethodsArchive = require("TOC/OverridenMethodsArchive")
local og_ISClothingExtraAction_isValid = OverridenMethodsArchive.Get("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
local testItem = instanceItem(self.extra)
return ProsthesisHandler.Validate(testItem, isEquippable)
end
local og_ISClothingExtraAction_perform = OverridenMethodsArchive.Get("ISClothingExtraAction_perform")
function ISClothingExtraAction:perform()
local extraItem = instanceItem(self.extra)
ProsthesisHandler.SearchAndSetupProsthesis(extraItem, true)
og_ISClothingExtraAction_perform(self)
end
local og_ISUnequipAction_complete = ISUnequipAction.complete
function ISUnequipAction:complete()
-- Horrendous workaround. For B42, as of now, it will basically happen two times, once with :perform and once with :complete. Shouldn't
-- matter for performance but it's really ugly.
-- local isProst = ProsthesisHandler.SearchAndSetupProsthesis(self.item, false)
-- local group
-- if isProst then
-- group = BodyLocations.getGroup("Human")
-- group:setMultiItem("TOC_ArmProst", false)
-- end
og_ISUnequipAction_complete(self)
-- if isProst then
-- group:setMultiItem("TOC_ArmProst", true)
-- end
end

View File

@@ -12,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
@@ -46,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()

View File

@@ -397,7 +397,7 @@ end
local og_ISClothingExtraAction_isValid = OverridenMethodsArchive.Save("ISClothingExtraAction_isValid", ISClothingExtraAction.isValid)
---@diagnostic disable-next-line: duplicate-set-field
function ISClothingExtraAction:isValid()
return LimitActionsController.WrapClothingAction(self, og_ISClothingExtraAction_isValid, InventoryItemFactory.CreateItem(self.extra))
return LimitActionsController.WrapClothingAction(self, og_ISClothingExtraAction_isValid, instanceItem(self.extra))
end

View File

@@ -1,8 +1,11 @@
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")
-----------
@@ -37,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
@@ -56,7 +58,7 @@ function LocalPlayerController.ManageTraits()
local AmputationHandler = require("TOC/Handlers/AmputationHandler")
for k, v in pairs(StaticData.TRAITS_BP) do
if playerObj:HasTrait(k) then
if playerObj:hasTrait(TOC.traits[k]) then
-- Once we find one, we should be done since they're exclusive
TOC_DEBUG.print("Player has amputation trait " .. k .. ", executing it")
local tempHandler = AmputationHandler:new(v, playerObj)
@@ -93,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)
@@ -110,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()
@@ -183,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
@@ -317,9 +320,10 @@ function LocalPlayerController.HandleSetCicatrization(dcInst, playerObj, limbNam
dcInst:setIsCicatrized(limbName, true)
dcInst:setCicatrizationTime(limbName, 0)
-- Set visuals for the amputation
local ItemsController = require("TOC/Controllers/ItemsController")
ItemsController.Player.OverrideAmputationItemVisuals(playerObj, limbName, true)
-- -- Set visuals for the amputation
sendClientCommand(CommandsData.modules.TOC_ITEMS, "OverrideAmputationItemVisuals",
{playerNum = playerObj:getOnlineID(), limbName = limbName, isCicatrized = true})
end
--* Object drop handling when amputation occurs

View File

@@ -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")
@@ -152,8 +155,8 @@ 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. This method doesn't check if the upper limb has been amputated or not, so if
@@ -174,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()
@@ -190,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
@@ -203,7 +216,7 @@ function AmputationHandler:execute(damagePlayer)
triggerEvent("OnAmputatedLimb", self.limbName)
end
---Deletes the instance
---Delete the instance
function AmputationHandler:close()
AmputationHandler.instance = nil
end

View File

@@ -9,7 +9,7 @@ local OverridenMethodsArchive = require("TOC/OverridenMethodsArchive")
---@class ProsthesisHandler
local ProsthesisHandler = {}
local bodylocArmProstBaseline = "TOC_ArmProst"
local bodylocArmProstBaseline = "toc:toc_armprost"
--local bodyLocLegProst = "TOC_LegProst"
---Check if the following item is a prosthesis or not
@@ -17,13 +17,12 @@ local bodylocArmProstBaseline = "TOC_ArmProst"
---@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(bodylocArmProstBaseline)
return item:getBodyLocation():toString():contains(bodylocArmProstBaseline)
end
---Get the grouping for the prosthesis
@@ -35,7 +34,7 @@ function ProsthesisHandler.GetGroup(item)
local bodyLocation = item:getBodyLocation()
local position
if bodyLocation:contains(bodylocArmProstBaseline) then
if bodyLocation:toString():contains(bodylocArmProstBaseline) then
position = "Top_"
else
TOC_DEBUG.print("Something is wrong, no position in this item")

View File

@@ -6,7 +6,7 @@ require("TOC/Events")
---@class Main
local Main = {
_version = "2.2.2"
_version = "2.3"
}
function Main.Start()

View File

@@ -87,7 +87,7 @@ function CleanWoundAction:perform()
TOC_DEBUG.print("CleanWound for " .. self.otherPlayer:getUsername())
if self.character:HasTrait("Hemophobic") then
if self.character:hasTrait("Hemophobic") then
self.character:getStats():setPanic(self.character:getStats():getPanic() + 15)
end

View File

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

View File

@@ -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:HasTrait("Desensitized") or pl:getPerkLevel(Perks.Strength) > 5
local isTempHighEnough = stoveObj:getCurrentTemperature() >= 250
local isPlayerCourageous = pl:hasTrait(CharacterTrait.BRAVE) or pl:hasTrait(CharacterTrait.DESENSITIZED) or pl:getPerkLevel(Perks.Strength) > 5
local isTempHighEnough = stoveObj:getCurrentTemperature()-1 >= 2.50
local isLimbFree = not dcInst:getIsProstEquipped(limbName)
TOC_DEBUG.print(stoveObj:getCurrentTemperature())
option.notAvailable = not(isPlayerCourageous and isTempHighEnough and isLimbFree)
if not isTempHighEnough then

View File

@@ -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!
@@ -47,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
@@ -93,11 +99,7 @@ function ItemsController.Player.DeleteAllOldAmputationItems(playerObj)
---@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.
@@ -105,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

View File

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

View File

@@ -21,7 +21,7 @@ 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, damagePlayer = true}
@@ -43,7 +43,7 @@ end
---@param args relayForcedAmputationParams
function ServerRelayCommands.RelayForcedAmputation(adminObj, args)
local patientPl = getPlayerByOnlineID(args.patientNum)
local adminNum = adminObj:getOnlineID()
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
@@ -53,7 +53,11 @@ function ServerRelayCommands.RelayForcedAmputation(adminObj, args)
sendServerCommand(patientPl, CommandsData.modules.TOC_RELAY, CommandsData.client.Relay.ReceiveForcedCicatrization, {limbName = args.limbName})
end
function ServerRelayCommands.DeleteAllOldAmputationItems(_, args)
local playerObj = getPlayerByOnlineID(args.playerNum)
local ItemsController = require("TOC/Controllers/ItemsController")
ItemsController.Player.DeleteAllOldAmputationItems(playerObj)
end
-------------------------

View File

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

View File

@@ -5,7 +5,8 @@ local CommandsData = {}
CommandsData.modules = {
TOC_DEBUG = "TOC_DEBUG",
TOC_RELAY = "TOC_RELAY"
TOC_RELAY = "TOC_RELAY",
TOC_ITEMS = "TOC_ITEMS"
}
CommandsData.client = {
@@ -15,6 +16,7 @@ CommandsData.client = {
--* APPLY *--
ReceiveApplyFromServer = "ReceiveApplyFromServer",
ReceiveWearAmputation = "ReceiveWearAmputation",
--* ADMIN ONLY --*
ReceiveExecuteInitialization = "ReceiveExecuteInitialization",

View File

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

View File

@@ -5,7 +5,6 @@
---@alias tocModDataType { limbs : limbsTable, prostheses : prosthesesTable, isIgnoredPartInfected : boolean, isAnyLimbCut : boolean}
---------------------------
-- _STR = Only strings, no index
-- _IND_STR = indexed Strings
-- _IND_BPT = Indexed BodyPartType
@@ -49,15 +48,6 @@ StaticData.PARTS_STR = {
"UpperArm"
}
-- TODO make it a bit more elegant
StaticData.MOD_BODYLOCS_BASE_IND_STR = {
TOC_ArmProst_L = "TOC_ArmProst_L",
TOC_ArmProst_R = "TOC_ArmProst_R",
TOC_Arm_L = "TOC_Arm_L",
TOC_Arm_R = "TOC_Arm_R",
--TOC_LegProst = "TOC_LegProst",
}
-- No "MAX" here.
StaticData.IGNORED_BODYLOCS_BPT = {
@@ -193,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
}
@@ -242,7 +232,7 @@ end
StaticData.TRAITS_BP = {
Amputee_Hand = "Hand_L",
Amputee_ForeArm = "ForeArm_L",
Amputee_UpperArm = "UpperArm_L"
Amputee_UpperArm = "UpperArm_L",
}
-----------------

View File

@@ -4,17 +4,17 @@ ContextMenu_FR = {
ContextMenu_Amputate_Stitch = "Amputer et suturer",
ContextMenu_Amputate_Stitch_Bandage = "Amputer, suturer et bander",
ContextMenu_Cauterize = "Cautériser",
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_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_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_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",
@@ -24,6 +24,6 @@ ContextMenu_FR = {
ContextMenu_CleanWound = "Nettoyer la plaie",
ContextMenu_Admin_TOC = "TOC",
ContextMenu_Admin_ResetTOC = "Réinitialiser les amputations",
ContextMenu_Admin_ResetTOC = "Réinitialiser les amputations",
ContextMenu_Admin_ForceAmputation = "Forcer l'amputation",
}

View File

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

View File

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

View File

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

View File

@@ -1,10 +1,10 @@
Sandbox_FR = {
Sandbox_TOC = "Le Seul Remède",
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_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",
Sandbox_TOC_ZombieAmputationDamageThreshold = "Seuil de dégâts pour amputations de zombies",
Sandbox_TOC_ZombieAmputationDamageChance = "Probabilité d'amputations de zombies",
}

View File

@@ -1,10 +1,10 @@
Tooltip_FR = {
Tooltip_Surgery_CantCauterize = "Vous ne pouvez pas cautériser la plaie",
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_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",
Tooltip_Surgery_LimbNotFree = "Vous devez d'abord retirer la prothése",
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@@ -0,0 +1,19 @@
IG_UI_TR = {
IGUI_perks_Amputations = "Amputasyonlar",
IGUI_perks_Side_R = "Sağ Taraf",
IGUI_perks_Side_L = "Sol Taraf",
IGUI_perks_Prosthesis = "Protez",
IGUI_perks_ProstFamiliarity = "Aşinalık",
IGUI_ItemCat_Prosthesis = "Protez",
IGUI_ItemCat_Surgery = "Cerrahi",
IGUI_ItemCat_Amputation = "Amputasyon",
IGUI_HealthPanel_Cicatrization = "Yara İyileşmesi",
IGUI_HealthPanel_Cicatrized = "İyileşti",
IGUI_HealthPanel_Cauterized = "Dağlandı",
IGUI_HealthPanel_WoundDirtyness = "Yara Kirliliği",
IGUI_HealthPanel_ProstEquipped = "Protez Takılı",
IGUI_Confirmation_Amputate = " <CENTRE> Bu uzvu gerçekten ampute etmek istiyor musunuz?"
}

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