• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

RevScripts use levers around map

T

Tibia Demon

Guest
i made mistake checking table again
i made this script player should use levers with actionid 5009 in different positions around map
1 if player use lever he didnt use before it send teleport effect and add storage
2 if player use lever he clicked before it send poff effect
3 when player used all levers it and try reuse any lever again it add one last storage more
4 when player used all levers and got last storage too and try reuse any lever again it send poff effect
i need all 4 check pls no remove any i use later for missions
it was working i think i made mistake with end or return true
i explained with tag too in script
i will add sendTextMessage later for next mission i wait friend translate
Lua:
local Mission3Lever = Action()
local LeverAID = 5009
local kickPosition = Position(1070, 1225, 7)
local LastLeverStorage = PlayerStorageKeys.lastleverstorage -- storage to add after used all levers but have to reuse 1 time more
local LeverMission3Table = {
    {
        leverstorage = PlayerStorageKeys.leverstorage1, -- storage to add to player
        leverpos = Position(1070, 1109, 7)
    },
    {
        leverstorage = PlayerStorageKeys.leverstorage2, -- storage to add to player
        leverpos = Position(1087, 1115, 7)
    },
    {
        leverstorage = PlayerStorageKeys.leverstorage3 -- storage to add to player
        leverpos = Position(1098, 1120, 7)
    }
}

function Mission3Lever.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local hasAllStorages = true
    for v, k in pairs(LeverMission3Table) do
        if player:getStorageValue(k.leverstorage) ~= 1 then
            hasAllStorages = false
        end
        local tile = Tile(k.leverpos)
        if not tile then
            return true
        end
        if toPosition == k.leverpos then
            if player:getStorageValue(k.leverstorage) ~= 1 then -- here when player didnt use all levers so it add lever storage by checking lever position in table
                player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
                player:setStorageValue(k.leverstorage, 1)
                toPosition:sendMagicEffect(CONST_ME_TELEPORT)
                player:teleportTo(kickPosition)
            elseif not hasAllStorages and player:getStorageValue(k.leverstorage) == 1 then -- here when player try to use same lever he already done used before
                toPosition:sendMagicEffect(CONST_ME_POFF)
                player:getPosition():sendMagicEffect(CONST_ME_POFF)
                player:teleportTo(kickPosition)
            end
        elseif hasAllStorages and player:getStorageValue(LastLeverStorage) == 1 then -- here when used all lever in map and gained (LastLeverStorage) so it only kick with poff effect
            toPosition:sendMagicEffect(CONST_ME_POFF)
            player:getPosition():sendMagicEffect(CONST_ME_POFF)
            player:teleportTo(kickPosition)
        elseif hasAllStorages and player:getStorageValue(LastLeverStorage) ~= 1 then -- here when used all lever in map but need to use any lever of them one more time to gain (LastLeverStorage) i need LastLeverStorage for other missions
            player:setStorageValue(LastLeverStorage, 1)
            toPosition:sendMagicEffect(CONST_ME_POFF)
            player:getPosition():sendMagicEffect(CONST_ME_POFF)
            player:teleportTo(kickPosition)
        end
    end
    return true
end
Mission3Lever:aid(LeverAID)
Mission3Lever:register()
 
Solution
No.

You need to stop and think about what is happening in your script.

for v, k in pairs(LeverMission3Table) do
This line is looping through your table.
pairs doesn't have a set execution order, so it's essentially random.
You have no control over what part of the table it checks first or last, So, you must assume when using pairs, that it's going to run through the entire table, unless you stop it yourself.

Under that assumption, you can safely assume, that hasAllStorages is only true, if the entire loop has completed.
We start with the assumption that it is true, until the loop checks a storage and finds it false.

So, knowing that we cannot know if it's true until the loop has completed.. we cannot use it inside...
No.

You need to stop and think about what is happening in your script.

for v, k in pairs(LeverMission3Table) do
This line is looping through your table.
pairs doesn't have a set execution order, so it's essentially random.
You have no control over what part of the table it checks first or last, So, you must assume when using pairs, that it's going to run through the entire table, unless you stop it yourself.

Under that assumption, you can safely assume, that hasAllStorages is only true, if the entire loop has completed.
We start with the assumption that it is true, until the loop checks a storage and finds it false.

So, knowing that we cannot know if it's true until the loop has completed.. we cannot use it inside of the loop to verify other information.
So immediately we know that lines 36, 41 and 45 have a chance of being incorrect.

And, since we don't know when hasAllStorages will switch from true to false.. or if it will never change.. we can't rely on any of those lines working correctly.

--
So, let's start from scratch and do your script line by line.
Lua:
local Mission3Lever = Action()

