--[ ===================================== Movement Handler ====================================== ]
--This script handles movement cases. It receives "Move X" where X is the direction. "North" and "N"
-- both map to the same thing.
--Sets the handler variable if it handled the input.

--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)

--[ ====================================== Command Verify ======================================= ]
--Check if this is actually a movement command.
local sFirstLetter = "x"

--If the command starts with "move":
if(string.sub(sString, 1, 4) == "move") then
    sFirstLetter = string.sub(sString, 6, 6)

--If the command starts with "go":
elseif(string.sub(sString, 1, 2) == "go") then
    sFirstLetter = string.sub(sString, 4, 4)

--If the command is a single letter long and is one of the movement directions:
elseif(sString == "n" or sString == "s" or sString == "e" or sString == "w" or sString == "u" or sString == "d") then
    sFirstLetter = string.sub(sString, 1, 1)

--If the command is a single word long and that is a movement direction:
elseif(sString == "north" or sString == "south" or sString == "east" or sString == "west" or sString == "up" or sString == "down") then
    sFirstLetter = string.sub(sString, 1, 1)

--Failed.
else
    return
end

--If we got this far, it's a movement command.
gbHandledInput = true

--[ ========================================= Execution ========================================= ]
--[Doll Lock Check]
--Player cannot leave while Pygmalie is transforming someone.
if(gzTextVar.gzPlayer.bDollMoveLock == true) then
    TL_SetProperty("Append", "Your creator wills that you stay here and help her make a new sister." .. gsDE)
    return
end

--[String Trap Finale Check]
--Dollified Mary cannot leave the trap to the north. Player must proceed to get a bad end.
if(gzTextVar.iMaryStringTrapState == 3 and gzTextVar.gzPlayer.sLocation == "Eerie Antechamber" and sFirstLetter == "n") then
    TL_SetProperty("Append", "You need to lure the silly humans into the string trap, so they can be just as pretty as you!" .. gsDE)
    return
end

--[String Trap Activity Check]
--When in the string trap, each room has a special set of variables that determine if the trap activates.
if(gzTextVar.bStringTrapActive == true and gzTextVar.bStringTrapDisarmed == false) then
    
    --Reset.
    gzTextVar.bStringTrapActiveN = false
    gzTextVar.bStringTrapActiveE = false
    gzTextVar.bStringTrapActiveS = false
    gzTextVar.bStringTrapActiveW = false
    
    --The individual room will flag which directions will activate the trap.
    gzTextVar.bStringTrapActivityCheck = true
    LM_ExecuteScript(gzTextVar.sRoomHandlers .. gzTextVar.gzPlayer.sLocation .. ".lua", sString)
    gzTextVar.bStringTrapActivityCheck = false
    
    --If the player moved north and the string trap is active to the north:
    if(sFirstLetter == "n" and gzTextVar.bStringTrapActiveN == true) then
        LM_ExecuteScript(gzTextVar.sStringTriggerPath)
        return
    --East.
    elseif(sFirstLetter == "e" and gzTextVar.bStringTrapActiveE == true) then
        LM_ExecuteScript(gzTextVar.sStringTriggerPath)
        return
    --South.
    elseif(sFirstLetter == "s" and gzTextVar.bStringTrapActiveS == true) then
        LM_ExecuteScript(gzTextVar.sStringTriggerPath)
        return
    --West.
    elseif(sFirstLetter == "w" and gzTextVar.bStringTrapActiveW == true) then
        LM_ExecuteScript(gzTextVar.sStringTriggerPath)
        return
    end
end

