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

MoveEvent [TFS 1.2] Training anti-afk/sp limit

zbizu

Legendary OT User
Joined
Nov 22, 2010
Messages
3,323
Solutions
26
Reaction score
2,690
Location
Poland
By stepping on training tile you lose 1 soulpoint and it allows you to train with monks for one minute. If you step out of training tile earlier, remaining seconds will be lost.
03:58 Training started.
Cost: 1 SP per minute.
You have 3 hours and 15 minutes of training time left.

- With this script training becomes limited to amount of player's soul points(default max 200(it's 3h 20 min) with promotion).
- It also allows you to run anti-afk checks on players who stand on training tile(just a command or code rewriting, depends on "usecode" value), feature can be disabled by switching "confirm" to false.

usecode = true
04:00 [AntiAfk]: Anti-afk test launched. You have 5 minutes to prove that you are a human.
04:00 [AntiAfk]: Code: 47ć´Ń8ż4Ś˘
04:00 [AntiAfk]: Type !continue with numbers only. Example: !continue 4502

usecode = false
03:59 [AntiAfk]: Type !continue or move your character or you will be kicked out in 5 minutes.

It's recommended to use switches with id 11062 as they prevent other players from stepping on them.

Installation:

Map:
L79IznQ.jpg


talkactions.xml:
Code:
<talkaction words="!continue" separator=" " script="training_continue.lua"/>

training_continue.lua
Code:
function onSay(player, words, param)
   onlineTraining_talkaction(player:getId(), words, param)
return false
end

movements.xml:
Code:
  <movevent event="StepIn" actionid="831" script="online_training.lua"/>
   <movevent event="StepIn" actionid="832" script="online_training.lua"/>
   <movevent event="StepIn" actionid="833" script="online_training.lua"/>

online_training.lua
Code:
local training_exit = {
   [831] = {x = 98, y = 95, z = 6}, -- player will land here after he runs out of sp
   [832] = {x = 98, y = 95, z = 6}, -- example: training room in another town
   [833] = {x = 98, y = 95, z = 6, free = true} -- no sp will be charged, useful if you want to execute anti-exit only
}
local confirm = true -- anti-exit
local usecode = true -- confirm with code
local antiafk_interval = 9 * 60 * 1000 -- 9 minutes after training started
local words = "!continue" -- command to continue
local prefix = "[AntiAfk]: "
local minutes_to_reply = 5 -- minutes to rewrite code
local code_storage = 800 -- code storage

-- should not be changed
local sid = 831 -- session id storage
local antiafk_marks = {"ę", "€", "ó", "ś", "ż", "ź", "ć", "ń", "~", "@", "#", "&", "_", "\"", "|", "`", ";", "'", ",", "Ę", "Ó", "Ą", "Ś", "Ł", "Ż", "Ź", "Ć", "Ń", "ż", "ś", "ß", "¸", "¨", "´", "·", "`", "°", "˘", "ˇ", "~", "¦", "đ", "Đ", "§"}
antiafk_word = {}
local antiafk_string = {}

function onlineTraining_talkaction(cid, words, param)
   local p = Player(cid)
   local pos = p:getPosition()

   if not usecode then
     p:setStorageValue(sid, p:getStorageValue(sid) + 1)
     p:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, prefix .. "Training time extended.")
     local ground = Tile(pos):getGround():getActionId()
     if training_exit[ground] then
       addEvent(skillAntiExit, antiafk_interval, cid, pos, p:getStorageValue(sid))
       p:addSoul(-1)
       checkTrainingTile(cid, pos, p:getStorageValue(sid), ground)
     end
     return true
   end

   if p:getStorageValue(code_storage) < 1 then
     p:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, "No code to rewrite.")
     return true
   end

   local pnum = tonumber(param) and tonumber(param) or 0
   if pnum ~= p:getStorageValue(code_storage) then
     p:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, prefix .. "Incorrect code!")
     return true
   else
     p:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, prefix .. "Code accepted.")
     p:setStorageValue(sid, p:getStorageValue(sid) + 1)
     p:setStorageValue(code_storage, 0)
     local ground = training_exit[Tile(pos):getGround():getActionId()]
     if ground then
       addEvent(skillAntiExit, antiafk_interval, cid, pos, p:getStorageValue(sid))
       addEvent(checkTrainingTile, 60000, cid, pos, p:getStorageValue(sid), ground)
     end
     return true
   end

   return true
