• 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!

Action Moving Boat

Limos

Senator
Premium User
Joined
Jun 7, 2010
Messages
10,013
Solutions
8
Reaction score
3,056
Location
Netherlands
Tested with TFS 0.3.6 and TFS 0.2.14
Should work on almost every server.

I was making this script for someone, but since I couldn't find a script on otland that works the same way I decided to release it here and maybe it will be useful to other people aswell.

3o6ozC2wGVXPcfXVSM.gif


How does it work:
Add actionid 6901 to the middle part of the boat.
Where the boat should go, add water with itemid 4820.
The borders the boat will go on when it goes on land, should be the ones in the config endborders.
The border next to it should have the same itemid (so atleast 2 straight borders next to eachother), because this is what makes the boat turn.
ZZwopm.png



actions.xml
TFS 0.3/0.4
Code:
<action actionid="6901" event="script" value="other/movingboat.lua"/>

TFS 0.2/1.0
Code:
<action actionid="6901" script="other/movingboat.lua"/>

movingboat.lua
Code:
-- Moving Boat by Limos

local config = {
   endborders = {4644, 4646},
   speed = 300,
   ignorefirstborders = 3
}

local fight = createConditionObject(CONDITION_INFIGHT)
setConditionParam(fight, CONDITION_PARAM_TICKS, -1)

local function comparePos(poss, pos)
     return pos.x == poss.x and pos.y == poss.y
end

local n, s = 0, 0

local function getRightPos(poss, last)

     ps = {
         {x = poss.x, y = poss.y - 1, z = poss.z},
         {x = poss.x + 1, y = poss.y, z = poss.z},
         {x = poss.x, y = poss.y + 1, z = poss.z},
         {x = poss.x - 1, y = poss.y, z = poss.z}
     }
     for _, pos in pairs(ps) do
         if getTileItemById(pos, 4820).uid > 0 then
             if not comparePos(last, pos) then
                 p = pos
                 return p
             end
         else
             for b = 1, #config.endborders do
                 if getTileItemById(pos, config.endborders[b]).uid > 0 and s > config.ignorefirstborders then
                     n = n + 1
                     p = pos
                     return p
                 end
             end
         end
     end
end

local function doTravel(cid, poss, last)

     getRightPos(poss, last)
     travel = p.x > poss.x and "east" or (p.y < poss.y and "north" or (p.y > poss.y and "south" or (p.x < poss.x and "west" or "false")))
     if n > 1 then
         p = poss
     end
     if travel == "false" then
        if getCreatureCondition(cid, CONDITION_INFIGHT) then
             doRemoveCondition(cid, CONDITION_INFIGHT)
         end
         n = 0
         s = 0
         return false
     end

     local des = {
         ["north"] = {cPos = {{x = p.x, y = p.y - 1, z = p.z}, p, {x = p.x, y = p.y + 1, z = p.z}}, dir = 0, boat = {3587, 3589, 3591}},
         ["east"] = {cPos = {{x = p.x + 1, y = p.y, z = p.z}, p, {x = p.x - 1, y = p.y, z = p.z}}, dir = 1, boat = {3596, 3594, 3592}},
         ["south"] = {cPos = {{x = p.x, y = p.y + 1, z = p.z}, p, {x = p.x, y = p.y - 1, z = p.z}}, dir = 2, boat = {3591, 3589, 3587}},
         ["west"] = {cPos = {{x = p.x - 1, y = p.y, z = p.z}, p, {x = p.x + 1, y = p.y, z = p.z}}, dir = 3, boat = {3592, 3594, 3596}}
     }

     local x = des[travel]
     if x then
         for x = p.x - 2, p.x + 2 do
             for y = p.y - 2, p.y + 2 do
                 pos = {x = x, y = y, z = p.z}
                 for id = 3587, 3596 do
                     if getTileItemById(pos, id).uid > 0 then
                         doRemoveItem(getTileItemById(pos, id).uid, 1)
                     end
                 end
             end
         end
         for c = 1, #x.boat do
             its = doCreateItem(x.boat[c], 1, x.cPos[c])
             if n > 0 and c == 2 then
                 doSetItemActionId(its, 6901)
             end
         end
         doTeleportThing(cid, x.cPos[2], false)
         doCreatureSetLookDir(cid, x.dir)
         if n > 1 then
             if getCreatureCondition(cid, CONDITION_INFIGHT) then
                 doRemoveCondition(cid, CONDITION_INFIGHT)
             end
             n = 0
             s = 0
             return false
         end
         s = s + 1
     end
     return addEvent(doTravel, config.speed, cid, p, poss)
end

function onUse(cid, item, fromPosition, itemEx, toPosition)

     if getCreatureCondition(cid, CONDITION_INFIGHT) then
         return doPlayerSendCancel(cid, "You can't travel when you're in a fight.")
     end
     doTeleportThing(cid, toPosition)
     doAddCondition(cid, fight)
     doTravel(cid, getPlayerPosition(cid), getPlayerPosition(cid))
     return true