--[Hypnosis Check]
--Mary is hypnotised and will only move towards the Stone Gallery.
if(gzTextVar.gzPlayer.sFormState == "Human" and gzTextVar.iHypnoticCheck >= 10) then
    
    --Player is at the Stone Gallery, fail all moves.
    if(gzTextVar.gzPlayer.sLocation == "Stone Gallery") then
        TL_SetProperty("Append", "You CANNOT LEAVE. You WILL STAY HERE and GAZE INTO THE LIGHT. You obey." .. gsDE)
        return
    end
    
    --Player is otherwise only allowed to move west.
    if(sFirstLetter == "n") then
        sFirstLetter = "w"
        TL_SetProperty("Append", "You MUST GO TO THE LIGHT. Your body carries you to the west..." .. gsDE)
    elseif(sFirstLetter == "s") then
        sFirstLetter = "w"
        TL_SetProperty("Append", "You MUST GO TO THE LIGHT. Your body carries you to the west..." .. gsDE)
    elseif(sFirstLetter == "e") then
        sFirstLetter = "w"
        TL_SetProperty("Append", "You MUST GO TO THE LIGHT. Your body carries you to the west..." .. gsDE)
    elseif(sFirstLetter == "w") then
        TL_SetProperty("Append", "In a trance, you feel compelled to go west..." .. gsDE)
    elseif(sFirstLetter == "u") then
        sFirstLetter = "w"
        TL_SetProperty("Append", "You MUST GO TO THE LIGHT. Your body carries you to the west..." .. gsDE)
    elseif(sFirstLetter == "d") then
        sFirstLetter = "w"
        TL_SetProperty("Append", "You MUST GO TO THE LIGHT. Your body carries you to the west..." .. gsDE)
    end

--Human, not hypnotised, but in the Stone Gallery and the light hasn't been dealt with. Western moves are illegal.
elseif(gzTextVar.gzPlayer.sFormState == "Human" and gzTextVar.iHypnoticCheck < 10 and gzTextVar.gzPlayer.sLocation == "Stone Gallery") then

    --Have not disabled the light:
    if(gzTextVar.bDisabledLight == false) then
        if(sFirstLetter == "w") then
            TL_SetProperty("Append", "You try to go west, but your body fights you. You WILL NOT GO IN THERE. You will GAZE INTO THE LIGHT." .. gsDE)
            return
        end
        
    --Have disabled the light, but haven't told Jessie and Lauren.
    elseif(gzTextVar.bDisabledLightCutscene == false) then
        if(sFirstLetter == "w") then
            TL_SetProperty("Append", "Now that the light has been taken care of, you should go let Lauren and Jessie know it's safe here." .. gsDE)
            return
        end
    
    end

--Statue. Cannot go west from the Stone Gallery for any reason.
elseif(gzTextVar.gzPlayer.sFormState == "Statue" and gzTextVar.gzPlayer.sLocation == "Stone Gallery") then
    if(sFirstLetter == "w") then
        TL_SetProperty("Append", "YOU DO NOT ENTER THE ROOM BEYOND THE LIGHT. THERE IS NO ROOM BEHIND THE LIGHT. YOU WILL FIND THE INTRUDERS. YOU WILL BRING THEM TO THE LIGHT." .. gsDE)
        return
    end

--Non-human. Cannot enter Pygmalie's Study. In Phase 5 this is relaxed.
elseif(gzTextVar.gzPlayer.sFormState ~= "Human" and gzTextVar.gzPlayer.sLocation == "Stone Gallery" and gzTextVar.iGameStage < 5) then

    --If Jessie or Lauren is in the room, you can enter it.
    if(gzTextVar.zEntities[gzTextVar.iJessieIndex].sLocation == "Pygmalie's Study" or gzTextVar.zEntities[gzTextVar.iLaurenIndex].sLocation == "Pygmalie's Study") then

    elseif(sFirstLetter == "w") then
        TL_SetProperty("Append", "You stop. You are not supposed to enter this room. At all. You immediately forget the room and leave the door alone." .. gsDE)
        return
    end
end

