--[ ======================================= Input Handler ======================================= ]
--Whenever the player inputs a string, this script gets called to handle it. Anything that handles
-- the input should return afterwards. If nothing handles the input, then an error message is shown.

--Argument Listing:
-- 0: sString - The string to be handled. Should be in all lowercase.

--Arg check.
local iRequiredArgs = 1
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 sString = LM_GetScriptArgument(0)

--Don't do anything if the string is empty.
if(sString == "") then return end

--Others.
local iRoom = fnGetRoomIndex(gzTextVar.gzPlayer.sLocation)
if(iRoom == -1) then return end

--[ ====================================== Save Overwrite ======================================= ]
if(gzTextVar.bIsSaveOverwrite == true) then
    
    --Execute overwrite.
    if(sString == "y" or sString == "yes") then
        
        --Text.
        if(gzTextVar.bIsUsingSaveGlyph == true) then
            
            --Text changes based on what we're doing.
            if(gzTextVar.bIsSaveGlyphUsingNotOverwrite == true) then
                TL_SetProperty("Append", "Wrote savefile. The [save glyph] crumbles to dust in your hands..." .. gsDE)
            else
                TL_SetProperty("Append", "Overwrote savefile. The [save glyph] crumbles to dust in your hands..." .. gsDE)
            end
            
            --Remove the glyph.
            for i = 1, gzTextVar.gzPlayer.iItemsTotal, 1 do
                if(gzTextVar.gzPlayer.zaItems[i].sUniqueName == "save glyph") then
                    fnRemoveItemFromInventory(i)
                    break
                end
            end
            
            --Update the locality window.
            fnBuildLocalityInfo()
        else
            TL_SetProperty("Append", "Overwrote savefile." .. gsDE)
        end
        
        --Save the game *after* the glyph is removed.
        gzTextVar.bIsSaveOverwrite = false
        TL_Save(gzTextVar.sSaveOverwritePath)
    
    --Cancel.
    else
        gzTextVar.bIsSaveOverwrite = false
        gzTextVar.sSaveOverwritePath = "Null"
        TL_SetProperty("Append", "Canceled save." .. gsDE)
    end
    
    --Clear all flags.
    gzTextVar.bIsUsingSaveGlyph = false
    gzTextVar.bIsSaveGlyphUsingNotOverwrite = false
    
    return
end

--[ =========================================== Common ========================================== ]
--Common functionality goes here.
if(sString == "exit" or sString == "quit") then
    TL_SetProperty("Append", "Exiting program...")
    
    --In "one-game" mode, exit the game entirely.
    if(gbIsOneGameMode == true) then
        Game_Quit()
        
    --Otherwise, go back to the game select.
    else
        MapM_BackToTitle()
    end
    return
end

--Restart. Attempts to reboot the scenario.
if(sString == "restart") then
    LM_ExecuteScript(gzTextVar.sRootPath .. "998 Exec Restart.lua")
    return
end

--Show saves, shows the last X savefiles.
if(sString == "show saves") then
    
    --Populate saves data.
    local saSavePaths = {}
    local iRecentSavesTotal = TL_GetSaveFileList("Saves/")
    if(iRecentSavesTotal > 20) then iRecentSavesTotal = 20 end
    
    --No saves found.
    if(iRecentSavesTotal == 0) then
        TL_SetProperty("Append", "No savefiles detected in the Saves/ directory." .. gsDE)
    
    --One savefile.
    elseif(iRecentSavesTotal == 1) then
        TL_SetProperty("Append", "Most recent savefile: [" .. TL_GetProperty("Save Path At", 0) .. "]." .. gsDE)
    
    --Two savefiles.
    elseif(iRecentSavesTotal == 2) then
        TL_SetProperty("Append", "Most recent savefiles: [" .. TL_GetProperty("Save Path At", 0) .. "] and [" .. TL_GetProperty("Save Path At", 1) .. "]." .. gsDE)
    
    --More savefiles.
    else
        --String.
        local sString = iRecentSavesTotal .. " most recent savefiles: "

        for i = 1, iRecentSavesTotal-1, 1 do
            
            --Get the save.
            local sPath = "[" .. TL_GetProperty("Save Path At", i-1) .. "]"
            
            --Append.
            sString = sString .. sPath .. ", "
        end

        --Last savefile.
        sString = sString .. "and [" .. TL_GetProperty("Save Path At", iRecentSavesTotal-1) .. "]." .. gsDE
        TL_SetProperty("Append", sString)
    end
    return
end
    