local leverAID = 5009
local kickPosition = Position(1070, 1225, 7)
local lastLeverStorage = PlayerStorageKeys.lastleverstorage

local leverMission3Table = {
    {
        leverStorage = PlayerStorageKeys.leverstorage1,
        leverPos = Position(1070, 1109, 7)
    },
    {
        leverStorage = PlayerStorageKeys.leverstorage2,
        leverPos = Position(1087, 1115, 7)
    },
    {
        leverStorage = PlayerStorageKeys.leverstorage3
        leverPos = Position(1098, 1120, 7)
    }
}

function Mission3Lever.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    
    return true
end

Mission3Lever:aid(LeverAID)
Mission3Lever:register()

1 if player use lever he didnt use before it send teleport effect and add storage
2 if player use lever he clicked before it send poff effect
Both of these are very similar to each other (true or false of same check) so we'll do them together.

Because you refuse to use multiple actionId's for whatever reason, we are forced to loop through the table.
Lua:
function Mission3Lever.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    
    -- we have multiple ways to loop through the table, (ipairs, pairs, for)
    -- But since we don't know which of the levers a player might use, the execution order of the table doesn't matter
    -- so we'll use the fastest loop type (pairs)
    
    for v, k in pairs(leverMission3Table) do
        
        -- since we don't know which lever is being used, we need to figure that out
        -- so we'll compare the position of the lever, to the item position (and since we know the lever cannot be in the player inventory, we can assume that toPosition is the lever we clicked on the ground.)
        if k.leverPos == toPosition then
            
            -- now that we know we are looking at the correct lever, we can check it's storage.
            if player:getStorageValue(k.leverstorage) == 1 then
                -- lever has been used before..
                
                toPosition:sendMagicEffect(CONST_ME_POFF)
                player:getPosition():sendMagicEffect(CONST_ME_POFF)
                return true -- we return true because we have reached an 'end point'. We don't need to check anything further, so end the script here.
            end
            
            -- if it reaches here, we know the lever has not been used before
            toPosition:sendMagicEffect(CONST_ME_TELEPORT)
            player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
            player:setStorageValue(k.leverstorage, 1)
            return true -- same as above, we have reached an end point. We don't need to check anything further, so end the script here.
        end
    end
    return true
end

3 when player used all levers it and try reuse any lever again it add one last storage more
4 when player used all levers and got last storage too and try reuse any lever again it send poff effect
Same as before, these are true/false statements, so we'll do them together again.

when player used all levers -> this means we need to loop through all of the storages to verify if the player has them
Our current script is looping through all of the positions, and then checking a single storage..
But now we need to keep track of all storages we check.

So let's add that in
Lua:
function Mission3Lever.onUse(player, item, fromPosition, target, toPosition, isHotkey)

    local hasAllStorages = true -- we assume it's true until proven otherwise. (inside the loop)
    
    -- ignore the loop for now, since it needs to be modified to check this new inclusion
    for v, k in pairs(leverMission3Table) do
        .
        .
        .
    end
    
    -- we cannot use hasAllStorages inside the loop, because it may be true or false, and may get false positives.
    -- so after the loop has confirmed it to be true or false, we can now use it to do checks.
    -- slight irony here, is that in order to get past the loop, we know hasAllStorage has to be true.. so we only need to check if the player has the final storage or not
    
    if player:getStorageValue(lastLeverStorage) == 1 then -- if player has final storage
        toPosition:sendMagicEffect(CONST_ME_POFF)
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
        return true
    end
    
    -- if player doesn't have final storage
    player:setStorageValue(k.leverstorage, 1)
    return true
end

Now all that's left is to finish modifying the loop with the previous requirements in mind.
Lua:
function Mission3Lever.onUse(player, item, fromPosition, target, toPosition, isHotkey)

    local hasAllStorages = true
    
    for v, k in pairs(leverMission3Table) do
    
        -- since all the storages matter now, not just the particular lever we are using, we check the storage first.
        if player:getStorageValue(k.leverstorage) ~= 1 then
            
            -- if the player does not have the storage, we check if it's the current lever using the position, like before.
            if k.leverPos == toPosition then
                toPosition:sendMagicEffect(CONST_ME_TELEPORT)
                player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
                player:setStorageValue(k.leverstorage, 1)
                return true -- and once again, we have found an 'end point', so end the script here to save resources.
            end
            hasAllStorages = false -- assuming that this is some other lever, we let the script know that we don't have all the storages.
            -- we cannot 'return true' and break the loop, because there is no guarentee that we have found out if this is this lever has been used previously.
        end
        
        -- this is what the loop looked like before.
        if k.leverPos == toPosition then
            if player:getStorageValue(k.leverstorage) == 1 then
                toPosition:sendMagicEffect(CONST_ME_POFF)             -- we actually have a conflict of interest here.
                player:getPosition():sendMagicEffect(CONST_ME_POFF)   -- if we play these effects because the storage has been obtained before   --
                return true                                                                                                                      --
            end                                                                                                                                  --
            toPosition:sendMagicEffect(CONST_ME_TELEPORT)                                                                                        --
            player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)                                                                              --
            player:setStorageValue(k.leverstorage, 1)                                                                                            --
            return true                                                                                                                          --
        end                                                                                                                                      --
    end                                                                                                                                          --
                                                                                                                                                 --
    if player:getStorageValue(lastLeverStorage) == 1 then                                                                                        --
        toPosition:sendMagicEffect(CONST_ME_POFF)                                                                                                --
        player:getPosition():sendMagicEffect(CONST_ME_POFF)                                                                                      --
        return true                                                                                                                              --
    end                                                                                                                                          --
                                                                                                                                                 --
    player:setStorageValue(k.leverstorage, 1)   -- then if all of the storages have been received, this will receive the effect as well  <---------
    return true
