It's been awhile since I released something, so here it is. I upgraded someones else Capture The Flag event, from one of my old servers. If you reconize it, please be sure to add credits. This was tested on latest OTX based off TFS 1.3.
Let's install:
data/actions/actions.xml
data/actions/actions/scripts/ctf.lua
data/creaturescripts/creaturescripts.xml
data/creaturescripts/scripts/ctf.lua
data/globalevents/globalevents.xml
data/globalevents/scripts/ctf.lua
data/lib/libs.lua
data/lib/ctf.lua - CONFIGURATION IS ALL HERE.
data/movements/movements.xml
data/movements/ctf.lua
Now you have installed your files, you must set up your map first as such:
-Arena
-Waiting Room
-Death Room
*NOTE you must have a teleport out of the event in the Arena (on both sides) and waiting room.
On your map, you need the follow IDs:
ACTIONID - 15155 - is what you put on the tiles on each respawn of the teams. This is how you score points.
ACTIONID - 15154 - use this actionID on your teleports that teleport the player out of the arena.
ACTIONID - 15153 - use this actionID on your teleport TO the event.
Known Complications:
When the event is running, players can still enter the event tp. This only happens when the game is not maxed out players. They can only go to the waiting room and will be teleport out, or they can use the teleport in the waiting room to go back to the temple. This does NOT effect the event whatsoever. It works perfectly fine. When the event is not running, players can't enter.
You must provide your own map, sorry!
Let's install:
data/actions/actions.xml
Code:
<action fromaid="15150" toaid="15151" script="ctf.lua" />
data/actions/actions/scripts/ctf.lua
Code:
function onUse(player, item, fromPosition, target, toPosition, isHotkey)
local flag = captureTheFlag.getFlag(item)
if flag then
local info = captureTheFlag.players[player:getName()]
if info.team ~= flag.team then
flag:remove()
item:remove()
flag:setHolder(player)
info.flag = flag
for name, _ in pairs(captureTheFlag.players) do
local player = Player(name)
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, info.name .. ' has captured the flag for team ' .. (info.team == 1 and 'A' or 'B') .. '!')
end
end
end
return true
end
data/creaturescripts/creaturescripts.xml
Code:
<event type="preparedeath" name="CTFDeath" script="ctf.lua" />
<event type="healthchange" name="CTFHealthChange" script="ctf.lua" />
data/creaturescripts/scripts/ctf.lua
Code:
function onPrepareDeath(creature, killer)
if captureTheFlag.getPlayerState(creature) == CTF_STATE_FIGHT then
captureTheFlag.onDeath(creature)
return false
end
return true
end
function onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
local infoA = captureTheFlag.players[creature:getName()]
local infoB = attacker and captureTheFlag.players[attacker:getName()]
if infoA and infoB and infoA.team == infoB.team and primaryType ~= COMBAT_HEALING then
return 0, 0, 0, 0
end
return primaryDamage, primaryType, secondaryDamage, secondaryType
end
data/globalevents/globalevents.xml
Code:
<globalevent name="Capture The Flag" time="10:00:00" script="ctf.lua" />
data/globalevents/scripts/ctf.lua
Code:
function onTime()
captureTheFlag.close()
captureTheFlag.start()
addEvent(captureTheFlag.round, 10*60*1000)
broadcastMessage("Capture the Flag event will start in 10 minutes, entrance in Event Room.", MESSAGE_STATUS_WARNING)
addEvent(broadcastMessage, 5 * 60 * 1000, "Capture the Flag event will start in 5 minutes, entrance in Event Room.", MESSAGE_STATUS_WARNING)
addEvent(broadcastMessage, 8 * 60 * 1000, "Capture the Flag event will start in 2 minutes, entrance in Event Room .", MESSAGE_STATUS_WARNING)
end
data/lib/libs.lua
Code:
dofile('data/lib/ctf.lua')
data/lib/ctf.lua - CONFIGURATION IS ALL HERE.
Code:
local function newOutfitCondition(outfit)
local condition = Condition(CONDITION_OUTFIT)
condition:setTicks(120 * 60 * 1000) -- estava: condition:setTicks(-1)
condition:setOutfit(outfit)
return condition
end
CTF_STATE_NONE = 0
CTF_STATE_WAIT = 1
CTF_STATE_FIGHT = 2
CTF_TEAM_A = 1
CTF_TEAM_B = 2
if not captureTheFlag then
Flag = {
-- (Modify) effect period (in ms)
effectPeriod = 3000,
new = function(self, obj)
return setmetatable(obj, {__index = self})
end
}
captureTheFlag = {
-- Whether the event is happening right now
open = false,
-- (Modify) How many points to win
goal = 10,
-- (Modify) Rewards: {itemid, count}
rewards = {
{26337, 1},
},
-- [name] = {name = 'playerName', state = CTF_STATE_, team = CTF_TEAM_, flag = Frag|nil}
players = { },
-- (Modify) Waiting Room position
waitingRoom = Position(1536, 896, 14),
-- Death Room position
deathRoom = Position(1459, 907, 14),
-- (Modify) Exit position,
exit = Position(1000, 1000, 7),
teams = {
[CTF_TEAM_A] = {
-- (Modify) Team A Outfit
outfit = newOutfitCondition {
lookType = 619,
lookHead = 114,
lookBody = 94,
lookLegs = 94,
lookFeet = 114
},
-- (Modify) Team A Outfit
outfitFlag = newOutfitCondition {
lookType = 619,
lookHead = 132,
lookBody = 132,
lookLegs = 132,
lookFeet = 132
},
-- (Modify) Base position (entrance)
base = Position(1412, 854, 14),
-- (Modify) Flag, change position and actionid
flag = Flag:new {position = Position(1424, 875, 14), id = 8617, actionid = 15150, team = CTF_TEAM_A},
-- How many players are in this team
players = 0,
-- How many points the team has scored so far
score = 0
},
[CTF_TEAM_B] = {
-- (Modify) Team B Outfit
outfit = newOutfitCondition {
lookType = 619,
lookHead = 114,
lookBody = 86,
lookLegs = 86,
lookFeet = 114
},
-- (Modify) Team B Outfit
outfitFlag = newOutfitCondition {
lookType = 619,
lookHead = 126,
lookBody = 126,
lookLegs = 126,
lookFeet = 126
},
-- (Modify) Base position (entrance)
base = Position(1484, 918, 14),
-- (Modify) Flag, change position and actionid
flag = Flag:new {position = Position(1470, 913, 14), id = 8622, actionid = 15151, team = CTF_TEAM_B},
-- How many players are in this team
players = 0,
-- How many points the team has scored so far
score = 0
},
}
}
function Flag:setHolder(player)
self.holder = player and player:getName()
if not self.event then
self:doEffect()
end
end
function Flag:remove()
if not self.holder then
local flag = Tile(self:getPosition()):getItemById(self.id)
flag:remove()
end
if self.event then
stopEvent(self.event)
self.event = nil
end
self.currentPosition = nil
self.holder = nil
end
function Flag:getPosition()
return self.currentPosition or self.position
end
function Flag:doEffect()
local position = self:getPosition()
local holder = Player(self.holder)
if holder then
holder:addCondition(captureTheFlag.teams[captureTheFlag.players[holder:getName()].team].outfitFlag)
position = holder:getPosition()
end
position:sendMagicEffect(CONST_ME_TUTORIALARROW)
self.event = addEvent(self.doEffect, self.effectPeriod, self)
end
function Flag:drop(position)
local flag = Game.createItem(self.id, 1, position)
flag:setActionId(self.actionid)
self.currentPosition = position
self.holder = nil
if not self.event then
self:doEffect()
end
end
captureTheFlag.start = function()
if captureTheFlag.open then
return false
end
captureTheFlag.open = true
for _, team in ipairs(captureTheFlag.teams) do
team.score = 0
team.flag:drop(team.flag.position)
end
end
captureTheFlag.close = function()
if not captureTheFlag.open then
return true
end
for _, info in pairs(captureTheFlag.players) do
local player = Player(info.name)
captureTheFlag.onLeave(player)
end
for _, team in ipairs(captureTheFlag.teams) do
team.flag:remove()
team.players = 0
team.score = 0
end
captureTheFlag.open = false
end
captureTheFlag.round = function(team)
if not captureTheFlag.open then
return true
end
local winner
for _, team in ipairs(captureTheFlag.teams) do
team.flag:remove()
team.flag:drop(team.flag.position)
if team.score == captureTheFlag.goal then
winner = _
end
end
if not winner then
local status = 'Team A: ' .. captureTheFlag.teams[CTF_TEAM_A].score .. ' x Team B: ' .. captureTheFlag.teams[CTF_TEAM_B].score
if team then
status = string.format('Team %s has returned the flag and won the round. %s', team == CTF_TEAM_A and 'A' or 'B', status)
end
for _, info in pairs(captureTheFlag.players) do
local player = Player(info.name)
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, status)
player:teleportTo(captureTheFlag.teams[info.team].base)
player:addCondition(captureTheFlag.teams[info.team].outfit)
info.state = CTF_STATE_FIGHT
end
else
local status = 'Team ' .. (winner == CTF_TEAM_A and 'A' or 'B') .. ' has won!'
for _, info in pairs(captureTheFlag.players) do
local player = Player(info.name)
player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, status)
if info.team == winner then
for i, reward in ipairs(captureTheFlag.rewards) do
player:addItem(reward[1], reward[2])
end
end
end
captureTheFlag.close()
end
end
captureTheFlag.getPlayerState = function(player)
local info = captureTheFlag.players[player:getName()]
return info and info.state or CTF_STATE_NONE
end
captureTheFlag.setPlayerState = function(player, state)
local info = captureTheFlag.players[player:getName()]
if info then
info.state = state
end
end
captureTheFlag.onJoin = function(player)
local info = {name = player:getName(), state = CTF_STATE_WAIT, flag = false}
local playersA, playersB = captureTheFlag.teams[CTF_TEAM_A].players, captureTheFlag.teams[CTF_TEAM_B].players
if playersA == playersB then
info.team = math.random(CTF_TEAM_A, CTF_TEAM_B)
elseif playersA > playersB then
info.team = CTF_TEAM_B
else
info.team = CTF_TEAM_A
end
captureTheFlag.players[info.name] = info
captureTheFlag.teams[info.team].players = captureTheFlag.teams[info.team].players + 1
player:teleportTo(captureTheFlag.waitingRoom)
player:addCondition(captureTheFlag.teams[info.team].outfit)
player:registerEvent('CTFHealthChange')
player:registerEvent('CTFDeath')
end
captureTheFlag.onDeath = function(player)
local info = captureTheFlag.players[player:getName()]
if info then
-- info.state = CTF_STATE_WAIT MUDEI AQUI, PROBLEM?
info.state = CTF_STATE_FIGHT
if info.flag then
info.flag:drop(info.flag.position)
info.flag = nil
end
end
--player:teleportTo(captureTheFlag.waitingRoom) MUDEI AQUI, PROBLEM?
player:teleportTo(captureTheFlag.deathRoom)
player:addCondition(captureTheFlag.teams[info.team].outfit)
-- testar
player:sendTextMessage(MESSAGE_INFO_DESCR, "You was killed.")
--teste
player:addHealth(player:getMaxHealth())
player:addMana(player:getMaxMana())
if player:getIp() == 0 then
captureTheFlag.onLeave(player)
end
end
captureTheFlag.onLeave = function(player)
local info = captureTheFlag.players[player:getName()]
if info then
captureTheFlag.teams[info.team].players = captureTheFlag.teams[info.team].players - 1
captureTheFlag.players[info.name] = nil
if info.flag then
info.flag:drop(info.flag.position)
info.flag = nil
end
end
player:teleportTo(captureTheFlag.exit)
player:removeCondition(CONDITION_OUTFIT)
player:unregisterEvent('CTFHealthChange')
player:unregisterEvent('CTFDeath')
end
captureTheFlag.getFlag = function(item)
for _, team in ipairs(captureTheFlag.teams) do
if team.flag.id == item:getId() and team.flag.actionid == item:getActionId() then
return team.flag
end
end
return nil
end
end
data/movements/movements.xml
Code:
<movevent event="StepIn" fromaid="15153" toaid="15155" script="ctf.lua" />
data/movements/ctf.lua
Code:
local CTF_JOIN = 15153
local CTF_LEAVE = 15154
local CTF_DROPFLAG = 15155
function onStepIn(creature, item, position, fromPosition)
local actionid = item:getActionId()
if not captureTheFlag.open then
if position ~= fromPosition then
creature:teleportTo(fromPosition)
end
creature:sendCancelMessage('This event is currently closed.')
return true
end
if creature:getLevel() < 200 then
local vaeas = {x = 1000, y = 1000, z = 7} -- 32470, 32473, 6
creature:teleportTo(vaeas)
creature:sendTextMessage(MESSAGE_INFO_DESCR, "YOU NEED LEVEL 200+ TO ENTER.")
return false
end
-- CAPTURE START
if creature:isPlayer() then
if creature:getItemCount(2165) > 0 then
local vaeap = {x = 1000, y = 1000, z = 7} -- 32470, 32473, 6
creature:teleportTo(vaeap)
creature:sendTextMessage(MESSAGE_INFO_DESCR, "You can't enter with stealth ring.")
return false
end
end
-- CAPTURE END
-- AQUI
if actionid == CTF_JOIN then
captureTheFlag.onJoin(creature)
broadcastMessage("Player "..creature:getName().." joined Capture The Flag event!", MESSAGE_STATUS_WARNING)
elseif actionid == CTF_LEAVE then
captureTheFlag.onLeave(creature)
broadcastMessage("Player "..creature:getName().." left the event Capture The Flag!", MESSAGE_STATUS_WARNING)
elseif actionid == CTF_DROPFLAG then
local info = captureTheFlag.players[creature:getName()]
local team = captureTheFlag.teams[info.team]
if info.flag and position:getDistance(team.base) < position:getDistance(captureTheFlag.teams[info.team == 1 and 2 or 1].base) then
team.score = team.score + 1
captureTheFlag.round(info.team)
info.flag = nil
end
end
return true
end
Now you have installed your files, you must set up your map first as such:
-Arena
-Waiting Room
-Death Room
*NOTE you must have a teleport out of the event in the Arena (on both sides) and waiting room.
On your map, you need the follow IDs:
ACTIONID - 15155 - is what you put on the tiles on each respawn of the teams. This is how you score points.
ACTIONID - 15154 - use this actionID on your teleports that teleport the player out of the arena.
ACTIONID - 15153 - use this actionID on your teleport TO the event.
Known Complications:
When the event is running, players can still enter the event tp. This only happens when the game is not maxed out players. They can only go to the waiting room and will be teleport out, or they can use the teleport in the waiting room to go back to the temple. This does NOT effect the event whatsoever. It works perfectly fine. When the event is not running, players can't enter.
You must provide your own map, sorry!