--Save. Saves the game, obviously.
if(string.sub(sString, 1, 4) == "save") then
    
    --Name of save.
    local sNameOfSave = string.sub(sString, 6)
    
    --If the player is in the tutorial, they cannot save the game.
    if(gzTextVar.sManorType == "Tutorial") then
        TL_SetProperty("Append", "You cannot save the game during the tutorial." .. gsDE)
        return
    end
    
    --Reset this flag.
    gzTextVar.bIsUsingSaveGlyph = false
    gzTextVar.bIsSaveGlyphUsingNotOverwrite = false
    
    --If the save-anywhere flag is false, the player needs to be at a fountain to save.
    if(gzTextVar.bAllowSaveAnywhere == false) then
        
        --Check the player's current location using a state machine flag. The fountains are set to toggle it.
        gzTextVar.bIsAtSaveLocation = false
        gzTextVar.bIsStateCheckingSave = true
        LM_ExecuteScript(gzTextVar.sRoomHandlers .. gzTextVar.gzPlayer.sLocation .. ".lua", "Dummy Save Check")
        gzTextVar.bIsStateCheckingSave = false
        
        --If not allowed to save here, fail.
        if(gzTextVar.bIsAtSaveLocation == false) then
            
            --Check if the player has at least one Save Glyph in their inventory. This allows them to save, but is used up.
            local bHasASaveGlyph = false
            for i = 1, gzTextVar.gzPlayer.iItemsTotal, 1 do
                if(gzTextVar.gzPlayer.zaItems[i].sUniqueName == "save glyph") then
                    bHasASaveGlyph = true
                    break
                end
            end
            
            --No save glyphs, not at a fountain.
            if(bHasASaveGlyph == false) then
                TL_SetProperty("Append", "You need to be at a fountain to save your game, or have a [save glyph] in your inventory." .. gsDE)
                return
            
            --Has a save glyph.
            else
                gzTextVar.bIsUsingSaveGlyph = true
            
            end
            
        end
    end
    
    --Error check.
    if(string.len(sNameOfSave) < 1) then
        TL_SetProperty("Append", "Please enter a name for the save file. Example: [save mary] or [save mygame]. Enter [show saves] to see a list of savefiles." .. gsDE)
        
    --Since 'cancel' is how the user backs out of loading a game on the main menu, you can't save as that.
    elseif(sNameOfSave == "cancel") then
        TL_SetProperty("Append", "That is a reserved word. Please select another name." .. gsDE)
        
    --Jerk!
    elseif(sNameOfSave == "saltysucks") then
        TL_SetProperty("Append", "No I don't!" .. gsDE)
    
    --All checks passed, save it.
    else
    
        --If the name already exists, ask the player to overwrite it.
        if(FS_Exists("Saves/" .. sNameOfSave .. ".tls") == true) then
            gzTextVar.bIsSaveOverwrite = true
            gzTextVar.sSaveOverwritePath = "Saves/" .. sNameOfSave .. ".tls"
            
            --No save glyph:
            if(gzTextVar.bIsUsingSaveGlyph == false) then
                TL_SetProperty("Append", "File already exists. Overwrite? (y/n)" .. gsDE)
            
            --Save glyph:
            else
                TL_SetProperty("Append", "This will consume a [save glyph]. File already exists. Overwrite? (y/n)" .. gsDE)
            end
        
        --File does not exist, but we're using a save glyph up.
        elseif(gzTextVar.bIsUsingSaveGlyph == true) then
            TL_SetProperty("Append", "This will consume a [save glyph]. Proceed? (y/n)" .. gsDE)
            gzTextVar.bIsSaveOverwrite = true
            gzTextVar.bIsSaveGlyphUsingNotOverwrite = true
            gzTextVar.sSaveOverwritePath = "Saves/" .. sNameOfSave .. ".tls"
        
        --Just write the save.
        else
            TL_Save("Saves/" .. sNameOfSave .. ".tls")
            TL_SetProperty("Append", "Wrote save file. Enter [show saves] to see a list of savefiles." .. gsDE)
        end
    end
    return
end

