• 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 0.X luaDoCreatureSetTarget not creating red square

maikons

Member
Joined
Aug 1, 2015
Messages
227
Reaction score
16
I want to create a spell that make a player atk other player, like exeta res to pvp
It looks like work, it is opeing PK, but it is not creating the red square...

Why?

What do i doing wrong?

spell:
Code:
local combat = createCombatObject()
setCombatParam(combat, COMBAT_PARAM_TYPE, COMBAT_HEALING)
setCombatParam(combat, COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_RED)
setCombatParam(combat, COMBAT_PARAM_AGGRESSIVE, false)
local arr = {
    {0, 0, 0, 0, 0},
    {0, 1, 1, 1, 0},
    {0, 1, 2, 1, 0},
    {0, 1, 1, 1, 0},
    {0, 0, 0, 0, 0},
}
local area = createCombatArea(arr)

setCombatArea(combat, area)

function onCastSpell(cid, var)
    for i, tid in ipairs(getSpectators(getCreaturePosition(cid), 1, 1, false)) do
        if(isPlayer(tid) and tid ~= cid) then
            doCreatureSetTarget(tid, cid)
        end
    end
    return doCombat(cid, combat, var)
end

source code:
Code:
int32_t LuaInterface::luaDoCreatureSetTarget(lua_State* L)
{
    //doCreatureSetTarget(cid, target)
    uint32_t targetId = popNumber(L);
    ScriptEnviroment* env = getEnv();

    Creature* creature = env->getCreatureByUID(popNumber(L));
    if(!creature)
    {
        errorEx(getError(LUA_ERROR_CREATURE_NOT_FOUND));
        lua_pushboolean(L, false);
        return 1;
    }

    Creature* target = env->getCreatureByUID(targetId);
    if(!target && targetId != 0)
    {
        errorEx(getError(LUA_ERROR_CREATURE_NOT_FOUND));
        lua_pushboolean(L, false);
        return 1;
    }


    bool attackedCreatureChanged = creature->setAttackedCreature(target);
    
    // Remove red square in client if setting target to NULL
    Player *player = creature->getPlayer();
    if(player != NULL && targetId == 0 && attackedCreatureChanged) {
        player->sendCancelTarget();
    } else {
        player->sendCreatureSquare(target, 112);
    }

    lua_pushboolean(L, attackedCreatureChanged);

    return 1;
}
 
This is not achievable with cip client, you have to make custom packet for this if you use otc. You are using server to set the target, client does not get any info that he is attacking the target.
 
Ok, i gonna use OTC...

@Sarah Wesker you mean this?
Code:
local combat = createCombatObject()
setCombatParam(combat, COMBAT_PARAM_TYPE, COMBAT_HEALING)
setCombatParam(combat, COMBAT_PARAM_EFFECT, CONST_ME_MAGIC_RED)
setCombatParam(combat, COMBAT_PARAM_AGGRESSIVE, false)
local arr = {
    {1, 1, 1, 1, 1},
    {1, 1, 1, 1, 1},
    {1, 1, 2, 1, 1},
    {1, 1, 1, 1, 1},
    {1, 1, 1, 1, 1},
}
local area = createCombatArea(arr)

setCombatArea(combat, area)

-- 
function onCastSpell(cid, var)
    local mySkull = getCreatureSkullType(cid)
    if mySkull ~= SKULL_WHITE and mySkull ~= SKULL_RED and mySkull ~= SKULL_BLACK then
        doPlayerSendCancel(cid, "You do not have a skull.")
        return false
    end
    -- 
    for i, tid in ipairs(getSpectators(getCreaturePosition(cid), 2, 2, false)) do
        if(isPlayer(tid) and tid ~= cid) then
            local targetSkull = getCreatureSkullType(tid)
            if targetSkull == SKULL_WHITE or targetSkull == SKULL_RED or targetSkull == SKULL_BLACK then
                local targetTarget = getCreatureTarget(tid)
                if targetTarget ~= 0 then
                    doCreatureSetTarget(tid, 0)
                    doCreatureSetTarget(tid, cid)
                    onExtendedOpcode(cid, 55, tostring(cid::getId()))
                end
            end
        end
    end
    return doCombat(cid, combat, var)
