 --[[
Injury Detection And Armor Based Injury Blocking
By Nolan Ritchie


]]

function loadArmorToPlayer(Armor, player)
    loadArmor(Armor);
    ArmorSaveBodyDamage(player);
end

function getBodyPartDisplayName(TypeIn)

    BPType = tostring(TypeIn);
    if(BPType == "Foot_L") then return "Left Foot";
    elseif(BPType == "Foot_R") then return "Right Foot";
    elseif(BPType == "ForeArm_L") then return "Left Fore Arm";
    elseif(BPType == "ForeArm_R") then return "Right Fore Arm";
    elseif(BPType == "Hand_L") then return "Left Hand";
    elseif(BPType == "Hand_R") then return "Right Hand";
    elseif(BPType == "LowerLeg_L") then return "Left Lower Leg";
    elseif(BPType == "LowerLeg_R") then return "Right Lower Leg";
    elseif(BPType == "Torso_Lower") then return "Lower Torso";
    elseif(BPType == "Torso_Upper") then return "Upper Torso";
    elseif(BPType == "UpperArm_L") then return "Left Upper Arm";
    elseif(BPType == "UpperArm_R") then return "Right Upper Arm";
    elseif(BPType == "UpperLeg_L") then return "Left Upper Leg";
    elseif(BPType == "UpperLeg_R") then return "Right Upper Leg";
    else return BPType;
    end

end

function ExamineArmor(items, result, player)
    
    for i=0, items:size()-1 do
        Armor = items:get(i);
    end
    
    loadArmor(Armor);
    
    local out = "Remaining Durability: " .. tostring(Armor:getModData().Durability) .. "\n";
    local BPs = player:getBodyDamage():getBodyParts();
    for i=0, BPs:size()-1 do        
        
        if(Armor:getModData().ScratchRes ~= nil) and (Armor:getModData().ScratchRes[tostring(BPs:get(i):getType())] ~= nil) then
            out = out .. tostring(Armor:getModData().ScratchRes[tostring(BPs:get(i):getType())]).. "%" .. " chance to block Scratches on the " .. getBodyPartDisplayName(BPs:get(i):getType()) .. "\n";
        end
        if(Armor:getModData().DeepWoundRes ~= nil) and (Armor:getModData().DeepWoundRes[tostring(BPs:get(i):getType())] ~= nil) then
            out = out  .. tostring(Armor:getModData().DeepWoundRes[tostring(BPs:get(i):getType())]).. "%" .. " Chance to block to Deep Wounds on the " .. getBodyPartDisplayName(BPs:get(i):getType()) .. "\n";
        end
        if(Armor:getModData().BiteRes ~= nil) and (Armor:getModData().BiteRes[tostring(BPs:get(i):getType())] ~= nil) then
            out = out  .. tostring(Armor:getModData().BiteRes[tostring(BPs:get(i):getType())]) .. "%".. " Chance to block to Bites on the " .. getBodyPartDisplayName(BPs:get(i):getType()) .. "\n";
        end
        if(Armor:getModData().GlassRes ~= nil) and (Armor:getModData().GlassRes[tostring(BPs:get(i):getType())] ~= nil) then
            out = out  .. tostring(Armor:getModData().GlassRes[tostring(BPs:get(i):getType())]) .. "%".. " Chance to block to Glass on the " .. getBodyPartDisplayName(BPs:get(i):getType()) .. "\n";
        end
        if(Armor:getModData().FractureRes ~= nil) and (Armor:getModData().FractureRes[tostring(BPs:get(i):getType())] ~= nil) then
            out = out  .. tostring(Armor:getModData().FractureRes[tostring(BPs:get(i):getType())]) .. "%".. " Chance to block to Fractures on the " .. getBodyPartDisplayName(BPs:get(i):getType()) .. "\n";
        end
        if(Armor:getModData().BurnRes ~= nil) and (Armor:getModData().BurnRes[tostring(BPs:get(i):getType())] ~= nil) then
            out = out .. tostring(Armor:getModData().BurnRes[tostring(BPs:get(i):getType())])  .. "%".. " Chance to block to Burns on the " .. getBodyPartDisplayName(BPs:get(i):getType()) .. "\n";
        end
        if(Armor:getModData().BulletRes ~= nil) and (Armor:getModData().BulletRes[tostring(BPs:get(i):getType())] ~= nil) then
            out = out  .. tostring(Armor:getModData().BulletRes[tostring(BPs:get(i):getType())]).. "%" .. " Chance to block to Bullets on the " .. getBodyPartDisplayName(BPs:get(i):getType()) .. "\n";
        end
    end
    out = Armor:getDisplayName() .. "\n" .. out;
    ArmorWindow:setText(out);
    ArmorWindow:setVisible(true);
    --player:Say();