--Load. Loads the game, calls an external script.
if(string.sub(sString, 1, 4) == "load") then
    
    --Name of savefile.
    local sNameOfSave = string.sub(sString, 6)
    if(string.len(sNameOfSave) < 1) then
        TL_SetProperty("Append", "Please enter a name for the save file to load from." .. gsDE)
        
        --Populate saves data.
        local saSavePaths = {}
        local iRecentSavesTotal = TL_GetSaveFileList("Saves/")
        
        --No saves found.
        if(iRecentSavesTotal == 0) then
            TL_SetProperty("Append", "No savefiles detected in the Saves/ directory." .. gsDE)
        
        --One savefile.
        elseif(iRecentSavesTotal == 1) then
            TL_SetProperty("Append", "Most recent savefile: " .. TL_GetProperty("Save Path At", 0) .. "." .. gsDE)
        
        --Two savefiles.
        elseif(iRecentSavesTotal == 2) then
            TL_SetProperty("Append", "Most recent savefiles: " .. TL_GetProperty("Save Path At", 0) .. " and " .. TL_GetProperty("Save Path At", 1) .. "." .. gsDE)
        
        --Three or more.
        else
        
            --String.
            local sString = "Most recent savefiles: "
        
            for i = 1, iRecentSavesTotal-1, 1 do
                
                --Get the save.
                local sPath = TL_GetProperty("Save Path At", i-1)
                
                --Append.
                sString = sString .. sPath .. ", "
            end
        
            --Last savefile.
            sString = sString .. "and " .. TL_GetProperty("Save Path At", iRecentSavesTotal-1) .. "." .. gsDE
            TL_SetProperty("Append", sString)
        end
        
    else
        LM_ExecuteScript(gzTextVar.sRootPath .. "Functions/Load Game.lua", sNameOfSave)
    end
    return
end

--[ ======================================= System Inputs ======================================= ]
--These inputs ignore things like turn priority and are used for displaying help or setting options.
-- First is help, which explains how to play the game.
gbHandledInput = false
LM_ExecuteScript(gzTextVar.sRootPath .. "120 Help.lua", sString)
if(gbHandledInput == true) then return end

--Options commands.
LM_ExecuteScript(gzTextVar.sRootPath .. "130 Options.lua", sString)
if(gbHandledInput == true) then return end

--Think shows the player their current objectives.
if(sString == "think" or sString == "t") then
    LM_ExecuteScript(gzTextVar.sThinkHandler)
    return
end

--Show the player's inventory.
if(sString == "inventory" or sString == "i") then
    
    --Player has nothing in their inventory.
    if(gzTextVar.gzPlayer.iItemsTotal == 0) then
        TL_SetProperty("Append", "You are not carrying anything." .. gsDE)
    
    --Player has one object in their inventory:
    elseif(gzTextVar.gzPlayer.iItemsTotal == 1) then
        TL_SetProperty("Append", "You are carrying [" .. gzTextVar.gzPlayer.zaItems[1].sDisplayName .. "]." .. gsDE)
    
    --Two objects.
    elseif(gzTextVar.gzPlayer.iItemsTotal == 2) then
        TL_SetProperty("Append", "You are carrying [" .. gzTextVar.gzPlayer.zaItems[1].sDisplayName .. "] and [" .. gzTextVar.gzPlayer.zaItems[2].sDisplayName .. "]." .. gsDE)
    
    --List builder.
    else
    
        --Setup.
        local sSentence = "You are carrying"
        
        --All members except the end.
        for i = 1, gzTextVar.gzPlayer.iItemsTotal - 1, 1 do
            sSentence = sSentence .. "[" .. gzTextVar.gzPlayer.zaItems[i].sDisplayName .. "], "
        end
        
        --Add to the end.
        sSentence = sSentence .. "and [" .. gzTextVar.gzPlayer.zaItems[gzTextVar.gzPlayer.iItemsTotal].sDisplayName .. "]." .. gsDE
        
        --Append it.
        TL_SetProperty("Append", sSentence)
    
    end
    return
end

--Objects shows objects in the same room as the player.
if(sString == "objects") then
    fnListObjects(gzTextVar.gzPlayer.sLocation, false)
    return
end

--Entities shows nearby entities.
if(sString == "entities") then
    fnListEntities(gzTextVar.gzPlayer.sLocation, false)
    return
end

--Self-examination.
if(sString == "look me" or sString == "x me") then
    LM_ExecuteScript(gzTextVar.sEntityHandlers .. "Self.lua")
    return
end

if(sString == "equipment") then
    LM_ExecuteScript(gzTextVar.sEntityHandlers .. "SelfEquipment.lua")
    return
end

