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

revscriptsys

hellboy

Intermediate OT User
Joined
Apr 6, 2008
Messages
544
Solutions
6
Reaction score
121
Location
player:getTown()
Yesterday I saw this commit:

revscriptsys (#2558) · otland/forgottenserver@62dac47 (https://github.com/otland/forgottenserver/commit/62dac47c01610f652a5d792d4c9e06f4f0febefa)

1. There is any additional documentation about this? Last time I heard about revscriptsys few years ago (I guess in 2011).
2. If I create lua script for knife in both ways (revscriptsys and "classic way") which script run on use item?
3. Next TFS release will be 1.3 (with some backward compability) or 2.0 (with no backward compability)?
Or it'll be: 1.0 -> 1.1 -> 1.2 -> 1.3 -> 2.0

Anyway I like idea of registering functions in lua:
Code:
local spellbook = Action()
function spellbook.onUse(player, item, fromPosition, target, toPosition, isHotkey)
-- do stuff here
end

spellbook:id(2175, 6120, 8900, 8901, 8902, 8903, 8904, 8918)
spellbook:register()
 
1) I'll write a detailed guide once everything is implemented as intended.
2) It'll give you an error message in console that you tried to register an id twice, as xml is still loaded first it'll enable that one.
3) next release will be 1.3 with backwards compatibility, as I need to introduce tools first for people to easily convert their stuff from xml standard to pure lua.
For 2.0 there's still no strict plan on how everything will be sorted out and if xml gets completly dropped.
 
1) I'll write a detailed guide once everything is implemented as intended.
2) It'll give you an error message in console that you tried to register an id twice, as xml is still loaded first it'll enable that one.
3) next release will be 1.3 with backwards compatibility, as I need to introduce tools first for people to easily convert their stuff from xml standard to pure lua.
For 2.0 there's still no strict plan on how everything will be sorted out and if xml gets completly dropped.

