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,142 @@
------------------------------------------
-------------- THE ONLY CURE -------------
------------------------------------------
---------- COMPATIBILITY FUNCS -----------
if TOC_Compat == nil then
TOC_Compat = {}
end
-- Gets the old status and turns it into the new.
TOC_Compat.CheckCompatibilityWithOlderVersions = function(modData)
if modData.TOC ~= nil then
print("TOC: found old data from TOC")
if modData.TOC.Limbs ~= nil then
TOC_Compat.MapOldDataToNew(modData)
modData.TOC = nil -- Deletes the old mod data stuff
else
print("TOC: something is wrong, couldn't find Limbs table in old TOC modData")
end
else
print("TOC: couldn't find old TOC data")
end
end
TOC_Compat.MapOldDataToNew = function(modData)
local oldNamesTable = { "RightHand", "RightForearm", "RightArm", "LeftHand", "LeftForearm", "LeftArm" }
local newNamesTable = { "Right_Hand", "Right_LowerArm", "Right_UpperArm", "Left_Hand", "Left_LowerArm", "Left_UpperArm" }
print("TOC: Trying to backup old data from TOC")
if modData == nil then
return
end
print("TOC: found old data from TOC")
TOC_Cheat.ResetEverything()
-- Another check just in case the user is using Mr Bounty og version. I really don't wanna map that out so let's just reset everything directly
local compatEnum = nil
-- Player has the og version of the mod
if modData.TOC.Limbs.RightHand.IsCut ~= nil then
print("TOC: Found TOC Beta data")
compatEnum = 1
elseif modData.TOC.Limbs.Right_Hand.is_cut ~= nil then
print("TOC: Found TOCBB data")
compatEnum = 2
end
if compatEnum == nil then
print("TOC: Couldn't find any compatible data that could be retrieved")
return
end
-- Key setup
local isCutOldKey = nil
local isInfectedOldKey = nil
local isOperatedOldKey = nil
local isCicatrizedOldKey = nil
local isCauterizedOldKey = nil
local isAmputationShownOldKey = nil
local cicatrizationTimeOldKey = nil
local isOtherBodypartInfectedOldKey = nil
if compatEnum == 1 then
isCutOldKey = "IsCut"
isInfectedOldKey = "IsInfected"
isOperatedOldKey = "IsOperated"
isCicatrizedOldKey = "IsCicatrized"
isCauterizedOldKey = "ISBurn"
isAmputationShownOldKey = "ToDisplay"
cicatrizationTimeOldKey = "CicaTimeLeft"
isOtherBodypartInfectedOldKey = "OtherBody_IsInfected"
elseif compatEnum == 2 then
isCutOldKey = "is_cut"
isInfectedOldKey = "is_infected"
isOperatedOldKey = "is_operated"
isCicatrizedOldKey = "is_cicatrized"
isCauterizedOldKey = "is_cauterized"
isAmputationShownOldKey = "is_amputation_shown"
cicatrizationTimeOldKey = "cicatrization_time"
isOtherBodypartInfectedOldKey = "is_other_bodypart_infected"
elseif compatEnum == 3 then
isCutOldKey = "isCut"
isInfectedOldKey = "isInfected"
isOperatedOldKey = "isOperated"
isCicatrizedOldKey = "isCicatrized"
isCauterizedOldKey = "isCauterized"
isAmputationShownOldKey = "isAmputationShwon"
cicatrizationTimeOldKey = "cicatrizationTime"
isOtherBodypartInfectedOldKey = "isOtherBodypartInfected"
end
-- Starts reapplying stuff
modData.TOC.limbs.isOtherBodypartInfected = modData.TOC.Limbs[isOtherBodypartInfectedOldKey]
for i = 1, #newNamesTable do
local oldName = oldNamesTable[i]
local newName = newNamesTable[i]
print("TOC: isCut: " .. oldName .. " " .. tostring(modData.TOC.Limbs[oldName][isCutOldKey]))
print("TOC: isOperated: " .. oldName .. " " .. tostring(modData.TOC.Limbs[oldName][isOperatedOldKey]))
print("TOC: isCicatrized: " .. oldName .. " " .. tostring(modData.TOC.Limbs[oldName][isCicatrizedOldKey]))
print("TOC: isAmputationShown: " .. oldName .. " " .. tostring(modData.TOC.Limbs[oldName][isAmputationShownOldKey]))
print("TOC: cicatrizationTime: " .. oldName .. " " .. tostring(modData.TOC.Limbs[oldName][cicatrizationTimeOldKey]))
modData.TOC.limbs[newName].isCut = modData.TOC.Limbs[oldName][isCutOldKey]
if modData.TOC.limbs[newName].isCut then
print("TOC: Found old cut limb, reapplying model")
local cloth = getPlayer():getInventory():AddItem(TOC_Common.FindAmputatedClothingName(newName))
getPlayer():setWornItem(cloth:getBodyLocation(), cloth)
end
modData.TOC.limbs[newName].isInfected = modData.TOC.Limbs[oldName][isInfectedOldKey]
modData.TOC.limbs[newName].isOperated = modData.TOC.Limbs[oldName][isOperatedOldKey]
modData.TOC.limbs[newName].isCicatrized = modData.TOC.Limbs[oldName][isCicatrizedOldKey]
modData.TOC.limbs[newName].isCauterized = modData.TOC.Limbs[oldName][isCauterizedOldKey]
modData.TOC.limbs[newName].isAmputationShown = modData.TOC.Limbs[oldName][isAmputationShownOldKey]
modData.TOC.limbs[newName].cicatrizationTime = modData.TOC.Limbs[oldName][cicatrizationTimeOldKey]
end
end

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

View File

@@ -0,0 +1,123 @@
-- TODO this should be moved
local function TryToToResetEverythingOtherPlayer(_, patient, surgeon)
sendClientCommand(surgeon, "TOC", "AskToResetEverything", { patient:getOnlineID() })
end
----------------------------------------------------------------------------------------------------------
if TOC_ContextMenu == nil then
TOC_ContextMenu = {}
end
TOC_ContextMenu.CreateCheatsMenu = function(playerId, context, worldObjects, _)
local clickedPlayers = {}
local currentClickedPlayer = nil
local localPlayer = getSpecificPlayer(playerId)
--local players = getOnlinePlayers()
for _, v in pairs(worldObjects) do
-- help detecting a player by checking nearby squares
for x = v:getSquare():getX() - 1, v:getSquare():getX() + 1 do
for y = v:getSquare():getY() - 1, v:getSquare():getY() + 1 do
local sq = getCell():getGridSquare(x, y, v:getSquare():getZ())
if sq then
for i = 0, sq:getMovingObjects():size() - 1 do
local o = sq:getMovingObjects():get(i)
if instanceof(o, "IsoPlayer") then
currentClickedPlayer = o
if clickedPlayers[currentClickedPlayer:getUsername()] == nil then
-- FIXME this is to prevent context menu spamming. Find a better way
clickedPlayers[currentClickedPlayer:getUsername()] = true
if localPlayer:getAccessLevel() == "Admin" or isDebugEnabled() then
local rootOption = context:addOption("TOC - Cheats on " .. currentClickedPlayer:getUsername())
local rootMenu = context:getNew(context)
if currentClickedPlayer == localPlayer then
rootMenu:addOption("Reset TOC for me", _, TOC_Cheat.ResetEverything)
else
rootMenu:addOption("Reset TOC for " .. currentClickedPlayer:getUsername(), _, TryToToResetEverythingOtherPlayer,
currentClickedPlayer, localPlayer)
end
context:addSubMenu(rootOption, rootMenu)
end
-- TocContextMenus.FillCutAndOperateMenus(local_player, clicked_player, worldObjects,
-- cut_menu, operate_menu)
--TocContextMenus.FillCheatMenu(context, cheat_menu)
break
end
end
end
end
end
end
end
end
TOC_ContextMenu.CreateOperateWithOvenMenu = function(playerId, context, worldObjects, test)
local player = getSpecificPlayer(playerId)
-- TODO Let the player move towards the oven
local partData = player:getModData().TOC.limbs
local isMainMenuAlreadyCreated = false
for _, currentObject in pairs(worldObjects) do
if instanceof(currentObject, "IsoStove") and (player:HasTrait("Brave") or player:getPerkLevel(Perks.Strength) >= 6) then
-- Check temperature
if currentObject:getCurrentTemperature() > 250 then
for _, partName in ipairs(TOC_Common.GetPartNames()) do
if partData[partName].isCut and partData[partName].isAmputationShown and
not partData[partName].isOperated then
local subMenu = context:getNew(context);
if isMainMenuAlreadyCreated == false then
local rootMenu = context:addOption(getText('UI_ContextMenu_OperateOven'), worldObjects, nil);
context:addSubMenu(rootMenu, subMenu)
isMainMenuAlreadyCreated = true
end
subMenu:addOption(getText('UI_ContextMenu_' .. partName), worldObjects, TOC_LocalActions.Operate,
getSpecificPlayer(playerId), partName,true)
end
end
end
break -- stop searching for stoves
end
end
end
TOC_ContextMenu.CreateNewMenu = function(name, context, rootMenu)
local new_option = rootMenu:addOption(name)
local new_menu = context:getNew(context)
context:addSubMenu(new_option, new_menu)
return new_menu
end
TOC_ContextMenu.FillCheatMenus = function(context, cheat_menu)
if cheat_menu then
local cheat_cut_and_fix_menu = TOC_ContextMenu.CreateNewMenu("Cut and Fix", context, cheat_menu)
end
end
Events.OnFillWorldObjectContextMenu.Add(TOC_ContextMenu.CreateOperateWithOvenMenu) -- this is probably too much
Events.OnFillWorldObjectContextMenu.Add(TOC_ContextMenu.CreateCheatsMenu) -- TODO Add check only when admin is active

View File