end

function showTimeLeft(number, usewords)
   local number = tonumber(number)
   if not number then
     return "error"
   end

   if number < 0 then
     return "expired"
   end

   local clocknum = os.date("!%X",number):split(":") -- h:m:s
   local day = math.modf(number / 86400)
   local hour = clocknum[1]
   local minute = clocknum[2]
   local second = clocknum[3]

   if not usewords then
     return table.concat({day, hour, minute, second}, ":")
   end

   local text = {}
   if day > 0 then
     table.insert(text, tonumber(day) .. " day" .. (day > 1 and "s" or ""))
   end

   if hour ~= "00" then
     table.insert(text, tonumber(hour) .. " hour" .. (tonumber(hour) > 1 and "s" or ""))
   end

   if minute ~= "00" then
     table.insert(text, tonumber(minute) .. " minute" .. (tonumber(minute) > 1 and "s" or ""))
   end

   if second ~= "00" then
     table.insert(text, tonumber(second) .. " second" .. (tonumber(second) > 1 and "s" or ""))
   end

   countdown_text = ""
   if #text > 0 then
     countdown_text = text[1]
     for i = 2, #text - 1 do
       countdown_text = countdown_text .. ", " .. text[i]
     end
     if #text > 1 then
       countdown_text = countdown_text .. " and " .. text[#text]
     end
   else
     countdown_text = "expired"
   end
return countdown_text
end

function checkTrainingTile(cid, pos, nsid, actionid)
   local p = Player(cid)
   if not p then return true end
   if getTopCreature(pos).uid == p:getId() and p:getStorageValue(sid) == nsid then
     if p:getSoul() < 1 then
       p:teleportTo(training_exit[actionid], false)
       Position(pos):sendMagicEffect(CONST_ME_TELEPORT)
       p:sendTextMessage(MESSAGE_INFO_DESCR, "Out of SP.")
       Position(p:getPosition()):sendMagicEffect(CONST_ME_TELEPORT)
       return true
     end
     p:addSoul(-1)
     addEvent(checkTrainingTile, 60000, cid, pos, nsid, actionid)
     return true
   end
   return true
end

function checkTrainingPlayer(cid, minutes, pos, nsid)
   local minutes = minutes - 1
   local p = Player(cid)
   if not p then
     return true
   end

   if p:getStorageValue(sid) ~= nsid then
     return true
   end

   if minutes < 1 then
     local npos = p:getPosition()
       if pos.x == npos.x and pos.y == npos.y and pos.z == npos.z then
         p:setStorageValue(code_storage, 0)
         p:remove()
       end
     return true
   end

   local bot_min_s = ""
   if antiafk_word[cid] and usecode then
     if minutes ~= 1 then bot_min_s = "s" end
     p:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, prefix .. "Anti-afk test launched. You have " .. minutes .. " minute" .. bot_min_s .. " to prove that you are a human.")
     p:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, prefix .. "Code: " .. table.concat(antiafk_word[cid]))
     p:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, prefix .. "Type " .. words .. " with numbers only. Example: " .. words .. " 4502")
     addEvent(checkTrainingPlayer, 60000, cid, minutes, pos, nsid)
     return true
   else
     if minutes ~= 1 then bot_min_s = "s" end
     p:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, prefix .. "Type " .. words .. " or move your character or you will be kicked out in " .. minutes .. " minute" .. bot_min_s .. ".")
     addEvent(checkTrainingPlayer, 60000, cid, minutes, pos, nsid)
     return true
   end
return true
end

