• 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.4] Spell: Empower Summons (Monster AI)

Znote

<?php echo $title; ?>
Staff member
Global Moderator
Premium User
Joined
Feb 14, 2008
Messages
7,030
Solutions
256
Reaction score
2,115
Location
Norway
GitHub
Znote
Created a spell that makes your summons more interesting to play with.

From the AcidsOT advertisement thread:
Changelog: 13 October 2021
  • New spell for Elder Druids: Empower Summons: utevo gran res
    • Required level 70, costs 1800 mana.
    • Your summons gain +800 max health.
    • Your summons gain extra spells: (spell formula based on the master's skills)
      • Light healing (exura) if summon is below 65% hp.
      • Heal master (exura sio "master") if master is below 65% hp.
      • Challenge creature (exori res) if the monster has attack on master.
      • Death strike (exori mort) on target


utevogranres1.gif

utevogranres2.gif

Create file in data/scripts/ folder, like empowermonster.lua and put this in:
Lua:
-- Player spell (utevo gran res) that empowers summons
upgradedSummons = {}
local empower = Spell(SPELL_INSTANT)
empower:name("Empower Summons")
empower:words("utevo gran res")
empower:group("support")
empower:cooldown(2000)
empower:level(70)
empower:mana(1800)
empower:isAggressive(false)
empower:vocation("Elder Druid")

function empower.onCastSpell(creature, variant)
    local summons = creature:getSummons()

    if #summons == 0 then
        creature:sendCancelMessage("Found no summons to empower.")
        creature:getPosition():sendMagicEffect(CONST_ME_POFF)
        return false
    end

    local upgraded = {}
    local pid_str = ""..creature:getGuid()

    if upgradedSummons[pid_str] == nil then
        upgradedSummons[pid_str] = {}
    end

    local upgrades = 0

    for _, summon in ipairs(summons) do
        local summonId_str = ""..summon:getId()
        local alreadyUpgraded = false

        -- Empower summon if it isn't already empowered
        if upgradedSummons[pid_str][summonId_str] == nil then
            local now = os.mtime()
            upgradedSummons[pid_str][summonId_str] = {
                ["heal"] = now,
                ["challenge"] = now,
                ["attack"] = now,
                ["action"] = now
            }
            upgrades = upgrades + 1
            summon:say("Brwuaaah!")
            summon:setMaxHealth(summon:getMaxHealth() + 800)
            summon:getPosition():sendMagicEffect(CONST_ME_MAGIC_RED)
            summon:registerEvent("empoweredBrain")
        end
    end

    if upgrades == 0 then
        creature:sendCancelMessage("All summons are already empowered.")
        creature:getPosition():sendMagicEffect(CONST_ME_POFF)
        return false
    end

    return true
end
empower:register()

-- Healing (exura, exura sio "master") combat ability formula
local healing = Combat()
healing:setParameter(COMBAT_PARAM_TYPE, COMBAT_HEALING)
healing:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_BLUE)
healing:setParameter(COMBAT_PARAM_AGGRESSIVE, false)
function onGetFormulaValuesHeal(player, level, magicLevel)
    local min = (level / 5) + (magicLevel * 1.4) + 8
    local max = (level / 5) + (magicLevel * 1.8) + 11
    return min, max
end
healing:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValuesHeal")

-- Attacking (exori mort) combat ability formula
local attacking = Combat()
attacking:setParameter(COMBAT_PARAM_TYPE, COMBAT_DEATHDAMAGE)
attacking:setParameter(COMBAT_PARAM_EFFECT, CONST_ME_MORTAREA)
function onGetFormulaValues(player, level, magicLevel)
    local min = (level / 5) + (magicLevel * 0.8) + 5
    local max = (level / 5) + (magicLevel * 2) + 12
    return -min, -max
end
attacking:setCallback(CALLBACK_PARAM_LEVELMAGICVALUE, "onGetFormulaValues")

local function teleportSummon(summon, position)
    local tile = Tile(position)
    if tile
    and tile:isWalkable()
    and not tile:hasFlag(TILESTATE_PROTECTIONZONE)
    and not tile:hasFlag(TILESTATE_TELEPORT)
    and not tile:getTopCreature() then
        summon:teleportTo(position)
        position:sendMagicEffect(CONST_ME_TELEPORT)
        return true
    end
    return false
end

