• 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!
  • If you're using Gesior 2012 or MyAAC, please review this thread for information about a serious security vulnerability and a fix.

[tfs 1.3] castle war / war of emperium

Sun

Knowledge is power - France is bacon
Joined
Jan 26, 2015
Messages
333
Solutions
21
Reaction score
242
Made this on request of a client that turned out to be a scammer, so I've decided to release it to the public.

WOE (war of emperium) or castle war are rather famous guild war events.

How it works:
It creates gates & a crystal (monsters) at predefined locations
Guilds have to make it past the gates & to the crystal.
The crystal stores how much damage each guild has done (only players in a guild can deal damage to the crystal)
The guild that deals the most damage gains ownership of a castle (a house, the guild head becomes the owner & can decide who to invite).

Creaturescripts
creaturescripts/creaturescripts.xml
XML:
<event type="healthchange" name="hpChange" script="woe.lua"/>
creaturescripts/scripts/woe.lua
Lua:
local guilds = {}

function onHealthChange(creature, attacker, primaryDamage, primaryType, secondaryDamage, secondaryType, origin)
    local isGuild = false
    local damage = primaryDamage + secondaryDamage

    if attacker:isPlayer() == false then
        if attacker:getMaster() == false then
            return
        end
        attacker = attacker:getMaster()
    end

    if attacker:getGuild() == nil then
        return
    end

    for k,v in pairs(guilds) do
        if v[1] == attacker:getGuild():getId() then
            v = {v[1], v[2] + damage}
            isGuild = true
            break
        end
    end


    if not isGuild then
        guilds[#guilds+1] = {attacker:getGuild():getId(), damage}
    end

    if creature:getHealth() - damage <= 0 then
        table.sort(guilds, function(a,b) return a[2] > b[2] end)
        db.query("CREATE TABLE IF NOT EXISTS `castle` (`guild_id` int(11) NOT NULL, guild_name varchar(255) NOT NULL) ENGINE=InnoDB DEFAULT CHARACTER SET=utf8;")
        db.query("DELETE FROM `castle`")
        if guilds[1][1] ~= nil then
            local info = db.storeQuery("SELECT `name`, `ownerid` FROM `guilds` WHERE `id` = " .. guilds[1][1] .. " LIMIT 1")
            local name = result.getString(info, "name")
            local owner = result.getString(info, "ownerid")
            db.query("INSERT INTO `castle` VALUES (".. guilds[1][1] ..", '".. name .."')")
            broadcastMessage(woe.eventName.." has ended. Congratulations to ".. name .." for claiming ownership of the castle!", MESSAGE_EVENT_ADVANCE)
            Tile(woe.castle):getHouse():setOwnerGuid(owner)
        end
        guilds = {}

        for k,v in pairs(woe.doors) do

            if Creature(v.name) ~= nil then
                Creature(v.name):remove()
            end
        
            local door = Game.createItem(v.id, 1, v.pos)
            door:setActionId(woe.actionid)
        end

    end

    return primaryDamage, primaryType, -secondaryDamage, secondaryType
end

Globalevents
globalevents/globalevents.xml
XML:
<globalevent name="War of Emperium" time="18:00" script="woe.lua"/>
globalevents/scripts/woe.lua

Lua:
function onTime(interval)
    if os.date("%H:%M") == woe.days[os.date("%A")] then
        woe.queueEvent(woe.timeDelay+1)
    end
end
Lib
lib/lib.lua
add
Lua:
-- Custom functions
dofile('data/lib/custom/custom.lua')
lib/custom/custom.lua
Lua:
dofile('data/lib/custom/woe.lua')
lib/custom/woe.lua

Lua:
woe = {
    eventName = "[WOE]",
    timeDelay = 1, -- minutes before event starts
    bcMsg = " is starting in ",
    doors = {
        {name = "Castle Gate", id = 6257, pos = {x = 1021, y = 1028, z = 7} },
        {name = "Castle Gate", id = 6257, pos = {x = 1022, y = 1028, z = 7} }
    },
    actionid = 33542, -- for the doors
    crystal = {id = 9784, name="Emperium", pos = {x = 1022, y = 1020, z = 7} },
    castle = {x = 1012, y = 1027, z = 7}, -- just has to be one of the housetiles of the castle
    days = {
        -- to enable a day for the globalevent do ["Weekday"] = time
        -- for example: ["Monday"] = 18:00,
    },

    queueEvent = function(x)
        x = x - 1
        if x > 0 then
            broadcastMessage(woe.eventName..woe.bcMsg..x..(x > 1 and "minutes!" or "minute!"), MESSAGE_EVENT_ADVANCE)
            addEvent(woe.queueEvent, x * 60 * 1000, x)
        else
            woe.startEvent()
        end
    end,

    startEvent = function()
        for k,v in pairs(woe.doors) do
            local item = Tile(v.pos):getItemById(v.id)
            if item ~= nil then
                item:remove()
                Game.createMonster(v.name, v.pos, false, true)
            else
                print("WOE GATE POSITION INVALID OR MISSING [x:"..v.pos.x.." | y:"..v.pos.y.." | z:"..v.pos.z.."]")
            end
        end
        local c = woe.crystal
        local item = Tile(c.pos):getItemById(c.id)
        if item ~= nil then
            item:remove()
            Game.createMonster(c.name, c.pos, false, true)
        else
            print("WOE CRYSTAL POSITION INVALID OR MISSING [x:"..c.pos.x.." | y:"..c.pos.y.." | z:"..c.pos.z.."]")
        end
    end,

}

Talkactions
talkactions/talkactions.xml
XML:
<talkaction words="!woe" separator=" " script="woe.lua" />
talkactions/scripts/woe.lua
Lua:
function onSay(player, words, param)
    if not player:getGroup():getAccess() then
        return true
    end

    if player:getAccountType() < ACCOUNT_TYPE_GOD then
        return false
    end

    woe.queueEvent(woe.timeDelay+1)

    return false
end



Included a test map & monster files
 

Attachments

janes123

New Member
Joined
Jun 21, 2012
Messages
100
Reaction score
4
Code:
Lua Script Error: [TalkAction Interface]
data/talkactions/scripts/woe.lua:onSay
data/lib/custom/woe.lua:20: attempt to call global 'broadcastMessage' (a nil value)
stack traceback:
        [C]: in function 'broadcastMessage'
        data/lib/custom/woe.lua:20: in function 'queueEvent'
        data/talkactions/scripts/woe.lua:10: in function <data/talkactions/scripts/woe.lua:1>
 
OP
OP
Sun

Sun

Knowledge is power - France is bacon
Joined
Jan 26, 2015
Messages
333
Solutions
21
Reaction score
242
Code:
Lua Script Error: [TalkAction Interface]
data/talkactions/scripts/woe.lua:onSay
data/lib/custom/woe.lua:20: attempt to call global 'broadcastMessage' (a nil value)
stack traceback:
        [C]: in function 'broadcastMessage'
        data/lib/custom/woe.lua:20: in function 'queueEvent'
        data/talkactions/scripts/woe.lua:10: in function <data/talkactions/scripts/woe.lua:1>
otland/forgottenserver
 

janes123

New Member
Joined
Jun 21, 2012
Messages
100
Reaction score
4
Now ;p
Lua:
> Broadcasted message: "[WOE] is starting in 1minute!".
> Broadcasted message: "[WOE] has ended. Congratulations to ADMIN for claiming ownership of the castle!".

Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/woe.lua:onHealthChange
data/creaturescripts/scripts/woe.lua:41: attempt to index a nil value
stack traceback:
        [C]: in function '__index'
        data/creaturescripts/scripts/woe.lua:41: in function <data/creaturescripts/scripts/woe.lua:3>
        [C]: at 0x7ff62e6ae930
 
OP
OP
Sun

Sun

Knowledge is power - France is bacon
Joined
Jan 26, 2015
Messages
333
Solutions
21
Reaction score
242
I don't think you're using tfs 1.3
 
OP
OP
Sun

Sun

Knowledge is power - France is bacon
Joined
Jan 26, 2015
Messages
333
Solutions
21
Reaction score
242
strange that you didn't have a default function then.
Anyways, did you set woe.castle to the position of a valid house tile?
 

djblah

Active Member
Joined
Oct 15, 2010
Messages
101
Solutions
2
Reaction score
25
I was testing the system and from what I noticed and between several tests, this system does not do a cumulative damage if not. takes the best damage of the guild, any member that hits as high as possible, and from what I see is not convenient around here, the knights do not participate, but the magicians who will hit twice as much as a knight
 
Top