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

GlobalEvent [1.3] Metin Stone Event - Full auto

Perun

nems.online
Joined
May 1, 2009
Messages
378
Solutions
7
Reaction score
176
Hello, here is full auto %hp based metin stone event.
Config is easy, probably no bugs, but if you find any msg me so i can fix :)

SRHvZg8.jpg

37085
Im using @Stigma monster storage from this post. So if you don't have this in your engine just add.

1. Create file metin.lua in data/lib/
2. Add this in lib.lua
Lua:
--Metin lib
dofile('data/lib/metin.lua')
3. Add this in metin.lua and look at config.
Lua:
if not Metin then
    Metin = {}
    --About drop, it's easy to add dropLoot func here, but easier just put loot to boss, in this example it's Dragon Lord and Demon
    --And set monster speed to 0 in script if you want to boss stay on 1 sqm.
    Metin.cfg = {
        indexStorage = 26000, --cfg cuz maybe in future ill add some things there
        stonesIndexStorage = 26001,

        maxStonesPerServer = 2, --how many metin stones can be spawned on map
    }

    Metin.cfg.spawns = { --metin spawn positions
        {x = 1019, y = 1012, z = 7},
        {x = 1026, y = 1012, z = 7},
        {x = 1033, y = 1012, z = 7}
    }

    Metin.stones = {
        ['Orc'] = { --just one monster with same name can be in table, i could add index to fix that but im not sure if someone want multiple summons config for same monster
            {percentHealth = 81, monsters = {"Orc", "Orc", "Orc"}}, --from biggest to lowest hp %
            {percentHealth = 80, monsters = {"Orc Warrior", "Orc", "Orc Warrior"}},
            {percentHealth = 70, monsters = {"Orc Spearman", "Orc Rider", "Orc Rider"}},
            {percentHealth = 60, monsters = {"Orc Maruder", "Orc Shaman", "Orc Shaman"}},
            {percentHealth = 25, monsters = {"Orc Warlord", "Orc Warlord", "Orc Warlord"}},
        },
        ['Demon'] = {
            {percentHealth = 90, monsters = {"Fire Devil", "Fire Devil"}}, --from biggest to lowest hp %
            {percentHealth = 55, monsters = {"Diabolic Imp", "Fire Devil", "Fire Devil"}},
            {percentHealth = 34, monsters = {"Warlock", "Fire Devil", "Fire Devil"}},
            {percentHealth = 25, monsters = {"Infernalist", "Infernalist", "Infernalist"}},
        }
    }

    function Metin.getRandomSpawn()
        local freeSpawns = {}
        for i = 1, #Metin.cfg.spawns do
            local t = Tile(Metin.cfg.spawns[i])
            if t ~= nil then
                local creaturesOnTile = t:getCreatures()
                if(creaturesOnTile and #t:getCreatures() == 0) then --Delete this if you want to avoid spawn block (almost impossible to block all if have a lot of spawns)
                    table.insert(freeSpawns, Metin.cfg.spawns[i])
                end
            end
        end

        if(#freeSpawns > 0) then
            return freeSpawns[math.random(1, #freeSpawns)]
        end
        return false
    end

    function Metin.spawnOperator()
        local spawnedStones = Game.getStorageValue(Metin.cfg.stonesIndexStorage)
        if(spawnedStones < Metin.cfg.maxStonesPerServer) then
           
            local spawnPoint = Metin.getRandomSpawn()
       
            if(spawnPoint) then
                local monster = Game.createMonster(Metin.cache.allStones[math.random(1, #Metin.cache.allStones)], spawnPoint, true)
                monster:registerEvent("MetinHealthChange")
                monster:registerEvent("MetinDeath")
                Metin.setIndex(monster, 1)
                broadcastMessage("Metin stone spawned somewhere on map.", MESSAGE_STATUS_WARNING)
                Game.setStorageValue(Metin.cfg.stonesIndexStorage, (spawnedStones + 1))
            end
        end
    end
   

    Metin.cache = {
        allStones = {}, --stonename
        stoneCfg = {},--['stonename'] = {monstersTableSize = x, healthChangesOnPercents = {x,y,z,v,q,w..}}
        pholder = {
            monstersTableSize = 0,
            healthChangesOnPercents = {}
        }
    }
    --cache loader
        for k,v in pairs(Metin.stones) do
            table.insert(Metin.cache.allStones, k)

            Metin.cache.stoneCfg[k] = {}        
           
            table.insert(Metin.cache.stoneCfg[k], Metin.cache.pholder)
            Metin.cache.stoneCfg[k].monstersTableSize = #v
            Metin.cache.stoneCfg[k].healthChangesOnPercents = {}

            for tableEntry,mobCfg in pairs(v) do
                table.insert(Metin.cache.stoneCfg[k].healthChangesOnPercents, mobCfg.percentHealth)
            end
        end

    if(Game.getStorageValue(Metin.cfg.stonesIndexStorage) == nil) then
        Game.setStorageValue(Metin.cfg.stonesIndexStorage, 0)
    end
    --end

    function Metin.getNewHealth(monster, damage)
        if(monster:getHealth() == 0) then return false end
        local MetinIndex = Metin.getIndex(monster)
        if(MetinIndex and MetinIndex ~= -1) then --verify if monster is metin
            local metinCfg = Metin.cache.stoneCfg[monster:getName()]
            if(not metinCfg) then return print("Metin Stone error. Wrong monster name in config.") and true end

            if(metinCfg.healthChangesOnPercents[MetinIndex] == nil) then return 0 end --monster die
            local maxRetHealth = (metinCfg.healthChangesOnPercents[MetinIndex] * monster:getMaxHealth()) / 100
            local normalDamage = monster:getHealth() - damage
            if(normalDamage > maxRetHealth) then
                return normalDamage
            else
                local monsters = Metin.stones[monster:getName()][MetinIndex].monsters
                for i = 1, #monsters do
                    local summon = Game.createMonster(monsters[i], monster:getPosition(), true)
                    monster:addSummon(summon)                  
                end
                Metin.setIndex(monster, (MetinIndex + 1))          
                return maxRetHealth
            end        
        end
        return monster:getMaxHealth() --return max if not metin, can add error bud idk if someone need
    end

    function Metin.getIndex(monster)
        return monster:getStorageValue(Metin.cfg.indexStorage)
    end

    function Metin.setIndex(monster, newIndex)
        return monster:setStorageValue(Metin.cfg.indexStorage, newIndex)
    end
end
3. Add this in data/creaturescripts/creaturescripts.xml
XML:
<!-- Metin Stones -->
    <event type="healthchange" name="MetinHealthChange" script="metin/metinhealth.lua" />
    <event type="death" name="MetinDeath" script="metin/metinDeath.lua" />

4. Create folder metin in data/creaturescripts/scripts
5. Create file metinDeath.lua in data/creaturescripts/scripts/metin with this:
Lua:
function onDeath(monster)
    local spawnedStones = Game.getStorageValue(Metin.cfg.stonesIndexStorage)
    Game.setStorageValue(Metin.cfg.stonesIndexStorage, (spawnedStones - 1))
    local txt = "Metin stone was defeated. "
    if((spawnedStones - 1) > 0) then
        txt = txt.."But still you can find "..(spawnedStones - 1).."x metin stone on map."
    end
    broadcastMessage(txt, MESSAGE_STATUS_WARNING)  
end
6. Create file metinhealth.lua in data/creaturescripts/scripts/metin with this:
Lua:
function onHealthChange(creature, attacker, damage)
    if(#creature:getSummons() > 0) then
        return true
    end

    local newHealth = Metin.getNewHealth(creature, damage)
    if(newHealth and creature:getId()) then
        local monster = creature;      
        local mHealth = monster:getHealth()
        local fixedDamage = mHealth-newHealth

        local metinCfg = Metin.cache.stoneCfg[monster:getName()]
        local m_index = Metin.getIndex(monster);
        if(monster:getHealth() - fixedDamage <= 0 and m_index <= #metinCfg.healthChangesOnPercents) then
            fixedDamage = 0
        end
        monster:getPosition():sendMagicEffect(5) --just effect, delete if you want
       
        if(monster:getHealth() - fixedDamage <= 0 and m_index > #metinCfg.healthChangesOnPercents) then    
            if(#creature:getSummons() > 0) then --Second check cuz when mob have very low maxHealth there is bug sometimes.
                return true
            end    
        end
        monster:addHealth(-fixedDamage)
    end  
    return true
end

Now you can use function
Lua:
Metin.spawnOperator()
to spawn metin in random position. You can put it as your command, action script or globalevent. I.e:
data/globalevents/globalevents.xml
XML:
<globalevent name="Metin Spawn" time="10:55:00" script="metinspawn.lua" />
data/globalevents/scripts/metinspawn.lua
Lua:
function onTime(interval)
    Metin.spawnOperator()
end

Im just learning new tfs [1+] so it's not perfect, cuz i don't know most functions, in older tfs everything was diffrent but if you have any advices feel free to msg :)
Look here if you need any FREE scripts:
 
Last edited:
So, you wrote dofile in data/lib, but you put the actual lib in main directory?
I've always had this problem, when I try to add a "dofile('data/")" to libs.lua. It happened to me with another event.
37103
37104
 
Last edited:
Nice release!
Since it's for 1.3 I'd recommend using the newly implemented revscriptsys.
That way you can have everything in 1 file. Easier to install & more organized.
 
Aight, so it's just a target dummy that spawns waves and waves of crap as the HP % goes down.

That's pretty cool, I like it.
 
Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/metin/metinhealth.lua:eek:nHealthChange
data/lib/metin.lua:118: attempt to call method 'getStorageValue' (a nil value)

TFS 1.3
 
[Warning - Monster::Monster] Unknown event name: StonesThink_Event
[Warning - Monster::Monster] Unknown event name: StonesDeath_Event
[Warning - Monster::Monster] Unknown event name: StonesStatsChange_Event
tfs 1.2
Post automatically merged:

Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/metin/metinhealth.lua:eek:nHealthChange
data/lib/metin.lua:122: attempt to call method 'getStorageValue' (a nil value)
Post automatically merged:

attempt to call method 'addSummon' (a nil value)
Post automatically merged:

metin can't get lower than 81% hp, he is healing by script wow
 
Last edited:
[Warning - Monster::Monster] Unknown event name: StonesThink_Event
[Warning - Monster::Monster] Unknown event name: StonesDeath_Event
[Warning - Monster::Monster] Unknown event name: StonesStatsChange_Event
tfs 1.2
Post automatically merged:

Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/metin/metinhealth.lua:eek:nHealthChange
data/lib/metin.lua:122: attempt to call method 'getStorageValue' (a nil value)
Post automatically merged:

attempt to call method 'addSummon' (a nil value)
Post automatically merged:

metin can't get lower than 81% hp, he is healing by script wow
This script dont work correctly in TFS 1.3, and less in TFS 1.2.
Code:
[Warning - Monster::Monster] Unknown event name: StonesThink_Event
monsters is trying to find script with that name "StonesThink_Event" and doesnt exist.
 
Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/metin/metinhealth.lua:eek:nHealthChange
data/lib/metin.lua:122: attempt to call method 'getStorageValue' (a nil value)
How fix this error?
 
Lua Script Error: [CreatureScript Interface]
data/creaturescripts/scripts/metin/metinhealth.lua:eek:nHealthChange
data/lib/metin.lua:122: attempt to call method 'getStorageValue' (a nil value)
How fix this error?

Go to line 122 and fix the null reference.
 
Back
Top