end

Movement script (to prevent people stepping out of the boat on the walkable water when the boat stands still)

movements.xml
TFS 0.3/0.4
Code:
<movevent type="StepIn" itemid="4820" event="script" value="water.lua"/>
TFS 0.2/1.0
Code:
<movevent event="StepIn" itemid="4820" script="water.lua"/>

water.lua
Code:
local boatids = {3589, 3594}

function onStepIn(cid, item, position, fromPosition)

   for _, id in pairs(boatids) do
     if getTileItemById(fromPosition, id).uid > 0 then
       return doTeleportThing(cid, fromPosition)
     end
   end
   return true
end


If you use TFS 0.3/0.4, add this in 050-function.lua (if it's not already there).
Code:
function doSetItemActionId(uid, actionid)
   return doItemSetAttribute(uid, "aid", actionid)
end



Questions or bugs? Let me know.
 
Last edited:
Oh no you didnt :) Really really cool Limos, thank you!!
 
Thanks for the comments.

There were some people who mentioned possible issues incase people want to use the boat script for places where players can only go with the boat (when they die/logout, the boat won't return).
So for people who want that, you can use a function like this and add it in a login, logout and preparedeath script.
Code:
function returnBoat(cid)

   local config = {
     storage = 42956,
     removeBoat = {x = 61, y = 86, z = 7}, -- middle part of the boat
     firstBoat = {
       {pos = {x = 69, y = 122, z = 7}, id = 3592},
       {pos = {x = 70, y = 122, z = 7}, id = 3594},
       {pos = {x = 71, y = 122, z = 7}, id = 3596}
     }
   }

   if(getPlayerStorageValue(cid, config.storage) == 1) then
     local p = config.removeBoat
     for x = p.x - 1, p.x + 1 do
       for y = p.y - 1, p.y + 1 do
         pos = {x = x, y = y, z = p.z}
         for id = 3587, 3596 do
           if(getTileItemById(pos, id).uid > 0) then
             doRemoveItem(getTileItemById(pos, id).uid, 1)
           end
         end
       end
     end
     for b = 1, #config.firstBoat do
       if(getTileItemById(config.firstBoat[b].pos, config.firstBoat[b].id).uid < 1) then
         boat = doCreateItem(config.firstBoat[b].id, 1, config.firstBoat[b].pos)
         if(b == 2) then
             doSetItemActionId(boat, 6901)
         end
       end
     end
   end
   return true
end
You can add it in a lib file and then use the function like this.
Code:
returnBoat(cid)

Then set the storage to 1 and -1 when using the boat.
Code:
setPlayerStorageValue(cid, 42956, getPlayerStorageValue(cid, 42956) == -1 and 1 or -1)

Then in a login script (under the function)
Code:
if(getPlayerStorageValue(cid, 42956) == 1) then
     doTeleportThing(cid, getTownTemplePosition(getPlayerTown(cid)))
     setPlayerStorageValue(cid, 42956, -1)
end
 
Last edited:
Thanks, is very useful for me!

I have a kind of idea with this action!

Thank you very much, sorry for my bad english, i talk spanish xD
 
Hey im getting: Can not load script: scripts/movingboat.lua

data/actions/scripts/nieuw/movingboat.lua:2: unexpected symbol near '}'

In the forgotten server 1.0 can u please help me? would love to use the script:)
 
I have this error:
Code:
[5/1/2014 14:37:57] [Error - Action Interface]
[5/1/2014 14:37:57] mods/scripts/Scripts en General/Azzkaban Acciones Respaldo/movingboat.lua:onUse
[5/1/2014 14:37:57] Description:
[5/1/2014 14:37:57] ...en General/Azzkaban Acciones Respaldo/movingboat.lua:47: attempt to index global 'p' (a nil value)
[5/1/2014 14:37:57] stack traceback:
[5/1/2014 14:37:57]     ...en General/Azzkaban Acciones Respaldo/movingboat.lua:47: in function 'doTravel'
[5/1/2014 14:37:57]     ...en General/Azzkaban Acciones Respaldo/movingboat.lua:107: in function <...en General/Azzkaban Acciones Respaldo/movingboat.lua:100>


Edit: Work 100% :)
h42.gif
 
Last edited:
Thanks for the comments.

An other version of the moving boat, requested by andree.
Here it works with 2 boats, 1 at each side. Using 1 boat will remove the other and recreate the first one when the boat stops.
This way there will always be 1 boat at each side and people can keep using them from both sides.
Code:
local config = {
     endborders = {4644, 4646},
     speed = 300,
     ignorefirstborders = 3
}

local boatpositions = {
     boat1 = {
         {id = 3592, pos = {x = 69, y = 122, z = 7}},
         {id = 3594, pos = {x = 70, y = 122, z = 7}},
         {id = 3596, pos = {x = 71, y = 122, z = 7}}
     },
     boat2 = {
         {id = 3592, pos = {x = 60, y = 86, z = 7}},
         {id = 3594, pos = {x = 61, y = 86, z = 7}},
         {id = 3596, pos = {x = 62, y = 86, z = 7}}
     }
}

