reworking

This commit is contained in:
ZioPao
2023-11-06 04:16:43 +01:00
parent d79dfcc509
commit 875e0fdceb
207 changed files with 113 additions and 2 deletions

View File

@@ -0,0 +1,294 @@
------------------------------------------
-------------- THE ONLY CURE -------------
------------------------------------------
----------- CUT LIMB FUNCTIONS -----------
-- Seems to be the first file loaded, so let's add this
if TOC == nil then
TOC = {}
end
local function CheckIfStillInfected(limbsData)
if limbsData == nil then
return
end
-- Check ALL body part types to check if the player is still gonna die
local check = false
for _, v in pairs(TOC_Common.GetPartNames()) do
if limbsData[v].isInfected then
check = true
end
end
if limbsData.isOtherBodypartInfected then
check = true
end
return check
end
local function CureInfection(bodyDamage, partName)
local bodyPartType = bodyDamage:getBodyPart(TOC_Common.GetBodyPartFromPartName(partName))
bodyDamage:setInfected(false)
bodyPartType:SetInfected(false)
bodyDamage:setInfectionMortalityDuration(-1)
bodyDamage:setInfectionTime(-1)
bodyDamage:setInfectionLevel(0)
local bodypartTypesTable = bodyDamage:getBodyParts()
-- TODO I think this is enough... we should just cycle if with everything instead of that crap up there
for i = bodypartTypesTable:size() - 1, 0, -1 do
local bodyPart = bodypartTypesTable:get(i)
bodyPart:SetInfected(false)
end
if bodyPartType:scratched() then bodyPartType:setScratched(false, false) end
if bodyPartType:haveGlass() then bodyPartType:setHaveGlass(false) end
if bodyPartType:haveBullet() then bodyPartType:setHaveBullet(false, 0) end
if bodyPartType:isInfectedWound() then bodyPartType:setInfectedWound(false) end
if bodyPartType:isBurnt() then bodyPartType:setBurnTime(0) end
if bodyPartType:isCut() then bodyPartType:setCut(false, false) end --Lacerations
if bodyPartType:getFractureTime() > 0 then bodyPartType:setFractureTime(0) end
end
local function DeleteOtherAmputatedLimbs(side)
-- if left hand is cut and we cut left lowerarm, then delete hand
for _, limb in pairs(TOC.limbNames) do
local partName = "TOC.Amputation_" .. TOC_Common.ConcatPartName(side, limb)
local amputatedLimbItem = getPlayer():getInventory():FindAndReturn(partName)
if amputatedLimbItem then
getPlayer():getInventory():Remove(amputatedLimbItem)
end
end
end
---@param player any
---@param perk any The perk to scale down
local function LosePerkLevel(player, perk)
player:LoseLevel(perk)
local actualLevel = player:getPerkLevel(perk)
local perkXp = player:getXp()
perkXp:setXPToLevel(perk, actualLevel)
SyncXp(player)
end
---@param isHealingBite boolean
local function SetParametersForMissingLimb(bodyPart, isHealingBite)
bodyPart:setBleeding(false)
bodyPart:setBleedingTime(0)
bodyPart:setDeepWounded(false)
bodyPart:setDeepWoundTime(0)
bodyPart:setScratched(false, false) -- why the fuck are there 2 booleans TIS?
bodyPart:setScratchTime(0)
bodyPart:setCut(false)
bodyPart:setCutTime(0)
if isHealingBite then
bodyPart:SetBitten(false)
bodyPart:setBiteTime(0)
end
end
function TOC.DamagePlayerDuringAmputation(patient, partName)
-- Since we're cutting that specific part, it only makes sense that the bleeding starts from there.
-- Then, we just delete the bleeding somewhere else before applying the other damage to to upper part of the limb
local bodyPartType = TOC_Common.GetBodyPartFromPartName(partName)
local bodyDamage = patient:getBodyDamage()
local bodyDamagePart = bodyDamage:getBodyPart(bodyPartType)
bodyDamagePart:setBleeding(true)
bodyDamagePart:setCut(true)
bodyDamagePart:setBleedingTime(ZombRand(10, 20))
end
local function FindTourniquetInWornItems(patient, side)
local checkString = "Surgery_" .. side .. "_Tourniquet"
local item = TOC_Common.FindItemInWornItems(patient, checkString)
return item
end
local function FindWristWatchInWornItems(patient, side)
local checkString = "Watch_" .. side
local item = TOC_Common.FindItemInWornItems(patient, checkString)
return item
end
----------------------------------------------------------------------------------
--- Main function for cutting a limb
---@param partName string the part name to amputate
---@param surgeonFactor any the surgeon factor, which will determine some stats for the inflicted wound
---@param bandageTable any bandages info
---@param painkillerTable any painkillers info, not used
TOC.CutLimb = function(partName, surgeonFactor, bandageTable, painkillerTable)
-- TODO Separate Cut Limb in side and limb instead of single part_name
-- Items get unequipped in ISCutLimb.Start
local player = getPlayer()
local TOCModData = player:getModData().TOC
local limbParameters = TOC.limbParameters
local limbsData = TOCModData.limbs
-- Cut Hand -> Damage in forearm
-- Cut Forearm -> Damage in Upperarm
-- Cut UpperArm -> Damage to torso
local bodyDamage = player:getBodyDamage()
local bodyPart = bodyDamage:getBodyPart(TOC_Common.GetBodyPartFromPartName(partName))
local adjacentBodyPart = player:getBodyDamage():getBodyPart(TOC_Common.GetAdjacentBodyPartFromPartName(partName))
local stats = player:getStats()
local side = TOC_Common.GetSideFromPartName(partName)
-- Reset the status of the first body part, since we just cut it off it shouldn't be bleeding anymore
-- The bit will be checked later since we're not sure if the player is not infected from another wound
SetParametersForMissingLimb(bodyPart, false)
-- Use a tourniquet if available
local tourniquetItem = FindTourniquetInWornItems(player, side)
local baseDamageValue = 100
if tourniquetItem ~= nil then
baseDamageValue = 50 -- TODO Decrease mostly blood and damage, add pain, not everything else
if partName == TOC_Common.ConcatPartName(side, "UpperArm") then
player:removeWornItem(tourniquetItem)
end
end
-- Removes wrist watches in case they're amputating the same side where they equipped it
local wristWatchItem = FindWristWatchInWornItems(player, side)
if wristWatchItem ~= nil then
if partName == side .. "_LowerArm" or partName == side .. "_UpperArm" then
player:removeWornItem(wristWatchItem)
end
end
-- Set damage, stress, and low endurance after amputation
adjacentBodyPart:AddDamage(baseDamageValue - surgeonFactor)
adjacentBodyPart:setAdditionalPain(baseDamageValue - surgeonFactor)
adjacentBodyPart:setBleeding(true)
adjacentBodyPart:setBleedingTime(baseDamageValue - surgeonFactor)
adjacentBodyPart:setDeepWounded(true)
adjacentBodyPart:setDeepWoundTime(baseDamageValue - surgeonFactor)
stats:setEndurance(surgeonFactor)
stats:setStress(baseDamageValue - surgeonFactor)
-- Set malus for strength and fitness
-- TODO Make it more "random" with just some XP scaling down instead of a whole level, depending on the limb that we're cutting
LosePerkLevel(player, Perks.Fitness)
LosePerkLevel(player, Perks.Strength)
-- If bandages are available, use them
adjacentBodyPart:setBandaged(bandageTable.useBandage, 10, bandageTable.isBandageSterilized,
bandageTable.bandageType)
-- If painkillers are available, use them
-- TODO add painkiller support
-- A check for isCut shouldn't be necessary here since if we've got here we've already checked it out enough
if limbsData[partName].isCut == false then
limbsData[partName].isCut = true
limbsData[partName].isAmputationShown = true
limbsData[partName].cicatrizationTime = limbParameters[partName].cicatrizationBaseTime - surgeonFactor * 50
for _, depended_v in pairs(limbParameters[partName].dependsOn) do
limbsData[depended_v].isCut = true
limbsData[depended_v].isAmputationShown = false
limbsData[depended_v].cicatrizationTime = limbParameters[partName].cicatrizationBaseTime -
surgeonFactor * 50
local canHealDependedV = limbsData[depended_v].isInfected and
bodyDamage:getInfectionLevel() < 20
local depended_body_part = bodyDamage:getBodyPart(TOC_Common.GetBodyPartFromPartName(depended_v))
SetParametersForMissingLimb(depended_body_part, canHealDependedV)
if canHealDependedV then
limbsData[depended_v].isInfected = false
end
end
-- Heal the infection here
local body_damage = player:getBodyDamage()
if limbsData[partName].isInfected and body_damage:getInfectionLevel() < 20 then
limbsData[partName].isInfected = false
-- NOT THE ADIACENT ONE!!!
bodyPart:SetBitten(false)
bodyPart:setBiteTime(0)
-- Second check, let's see if there is any other infected limb.
if CheckIfStillInfected(limbsData) == false then
CureInfection(body_damage, partName)
getPlayer():Say("I'm gonna be fine...") -- TODO Make it visible to other players, check True Actions as reference
else
getPlayer():Say("I'm still gonna die...")
end
end
-- Check for older amputation models and deletes them from player's inventory
local side = string.match(partName, '(%w+)_')
DeleteOtherAmputatedLimbs(side)
--Equip new model for amputation
local amputation_clothing_item_name = TOC_Common.FindAmputatedClothingName(partName)
print(amputation_clothing_item_name)
local amputation_clothing_item = player:getInventory():AddItem(amputation_clothing_item_name)
TOC_Visuals.SetTextureForAmputation(amputation_clothing_item, player, false)
player:setWornItem(amputation_clothing_item:getBodyLocation(), amputation_clothing_item)
-- Set blood on the amputated limb
TOC_Visuals.SetBloodOnAmputation(getPlayer(), adjacentBodyPart)
if partName == "Left_Foot" or partName == "Right_Foot" then
TOC_Anims.SetMissingFootAnimation(true)
end
end
end

