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

Summon not coming back

Dhendra

New Member
Joined
Feb 3, 2024
Messages
2
Reaction score
0
Hi there,
Recently, I downloaded "Pokemon PokeDash Pota" by @philippelo from here: [10.98][TFS 1.2] Pokemon PokeDash Pota v1.0 (https://otland.net/threads/10-98-tfs-1-2-pokemon-pokedash-pota-v1-0.278516/)
(The thread references an external site where the updated version is available, that's the version I'm working with.)
So far, it is running fine and I've managed to make some changes as I see fit with my limited LUA knowledge and ChatGPT by my side.

Still, there are some stuff that I have not solved yet, and that's the reason for this post.
So there's this script:
Lua:
function onUse(player, item, fromPosition, target, toPosition, isHotkey)
    -- Check if summoning is blocked for the player
    if player:isSummonBlocked() then
        return true -- Return true to indicate that the item use was handled
    end
    -- Retrieve the key associated with the ball item
    local ballKey = getBallKey(item:getId())
    if hasSummons(player) then -- If the player already has summons
        local usingBall = player:getUsingBall()
        if usingBall == item then
            -- Remove the summon associated with the ball
            doRemoveSummon(player:getId(), balls[ballKey].effectRelease, false, true, balls[ballKey].missile)
            -- Transform the ball item into its unused state
            item:transform(balls[ballKey].usedOn)
            return true -- Return true to indicate that the item use was handled
        else
            -- If the clicked Pokéball doesn't correspond to the currently summoned Pokémon,
            -- return true without further action
            return true
        end
    else -- If the player doesn't have any summons
        if item:getTopParent() == player then -- If the item is held by the player
            if player:canReleaseSummon(item:getSummonLevel(), item:getSummonBoost(), item:getSummonOwner()) then
                -- Transform the ball item into its used state
                item:transform(balls[ballKey].usedOff)
                -- Set a special attribute to indicate that the ball is being used
                item:setSpecialAttribute("isBeingUsed", 1)
                -- Release the summon associated with the ball
                doReleaseSummon(player:getId(), player:getPosition(), balls[ballKey].effectRelease, true, balls[ballKey].missile)
            end
        else -- If the item is not held by the player
            if item:getSpecialAttribute("isBeingUsed") == 1 then -- Check if the ball item is marked as being used
                -- Transform the ball item into its unused state
                item:transform(balls[ballKey].usedOn)
                -- Reset the special attribute indicating that the ball is being used
                item:setSpecialAttribute("isBeingUsed", 0)
            end
        end
    end
    return true -- Return true to indicate that the item use was handled
end

The script's purpose is to summon (release) the Pokemon out of its ball if there's no summon already present, and call it back if the same ball is actioned once again.
The problem is that the Pokemon is not called back to its Pokeball, the effect shows up but instead of calling the Pokemon back, it just gets teleported to the player's location (as if it was a new release event).

There's no error log, it just does not work as expected.
Do you have any ideas/suggestions on how to solve this?

TIA

Edit - I'm adding the current functions doRemoveSummon, doReleaseSummon and hasSummons:

doRemoveSummon
Lua:
-- Function to remove a summon
-- Parameters:
--   cid: the creature ID of the player
--   effect: optional parameter to specify the magic effect when removing the summon (default is CONST_ME_POFF)
--   uid: optional parameter for the UID of the summon
--   message: optional parameter to specify if a message should be displayed (default is true)
--   missile: optional parameter to specify a distance shooting effect
function doRemoveSummon(cid, effect, uid, message, missile)
    -- Get the player by their creature ID
    local player = Player(cid)
    if not player then return false end -- If player does not exist, exit the function
   
    -- Set default values if not provided
    if effect == nil then effect = CONST_ME_POFF end
    if message == nil then message = true end
   
    -- Get the summons of the player
    local summons = player:getSummons()
    if not summons then return false end -- If no summons, exit the function
   
    -- Get the first summon
    local summon = Creature(summons[1])
    if not summon then
        return false
    end
   
    -- Get the position of the summon
    local summonPos = summon:getPosition()
   
    -- Get all creatures attacking the summon
    local attackers = Game.getSpectators(summonPos, true, false)
    for i = 1, #attackers do
        local attacker = attackers[i]
        if attacker and attacker:isMonster() then
            -- Remove the summon from the target list of attackers
            local targetList = attacker:getTargetList()
            for j = 1, #targetList do
                if targetList[j] == summon then
                    attacker:removeTarget(summon)
                    attacker:setIdle()
                    addEvent(function()
                        attacker:addTarget(Creature(player:getId()))
                    end, 1000) -- 1000 milliseconds = 1 second
                end
            end
        end
    end
   
    -- Send magic effect at the summon's position
    if effect then
        summonPos:sendMagicEffect(effect)
    end
   
    -- Send missile effect
    if missile then
        doSendDistanceShoot(summonPos, player:getPosition(), missile)
    end
   
    -- Unregister events
    summon:unregisterEvent("MonsterGetExperience")
    summon:unregisterEvent("MonsterHealthChange")
    player:unregisterEvent("RemoveSummon")
   
    -- Set special attributes for the summon's pokeball, if applicable
    local ball = player:getUsingBall()
    if uid and not ball then
        ball = Item(uid)
    end
    if ball and ball:isPokeball() then
        ball:setSpecialAttribute("pokeHealth", summon:getHealth())
        ball:setSpecialAttribute("pokeLookDir", summon:getDirection())
    end
   
    -- Check if the player or summon is in a special state
    if not (player:isOnFly() or player:isOnRide() or player:isOnSurf() or summon:isEvolving()) then
        if ball then
            ball:setSpecialAttribute("isBeingUsed", 0)
        else
            print("WARNING! Player " .. player:getName() .. " had problems on remove summon: ball does not exist.")
        end
    end
   
    -- Set storage value if the summon is evolving
    if summon:isEvolving() then
        player:setStorageValue(storageEvolving, -1)
    end
   
    -- Display a message if required
    if message then
        player:say("Thanks for your help, " .. summon:getName() .. ", go back to your pokeball!", TALKTYPE_MONSTER_SAY)
    end
   
    -- Remove the summon
    summon:remove()
    return true -- Return true to indicate successful removal
end

doReleaseSummon

Lua:
-- Function to release a summon from a pokeball
-- Parameters:
--   cid: the creature ID of the player
--   pos: position where the summon should be released
--   effect: optional parameter to specify the magic effect when releasing the summon (default is CONST_ME_TELEPORT)
--   message: optional parameter to specify if a message should be displayed (default is true)
--   missile: optional parameter to specify a distance shooting effect
function doReleaseSummon(cid, pos, effect, message, missile)
    -- Get the player by their creature ID
    local player = Player(cid)
    if not player then return false end -- If player does not exist, exit the function
    
    -- Get the pokeball the player is using
    local ball = player:getUsingBall()
    if not ball then return false end -- If no ball, exit the function
    
    -- Set default values if not provided
    if effect == nil then effect = CONST_ME_TELEPORT end
    if message == nil then message = true end
    
    -- Get the name of the summoned creature from the pokeball
    local name = ball:getSpecialAttribute("pokeName")
    if not name then
        ball:remove()
        return false
    end
    
    -- Handle transformations for Ditto
    if name == "Ditto" or name == "Shiny ditto" or name == "Xmas ditto" then
        local dittoTime = ball:getSpecialAttribute("dittoTime")
        if dittoTime and os.time() < dittoTime then
            name = ball:getSpecialAttribute("dittoTransform")
        end
    end
    
    -- Get the monster type
    local monsterType = MonsterType(name)
    
    -- Check if the monster is convinceable, illusionable, and summonable
    if not monsterType:isConvinceable() or not monsterType:isIllusionable() or not monsterType:isSummonable() then
        print("WARNING: Monster " .. name .. " is not convinceable, illusionable, or summonable.")
        player:sendCancelMessage("Sorry, not possible. This problem was reported.")
        ball:setSpecialAttribute("isBeingUsed", 0)
        return false 
    end
    
    -- Get the health of the summon from the pokeball
    local health = ball:getSpecialAttribute("pokeHealth") or 0
    if health <= 0 then
        player:sendCancelMessage("Sorry, you can't release " .. name .." at the moment, it is fainted after being defeated!")
        ball:setSpecialAttribute("isBeingUsed", 0)
        return true
    end
    
    -- Get summon level and boost from the pokeball
    local summonLevel = ball:getSpecialAttribute("pokeLevel")
    local summonBoost = ball:getSpecialAttribute("pokeBoost") or 0
    
    -- Get closest free position to release the summon
    local newPos = player:getClosestFreePosition(pos, 2) or pos
    if newPos.x == 0 then
        newPos = pos
    end
    
    -- Create the monster at the specified position
    local monster = Game.createMonster(name, newPos, true, true, summonLevel, summonBoost)
    if monster ~= nil then
        -- Display message if required
        -- Define an array of messages
        local releaseMessages = {
            "Go " .. monster:getName() .. "!",
            "I need your help " .. monster:getName() .. "!",
            "It's go time " .. monster:getName() .. "!",
            "Let's do this " .. monster:getName() .. "!",
            "I choose you " .. monster:getName() .. "!",
        }
        -- Randomly select a message from the array
        local randomIndex = math.random(1, #releaseMessages)
        local randomMessage = releaseMessages[randomIndex]
    -- Send the randomly selected message
        if message then
            player:say(randomMessage, TALKTYPE_MONSTER_SAY)
        end
        
        -- Add the summon to the player's list of summons
        player:addSummon(monster)
        
        -- Set summon's direction
        monster:setDirection(ball:getSpecialAttribute("pokeLookDir") or DIRECTION_SOUTH)
        
        -- Start Aurea effect if boost is maximum
        if summonBoost >= maxBoost then
            doStartAurea(monster)
        end
        
        -- Set max health and current health of the summon
        local maxHealth = monster:getTotalHealth()
        monster:setMaxHealth(maxHealth)
        monster:setHealth(health)
        
        -- Adjust summon's speed
        monster:changeSpeed(-monster:getSpeed() + monster:getTotalSpeed())
        
        -- Send magic effect at the summon's position
        if effect then
            monster:getPosition():sendMagicEffect(effect)
        end
        
        -- Send missile effect
        if missile then
            doSendDistanceShoot(player:getPosition(), monster:getPosition(), missile)
        end
        
        -- Remove player from summon's target list
        monster:removeTarget(player)
        
        -- Register events for the summon
        monster:registerEvent("MonsterHealthChange")
        monster:registerEvent("MonsterDeath")
        -- Adjust targets of attackers
        local attackers = Game.getSpectators(newPos, true, false) 
        for i = 1, #attackers do
            local attacker = attackers[i]
            if attacker and attacker:isMonster() then
                local hostile = MonsterType(Monster(attacker):getName()):isHostile()
                if hostile then
                    if attacker:getTarget() == player then
                        attacker:addTarget(monster, true)
                        attacker:removeTarget(Creature(player:getId()))
                        attacker:searchTarget()
                    end
                end
            end
        end
        
        -- Send moves information to the player
        local movesTable = {}
        local moves = monsterType:getMoveList()
        for i = 1, #moveWords do
            local move = moves[i]
            if move then
                if i == 1 then
                    table.insert(movesTable, move.name)
                else
                    table.insert(movesTable, "," .. move.name)
                end
            end
        end
        for i = 1, #moveWords do
            local move = moves[i]
            if move then
                table.insert(movesTable, "," .. move.speed)
            end
        end
        for i = 1, #moveWords do
            local move = "cd" .. tostring(i)
            local moveCooldown = ball:getSpecialAttribute(move) or 0
            if os.time() > moveCooldown then
                table.insert(movesTable, ",0")
            else
                table.insert(movesTable, "," .. 1000 * math.floor(ball:getSpecialAttribute(move) - os.time()))
            end
        end
        table.insert(movesTable, ",")
        player:sendExtendedOpcode(52, table.concat(movesTable))
        return monster:getId() -- Return the ID of the summoned monster
    end
    return true -- Return true to indicate successful release
end

Regarding hasSummons, I found these 2 script pieces:
Lua:
-- Function to check if a player has any summons
-- Parameters:
--   cid: the creature ID of the player
function hasSummons(cid)
-- Get the summons of the player
local summons = cid:getSummons()
 
-- Check if the player has any summons
if #summons > 0 then
return true -- Return true if the player has summons
end
 
return false -- Return false if the player has no summons
end

Lua:
-- Method to get the first summon of a player
-- Parameters:
--   self: the player object
function Player.getSummon(self)
-- Check if the player has summons
if hasSummons(self) then
-- Return the first summon of the player
return self:getSummons()[1]
end
return false -- Return false if the player has no summons
end
 
Last edited:
I assume that the function to release the pokemon is "doReleaseSummon", if the script are calling it in both cases, it is because the "hasSummons(player)" function is returning false, so I suggest you post this function and if inside this function there is more functions, also post
 
doRemoveSummon, line 18 why not just call:
Lua:
local summon = player:getSummon()
summon will either be the first summon or false
check it, then cast it (if that's how lua works)
Lua:
if not summon then
    return false
end
summon=Creature(summon)

you can remove lines 17-19
Lua:
-- Get the summons of the player
local summons = player:getSummons()
if not summons then return false end -- If no summons, exit the function


anyway, check the source code for what line 94, summon:remove() does.
Judging by the onUse script the mob might get removed and somehow get created straight away.
Seems strange for such an important feature to be broken on a highly-developed OT
 
Last edited:
Back
Top