@@ -0,0 +1,700 @@
if TOC_UI == nil then
TOC_UI = {}
end
local mainUI, descUI, confirmUI, confirmUIMP
-------------------------
-- MP stuff
-- TODO Strip out all this crap and redo it
local function PrerenderFuncMP()
local toSee = confirmUIMP
if confirmUIMP.responseReceive then
if not confirmUIMP.responseCan then
getPlayer():Say("I can't do that !")
confirmUIMP.responseReceive = false
confirmUIMP:close()
return false;
end
-- Prerender basically hooks onto SendCommandToConfirmUI, dunno how but it does
SendCommandToConfirmUIMP(confirmUIMP.responseAction, confirmUIMP.responseIsBitten,
confirmUIMP.responseUserName, confirmUIMP.responsePartName);
end
end
-----------------------
-- Getters
function GetConfirmUIMP()
return confirmUIMP;
end
------------------------------
-- UI Visible stuff functions
local function GetImageName(partName, limbsData)
local name = ""
local partData = limbsData[partName]
if partData.isCut and partData.isCicatrized and partData.isProsthesisEquipped then -- Cut and equip
if partName == "Right_Hand" or partName == "Left_Hand" then
name = "media/ui/TOC/" .. partName .. "/Hook.png"
else
name = "media/ui/TOC/" .. partName .. "/Prothesis.png"
end
elseif partData.isCut and partData.isCicatrized and not partData.isProsthesisEquipped and
partData.isAmputationShown then -- Cut and heal
name = "media/ui/TOC/" .. partName .. "/Cut.png"
elseif partData.isCut and not partData.isCicatrized and partData.isAmputationShown and
not partData.isOperated then -- Cut but not healead
name = "media/ui/TOC/" .. partName .. "/Bleed.png"
elseif partData.isCut and not partData.isCicatrized and partData.isAmputationShown and partData.isOperated then -- Cut but not healed and operated
name = "media/ui/TOC/" .. partName .. "/Operate.png"
elseif partData.isCut and not partData.isAmputationShown then -- Empty (like hand if forearm cut)
name = "media/ui/TOC/Empty.png"
elseif not partData.isCut and
-- FIXME This doesn't work in MP on another player since we're trying to retrieve bodyDamage from another player
getPlayer():getBodyDamage():getBodyPart(TOC_Common.GetBodyPartFromPartName(partName)):bitten() then -- Not cut but bitten
name = "media/ui/TOC/" .. partName .. "/Bite.png"
else -- Not cut
name = "media/ui/TOC/" .. partName .. "/Base.png"
end
-- If foreaerm equip, change hand
if partName == "Right_Hand" and limbsData["Right_LowerArm"].isProsthesisEquipped then
name = "media/ui/TOC/" .. partName .. "/Hook.png"
elseif partName == "Left_Hand" and limbsData["Left_LowerArm"].isProsthesisEquipped then
name = "media/ui/TOC/" .. partName .. "/Hook.png"
end
return name
end
------------------------------------------
-- Check functions
local function IsProsthesisInstalled(partData)
return partData.isCut and partData.isCicatrized and partData.isProsthesisEquipped
end
local function CanProsthesisBeEquipped(partData)
return partData.isCut and partData.isCicatrized and not partData.isProsthesisEquipped and
partData.isAmputationShown
end
local function IsAmputatedLimbHealed(partData)
return partData.isCut and not partData.isCicatrized and partData.isAmputationShown
end
local function IsAmputatedLimbToBeVisible(partData)
return partData.isCut and not partData.isAmputationShown
end
local function IsPartBitten(partData, partName)
return not partData.isCut and
getPlayer():getBodyDamage():getBodyPart(TOC_Common.GetBodyPartFromPartName(partName)):bitten()
end
local function FindMinMax(lv)
local min, max
if lv == 1 then
min = 0;
max = 75;
elseif lv == 2 then
min = 75;
max = 150 + 75;
elseif lv == 3 then
min = 150;
max = 300 + 75 + 150;
elseif lv == 4 then
min = 300;
max = 750 + 75 + 150 + 300;
elseif lv == 5 then
min = 750;
max = 1500 + 75 + 150 + 300 + 750;
elseif lv == 6 then
min = 1500;
max = 3000 + 75 + 150 + 300 + 750 + 1500;
elseif lv == 7 then
min = 3000;
max = 4500 + 75 + 150 + 300 + 750 + 1500 + 3000;
elseif lv == 8 then
min = 4500;
max = 6000 + 75 + 150 + 300 + 750 + 1500 + 3000 + 4500;
elseif lv == 9 then
min = 6000;
max = 7500 + 75 + 150 + 300 + 750 + 1500 + 3000 + 4500 + 6000;
elseif lv == 10 then
min = 7500;
max = 9000 + 75 + 150 + 300 + 750 + 1500 + 3000 + 4500 + 6000 + 7500;
end
return min, max;
end
-----------------------------------------
-- Setup stuff with variables and shit
TOC_UI.SetupMainUI = function(surgeon, patient, limbsData)
mainUI.surgeon = surgeon -- we shouldn't need an arg for this
mainUI.patient = patient
if limbsData then
mainUI.limbsData = limbsData
mainUI["b11"]:setPath(GetImageName("Right_UpperArm", limbsData))
mainUI["b12"]:setPath(GetImageName("Left_UpperArm", limbsData))
mainUI["b21"]:setPath(GetImageName("Right_LowerArm", limbsData))
mainUI["b22"]:setPath(GetImageName("Left_LowerArm", limbsData))
mainUI["b31"]:setPath(GetImageName("Right_Hand", limbsData))
mainUI["b32"]:setPath(GetImageName("Left_Hand", limbsData))
mainUI["b41"]:setPath(GetImageName("Right_Foot", limbsData))
mainUI["b42"]:setPath(GetImageName("Left_Foot", limbsData))
end
end
TOC_UI.SetupDescUI = function(surgeon, patient, limbsData, partName)
descUI["textTitle"]:setText(getText("UI_ContextMenu_" .. partName))
descUI.partName = partName
descUI.surgeon = surgeon
descUI.patient = patient
local partData = limbsData[partName]
if IsProsthesisInstalled(partData) then
-- Limb cut with prosthesis
descUI["status"]:setText("Prosthesis equipped")
descUI["status"]:setColor(1, 0, 1, 0)
descUI["b1"]:setText("Unequip")
descUI["b1"]:addArg("option", "Unequip")
descUI["b1"]:setVisible(true)
elseif CanProsthesisBeEquipped(partData) then
-- Limb cut but no prosthesis
descUI["status"]:setText("Amputated and healed")
descUI["status"]:setColor(1, 0, 1, 0)
-- Another check for UpperArm
if partName == "Right_UpperArm" or partName == "Left_UpperArm" then
descUI["b1"]:setVisible(false)
else
descUI["b1"]:setText("Equip")
descUI["b1"]:addArg("option", "Equip")
descUI["b1"]:setVisible(true)
end
-- Limb cut but still healing
elseif IsAmputatedLimbHealed(partData) then
-- Limb cut and healed, no prosthesis equipped
if partData.isOperated then
descUI["b1"]:setVisible(false) -- no operate prompt
if partData.cicatrizationTime > 1000 then
descUI["status"]:setText("Still a long way to go")
descUI["status"]:setColor(1, 0.8, 1, 0.2);
elseif partData.cicatrizationTime > 500 then
descUI["status"]:setText("Starting to get better")
descUI["status"]:setColor(1, 0.8, 1, 0.2)
elseif partData.cicatrizationTime > 100 then
descUI["status"]:setText("Almost cicatrized")
descUI["status"]:setColor(1, 0.8, 1, 0.2)
end
else
-- Set the operate button
descUI["b1"]:setText("Operate")
descUI["b1"]:addArg("option", "Operate")
descUI["b1"]:setVisible(true)
if partData.cicatrizationTime > 1000 then
descUI["status"]:setText("It hurts so much...")
descUI["status"]:setColor(1, 1, 0, 0)
elseif partData.cicatrizationTime > 500 then
descUI["status"]:setText("It still hurts a lot")
descUI["status"]:setColor(1, 0.8, 1, 0.2)
elseif partData.cicatrizationTime > 500 then
descUI["status"]:setText("I think it's almost over...")
descUI["status"]:setColor(1, 0.8, 1, 0.2)
end
end
elseif IsAmputatedLimbToBeVisible(partData) then
-- Limb cut and not visible (ex: hand after having amputated forearm)
descUI["status"]:setText("Nothing here")
descUI["status"]:setColor(1, 1, 1, 1)
descUI["b1"]:setVisible(false)
elseif TOC_Common.CheckIfCanBeCut(partName, limbsData) then
-- Everything else
-- TODO add check for cuts and scratches
descUI["status"]:setText("Not cut")
descUI["status"]:setColor(1, 1, 1, 1)
if TOC_Common.GetSawInInventory(surgeon) and not TOC_Common.CheckIfProsthesisAlreadyInstalled(limbsData, partName) then
descUI["b1"]:setVisible(true)
descUI["b1"]:setText("Cut")
descUI["b1"]:addArg("option", "Cut")
elseif TOC_Common.GetSawInInventory(surgeon) and TOC_Common.CheckIfProsthesisAlreadyInstalled(limbsData, partName) then
descUI["b1"]:setVisible(true)
descUI["b1"]:setText("Remove prosthesis before")
descUI["b1"]:addArg("option", "Nothing")
else
descUI["b1"]:setVisible(false)
end
else
descUI["status"]:setText("Not cut")
descUI["status"]:setColor(1, 1, 1, 1)
descUI["b1"]:setVisible(true)
descUI["b1"]:setText("Remove prosthesis before")
descUI["b1"]:addArg("option", "Nothing")
end
-- Prosthesis Level
if string.find(partName, "Right") then
local lv = patient:getPerkLevel(Perks.Right_Hand) + 1
descUI["textLV2"]:setText("Level: " .. lv .. " / 10")
local xp = patient:getXp():getXP(Perks.Right_Hand)
local min, max = FindMinMax(lv)
descUI["pbarNLV"]:setMinMax(min, max)
descUI["pbarNLV"]:setValue(xp)
else
local lv = patient:getPerkLevel(Perks.Left_Hand) + 1
descUI["textLV2"]:setText("Level: " .. lv .. " / 10")
local xp = patient:getXp():getXP(Perks.Left_Hand)
local min, max = FindMinMax(lv)
descUI["pbarNLV"]:setMinMax(min, max)
descUI["pbarNLV"]:setValue(xp)
end
end
------------------------------------------------
-- On Click Functions
local function OnClickMainUI(button, args)
descUI:open()
descUI:setPositionPixel(mainUI:getRight(), mainUI:getY())
TOC_UI.SetupDescUI(mainUI.surgeon, mainUI.patient, mainUI.limbsData, args.partName) -- surgeon is generic.
end
-- Generic TOC action, used in OnClickDescUI
local function TryTOCAction(_, partName, action, surgeon, patient)
-- TODO at this point surgeon doesnt do anything. We'll fix this later
-- Check if SinglePlayer
if not isServer() and not isClient() then
if action == "Cut" then
TOC_LocalActions.Cut(_, surgeon, partName)
elseif action == "Operate" then
TOC_LocalActions.Operate(_, surgeon, partName, false)
elseif action == "Equip" then
TOC_LocalActions.EquipProsthesis(_, surgeon, partName)
elseif action == "Unequip" then
TOC_LocalActions.UnequipProsthesis(_, surgeon, partName)
end
else
local ui = GetConfirmUIMP()
if not ui then
CreateConfirmUIMP()
ui = GetConfirmUIMP()
end
if patient == nil then
patient = surgeon
end
if action == "Cut" then
AskCanCutLimb(patient, partName)
elseif action == "Operate" then
AskCanOperateLimb(patient, partName)
elseif action == "Equip" then
AskCanEquipProsthesis(patient, partName)
elseif action == "Unequip" then
AskCanUnequipProsthesis(patient, partName)
end
ui.actionAct = action
ui.partNameAct = partName
ui.patient = patient
SendCommandToConfirmUIMP("Wait server")
end
end
local function OnClickDescUI(button, args)
-- Gets every arg from main
local patient = descUI.patient
local surgeon = descUI.surgeon
if args.option ~= "Nothing" then
TryTOCAction(_, descUI.partName, args.option, surgeon, patient)
end
mainUI:close()
end
local function OnClickConfirmUIMP(button, args)
local player = getPlayer()
if confirmUIMP.actionAct == "Cut" and args.option == "yes" then
ISTimedActionQueue.add(TOC_CutLimbAction:new(confirmUIMP.patient, player, confirmUIMP.partNameAct))
elseif confirmUIMP.actionAct == "Operate" and args.option == "yes" then
local kit = TOC_Common.GetKitInInventory(player)
if kit then
ISTimedActionQueue.add(TOC_OperateLimbAction:new(confirmUIMP.patient, player, kit, confirmUIMP.partNameAct,
false))
else
player:Say("I need a kit")
end
elseif confirmUIMP.actionAct == "Equip" and args.option == "yes" then
-- TODO Gonna be broken soon!
local surgeon_inventory = player:getInventory()
local prosthesis_to_equip = surgeon_inventory:getItemFromType('TOC.MetalHand') or
surgeon_inventory:getItemFromType('TOC.MetalHook') or
surgeon_inventory:getItemFromType('TOC.WoodenHook')
if prosthesis_to_equip then
ISTimedActionQueue.add(TOC_InstallProsthesisAction:new(player, confirmUIMP.patient, prosthesis_to_equip,
confirmUIMP.partNameAct))
else
player:Say("I don't have a prosthesis right now")
end
elseif confirmUIMP.actionAct == "Unequip" and args.option == "yes" then
-- We can't check if the player has a prosthesis right now, we need to do it later
-- TODO should check if player has a prosthesis equipped before doing it
-- TODO Player is surgeon, but we don't have a confirm_ui_mp.surgeon... awful awful awful
-- TODO Workaround for now, we'd need to send data from patient before doing it since we can't access his inventory from the surgeon
if confirmUIMP.patient == player then
ISTimedActionQueue.add(TOC_UninstallProsthesisAction:new(player, confirmUIMP.patient, confirmUIMP.partNameAct))
else
player:Say("I can't do that, they need to do it themselves")
end
end
confirmUIMP:close()
confirmUIMP.responseReceive = false
end
-----------------------------------------------
-- CREATE UI SECTION
local function CreateMainUI()
mainUI = NewUI()
mainUI:setTitle("The Only Cure Menu")
mainUI:setWidthPercent(0.1)
mainUI:addImageButton("b11", "", OnClickMainUI)
mainUI["b11"]:addArg("partName", "Right_UpperArm")
mainUI:addImageButton("b12", "", OnClickMainUI)
mainUI["b12"]:addArg("partName", "Left_UpperArm")
mainUI:nextLine()
mainUI:addImageButton("b21", "", OnClickMainUI)
mainUI["b21"]:addArg("partName", "Right_LowerArm")
mainUI:addImageButton("b22", "", OnClickMainUI)
mainUI["b22"]:addArg("partName", "Left_LowerArm")
mainUI:nextLine()
mainUI:addImageButton("b31", "", OnClickMainUI)
mainUI["b31"]:addArg("partName", "Right_Hand")
mainUI:addImageButton("b32", "", OnClickMainUI)
mainUI["b32"]:addArg("partName", "Left_Hand")
mainUI:nextLine()
mainUI:addImageButton("b41", "", OnClickMainUI)
mainUI["b41"]:addArg("partName", "Right_Foot")
mainUI:addImageButton("b42", "", OnClickMainUI)
mainUI["b42"]:addArg("partName", "Left_Foot")
mainUI:saveLayout()
end
-- Create a temporary desc UI with fake data (for now)
local function CreateDescUI()
descUI = NewUI()
descUI:setTitle("The only cure description");
descUI:isSubUIOf(mainUI)
descUI:setWidthPixel(250)
descUI:setColumnWidthPixel(1, 100)
descUI:addText("textTitle", "Right arm", "Large", "Center")
descUI:nextLine()
descUI:addText("textLV2", "Level 3/10", _, "Center")
descUI:nextLine()
descUI:addText("textLV", "Next LV:", _, "Right")
descUI:addProgressBar("pbarNLV", 39, 0, 100)
descUI["pbarNLV"]:setMarginPixel(10, 6)
descUI:nextLine()
descUI:addEmpty("border1")
descUI:setLineHeightPixel(1)
descUI["border1"]:setBorder(true)
descUI:nextLine()
descUI:addEmpty()
descUI:nextLine()
descUI:addText("status", "Temporary", "Medium", "Center")
descUI["status"]:setColor(1, 1, 0, 0)
descUI:nextLine()
descUI:addEmpty()
descUI:nextLine()
descUI:addButton("b1", "Operate", OnClickDescUI)
descUI:saveLayout()
end
function CreateConfirmUIMP()
confirmUIMP = NewUI()
confirmUIMP.responseReceive = false
confirmUIMP:addText("text1", "Are you sure?", "Title", "Center");
confirmUIMP:setLineHeightPixel(getTextManager():getFontHeight(confirmUIMP.text1.font) + 10)
confirmUIMP:nextLine();
confirmUIMP:addText("text4", "", "Medium", "Center");
confirmUIMP:setLineHeightPixel(getTextManager():getFontHeight(confirmUIMP.text4.font) + 10)
confirmUIMP:nextLine();
confirmUIMP:addText("text2", "", _, "Center");
confirmUIMP:nextLine();
confirmUIMP:addText("text3", "", _, "Center");
confirmUIMP:nextLine();
confirmUIMP:addEmpty();
confirmUIMP:nextLine();
confirmUIMP:addEmpty();
confirmUIMP:addButton("b1", "Yes", OnClickConfirmUIMP);
confirmUIMP.b1:addArg("option", "yes");
confirmUIMP:addEmpty();
confirmUIMP:addButton("b2", "No", OnClickConfirmUIMP);
confirmUIMP:addEmpty();
confirmUIMP:nextLine();
confirmUIMP:addEmpty();
confirmUIMP:saveLayout();
confirmUIMP:addPrerenderFunction(PrerenderFuncMP);
confirmUIMP:close();
end
-- We create everything from here
TOC_UI.OnCreate = function()
CreateMainUI()
CreateDescUI()
CreateConfirmUIMP()
if isClient() then CreateConfirmUIMP() end
mainUI:close()
end
--------------------------------------------
-- MP Confirm (I should add it to client too but hey not sure how it works tbh)
function SendCommandToConfirmUIMP(action, isBitten, userName, partName)
confirmUIMP:setInCenterOfScreen()
confirmUIMP:bringToTop()
confirmUIMP:open()
if action ~= "Wait server" then
confirmUIMP["text4"]:setText("You're gonna " ..
action .. " the " .. getText("UI_ContextMenu_" .. partName) .. " of " .. userName)
confirmUIMP["text2"]:setText("Are you sure?")
confirmUIMP["text2"]:setColor(1, 0, 0, 0)
confirmUIMP["b1"]:setVisible(true)
confirmUIMP["b2"]:setVisible(true)
else
confirmUIMP["text4"]:setText(action)
confirmUIMP["text3"]:setText("")
confirmUIMP["text2"]:setText("")
confirmUIMP["b1"]:setVisible(false)
confirmUIMP["b2"]:setVisible(false)
end
end
--------------------------------------------
-- Add TOC element to Health Panel
TOC_UI.onlineTempTable = {patient = nil, surgeon = nil}
TOC.RefreshClientMenu = function(_)
if mainUI:getIsVisible() == false then
Events.OnTick.Remove(TOC.RefreshClientMenu)
TOC_UI.onlineTempTable.patient = nil
TOC_UI.onlineTempTable.surgeon = nil
else
local limbs_data = TOC_UI.onlineTempTable.patient:getModData().TOC.limbs
TOC_UI.SetupMainUI(TOC_UI.onlineTempTable.patient, TOC_UI.onlineTempTable.patient, limbs_data)
end
end
TOC.RefreshOtherPlayerMenu = function(_)
if mainUI:getIsVisible() == false then
Events.OnTick.Remove(TOC.RefreshOtherPlayerMenu)
TOC_UI.onlineTempTable.patient = nil
TOC_UI.onlineTempTable.surgeon = nil
else
if ModData.get("TOC_PLAYER_DATA")[TOC_UI.onlineTempTable.patient:getUsername()] ~= nil then
local otherPlayerPartData = ModData.get("TOC_PLAYER_DATA")[TOC_UI.onlineTempTable.patient:getUsername()]
TOC_UI.SetupMainUI(TOC_UI.onlineTempTable.surgeon, TOC_UI.onlineTempTable.patient, otherPlayerPartData[1])
end
end
end
local ISHealthPanel_createChildren = ISHealthPanel.createChildren
local ISHealthPanel_render = ISHealthPanel.render
-- Add button to health panel
function ISNewHealthPanel.onClickTOC(button)
local surgeon = button.otherPlayer
local patient = button.character
TOC_UI.onlineTempTable.patient = patient
TOC_UI.onlineTempTable.surgeon = surgeon
-- MP Handling
if surgeon then
if surgeon == patient then
Events.OnTick.Add(TOC.RefreshClientMenu)
else
Events.OnTick.Add(TOC.RefreshOtherPlayerMenu) -- MP stuff, try to get the other player data and display it on the surgeon display
end
else
-- SP Handling
Events.OnTick.Add(TOC.RefreshClientMenu)
end
-- Set the correct main title
-- TODO sizes of the menu are strange in MP, they're not consistent with SP
local separatedUsername = {}
for v in string.gmatch(patient:getUsername(), "%u%l+") do
table.insert(separatedUsername, v)
end
local main_title
if separatedUsername[1] == nil then
main_title = patient:getUsername() .. " - TOC"
else
main_title = separatedUsername[1] .. " " .. separatedUsername[2] .. " - TOC"
end
mainUI:setTitle(main_title)
mainUI:toggle()
mainUI:setInCenterOfScreen()
end
function ISHealthPanel:createChildren()
ISHealthPanel_createChildren(self)
self.fitness:setWidth(self.fitness:getWidth() / 1.4)
self.TOCButton = ISButton:new(self.fitness:getRight() + 10, self.healthPanel.y, 60, 20, "", self,
ISNewHealthPanel.onClickTOC)
self.TOCButton:setImage(getTexture("media/ui/TOC/iconForMenu.png"))
self.TOCButton.anchorTop = false
self.TOCButton.anchorBottom = true
self.TOCButton:initialise()
self.TOCButton:instantiate()
self:addChild(self.TOCButton)
if getCore():getGameMode() == "Tutorial" then
self.TOCButton:setVisible(false)
end
end
function ISHealthPanel:render()
ISHealthPanel_render(self);
self.TOCButton:setY(self.fitness:getY());
end
-- EVENTS
Events.OnCreateUI.Add(TOC_UI.OnCreate)