--Activates surrendering mode, or deactivates it. This causes the next battle to instantly resolve in defeat, and changes
-- some of the dialogue.
if(sString == "surrender") then
    
    --Start surrendering.
    if(gzTextVar.bIsPlayerSurrendering == false) then
        
        if(gzTextVar.gzPlayer.sFormState == "Human") then
            gzTextVar.bIsPlayerSurrendering = true
            TL_SetProperty("Append", "You decide you will let the next creature that finds you, take you." .. gsDE)
        elseif(gzTextVar.gzPlayer.sFormState == "Statue") then
            TL_SetProperty("Append", "STATUES DO NOT SURRENDER. STATUES OBEY. YOU ARE A STATUE. The light dictates that you will not surrender. You obey." .. gsDE)
        else
            
            --Phase 6. Can't do this.
            if(gzTextVar.iGameStage == 6) then
                TL_SetProperty("Append", "You've come this far. You have no intention of giving up now." .. gsDE)
            
            --All other cases.
            else
                TL_SetProperty("Append", "The will of your creator dictates your thoughts. You must not surrender to the humans." .. gsDE)
            end
        end
    --End surrendering.
    else
    
        --Can't do this in phase 5!
        if(gzTextVar.iGameStage == 5) then
            TL_SetProperty("Append", "You think for a moment. Didn't that nice girl tell you to volunteer? Yeah! You had better surrender!" .. gsDE)
        
        --All other cases.
        else
            gzTextVar.bIsPlayerSurrendering = false
            TL_SetProperty("Append", "You decide you're going to fight back the next time a creature finds you." .. gsDE)
        end
    
    end
    return
end

--[ ========================================= Subscripts ======================================== ]
--[Remaps]
--Modify the player's command to "wait" if they are crippled. Only certain commands are remapped.
if(gzTextVar.gzPlayer.bIsCrippled) then
    if(string.sub(sString, 1, 4) == "look") then
    elseif(string.sub(sString, 1, 7) == "examine") then
    elseif(sString == "x") then
    elseif(string.sub(sString, 1, 5) == "talk ") then
    elseif(string.sub(sString, 1, 5) == "think") then
    else
        sString = "wait"
    end
end

--Calls a set of subscripts to handle the input. If one handles it, stops there.
gbHandledInput = false
LM_ExecuteScript(gzTextVar.sRootPath .. "101 Move Handler.lua", sString)
if(gbHandledInput == true) then return end

LM_ExecuteScript(gzTextVar.sRootPath .. "102 Secret Inputs.lua", sString)
if(gbHandledInput == true) then return end

LM_ExecuteScript(gzTextVar.sRootPath .. "103 Door Handler.lua", sString)
if(gbHandledInput == true) then return end

LM_ExecuteScript(gzTextVar.sRootPath .. "104 Deck Handler.lua", sString)
if(gbHandledInput == true) then return end

--[ ======================================= Room Handlers ======================================= ]
--Call the script that matches the room name. It handles internal logic for special cases. Not all
-- room scripts will do anything.
if(sString == "look" or sString == "examine" or sString == "x") then
    gzTextVar.bIsExaminationCheck = true
end
LM_ExecuteScript(gzTextVar.sRoomHandlers .. gzTextVar.gzPlayer.sLocation .. ".lua", sString)
gzTextVar.bIsExaminationCheck = false
if(gbHandledInput == true) then return end

--If the command "look" is used but was not handled, print this.
if(sString == "look" or sString == "examine" or sString == "x") then
    TL_SetProperty("Append", "There is nothing interesting about this room." .. gsDE)
    fnListEntities(gzTextVar.gzPlayer.sLocation, true)
    fnListObjects(gzTextVar.gzPlayer.sLocation, true)
    return
end