--[Statue Movement Check]
if(gzTextVar.gzPlayer.sFormState == "Statue" and gzTextVar.bForceMoveStatue) then
    
    --Player is not at the Stone Gallery.
    if(gzTextVar.gzPlayer.sLocation ~= "Stone Gallery") then
        
        --Display.
        if(gzTextVar.bSecretStatue == false) then
            TL_SetProperty("Append", "CARRY INTRUDER TO THE LIGHT. You drag the stunned intruder behind you, towards the Stone Gallery. Towards THE LIGHT." .. gsDE)
        else
            TL_SetProperty("Append", "BRING THEM TO THE LIGHT. You lead the intruders to the Stone Gallery. Towards THE LIGHT." .. gsDE)
        end
    
        --Resolve target room index.
        local iTargetIndex = fnGetRoomIndex("Stone Gallery")
        local iRoomIndex = fnGetRoomIndex(gzTextVar.gzPlayer.sLocation)

        --Get the first letter of matching movement.
        local sPathInstructions = gzTextCon.zRoomList[iTargetIndex].zPathListing[iRoomIndex]
        if(sPathInstructions == "") then return end
        local sFirstPathLetter = string.sub(sPathInstructions, 1, 1)

        --Move in the requested direction:
        local sDestination = "Nowhere"
        if(sFirstPathLetter == "N") then
            sFirstLetter = "n"
            sDestination = gzTextVar.zRoomList[iRoomIndex].sMoveN
        elseif(sFirstPathLetter == "S") then
            sFirstLetter = "s"
            sDestination = gzTextVar.zRoomList[iRoomIndex].sMoveS
        elseif(sFirstPathLetter == "E") then
            sFirstLetter = "e"
            sDestination = gzTextVar.zRoomList[iRoomIndex].sMoveE
        elseif(sFirstPathLetter == "W") then
            sFirstLetter = "w"
            sDestination = gzTextVar.zRoomList[iRoomIndex].sMoveW
        elseif(sFirstPathLetter == "U") then
            sFirstLetter = "u"
            sDestination = gzTextVar.zRoomList[iRoomIndex].sMoveU
        elseif(sFirstPathLetter == "D") then
            sFirstLetter = "d"
            sDestination = gzTextVar.zRoomList[iRoomIndex].sMoveD
        end
    
        --If Jessie is crippled, she moves along.
        local j = gzTextVar.iJessieIndex
        if(gzTextVar.zEntities[j].bIsCrippled) then
            local sOldLocation = gzTextVar.zEntities[j].sLocation
            gzTextVar.zEntities[j].sLocation = sDestination
            local fOldX, fOldY, fOldZ = fnGetRoomPosition(sOldLocation)
            local fNewX, fNewY, fNewZ = fnGetRoomPosition(sDestination)
            TL_SetProperty("Move Entity Indicator", fOldX, fOldY, fOldZ, gzTextVar.zEntities[j].sIndicatorName, fNewX, fNewY, fNewZ)
        end
    
        --If Lauren is crippled, she moves along.
        local l = gzTextVar.iLaurenIndex
        if(gzTextVar.zEntities[l].bIsCrippled) then
            local sOldLocation = gzTextVar.zEntities[l].sLocation
            gzTextVar.zEntities[l].sLocation = sDestination
            local fOldX, fOldY, fOldZ = fnGetRoomPosition(sOldLocation)
            local fNewX, fNewY, fNewZ = fnGetRoomPosition(sDestination)
            TL_SetProperty("Move Entity Indicator", fOldX, fOldY, fOldZ, gzTextVar.zEntities[l].sIndicatorName, fNewX, fNewY, fNewZ)
        end
    
    --Player is at the Stone Gallery.
    else
        return
    end
    
end

--[Wound Checker]
--If the player is crippled, they cannot move.
if(gzTextVar.gzPlayer.bIsCrippled) then
    
    --Blank doll.
    if(gzTextVar.gzPlayer.sFormState == "Blank Doll") then
        TL_SetProperty("Append", "You cannot move a muscle, and your mind is empty." .. gsDE)
        
    --Transformation.
    elseif(string.sub(gzTextVar.gzPlayer.sFormState, 1, 8) == "Bride TF") then
        TL_SetProperty("Append", "You should not move while your creator is working on you." .. gsDE)
        
    --Transformation.
    elseif(string.sub(gzTextVar.gzPlayer.sFormState, 1, 9) == "Dancer TF") then
        TL_SetProperty("Append", "You should not move while your creator is working on you." .. gsDE)
        
    --Transformation.
    elseif(string.sub(gzTextVar.gzPlayer.sFormState, 1, 9) == "Geisha TF") then
        TL_SetProperty("Append", "You should not move while your creator is working on you." .. gsDE)
        
    --Transformation.
    elseif(string.sub(gzTextVar.gzPlayer.sFormState, 1, 7) == "Goth TF") then
        TL_SetProperty("Append", "You should not move while your creator is working on you." .. gsDE)
        
    --Transformation.
    elseif(string.sub(gzTextVar.gzPlayer.sFormState, 1, 11) == "Princess TF") then
        TL_SetProperty("Append", "You should not move while your creator is working on you." .. gsDE)
        
    --Transformation.
    elseif(string.sub(gzTextVar.gzPlayer.sFormState, 1, 7) == "Punk TF") then
        TL_SetProperty("Append", "You should not move while your creator is working on you." .. gsDE)
    
    --Default.
    else
        TL_SetProperty("Append", "You are too hurt to move." .. gsDE)
    end
    
    LM_ExecuteScript(gzTextVar.sTurnEndScript)
    return