View File

@@ -0,0 +1,25 @@
-- Thanks to Glytcher and Matías N. Salas for helping out with this
if TOC_Anims == nil then
TOC_Anims = {}
end
TOC_Anims.SetMissingFootAnimation = function(check)
local player = getPlayer()
player:setVariable("IsCrawling", tostring(check))
if not isServer() and not isClient() then
print("SP, so it's fine")
else
sendClientCommand(player, "TOC", "NotifyNewCrawlAnimation", {id = player:getOnlineID(), check = check})
end
end
TOC_Anims.CheckAndSetMissingFootAnims = function(modData)
if modData.TOC.limbs["Left_Foot"].isCut or modData.TOC.limbs["Right_Foot"].isCut then
TOC_Anims.SetMissingFootAnimation(true)
end
end

View File

@@ -0,0 +1,57 @@
------------------------------------------
-------------- THE ONLY CURE -------------
------------------------------------------
---------------- CHEATS -----------------
if TOC_Cheat == nil then
TOC_Cheat = {}
end
TOC_Cheat.ResetEverything = function()
-- This has to be run on the local player to be sure that we're correctly reassigning everything
local player = getPlayer()
local playerInv = player:getInventory()
local modData = player:getModData()
modData.TOC = nil
-- Removes traits just to be sure
local customTraits = player:getTraits()
customTraits:remove("Amputee_Hand")
customTraits:remove("Amputee_LowerArm")
customTraits:remove("Amputee_UpperArm")
TOC.Init(_, player)
-- Destroy the amputation or prosthesis item
for _, partName in pairs(TOC_Common.GetPartNames()) do
local amputationItemName = TOC_Common.FindAmputationOrProsthesisName(partName, player, "Amputation")
local prostItemName = TOC_Common.FindAmputationOrProsthesisName(partName, player, "Prosthesis")
if amputationItemName ~= nil then
local amputationItem = playerInv:FindAndReturn(amputationItemName)
if amputationItem ~= nil then
print("Resetting " .. amputationItem:getName())
player:removeWornItem(amputationItem)
player:getInventory():Remove(amputationItem)
end
amputationItem = nil -- reset it
end
if prostItemName ~= nil then
local prostItem = playerInv:FindAndReturn(prostItemName)
if prostItem ~= nil then
print("Resetting " .. prostItem:getName())
player:removeWornItem(prostItem)
player:getInventory():Remove(prostItem)
end
prostItem = nil -- reset it
end
end
-- Reset special flag for legs amputations
TOC_Anims.SetMissingFootAnimation(false)
end

View File

@@ -0,0 +1,303 @@
------------------------------------------
-------------- THE ONLY CURE -------------
------------------------------------------
------------ COMMON FUNCTIONS ------------
if TOC_Common == nil then
TOC_Common = {}
end
TOC_Common.partNames = {}
TOC_Common.GeneratePartNames = function()
local partNamesTable = {}
for _, side in ipairs(TOC.sideNames) do
for _, limb in ipairs(TOC.limbNames) do
local tempPartName = TOC_Common.ConcatPartName(side, limb)
table.insert(partNamesTable, tempPartName)
end
end
TOC_Common.partNames = partNamesTable
end
TOC_Common.GetPartNames = function()
if TOC_Common.partNames[1] == nil then
TOC_Common.GeneratePartNames()
end
return TOC_Common.partNames
end
TOC_Common.GetSideFromPartName = function(partName)
if string.find(partName, "Left") then
return "Left"
else
return "Right"
end
end
TOC_Common.ConcatPartName = function(side, limb)
return side .. "_" .. limb
end
---------------------------------
TOC_Common.GetAcceptableBodyPartTypes = function()
-- TODO Add Foot_L and Foot_R
return {
BodyPartType.Hand_R, BodyPartType.ForeArm_R, BodyPartType.UpperArm_R,
BodyPartType.Hand_L, BodyPartType.ForeArm_L, BodyPartType.UpperArm_L
}
end
TOC_Common.GetOtherBodyPartTypes = function()
return {
BodyPartType.Torso_Upper, BodyPartType.Torso_Lower, BodyPartType.Head,
BodyPartType.Neck, BodyPartType.Groin, BodyPartType.UpperLeg_L,
BodyPartType.UpperLeg_R, BodyPartType.LowerLeg_L,
BodyPartType.LowerLeg_R, BodyPartType.Foot_L, BodyPartType.Foot_R,
BodyPartType.Back
}
end
function GetProsthesisList()
-- TODO Not gonna work anymore
return {"WoodenHook", "MetalHook", "MetalHand"}
end
TOC_Common.FindAmputatedClothingName = function(partName)
return "TOC.Amputation_" .. partName
end
TOC_Common.GetPartNameFromBodyPartType = function(bodyPartType)
if bodyPartType == BodyPartType.Hand_R then
return "Right_Hand"
elseif bodyPartType == BodyPartType.ForeArm_R then
return "Right_LowerArm"
elseif bodyPartType == BodyPartType.UpperArm_R then
return "Right_UpperArm"
elseif bodyPartType == BodyPartType.Hand_L then
return "Left_Hand"
elseif bodyPartType == BodyPartType.ForeArm_L then
return "Left_LowerArm"
elseif bodyPartType == BodyPartType.UpperArm_L then
return "Left_UpperArm"
else
return nil
end
end
-- 1:1 map of partName to BodyPartType
TOC_Common.GetBodyPartFromPartName = function(partName)
if partName == "Right_Hand" then return BodyPartType.Hand_R end
if partName == "Right_LowerArm" then return BodyPartType.ForeArm_R end
if partName == "Right_UpperArm" then return BodyPartType.UpperArm_R end
if partName == "Left_Hand" then return BodyPartType.Hand_L end
if partName == "Left_LowerArm" then return BodyPartType.ForeArm_L end
if partName == "Left_UpperArm" then return BodyPartType.UpperArm_L end
-- New Legs stuff
if partName == "Right_Foot" then return BodyPartType.Foot_R end
if partName == "Left_Foot" then return BodyPartType.Foot_L end
end
-- Custom mapping to make more sense when cutting a limb
TOC_Common.GetAdjacentBodyPartFromPartName = function(partName)
if partName == "Right_Hand" then return BodyPartType.ForeArm_R end
if partName == "Right_LowerArm" then return BodyPartType.UpperArm_R end
if partName == "Right_UpperArm" then return BodyPartType.Torso_Upper end
if partName == "Left_Hand" then return BodyPartType.ForeArm_L end
if partName == "Left_LowerArm" then return BodyPartType.UpperArm_L end
if partName == "Left_UpperArm" then return BodyPartType.Torso_Upper end
if partName == "Right_Foot" then return BodyPartType.LowerLeg_R end
if partName == "Left_Foot" then return BodyPartType.LowerLeg_L end
end
function TocFindCorrectClothingProsthesis(itemName, partName)
-- TODO This is not gonna work soon, so don't use this
local correctName = "TOC.Prost_" .. partName .. "_" .. itemName
return correctName
end
TOC_Common.GetAmputationItemInInventory = function(player, partName)
local playerInv = player:getInventory()
local amputationItemName = TOC_Common.FindAmputationOrProsthesisName(partName, player, "Amputation")
local amputationItem = playerInv:FindAndReturn(amputationItemName)
return amputationItem
end
TOC_Common.GetSawInInventory = function(surgeon)
local playerInv = surgeon:getInventory()
local item = playerInv:getItemFromType("Saw") or playerInv:getItemFromType("GardenSaw") or
playerInv:getItemFromType("Chainsaw")
return item
end
-----------------------------------
-- Online Handling checks
TOC_Common.CheckIfCanBeCut = function(partName, limbsData)
if limbsData == nil then
limbsData = getPlayer():getModData().TOC.limbs
end
local check = (not limbsData[partName].isCut) and
(not TOC_Common.CheckIfProsthesisAlreadyInstalled(limbsData, partName))
return check
end
TOC_Common.CheckIfCanBeOperated = function(partName, limbsData)
if limbsData == nil then
limbsData = getPlayer():getModData().TOC.limbs
end
return limbsData[partName].isOperated == false and limbsData[partName].isAmputationShown
end
TOC_Common.CheckIfProsthesisCanBeEquipped = function(partName)
local limbs_data = getPlayer():getModData().TOC.limbs
return limbs_data[partName].isCauterized or limbs_data[partName].isCicatrized
-- check if prosthesis is in the surgeon inventory... we need to get it before
end
TOC_Common.CheckIfProsthesisCanBeUnequipped = function(partName)
-- TODO we should get item here to be sure that we can do this action instead of relying on some later checks
return true
end
-----------------------------------------
-- Various checks
-----------------------------------------
TOC_Common.CheckIfItemIsAmputatedLimb = function(item)
local itemFullType = item:getFullType()
local check
if string.find(itemFullType, "TOC.Amputation_") then
check = true
else
check = false
end
return check
end
function CheckIfItemIsProsthesis(item)
local itemFullType = item:getFullType()
-- TODO This isn't gonna work anymore! Modular prosthetics needs to be handled in a different way
local prosthesisList = GetProsthesisList()
for _, v in pairs(prosthesisList) do
if v == itemFullType then
return true
end
end
return false
end
TOC_Common.CheckIfItemIsInstalledProsthesis = function(item)
local itemFullType = item:getFullType()
if string.find(itemFullType, "TOC.Prost_") then
return true
else
return false
end
end
TOC_Common.CheckIfProsthesisAlreadyInstalled = function(limbsData, partName)
for _, side in pairs(TOC.sideNames) do
if string.find(partName, side) then
return (limbsData[TOC_Common.ConcatPartName(side, "Hand")].isProsthesisEquipped or limbsData[TOC_Common.ConcatPartName(side, "LowerArm")].isProsthesisEquipped)
end
end
end
TOC_Common.GetCanBeHeldTable = function(limbs_data)
local canBeHeld = {}
for _, side in pairs(TOC.sideNames) do
canBeHeld[side] = true
if limbs_data[TOC_Common.ConcatPartName(side, "Hand")].isCut then
if limbs_data[TOC_Common.ConcatPartName(side, "LowerArm")].isCut then
if not limbs_data[TOC_Common.ConcatPartName(side, "LowerArm")].isProsthesisEquipped then
canBeHeld[side] = false
end
elseif not limbs_data[TOC_Common.ConcatPartName(side, "Hand")].isProsthesisEquipped then
canBeHeld[side] = false
end
end
end
return canBeHeld
end
-------------------------------
TOC_Common.FindItemInWornItems = function(player, checkString)
local wornItems = player:getWornItems()
for i = 1, wornItems:size() - 1 do -- Maybe wornItems:size()-1
local item = wornItems:get(i):getItem()
local itemFullType = item:getFullType()
if string.find(itemFullType, checkString) then
return item
end
end
return nil
end
TOC_Common.FindModItem = function(inventory)
for _, partName in pairs(TOC_Common.GetPartNames()) do
if inventory:contains("TOC.Amputation_" .. partName) then
return true
end
end
return false
end

View File

@@ -0,0 +1,70 @@
-- TODO this needs to be moved away
function TOC_Common.GetKitInInventory(surgeon)
local playerInv = surgeon:getInventory()
local item = playerInv:getItemFromType('TOC.Real_surgeon_kit') or playerInv:getItemFromType('TOC.Surgeon_kit') or
playerInv:getItemFromType('TOC.Improvised_surgeon_kit')
return item
end
-- Unequip Prosthesis
local function PartNameToBodyLocationProsthesis(name)
if name == "Right_Hand" then return "TOC_ArmRightProsthesis" end
if name == "Right_LowerArm" then return "TOC_ArmRightProsthesis" end
if name == "Right_UpperArm" then return "TOC_ArmRightProsthesis" end
if name == "Left_Hand" then return "TOC_ArmLeftProsthesis" end
if name == "Left_LowerArm" then return "TOC_ArmLeftProsthesis" end
if name == "Left_UpperArm" then return "TOC_ArmLeftProsthesis" end
end
local function PartNameToBodyLocationAmputation(name)
if name == "Right_Hand" then return "TOC_ArmRight" end
if name == "Right_LowerArm" then return "TOC_ArmRight" end
if name == "Right_UpperArm" then return "TOC_ArmRight" end
if name == "Left_Hand" then return "TOC_ArmLeft" end
if name == "Left_LowerArm" then return "TOC_ArmLeft" end
if name == "Left_UpperArm" then return "TOC_ArmLeft" end
if name == "Left_Foot" then return "TOC_LegLeft" end
if name == "Right_Foot" then return "TOC_LegRight" end
end
function TOC_Common.FindItemInProstBodyLocation(partName, patient)
-- Can't be used for online purposes, since we can't get the online inventory of another player
local wornItems = patient:getWornItems()
-- Particular case where i= 1 and size - 1 I guess?
for i = 1, wornItems:size() - 1 do
local item = wornItems:get(i):getItem()
if item:getBodyLocation() == PartNameToBodyLocationProsthesis(partName) then
return item
end
end
end
-- Debug cheat and update every minute for cicatrization
function TOC_Common.FindAmputationOrProsthesisName(partName, player, choice)
local wornItems = player:getWornItems()
for i = 1, wornItems:size() - 1 do
local item = wornItems:get(i):getItem()
if choice == "Amputation" then
if item:getBodyLocation() == PartNameToBodyLocationAmputation(partName) then
return item:getFullType()
end
elseif choice == "Prosthesis" then
if item:getBodyLocation() == PartNameToBodyLocationProsthesis(partName) then
return item:getFullType()
end
end
end
end