View File

@@ -0,0 +1,51 @@
------------------------------------------
-------------- THE ONLY CURE -------------
------------------------------------------
------------- LOCAL ACTIONS --------------
--Used to handle SP scenarios
if TOC_LocalActions == nil then
TOC_LocalActions = {}
end
function TOC_LocalActions.Cut(_, player, partName)
if TOC_Common.GetSawInInventory(player) ~= nil then
ISTimedActionQueue.add(TOC_CutLimbAction:new(player, player, partName))
else
player:Say("I don't have a saw on me")
end
end
function TOC_LocalActions.Operate(_, player, partName, useOven)
if useOven then
ISTimedActionQueue.add(TOC_OperateLimbAction:new(player, player, _, partName, useOven));
else
local kit = TOC_Common.GetKitInInventory(player)
if kit ~= nil then
ISTimedActionQueue.add(TOC_OperateLimbAction:new(player, player, kit, partName, false))
else
player:Say("I don't have a kit on me")
end
end
end
function TOC_LocalActions.EquipProsthesis(_, player, partName)
local surgeonInv = player:getInventory()
-- TODO Find a better way to filter objects. Disabled for now and only gets LeatherBase
local prosthesisToEquip = surgeonInv:getItemFromType('TOC.LeatherBase_MetalHook')
if prosthesisToEquip then
ISTimedActionQueue.add(TOC_InstallProsthesisAction:new(player, player, prosthesisToEquip, partName))
else
player:Say("I need a prosthesis")
end
end
function TOC_LocalActions.UnequipProsthesis(_, player, partName)
ISTimedActionQueue.add(TOC_UninstallProsthesisAction:new(player, player, partName))
end

