--[ ===================================== Scenario Builder ====================================== ]
--In the interest of making every playthrough of Doll Manor just that little bit more inscrutable,
-- there are several combinations of item placement. Each of these is a scenario, set up in this file.
local iScenarioRoll = 1

--[Item Lookup Registration Function]
--Creates an item with the given properties.
local zaItemLookups = {}
local fnAddItemLookup = function(psStorageName, psDisplayName, psInternalName, psCallPath)
    if(psStorageName  == nil) then return end
    if(psDisplayName  == nil) then return end
    if(psInternalName == nil) then return end
    if(psCallPath     == nil) then return end
    local i = #zaItemLookups + 1
    zaItemLookups[i] = {}
    zaItemLookups[i].sStorageName  = psStorageName
    zaItemLookups[i].sDisplayName  = psDisplayName
    zaItemLookups[i].sInternalName = psInternalName
    zaItemLookups[i].sCallPath     = psCallPath
end
    
--[Equipment]
--Starting equipment. Equip this to the player right away.
gzTextVar.gzPlayer.zWeapon = {}
gzTextVar.gzPlayer.zWeapon.sUniqueName = "heavy stick"
gzTextVar.gzPlayer.zWeapon.sDisplayName = "heavy stick"
gzTextVar.gzPlayer.zWeapon.bCanBePickedUp = true
gzTextVar.gzPlayer.zWeapon.sHandlerScript = gzTextVar.sRootPath .. "Item Handlers/Weapons/Heavy Stick.lua"
gzTextVar.gzPlayer.zWeapon.bIsStackable = false
gzTextVar.gzPlayer.zWeapon.iStackSize = 1
gzTextVar.gzPlayer.zWeapon.iJournalPage = -1
gzTextVar.gzPlayer.zWeapon.bIsClaygirlTrapped = false
gzTextVar.gzPlayer.zWeapon.sClaygirlName = "Null"
gzTextVar.gzPlayer.zWeapon.saClaygirlList = {}

--[ ======================================= Item Lookups ======================================== ]
--These are lookups for how to spawn a specific item. The locations are stored in the Tiled files.

--[Tools and Consumables]
--Consumables
fnAddItemLookup("Potion",     "potion",     "potion",     gzTextVar.sRootPath .. "Item Handlers/ToolsConsumables/Health Potion.lua")
fnAddItemLookup("Save Glyph", "save glyph", "save glyph", gzTextVar.sRootPath .. "Item Handlers/ToolsConsumables/Save Glyph.lua")

--Tools
fnAddItemLookup("Scissors",         "scissors",         "scissors",         gzTextVar.sRootPath .. "Item Handlers/ToolsConsumables/Scissors.lua")
fnAddItemLookup("Blunted Scissors", "blunted scissors", "blunted scissors", gzTextVar.sRootPath .. "Item Handlers/ToolsConsumables/Blunted Scissors.lua")

--Crystal Pieces
fnAddItemLookup("Crystal Piece", "crystal piece", "crystal piece", gzTextVar.sRootPath .. "Item Handlers/ToolsConsumables/Crystal Piece.lua")

--Misc.
fnAddItemLookup("Love Letter",   "love letter",   "love letter",   gzTextVar.sRootPath .. "Item Handlers/ToolsConsumables/Love Letter.lua")
fnAddItemLookup("Broken Pistol", "broken pistol", "broken pistol", gzTextVar.sRootPath .. "Item Handlers/ToolsConsumables/Broken Pistol.lua")

--[Map Fragments]
--Picking up fragments adds to the map.
fnAddItemLookup("Map", "map", "map", gzTextVar.sRootPath .. "Item Handlers/MapPieces/Map.lua")
fnAddItemLookup("Map Piece 0", "map piece", "map piece", gzTextVar.sRootPath .. "Item Handlers/MapPieces/MapPieceSWHouse.lua")
fnAddItemLookup("Map Piece 1", "map piece", "map piece", gzTextVar.sRootPath .. "Item Handlers/MapPieces/MapPieceWManor.lua")
fnAddItemLookup("Map Piece 2", "map piece", "map piece", gzTextVar.sRootPath .. "Item Handlers/MapPieces/MapPieceCGardens.lua") --Dropped by Pygmalie
fnAddItemLookup("Map Piece 3", "map piece", "map piece", gzTextVar.sRootPath .. "Item Handlers/MapPieces/MapPieceChapel.lua")
fnAddItemLookup("Map Piece 4", "map piece", "map piece", gzTextVar.sRootPath .. "Item Handlers/MapPieces/MapPieceChapelRear.lua")
fnAddItemLookup("Map Piece 5", "map piece", "map piece", gzTextVar.sRootPath .. "Item Handlers/MapPieces/MapPieceMistyWoods.lua")
fnAddItemLookup("Map Piece 6", "map piece", "map piece", gzTextVar.sRootPath .. "Item Handlers/MapPieces/MapPieceBrewery.lua")