View File

@@ -0,0 +1,186 @@
------------------------------------------
-------------- THE ONLY CURE -------------
------------------------------------------
------------- INIT FUNCTIONS -------------
--[[
Original code and idea by: Mr. Bounty
Rewritten and maintained by: Pao
--]]
TOC.InitializeTraits = function()
local amp1 = TraitFactory.addTrait("Amputee_Hand", getText("UI_trait_Amputee_Hand"), -8,
getText("UI_trait_Amputee_Hand_desc"), false, false)
amp1:addXPBoost(Perks.Left_Hand, 4)
amp1:addXPBoost(Perks.Fitness, -1)
amp1:addXPBoost(Perks.Strength, -1)
local amp2 = TraitFactory.addTrait("Amputee_LowerArm", getText("UI_trait_Amputee_LowerArm"), -10,
getText("UI_trait_Amputee_LowerArm_desc"), false, false)
amp2:addXPBoost(Perks.Left_Hand, 4)
amp2:addXPBoost(Perks.Fitness, -1)
amp2:addXPBoost(Perks.Strength, -1)
local amp3 = TraitFactory.addTrait("Amputee_UpperArm", getText("UI_trait_Amputee_UpperArm"), -20,
getText("UI_trait_Amputee_UpperArm_desc"), false, false)
amp3:addXPBoost(Perks.Left_Hand, 4)
amp3:addXPBoost(Perks.Fitness, -1)
amp3:addXPBoost(Perks.Strength, -1)
TraitFactory.addTrait("Insensitive", getText("UI_trait_Insensitive"), 6, getText("UI_trait_Insensitivedesc"), false,
false)
TraitFactory.setMutualExclusive("Amputee_Hand", "Amputee_LowerArm")
TraitFactory.setMutualExclusive("Amputee_Hand", "Amputee_UpperArm")
TraitFactory.setMutualExclusive("Amputee_LowerArm", "Amputee_UpperArm")
end
-- TODO Refactor this
TOC.CutLimbForTrait = function(player, TOCModData, partName)
local limbsData = TOCModData.limbs
local amputationClothingItem = player:getInventory():AddItem("TOC.Amputation_" .. partName)
TOC_Visuals.SetTextureForAmputation(amputationClothingItem, player, true)
player:setWornItem(amputationClothingItem:getBodyLocation(), amputationClothingItem)
limbsData[partName].isCut = true
limbsData[partName].isOperated = true
limbsData[partName].isAmputationShown = true
limbsData[partName].isCicatrized = true
for _, v in pairs(TOC.limbParameters[partName].dependsOn) do
limbsData[v].isCut = true
limbsData[v].isOperated = true
limbsData[v].isAmputationShown = false
limbsData[v].isCicatrized = true
end
end
TOC.InitPart = function(limbsData, partName)
limbsData[partName].isCut = false
limbsData[partName].isInfected = false
limbsData[partName].isOperated = false
limbsData[partName].isCicatrized = false
limbsData[partName].isCauterized = false
limbsData[partName].isAmputation_shown = false
limbsData[partName].cicatrizationTime = 0
limbsData[partName].isProsthesisEquipped = false
limbsData[partName].equippedProsthesis = {}
end
TOC.SetInitData = function(modData, player)
print("TOC: Creating mod_data.TOC")
modData.TOC = {}
-- Limbs
modData.TOC.limbs = {
Right_Hand = {},
Right_LowerArm = {},
Right_UpperArm = {},
Left_Hand = {},
Left_LowerArm = {},
Left_UpperArm = {},
Left_Foot = {},
Right_Foot = {},
isOtherBodypartInfected = false
}
for _, side in pairs(TOC.sideNames) do
for _, limb in pairs(TOC.limbNames) do
local partName = TOC_Common.ConcatPartName(side, limb)
TOC.InitPart(modData.TOC.limbs, partName)
end
end
-- Setup traits
if player:HasTrait("Amputee_Hand") then
TOC.CutLimbForTrait(player, modData.TOC, "Left_Hand")
elseif player:HasTrait("Amputee_LowerArm") then
TOC.CutLimbForTrait(player, modData.TOC, "Left_LowerArm")
elseif player:HasTrait("Amputee_UpperArm") then
TOC.CutLimbForTrait(player, modData.TOC, "Left_UpperArm")
end
end
TOC.Init = function(_, player)
local modData = player:getModData()
if modData.TOC == nil then
TOC.SetInitData(modData, player)
else
TOC_Compat.CheckCompatibilityWithOlderVersions(modData)
TOC_Anims.CheckAndSetMissingFootAnims(modData)
end
-- Compat fix with older versions
if modData.TOC ~= nil then
print("TOC: found older data from TOC or TOCBB")
TOC_Compat.CheckCompatibilityWithOlderVersions(modData)
end
end
------------------------------------------------------------------------------------
-- Rewrite 2 Electirc Bogaloo
local function InitializeTheOnlyCure()
if not TOC then
TOC = {}
end
-- Initializes static values in a global table
TOC.sideNames = {"Left", "Right"}
TOC.limbNames = { "Hand", "LowerArm", "UpperArm", "Foot"}
TOC.limbParameters = {}
for _, side in pairs(TOC.sideNames) do
for _, limb in pairs(TOC.limbNames) do
local partName = TOC_Common.ConcatPartName(side, limb)
TOC.limbParameters[partName] = {}
if limb == "Hand" then
TOC.limbParameters[partName].cicatrizationBaseTime = 1700
TOC.limbParameters[partName].dependsOn = {}
elseif limb == "LowerArm" then
TOC.limbParameters[partName].cicatrizationBaseTime = 1800
TOC.limbParameters[partName].dependsOn = { TOC_Common.ConcatPartName(side, "Hand") }
elseif limb == "UpperArm" then
TOC.limbParameters[partName].cicatrizationBaseTime = 2000
TOC.limbParameters[partName].dependsOn = { TOC_Common.ConcatPartName(side, "Hand"), TOC_Common.ConcatPartName(side, "LowerArm"), }
elseif limb == "Foot" then
TOC.limbParameters[partName].cicatrizationBaseTime = 1700
TOC.limbParameters[partName].dependsOn = {}
end
end
end
--------------------------
TOC.InitializeTraits()
Events.OnCreatePlayer.Add(TOC.Init)
-- Setup updates
Events.OnTick.Add(TOC.UpdateOnTick)
Events.EveryTenMinutes.Add(TOC.UpdateEveryTenMinutes)
Events.EveryOneMinute.Add(TOC.UpdateEveryOneMinute)
-- Mod Checker
CheckMyModTable = CheckMyModTable or {}
CheckMyModTable["Amputation"] = 2703664356 -- TODO should we change the ID with the update or not?
end
Events.OnGameBoot.Add(InitializeTheOnlyCure)

View File

@@ -0,0 +1,75 @@
------------------------------------------
-------------- THE ONLY CURE -------------
------------------------------------------
------------------------------------------
-- Compatibility Handler by Dhert
------------------------------------------
-- TODO Connect this with TOC logic instead of hardcoding it here
local parts = {
"Right_Hand",
"Left_Hand",
"Right_LowerArm",
"Left_LowerArm"
}
-- TODO Connect this with TOC logic instead of hardcoding it here
local vars = {
"isCut",
"isProsthesisEquipped"
}
local TOC_Compat = {}
-- Raw access, must pass valid part
--- @param player
--- @param part string
--- @return boolean
TOC_Compat.hasArmPart = function(player, part)
if not player or not part then return false end
local data = (player:getModData().TOC and player:getModData().TOC.Limbs) or nil
return not data or not data[part] or (data[part][vars[1]] and data[part][vars[2]]) or not data[part][vars[1]]
end
-- Raw access, must pass valid parts. Will check for 2 parts (arm and hand)
--- @param player
--- @param part string
--- @param part2 string
--- @return boolean
TOC_Compat.hasArm = function(player, part, part2)
if not player or not part then return false end
local data = (player:getModData().TOC and player:getModData().TOC.Limbs) or nil
return not data or (not data[part] or (data[part][vars[1]] and data[part][vars[2]]) or not data[part][vars[1]]) or (not data[part] or (data[part2][vars[1]] and data[part2][vars[2]]) or not data[part2][vars[1]])
end
-- Check if hand is available
--- @param player
--- @param left boolean -- optional
--- @return boolean
TOC_Compat.hasHand = function(player, left)
return TOC_Compat.hasArm(player, ((left and parts[2]) or parts[1]), ((left and parts[4]) or parts[3]))
end
-- Check if both hands are available
--- @param player
--- @return boolean
TOC_Compat.hasBothHands = function(player)
return TOC_Compat.hasArm(player, parts[1], parts[3]) and TOC_Compat.hasArm(player, parts[2], parts[4])
end
-- This returns a number for the hands that you have
----- 11 == both hands
----- 10 == left hand
----- 01 (1) == right hand
----- 00 (0) == no hands
--- @param player
--- @return integer
TOC_Compat.getHands = function(player)
return ((TOC_Compat.hasArm(player, parts[1], parts[3]) and 1) or 0) + ((TOC_Compat.hasArm(player, parts[2], parts[4]) and 10) or 0)
end
return TOC_Compat

View File

@@ -0,0 +1,268 @@
require "TimedActions/ISBaseTimedAction"
require "TimedActions/ISEquipWeaponAction"
require "TimedActions/ISUnequipAction"
require "ISUI/ISInventoryPaneContextMenu"
-- TODO 1) Add exceptions for watches
local og_ISBaseTimedActionAdjustMaxTime = ISBaseTimedAction.adjustMaxTime
function ISBaseTimedAction:adjustMaxTime(maxTime)
-- TODO we can customize it better through clothing items modifier, you mook
-- RunSpeedModifier = 0.93 for example
local originalMaxTime = og_ISBaseTimedActionAdjustMaxTime(self, maxTime)
if originalMaxTime ~= -1 then
local modData = getPlayer():getModData()
local limbParameters = TOC.limbParameters
local limbsData = modData.TOC.limbs
local modifiedMaxTime = originalMaxTime
local burnFactor = 1.3 -- TODO Move this crap
for _, partName in pairs(TOC_Common.GetPartNames()) do
if limbsData[partName].isCut then
--Equipped prosthesis or not
if limbsData[partName].isProsthesisEquipped then
-- FIXME We should apply the correct values to equippedProsthesis once we equip it
--modifiedMaxTime = modifiedMaxTime * limbsData[partName].equipped_prosthesis.prosthesis_factor
else
-- TODO this should depend on the limb?
modifiedMaxTime = modifiedMaxTime * 1.5
end
-- Cauterization check
if limbsData[partName].is_cauterized then
modifiedMaxTime = modifiedMaxTime * burnFactor
end
-- Perk scaling
if partName == "Right_Hand" or partName == "Left_Hand" then
modifiedMaxTime = modifiedMaxTime *
(1 + (9 - self.character:getPerkLevel(Perks[partName])) / 20)
end
end
end
if modifiedMaxTime > 10 * originalMaxTime then modifiedMaxTime = 10 * originalMaxTime end
return modifiedMaxTime
end
return originalMaxTime
end
-------------------------------------------------
-- Block access to drag, picking, inspecting, etc to amputated limbs
local og_ISInventoryPaneOnMouseDoubleClick = ISInventoryPane.onMouseDoubleClick
function ISInventoryPane:onMouseDoubleClick(x, y)
local item_to_check = self.items[self.mouseOverOption]
local player_inventory = getPlayerInventory(self.player).inventory
if instanceof(item_to_check, "InventoryItem") then
og_ISInventoryPaneOnMouseDoubleClick(self, x, y)
elseif TOC_Common.CheckIfItemIsAmputatedLimb(item_to_check.items[1]) or TOC_Common.CheckIfItemIsInstalledProsthesis(item_to_check.items[1]) then
--print("TOC: Can't double click this item")
end
og_ISInventoryPaneOnMouseDoubleClick(self, x, y)
end
local og_ISInventoryPaneGetActualItems = ISInventoryPane.getActualItems
function ISInventoryPane.getActualItems(items)
-- TODO add an exception for installed prosthesis, make them unequippable automatically from here and get the correct obj
local ret = og_ISInventoryPaneGetActualItems(items)
-- This is gonna be slower than just overriding the function but hey it's more compatible
for i = 1, #ret do
local item_full_type = ret[i]:getFullType()
if string.find(item_full_type, "Amputation_") or string.find(item_full_type, "Prost_") then
table.remove(ret, i)
end
end
return ret
end
local og_ISInventoryPaneContextMenuOnInspectClothing = ISInventoryPaneContextMenu.onInspectClothing
ISInventoryPaneContextMenu.onInspectClothing = function(playerObj, clothing)
-- Inspect menu bypasses getActualItems, so we need to add that workaround here too
local clothing_full_type = clothing:getFullType()
if TOC_Common.CheckIfItemIsAmputatedLimb(clothing) or TOC_Common.CheckIfItemIsInstalledProsthesis(clothing) then
--print("TOC: Can't inspect this!")
else
og_ISInventoryPaneContextMenuOnInspectClothing(playerObj, clothing)
end
end
local og_ISEquipWeaponActionPerform = ISEquipWeaponAction.perform
function ISEquipWeaponAction:perform()
-- TODO this is only for weapons, not items. Won't work for everything I think
--TODO Block it before even performing
-- TODO in the inventory menu there is something broken, even though this works
og_ISEquipWeaponActionPerform(self)
local limbs_data = self.character:getModData().TOC.limbs
local can_be_held = TOC_Common.GetCanBeHeldTable(limbs_data)
if not self.item:isRequiresEquippedBothHands() then
if can_be_held["Right"] and not can_be_held["Left"] then
self.character:setPrimaryHandItem(self.item)
self.character:setSecondaryHandItem(nil)
elseif not can_be_held["Right"] and can_be_held["Left"] then
self.character:setPrimaryHandItem(nil)
self.character:setSecondaryHandItem(self.item)
elseif not can_be_held["Left"] and not can_be_held["Right"] then
self.character:dropHandItems()
end
else
if (can_be_held["Right"] and not can_be_held["Left"]) or
(not can_be_held["Right"] and can_be_held["Left"]) or
(not can_be_held["Left"] and not can_be_held["Right"]) then
self.character:dropHandItems()
end
end
-- Check if it's a prosthesis and let the player know that they're fucking things up
if self.item then
local item_name = self.item:getFullType()
for _, prost_v in pairs(GetProsthesisList()) do
local prosthesis_name = string.match(item_name, prost_v)
if prosthesis_name then
self.character:Say("This isn't the right way to equip this...")
end
end
end
end
local og_ISInventoryPaneContextMenuUnequipItem = ISInventoryPaneContextMenu.unequipItem
function ISInventoryPaneContextMenu.unequipItem(item, player)
if item == nil then
return
end
if TOC_Common.CheckIfItemIsAmputatedLimb(item) == false and TOC_Common.CheckIfItemIsInstalledProsthesis(item) == false then
og_ISInventoryPaneContextMenuUnequipItem(item, player)
end
end
local og_ISInventoryPaneContextMenuDropItem = ISInventoryPaneContextMenu.dropItem
function ISInventoryPaneContextMenu.dropItem(item, player)
if TOC_Common.CheckIfItemIsAmputatedLimb(item) == false and TOC_Common.CheckIfItemIsInstalledProsthesis(item) == false then
og_ISInventoryPaneContextMenuDropItem(item, player)
end
end
-- Make the player unable to equip a tourniquet or watches on an already fully amputated limb
local og_ISWearClothingIsValid = ISWearClothing.isValid
function ISWearClothing:isValid()
local baseCheck = og_ISWearClothingIsValid(self)
local itemFullType = self.item:getFullType()
local limbsData = self.character:getModData().TOC.limbs
local itemToCheck = "Surgery_%s_Tourniquet"
for _, side in pairs(TOC.sideNames) do
local formattedItemName = string.format(itemToCheck, side)
if string.find(itemFullType, formattedItemName) then
if limbsData[TOC_Common.ConcatPartName(side, "UpperArm")].isCut then
return false
end
end
end
return baseCheck
end
-- This is to manage the watches, we don't want them equipped over an amputated limb of course
local og_ISWearClothingExtraAction = ISClothingExtraAction.isValid
function ISClothingExtraAction:isValid()
local baseCheck = og_ISWearClothingExtraAction(self)
-- Check the new extra instead of the old item
local newItem = self:createItem(self.item, self.extra)
local itemFullType = newItem:getFullType()
local location = newItem:getBodyLocation()
--print("TOC: watch full type " .. itemFullType)
--print("TOC: watch location " .. location)
local itemToCheck = "Watch_"
local limbsData = self.character:getModData().TOC.limbs
if string.find(itemFullType, itemToCheck) then
for _, side in pairs (TOC.sideNames) do
if location == side .. "Wrist" then
if limbsData[TOC_Common.ConcatPartName(side, "LowerArm")].isCut then
return false
end
end
end
end
return baseCheck
end
-- Manages the Loot All button to prevent stuff like picking up the amputation items
local og_ISInventoryPagePrerender = ISInventoryPage.prerender
function ISInventoryPage:prerender()
-- Check if there is any amputated limb here. if there is, just fail and maybe notify the player
og_ISInventoryPagePrerender(self)
if TOC_Common.FindModItem(self.inventory) then
self.canLootAll = false
else
self.canLootAll = true
end
end
local og_ISInventoryPageLootAll = ISInventoryPage.lootAll
function ISInventoryPage:lootAll()
if self.canLootAll then
og_ISInventoryPageLootAll(self)
end
end