end

--[Not Wounded, but TFing]
--If the player is in the middle of a transformation sequence, even if they are not crippled, they cannot move.
if(gzTextVar.gzPlayer.sFormState == "Blank Doll") then
    TL_SetProperty("Append", "You cannot move a muscle, and your mind is empty." .. gsDE)
    LM_ExecuteScript(gzTextVar.sTurnEndScript)
    return
    
--Transformation.
elseif(string.sub(gzTextVar.gzPlayer.sFormState, 1, 8) == "Bride TF") then
    TL_SetProperty("Append", "You should not move while your creator is working on you." .. gsDE)
    LM_ExecuteScript(gzTextVar.sTurnEndScript)
    return
    
--Transformation.
elseif(string.sub(gzTextVar.gzPlayer.sFormState, 1, 9) == "Dancer TF") then
    TL_SetProperty("Append", "You should not move while your creator is working on you." .. gsDE)
    LM_ExecuteScript(gzTextVar.sTurnEndScript)
    return
    
--Transformation.
elseif(string.sub(gzTextVar.gzPlayer.sFormState, 1, 9) == "Geisha TF") then
    TL_SetProperty("Append", "You should not move while your creator is working on you." .. gsDE)
    LM_ExecuteScript(gzTextVar.sTurnEndScript)
    return
    
--Transformation.
elseif(string.sub(gzTextVar.gzPlayer.sFormState, 1, 7) == "Goth TF") then
    TL_SetProperty("Append", "You should not move while your creator is working on you." .. gsDE)
    LM_ExecuteScript(gzTextVar.sTurnEndScript)
    return
    
--Transformation.
elseif(string.sub(gzTextVar.gzPlayer.sFormState, 1, 11) == "Princess TF") then
    TL_SetProperty("Append", "You should not move while your creator is working on you." .. gsDE)
    LM_ExecuteScript(gzTextVar.sTurnEndScript)
    return
    
--Transformation.
elseif(string.sub(gzTextVar.gzPlayer.sFormState, 1, 7) == "Punk TF") then
    TL_SetProperty("Append", "You should not move while your creator is working on you." .. gsDE)
    LM_ExecuteScript(gzTextVar.sTurnEndScript)
    return
end

--[Room Locator]
--Find out what room the player is currently in. If they're not in a room, moves always fail.
local iRoomIndex = fnGetRoomIndex(gzTextVar.gzPlayer.sLocation)
if(iRoomIndex == -1) then return end

--[Connection Checker]
--See if this room has a connection in the requested direction. If it's "Null" then we don't.
local sDestination = "Null"
if(sFirstLetter == "n") then
    sDestination = gzTextVar.zRoomList[iRoomIndex].sMoveN
elseif(sFirstLetter == "s") then
    sDestination = gzTextVar.zRoomList[iRoomIndex].sMoveS
elseif(sFirstLetter == "e") then
    sDestination = gzTextVar.zRoomList[iRoomIndex].sMoveE
elseif(sFirstLetter == "w") then
    sDestination = gzTextVar.zRoomList[iRoomIndex].sMoveW
elseif(sFirstLetter == "u") then
    sDestination = gzTextVar.zRoomList[iRoomIndex].sMoveU
elseif(sFirstLetter == "d") then
    sDestination = gzTextVar.zRoomList[iRoomIndex].sMoveD
end

--Failure:
if(sDestination == "Null") then
    TL_SetProperty("Append", "You can't go that way." .. gsDE)
    return
end

local iDestIndex = fnGetRoomIndex(sDestination)
if(iDestIndex == -1) then
    TL_SetProperty("Append", "You can't go that way." .. gsDE)
    return
end

--Get positions.
local fOldX, fOldY, fOldZ = fnGetRoomPosition(gzTextVar.gzPlayer.sLocation)
local fX, fY, fZ = fnGetRoomPosition(sDestination)

