--[ ======================================= fnSpawnDoll() ======================================= ]
--Spawns a doll enemy. Dolls are enemies unless the player is also a doll.
fnSpawnDollTutPatrol = function(sSpawnLocation, sIdentifier, saPatrolList)
    
    --[Argument Handler]
    gzTextVar.iLastSpawnedEntity = -1
    if(sSpawnLocation == nil) then return end
    if(sIdentifier == nil) then return end
    
    --If the patrol list is nil, then the doll will move randomly. We don't check it.
    
    --[Location]
    --Location Resolver. If the first letter of the location is an "_" then we need to resolve the room's name
    -- by its coordinates on the 3D map.
    if(string.sub(sSpawnLocation, 1, 1) == "_") then
        
        --Subroutine does the work. Range-check it.
        local iIndex = fnGetRoomIndexFromString(sSpawnLocation)
        if(iIndex == -1 or iIndex >= gzTextVar.iRoomsTotal) then return end
        
        --Modify the sSpawnLocation to be the name of the room.
        sSpawnLocation = gzTextVar.zRoomList[iIndex].sName
    end
    
    --[Patrol List]
    --Go through the patrol list and do this modification to all of its entries, turning coordinates to names.
    if(saPatrolList ~= nil) then
        for i = 1, #saPatrolList, 1 do
            
            if(string.sub(saPatrolList[i], 1, 1) == "_") then
                
                --Subroutine does the work. Range-check it.
                local iIndex = fnGetRoomIndexFromString(saPatrolList[i])
                if(iIndex == -1 or iIndex >= gzTextVar.iRoomsTotal) then return end
                
                --Modify the sSpawnLocation to be the name of the room.
                saPatrolList[i] = gzTextVar.zRoomList[iIndex].sName
            end
        end
    end
    
    --[Creation]
    --Add space for a new entity.
    gzTextVar.zEntitiesTotal = gzTextVar.zEntitiesTotal + 1

    --Shorthand
    local i = gzTextVar.zEntitiesTotal

    --Possible names.
    if(gzTextVar.saDollNameList == nil) then
        gzTextVar.saDollNameList = {"Francine", "Pearl", "Priscilla", "Rosemary", "Marilee", "Carolina", "Alice", "Melanie", "Jackqueline", "Florence", "Bonnie", "Tiffany", "May", "Isabelle", "Joanne", "Marianne", "Natalie", "Rosa", "Edith", "Tina", "Tess", "Ilhan", "Maya", "Laura", "Elizabeth", "Mina", "Dahlia", "Bethany", "Ginny"}
        gzTextVar.saDollLowercaseNameList = {}
        for i = 1, #gzTextVar.saDollNameList, 1 do
            gzTextVar.saDollLowercaseNameList[i] = string.lower(gzTextVar.saDollNameList[i])
        end
    end

    --Roll a name. Retry until we get a legal one or make 100 attempts.
    local iAttemptsLeft = 100
    local bStop = false
    local iRoll = 1
    while(iAttemptsLeft > 0) do
        
        --Roll.
        bStop = false
        iAttemptsLeft = iAttemptsLeft - 1
        iRoll = LM_GetRandomNumber(1, #gzTextVar.saDollNameList)
        
        --Check if the name is taken. If it is, reroll.
        for p = 1, gzTextVar.zEntitiesTotal - 1, 1 do
            if(gzTextVar.zEntities[p].sQueryName == gzTextVar.saDollLowercaseNameList[iRoll]) then
                bStop = true
                break
            end
        end
        
        --Exit case.
        if(bStop == false) then break end
    end

    --Couldn't generate a legal name.
    if(iAttemptsLeft == 0) then
        gzTextVar.zEntitiesTotal = gzTextVar.zEntitiesTotal - 1
        return
    end

    --[Initialization]
    --Strings
    gzTextVar.iLastSpawnedEntity = i
    gzTextVar.zEntities[i] = {}
    gzTextVar.zEntities[i].sDisplayName = gzTextVar.saDollNameList[iRoll]
    gzTextVar.zEntities[i].sQueryName = gzTextVar.saDollLowercaseNameList[iRoll]
    gzTextVar.zEntities[i].sQueryPicture = "Root/Images/DollManor/Characters/Doll Dancer A"
    gzTextVar.zEntities[i].sUniqueName = gzTextVar.saDollLowercaseNameList[iRoll]
    gzTextVar.zEntities[i].sLocation = sSpawnLocation
    gzTextVar.zEntities[i].sSpecialIdentifier = sIdentifier
    
    --Skin color.
    local iSkinRoll = LM_GetRandomNumber(0, 3)
    local sEndLetter = string.char(iSkinRoll + 65) --65 being 'A'
    
    --Sets. No differences exist between these except appearances.
    local iTypeRoll = LM_GetRandomNumber(1, 6)
    if(iTypeRoll == 1) then
        gzTextVar.zEntities[i].sQueryPicture = "Root/Images/DollManor/Characters/Doll Bride " .. sEndLetter
    elseif(iTypeRoll == 2) then
        gzTextVar.zEntities[i].sQueryPicture = "Root/Images/DollManor/Characters/Doll Dancer " .. sEndLetter
    elseif(iTypeRoll == 3) then
        gzTextVar.zEntities[i].sQueryPicture = "Root/Images/DollManor/Characters/Doll Geisha " .. sEndLetter
    elseif(iTypeRoll == 4) then
        gzTextVar.zEntities[i].sQueryPicture = "Root/Images/DollManor/Characters/Doll Goth " .. sEndLetter
    elseif(iTypeRoll == 5) then
        gzTextVar.zEntities[i].sQueryPicture = "Root/Images/DollManor/Characters/Doll Princess " .. sEndLetter
    else
        gzTextVar.zEntities[i].sQueryPicture = "Root/Images/DollManor/Characters/Doll Punk " .. sEndLetter
    end
    
    --Debug: Randomly rolls a location.
    if(false) then
        while(gzTextVar.iRoomsTotal > 0) do
            
            --Random location.
            local iRoll = LM_GetRandomNumber(1, gzTextVar.iRoomsTotal)
            
            --Check if the room is the one the player is currently in. If it is, we can't spawn there.
            if(gzTextVar.zRoomList[iRoll].sName == gzTextVar.gzPlayer.sLocation) then
            
            --Check if this room is the Main Hall. We can't spawn there since it's protected.
            elseif(gzTextVar.zRoomList[iRoll].sName == "Main Hall") then
            
            --All checks passed. Spawn.
            else
                gzTextVar.zEntities[i].sLocation = gzTextVar.zRoomList[iRoll].sName
                break
            end
        end
    
    --Debug force position.
    elseif(false) then
        gzTextVar.zEntities[i].sLocation = "Main Hall"
    end

    --[AI Variables]
    --Command Handler
    gzTextVar.zEntities[i].sCommandHandler = gzTextVar.sEntityHandlers .. "Doll.lua"
    gzTextVar.zEntities[i].sAIHandlerHostility = "Doll Tutorial Patrol"
    gzTextVar.zEntities[i].sAIHandlerPostTurn = "Doll Tutorial Patrol"
    gzTextVar.zEntities[i].sAIHandlerPrimary = "Doll Tutorial Patrol"
    gzTextVar.zEntities[i].iMoveIndex = -1
    gzTextVar.zEntities[i].iPatrolIndex = 1
    if(saPatrolList ~= nil) then
        gzTextVar.zEntities[i].saPatrolList = saPatrolList
        gzTextVar.zEntities[i].bMovesRandomly = false
    else
        gzTextVar.zEntities[i].saPatrolList = {"None"}
        gzTextVar.zEntities[i].bMovesRandomly = true
    end
    gzTextVar.zEntities[i].iStayStillTurns = 0
    gzTextVar.zEntities[i].sLastDoorDir = "P"
    gzTextVar.zEntities[i].sIndicatorName = gzTextVar.zEntities[i].sUniqueName
    gzTextVar.zEntities[i].sFirstSawPlayer = "Nowhere"
    gzTextVar.zEntities[i].sLastSawPlayer = "Nowhere"
    gzTextVar.zEntities[i].iChanceToForget = 20
    gzTextVar.zEntities[i].sInDisguise = "Null"

    --[Combat Properties]
    --Dolls lose HP and DPS as the difficulty goes down.
    gzTextVar.zEntities[i].zCombatTable = {}
    gzTextVar.zEntities[i].zCombatTable.bScalesWithPhase = true
    
    --Easy:
    if(gzTextVar.sDifficulty == "Easy") then
        local fTimeFactor = 2.00 + gzTextVar.fDollBonusSpd
        gzTextVar.zEntities[i].zCombatTable.iHealth = 27 + gzTextVar.iDollBonusHP
        gzTextVar.zEntities[i].zCombatTable.iAttacksTotal = 2
        gzTextVar.zEntities[i].zCombatTable.zAttacks = {}
        gzTextVar.zEntities[i].zCombatTable.zAttacks[1] = {100, 4 + gzTextVar.iDollBonusAtp, 300 * fTimeFactor, 0}
        gzTextVar.zEntities[i].zCombatTable.zAttacks[2] = {100, 5 + gzTextVar.iDollBonusAtp, 400 * fTimeFactor, 0}
    
    --Normal:
    elseif(gzTextVar.sDifficulty == "Normal") then
        local fTimeFactor = 1.00 + gzTextVar.fDollBonusSpd
        gzTextVar.zEntities[i].zCombatTable.iHealth = 35 + gzTextVar.iDollBonusHP
        gzTextVar.zEntities[i].zCombatTable.iAttacksTotal = 2
        gzTextVar.zEntities[i].zCombatTable.zAttacks = {}
        gzTextVar.zEntities[i].zCombatTable.zAttacks[1] = {100, 4 + gzTextVar.iDollBonusAtp, 400 * fTimeFactor, 0} --0.60 DPS
        gzTextVar.zEntities[i].zCombatTable.zAttacks[2] = {100, 6 + gzTextVar.iDollBonusAtp, 500 * fTimeFactor, 0} --0.72 DPS
    
    --Hard:
    else
        local fTimeFactor = 1.00 + gzTextVar.fDollBonusSpd
        gzTextVar.zEntities[i].zCombatTable.iHealth = 45 + gzTextVar.iDollBonusHP
        gzTextVar.zEntities[i].zCombatTable.iAttacksTotal = 2
        gzTextVar.zEntities[i].zCombatTable.zAttacks = {}
        gzTextVar.zEntities[i].zCombatTable.zAttacks[1] = {100, 4 + gzTextVar.iDollBonusAtp, 300 * fTimeFactor, 0} --0.80 DPS
        gzTextVar.zEntities[i].zCombatTable.zAttacks[2] = {100, 6 + gzTextVar.iDollBonusAtp, 400 * fTimeFactor, 0} --0.90 DPS
    end
    
    --Weaknesses. Dolls are weak to fire.
    gzTextVar.zEntities[i].zCombatTable.iaWeaknesses = {}
    gzTextVar.zEntities[i].zCombatTable.iaWeaknesses[gciElementSlot_Fire] = 1
    gzTextVar.zEntities[i].zCombatTable.iaWeaknesses[gciElementSlot_Water] = 0
    gzTextVar.zEntities[i].zCombatTable.iaWeaknesses[gciElementSlot_Wind] = 0
    gzTextVar.zEntities[i].zCombatTable.iaWeaknesses[gciElementSlot_Earth] = 0
    gzTextVar.zEntities[i].zCombatTable.iaWeaknesses[gciElementSlot_Life] = 0
    gzTextVar.zEntities[i].zCombatTable.iaWeaknesses[gciElementSlot_Death] = 0

    --[Indicator]
    --Determine tilesheet position based on doll type.
    local fX, fY, fZ = fnGetRoomPosition(gzTextVar.zEntities[i].sLocation)
    local iIndicatorX = 0
    if(iTypeRoll == 1) then
        iIndicatorX = 1
    elseif(iTypeRoll == 2) then
        iIndicatorX = 2
    elseif(iTypeRoll == 3) then
        iIndicatorX = 3
    elseif(iTypeRoll == 4) then
        iIndicatorX = 0
    elseif(iTypeRoll == 5) then
        iIndicatorX = 4
    else
        iIndicatorX = 5
    end
    
    --Spawn indicator.
    gzTextVar.zEntities[i].iIndicatorX = iIndicatorX
    gzTextVar.zEntities[i].iIndicatorY = 4
    gzTextVar.zEntities[i].iIndicatorC = ciCodeUnfriendly
    gzTextVar.zEntities[i].iIndicatorH = 0
    TL_SetProperty("Register Entity Indicator", fX, fY, fZ, gzTextVar.zEntities[i].sIndicatorName, gzTextVar.zEntities[i].iIndicatorX, gzTextVar.zEntities[i].iIndicatorY, gzTextVar.zEntities[i].iIndicatorC)
    
    --Determine Hostility
    if(gzTextVar.gzPlayer.sFormState == "Human") then
        gzTextVar.zEntities[i].iIndicatorH = 1
        TL_SetProperty("Modify Entity Indicator Hosility", fX, fY, fZ, gzTextVar.zEntities[i].sIndicatorName, ciHostilityX_Enemy, ciHostilityY_Enemy)
    end
    
    --Debug.
    --io.write("Spawned enemy correctly.\n")
end