View File

@@ -0,0 +1,189 @@
-- Use the XLSX as a base for these stats
local baseTable = {
LeatherBase = {
durability = 25,
speed = 15
},
WoodenBase = {
durability = 10,
speed = 5,
},
MetalBase = {
durability = 75,
speed = 7,
}
}
local topTable = {
MetalHook = {
durability = 1,
speed = 1,
},
WoodenHook = {
durability = 1,
speed = 1,
}
}
local function GetProsthesisStats(arrayStats, prosthesisName)
local durability
local speed
for name, values in pairs(arrayStats) do
-- Check the name of the prosthesis item, set the correct values
if string.find(prosthesisName, name) then
durability = values.durability
speed = values.speed
return durability, speed
end
end
end
---comment
---@param prosthesisItem any Normal item
---@param inventory any player inventory
---@param partName any
---@return any equipped_prosthesis clothing item equipped prosthesis
function GenerateEquippedProsthesis(prosthesisItem, inventory, partName)
-- TODO Durability should be decided from the clothing item xml. Same thing for disassembling stuff
-- TODO some stuff should be defined by the limb, like -10 if forearm in speed
-- when we equip a prosthesis, we're gonna pass these parameters to the newly generated clothing item
-- when we unequip it, we regen the normal item with the parameters from the clothing item
local prosthesisName = prosthesisItem:getFullType()
local itemModData = prosthesisItem:getModData()
local durabilityBase = 0
local speedBase = 0
local durabilityTop = 0
local speedTop = 0
-- Check the item mod data if the values are different than the default values
if itemModData.TOC ~= nil then
durabilityBase = itemModData.baseDurability
durabilityTop = itemModData.topDurability
-- else
-- durability_base, speed_base = GetProsthesisStats(base_table, prosthesis_name)
-- durability_top, speed_top = GetProsthesisStats(top_table, prosthesis_name)
end
local baseName = prosthesisItem:getType()
local equippedProsthesisName = TocFindCorrectClothingProsthesis(baseName, partName)
local equippedProsthesis = inventory:AddItem(equippedProsthesisName)
equippedProsthesis:setCondition(prosthesisItem:getCondition())
equippedProsthesis:getModData().TOC = {
baseDurability = durabilityBase,
topDurability = durabilityTop,
}
return equippedProsthesis
end
----------------------------------------------------------
-- Recipe functions
ProsthesisRecipes = {}
-- Parts should have a default condition max set at creation
-- When we create a prosthesis, we carry the condition from the parts
-- If we disassemble the prosthesis, the condition will be carried back to the parts
-- Speed stat should be managed in another way, so change it
local function GetProsthesisPartName(arrayStats, prosthesisName)
for name, _ in pairs(arrayStats) do
if string.find(prosthesisName, name) then
return name
end
end
end
-- Creates the Normal Prosthesis Item
function ProsthesisRecipes.OnCreateProsthesis(items, result, player, selectedItem)
-- TODO We need a screwdriver to craft it? Some screws maybe
-- Set mod data for item with durability and all that crap
-- Get condition from the items
print("TOC: setting stats for prosthesis item")
local condition = 0
for i=1,items:size() do
local item = items:get(i-1)
condition = condition + item:getCondition()
end
result:setCondition(condition) -- Should be the sum?
result:getModData().TOC = {
baseDurability = 100,
topDurability = 100, -- Stores it here too so we can re-reference it for later
}
end
-- Reassign the correct condition to each item
function ProsthesisRecipes.OnDisassembleProsthesis(item, resultItems, player, selectedItem)
-- Check durability of original item
local itemModData = item.getModData().TOC
local durabilityTop = itemModData.top.durability
local durabilityBase = itemModData.base.durability
-- TODO do we actually need to store speed again?
local speedTop = itemModData.top.speed
local speedBase = itemModData.base.speed
-- Check name of the item
local prosthesisItemName = item:getFullType()
local baseName = GetProsthesisPartName(baseTable, prosthesisItemName)
local topName = GetProsthesisPartName(topTable, prosthesisItemName)
print("TOC: " .. baseName .. " and " .. topName)
local playerInv = player:getInventory()
local partBase = playerInv:AddItem("TOC.ProstPart" .. baseName)
partBase:setCondition(durabilityBase)
local partTop = playerInv:AddItem("TOC.ProstPart" .. topName)
partTop:setCondition(durabilityTop)
-- TODO Add Screws from the item back with a chance of them breaking
end
function ProsthesisRecipes.OnCreateProsthesisPartItem(items, result, player, selectedItem)
-- TODO Assign condition here from the table
end

View File

@@ -0,0 +1,273 @@
------------------------------------------
-------------- THE ONLY CURE -------------
------------------------------------------
------------- SERVER COMMANDS ------------
local ServerCommands = {}
ServerCommands.ResponseCanAct = function(arg)
print("TOC: ResponseCanAct")
local ui = GetConfirmUIMP()
ui.responseReceive = true
ui.responseAction = arg["toSend"][2]
ui.responsePartName = arg["toSend"][1]
ui.responseCan = arg["toSend"][3]
ui.responseUserName = getPlayerByOnlineID(arg["From"]):getUsername()
ui.responseActionIsBitten = getPlayerByOnlineID(arg["From"]):getBodyDamage():getBodyPart(TOC_Common.GetBodyPartFromPartName(ui
.responsePartName)):bitten()
end
ServerCommands.CanCutLimb = function(arg)
local partName = arg["toSend"]
arg["To"] = arg["From"]
arg["From"] = getPlayer():getOnlineID()
arg["command"] = "ResponseCanAct"
arg["toSend"] = { partName, "Cut", TOC_Common.CheckIfCanBeCut(partName) }
sendClientCommand("TOC", "SendServer", arg)
end
ServerCommands.CutLimb = function(arg)
local data = arg["toSend"]
local partName = data[1]
local surgeonFactor = data[2]
local bandageTable = data[3]
local painkillerTable = data[4]
TOC.CutLimb(partName, surgeonFactor, bandageTable, painkillerTable)
end
ServerCommands.CanOperateLimb = function(arg)
local partName = arg["toSend"]
arg["To"] = arg["From"]
arg["From"] = getPlayer():getOnlineID()
arg["command"] = "ResponseCanAct"
arg["toSend"] = { partName, "Operate", TOC_Common.CheckIfCanBeOperated(partName) }
sendClientCommand("TOC", "SendServer", arg)
end
ServerCommands.OperateLimb = function(arg)
local data = arg["toSend"]
local partName = data[1]
local surgeonFactor = data[2]
local useOven = data[3]
TOC.OperateLimb(partName, surgeonFactor, useOven)
end
ServerCommands.CanEquipProsthesis = function(arg)
local partName = arg["toSend"]
--local item = arg["toSend"][2] -- TODO Add item prosth here
arg["To"] = arg["From"]
arg["From"] = getPlayer():getOnlineID()
arg["command"] = "ResponseCanAct"
arg["toSend"] = {partName, "Equip", TOC_Common.CheckIfProsthesisCanBeEquipped(partName) }
sendClientCommand("TOC", "SendServer", arg)
end
ServerCommands.EquipProsthesis = function(arg)
-- part_name = arg[1]
-- prosthesis_item = arg[2]
-- prosthesis_name = arg[3]
local data = arg["toSend"]
local partName = data[1]
local prosthesisItem = data[2]
TOC.EquipProsthesis(partName, prosthesisItem, _) -- TODO Add the third param when modular prost are done
end
ServerCommands.CanUnequipProsthesis = function(arg)
local partName = arg["toSend"]
arg["To"] = arg["From"]
arg["From"] = getPlayer():getOnlineID()
arg["command"] = "ResponseCanAct"
arg["toSend"] = { partName, "Unequip", TOC_Common.CheckIfProsthesisCanBeUnequipped(partName)}
sendClientCommand("TOC", "SendServer", arg)
end
ServerCommands.UnequipProsthesis = function(arg)
local data = arg["toSend"]
local patient = data[1]
local partName = data[2]
local equippedProsthesis = data[3]
TOC.UnequipProsthesis(patient, partName, equippedProsthesis)
end
ServerCommands.CanResetEverything = function(arg)
local partName = "RightHand" --useless
arg["To"] = arg["From"]
arg["From"] = getPlayer():getOnlineID()
arg["command"] = "ResponseCanAct"
arg["toSend"] = { partName, "Cut", true }
sendClientCommand("TOC", "SendServer", arg)
end
ServerCommands.ResetEverything = function(_)
TOC_Cheat.ResetEverything()
end
-- Used when amputating the limb of another player
ServerCommands.AcceptDamageOtherPlayer = function(arg)
local patient = getPlayerByOnlineID(arg[1])
local partName = arg[2]
TOC.DamagePlayerDuringAmputation(patient, partName)
end
-- Used to propagate animation changes after amputating a foot
ServerCommands.SetCrawlAnimation = function(args)
local player = getPlayerByOnlineID(args.id)
local check = args.check
player:setVariable('IsCrawling', tostring(check))
end
-- Used to propagate the stop of the sound of amputation
ServerCommands.StopAmputationSound = function(args)
local player = getPlayerByOnlineID(args.surgeon_id)
player:getEmitter():stopSoundByName("Amputation_Sound")
end
local function OnServerCommand(module, command, args)
if module == 'TOC' then
print("TOC: On TOC Server Command " .. command)
if ServerCommands[command] then
print("Found command, executing it now")
args = args or {}
ServerCommands[command](args)
end
end
end
Events.OnServerCommand.Add(OnServerCommand)
---------------------------------- Global Mod Data -----------------------------
local function OnReceiveGlobalModData(key, modData)
if modData then
ModData.remove(key)
ModData.add(key, modData)
end
end
Events.OnReceiveGlobalModData.Add(OnReceiveGlobalModData)
local function OnConnected()
ModData.request("TOC_PLAYER_DATA")
end
Events.OnConnected.Add(OnConnected)
--------------------------------------------------------
function SendCutLimb(player, partName, surgeonFactor, bandageTable, painkillerTable)
local arg = {}
arg["From"] = getPlayer():getOnlineID()
arg["To"] = player:getOnlineID()
arg["command"] = "CutLimb"
-- TODO Hotfix for sound, fix this later
arg["toSend"] = {partName, surgeonFactor, bandageTable, painkillerTable}
sendClientCommand("TOC", "SendServer", arg)
end
function SendOperateLimb(player, partName, surgeonFactor, useOven)
local arg = {}
arg["From"] = getPlayer():getOnlineID()
arg["To"] = player:getOnlineID()
arg["command"] = "OperateLimb"
arg["toSend"] = { partName, surgeonFactor, useOven }
sendClientCommand("TOC", "SendServer", arg)
end
function SendEquipProsthesis(player, partName, item, prosthesisBaseName)
local arg = {}
arg["From"] = getPlayer():getOnlineID()
arg["To"] = player:getOnlineID()
arg["command"] = "EquipProsthesis"
arg["toSend"] = { partName, item, prosthesisBaseName}
sendClientCommand("TOC", "SendServer", arg)
end
function SendUnequipProsthesis(player, partName, item)
local arg = {}
arg["From"] = getPlayer():getOnlineID()
arg["To"] = player:getOnlineID()
arg["command"] = "UnequipProsthesis"
arg["toSend"] = { player, partName, item}
sendClientCommand("TOC", "SendServer", arg)
end
function AskCanCutLimb(player, partName)
GetConfirmUIMP().responseReceive = false
local arg = {}
arg["From"] = getPlayer():getOnlineID()
arg["To"] = player:getOnlineID()
arg["command"] = "CanCutLimb"
arg["toSend"] = partName
sendClientCommand("TOC", "SendServer", arg)
end
function AskCanOperateLimb(player, partName)
GetConfirmUIMP().responseReceive = false
local arg = {}
arg["From"] = getPlayer():getOnlineID()
arg["To"] = player:getOnlineID()
arg["command"] = "CanOperateLimb"
arg["toSend"] = partName
sendClientCommand("TOC", "SendServer", arg)
end
function AskCanEquipProsthesis(player, partName)
GetConfirmUIMP().responseReceive = false
local arg = {}
arg["From"] = getPlayer():getOnlineID()
arg["To"] = player:getOnlineID()
arg["command"] = "CanEquipProsthesis"
arg["toSend"] = partName -- TODO to be more precise there should be prosthesis item here too to check
sendClientCommand("TOC", "SendServer", arg)
end
function AskCanUnequipProsthesis(player, partName)
GetConfirmUIMP().responseReceive = false
local arg = {}
arg["From"] = getPlayer():getOnlineID()
arg["To"] = player:getOnlineID()
arg["command"] = "CanUnequipProsthesis"
arg["toSend"] = partName
sendClientCommand("TOC", "SendServer", arg)
end

