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

Citywar

xGustadoIts

New Member
Joined
Apr 13, 2015
Messages
50
Reaction score
0
please help me to fix tfs 1.x

Code:
Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/modalwindowhelper.lua:onModalWindow
data/creaturescripts/scripts/citywar.lua:147: attempt to call method 'getBankBalance' (a nil value)
stack traceback:
        [C]: in function 'getBankBalance'
        data/creaturescripts/scripts/citywar.lua:147: in function 'callback'
        data/creaturescripts/scripts/modalwindowhelper.lua:26: in function <data/creaturescripts/scripts/modalwindowhelper.lua:1>

Code:
function onLogout(player)
    local city, registry = CityWars.getPlayerWar(player)
    if city then
        city:onLogout(player)
    end
    return true
end
 
function onPrepareDeath(player, killer)
    local city, registry = CityWars.getPlayerWar(player)
    city:onDeath(player, registry, killer)
    return false
end
 
local function newSetting(func, format, id)
    return {
        format = format,
        func = func,
        current = 0,
        id = id
    }
end
 
local function getSetting(settings, id)
    for _, setting in ipairs(settings) do
        if setting.id == id then
            return (setting.func(setting.current))
        end
    end
end
 
local function filter(list, predicate)
    local ret = {}
    for k, v in ipairs(list) do
        if predicate(v) then
            table.insert(ret, v)
        end
    end
    return ret
end
 
local function getGuildLeaders(guild)
    return filter(guild:getMembersOnline(), function(p) return p:getGuildLevel() >= CityWars.minGuildRank end)
end
 
local SETTING_CITY = 0
local SETTING_BUYIN = 1
local SETTING_FRAGLIMIT = 2
local SETTING_UE = 3
local SETTING_SD = 4
local SETTING_TEAMSIZE = 5
 
local function sendWarSettings(player, info)
    local enemyGuild = Guild(info.invitedGuildId)
    if enemyGuild then
        local window = ModalWindow {
            title = 'War against ' .. enemyGuild:getName(),
            message = 'Settings:'
        }
 
        info.settings = info.settings or {
            newSetting(function(n)
                if n < CITY_WAR_FIRST then
                    n = CITY_WAR_FIRST
                elseif n > CITY_WAR_LAST then
                    n = CITY_WAR_LAST
                end
 
                return CityWars[n].name, n
            end, 'City: %s', SETTING_CITY),
 
            newSetting(function(n)
                n = math.max(0, n)
                return n * CityWars.buyInMultiplier, n
            end, 'Buy in: %d gold coins', SETTING_BUYIN),
 
            newSetting(function(n)
                n = math.max(1, n)
                return n * CityWars.fragLimitMultiplier, n
            end, 'Frag limit: %d kills', SETTING_FRAGLIMIT),
 
            newSetting(function(n)
                return n % 2 == 0, n
            end, 'U.E enabled: %s', SETTING_UE),
 
            newSetting(function(n)
                return n % 2 ~= 0, n
            end, 'S.D only: %s', SETTING_SD),
 
            newSetting(function(n)
                n = math.max(1, n)
                return n * CityWars.teamSizeMultiplier, n
            end, 'Team size: %d', SETTING_TEAMSIZE)
        }
 
        for _, setting in ipairs(info.settings) do
            local s, n = setting.func(setting.current)
            local choice = window:addChoice(setting.format:format(s))
            choice.setting = setting
            setting.current = n
        end
 
        window:addButton('<', function(button, choice)
            choice.setting.current = choice.setting.current - 1
            sendWarSettings(player, info)
        end)
 
        window:addButton('Ok', function(button, choice)
            local guild = player:getGuild()
            if not guild then
                return player:sendCancelMessage('You do not belong to a guild.')
            end
 
            local enemyGuild = Guild(info.invitedGuildId)
            if not enemyGuild then
                return player:sendCancelMessage('Enemy guild not found.')
            else
                local ret = CityWars.isValidGuild(enemyGuild)
                if ret == CW_RETURNVALUE_TOOFEWPLAYERS then
                    return player:sendCancelMessage('The enemy guild has too few online players to be able to participate in a city war.')
                elseif ret == CW_RETURNVALUE_TOOFEWUNIQUEIPS then
                    return player:sendCancelMessage('The enemy guild has too few unique ip addresses to be able to participate in a city war.')
                end
            end
 
            local enemyLeaders = getGuildLeaders(enemyGuild)      
            if #enemyLeaders == 0 then
                return player:sendCancelMessage('There is no one online in the enemy guild able to accept a city war request.')
            end
 
            local city = CityWars.getCityByName(getSetting(info.settings, SETTING_CITY))
            if not city then
                return player:sendCancelMessage('City not found.')
            elseif not city:isFree() then
                return player:sendCancelMessage(city:getName() .. ' is being used at the moment.')
            end      
 
            local options = {
                city = city,
                ultimateExplosion = getSetting(info.settings, SETTING_UE),
                fragLimit = getSetting(info.settings, SETTING_FRAGLIMIT),
                suddenDeathOnly = getSetting(info.settings, SETTING_SD),
                teamSize = getSetting(info.settings, SETTING_TEAMSIZE),
                buyIn = getSetting(info.settings, SETTING_BUYIN)
            }        
 
            if guild:getBankBalance() < options.buyIn then
                return player:sendCancelMessage('Your guild does not have enough funds in the bank to pay the buy in.')
            end
 
            local ret = CityWars.onInvite(city, player, enemyGuild, enemyLeaders, options)
            if ret == CW_RETURNVALUE_LIVEINVITE then
                return player:sendCancelMessage('The last invite you sent to this guild is still active.')
            elseif ret == CW_RETURNVALUE_INVITERINWAR then
                return player:sendCancelMessage('You can only invite another guild for war after your current one ends.')
            elseif ret == CW_RETURNVALUE_INVITEDINWAR then
                return player:sendCancelMessage('The guild you invited is currently in war.')
            elseif ret == CW_RETURNVALUE_NOERROR then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'The invite was sent. The enemy guild\'s leader has two minutes to accept it.')
                local guildName = player:getGuild():getName()
                for _, leader in ipairs(enemyLeaders) do
                    leader:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, '"' .. player:getName() .. '" from guild "' .. guildName .. '" has invited your guild for a city war. If you wish to accept, head to a temple and read the guild book.')
                    leader:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, CityWars.getOptionsString(options))
                end
            end
        end)
        window:setDefaultEnterButton('Ok')
 
        window:addButton('>', function(button, choice)
            choice.setting.current = choice.setting.current + 1
            sendWarSettings(player, info)
        end)
 
        window:addButton('Cancel')
 
        window:sendToPlayer(player)
    end
 
    return false
end
 
function onTextEdit(player, item, text)
    player:unregisterEvent('CityWarInvite')
    if item:getId() == CityWars.inviteItemId then
        local enemy = {}
        for k, v in ipairs(Game.getPlayers()) do
            local tmp = v:getGuild()
            if tmp and tmp:getName():lower() == text:lower() then
                enemy.guild = tmp
                enemy.leaders = getGuildLeaders(enemy.guild)          
                break
            end
        end
 
        if not enemy.guild then
            return player:sendCancelMessage('Enemy guild not found.')
        else
            local guild = player:getGuild()
            if not guild then
                return player:sendCancelMessage('You do not belong to a guild.')
            end
 
            if guild:getId() == enemy.guild:getId() then
                return player:sendCancelMessage('You can not start a war against your own guild.')
            end
 
            local ret = CityWars.isValidGuild(enemy.guild)
            if ret == CW_RETURNVALUE_TOOFEWPLAYERS then
                return player:sendCancelMessage('The enemy guild has too few online players to be able to participate in a city war.')
            elseif ret == CW_RETURNVALUE_TOOFEWUNIQUEIPS then
                return player:sendCancelMessage('The enemy guild has too few unique ip addresses to be able to participate in a city war.')
            end
        end
 
        if #enemy.leaders == 0 then
            return player:sendCancelMessage('There are no online leaders on the enemy guild.')
        end  
 
        return sendWarSettings(player, {
            invitedGuildId = enemy.guild:getId()
        })
    end