Thanks for reply.
There are plans in near future to release 1.3? I can see only one bug left in task manager/task tracker.
otland/forgottenserver (https://github.com/otland/forgottenserver/projects/2)
 
once the rest of revscriptsys is done and the last bug is solved, as far as I can recall.
There is no deadline set, not sure how long that will take tho.
 
Sample code taken/reposted from this:

What is revscriptsys?
It's an easy drag and drop system where the lua files get load on startup (or on occasional load)
It doesn't break backwards compatibility and works normaly alongside the other xml stuff.
It would give the ability to write long quests and such easily in one file for organisation manner.

It invokes metatables for:
  • Action()
  • CreatureEvent()
  • GlobalEvent()
  • MoveEvent()
  • TalkAction()
with their corresponding functions to be able to set them up properly.

Supports:
  • Actions
  • Creaturescripts
  • Globalevents
  • Movements
  • Talkactions
  • Weapons (as of this)
Here are some working examples:
Action
Lua:
local shovel = Action()

local holes = {468, 481, 483}
function shovel.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if toPosition.x == CONTAINER_POSITION then
        return false
    end

    local tile = Tile(toPosition)
    if not tile then
        return false
    end

    local ground = tile:getGround()
    if not ground then
        return false
    end

    local groundId = ground:getId()
    if isInArray(holes, groundId) then
        ground:transform(groundId + 1)
        ground:decay()

        toPosition.z = toPosition.z + 1
        tile:relocateTo(toPosition)
    elseif groundId == 231 then
        local randomValue = math.random(1, 100)
        if randomValue == 1 then
            Game.createItem(2159, 1, toPosition)
        elseif randomValue > 95 then
            Game.createMonster("Scarab", toPosition)
        end
        toPosition:sendMagicEffect(CONST_ME_POFF)
    else
        return false
    end

    return true
end

shovel:id(2554)
shovel:register()

Globalevents
Lua:
local shutdownAtServerSave = false
local cleanMapAtServerSave = false

local function serverSave()
    if shutdownAtServerSave then
        Game.setGameState(GAME_STATE_SHUTDOWN)
    else
        Game.setGameState(GAME_STATE_CLOSED)

        if cleanMapAtServerSave then
            cleanMap()
        end

        Game.setGameState(GAME_STATE_NORMAL)
    end
end

local function secondServerSaveWarning()
    broadcastMessage("Server is saving game in one minute. Please logout.", MESSAGE_STATUS_WARNING)
    addEvent(serverSave, 60000)
end

local function firstServerSaveWarning()
    broadcastMessage("Server is saving game in 3 minutes. Please logout.", MESSAGE_STATUS_WARNING)
    addEvent(secondServerSaveWarning, 120000)
end

local event = GlobalEvent("Server Save")

function event.onTime(interval)
    broadcastMessage("Server is saving game in 5 minutes. Please logout.", MESSAGE_STATUS_WARNING)
    Game.setGameState(GAME_STATE_STARTUP)
    addEvent(firstServerSaveWarning, 120000)
    return not shutdownAtServerSave
end

event:time("09:55:00")
event:register()

Creaturescripts
Lua:
local login = CreatureEvent("PlayerLogin")

function login.onLogin(player)
    local loginStr = "Welcome to " .. configManager.getString(configKeys.SERVER_NAME) .. "!"
    if player:getLastLoginSaved() <= 0 then
        loginStr = loginStr .. " Please choose your outfit."
        player:sendOutfitWindow()
    else
        if loginStr ~= "" then
            player:sendTextMessage(MESSAGE_STATUS_DEFAULT, loginStr)
        end

        loginStr = string.format("Your last visit was on %s.", os.date("%a %b %d %X %Y", player:getLastLoginSaved()))
    end
    player:sendTextMessage(MESSAGE_STATUS_DEFAULT, loginStr)

    -- Stamina
    nextUseStaminaTime[player.uid] = 0

    -- Promotion
    local vocation = player:getVocation()
    local promotion = vocation:getPromotion()
    if player:isPremium() then
        local value = player:getStorageValue(STORAGEVALUE_PROMOTION)
        if not promotion and value ~= 1 then
            player:setStorageValue(STORAGEVALUE_PROMOTION, 1)
        elseif value == 1 then
            player:setVocation(promotion)
        end
    elseif not promotion then
        player:setVocation(vocation:getDemotion())
    end

    -- Events
    player:registerEvent("PlayerDeath")
    player:registerEvent("DropLoot")
    return true
end

login:register()

Talkactions
Lua:
local talk = TalkAction("/pos")

function talk.onSay(player, words, param)
    if player:getGroup():getAccess() and param ~= "" then
        local split = param:split(",")
        player:teleportTo(Position(split[1], split[2], split[3]))
    else
        local position = player:getPosition()
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Your current position is: " .. position.x .. ", " .. position.y .. ", " .. position.z .. ".")
    end
    return false
end

talk:separator(" ")
talk:register()

Movements (stepin/stepout/additem/removeitem) with pre defined items.xml values
Lua:
local campfireStepIn = MoveEvent()
campfireStepIn:type("stepin")
campfireStepIn:id(1423, 1424, 1425)
campfireStepIn:register()

local campfireAddItem = MoveEvent()
campfireAddItem:type("additem")
campfireAddItem:id(1423, 1424, 1425)
campfireAddItem:register()

Movements (stepin/stepout/additem/removeitem) with a lua script return value
Lua:
local increasing = {[416] = 417, [426] = 425, [446] = 447, [3216] = 3217, [3202] = 3215, [11062] = 11063}
local decreasing = {[417] = 416, [425] = 426, [447] = 446, [3217] = 3216, [3215] = 3202, [11063] = 11062}

local tileStepIn = MoveEvent()

function tileStepIn.onStepIn(creature, item, position, fromPosition)
    if not increasing[item.itemid] then
        return true
    end

    local player = creature:getPlayer()
    if player == nil or player:isInGhostMode() then
        return true
    end

    item:transform(increasing[item.itemid])

    if item.actionid >= 1000 then
        if player:getLevel() < item.actionid - 1000 then
            player:teleportTo(fromPosition, false)
            position:sendMagicEffect(CONST_ME_MAGIC_BLUE)
            player:sendTextMessage(MESSAGE_INFO_DESCR, "The tile seems to be protected against unwanted intruders.")
        end
        return true
    end

    if Tile(position):hasFlag(TILESTATE_PROTECTIONZONE) then
        local lookPosition = player:getPosition()
        lookPosition:getNextPosition(player:getDirection())
        local depotItem = Tile(lookPosition):getItemByType(ITEM_TYPE_DEPOT)
        if depotItem ~= nil then
            local depotItems = player:getDepotChest(getDepotId(depotItem:getUniqueId()), true):getItemHoldingCount()
            player:sendTextMessage(MESSAGE_STATUS_DEFAULT, "Your depot contains " .. depotItems .. " item" .. (depotItems > 1 and "s." or "."))
            return true
        end
    end

    if item.actionid ~= 0 and player:getStorageValue(item.actionid) <= 0 then
        player:teleportTo(fromPosition, false)
        position:sendMagicEffect(CONST_ME_MAGIC_BLUE)
        player:sendTextMessage(MESSAGE_INFO_DESCR, "The tile seems to be protected against unwanted intruders.")
        return true
    end
    return true
end

for k, v in pairs(increasing) do
    tileStepIn:id(k)
end
tileStepIn:register()

local tileStepOut = MoveEvent()

function tileStepOut.onStepOut(creature, item, position, fromPosition)
    if not decreasing[item.itemid] then
        return true
    end

    if creature:isPlayer() and creature:isInGhostMode() then
        return true
    end

    item:transform(decreasing[item.itemid])
    return true
end

for k, v in pairs(decreasing) do
    tileStepOut:id(k)
end
tileStepOut:register()

Movements (equip/deequip) with pre defined like movements.xml values
Lua:
-- Equip armor(s) for sorceres and druids at any level
local equip = MoveEvent()
equip.onEquip = defaultEquip
equip:type("equip")
equip:slot("armor")
equip:vocation("sorcerer", true, false) -- showInDescription / lastVoc
equip:vocation("master sorcerer")
equip:vocation("druid", true, true)
equip:vocation("elder druid")
equip:id(8819, 8892, 8870, 8871)
equip:register()

Movements (equip/deequip) with lua script attached and combination of pre defined values
Lua:
-- Equip armor(s) for sorceres and druids at any level
local equip = MoveEvent()
function equip.onEquip(player, item, slot)
    print("I do work")
    return true
end
equip:type("equip")
equip:slot("armor")
equip:vocation("sorcerer", true, false) -- showInDescription / lastVoc
equip:vocation("master sorcerer")
equip:vocation("druid", true, true)
equip:vocation("elder druid")
equip:id(8819, 8892, 8870, 8871)
equip:register()
 
Sample code taken/reposted from this:

What is revscriptsys?
It's an easy drag and drop system where the lua files get load on startup (or on occasional load)
It doesn't break backwards compatibility and works normaly alongside the other xml stuff.
It would give the ability to write long quests and such easily in one file for organisation manner.

It invokes metatables for:
  • Action()
  • CreatureEvent()
  • GlobalEvent()
  • MoveEvent()
  • TalkAction()
with their corresponding functions to be able to set them up properly.

Supports:
  • Actions
  • Creaturescripts
  • Globalevents
  • Movements
  • Talkactions
  • Weapons (as of this)
Here are some working examples:
Action
Lua:
local shovel = Action()

local holes = {468, 481, 483}
function shovel.onUse(player, item, fromPosition, target, toPosition, isHotkey)
    if toPosition.x == CONTAINER_POSITION then
        return false
    end

    local tile = Tile(toPosition)
    if not tile then
        return false
    end

    local ground = tile:getGround()
    if not ground then
        return false
    end

    local groundId = ground:getId()
    if isInArray(holes, groundId) then
        ground:transform(groundId + 1)
        ground:decay()

        toPosition.z = toPosition.z + 1
        tile:relocateTo(toPosition)
    elseif groundId == 231 then
        local randomValue = math.random(1, 100)
        if randomValue == 1 then
            Game.createItem(2159, 1, toPosition)
        elseif randomValue > 95 then
            Game.createMonster("Scarab", toPosition)
        end
        toPosition:sendMagicEffect(CONST_ME_POFF)
    else
        return false
    end

    return true
end

shovel:id(2554)
shovel:register()

Globalevents
Lua:
local shutdownAtServerSave = false
local cleanMapAtServerSave = false

local function serverSave()
    if shutdownAtServerSave then
        Game.setGameState(GAME_STATE_SHUTDOWN)
    else
        Game.setGameState(GAME_STATE_CLOSED)

        if cleanMapAtServerSave then
            cleanMap()
        end

        Game.setGameState(GAME_STATE_NORMAL)
    end
end

local function secondServerSaveWarning()
    broadcastMessage("Server is saving game in one minute. Please logout.", MESSAGE_STATUS_WARNING)
    addEvent(serverSave, 60000)
end

local function firstServerSaveWarning()
    broadcastMessage("Server is saving game in 3 minutes. Please logout.", MESSAGE_STATUS_WARNING)
    addEvent(secondServerSaveWarning, 120000)
end

local event = GlobalEvent("Server Save")

function event.onTime(interval)
    broadcastMessage("Server is saving game in 5 minutes. Please logout.", MESSAGE_STATUS_WARNING)
    Game.setGameState(GAME_STATE_STARTUP)
    addEvent(firstServerSaveWarning, 120000)
    return not shutdownAtServerSave
end

event:time("09:55:00")
event:register()

Creaturescripts
Lua:
local login = CreatureEvent("PlayerLogin")

function login.onLogin(player)
    local loginStr = "Welcome to " .. configManager.getString(configKeys.SERVER_NAME) .. "!"
    if player:getLastLoginSaved() <= 0 then
        loginStr = loginStr .. " Please choose your outfit."
        player:sendOutfitWindow()
    else
        if loginStr ~= "" then
            player:sendTextMessage(MESSAGE_STATUS_DEFAULT, loginStr)
        end

        loginStr = string.format("Your last visit was on %s.", os.date("%a %b %d %X %Y", player:getLastLoginSaved()))
    end
    player:sendTextMessage(MESSAGE_STATUS_DEFAULT, loginStr)

    -- Stamina
    nextUseStaminaTime[player.uid] = 0

    -- Promotion
    local vocation = player:getVocation()
    local promotion = vocation:getPromotion()
    if player:isPremium() then
        local value = player:getStorageValue(STORAGEVALUE_PROMOTION)
        if not promotion and value ~= 1 then
            player:setStorageValue(STORAGEVALUE_PROMOTION, 1)
        elseif value == 1 then
            player:setVocation(promotion)
        end
    elseif not promotion then
        player:setVocation(vocation:getDemotion())
    end

    -- Events
    player:registerEvent("PlayerDeath")
    player:registerEvent("DropLoot")
    return true
end

login:register()

Talkactions
Lua:
local talk = TalkAction("/pos")

function talk.onSay(player, words, param)
    if player:getGroup():getAccess() and param ~= "" then
        local split = param:split(",")
        player:teleportTo(Position(split[1], split[2], split[3]))
    else
        local position = player:getPosition()
        player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "Your current position is: " .. position.x .. ", " .. position.y .. ", " .. position.z .. ".")
    end
    return false
