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

Psychonaut's Free Scripting Service [TFS 1.x]

psychonaut

Well-Known Member
Joined
Dec 1, 2017
Messages
75
Solutions
6
Reaction score
56
Like Xikini i'm only gonna take quick scripts and i don't wanna do spells, weapons, raids or monster scripts, websites edits and database queries. Source edits need to be a really small thing(would be very boring to keep cloning TFS repo to test each one). Post in the topic too, no dm.

I wanna reserve this for interesting scripts too and try to detail as much as possible how the script need to work.

Diablo III Rifts idea by Aeronx
Sokoban game, idea by Xikini

ouzZjhG.gif
 
Last edited:
I'm looking for a function which I can put on the player's onLook script which shows the Tier of EQ the player currently has.
Let me explain:
If a player has full Tier 1 Set, it would say "Tier: 1" on a player when I look at them.
If a player has full Tier 5, it would say "Tier: 5", simple.

There's 8 items in a Set, not counting Backpack & Ammo Slot.
So for each item in Tier 1 for example would give 1/8=0.125
Each item in Tier 5 would give 5/8=0.625

I also only want it to show one decimal if that's possible; 5.4 for example and not 5.42.
 
@psychonaut about the "Sokoban Game", how we can do it in different levels, without set the positions, instead of using positions declared in variables we could use ids of the "correct spots", we just need set the pos of the crates, so, can help me with that?
 
To just set the pos of the crates, you can use only the crates function so, but it's easy to get pos now as you can copy it from RME.

Lua:
if sokobanBuildSpots(spots, specialAid) then
      sokobanBuildCrates(player, crates, specialAid)
end

Would be just sokobanBuildCrates(player, crates, specialAid), the crates check if there's a spot under them so i guess that there's no problem.

Lua:
if item.actionid == 2412 then
       player:setStorageValue(sokoban.storage, 0)
       if sokobanBuildSpots(spots, specialAid) then
           sokobanBuildCrates(player, crates, specialAid)
       end
       player:setStorageValue(sokoban.gameStorage, 1)
       return true
end

Is the teleport, so for different levels you would call it with another actionid and call the function sokobanBuildCrates with another table for the crates.

It's possible to do a level maker for that in python or anything else, to generate the pos of everything.

Changed the sokoban script.
Now levels can be set with sokobanSetLevel(player, item.actionid, <tp action id>, <crates position>, <spot count>).
Spots need to be set in RME.

Need to enable the level here
local levels = {[2412] = true}
 
Last edited by a moderator:
Hello pyschonaut! Still free?

If so, think about this.

PvP Arenas. (WoW like)

How it works:
player1 queues for Arena.
player2 queues for Arena.