end

(im using 0.4)

Code:
[21:59:37.812] [Error - LuaInterface::loadFile] data/spells/scripts/exeta_player.lua:33: '<name>' expected near ':'
[21:59:37.812] [Warning - Event::loadScript] Cannot load script (data/spells/scripts/exeta_player.lua)
[21:59:37.812] data/spells/scripts/exeta_player.lua:33: '<name>' expected near ':'
 
Ok, i gonna use OTC...


Code:
[21:59:37.812] [Error - LuaInterface::loadFile] data/spells/scripts/exeta_player.lua:33: '<name>' expected near ':'
[21:59:37.812] [Warning - Event::loadScript] Cannot load script (data/spells/scripts/exeta_player.lua)
[21:59:37.812] data/spells/scripts/exeta_player.lua:33: '<name>' expected near ':'
Code:
onExtendedOpcode(cid, 55, tostring(cid::getId()))
Parameters should be:
Code:
OTHER_FUNCTION_NAME(tid, 55, tostring(cid))
As we want to set 'tid' target to 'cid' (spell caster).
Also you must use other function, 'onExtendedOpcode' is for handling packets from OTC to TFS. There must be function like 'sendExtendedOpcode' to send packet from TFS to OTC, but it was not available in official 0.4.
 
@Gesior.pl @Sarah Wesker

Just the function in my script, right?
Or do i need to change something in otclient too?

There is a function with the name u told in 0.4:


@Sarah Wesker @Gesior.pl halp
 
On server side put script you posted above, just change:
Code:
onExtendedOpcode(cid, 55, tostring(cid::getId()))
with:
Code:
doPlayerSendExtendedOpcode(tid, 55, tostring(cid))

On client side, you need code that handle extended opcode with ID 55, reads string from network packet, finds creature with given name on screen and mark it as attacked. Someone must write it. There are many threads with 'free scripting service', try to find someone.
 
On server side put script you posted above, just change:
Code:
onExtendedOpcode(cid, 55, tostring(cid::getId()))
with:
Code:
doPlayerSendExtendedOpcode(tid, 55, tostring(cid))

On client side, you need code that handle extended opcode with ID 55, reads string from network packet, finds creature with given name on screen and mark it as attacked. Someone must write it. There are many threads with 'free scripting service', try to find someone.

TY @Gesior.pl
@Sarah Wesker could u share to us how did u do on otc side?
 
TY @Gesior.pl
@Sarah Wesker could u share to us how did u do on otc side?
Lua:
-- Register
ProtocolGame.registerExtendedOpcode(55, onRecvOpcode)

-- Functions
local getCreatureById = function (id)
    local localPlayer = g_game.getLocalPlayer()
    if not localPlayer or localPlayer:getId() == id then
        return
    end

    for i, spec in ipairs(g_map.getSpectators(localPlayer:getPosition(), false)) do
     if spec:getId() == id then
        return spec
     end
  end
end

function onRecvOpcode(protocol, opcode, packet)
    local creature = getCreatureById(tonumber(packet))
    if creature then
        g_game.cancelAttack()
        g_game.attack(creature)
    end
end
 
Lua:
-- Register
ProtocolGame.registerExtendedOpcode(55, onRecvOpcode)

-- Functions
local getCreatureById = function (id)
    local localPlayer = g_game.getLocalPlayer()
    if not localPlayer or localPlayer:getId() == id then
        return
    end

    for i, spec in ipairs(g_map.getSpectators(localPlayer:getPosition(), false)) do
     if spec:getId() == id then
        return spec
     end
  end
end

function onRecvOpcode(protocol, opcode, packet)
    local creature = getCreatureById(tonumber(packet))
    if creature then
        g_game.cancelAttack()
        g_game.attack(creature)
    end
end
FYI g_map.getCreatureById(id)
 
There is a function like: updateCreatureTarget(cid)... if you can find that add it to the sources for doCreatureSetTarget()
 
Back
Top