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

Lua Auto Raids on [TFS 1.4.2] - Nekiro system.

OTcreator

Active Member
Joined
Feb 14, 2022
Messages
425
Solutions
1
Reaction score
44
Hi,
I use this script in TFS 1.4.2 buy monsters are duplicated.
No errors in consola.
What to change to make it check properly if the boss has already been respawned and to not respawn duplicates.

Lua:
local raids = {
    -- Bosses
    [1]  = {type = 'BOSS', position = Position(32960, 32075, 6), monster = 'demodras', message = 'Demodras has spawned', chance = 30},
    [2]  = {type = 'BOSS', position = Position(998, 1006, 7), monster = 'orshabaal', chance = 40},
    [3]  = {type = 'BOSS', position = Position(998, 1006, 7), monster = 'ferumbras', chance = 30},
 
    -- Raids fromPos, toPos
    [4] = {type = 'NORMAL', fromPos = Position(997, 1005, 7), toPos = Position(1009, 1014, 7), monsters = {'orc', 'orc Spearman', 'orc warrior'}, count = 10, message = 'orcs raid', chance = 20},
    [5] = {type = 'NORMAL', fromPos = Position(997, 1005, 7), toPos = Position(1009, 1014, 7), monsters = 'demon', count = 10, message = 'demons raid', chance = 50},
}

local spawnedBosses = {}

local function isSpawned(name)
    for i = 1, #spawnedBosses do
        local monster = Monster(spawnedBosses[i])
        if monster and monster:getName():lower() == name then
            return true
        else
            spawnedBosses[i] = nil
        end
    end
    return false
end