View File

@@ -0,0 +1,91 @@
------------------------------------------
-------------- THE ONLY CURE -------------
------------------------------------------
--------- TEST AND DEBUG FUNCTIONS -------
------ TEST FUNCTIONS, DON'T USE THESE!!! ---------------
-- Side functions
local function TocGetAmputationFullTypeFromInventory(player, side, limb)
local player_inventory = player:getInventory()
local item_name = "TOC.Amputation_" .. TOC_Common.ConcatPartName(side, limb)
local found_item = player_inventory:FindAndReturn(item_name)
if found_item then
return found_item:getFullType()
end
end
local function TocGetEquippedProsthesisFullTypeFromInventory(player, side, limb)
local playerInventory = player:getInventory()
for _, prost in ipairs(GetProsthesisList()) do
local itemName = TocFindCorrectClothingProsthesis(prost, TOC_Common.ConcatPartName(side, limb))
local foundItem = playerInventory:FindAndReturn(itemName)
if foundItem then
return foundItem:getFullType()
end
end
end
-- Set correct body locations for items in inventory
function TocResetClothingItemBodyLocation(player, side, limb)
local playerInv = player:getInventory()
local limbsData = player:getModData().TOC.limbs
local amputationItemName = TocGetAmputationFullTypeFromInventory(player, side, limb)
local equippedProsthesisItemName = TocGetEquippedProsthesisFullTypeFromInventory(player, side, limb)
if amputationItemName ~= nil then
local amputationItem = playerInv:FindAndReturn(amputationItemName)
if amputationItem ~= nil then
player:removeWornItem(amputationItem)
player:getInventory():Remove(amputationItem)
amputationItem = playerInv:AddItem(amputationItemName)
TOC_Visuals.SetTextureForAmputation(amputationItem, player, limbsData[TOC_Common.ConcatPartName(side, limb)].isCicatrized)
player:setWornItem(amputationItem:getBodyLocation(), amputationItem)
end
amputationItem = nil -- reset it
end
if equippedProsthesisItemName ~= nil then
local prosthesisItem = playerInv:FindAndReturn(equippedProsthesisItemName)
if prosthesisItem ~= nil then
print("Resetting " .. prosthesisItem:getName())
player:removeWornItem(prosthesisItem)
player:getInventory():Remove(prosthesisItem)
prosthesisItem = playerInv:AddItem(equippedProsthesisItemName)
player:setWornItem(prosthesisItem:getBodyLocation(), prosthesisItem)
end
prosthesisItem = nil -- reset it
end
end
function TocTestBodyLocations()
local group = BodyLocations.getGroup("Human")
local list = getClassFieldVal(group, getClassField(group, 1))
for i=1, list:size() do
print(list:get(i -1):getId())
end
end
function TOCTestItem()
local player = getPlayer()
local player_inventory = player:getInventory()
local item_name = "TOC.Amputation_" .. "Right" .. "_" .. "Hand"
local found_item = player_inventory:FindAndReturn(item_name)
print(found_item:getID())
print("_______________")
found_item:setID(12334)
print(found_item:getID())
end

View File

@@ -0,0 +1,256 @@
------------------------------------------
-------------- THE ONLY CURE -------------
------------------------------------------
------------- UPDATE EVENTS --------------
require "TOC_Init"
local function CheckIfPlayerIsInfected(player, limbsData)
local bodyDamage = player:getBodyDamage()
-- Check for amputable limbs
for _, v in ipairs(TOC_Common.GetAcceptableBodyPartTypes()) do
local partName = TOC_Common.GetPartNameFromBodyPartType(v)
local partData = limbsData[partName]
local bodyPart = bodyDamage:getBodyPart(v)
if bodyPart:bitten() and partData ~= nil then
if partData.isCut == false then
partData.isInfected = true
end
end
end
-- Check for everything else
for _, v in pairs(TOC_Common.GetOtherBodyPartTypes()) do
if bodyDamage:getBodyPart(v):bitten() then
limbsData.isOtherBodypartInfected = true -- Even one is enough, stop cycling if we find it
break
end
end
end
local function ManagePhantomPain(player, TOCModData)
local limbsData = TOCModData.limbs
local limbParameters = TOC.limbParameters
local body_damage = player:getBodyDamage()
for _, partName in pairs(TOC_Common.GetPartNames()) do
if limbsData[partName].isCut and limbsData[partName].isAmputationShown and ZombRand(1, 100) < 10 then
local bodyPart = body_damage:getBodyPart(TOC_Common.GetBodyPartFromPartName(partName))
local addedPain
if limbsData[partName].isCauterized then addedPain = 60 else addedPain = 30 end
bodyPart:setAdditionalPain(ZombRand(1, addedPain))
for _, depended_v in pairs(limbParameters[partName].dependsOn) do
if limbsData[depended_v].isCauterized then addedPain = 60 else addedPain = 30 end
bodyPart:setAdditionalPain(ZombRand(1, addedPain))
end
end
end
end
local function SetHealthStatusForBodyPart(partData, partName, player)
-- In case the player gets bit in a cut area, we have to heal him...
local bodyDamage = player:getBodyDamage()
local bodyPart = bodyDamage:getBodyPart(TOC_Common.GetBodyPartFromPartName(partName))
if not bodyPart then
print("TOC ERROR: Can't update health of " .. partName)
return false
end
-- Check bandages
local isBandaged = false
local bandageLife = 0
local bandageType = ""
-- TODO Bandages should have some disadvantage when not operated... Like getting drenched or something
if bodyPart:bandaged() then
isBandaged = true -- this is useless
bandageLife = bodyPart:getBandageLife()
bandageType = bodyPart:getBandageType()
end
-- Check for stitching
local isStitched = false -- TODO Implement this
if partData[partName].isCut then
--print("TOC: Check update for " .. part_name)
-- if the player gets attacked and damaged in a cut area we have to reset it here since it doesn't make any sense
-- this is using map 1:1, so it doesn't affect the wound caused by the amputation
-- TODO if the players gets damaged in a cut part and it has a prosthesis, damage the prosthesis
bodyPart:setBleeding(false)
bodyPart:setDeepWounded(false)
bodyPart:setBleedingTime(0)
bodyPart:setDeepWoundTime(0)
bodyPart:SetBitten(false)
bodyPart:setScratched(false, false) -- ffs it always fucks me
bodyPart:setCut(false)
bodyPart:SetInfected(false)
bodyPart:setBiteTime(0)
partData[partName].isInfected = false
-- Set max health for body part
if partData[partName].isCicatrized and bodyPart:getHealth() > 80 then
bodyPart:SetHealth(80)
elseif bodyPart:getHealth() > 40 then
bodyPart:SetHealth(40)
end
-- Cicatrization check
if not partData[partName].isCicatrized then
if partData[partName].cicatrizationTime < 0 then
partData[partName].isCicatrized = true
local playerInv = player:getInventory()
local amputatedClothingItemName = TOC_Common.FindAmputationOrProsthesisName(partName, player, "Amputation")
local amputatedClothingItem = playerInv:FindAndReturn(amputatedClothingItemName)
player:removeWornItem(amputatedClothingItem)
TOC_Visuals.SetTextureForAmputation(amputatedClothingItem, player, true)
player:setWornItem(amputatedClothingItem:getBodyLocation(), amputatedClothingItem)
if (not player:HasTrait("Brave")) and ZombRand(1, 11) > 5 then
player:getTraits():add("Brave")
end
if (not player:HasTrait("Insensitive")) and ZombRand(1, 11) > 5 then
player:getTraits():add("Insensitive")
end
end
end
end
end
local function UpdatePlayerHealth(player, partData)
local bodyDamage = player:getBodyDamage()
if player:HasTrait("Insensitive") then bodyDamage:setPainReduction(49) end
for _, partName in pairs(TOC_Common.GetPartNames()) do
if partData[partName].isCut then
SetHealthStatusForBodyPart(partData, partName, player)
end
end
end
-------------------------------------------
-- MAIN UPDATE FUNCTIONS
TOC.UpdateOnTick = function()
local player = getPlayer()
if player == nil then
return
end
local TOCModData = player:getModData().TOC
if TOCModData ~= nil then
CheckIfPlayerIsInfected(player, TOCModData.limbs)
UpdatePlayerHealth(player, TOCModData.limbs)
end
end
TOC.UpdateEveryTenMinutes = function()
local player = getPlayer()
if player == nil then
return
end
local partData = player:getModData().TOC.limbs
--Experience for prosthesis user
for _, side in pairs(TOC.sideNames) do
if partData[TOC_Common.ConcatPartName(side, "Hand")].isProsthesisEquipped or partData[TOC_Common.ConcatPartName(side, "LowerArm")].isProsthesisEquipped then
player:getXp():AddXP(Perks[TOC_Common.ConcatPartName(side, "Hand")], 4)
end
end
-- Updates the cicatrization time
for _, partName in pairs(TOC_Common.GetPartNames()) do
if partData[partName].isCut and not partData[partName].isCicatrized then
--Wound cleanliness contributes to cicatrization
-- TODO we reset this stuff every time we restart the game for compat reason, this is an issue
local amputatedLimbItem = TOC_Common.GetAmputationItemInInventory(player, partName)
local itemDirtyness = amputatedLimbItem:getDirtyness()/100
local itemBloodyness = amputatedLimbItem:getBloodLevel()/100
local modifier = SandboxVars.TOC.CicatrizationSpeedMultiplier - itemBloodyness - itemDirtyness
--print("TOC: Type " .. amputated_limb_item:getFullType())
--print("TOC: Dirtyness " .. item_dirtyness)
--print("TOC: Bloodyness " .. item_bloodyness)
partData[partName].cicatrizationTime = partData[partName].cicatrizationTime - modifier
end
end
end
TOC.UpdateEveryOneMinute = function()
local player = getPlayer()
-- To prevent errors during loading
if player == nil then
return
end
local TOCModData = player:getModData().TOC
if SandboxVars.TOC.EnablePhantomPain then
if TOCModData ~= nil then
ManagePhantomPain(player, TOCModData)
end
end
-- Updates TOC data in a global way, basically player:transmitModData but it works
-- Sends only Limbs since the other stuff is mostly static
if TOCModData ~= nil then
-- FIXME Send little packets instead of the whole thing?
-- TODO we shouldn't run this if we're in SP I guess?
sendClientCommand(player, 'TOC', 'ChangePlayerState', { TOCModData.limbs } )
end
end

View File

@@ -0,0 +1,60 @@
------------------------------------------
-------------- THE ONLY CURE -------------
------------------------------------------
------------ VISUALS FUNCTIONS -----------
if TOC_Visuals == nil then
TOC_Visuals = {}
end
TOC_Visuals.SetTextureForAmputation = function(item, player, cicatrized)
local humanVisual = player:getHumanVisual()
local textureString = humanVisual:getSkinTexture()
local isHairy = string.find(textureString, "a$")
-- Hairy bodies
if isHairy then
textureString = textureString:sub(1, -2) -- Removes b at the end to make it compatible
end
local matchedIndex = string.match(textureString, "%d$")
if isHairy then
matchedIndex = matchedIndex + 5
end
if cicatrized then
if isHairy then
matchedIndex = matchedIndex + 5 -- to use the cicatrized texture on hairy bodies
else
matchedIndex = matchedIndex + 10 -- cicatrized texture only, no hairs
end
end
--print("TOC: Setting texture " .. matched_index)
item:getVisual():setTextureChoice(tonumber(matchedIndex - 1)) -- it counts from 0, so we have to subtract 1
end
TOC_Visuals.SetBloodOnAmputation = function(player, bodyPart)
local bodyPartType = bodyPart:getType()
local bloodBodyPartType
if bodyPartType == BodyPartType.Hand_R then
bloodBodyPartType = BloodBodyPartType.ForeArm_R
elseif bodyPartType == BodyPartType.Hand_L then
bloodBodyPartType = BloodBodyPartType.ForeArm_L
elseif bodyPartType == BodyPartType.Forearm_L or bodyPartType == BodyPartType.UpperArm_L then
bloodBodyPartType = BloodBodyPartType.UpperArm_L
elseif bodyPartType == BodyPartType.Forearm_R or bodyPartType == BodyPartType.UpperArm_R then
bloodBodyPartType = BloodBodyPartType.UpperArm_R
end
player:addBlood(bloodBodyPartType, false, true, false)
player:addBlood(BloodBodyPartType.Torso_Lower, false, true, false)
end

View File