When 2 players are queued and they are not in combat, send them to the arena.
(Give them something like 1 minute to finish combat and be able to teleport inside the arena)
(Or maybe instead of just teleport them into the arena if there's a match, tell them "There's a match, enter the arena?" would be way better).
Arena Lasts 15 minutes or until someone loses.
When that happens both are sent back to their places.

All players start with 1000 points.
Losing you lose -30 points.
Wining you win +30 points.

If player1 have 900 points and player2 have 1400 points.
-if player1 win he gets more than 35 points players2 loses 35.
-if player2 win he gets 25 points, player 1 loses 25 points.
Point safeward may be needed so friend1 with 900 points loses to friend2 with 1500 in purpose to boost friend2 or viceversa.
(You see the idea on points matchmaking).

Players may join alone, in party of 3 (3vs3) or party of 5(5vs5)

Some way to see leatherboard ingame of top25 player points.

If arena1 is bussy, teleport them to arena2. Maybe 5 arenas?

Need more info? Let me know.

Thanks for your time and hard work for the community!
 
Hello pyschonaut! Still free?

If so, think about this.

PvP Arenas. (WoW like)

How it works:
player1 queues for Arena.
player2 queues for Arena.

When 2 players are queued and they are not in combat, send them to the arena.
(Give them something like 1 minute to finish combat and be able to teleport inside the arena)
(Or maybe instead of just teleport them into the arena if there's a match, tell them "There's a match, enter the arena?" would be way better).
Arena Lasts 15 minutes or until someone loses.
When that happens both are sent back to their places.

All players start with 1000 points.
Losing you lose -30 points.
Wining you win +30 points.

If player1 have 900 points and player2 have 1400 points.
-if player1 win he gets more than 35 points players2 loses 35.
-if player2 win he gets 25 points, player 1 loses 25 points.
Point safeward may be needed so friend1 with 900 points loses to friend2 with 1500 in purpose to boost friend2 or viceversa.
(You see the idea on points matchmaking).

Players may join alone, in party of 3 (3vs3) or party of 5(5vs5)

Some way to see leatherboard ingame of top25 player points.

If arena1 is bussy, teleport them to arena2. Maybe 5 arenas?

Need more info? Let me know.

Thanks for your time and hard work for the community!

Thanks, it sounds like a funny script but some things make it not a quick script sorry.
 
Like what things? Maybe we can simplify it.

Just explained how it works, its not 100% necessary to work like that.
 
I'm not sure if i can make the players in party not being able to leave it or killing themselves without source edit, and i guess that for a correct leaderboard i would need queries(what i don't do here), and the points system how you wanna it to players not die in purpose, i didn't got the safeward.
 
Okey then lets simplify it.

Forget 3vs3 and 5v5.
(My party members cant damage themselves or others in same party actually, so that part is easy)
(About not leaving party is harder)
-About the 3vs3 and 5vs5, instead of joining as party, just send 3 random players to teamA and 3 other random players to teamB. Add a storage to each team. Players with same storage cannot attack each other. Its a viable solution. Possible commands: !join arena, !join arena3 or !join arena5 depending on which kind of match you wana play. (Each type of arena has its own points)
Forget Leaderboard (Ill do that part)

About the safeward its easy.

If the diference between player points is more than lets say 200 they cant match together, or if the difference is greater than 200 no win nor lose points.
 
Last edited:
Okey then lets simplify it.

Forget 3vs3 and 5v5.
Forget Leaderboard (Ill do that part)

About the safeward its easy.

If the diference between player points is more than lets say 200 they cant match together, or if the difference is greater than 200 no win nor lose points.

Sounds quick now, going to do it. Btw talkactions?
 
Check my post. Edited.

If going only for 1vs1 guess that !queue arena and !join arena should be enough?
 
erhm.. I think you do not.

What about this on events/creature.lua

Code:
function Creature:onTargetCombat(target)
if self:isPlayer() and target:isPlayer() then
if self:getStorageValue(65464) and target:getStorageValue(65464) then
return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER
end
end
return true
end

With this script players with same storage can not damage each other >.<
 
Oh well, i always forget them, with events it's possible so i guess, maybe even the party thing

@Aeronx If player gets to 0 points, he'll get the 1000 free points again? Or it will become negative. And just to prompt if he wanna join or no it would be 3 files(i can't use the modal lib for that).
 
Last edited:
I dont mind about hiw many files haha points shouldnt go lower than 500. Once a month i would reset all people points to 1000 and give something to top3.

(Even if you quote me at a post, if its an edit of older post i dont get the warning of new post, sorry for delay)
 
I didn't saw your reply, i went offline yesterday

Did already something

XML:
<talkaction words="!join" separator=" " script="joinArena.lua" />

XML:
<event type="kill" name="PvpArena" script="pvparena.lua"/>

Lua:
pvpArena = { arena = {}, arena3 = {}, arena5 = {} }
pvpArenaEvents = {}
local arenaTeleports = { arena = {tp1 = {x = 1022, y = 1024, z = 7}, tp2 = {x = 1025, y = 1024, z = 7}} }
local tpBack = {x = 1023, y = 1029, z = 7}
local arenaStorage, pointsStorage, registeredStorage, queueStorage = 3142, 3143, 3144, 3145

local function playersIn(arena)
    local n = 0
    for _ in ipairs(arena) do
        n = n + 1
    end
    return n
end