end

function ArmorSaveBodyDamage(player)
    
    ArmorTempBodyDamage = {};
    local BD = player:getBodyDamage();
    --local InjuryTypes = {0 = "Scratch",1 = "DeepWound", 2 = "Burn", 3 = "BulletRes", 4 = "Fracture", 5 = "Glass"};
    
    ArmorTempBodyDamage["IsInfected"] = BD:IsInfected();
        
    local BPs = BD:getBodyParts();
    for i=0, BPs:size()-1 do
            ArmorTempBodyDamage[tostring(BPs:get(i):getType())] = {Splint= false, Bandage = false, Bite = false, Scratch = false, DeepWound = false, Burn = false, Bullet = false, Fracture = false, Glass = false};
        
            ArmorTempBodyDamage[tostring(BPs:get(i):getType())]["Splint"] = BPs:get(i):isSplint();
            ArmorTempBodyDamage[tostring(BPs:get(i):getType())]["Bandage"] = BPs:get(i):bandaged();
            ArmorTempBodyDamage[tostring(BPs:get(i):getType())]["Scratch"] = BPs:get(i):scratched();
            ArmorTempBodyDamage[tostring(BPs:get(i):getType())]["DeepWound"] = BPs:get(i):deepWounded();
            ArmorTempBodyDamage[tostring(BPs:get(i):getType())]["Burn"] = BPs:get(i):getBurnTime();
            ArmorTempBodyDamage[tostring(BPs:get(i):getType())]["Bullet"] = BPs:get(i):haveBullet();
            ArmorTempBodyDamage[tostring(BPs:get(i):getType())]["Fracture"] = BPs:get(i):getFractureTime();
            ArmorTempBodyDamage[tostring(BPs:get(i):getType())]["Glass"] = BPs:get(i):haveGlass();
            ArmorTempBodyDamage[tostring(BPs:get(i):getType())]["Bite"] = BPs:get(i):bitten();
        
    end
    ArmorBDamageSaved = true;
end

function tryBlock(BodyPartType, InjuryType, ArmorType, player)
    local Armor = player:getInventory():getItemFromType(ArmorType);
    if(InjuryType == "Scratch") then
        if(Armor:getModData().ScratchRes ~= nil) and (Armor:getModData().ScratchRes[BodyPartType] ~= nil) then
            return ( (ZombRand(100)+1) < Armor:getModData().ScratchRes[BodyPartType] );
        end    
    elseif(InjuryType == "DeepWound") then
        if((Armor:getModData().DeepWoundRes ~= nil) and Armor:getModData().DeepWoundRes[BodyPartType] ~= nil) then
            return ( (ZombRand(100)+1) < Armor:getModData().DeepWoundRes[BodyPartType] );
        end
    elseif(InjuryType == "Bite") then
        if(Armor:getModData().BiteRes ~= nil) and (Armor:getModData().BiteRes[BodyPartType] ~= nil) then
            return ( (ZombRand(100)+1) < Armor:getModData().BiteRes[BodyPartType] );
        end
    elseif(InjuryType == "Fracture") then
        if(Armor:getModData().FractureRes ~= nil) and (Armor:getModData().FractureRes[BodyPartType] ~= nil) then
            return ( (ZombRand(100)+1) < Armor:getModData().FractureRes[BodyPartType] );
        end
    elseif(InjuryType == "Burn") then
        if(Armor:getModData().BurnRes ~= nil) and (Armor:getModData().BurnRes[BodyPartType] ~= nil) then
            return ( (ZombRand(100)+1) < Armor:getModData().BurnRes[BodyPartType] );
        end
    elseif(InjuryType == "Glass") then
        if(Armor:getModData().GlassRes ~= nil) and (Armor:getModData().GlassRes[BodyPartType] ~= nil) then
            return ( (ZombRand(100)+1) < Armor:getModData().GlassRes[BodyPartType] );
        end
    elseif(InjuryType == "Bullet") then
        if(Armor:getModData().BulletRes ~= nil) and (Armor:getModData().BulletRes[BodyPartType] ~= nil) then
            return ( (ZombRand(100)+1) < Armor:getModData().BulletRes[BodyPartType] );
        end
    end

