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

CreatureEvent [TFS 1.1] Fast Travel To Unlocked Locations, modalwindow

RazorBlade

Retired Snek
Joined
Nov 7, 2009
Messages
2,015
Solutions
3
Reaction score
629
Location
Canada
If you've seen any of my other systems that are released, you'll know they're inspired by Skyrim. So here's another! I decided to play around and make a fast travel system that allows players to instantly teleport to a certain location that they have previously visited.

Pics or it didn't happen:
Say !travel
Screenshot1_zpssozy9zvu.png

Notice there's nothing in the list yet
Screenshot2_zpsutnwombg.png

Go find a location
Screenshot3_zpsoxpc8tlr.png

Go find another for good measure
Screenshot4_zpszisvurk2.png

We have one option for a location.
Screenshot5_zpsovufoe3m.png

Expand it to see all the sublocations within it
Screenshot6_zpsnhyekqav.png

Select Depot then click Travel or hit "enter" on your keyboard. Oh look! We're at the depot.
Screenshot7_zpswpbtvcx3.png

"Used" a map with actionid 5004, allowing me to discover some new locations in a far away land
Screenshot8_zpstmsjcxw3.png

More location options!
Screenshot9_zpswyxosaug.png

Expand Solare. Looks pretty similar because both locations only have two sublocations with the same names for this example.
Screenshot10_zpszh0myynm.png

Travel to the depot, and we find ourselves in a strange new place that we never visited before.
Screenshot11_zps0uo9jyc7.png

So here is everything you need:
Recommended: [TFS 1.x] lib folder in "data" like 0.4
In creaturescripts.xml:
Code:
<event type="modalwindow" name="fasttravel_modal" script="fasttravel.lua"/>
In login.lua, register the event:
Code:
player:registerEvent("fasttravel_modal")
In creaturescripts/scripts create fasttravel.lua and enter:
Code:
function onModalWindow(player, modalWindowId, buttonId, choiceId)
    player:locationWindowChoice(modalWindowId, buttonId, choiceId)
    player:travelWindowChoice(modalWindowId, buttonId, choiceId)
    return true
end
If you use the system by @zbizu [TFS 1.x] lib folder in "data" like 0.4 then just create the script fasttravel.lua in data/lib and enter:
Code:
-- config
local modalId = 1001
local choice = nil
tlocations = {
    [1] = {name = "Infernus", storage = 37101,
        sublocations = {
            [1] = {pos = {x = 7000, y = 2000, z = 7}, name = "Temple", storage = 37102},
            [2] = {pos = {x = 7031, y = 1955, z = 7}, name = "Depot", storage = 37103},
        }
    },
    [2] = {name = "Solare", storage = 37111,
        sublocations = {
            [1] = {pos = {x = 2000, y = 4000, z = 7}, name = "Temple", storage = 37112},
            [2] = {pos = {x = 2000, y = 4150, z = 7}, name = "Depot", storage = 37113},
        }
    },

}

sublocations = {
    [37102] = 37101,
    [37103] = 37101,
    [37112] = 37111,
    [37113] = 37111
}

function Player:sendLocationWindow()
    local window = ModalWindow(modalId, "Fast Travel", "You can fast travel to any of the below locations.")
    local choices = 0
   
    for i = 1, #tlocations do
        if self:getStorageValue(tlocations[i]["storage"]) == 1 then
            window:addChoice(i, tlocations[i]["name"])
            choices = choices + 1
        end
    end
    if choices > 0 then
        window:addButton(1, "Expand")
        window:setDefaultEnterButton(1)
    end
    window:addButton(2, "Exit")
    window:setDefaultEscapeButton(2)
    window:sendToPlayer(self)
    return true
end

