• 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 [TFS 0.X] Ultimate Survival MOD - Monster waves event

potinho

Advanced OT User
Joined
Oct 11, 2009
Messages
1,458
Solutions
17
Reaction score
175
Location
Brazil
Hello guys, i'm trying to use this MOD in my server but i cant make it work totally. Sometimes i cant advance to next wave, sometimes i advance to next wave but the reward from previous wave its not delivered to player. And now i get this error at each killed monster. Can u guys help me to fix and improve code?

2024-11-16 10:29:32 - :onKill
2024-11-16 10:29:32 - Description:
2024-11-16 10:29:32 - [string "LuaInterface::loadBuffer"]:4: attempt to get length of a number value
2024-11-16 10:29:32 - stack traceback:
2024-11-16 10:29:32 - [string "LuaInterface::loadBuffer"]:4: in function <[string "LuaInterface::loadBuffer"]:2>

LUA:
<?xml version="1.0" encoding="UTF-8"?>
 
<mod name="Ultimate Survival" version="1.0" author="Omega" enabled="yes">
<config name="ultimatelib"><![CDATA[
USurvival = {
    posi = {x = 382, y = 1283, z = 7},
    posf = {x = 409, y = 1298, z = 7},
    posc = {x = 395, y = 1291, z = 7},
    
  waves = {
        [1] = {monsters = {'dragon'}, count = 10, reward = {exp = 0, item = 6065, amount = 1, money = 10000}},
        [2] = {monsters = {'dragon lord'}, count = 20, reward = {exp = 0, item = 6065, amount = 2, money = 10000}},
        [3] = {monsters = {'hydra', 'dragon lord'}, count = 30, reward = {exp = 0, item = 6065, amount = 3, money = 10000}},
        [4] = {monsters = {'behemoth'}, count = 20, reward = {exp = 0, item = 6065, amount = 4, money = 10000}},
        [5] = {monsters = {'behemoth', 'warlock'}, count = 30, reward = {exp = 0, item = 6065, amount = 5, money = 20000}},
        [6] = {monsters = {'warlock', 'demon'}, count = 30, reward = {exp = 0, item = 6065, amount = 6, money = 20000}},
        [7] = {monsters = {'undead dragon', 'demon'}, count = 30, reward = {exp = 0, item = 6065, amount = 7, money = 20000}},
        [8] = {monsters = {'war golem', 'undead dragon'}, count = 30, reward = {exp = 0, item = 6065, amount = 8, money = 30000}},
        [9] = {monsters = {'war golem', 'juggernaut'}, count = 30, reward = {exp = 0, item = 6065, amount = 9, money = 30000}},
        [10] = {monsters = {'juggernaut', 'royal guards'}, count = 30, reward = {exp = 0, item = 6065, amount =109, money = 30000}},
        [11] = {monsters = {'orshabaal', 'royal guards'}, count = 30, reward = {exp = 0, item = 6065, amount = 11, money = 40000}},
        [12] = {monsters = {'orshabaal', 'perfect troll'}, count = 30, reward = {exp = 0, item = 6065, amount = 12, money = 40000}},
        [13] = {monsters = {'perfect troll', 'undead plague'}, count = 30, reward = {exp = 0, item = 6065, amount = 13, money = 50000}},
        [14] = {monsters = {'undead plague', 'stone angel'}, count = 30, reward = {exp = 0, item = 6065, amount = 14, money = 50000}},
        [15] = {monsters = {'ferumbras'}, count = 10, reward = {exp = 0, item = 6065, amount = 15, money = 100000}},
    },
    exhaust = 1 * 24 * 60 * 60,
    final_reward = {item = 6065, amount = 5, exp = 10000, money = 10000},
    
    storage_ex = 607069,
    storage_wave = 607089,
}

local function isWalkable(pos)
    if getTileThingByPos({x = pos.x, y = pos.y, z = pos.z, stackpos = 0}).itemid == 0 then
        return false
    elseif isCreature(getTopCreature(pos).uid) then
        return false
    elseif getTileInfo(pos).protection then
        return false
    elseif hasProperty(getThingFromPos(pos).uid, 3) or hasProperty(getThingFromPos(pos).uid, 7) then
        return false
    end
    return true
end

local function doSpawnMonsters(monsters, pos, radius, limit)
    if not pos.x or not pos.y or not pos.z or type(monsters) ~= 'table' then
        return false
    end
    radius = math.max(2, math.min(radius, 5))
    limit = math.max(1, math.min(limit, math.floor((radius * 1.5) ^ 2)))

    local k = 0
    for tries = 1, 100 do
        for x = pos.x - radius, pos.x + radius do
            for y = pos.y - radius, pos.y + radius do
                if isWalkable({x=x, y=y, z=pos.z}) then
                    local monster = monsters[math.random(1, #monsters)]
                    if k < limit and math.random(1, 100) <= 8 then
                        if doCreateMonster(monster, {x=x, y=y, z=pos.z}) then
                            k = k + 1
                        end
                    end
                    if k >= limit then
                        break
                    end
                end
            end
            if k >= limit then
                break
            end
        end
        if k >= limit then
            break
        end
    end
    return k >= limit
end

local function getPlayersInArea(pos1, pos2)
    local players = {}
    if pos1.z == pos2.z then
        for a = pos1.x, pos2.x do
            for b = pos1.y, pos2.y do
                local pos = {x=a, y=b, z=pos1.z}
                local creature = getTopCreature(pos).uid
                if isPlayer(creature) then
                    table.insert(players, creature)
                end
            end
        end
    end
    return players
end

local function getMonstersInArea(pos1, pos2)
    local monsters = {}
    if pos1.z == pos2.z then
        for a = pos1.x, pos2.x do
            for b = pos1.y, pos2.y do
                local pos = {x=a, y=b, z=pos1.z}
                local creature = getTopCreature(pos).uid
                if isMonster(creature) then
                    table.insert(monsters, creature)
                end
            end
        end
    end
    return monsters
end

local function doCleanArena()
    local monsters = getMonstersInArea(USurvival.posi, USurvival.posf)
    for _, cid in pairs(monsters) do
        doRemoveCreature(cid)
    end
end

local function doStartWave(waveID, cid)
    if isCreature(cid) and USurvival.waves[waveID] then
        local wave = USurvival.waves[waveID]
        doSpawnMonsters(wave.monsters, USurvival.posc, 5, wave.count)
        doPlayerSendTextMessage(cid, 21, 'Wave ' .. waveID .. ' has started! FIGHT!')
    end
end
]]></config>

<action actionid="4599" event="script" override="yes"><![CDATA[
domodlib('ultimatelib')
function onUse(cid, item)
    if getPlayerStorageValue(cid, USurvival.storage_ex) <= os.time() then
        if #getPlayersInArea(USurvival.posi, USurvival.posf) == 0 then
            doCleanArena()
            doTeleportThing(cid, USurvival.posc)
            doPlayerSendTextMessage(cid, 21, 'The Ultimate Survival will Start in 10 seconds! Be ready to face your destiny!')
            addEvent(doStartWave, 10000, 1, cid)
            setPlayerStorageValue(cid, USurvival.storage_wave, 1)
            setPlayerStorageValue(cid, USurvival.storage_ex, os.time() + USurvival.exhaust)
            doTransformItem(item.uid, item.itemid % 2 == 1 and item.itemid + 1 or item.itemid - 1)
        else
            doPlayerSendCancel(cid, 'Someone is already in the arena.')
            doSendMagicEffect(getThingPos(cid), 2)
        end
    else
        local left = getPlayerStorageValue(cid, USurvival.storage_ex) - os.time()
        doPlayerSendCancel(cid, string.format('You have to wait %dh and %dmin.', math.floor(left/3600), math.ceil((left % 3600)/60)))
        doSendMagicEffect(getThingPos(cid), 2)
    end
    return true
end
]]></action>

<event type="login" name="US Login" event="script"><![CDATA[
domodlib('ultimatelib')
function onLogin(cid)
    registerCreatureEvent(cid, 'UltimateSurvival1')
    registerCreatureEvent(cid, 'UltimateSurvival2')
    if isInArea(getThingPos(cid), USurvival.posi, USurvival.posf) then
        doTeleportThing(cid, getTownTemplePosition(getPlayerTown(cid)))
        doSendMagicEffect(getThingPos(cid), 10)
    end
    return true
end
]]></event>

<event type="kill" name="UltimateSurvival1" event="script"><![CDATA[
domodlib('ultimatelib')
function onKill(cid, target)
    if isInArea(getThingPos(cid), USurvival.posi, USurvival.posf) then
        if #getMonstersInArea(USurvival.posi, USurvival.posf) == 1 then
            local wave = getPlayerStorageValue(cid, USurvival.storage_wave)
            if USurvival.waves[wave + 1] then
                setPlayerStorageValue(cid, USurvival.storage_wave, wave + 1)
                addEvent(doStartWave, 5000, wave + 1, cid)
                doPlayerSendTextMessage(cid, 22, 'Congratulations! Next wave will start in 5 seconds!')
            else
                doPlayerSendTextMessage(cid, 22, 'CONGRATULATIONS! YOU HAVE BEATEN THE ULTIMATE SURVIVAL!')
                local reward = USurvival.final_reward
                if reward.item then
                    doPlayerAddItem(cid, reward.item, reward.amount or 1, false)
                end
                if reward.exp then
                    doPlayerAddExp(cid, reward.exp)
                end
                if reward.money then
                    doPlayerAddMoney(cid, reward.money)
                end
                local medal = doPlayerAddItem(cid, 5217, 1, false)
                if medal then
                    doItemSetAttribute(medal, 'description', 'This was awarded to ' .. getCreatureName(cid) .. ' for completing the Ultimate Survival Arena.')
                end
                doTeleportThing(cid, getTownTemplePosition(getPlayerTown(cid)))
            end
        end
    end
    return true
end
]]></event>
</mod>
 
Back
Top