end
function EquipAsShield(items, result, player) -- Recipe must only have one ingredient which is the armor, and be set to "keep"
    for i=0, items:size()-1 do
        loadArmorToPlayer(items:get(i), player);        
        if (player:getSecondaryHandItem() == player:getPrimaryHandItem()) then
            player:setPrimaryHandItem(nil);
        end
        player:setSecondaryHandItem(items:get(i));
        player:getModData().ShieldArmor = items:get(i):getType();            
    end
end
function EquipOnHead(items, result, player) -- Recipe must only have one ingredient which is the armor, and be set to "keep"
    for i=0, items:size()-1 do
        loadArmorToPlayer(items:get(i), player);
        player:getModData().HeadArmor = items:get(i):getType();            
    end
end
function EquipOnHands(items, result, player) -- Recipe must only have one ingredient which is the armor, and be set to "keep"
    for i=0, items:size()-1 do
        loadArmorToPlayer(items:get(i), player);
        player:getModData().HandArmor = items:get(i):getType();            
    end
end
function EquipOnArms(items, result, player) -- Recipe must only have one ingredient which is the armor, and be set to "keep"
    for i=0, items:size()-1 do
        loadArmorToPlayer(items:get(i), player);
        player:getModData().ArmArmor = items:get(i):getType();            
    end
end
function EquipOnLegs(items, result, player) -- Recipe must only have one ingredient which is the armor, and be set to "keep"
    for i=0, items:size()-1 do
        loadArmorToPlayer(items:get(i), player);
        player:getModData().LegArmor = items:get(i):getType();            
    end
end
function EquipOnChest(items, result, player) -- Recipe must only have one ingredient which is the armor, and be set to "keep"
    for i=0, items:size()-1 do
        loadArmorToPlayer(items:get(i), player);
        player:getModData().ChestArmor = items:get(i):getType();            
    end
end
function EquipOnFeet(items, result, player) -- Recipe must only have one ingredient which is the armor, and be set to "keep"
    for i=0, items:size()-1 do
        loadArmorToPlayer(items:get(i), player);
        player:getModData().FootArmor = items:get(i):getType();            
    end
end

function DamageArmor(Armor, player, InjuryType)

    local Damage = 1;
    
    if(InjuryType == "Scratch") then
        Damage = 1;
    elseif(InjuryType == "DeepWound") then
        Damage = 3;
    elseif(InjuryType == "Bite") then
        Damage = 2;
    elseif(InjuryType == "Fracture") then
        Damage = 3;
    elseif(InjuryType == "Burn") then
        Damage = 2;
    elseif(InjuryType == "Glass") then
        Damage = 2;
    elseif(InjuryType == "Bullet") then
        Damage = 5;
    end

    local isBroken = false;
    Armor:getModData().Durability = Armor:getModData().Durability - Damage;
    if (Armor:getModData().Durability <= 0) then
        isBroken = true;
        if(Armor:getModData().onBreakTurnInto ~= nil) then
            player:Say("adding broken armor" .. Armor:getModData().onBreakTurnInto);
            player:getInventory():AddItem(Armor:getModData().onBreakTurnInto);
        end
        player:getInventory():Remove(Armor);
    end
    return isBroken;