function Player:sendTravelWindow(location)
    local window = ModalWindow(modalId + 1, location["name"], "You can fast travel to any of the below locations.")
    local choices = 0
    for i = 1, #location["sublocations"] do
        if self:getStorageValue(location["sublocations"][i]["storage"]) == 1 then
            window:addChoice(i, location["sublocations"][i]["name"])
            choices = choices + 1
        end
    end
    if choices > 0 then
        window:addButton(1, "Travel")
        window:setDefaultEnterButton(1)
    end
    window:addButton(2, "Back")
    window:setDefaultEscapeButton(2)
    window:sendToPlayer(self)
    return true
end

function Player:locationWindowChoice(windowId, buttonId, choiceId)
    if windowId == modalId then
        if buttonId == 1 then
            choice = choiceId
            self:sendTravelWindow(tlocations[choiceId])
            return true
        end
        return false
    end
    return false
end

function Player:travelWindowChoice(windowId, buttonId, choiceId)
    if windowId == modalId + 1 then
        if buttonId == 1 then
            self:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You have arrived at " .. tlocations[choice]["sublocations"][choiceId]["name"] .. " in " .. tlocations[choice]["name"] .. ".")
            self:teleportTo(tlocations[choice]["sublocations"][choiceId]["pos"])
            self:setDirection(DIRECTION_SOUTH)
            return true
        elseif buttonId == 2 then
            self:sendLocationWindow()
        end
        return false
    end
   
    return false
end

Otherwise, create the script as above and save it in your main "data/" folder, then enter this in global.lua:
Code:
dofile('data/fasttravel.lua')

In talkactions.xml:
Code:
<talkaction words="!travel" script="fasttravel.lua"/>

In talkactions/scripts create fasttravel.lua and enter:
Code:
function onSay(player, words, param)
    if getCreatureCondition(player, CONDITION_INFIGHT) == false or getTilePzInfo(player:getPosition()) then
        player:sendLocationWindow()
    else
        player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You cannot fast travel while in combat.")
    end
    return false
end

Example of stepping onto a tile to discover a location:
Movements.xml:
Code:
<movevent event="StepIn" itemid="7351" script="discover.lua"/>

in movements/scripts, discover.lua:
Code:
function onStepIn(creature, item, position, fromPosition)
    local player = Player(creature)
    if not Player(player) then
        return false
    end
    if item.actionid > 37100 and item.actionid < 38000 then
        local storage = player:getStorageValue(item.actionid)
        if storage ~= 1 then
            player:setStorageValue(item.actionid, 1)
            player:setStorageValue(sublocations[item.actionid], 1)
            player:sendTextMessage(MESSAGE_INFO_DESCR, "You have discovered " .. tlocations[sublocations[item.actionid] - 37100]["sublocations"][item.actionid - 37101]["name"] .." in " .. tlocations[sublocations[item.actionid] - 37100]["name"] .. "!")
        end
    end
   
    return true
end

I decided to make script so that a player can use a map and based on the actionid of that map, they can automatically discover one or more locations.
I chose two different maps, but the id of the item does not matter as long as it's set in actions.xml.
In actions.xml:
Code:
<action itemid="1956" script="YOUR_FOLDER/travelmap.lua"/>
<action itemid="1957" script="YOUR_FOLDER/travelmap.lua"/>

in actions/scripts/YOUR_FOLDER, create travelmap.lua and enter:
Code:
function onUse(cid, item, fromPosition, target, toPosition, isHotkey)
    local versions = {
    [5001] = {storages = {37101, 37102, 37103}},
    [5002] = {storages = {37101, 37104}},
    [5003] = {storages = {37111, 37112, 37113}},
    [5004] = {storages = {37101, 37102, 37103, 37111, 37112, 37113}},
    }
    local discover = false
    local player = Player(cid)
    if not Player(player) then
        return false
    end
    if versions[item.actionid] then
        for i = 1, #versions[item.actionid]["storages"] do
        
            if player:getStorageValue(versions[item.actionid]["storages"][i]) ~= 1 then
                player:setStorageValue(versions[item.actionid]["storages"][i], 1)
                discover = true
            end
        end
        if discover then
            player:sendTextMessage(MESSAGE_INFO_DESCR, "You have discovered new locations that you can travel to!")
        end
    else
        return false
    end
    return true