function onThink(interval, lastExecution, thinkInterval)
    local table = raids[math.random(#raids)]
 
    if math.random(100) > table.chance then
        return true
    end
 
    if table.type == 'BOSS' then
        if not isSpawned(table.monster:lower()) then
            local boss = Game.createMonster(table.monster, table.position, true, false)
            if boss then
                spawnedBosses[#spawnedBosses + 1] = boss:getId()
            end
            if table.message ~= nil then
                broadcastMessage(table.message, MESSAGE_EVENT_ADVANCE)
            end
        end
    elseif table.type == 'NORMAL' then
        for i = 1, table.count do
            local randomPosition = Position(math.random(table.fromPos.x, table.toPos.x), math.random(table.fromPos.y, table.toPos.y), table.fromPos.z)
            if type(table.monsters) == 'string' then
                Game.createMonster(table.monsters, randomPosition, true, false)
            else
                Game.createMonster(table.monsters[math.random(#table.monsters)], randomPosition, true, false)
            end
        end
        if table.message ~= nil then
            broadcastMessage(table.message, MESSAGE_EVENT_ADVANCE)
        end
    end
    return true
end
 
try, however this approach will limit boss to spawn 1 time per restart

Lua:
local raids = {
    -- Bosses
    [1]  = {type = 'BOSS', position = Position(32960, 32075, 6), monster = 'demodras', message = 'Demodras has spawned', chance = 30, storage = 10000},
    [2]  = {type = 'BOSS', position = Position(998, 1006, 7), monster = 'orshabaal', chance = 40, storage = 10001},
    [3]  = {type = 'BOSS', position = Position(998, 1006, 7), monster = 'ferumbras', chance = 30, storage = 10002},
 
    -- Raids fromPos, toPos
    [4] = {type = 'NORMAL', fromPos = Position(997, 1005, 7), toPos = Position(1009, 1014, 7), monsters = {'orc', 'orc Spearman', 'orc warrior'}, count = 10, message = 'orcs raid', chance = 20},
    [5] = {type = 'NORMAL', fromPos = Position(997, 1005, 7), toPos = Position(1009, 1014, 7), monsters = 'demon', count = 10, message = 'demons raid', chance = 50},
}

local spawnedBosses = {}

local function isSpawned(name)
    for i = 1, #spawnedBosses do
        local monster = Monster(spawnedBosses[i])
        if monster and monster:getName():lower() == name then
            return true
        else
            spawnedBosses[i] = nil
        end
    end
    return false
end

function onThink(interval, lastExecution, thinkInterval)
    local table = raids[math.random(#raids)]

    if table.storage ~= nil then
      if getGlobalStorageValue(table.storage) == 1 then
        return true
      end
    end
 
    if math.random(100) > table.chance then
        return true
    end
 
    if table.type == 'BOSS' then
        if not isSpawned(table.monster:lower()) then
            local boss = Game.createMonster(table.monster, table.position, true, false)
            if boss then
                spawnedBosses[#spawnedBosses + 1] = boss:getId()
            end
            if table.message ~= nil then
                broadcastMessage(table.message, MESSAGE_EVENT_ADVANCE)
            end
          
            if table.storage ~= nil then
              setGlobalStorageValue(table.storage, 1)
            end
        end
    elseif table.type == 'NORMAL' then
        for i = 1, table.count do
            local randomPosition = Position(math.random(table.fromPos.x, table.toPos.x), math.random(table.fromPos.y, table.toPos.y), table.fromPos.z)
            if type(table.monsters) == 'string' then
                Game.createMonster(table.monsters, randomPosition, true, false)
            else
                Game.createMonster(table.monsters[math.random(#table.monsters)], randomPosition, true, false)
            end
        end
        if table.message ~= nil then
            broadcastMessage(table.message, MESSAGE_EVENT_ADVANCE)
        end
    end
    return true
end
 
No such script is needed.
I think that if it worked well in version 1.2 , then in version 1.4.2 there must have been some changes that changed the monster name checking.
 
No such script is needed.
I think that if it worked well in version 1.2 , then in version 1.4.2 there must have been some changes that changed the monster name checking.
Your old script only checked if a boss is alive, it doesn't check if it has already been spawned or not...

I just refactored your script a little (untested):
Lua:
local raids = {
    -- Bosses
    [1]  = {type = 'boss', position = Position(32960, 32075, 6), monster = 'demodras', message = 'Demodras has spawned', chance = 30},
    [2]  = {type = 'boss', position = Position(998, 1006, 7), monster = 'orshabaal', chance = 40},
    [3]  = {type = 'boss', position = Position(998, 1006, 7), monster = 'ferumbras', chance = 30},
 
    -- Raids fromPos, toPos
    [4] = {type = 'raid', fromPos = Position(997, 1005, 7), toPos = Position(1009, 1014, 7), monsters = {'orc', 'orc Spearman', 'orc warrior'}, count = 10, message = 'orcs raid', chance = 20},
    [5] = {type = 'raid', fromPos = Position(997, 1005, 7), toPos = Position(1009, 1014, 7), monsters = 'demon', count = 10, message = 'demons raid', chance = 50},
}

function onThink(interval, lastExecution, thinkInterval)

    local raidIndex = math.random(#raids)
    local raid = raids[raidIndex]
    if math.random(100) > raid.chance then
        return true
    end
 
    if raid.type == 'boss' then
        local boss = Game.createMonster(raid.monster, raid.position, true, false)
        if boss then
            if raid.message ~= nil then
                broadcastMessage(raid.message, MESSAGE_EVENT_ADVANCE)
            end   
        end   
        table.remove(raids, raidIndex)
    elseif raid.type == 'raid' then
        for i = 1, raid.count do
            local randomPosition = Position(math.random(raid.fromPos.x, raid.toPos.x), math.random(raid.fromPos.y, raid.toPos.y), raid.fromPos.z)
            if type(raid.monsters) == 'table' then
                Game.createMonster(raid.monsters[math.random(#raid.monsters)], randomPosition, true, false)
            else
                Game.createMonster(raid.monsters, randomPosition, true, false)
            end
        end
        if raid.message ~= nil then
            broadcastMessage(raid.message, MESSAGE_EVENT_ADVANCE)
        end
    end
    
    return true
end
 
Your old script only checked if a boss is alive, it doesn't check if it has already been spawned or not...

I just refactored your script a little (untested):
Lua:
local raids = {
    -- Bosses
    [1]  = {type = 'boss', position = Position(32960, 32075, 6), monster = 'demodras', message = 'Demodras has spawned', chance = 30},
    [2]  = {type = 'boss', position = Position(998, 1006, 7), monster = 'orshabaal', chance = 40},
    [3]  = {type = 'boss', position = Position(998, 1006, 7), monster = 'ferumbras', chance = 30},
 
    -- Raids fromPos, toPos
    [4] = {type = 'raid', fromPos = Position(997, 1005, 7), toPos = Position(1009, 1014, 7), monsters = {'orc', 'orc Spearman', 'orc warrior'}, count = 10, message = 'orcs raid', chance = 20},
    [5] = {type = 'raid', fromPos = Position(997, 1005, 7), toPos = Position(1009, 1014, 7), monsters = 'demon', count = 10, message = 'demons raid', chance = 50},
}

function onThink(interval, lastExecution, thinkInterval)

    local raidIndex = math.random(#raids)
    local raid = raids[raidIndex]
    if math.random(100) > raid.chance then
        return true
    end
 
    if raid.type == 'boss' then
        local boss = Game.createMonster(raid.monster, raid.position, true, false)
        if boss then
            if raid.message ~= nil then
                broadcastMessage(raid.message, MESSAGE_EVENT_ADVANCE)
            end  
        end  
        table.remove(raids, raidIndex)
    elseif raid.type == 'raid' then
        for i = 1, raid.count do
            local randomPosition = Position(math.random(raid.fromPos.x, raid.toPos.x), math.random(raid.fromPos.y, raid.toPos.y), raid.fromPos.z)
            if type(raid.monsters) == 'table' then
                Game.createMonster(raid.monsters[math.random(#raid.monsters)], randomPosition, true, false)
            else
                Game.createMonster(raid.monsters, randomPosition, true, false)
            end
        end
        if raid.message ~= nil then
            broadcastMessage(raid.message, MESSAGE_EVENT_ADVANCE)
        end
    end
   
    return true
end

Well that's right, if someone would kill him it's not a problem, let him respawn a second time it was OK, only that he whether he lived or died was respawned again anyway.
 
ok im confused.
So you dont mind if multiple are spawned during the day, as long as there are not more than 1 at any time, correct?
 
ok im confused.
So you dont mind if multiple are spawned during the day, as long as there are not more than 1 at any time, correct?
Yes, it doesn't matter to me.
The main thing is that only one should be able to resupply in a given place.

Earlier, someone entered and there were 5 of the same boos and instantly dead.
 
Yes, it doesn't matter to me.
The main thing is that only one should be able to resupply in a given place.

Earlier, someone entered and there were 5 of the same boos and instantly dead.
Converted it to revscript. I've made several edits to the script below since I first posted it.

Make sure this goes in data/scripts/globalevents/. You can give the file any name you like, and it self registers so there is no need to add anything to any XML. Also make sure you detach your old script from globalevents.xml

Lua:
local raids = {
    -- Bosses
    {type = 'boss', position = Position(32960, 32075, 6), monster = 'demodras', message = 'Demodras has spawned', chance = 30},
    {type = 'boss', position = Position(998, 1006, 7), monster = 'orshabaal', chance = 40},
    {type = 'boss', position = Position(998, 1006, 7), monster = 'ferumbras', chance = 30},
 
    -- Raids fromPos, toPos
    {type = 'raid', fromPos = Position(997, 1005, 7), toPos = Position(1009, 1014, 7), monsters = {'orc', 'orc Spearman', 'orc warrior'}, count = 10, message = 'orcs raid', chance = 20},
    {type = 'raid', fromPos = Position(997, 1005, 7), toPos = Position(1009, 1014, 7), monsters = 'demon', count = 10, message = 'demons raid', chance = 50},
}

local raidBossDeath = CreatureEvent("raidBossDeath")
function raidBossDeath.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
 
    local bossId = creature:getId()
    for _, raid in ipairs(raids) do
        if raid.type == 'boss' and raid.bossId and raid.bossId == bossId then
            raid.alive = nil
            raid.bossId = nil
            break
        end
    end
 
    return true
end
raidBossDeath:register()

local raidThink = GlobalEvent("raidThink")
function raidThink.onThink(interval)

    local raid = raids[math.random(#raids)]
    if math.random(100) > raid.chance then
        return true
    end
 
    if raid.type == 'boss' and not raid.alive then
        local boss = Game.createMonster(raid.monster, raid.position, true, false)
        if boss then
            raid.alive = true
            raid.bossId = boss:getId()
            boss:registerEvent("raidBossDeath")
        end
        table.remove(raids, raidIndex)
    elseif raid.type == 'raid' then
        for i = 1, raid.count do
            local randomPosition = Position(math.random(raid.fromPos.x, raid.toPos.x), math.random(raid.fromPos.y, raid.toPos.y), raid.fromPos.z)
            if type(raid.monsters) == 'table' then
                Game.createMonster(raid.monsters[math.random(#raid.monsters)], randomPosition, true, false)
            else
                Game.createMonster(raid.monsters, randomPosition, true, false)
            end
        end
    end
 
    if raid.message ~= nil then
        broadcastMessage(raid.message, MESSAGE_EVENT_ADVANCE)
    end
 
    return true
end
raidThink:interval(60 * 60 * 1000) --every hour
raidThink:register()
 
Last edited:
Converted it to revscript. I've made several edits to the script below since I first posted it.

Make sure this goes in data/scripts/globalevents/. You can give the file any name you like, and it self registers so there is no need to add anything to any XML. Also make sure you detach your old script from globalevents.xml

Lua:
local raids = {
    -- Bosses
    {type = 'boss', position = Position(32960, 32075, 6), monster = 'demodras', message = 'Demodras has spawned', chance = 30},
    {type = 'boss', position = Position(998, 1006, 7), monster = 'orshabaal', chance = 40},
    {type = 'boss', position = Position(998, 1006, 7), monster = 'ferumbras', chance = 30},
 
    -- Raids fromPos, toPos
    {type = 'raid', fromPos = Position(997, 1005, 7), toPos = Position(1009, 1014, 7), monsters = {'orc', 'orc Spearman', 'orc warrior'}, count = 10, message = 'orcs raid', chance = 20},
    {type = 'raid', fromPos = Position(997, 1005, 7), toPos = Position(1009, 1014, 7), monsters = 'demon', count = 10, message = 'demons raid', chance = 50},
}

local raidBossDeath = CreatureEvent("raidBossDeath")
function raidBossDeath.onDeath(creature, corpse, killer, mostDamageKiller, lastHitUnjustified, mostDamageUnjustified)
 
    local bossId = creature:getId()
    for _, raid in ipairs(raids) do
        if raid.type == 'boss' and raid.bossId and raid.bossId == bossId then
            raid.alive = nil
            raid.bossId = nil
            break
        end
    end
 
    return true
end
raidBossDeath:register()

local raidThink = GlobalEvent("raidThink")
function raidThink.onThink(interval)

    local raid = raids[math.random(#raids)]
    if math.random(100) > raid.chance then
        return true
    end
 
    if raid.type == 'boss' and not raid.alive then
        local boss = Game.createMonster(raid.monster, raid.position, true, false)
        if boss then
            raid.alive = true
            raid.bossId = boss:getId()
            boss:registerEvent("raidBossDeath")
        end
        table.remove(raids, raidIndex)
    elseif raid.type == 'raid' then
        for i = 1, raid.count do
            local randomPosition = Position(math.random(raid.fromPos.x, raid.toPos.x), math.random(raid.fromPos.y, raid.toPos.y), raid.fromPos.z)
            if type(raid.monsters) == 'table' then
                Game.createMonster(raid.monsters[math.random(#raid.monsters)], randomPosition, true, false)
            else
                Game.createMonster(raid.monsters, randomPosition, true, false)
            end
        end
    end
 
    if raid.message ~= nil then
        broadcastMessage(raid.message, MESSAGE_EVENT_ADVANCE)
    end
 
    return true
end
raidThink:interval(60 * 60 * 1000) --every hour
raidThink:register()
I try this.
 
Back
Top