end

function wasDamagedBlocked(BodyPartType, InjuryType, player)

    if(ArmorTempBodyDamage[tostring(BodyPartType)]["Bandage"] == true) or (ArmorTempBodyDamage[tostring(BodyPartType)]["Splint"] == true) then
    return false;
    end

    if(player:getSecondaryHandItem() ~= nil) then
        if(player:getModData().ShieldArmor ~= nil) and (player:getSecondaryHandItem():getType() == player:getModData().ShieldArmor)  then
            if(tryBlock(BodyPartType, InjuryType, player:getModData().ShieldArmor, player) == true) then
                if(DamageArmor(player:getInventory():getItemFromType(player:getModData().ShieldArmor),player,InjuryType) == true) then
                    player:setSecondaryHandItem(nil);
                end
                return true;
            end
        end
    end
    if(player:getModData().HeadArmor ~= nil) and (player:getInventory():contains(player:getModData().HeadArmor)) then
        if(tryBlock(BodyPartType, InjuryType, player:getModData().HeadArmor, player) == true) then
            DamageArmor(player:getInventory():getItemFromType(player:getModData().HeadArmor),player,InjuryType);
            return true;
        end
    end
    if(player:getModData().HandArmor ~= nil) and (player:getInventory():contains(player:getModData().HandArmor)) then
        if(tryBlock(BodyPartType, InjuryType, player:getModData().HandArmor, player) == true) then
            DamageArmor(player:getInventory():getItemFromType(player:getModData().HandArmor),player,InjuryType);
            return true;
        end
    end
    if(player:getModData().ArmArmor ~= nil) and (player:getInventory():contains(player:getModData().ArmArmor)) then
        if(tryBlock(BodyPartType, InjuryType, player:getModData().ArmArmor, player) == true) then
            DamageArmor(player:getInventory():getItemFromType(player:getModData().ArmArmor),player,InjuryType);
            return true;
        end
    end
    if(player:getModData().ChestArmor ~= nil) and (player:getInventory():contains(player:getModData().ChestArmor)) then
        if(tryBlock(BodyPartType, InjuryType, player:getModData().ChestArmor, player) == true) then
            DamageArmor(player:getInventory():getItemFromType(player:getModData().ChestArmor),player,InjuryType);
            return true;
        end
    end
    if(player:getModData().LegArmor ~= nil) and (player:getInventory():contains(player:getModData().LegArmor)) then
        if(tryBlock(BodyPartType, InjuryType, player:getModData().LegArmor, player) == true) then
            DamageArmor(player:getInventory():getItemFromType(player:getModData().LegArmor),player,InjuryType);
            return true;
        end
    end
    if(player:getModData().FootArmor ~= nil) and (player:getInventory():contains(player:getModData().FootArmor)) then
        if(tryBlock(BodyPartType, InjuryType, player:getModData().FootArmor, player) == true) then
            DamageArmor(player:getInventory():getItemFromType(player:getModData().FootArmor),player,InjuryType);
            return true;
        end
    end

    return false;
    
end

