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

C++ Creature:CastSpell check if need target

zxmatzx

Advanced OT User
Joined
Dec 1, 2010
Messages
312
Solutions
27
Reaction score
155
Location
Brazil
GitHub
Mateuso8
Hello,
Im using this function to do a Creature cast a spell, but if the spell have needtarget="1"(Energy Strike, Fire Strike, Brutal Strike) in spells.xml and the creature don't have target, the code still cast the spell and return true, and i need it don't cast the spell and return false. I need to check if needTarget, i've tryed to do by myself but could not, the server don't compiled. Here is the function:

Its TFS 1.2:
Luascript.cpp:
C++:
registerMethod("Creature", "castSpell", LuaScriptInterface::luaCreatureCastSpell);

C++:
int LuaScriptInterface::luaCreatureCastSpell(lua_State* L)
{
    //creature:castSpell("name")
    const std::string& spellName = getString(L, 2);

    if(Creature* creature = getUserdata<Creature>(L, 1))
    {
        InstantSpell* spell = g_spells->getInstantSpellByName(spellName);
        if(!spell)
        {
            lua_pushboolean(L, false);
            return 1;
        }
    
        Creature* target = creature->getAttackedCreature();

        if(target)
        {
            spell->castSpell(creature, target);
        }
        else
        {
            spell->castSpell(creature, creature);
        }

        lua_pushboolean(L, true);
    }
    else
    {
        lua_pushboolean(L, false);
    }
    return 1;
}
Luascript.h:
C++:
static int luaCreatureCastSpell(lua_State* L);
I tryed to access needTarget variable in spell, but i don't found the right way to do.
Any help will be welcome.
Thanks.


--Edit:
After try a lot, i did:
Spells.h:
Change class InstantSpell for this:
C++:
class InstantSpell : public TalkAction, public Spell
{
    public:
        explicit InstantSpell(LuaScriptInterface* interface) : TalkAction(interface) {}

        bool configureEvent(const pugi::xml_node& node) override;
        bool loadFunction(const pugi::xml_attribute& attr) override;

        virtual bool playerCastInstant(Player* player, std::string& param);

        bool castSpell(Creature* creature) override;
        bool castSpell(Creature* creature, Creature* target) override;

        //scripting
        bool executeCastSpell(Creature* creature, const LuaVariant& var);

        bool isInstant() const final {
            return true;
        }
        bool getHasParam() const {
            return hasParam;
        }
        bool getHasPlayerNameParam() const {
            return hasPlayerNameParam;
        }
        bool canCast(const Player* player) const;
        bool canThrowSpell(const Creature* creature, const Creature* target) const;
      
        bool getNeedTarget() const { //Added this to return needTarget variable that is protected in Spell class.
            return needTarget;
        }
    protected:
        std::string getScriptEventName() const override;

        static InstantSpellFunction HouseGuestList;
        static InstantSpellFunction HouseSubOwnerList;
        static InstantSpellFunction HouseDoorList;
        static InstantSpellFunction HouseKick;
        static InstantSpellFunction SearchPlayer;
        static InstantSpellFunction SummonMonster;
        static InstantSpellFunction Levitate;
        static InstantSpellFunction Illusion;

        static House* getHouseFromPos(Creature* creature);

        bool internalCastSpell(Creature* creature, const LuaVariant& var);

        InstantSpellFunction* function = nullptr;

        bool needDirection = false;
        bool hasParam = false;
        bool hasPlayerNameParam = false;
        bool checkLineOfSight = true;
        bool casterTargetOrDirection = false;
};

Luascript.cpp:

C++:
int LuaScriptInterface::luaCreatureCastSpell(lua_State* L)
{
    //creature:castSpell("name")
    const std::string& spellName = getString(L, 2);

    if(Creature* creature = getUserdata<Creature>(L, 1))
    {
        InstantSpell* spell = g_spells->getInstantSpellByName(spellName);
        if(!spell)
        {
            lua_pushboolean(L, false);
            return 1;
        }
      
        Creature* target = creature->getAttackedCreature();
      
        //Check if needTarget is true and Creature don't have target, then return false.
        if (spell->getNeedTarget() == true && !target)
        {
            lua_pushboolean(L, false);
            return 1;
        }

        if(target)
        {
            spell->castSpell(creature, target);
        }
        else
        {
            spell->castSpell(creature, creature);
        }

        lua_pushboolean(L, true);
    }
    else
    {
        lua_pushboolean(L, false);
    }
    return 1;
}
I don't know if is the right way to do, but is working nice here.
 
Last edited:
Back
Top