--[Search Carefully]
--Special. If used and the player has the ability to spot claygirls, this will expose them without
-- the player getting infected. It also halves their starting HP!
if(sString == "search carefully") then

    --Player is not a human.
    if(gzTextVar.gzPlayer.sFormState ~= "Human") then
        
        --Phase 6:
        if(gzTextVar.iGameStage == 6) then
        
        --All other cases.
        else
            TL_SetProperty("Append", "The humans are clearly not here. No need to search more carefully than that!" .. gsDE)
            return
        end
    end

    --Player does not know how to search carefully.
    if(gzTextVar.bCanSpotClaygirls == false) then
        TL_SetProperty("Append", "You would search the room carefully, but you have no idea what you're looking for with such precision." .. gsDE)
        return
    end

    --Check objects local to the room.
    for i = 1, gzTextVar.zRoomList[iRoom].iObjectsTotal, 1 do
        if(gzTextVar.zRoomList[iRoom].zObjects[i].sHandlerScript ~= nil) then
            
            --Special: If a claygirl is in this room and disguised as this object, we can spot them.
            if(gzTextVar.zRoomList[iRoom].zObjects[i].bIsClaygirlTrapped == true) then
            
                --Get the enemy's index.
                local c = -1
                for p = 1, gzTextVar.zEntitiesTotal, 1 do
                    if(gzTextVar.zEntities[p].sUniqueName == gzTextVar.zRoomList[iRoom].zObjects[i].sClaygirlName) then
                        c = p
                        break
                    end
                end
                
                --Determine clay color.
                local iIndicatorX = 6
                local sClayColor = "Blue"
                if(gzTextVar.zEntities[c].sQueryPicture == "Root/Images/DollManor/Characters/ClayGirlRed") then
                    sClayColor = "Red"
                    iIndicatorX = 7
                elseif(gzTextVar.zEntities[c].sQueryPicture == "Root/Images/DollManor/Characters/ClayGirlYellow") then
                    sClayColor = "Yellow"
                    iIndicatorX = 8
                end
                
                --Create an indicator for the enemy.
                local fX, fY, fZ = fnGetRoomPosition(gzTextVar.gzPlayer.sLocation)
                gzTextVar.zEntities[c].iIndicatorX = iIndicatorX
                gzTextVar.zEntities[c].iIndicatorY = 4
                gzTextVar.zEntities[c].iIndicatorC = ciCodeUnfriendly
                TL_SetProperty("Register Entity Indicator", fX, fY, fZ, gzTextVar.zEntities[c].sIndicatorName, gzTextVar.zEntities[c].iIndicatorX, gzTextVar.zEntities[c].iIndicatorY, gzTextVar.zEntities[c].iIndicatorC)
                
                --Rebuild locality info to show the new enemy.
                fnRebuildEntityVisibility()
                fnBuildLocalityInfo()
                    
                --When surrendering:
                if(gzTextVar.bIsPlayerSurrendering == true) then
                    gbHandledInput = true
                    LM_ExecuteScript(gzTextVar.sRootPath .. "AIs/CutsceneClaygirl/Surrender To Claygirl On Item.lua", iRoom, i, c)
                    
                --Normal:
                else
            
                    --Unset flags.
                    gzTextVar.zRoomList[iRoom].zObjects[i].bIsClaygirlTrapped = false
                    gzTextVar.zRoomList[iRoom].zObjects[i].sClaygirlName = "Null"
                    gzTextVar.zRoomList[iRoom].zObjects[i].saClaygirlList = {}
                    gzTextVar.zEntities[c].sInDisguise = "Null"
                        
                    --Dialogue.
                    TL_SetProperty("Append", "You search the room carefully..." .. gsDE)
                    TL_SetProperty("Create Blocker")
                    
                    TL_SetProperty("Append", "As you are about to touch the " .. gzTextVar.zRoomList[iRoom].zObjects[i].sDisplayName .. ", you think better of it. It seems... off..." .. gsDE)
                    TL_SetProperty("Create Blocker")
                    
                    TL_SetProperty("Append", "Instead, you give it a hard kick!" .. gsDE)
                    TL_SetProperty("Create Blocker")
                    
                    TL_SetProperty("Append", "Your suspicions were correct, it was a trap! A layer of clay sloughs off and pools on the ground..." .. gsDE)
                    TL_SetProperty("Create Blocker")
                    
                    TL_SetProperty("Register Image", "You", gzTextVar.zEntities[c].sQueryPicture, ciImageLayerDefault)
                    TL_SetProperty("Append", "The pool rapidly expands, then gives way to a head, torso and legs. A girl made of clay, but lacking a face, menaces you!" .. gsDE)
                    TL_SetProperty("Create Blocker")
                    
                    --Phase 6.
                    if(gzTextVar.iGameStage == 6) then
                        TL_SetProperty("Append", "The claygirl stares at you, uncertain. It is evaluating the strange situation." .. gsDE)
                        TL_SetProperty("Create Blocker")
                        TL_SetProperty("Unregister Image")
                        
                        TL_SetProperty("Append", "You giggle. 'Silly girl, I already found the humans! I'm taking them to the creator!'" .. gsDE)
                        TL_SetProperty("Create Blocker")
                        
                        TL_SetProperty("Append", "'Sorry for hitting you. I get scared very easily. I'm sorry.'" .. gsDE)
                        TL_SetProperty("Create Blocker")
                        
                        TL_SetProperty("Register Image", "You", gzTextVar.zEntities[c].sQueryPicture, ciImageLayerDefault)
                        TL_SetProperty("Append", "The claygirl backs up. She seems to have believed you. You curtsey for her before continuing." .. gsDE)
                        TL_SetProperty("Create Blocker")
                        return
                    
                    --All other cases:
                    else
                    
                        TL_SetProperty("Append", "Fortunately, it seems seriously wounded as a result of your kick. Defend yourself!" .. gsDE)
                        TL_SetProperty("Create Blocker")
                        TL_SetProperty("Unregister Image")
                        
                        --Combat!
                        gzTextVar.bEnemySpawnsAtHalfHealth = true
                        TL_SetProperty("Exec Script", gzTextVar.sCombatHandler, 3, c, "Standard", "Standard")
                        gbHandledInput = true
                        return
                    end
                end
            end
                
        end
    end
    
    --If we got this far, we didn't find anything.
    TL_SetProperty("Append", "You check over the room carefully. You are fairly certain there are no enemies here waiting to ambush you." .. gsDE)
    LM_ExecuteScript(gzTextVar.sTurnEndScript)
    
    --In all cases, handle the input.
    return
