--[ ======================================= Combat Handler ====================================== ]
--Builds combat, centralizing it from several script locations.

--Argument Listing:
-- 0: iEntitySlot - Specifies which slot the entity is in.
-- 1: sVictoryScript - Script to call when the player wins. Pass "Standard" to use the standard handler.
-- 2: sDefeatScript - Script to call when the player loses. Pass "Standard" to use the standard handler.

--Arg check.
local iRequiredArgs = 3
local iArgs = LM_GetNumOfArgs()
if(iArgs < iRequiredArgs) then
	Debug_ForcePrint(fnResolvePath() .. ": Error, incorrect argument count. Got " .. iArgs .. " expected " .. iRequiredArgs .. ".\n")
	return
end

--Arg resolve.
local iEntitySlot    = tonumber(LM_GetScriptArgument(0))
local sVictoryScript = LM_GetScriptArgument(1)
local sDefeatScript  = LM_GetScriptArgument(2)

--Arg validity check.
if(iEntitySlot < 1 or iEntitySlot > gzTextVar.zEntitiesTotal) then return end

--[Standard Handlers]
if(sVictoryScript == "Standard") then
    sVictoryScript = gzTextVar.sRootPath .. "Combat Handlers/Standard Victory Handler.lua"
end
if(sDefeatScript == "Standard") then
    sDefeatScript = gzTextVar.sRootPath .. "Combat Handlers/Standard Defeat Handler.lua"
end