end
 
Last edited:
Add function
Code:
local function getGuildBalance(id)
   local guild = Guild(id)
    if guild then
        return guild:getBankBalance()
    else
        local balance
        local resultId = db.storeQuery('SELECT `balance` FROM `guilds` WHERE `id` = ' .. id)
        if resultId then
            balance = result.getNumber(resultId, 'balance')
            result.free(resultId)
        end

        return balance
    end
end

Change line 147:
Code:
if guild:getBankBalance() < options.buyIn then

To:
Code:
if getGuildBalance(guild:getId()) < options.buyIn then
 
Add function
Code:
local function getGuildBalance(id)
   local guild = Guild(id)
    if guild then
        return guild:getBankBalance()
    else
        local balance
        local resultId = db.storeQuery('SELECT `balance` FROM `guilds` WHERE `id` = ' .. id)
        if resultId then
            balance = result.getNumber(resultId, 'balance')
            result.free(resultId)
        end

        return balance
    end
end

Change line 147:
Code:
if guild:getBankBalance() < options.buyIn then

To:
Code:
if getGuildBalance(guild:getId()) < options.buyIn then
okok i was checking the wrong script im idiot XD thanks im going to check if it Works now^^
 
@HeberPcL ok now im getting this error

Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/modalwindowhelper.lua:eek:nModalWindow
data/creaturescripts/scripts/citywar.lua:4: attempt to call method 'getBankBalance' (a nil value)
stack traceback:
[C]: in function 'getBankBalance'
data/creaturescripts/scripts/citywar.lua:4: in function 'getGuildBalance'
data/creaturescripts/scripts/citywar.lua:163: in function 'callback'
data/creaturescripts/scripts/modalwindowhelper.lua:26: in function <data/creaturescripts/scripts/modalwindowhelper.lua:1>

Lane 163 is the same as before because i added too the function u said >.< so same error and error in the function u said T.T
 
Change function:
Code:
local function getGuildBalance(id)
        local guild = Guild(id)
        local balance
        local resultId = db.storeQuery('SELECT `balance` FROM `guilds` WHERE `id` = ' .. id)
        if resultId then
            balance = result.getNumber(resultId, 'balance')
            result.free(resultId)
        end

        return balance
end
 
@HeberPcL Ok thanks my friend! now it worked but now i got a error when i accept the war T_T
Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/modalwindowhelper.lua:eek:nModalWindow
data/lib/citywars.lua:542: attempt to call method 'getBankBalance' (a nil value)
stack traceback:
[C]: in function 'getBankBalance'
data/lib/citywars.lua:542: in function 'onInviteAccepted'
data/actions/scripts/Novos/citywar.lua:146: in function 'callback'
data/creaturescripts/scripts/modalwindowhelper.lua:26: in function <data/creaturescripts/scripts/modalwindowhelper.lua:1>

That's the script: on lib
Code:
CITY_WAR_FIRST      = 0
CITY_WAR_EDRON     = 0
CITY_WAR_YALAHAR  = 1
CITY_WAR_DARASHIA      = 2
CITY_WAR_LIBERTYBAY  = 3
CITY_WAR_LAST       = 3
 
CW_RETURNVALUE_NOERROR = 0
CW_RETURNVALUE_LIVEINVITE = 1
CW_RETURNVALUE_INVITERINWAR = 2
CW_RETURNVALUE_INVITEDINWAR = 3
CW_RETURNVALUE_TOOFEWPLAYERS = 4
CW_RETURNVALUE_TOOFEWUNIQUEIPS = 5
 

local function capitalize(self)
    local tmp = self:lower()
    return tmp:sub(1, 1):upper() .. tmp:sub(2)
end
 
local function reduce(list, predicate)
    local ret = list[1]
    for i = 2, #list do
        ret = predicate(ret, list[i])
    end
    return ret
end
 
local function resumeThread(thread, info, ...)
    local suc, tmp = coroutine.resume(thread, ...)
    if not suc then
        error(tmp)
    end
 
    local wait = tonumber(tmp)
    if wait then
        info.id = addEvent(resumeThread, wait, thread, info)
    end
end
 
local function addThread(func, delay, ...)
    local thread = coroutine.create(func)
    local info = { }
    if delay == 0 then
        resumeThread(thread, info, ...)
    else
        info.id = addEvent(resumeThread, delay, thread, info, ...)
    end
    return info
end
 