local function arenaJoin(player, arena, max)
    local currentPlayers = playersIn(arena)
 
    if currentPlayers >= max then
        player:sendCancelMessage(MESSAGE_INFO_DESCR, "The arena is being used.")
        return false
    end
 
    if currentPlayers > 0 then
        local playerPoints = player:getStorageValue(pointsStorage)
        for _, arenaPlayerName in ipairs(arena) do
            if arenaPlayerName == player:getName() then
                player:sendCancelMessage("You're already in the queue.")
                return false
            end                      
        end
        local arenaPlayer = Player(arena[1])
        if (arenaPlayer:getStorageValue(pointsStorage) > playerPoints + 200) or (arenaPlayer:getStorageValue(pointsStorage) < playerPoints - 200) then
            player:sendCancelMessage("Your points are too low or high for the current queue.")
            return false
        end
    end
    
    arena[#arena+1] = player:getName()
    
    if playersIn(arena) == max then
        for _, arenaPlayerName in ipairs(arena) do
            Player(arenaPlayerName):sendTextMessage(MESSAGE_INFO_DESCR, "Arena is ready and will start in one minute, please leave any combat that you're in.")
        end
        return true
    else
        player:sendTextMessage(MESSAGE_INFO_DESCR, "You're now in the arena queue.")
    end
 
    return false
end

local function arenaCheck(arena)
    for _, arenaPlayer in ipairs(arena) do
        local arenaPlayer = Player(arenaPlayer)
        if arenaPlayer == nil then
            for k, arenaPlayerMessage in ipairs(arena) do
                if Player(arenaPlayerMessage) ~= nil then
                    Player(arenaPlayerMessage):sendTextMessage(MESSAGE_INFO_DESCR, "A player is offline, arena was canceled, please join the queue again later.")
                end
                arena[k] = nil
            end
            return false
        end

        if arenaPlayer:getCondition(CONDITION_INFIGHT, CONDITIONID_DEFAULT) then
            for k, arenaPlayer in ipairs(arena) do
                if Player(arenaPlayer) ~= nil then
                    Player(arenaPlayer):sendTextMessage(MESSAGE_INFO_DESCR, "A player was in battle, arena was canceled, please join the queue again later.")
                end
                arena[k] = nil
            end
            return false
        end
        if arenaPlayer:getStorageValue(registeredStorage) ~= 1 then
            arenaPlayer:sendTextMessage(MESSAGE_INFO_DESCR, "As it's your first arena, you'll get 1000 points to start.")
            arenaPlayer:setStorageValue(pointsStorage, 1000)
            arenaPlayer:setStorageValue(registeredStorage, 1)
        end    
    end
    return true
end

local function finishArena(arena)
    for k, arenaPlayer in ipairs(arena) do
        local arenaPlayer = Player(arenaPlayer)
        arenaPlayer:sendTextMessage(MESSAGE_INFO_DESCR, "Arena is over by time limit.")
        arenaPlayer:unregisterEvent("PvpArena")
        doTeleportThing(arenaPlayer.uid, tpBack)
        arena[k] = nil
    end
end


local function tpArena(arena, arenaType)
    if arenaCheck(arena) then    
        for _, arenaPlayer in ipairs(arena) do
            local arenaPlayer = Player(arenaPlayer)
            arenaPlayer:registerEvent("PvpArena")
            arenaPlayer:setStorageValue(arenaStorage, arenaType)
        end
        if arenaType == 1 then
            for k, arenaPlayer in ipairs(arena) do
                if k <= #arena/2 then
                    doTeleportThing(Player(arenaPlayer).uid, arenaTeleports.arena.tp1)
                else
                    doTeleportThing(Player(arenaPlayer).uid, arenaTeleports.arena.tp2)
                end
            end
            pvpArenaEvents.arena1 = addEvent(finishArena, 15 * 60 * 1000, pvpArena.arena)
        elseif arenaType == 3 then
            --code here
        end    
    end
end

function onSay(player, words, param)
    local itemType = ItemType(param)
    if param == "arena" then
        if arenaJoin(player, pvpArena.arena, 2) then
            pvpArenaEvents.tpArena1 = addEvent(tpArena, 1 * 60 * 1000, pvpArena.arena, 1)        
        end
    else
        player:sendCancelMessage("Please use !join arena")
    end
   return false
end

Lua:
local arenaStorage, pointsStorage, tpBack = 3142, 3143, {x = 1023, y = 1029, z = 7}

function onKill(creature, target)
    local targetPlayer = Player(target)
    if not targetPlayer or creature:getPlayer():getStorageValue(arenaStorage) < 1 then
        return true
    end
 
    if targetPlayer:getStorageValue(arenaStorage) == 1 then
        local winnerPoints, loserPoints = creature:getPlayer():getStorageValue(pointsStorage), targetPlayer:getStorageValue(pointsStorage)
        stopEvent(pvpArenaEvents.arena1)
        for k, arenaPlayer in ipairs(pvpArena.arena) do
            local arenaPlayer = Player(arenaPlayer)
            if arenaPlayer ~= nil then
                arenaPlayer:unregisterEvent("PvpArena")
                arenaPlayer:setStorageValue(arenaStorage, 0)
                doTeleportThing(arenaPlayer.uid, tpBack)
                arenaPlayer:sendTextMessage(MESSAGE_INFO_DESCR, "Arena is over, " .. creature:getPlayer():getName() .. " won.")       
            end
            pvpArena.arena[k] = nil
        end
        if winnerPoints < loserPoints then
            creature:getPlayer():setStorageValue(pointsStorage, winnerPoints + 35)
            targetPlayer:setStorageValue(pointsStorage, loserPoints - 35)
        else
            creature:getPlayer():setStorageValue(pointsStorage, winnerPoints + 25)
            targetPlayer:setStorageValue(pointsStorage, loserPoints - 25)
        end    
    end
    return true
end

I did with functions so it's really easy to edit it, arenaJoin check if the player can join in which arena and with a number of max players and return true if the arena is going to start(max number of players reached), it checks if the player have enough points to join with that players too, the first one to join will create a limit, but it's possible to create an average too, tpArena is called in an addEvent, with an arena and the arenaType, it will first run the function arenaCheck for that arena, that will check if the player is online and if the player is in battle, then it will cancel the current arena, and will give 1k points to the player if he never did an arena before too. There's a time limit and finishArena will be called to stop the arena if the time limit is reached, it's an event called with tpArena. I created the another arena tables as example too.

To create new ones with party it's needed to create the party with the players in the table(using that #arena/2), and returning false in events in both party onLeave and onDisband if the player got the arenaStorage.
 
Last edited by a moderator:
I will test shortly. Only with reading it a see a bug.

pvparena.lua can not be onKill, it should be onPrepareDeath() since you do not kill the other player, you just drop his life to 0, and when that happens, everything else.
If you use onKill you will really kill the other player and there is already a creaturescript that makes something happen when the players dies (in normal case, teleport them to temple and reduce exp/skills).

Thank you for your time and effort! :) i'll edit with the results.
 
