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

Action [TFS 1.X] Cursed Chests

I can do that for you if you want, not gonna make it official tho.

you can do it?

It would be something like: 10% chance to open (math.random (1,10) and win the reward without facing the waves.
 
you can do it?

It would be something like: 10% chance to open (math.random (1,10) and win the reward without facing the waves.
Replace in actions. Change % here CURSED_CHESTS_OPEN_CHANCE.
 

Attachments

@oen432 Is it possible to start a globalevent like this one by.. like another script?

"sacrifice item x on pos x to start global event cursed_chest"?
How would that look incase it's possible
 
@oen432 Is it possible to start a globalevent like this one by.. like another script?

"sacrifice item x on pos x to start global event cursed_chest"?
How would that look incase it's possible
You mean not every X minutes but only when an item is used? More details required. You want to start that event but how many chests would you like to spawn and where? Every possible chest at the same time? Or make it spawn for X minutes every X minutes? Everything is possible, not even that hard I guess.
 
Yes, Start the event when item is used. Could probably choose what chest by editing the chances of the quests such as:

Code:
{
        tier = CURSED_CHESTS_TIER_EPIC,
        chance = 100,
        text = "Epic Cursed Chest",
        item = 5099,
        monstersPerWave = 9
    },
    {
        tier = CURSED_CHESTS_TIER_LEGENDARY,
        chance = 0,
        text = "Legendary Cursed Chest",
        item = 5099,
        monstersPerWave = 11
    }

To create the event ONE time when Item is used.
For example

Code:
function onAddItem(item, tileitem, position)
    if Game.isItemThere({x = 33098, y = 32816, z = 13},3042) then
        Game.removeItemOnMap({x = 33098, y = 32816, z = 13}, 3042)
    else
        Game.sendMagicEffect({x = 33098, y = 32816, z = 13}, 3)
        Start event Cursed_Chest
    end
end

Probably not using "start event".. how could that be done?
Also set
Code:
<globalevent name="CursedChestSpawner" interval="0" script="cursed_chest_spawner.lua"/>
Would that make the event never happen unless triggerd by item used?
 
Add somewhere at the top inside cursed_chests.lua in actions.
Lua:
CURSED_CHESTS_ACTIVE = false
Then open data\globalevents\scripts\cursed_chest_spawner.lua
Under
Lua:
function onThink(cid, interval, lastExecution)
Add
Lua:
if CURSED_CHESTS_ACTIVE == false then return true end
In the same file, at the bottom right above return true, add
Lua:
CURSED_CHESTS_ACTIVE = false

Now add CURSED_CHESTS_ACTIVE = true to your script that should start the event. When it's set to true, event will be executed on the next globalevent tick and execute spawning ONCE and then set to false so it won't execute unless your script sets it to true.
 
Added everything you said.
And using this in attempt to start the event. Tho Nothing happends.. My item ingame vanishes and sends magic effect but no sign of starting Cursed chest event.

Code:
function onAddItem(item, tileitem, position)
    if Game.isItemThere({x = 32373, y = 32215, z = 7},3042) then
        Game.removeItemOnMap({x = 32373, y = 32215, z = 7}, 3042)
        CURSED_CHESTS_ACTIVE = true
        Game.sendMagicEffect({x = 32373, y = 32215, z = 7}, 13)
    
    else
        
        
    end
end
 
Added everything you said.
And using this in attempt to start the event. Tho Nothing happends.. My item ingame vanishes and sends magic effect but no sign of starting Cursed chest event.

Code:
function onAddItem(item, tileitem, position)
    if Game.isItemThere({x = 32373, y = 32215, z = 7},3042) then
        Game.removeItemOnMap({x = 32373, y = 32215, z = 7}, 3042)
        CURSED_CHESTS_ACTIVE = true
        Game.sendMagicEffect({x = 32373, y = 32215, z = 7}, 13)
  
    else
      
      
    end
end
Change interval inside globalevents.xml. It's set to 5 minutes so you would have to wait. Set it to 5000 (5 seconds).
And you can add this
Lua:
broadcastMessage("Cursed Chests Event started.", MESSAGE_STATUS_WARNING)
Under
Lua:
if CURSED_CHESTS_ACTIVE == false then return true end
Inside cursed_chest_spawner.lua.
 
Code:
function onAddItem(item, tileitem, position)
    if Game.isItemThere({x = 32373, y = 32215, z = 7},3042) then
        Game.removeItemOnMap({x = 32373, y = 32215, z = 7}, 3042)
        CURSED_CHESTS_ACTIVE = true
        Game.sendMagicEffect({x = 32373, y = 32215, z = 7}, 13)
   
    else
       
       
    end
end

@oen432

Atm when putting 2x of 3042 on the tile both of them get consumed. Anyway to make it only consume 1 or not work at all with 2 of 3042?
Or if CURSED_CHESTS_ACTIVE = true then not consuming 3042 at all?
 
Last edited:
Code:
function onAddItem(item, tileitem, position)
    if Game.isItemThere({x = 32373, y = 32215, z = 7},3042) then
        Game.removeItemOnMap({x = 32373, y = 32215, z = 7}, 3042)
        CURSED_CHESTS_ACTIVE = true
        Game.sendMagicEffect({x = 32373, y = 32215, z = 7}, 13)
   
    else
       
       
    end
end

@oen432

Atm when putting 2x of 3042 on the tile both of them get consumed. Anyway to make it only consume 1 or not work at all with 2 of 3042?
These functions are custom so you would need something new for this. But you can check if there are items on that position already. If there is more than one then do nothing. If you have something added on that tile (using map editor) then change that 1 next to tile:getItemCount() to something else (every pre-made item on that tile -1).
Lua:
function onAddItem(item, tileitem, position)
  local pos = Position(32373, 32215, 7)
  tile = Tile(pos)
  if tile and tile:getItemCount() > 1 then
    return
  end
  if Game.isItemThere(pos, 3042) then
    Game.removeItemOnMap(pos, 3042)
    CURSED_CHESTS_ACTIVE = true
    Game.sendMagicEffect(pos, 13)
  end
end
 
@oen432
Can you somehow make the dead monsters disappear after a few seconds?
Just feels so messy when the 20 dead monsters are in the same place ^^
 
@oen432
Can you somehow make the dead monsters disappear after a few seconds?
Just feels so messy when the 20 dead monsters are in the same place ^^
They are still dropping loot so not sure if that's a good idea. Players might like to check the corpses after killing everything.
 
They are still dropping loot so not sure if that's a good idea. Players might like to check the corpses after killing everything.

Than maybe you can fix so the corpses disappear after 10 to 20 second after the chest have been removed?
So players have time to check the corpses when everything is finish.
 
Than maybe you can fix so the corpses disappear after 10 to 20 second after the chest have been removed?
So players have time to check the corpses when everything is finish.
There you go. You can change after how long corpses should be cleared - CURSED_CHESTS_CLEAR_CORPSES.
Replace data/actions/scripts/custom/cursed_chest.lua.
 

Attachments

BIG LOVE!
I changed tfs to 1.3 just for your scripts. And it was worth it, my war server will be perfect with your scripts.
right now I use, Item sets, upgrade items, cursed chests & the combo spells.
 
Hey im getting this erorr when i click the chest, could anyone help me out?37078
 
a way to change the boss to each chest?


Lua:
local CURSED_CHESTS_VERSION = "1.1.1"

local CURSED_CHESTS_SKULL_DEFAULT = SKULL_WHITE
local CURSED_CHESTS_SKULL_BOSS = SKULL_BLACK

CURSED_CHESTS_TIER_COMMON = 1
CURSED_CHESTS_TIER_RARE = 2
CURSED_CHESTS_TIER_EPIC = 3
CURSED_CHESTS_TIER_LEGENDARY = 4

CURSED_CHESTS_TIERS = {
    {
        tier = CURSED_CHESTS_TIER_COMMON,
        chance = 70,
        text = "Common Cursed Chest",
        item = 1740,
        monstersPerWave = 1
    },
    {
        tier = CURSED_CHESTS_TIER_RARE,
        chance = 50,
        text = "Rare Cursed Chest",
        item = 1750,
        monstersPerWave = 1
    },
    {
        tier = CURSED_CHESTS_TIER_EPIC,
        chance = 30,
        text = "Epic Cursed Chest",
        item = 1746,
        monstersPerWave = 1
    },
    {
        tier = CURSED_CHESTS_TIER_LEGENDARY,
        chance = 10,
        text = "Legendary Cursed Chest",
        item = 12664,
        monstersPerWave = 1
    }
}

CURSED_CHESTS_CONFIG = {
    [1] = {
            message = "Prepare to defend against 5 waves of monsters and a boss at the end.",
            rewards = {
                [CURSED_CHESTS_TIER_COMMON] = {
                    { -- Platinum Coins
                        chance = 100,
                        item = 2152,
                        random = true,
                        amount = 60
                    },
                    { -- Crystal Coins
                        chance = 20,
                        item = 2160,
                        random = true,
                        amount = 2
                    }
                },
                [CURSED_CHESTS_TIER_RARE] = {
                    { -- Platinum Coins
                        chance = 100,
                        item = 2152,
                        random = true,
                        amount = 80
                    },
                    { -- Crystal Coins
                        chance = 40,
                        item = 2160,
                        amount = 1
                    },
                    { -- Demon Legs
                        chance = 20,
                        item = 2495,
                        amount = 1
                    }
                },
                [CURSED_CHESTS_TIER_EPIC] = {
                    { -- Platinum Coins
                        chance = 100,
                        item = 2152,
                        random = true,
                        amount = 100
                    },
                    { -- Crystal Coins
                        chance = 60,
                        item = 2160,
                        amount = 1
                    },
                    { -- Demon Legs
                        chance = 20,
                        item = 2495,
                        amount = 1
                    },
                    { -- Demon Armor
                        chance = 20,
                        item = 2494,
                        amount = 1
                    }
                },
                [CURSED_CHESTS_TIER_LEGENDARY] = {
                    { -- Platinum Coins
                        chance = 100,
                        item = 2152,
                        random = true,
                        amount = 100
                    },
                    { -- Crystal Coins
                        chance = 70,
                        item = 2160,
                        random = true,
                        amount = 2
                    },
                    { -- Demon Legs
                        chance = 40,
                        item = 2495,
                        amount = 1
                    },
                    { -- Demon Armor
                        chance = 30,
                        item = 2494,
                        amount = 1
                    },
                    { -- Demon Helmet
                        chance = 10,
                        item = 2493,
                        amount = 1
                    },
                    { -- Firewalker Boots
                        chance = 2,
                        item = 9933,
                        amount = 1
                    }
                }
            },
            waves = {
                [CURSED_CHESTS_TIER_COMMON] = {
                    { -- Wave 1
                        "Troll",
                        "Orc",
                        "Dwarf"
                    },
                    { -- Wave 2
                        "Amazon",
                        "Nomad",
                        "Valkyrie",
                        "Bandit"
                    },
                    { -- Wave 3
                        "Dwarf Soldier",
                        "Ghoul",
                        "Minotaur Guard",
                        "Smuggler",
                        "Tarantula"
                    },
                    { -- Wave 4
                        "Barbarian Skullhunter",
                        "Wild Warrior",
                        "Terror Bird",
                        "Slime",
                        "Sibang"
                    },
                    { -- Wave 5
                        "Stone Golem",
                        "Leaf Golem",
                        "Frost Giant",
                        "Cyclops",
                        "Insectoid Scout"
                    }
                },
                boss = {
                name = "Ice Golem",
                fightDuration = 90,
                message = "Boss incoming! You have 90 seconds to kill Ice Golem!"
            },
                [CURSED_CHESTS_TIER_RARE] = {
                    { -- Wave 1
                        "Cyclops",
                        "Bonelord",
                        "Insectoid Scout"
                    },
                    { -- Wave 2
                        "Dark Monk",
                        "Dwarf Guard",
                        "Crypt Shambler",
                        "Hunter"
                    },
                    { -- Wave 3
                        "Minotaur Mage",
                        "Terramite",
                        "Crystal Wolf",
                        "Crystalcrusher",
                        "Cyclops Smith"
                    },
                    { -- Wave 4
                        "Demon Skeleton",
                        "Dragon",
                        "Earth Elemental",
                        "Elder Bonelord",
                        "Energy Elemental"
                    },
                    { -- Wave 5
                        "Faun",
                        "Fire Elemental",
                        "Frost Dragon",
                        "Giant Spider",
                        "Grave Guard"
                    }
                },
                boss = {
                name = "Dragon Lord",
                fightDuration = 90,
                message = "Boss incoming! You have 90 seconds to kill Dragon Lord!"
            },
                [CURSED_CHESTS_TIER_EPIC] = {
                    { -- Wave 1
                        "Fire Devil",
                        "Gozzler",
                        "Nightstalker"
                    },
                    { -- Wave 2
                        "Fire Devil",
                        "Gozzler",
                        "Nightstalker",
                        "Diabolic Imp"
                    },
                    { -- Wave 3
                        "Fire Devil",
                        "Gozzler",
                        "Nightstalker",
                        "Diabolic Imp",
                        "Nightmare"
                    },
                    { -- Wave 4
                        "Fire Devil",
                        "Nightstalker",
                        "Diabolic Imp",
                        "Nightmare",
                        "Frazzlemaw"
                    },
                    { -- Wave 5
                        "Hellspawn",
                        "Fury",
                        "Dark Torturer",
                        "Guzzlemaw",
                        "Demon"
                    }
                },
                [CURSED_CHESTS_TIER_LEGENDARY] = {
                    { -- Wave 1
                        "Fire Devil",
                        "Gozzler",
                        "Nightstalker"
                    },
                    { -- Wave 2
                        "Fire Devil",
                        "Gozzler",
                        "Nightstalker",
                        "Diabolic Imp"
                    },
                    { -- Wave 3
                        "Fire Devil",
                        "Gozzler",
                        "Nightstalker",
                        "Diabolic Imp",
                        "Nightmare"
                    },
                    { -- Wave 4
                        "Fire Devil",
                        "Nightstalker",
                        "Diabolic Imp",
                        "Nightmare",
                        "Frazzlemaw"
                    },
                    { -- Wave 5
                        "Hellspawn",
                        "Fury",
                        "Dark Torturer",
                        "Guzzlemaw",
                        "Demon"
                    }
                }
            },
        }
}

CURSED_CHESTS_DATA = {}

function CursedChestsLoad()
    print(">> Loaded Cursed Chests v" .. CURSED_CHESTS_VERSION)
    ShowEffects()
end

function ShowEffects()
    for _, data in ipairs(CURSED_CHESTS_DATA) do
        local tile = Tile(data.pos)
        if tile then
            for _, item in ipairs(tile:getItems()) do
                if item:getId() == data.rarity.item then
                    if data.active == 0 and data.finished == false then
                        data.pos:sendMagicEffect(CONST_ME_YALAHARIGHOST)
                        data.pos:sendAnimatedText(data.rarity.text)
                    elseif data.active == 1 and data.wave > 0 then
                        data.pos:sendMagicEffect(CONST_ME_YALAHARIGHOST)
                        if data.wave <= #data.chest.waves[data.rarity.tier] and not data.bossWave then
                            data.pos:sendAnimatedText(string.format("Wave %d / %d\nMonsters Alive: %d", data.wave, #data.chest.waves[data.rarity.tier], #data.monsters))
                        elseif data.chest.boss ~= nil and data.bossWave == true then
                            data.pos:sendAnimatedText(string.format("Boss Fight\n%s", data.chest.boss.name))
                        end
                    elseif data.finished == true then
                        data.pos:sendMagicEffect(CONST_ME_GIFT_WRAPS)
                        data.pos:sendAnimatedText("Get your reward!")
                    end
                end
            end
        end
    end
    addEvent(ShowEffects, 3000)
end

function CursedChestEvent(data)
    data.wave = data.wave + 1
    local from = Position(data.pos.x - 5, data.pos.y - 5, data.pos.z)
    local to = Position(data.pos.x + 5, data.pos.y + 5, data.pos.z)
    if data.wave <= #data.chest.waves[data.rarity.tier] then
        local mobs = CURSED_CHESTS_TIERS[data.rarity.tier].monstersPerWave * data.wave
        for i = 1, mobs do
            local mobName = data.chest.waves[data.rarity.tier][data.wave][math.random(1, #data.chest.waves[data.rarity.tier][data.wave])]
            local spawnPos = Position(math.random(from.x, to.x), math.random(from.y, to.y), data.pos.z)
            local tile = Tile(spawnPos)
            local spawnTest = 0
            while spawnTest < 100 do
                if data.pos == spawnPos or isBadTile(tile) then
                    spawnPos = Position(math.random(from.x, to.x), math.random(from.y, to.y), data.pos.z)
                    tile = Tile(spawnPos)
                    spawnTest = spawnTest + 1
                else
                    break
                end
            end
                    

            if spawnTest < 100 then
                local mob = Game.createMonster(mobName, spawnPos, false, true)
                if mob then
                    mob:setSkull(CURSED_CHESTS_SKULL_DEFAULT)
                    mob:registerEvent("CursedChestsDeath")
                    table.insert(data.monsters, mob:getId())
                end
            end
        end
    elseif data.chest.boss ~= nil then
        data.bossWave = true
        local spawnPos = Position(math.random(from.x, to.x), math.random(from.y, to.y), data.pos.z)
        local tile = Tile(spawnPos)
        local spawnTest = 0
        while spawnTest < 100 do
            if data.pos == spawnPos or isBadTile(tile) then
                spawnPos = Position(math.random(from.x, to.x), math.random(from.y, to.y), data.pos.z)
                tile = Tile(spawnPos)
                spawnTest = spawnTest + 1
            else
                break
            end
        end

        if spawnTest < 100 then
            local mob = Game.createMonster(data.chest.boss.name, spawnPos, false, true)
            if mob then
                mob:setSkull(CURSED_CHESTS_SKULL_BOSS)
                mob:registerEvent("CursedChestsDeath")
                table.insert(data.monsters, mob:getId())
                stopEvent(data.event)
                data.event = addEvent(CursedChestBoss, data.chest.boss.fightDuration * 1000, data)
            end
        end
    end
end

function CursedChestBoss(data)
    if #data.monsters == 1 then
        local boss = Monster(data.monsters[1])
        if boss then
            boss:remove()
            stopEvent(data.event)
            for i = 1, #CURSED_CHESTS_DATA do
                if CURSED_CHESTS_DATA[i] == data then table.remove(CURSED_CHESTS_DATA, i) end
            end
            data.container:getPosition():sendMagicEffect(CONST_ME_POFF)
            data.container:remove()
            CURSED_CHESTS_SPAWNS[data.spawnId].spawned = false
            data.pos:sendAnimatedText("Boss fight is over! You failed!")
        end
    end
end

function FinishCursedChestEvent(data)
    if data.chest.boss ~= nil and data.bossWave == true and #data.monsters == 0 or not data.chest.boss and data.wave == #data.chest.waves[data.rarity.tier] and #data.monsters == 0 then
        stopEvent(data.event)
        data.finished = true
        data.active = 0
        local loot = "Cursed Chest reward: "
        local items = {}

        for i = 1, #data.chest.rewards[data.rarity.tier] do
            if data.container:getEmptySlots() == 0 then break end

            local reward = data.chest.rewards[data.rarity.tier][i]
            if reward.chance == 100 then
                local amount = reward.random == true and math.random(1, reward.amount) or reward.amount
                local item = Game.createItem(reward.item, amount)
                data.container:addItemEx(item)
                table.insert(items, item)
            elseif math.random(1, 100) <= reward.chance then
                local amount = reward.random == true and math.random(1, reward.amount) or reward.amount
                local item = Game.createItem(reward.item, amount)
                data.container:addItemEx(item)
                table.insert(items, item)
            end
        end

        for i = #items, 1, -1 do
            if items[i]:getCount() > 1 then
                loot = loot .. items[i]:getCount() .. " "
                loot = loot .. items[i]:getPluralName()
            else
                loot = loot .. items[i]:getName()
            end
            if i > 1 then loot = loot .. ", " end
        end

        loot = loot .. "."

        local specs = Game.getSpectators(data.pos, false, true, 9, 9, 9, 9)
    if #specs > 0 then
        for i = 1, #specs do
            specs[i]:sendTextMessage(MESSAGE_STATUS_WARNING, loot)
        end
        end
        
        data.checks = 0
        data.event = addEvent(CursedChestCheck, 1000, data)
    end
end

function CursedChestCheck(data)
    data.event = addEvent(CursedChestCheck, 1000, data)
    addEvent(CursedChestDelete, 5 * 60 * 1000, data)
    if data.container:getEmptySlots() == data.container:getCapacity() then
        stopEvent(data.event)
        for i = 1, #CURSED_CHESTS_DATA do
            if CURSED_CHESTS_DATA[i] == data then table.remove(CURSED_CHESTS_DATA, i) end
        end
        data.container:getPosition():sendMagicEffect(CONST_ME_POFF)
        data.container:remove()
        CURSED_CHESTS_SPAWNS[data.spawnId].spawned = false
    end
end

function CursedChestDelete(data)
    for i = 1, #CURSED_CHESTS_DATA do
        if CURSED_CHESTS_DATA[i] == data then
            stopEvent(data.event)
            data.container:getPosition():sendMagicEffect(CONST_ME_POFF)
            data.container:remove()
            CURSED_CHESTS_SPAWNS[data.spawnId].spawned = false
            table.remove(CURSED_CHESTS_DATA, i)
        end
    end
end

function CursedChests_onDeath(creature, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified)
    for _, data in ipairs(CURSED_CHESTS_DATA) do
        if data.active == 1 then
            for i = 1, #data.monsters do
                if data.monsters[i] == creature:getId() then
                    table.remove(data.monsters, i)
                    if data.wave < #data.chest.waves[data.rarity.tier] and #data.monsters == 0 then
                        addEvent(CursedChestEvent, 1500, data)
                    elseif data.chest.boss ~= nil and not data.bossWave and #data.monsters == 0 then
                        killer:getPosition():sendAnimatedText(data.chest.boss.message)
                        addEvent(CursedChestEvent, 3000, data)
                    end
                    if data.wave == #data.chest.waves[data.rarity.tier] and #data.monsters == 0 or data.bossWave == true and #data.monsters == 0 then FinishCursedChestEvent(data) end
                    break
                end
            end
        end
    end
    return true
end

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    for _, data in ipairs(CURSED_CHESTS_DATA) do
        if data.pos == item:getPosition() then
            if data.active == 0 and data.finished == false then
                player:getPosition():sendAnimatedText(data.chest.message .. "\nKill all monsters to get awesome rewards!")
                if player:getParty() then
                    data.solo = false
                else
                    data.solo = true
                end
                data.owner = player:getName()
                data.wave = 0
                data.monsters = {}
                data.active = 1
                data.finished = false
                data.container = item
                data.event = addEvent(CursedChestEvent, 2000, data)
            elseif data.finished == true then
                if data.solo and data.owner == player:getName() then
                    return false
                elseif not data.solo then
                    local party = player:getParty()
                    if not party then return true end
                    if data.owner == player:getName() then return false end
                    local members = party:getMembers()
                    for i = 1, #members do
                        if members[i]:getName() == player:getName() then
                            return false
                        end
                    end
                end
                return true
            end
            return true
        end
    end
    return false
end

function isBadTile(tile)
    return (tile == nil or tile:getGround() == nil or tile:hasProperty(TILESTATE_NONE) or tile:hasProperty(TILESTATE_FLOORCHANGE_EAST) or isItem(tile:getThing()) and not isMoveable(tile:getThing()) or tile:getTopCreature() or tile:hasFlag(TILESTATE_PROTECTIONZONE))
end

what did i do worng?

did i place this line in the worng place?

boss = { name = "Dragon Lord", fightDuration = 90, message = "Boss incoming! You have 90 seconds to kill Dragon Lord!" },
 
a way to change the boss to each chest?


Lua:
local CURSED_CHESTS_VERSION = "1.1.1"

local CURSED_CHESTS_SKULL_DEFAULT = SKULL_WHITE
local CURSED_CHESTS_SKULL_BOSS = SKULL_BLACK

CURSED_CHESTS_TIER_COMMON = 1
CURSED_CHESTS_TIER_RARE = 2
CURSED_CHESTS_TIER_EPIC = 3
CURSED_CHESTS_TIER_LEGENDARY = 4

CURSED_CHESTS_TIERS = {
    {
        tier = CURSED_CHESTS_TIER_COMMON,
        chance = 70,
        text = "Common Cursed Chest",
        item = 1740,
        monstersPerWave = 1
    },
    {
        tier = CURSED_CHESTS_TIER_RARE,
        chance = 50,
        text = "Rare Cursed Chest",
        item = 1750,
        monstersPerWave = 1
    },
    {
        tier = CURSED_CHESTS_TIER_EPIC,
        chance = 30,
        text = "Epic Cursed Chest",
        item = 1746,
        monstersPerWave = 1
    },
    {
        tier = CURSED_CHESTS_TIER_LEGENDARY,
        chance = 10,
        text = "Legendary Cursed Chest",
        item = 12664,
        monstersPerWave = 1
    }
}

CURSED_CHESTS_CONFIG = {
    [1] = {
            message = "Prepare to defend against 5 waves of monsters and a boss at the end.",
            rewards = {
                [CURSED_CHESTS_TIER_COMMON] = {
                    { -- Platinum Coins
                        chance = 100,
                        item = 2152,
                        random = true,
                        amount = 60
                    },
                    { -- Crystal Coins
                        chance = 20,
                        item = 2160,
                        random = true,
                        amount = 2
                    }
                },
                [CURSED_CHESTS_TIER_RARE] = {
                    { -- Platinum Coins
                        chance = 100,
                        item = 2152,
                        random = true,
                        amount = 80
                    },
                    { -- Crystal Coins
                        chance = 40,
                        item = 2160,
                        amount = 1
                    },
                    { -- Demon Legs
                        chance = 20,
                        item = 2495,
                        amount = 1
                    }
                },
                [CURSED_CHESTS_TIER_EPIC] = {
                    { -- Platinum Coins
                        chance = 100,
                        item = 2152,
                        random = true,
                        amount = 100
                    },
                    { -- Crystal Coins
                        chance = 60,
                        item = 2160,
                        amount = 1
                    },
                    { -- Demon Legs
                        chance = 20,
                        item = 2495,
                        amount = 1
                    },
                    { -- Demon Armor
                        chance = 20,
                        item = 2494,
                        amount = 1
                    }
                },
                [CURSED_CHESTS_TIER_LEGENDARY] = {
                    { -- Platinum Coins
                        chance = 100,
                        item = 2152,
                        random = true,
                        amount = 100
                    },
                    { -- Crystal Coins
                        chance = 70,
                        item = 2160,
                        random = true,
                        amount = 2
                    },
                    { -- Demon Legs
                        chance = 40,
                        item = 2495,
                        amount = 1
                    },
                    { -- Demon Armor
                        chance = 30,
                        item = 2494,
                        amount = 1
                    },
                    { -- Demon Helmet
                        chance = 10,
                        item = 2493,
                        amount = 1
                    },
                    { -- Firewalker Boots
                        chance = 2,
                        item = 9933,
                        amount = 1
                    }
                }
            },
            waves = {
                [CURSED_CHESTS_TIER_COMMON] = {
                    { -- Wave 1
                        "Troll",
                        "Orc",
                        "Dwarf"
                    },
                    { -- Wave 2
                        "Amazon",
                        "Nomad",
                        "Valkyrie",
                        "Bandit"
                    },
                    { -- Wave 3
                        "Dwarf Soldier",
                        "Ghoul",
                        "Minotaur Guard",
                        "Smuggler",
                        "Tarantula"
                    },
                    { -- Wave 4
                        "Barbarian Skullhunter",
                        "Wild Warrior",
                        "Terror Bird",
                        "Slime",
                        "Sibang"
                    },
                    { -- Wave 5
                        "Stone Golem",
                        "Leaf Golem",
                        "Frost Giant",
                        "Cyclops",
                        "Insectoid Scout"
                    }
                },
                boss = {
                name = "Ice Golem",
                fightDuration = 90,
                message = "Boss incoming! You have 90 seconds to kill Ice Golem!"
            },
                [CURSED_CHESTS_TIER_RARE] = {
                    { -- Wave 1
                        "Cyclops",
                        "Bonelord",
                        "Insectoid Scout"
                    },
                    { -- Wave 2
                        "Dark Monk",
                        "Dwarf Guard",
                        "Crypt Shambler",
                        "Hunter"
                    },
                    { -- Wave 3
                        "Minotaur Mage",
                        "Terramite",
                        "Crystal Wolf",
                        "Crystalcrusher",
                        "Cyclops Smith"
                    },
                    { -- Wave 4
                        "Demon Skeleton",
                        "Dragon",
                        "Earth Elemental",
                        "Elder Bonelord",
                        "Energy Elemental"
                    },
                    { -- Wave 5
                        "Faun",
                        "Fire Elemental",
                        "Frost Dragon",
                        "Giant Spider",
                        "Grave Guard"
                    }
                },
                boss = {
                name = "Dragon Lord",
                fightDuration = 90,
                message = "Boss incoming! You have 90 seconds to kill Dragon Lord!"
            },
                [CURSED_CHESTS_TIER_EPIC] = {
                    { -- Wave 1
                        "Fire Devil",
                        "Gozzler",
                        "Nightstalker"
                    },
                    { -- Wave 2
                        "Fire Devil",
                        "Gozzler",
                        "Nightstalker",
                        "Diabolic Imp"
                    },
                    { -- Wave 3
                        "Fire Devil",
                        "Gozzler",
                        "Nightstalker",
                        "Diabolic Imp",
                        "Nightmare"
                    },
                    { -- Wave 4
                        "Fire Devil",
                        "Nightstalker",
                        "Diabolic Imp",
                        "Nightmare",
                        "Frazzlemaw"
                    },
                    { -- Wave 5
                        "Hellspawn",
                        "Fury",
                        "Dark Torturer",
                        "Guzzlemaw",
                        "Demon"
                    }
                },
                [CURSED_CHESTS_TIER_LEGENDARY] = {
                    { -- Wave 1
                        "Fire Devil",
                        "Gozzler",
                        "Nightstalker"
                    },
                    { -- Wave 2
                        "Fire Devil",
                        "Gozzler",
                        "Nightstalker",
                        "Diabolic Imp"
                    },
                    { -- Wave 3
                        "Fire Devil",
                        "Gozzler",
                        "Nightstalker",
                        "Diabolic Imp",
                        "Nightmare"
                    },
                    { -- Wave 4
                        "Fire Devil",
                        "Nightstalker",
                        "Diabolic Imp",
                        "Nightmare",
                        "Frazzlemaw"
                    },
                    { -- Wave 5
                        "Hellspawn",
                        "Fury",
                        "Dark Torturer",
                        "Guzzlemaw",
                        "Demon"
                    }
                }
            },
        }
}

CURSED_CHESTS_DATA = {}

function CursedChestsLoad()
    print(">> Loaded Cursed Chests v" .. CURSED_CHESTS_VERSION)
    ShowEffects()
end

function ShowEffects()
    for _, data in ipairs(CURSED_CHESTS_DATA) do
        local tile = Tile(data.pos)
        if tile then
            for _, item in ipairs(tile:getItems()) do
                if item:getId() == data.rarity.item then
                    if data.active == 0 and data.finished == false then
                        data.pos:sendMagicEffect(CONST_ME_YALAHARIGHOST)
                        data.pos:sendAnimatedText(data.rarity.text)
                    elseif data.active == 1 and data.wave > 0 then
                        data.pos:sendMagicEffect(CONST_ME_YALAHARIGHOST)
                        if data.wave <= #data.chest.waves[data.rarity.tier] and not data.bossWave then
                            data.pos:sendAnimatedText(string.format("Wave %d / %d\nMonsters Alive: %d", data.wave, #data.chest.waves[data.rarity.tier], #data.monsters))
                        elseif data.chest.boss ~= nil and data.bossWave == true then
                            data.pos:sendAnimatedText(string.format("Boss Fight\n%s", data.chest.boss.name))
                        end
                    elseif data.finished == true then
                        data.pos:sendMagicEffect(CONST_ME_GIFT_WRAPS)
                        data.pos:sendAnimatedText("Get your reward!")
                    end
                end
            end
        end
    end
    addEvent(ShowEffects, 3000)
end

function CursedChestEvent(data)
    data.wave = data.wave + 1
    local from = Position(data.pos.x - 5, data.pos.y - 5, data.pos.z)
    local to = Position(data.pos.x + 5, data.pos.y + 5, data.pos.z)
    if data.wave <= #data.chest.waves[data.rarity.tier] then
        local mobs = CURSED_CHESTS_TIERS[data.rarity.tier].monstersPerWave * data.wave
        for i = 1, mobs do
            local mobName = data.chest.waves[data.rarity.tier][data.wave][math.random(1, #data.chest.waves[data.rarity.tier][data.wave])]
            local spawnPos = Position(math.random(from.x, to.x), math.random(from.y, to.y), data.pos.z)
            local tile = Tile(spawnPos)
            local spawnTest = 0
            while spawnTest < 100 do
                if data.pos == spawnPos or isBadTile(tile) then
                    spawnPos = Position(math.random(from.x, to.x), math.random(from.y, to.y), data.pos.z)
                    tile = Tile(spawnPos)
                    spawnTest = spawnTest + 1
                else
                    break
                end
            end
                   

            if spawnTest < 100 then
                local mob = Game.createMonster(mobName, spawnPos, false, true)
                if mob then
                    mob:setSkull(CURSED_CHESTS_SKULL_DEFAULT)
                    mob:registerEvent("CursedChestsDeath")
                    table.insert(data.monsters, mob:getId())
                end
            end
        end
    elseif data.chest.boss ~= nil then
        data.bossWave = true
        local spawnPos = Position(math.random(from.x, to.x), math.random(from.y, to.y), data.pos.z)
        local tile = Tile(spawnPos)
        local spawnTest = 0
        while spawnTest < 100 do
            if data.pos == spawnPos or isBadTile(tile) then
                spawnPos = Position(math.random(from.x, to.x), math.random(from.y, to.y), data.pos.z)
                tile = Tile(spawnPos)
                spawnTest = spawnTest + 1
            else
                break
            end
        end

        if spawnTest < 100 then
            local mob = Game.createMonster(data.chest.boss.name, spawnPos, false, true)
            if mob then
                mob:setSkull(CURSED_CHESTS_SKULL_BOSS)
                mob:registerEvent("CursedChestsDeath")
                table.insert(data.monsters, mob:getId())
                stopEvent(data.event)
                data.event = addEvent(CursedChestBoss, data.chest.boss.fightDuration * 1000, data)
            end
        end
    end
end

function CursedChestBoss(data)
    if #data.monsters == 1 then
        local boss = Monster(data.monsters[1])
        if boss then
            boss:remove()
            stopEvent(data.event)
            for i = 1, #CURSED_CHESTS_DATA do
                if CURSED_CHESTS_DATA[i] == data then table.remove(CURSED_CHESTS_DATA, i) end
            end
            data.container:getPosition():sendMagicEffect(CONST_ME_POFF)
            data.container:remove()
            CURSED_CHESTS_SPAWNS[data.spawnId].spawned = false
            data.pos:sendAnimatedText("Boss fight is over! You failed!")
        end
    end
end

function FinishCursedChestEvent(data)
    if data.chest.boss ~= nil and data.bossWave == true and #data.monsters == 0 or not data.chest.boss and data.wave == #data.chest.waves[data.rarity.tier] and #data.monsters == 0 then
        stopEvent(data.event)
        data.finished = true
        data.active = 0
        local loot = "Cursed Chest reward: "
        local items = {}

        for i = 1, #data.chest.rewards[data.rarity.tier] do
            if data.container:getEmptySlots() == 0 then break end

            local reward = data.chest.rewards[data.rarity.tier][i]
            if reward.chance == 100 then
                local amount = reward.random == true and math.random(1, reward.amount) or reward.amount
                local item = Game.createItem(reward.item, amount)
                data.container:addItemEx(item)
                table.insert(items, item)
            elseif math.random(1, 100) <= reward.chance then
                local amount = reward.random == true and math.random(1, reward.amount) or reward.amount
                local item = Game.createItem(reward.item, amount)
                data.container:addItemEx(item)
                table.insert(items, item)
            end
        end

        for i = #items, 1, -1 do
            if items[i]:getCount() > 1 then
                loot = loot .. items[i]:getCount() .. " "
                loot = loot .. items[i]:getPluralName()
            else
                loot = loot .. items[i]:getName()
            end
            if i > 1 then loot = loot .. ", " end
        end

        loot = loot .. "."

        local specs = Game.getSpectators(data.pos, false, true, 9, 9, 9, 9)
    if #specs > 0 then
        for i = 1, #specs do
            specs[i]:sendTextMessage(MESSAGE_STATUS_WARNING, loot)
        end
        end
       
        data.checks = 0
        data.event = addEvent(CursedChestCheck, 1000, data)
    end
end

function CursedChestCheck(data)
    data.event = addEvent(CursedChestCheck, 1000, data)
    addEvent(CursedChestDelete, 5 * 60 * 1000, data)
    if data.container:getEmptySlots() == data.container:getCapacity() then
        stopEvent(data.event)
        for i = 1, #CURSED_CHESTS_DATA do
            if CURSED_CHESTS_DATA[i] == data then table.remove(CURSED_CHESTS_DATA, i) end
        end
        data.container:getPosition():sendMagicEffect(CONST_ME_POFF)
        data.container:remove()
        CURSED_CHESTS_SPAWNS[data.spawnId].spawned = false
    end
end

function CursedChestDelete(data)
    for i = 1, #CURSED_CHESTS_DATA do
        if CURSED_CHESTS_DATA[i] == data then
            stopEvent(data.event)
            data.container:getPosition():sendMagicEffect(CONST_ME_POFF)
            data.container:remove()
            CURSED_CHESTS_SPAWNS[data.spawnId].spawned = false
            table.remove(CURSED_CHESTS_DATA, i)
        end
    end
end

function CursedChests_onDeath(creature, corpse, killer, mostDamageKiller, unjustified, mostDamageUnjustified)
    for _, data in ipairs(CURSED_CHESTS_DATA) do
        if data.active == 1 then
            for i = 1, #data.monsters do
                if data.monsters[i] == creature:getId() then
                    table.remove(data.monsters, i)
                    if data.wave < #data.chest.waves[data.rarity.tier] and #data.monsters == 0 then
                        addEvent(CursedChestEvent, 1500, data)
                    elseif data.chest.boss ~= nil and not data.bossWave and #data.monsters == 0 then
                        killer:getPosition():sendAnimatedText(data.chest.boss.message)
                        addEvent(CursedChestEvent, 3000, data)
                    end
                    if data.wave == #data.chest.waves[data.rarity.tier] and #data.monsters == 0 or data.bossWave == true and #data.monsters == 0 then FinishCursedChestEvent(data) end
                    break
                end
            end
        end
    end
    return true
end

function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    for _, data in ipairs(CURSED_CHESTS_DATA) do
        if data.pos == item:getPosition() then
            if data.active == 0 and data.finished == false then
                player:getPosition():sendAnimatedText(data.chest.message .. "\nKill all monsters to get awesome rewards!")
                if player:getParty() then
                    data.solo = false
                else
                    data.solo = true
                end
                data.owner = player:getName()
                data.wave = 0
                data.monsters = {}
                data.active = 1
                data.finished = false
                data.container = item
                data.event = addEvent(CursedChestEvent, 2000, data)
            elseif data.finished == true then
                if data.solo and data.owner == player:getName() then
                    return false
                elseif not data.solo then
                    local party = player:getParty()
                    if not party then return true end
                    if data.owner == player:getName() then return false end
                    local members = party:getMembers()
                    for i = 1, #members do
                        if members[i]:getName() == player:getName() then
                            return false
                        end
                    end
                end
                return true
            end
            return true
        end
    end
    return false
end

function isBadTile(tile)
    return (tile == nil or tile:getGround() == nil or tile:hasProperty(TILESTATE_NONE) or tile:hasProperty(TILESTATE_FLOORCHANGE_EAST) or isItem(tile:getThing()) and not isMoveable(tile:getThing()) or tile:getTopCreature() or tile:hasFlag(TILESTATE_PROTECTIONZONE))
end

what did i do worng?

did i place this line in the worng place?

boss = { name = "Dragon Lord", fightDuration = 90, message = "Boss incoming! You have 90 seconds to kill Dragon Lord!" },
No, you can't do that.
 
Back
Top