28 Commits

Author SHA1 Message Date
ZioPao
013f852e7e Fixed huge bug that would break things after a player died 2024-05-06 17:14:45 +02:00
ZioPao
a7a064119d Added destroy instance in DataController after death 2024-05-05 21:07:33 +02:00
ZioPao
9b1876b235 mod.info and version bump 2024-05-05 18:04:10 +02:00
ZioPao
0d9ee4203c Revert "Revert "Added tests for blood on limbs""
This reverts commit 2ea03601f5.
2024-05-05 18:03:39 +02:00
ZioPao
2ea03601f5 Revert "Added tests for blood on limbs"
This reverts commit 3d4a54418c.
2024-05-05 18:03:08 +02:00
ZioPao
3d4a54418c Added tests for blood on limbs 2024-05-05 18:02:48 +02:00
ZioPao
17718cbbca bit of cleaning 2024-05-05 17:02:14 +02:00
ZioPao
f9ad597d2b bump to mod.info 2024-05-05 17:01:40 +02:00
ZioPao
c8b6a8c5ed Wash Yourself override 2024-05-05 16:58:16 +02:00
ZioPao
9478e0faa1 Added ProstFamiliarity in adjustMaxTime function 2024-05-05 13:56:58 +02:00
ZioPao
d512f0ba81 bump to mod.info and _version 2024-05-05 13:51:03 +02:00
ZioPao
31995965f9 Added leveling for ProstFamiliarity, dynamic xp 2024-05-05 13:50:47 +02:00
ZioPao
d35840d825 Added level scaling for prosthetics 2024-05-05 13:27:20 +02:00
ZioPao
e270b4f73b updated steam desc 2024-05-05 12:38:20 +02:00
ZioPao
4757d9dfa8 bump to modversion 2024-05-05 01:00:49 +02:00
ZioPao
1b235ebaa4 bump to mod.info 2024-05-05 00:49:05 +02:00
Pao
44d486dfeb Merge pull request #36 from ZioPao/main
backmerge to dev since I'm an idiot
2024-05-05 00:48:40 +02:00
ZioPao
5cc982188a Fixed prosthesis not working correctly 2024-05-05 00:47:50 +02:00
ZioPao
aadbe02df4 Fixed sync with server after setup to prevent issues with medical check 2024-05-05 00:14:37 +02:00
Pao
20bed84910 Merge pull request #33 from ZioPao/dev
v2.0.2
2024-05-04 18:00:40 +02:00
ZioPao
fc3113f243 Bump to mod info and description 2024-05-04 17:59:53 +02:00
ZioPao
be368738ba Fix to cicatrization visuals with traits 2024-05-04 17:11:38 +02:00
ZioPao
4209f690a8 Added IT translation 2024-05-04 16:45:57 +02:00
ZioPao
a3a2614124 Fixed traits 2024-05-04 16:27:46 +02:00
ZioPao
50f6db9344 Added check to prevent incompatibilities with other mods 2024-05-04 15:35:25 +02:00
Pao
17d554d269 Merge pull request #28 from ZioPao/main
back merge from main to dev
2024-05-03 14:25:25 +02:00
ZioPao
1bef713de5 Merge branch 'main' of https://github.com/ZioPao/The-Only-Cure 2024-05-03 14:20:59 +02:00
Pao
92334b2f54 Update README.md 2024-05-02 20:41:18 +02:00
30 changed files with 422 additions and 93 deletions

View File