--Check if there's a door in that direction, and handle locking cases.
if(sFirstLetter == "n") then
    if(gzTextVar.zRoomList[iRoomIndex].sDoorN ~= nil) then
        
        --Get the string past the first letter.
        local sDoorState = string.sub(gzTextVar.zRoomList[iRoomIndex].sDoorN, 1, 1)
        local sLockType = string.sub(gzTextVar.zRoomList[iRoomIndex].sDoorN, 2)
        
        --Is the door closed?
        if(sDoorState == "C") then
            
            --Check key states. 
            local bOpenedDoor = true
            local sPrintString = "You open the door." .. gsDE
            local sOpenSound = "Doll|OpenDoor"
            
            --Clay lock, triggers the special sequence if the clay house is not disarmed. Is otherwise
            -- the same as a normal lock.
            if(sLockType == " Clay") then
                if(gzTextVar.bClayDisarmed == false) then
                    gzTextVar.bClayDoorThisTurn = true
                end
            
            --Unopenable.
            elseif(sLockType == " ClayUnopenable") then
                bOpenedDoor = false
                sPrintString = "The door has merged with the wall, completely cutting access from this room!" .. gsDE
            
            --Check if the lock can't be opened.
            elseif(sLockType ~= " Normal" and sLockType ~= " None") then
                bOpenedDoor, sPrintString = fnCheckKeyStates(sLockType)
                sOpenSound = "Doll|OpenDoorLocked"
            end
            
            --Check if we failed to open the door.
            if(bOpenedDoor == false) then
                TL_SetProperty("Append", sPrintString)
                fnMarkLockAsKnown(iRoomIndex, gzTextCon.iDirNorth)
                return
            end
            
            --Small keys destroy one of the small keys in our inventory.
            if(sLockType == " Small") then
                for i = 1, gzTextVar.gzPlayer.iItemsTotal, 1 do
                    if(gzTextVar.gzPlayer.zaItems[i].sDisplayName == "small key") then
                        fnRemoveItemFromInventory(i)
                        break
                    end
                end
            end
            
            --We moved through the door, so open it.
            TL_SetProperty("Append", sPrintString)
            LM_ExecuteScript(gzTextVar.sRootPath .. "Functions/Modify Door State.lua", gzTextVar.gzPlayer.sLocation, "O" .. sLockType, "N", ciDoNotModifyVisibility, 1)
            fnMarkLockAsKnown(iRoomIndex, gzTextCon.iDirNorth)
            
            --SFX.
            AudioManager_PlaySound(sOpenSound)
        end
    end
    
elseif(sFirstLetter == "s") then
    if(gzTextVar.zRoomList[iRoomIndex].sDoorS ~= nil) then
        
        --Get the string past the first letter.
        local sDoorState = string.sub(gzTextVar.zRoomList[iRoomIndex].sDoorS, 1, 1)
        local sLockType = string.sub(gzTextVar.zRoomList[iRoomIndex].sDoorS, 2)
        
        --Is the door closed?
        if(sDoorState == "C") then
            
            --Check key states. 
            local bOpenedDoor = true
            local sPrintString = "You open the door." .. gsDE
            local sOpenSound = "Doll|OpenDoor"
            
            --Clay lock, triggers the special sequence if the clay house is not disarmed. Is otherwise
            -- the same as a normal lock.
            if(sLockType == " Clay") then
                if(gzTextVar.bClayDisarmed == false) then
                    gzTextVar.bClayDoorThisTurn = true
                end
            
            --Unopenable.
            elseif(sLockType == " ClayUnopenable") then
                bOpenedDoor = false
                sPrintString = "The door has merged with the wall, completely cutting access from this room!" .. gsDE
            
            --Check if the lock can't be opened.
            elseif(sLockType ~= " Normal" and sLockType ~= " None") then
                bOpenedDoor, sPrintString = fnCheckKeyStates(sLockType)
                sOpenSound = "Doll|OpenDoorLocked"
            end
            
            --Check if we failed to open the door.
            if(bOpenedDoor == false) then
                TL_SetProperty("Append", sPrintString)
                fnMarkLockAsKnown(iRoomIndex, gzTextCon.iDirSouth)
                return
            end
            
            --Small keys destroy one of the small keys in our inventory.
            if(sLockType == " Small") then
                for i = 1, gzTextVar.gzPlayer.iItemsTotal, 1 do
                    if(gzTextVar.gzPlayer.zaItems[i].sDisplayName == "small key") then
                        fnRemoveItemFromInventory(i)
                        break
                    end
                end
            end
            
            --We moved through the door, so open it.
            TL_SetProperty("Append", sPrintString)
            LM_ExecuteScript(gzTextVar.sRootPath .. "Functions/Modify Door State.lua", gzTextVar.gzPlayer.sLocation, "O" .. sLockType, "S", ciDoNotModifyVisibility, 1)
            fnMarkLockAsKnown(iRoomIndex, gzTextCon.iDirSouth)
            
            --SFX.
            AudioManager_PlaySound(sOpenSound)
        end
    end
    