end

So let's resolve that conflict.
Lua:
function Mission3Lever.onUse(player, item, fromPosition, target, toPosition, isHotkey)

    -- so because of that conflict of interest, we need to assume that the storages have not been obtained.
    -- instead of true/false, we shall now count all of the storages the player does have.
    local storageCount = 0 -- start at 0. (and rename from hasAllStorages to storageCount to reflect what we are doing)
    
    for v, k in pairs(leverMission3Table) do
        if player:getStorageValue(k.leverstorage) == 1 then -- now we check if they do have the storage
            storageCount = storageCount + 1 -- and add to their count
            
        else -- if they don't have the storage
            if k.leverPos == toPosition then -- check the position like before.
                toPosition:sendMagicEffect(CONST_ME_TELEPORT)
                player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
                player:setStorageValue(k.leverstorage, 1)
                return true
            end
        end
    end
    
    -- so now we need to check if they have all the storages.
    if storageCount ~= #leverMission3Table then -- so we check that here. (counting the number of entries in the table against how many storages they have)
        
        -- we can now safely assume that they don't have all the storages.
        -- at this point we know they used a lever for a 2nd time, so here is where we resolve the conflict of interest
        -- now we can safely send the magic effects.
        toPosition:sendMagicEffect(CONST_ME_POFF)
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
        return true -- and this becomes an 'end point'
    end
    
    if player:getStorageValue(lastLeverStorage) == 1 then
        toPosition:sendMagicEffect(CONST_ME_POFF)
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
        return true
    end
    
    player:setStorageValue(k.leverstorage, 1)
    return true
end

And thus, we finish the script.
Lua:
local Mission3Lever = Action()

local leverAID = 5009
local kickPosition = Position(1070, 1225, 7) -- never used, because none of your descriptions called for teleporting players.
local lastLeverStorage = PlayerStorageKeys.lastleverstorage

local leverMission3Table = {
    {
        leverStorage = PlayerStorageKeys.leverstorage1,
        leverPos = Position(1070, 1109, 7)
    },
    {
        leverStorage = PlayerStorageKeys.leverstorage2,
        leverPos = Position(1087, 1115, 7)
    },
    {
        leverStorage = PlayerStorageKeys.leverstorage3
        leverPos = Position(1098, 1120, 7)
    }
}

function Mission3Lever.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local storageCount = 0
    
    for v, k in pairs(leverMission3Table) do
        if player:getStorageValue(k.leverstorage) == 1 then
            storageCount = storageCount + 1
        else
            if k.leverPos == toPosition then
                toPosition:sendMagicEffect(CONST_ME_TELEPORT)
                player:getPosition():sendMagicEffect(CONST_ME_TELEPORT)
                player:setStorageValue(k.leverstorage, 1)
                return true -- 1 if player use lever he didnt use before it send teleport effect and add storage
            end
        end
    end
    
    if storageCount ~= #leverMission3Table then
        toPosition:sendMagicEffect(CONST_ME_POFF)
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
        return true -- 2 if player use lever he clicked before it send poff effect
    end
    
    if player:getStorageValue(lastLeverStorage) == 1 then
        toPosition:sendMagicEffect(CONST_ME_POFF)
        player:getPosition():sendMagicEffect(CONST_ME_POFF)
        return true -- 4 when player used all levers and got last storage too and try reuse any lever again it send poff effect
    end
    
    player:setStorageValue(k.leverstorage, 1)
    return true -- 3 when player used all levers it and try reuse any lever again it add one last storage more
end

Mission3Lever:aid(leverAID)
Mission3Lever:register()
 
Solution
Back
Top