1
.vscode/settings.json
vendored
1
.vscode/settings.json
vendored
@@ -1,5 +1,6 @@
|
|||||||
{
|
{
|
||||||
"todo-tree.tree.scanMode": "workspace",
|
"todo-tree.tree.scanMode": "workspace",
|
||||||
|
"mod_id": "3236152598",
|
||||||
"zomboid_user_folder": "C:/Users/picch/Zomboid",
|
"zomboid_user_folder": "C:/Users/picch/Zomboid",
|
||||||
"zomboid_folder": "E:\\Steam\\steamapps\\common\\ProjectZomboid",
|
"zomboid_folder": "E:\\Steam\\steamapps\\common\\ProjectZomboid",
|
||||||
"zomboid_server_folder": "E:\\Steam\\steamapps\\common\\Project Zomboid Dedicated Server",
|
"zomboid_server_folder": "E:\\Steam\\steamapps\\common\\Project Zomboid Dedicated Server",
|
||||||
|
|||||||
15
.vscode/tasks.json
vendored
15
.vscode/tasks.json
vendored
@@ -9,6 +9,12 @@
|
|||||||
"options": {"statusbar": {"label": "$(combine) Assemble Mod"}},
|
"options": {"statusbar": {"label": "$(combine) Assemble Mod"}},
|
||||||
"command": "python ${config:zomboid_user_folder}/PaosCrap/make_workshop_pack.py picch ${workspaceFolderBasename}",
|
"command": "python ${config:zomboid_user_folder}/PaosCrap/make_workshop_pack.py picch ${workspaceFolderBasename}",
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
"label": "Upload mod",
|
||||||
|
"type": "shell",
|
||||||
|
"options": {"statusbar": {"label": "$(arrow-up) Upload Mod"}},
|
||||||
|
"command": "python ${config:zomboid_user_folder}/PaosCrap/upload_mod_to_steam/main.py ${config:mod_id} ${config:zomboid_user_folder}/Workshop/${workspaceFolderBasename}",
|
||||||
|
},
|
||||||
{
|
{
|
||||||
"label": "Run Zomboid Debug No Steam",
|
"label": "Run Zomboid Debug No Steam",
|
||||||
"type": "shell",
|
"type": "shell",
|
||||||
@@ -59,6 +65,15 @@
|
|||||||
"problemMatcher": [
|
"problemMatcher": [
|
||||||
"$eslint-stylish"
|
"$eslint-stylish"
|
||||||
]
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"label": "Run Zomboid Test Server 3",
|
||||||
|
"options": {"statusbar": {"label": "$(run) Zomboid Server (TOC+FH+BH+iMedsFixed)"}},
|
||||||
|
"type": "shell",
|
||||||
|
"command":"\"${config:zomboid_server_folder}\\StartServer64_nosteam_custom.bat\" TOC_FH_BH_imeds",
|
||||||
|
"problemMatcher": [
|
||||||
|
"$eslint-stylish"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
@@ -1,39 +1,75 @@
|
|||||||
|
|
||||||
|
---@class Compat
|
||||||
|
---@field handlers table<string, {fun : function, isActive : boolean}>
|
||||||
|
local Compat = {
|
||||||
|
handlers = {}
|
||||||
|
}
|
||||||
|
|
||||||
local function HandleModCompatibility()
|
--- Brutal hands has a TOC_COMPAT but its check is wrong and uses an old API.
|
||||||
|
function Compat.BrutalHandwork()
|
||||||
|
BrutalHands = BrutalHands or {}
|
||||||
|
BrutalHands.TOC = require("TOC/API")
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
--- Was handled inside old TOC
|
||||||
local activatedMods = getActivatedMods()
|
function Compat.FancyHandwork()
|
||||||
TOC_DEBUG.print("Checking for mods compatibility")
|
require("TimedActions/FHSwapHandsAction")
|
||||||
|
local og_FHSwapHandsAction_isValid = FHSwapHandsAction.isValid
|
||||||
--[[
|
function FHSwapHandsAction:isValid()
|
||||||
Brutal hands has a TOC_COMPAT but its check is wrong and uses an old API.
|
local tocApi = require("TOC/API")
|
||||||
]]
|
if tocApi.hasBothHands(self.character) then
|
||||||
if activatedMods:contains('BrutalHandwork') then
|
return og_FHSwapHandsAction_isValid(self)
|
||||||
TOC_DEBUG.print("found BrutalHandwork, activating compat module")
|
else
|
||||||
BrutalHands = BrutalHands or {}
|
return false
|
||||||
BrutalHands.TOC = require("TOC/API")
|
|
||||||
end
|
|
||||||
|
|
||||||
--[[
|
|
||||||
Was handled inside old TOC
|
|
||||||
]]
|
|
||||||
if activatedMods:contains('FancyHandwork') then
|
|
||||||
TOC_DEBUG.print("found FancyHandwork, activating compat module")
|
|
||||||
|
|
||||||
require("TimedActions/FHSwapHandsAction")
|
|
||||||
local og_FHSwapHandsAction_isValid = FHSwapHandsAction.isValid
|
|
||||||
function FHSwapHandsAction:isValid()
|
|
||||||
local tocApi = require("TOC/API")
|
|
||||||
if tocApi.hasBothHands(self.character) then
|
|
||||||
return og_FHSwapHandsAction_isValid(self)
|
|
||||||
else
|
|
||||||
return false
|
|
||||||
end
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
Events.OnGameStart.Add(HandleModCompatibility)
|
|
||||||
|
|
||||||
|
function Compat.iMeds()
|
||||||
|
require("Component/Interface/Service/ContextMenu/Menu/HealthPanel/HealthPanelMenuInitializer")
|
||||||
|
-- placeholder, in case we need to do something more drastic with it.
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------
|
||||||
|
|
||||||
|
Compat.handlers = {
|
||||||
|
["BrutalHandwork"] = {
|
||||||
|
fun = Compat.BrutalHandwork,
|
||||||
|
isActive = false},
|
||||||
|
["FancyHandwork"] = {
|
||||||
|
fun = Compat.FancyHandwork,
|
||||||
|
isActive = false},
|
||||||
|
|
||||||
|
-- either or
|
||||||
|
['iMeds'] = {
|
||||||
|
fun = Compat.iMeds,
|
||||||
|
isActive = false},
|
||||||
|
['iMedsFixed'] = {
|
||||||
|
fun = Compat.iMeds,
|
||||||
|
isActive = false}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function Compat.RunModCompatibility()
|
||||||
|
local activatedMods = getActivatedMods()
|
||||||
|
TOC_DEBUG.print("Checking for mods compatibility")
|
||||||
|
|
||||||
|
for k, modCompatHandler in pairs(Compat.handlers) do
|
||||||
|
if activatedMods:contains(k) then
|
||||||
|
TOC_DEBUG.print("Found " .. k .. ", running compatibility handler")
|
||||||
|
modCompatHandler.fun()
|
||||||
|
modCompatHandler.isActive = true
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
|
Events.OnGameStart.Add(Compat.RunModCompatibility)
|
||||||
|
|
||||||
|
return Compat
|
||||||
@@ -6,7 +6,7 @@ require("TOC/Events")
|
|||||||
|
|
||||||
---@class Main
|
---@class Main
|
||||||
local Main = {
|
local Main = {
|
||||||
_version = "2.0.15"
|
_version = "2.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
function Main.Start()
|
function Main.Start()
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
local StaticData = require("TOC/StaticData")
|
local StaticData = require("TOC/StaticData")
|
||||||
local CommandsData = require("TOC/CommandsData")
|
|
||||||
local DataController = require("TOC/Controllers/DataController")
|
local DataController = require("TOC/Controllers/DataController")
|
||||||
local CachedDataHandler = require("TOC/Handlers/CachedDataHandler")
|
local CachedDataHandler = require("TOC/Handlers/CachedDataHandler")
|
||||||
|
local Compat = require("TOC/Compat")
|
||||||
|
|
||||||
local CutLimbInteractionHandler = require("TOC/UI/Interactions/CutLimbInteractionHandler")
|
local CutLimbInteractionHandler = require("TOC/UI/Interactions/CutLimbInteractionHandler")
|
||||||
local WoundCleaningInteractionHandler = require("TOC/UI/Interactions/WoundCleaningInteractionHandler")
|
local WoundCleaningInteractionHandler = require("TOC/UI/Interactions/WoundCleaningInteractionHandler")
|
||||||
@@ -11,6 +11,9 @@ local WoundCleaningInteractionHandler = require("TOC/UI/Interactions/WoundCleani
|
|||||||
local isReady = false
|
local isReady = false
|
||||||
|
|
||||||
function SetHealthPanelTOC()
|
function SetHealthPanelTOC()
|
||||||
|
|
||||||
|
-- depending on compatibility
|
||||||
|
|
||||||
isReady = true
|
isReady = true
|
||||||
end
|
end
|
||||||
|
|
||||||
@@ -128,23 +131,23 @@ function ISHealthPanel:render()
|
|||||||
end
|
end
|
||||||
|
|
||||||
|
|
||||||
local og_ISHealthPanel_update = ISHealthPanel.update
|
-- local og_ISHealthPanel_update = ISHealthPanel.update
|
||||||
function ISHealthPanel:update()
|
-- function ISHealthPanel:update()
|
||||||
og_ISHealthPanel_update(self)
|
-- og_ISHealthPanel_update(self)
|
||||||
-- TODO Listen for changes on other player side instead of looping this
|
-- -- TODO Listen for changes on other player side instead of looping this
|
||||||
|
|
||||||
|
|
||||||
-- FIX Re-enable it, just for test
|
-- -- FIX Re-enable it, just for test
|
||||||
if self.character then
|
-- if self.character then
|
||||||
local locPlUsername = getPlayer():getUsername()
|
-- local locPlUsername = getPlayer():getUsername()
|
||||||
local remPlUsername = self.character:getUsername()
|
-- local remPlUsername = self.character:getUsername()
|
||||||
if locPlUsername ~= remPlUsername and self:isReallyVisible() then
|
-- if locPlUsername ~= remPlUsername and self:isReallyVisible() then
|
||||||
-- Request update for TOC DATA
|
-- -- Request update for TOC DATA
|
||||||
local key = CommandsData.GetKey(remPlUsername)
|
-- local key = CommandsData.GetKey(remPlUsername)
|
||||||
--ModData.request(key)
|
-- --ModData.request(key)
|
||||||
end
|
-- end
|
||||||
end
|
-- end
|
||||||
end
|
-- end
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
@@ -252,10 +255,10 @@ end
|
|||||||
|
|
||||||
local og_ISHealthPanel_getDamagedParts = ISHealthPanel.getDamagedParts
|
local og_ISHealthPanel_getDamagedParts = ISHealthPanel.getDamagedParts
|
||||||
function ISHealthPanel:getDamagedParts()
|
function ISHealthPanel:getDamagedParts()
|
||||||
-- TODO Overriding it is a lot easier, but ew
|
-- check for imeds or if TOC is ready to display its stuff on the health panel
|
||||||
|
if isReady == false or Compat.handlers['iMeds'].isActive or Compat.handlers['iMedsFixed'].isActive then
|
||||||
if isReady then
|
return og_ISHealthPanel_getDamagedParts(self)
|
||||||
|
elseif isReady then
|
||||||
local result = {}
|
local result = {}
|
||||||
local bodyParts = self:getPatient():getBodyDamage():getBodyParts()
|
local bodyParts = self:getPatient():getBodyDamage():getBodyParts()
|
||||||
if isClient() and not self:getPatient():isLocalPlayer() then
|
if isClient() and not self:getPatient():isLocalPlayer() then
|
||||||
@@ -274,8 +277,5 @@ function ISHealthPanel:getDamagedParts()
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
return result
|
return result
|
||||||
|
|
||||||
else
|
|
||||||
return og_ISHealthPanel_getDamagedParts(self)
|
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
@@ -1,151 +1,148 @@
|
|||||||
-- todo activate after some more testing
|
|
||||||
|
if not SandboxVars.TOC.EnableZombieAmputations then return end
|
||||||
|
|
||||||
|
require "lua_timers"
|
||||||
|
|
||||||
|
local ItemsController = require("TOC/Controllers/ItemsController")
|
||||||
|
local StaticData = require("TOC/StaticData")
|
||||||
|
local CommandsData = require("TOC/CommandsData")
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
---@param zombie IsoZombie|IsoGameCharacter|IsoMovingObject|IsoObject
|
||||||
|
---@return integer trueID
|
||||||
|
local function GetZombieID(zombie)
|
||||||
|
-- Big love to Chuck and Sir Doggy Jvla for this code
|
||||||
|
---@diagnostic disable-next-line: param-type-mismatch
|
||||||
|
local pID = zombie:getPersistentOutfitID()
|
||||||
|
local bits = string.split(string.reverse(Long.toUnsignedString(pID, 2)), "")
|
||||||
|
while #bits < 16 do bits[#bits + 1] = 0 end
|
||||||
|
|
||||||
|
-- trueID
|
||||||
|
bits[16] = 0
|
||||||
|
local trueID = Long.parseUnsignedLong(string.reverse(table.concat(bits, "")), 2)
|
||||||
|
|
||||||
|
return trueID
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
|
||||||
-- local ItemsController = require("TOC/Controllers/ItemsController")
|
---@param item InventoryItem
|
||||||
-- local StaticData = require("TOC/StaticData")
|
local function PredicateAmputationItems(item)
|
||||||
-- local CommandsData = require("TOC/CommandsData")
|
return item:getType():contains("Amputation_")
|
||||||
-- -------------------------------
|
end
|
||||||
|
|
||||||
-- ---@param item InventoryItem
|
---@param item InventoryItem
|
||||||
-- local function PredicateAmputationItems(item)
|
local function PredicateAmputationItemLeft(item)
|
||||||
-- return item:getType():contains("Amputation_")
|
return item:getType():contains("Amputation_") and item:getType():contains("_L")
|
||||||
-- end
|
end
|
||||||
|
|
||||||
|
---@param item InventoryItem
|
||||||
|
local function PredicateAmputationItemRight(item)
|
||||||
|
return item:getType():contains("Amputation_") and item:getType():contains("_R")
|
||||||
|
end
|
||||||
|
|
||||||
|
---@param zombie IsoZombie
|
||||||
|
local function SpawnAmputation(zombie, side)
|
||||||
|
local index = ZombRand(1, #StaticData.PARTS_STR)
|
||||||
|
local limb = StaticData.PARTS_STR[index] .. "_" .. side
|
||||||
|
local amputationFullType = StaticData.AMPUTATION_CLOTHING_ITEM_BASE .. limb
|
||||||
|
|
||||||
|
|
||||||
|
ItemsController.Zombie.SpawnAmputationItem(zombie, amputationFullType)
|
||||||
|
|
||||||
|
|
||||||
|
-- Add reference and transmit it to server
|
||||||
|
local pID = GetZombieID(zombie)
|
||||||
|
local zombieKey = CommandsData.GetZombieKey()
|
||||||
|
local zombiesMD = ModData.getOrCreate(zombieKey)
|
||||||
|
if zombiesMD[pID] == nil then zombiesMD[pID] = {} end
|
||||||
|
zombiesMD[pID][side] = amputationFullType
|
||||||
|
ModData.add(zombieKey, zombiesMD)
|
||||||
|
ModData.transmit(zombieKey)
|
||||||
|
end
|
||||||
|
|
||||||
|
-------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- local function PredicateAmputationItemLeft(item)
|
local bloodAmount = 10
|
||||||
-- return item:getType():contains("Amputation_") and item:getType():contains("_L")
|
|
||||||
-- end
|
|
||||||
|
|
||||||
-- local function PredicateAmputationItemRight(item)
|
|
||||||
-- return item:getType():contains("Amputation_") and item:getType():contains("_R")
|
|
||||||
-- end
|
|
||||||
|
|
||||||
-- ---@param zombie IsoZombie|IsoGameCharacter|IsoMovingObject|IsoObject
|
|
||||||
-- ---@return integer trueID
|
|
||||||
-- local function GetZombieID(zombie)
|
|
||||||
|
|
||||||
-- -- Big love to Chuck and Sir Doggy Jvla for this code
|
|
||||||
-- ---@diagnostic disable-next-line: param-type-mismatch
|
|
||||||
-- local pID = zombie:getPersistentOutfitID()
|
|
||||||
-- local bits = string.split(string.reverse(Long.toUnsignedString(pID, 2)), "")
|
|
||||||
-- while #bits < 16 do bits[#bits+1] = 0 end
|
|
||||||
|
|
||||||
-- -- trueID
|
|
||||||
-- bits[16] = 0
|
|
||||||
-- local trueID = Long.parseUnsignedLong(string.reverse(table.concat(bits, "")), 2)
|
|
||||||
|
|
||||||
-- return trueID
|
|
||||||
-- end
|
|
||||||
|
|
||||||
|
|
||||||
-- ---@param zombie IsoZombie
|
---@param player IsoGameCharacter
|
||||||
-- local function SpawnAmputation(zombie, side)
|
---@param zombie IsoZombie
|
||||||
-- local index = ZombRand(1, #StaticData.PARTS_STR)
|
---@param handWeapon HandWeapon
|
||||||
-- local limb = StaticData.PARTS_STR[index] .. "_" .. side
|
local function HandleZombiesAmputations(player, zombie, handWeapon, damage)
|
||||||
-- local amputationFullType = StaticData.AMPUTATION_CLOTHING_ITEM_BASE .. limb
|
if not instanceof(zombie, "IsoZombie") or not instanceof(player, "IsoPlayer") then return end
|
||||||
|
if player ~= getPlayer() then return end
|
||||||
|
|
||||||
|
-- Check type of weapon. No hands, only knifes or such
|
||||||
|
local weaponCategories = handWeapon:getScriptItem():getCategories()
|
||||||
|
if not (weaponCategories:contains("Axe") or weaponCategories:contains("LongBlade")) then return end
|
||||||
|
|
||||||
|
local isCrit = player:isCriticalHit()
|
||||||
|
local randomChance = ZombRand(0, 100) > (100 - SandboxVars.TOC.ZombieAmputationDamageChance)
|
||||||
|
if (damage > SandboxVars.TOC.ZombieAmputationDamageThreshold and randomChance) or isCrit then
|
||||||
|
TOC_DEBUG.print("Amputating zombie limbs - damage: " .. tostring(damage))
|
||||||
|
local zombieInv = zombie:getInventory()
|
||||||
|
-- Check left or right
|
||||||
|
if not zombieInv:containsEval(PredicateAmputationItemLeft) then
|
||||||
|
SpawnAmputation(zombie, "L")
|
||||||
|
elseif not zombieInv:containsEval(PredicateAmputationItemRight) then
|
||||||
|
SpawnAmputation(zombie, "R")
|
||||||
|
end
|
||||||
|
|
||||||
|
|
||||||
-- ItemsController.Zombie.SpawnAmputationItem(zombie, amputationFullType)
|
-- add blood splat every couple of seconds for a while
|
||||||
|
addBloodSplat(getCell():getGridSquare(zombie:getX(), zombie:getY(), zombie:getZ()), bloodAmount)
|
||||||
|
local timerName = tostring(GetZombieID(zombie)) .. "_timer"
|
||||||
|
timer:Create(timerName, 1, 10, function()
|
||||||
|
addBloodSplat(getCell():getGridSquare(zombie:getX(), zombie:getY(), zombie:getZ()), bloodAmount)
|
||||||
|
end)
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Events.OnWeaponHitCharacter.Add(HandleZombiesAmputations)
|
||||||
|
|
||||||
|
-----------------------------
|
||||||
|
|
||||||
|
local localOnlyZombiesMD
|
||||||
|
|
||||||
|
local function SetupZombiesModData()
|
||||||
|
local zombieKey = CommandsData.GetZombieKey()
|
||||||
|
localOnlyZombiesMD = ModData.getOrCreate(zombieKey)
|
||||||
|
end
|
||||||
|
|
||||||
|
Events.OnInitGlobalModData.Add(SetupZombiesModData)
|
||||||
|
|
||||||
|
|
||||||
-- -- Add reference and transmit it to server
|
---@param zombie IsoZombie
|
||||||
-- local pID = GetZombieID(zombie)
|
local function ReapplyAmputation(zombie)
|
||||||
-- local zombieKey = CommandsData.GetZombieKey()
|
local pID = GetZombieID(zombie)
|
||||||
-- local zombiesMD = ModData.getOrCreate(zombieKey)
|
|
||||||
-- if zombiesMD[pID] == nil then zombiesMD[pID] = {} end
|
|
||||||
-- zombiesMD[pID][side] = amputationFullType
|
|
||||||
-- ModData.add(zombieKey, zombiesMD)
|
|
||||||
-- ModData.transmit(zombieKey)
|
|
||||||
-- end
|
|
||||||
|
|
||||||
-- -------------------------------
|
|
||||||
|
|
||||||
-- ---@param player IsoGameCharacter
|
|
||||||
-- ---@param zombie IsoZombie
|
|
||||||
-- ---@param handWeapon HandWeapon
|
|
||||||
-- function HandleZombiesAmputations(player, zombie, handWeapon, damage)
|
|
||||||
-- if not instanceof(zombie, "IsoZombie") or not instanceof(player, "IsoPlayer") then return end
|
|
||||||
-- if player ~= getPlayer() then return end
|
|
||||||
|
|
||||||
-- -- TODO Check type of weapon. No hands, only knifes or such
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- if damage < 3 or ZombRand(0,100) < 25 then return end
|
|
||||||
|
|
||||||
-- TOC_DEBUG.print(handWeapon:getName())
|
|
||||||
|
|
||||||
|
|
||||||
-- local zombieInv = zombie:getInventory()
|
|
||||||
|
|
||||||
|
|
||||||
-- -- Check left or right
|
|
||||||
-- local leftItem = zombieInv:containsEval(PredicateAmputationItemLeft)
|
|
||||||
|
|
||||||
-- if not leftItem then
|
|
||||||
-- SpawnAmputation(zombie, "L")
|
|
||||||
-- return
|
|
||||||
-- end
|
|
||||||
|
|
||||||
|
|
||||||
-- local rightItem = zombieInv:containsEval(PredicateAmputationItemRight)
|
|
||||||
-- if not rightItem then
|
|
||||||
-- SpawnAmputation(zombie, "R")
|
|
||||||
-- return
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
|
|
||||||
|
|
||||||
-- Events.OnWeaponHitCharacter.Add(HandleZombiesAmputations)
|
|
||||||
|
|
||||||
-- -----------------------------
|
|
||||||
|
|
||||||
-- local localOnlyZombiesMD
|
|
||||||
|
|
||||||
-- local function SetupZombiesModData()
|
|
||||||
-- local zombieKey = CommandsData.GetZombieKey()
|
|
||||||
-- localOnlyZombiesMD = ModData.getOrCreate(zombieKey)
|
|
||||||
|
|
||||||
-- end
|
|
||||||
|
|
||||||
-- Events.OnInitGlobalModData.Add(SetupZombiesModData)
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
-- ---@param zombie IsoZombie
|
|
||||||
-- local function ReapplyAmputation(zombie)
|
|
||||||
-- local pID = GetZombieID(zombie)
|
|
||||||
|
|
||||||
-- if localOnlyZombiesMD[pID] ~= nil then
|
|
||||||
-- -- check if zombie has amputation
|
|
||||||
-- local zombiesAmpData = localOnlyZombiesMD[pID]
|
|
||||||
-- local zombieInv = zombie:getInventory()
|
|
||||||
-- local foundItem = zombieInv:containsEvalRecurse(PredicateAmputationItems)
|
|
||||||
|
|
||||||
-- if foundItem then
|
|
||||||
-- return
|
|
||||||
-- else
|
|
||||||
-- local leftAmp = zombiesAmpData['L']
|
|
||||||
-- if leftAmp then
|
|
||||||
-- ItemsController.Zombie.SpawnAmputationItem(zombie, leftAmp)
|
|
||||||
-- end
|
|
||||||
|
|
||||||
-- local rightAmp = zombiesAmpData['R']
|
|
||||||
-- if rightAmp then
|
|
||||||
-- ItemsController.Zombie.SpawnAmputationItem(zombie, rightAmp)
|
|
||||||
-- end
|
|
||||||
|
|
||||||
-- -- Removes reference, local only
|
|
||||||
-- localOnlyZombiesMD[pID] = nil
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
-- end
|
|
||||||
|
|
||||||
-- Events.OnZombieUpdate.Add(ReapplyAmputation)
|
|
||||||
|
|
||||||
|
if localOnlyZombiesMD[pID] ~= nil then
|
||||||
|
-- check if zombie has amputation
|
||||||
|
local zombiesAmpData = localOnlyZombiesMD[pID]
|
||||||
|
local zombieInv = zombie:getInventory()
|
||||||
|
local foundItem = zombieInv:containsEvalRecurse(PredicateAmputationItems)
|
||||||
|
|
||||||
|
if foundItem then
|
||||||
|
return
|
||||||
|
else
|
||||||
|
local leftAmp = zombiesAmpData['L']
|
||||||
|
if leftAmp then
|
||||||
|
ItemsController.Zombie.SpawnAmputationItem(zombie, leftAmp)
|
||||||
|
end
|
||||||
|
|
||||||
|
local rightAmp = zombiesAmpData['R']
|
||||||
|
if rightAmp then
|
||||||
|
ItemsController.Zombie.SpawnAmputationItem(zombie, rightAmp)
|
||||||
|
end
|
||||||
|
|
||||||
|
-- Removes reference, local only
|
||||||
|
localOnlyZombiesMD[pID] = nil
|
||||||
|
end
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
Events.OnZombieUpdate.Add(ReapplyAmputation)
|
||||||
|
|||||||
216
media/lua/client/lua_timers.lua
Normal file
216
media/lua/client/lua_timers.lua
Normal file
@@ -0,0 +1,216 @@
|
|||||||
|
-- Made by Vyshnia
|
||||||
|
-- Workshop ID: 2875394066
|
||||||
|
-- Mod ID: LuaTimers
|
||||||
|
|
||||||
|
local os_time = os.time
|
||||||
|
local table_insert = table.insert
|
||||||
|
local table_remove = table.remove
|
||||||
|
local assert = assert
|
||||||
|
local type = type
|
||||||
|
local pairs = pairs
|
||||||
|
|
||||||
|
timer = {
|
||||||
|
Timers = {},
|
||||||
|
SimpleTimers = {}
|
||||||
|
}
|
||||||
|
|
||||||
|
function timer:Simple(delay, func)
|
||||||
|
|
||||||
|
assert(type(delay) == "number", "Delay of timer should be a number type")
|
||||||
|
assert(type(func) == "function", "Func of timer should be a function type (lol)")
|
||||||
|
|
||||||
|
table_insert(self.SimpleTimers, {
|
||||||
|
EndTime = os_time() + delay,
|
||||||
|
Func = func
|
||||||
|
})
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function timer:Create(name, delay, repetitions, func)
|
||||||
|
|
||||||
|
assert(type(name) == "string", "ID of timer should be a string type")
|
||||||
|
assert(type(delay) == "number", "Delay of timer should be a number type")
|
||||||
|
assert(type(repetitions) == "number", "Repetitions of timer should be a number type")
|
||||||
|
assert(type(func) == "function", "Func of timer should be a function type (lol)")
|
||||||
|
|
||||||
|
self.Timers[name] = {
|
||||||
|
Delay = delay,
|
||||||
|
StartRepetitions = repetitions,
|
||||||
|
Repetitions = repetitions,
|
||||||
|
Infinity = repetitions == 0,
|
||||||
|
LastFuncTime = os_time(),
|
||||||
|
Func = func,
|
||||||
|
Paused = false,
|
||||||
|
}
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local function timerUpdate()
|
||||||
|
|
||||||
|
local cur_time = os_time()
|
||||||
|
|
||||||
|
for k,v in pairs(timer.Timers) do
|
||||||
|
|
||||||
|
if not v.Paused then
|
||||||
|
|
||||||
|
if cur_time >= v.LastFuncTime + v.Delay then
|
||||||
|
|
||||||
|
v.Func()
|
||||||
|
|
||||||
|
v.LastFuncTime = cur_time
|
||||||
|
|
||||||
|
if not v.Infinity then
|
||||||
|
|
||||||
|
v.Repetitions = v.Repetitions - 1
|
||||||
|
|
||||||
|
if v.Repetitions <= 0 then
|
||||||
|
|
||||||
|
timer.Timers[k] = nil
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
local simple_timers = timer.SimpleTimers
|
||||||
|
|
||||||
|
for i = #simple_timers, 1, -1 do
|
||||||
|
|
||||||
|
local t = simple_timers[i]
|
||||||
|
|
||||||
|
if t.EndTime <= cur_time then
|
||||||
|
|
||||||
|
t.Func()
|
||||||
|
|
||||||
|
table_remove(simple_timers, i)
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
Events.OnTickEvenPaused.Add(timerUpdate)
|
||||||
|
|
||||||
|
function timer:Remove(name)
|
||||||
|
|
||||||
|
local t = self.Timers[name]
|
||||||
|
|
||||||
|
if not t then return false end
|
||||||
|
|
||||||
|
self.Timers[name] = nil
|
||||||
|
|
||||||
|
return true
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function timer:Exists(name)
|
||||||
|
|
||||||
|
return self.Timers[name] and true or false
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function timer:Start(name)
|
||||||
|
|
||||||
|
local t = self.Timers[name]
|
||||||
|
|
||||||
|
if not t then return false end
|
||||||
|
|
||||||
|
t.Repetitions = t.StartRepetitions
|
||||||
|
t.LastFuncTime = os_time()
|
||||||
|
t.Paused = false
|
||||||
|
t.PausedTime = nil
|
||||||
|
|
||||||
|
return true
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function timer:Pause(name)
|
||||||
|
|
||||||
|
local t = self.Timers[name]
|
||||||
|
|
||||||
|
if not t then return false end
|
||||||
|
|
||||||
|
if t.Paused then return false end
|
||||||
|
|
||||||
|
t.Paused = true
|
||||||
|
t.PausedTime = os_time()
|
||||||
|
|
||||||
|
return true
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function timer:UnPause(name)
|
||||||
|
|
||||||
|
local t = self.Timers[name]
|
||||||
|
|
||||||
|
if not t then return false end
|
||||||
|
|
||||||
|
if not t.Paused then return false end
|
||||||
|
|
||||||
|
t.Paused = false
|
||||||
|
|
||||||
|
return true
|
||||||
|
|
||||||
|
end
|
||||||
|
timer.Resume = timer.UnPause
|
||||||
|
|
||||||
|
function timer:Toggle(name)
|
||||||
|
|
||||||
|
local t = self.Timers[name]
|
||||||
|
|
||||||
|
if not t then return false end
|
||||||
|
|
||||||
|
t.Paused = not t.Paused
|
||||||
|
|
||||||
|
return true
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function timer:TimeLeft(name)
|
||||||
|
|
||||||
|
local t = self.Timers[name]
|
||||||
|
|
||||||
|
if not t then return end
|
||||||
|
|
||||||
|
if t.Paused then
|
||||||
|
|
||||||
|
return (t.Repetitions - 1) * t.Delay + (t.LastFuncTime + t.Delay - t.PausedTime)
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
return (t.Repetitions - 1) * t.Delay + (t.LastFuncTime + t.Delay - os_time())
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function timer:NextTimeLeft(name)
|
||||||
|
|
||||||
|
local t = self.Timers[name]
|
||||||
|
|
||||||
|
if not t then return end
|
||||||
|
|
||||||
|
if t.Paused then
|
||||||
|
|
||||||
|
return t.LastFuncTime + t.Delay - t.PausedTime
|
||||||
|
|
||||||
|
else
|
||||||
|
|
||||||
|
return t.LastFuncTime + t.Delay - os_time()
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
end
|
||||||
|
|
||||||
|
function timer:RepsLeft(name)
|
||||||
|
|
||||||
|
local t = self.Timers[name]
|
||||||
|
|
||||||
|
return t and t.Repetitions
|
||||||
|
|
||||||
|
end
|
||||||
@@ -3,14 +3,9 @@ local StaticData = require("TOC/StaticData")
|
|||||||
local CommandsData = require("TOC/CommandsData")
|
local CommandsData = require("TOC/CommandsData")
|
||||||
------------------------
|
------------------------
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
local ServerDataHandler = {}
|
local ServerDataHandler = {}
|
||||||
ServerDataHandler.modData = {}
|
ServerDataHandler.modData = {}
|
||||||
|
|
||||||
|
|
||||||
---Get the server mod data table containing that player TOC data
|
---Get the server mod data table containing that player TOC data
|
||||||
---@param key string
|
---@param key string
|
||||||
---@return tocModDataType
|
---@return tocModDataType
|
||||||
|
|||||||
@@ -3,5 +3,8 @@ Sandbox_EN = {
|
|||||||
Sandbox_TOC_CicatrizationSpeed = "Cicatrization Speed",
|
Sandbox_TOC_CicatrizationSpeed = "Cicatrization Speed",
|
||||||
Sandbox_TOC_WoundDirtynessMultiplier = "Wound Dirtyness Multiplier",
|
Sandbox_TOC_WoundDirtynessMultiplier = "Wound Dirtyness Multiplier",
|
||||||
Sandbox_TOC_SurgeonAbilityImportance = "Relevance of surgeon doctor ability",
|
Sandbox_TOC_SurgeonAbilityImportance = "Relevance of surgeon doctor ability",
|
||||||
|
Sandbox_TOC_EnableZombieAmputations = "Enable Zombie amputations",
|
||||||
|
Sandbox_TOC_ZombieAmputationDamageThreshold = "Zombie amputations damage treshold",
|
||||||
|
Sandbox_TOC_ZombieAmputationDamageChance = "Zombie amputations damage chance",
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -28,3 +28,31 @@ option TOC.SurgeonAbilityImportance
|
|||||||
translation = TOC_SurgeonAbilityImportance,
|
translation = TOC_SurgeonAbilityImportance,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
option TOC.EnableZombieAmputations
|
||||||
|
{
|
||||||
|
type = boolean,
|
||||||
|
default = false,
|
||||||
|
page = TOC,
|
||||||
|
translation= TOC_EnableZombieAmputations,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
option TOC.ZombieAmputationDamageThreshold
|
||||||
|
{
|
||||||
|
type = integer,
|
||||||
|
min = 0,
|
||||||
|
max = 10,
|
||||||
|
default = 4,
|
||||||
|
page = TOC,
|
||||||
|
translation = TOC_ZombieAmputationDamageThreshold,
|
||||||
|
}
|
||||||
|
|
||||||
|
option TOC.ZombieAmputationDamageChance
|
||||||
|
{
|
||||||
|
type = integer,
|
||||||
|
min = 0,
|
||||||
|
max = 100,
|
||||||
|
default = 25,
|
||||||
|
page = TOC,
|
||||||
|
translation = TOC_ZombieAmputationDamageChance,
|
||||||
|
}
|
||||||
2
mod.info
2
mod.info
@@ -4,5 +4,5 @@ description=You've been bitten. You have only two choices.
|
|||||||
id=TheOnlyCure
|
id=TheOnlyCure
|
||||||
icon=icon.png
|
icon=icon.png
|
||||||
url=https://github.com/ZioPao/The-Only-Cure
|
url=https://github.com/ZioPao/The-Only-Cure
|
||||||
modversion=2.0.15
|
modversion=2.1
|
||||||
pzversion=41.65
|
pzversion=41.65
|
||||||
|
|||||||
147
workshop.txt
147
workshop.txt
@@ -1,147 +0,0 @@
|
|||||||
version=1
|
|
||||||
id=3236152598
|
|
||||||
title=The Only Cure - Rebuilt
|
|
||||||
description=[img]https://raw.githubusercontent.com/ZioPao/The-Only-Cure/551125bb50cb65608ad89ca81ef0daccb3b02c4c/dev_stuff/logos/title.png[/img]
|
|
||||||
|
|
||||||
description=
|
|
||||||
|
|
||||||
description=[h1]You're bitten. You have two choices.[/h1]
|
|
||||||
|
|
||||||
description=Wait until you succumb to the virus or take matters into your hands.
|
|
||||||
|
|
||||||
description=
|
|
||||||
|
|
||||||
description=This version of [b]The Only Cure[/b] has been rebuilt from scratch to support future additions.
|
|
||||||
|
|
||||||
description=
|
|
||||||
|
|
||||||
description=Supports [b]Single Player[/b] and [b]Multiplayer[/b]!
|
|
||||||
|
|
||||||
description=
|
|
||||||
|
|
||||||
description=[h1]Setup[/h1]
|
|
||||||
|
|
||||||
description=Use it with the following mods for the intended experience:
|
|
||||||
|
|
||||||
description=[list]
|
|
||||||
|
|
||||||
description=[*] [url=https://steamcommunity.com/sharedfiles/filedetails/?id=2904920097]Fancy Handwork[/url]
|
|
||||||
|
|
||||||
description=[*] [url=https://steamcommunity.com/sharedfiles/filedetails/?id=2934621024]Brutal Handwork[/url]
|
|
||||||
|
|
||||||
description=[/list]
|
|
||||||
|
|
||||||
description=
|
|
||||||
|
|
||||||
description=[h1]Quick guide[/h1]
|
|
||||||
|
|
||||||
description=[h2]Amputation[/h2]
|
|
||||||
|
|
||||||
description=Get a [i]Saw[/i] or a [i]Garden Saw[/i], right click on it, and choose which limb to amputate. You can also drag n' drop your Saw item directly into the afflicted area to start cutting it off.
|
|
||||||
|
|
||||||
description=
|
|
||||||
|
|
||||||
description=If you have a tourniquet, place it on the correct side to dampen the amount of damage you will take after you're done amputating the limb.
|
|
||||||
|
|
||||||
description=
|
|
||||||
|
|
||||||
description=Keep in mind that if you amputate your upper arm, you won't be able to equip any prosthesis.
|
|
||||||
|
|
||||||
description=
|
|
||||||
|
|
||||||
description=[h2]Cicatrization[/h2]
|
|
||||||
|
|
||||||
description=You can check the cicatrization status of an amputated limb from your [b]Health Panel[/b]
|
|
||||||
|
|
||||||
description=From time to time, you should clean your wounds with a bandage to help the cicatrization process.
|
|
||||||
|
|
||||||
description=If your limb isn't completely cicatrized, you can still equip prosthetic limbs, but that can trigger random bleedings from that area.
|
|
||||||
|
|
||||||
description=
|
|
||||||
|
|
||||||
description=[h2]Prosthesis[/h2]
|
|
||||||
|
|
||||||
description=If you're missing a hand, you won't be able to do a lot of things, such as equipping two-handed weapons. With prosthetics limbs, you can fix that.
|
|
||||||
|
|
||||||
description=There are two prosthesis type that can be crafted\found in medical areas:
|
|
||||||
|
|
||||||
description=[list]
|
|
||||||
|
|
||||||
description=[*] Hook Prosthesis
|
|
||||||
|
|
||||||
description=[*] Arm Prosthesis
|
|
||||||
|
|
||||||
description=[/list]
|
|
||||||
|
|
||||||
description=
|
|
||||||
|
|
||||||
description=The main difference between the twos is that your actions will take longer with the Hook Prosthesis.
|
|
||||||
|
|
||||||
description=
|
|
||||||
|
|
||||||
description=[h1]Issues[/h1]
|
|
||||||
|
|
||||||
description=Got any issues? Report them on GitHub!
|
|
||||||
|
|
||||||
description=[url=https://github.com/ZioPao/The-Only-Cure][img]https://img.shields.io/badge/GitHub-100000?style=for-the-badge&logo=github&logoColor=white[/img][/url]
|
|
||||||
|
|
||||||
description=
|
|
||||||
|
|
||||||
description=
|
|
||||||
|
|
||||||
description=[h1]Credits[/h1]
|
|
||||||
|
|
||||||
description=
|
|
||||||
|
|
||||||
description=[table]
|
|
||||||
|
|
||||||
description= [tr]
|
|
||||||
|
|
||||||
description= [th]Pao[/th]
|
|
||||||
|
|
||||||
description= [th]Developer[/th]
|
|
||||||
|
|
||||||
description= [/tr]
|
|
||||||
|
|
||||||
description= [tr]
|
|
||||||
|
|
||||||
description= [th]Mr. Bounty[/th]
|
|
||||||
|
|
||||||
description= [th]Original Developer[/th]
|
|
||||||
|
|
||||||
description= [/tr]
|
|
||||||
|
|
||||||
description= [tr]
|
|
||||||
|
|
||||||
description= [th]Chuckleberry Finn[/th]
|
|
||||||
|
|
||||||
description= [th]Logo and Icon[/th]
|
|
||||||
|
|
||||||
description= [/tr]
|
|
||||||
|
|
||||||
description= [tr]
|
|
||||||
|
|
||||||
description= [th]dhert[/th]
|
|
||||||
|
|
||||||
description= [th]Compatibility API[/th]
|
|
||||||
|
|
||||||
description= [/tr]
|
|
||||||
|
|
||||||
description=[/table]
|
|
||||||
|
|
||||||
description=
|
|
||||||
|
|
||||||
description=[hr]
|
|
||||||
|
|
||||||
description=
|
|
||||||
|
|
||||||
description=[h1]Want to support me?[/h1]
|
|
||||||
|
|
||||||
description=[url=https://ko-fi.com/M4M7IERNW][img]https://storage.ko-fi.com/cdn/kofi3.png[/img][/url]
|
|
||||||
|
|
||||||
description=
|
|
||||||
|
|
||||||
description=[hr]
|
|
||||||
|
|
||||||
tags=Build 41;Balance;Interface;Items;Misc;Multiplayer;Realistic;Textures
|
|
||||||
visibility=private
|
|
||||||
@@ -159,7 +159,7 @@ description= [/tr]
|
|||||||
|
|
||||||
description= [tr]
|
description= [tr]
|
||||||
|
|
||||||
description= [th]JCloudJalix, Rinary1[/th]
|
description= [th]JCloudJalix, Rinary1, pllq, ttaeo[/th]
|
||||||
|
|
||||||
description= [th]Translations[/th]
|
description= [th]Translations[/th]
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user