elseif(sFirstLetter == "e") then
    if(gzTextVar.zRoomList[iRoomIndex].sDoorE ~= nil) then
        
        --Get the string past the first letter.
        local sDoorState = string.sub(gzTextVar.zRoomList[iRoomIndex].sDoorE, 1, 1)
        local sLockType = string.sub(gzTextVar.zRoomList[iRoomIndex].sDoorE, 2)
        
        --Is the door closed?
        if(sDoorState == "C") then
            
            --Check key states. 
            local bOpenedDoor = true
            local sPrintString = "You open the door." .. gsDE
            local sOpenSound = "Doll|OpenDoor"
            
            --Clay lock, triggers the special sequence if the clay house is not disarmed. Is otherwise
            -- the same as a normal lock.
            if(sLockType == " Clay") then
                if(gzTextVar.bClayDisarmed == false) then
                    gzTextVar.bClayDoorThisTurn = true
                end
            
            --Unopenable.
            elseif(sLockType == " ClayUnopenable") then
                bOpenedDoor = false
                sPrintString = "The door has merged with the wall, completely cutting access from this room!" .. gsDE
            
            --Check if the lock can't be opened.
            elseif(sLockType ~= " Normal" and sLockType ~= " None") then
                bOpenedDoor, sPrintString = fnCheckKeyStates(sLockType)
                sOpenSound = "Doll|OpenDoorLocked"
            end
            
            --Check if we failed to open the door.
            if(bOpenedDoor == false) then
                TL_SetProperty("Append", sPrintString)
                fnMarkLockAsKnown(iRoomIndex, gzTextCon.iDirEast)
                return
            end
            
            --Small keys destroy one of the small keys in our inventory.
            if(sLockType == " Small") then
                for i = 1, gzTextVar.gzPlayer.iItemsTotal, 1 do
                    if(gzTextVar.gzPlayer.zaItems[i].sDisplayName == "small key") then
                        fnRemoveItemFromInventory(i)
                        break
                    end
                end
            end
            
            --We moved through the door, so open it.
            TL_SetProperty("Append", sPrintString)
            LM_ExecuteScript(gzTextVar.sRootPath .. "Functions/Modify Door State.lua", gzTextVar.gzPlayer.sLocation, "O" .. sLockType, "E", ciDoNotModifyVisibility, 1)
            fnMarkLockAsKnown(iRoomIndex, gzTextCon.iDirEast)
            
            --SFX.
            AudioManager_PlaySound(sOpenSound)
        end
    end
    