View File

@@ -0,0 +1,73 @@
------------------------------------------
-------- THE ONLY CURE --------
------------------------------------------
--------- OPERATE LIMB FUNCTIONS ---------
local function FixSingleBodyPartType(bodyPartType, useOven)
bodyPartType:setDeepWounded(false) --Basically like stitching
bodyPartType:setDeepWoundTime(0)
if useOven then
bodyPartType:AddDamage(100)
bodyPartType:setAdditionalPain(100);
bodyPartType:setBleeding(false)
bodyPartType:setBleedingTime(0) -- no bleeding since it's been cauterized
else
-- TODO Think a little better about this, do we want to trigger bleeding or not?
bodyPartType:setBleeding(false)
--body_part_type:setBleedingTime(ZombRand(1, 5)) -- Reset the bleeding, maybe make it random
end
end
local function SetBodyPartsStatusAfterOperation(player, limbParameters, partName, useOven)
local bodyPartType = player:getBodyDamage():getBodyPart(TOC_Common.GetAdjacentBodyPartFromPartName(partName))
FixSingleBodyPartType(bodyPartType, useOven)
for _, v in pairs(limbParameters[partName].dependsOn) do
local dependedBodyPartType = player:getBodyDamage():getBodyPart(TOC_Common.GetAdjacentBodyPartFromPartName(v))
FixSingleBodyPartType(dependedBodyPartType, useOven)
end
end
----------------------------------------------------------------------------------
---Main function to operate a limb after amputation
---@param partName any
---@param surgeonFactor any
---@param useOven boolean wheter using oven instead of a kit or not
function TOC.OperateLimb(partName, surgeonFactor, useOven)
local player = getPlayer()
local TOCModData = player:getModData().TOC
local limbParameters = TOC.limbParameters
local limbsData = TOCModData.limbs
if useOven then
local stats = player:getStats()
stats:setEndurance(100)
stats:setStress(100)
end
if limbsData[partName].isOperated == false and limbsData[partName].isCut == true then
limbsData[partName].isOperated = true
limbsData[partName].cicatrizationTime = limbsData[partName].cicatrizationTime - (surgeonFactor * 200)
if useOven then limbsData[partName].isCauterized = true end
for _, dependedPart in pairs(limbParameters[partName].dependsOn) do
limbsData[dependedPart].isOperated = true
-- TODO We should not have cicatrization time for depended parts.
-- limbsData[dependedPart].cicatrizationTime = limbsData[dependedPart].cicatrizationTime -
-- (surgeonFactor * 200)
if useOven then limbsData[dependedPart].isCauterized = true end
end
end
SetBodyPartsStatusAfterOperation(player, limbParameters, partName, useOven)
end