if not CityWars then
    CityWars = {
        cityWarDuration = 2 * 60 * 60,
        cityWarStorage = 15600,
        rankingLimit = 10, -- How many players should appear in the ranking message
        minGuildSize = 1, -- How many guild members need to be online
        minDifferentIPs = 1, -- Minimum number of unique ips
        inviteItemId = 1949,
        buyInMultiplier = 50000,
        fragLimitMultiplier = 5,
        teamSizeMultiplier = 10,
 
        minGuildRank = 3, -- Minimum guild rank to start/accept/cancel a city war
        removeConditions = {CONDITION_POISON, CONDITION_FIRE, CONDITION_ENERGY, CONDITION_BLEEDING, CONDITION_PARALYZE, CONDITION_INFIGHT},
        -- [invitedName] = { {city = City, invitedPlayer = Player, invitedGuild = Guild, inviterPlayer = Player, inviterGuild = Guild, options = { }} }
        invites = {},
     
        [CITY_WAR_EDRON] = {
            spawns = {
                -- Team 1 position
                [1] = Position(30974, 32641, 7),
                -- Team 2 position
                [2] = Position(30909, 32519, 7),
            },
 
            name = 'edron',
 
            --  [playerId] = {player = player, name = name, team = 1/2, kills = 0, deaths = 0}
            players = { },
 
            -- [team] = {guild = guild, name = name, kills = 0, deaths = 0}
            teams = { }
        },
 
        [CITY_WAR_DARASHIA] = {
            spawns = {
                -- Team 1 position
                [1] = Position(31217, 32552, 7),
                -- Team 2 position
                [2] = Position(31295, 32639, 7),
            },
 
            name = 'darashia',
 
            --  [playerId] = {player = player, name = name, team = 1/2, kills = 0, deaths = 0}
            players = { },
 
            -- [team] = {guild = guild, name = name, kills = 0, deaths = 0}
            teams = { }
        },
 
        [CITY_WAR_LIBERTYBAY] = {
            spawns = {
                -- Team 1 position
                [1] = Position(30740, 32734, 7),
                -- Team 2 position
                [2] = Position(30767, 32567, 7),
            },
 
            name = 'liberty bay',
 
            --  [playerId] = {player = player, name = name, team = 1/2, kills = 0, deaths = 0}
            players = { },
 
            -- [team] = {guild = guild, name = name, kills = 0, deaths = 0}
            teams = { }
        },
 
        [CITY_WAR_YALAHAR] = {
            spawns = {
                -- Team 1 position
                [1] = Position(30925, 32825, 7),
                -- Team 2 position
                [2] = Position(30982, 32827, 7),
            },
 
 
            name = 'yalahar',
 
            --  [playerId] = {player = player, name = name, team = 1/2, kills = 0, deaths = 0}
            players = { },
 
            -- [team] = {guild = guild, name = name, kills = 0, deaths = 0}
            teams = { },
        },
    }
 
    local City = {}
    City.__index = City
 
    for i = CITY_WAR_FIRST, CITY_WAR_LAST do
        setmetatable(CityWars[i], City)
    end
 
    function City:onStart()
        if not self.endEvent then
            self.endEvent = addThread(
                function(city)
                    for i = 10, 1, -1 do
                        city:countdown(i)
                        coroutine.yield(60 * 1000)
                    end
 
                    local winner    
                    if self.teams[1].kills > self.teams[2].kills then
                        winner = 1
                    elseif self.teams[1].kills < self.teams[2].kills then
                        winner = 2
                    end
 
                    city:onEnd(winner)              
                end,
 
                (CityWars.cityWarDuration - 10 * 60) * 1000,
 
                self
            )
        end
    end
 
    function City:onEnd(winner)
        stopEvent(self.endEvent.id)
 
        for k, v in pairs(self.players) do
            if v.player and v.player:getStorageValue(CityWars.cityWarStorage) > 0 then
                v.player:teleportTo(v.player:getTown():getTemplePosition())
                v.player:addHealth(v.player:getMaxHealth())
                v.player:addMana(v.player:getMaxMana())
                v.player:setStorageValue(CityWars.cityWarStorage, -1)
                v.player:unregisterEvent('CityWarDeath')
                for _, cond in ipairs(CityWars.removeConditions) do
                    v.player:removeCondition(cond, CONDITIONID_DEFAULT)
                end
            end
        end  
 
        self:broadcastMessage(self:getRank())
 
        if not winner then
            self:broadcastMessage('The war has ended, it is a draw!')
 
            local guild1 = Guild(self.teams[1].id)
            local guild2 = Guild(self.teams[2].id)
            if guild1 then
                guild1:setBankBalance(guild1:getBankBalance() + self.options.buyIn)
            end
            if guild2 then
                guild2:setBankBalance(guild2:getBankBalance() + self.options.buyIn)
            end
        else
            self:broadcastMessage('The war has ended, "' .. self.teams[winner].name .. '" have won the war and taken home the prize of ' .. (2 * self.options.buyIn) .. ' gold coins.')
 
            local winnerGuild = Guild(self.teams[winner].id)
            if winnerGuild then
                winnerGuild:setBankBalance(winnerGuild:getBankBalance() + 2 * self.options.buyIn)
            end
        end  
 
        self.players = { }
        self.teams = { }
        self.options = { }
        self.endEvent = nil
    end
 
    function City:onCancel(player)
        if player:getGuildLevel() < CityWars.minGuildRank then
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Only leaders can cancel an ongoing city war.')
            return false
        end
 
        local registry = self.players[player:getGuid()]
        self:broadcastMessage(player:getName() .. ' has forfeited the war.')
 
        self:onEnd((registry.team == 1) and 2 or 1)
    end
 
    function City:onCastSpell(player, kind)
        if player:getStorageValue(CityWars.cityWarStorage) > 0 then
            if kind == 'ultimateExplosion' and not self.options.ultimateExplosion then
                return false
            elseif kind == 'areaSpell' and self.options.suddenDeathOnly then
                return false
            end
        end
        return true
    end
 
    function City:onScoreUpdated()
        local winner
        for i, team in ipairs(self.teams) do
            if team.kills >= self.options.fragLimit then
                winner = i
                break
            end  
        end
 
        self:broadcastScore()
        if winner then  
            self:onEnd(winner)
        end
    end
 
    function City:onJoin(player)
        local registry = self.players[player:getGuid()]
        local team = self.teams[registry.team]
        if team.players < self.options.teamSize then
            if player:getStorageValue(CityWars.cityWarStorage) < 0 then
                team.players = team.players + 1
 
                player:registerEvent('CityWarDeath')
                player:setStorageValue(CityWars.cityWarStorage, 1)
                player:teleportTo(self.spawns[registry.team])
            end
        else
            player:sendTextMessage('Your guild has reached the team limit! You may not join them right now.')
        end
    end
 
    function City:onDeath(player, registry, killer)
        if player:getStorageValue(CityWars.cityWarStorage) > 0 then      
            player:teleportTo(self.spawns[registry.team])
            player:addHealth(player:getMaxHealth())
            player:addMana(player:getMaxMana())
            for _, cond in ipairs(CityWars.removeConditions) do
                player:removeCondition(cond, CONDITIONID_DEFAULT)
            end
 
            registry.deaths = registry.deaths + 1
            local team = self.teams[registry.team]
            team.deaths = team.deaths + 1
 
            local killerRegistry
            if killer then
                if not killer:isPlayer() then
                    killer = killer:getMaster()
 
                    if not killer or not killer:isPlayer() then
                        killer = nil
                    end
                end
 
                if killer then
                    local _
                    _, killerRegistry = CityWars.getPlayerWar(killer)    
                end
            end
 
            if killerRegistry and killerRegistry.team ~= registry.team then
                killerRegistry.kills = killerRegistry.kills + 1
            end      
 
            local enemyTeam = self.teams[(registry.team == 1) and 2 or 1]
            enemyTeam.kills = enemyTeam.kills + 1
 
            self:onScoreUpdated()
            return true
        end
 
        return false
    end
 
    function City:onLeave(player)    
        if player:getStorageValue(CityWars.cityWarStorage) > 0 then      
            player:unregisterEvent('CityWarDeath')
            player:setStorageValue(CityWars.cityWarStorage, -1)
            player:teleportTo(player:getTown():getTemplePosition())
            for _, cond in ipairs(CityWars.removeConditions) do
                player:removeCondition(cond, CONDITIONID_DEFAULT)
            end
 
            local registry = self.players[player:getGuid()]
            registry.player = nil
            -- update team's player count
            local team = self.teams[registry.team]
            team.players = team.players - 1      
        end
    end
    City.onLogout = City.onLeave
 
    function City:getName()
        return capitalize(self.name)
    end
 
    function City:addPlayer(player, team)
        local current = self.players[player:getGuid()]
        if not current then
            current = {player = player, team = team, name = player:getName(), kills = 0, deaths = 0}
        else
            -- update player object
            current.player = player
        end
        self.players[player:getGuid()] = current
    end
 
    function City:countdown(minutesLeft)
        self:broadcastMessage('Countdown: ' .. minutesLeft .. ' minutes until the war ends.')
    end
 
    function City:broadcastMessage(msg)
        for k, v in pairs(self.players) do
            if v.player then
                v.player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, msg)
            end
        end
    end
 
    local broadcastFormat = 'Score: "%s" (%d) versus "%s" (%d)'
    function City:broadcastScore()
        self:broadcastMessage(broadcastFormat:format(self.teams[1].name, self.teams[1].kills, self.teams[2].name, self.teams[2].kills))
    end
 
    function City:getRank()
        local rank = {}
        for k, v in pairs(self.players) do
            table.insert(rank, {name = v.name, kills = v.kills, deaths = v.deaths, guildName = self.teams[v.team].name})
        end
        table.sort(rank,
            function(a, b)
                if a.kills ~= b.kills then
                    return a.kills > b.kills
                end
                return a.deaths < b.deaths
            end      
        )
        local msg = 'Ranking:'
        for i = 1, CityWars.rankingLimit do
            local player = rank[i]
            if player then          
                msg = msg .. '\n' .. i .. '. ' .. player.name .. ' - ' .. player.kills .. '/' .. player.deaths .. ' From: "' .. player.guildName .. '"'
            end
        end
        return msg
    end
 
    local winFormat = '"%s" has beaten "%s" by %d to %d kills.'
    local drawFormat = 'The city war between "%s" and "%s" resulted in a draw.'
    function City:broadcastResult()
        local msg
        if self.teams[1].kills > self.teams[2].kills then
            msg = winFormat:format(self.teams[1].name, self.teams[2].name, self.teams[1].kills, self.teams[2].kills)
        elseif self.teams[1].kills < self.teams[2].kills then
            msg = winFormat:format(self.teams[2].name, self.teams[1].name, self.teams[2].kills, self.teams[1].kills)
        else
            msg = drawFormat:format(self.teams[1].name, self.teams[2].name)
        end
 
        self:broadcastMessage(msg)
    end
 
    function City:isFree()
        return #self.teams == 0
    end