end

--[ ====================================== Entity Handlers ====================================== ]
--See if an entity handled the command.
for i = 1, gzTextVar.zEntitiesTotal, 1 do
   
   --Store
   gzTextVar.iCurrentEntity = i
   
    --Check if the entity is in the same room as the player.
    if(gzTextVar.zEntities[i].sLocation == gzTextVar.gzPlayer.sLocation) then
        
        --Run the handler. Most entities only respond to their own name, but special actions are possible.
        LM_ExecuteScript(gzTextVar.zEntities[i].sCommandHandler, sString)
        if(gbHandledInput) then return end
    end
end

--Clear the activity variable.
gzTextVar.iCurrentEntity = -1

--[ ===================================== Objects Handlers ====================================== ]
--Handles objects, obviously. This includes inventory items. Inventory gets priority for the purposes
-- of using items, but the player can actually drink a potion right off the floor. Equipment is
-- specialized and goes first.

--Equipment.
if(gzTextVar.gzPlayer.zWeapon ~= nil) then
    LM_ExecuteScript(gzTextVar.gzPlayer.zWeapon.sHandlerScript, sString, -1, -1, ciEquipSlotWeapon)
    if(gbHandledInput == true) then return end
end
if(gzTextVar.gzPlayer.zArmor ~= nil) then
    LM_ExecuteScript(gzTextVar.gzPlayer.zArmor.sHandlerScript, sString, -1, -1, ciEquipSlotArmor)
    if(gbHandledInput == true) then return end
end
if(gzTextVar.gzPlayer.zGloves ~= nil) then
    LM_ExecuteScript(gzTextVar.gzPlayer.zGloves.sHandlerScript, sString, -1, -1, ciEquipSlotGloves)
    if(gbHandledInput == true) then return end
end

--Inventory.
for i = 1, gzTextVar.gzPlayer.iItemsTotal, 1 do
    if(gzTextVar.gzPlayer.zaItems[i].sHandlerScript ~= nil) then
        LM_ExecuteScript(gzTextVar.gzPlayer.zaItems[i].sHandlerScript, sString, i, -1, -1)
        if(gbHandledInput == true) then return end
    end
end

--[Take All]
--Command attempts to take all of the objects in the same room.
local bTookOneItem = false
gzTextVar.bTakeAll = false
if(sString == "take all") then
    
    --No items to take.
    if(gzTextVar.zRoomList[iRoom].iObjectsTotal == 0) then
        TL_SetProperty("Append", "There are no items to take here." .. gsDE)
        return
    
    --Exactly one item to take, change the command to just take that item.
    elseif(gzTextVar.zRoomList[iRoom].iObjectsTotal == 1) then
        sString = "take " .. gzTextVar.zRoomList[iRoom].zObjects[1].sDisplayName
    
    --Special flag gets set. Items will be taken but will not stop the update cycle. Hitting a claygirl stops the cycle!
    else
        gzTextVar.bTakeAll = true
    end
end

