diff --git a/.vscode/settings.json b/.vscode/settings.json new file mode 100644 index 0000000..2331d4d --- /dev/null +++ b/.vscode/settings.json @@ -0,0 +1,6 @@ +{ + "todo-tree.tree.scanMode": "workspace", + "Lua.diagnostics.globals": [ + "ZombRand" + ] +} \ No newline at end of file diff --git a/media/lua/client/MP_commands/TOC_MP_client.lua b/media/lua/client/MP_commands/TOC_MP_client.lua index 13c0faa..16ac6b1 100644 --- a/media/lua/client/MP_commands/TOC_MP_client.lua +++ b/media/lua/client/MP_commands/TOC_MP_client.lua @@ -88,43 +88,10 @@ end -------------------------------------------------------------------- -function AskGetOtherPlayerData(player) - local arg = {} - - arg["From"] = getPlayer():getOnlineID() --surgoen - arg["To"] = player:getOnlineID() --patient - - - arg["command"] = "SendOtherPlayerData"; - arg["toSend"] = {player:getModData().TOC} -- will it work? - sendClientCommand("TOC", "SendServer", arg); - -end - - - - - -function SendGetOtherPlayerData(player) - local arg = {} - - arg["From"] = getPlayer():getOnlineID() --surgoen - arg["To"] = player:getOnlineID() --patient - - - arg["command"] = "GetOtherPlayerData"; - arg["toSend"] = {player:getModData().TOC} -- will it work? - sendClientCommand("TOC", "SendServer", arg); -end - - - -- todo why is this here? this doesnt make any sense - - -- Event local onServerCommand = function(module, command, args) - -- TODO change this name + -- TODO this doesn't belong here. if module == "TOC" and Commands[command] then args = args or {} Commands[command](args) diff --git a/media/lua/client/TOC_UI.lua b/media/lua/client/TOC_UI.lua index 743dd21..3f7ef6b 100644 --- a/media/lua/client/TOC_UI.lua +++ b/media/lua/client/TOC_UI.lua @@ -43,13 +43,13 @@ end local function getImageName(partName, modData) local partData = modData[partName]; local name = ""; - if partData.is_cut and partData.is_cicatrized and partData.has_prothesis_equipped then -- Cut and equip + if partData.is_cut and partData.is_cicatrized and partData.has_prosthesis_equipped then -- Cut and equip if partName == "RightHand" or partName == "LeftHand" then name = "media/ui/TOC/" .. partName .. "/Hook.png"; else name = "media/ui/TOC/" .. partName .. "/Prothesis.png"; end - elseif partData.is_cut and partData.is_cicatrized and not partData.has_prothesis_equipped and partData.is_amputation_shown then -- Cut and heal + elseif partData.is_cut and partData.is_cicatrized and not partData.has_prosthesis_equipped and partData.is_amputation_shown then -- Cut and heal name = "media/ui/TOC/" .. partName .. "/Cut.png"; elseif partData.is_cut and not partData.is_cicatrized and partData.is_amputation_shown and not partData.is_operated then -- Cut not heal name = "media/ui/TOC/" .. partName .. "/Bleed.png"; @@ -64,9 +64,9 @@ end end -- If foreaerm equip, change hand - if partName == "RightHand" and modData["RightForearm"].has_prothesis_equipped then + if partName == "RightHand" and modData["RightForearm"].has_prosthesis_equipped then name = "media/ui/TOC/" .. partName .. "/Hook.png"; - elseif partName == "LeftHand" and modData["LeftForearm"].has_prothesis_equipped then + elseif partName == "LeftHand" and modData["LeftForearm"].has_prosthesis_equipped then name = "media/ui/TOC/" .. partName .. "/Hook.png"; end return name; @@ -146,7 +146,7 @@ local function setDescUI(toc_data, partName) descUI.partNameAct = partName -- Cut and equip - if partData.is_cut and partData.is_cicatrized and partData.has_prothesis_equipped then + if partData.is_cut and partData.is_cicatrized and partData.has_prosthesis_equipped then descUI["textEtat"]:setText("Cut and healed") descUI["textEtat"]:setColor(1, 0, 1, 0) descUI["b1"]:setText("Unequip") @@ -154,7 +154,7 @@ local function setDescUI(toc_data, partName) descUI["b1"]:setVisible(true) -- Cut and healed - elseif partData.is_cut and partData.is_cicatrized and not partData.has_prothesis_equipped and partData.is_amputation_shown then + elseif partData.is_cut and partData.is_cicatrized and not partData.has_prosthesis_equipped and partData.is_amputation_shown then descUI["textEtat"]:setText("Cut and healed"); descUI["textEtat"]:setColor(1, 0, 1, 0); if partName == "RightArm" or partName == "LeftArm" then @@ -404,8 +404,8 @@ local function descPress(button, args) -- TODO Change to correct player local modData = player:getModData().TOC; -- Do not cut if prothesis equip - if (string.find(descUI.partNameAct, "Right") and (modData["RightHand"].has_prothesis_equipped or modData["RightForearm"].has_prothesis_equipped)) - or (string.find(descUI.partNameAct, "Left") and (modData["LeftHand"].has_prothesis_equipped or modData["LeftForearm"].has_prothesis_equipped)) then + if (string.find(descUI.partNameAct, "Right") and (modData["RightHand"].has_prosthesis_equipped or modData["RightForearm"].has_prosthesis_equipped)) + or (string.find(descUI.partNameAct, "Left") and (modData["LeftHand"].has_prosthesis_equipped or modData["LeftForearm"].has_prosthesis_equipped)) then player:Say("I need to remove my prothesis first"); mainUI:close(); return false; diff --git a/media/lua/client/TOC_Update.lua b/media/lua/client/TOC_Update.lua new file mode 100644 index 0000000..4614fca --- /dev/null +++ b/media/lua/client/TOC_Update.lua @@ -0,0 +1,189 @@ +function TheOnlyCure.CheckIfPlayerIsInfected(player, toc_data) + + local body_damage = player:getBodyDamage() + + for _, v in GetLimbsBodyPartTypes() do + + local toc_bodypart = TheOnlyCure.FindBodyPartFromBodyPartType(toc_data, v) + if body_damage:getBodyPart(v):bitten() and not toc_data[toc_bodypart].is_cut then + toc_data[toc_bodypart].is_infected = true + player:transmitModData() + end + end + + for _, v in GetOtherBodyPartTypes() do + if body_damage:getBodyPart(v):bitten() then + toc_data.is_other_bodypart_infected = true -- Even one is enough, stop cycling if we find it + player:transmitModData() + break + end + end +end + +function TheOnlyCure.UpdatePlayerHealth(player, toc_data) + local body_damage = player:getBodyDamage() + + + + if player:HasTrait("Insensitive") then body_damage:setPainReduction(49) end + + for i, part_name in pairs(GetBodyParts()) do + if toc_data[part_name].is_cut then + TheOnlyCure.HealSpecificPart(toc_data, part_name, player) + + end + end + + player:transmitModData() + + +end + +--Helper function for UpdatePlayerHealth +function TheOnlyCure.HealSpecificPart(toc_data, part_name, player) + + + local body_damage = player:getBodyDamage() + local body_part_type = body_damage:getBodyPart(TOC_getBodyPart(part_name)) + if not body_part_type then + print("TOC ERROR : Can't update health of " .. part_name); + return false + end + + -- Check bandages + local is_bandaged = false + local bandage_life = 0 + local bandage_type = "" + + if body_part_type:bandaged() then + is_bandaged = true -- this is useless + bandage_life = body_part_type:getBandageLife() + bandage_type = body_part_type:getBandageType() + + end + + + + -- Set max health + if toc_data[part_name].is_cicatrized and body_part_type:getHealth() > 80 then + body_part_type:SetHealth(80) + elseif body_part_type:getHealth() > 40 then + body_part_type:SetHealth(40) + end + + -- This is useless here. We don't need to do this every single time, only after operation +-- if modData_part.is_cicatrized then +-- if bodyPart:deepWounded() then bodyPart:setDeepWounded(false) end +-- if bodyPart:bleeding() then bodyPart:setBleeding(false) end +-- end + + + -- Check if we can heal the infection + if body_part_type:bitten() then + body_part_type:SetBitten(false) + if not toc_data[part_name].is_other_bodypart_infected and not TheOnlyCure.CheckIfOtherLimbsAreInfected(toc_data, part_name) then + body_part_type:setInfected(false) + body_part_type:setInfectionMortalityDuration(-1) + body_part_type:setInfectionTime(-1) + body_part_type:setInfectionLevel(0) + local body_part_types = body_damage:getBodyParts() + + -- TODO I think this is enough... we should just cycle if with everything instead of that crap up there + for i=body_part_types:size()-1, 0, -1 do + local bodyPart = body_part_types:get(i); + bodyPart:SetInfected(false); + end + end + end + + if body_part_type:scratched() then body_part_type:setScratched(false, false) end + if body_part_type:haveGlass() then body_part_type:setHaveGlass(false) end + if body_part_type:haveBullet() then body_part_type:setHaveBullet(false, 0) end + if body_part_type:isInfectedWound() then body_part_type:setInfectedWound(false) end + if body_part_type:isBurnt() then body_part_type:setBurnTime(0) end + if body_part_type:isCut() then body_part_type:setCut(false, false) end --Lacerations + if body_part_type:getFractureTime()>0 then body_part_type:setFractureTime(0) end + + -- Cicatrization check + if toc_data[part_name].is_cut and not toc_data[part_name].is_cicatrized then + if toc_data[part_name].cicatrization_time < 0 then + toc_data[part_name].is_cicatrized = true + + -- TODO make this random if the player gets it or not + player:getTraits():add("Brave") + player:getTraits():add("Insensitive") + body_part_type:setBleeding(false); + body_part_type:setDeepWounded(false) + body_part_type:setBleedingTime(0) + body_part_type:setDeepWoundTime(0) + end + end + + -- Phantom Pain + if toc_data[part_name].is_amputation_shown and ZombRand(1, 100) < 10 then + local added_pain + if toc_data[part_name].is_cauterized then added_pain = 60 else added_pain = 30 end + body_part_type:setAdditionalPain(ZombRand(1, added_pain)) + end + + -- Reapplies bandages after the whole ordeal + -- TODO not sure if this still works + body_part_type:setBandaged(true, bandage_life, false, bandage_type) +end + +--Helper function for UpdatePlayerHealth +function TheOnlyCure.CheckIfOtherLimbsAreInfected(toc_data, part_name) + + + local body_parts = GetBodyParts() + body_parts[part_name] = nil + + for _,v in pairs(body_parts) do + if toc_data[v].is_infected then + return true + end + end + return false +end + + +-- MAIN UPDATE FUNCTIONS + +function TheOnlyCure.UpdateEveryOneMinute() + + local player = getPlayer() + local toc_data = player:getModData().TOC + + if toc_data ~= nil then + TheOnlyCure.TryDropItem(player, toc_data) + TheOnlyCure.CheckIfPlayerIsInfected(player, toc_data) + TheOnlyCure.UpdatePlayerHealth(player, toc_data) + end + +end + +function TheOnlyCure.UpdateEveryTenMinutes() + + local player = getPlayer() + local toc_data = player:getModData().TOC + + + --Experience for prosthesis + if toc_data.RightHand.has_prosthesis_equipped or toc_data.RightForearm.has_prosthesis_equipped then player:getXp():AddXP(Perks.RightHand, 4) end + if toc_data.LeftHand.has_prosthesis_equipped or toc_data.LeftForearm.has_prosthesis_equipped then player:getXp():AddXP(Perks.LeftHand, 4) end + + -- Updates the cicatrization time + for _, part_name in pairs(GetBodyParts()) do + if toc_data[part_name].is_cut and toc_data[part_naem].is_cicatrized then + toc_data[part_name].cicatrization_time = toc_data[part_name].cicatrization_time - 1 -- TODO Make it more "dynamic" + + + end + end + + player:transmitModData() -- TODO if we do this every minutes, do we need to re do it here? +end + + +Events.EveryTenMinutes(TheOnlyCure.UpdateEveryTenMinutes) +Events.EveryOneMinute.Add(TheOnlyCure.UpdateEveryOneMinute) \ No newline at end of file diff --git a/media/lua/client/TOC_main.lua b/media/lua/client/TOC_main.lua index 887adf7..df20b03 100644 --- a/media/lua/client/TOC_main.lua +++ b/media/lua/client/TOC_main.lua @@ -4,19 +4,72 @@ end -local function dropItem(player, modData) - if (modData.TOC.RightHand.is_cut and not (modData.TOC.RightHand.has_prothesis_equipped or modData.TOC.RightForearm.has_prothesis_equipped)) or (modData.TOC.RightForearm.is_cut and not modData.TOC.RightForearm.has_prothesis_equipped) then - if player:getPrimaryHandItem() ~= nil then - if player:getPrimaryHandItem():getName() ~= "Bare Hands" then player:dropHandItems() end +-- GLOBAL STRINGS +Left = "Left" +Right = "Right" + +Hand = "Hand" +Forearm = "Forearm" +Arm = "Arm" + + + + +-- Makes the player drop an item if they don't have a limb or haven't equipped a prosthesis +function TheOnlyCure.TryDropItem(player, toc_data) + if TheOnlyCure.CheckIfCanPickUpItem(toc_data, Right, Hand, Forearm) and player:getPrimaryHandItem() ~= nil then + if player:getPrimaryHandItem():getName() ~= "Bare Hands" then + player:dropHandItems() end end - if (modData.TOC.LeftHand.is_cut and not (modData.TOC.LeftHand.has_prothesis_equipped or modData.TOC.LeftForearm.has_prothesis_equipped)) or (modData.TOC.LeftForearm.is_cut and not modData.TOC.LeftForearm.has_prothesis_equipped) then - if player:getSecondaryHandItem() ~= nil then - if player:getSecondaryHandItem():getName() ~= "Bare Hands" then player:dropHandItems() end + + if TheOnlyCure.CheckIfCanPickUpItem(toc_data, Left, Hand, Forearm) and player:getSecondaryHandItem() ~= nil then + if player:getSecondaryHandItem():getName() ~= "Bare Hands" then + player:dropHandItems() end end + + end +-- Helper for DropItem +function TheOnlyCure.CheckIfCanPickUpItem(toc_data, side, limb, secondary_limb) + + local full_primary_limb = side .. limb + local full_secondary_limb = side .. secondary_limb + + + return toc_data[full_primary_limb].is_cut and not (toc_data[full_primary_limb].has_prosthesis_equipped or toc_data[full_secondary_limb]) or + (toc_data[full_secondary_limb].is_cut and not toc_data[full_secondary_limb].has_prosthesis_equipped) + + +end + + + + + + + + + + + + + + +---------- +-- Updates + + + + + + + + + + local function everyOneMinute() local player = getPlayer() local modData = player:getModData() @@ -37,8 +90,8 @@ local function everyTenMinutes() local names = {"RightHand", "RightForearm", "RightArm", "LeftHand", "LeftForearm", "LeftArm"} --Augmente l'xp si equip - if modData.TOC.RightHand.has_prothesis_equipped or modData.TOC.RightForearm.has_prothesis_equipped then player:getXp():AddXP(Perks.RightHand, 4) end - if modData.TOC.LeftHand.has_prothesis_equipped or modData.TOC.LeftForearm.has_prothesis_equipped then player:getXp():AddXP(Perks.LeftHand, 4) end + if modData.TOC.RightHand.has_prosthesis_equipped or modData.TOC.RightForearm.has_prosthesis_equipped then player:getXp():AddXP(Perks.RightHand, 4) end + if modData.TOC.LeftHand.has_prosthesis_equipped or modData.TOC.LeftForearm.has_prosthesis_equipped then player:getXp():AddXP(Perks.LeftHand, 4) end --Reduit le temps de cicatri restant for i,name in pairs(names) do @@ -89,7 +142,7 @@ local function initVariable(_, player) modData.TOC[v].cicatrization_time = 0 - modData.TOC[v].has_prothesis_equipped = false + modData.TOC[v].has_prosthesis_equipped = false modData.TOC[v].prothesis_factor = 1.0 -- Every prothesis has the same... does this even make sense here? modData.TOC[v].prothesis_material_id = nil end @@ -116,6 +169,11 @@ local function initVariable(_, player) + modData.TOC.is_other_bodypart_infected = false + + + + if player:HasTrait("amputee1") then local cloth = player:getInventory():AddItem("TOC.ArmLeft_noHand"); player:setWornItem(cloth:getBodyLocation(), cloth); @@ -155,8 +213,5 @@ local function initTOCTraits() TraitFactory.setMutualExclusive("amputee2", "amputee3"); end -Events.EveryHours.Add(everyHours); -Events.EveryTenMinutes.Add(everyTenMinutes); -Events.EveryOneMinute.Add(everyOneMinute); Events.OnCreatePlayer.Add(initVariable); Events.OnGameBoot.Add(initTOCTraits); \ No newline at end of file diff --git a/media/lua/client/TimedActions/AddedToOther.lua b/media/lua/client/TimedActions/AddedToOther.lua index c499c03..53391bd 100644 --- a/media/lua/client/TimedActions/AddedToOther.lua +++ b/media/lua/client/TimedActions/AddedToOther.lua @@ -27,7 +27,7 @@ function ISBaseTimedAction:adjustMaxTime(maxTime) for i,name in ipairs(protPartNames) do if modData.TOC[name].is_cut then - if modData.TOC[name].has_prothesis_equipped then + if modData.TOC[name].has_prosthesis_equipped then maxTime = maxTime * modData.TOC[name].EquipFact --todo this is dumb else maxTime = maxTime * 2; @@ -119,12 +119,12 @@ function ISEquipWeaponAction:perform() if not self.item:isRequiresEquippedBothHands() then if modData.TOC.RightHand.is_cut then if modData.TOC.RightForearm.is_cut then - if not modData.TOC.RightForearm.has_prothesis_equipped then + if not modData.TOC.RightForearm.has_prosthesis_equipped then self.character:setPrimaryHandItem(nil); self.character:setSecondaryHandItem(self.item); end else - if not modData.TOC.RightHand.has_prothesis_equipped then + if not modData.TOC.RightHand.has_prosthesis_equipped then self.character:setPrimaryHandItem(nil); self.character:setSecondaryHandItem(self.item); end @@ -132,23 +132,23 @@ function ISEquipWeaponAction:perform() end if modData.TOC.LeftHand.is_cut then if modData.TOC.LeftForearm.is_cut then - if not modData.TOC.LeftForearm.has_prothesis_equipped then + if not modData.TOC.LeftForearm.has_prosthesis_equipped then self.character:setPrimaryHandItem(self.item); self.character:setSecondaryHandItem(nil); end else - if not modData.TOC.LeftHand.has_prothesis_equipped then + if not modData.TOC.LeftHand.has_prosthesis_equipped then self.character:setPrimaryHandItem(self.item); self.character:setSecondaryHandItem(nil); end end end - if (modData.TOC.RightHand.is_cut and not (modData.TOC.RightHand.has_prothesis_equipped or modData.TOC.RightForearm.has_prothesis_equipped)) and (modData.TOC.LeftHand.is_cut and not (modData.TOC.LeftHand.has_prothesis_equipped or modData.TOC.LeftForearm.has_prothesis_equipped)) then + if (modData.TOC.RightHand.is_cut and not (modData.TOC.RightHand.has_prosthesis_equipped or modData.TOC.RightForearm.has_prosthesis_equipped)) and (modData.TOC.LeftHand.is_cut and not (modData.TOC.LeftHand.has_prosthesis_equipped or modData.TOC.LeftForearm.has_prosthesis_equipped)) then self.character:dropHandItems(); end end - if self.item:isRequiresEquippedBothHands() and ((modData.TOC.RightHand.is_cut and not modData.TOC.RightHand.has_prothesis_equipped) or (modData.TOC.RightForearm.is_cut and not modData.TOC.RightForearm.has_prothesis_equipped) or (modData.TOC.LeftHand.is_cut and not modData.TOC.LeftHand.has_prothesis_equipped) or (modData.TOC.LeftForearm.is_cut and not modData.TOC.LeftForearm.has_prothesis_equipped)) then + if self.item:isRequiresEquippedBothHands() and ((modData.TOC.RightHand.is_cut and not modData.TOC.RightHand.has_prosthesis_equipped) or (modData.TOC.RightForearm.is_cut and not modData.TOC.RightForearm.has_prosthesis_equipped) or (modData.TOC.LeftHand.is_cut and not modData.TOC.LeftHand.has_prosthesis_equipped) or (modData.TOC.LeftForearm.is_cut and not modData.TOC.LeftForearm.has_prosthesis_equipped)) then self.character:dropHandItems(); end diff --git a/media/lua/client/TimedActions/NewOnOperate.lua b/media/lua/client/TimedActions/NewOnOperate.lua index 86a458b..91ed148 100644 --- a/media/lua/client/TimedActions/NewOnOperate.lua +++ b/media/lua/client/TimedActions/NewOnOperate.lua @@ -62,6 +62,8 @@ function ISOperateArm:perform() OperateArm(self.partName, surgeonFact, useOven) end self.surgeon:getXp():AddXP(Perks.Doctor, 400) + + -- FIXME Add a check for kit to prevent errors if self.kit then self.surgeon:getInventory():Remove(self.kit) end diff --git a/media/lua/client/Utils/UsefulFunctions.lua b/media/lua/client/Utils/UsefulFunctions.lua index e3f5c67..38ea2a1 100644 --- a/media/lua/client/Utils/UsefulFunctions.lua +++ b/media/lua/client/Utils/UsefulFunctions.lua @@ -3,6 +3,21 @@ function GetBodyParts() return bodyparts end +function GetLimbsBodyPartTypes() + + return {BodyPartType.Hand_R, BodyPartType.ForeArm_R, BodyPartType.UpperArm_R, + BodyPartType.Hand_L, BodyPartType.ForeArm_L, BodyPartType.UpperArm_L} + +end + +function GetOtherBodyPartTypes() + + 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 find_clothName_TOC(bodyPart) @@ -43,6 +58,21 @@ function find_clothName2_TOC(name) if name == "LeftArm" then return "TOC.ArmLeft_noArm" end end + + +function TheOnlyCure.FindBodyPartFromBodyPartType(toc_data, bodyPartType) + if bodyPartType == BodyPartType.Hand_R then return toc_data.RightHand + elseif bodyPartType == BodyPartType.ForeArm_R then return toc_data.RightForearm + elseif bodyPartType == BodyPartType.UpperArm_R then return toc_data.RightArm + elseif bodyPartType == BodyPartType.Hand_L then return toc_data.LeftHand + elseif bodyPartType == BodyPartType.ForeArm_L then return toc_data.LeftForearm + elseif bodyPartType == BodyPartType.UpperArm_L then return toc_data.LeftArm + else return nil + end +end + + + function find_bodyPart_TOC(modData, bodyPart) if modData.RightHand == nil then modData = modData.TOC end if bodyPart:getType() == BodyPartType.Hand_R then return modData.RightHand diff --git a/media/lua/server/TOC_MP_server.lua b/media/lua/server/TOC_MP_server.lua index 471e219..6c9e806 100644 --- a/media/lua/server/TOC_MP_server.lua +++ b/media/lua/server/TOC_MP_server.lua @@ -13,11 +13,6 @@ Commands["SendServer"] = function(player, arg) sendServerCommand(otherPlayer, "TOC", arg["command"], arg) end - - - - - local function OnTocClientCommand(module, command, player, args) if module == 'TOC' then