• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

TFS 1.2 How can i edit this code so it would spawn only one Boss

henkas

Well-Known Member
Joined
Jul 8, 2015
Messages
993
Solutions
5
Reaction score
55
Hello im using script that spawns boss every hour and it has 10% chance to be spawned every one hour but i want it to edit because it has one issue, how can i stop it from spawning that same boss if it was already spawned?

Lua:
local timeToRemove = 3600 * 1000 -- 1 hour 

local function removeBoss(uid)
    local monster = Monster(uid)
    if not monster then
        return
    end

    monster:remove()
    broadcastMessage("1 Hour has passed, and no one defeated the Daily Boss!", MESSAGE_EVENT_ADVANCE)
end

function onThink(interval)
    local state = Game.getGameState()
    if state == GAME_STATE_CLOSED or state == GAME_STATE_CLOSING then
        return true
    end

    local rand = math.random(1, 100)
    if rand <= 10 then
        local creature = monsterSystem[math.random(#monsterSystem)]
        local monster = Game.createMonster(creature.name, creature.pos)
        if monster then
            broadcastMessage(creature.msg, MESSAGE_EVENT_ADVANCE)

            Creature(monster):registerEvent("AutoEvent")
            addEvent(removeBoss, timeToRemove, monster:getId())
        end
        return true
    end
    return true
end
 
Solution
Alright, this should do what you want. The only problem with it is: if all bosses are spawned it will do an infinite loop (I stopped by by only allowing the loop to go through (boss amount * 2 times.) which is a bad work around in my opinion. If you can think of a better way go for it.

Lua:
local areas = {
    [1] = {chanceSpawn = 35,
        bosses = {
            {"Prisoner 1", Position(1654, 106, 7)},
            {"Prisoner 2", Position(1661, 106, 7)},
            {"Prisoner 3", Position(1661, 118, 7)},
            {"Prisoner 4", Position(1654, 118, 7)}
        }
    }
   
}

local BOSSES_SPAWNED = {}

for i = 1, #areas do
    BOSSES_SPAWNED[i] = {}
end

function onThink(interval)
    for i = 1, #areas do
        if math.random(100)...
use a global storage.

When summoned through this script, set global storage to 1
When server starts up, set storage to 0
 
use a global storage.

When summoned through this script, set global storage to 1
When server starts up, set storage to 0
Isnt there a better way to do it? Dont really want to mess it up with storages and doesnt sound like a perfect solution. And this way it wont spawn different bosses with different name
 
Isnt there a better way to do it? Dont really want to mess it up with storages and doesnt sound like a perfect solution. And this way it wont spawn different bosses with different name
What isn't perfect about my solution?

Storage resets every time the server starts up.

When Boss is summoned, storage prevents a 2nd boss from being summoned until the server restarts again.
 
What isn't perfect about my solution?

Storage resets every time the server starts up.

When Boss is summoned, storage prevents a 2nd boss from being summoned until the server restarts again.
But like i said what if i have "Boss Name 1" and "Boss Name 2", "Boss Name 3" if one of them will be spawned, it wont spawn the rest of them.
 
But like i said what if i have "Boss Name 1" and "Boss Name 2", "Boss Name 3" if one of them will be spawned, it wont spawn the rest of them.
Don't see how that would be a problem, but w/e.

Game.getSpectators get's all creatures in radius.
You can loop through them to check if a boss is spawned, but if the boss is not in the area you're checking, or the boss has been killed, another boss can spawn again.
 
Don't see how that would be a problem, but w/e.

Game.getSpectators get's all creatures in radius.
You can loop through them to check if a boss is spawned, but if the boss is not in the area you're checking, or the boss has been killed, another boss can spawn again.
Should be like this?
Lua:
local radiusX = 3
local radiusY = 3
local areapos = getCreaturePosition(cid)
local timeToRemove = 3600 * 1000 -- 1 hour 

local function removeBoss(uid)
    local monster = Monster(uid)
    if not monster then
        return
    end

    monster:remove()
    broadcastMessage("1 Hour has passed, and no one defeated the Daily Boss!", MESSAGE_EVENT_ADVANCE)
end

function onThink(interval)
    local state = Game.getGameState()
    if state == GAME_STATE_CLOSED or state == GAME_STATE_CLOSING then
        return true
    end

    local rand = math.random(1, 100)
    if rand <= 10 then
        local creature = monsterSystem[math.random(#monsterSystem)]
        local monster = Game.createMonster(creature.name, creature.pos)
        if monster then 
            if #getSpectators(areapos, false, true, 0, radiusX, 0, radiusY) >= 1 then
            broadcastMessage(creature.msg, MESSAGE_EVENT_ADVANCE)

            Creature(monster):registerEvent("AutoEvent")
            addEvent(removeBoss, timeToRemove, monster:getId())
        end
    end
        return true
    end
    return true
end
 
Should be like this?
Lua:
local radiusX = 3
local radiusY = 3
local areapos = getCreaturePosition(cid)
local timeToRemove = 3600 * 1000 -- 1 hour

local function removeBoss(uid)
    local monster = Monster(uid)
    if not monster then
        return
    end

    monster:remove()
    broadcastMessage("1 Hour has passed, and no one defeated the Daily Boss!", MESSAGE_EVENT_ADVANCE)
end

function onThink(interval)
    local state = Game.getGameState()
    if state == GAME_STATE_CLOSED or state == GAME_STATE_CLOSING then
        return true
    end

    local rand = math.random(1, 100)
    if rand <= 10 then
        local creature = monsterSystem[math.random(#monsterSystem)]
        local monster = Game.createMonster(creature.name, creature.pos)
        if monster then
            if #getSpectators(areapos, false, true, 0, radiusX, 0, radiusY) >= 1 then
            broadcastMessage(creature.msg, MESSAGE_EVENT_ADVANCE)

            Creature(monster):registerEvent("AutoEvent")
            addEvent(removeBoss, timeToRemove, monster:getId())
        end
    end
        return true
    end
    return true
end
Turn the chance into 100%, lower the interval, and test.

Find out if it works as you intended it too.
 
Try:
Set a globalStorageValue(number,1) when boss is spawned
Set a globalStorageValue(number,0) when the boss is killed with a function onKill/onDeath

If globalStorageValue(number) == 1 , then not spaw another boss, else, spawn and set to 1.

BTW: like Xikini said this functions get all monsters in radio and if u will check this with a globalEvent and the area is big maybe u will loss some computer process.
 
Try:
Set a globalStorageValue(number,1) when boss is spawned
Set a globalStorageValue(number,0) when the boss is killed with a function onKill/onDeath

If globalStorageValue(number) == 1 , then not spaw another boss, else, spawn and set to 1.

BTW: like Xikini said this functions get all monsters in radio and if u will check this with a globalEvent and the area is big maybe u will loss some computer process.
Like i said this way it wont spawn different name bosses which is terrible it ruins the whole point what im trying to achieve.
 
Just put 1 storage for each boss like the bosses in Thais temple has.
How?
Lua:
monsterSystem = {
    [1] = {name = "Boss 1", pos = Position(228, 1043, 7), chance = 5, expReward = 1500, pointsReward = 10, goldReward = 1000000, RandomitemReward = 8373, RandomitemCount = 1, itemReward = 16857, itemCount = 15, msg = "Testsdfsdfsdfsdf"},
    [2] = {name = "Boss 2", pos = Position(960, 937, 7), chance = 5, expReward = 1500, pointsReward = 10, goldReward = 1000000, RandomitemReward = 8373, RandomitemCount = 1, itemReward = 16857, itemCount = 15, msg = "Testdfsdfsdfsdff!"}
}
 
How?
Lua:
monsterSystem = {
    [1] = {name = "Boss 1", pos = Position(228, 1043, 7), chance = 5, expReward = 1500, pointsReward = 10, goldReward = 1000000, RandomitemReward = 8373, RandomitemCount = 1, itemReward = 16857, itemCount = 15, msg = "Testsdfsdfsdfsdf"},
    [2] = {name = "Boss 2", pos = Position(960, 937, 7), chance = 5, expReward = 1500, pointsReward = 10, goldReward = 1000000, RandomitemReward = 8373, RandomitemCount = 1, itemReward = 16857, itemCount = 15, msg = "Testdfsdfsdfsdff!"}
}
Can you explain in 1 post how this system should work? I can write new one tonight cuz idea is pretty cool so i cna share

Anyway you dont need any storages on new tfs, you can just save everything in table like

local spawnedBosses = {}

and then insert boss id when u spawn it for example

local bosses = {"boss 1", "boss 2"} etc.. and then

check if not table.contains(spawnedBosses, bosses[1, #bosses] ... then spawn this random choosen boss,
Umm better way is to use ID instead of names if you want to spawn same boss in 2 difrent places but its hard for me to explain that, if you can just describe how this system should work and i can write it
 
Henkas - a suggestion: write down exactly what you want to do. And if you can, make the title match your main objective.

A. You seem to have a working system to:
  • Once an hour, you may spawn a boss with a 10% chance
  • Remove that boss after one hour if it hasn't been killed
B. You have a set of candidate bosses (5 or so?). If a boss spawns (10% chance) you select one of these, but not entirely at random.

C. You don't want to spawn the same boss repeatedly ... but you haven't specified what patterns are possible.
For example if we assume 5 bosses, B1, B2, B3, B4, B5: it's clear from your posts that pattern B1, B1, B3, isn't ok.

But do you, for example, actually want to spawn each boss once per 5 spawns, but in a random order (so B3, B4, B2, B5, B1 would be ok, then you'd roll the dice again and you might get B4, B1, B5, B3, B2)?
NB: in my example you'd need to check for a repeat across successive sets of 5 (so the last in one set doesn't come up as the first in the next set), but that's easy enough.

(C) implies you must have a "memory" between each roll for a boss. A "storage" is the obvious solution - your rejecting it in your second post was probably not the right decision.
But if you want the "memory" to last across a game restart, as I understand it, you'd need something else. You should include or explicitly exclude that requirement.

The exact information you need to remember between spawn attempts will vary depending on the desired/acceptable sequence of bosses that are spawned. For example a minimal solution to avoid spawning the same one twice in a row only requires that you "remember" the last boss that spawned, so you can reject it (select from the other four) next time you spawn a boss.

The "random cycle" of 5 bosses I showed above requires you to remember each active sequence for five spawns, but if global storage is a scarce resource it can be done with just 5 numbers, bossIDs, or indexes into a "Boss Table".

BTW those two aren't the only possible ways to select the next boss while excluding repeats, but I can't think of anything that would make it complicated - I doubt this will be hard to implement in LUA.
 
Last edited:
Can you explain in 1 post how this system should work? I can write new one tonight cuz idea is pretty cool so i cna share

Anyway you dont need any storages on new tfs, you can just save everything in table like

local spawnedBosses = {}

and then insert boss id when u spawn it for example

local bosses = {"boss 1", "boss 2"} etc.. and then

check if not table.contains(spawnedBosses, bosses[1, #bosses] ... then spawn this random choosen boss,
Umm better way is to use ID instead of names if you want to spawn same boss in 2 difrent places but its hard for me to explain that, if you can just describe how this system should work and i can write it
So basically this system should work like this.
Every 2 Hours there is lets say 45% chance to spawn a boss to a X,Y,Z there is like 10 different bosses with different names each of them have their own spawn location (Basically i mapped different rooms for each of them, they dont share same location) when they are spawned, lets say Boss 5 spawns, he cant be spawned again so the reason for it is so, it wont loop just in case, because lets say what if server is online for 1 week without any reloads so there is a big chance same creature might be spawned but different bosses can be spawned but Boss 5 cant be spawned anymore until hes not killed or something happens or he disappears. And thats it then it goes rewards when you kill that boss but there is no point talking about it because i will do it myself i hope, the main focus is spawn it properly.
 
How?
Lua:
monsterSystem = {
    [1] = {name = "Boss 1", pos = Position(228, 1043, 7), chance = 5, expReward = 1500, pointsReward = 10, goldReward = 1000000, RandomitemReward = 8373, RandomitemCount = 1, itemReward = 16857, itemCount = 15, msg = "Testsdfsdfsdfsdf"},
    [2] = {name = "Boss 2", pos = Position(960, 937, 7), chance = 5, expReward = 1500, pointsReward = 10, goldReward = 1000000, RandomitemReward = 8373, RandomitemCount = 1, itemReward = 16857, itemCount = 15, msg = "Testdfsdfsdfsdff!"}
}

GLOBAL VARIABLE lastBoss = 1 (last boss summoned was 1(example) -- this is to prevent that boss 1 go again in a row

if getGlobalStorageValue(boss1) == 0 and lastBoss ~= 1 then
spawn boss 1
setglobal....(boss1,1)
setglobal....(boss1Timer,time-os.time)
lastBoss = 1
return true
elseif getGlobalStorageValue(boss2) == 0 and lastBoss ~= 2 then
spawn boss 2
setgloba....(boss2,1)
setglobal....(boss2Timer,time-os.time)
lastboss = 2
return true
elseif ....
end
....


Put when the boss dies he trigg a onDeath event that sets the storageGlobal(bossNumber, to 0)


A globalEvents that checks if getGlobalValue(boss2Timer) - os.time > 0, if yes, check the area with game.getspec.... then monster:remove()
 
I think this is what your looking for?

1) Spawns a random boss in one of the areas
2) Removes that boss from being able to be spawned again
3) Removes the boss after 1 hour if not killed.

NOTE There is multiple areas set up for different parts of the map. So if you have more than 1 area of bosses set up like this. The bosses are linked to the area. They are not all linked together.

Lua:
local areas = {
    [1] = {chanceSpawn = 100, -- 100% chance to spawn one of the bosses
        bosses = {
            {"Name", Position(1000, 1000, 7)},
            {"Name", Position(1000, 1000, 7)}
        }
    },
    [2] = {chanceSpawn = 35,
        bosses = {
            {"Name", Position(1000, 1000, 7)},
            {"Name", Position(1000, 1000, 7)},
            {"Name", Position(1000, 1000, 7)}
        }
    }
   
}

local possibleBosses = {
    [1] = {1, 2}, -- Should be the same as the amount of bosses in each area. (4 bosses = 1, 2, 3, 4)
    [2] = {1, 2, 3}
}

function onThink(interval)
    for i = 1, #areas do
        if math.random(100) <= areas[i].chanceSpawn then

        local POSSIBLEBOSS = possibleBosses[i]
       
            if #POSSIBLEBOSS > 0 then
                local BOSSID = math.random(#POSSIBLEBOSS)
                POSSIBLEBOSS[BOSSID] = nil
                local BOSS = areas[i].bosses[BOSSID]
               
                if BOSS then
                    local MONS = Game.createMonster(BOSS[1], BOSS[2])
                    addEvent(removeBoss, 60 * 60 * 1000, MONS:getId())
                end
            end
        end
    end
    return true
end

function removeBoss(id)
    local monster = Monster(id)
    if monster then
        monster:remove()
    end
end
 
Back
Top