@@ -7,7 +7,7 @@
<img src='https://img.shields.io/badge/Steam-000000?style=for-the-badge&logo=steam&logoColor=white' />
</a>
</p>
# You're bitten. You have two choices.
You're bitten. You have two choices.
Wait until you succumb to the virus or take matters into your hands. Cut off that infected part and live to die another day.
This version of **The Only Cure** has been rebuilt from scratch to support future additions and to feel as close as possible as a vanilla mechanic.
@@ -16,7 +16,6 @@ This version of **The Only Cure** has been rebuilt from scratch to support futur
Supports **Single Player** and **Multiplayer**!
# Setup
Use it with the following mods for the intended experience:
- [Fancy Handwork](https://steamcommunity.com/sharedfiles/filedetails/?id=2904920097)

Binary file not shown.

After

Width:  |  Height:  |  Size: 540 KiB

View File

@@ -6,9 +6,9 @@ Wait until you succumb to the virus or take matters into your hands. Cut off tha
This version of [b]The Only Cure[/b] has been rebuilt from scratch to support future additions and to feel as close as possible as a vanilla mechanic.
[b]If you're using an older version of The Only Cure and want to switch with this, you're gonna need to create a new character\save to prevent issues.[/b]
[b]The older version will be delisted shortly and it will not be supported anymore.[/b]
Supports [b]Single Player[/b] and [b]Multiplayer[/b]!
[h1]Supports [b]Single Player[/b] and [b]Multiplayer[/b]. Host Mode is currently [b]UNSUPPORTED![/b][/h1]
[h1]Setup[/h1]
Use it with the following mods for the intended experience:
@@ -17,6 +17,8 @@ Use it with the following mods for the intended experience:
[*] [url=https://steamcommunity.com/sharedfiles/filedetails/?id=2934621024]Brutal Handwork[/url]
[/list]
Place them [b]BEFORE[/b] The Only Cure in your mod list!
[hr][/hr]
[h1]Quick guide[/h1]
@@ -74,6 +76,10 @@ Got any issues or found some pesky bugs? Report them on GitHub!
[th]dhert[/th]
[th]Compatibility API[/th]
[/tr]
[tr]
[th]JCloudJalix[/th]
[th]German translation[/th]
[/tr]
[/table]
[hr][/hr]

View File

@@ -57,6 +57,7 @@ function DataController:setup(key)
---@type tocModDataType
self.tocData = {
-- Generic stuff that does not belong anywhere else
isInitializing = true,
isIgnoredPartInfected = false,
isAnyLimbCut = false,
limbs = {},
@@ -86,9 +87,16 @@ 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()
-- -- Disable lock
-- self.tocData.isInitializing = false
-- ModData.add(key, self.tocData)
end
---In case of desync between the table on ModData and the table here
@@ -100,7 +108,7 @@ function DataController:applyOnlineData(tocData)
end
---@param key string
function DataController:loadLocalData(key)
function DataController:tryLoadLocalData(key)
self.tocData = ModData.get(key)
--TOC_DEBUG.printTable(self.tocData)
@@ -368,10 +376,13 @@ 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")
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
@@ -387,14 +398,17 @@ 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
elseif data and data.limbs then
-- Let's validate that the data structure is actually valid to prevent issues
if data.isUpdateFromServer then
TOC_DEBUG.print("Update from the server")
end
handler:applyOnlineData(data)
elseif username == getPlayer():getUsername() then
handler:loadLocalData(key)
TOC_DEBUG.print("loading local data")
handler:tryLoadLocalData(key)
end
@@ -434,7 +448,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 +476,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

View File

@@ -15,8 +15,12 @@ local StaticData = require("TOC/StaticData")
-- a prosthesis on, that can trigger random bleeds.
local function CheckHandFeasibility(limbName)
TOC_DEBUG.print("Checking hand feasibility: " .. 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
@@ -39,13 +43,18 @@ function ISBaseTimedAction:adjustMaxTime(maxTime)
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
end
end
return time
@@ -59,22 +68,31 @@ function ISBaseTimedAction:perform()
og_ISBaseTimedAction_perform(self)
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
local amputatedLimbs = CachedDataHandler.GetAmputatedLimbs(LocalPlayerController.username)
local xp = self.maxTime/100
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
LocalPlayerController.playerObj:getXp():AddXP(Perks["Side_" .. side], xp)
if not dcInst:getIsCicatrized(limbName) and dcInst:getIsProstEquipped(limbName) then
TOC_DEBUG.print("Trying for bleed, player met the criteria")
LocalPlayerController.TryRandomBleed(self.character, limbName)
end
-- Level up prosthesis perk
if dcInst:getIsProstEquipped(limbName) then
LocalPlayerController.playerObj:getXp():AddXP(Perks["ProstFamiliarity"], xp)
end
end
end
end
@@ -107,6 +125,8 @@ end
---A recreation of the original method, but with amputations in mind
---@param dcInst DataController
function ISEquipWeaponAction:performWithAmputation(dcInst)
TOC_DEBUG.print("running ISEquipWeaponAction performWithAmputation")
local hand = nil
local otherHand = nil
local getMethodFirst = nil
@@ -130,6 +150,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 +169,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 +180,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))

View File

@@ -33,6 +33,9 @@ function LocalPlayerController.InitializePlayer(isForced)
Events.OnAmputatedLimb.Add(LocalPlayerController.ToggleUpdateAmputations)
LocalPlayerController.ToggleUpdateAmputations()
-- Manage their traits
LocalPlayerController.ManageTraits(playerObj)
-- Since isForced is used to reset an existing player data, we're gonna clean their ISHealthPanel table too
if isForced then
local ItemsController = require("TOC/Controllers/ItemsController")
@@ -47,13 +50,16 @@ end
---Handles the traits
---@param playerObj IsoPlayer
function LocalPlayerController.ManageTraits(playerObj)
local AmputationHandler = require("Handlers/TOC_AmputationHandler")
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)
-- Once we find one, we should be done since they're exclusive
local tempHandler = AmputationHandler:new(v, playerObj)
tempHandler:execute(false) -- No damage
tempHandler:close()
-- The wound should be already cicatrized
LocalPlayerController.HandleSetCicatrization(DataController.GetInstance(), playerObj, v)
return
end
end
@@ -257,14 +263,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 +288,23 @@ 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(tostring(limbName) .. " is cicatrized")
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)
end
--* Object drop handling when amputation occurs
@@ -334,10 +354,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)

View File

@@ -1,3 +1,4 @@
--* Setup Events *--
LuaEventManager.AddEvent("OnAmputatedLimb") --Triggered when a limb has been amputated
LuaEventManager.AddEvent("OnProsthesisUnequipped")
LuaEventManager.AddEvent("OnReceivedTocData") -- Triggered when TOC data is ready