end

talk:separator(" ")
talk:register()

Movements (stepin/stepout/additem/removeitem) with pre defined items.xml values
Lua:
local campfireStepIn = MoveEvent()
campfireStepIn:type("stepin")
campfireStepIn:id(1423, 1424, 1425)
campfireStepIn:register()

local campfireAddItem = MoveEvent()
campfireAddItem:type("additem")
campfireAddItem:id(1423, 1424, 1425)
campfireAddItem:register()

Movements (stepin/stepout/additem/removeitem) with a lua script return value
Lua:
local increasing = {[416] = 417, [426] = 425, [446] = 447, [3216] = 3217, [3202] = 3215, [11062] = 11063}
local decreasing = {[417] = 416, [425] = 426, [447] = 446, [3217] = 3216, [3215] = 3202, [11063] = 11062}

local tileStepIn = MoveEvent()

function tileStepIn.onStepIn(creature, item, position, fromPosition)
    if not increasing[item.itemid] then
        return true
    end

    local player = creature:getPlayer()
    if player == nil or player:isInGhostMode() then
        return true
    end

    item:transform(increasing[item.itemid])

    if item.actionid >= 1000 then
        if player:getLevel() < item.actionid - 1000 then
            player:teleportTo(fromPosition, false)
            position:sendMagicEffect(CONST_ME_MAGIC_BLUE)
            player:sendTextMessage(MESSAGE_INFO_DESCR, "The tile seems to be protected against unwanted intruders.")
        end
        return true
    end

    if Tile(position):hasFlag(TILESTATE_PROTECTIONZONE) then
        local lookPosition = player:getPosition()
        lookPosition:getNextPosition(player:getDirection())
        local depotItem = Tile(lookPosition):getItemByType(ITEM_TYPE_DEPOT)
        if depotItem ~= nil then
            local depotItems = player:getDepotChest(getDepotId(depotItem:getUniqueId()), true):getItemHoldingCount()
            player:sendTextMessage(MESSAGE_STATUS_DEFAULT, "Your depot contains " .. depotItems .. " item" .. (depotItems > 1 and "s." or "."))
            return true
        end
    end

    if item.actionid ~= 0 and player:getStorageValue(item.actionid) <= 0 then
        player:teleportTo(fromPosition, false)
        position:sendMagicEffect(CONST_ME_MAGIC_BLUE)
        player:sendTextMessage(MESSAGE_INFO_DESCR, "The tile seems to be protected against unwanted intruders.")
        return true
    end
    return true
