• 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.X+ How to modify this event (Two thinks)

henkas

Well-Known Member
Joined
Jul 8, 2015
Messages
993
Solutions
5
Reaction score
55
Using TFS: 1.2

This is how i would like to modify it.
1. Make it 10% chance per 2 hour to respawn (boss)
2. If boss is not killed per 1hour it will be deleted with broadcast (i have this function already but its not convenient because it will delete everything around even if player will stand close so you will be kicked to.
Or it would be great instead of deleting it if monster is not killed do not spawn another boss if that first boss is not killed to avoid couple spawns.
3. Last think if its possible to give exp reward if they deal some dmg to that boss because its not really good to use share exp function on such event like this. So it would be nice to see if everyone would get the same amount exp.

I'll explain how my script works now.
Lua:
local bosses = {
    {bossName = "Test LvL 1", bossPosition = Position(315, 179, 7)},
    {bossName = "Test LvL 2", bossPosition = Position(315, 179, 7)}
}
Bosses = {}

function spawnBoss()
    if #Bosses >= #bosses then
        for i = #Bosses, 1, -1 do
            Bosses[i] = nil
        end
    end

    local creature = bosses[math.random(#bosses)]
    if isInArray(Bosses, creature.bossName) then
        -- print('>> attempt to spawn '..creature.bossName..' again.')
        creature = spawnBoss() -- recursive, call again if name exist
    else
        -- update the global Bosses table with the creature name if it does not exist
        table.insert(Bosses, creature.bossName)
    end
    -- return the local table's return value
    return creature
end
local function removeBoss()
    local center = Position(315, 179, 7)
    local radius = 10
    local monsters = Game.getSpectators(center, false, false, radius, radius, radius, radius)

    if monsters == nil then
        return false
    end

    if #monsters < 0 then
        return false
    end

    for i = 1, #monsters do
        monster = Creature(monsters[i])
        monster:remove()
    end
    broadcastMessage("1 Hour passed and you was not able to defeat the daily boss!", MESSAGE_EVENT_ADVANCE)
    return true
end

function onTime(interval)
    local rand = spawnBoss()
    local monster = Game.createMonster(rand.bossName, rand.bossPosition)
    if not monster then
        print('>> Failed to spawn '..rand.bossName..'.')
        return true
    end
    print('>> The boss: ' ..monster:getName() .. ' spawn.')
    broadcastMessage("Daily boss have been spawned infront of temple!.", MESSAGE_EVENT_ADVANCE)
    return true
    end
        addEvent(removeBoss, 3600000)

Code:
    <globalevent name="SpawnBoss" time="20:00:00" script="spawn.lua" />

So every 20:00 boss randomly between Test LvL 1, Test LvL 2 will be spawned, it will choose one of them to spawn if boss is not killed it will delete that boss with broadcast but as you can see it will delete players to if they stand next to that monster
 
Solution
I didn't like how all the system was done, so I just remade it for you (Taking into consideration that you want all of it in just 1 table):

Add to your data/global.lua:
Lua:
monsterSystem = {
    [1] = {name = "rat", pos = Position(1000, 1000, 7), expReward = 5000, goldReward = 1000},
    [2] = {name = "demon", pos = Position(1000, 1000, 7), expReward = 9000, goldReward = 1000}
}


This goes to creaturescripts/scripts/henkas.lua:
Lua:
function onDeath(creature, corpse, killer, mostDamage, unjustified, mostDamage_unjustified)
    local percent = creature:getMaxHealth() * 0.01
    for k, v in pairs(monsterSystem) do
            if v.name:lower() == creature:getName():lower() then
            for pid, info in pairs(creature:getDamageMap())...
1 and 2)
7200 seconds = 2 hours, but interval is in miliseconds as far as I know
<globalevent name="SpawnBoss" interval="720000" script="spawn.lua" />

Code:
local bosses = {
    {bossName = "Test LvL 1", bossPosition = Position(315, 179, 7)},
    {bossName = "Test LvL 2", bossPosition = Position(315, 179, 7)}
}
Bosses = {}
function spawnBoss()
    if #Bosses >= #bosses then
        for i = #Bosses, 1, -1 do
            Bosses[i] = nil
        end
    end
    local creature = bosses[math.random(#bosses)]
    if isInArray(Bosses, creature.bossName) then
        -- print('>> attempt to spawn '..creature.bossName..' again.')
        creature = spawnBoss() -- recursive, call again if name exist
    else
        -- update the global Bosses table with the creature name if it does not exist
        table.insert(Bosses, creature.bossName)
    end
    -- return the local table's return value
    return creature
end
local function removeBoss()
    local center = Position(315, 179, 7)
    local radius = 10
    local monsters = Game.getSpectators(center, false, false, radius, radius, radius, radius)
    if monsters == nil then
        return false
    end
    if #monsters < 0 then
        return false
    end
    for i = 1, #monsters do
        monster = Monster(monsters[i])
        for i, v in ipairs(bosses) do       
            if monster:getName() == v.bossName then -- let's only remove if the boss name is the same as the bosses in boss tab
                monster:remove()
            end
        end
    end
    broadcastMessage("1 Hour passed and you was not able to defeat the daily boss!", MESSAGE_EVENT_ADVANCE)
    return true
end
function onTime(interval)
    if math.random(1, 100) <= 10 then
        local rand = spawnBoss()
        local monster = Game.createMonster(rand.bossName, rand.bossPosition)
        if not monster then
            print('>> Failed to spawn '..rand.bossName..'.')
            return true
        end
        addEvent(removeBoss, 3600000)
        print('>> The boss: ' ..monster:getName() .. ' spawn.')
        broadcastMessage("Daily boss have been spawned infront of temple!.", MESSAGE_EVENT_ADVANCE)
    end
return true
end
 
1 and 2)
7200 seconds = 2 hours, but interval is in miliseconds as far as I know
<globalevent name="SpawnBoss" interval="720000" script="spawn.lua" />

Code:
local bosses = {
    {bossName = "Test LvL 1", bossPosition = Position(315, 179, 7)},
    {bossName = "Test LvL 2", bossPosition = Position(315, 179, 7)}
}
Bosses = {}
function spawnBoss()
    if #Bosses >= #bosses then
        for i = #Bosses, 1, -1 do
            Bosses[i] = nil
        end
    end
    local creature = bosses[math.random(#bosses)]
    if isInArray(Bosses, creature.bossName) then
        -- print('>> attempt to spawn '..creature.bossName..' again.')
        creature = spawnBoss() -- recursive, call again if name exist
    else
        -- update the global Bosses table with the creature name if it does not exist
        table.insert(Bosses, creature.bossName)
    end
    -- return the local table's return value
    return creature
end
local function removeBoss()
    local center = Position(315, 179, 7)
    local radius = 10
    local monsters = Game.getSpectators(center, false, false, radius, radius, radius, radius)
    if monsters == nil then
        return false
    end
    if #monsters < 0 then
        return false
    end
    for i = 1, #monsters do
        monster = Monster(monsters[i])
        for i, v in ipairs(bosses) do      
            if monster:getName() == v.bossName then -- let's only remove if the boss name is the same as the bosses in boss tab
                monster:remove()
            end
        end
    end
    broadcastMessage("1 Hour passed and you was not able to defeat the daily boss!", MESSAGE_EVENT_ADVANCE)
    return true
end
function onTime(interval)
    if math.random(1, 100) <= 10 then
        local rand = spawnBoss()
        local monster = Game.createMonster(rand.bossName, rand.bossPosition)
        if not monster then
            print('>> Failed to spawn '..rand.bossName..'.')
            return true
        end
        addEvent(removeBoss, 3600000)
        print('>> The boss: ' ..monster:getName() .. ' spawn.')
        broadcastMessage("Daily boss have been spawned infront of temple!.", MESSAGE_EVENT_ADVANCE)
    end
return true
end
Event onThink not found. scripts/spawn.lua
 
change function onTime(interval) to function onThink(interval)
O yea. So as i understand you managed to fix question 2 right? So as i understand it still need to use
local center = Position(315, 179, 7)
local radius = 10
? Doesnt it gonna delete players around to? Is it possible to remove the monster without making pos if 1hour pass? Because what if i make random pos to spawn the monster so that means it only gonna delete boos in 315, 179, 7, right?
 
let's go in depth in this function:


  1. local function removeBoss()
  2. local center = Position(315, 179, 7)
  3. local radius = 10
  4. local monsters = Game.getSpectators(center, false, false, radius, radius, radius, radius)
  5. if monsters == nil then
  6. return false
  7. end
  8. if #monsters < 0 then
  9. return false
  10. end
  11. for i = 1, #monsters do
  12. monster = Monster(monsters)
    [*] for i, v in ipairs(bosses) do
    [*] if monster:getName() == v.bossName then -- let's only remove if the boss name is the same as the bosses in boss tab
    [*] monster:remove()
    [*] end
    [*] end
    [*] end
    [*] broadcastMessage("1 Hour passed and you was not able to defeat the daily boss!", MESSAGE_EVENT_ADVANCE)
    [*] return true
    [*]end

    in line 2 you start by defining the center, basically where is the center of the area where your boss it at.
    in line 3 you define the radius, the sqms from the center you'll cover. Using 10 means if our center is "C" then we will be covering everything in "W":

    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W C W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W

    Your radius is the square formed by 10 sqm left, 10 sqm right, 10 sqm up and 10 sqm down of your center.
    The function in line 4 basically goes all through this area and returns an table with all the creatures found there. We check if it exists and if the table is not empty (have at least one creature returned) and then we iterate over the table to check if there any monster with the name as the ones that you should have spawned (lines 11 to 17)

 
let's go in depth in this function:


  1. local function removeBoss()
  2. local center = Position(315, 179, 7)
  3. local radius = 10
  4. local monsters = Game.getSpectators(center, false, false, radius, radius, radius, radius)
  5. if monsters == nil then
  6. return false
  7. end
  8. if #monsters < 0 then
  9. return false
  10. end
  11. for i = 1, #monsters do
  12. monster = Monster(monsters)
    [*] for i, v in ipairs(bosses) do
    [*] if monster:getName() == v.bossName then -- let's only remove if the boss name is the same as the bosses in boss tab
    [*] monster:remove()
    [*] end
    [*] end
    [*] end
    [*] broadcastMessage("1 Hour passed and you was not able to defeat the daily boss!", MESSAGE_EVENT_ADVANCE)
    [*] return true
    [*]end

    in line 2 you start by defining the center, basically where is the center of the area where your boss it at.
    in line 3 you define the radius, the sqms from the center you'll cover. Using 10 means if our center is "C" then we will be covering everything in "W":

    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W C W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W
    W W W W W W W W W W W W W W W W W W W W W

    Your radius is the square formed by 10 sqm left, 10 sqm right, 10 sqm up and 10 sqm down of your center.
    The function in line 4 basically goes all through this area and returns an table with all the creatures found there. We check if it exists and if the table is not empty (have at least one creature returned) and then we iterate over the table to check if there any monster with the name as the ones that you should have spawned (lines 11 to 17)
Yea i knew that so that means it still gonna delete every creature around so its not the solution for question two
 
you only delete the monster you spawn. I added a check to it to only delete the names
Aaa i though if there is monster:remove it will delete everything around, but if you say it wont this is great. So the last think left then, about exp reward do you know something about it?
 
Just a small input, I would update this line..
Lua:
if monster:getName() == v.bossName then -- let's only remove if the boss name is the same as the bosses in boss tab
Lua:
if monster:getName():lower() == v.bossName:lower() then -- let's only remove if the boss name is the same as the bosses in boss tab
Just so you don't have to worry about capitalization when you add more stuff to the table in some distant future.
 
Just a small input, I would update this line..
Lua:
if monster:getName() == v.bossName then -- let's only remove if the boss name is the same as the bosses in boss tab
Lua:
if monster:getName():lower() == v.bossName:lower() then -- let's only remove if the boss name is the same as the bosses in boss tab
Just so you don't have to worry about capitalization when you add more stuff to the table in some distant future.
thanks for noticing
 
Bump
3. Last think if its possible to give exp reward if they deal some dmg to that boss because its not really good to use share exp function on such event like this. So it would be nice to see if everyone would get the same amount exp.
 
for the 3) you should remove the experience from the monster file (put experience="0") and then you should create an onDeath creaturescript that if the monster is name XXXX then it should give exp to everyone on the screen.

Use this as base
  1. local function removeBoss()
  2. local center = Position(315, 179, 7)
  3. local radius = 10
  4. local monsters = Game.getSpectators(center, false, false, radius, radius, radius, radius)

  5. if monsters == nil then
  6. return false
  7. end

  8. if #monsters < 0 then
  9. return false
  10. end

  11. for i = 1, #monsters do
  12. monster = Player(monsters) -- only give exp to players
    [*] monster:addExperience(5000) -- gives 5k exp
    [*] end
 
for the 3) you should remove the experience from the monster file (put experience="0") and then you should create an onDeath creaturescript that if the monster is name XXXX then it should give exp to everyone on the screen.

Use this as base
  1. local function removeBoss()
  2. local center = Position(315, 179, 7)
  3. local radius = 10
  4. local monsters = Game.getSpectators(center, false, false, radius, radius, radius, radius)

  5. if monsters == nil then
  6. return false
  7. end

  8. if #monsters < 0 then
  9. return false
  10. end

  11. for i = 1, #monsters do
  12. monster = Player(monsters) -- only give exp to players
    [*] monster:addExperience(5000) -- gives 5k exp
    [*] end
So it means that even if you didnt hit a dmg you still will get exp?
 
yes, this would be the easiest way. The other way is to modify in the source to return the damage map in the onDeath event
Hmmm its not really how i want it to be, because then you could abuse this exp just by standing and doing nothing, thats why it would be better if you get exp only if you deal 1% of his health or deal like 500k dmg
 
then you will have to do the following:
make a onstatschange event that checks if creature is the monster and increase a storage on the attacker. On the ondeath function you have to get player which storage are higher than 1% max health of the boss and you addExp to them. If they have reached this storage of not, you must set the storage to 0
 
then you will have to do the following:
make a onstatschange event that checks if creature is the monster and increase a storage on the attacker. On the ondeath function you have to get player which storage are higher than 1% max health of the boss and you addExp to them. If they have reached this storage of not, you must set the storage to 0
Uch, is there tutorial for such think because now its sounds like a next level
 
I don't see any reason for him to use storages since he works with tfs 1.2
Example:
Code:
local config = {
    experience = 5000
}

function onDeath(monster, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified)
    local onepercent = monster:getMaxHealth() * 0.01
    for cid, info in pairs(monster:getDamageMap()) do
        local creature = Creature(cid)
        if(creature and info.total >= onepercent) then
            --this creature has dealt 1% dmg

            local player = creature:getPlayer()
            if(player) then
                player:addExperience(config.experience)
            end
        end
    end

    return true
end
This script should work but keep in mind to register this creatureevent to monster and not in login.lua
I know you all try to help people but maybe try to read some tfs lua functions manual before you say there wasn't a function for this.
 
I don't see any reason for him to use storages since he works with tfs 1.2
Example:
Code:
local config = {
    experience = 5000
}

function onDeath(monster, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified)
    local onepercent = monster:getMaxHealth() * 0.01
    for cid, info in pairs(monster:getDamageMap()) do
        local creature = Creature(cid)
        if(creature and info.total >= onepercent) then
            --this creature has dealt 1% dmg

            local player = creature:getPlayer()
            if(player) then
                player:addExperience(config.experience)
            end
        end
    end

    return true
end
This script should work but keep in mind to register this creatureevent to monster and not in login.lua
I know you all try to help people but maybe try to read some tfs lua functions manual before you say there wasn't a function for this.
About this local config so how to use it if want to apply different exp to every monster so instead of creating new config is it possible to apply in this local bosses
Lua:
local bosses = {
    {bossName = "Test LvL 1", bossPosition = Position(315, 179, 7)},
    {bossName = "Test LvL 2", bossPosition = Position(315, 179, 7)}
}
?
 
Back
Top