end
 
function CityWars.getCityByName(name)
    for i = CITY_WAR_FIRST, CITY_WAR_LAST do
        local city = CityWars[i]
        if city.name == name then
            return city
        end
    end
 
    return nil
end
 
function CityWars.getPlayerWar(player, registerPlayer)
    local playerGuild = player:getGuild()
    if not playerGuild then
        return nil
    end
    for i = CITY_WAR_FIRST, CITY_WAR_LAST do
        local city = CityWars[i]
        if not city:isFree() then
            for k, team in ipairs(city.teams) do
             
                if team.id == playerGuild:getId() then
                    local guid = player:getGuid()
                    local registry = city.players[guid]
                    if registerPlayer and (not registry or registry.team ~= k) then
                        registry = {player = player, name = player:getName(), team = k, kills = 0, deaths = 0}
                        city.players[guid] = registry
                    end
                    return city, registry
                end
            end
        end
    end
end
 
function CityWars.isValidGuild(guild)
    local onlineMembers = guild:getMembersOnline()
    if #onlineMembers < CityWars.minGuildSize then
        return CW_RETURNVALUE_TOOFEWPLAYERS
    end
 
    local uniqueIPs = 0
    local addressMap = {}
    for k, v in ipairs(onlineMembers) do
        local ip = v:getIp()
        if ip ~= 0 and not addressMap[ip] then
            addressMap[ip] = true
            uniqueIPs = uniqueIPs + 1
        end
    end
    if uniqueIPs < CityWars.minDifferentIPs then
        return CW_RETURNVALUE_TOOFEWUNIQUEIPS
    end
 
    return CW_RETURNVALUE_NOERROR
end
 
function CityWars.getGuildWar(guild)
    for i = CITY_WAR_FIRST, CITY_WAR_LAST do
        local city = CityWars[i]
        if not city:isFree() then
            for k, team in ipairs(city.teams) do
                if team.id == guild:getId() then
                    return city
                end
            end
        end
    end
end
 
function CityWars.getInvites(guildName)
    return CityWars.invites[guildName]
end
 
function CityWars.onInviteExpired(invite)
    for k, _invite in ipairs(invite.invites) do
        if _invite == invite then
            local player = Player(invite.inviterPlayerName)
            if player then
                local guild = Guild(invite.invitedGuildId)
                local guildName = guild and guild:getName() or 'deleted guild'
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Your city war invite for guild "' .. guildName .. '" has expired.')
            end
 
            if invite.invitedLeaders then
                local guild = Guild(invite.inviterGuildId)
                local guildName = guild and guild:getName() or 'deleted guild'
                for _, leaderName in ipairs(invite.invitedLeaders) do
                    local leader = Player(leaderName)
                    if leader then
                        leader:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'You failed to answer the city war invite from guild "' .. guildName .. '" and it is now expired.')
                    end
                end
            end
 
            table.remove(invite.invites, k)
            return
        end
    end
end
 
local optionsFormat = 'City: %s | Buy in: %d gold %s | Frag limit: %d | U.E: %s | S.D only: %s | Team size: %d'
function CityWars.getOptionsString(options)
    return optionsFormat:format(options.city:getName(), options.buyIn, (options.buyIn == 1) and 'coin' or 'coins', options.fragLimit, options.ultimateExplosion and 'enabled' or 'disabled', options.suddenDeathOnly and 'true' or 'false', options.teamSize)
end
 
function CityWars.onInviteAccepted(player, invite)
    for k, _invite in ipairs(invite.invites) do
        if _invite == invite then
            stopEvent(invite.expireEvent)
            table.remove(invite.invites, k)
 
            if not invite.city:isFree() then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, invite.city:getName() .. ' is not free anymore.')
                return false
            end      
 
            local inviterGuild = Guild(invite.inviterGuildId)
            if not inviterGuild then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Inviter guild does not exist anymore.')            
                return false
            elseif CityWars.getGuildWar(inviterGuild) then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'The inviter guild is already in war.')
            end
 
            local invitedGuild = Guild(invite.invitedGuildId)
            if not invitedGuild then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'You do not belong to a guild.')            
                return false
            elseif CityWars.getGuildWar(invitedGuild) then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'You can not accept a war invite while in another one.')
                return false
            end
 
            local msg
            local start = false
            if inviterGuild:getBankBalance() < invite.options.buyIn then
                msg = 'The guild "' .. inviterGuild:getName() .. '" can not participate in this war due to lack of funds in its guild bank.'
            elseif invitedGuild:getBankBalance() < invite.options.buyIn then
                msg = 'The guild "' .. invitedGuild:getName() .. '" can not participate in this war due to lack of funds in its guild bank.'
            else
                inviterGuild:setBankBalance(inviterGuild:getBankBalance() - invite.options.buyIn)
                invitedGuild:setBankBalance(invitedGuild:getBankBalance() - invite.options.buyIn)
                start = true
                msg = 'A city war between the guilds "' .. inviterGuild:getName() .. '" and "' .. invitedGuild:getName() .. '" has begun!\n' ..
                    CityWars.getOptionsString(invite.options) .. '\n' ..
                    'If you wish to join, head to a temple and read the guild book.'
            end
 
            for _, player in ipairs(inviterGuild:getMembersOnline()) do
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, msg)
                if start then
                    invite.city:addPlayer(player, 1)
                end
            end
 
            for _, player in ipairs(invitedGuild:getMembersOnline()) do
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, msg)
                if start then
                    invite.city:addPlayer(player, 2)
                end
            end
 
            if start then
                invite.city.teams = {
                    {id = invite.inviterGuildId, name = inviterGuild:getName(), kills = 0, deaths = 0, players = 0},
                    {id = invite.invitedGuildId, name = invitedGuild:getName(), kills = 0, deaths = 0, players = 0}
                }
                invite.city.options = invite.options
                invite.city:onStart()
            end
 
            return true
        end
    end
    return false
end
 