function skillAntiExit(cid, pos, nsid)
   local p = Player(cid)
   if not p then return true end
   if p:getStorageValue(sid) == nsid then
     local npos = p:getPosition()
     if pos.x == npos.x and pos.y == npos.y and pos.z == npos.z then
       if usecode then
         math.randomseed(os.time())
         antiafk_word[cid] = {}
         for i = 1, 6 do
           antiafk_word[cid][i] = antiafk_marks[math.random(1, #antiafk_marks)]
         end
      
         antiafk_string[cid] = {}
         for i = 1, 4 do
           table.insert(antiafk_word[cid], math.random(1, #antiafk_word[cid]), math.random(0, 9))
         end

         for i = 1, #antiafk_word[cid] do
           if tonumber(antiafk_word[cid][i]) ~= nil then
             table.insert(antiafk_string[cid], antiafk_word[cid][i])
           end
         end
      
         p:setStorageValue(code_storage, tonumber(table.concat(antiafk_string[cid])))
       end    
       checkTrainingPlayer(cid, minutes_to_reply + 1, pos, nsid)
     end
   end
   return true
end

function onStepIn(player, item, position, fromPosition)
   local cid = player:getId()
   local p = player
   if not p then return true end
   local pos = p:getPosition()

   p:setStorageValue(sid, p:getStorageValue(sid) + 1)
   if confirm then
     addEvent(skillAntiExit, antiafk_interval, cid, pos, p:getStorageValue(sid))
   end

   if training_exit[item.actionid].free then
     return true
   end

   if p:getSoul() < 1 then
     p:teleportTo(training_exit[item.actionid], false)
     Position(pos):sendMagicEffect(CONST_ME_POFF)
     p:sendTextMessage(MESSAGE_INFO_DESCR, "You don't have enough SP.")
     Position(p:getPosition()):sendMagicEffect(CONST_ME_TELEPORT)
     return true
   end

   Position(pos):sendMagicEffect(CONST_ME_MAGIC_GREEN)
   p:sendTextMessage(MESSAGE_INFO_DESCR, "Training started.\nCost: 1 SP per minute.\nYou have " .. showTimeLeft(p:getSoul() * 60, true) .. " of training time left.")
   p:addSoul(-1)
   addEvent(checkTrainingTile, 60000, cid, pos, p:getStorageValue(sid), item.actionid)
   return true
end
 
Last edited:
if you accept suggestions, what about costing an certain itemID(and amount) to train for 1 hour with a limit of training time ofc (like 4 hours)
 
oh yeah indeed xD and what about creating monsters OnStepIn and removing them OnStepOut? just to let it fancy xD nothing that would affect user at all just the awesomeness :p
 
oh yeah indeed xD and what about creating monsters OnStepIn and removing them OnStepOut? just to let it fancy xD nothing that would affect user at all just the awesomeness :p

in last lines of that code it should look like this:
Code:
p:addSoul(-1)
training_monks[p:getId()] = {}
table.insert(training_monks[p:getId()], --[[monster spawning function here]])
addEvent(checkTrainingTile, 60000, cid, pos, p:getStorageValue(sid), item.actionid)
return true
end

and add this:
Code:
training_monks = {}
function onStepOut(player)

if not training_monks[player:getId()] then return true end

for i = 1, #training_monks[player:getId()] do
Creature(training_monks[player:getId()][i]):remove()
end
return true
end

Code:
<movevent event="StepOut" actionid="831" script="online_training.lua"/>
<movevent event="StepOut" actionid="832" script="online_training.lua"/>
<movevent event="StepOut" actionid="833" script="online_training.lua"/>
 
Last edited:
I'm getting this error.
Code:
Lua Script Error: [Main Interface] in a timer event called from: <Unknown scriptfile>
data/movements/scripts/online_training.lua:115: attempt to call global 'getTopCreature' <a nil value>
stack traceback:
    [C]: in function 'getTopCreature'
    data/movements/scripts/online_training.lua:115: in function <data/movements/scripts/online_training.lua:112>
 
function getTopCreature(position)
local t = Tile(position)
if t == nil then
return pushThing(nil)
end
return pushThing(t:getTopCreature())
end
 
Hello, this occurring the following error to me:

[Warning - Event::checkScript] Can not load script: scripts/online_training.lua
data/movements/scripts/online_training.lua:40: 'end' expected (to close 'if' at line 36) near <eof>
[Warning - Event::checkScript] Can not load script: scripts/online_training.lua
data/movements/scripts/online_training.lua:40: 'end' expected (to close 'if' at line 36) near <eof>
[Warning - Event::checkScript] Can not load script: scripts/online_training.lua
data/movements/scripts/online_training.lua:40: 'end' expected (to close 'if' at line 36) near <eof>

@resolved
I have great one new .lua.
Att Sartwood.
 
Last edited:
Is it possible to kick ppl if their sp have reached 0?
Without the !continue etc.
 
Oh crap .. My mistake. Excuse me, please.
I meant if there is a way to keep the kick at 0 but switch off !Continue?

Lua:
local confirm = false -- anti-exit
local usecode = false -- confirm with code
With this it doesn't kick you anymore. :/

Edit: Nvm.. My Exits were wrong..
 
Last edited:
Back
Top