@@ -0,0 +1,182 @@
------------------------------------------
-------------- THE ONLY CURE -------------
------------------------------------------
require "TimedActions/ISBaseTimedAction"
TOC_CutLimbAction = ISBaseTimedAction:derive("TOC_CutLimbAction")
function TOC_CutLimbAction:isValid()
return self.patientX == self.patient:getX() and self.patientY == self.patient:getY()
end
function TOC_CutLimbAction:waitToStart()
if self.patient == self.surgeon then
return false
end
self.surgeon:faceThisObject(self.patient)
return self.surgeon:shouldBeTurning()
end
function TOC_CutLimbAction:update()
if self.patient ~= self.surgeon then
self.surgeon:faceThisObject(self.patient)
end
-- Sound handling
if self.soundTime < getTimestamp() then
self.soundTime = getTimestamp()
if not self.character:getEmitter():isPlaying(self.sawSound) then
--print("TOC: Running sound again")
self.sawSound = self.character:getEmitter():playSound("Amputation_Sound")
addSound(self.surgeon, self.surgeon:getX(), self.surgeon:getY(), self.surgeon:getZ(), 3, 3)
end
end
end
function TOC_CutLimbAction:stop()
--print("Stopping ISCutLimb")
-- Handles sound
if self.sawSound and self.sawSound ~= 0 and self.surgeon:getEmitter():isPlaying(self.sawSound) then
self.surgeon:getEmitter():stopSound(self.sawSound)
end
-- TODO test this with more than 2 players
-- TODO this gets bugged when player dies while amputating
end
function TOC_CutLimbAction:start()
-- TODO Add a check so you can't cut your arm if you don't have hands or if you only have one arm and want to cut that same arm.
self:setActionAnim("SawLog")
local sawItem = TOC_Common.GetSawInInventory(self.surgeon)
self.soundTime = 0
self.worldSoundTime = 0
self.sawSound = self.surgeon:getEmitter():playSound("Amputation_Sound")
-- Return whatever object we've got in the inventory
if self.surgeon:getPrimaryHandItem() then
ISTimedActionQueue.add(ISUnequipAction:new(self.surgeon, self.surgeon:getPrimaryHandItem(), 2));
end
if self.surgeon:getSecondaryHandItem() and self.surgeon:getSecondaryHandItem() ~= self.surgeon:getPrimaryHandItem() then
ISTimedActionQueue.add(ISUnequipAction:new(self.surgeon, self.surgeon:getSecondaryHandItem(), 2));
end
if sawItem then
self:setOverrideHandModels(sawItem:getStaticModel(), nil)
end
if self.patient == self.surgeon then
TOC.DamagePlayerDuringAmputation(self.patient, self.partName)
else
sendClientCommand(self.surgeon, "TOC", "AskDamageOtherPlayer", {self.patient:getOnlineID(), self.partName})
end
end
function TOC_CutLimbAction:findArgs()
local surgeonFactor = self.surgeon:getPerkLevel(Perks.Doctor)
if self.surgeon:getDescriptor():getProfession() == "surgeon" then surgeonFactor = surgeonFactor + 15 end
if self.surgeon:getDescriptor():getProfession() == "doctor" then surgeonFactor = surgeonFactor + 9 end
if self.surgeon:getDescriptor():getProfession() == "nurse" then surgeonFactor = surgeonFactor + 4 end
local bandageTable = {
useBandage = false,
bandageType = nil,
isBandageSterilized = nil
}
local painkiller_table = {}
local bandage = self.surgeon:getInventory():FindAndReturn('Bandage')
local sterilizedBandage = self.surgeon:getInventory():FindAndReturn('AlcoholBandage')
--local ripped_sheets = self.surgeon:getInventory():FindAndReturn("...")
if sterilizedBandage then
bandageTable.bandageType = sterilizedBandage:getType()
bandageTable.isBandageSterilized = true
bandageTable.useBandage = true
self.surgeon:getInventory():Remove(sterilizedBandage)
surgeonFactor = surgeonFactor + 4
elseif bandage then
bandageTable.bandageType = bandage:getType()
bandageTable.isBandageSterilized = false
bandageTable.useBandage = true
self.surgeon:getInventory():Remove(bandage)
surgeonFactor = surgeonFactor + 2
else
bandageTable.bandageType = ""
bandageTable.useBandage = false
bandageTable.isBandageSterilized = false
end
-- local painkiller = self.surgeon:getInventory():FindAndReturn('Pills');
-- if painkiller then
-- usePainkiller = true;
-- painkillerCount = painkiller:getRemainingUses();
-- end
return surgeonFactor, bandageTable, painkiller_table
end
function TOC_CutLimbAction:perform()
local surgeonFactor, bandageTable, painkillerTable = self:findArgs()
if self.patient ~= self.surgeon and isClient() then
SendCutLimb(self.patient, self.partName, surgeonFactor, bandageTable, painkillerTable)
sendClientCommand(self.surgeon, "TOC", "AskStopAmputationSound", {surgeonID = self.surgeon:getOnlineID()})
else
TOC.CutLimb(self.partName, surgeonFactor, bandageTable, painkillerTable)
end
self.surgeon:getEmitter():stopSoundByName("Amputation_Sound")
self.surgeon:getXp():AddXP(Perks.Doctor, 400)
ISBaseTimedAction.perform(self)
end
function TOC_CutLimbAction:new(patient, surgeon, partName)
-- TODO align surgeon, patient not patient, surgeon
local o = {}
setmetatable(o, self)
self.__index = self
o.partName = partName
o.character = surgeon -- For anim
o.surgeon = surgeon; -- Surgeon or player that make the operation
o.patient = patient; -- Player to amputate
o.patientX = patient:getX()
o.patientY = patient:getY()
o.maxTime = 1000 - (surgeon:getPerkLevel(Perks.Doctor) * 50)
o.stopOnWalk = true
o.stopOnRun = true
o.ignoreHandsWounds = false
o.fromHotbar = true
if o.patient:isTimedActionInstant() then o.maxTime = 1 end
return o
end

View File

@@ -0,0 +1,84 @@
require "TimedActions/ISBaseTimedAction"
TOC_InstallProsthesisAction = ISBaseTimedAction:derive("TOC_InstallProsthesisAction")
function TOC_InstallProsthesisAction:isValid()
-- TODO add here conditions if the action can be performed or not, so if thing is in inventory
-- TODO 'not sure about multiplayer, maybe an overriding check?
return true
end
function TOC_InstallProsthesisAction:update()
self.item:setJobDelta(self:getJobDelta())
end
function TOC_InstallProsthesisAction:start()
self.item:setJobType("Install prosthesis")
self.item:setJobDelta(0.0)
self:setActionAnim("WearClothing")
self:setAnimVariable("WearClothingLocation", "Jacket")
end
function TOC_InstallProsthesisAction:stop()
ISBaseTimedAction.stop(self)
self.item:setJobDelta(0.0)
end
function TOC_InstallProsthesisAction:perform()
local prosthesisBaseName = self.item:getType()
self.item:setJobDelta(0.0)
-- local toc_data = self.character:getModData().TOC
--local partName = TocGetPartNameFromBodyPartType(self.bodyPart:getType())
local bodyPartType = TOC_Common.GetBodyPartFromPartName(self.partName)
-- Check if can be performed. This shouldn't be necessary, but just to be sure
if bodyPartType == BodyPartType.UpperArm_L or bodyPartType == BodyPartType.UpperArm_R then
print("Can't equip prosthesis")
return
end
if self.patient ~= self.surgeon and isClient() then
SendEquipProsthesis(self.patient, self.partName, self.item, prosthesisBaseName)
else
TOC.EquipProsthesis(self.partName, self.item, prosthesisBaseName)
end
self.surgeon:getInventory():Remove(prosthesisBaseName) -- Removes the base item after we transferred everything
-- needed to remove from queue / start next.
ISBaseTimedAction.perform(self)
end
function TOC_InstallProsthesisAction:new(surgeon, patient, item, partName)
local o = ISBaseTimedAction.new(self, patient)
o.character = surgeon -- For animation, since self.startAnim or whatever relies on this
o.surgeon = surgeon
o.patient = patient
o.item = item
o.partName = partName
--o.bodyPart = bodyPart
o.maxTime = 100
o.stopOnWalk = true
o.stopOnRun = true
o.cloth = nil
o.ignoreHandsWounds = false
o.fromHotbar = true -- just to disable hotbar:update() during the wearing
if o.character:isTimedActionInstant() then o.maxTime = 1 end
return o
end

View File

@@ -0,0 +1,101 @@
require "TimedActions/ISBaseTimedAction"
TOC_OperateLimbAction = ISBaseTimedAction:derive("TOC_OperateLimbAction")
function TOC_OperateLimbAction:isValid()
return self.patientX == self.patient:getX() and self.patientY == self.patient:getY()
end
function TOC_OperateLimbAction:waitToStart()
if self.patient == self.surgeon then
return false
end
self.surgeon:faceThisObject(self.patient)
return self.surgeon:shouldBeTurning()
end
function TOC_OperateLimbAction:update()
if self.patient ~= self.surgeon then
self.surgeon:faceThisObject(self.patient)
end
end
function TOC_OperateLimbAction:start()
self:setActionAnim("MedicalCheck")
if self.useOven then
self.sound = self.patient:getEmitter():playSound("Burn_sound")
self:forceComplete()
end
end
function TOC_OperateLimbAction:findArgs()
local surgeonFactor = self.surgeon:getPerkLevel(Perks.Doctor)
if self.useOven then
surgeonFactor = surgeonFactor + 100
else
if self.kit then
local weight = math.floor(self.kit:getWeight() * 10 + 0.5)
if weight == 1 then
surgeonFactor = surgeonFactor + 2
elseif weight == surgeonFactor then
surgeonFactor = surgeonFactor + 4
elseif weight == 3 then
surgeonFactor = surgeonFactor + 6
end
end
if self.surgeon:getDescriptor():getProfession() == "surgeon" then surgeonFactor = surgeonFactor + 10 end
if self.surgeon:getDescriptor():getProfession() == "doctor" then surgeonFactor = surgeonFactor + 5 end
if self.surgeon:getDescriptor():getProfession() == "nurse" then surgeonFactor = surgeonFactor + 2 end
end
return surgeonFactor, self.useOven;
end
function TOC_OperateLimbAction:perform()
local surgeonFactor, useOven = self:findArgs()
if self.patient ~= self.surgeon and isClient() then
SendOperateLimb(self.patient, self.partName, surgeonFactor, useOven)
else
TOC.OperateLimb(self.partName, surgeonFactor, useOven)
end
self.surgeon:getXp():AddXP(Perks.Doctor, 400)
if self.kit and not useOven then
self.surgeon:getInventory():Remove(self.kit)
end
ISBaseTimedAction.perform(self)
end
function TOC_OperateLimbAction:new(patient, surgeon, kit, partName, useOven)
local o = ISBaseTimedAction.new(self, patient)
o.partName = partName
o.patient = patient
o.character = surgeon -- For anim
o.patientX = patient:getX()
o.patientY = patient:getY()
o.surgeon = surgeon
o.kit = kit
o.useOven = useOven
--o.useOven = useOven;
if useOven then
o.maxTime = 30
else
o.maxTime = 200 - (surgeon:getPerkLevel(Perks.Doctor) * 10)
end
o.stopOnWalk = true
o.stopOnRun = true
o.ignoreHandsWounds = false
o.fromHotbar = true
if o.patient:isTimedActionInstant() then
o.maxTime = 1
end
return o
end

View File

@@ -0,0 +1,87 @@
require "TimedActions/ISBaseTimedAction"
TOC_UninstallProsthesisAction = ISBaseTimedAction:derive("TOC_UninstallProsthesisAction")
function TOC_UninstallProsthesisAction:isValid()
if self.item ~= nil and self.isProsthesisEquipped then
return true
else
return false
end
end
function TOC_UninstallProsthesisAction:update()
self.item:setJobDelta(self:getJobDelta())
end
function TOC_UninstallProsthesisAction:start()
self.item:setJobType("Uninstall prothesis")
self.item:setJobDelta(0.0);
self:setActionAnim("WearClothing");
if self.item:IsClothing() then
self:setAnimVariable("WearClothingLocation", "Jacket")
elseif self.item:IsInventoryContainer() and self.item:canBeEquipped() ~= "" then
self:setAnimVariable("WearClothingLocation", "Jacket")
end
self.character:setPrimaryHandItem(nil)
self.character:setSecondaryHandItem(self.item)
end
function TOC_UninstallProsthesisAction:stop()
ISBaseTimedAction.stop(self);
self.item:setJobDelta(0.0);
end
function TOC_UninstallProsthesisAction:perform()
self.item:getContainer():setDrawDirty(true)
self.item:setJobDelta(0.0)
if instanceof(self.item, "InventoryContainer") and self.item:canBeEquipped() ~= "" then
self.character:removeFromHands(self.item)
self.character:setWornItem(self.item:canBeEquipped(), self.item)
getPlayerInventory(self.character:getPlayerNum()):refreshBackpacks()
elseif self.item:getCategory() == "Clothing" then
if self.item:getBodyLocation() ~= "" then
self.character:setWornItem(self.item:getBodyLocation(), self.item)
end
end
if self.patient ~= self.surgeon and isClient() then
SendUnequipProsthesis(self.patient, self.partName, self.item)
else
TOC.OperateLimb(self.patient, self.partName, self.item)
end
ISBaseTimedAction.perform(self)
end
function TOC_UninstallProsthesisAction:new(surgeon, patient, partName)
local o = ISBaseTimedAction.new(self, surgeon)
local limbsData = patient:getModData().TOC.limbs
o.item = TOC_Common.FindItemInProstBodyLocation(partName, patient)
o.character = surgeon -- For animation purposes
o.patient = patient
o.surgeon = surgeon
o.partName = partName
o.isProsthesisEquipped = limbsData[partName].isProsthesisEquipped
o.maxTime = 100;
o.stopOnWalk = true
o.stopOnRun = true
o.ignoreHandsWounds = false
o.fromHotbar = true -- just to disable hotbar:update() during the wearing
if o.character:isTimedActionInstant() then o.maxTime = 1 end
return o
end

View File

@@ -0,0 +1,67 @@
require 'Items/ProceduralDistributions'
table.insert(ProceduralDistributions.list.MedicalClinicTools.items, "TOC.SurgeonMag1")
table.insert(ProceduralDistributions.list.MedicalClinicTools.items, 10)
table.insert(ProceduralDistributions.list.MedicalStorageTools.items, "TOC.SurgeonMag1")
table.insert(ProceduralDistributions.list.MedicalStorageTools.items, 10)
table.insert(ProceduralDistributions.list.ArmyStorageMedical.items, "TOC.SurgeonMag1")
table.insert(ProceduralDistributions.list.ArmyStorageMedical.items, 10)
table.insert(ProceduralDistributions.list.SafehouseMedical.items, "TOC.SurgeonMag1")
table.insert(ProceduralDistributions.list.SafehouseMedical.items, 10)
table.insert(ProceduralDistributions.list.MedicalClinicTools.items, "TOC.SurgeonMag2")
table.insert(ProceduralDistributions.list.MedicalClinicTools.items, 10)
table.insert(ProceduralDistributions.list.MedicalStorageTools.items, "TOC.SurgeonMag2")
table.insert(ProceduralDistributions.list.MedicalStorageTools.items, 10)
table.insert(ProceduralDistributions.list.ArmyStorageMedical.items, "TOC.SurgeonMag2")
table.insert(ProceduralDistributions.list.ArmyStorageMedical.items, 10)
table.insert(ProceduralDistributions.list.SafehouseMedical.items, "TOC.SurgeonMag2")
table.insert(ProceduralDistributions.list.SafehouseMedical.items, 10)
table.insert(ProceduralDistributions.list.MedicalClinicTools.items, "TOC.SurgeonMag3")
table.insert(ProceduralDistributions.list.MedicalClinicTools.items, 10)
table.insert(ProceduralDistributions.list.MedicalStorageTools.items, "TOC.SurgeonMag3")
table.insert(ProceduralDistributions.list.MedicalStorageTools.items, 10)
table.insert(ProceduralDistributions.list.ArmyStorageMedical.items, "TOC.SurgeonMag3")
table.insert(ProceduralDistributions.list.ArmyStorageMedical.items, 10)
table.insert(ProceduralDistributions.list.SafehouseMedical.items, "TOC.SurgeonMag3")
table.insert(ProceduralDistributions.list.SafehouseMedical.items, 10)
table.insert(ProceduralDistributions.list.MedicalClinicTools.items, "TOC.ProthesisMag1")
table.insert(ProceduralDistributions.list.MedicalClinicTools.items, 5)
table.insert(ProceduralDistributions.list.MedicalStorageTools.items, "TOC.ProthesisMag1")
table.insert(ProceduralDistributions.list.MedicalStorageTools.items, 5)
table.insert(ProceduralDistributions.list.ArmyStorageMedical.items, "TOC.ProthesisMag1")
table.insert(ProceduralDistributions.list.ArmyStorageMedical.items, 5)
table.insert(ProceduralDistributions.list.SafehouseMedical.items, "TOC.ProthesisMag1")
table.insert(ProceduralDistributions.list.SafehouseMedical.items, 5)
table.insert(ProceduralDistributions.list.StoreShelfMechanics.items, "TOC.ProthesisMag1")
table.insert(ProceduralDistributions.list.StoreShelfMechanics.items, 5)
table.insert(ProceduralDistributions.list.MechanicShelfTools.items, "TOC.ProthesisMag1")
table.insert(ProceduralDistributions.list.MechanicShelfTools.items, 5)
table.insert(ProceduralDistributions.list.MedicalClinicTools.items, "TOC.ProthesisMag2")
table.insert(ProceduralDistributions.list.MedicalClinicTools.items, 5)
table.insert(ProceduralDistributions.list.MedicalStorageTools.items, "TOC.ProthesisMag2")
table.insert(ProceduralDistributions.list.MedicalStorageTools.items, 5)
table.insert(ProceduralDistributions.list.ArmyStorageMedical.items, "TOC.ProthesisMag2")
table.insert(ProceduralDistributions.list.ArmyStorageMedical.items, 5)
table.insert(ProceduralDistributions.list.SafehouseMedical.items, "TOC.ProthesisMag2")
table.insert(ProceduralDistributions.list.SafehouseMedical.items, 5)
table.insert(ProceduralDistributions.list.StoreShelfMechanics.items, "TOC.ProthesisMag2")
table.insert(ProceduralDistributions.list.StoreShelfMechanics.items, 5)
table.insert(ProceduralDistributions.list.MechanicShelfTools.items, "TOC.ProthesisMag2")
table.insert(ProceduralDistributions.list.MechanicShelfTools.items, 5)
table.insert(ProceduralDistributions.list.MedicalClinicTools.items, "TOC.ProthesisMag3")
table.insert(ProceduralDistributions.list.MedicalClinicTools.items, 5)
table.insert(ProceduralDistributions.list.MedicalStorageTools.items, "TOC.ProthesisMag3")
table.insert(ProceduralDistributions.list.MedicalStorageTools.items, 5)
table.insert(ProceduralDistributions.list.ArmyStorageMedical.items, "TOC.ProthesisMag3")
table.insert(ProceduralDistributions.list.ArmyStorageMedical.items, 5)
table.insert(ProceduralDistributions.list.SafehouseMedical.items, "TOC.ProthesisMag3")
table.insert(ProceduralDistributions.list.SafehouseMedical.items, 5)
table.insert(ProceduralDistributions.list.StoreShelfMechanics.items, "TOC.ProthesisMag3")
table.insert(ProceduralDistributions.list.StoreShelfMechanics.items, 5)
table.insert(ProceduralDistributions.list.MechanicShelfTools.items, "TOC.ProthesisMag3")
table.insert(ProceduralDistributions.list.MechanicShelfTools.items, 5)