function CityWars.onInvite(city, inviter, invitedGuild, invitedLeaders, options)
    if CityWars.getGuildWar(inviter:getGuild()) then
        return CW_RETURNVALUE_INVITERINWAR
    end
 
    if CityWars.getGuildWar(invitedGuild) then
        return CW_RETURNVALUE_INVITEDINWAR
    end
 
    local invites = CityWars.invites[invitedGuild:getName()]
    if invites and #invites ~= 0 then
        for _, invite in ipairs(invites) do
            local guild = Guild(invite.inviterGuildId)
            if guild and guild:getId() == inviter:getGuild():getId() then
                return CW_RETURNVALUE_LIVEINVITE
            end
        end
    elseif not invites then
        invites = { }
        CityWars.invites[invitedGuild:getName()] = invites
    end
 
    local invitedLeadersNames = {}
    for k, v in ipairs(invitedLeaders) do
        table.insert(invitedLeadersNames, v:getName())
    end
 
    local invite = {
        city = city,
        invites = invites,
        inviterPlayerName = inviter:getName(),
        inviterGuildId = inviter:getGuild():getId(),
        invitedGuildId = invitedGuild:getId(),
        invitedLeaders = invitedLeadersNames,
        options = options
    }
    invite.expireEvent = addEvent(CityWars.onInviteExpired, 15 * 1000, invite)
    table.insert(invites, invite)
 
    return CW_RETURNVALUE_NOERROR
end
 
and that the action scripts
Code:
--CityWars.minGuildSize = 10 

--CityWars.minDifferentIPs = 10

CityWars.onInviteExpired = function(invite)
    for k, _invite in ipairs(invite.invites) do
        if _invite == invite then
            local player = Player(invite.inviterPlayerName)
            if player then
                local guild = Guild(invite.invitedGuildId)
                local guildName = guild and guild:getName() or 'deleted guild'
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Your city war invite for guild "' .. guildName .. '" has expired.')
            end
 
            if invite.invitedLeaders then
                local guild = Guild(invite.inviterGuildId)
                local guildName = guild and guild:getName() or 'deleted guild'
                for _, leaderName in ipairs(invite.invitedLeaders) do
                    local leader = Player(leaderName)
                    if leader then
                        leader:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'You failed to answer the city war invite from guild "' .. guildName .. '" and it is now expired.')
                    end
                end
            end
 
            table.remove(invite.invites, k)
            return
        end
    end
end
 
CityWars.onInvite = function(city, inviter, invitedGuild, invitedLeaders, options)
    if CityWars.getGuildWar(inviter:getGuild()) then
        return CW_RETURNVALUE_INVITERINWAR
    end
 
    if CityWars.getGuildWar(invitedGuild) then
        return CW_RETURNVALUE_INVITEDINWAR
    end
 
    local invites = CityWars.invites[invitedGuild:getName()]
    if invites and #invites ~= 0 then
        for _, invite in ipairs(invites) do
            local guild = Guild(invite.inviterGuildId)
            if guild and guild:getId() == inviter:getGuild():getId() then
                return CW_RETURNVALUE_LIVEINVITE
            end
        end
    elseif not invites then
        invites = { }
        CityWars.invites[invitedGuild:getName()] = invites
    end
 
    local invitedLeadersNames = {}
    for k, v in ipairs(invitedLeaders) do
        table.insert(invitedLeadersNames, v:getName())
    end
 
    local invite = {
        city = city,
        invites = invites,
        inviterPlayerName = inviter:getName(),
        inviterGuildId = inviter:getGuild():getId(),
        invitedGuildId = invitedGuild:getId(),
        invitedLeaders = invitedLeadersNames,
        options = options
    }
    invite.expireEvent = addEvent(CityWars.onInviteExpired, 120 * 1000, invite)
    table.insert(invites, invite)
 
    return CW_RETURNVALUE_NOERROR
end

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    local guild = player:getGuild()
    if not guild then
        return player:sendCancelMessage('You need to belong to a guild.')
    end
    local guildId = guild:getId()
 
    local city, registry = CityWars.getPlayerWar(player)
    local window = ModalWindow {
        title = 'War Menu',
        message = 'Invite a guild to war or join, leave or cancel an ongoing war.'
    }
 
    local invite, accept, join, leave, cancel, rank
 
    if player:getGuildLevel() >= CityWars.minGuildRank then
        if not city then
            invite = window:addChoice('Invite guild to war')
            accept = window:addChoice('Accept a war invite')
        else
            cancel = window:addChoice('Cancel current war')
        end
    end
 
    if city then
        rank = window:addChoice('Show rank')
        if player:getStorageValue(CityWars.cityWarStorage) > 0 then
            leave = window:addChoice('Leave the war')
        else
            join = window:addChoice('Join the war')
        end
 
    end
 
    window:addButton('Ok', function(button, choice)
        local guild = Guild(guildId)
        if not guild then
            return player:sendCancelMessage('Your guild does not exist anymore.')
        end
 
        if invite and choice == invite then
            local ret = CityWars.isValidGuild(guild)
            if ret == CW_RETURNVALUE_TOOFEWPLAYERS then
                return player:sendCancelMessage('Your guild has too few online players to be able to participate in a city war.')
            elseif ret == CW_RETURNVALUE_TOOFEWUNIQUEIPS then
                return player:sendCancelMessage('Your guild has too few unique ip addresses to be able to participate in a city war.')
            end
 
            player:registerEvent('CityWarInvite')
            player:showTextDialog(CityWars.inviteItemId, '// Write guild name', true)
        elseif accept and choice == accept then
            local guildName = guild:getName()
            local invites = CityWars.getInvites(guildName)
            if not invites or #invites == 0 then
                return player:popupFYI('No invites were found.')
            end
 
            local invitesWindow = ModalWindow {
                title = 'Invites',
                message = 'Select an invite to accept it'
            }
 
            for _, invite in ipairs(invites) do
                local guild = Guild(invite.inviterGuildId)
                if guild then
                    local choice = invitesWindow:addChoice(guild:getName())
                    choice.invite = invite                 
                end
            end
 
            invitesWindow:addButton('Ok', function(button, choice)
                if choice then
                    CityWars.onInviteAccepted(player, choice.invite)
                end
            end)
            invitesWindow:setDefaultEnterButton('Ok')
            invitesWindow:addButton('Cancel')
 
            invitesWindow:sendToPlayer(player)
        elseif join and choice == join then
            local city, registry = CityWars.getPlayerWar(player)
            if not city then
                return player:sendCancelMessage('You are not participating in any city war.')
            end
 
            city:addPlayer(player)
            city:onJoin(player)
        elseif leave and choice == leave then
            local city, registry = CityWars.getPlayerWar(player)
            if not city then
                return player:sendCancelMessage('You are not participating in any city war.')
            end
 
            city:onLeave(player)
        elseif cancel and choice == cancel then
            local city, registry = CityWars.getPlayerWar(player)
            if not city then
                return player:sendCancelMessage('You are not participating in any city war.')
            end
 
            city:onCancel(player)
        elseif rank and choice == rank then
            local city, registry = CityWars.getPlayerWar(player)
            if not city then
                return player:sendCancelMessage('You are not participating in any city war.')
            end
 
            player:popupFYI(city:getRank())
        end
    end)
    window:setDefaultEnterButton('Ok')
    window:addButton('Cancel')
 
    if invite or rank then
        window:sendToPlayer(player)
    else
        player:sendCancelMessage('There is no action you can take right now.')
    end
 
    return true
end
 
@HeberPcL change the lane and now it says this error:
Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/modalwindowhelper.lua:eek:nModalWindow
data/lib/citywars.lua:542: attempt to call global 'getGuildBalance' (a nil value)
stack traceback:
[C]: in function 'getGuildBalance'
data/lib/citywars.lua:542: in function 'onInviteAccepted'
data/actions/scripts/Novos/citywar.lua:146: in function 'callback'
data/creaturescripts/scripts/modalwindowhelper.lua:26: in function <data/creaturescripts/scripts/modalwindowhelper.lua:1>
 