elseif(sFirstLetter == "w") then
    if(gzTextVar.zRoomList[iRoomIndex].sDoorW ~= nil) then
        
        --Get the string past the first letter.
        local sDoorState = string.sub(gzTextVar.zRoomList[iRoomIndex].sDoorW, 1, 1)
        local sLockType = string.sub(gzTextVar.zRoomList[iRoomIndex].sDoorW, 2)
        
        --Is the door closed?
        if(sDoorState == "C") then
            
            --Check key states. 
            local bOpenedDoor = true
            local sPrintString = "You open the door." .. gsDE
            local sOpenSound = "Doll|OpenDoor"
            
            --Clay lock, triggers the special sequence if the clay house is not disarmed. Is otherwise
            -- the same as a normal lock.
            if(sLockType == " Clay") then
                if(gzTextVar.bClayDisarmed == false) then
                    gzTextVar.bClayDoorThisTurn = true
                end
            
            --Unopenable.
            elseif(sLockType == " ClayUnopenable") then
                bOpenedDoor = false
                sPrintString = "The door has merged with the wall, completely cutting access from this room!" .. gsDE
                
            --Check if the lock can't be opened.
            elseif(sLockType ~= " Normal" and sLockType ~= " None") then
                bOpenedDoor, sPrintString = fnCheckKeyStates(sLockType)
                sOpenSound = "Doll|OpenDoorLocked"
            end
            
            --Check if we failed to open the door.
            if(bOpenedDoor == false) then
                TL_SetProperty("Append", sPrintString)
                fnMarkLockAsKnown(iRoomIndex, gzTextCon.iDirWest)
                return
            end
            
            --Small keys destroy one of the small keys in our inventory.
            if(sLockType == " Small") then
                for i = 1, gzTextVar.gzPlayer.iItemsTotal, 1 do
                    if(gzTextVar.gzPlayer.zaItems[i].sDisplayName == "small key") then
                        fnRemoveItemFromInventory(i)
                        break
                    end
                end
            end
            
            --We moved through the door, so open it.
            TL_SetProperty("Append", sPrintString)
            LM_ExecuteScript(gzTextVar.sRootPath .. "Functions/Modify Door State.lua", gzTextVar.gzPlayer.sLocation, "O" .. sLockType, "W", ciDoNotModifyVisibility, 1)
            fnMarkLockAsKnown(iRoomIndex, gzTextCon.iDirWest)
            
            --SFX.
            AudioManager_PlaySound(sOpenSound)
        end
    end
end

--Unmark the previous location, and mark this one as visible.
fnUnmarkMinimapForPosition(gzTextVar.gzPlayer.sLocation)
fnMarkMinimapForPosition(sDestination)

--Success! Move the character.
gzTextVar.gzPlayer.sPrevLocation = gzTextVar.gzPlayer.sLocation
gzTextVar.gzPlayer.sLocation = sDestination
TL_SetProperty("Set Map Focus", -fX, -fY)

--[Stranger Grouping]
--Check if the Stranger grouping is different for this room.
if(gzTextVar.zStranger ~= nil) then
    local sOldGrouping = gzTextVar.zStranger.sPlayerCurrentGrouping
    local sNewGrouping = gzTextVar.zRoomList[iDestIndex].sStrangerGroup

    --New Grouping is "Null", so do nothing.
    if(sNewGrouping == "Null") then

    --New Grouping is the same as the old one, so do nothing.
    elseif(sOldGrouping == sNewGrouping) then

    --New Grouping is different, update it. We store the previous grouping if and only if it was not "None".
    else
        if(gzTextVar.zStranger.sPlayerCurrentGrouping ~= "None") then
            gzTextVar.zStranger.sPlayerPreviousGrouping = gzTextVar.zStranger.sPlayerCurrentGrouping
        end
        gzTextVar.zStranger.sPlayerCurrentGrouping = sNewGrouping
    end
end

--Change the indicator's position.
TL_SetProperty("Move Entity Indicator", fOldX, fOldY, fOldZ, "Player", fX, fY, fZ)
TL_SetProperty("Player World Position", fX, fY, fZ)

--SFX.
fnRandomFootstep()

--Rendering handler. Top floor renders the middle floor, otherwise no secondary rendering.
TL_SetProperty("Set Rendering Z Level", fZ)
if(fZ < 0) then
    TL_SetProperty("Set Under Rendering Z Level", fZ+1, 0)
else
    TL_SetProperty("Set Under Rendering Z Level", ciDoNotRenderUnder, ciDoNotRenderUnder)
end

--Show the room's name, list of entities, and objects.
TL_SetProperty("Append", "Arriving at " .. sDestination .. "." .. gsDE)

--Call the room's description handler. It will flag gbHandledInput if it printed anything.
gbHandledInput = false
gzTextVar.bIsExaminationCheck = true
LM_ExecuteScript(gzTextVar.sRoomHandlers .. sDestination .. ".lua", sString)
gzTextVar.bIsExaminationCheck = false

--Input was not handled, list the entities and objects here.
if(gbHandledInput == false) then
    fnListEntities(gzTextVar.gzPlayer.sLocation, true)
    fnListObjects(gzTextVar.gzPlayer.sLocation, true)
end

--Reresolve fading cases.
TL_SetProperty("Reresolve Fades")

--End the turn.
gbHandledInput = true
LM_ExecuteScript(gzTextVar.sTurnEndScript)