--Check objects local to the room.
local i = 1
while(i <= gzTextVar.zRoomList[iRoom].iObjectsTotal) do
    if(gzTextVar.zRoomList[iRoom].zObjects[i].sHandlerScript ~= nil) then
        
        --Store how many items were in the room.
        local iPreviousItems = gzTextVar.zRoomList[iRoom].iObjectsTotal
        
        --Emulate whether or not the command is referring to this item.
        gzTextVar.iItemEmulation = 1
        LM_ExecuteScript(gzTextVar.zRoomList[iRoom].zObjects[i].sHandlerScript, sString, i, iRoom, -1)
        
        --If this flag is set, the emulation flag is ALWAYS set to 2, as the program is trying to take all the items.
        local sStorageString = sString
        if(gzTextVar.bTakeAll) then
            gzTextVar.iItemEmulation = 2
            sString = "take " .. gzTextVar.zRoomList[iRoom].zObjects[i].sDisplayName
        end
        
        --If this flag got set to 2, it means this item responded because it was the one the player tried to interact with.
        if(gzTextVar.iItemEmulation == 2) then
        
            --Special: If a claygirl is in this room and disguised as this object, then the object infects the player and
            -- triggers a battle! This only occurs for take/equip commands, not examine.
            if(gzTextVar.zRoomList[iRoom].zObjects[i].bIsClaygirlTrapped == true) then
                
                --Scan across the list of trapped words. If the command matches, spring the trap!
                local bCommandMatch = false
                for p = 1, #gzTextVar.zRoomList[iRoom].zObjects[i].saClaygirlList, 1 do
                
                    local iSubLen = string.len(gzTextVar.zRoomList[iRoom].zObjects[i].saClaygirlList[p])
                    if(gzTextVar.zRoomList[iRoom].zObjects[i].saClaygirlList[p] == string.sub(sString, 1, iSubLen)) then
                        bCommandMatch = true
                    end
                end
                
                --If the player is non-human, the command never matches. Non-humans can never trigger claygirl attacks.
                if(gzTextVar.gzPlayer.sFormState ~= "Human") then
                    bCommandMatch = false
                end
            
                --No command match? Run the normal script.
                if(bCommandMatch == false) then
                    LM_ExecuteScript(gzTextVar.zRoomList[iRoom].zObjects[i].sHandlerScript, sString, i, iRoom, -1)
                
                --Command match! Spring the trap!
                else
                
                    --Get the enemy's index.
                    local c = -1
                    for p = 1, gzTextVar.zEntitiesTotal, 1 do
                        if(gzTextVar.zEntities[p].sUniqueName == gzTextVar.zRoomList[iRoom].zObjects[i].sClaygirlName) then
                            c = p
                            break
                        end
                    end
                    if(c == -1) then 
                        LM_ExecuteScript(gzTextVar.zRoomList[iRoom].zObjects[i].sHandlerScript, sString, i, iRoom, -1)
                        return 
                    end
                
                    --Determine clay color.
                    local iIndicatorX = 6
                    local sClayColor = "Blue"
                    if(gzTextVar.zEntities[c].sQueryPicture == "Root/Images/DollManor/Characters/ClayGirlRed") then
                        sClayColor = "Red"
                        iIndicatorX = 7
                    elseif(gzTextVar.zEntities[c].sQueryPicture == "Root/Images/DollManor/Characters/ClayGirlYellow") then
                        sClayColor = "Yellow"
                        iIndicatorX = 8
                    end
                
                    --Create an indicator for the enemy.
                    local fX, fY, fZ = fnGetRoomPosition(gzTextVar.gzPlayer.sLocation)
                    gzTextVar.zEntities[c].iIndicatorX = iIndicatorX
                    gzTextVar.zEntities[c].iIndicatorY = 4
                    gzTextVar.zEntities[c].iIndicatorC = ciCodeUnfriendly
                    TL_SetProperty("Register Entity Indicator", fX, fY, fZ, gzTextVar.zEntities[c].sIndicatorName, gzTextVar.zEntities[c].iIndicatorX, gzTextVar.zEntities[c].iIndicatorY, gzTextVar.zEntities[c].iIndicatorC)
                
                    --Rebuild locality info to show the new enemy.
                    fnRebuildEntityVisibility()
                    fnBuildLocalityInfo()
                    
                    --When surrendering:
                    if(gzTextVar.bIsPlayerSurrendering == true) then
                        gbHandledInput = true
                        LM_ExecuteScript(gzTextVar.sRootPath .. "AIs/CutsceneClaygirl/Surrender To Claygirl On Item.lua", iRoom, i, c)
                        
                    --Normal:
                    else
                
                        --Dialogue. Change Mary's image.
                        gzTextVar.gzPlayer.sQuerySprite = "Root/Images/DollManor/Transformation/MaryClay" .. sClayColor .. "TF0"
                        gzTextVar.gzPlayer.sLayer0 = gzTextVar.gzPlayer.sQuerySprite
                        TL_SetProperty("Register Image", "You", "Root/Images/DollManor/Characters/Mary", ciImageLayerDefault)
                        TL_SetProperty("Append", "The second you touch the " .. gzTextVar.zRoomList[iRoom].zObjects[i].sDisplayName .. ", it becomes soft. It's covered in some sort of clay!" .. gsDE)
                        TL_SetProperty("Create Blocker")
                        
                        TL_SetProperty("Default Image", "You", gzTextVar.gzPlayer.sQuerySprite, ciImageLayerDefault)
                        TL_SetProperty("Register Image", "You", gzTextVar.gzPlayer.sQuerySprite, ciImageLayerDefault)
                        TL_SetProperty("Append", "The clay coats your hand, feeling cold and slimy. It's almost alive - but you have much bigger problems." .. gsDE)
                        TL_SetProperty("Create Blocker")
                        
                        TL_SetProperty("Append", "The clay oozes off the " .. gzTextVar.zRoomList[iRoom].zObjects[i].sDisplayName .. " and expands, forming a puddle." .. gsDE)
                        TL_SetProperty("Create Blocker")
                        
                        TL_SetProperty("Register Image", "You", gzTextVar.gzPlayer.sQuerySprite, ciImageLayerDefault)
                        TL_SetProperty("Append", "The puddle gives way to a head, torso, and then legs. A girl made of clay, but lacking a face, menaces you! Defend yourself!" .. gsDE)
                        TL_SetProperty("Create Blocker")
                        TL_SetProperty("Unregister Image")
                    
                        --Unset flags.
                        gzTextVar.zRoomList[iRoom].zObjects[i].bIsClaygirlTrapped = false
                        gzTextVar.zRoomList[iRoom].zObjects[i].sClaygirlName = "Null"
                        gzTextVar.zRoomList[iRoom].zObjects[i].saClaygirlList = {}
                        gzTextVar.zEntities[c].sInDisguise = "Null"
                        
                        --Player gains a clay infection.
                        if(gzTextVar.gzPlayer.iClayInfection < 0) then
                            gzTextVar.gzPlayer.iClayInfection = 0
                        end
                        
                        --Combat!
                        TL_SetProperty("Exec Script", gzTextVar.sCombatHandler, 3, c, "Standard", "Standard")
                        gbHandledInput = true
                        gzTextVar.bTakeAll = false
                    end
                end
                
            --Otherwise, run the handler as normal.
            else
                gzTextVar.iItemEmulation = 0
                LM_ExecuteScript(gzTextVar.zRoomList[iRoom].zObjects[i].sHandlerScript, sString, i, iRoom, -1)
            end
        end
        
        --Reset flag.
        gzTextVar.iItemEmulation = 0
        
        --If this flag is set, we're "taking all".
        if(gbHandledInput and gzTextVar.bTakeAll == true) then
            
            --If the number of items in the room is the same as before, we didn't actually take an item. This can happen
            -- if an item responds to the command, but cannot be taken.
            if(gzTextVar.zRoomList[iRoom].iObjectsTotal == iPreviousItems) then
            
            --We took an item, so set flags.
            else
                bTookOneItem = true
                gbHandledInput = false
                sString = sStorageString
                i = i - 1
            end
        end
        
        --Exit if handled.
        if(gbHandledInput == true) then return end
    end
        
    --Next.
    i = i + 1