local fight = createConditionObject(CONDITION_INFIGHT)
setConditionParam(fight, CONDITION_PARAM_TICKS, -1)

local function doRelocateBoat(boat, remove)
     if remove then
         for x = 1, #boatpositions.boat1 do
             if boat == 1 then
                 doRemoveItem(getTileItemById(boatpositions.boat2[x].pos, boatpositions.boat2[x].id).uid, 1)
             else
                 doRemoveItem(getTileItemById(boatpositions.boat1[x].pos, boatpositions.boat1[x].id).uid, 1)
             end
         end
     else
         for c = 1, #boatpositions.boat1 do
             if boat == 1 then
                 b = doCreateItem(boatpositions.boat1[c].id, 1, boatpositions.boat1[c].pos)
             else
                 b = doCreateItem(boatpositions.boat2[c].id, 1, boatpositions.boat2[c].pos)
             end
             if c == 2 then
                 doSetItemActionId(b, 6901)
             end
         end
     end
     return true
end

local function comparePos(poss, pos)
   return pos.x == poss.x and pos.y == poss.y
end

local n, s = 0, 0

local function getRightPos(poss, last)
     ps = {
         {x = poss.x, y = poss.y - 1, z = poss.z},
         {x = poss.x + 1, y = poss.y, z = poss.z},
         {x = poss.x, y = poss.y + 1, z = poss.z},
         {x = poss.x - 1, y = poss.y, z = poss.z}
     }
     for _, pos in pairs(ps) do
         if getTileItemById(pos, 4820).uid > 0 then
             if(not comparePos(last, pos)) then
                 p = pos
                 return p
             end
         else
             for b = 1, #config.endborders do
                 if getTileItemById(pos, config.endborders[b]).uid > 0 and s > config.ignorefirstborders then
                     n = n + 1
                     p = pos
                     return p and n
                 end
             end
         end
     end
end

local function doTravel(cid, poss, last, boat)
     getRightPos(poss, last)
     travel = p.x > poss.x and "east" or (p.y < poss.y and "north" or (p.y > poss.y and "south" or (p.x < poss.x and "west" or "false")))
     if n > 1 then
         p = poss
     end
     if travel == "false" then
         doRelocateBoat(boat, false)
         doRemoveCondition(cid, CONDITION_INFIGHT)
         n = 0
         s = 0
         return false
     end

     local des = {
         ["north"] = {cPos = {{x = p.x, y = p.y - 1, z = p.z}, p, {x = p.x, y = p.y + 1, z = p.z}}, dir = 0, boat = {3587, 3589, 3591}},
         ["east"] = {cPos = {{x = p.x + 1, y = p.y, z = p.z}, p, {x = p.x - 1, y = p.y, z = p.z}}, dir = 1, boat = {3596, 3594, 3592}},
         ["south"] = {cPos = {{x = p.x, y = p.y + 1, z = p.z}, p, {x = p.x, y = p.y - 1, z = p.z}}, dir = 2, boat = {3591, 3589, 3587}},
         ["west"] = {cPos = {{x = p.x - 1, y = p.y, z = p.z}, p, {x = p.x + 1, y = p.y, z = p.z}}, dir = 3, boat = {3592, 3594, 3596}}
     }

     local x = des[travel]
     if x then
         for x = p.x - 2, p.x + 2 do
             for y = p.y - 2, p.y + 2 do
                 pos = {x = x, y = y, z = p.z}
                 for id = 3587, 3596 do
                     if(getTileItemById(pos, id).uid > 0) then
                         doRemoveItem(getTileItemById(pos, id).uid, 1)
                     end
                 end
             end
         end
         for c = 1, #x.boat do
             its = doCreateItem(x.boat[c], 1, x.cPos[c])
             if n > 0 and c == 2 then
                 doSetItemActionId(its, 6901)
             end
         end
         doTeleportThing(cid, x.cPos[2], false)
         doCreatureSetLookDir(cid, x.dir)
         if n > 1 then
             doRelocateBoat(boat, false)
             doRemoveCondition(cid, CONDITION_INFIGHT)
             n = 0
             s = 0
             return false
         end
         s = s + 1
     end
     return addEvent(doTravel, config.speed, cid, p, poss, boat)
end

function onUse(cid, item, fromPosition, itemEx, toPosition)

     if getCreatureCondition(cid, CONDITION_INFIGHT) then
         return doPlayerSendCancel(cid, "You can't travel when you're in a fight.")
     end

     local boat = 1
     if comparePos(toPosition, boatpositions.boat2[2].pos) then
         boat = 2
     end
     doRelocateBoat(boat, true)
     doTeleportThing(cid, toPosition)
     doAddCondition(cid, fight)
     doTravel(cid, getPlayerPosition(cid), getPlayerPosition(cid), boat)
     return true
end
 
Last edited:
Back
Top