function ArmorCheckForDamage(player)
local ArmorbInjuryDetected = false;
    if(ArmorBDamageSaved ~= nil) and (player ~= nil) then
        
        local BD = player:getBodyDamage();
        --local InjuryTypes = {0 = "Scratch",1 = "DeepWound", 2 = "Burn", 3 = "BulletRes", 4 = "Fracture", 5 = "Glass"};
        
        --ArmorTempBodyDamage["IsInfected"] = BD:IsInfected();
            
        local BPs = BD:getBodyParts();
        for i=0, BPs:size()-1 do
            
            
                if(ArmorTempBodyDamage[tostring(BPs:get(i):getType())]["Scratch"] ~= BPs:get(i):scratched()) and (BPs:get(i):scratched() == true) then
                    --player:Say("Scratch Detected on ".. tostring(BPs:get(i):getType()));
                    if(wasDamagedBlocked(tostring(BPs:get(i):getType()), "Scratch", player)) then
                        BPs:get(i):setScratched(false);
                        BPs:get(i):RestoreToFullHealth();
                        if(ArmorTempBodyDamage["IsInfected"] == false) and (BD:IsInfected() == true) then
                            BD:setInf(false); -- remove infection if did not have before the blocked scratch
                        end
                        player:Say("!");
                        sendClientCommand(player, "Armor", "Say", {saythis = "!"});
                    end
                    ArmorbInjuryDetected = true;
                end
                if(ArmorTempBodyDamage[tostring(BPs:get(i):getType())]["DeepWound"] ~= BPs:get(i):deepWounded()) and (BPs:get(i):deepWounded() == true) and (BPs:get(i):haveBullet() == false) and (BPs:get(i):haveGlass() == false) then
                    --player:Say("Deep Wound Detected on ".. tostring(BPs:get(i):getType()));
                    if(wasDamagedBlocked(tostring(BPs:get(i):getType()), "DeepWound", player)) then
                        BPs:get(i):setDeepWounded(false);
                        BPs:get(i):RestoreToFullHealth();
                        player:Say("!");
                        sendClientCommand(player, "Armor", "Say", {saythis = "!"});
                    end
                    ArmorbInjuryDetected = true;
                end
                if(ArmorTempBodyDamage[tostring(BPs:get(i):getType())]["Bite"] ~= BPs:get(i):bitten()) and (BPs:get(i):bitten() == true) then
                    --player:Say("Bite Detected on ".. tostring(BPs:get(i):getType()));
                    if(wasDamagedBlocked(tostring(BPs:get(i):getType()), "Bite", player)) then
                        BPs:get(i):SetBitten(false);
                        BPs:get(i):RestoreToFullHealth();
                        if(ArmorTempBodyDamage["IsInfected"] == false) and (BD:IsInfected() == true) then
                            BD:setInf(false); -- remove infection if did not have before the blocked bite
                        end
                        player:Say("!");
                        sendClientCommand(player, "Armor", "Say", {saythis = "!"});
                    end
                    ArmorbInjuryDetected = true;
                end
                if(ArmorTempBodyDamage[tostring(BPs:get(i):getType())]["Burn"] ~= BPs:get(i):getBurnTime()) and (BPs:get(i):getBurnTime() ~= 0) then
                    --player:Say("Burn Detected on ".. tostring(BPs:get(i):getType()) );
                    if(wasDamagedBlocked(tostring(BPs:get(i):getType()), "Burn", player)) then
                        BPs:get(i):setBurnTime(0);
                        BPs:get(i):RestoreToFullHealth();
                        player:Say("!");
                        sendClientCommand(player, "Armor", "Say", {saythis = "!"});
                    end
                    ArmorbInjuryDetected = true;
                end
                if(ArmorTempBodyDamage[tostring(BPs:get(i):getType())]["Bullet"] ~= BPs:get(i):haveBullet()) and (BPs:get(i):haveBullet() == true) then
                    --player:Say("Lodged Bullets Detected on ".. tostring(BPs:get(i):getType()));
                    if(wasDamagedBlocked(tostring(BPs:get(i):getType()), "Bullet", player)) then
                        BPs:get(i):setDeepWounded(false);
                        BPs:get(i):setHaveBullet(false,10);
                        BPs:get(i):RestoreToFullHealth();
                        player:Say("!");
                        sendClientCommand(player, "Armor", "Say", {saythis = "!"});
                    end
                    ArmorbInjuryDetected = true;
                end
                if(ArmorTempBodyDamage[tostring(BPs:get(i):getType())]["Fracture"] ~= BPs:get(i):getFractureTime()) and (BPs:get(i):getFractureTime() ~= 0) then
                    --player:Say("Fracture Detected on ".. tostring(BPs:get(i):getType()));
                    if(wasDamagedBlocked(tostring(BPs:get(i):getType()), "Fracture", player)) then
                        BPs:get(i):setFractureTime(0);
                        BPs:get(i):RestoreToFullHealth();
                        player:Say("!");
                        sendClientCommand(player, "Armor", "Say", {saythis = "!"});
                    end
                    ArmorbInjuryDetected = true;
                end
                if(ArmorTempBodyDamage[tostring(BPs:get(i):getType())]["Glass"] ~= BPs:get(i):haveGlass()) and (BPs:get(i):haveGlass() == true) then
                    --player:Say("Logged Glass Detected on ".. tostring(BPs:get(i):getType()));
                    if(wasDamagedBlocked(tostring(BPs:get(i):getType()), "Glass", player)) then
                        BPs:get(i):setDeepWounded(false);
                        BPs:get(i):setHaveGlass(false);
                        BPs:get(i):RestoreToFullHealth();
                        player:Say("!");
                        sendClientCommand(player, "Armor", "Say", {saythis = "!"});
                    end
                    ArmorbInjuryDetected = true;
                end
            end
        
        
    end
    
    if(ArmorbInjuryDetected) then
        ArmorSaveBodyDamage(player);
    end
    
    return ArmorbInjuryDetected;