View File

@@ -111,6 +111,8 @@ end
--* Hand feasibility caching *--
CachedDataHandler.handFeasibility = {}

View File

@@ -70,7 +70,6 @@ function ProsthesisHandler.CheckIfEquippable(fullType)
return false
end
---Handle equipping or unequipping prosthetics
---@param item InventoryItem
---@param isEquipping boolean
@@ -133,8 +132,6 @@ function ISClothingExtraAction:isValid()
return HandleProsthesisValidation(testItem, isEquippable)
end
--[[
Horrendous workaround
@@ -148,8 +145,8 @@ end
local og_ISClothingExtraAction_perform = ISClothingExtraAction.perform
function ISClothingExtraAction:perform()
--local extraItem = InventoryItemFactory.CreateItem(self.extra)
local isProst = ProsthesisHandler.SearchAndSetupProsthesis(self.item, true)
local extraItem = InventoryItemFactory.CreateItem(self.extra)
local isProst = ProsthesisHandler.SearchAndSetupProsthesis(extraItem, true)
local group
if isProst then
group = BodyLocations.getGroup("Human")
@@ -161,7 +158,6 @@ function ISClothingExtraAction:perform()
if isProst then
group:setMultiItem("TOC_ArmProst", true)
end
end
local og_ISUnequipAction_perform = ISUnequipAction.perform
@@ -176,8 +172,15 @@ function ISUnequipAction:perform()
if isProst then
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]
triggerEvent("OnProsthesisUnequipped", hal)
end
end
end
return ProsthesisHandler

View File

@@ -6,39 +6,11 @@ require("TOC/Events")
---@class Main
local Main = {
_version = 2.0
_version = "2.0.7"
}
---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,14 @@ 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
local DataController = require("TOC/Controllers/DataController")
DataController.DestroyInstance(username)
end
--* Events *--

View File

@@ -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
@@ -154,6 +153,38 @@ TestFramework.registerTestModule("Various", "Player", function()
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)
--------------------------------------------------------------------------------------
if not getActivatedMods():contains("PerfTestFramework") or not isDebugEnabled() then return end

View File

@@ -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)

View File

@@ -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

View File

@@ -29,12 +29,15 @@ 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
table.isUpdateFromServer = true -- FIX this is useless as of now
ModData.add(key, table) -- Add it to the server mod data
ServerDataHandler.modData[key] = table
-- 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)

View File

@@ -2,7 +2,7 @@
---@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, isUpdateFromServer : boolean, isInitializing : boolean}
---------------------------
@@ -232,9 +232,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"
}
-----------------

View File

@@ -0,0 +1,49 @@
---Setups the custom TOC traits
local TRAITS = {
Amputee_Hand = "Amputee_Hand",
Amputee_ForeArm = "Amputee_ForeArm",
Amputee_UpperArm = "Amputee_UpperArm",
Insensitive = "Insensitive"
}
local function GetTraitText(trait)
return getText("UI_trait_" .. trait)
end
local function GetTraitDesc(trait)
return getText("UI_trait_" .. trait .. "_desc")
end
local function SetupTraits()
-- Perks.Left_Hand is defined in perks.txt
local traitsTable = {
[1] = TraitFactory.addTrait(TRAITS.Amputee_Hand, GetTraitText(TRAITS.Amputee_Hand), -8, GetTraitDesc(TRAITS.Amputee_Hand), false, false),
[2] = TraitFactory.addTrait(TRAITS.Amputee_ForeArm, GetTraitText(TRAITS.Amputee_ForeArm), -10, GetTraitDesc(TRAITS.Amputee_ForeArm), false, false),
[3] = TraitFactory.addTrait(TRAITS.Amputee_UpperArm, GetTraitText(TRAITS.Amputee_UpperArm), -20, GetTraitDesc(TRAITS.Amputee_UpperArm), 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(TRAITS.Insensitive, GetTraitText(TRAITS.Insensitive), 6, GetTraitDesc(TRAITS.Insensitive), false, false)
TraitFactory.setMutualExclusive(TRAITS.Amputee_Hand, TRAITS.Amputee_ForeArm)
TraitFactory.setMutualExclusive(TRAITS.Amputee_Hand, TRAITS.Amputee_UpperArm)
TraitFactory.setMutualExclusive(TRAITS.Amputee_ForeArm, TRAITS.Amputee_UpperArm)
end
Events.OnGameBoot.Add(SetupTraits)

View File

@@ -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",

View File

@@ -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 = "",

View 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",
}

View File

@@ -0,0 +1,18 @@
IG_UI_IT = {
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",
}

View 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",
}

View 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",
}

View 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",
}

View 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",
}

View 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..."
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 237 B

View File

@@ -1,8 +1,8 @@
name=The Only Cure
poster=poster.png
description=Bitten? Not a problem!
description=You've been bitten. You have only two choices.
id=TheOnlyCure
icon=icon.png
url=https://github.com/ZioPao/The-Only-Cure
modversion=2.0.1
modversion=2.0.7
pzversion=41.65