--[Keys]
--Used to unlock doors.
fnAddItemLookup("Small Key",   "small key",   "small key",   gzTextVar.sRootPath .. "Item Handlers/Keys/Small Key.lua")
fnAddItemLookup("Chapel Key",  "chapel key",  "chapel key",  gzTextVar.sRootPath .. "Item Handlers/Keys/Chapel Key.lua")
fnAddItemLookup("Heart Key",   "heart key",   "heart key",   gzTextVar.sRootPath .. "Item Handlers/Keys/Heart Key.lua") --Dropped by Pygmalie
fnAddItemLookup("Diamond Key", "diamond key", "diamond key", gzTextVar.sRootPath .. "Item Handlers/Keys/Diamond Key.lua")
fnAddItemLookup("Club Key",    "club key",    "club key",    gzTextVar.sRootPath .. "Item Handlers/Keys/Club Key.lua")
fnAddItemLookup("Spade Key",   "spade key",   "spade key",   gzTextVar.sRootPath .. "Item Handlers/Keys/Spade Key.lua")

--[Equipment]
--T1 Equipment (heavy stick not included)
fnAddItemLookup("Climber's Coat", "climber's coat", "climber's coat", gzTextVar.sRootPath .. "Item Handlers/Armors/Climbers Coat.lua")
fnAddItemLookup("Leather Jacket", "leather jacket", "leather jacket", gzTextVar.sRootPath .. "Item Handlers/Armors/Leather Jacket.lua")
fnAddItemLookup("Leather Gloves", "leather gloves", "leather gloves", gzTextVar.sRootPath .. "Item Handlers/Gloves/Leather Gloves.lua")

--T2 Equipment
fnAddItemLookup("Fire Poker", "fire poker", "fire poker", gzTextVar.sRootPath .. "Item Handlers/Weapons/Fire Poker.lua")
fnAddItemLookup("Pool Cue",   "pool cue",   "pool cue",   gzTextVar.sRootPath .. "Item Handlers/Weapons/Pool Cue.lua")
fnAddItemLookup("Table Leg",  "table leg",  "table leg",  gzTextVar.sRootPath .. "Item Handlers/Weapons/Table Leg.lua")
fnAddItemLookup("Torch",      "torch",      "torch",      gzTextVar.sRootPath .. "Item Handlers/Weapons/Torch.lua")

--T3 Equipment
fnAddItemLookup("Shortsword",    "shortsword",    "shortsword",    gzTextVar.sRootPath .. "Item Handlers/Weapons/Shortsword.lua")
fnAddItemLookup("Leather Armor", "leather armor", "leather armor", gzTextVar.sRootPath .. "Item Handlers/Armors/Leather Armor.lua")

--T4 Equipment
fnAddItemLookup("Enchanted Rapier",  "enchanted rapier",  "enchanted rapier",  gzTextVar.sRootPath .. "Item Handlers/Weapons/Enchanted Rapier.lua")
fnAddItemLookup("Salamander Gloves", "salamander gloves", "salamander gloves", gzTextVar.sRootPath .. "Item Handlers/Gloves/Salamander Gloves.lua")
fnAddItemLookup("Rusalka Gloves",    "rusalka gloves",    "rusalka gloves",    gzTextVar.sRootPath .. "Item Handlers/Gloves/Rusalka Gloves.lua")
fnAddItemLookup("Mora Gloves",       "mora gloves",       "mora gloves",       gzTextVar.sRootPath .. "Item Handlers/Gloves/Mora Gloves.lua")
fnAddItemLookup("Cerulis Gloves",    "cerulis gloves",    "cerulis gloves",    gzTextVar.sRootPath .. "Item Handlers/Gloves/Cerulis Gloves.lua")
fnAddItemLookup("Mail Vest",         "mail vest",         "mail vest",         gzTextVar.sRootPath .. "Item Handlers/Armors/Mail Vest.lua")