--[Combat Setup]
--This must be called before any of the TL_SetTypeCombatProperty() functions will work.
if(TL_GetProperty("Is Combat Active") == false) then
    
    --Boot combat.
    TL_SetProperty("Activate Combat")

    --Common.
    TL_SetProperty("Set Combat Scripts", sVictoryScript, sDefeatScript)

    --[Typing Version]
    if(gzTextVar.bIsCombatTypingBased == true) then

        --Offense words.
        TL_SetTypeCombatProperty("Add Word To Attack Pool", "strike")
        TL_SetTypeCombatProperty("Add Word To Attack Pool", "attack")
        TL_SetTypeCombatProperty("Add Word To Attack Pool", "hurt")
        TL_SetTypeCombatProperty("Add Word To Attack Pool", "punch")
        TL_SetTypeCombatProperty("Add Word To Attack Pool", "wound")
        TL_SetTypeCombatProperty("Add Word To Attack Pool", "damage")
        TL_SetTypeCombatProperty("Add Word To Attack Pool", "slice")
        TL_SetTypeCombatProperty("Add Word To Attack Pool", "kick")
        TL_SetTypeCombatProperty("Add Word To Attack Pool", "assault")
        TL_SetTypeCombatProperty("Add Word To Attack Pool", "injure")

        --Defense versions.
        TL_SetTypeCombatProperty("Add Word To Defend Pool", "block")
        TL_SetTypeCombatProperty("Add Word To Defend Pool", "protect")
        TL_SetTypeCombatProperty("Add Word To Defend Pool", "guard")
        TL_SetTypeCombatProperty("Add Word To Defend Pool", "defend")
        TL_SetTypeCombatProperty("Add Word To Defend Pool", "weather")
        TL_SetTypeCombatProperty("Add Word To Defend Pool", "persist")
        TL_SetTypeCombatProperty("Add Word To Defend Pool", "survive")
        TL_SetTypeCombatProperty("Add Word To Defend Pool", "endure")

        --[Enemy Prototypes]
        --Entities store their HP/Attack/Defense values internally. For now set them all to 1's.
        TL_SetTypeCombatProperty("Add Enemy", 10, 100, 1, gzTextVar.zEntities[iEntitySlot].sQueryPicture)

    --[Sentence Version]
    else

        --[Enemy Prototypes]
        local iHealth = gzTextVar.zEntities[iEntitySlot].zCombatTable.iHealth
        local iHealthMax = gzTextVar.zEntities[iEntitySlot].zCombatTable.iHealth
        if(gzTextVar.bEnemySpawnsAtHalfHealth == true) then
            gzTextVar.bEnemySpawnsAtHalfHealth = false
            iHealth = math.floor(iHealth / 2)
            if(iHealth < 1) then iHealth = 1 end
        end

        --Health is halved if this flag is set.
        local bEasyCombat = false
        if(gzTextVar.iEasyCombats > 0) then
            bEasyCombat = true
            iHealth = iHealth / 2
            iHealthMax = iHealthMax / 2
            gzTextVar.iEasyCombats = gzTextVar.iEasyCombats - 1
        end

        TL_SetWordCombatProperty("Add Enemy", iHealth, iHealthMax, gzTextVar.zEntities[iEntitySlot].sQueryPicture)
        for i = 1, gzTextVar.zEntities[iEntitySlot].zCombatTable.iAttacksTotal, 1 do
            local iWeight = gzTextVar.zEntities[iEntitySlot].zCombatTable.zAttacks[i][1]
            local iPower  = gzTextVar.zEntities[iEntitySlot].zCombatTable.zAttacks[i][2]
            local iWindup = gzTextVar.zEntities[iEntitySlot].zCombatTable.zAttacks[i][3]
            local uiElements = gzTextVar.zEntities[iEntitySlot].zCombatTable.zAttacks[i][4]
            
            --Windup increases by 25% for easy combats.
            if(bEasyCombat) then
                iWindup = math.floor(iWindup * 1.25)
            end
            
            --Windup decreased by in turn-based mode.
            if(gzTextVar.bIsCombatWaitMode == true) then
                iWindup = math.floor(iWindup * 0.50)
            end
            
            TL_SetWordCombatProperty("Add Attack To Enemy", iWeight, iPower, iWindup, uiElements)
        end
        
        --Weaknesses. Upload from the combat table.
        for i = gciElementSlot_Fire, gciElementSlot_Death, 1 do
            TL_SetWordCombatProperty("Add Weakness To Enemy", i, gzTextVar.zEntities[iEntitySlot].zCombatTable.iaWeaknesses[i])
        end
        
        --[Player Properties]
        --Determine how many potions to give.
        local iPotionCount = 0
        for i = 1, gzTextVar.gzPlayer.iItemsTotal, 1 do
            if(gzTextVar.gzPlayer.zaItems[i].sDisplayName == "potion") then iPotionCount = iPotionCount + gzTextVar.gzPlayer.zaItems[i].iStackSize end
        end
        TL_SetWordCombatProperty("Player Properties", gzTextVar.gzPlayer.iHP, gzTextVar.gzPlayer.iHPMax, iPotionCount)
        
        --[Player Statistics]
        --Run this function to recompute player stats.
        fnComputePlayerStatBonuses()
        
        --[Player Cards]
        --Card Names
        local saAttackNames = {"Blow",  "Strike", "Attack", "Throw",   "Bash", "Tackle", "Crush"}
        local saDefendNames = {"Block", "Guard",  "Defend", "Protect", "Parry"}
        local saWaterNames = {"Freezing", "Chilling", "Boiling"}
        local saFireNames = {"Flaming", "Burning", "Scorching", "Flaring", "Torching"}
        local saWindNames = {"Shocking", "Whirling", "Blasting", "Blowing", "Thundering"}
        local saEarthNames = {"Rumbling", "Quaking", "Trembling", "Erupting", "Grinding"}
        local saLifeNames = {"Living", "Growing", "Flourishing"}
        local saDeathNames = {"Dying", "Killing", "Choking", "Murdering"}
        local saNames = {saAttackNames, saDefendNames, saWaterNames, saFireNames, saWindNames, saEarthNames, saLifeNames, saDeathNames, {"Of"}, {"And"}}
        
        --Flags. Literally here to make the next array lines shorter. There's no other reason!
        local ciNone = gciCardEffect_None
        local ciMod = gciCardType_Modifier
        
        --Begin building the player's deck, based on available types.
        local iLen = #gzTextVar.gzPlayer.zDeck.iaCardArray
        
        --Flags to indicate which type of card is in the slot.
        local iaFlagOrder = {gciCardType_Action, gciCardType_Action, ciMod, ciMod, ciMod, ciMod, ciMod, ciMod, gciCardType_Of, gciCardType_And}
        
        --Effect. Differentiates the two action types.
        local iaEffectOrder = {gciCardEffect_Damage, gciCardEffect_Defend, ciNone, ciNone, ciNone, ciNone, ciNone, ciNone, ciNone, ciNone}
        
        --Base bonus. Attack and the simple elements are base-1, Defend and the power-elements are base-2.
        local iaBaseOrder = {1, 2, 1, 1, 1, 1, 2, 2, 0, 0}
        
        --Which bonus to use for which property.
        local iaBonusOrder = {gzTextVar.iAtkBonus, gzTextVar.iDefBonus, gzTextVar.iWaterBonus, gzTextVar.iFireBonus, gzTextVar.iWindBonus, gzTextVar.iEarthBonus, gzTextVar.iLifeBonus, gzTextVar.iDeathBonus, 0, 0}
        
        --Elements associated with each card type.
        local iaElementOrder = {gciElement_None, gciElement_None, gciElement_Water, gciElement_Fire, gciElement_Wind, gciElement_Earth, gciElement_Life, gciElement_Death, gciElement_None, gciElement_None}
        
        --All arrays are set up, create the cards!
        for i = 1, iLen, 1 do
            
            --Get how many cards to create.
            local iCardsNeeded = gzTextVar.gzPlayer.zDeck.iaCardArray[i]
            local iMaxRoll = #saNames[i]
            
            --Iterate.
            for p = 1, iCardsNeeded, 1 do
            
                --Don't roll a random name if there's exactly one available.
                if(iMaxRoll == 1) then
                    TL_SetWordCombatProperty("Add Card To Deck", iaFlagOrder[i], iaEffectOrder[i], iaBaseOrder[i] + iaBonusOrder[i], saNames[i][1], iaElementOrder[i])
                    
                --Roll a random name. Duplicates are allowed.
                else
                    local iRoll = LM_GetRandomNumber(1, iMaxRoll)
                    TL_SetWordCombatProperty("Add Card To Deck", iaFlagOrder[i], iaEffectOrder[i], iaBaseOrder[i] + iaBonusOrder[i], saNames[i][iRoll], iaElementOrder[i])
            
                end
            end
        end
        
        --[Ace Card]
        --Action. Attack or Defend cards.
        if(gzTextVar.gzPlayer.zDeck.iAceType == gciCardType_Action) then
            
            --Type. Damage first.
            if(gzTextVar.gzPlayer.zDeck.iAceEffect == gciCardEffect_Damage) then
                TL_SetWordCombatProperty("Set Ace Card", gciCardType_Action, gciCardEffect_Damage, 1 + gzTextVar.gzPlayer.zDeck.iAcePower + gzTextVar.iAtkBonus, "Batter", gzTextVar.gzPlayer.zDeck.iAceElement)
                
            --Defense cards.
            else
                TL_SetWordCombatProperty("Set Ace Card", gciCardType_Action, gciCardEffect_Defend, 1 + gzTextVar.gzPlayer.zDeck.iAcePower + gzTextVar.iDefBonus, "Shield", gzTextVar.gzPlayer.zDeck.iAceElement)
            end
        
        --Elemental cards.
        else
        
            --Fire:
            if(gzTextVar.gzPlayer.zDeck.iAceElement == gciElement_Fire) then
                TL_SetWordCombatProperty("Set Ace Card", ciMod, ciNone, 1 + gzTextVar.gzPlayer.zDeck.iAcePower + gzTextVar.iFireBonus, "Incinerating", gzTextVar.gzPlayer.zDeck.iAceElement)
            
            --Water:
            elseif(gzTextVar.gzPlayer.zDeck.iAceElement == gciElement_Water) then
                TL_SetWordCombatProperty("Set Ace Card", ciMod, ciNone, 1 + gzTextVar.gzPlayer.zDeck.iAcePower + gzTextVar.iWaterBonus, "Drowning", gzTextVar.gzPlayer.zDeck.iAceElement)
            
            --Wind:
            elseif(gzTextVar.gzPlayer.zDeck.iAceElement == gciElement_Wind) then
                TL_SetWordCombatProperty("Set Ace Card", ciMod, ciNone, 1 + gzTextVar.gzPlayer.zDeck.iAcePower + gzTextVar.iWindBonus, "Surging", gzTextVar.gzPlayer.zDeck.iAceElement)
            
            --Earth:
            elseif(gzTextVar.gzPlayer.zDeck.iAceElement == gciElement_Earth) then
                TL_SetWordCombatProperty("Set Ace Card", ciMod, ciNone, 1 + gzTextVar.gzPlayer.zDeck.iAcePower + gzTextVar.iEarthBonus, "Sundering", gzTextVar.gzPlayer.zDeck.iAceElement)
            
            --Life:
            elseif(gzTextVar.gzPlayer.zDeck.iAceElement == gciElement_Life) then
                TL_SetWordCombatProperty("Set Ace Card", ciMod, ciNone, 2 + gzTextVar.gzPlayer.zDeck.iAcePower + gzTextVar.iLifeBonus, "Flowering", gzTextVar.gzPlayer.zDeck.iAceElement)
            
            --Death:
            elseif(gzTextVar.gzPlayer.zDeck.iAceElement == gciElement_Death) then
                TL_SetWordCombatProperty("Set Ace Card", ciMod, ciNone, 2 + gzTextVar.gzPlayer.zDeck.iAcePower + gzTextVar.iDeathBonus, "Slaughtering", gzTextVar.gzPlayer.zDeck.iAceElement)
                
            end
        end

        --Player gains shields if their base shield counter is above zero.
        TL_SetWordCombatProperty("Add Shields", gzTextVar.iStartShieldBonus)

    end

    --[Finalize]
    --Indicates setup is over and the first round can start.
    TL_SetProperty("Finalize Combat")