Creaturescripts ok thanks
Now Lib erro :S
Help fix?

Code:
Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/modalwindowhelper.lua:onModalWindow
data/lib/citywars.lua:553: attempt to call method 'getBankBalance' (a nil value)
stack traceback:
    [C]: in function 'getBankBalance'
    data/lib/citywars.lua:553: in function 'onInviteAccepted'
    data/actions/scripts/citywar.lua:146: in function 'callback'
    data/creaturescripts/scripts/modalwindowhelper.lua:26: in function <data/creaturescripts/scripts/modalwindowhelper.lua:1

Lib:
Code:
CITY_WAR_FIRST      = 0
CITY_WAR_EDRON     = 0
CITY_WAR_YALAHAR  = 1
CITY_WAR_DARASHIA      = 2
CITY_WAR_LIBERTYBAY  = 3
CITY_WAR_LAST       = 3
 
CW_RETURNVALUE_NOERROR = 0
CW_RETURNVALUE_LIVEINVITE = 1
CW_RETURNVALUE_INVITERINWAR = 2
CW_RETURNVALUE_INVITEDINWAR = 3
CW_RETURNVALUE_TOOFEWPLAYERS = 4
CW_RETURNVALUE_TOOFEWUNIQUEIPS = 5
 
local function capitalize(self)
    local tmp = self:lower()
    return tmp:sub(1, 1):upper() .. tmp:sub(2)
end
 
local function reduce(list, predicate)
    local ret = list[1]
    for i = 2, #list do
        ret = predicate(ret, list[i])
    end
    return ret
end
 
local function resumeThread(thread, info, ...)
    local suc, tmp = coroutine.resume(thread, ...)
    if not suc then
        error(tmp)
    end
 
    local wait = tonumber(tmp)
    if wait then
        info.id = addEvent(resumeThread, wait, thread, info)
    end
end
 
local function addThread(func, delay, ...)
    local thread = coroutine.create(func)
    local info = { }
    if delay == 0 then
        resumeThread(thread, info, ...)
    else
        info.id = addEvent(resumeThread, delay, thread, info, ...)
    end
    return info
end
 