--Eileen's Equipment
fnAddItemLookup("Twinblade",    "twinblade",    "twinblade",    gzTextVar.sRootPath .. "Item Handlers/Weapons/Twinblade.lua")
fnAddItemLookup("Feather Coat", "feather coat", "feather coat", gzTextVar.sRootPath .. "Item Handlers/Armors/Feather Coat.lua")

--[Books]
--Storybooks, provide details about the world.
fnAddItemLookup("Blue Storybook",   "blue storybook",   "blue storybook",   gzTextVar.sRootPath .. "Item Handlers/Books/Blue Storybook.lua")
fnAddItemLookup("White Storybook",  "white storybook",  "white storybook",  gzTextVar.sRootPath .. "Item Handlers/Books/White Storybook.lua")
fnAddItemLookup("Red Storybook",    "red storybook",    "red storybook",    gzTextVar.sRootPath .. "Item Handlers/Books/Red Storybook.lua")
fnAddItemLookup("Orange Storybook", "orange storybook", "orange storybook", gzTextVar.sRootPath .. "Item Handlers/Books/Orange Storybook.lua")

--[Fakes]
--Look the same as normal items, but trigger the claygirl house trap!
fnAddItemLookup("Fake Potion",           "potion",           "potion",           gzTextVar.sRootPath .. "Item Handlers/Fakes/Fake Health Potion.lua")
fnAddItemLookup("Fake Enchanted Rapier", "enchanted rapier", "enchanted rapier", gzTextVar.sRootPath .. "Item Handlers/Fakes/Fake Enchanted Rapier.lua")
fnAddItemLookup("Fake Mail Vest",        "mail vest",        "mail vest",        gzTextVar.sRootPath .. "Item Handlers/Fakes/Fake Mail Vest.lua")

--[Cards]
fnAddItemLookup("Card Sleeve", "card sleeve", "card sleeve", gzTextVar.sRootPath .. "Item Handlers/Cards/Card Sleeve.lua")
fnAddItemLookup("Water Card",  "water card",  "water card",  gzTextVar.sRootPath .. "Item Handlers/Cards/Water Card.lua")
fnAddItemLookup("Fire Card",   "fire card",   "fire card",   gzTextVar.sRootPath .. "Item Handlers/Cards/Fire Card.lua")
fnAddItemLookup("Wind Card",   "wind card",   "wind card",   gzTextVar.sRootPath .. "Item Handlers/Cards/Wind Card.lua")
fnAddItemLookup("Earth Card",  "earth card",  "earth card",  gzTextVar.sRootPath .. "Item Handlers/Cards/Earth Card.lua")
fnAddItemLookup("Life Card",   "life card",   "life card",   gzTextVar.sRootPath .. "Item Handlers/Cards/Life Card.lua")
fnAddItemLookup("Death Card",  "death card",  "death card",  gzTextVar.sRootPath .. "Item Handlers/Cards/Death Card.lua")