end

--If this flag got set, we took at least one item with "take all", so stop.
if(bTookOneItem == true) then
    
    LM_ExecuteScript(gzTextVar.sTurnEndScript)
    return
end

--If the take-all command went but no items actually responded, print this.
if(gzTextVar.bTakeAll == true and gbHandledInput == false) then
    TL_SetProperty("Append", "There are no items that can be taken here." .. gsDE)
    return
end

--[ ======================================= Other Actions ======================================= ]
if(sString == "wait" or sString == ".") then
    
    --Special: Hypnotized into becoming a statue.
    if(gzTextVar.gzPlayer.sFormState == "Human" and gzTextVar.iHypnoticCheck >= 10) then
        
        --Player is at the Stone Gallery. We don't need to do anything special.
        if(gzTextVar.gzPlayer.sLocation == "Stone Gallery") then
            TL_SetProperty("Append", "Time passes." .. gsDE)
            LM_ExecuteScript(gzTextVar.sTurnEndScript)
            return
        
        --All other locations, player moves west.
        else
            gbHandledInput = false
            LM_ExecuteScript(gzTextVar.sRootPath .. "101 Move Handler.lua", "w")
            if(gbHandledInput == true) then return end
        
        end
    end
    
    
    TL_SetProperty("Append", "Time passes." .. gsDE)
    LM_ExecuteScript(gzTextVar.sTurnEndScript)
    return
end

--[ ========================================== Default ========================================== ]
--If we got this far, the command was not understood. Print a help message.
if(true) then
    TL_SetProperty("Append", "I was unable to understand what you meant. Please type 'help' if you need instructions." .. gsDE)
    return
end