if not CityWars then
    CityWars = {
        cityWarDuration = 2 * 60 * 60,
        cityWarStorage = 15600,
        rankingLimit = 1, -- How many players should appear in the ranking message
        minGuildSize = 1, -- How many guild members need to be online
        minDifferentIPs = 1, -- Minimum number of unique ips
        inviteItemId = 1949,
        buyInMultiplier = 50000,
        fragLimitMultiplier = 1,
        teamSizeMultiplier = 1,
 
        minGuildRank = 3, -- Minimum guild rank to start/accept/cancel a city war
        removeConditions = {CONDITION_POISON, CONDITION_FIRE, CONDITION_ENERGY, CONDITION_BLEEDING, CONDITION_PARALYZE, CONDITION_INFIGHT},
        -- [invitedName] = { {city = City, invitedPlayer = Player, invitedGuild = Guild, inviterPlayer = Player, inviterGuild = Guild, options = { }} }
        invites = {},
      
        [CITY_WAR_EDRON] = {
            spawns = {
                -- Team 1 position
                [1] = Position(518, 50, 7),
                -- Team 2 position
                [2] = Position(581, 118, 6),
            },
 
            name = 'edron',
 
            --  [playerId] = {player = player, name = name, team = 1/2, kills = 0, deaths = 0}
            players = { },
 
            -- [team] = {guild = guild, name = name, kills = 0, deaths = 0}
            teams = { }
        },
 
        [CITY_WAR_DARASHIA] = {
            spawns = {
                -- Team 1 position
                [1] = Position(31217, 32552, 7),
                -- Team 2 position
                [2] = Position(31295, 32639, 7),
            },
 
            name = 'darashia',
 
            --  [playerId] = {player = player, name = name, team = 1/2, kills = 0, deaths = 0}
            players = { },
 
            -- [team] = {guild = guild, name = name, kills = 0, deaths = 0}
            teams = { }
        },
 
        [CITY_WAR_LIBERTYBAY] = {
            spawns = {
                -- Team 1 position
                [1] = Position(30740, 32734, 7),
                -- Team 2 position
                [2] = Position(30767, 32567, 7),
            },
 
            name = 'liberty bay',
 
            --  [playerId] = {player = player, name = name, team = 1/2, kills = 0, deaths = 0}
            players = { },
 
            -- [team] = {guild = guild, name = name, kills = 0, deaths = 0}
            teams = { }
        },
 
        [CITY_WAR_YALAHAR] = {
            spawns = {
                -- Team 1 position
                [1] = Position(30925, 32825, 7),
                -- Team 2 position
                [2] = Position(30982, 32827, 7),
            },
 
 
            name = 'yalahar',
 
            --  [playerId] = {player = player, name = name, team = 1/2, kills = 0, deaths = 0}
            players = { },
 
            -- [team] = {guild = guild, name = name, kills = 0, deaths = 0}
            teams = { },
        },
    }
 
    local City = {}
    City.__index = City
 
    for i = CITY_WAR_FIRST, CITY_WAR_LAST do
        setmetatable(CityWars[i], City)
    end
 
    function City:onStart()
        if not self.endEvent then
            self.endEvent = addThread(
                function(city)
                    for i = 10, 1, -1 do
                        city:countdown(i)
                        coroutine.yield(60 * 1000)
                    end
 
                    local winner     
                    if self.teams[1].kills > self.teams[2].kills then
                        winner = 1
                    elseif self.teams[1].kills < self.teams[2].kills then
                        winner = 2
                    end
 
                    city:onEnd(winner)               
                end,
 
                (CityWars.cityWarDuration - 10 * 60) * 1000,
 
                self
            )
        end
    end
 
    function City:onEnd(winner)
        stopEvent(self.endEvent.id)
 
        for k, v in pairs(self.players) do
            if v.player and v.player:getStorageValue(CityWars.cityWarStorage) > 0 then
                v.player:teleportTo(v.player:getTown():getTemplePosition())
                v.player:addHealth(v.player:getMaxHealth())
                v.player:addMana(v.player:getMaxMana())
                v.player:setStorageValue(CityWars.cityWarStorage, -1)
                v.player:unregisterEvent('CityWarDeath')
                for _, cond in ipairs(CityWars.removeConditions) do
                    v.player:removeCondition(cond, CONDITIONID_DEFAULT)
                end
            end
        end   
 
        self:broadcastMessage(self:getRank())
 
        if not winner then
            self:broadcastMessage('The war has ended, it is a draw!')
 
            local guild1 = Guild(self.teams[1].id)
            local guild2 = Guild(self.teams[2].id)
            if guild1 then
                guild1:setBankBalance(guild1:getBankBalance() + self.options.buyIn)
            end
            if guild2 then
                guild2:setBankBalance(guild2:getBankBalance() + self.options.buyIn)
            end
        else
            self:broadcastMessage('The war has ended, "' .. self.teams[winner].name .. '" have won the war and taken home the prize of ' .. (2 * self.options.buyIn) .. ' gold coins.')
 
            local winnerGuild = Guild(self.teams[winner].id)
            if winnerGuild then
                winnerGuild:setBankBalance(winnerGuild:getBankBalance() + 2 * self.options.buyIn)
            end
        end   
 
        self.players = { }
        self.teams = { }
        self.options = { }
        self.endEvent = nil
    end
 
    function City:onCancel(player)
        if player:getGuildLevel() < CityWars.minGuildRank then
            player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Only leaders can cancel an ongoing city war.')
            return false
        end
 
        local registry = self.players[player:getGuid()]
        self:broadcastMessage(player:getName() .. ' has forfeited the war.')
 
        self:onEnd((registry.team == 1) and 2 or 1)
    end
 
    function City:onCastSpell(player, kind)
        if player:getStorageValue(CityWars.cityWarStorage) > 0 then
            if kind == 'ultimateExplosion' and not self.options.ultimateExplosion then
                return false
            elseif kind == 'areaSpell' and self.options.suddenDeathOnly then
                return false
            end
        end
        return true
    end
 
    function City:onScoreUpdated()
        local winner
        for i, team in ipairs(self.teams) do
            if team.kills >= self.options.fragLimit then
                winner = i
                break
            end   
        end
 
        self:broadcastScore()
        if winner then   
            self:onEnd(winner)
        end
    end
 
    function City:onJoin(player)
        local registry = self.players[player:getGuid()]
        local team = self.teams[registry.team]
        if team.players < self.options.teamSize then
            if player:getStorageValue(CityWars.cityWarStorage) < 0 then
                team.players = team.players + 1
 
                player:registerEvent('CityWarDeath')
                player:setStorageValue(CityWars.cityWarStorage, 1)
                player:teleportTo(self.spawns[registry.team])
            end
        else
            player:sendTextMessage('Your guild has reached the team limit! You may not join them right now.')
        end
    end
 
    function City:onDeath(player, registry, killer)
        if player:getStorageValue(CityWars.cityWarStorage) > 0 then       
            player:teleportTo(self.spawns[registry.team])
            player:addHealth(player:getMaxHealth())
            player:addMana(player:getMaxMana())
            for _, cond in ipairs(CityWars.removeConditions) do
                player:removeCondition(cond, CONDITIONID_DEFAULT)
            end
 
            registry.deaths = registry.deaths + 1
            local team = self.teams[registry.team]
            team.deaths = team.deaths + 1
 
            local killerRegistry
            if killer then
                if not killer:isPlayer() then
                    killer = killer:getMaster()
 
                    if not killer or not killer:isPlayer() then
                        killer = nil
                    end
                end
 
                if killer then
                    local _
                    _, killerRegistry = CityWars.getPlayerWar(killer)     
                end
            end
 
            if killerRegistry and killerRegistry.team ~= registry.team then
                killerRegistry.kills = killerRegistry.kills + 1
            end       
 
            local enemyTeam = self.teams[(registry.team == 1) and 2 or 1]
            enemyTeam.kills = enemyTeam.kills + 1
 
            self:onScoreUpdated()
            return true
        end
 
        return false
    end
 
    function City:onLeave(player)     
        if player:getStorageValue(CityWars.cityWarStorage) > 0 then       
            player:unregisterEvent('CityWarDeath')
            player:setStorageValue(CityWars.cityWarStorage, -1)
            player:teleportTo(player:getTown():getTemplePosition())
            for _, cond in ipairs(CityWars.removeConditions) do
                player:removeCondition(cond, CONDITIONID_DEFAULT)
            end
 
            local registry = self.players[player:getGuid()]
            registry.player = nil
            -- update team's player count
            local team = self.teams[registry.team]
            team.players = team.players - 1       
        end
    end
    City.onLogout = City.onLeave
 
    function City:getName()
        return capitalize(self.name)
    end
 
    function City:addPlayer(player, team)
        local current = self.players[player:getGuid()]
        if not current then
            current = {player = player, team = team, name = player:getName(), kills = 0, deaths = 0}
        else
            -- update player object
            current.player = player
        end
        self.players[player:getGuid()] = current
    end
 
    function City:countdown(minutesLeft)
        self:broadcastMessage('Countdown: ' .. minutesLeft .. ' minutes until the war ends.')
    end
 
    function City:broadcastMessage(msg)
        for k, v in pairs(self.players) do
            if v.player then
                v.player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, msg)
            end
        end
    end
 
    local broadcastFormat = 'Score: "%s" (%d) versus "%s" (%d)'
    function City:broadcastScore()
        self:broadcastMessage(broadcastFormat:format(self.teams[1].name, self.teams[1].kills, self.teams[2].name, self.teams[2].kills))
    end
 
    function City:getRank()
        local rank = {}
        for k, v in pairs(self.players) do
            table.insert(rank, {name = v.name, kills = v.kills, deaths = v.deaths, guildName = self.teams[v.team].name})
        end
        table.sort(rank,
            function(a, b)
                if a.kills ~= b.kills then
                    return a.kills > b.kills
                end
                return a.deaths < b.deaths
            end       
        )
        local msg = 'Ranking:'
        for i = 1, CityWars.rankingLimit do
            local player = rank[i]
            if player then           
                msg = msg .. '\n' .. i .. '. ' .. player.name .. ' - ' .. player.kills .. '/' .. player.deaths .. ' From: "' .. player.guildName .. '"'
            end
        end
        return msg
    end
 
    local winFormat = '"%s" has beaten "%s" by %d to %d kills.'
    local drawFormat = 'The city war between "%s" and "%s" resulted in a draw.'
    function City:broadcastResult()
        local msg
        if self.teams[1].kills > self.teams[2].kills then
            msg = winFormat:format(self.teams[1].name, self.teams[2].name, self.teams[1].kills, self.teams[2].kills)
        elseif self.teams[1].kills < self.teams[2].kills then
            msg = winFormat:format(self.teams[2].name, self.teams[1].name, self.teams[2].kills, self.teams[1].kills)
        else
            msg = drawFormat:format(self.teams[1].name, self.teams[2].name)
        end
 
        self:broadcastMessage(msg)
    end
 
    function City:isFree()
        return #self.teams == 0
    end
end
 
function CityWars.getCityByName(name)
    for i = CITY_WAR_FIRST, CITY_WAR_LAST do
        local city = CityWars[i]
        if city.name == name then
            return city
        end
    end
 
    return nil
end
 
function CityWars.getPlayerWar(player, registerPlayer)
    local playerGuild = player:getGuild()
    if not playerGuild then
        return nil
    end
    for i = CITY_WAR_FIRST, CITY_WAR_LAST do
        local city = CityWars[i]
        if not city:isFree() then
            for k, team in ipairs(city.teams) do
              
                if team.id == playerGuild:getId() then
                    local guid = player:getGuid()
                    local registry = city.players[guid]
                    if registerPlayer and (not registry or registry.team ~= k) then
                        registry = {player = player, name = player:getName(), team = k, kills = 0, deaths = 0}
                        city.players[guid] = registry
                    end
                    return city, registry
                end
            end
        end
    end
end
 
function CityWars.isValidGuild(guild)
    local onlineMembers = guild:getMembersOnline()
    if #onlineMembers < CityWars.minGuildSize then
        return CW_RETURNVALUE_TOOFEWPLAYERS
    end
 
    local uniqueIPs = 0
    local addressMap = {}
    for k, v in ipairs(onlineMembers) do
        local ip = v:getIp()
        if ip ~= 0 and not addressMap[ip] then
            addressMap[ip] = true
            uniqueIPs = uniqueIPs + 1
        end
    end
    if uniqueIPs < CityWars.minDifferentIPs then
        return CW_RETURNVALUE_TOOFEWUNIQUEIPS
    end
 
    return CW_RETURNVALUE_NOERROR
end
 