Its easy fixeable no worries! :)

Edit:

@psychonaut Working perfect. Once i changed the creaturevent to onPrepareDeath, i had to change target for creature and viceversa. Working great.

I've got a bit lost on the part on adding more than one arena (1vs1 arenas)
Also i get the part where you say to change onDisband and onLeave, but im not too good with tables at the moment and you lost me there a bit. Would you mind to explain a bit further the part (#arena/2) please?

Also I didnt see any stopEvent to stop the 15 minute timer event. Is not necesary to stop the event if you finish the arena before the time is up so players dont get teleported after 15 minutes even if they finished the arena long ago? (killing the other player)

Really great job, Congrats!! fun as hell!
 
Last edited:
Its easy fixeable no worries! :)

Edit:

@psychonaut Working perfect. Once i changed the creaturevent to onPrepareDeath, i had to change target for creature and viceversa. Working great.

I've got a bit lost on the part on adding more than one arena (1vs1 arenas)
Also i get the part where you say to change onDisband and onLeave, but im not too good with tables at the moment and you lost me there a bit. Would you mind to explain a bit further the part (#arena/2) please?

Also I didnt see any stopEvent to stop the 15 minute timer event. Is not necesary to stop the event if you finish the arena before the time is up so players dont get teleported after 15 minutes even if they finished the arena long ago? (killing the other player)

Really great job, Congrats!! fun as hell!

Thanks, i thought that i did one stop event, maybe missed it, just stop pvpArenaEvents.tpArenaX in onKill for each arena type that you did, the player storage is the type
 
Back
Top