--[Eileen's Testament]
fnAddItemLookup("Testament 0", "testament", "testament", gzTextVar.sRootPath .. "Item Handlers/Eileen/Testament 0.lua")
fnAddItemLookup("Testament 1", "testament", "testament", gzTextVar.sRootPath .. "Item Handlers/Eileen/Testament 1.lua")
fnAddItemLookup("Testament 2", "testament", "testament", gzTextVar.sRootPath .. "Item Handlers/Eileen/Testament 2.lua")
fnAddItemLookup("Testament 3", "testament", "testament", gzTextVar.sRootPath .. "Item Handlers/Eileen/Testament 3.lua")
fnAddItemLookup("Testament 4", "testament", "testament", gzTextVar.sRootPath .. "Item Handlers/Eileen/Testament 4.lua")
fnAddItemLookup("Testament 5", "testament", "testament", gzTextVar.sRootPath .. "Item Handlers/Eileen/Testament 5.lua")
fnAddItemLookup("Testament 6", "testament", "testament", gzTextVar.sRootPath .. "Item Handlers/Eileen/Testament 6.lua")
fnAddItemLookup("Testament 7", "testament", "testament", gzTextVar.sRootPath .. "Item Handlers/Eileen/Testament 7.lua")
fnAddItemLookup("Testament 8", "testament", "testament", gzTextVar.sRootPath .. "Item Handlers/Eileen/Testament 8.lua")

--[Tutorial Notes]
--These only actually exist in the tutorial, and will not appear during normal play.
fnAddItemLookup("Tutorial Note 0", "note", "note", gzTextVar.sRootPath .. "Item Handlers/Tutorial/Tutorial Note 0.lua")
fnAddItemLookup("Tutorial Note 1", "note", "note", gzTextVar.sRootPath .. "Item Handlers/Tutorial/Tutorial Note 1.lua")
fnAddItemLookup("Tutorial Note 2", "note", "note", gzTextVar.sRootPath .. "Item Handlers/Tutorial/Tutorial Note 2.lua")
fnAddItemLookup("Tutorial Note 3", "note", "note", gzTextVar.sRootPath .. "Item Handlers/Tutorial/Tutorial Note 3.lua")
fnAddItemLookup("Tutorial Note 4", "note", "note", gzTextVar.sRootPath .. "Item Handlers/Tutorial/Tutorial Note 4.lua")
fnAddItemLookup("Tutorial Note 5", "note", "note", gzTextVar.sRootPath .. "Item Handlers/Tutorial/Tutorial Note 5.lua")
fnAddItemLookup("Tutorial Note 6", "note", "note", gzTextVar.sRootPath .. "Item Handlers/Tutorial/Tutorial Note 6.lua")
fnAddItemLookup("Tutorial Note 7", "note", "note", gzTextVar.sRootPath .. "Item Handlers/Tutorial/Tutorial Note 7.lua")
fnAddItemLookup("Tutorial Note 8", "note", "note", gzTextVar.sRootPath .. "Item Handlers/Tutorial/Tutorial Note 8.lua")
fnAddItemLookup("Tutorial Note 9", "note", "note", gzTextVar.sRootPath .. "Item Handlers/Tutorial/Tutorial Note 9.lua")
fnAddItemLookup("Turn Mode",       "note", "note", gzTextVar.sRootPath .. "Item Handlers/Tutorial/Combat Note Turn.lua")
fnAddItemLookup("Active Mode",     "note", "note", gzTextVar.sRootPath .. "Item Handlers/Tutorial/Combat Note Active.lua")

--Set this flag to indicate script calls are building item info.
gzTextVar.bIsBuildingIndicatorInfo = true

--[ ====================================== Item Placement ======================================= ]
--Iterate across all the location packages and build scenario items/locations as needed.
local iIndex = 0
local iItemLookupsTotal = #zaItemLookups
while(true) do
    
    --Get the location index.
    local sItemType = TL_GetProperty("Location Type", iIndex)
    local sRoomName = TL_GetProperty("Location Room Name", iIndex)
    if(sItemType == "Null" or sRoomName == "Null") then
        
        --If the item type is not null, but the room is, print a warning. This means an item was out-of-bounds.
        if(sItemType ~= "Null" and sRoomName == "Null") then
            io.write("Warning: Item " .. iIndex .. " - " .. sItemType .. " was in a null room.\n")
        end
        break
    end
    
    --Scan against the item types.
    local bHandled = false
    for i = 1, iItemLookupsTotal, 1 do
        if(zaItemLookups[i].sStorageName == sItemType) then
            
            --Object registration.
            fnRegisterObject(sRoomName, zaItemLookups[i].sDisplayName, zaItemLookups[i].sInternalName, true, zaItemLookups[i].sCallPath)
            
            --Stop iterating.
            break
        end
    end
    
    --If the type is "Flee Location", add it as a location Jessie and Lauren can flee to if Mary is TF'd.
    if(sItemType == "Flee Location") then
        fnAddFleeLocation(sRoomName)
    
    --If the first few letters spell "Journal", this is a numbered journal entry.
    elseif(string.sub(sItemType, 1, 7) == "Journal") then
        local iPageNumber = tonumber(string.sub(sItemType, 9))
        fnCreateJournalPage(sRoomName, iPageNumber)
    
    --Mary Initial, where the player starts.
    elseif(sItemType == "Mary Initial") then
        gzTextVar.gzPlayer.sLocation = sRoomName
        gzTextVar.gzPlayer.sPrevLocation = sRoomName
        local fX, fY, fZ = fnGetRoomPosition(gzTextVar.gzPlayer.sLocation)
        TL_SetProperty("Player World Position", fX, fY, fZ)
        
    --Jessie Initial, where Jessie spawns,
    elseif(sItemType == "Jessie Initial") then
        local sOldLocation = gzTextVar.zEntities[gzTextVar.iJessieIndex].sLocation
        gzTextVar.zEntities[gzTextVar.iJessieIndex].sLocation = sRoomName
        local fOldX, fOldY, fOldZ = fnGetRoomPosition(sOldLocation)
        local fNewX, fNewY, fNewZ = fnGetRoomPosition(sRoomName)
        TL_SetProperty("Move Entity Indicator", fOldX, fOldY, fOldZ, gzTextVar.zEntities[gzTextVar.iJessieIndex].sIndicatorName, fNewX, fNewY, fNewZ)
        
    --Lauren Initial, where Lauren spawns,
    elseif(sItemType == "Lauren Initial") then
        local sOldLocation = gzTextVar.zEntities[gzTextVar.iLaurenIndex].sLocation
        gzTextVar.zEntities[gzTextVar.iLaurenIndex].sLocation = sRoomName
        local fOldX, fOldY, fOldZ = fnGetRoomPosition(sOldLocation)
        local fNewX, fNewY, fNewZ = fnGetRoomPosition(sRoomName)
        TL_SetProperty("Move Entity Indicator", fOldX, fOldY, fOldZ, gzTextVar.zEntities[gzTextVar.iLaurenIndex].sIndicatorName, fNewX, fNewY, fNewZ)
    
    --Eileen.
    elseif(sItemType == "Eileen Initial") then
        local sOldLocation = gzTextVar.zEntities[gzTextVar.iEileenIndex].sLocation
        gzTextVar.zEntities[gzTextVar.iEileenIndex].sLocation = sRoomName
        local fOldX, fOldY, fOldZ = fnGetRoomPosition(sOldLocation)
        local fNewX, fNewY, fNewZ = fnGetRoomPosition(sRoomName)
        TL_SetProperty("Move Entity Indicator", fOldX, fOldY, fOldZ, gzTextVar.zEntities[gzTextVar.iEileenIndex].sIndicatorName, fNewX, fNewY, fNewZ)
    
    end
    
    --Next.
    iIndex = iIndex + 1
end

--Unset this flag.
gzTextVar.bIsBuildingIndicatorInfo = false

--[Items for Claygirls]
--List of items that Claygirls can disguise themselves as.
gzTextVar.saClaygirlDisguises = {"climber's coat", "leather gloves", "fire poker", "table leg", "shortsword", "leather armor", "enchanted rapier", "salamander gloves", "rusalka gloves", "mora gloves", "cerulis gloves", "mail vest", "potion"}
gzTextVar.iClaygirlDisguisesTotal = #gzTextVar.saClaygirlDisguises

--[Variable Key]
--Set which key Pygmalie will drop.
gzTextVar.sPygmalieKey = "Heart Key"

--[ ====================================== Enemy Placement ====================================== ]
--Respawn list uses sets of coordinates to spawn entities. These are chunked into strings to make them easier to read.
gzTextVar.zRespawnList = {}

--Iterate across all paths and load them into the respawn lists.
local iPath = 0
local i = 0
while(true) do
    
    --Get this path's variables. If either comes back "Null", this path is invalid.
    local sPathIdentity  = TL_GetProperty("Pathnode Identity", iPath)
    local sPathEnemyType = TL_GetProperty("Pathnode Type", iPath)
    if(sPathIdentity == "Null" or sPathEnemyType == "Null") then break end
    
    --The zeroth path node needs to exist or the entry is invalid.
    local sZerothPathNode = TL_GetProperty("Pathnode Position", iPath, 0)
    if(sZerothPathNode == "Null") then break end
    
    --Add a new respawn entry.
    i = i + 1
    gzTextVar.zRespawnList[i] = {}
    gzTextVar.zRespawnList[i].sIdentity = sPathIdentity
    gzTextVar.zRespawnList[i].sEnemyType = sPathEnemyType
    gzTextVar.zRespawnList[i].bIsActive = false
    gzTextVar.zRespawnList[i].iRespawnTimer = 0
    gzTextVar.zRespawnList[i].sSpawnPosition = sZerothPathNode
    gzTextVar.zRespawnList[i].sPatrolPath = {sZerothPathNode}
    
    --Begin adding path nodes. First slot is already occupied.
    local p = 1
    while(true) do
        
        --Get the node.
        local sPathNode = TL_GetProperty("Pathnode Position", iPath, p)
        
        --Node comes back null, so that was the last one. Stop.
        if(sPathNode == "Null") then
            break
        
        --Add it to the end of the list.
        else
            p = p + 1
            gzTextVar.zRespawnList[i].sPatrolPath[p] = sPathNode
        end
    end
    
    --Next.
    iPath = iPath + 1
end

--[Debug]
if(false) then
    i = 1
    while(true) do
        if(gzTextVar.zRespawnList[i] == nil) then break end
        io.write("Path " .. i .. " is " .. gzTextVar.zRespawnList[i].sIdentity .. "\n")
        io.write(" Node listing:\n")
        local p = 1
        while(true) do
            if(gzTextVar.zRespawnList[i].sPatrolPath[p] == nil) then break end
            io.write(p .. ": " .. gzTextVar.zRespawnList[i].sPatrolPath[p] .. "\n")
            p = p + 1
        end
        io.write("\n")
        
        i = i + 1
    end
end


--[Tutorial]
--Spawn the tutorial enemies.
if(gzTextVar.sManorType == "Tutorial") then
    fnSpawnDollSentry("Evade Hall C", "Tutorial Doll A", nil)
    fnSpawnDollSentryCombat("Combat Hall C", "Tutorial Doll B", nil)
    fnSpawnDollSentryCombatB("Combat Sample Hall N", "Tutorial Doll C", nil)
    fnSpawnDollTutPatrol("Stealth Area E", "Tutorial Doll D", {"Stealth Area E", "Stealth Area H", "Stealth Area V", "Stealth Area S"})

--[Small Manor]
--Spawn the phase 1 enemies.
elseif(gzTextVar.sManorType == "Demo" or gzTextVar.sManorType == "Simple") then
    for i = 1, #gzTextVar.zRespawnList, 1 do
        if(gzTextVar.zRespawnList[i].sIdentity == "Doll A" or gzTextVar.zRespawnList[i].sIdentity == "Doll B" or gzTextVar.zRespawnList[i].sIdentity == "Doll C") then
            gzTextVar.zRespawnList[i].bIsActive = true
            fnSpawnDoll(gzTextVar.zRespawnList[i].sSpawnPosition, gzTextVar.zRespawnList[i].sIdentity, gzTextVar.zRespawnList[i].sPatrolPath)
        end
    end

--[Normal Manor]
--Spawn the phase 1 enemies.
elseif(gzTextVar.sManorType == "Normal") then
    for i = 1, #gzTextVar.zRespawnList, 1 do
        local sID = gzTextVar.zRespawnList[i].sIdentity
        if(sID == "Doll A" or sID == "Doll B" or sID == "Doll C" or sID == "Doll D" or sID == "Doll E") then
            --io.write("Spawned enemy " .. sID .. "\n")
            gzTextVar.zRespawnList[i].bIsActive = true
            fnSpawnDoll(gzTextVar.zRespawnList[i].sSpawnPosition, gzTextVar.zRespawnList[i].sIdentity, gzTextVar.zRespawnList[i].sPatrolPath)
        end
    end
end

--[ ================================= Strangers Patrol Pattern ================================== ]
--Create a list of all groupings.
gzTextVar.zStranger = {}
gzTextVar.zStranger.sImgPath = "Root/Images/DollManor/Characters/Stranger0"
gzTextVar.zStranger.iNeedsRespawn = 0
gzTextVar.zStranger.sPlayerPreviousGrouping = "None"
gzTextVar.zStranger.sPlayerCurrentGrouping = "None"
gzTextVar.zStranger.saGroupList = {"South Floor C", "South Floor E", "South Floor W", "South Gardens", "Gardens C", "Misty Woods", "Chapel Floor", "Chapel Rear", "Gardens W", "West Floor W", "West Floor E", "Basement", "2F West", "2F South E", "2F North"}

--For each grouping, create a group table.
gzTextVar.zStranger.zGroups = {}
for i = 1, #gzTextVar.zStranger.saGroupList, 1 do
    
    gzTextVar.zStranger.zGroups[i] = {}
    gzTextVar.zStranger.zGroups[i].sGrouping = gzTextVar.zStranger.saGroupList[i]
    gzTextVar.zStranger.zGroups[i].iEntriesMax = 0
    gzTextVar.zStranger.zGroups[i].saRooms = {}
    
end

--Iterate across the groupings.
iIndex = 0
while(true) do
    
    --Get the data. It will be "Null" when we're done iterating.
    local sType = TL_GetProperty("Location Type", iIndex)
    local sRoomName = TL_GetProperty("Location Room Name", iIndex)
    if(sItemType == "Null" or sRoomName == "Null") then break end
    
    --Make sure it's of the matching type.
    if(string.sub(sType, 1, 16) == "Stranger Search|") then
    
        --Next, get the grouping. The last two letters are "|A" or whatever the index is.
        local sGroupString = string.sub(sType, 17, -3)
        local sIndexString = string.sub(sType, -1)
        --io.write("Group String: " .. sGroupString .. " Index: " .. sIndexString .. "\n")
    
        --Check across the groupings.
        for i = 1, #gzTextVar.zStranger.saGroupList, 1 do
            if(sGroupString == gzTextVar.zStranger.saGroupList[i]) then
            
                --Get the index. It must be between 0 and 25.
                local iLetterIndex = string.byte(sIndexString, 1) - 65
                if(iLetterIndex >= 0 and iLetterIndex <= 25) then
                
                    --If this is higher than the current max entries, expand that.
                    if(iLetterIndex > gzTextVar.zStranger.zGroups[i].iEntriesMax) then
                        gzTextVar.zStranger.zGroups[i].iEntriesMax = iLetterIndex
                    end
                    
                    --Store the room name.
                    gzTextVar.zStranger.zGroups[i].saRooms[iLetterIndex] = sRoomName
                end
                break
            end
        end
    end

    --Next.
    iIndex = iIndex + 1
end

--Once all the entries are stored, iterate across the groups and fill any gaps.
for i = 1, #gzTextVar.zStranger.saGroupList, 1 do
    for p = 1, gzTextVar.zStranger.zGroups[i].iEntriesMax, 1 do
        if(gzTextVar.zStranger.zGroups[i].saRooms[p] == nil) then
            --io.write(" Missing entry " .. gzTextVar.zStranger.zGroups[i].sGrouping .. " " .. p .. "\n")
        end
    end
    --io.write("Grouping " .. gzTextVar.zStranger.zGroups[i].sGrouping .. " has " .. gzTextVar.zStranger.zGroups[i].iEntriesMax .. " entries.\n")
end

--[ ======================================= Item Movement ======================================= ]
--The "Normal" manor has one of the crystal pieces be placed in three possible locations at random.
-- In fact, crystals spawn in all three possible locations, and we just remove two.
if(gzTextVar.sManorType == "Normal") then
    
    --Setup.
    local sRemoveA = "Null"
    local sRemoveB = "Null"
    
    --Roll.
    local iRoll = LM_GetRandomNumber(1, 3)
    if(iRoll == 1) then
        sRemoveA = "Crystal Altar C"
        sRemoveB = "Crystal Altar D"
    elseif(iRoll == 2) then
        sRemoveA = "Crystal Altar D"
        sRemoveB = "Crystal Altar E"
    else
        sRemoveA = "Crystal Altar C"
        sRemoveB = "Crystal Altar E"
    end
    
    --Remove the two crystals. They should be the only items in the named rooms.
    local iIndexA = fnGetRoomIndex(sRemoveA)
    local iIndexB = fnGetRoomIndex(sRemoveB)
    fnRemoveItemFromRoom(iIndexA, 1)
    fnRemoveItemFromRoom(iIndexB, 1)
    
end

--[ =========================================== Debug =========================================== ]
--Spawn a potion and put a claygirl on it.
if(gzTextVar.sManorType == "Tutorial") then
    --fnRegisterObject("Entryway", "potion", "potion", true, gzTextVar.sRootPath .. "Item Handlers/ToolsConsumables/Health Potion.lua")
    --fnSpawnClayGirl("Trap Claygirl")
end

--[ ======================================== Door States ======================================== ]
--Some of the doors start the game open. Do that here.
if(gzTextVar.sManorType == "Normal") then
    LM_ExecuteScript(gzTextVar.sRootPath .. "Functions/Modify Door State.lua", "Curious House Junction", "O Normal", "N", ciModifyVisibility, 0)
    LM_ExecuteScript(gzTextVar.sRootPath .. "Functions/Modify Door State.lua", "Curious House Hall SW",  "O Normal", "W", ciModifyVisibility, 0)
    LM_ExecuteScript(gzTextVar.sRootPath .. "Functions/Modify Door State.lua", "Curious House Hall NW",  "O Normal", "N", ciModifyVisibility, 0)
    LM_ExecuteScript(gzTextVar.sRootPath .. "Functions/Modify Door State.lua", "Main Hall NE",           "O Normal", "N", ciModifyVisibility, 0)
    LM_ExecuteScript(gzTextVar.sRootPath .. "Functions/Modify Door State.lua", "Western Guest Room SE",  "O Normal", "N", ciModifyVisibility, 0)
end

--[ ======================================= Player's Map ======================================== ]
--These variables store which map layers are activated. It's parallel the map references.
gzTextVar.gzPlayer.baMapLayers = {}
gzTextVar.gzPlayer.baMapLayers[ 1] = {"Base",          true}
gzTextVar.gzPlayer.baMapLayers[ 2] = {"ClayHouse",     false}
gzTextVar.gzPlayer.baMapLayers[ 3] = {"SouthGardens",  true}
gzTextVar.gzPlayer.baMapLayers[ 4] = {"SouthManor",    true}
gzTextVar.gzPlayer.baMapLayers[ 5] = {"WestManor",     false}
gzTextVar.gzPlayer.baMapLayers[ 6] = {"CenterGardens", false}
gzTextVar.gzPlayer.baMapLayers[ 7] = {"MistyWoods",    false}
gzTextVar.gzPlayer.baMapLayers[ 8] = {"Chapel",        false}
gzTextVar.gzPlayer.baMapLayers[ 9] = {"ChapelRear",    false}
gzTextVar.gzPlayer.baMapLayers[10] = {"Brewery",       false}

--Crossload all the map references.
TL_SetProperty("Register Map Layer", "Base",          0, "Root/Images/DollManor/MapLayers/Base")
TL_SetProperty("Register Map Layer", "ClayHouse",     1, "Root/Images/DollManor/MapLayers/Layer00")
TL_SetProperty("Register Map Layer", "SouthGardens",  2, "Root/Images/DollManor/MapLayers/Layer01")
TL_SetProperty("Register Map Layer", "SouthManor",    3, "Root/Images/DollManor/MapLayers/Layer02")
TL_SetProperty("Register Map Layer", "WestManor",     4, "Root/Images/DollManor/MapLayers/Layer03")
TL_SetProperty("Register Map Layer", "CenterGardens", 5, "Root/Images/DollManor/MapLayers/Layer04")
TL_SetProperty("Register Map Layer", "MistyWoods",    6, "Root/Images/DollManor/MapLayers/Layer05")
TL_SetProperty("Register Map Layer", "Chapel",        7, "Root/Images/DollManor/MapLayers/Layer06")
TL_SetProperty("Register Map Layer", "ChapelRear",    8, "Root/Images/DollManor/MapLayers/Layer07")
TL_SetProperty("Register Map Layer", "Brewery",       9, "Root/Images/DollManor/MapLayers/Layer08")

--Activate all the map layers the map starts knowing about.
for i = 1, #gzTextVar.gzPlayer.baMapLayers, 1 do
    TL_SetProperty("Set Layer Visible", gzTextVar.gzPlayer.baMapLayers[i][1], gzTextVar.gzPlayer.baMapLayers[i][2])
end

--[ ========================================= Finish Up ========================================= ]
--Rebuild local info.
fnRebuildEntityVisibility()
fnBuildLocalityInfo()

--Clean up temporary data.
TL_SetProperty("Purge Temp Data")

--Run the options post-exec to make sure any variables from the menu got set.
LM_ExecuteScript(fnResolvePath() .. "997 Options PostExec.lua")
