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

TFS 1.X+ PVP Arena Modification (don't attack between the same town id)

ralke

(҂ ͠❛ ෴ ͡❛)ᕤ
Joined
Dec 17, 2011
Messages
1,521
Solutions
27
Reaction score
870
Location
Santiago - Chile
GitHub
ralke23
Twitch
ralke23
Lua:
function creatureeventPvPArena.onPrepareDeath(creature, killer)
    if not creature:isPlayer() then return true end
    if not creature:isPvPArenaPlayer() then return true end
    local town = config[creature:getTown():getId()]
    if not town then return true end

I use TFS 1.5 downgrade nekiro 8.6. This is an example of how town is get. How can I make the players from same town, to don't be allowed to attack each other?. If the player is from town 1, don't allow to attack players from town 1, and if the player is from town 2, don't allow to attack players from town 2.

The whole system is here

There's an extra function, isPvPArenaPlayer(), if i'm not wrong the town check should be part of "if player:isPvPArenaPlayer()" so it is applied only to players who's inside arena. And also disable the town restriction as soon that player:isPvpArena is false (triggered by target:setPvPArenaPlayer(false)).

Thanks in advance!
 
Solution
@ralke

see if it works
go in data/events/scripts and open creature.lua

for area combat
after:
Lua:
function Creature:onAreaCombat(tile, isAggressive)

add:
Lua:
    local player = Player(self)
    local target = tile:getTopCreature()
    if player and target and target:isPlayer() and player:isPvPArenaPlayer() and target:isPvPArenaPlayer() then
        if player:getTown():getId() == target:getTown():getId() then
            return false
        end
    end

for target combat
after:
Lua:
function Creature:onTargetCombat(target)

add:
Lua:
    local player = Player(self)
    if player and target and target:isPlayer() and player:isPvPArenaPlayer() and target:isPvPArenaPlayer() then
        if player:getTown():getId() ==...
@ralke

see if it works
go in data/events/scripts and open creature.lua

for area combat
after:
Lua:
function Creature:onAreaCombat(tile, isAggressive)

add:
Lua:
    local player = Player(self)
    local target = tile:getTopCreature()
    if player and target and target:isPlayer() and player:isPvPArenaPlayer() and target:isPvPArenaPlayer() then
        if player:getTown():getId() == target:getTown():getId() then
            return false
        end
    end

for target combat
after:
Lua:
function Creature:onTargetCombat(target)

add:
Lua:
    local player = Player(self)
    if player and target and target:isPlayer() and player:isPvPArenaPlayer() and target:isPvPArenaPlayer() then
        if player:getTown():getId() == target:getTown():getId() then
            return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER
        end
    end
 
Solution
@ralke

see if it works
go in data/events/scripts and open creature.lua

for area combat
after:
Lua:
function Creature:onAreaCombat(tile, isAggressive)

add:
Lua:
    local player = Player(self)
    local target = tile:getTopCreature()
    if player and target and target:isPlayer() and player:isPvPArenaPlayer() and target:isPvPArenaPlayer() then
        if player:getTown():getId() == target:getTown():getId() then
            return false
        end
    end

for target combat
after:
Lua:
function Creature:onTargetCombat(target)

add:
Lua:
    local player = Player(self)
    if player and target and target:isPlayer() and player:isPvPArenaPlayer() and target:isPvPArenaPlayer() then
        if player:getTown():getId() == target:getTown():getId() then
            return RETURNVALUE_YOUMAYNOTATTACKTHISPLAYER
        end
    end
Worked perfectly! Thanks a lot @mano368

If I might ask, before opening another thread. There could be a chance to automatically set outfit A if the player from town 1, and outfit B if the player is from town 2? Using the same PvPArena triggers. Also set the outfit that player has before entering to arena as soon the player exits (by being killed inside or using exit teleport, guess this will need target:setPvPArenaPlayer(false)), and don't allow outfit change if player isPvPArena. Msg me if any other information is needed, regards! :D

I'm currently trying something like this but is not much accurate:
Lua:
    if not player:isPvPArenaPlayer() then
        if position ~= town.tileEnterPos then
            player:sendCancelMessage("No perteneces a la faccion correcta para entrar aqui.")
            player:teleportTo(fromPosition, true)
            return true
        end
        --- Outfit
        local condition = Condition(CONDITION_OUTFIT)
        condition:setTicks(10 * 1000)
        condition:setOutfit({lookType = 60})
        
        local condition2 = Condition(CONDITION_OUTFIT)
        condition:setTicks(10 * 1000)
        condition:setOutfit({lookType = 59})
        
        if player:getTown():getId(1) then
        player:addCondition(condition)
        else if player:getTown:getId(2) then
        player:addCondition(condition2)
        
        -- Enter to Arena
        player:teleportTo(town.enterPos)
        town.enterPos:sendMagicEffect(CONST_ME_TELEPORT)
        player:setPvPArenaPlayer(true)
 
Last edited:
Worked perfectly! Thanks a lot @mano368

If I might ask, before opening another thread. There could be a chance to automatically set outfit A if the player from town 1, and outfit B if the player is from town 2? Using the same PvPArena triggers. Also set the outfit that player has before entering to arena as soon the player exits (by being killed inside or using exit teleport, guess this will need target:setPvPArenaPlayer(false)), and don't allow outfit change if player isPvPArena. Msg me if any other information is needed, regards! :D

I'm currently trying something like this but is not much accurate:
Lua:
    if not player:isPvPArenaPlayer() then
        if position ~= town.tileEnterPos then
            player:sendCancelMessage("No perteneces a la faccion correcta para entrar aqui.")
            player:teleportTo(fromPosition, true)
            return true
        end
        --- Outfit
        local condition = Condition(CONDITION_OUTFIT)
        condition:setTicks(10 * 1000)
        condition:setOutfit({lookType = 60})
      
        local condition2 = Condition(CONDITION_OUTFIT)
        condition:setTicks(10 * 1000)
        condition:setOutfit({lookType = 59})
      
        if player:getTown():getId(1) then
        player:addCondition(condition)
        else if player:getTown:getId(2) then
        player:addCondition(condition2)
      
        -- Enter to Arena
        player:teleportTo(town.enterPos)
        town.enterPos:sendMagicEffect(CONST_ME_TELEPORT)
        player:setPvPArenaPlayer(true)
yes, but If you don't want to allow player change outfit in arena, just modify in the same file...
after:
Lua:
function Creature:onChangeOutfit(outfit)

add:
Lua:
local player = Player(self)
if player:isPvPArenaPlayer() then
     player:sendCancelMessage("You cannot change outfit while in pvp event.")
     return false
end

add in the same place you added PVP_ARENA_PLAYERS = {}
Lua:
PVP_ARENA_PLAYERS_OUTFIT = {} -- TABLE WITH PLAYERS OUTFITS
and change your movement and creaturescript(also your global) to:
Lua:
-- Globalevent used to teleport players out of arena when server shuts down --
local globaleventPvPArena = GlobalEvent("PvP_Arena_Global")
function globaleventPvPArena.onShutdown()
    for _, player in pairs(Game.getPlayers()) do
        if player and player:isPvPArenaPlayer() then
            local town = config[player:getTown():getId()]
            if town then
                player:setPvPArenaPlayer(false) -- added to remove player from event
                player:teleportTo(town.exitPos)
                player:setOutfit(PVP_ARENA_PLAYERS_OUTFIT[player:getName()])-- give player outfit back after removing from event
            end
        end
    end
    return true
end
globaleventPvPArena:register()

-- Prepare death. Handles players dying in arena. --
local creatureeventPvPArena = CreatureEvent("PvP_Arena_PrepareDeath")
function creatureeventPvPArena.onPrepareDeath(creature, killer)
    if not creature:isPlayer() then return true end
    if not creature:isPvPArenaPlayer() then return true end
    local town = config[creature:getTown():getId()]
    if not town then return true end

    creature:teleportTo(town.exitPos)
    creature:addHealth(creature:getMaxHealth())
    creature:addMana(creature:getMaxMana())
    print("PVP")
    creature:setPvPArenaPlayer(false)
    creature:setOutfit(PVP_ARENA_PLAYERS_OUTFIT[creature:getName()])-- give player outfit back
    return false
end
creatureeventPvPArena:register()


-- Moveevent used to teleport players in and out of the arena --
local movementPvPArena = MoveEvent()
movementPvPArena:type("stepin")

-- change player looktype and save outfit before enter arena
local function setEventOutfit(player, typeA, typeB, colorA, colorB)
    if player == nil or typeA == nil or typeB == nil or colorA == nil or colorB == nil then
        return print("local function setEventOutfit with empty argument")
    end

    local looktype = typeA
    local color = colorA
    if player:getTown():getId() == 2 then
        looktype = typeB
        color = colorB
    end

    PVP_ARENA_PLAYERS_OUTFIT[player:getName()] = player:getOutfit() -- save players outfit
    player:setOutfit({lookType = looktype, lookLegs = color, lookHead = color, lookFeet = color, lookBody = color})
end

function movementPvPArena.onStepIn(player, item, position, fromPosition)
    if not player then return true end
    local town = config[player:getTown():getId()]
    if not town then
        player:sendCancelMessage("You do not have a town set. Report to GM.")
        player:teleportTo(fromPosition, true)
        return true
    end
 
    if not player:isPvPArenaPlayer() then
        if position ~= town.tileEnterPos then
            player:sendCancelMessage("You do not have the correct town to enter here.")
            player:teleportTo(fromPosition, true)
            return true
        end
       
        --- Outfit
        setEventOutfit(player, 60, 59, 94, 82) -- change players from town 1 to 60 and from town 2 to 59, and set color 94 and 82 for each one
        -- teleport and add player to event
        player:teleportTo(town.enterPos)
        town.enterPos:sendMagicEffect(CONST_ME_TELEPORT)
        player:setPvPArenaPlayer(true)
    else
        if position ~= town.tileExitPos then
            player:sendCancelMessage("You do not have the correct town to exit here.")
            player:teleportTo(fromPosition, true)
            return true
        end
  
        player:teleportTo(town.exitPos)
        town.exitPos:sendMagicEffect(CONST_ME_TELEPORT)
        player:setPvPArenaPlayer(false)
        player:setOutfit(PVP_ARENA_PLAYERS_OUTFIT[player:getName()])-- give player outfit back
    end
    return true
end
keep in mind that the outfit only takes into account that there are 2 towns as you requested earlier, if you want to add more, just change the setEventOutfit function to accept more towns IDs and outfits
 
yes, but If you don't want to allow player change outfit in arena, just modify in the same file...
after:
Lua:
function Creature:onChangeOutfit(outfit)

add:
Lua:
local player = Player(self)
if player:isPvPArenaPlayer() then
     player:sendCancelMessage("You cannot change outfit while in pvp event.")
     return false
end

add in the same place you added PVP_ARENA_PLAYERS = {}
Lua:
PVP_ARENA_PLAYERS_OUTFIT = {} -- TABLE WITH PLAYERS OUTFITS
and change your movement and creaturescript(also your global) to:
Lua:
-- Globalevent used to teleport players out of arena when server shuts down --
local globaleventPvPArena = GlobalEvent("PvP_Arena_Global")
function globaleventPvPArena.onShutdown()
    for _, player in pairs(Game.getPlayers()) do
        if player and player:isPvPArenaPlayer() then
            local town = config[player:getTown():getId()]
            if town then
                player:setPvPArenaPlayer(false) -- added to remove player from event
                player:teleportTo(town.exitPos)
                player:setOutfit(PVP_ARENA_PLAYERS_OUTFIT[player:getName()])-- give player outfit back after removing from event
            end
        end
    end
    return true
end
globaleventPvPArena:register()

-- Prepare death. Handles players dying in arena. --
local creatureeventPvPArena = CreatureEvent("PvP_Arena_PrepareDeath")
function creatureeventPvPArena.onPrepareDeath(creature, killer)
    if not creature:isPlayer() then return true end
    if not creature:isPvPArenaPlayer() then return true end
    local town = config[creature:getTown():getId()]
    if not town then return true end

    creature:teleportTo(town.exitPos)
    creature:addHealth(creature:getMaxHealth())
    creature:addMana(creature:getMaxMana())
    print("PVP")
    creature:setPvPArenaPlayer(false)
    creature:setOutfit(PVP_ARENA_PLAYERS_OUTFIT[creature:getName()])-- give player outfit back
    return false
end
creatureeventPvPArena:register()


-- Moveevent used to teleport players in and out of the arena --
local movementPvPArena = MoveEvent()
movementPvPArena:type("stepin")

-- change player looktype and save outfit before enter arena
local function setEventOutfit(player, typeA, typeB, colorA, colorB)
    if player == nil or typeA == nil or typeB == nil or colorA == nil or colorB == nil then
        return print("local function setEventOutfit with empty argument")
    end

    local looktype = typeA
    local color = colorA
    if player:getTown():getId() == 2 then
        looktype = typeB
        color = colorB
    end

    PVP_ARENA_PLAYERS_OUTFIT[player:getName()] = player:getOutfit() -- save players outfit
    player:setOutfit({lookType = looktype, lookLegs = color, lookHead = color, lookFeet = color, lookBody = color})
end

function movementPvPArena.onStepIn(player, item, position, fromPosition)
    if not player then return true end
    local town = config[player:getTown():getId()]
    if not town then
        player:sendCancelMessage("You do not have a town set. Report to GM.")
        player:teleportTo(fromPosition, true)
        return true
    end
 
    if not player:isPvPArenaPlayer() then
        if position ~= town.tileEnterPos then
            player:sendCancelMessage("You do not have the correct town to enter here.")
            player:teleportTo(fromPosition, true)
            return true
        end
      
        --- Outfit
        setEventOutfit(player, 60, 59, 94, 82) -- change players from town 1 to 60 and from town 2 to 59, and set color 94 and 82 for each one
        -- teleport and add player to event
        player:teleportTo(town.enterPos)
        town.enterPos:sendMagicEffect(CONST_ME_TELEPORT)
        player:setPvPArenaPlayer(true)
    else
        if position ~= town.tileExitPos then
            player:sendCancelMessage("You do not have the correct town to exit here.")
            player:teleportTo(fromPosition, true)
            return true
        end
 
        player:teleportTo(town.exitPos)
        town.exitPos:sendMagicEffect(CONST_ME_TELEPORT)
        player:setPvPArenaPlayer(false)
        player:setOutfit(PVP_ARENA_PLAYERS_OUTFIT[player:getName()])-- give player outfit back
    end
    return true
end
keep in mind that the outfit only takes into account that there are 2 towns as you requested earlier, if you want to add more, just change the setEventOutfit function to accept more towns IDs and outfits
Amazing! Worked perfectly, thanks a lot bro!! :)
 
@mano368 Hi there mano! For some reason I started to get this error:
1704857533337.png

and function Creature:eek:nChangeOutfit(outfit) is the line 89 so the error should be there ;p can you help me?
Here's the creature.lua file just in case. Regards!
 

Attachments

@mano368 Hi there mano! For some reason I started to get this error:
View attachment 81245

and function Creature:eek:nChangeOutfit(outfit) is the line 89 so the error should be there ;p can you help me?
Here's the creature.lua file just in case. Regards!
Try to add player in the line 92
Lua:
if player and player:isPvPArenaPlayer() then
 
Back
Top