1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
|
local debug = false
--- Appends an integer to a separated string
---@param str string current string
---@param separator string separator
---@param value integer integer to append
---@return string new string
local function appendIntToSeparatedString(str, separator, value)
if str == "" then
return tostring(value)
end
return str .. separator .. tostring(value)
end
---@diagnostic disable-next-line
local zombificationChance = SandboxVars.ZombificationChance.chance
local zombificationBodyPartsKey = "zombificationChance-infected"
--- Splits a string at a given separator
---@param inputstr string
---@param separator string
---@return table<integer, string>
local function splitString(inputstr, separator)
assert(separator ~= "", "Separator must be provided")
local result = {}
for element in string.gmatch(inputstr, "([^" .. separator .. "]+)") do
table.insert(result, element)
end
return result
end
--- Returns true if zombification should occur based on chance
---@return boolean
local function rollZombification()
return ZombRand(100) <= zombificationChance
end
--- Event handler: called when player receives damage
---@param character IsoGameCharacter
---@param damage number
local function onPlayerReceiveDamage(character, damageType, damage)
local bodyDamage = character:getBodyDamage()
local usedBodyPartIndexes = splitString(character:GetVariable(zombificationBodyPartsKey), " ")
for i = 0, bodyDamage:getBodyParts():size() - 1 do
local bodyPart = bodyDamage:getBodyParts():get(i)
if bodyPart:IsFakeInfected() then
local alreadyProcessed = false
for _, usedIndex in ipairs(usedBodyPartIndexes) do
if tonumber(usedIndex) == i then
alreadyProcessed = true
break
end
end
if not alreadyProcessed then
-- Mark this body part as processed
character:SetVariable(
zombificationBodyPartsKey,
appendIntToSeparatedString(character:GetVariable(zombificationBodyPartsKey), " ", i)
)
if rollZombification() then
if debug then character:Say("[PZC] Index: " ..
local i = 0
return function()
i = i + 1
if i <= #bodyPartIndexes then
return (bodyPartIndexes[i])
end
end
end
--- Removes an element from a separated string by value
---@param str string original string
---@param value string|number element to remove
---@param separator string separator (must be provided)
---@return string
function removeElementFromSeparatedString(str, value, separator)
assert(separator ~= "", "Separator must be provided")
value = tostring(value)
local result = {}
for element in string.gmatch(str, "([^" .. separator .. "]+)") do
if element ~= value then
table.insert(result, element)
end
end
return table.concat(result, separator)
end
--- Event handler: called every update for a player
---@param player IsoPlayer
local function forgetOldFakeInfections(player)
local bodyDamage = player:getBodyDamage()
for bodyPartIndex in ProcessedBodyPartIndeciesIterator(player) do
local bodyPart = bodyDamage:getBodyParts():get(bodyPartIndex)
if not bodyPart:IsFakeInfected() then
if debug then player:Say("[PZC] Index: " .. bodyPart:getIndex() .. ", isNotFakeInfected, now forgotton") end
player:SetVariable(
zombificationBodyPartsKey,
removeElementFromSeparatedString(
player:GetVariable(zombificationBodyPartsKey),
bodyPartIndex,
" "
)
)
end
end
end
-- Register events
Events.OnPlayerUpdate.Add(forgetOldFakeInfections)
Events.OnPlayerGetDamage.Add(onPlayerReceiveDamage)
|