--[Active Combat]
--Add the entity to the battle instead of booting a new one.
else

    --[Typing Version]
    if(gzTextVar.bIsCombatTypingBased == true) then

    --[Word Version]
    else
        
        --[Enemy Prototypes]
        local iHealth = gzTextVar.zEntities[iEntitySlot].zCombatTable.iHealth
        local iHealthMax = gzTextVar.zEntities[iEntitySlot].zCombatTable.iHealth
        if(gzTextVar.bEnemySpawnsAtHalfHealth == true) then
            gzTextVar.bEnemySpawnsAtHalfHealth = false
            iHealth = math.floor(iHealth / 2)
            if(iHealth < 1) then iHealth = 1 end
        end

        --Health is halved if this flag is set.
        local bEasyCombat = false
        if(gzTextVar.iEasyCombats > 0) then
            bEasyCombat = true
            iHealth = iHealth / 2
            iHealthMax = iHealthMax / 2
            gzTextVar.iEasyCombats = gzTextVar.iEasyCombats - 1
        end

        TL_SetWordCombatProperty("Add Enemy", iHealth, iHealthMax, gzTextVar.zEntities[iEntitySlot].sQueryPicture)
        for i = 1, gzTextVar.zEntities[iEntitySlot].zCombatTable.iAttacksTotal, 1 do
            local iWeight = gzTextVar.zEntities[iEntitySlot].zCombatTable.zAttacks[i][1]
            local iPower  = gzTextVar.zEntities[iEntitySlot].zCombatTable.zAttacks[i][2]
            local iWindup = gzTextVar.zEntities[iEntitySlot].zCombatTable.zAttacks[i][3]
            local uiElements = gzTextVar.zEntities[iEntitySlot].zCombatTable.zAttacks[i][4]
            
            --Windup increases by 25% for easy combats.
            if(bEasyCombat) then
                iWindup = math.floor(iWindup * 1.25)
            end
            
            --Windup decreased by in turn-based mode.
            if(gzTextVar.bIsCombatWaitMode == true) then
                iWindup = math.floor(iWindup * 0.50)
            end
            
            TL_SetWordCombatProperty("Add Attack To Enemy", iWeight, iPower, iWindup, uiElements)
        end
        
        --Weaknesses. Upload from the combat table.
        for i = gciElementSlot_Fire, gciElementSlot_Death, 1 do
            TL_SetWordCombatProperty("Add Weakness To Enemy", i, gzTextVar.zEntities[iEntitySlot].zCombatTable.iaWeaknesses[i])
        end
    
    end
end