end
The actionid (5001-5004 in this case) must be set on the map or other item of your choice, and then you can add storage values to that value in the table. You must include both the location storage and any sublocation storages within that location that you want to use if you want anything to appear in the sublocation list.



If you have any bugs or questions, post here. I won't answer PMs because if you have a problem, someone else probably does as well and I will only post solutions here so that everyone can see them.

This was tested on TFS 1.1 Final Release

EDIT:
I've adjusted the code in both lib/fastravel.lua and movements/scripts/discover.lua to accommodate the changes to how Unique IDs are handled. This system will now work fully in the final release of TFS 1.1

If you enjoy this, you should also check out my new action which goes hand-in-hand with this system: [TFS 1.1] Discover skills, quests, locations, spells from books like Skyrim
 
Last edited:
Added a movement script and made some changes to lib/fasttravel.lua
 
Added a second set of menus so that you can choose a location, like a city, then choose a destination within that city. It requires that you use unique id as well as actionid. Set the actionid the same for any locations in the the city or other overall location, then use uniqueid as the specific location within that city.
 
Added a description and walkthrough as to how to use and configure the system
 
You should put some screenshots... There's way too much text haha
 
I'll do that when I have a chance. :p I'm very close to my 10000 char limit so I'm gonna have to pastebin some of it I think xD
 
stop tagging me here ffs
once is enough, if I cared, I'd watch this thread
 

Congratulations, did you want a medal? I made this without referencing your script or the improved version that zbizu made, because I didn't know they existed when I made it. I made this as an addition to my server and so I decided to share it. Besides, it doesn't even work like yours. Mine is for the purpose of revisiting any old location within cities, spawns, quests, and uses submenus to organize, plus allows the player to teleport from anywhere, not just a selection of pre-determined locations. I based my system on the fast travel system of skyrim. Since my system works very differently from yours, your comment is essentially invalid.
 
Last edited:
Congratulations, did you want a medal? I made this without referencing your script or the improved version that zbizu made, because I didn't know they existed when I made it. I made this as an addition to my server and so I decided to share it. Besides, it doesn't even work like yours. Mine is for the purpose of revisiting any old location within cities, spawns, quests, and uses submenus to organize, plus allows the player to teleport from anywhere, not just a selection of pre-determined locations. I based my system on the fast travel system of skyrim. Since my system works very differently from yours, your comment is essentially invalid.

Answered my own question, :) Awesome script
 
Last edited by a moderator:
Answered my own question, :) Awesome script
Yeah, thanks ;D
To answer the question publicly for anyone else wondering, you can teleport when in PZ even if you have battle still, but outside PZ you must lose battle to use the teleport.


EDIT:

In addition, I will be removing the stepIn portion to discover a location as it no longer works in TFS 1.1+. Mark removed the ability to have multiple items with the same unique ID. I will add a workaround shortly.

Edit2:
I've removed the stepIn discovery and added a slightly modified version. I've also updated the main script in lib/fasttravel.lua to include the workaround that was needed after unique IDs became actually unique. This release should work 100% on TFS 1.1 final release now.
 
Last edited:
If anyone wants to make it so when a player steps on a tile the fast travel window comes up, simply create a script in movements called "fast_travel.lua" then add this text to it..

Code:
function onStepIn(player, item, position, fromPosition)
  if item:getUniqueId(13337) then
  player:sendLocationWindow()
  else
  player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You cannot fast travel while in combat.")
  end
  return false
end

movements.xml
Code:
<movevent event="StepIn" uniqueid="13337" script="travel.lua"/>

Now in your map editor, simply set a tiles uniqueID to 13337 and test it out!
 
If anyone wants to make it so when a player steps on a tile the fast travel window comes up, simply create a script in movements called "fast_travel.lua" then add this text to it..