end

function ArmorupdateThePlayer(player)
    ArmorCheckForDamage(player);
    player:getInventory():Remove("HCEquiparmor");
end

function ArmorInit()
    ArmorSaveBodyDamage(getPlayer());
end
function ArmorKeysUp(keynum)
    --getPlayer():Say(tostring(keynum));
    if keynum == 25 then
        local player = getPlayer();
        local armorstring = "Currently Equipped Armor \n";
        if(player:getModData().ShieldArmor ~= nil) and (player:getSecondaryHandItem() ~= nil) and (player:getSecondaryHandItem():getType() == player:getModData().ShieldArmor) then
        armorstring = armorstring .. "Shield: " .. player:getInventory():getItemFromType(player:getModData().ShieldArmor):getDisplayName() .. "\n";
        end
        if(player:getModData().HeadArmor ~= nil) and (player:getInventory():contains(player:getModData().HeadArmor)) then
        armorstring = armorstring .. "Helmet: " .. player:getInventory():getItemFromType(player:getModData().HeadArmor):getDisplayName() .. "\n";
        end
        if(player:getModData().HandArmor ~= nil) and (player:getInventory():contains(player:getModData().HandArmor)) then
        armorstring = armorstring .. "Hands: " .. player:getInventory():getItemFromType(player:getModData().HandArmor):getDisplayName() .. "\n";
        end
        if(player:getModData().ArmArmor ~= nil) and (player:getInventory():contains(player:getModData().ArmArmor)) then
        armorstring = armorstring .. "Arms: " .. player:getInventory():getItemFromType(player:getModData().ArmArmor):getDisplayName() .. "\n";
        end
        if(player:getModData().LegArmor ~= nil) and (player:getInventory():contains(player:getModData().LegArmor)) then
        armorstring = armorstring .. "Legs: " .. player:getInventory():getItemFromType(player:getModData().LegArmor):getDisplayName() .. "\n";
        end
        if(player:getModData().ChestArmor ~= nil) and (player:getInventory():contains(player:getModData().ChestArmor)) then
        armorstring = armorstring .. "Chest: " .. player:getInventory():getItemFromType(player:getModData().ChestArmor):getDisplayName() .. "\n";
        end
        if(player:getModData().FootArmor ~= nil) and (player:getInventory():contains(player:getModData().FootArmor)) then
        armorstring = armorstring .. "Feet: " .. player:getInventory():getItemFromType(player:getModData().FootArmor):getDisplayName() .. "\n";
        end
                
        ArmorWindow:setText(armorstring);
        ArmorWindow:setVisible(true);
    end        
end

Events.OnKeyPressed.Add(ArmorKeysUp);
Events.OnPlayerUpdate.Add(ArmorupdateThePlayer);
Events.OnGameStart.Add(ArmorInit); 