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

Monster "Artificial Inteligence" (Behavior)

Mkalo

ボーカロイド
Senator
Joined
Jun 1, 2011
Messages
1,118
Solutions
55
Reaction score
946
Location
Japan
For TFS 1.2, however you could easily convert it to any TFS.

Demo:
(I know the quality/fps is shitty, deal with it)

I know its not AI. Its just a set behavior but whatever I wanna call it AI, because its click-baity.

You can basically do any behavior you want pretty easy, I did only 2 for demonstration. (an easy one and a hard one)

Do a lib file or whatever put it in global.lua, I'm not going to put instructions for how to add a lib here is the code:

Code:
CREATURE_SAVE = {}
SUMMON_SAVE = {}
CREATURE_BEHAVIOR = {}
saveId = 1

-- Behavior functions ALWAYS have configid and monster as first parameters.
function doSplit(configid, monster, summon, amount, radiusx, radiusy)
    if monster and monster:isMonster() then
        local pos = monster:getPosition()
        local sumcount = 0
        for i = 1, amount do
            local monster = Game.createMonster(summon, Position(math.random(pos.x-radiusx, pos.x+radiusx), math.random(pos.y-radiusy, pos.y+radiusy), pos.z), true, true)
            if monster then
                monster:registerEvent("SummonDeath")
                SUMMON_SAVE[monster:getId()] = saveId
                sumcount = sumcount + 1
            end
        end
        CREATURE_BEHAVIOR[monster:getId()] = nil
        CREATURE_SAVE[saveId] = {configid, monster:getName(), monster:getHealth(), pos, sumcount}
        saveId = saveId+1
        monster:remove()
    end
end

function fullHeal(configid, monster)
    if monster and monster:isMonster() then
        monster:addHealth(monster:getMaxHealth()-monster:getHealth())
        CREATURE_BEHAVIOR[monster:getId()] = configid+1
    end
end

Now to the creaturescripts, 2 event "death" named "SummonDeath" and "CleanBehavior". If you don't know how to install the tags, research it.

sumdeath.lua: (SummonDeath)
Code:
function onDeath(creature, corpse, killer, mostDamage, unjustified, mostDamage_unjustified)
    if creature:isMonster() and SUMMON_SAVE then
        local saveId = SUMMON_SAVE[creature:getId()]
        if saveId then
            local save = CREATURE_SAVE[saveId]
            if save then
                save[6] = save[6] and save[6]+1 or 1
                if save[6] >= save[5] then
                    local monster = Game.createMonster(save[2], save[4], false, true)
                    if monster then
                        CREATURE_BEHAVIOR[monster:getId()] = save[1]+1
                        monster:addHealth(save[3]-monster:getHealth())
                    end
                    CREATURE_SAVE[saveId] = nil
                end
                SUMMON_SAVE[creature:getId()] = nil
            end
        end
    end
    return true
end

cleanbehavior.lua: (CleanBehavior)
Code:
function onDeath(creature, corpse, killer, mostDamage, unjustified, mostDamage_unjustified)
    if creature:isMonster() and CREATURE_BEHAVIOR then
        CREATURE_BEHAVIOR[creature:getId()] = nil
    end
    return true
end

Now to the monster script. You set the script here:
Code:
<monster name="Rat Master" nameDescription="a rat master" race="blood" experience="50000" speed="210" manacost="0" script="ratAI.lua">

Create folder "scripts" inside data\monster. (TFS doesn't come with it, the fuck.)

ratAI.lua:
Code:
-- Monster behavior depending on % of life.
local config = {
    [1] = {life = 80, func = doSplit, params = {"Rat", 10, 3, 3}},
    [2] = {life = 50, func = doSplit, params = {"Cave Rat", 10, 3, 3}},
    [3] = {life = 20, func = fullHeal, params = {}},
}

function onCreatureAppear(self, creature)
    self:registerEvent("CleanBehavior")
end

function onThink(self, interval)
    local configId = CREATURE_BEHAVIOR[self:getId()] or 1
    if configId and config[configId] then
        if (self:getHealth() / self:getMaxHealth())*100 <= config[configId].life then
            config[configId].func(configId, self, unpack(config[configId].params))
        end
    end
    return false
end

With this is up to you to make new functions and use them correctly to set the behavior id. This example will do as in the video and will fullHeal in 20% (this was not in the video I made after to show an easier function).

OBS: If the monster dies too quickly or 1 hit, it wont execute anything obviously because its an onThink.

If you have any nice idea to add as a behavior, ask for it and I might do it ( please if its easy shit try to do it yourself first.)

Cya.
 
Last edited:
Nice, really like the idea. But just a tip, onCreatureAppear gets executed everytime a creature appears in the screen. So you should make check, just make sure it will execute once when the creature appear:
Code:
if self == creature then

Else great job :p
 
Nice, really like the idea. But just a tip, onCreatureAppear gets executed everytime a creature appears in the screen. So you should make check, just make sure it will execute once when the creature appear:
Code:
if self == creature then

Else great job :p
I did it at the beginning, but then I tested it and it does not register if the creature is spawned in the map (the first time). So i let it like this so it will register when some player appears in the screen.
 
Yes, removing that if would fix the issue. But I think its intentional and the self firing the onCreatureAppear is actually the bug. The creature shouldn't appear for itself, I guess.
Well i have no idea, since the issue has not been answered. I'll keep an eye open :p
 
Back
Top