View File

@@ -0,0 +1,85 @@
------------------------------------------
------------- THE ONLY CURE --------------
------------------------------------------
---------- PROSTHESIS FUNCTIONS ----------
---Equip a prosthesis transforming a normal item into a clothing item
---@param partName string
---@param prosthesisItem any the prosthesis item
---@param prosthesisBaseName string I don't really remember
function TOC.EquipProsthesis(partName, prosthesisItem, prosthesisBaseName)
-- TODO probably will have to move this from the TOC menu to classic equip to have dynamic durability
-- TODO We need to pass the original item so we can get its data!
local player = getPlayer()
local TOCModData = player:getModData().TOC
local equippedProsthesis = GenerateEquippedProsthesis(prosthesisItem, player:getInventory(), partName)
--print("TOC: Test durability new item " .. added_prosthesis_mod_data.TOC.durability)
-- TODO equippedProsthesis must have something like the ProsthesisFactor from before!!!
if partName ~= nil then
if equippedProsthesis ~= nil then
TOCModData.limbs[partName].isProsthesisEquipped = true
-- Fill equippedProsthesis with the correct stuff
-- TODO For prosthetics we should fetch the data from a modData INSIDE them!
-- TODO Change the value passed, it's wrong
--TOCModData.limbs[partName].equippedProsthesis = TOCModData.Prosthesis[prosthesisBaseName][partName]
if player:isFemale() then
equippedProsthesis:getVisual():setTextureChoice(1)
else
equippedProsthesis:getVisual():setTextureChoice(0)
end
player:setWornItem(equippedProsthesis:getBodyLocation(), equippedProsthesis)
end
end
end
---Unequip a prosthesis clothing item and returns it to the inventory as a normal item
---@param partName string
function TOC.UnequipProsthesis(patient, partName, equippedProsthesis)
-- TODO Pass the parameters generated from EquipProsthesis to the re-generated normal item
local TOCModData = patient:getModData().TOC
TOCModData.limbs[partName].isProsthesisEquipped = false
local equippedProstFullType = equippedProsthesis:getFullType()
for _, prostValue in ipairs(GetProsthesisList()) do
local prostName = string.match(equippedProstFullType, prostValue)
if prostName then
-- Get mod data from equipped prosthesis so we can get its parameters
local equippedProstModData = equippedProsthesis:getModData()
local baseProstItem = patient:getInventory():AddItem("TOC." .. prostName)
local baseProstItemModData = baseProstItem.getModData()
baseProstItemModData.TOC = {
durability = equippedProstModData.TOC.durability,
speed = equippedProstModData.TOC.speed
}
patient:setWornItem(equippedProsthesis:getBodyLocation(), nil)
patient:getInventory():Remove(equippedProsthesis)
TOCModData.limbs[partName].equippedProsthesis = nil
end
end
end