View File

@@ -0,0 +1,79 @@
------------------------------------------
-------------- THE ONLY CURE -------------
------------------------------------------
------------- CLIENT COMMANDS ------------
local ClientCommands = {}
-- Main handler of base functions for TOC, based on the original work for TOC
ClientCommands.SendServer = function(_, arg)
local otherPlayer = getPlayerByOnlineID(arg["To"])
sendServerCommand(otherPlayer, "TOC", arg["command"], arg)
end
-- Cutting Limbs
ClientCommands.AskDamageOtherPlayer = function(_, arg)
local patient = getPlayerByOnlineID(arg[1])
local patient_id = arg[1]
local partName = arg[2]
sendServerCommand(patient, "TOC", "AcceptDamageOtherPlayer", {patient_id, partName})
end
ClientCommands.AskStopAmputationSound = function(_, args)
print("TOC: We're in AskStopAmputationSound")
sendServerCommand("TOC", "StopAmputationSound", {surgeon_id = args.surgeonID})
end
-- Animations
ClientCommands.NotifyNewCrawlAnimation = function(_, args)
sendServerCommand("TOC", "SetCrawlAnimation", {id = args.id, check = args.check})
end
-- Cheats
ClientCommands.AskToResetEverything = function(_, arg)
local clickedPlayer = getPlayerByOnlineID(arg[1])
sendServerCommand(clickedPlayer, "TOC", "ResetEverything", {})
end
-- Global Mod Data data handler
ClientCommands.ChangePlayerState = function(playerObj, args)
ModData.get("TOC_PLAYER_DATA")[playerObj:getUsername()] = args
ModData.transmit("TOC_PLAYER_DATA")
end
------ Global Mod Data -----------
local function OnInitGlobalModData()
ModData.getOrCreate("TOC_PLAYER_DATA")
end
Events.OnInitGlobalModData.Add(OnInitGlobalModData)
------------------------------------------------------
local function OnClientCommand(module, command, playerObj, args)
if module == 'TOC' and ClientCommands[command] then
ClientCommands[command](playerObj, args)
end
end
Events.OnClientCommand.Add(OnClientCommand)

View File

@@ -0,0 +1,26 @@
local function AddBodyLocationBefore(new_location, move_to_location)
local group = BodyLocations.getGroup("Human")
local list = getClassFieldVal(group, getClassField(group, 1))
group:getOrCreateLocation(new_location)
local new_item = list:get(list:size()-1)
print("TOC: Created new body location" .. new_item:getId())
list:remove(new_item) -- We can't use the Index, it works if we pass the item though!
local i = group:indexOf(move_to_location)
list:add(i, new_item)
end
AddBodyLocationBefore("TOC_ArmRight", "Shoes")
AddBodyLocationBefore("TOC_ArmLeft", "Shoes")
AddBodyLocationBefore("TOC_ArmRightProsthesis", "Shoes")
AddBodyLocationBefore("TOC_ArmLeftProsthesis", "Shoes")
AddBodyLocationBefore("TOC_LegRight", "FannyPackFront")
AddBodyLocationBefore("TOC_LegLeft", "FannyPackFront")
AddBodyLocationBefore("TOC_LegRightProsthesis", "FannyPackFront")
AddBodyLocationBefore("TOC_LegLeftProsthesis", "FannyPackFront")

View File

@@ -0,0 +1,28 @@
local function AddProfession()
local surgeon = ProfessionFactory.addProfession(
'surgeon',
getText("UI_prof_surgeon"),
"profession_surgeon",
-6,
getText("UI_profdesc_surgeon")
);
surgeon:addXPBoost(Perks.Doctor, 4)
surgeon:addXPBoost(Perks.SmallBlade, 3)
-- TODO Fix this, it doesn't make any sense
surgeon:getFreeRecipes():add("Make metal hand")
surgeon:getFreeRecipes():add("Make metal hook")
surgeon:getFreeRecipes():add("Make wooden hook")
surgeon:getFreeRecipes():add("Combine real surgeon kit")
surgeon:getFreeRecipes():add("Combine surgeon kit")
surgeon:getFreeRecipes():add("Combine improvised surgeon kit")
local profList = ProfessionFactory.getProfessions()
for i=1,profList:size() do
local prof = profList:get(i-1)
BaseGameCharacterDetails.SetProfessionDescription(prof)
end
end
Events.OnGameBoot.Add(AddProfession)

View File

@@ -0,0 +1,8 @@
ContextMenu_EN = {
ContextMenu_Cut_Arm = "Cut arm",
ContextMenu_Operate_Arm = "Operate arm",
ContextMenu_TourniquetRightSwitch = "Tourniquet on Right Arm",
ContextMenu_TourniquetLeftSwitch = "Tourniquet on Left Arm",
}

View File

@@ -0,0 +1,10 @@
IGUI_EN = {
IGUI_ItemCat_Prosthesis = "Prosthesis",
IGUI_ItemCat_Amputation = "Amputation"
IGUI_ItemCat_Surgeon_kit = "Surgeon kit",
IGUI_perks_Right_Hand = "Right hand",
IGUI_perks_Left_Hand = "Left hand",
IGUI_perks_Prosthesis = "Prosthesis skills",
IGUI_TOC_RollUpSleeveForAmputatedLimbs = "Roll up sleeves for amputated limbs"
}

View File

@@ -0,0 +1,38 @@
DisplayName_EN = {
ItemName_TOC.Amputation_Right_Hand = "Amputated Right Hand",
ItemName_TOC.Amputation_Right_LowerArm = "Amputated Right Forearm",
ItemName_TOC.Amputation_Right_UpperArm = "Amputated Entire Right Arm",
ItemName_TOC.Amputation_Left_Hand = "Amputated Left Hand",
ItemName_TOC.Amputation_Left_LowerArm = "Amputated Left Forearm",
ItemName_TOC.Amputation_Left_UpperArm = "Amputated Entire Left Arm",
ItemName_TOC.Improvised_surgeon_kit = "Improvised surgeon kit",
ItemName_TOC.Surgeon_kit = "Surgeon kit",
ItemName_TOC.Real_surgeon_kit = "Real surgeon kit",
ItemName_TOC.Prost_Right_Hand_WoodenHook = "Right Hand - Wooden Hook",
ItemName_TOC.Prost_Left_Hand_WoodenHook = "Left Hand - Wooden Hook",
ItemName_TOC.Prost_Right_LowerArm_WoodenHook = "Right Forearm - Wooden Hook",
ItemName_TOC.Prost_Left_LowerArm_WoodenHook = "Left Forearm - Wooden Hook",
ItemName_TOC.Prost_Right_Hand_MetalHook = "Right Hand - Metal Hook",
ItemName_TOC.Prost_Left_Hand_MetalHook = "Left Hand - Metal Hook",
ItemName_TOC.Prost_Right_LowerArm_MetalHook = "Right Forearm - Metal Hook",
ItemName_TOC.Prost_Left_LowerArm_MetalHook = "Left Forearm - Metal Hook",
ItemName_TOC.Prost_Right_Hand_MetalHand = "Right Hand - Metal Hand",
ItemName_TOC.Prost_Left_Hand_MetalHand = "Left Hand - Metal Hand",
ItemName_TOC.Prost_Right_LowerArm_MetalHand = "Right Forearm - Metal Hand",
ItemName_TOC.Prost_Left_LowerArm_MetalHand = "Left Forearm - Metal Hand",
ItemName_TOC.WoodenHook = "Wooden Hook",
ItemName_TOC.MetalHook = "Metal Hook",
ItemName_TOC.MetalHand = "Metal Hand",
ItemName_TOC.ProstheticKnife = "Prosthetic Knife",
ItemName_TOC.SurgeonMag1 = "Surgeon magazine for dummies",
ItemName_TOC.SurgeonMag2 = "Surgeon magazine for students",
ItemName_TOC.SurgeonMag3 = "Surgeon magazine for experts",
ItemName_TOC.ProthesisMag1 = "Prothesis magazine for dummies",
ItemName_TOC.ProthesisMag2 = "Prothesis magazine for experienced",
ItemName_TOC.ProthesisMag3 = "Prothesis magazine for experts",
}

View File

@@ -0,0 +1,14 @@
Sandbox_EN = {
Sandbox_TOC = "The Only Cure",
Sandbox_TOC_EnablePhantomPain = "Enable Phantom Pain",
Sandbox_TOC_EnablePhantomPain_tooltip = "Every once in a while, your character will get a pain sensation where the old limb, now amputated, is supposed to be.",
Sandbox_TOC_CicatrizationSpeedMultiplier = "Cicatrization speed multiplier",
Sandbox_TOC_CicatrizationSpeedMultiplier_tooltip = "Customize this to make the cicatrization process faster.",
Sandbox_TOC_AmputationTimeMultiplier = "Amputation Time Scaler",
Sandbox_TOC_AmputationTimeMultiplier_tooltip = "Scales the amount of time multplying added after amputation.",
}

View File

@@ -0,0 +1,35 @@
Tooltip_EN = {
Tooltip_Real_surgeon_kit = "Real surgeon kit. To be used on an amputated limb<br>Helps healing the severed limb, reducing a lot of the time necessary to cicatrize.",
Tooltip_Surgeon_kit = "Surgeon kit. To be used on an amputated limb<br>Helps healing the severed limb, reducing some of the time necessary to cicatrize.",
Tooltip_Improvised_surgeon_kit = "Improvised surgeon kit. To be used on an amputated limb<br>Helps healing the severed limb, reducing a little the time necessary to cicatrize.",
Tooltip_equip_prothesis_hand = "A prosthesis equipped to the forearm",
Tooltip_equip_prothesis_fore = "A prosthesis equipped to the hand",
Tooltip_prosthesic_limb = "A prosthetic limb. You'll have to wait until your limb is cicatrized before installing it.<br> It's done by having a bandage (alcohol is better) when cut, use a surgeon kit and wait.",
Tooltip_ProstheticKnife = "Prost Knife test",
Recipe_Tooltip_AssembleProsthesis = "Make a prosthetic limb",
Recipe_Tooltip_DisassembleProsthesis = "Disassemble a prosthetic limb",
Recipe_Tooltip_Wooden_hook = "Make a prosthesic wooden hook.<br>Can be used on an amputated hand or forearm.<br>Can't be equipped if the upper arm is amputated.",
Recipe_Tooltip_Metal_hook = "Make a prosthesic metal hook.<br>Can be used on an amputated hand or forearm.<br>Can't be equipped if the upper arm is amputated.",
Recipe_Tooltip_Metal_hand = "Make a prosthesic metal hand.<br>Can be used on an amputated hand or forearm.<br>Can't be equipped if the upper arm is amputated.",
Recipe_Tooltip_Real_surgeon_kit = "Make a real surgeon kit.<br>Helps healing the severed limb, reducing a lot of the time necessary to cicatrize.",
Recipe_Tooltip_Surgeon_kit = "Make a surgeon kit.<br>Helps healing the severed limb, reducing some of the time necessary to cicatrize.",
Recipe_Tooltip_Improvised_surgeon_kit = "Make an improvised surgeon kit.<br>Helps healing the severed limb, reducing a little the time necessary to cicatrize."
Tooltip_SurgeonMag1 = "Learn how to make an improvised surgeon kit!",
Tooltip_SurgeonMag2 = "Learn how to make a surgeon kit!",
Tooltip_SurgeonMag3 = "Learn how to make a real surgeon kit!",
Tooltip_ProthesisMag1 = "Learn how to make a wooden hook!",
Tooltip_ProthesisMag2 = "Learn how to make a metal hook!",
Tooltip_ProthesisMag3 = "Learn how to make a metal hand!",
}

View File

@@ -0,0 +1,42 @@
UI_EN = {
UI_ContextMenu_InstallProthesis = "Install prothesis",
UI_ContextMenu_UninstallProthesis = "Uninstall prothesis",
UI_ContextMenu_Operate = "Operate",
UI_ContextMenu_OperateOven = "Operate with oven",
UI_ContextMenu_CutArm = "Cut arm",
UI_prof_surgeon = "Surgeon",
UI_profdesc_surgeon = "You are a surgeon! Start with all recipe of the mod the only cure.<br>Easier to amputate and operate amputees.",
UI_trait_Amputee_Hand = "Left Hand Amputated",
UI_trait_Amputee_Hand_desc = "You lost your left hand way before the apocalypse began.",
UI_trait_Amputee_LowerArm = "Left Forearm Amputated",
UI_trait_Amputee_LowerArm_desc = "You lost your left forearm way before the apocalypse began.",
UI_trait_Amputee_UpperArm = "Entire left Arm Amputated",
UI_trait_Amputee_UpperArm_desc = "You lost your entire left arm before the apocalypse, good luck.",
UI_trait_Insensitive = "Insensitive to pain",
UI_trait_Insensitivedesc = "Reduces maximum pain.",
UI_ContextMenu_Right_Hand = "Right hand",
UI_ContextMenu_Right_LowerArm = "Right forearm",
UI_ContextMenu_Right_UpperArm = "Right arm",
UI_ContextMenu_Left_Hand = "Left hand",
UI_ContextMenu_Left_LowerArm = "Left forearm",
UI_ContextMenu_Left_UpperArm = "Left arm",
UI_ContextMenu_Left_Foot = "Left foot",
UI_ContextMenu_Right_Foot = "Right foot"
UI_ContextMenu_My = "My ",
UI_ContextMenu_Now_cut = " is now healed!",
}