-- Summon AI code
local empoweredBrain = CreatureEvent("empoweredBrain")
function empoweredBrain.onThink(summon)
    local master = summon:getMaster()
    local pid_str = ""..master:getGuid()
    local summonId_str = ""..summon:getId()
    local now = os.mtime()

    local summonPos = summon:getPosition()
    local masterPos = master:getPosition()

 
    -- If you are > 9 sqm away from master, try teleport somewhere in his behind vicinity
    if not masterPos:isInRange(
        Position(summonPos.x-9,summonPos.y-9,summonPos.z), Position(summonPos.x+9,summonPos.y+9,summonPos.z)
    ) then
        local masterDirection = master:getDirection()
        for i = -2, 1, 1 do
            -- Center
            local centerBehindPos = Position(masterPos)
            centerBehindPos:getNextPosition(masterDirection, i)
            if teleportSummon(summon, centerBehindPos) then return true end

            -- Adjacent to center
            local adjacent1 = Position(centerBehindPos)
            adjacent1:getNextPosition((masterDirection + 1) % 4, 1)
            if teleportSummon(summon, adjacent1) then return true end
         
            -- Opposite Adjacent to center
            local adjacent2 = Position(centerBehindPos)
            adjacent2:getNextPosition((masterDirection + 3) % 4, 1)
            if teleportSummon(summon, adjacent2) then return true end
        end
        return false
    end


    -- At least 2 seconds cooldown between any spell action
    local lastAction = upgradedSummons[pid_str][summonId_str]["action"]
    if now - lastAction < 2000 then
        return false
    end


    -- Heal master with 8 seconds cooldown
    local lastHeal = upgradedSummons[pid_str][summonId_str]["heal"]
    if now - lastHeal >= 8000
    and master:getHealth() <= master:getMaxHealth() * 0.65
    and summonPos:isSightClear(masterPos, true) then

        upgradedSummons[pid_str][summonId_str]["action"] = now
        upgradedSummons[pid_str][summonId_str]["heal"] = now
        masterPos:sendMagicEffect(CONST_ME_MAGIC_GREEN)
        summon:say('exura sio "'..master:getName()..'"')
        healing:execute(master, {
            ["type"] = 2,
            ["pos"] = masterPos
        })
        return true
    end


    -- Heal self with 4 seconds cooldown
    if now - lastHeal >= 4000 and summon:getHealth() <= summon:getMaxHealth() * 0.65 then
        upgradedSummons[pid_str][summonId_str]["action"] = now
        upgradedSummons[pid_str][summonId_str]["heal"] = now
        summonPos:sendMagicEffect(CONST_ME_MAGIC_GREEN)
        summon:say("exura")
        healing:execute(master, {
            ["type"] = 2,
            ["pos"] = summonPos
        })
        return true
    end


    -- Challenge with 10 seconds cooldown
    -- Enemies who are close to master and targets master
    local lastChallenge = upgradedSummons[pid_str][summonId_str]["challenge"]
    if now - lastChallenge >= 10000 then
        for x = -1, 1 do for y = -1, 1 do
            tempPos = Position(masterPos.x + x, masterPos.y + y, masterPos.z)
            local tile = Tile(tempPos)
            if tile then
                local enemy = tile:getTopCreature()
                if enemy ~= nil then
                    local enemyTarget = enemy:getTarget()

                    if enemyTarget
                    and summonPos:isSightClear(tempPos, true)
                    and enemyTarget:getId() == master:getId() then

                        upgradedSummons[pid_str][summonId_str]["action"] = now
                        upgradedSummons[pid_str][summonId_str]["challenge"] = now
                        summon:say("exori res")
                        doChallengeCreature(summon, enemy)
                        summonPos:sendDistanceEffect(tempPos, CONST_ANI_SMALLEARTH)
                        tempPos:sendMagicEffect(CONST_ME_MAGIC_RED)
                        return true
                    end
                end
            end
        end end -- 1 sqm radius x, y offsets
    end


    -- Attack with 5 seconds cooldown
    local lastAttack = upgradedSummons[pid_str][summonId_str]["attack"]
    if now - lastAttack >= 5000 then
        local masterTarget = master:getTarget()
        if masterTarget then
         
            local targetPos = masterTarget:getPosition()
            if summonPos:isSightClear(targetPos, true) then
                upgradedSummons[pid_str][summonId_str]["action"] = now
                upgradedSummons[pid_str][summonId_str]["attack"] = now
                summonPos:sendDistanceEffect(masterTarget:getPosition(), CONST_ANI_DEATH)
                summon:say("exori mort")
                attacking:execute(master, {
                    ["type"] = 1,
                    ["number"] = masterTarget:getId()
                })
                return true
            end
        end
    end

    return false
end

empoweredBrain:register()

Edit 14th october 2021: Updated script, added monster teleport if to far away and fixed some bugs.

Edit 14th July 2022: Canary users might be missing the Lua microtime function:
 
Last edited:
Very cool, will be playing with this for sure :D thanks for sharing
 
Last edited:
Updated script in main post:
  • Fixed bug where monster abilities exori mort, exori res and exura sio would cast through walls.
  • Fixed bug where exori res would work as an infinite challenge, now it wears off and the challenged creature can change and follow other targets after a while. (Just like exeta res).
  • Now the summons will teleport to master if they are > 9 SQM away from master.
 
Everyone is broken if they are high enough level
 
Hi znote! I've been looking into this spell and I have this thing
1681349931558.png

How can I avoid summons being teleported to stair tiles? At least stacking the summon on player pos if he goes up or something.
Happens downstairs aswell (summons stay in the sqm where the stair is placed)
Regards!
 
Hi znote! I've been looking into this spell and I have this thing
View attachment 74797

How can I avoid summons being teleported to stair tiles? At least stacking the summon on player pos if he goes up or something.
Happens downstairs aswell (summons stay in the sqm where the stair is placed)
Regards!
Try adding the line "and not tile:hasFlag(TILESTATE_FLOORCHANGE)" to the function teleportSummon like i have done below.
Lua:
local function teleportSummon(summon, position)
    local tile = Tile(position)
    if tile
    and tile:isWalkable()
    and not tile:hasFlag(TILESTATE_PROTECTIONZONE)
    and not tile:hasFlag(TILESTATE_TELEPORT)
    and not tile:hasFlag(TILESTATE_FLOORCHANGE)
    and not tile:getTopCreature() then
        summon:teleportTo(position)
        position:sendMagicEffect(CONST_ME_TELEPORT)
        return true
    end
    return false
end
 
Back
Top