Code:
function onStepIn(player, item, position, fromPosition)
  if item:getUniqueId(13337) then
  player:sendLocationWindow()
  else
  player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You cannot fast travel while in combat.")
  end
  return false
end

movements.xml
Code:
<movevent event="StepIn" uniqueid="13337" script="travel.lua"/>

Now in your map editor, simply set a tiles uniqueID to 13337 and test it out!

Actionid would be better because TFS 1.1 no longer supports duplicate uid.
 
You could use actionids, its just with this script on the tile I step on, I already have an actionid on it since they are used as "discovery" tiles; so I have to make multiple uids = 13337, 13338, 13339 for it to work.

EDIT: Actually, thinking about it, we could do
Code:
if item:getActionId >= 37000 then

So if the items action id is equal to or greater than 37000 (the main number used for this system) it will bring up the window? I'll try it once I get back home, since it would be much more efficient!

Edit 2:
Here we go, I modified the original movements files to keep it more organized and now you no longer need to set anything in the map if you have already added the action id.

in movements/scripts, discover.lua:
Code:
function onStepIn(player, item, position, fromPosition)
  if item.actionid > 37100 and item.actionid < 38000 then
  local storage = player:getStorageValue(item.actionid)
  if storage ~= 1 then
  player:setStorageValue(item.actionid, 1)
  player:setStorageValue(sublocations[item.actionid], 1)
  player:sendTextMessage(MESSAGE_INFO_DESCR, "You have re-activated a shrine, you're actions will forever be remembered!")
  end
  end
   if item.actionid > 37100 and item.actionid < 38000 or item.actionid > 5000 and item.actionid < 5005 then
       player:sendLocationWindow()
     else
       player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You cannot fast travel while in combat.")
  end

  return true
end

Edit 3:
For anyone who wants it, I've slightly modified the script to be mostly based off a movement script.

Using the 5001-5005 action ids, you will discover multiple locations.
Using the 37100-38000 action ids, you will discover single locations.
When stepping on any tile with these actionids, it will trigger the modal window.

I found this useful for the project I'm working on, it makes the starting of the server much more user friendly.

Code:
function onStepIn(player, item, position, fromPosition)
	-- Config for Discovering Multiple Locations
	local versions = {
    [5001] = {storages = {37101, 37102, 37103, 37104, 37111, 37112}},
    [5002] = {storages = {37101, 37104}},
    [5003] = {storages = {37111, 37112, 37113}},
    [5004] = {storages = {37101, 37102, 37103, 37111, 37112, 37113}},
    }
    local discover = false
	
	-- Discovering Locations using above actionIDs
	if versions[item.actionid] then
        for i = 1, #versions[item.actionid]["storages"] do
        
            if player:getStorageValue(versions[item.actionid]["storages"][i]) ~= 1 then
                player:setStorageValue(versions[item.actionid]["storages"][i], 1)
                discover = true
            end
        end
        if discover then
            player:sendTextMessage(MESSAGE_INFO_DESCR, "You have discovered new locations that you can travel to!")
        end
    end
	
	-- Activating one location through actionID
    if item.actionid > 37100 and item.actionid < 38000 then
        local storage = player:getStorageValue(item.actionid)
        if storage ~= 1 then
            player:setStorageValue(item.actionid, 1)
            player:setStorageValue(sublocations[item.actionid], 1)
            player:sendTextMessage(MESSAGE_INFO_DESCR, "You have re-activated a shrine, your actions will forever be remembered!")
        end
    end
	
	-- Fast Travel Modal Window
	if item.actionid > 37100 and item.actionid < 38000 or item.actionid > 5000 and item.actionid < 5005 then
			player:sendLocationWindow()
		else
			player:sendTextMessage(MESSAGE_EVENT_ADVANCE, "You cannot fast travel while in combat.")
    end
end
 
Last edited:
Back
Top