function CityWars.getGuildWar(guild)
    for i = CITY_WAR_FIRST, CITY_WAR_LAST do
        local city = CityWars[i]
        if not city:isFree() then
            for k, team in ipairs(city.teams) do
                if team.id == guild:getId() then
                    return city
                end
            end
        end
    end
end
 
function CityWars.getInvites(guildName)
    return CityWars.invites[guildName]
end
 
function CityWars.onInviteExpired(invite)
    for k, _invite in ipairs(invite.invites) do
        if _invite == invite then
            local player = Player(invite.inviterPlayerName)
            if player then
                local guild = Guild(invite.invitedGuildId)
                local guildName = guild and guild:getName() or 'deleted guild'
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Your city war invite for guild "' .. guildName .. '" has expired.')
            end
 
            if invite.invitedLeaders then
                local guild = Guild(invite.inviterGuildId)
                local guildName = guild and guild:getName() or 'deleted guild'
                for _, leaderName in ipairs(invite.invitedLeaders) do
                    local leader = Player(leaderName)
                    if leader then
                        leader:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'You failed to answer the city war invite from guild "' .. guildName .. '" and it is now expired.')
                    end
                end
            end
 
            table.remove(invite.invites, k)
            return
        end
    end
end
 
local optionsFormat = 'City: %s | Buy in: %d gold %s | Frag limit: %d | U.E: %s | S.D only: %s | Team size: %d'
function CityWars.getOptionsString(options)
    return optionsFormat:format(options.city:getName(), options.buyIn, (options.buyIn == 1) and 'coin' or 'coins', options.fragLimit, options.ultimateExplosion and 'enabled' or 'disabled', options.suddenDeathOnly and 'true' or 'false', options.teamSize)
end
 
function CityWars.onInviteAccepted(player, invite)
    for k, _invite in ipairs(invite.invites) do
        if _invite == invite then
            stopEvent(invite.expireEvent)
            table.remove(invite.invites, k)
 
            if not invite.city:isFree() then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, invite.city:getName() .. ' is not free anymore.')
                return false
            end       
 
            local inviterGuild = Guild(invite.inviterGuildId)
            if not inviterGuild then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'Inviter guild does not exist anymore.')             
                return false
            elseif CityWars.getGuildWar(inviterGuild) then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'The inviter guild is already in war.')
            end
 
            local invitedGuild = Guild(invite.invitedGuildId)
            if not invitedGuild then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'You do not belong to a guild.')             
                return false
            elseif CityWars.getGuildWar(invitedGuild) then
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, 'You can not accept a war invite while in another one.')
                return false
            end
 
            local msg
            local start = false
            if inviterGuild:getBankBalance() < invite.options.buyIn then
                msg = 'The guild "' .. inviterGuild:getName() .. '" can not participate in this war due to lack of funds in its guild bank.'
            elseif invitedGuild:getBankBalance() < invite.options.buyIn then
                msg = 'The guild "' .. invitedGuild:getName() .. '" can not participate in this war due to lack of funds in its guild bank.'
            else
                inviterGuild:setBankBalance(inviterGuild:getBankBalance() - invite.options.buyIn)
                invitedGuild:setBankBalance(invitedGuild:getBankBalance() - invite.options.buyIn)
                start = true
                msg = 'A city war between the guilds "' .. inviterGuild:getName() .. '" and "' .. invitedGuild:getName() .. '" has begun!\n' ..
                    CityWars.getOptionsString(invite.options) .. '\n' ..
                    'If you wish to join, head to a temple and read the guild book.'
            end
 
            for _, player in ipairs(inviterGuild:getMembersOnline()) do
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, msg)
                if start then
                    invite.city:addPlayer(player, 1)
                end
            end
 
            for _, player in ipairs(invitedGuild:getMembersOnline()) do
                player:sendTextMessage(MESSAGE_STATUS_CONSOLE_BLUE, msg)
                if start then
                    invite.city:addPlayer(player, 2)
                end
            end
 
            if start then
                invite.city.teams = {
                    {id = invite.inviterGuildId, name = inviterGuild:getName(), kills = 0, deaths = 0, players = 0},
                    {id = invite.invitedGuildId, name = invitedGuild:getName(), kills = 0, deaths = 0, players = 0}
                }
                invite.city.options = invite.options
                invite.city:onStart()
            end
 
            return true
        end
    end
    return false
end
 
function CityWars.onInvite(city, inviter, invitedGuild, invitedLeaders, options)
    if CityWars.getGuildWar(inviter:getGuild()) then
        return CW_RETURNVALUE_INVITERINWAR
    end
 
    if CityWars.getGuildWar(invitedGuild) then
        return CW_RETURNVALUE_INVITEDINWAR
    end
 
    local invites = CityWars.invites[invitedGuild:getName()]
    if invites and #invites ~= 0 then
        for _, invite in ipairs(invites) do
            local guild = Guild(invite.inviterGuildId)
            if guild and guild:getId() == inviter:getGuild():getId() then
                return CW_RETURNVALUE_LIVEINVITE
            end
        end
    elseif not invites then
        invites = { }
        CityWars.invites[invitedGuild:getName()] = invites
    end
 
    local invitedLeadersNames = {}
    for k, v in ipairs(invitedLeaders) do
        table.insert(invitedLeadersNames, v:getName())
    end
 
    local invite = {
        city = city,
        invites = invites,
        inviterPlayerName = inviter:getName(),
        inviterGuildId = inviter:getGuild():getId(),
        invitedGuildId = invitedGuild:getId(),
        invitedLeaders = invitedLeadersNames,
        options = options
    }
    invite.expireEvent = addEvent(CityWars.onInviteExpired, 15 * 1000, invite)
    table.insert(invites, invite)
 
    return CW_RETURNVALUE_NOERROR
end
 
all your problems are related to the same shit, you may take a minute, make a coffe and read the fucking log
"attempt to call method 'getBankBalance' (a nil value)"
no function so nil, you guys dont even try to learn, you stole information, you dont know how to use it and you dont learn...
 
This system can not be used as war private.
It has its own frags counter that does not count the frags if the guild is in war.
If the player dies inside the citywar he is teleported to starting position.
Citwar has no time, the system is counted by the system of frags itself that it has.
 
all your problems are related to the same shit, you may take a minute, make a coffe and read the fucking log
"attempt to call method 'getBankBalance' (a nil value)"
no function so nil, you guys dont even try to learn, you stole information, you dont know how to use it and you dont learn...
my friend i am new okay i dont know nothing about scripts so for something i ask for help if i know how to fix it i dont was lossing my time asking for help..
 
This system can not be used as war private.
It has its own frags counter that does not count the frags if the guild is in war.
If the player dies inside the citywar he is teleported to starting position.
Citwar has no time, the system is counted by the system of frags itself that it has.
Do you fixed it bro? i can invite but i can't accept the invites xd
 
@HeberPcL checked the functions streamside gived but idk how to use it T_T i hope you can help us when changed the lane 542, now it says this error:
Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/modalwindowhelper.lua:eek:nModalWindow
data/lib/citywars.lua:542: attempt to call global 'getGuildBalance' (a nil value)
stack traceback:
[C]: in function 'getGuildBalance'
data/lib/citywars.lua:542: in function 'onInviteAccepted'
data/actions/scripts/Novos/citywar.lua:146: in function 'callback'
data/creaturescripts/scripts/modalwindowhelper.lua:26: in function <data/creaturescripts/scripts/modalwindowhelper.lua:1>
 
Back
Top