end

for k, v in pairs(increasing) do
    tileStepIn:id(k)
end
tileStepIn:register()

local tileStepOut = MoveEvent()

function tileStepOut.onStepOut(creature, item, position, fromPosition)
    if not decreasing[item.itemid] then
        return true
    end

    if creature:isPlayer() and creature:isInGhostMode() then
        return true
    end

    item:transform(decreasing[item.itemid])
    return true
end

for k, v in pairs(decreasing) do
    tileStepOut:id(k)
end
tileStepOut:register()

Movements (equip/deequip) with pre defined like movements.xml values
Lua:
-- Equip armor(s) for sorceres and druids at any level
local equip = MoveEvent()
equip.onEquip = defaultEquip
equip:type("equip")
equip:slot("armor")
equip:vocation("sorcerer", true, false) -- showInDescription / lastVoc
equip:vocation("master sorcerer")
equip:vocation("druid", true, true)
equip:vocation("elder druid")
equip:id(8819, 8892, 8870, 8871)
equip:register()

Movements (equip/deequip) with lua script attached and combination of pre defined values
Lua:
-- Equip armor(s) for sorceres and druids at any level
local equip = MoveEvent()
function equip.onEquip(player, item, slot)
    print("I do work")
    return true
end
equip:type("equip")
equip:slot("armor")
equip:vocation("sorcerer", true, false) -- showInDescription / lastVoc
equip:vocation("master sorcerer")
equip:vocation("druid", true, true)
equip:vocation("elder druid")
equip:id(8819, 8892, 8870, 8871)
equip:register()
So it's kind of like the old mod system?
One file that can hold multiple area's?
 
Here I can see information about supporting monsters in revscriptsys.

I don't see any examples :/
 
Here I can see information about supporting monsters in revscriptsys.

I don't see any examples :/
Check data\scripts\monsters\#example.lua
 
I have a problem with register onThink globalevent revescript, could someone show me example? Not sure how tu work with callback there
 
Back
Top