• 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!
  • If you're using Gesior 2012 or MyAAC, please review this thread for information about a serious security vulnerability and a fix.

TFS 0.X Creature.h - Crash server

potinho

Premium User
Premium User
Joined
Oct 11, 2009
Messages
1,046
Solutions
18
Reaction score
77
Location
Brazil
Hello everyone, everything good?

My server has been crashing for some time now, but when I migrated to Linux I managed to get the crash log:

Thread 2 "pawn" received signal SIGSEGV, Segmentation fault.
[Switching to Thread 0x7ffff2153700 (LWP 11395)]
0x00005555555c7dce in Creature::getZone (this=0x0) at creature.h:274
274 ZoneType_t getZone() const {return getTile()->getZone();}

Can anyone help me fix this? Thanks.

creature.h
C++:
////////////////////////////////////////////////////////////////////////
// OpenTibia - an opensource roleplaying game
////////////////////////////////////////////////////////////////////////
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with this program.  If not, see <http://www.gnu.org/licenses/>.
////////////////////////////////////////////////////////////////////////

#ifndef __CREATURE__
#define __CREATURE__
#include "otsystem.h"

#include "templates.h"
#include <boost/any.hpp>

#include "const.h"
#include "enums.h"

#include "map.h"
#include "condition.h"
#include "creatureevent.h"

enum slots_t
{
    SLOT_PRE_FIRST = 0,
    SLOT_WHEREEVER = SLOT_PRE_FIRST,
    SLOT_FIRST = 1,
    SLOT_HEAD = SLOT_FIRST,
    SLOT_NECKLACE = 2,
    SLOT_BACKPACK = 3,
    SLOT_ARMOR = 4,
    SLOT_RIGHT = 5,
    SLOT_LEFT = 6,
    SLOT_LEGS = 7,
    SLOT_FEET = 8,
    SLOT_RING = 9,
    SLOT_AMMO = 10,
    SLOT_DEPOT = 11,
    SLOT_LAST = SLOT_DEPOT,
    SLOT_HAND = 12,
    SLOT_TWO_HAND = SLOT_HAND
};

enum lootDrop_t
{
    LOOT_DROP_FULL = 0,
    LOOT_DROP_PREVENT,
    LOOT_DROP_NONE
};

enum Visible_t
{
    VISIBLE_NONE = 0,
    VISIBLE_APPEAR = 1,
    VISIBLE_DISAPPEAR = 2,
    VISIBLE_GHOST_APPEAR = 3,
    VISIBLE_GHOST_DISAPPEAR = 4
};

struct FindPathParams
{
    bool fullPathSearch, clearSight, allowDiagonal, keepDistance;
    uint16_t maxClosedNodes;
    int32_t maxSearchDist, minTargetDist, maxTargetDist;
    FindPathParams()
    {
        fullPathSearch = clearSight = allowDiagonal = true;
        keepDistance = false;
        maxClosedNodes = 100;
        maxSearchDist = minTargetDist = maxTargetDist = -1;
    }
};

struct DeathLessThan;
struct DeathEntry
{
        DeathEntry(std::string name, int32_t dmg):
            data(name), damage(dmg), last(false), justify(false), unjustified(false) {}
        DeathEntry(Creature* killer, int32_t dmg):
            data(killer), damage(dmg), last(false), justify(false), unjustified(false) {}

        bool isCreatureKill() const {return data.type() == typeid(Creature*);}
        bool isNameKill() const {return !isCreatureKill();}

        void setWar(War_t v) {war = v;}
        War_t getWar() const {return war;}

        void setLast() {last = true;}
        bool isLast() const {return last;}

        void setJustify() {justify = true;}
        bool isJustify() const {return justify;}

        void setUnjustified() {unjustified = true;}
        bool isUnjustified() const {return unjustified;}

        const std::type_info& getKillerType() const {return data.type();}
        int32_t getDamage() const {return damage;}

        Creature* getKillerCreature() const {return boost::any_cast<Creature*>(data);}
        std::string getKillerName() const {return boost::any_cast<std::string>(data);}

    protected:
        friend struct DeathLessThan;

        boost::any data;
        int32_t damage;
        War_t war;

        bool last;
        bool justify;
        bool unjustified;
};

struct DeathLessThan
{
    bool operator()(const DeathEntry& d1, const DeathEntry& d2) {return d1.damage > d2.damage;}
};

typedef std::vector<DeathEntry> DeathList;
typedef std::list<CreatureEvent*> CreatureEventList;
typedef std::list<Condition*> ConditionList;
typedef std::map<std::string, std::string> StorageMap;

class Map;
class Tile;
class Thing;

class Player;
class Monster;
class Npc;

class Item;
class Container;

#define EVENT_CREATURECOUNT 10
#ifndef __GROUPED_ATTACKS__
#define EVENT_CREATURE_THINK_INTERVAL 1000
#else
#define EVENT_CREATURE_THINK_INTERVAL 500
#endif
#define EVENT_CHECK_CREATURE_INTERVAL (EVENT_CREATURE_THINK_INTERVAL / EVENT_CREATURECOUNT)

class FrozenPathingConditionCall
{
    public:
        FrozenPathingConditionCall(const Position& _targetPos);
        virtual ~FrozenPathingConditionCall() {}

        virtual bool operator()(const Position& startPos, const Position& testPos,
            const FindPathParams& fpp, int32_t& bestMatchDist) const;

        bool isInRange(const Position& startPos, const Position& testPos,
            const FindPathParams& fpp) const;

    protected:
        Position targetPos;
};

class Creature : public AutoId, virtual public Thing
{
    protected:
        Creature();

    public:
        virtual ~Creature();

        virtual Creature* getCreature() {return this;}
        virtual const Creature* getCreature() const {return this;}
        virtual Player* getPlayer() {return NULL;}
        virtual const Player* getPlayer() const {return NULL;}
        virtual Npc* getNpc() {return NULL;}
        virtual const Npc* getNpc() const {return NULL;}
        virtual Monster* getMonster() {return NULL;}
        virtual const Monster* getMonster() const {return NULL;}
        virtual CreatureType_t getType() const = 0;

        virtual const std::string& getName() const = 0;
        virtual const std::string& getNameDescription() const = 0;
        virtual std::string getDescription(int32_t lookDistance) const;

        uint32_t getID() const {return id;}
        void setID()
        {
            /*
             * 0x10000000 - Player
             * 0x40000000 - Monster
             * 0x80000000 - NPC
             */
            if(!id)
                id = autoId | rangeId();
        }

        void setRemoved() {removed = true;}
        virtual bool isRemoved() const {return removed;}

        virtual uint32_t rangeId() = 0;
        virtual void removeList() = 0;
        virtual void addList() = 0;

        virtual bool canSee(const Position& pos) const;
        virtual bool canSeeCreature(const Creature* creature) const;
        virtual bool canWalkthrough(const Creature* creature) const;

        Direction getDirection() const {return direction;}
        void setDirection(Direction dir) {direction = dir;}

        bool getHideName() const {return hideName;}
        void setHideName(bool v) {hideName = v;}

        bool getHideHealth() const {return hideHealth;}
        void setHideHealth(bool v) {hideHealth = v;}

        MessageClasses getSpeakType() const {return speakType;}
        void setSpeakType(MessageClasses type) {speakType = type;}

        Position getMasterPosition() const {return masterPosition;}
        void setMasterPosition(const Position& pos, uint32_t radius = 1) {masterPosition = pos; masterRadius = radius;}

        virtual int32_t getThrowRange() const {return 1;}
        virtual RaceType_t getRace() const {return RACE_NONE;}

        virtual bool isPushable() const {return getWalkDelay() <= 0;}
        virtual bool canSeeInvisibility() const {return false;}

        int32_t getWalkDelay(Direction dir) const;
        int32_t getWalkDelay() const;
        int32_t getStepDuration(Direction dir) const;
        int32_t getStepDuration() const;

        int64_t getEventStepTicks(bool onlyDelay = false) const;
        int64_t getTimeSinceLastMove() const;
        virtual int32_t getStepSpeed() const {return getSpeed();}

        int32_t getSpeed() const {return baseSpeed + varSpeed;}
        void setSpeed(int32_t varSpeedDelta)
        {
            int32_t oldSpeed = getSpeed();
            varSpeed = varSpeedDelta;
            if(getSpeed() <= 0)
            {
                stopEventWalk();
                cancelNextWalk = true;
            }
            else if(oldSpeed <= 0 && !listWalkDir.empty())
                addEventWalk();
        }

        void setBaseSpeed(uint32_t newBaseSpeed) {baseSpeed = newBaseSpeed;}
        int32_t getBaseSpeed() {return baseSpeed;}

        virtual int32_t getHealth() const {return health;}
        virtual int32_t getMaxHealth() const {return healthMax;}
        virtual int32_t getMana() const {return mana;}
        virtual int32_t getMaxMana() const {return manaMax;}

        const Outfit_t getCurrentOutfit() const {return currentOutfit;}
        void setCurrentOutfit(Outfit_t outfit) {currentOutfit = outfit;}
        const Outfit_t getDefaultOutfit() const {return defaultOutfit;}

        bool isInvisible() const {return hasCondition(CONDITION_INVISIBLE, -1, false);}
        virtual bool isGhost() const {return false;}
        virtual bool isWalkable() const {return false;}

        ZoneType_t getZone() const {return getTile()->getZone();}

        //walk functions
        bool startAutoWalk(std::list<Direction>& listDir);
        void stopWalk() {cancelNextWalk = true;}
        void addEventWalk(bool firstStep = false);
        void stopEventWalk();
        virtual void goToFollowCreature();

        //walk events
        virtual void onWalk(Direction& dir);
        virtual void onWalkAborted() {}
        virtual void onWalkComplete() {}

        //follow functions
        virtual Creature* getFollowCreature() const {return followCreature;}
        virtual bool setFollowCreature(Creature* creature, bool fullPathSearch = false);

        //follow events
        virtual void onFollowCreature(const Creature*) {}
        virtual void onFollowCreatureComplete(const Creature*) {}

        //combat functions
        Creature* getAttackedCreature() {return attackedCreature;}
        virtual bool setAttackedCreature(Creature* creature);
        virtual BlockType_t blockHit(Creature* attacker, CombatType_t combatType, int32_t& damage,
            bool checkDefense = false, bool checkArmor = false, bool reflect = true, bool field = false, bool element = false);

        void setMaster(Creature* creature) {master = creature;}
        Creature* getMaster() {return master;}
        const Creature* getMaster() const {return master;}
        Player* getPlayerMaster() const {return isPlayerSummon() ? master->getPlayer() : NULL;}
        bool isSummon() const {return master != NULL;}
        bool isPlayerSummon() const {return master && master->getPlayer();}

        virtual void addSummon(Creature* creature);
        virtual void removeSummon(const Creature* creature);
        const std::list<Creature*>& getSummons() {return summons;}
        void destroySummons();
        uint32_t getSummonCount() const {return summons.size();}

        virtual int32_t getArmor() const {return 0;}
        virtual int32_t getDefense() const {return 0;}
        virtual float getAttackFactor() const {return 1.0f;}
        virtual float getDefenseFactor() const {return 1.0f;}

        bool addCondition(Condition* condition);
        bool addCombatCondition(Condition* condition);
        void removeCondition(ConditionType_t type);
        void removeCondition(ConditionType_t type, ConditionId_t id);
        void removeCondition(Condition* condition);
        void removeCondition(const Creature* attacker, ConditionType_t type);
        void removeConditions(ConditionEnd_t reason, bool onlyPersistent = true);
        Condition* getCondition(ConditionType_t type, ConditionId_t id, uint32_t subId = 0) const;
        void executeConditions(uint32_t interval);
        bool hasCondition(ConditionType_t type, int32_t subId = 0, bool checkTime = true) const;
        virtual bool isImmune(ConditionType_t type) const;
        virtual bool isImmune(CombatType_t type) const;
        virtual bool isSuppress(ConditionType_t type) const;
        virtual uint32_t getDamageImmunities() const {return 0;}
        virtual uint32_t getConditionImmunities() const {return 0;}
        virtual uint32_t getConditionSuppressions() const {return 0;}
        virtual bool isAttackable() const {return true;}
        virtual bool isAccountManager() const {return false;}

        virtual void changeHealth(int32_t healthChange);
        void changeMaxHealth(uint32_t healthChange) {healthMax = healthChange;}
        virtual void changeMana(int32_t manaChange);
        void changeMaxMana(uint32_t manaChange) {manaMax = manaChange;}

        virtual bool getStorage(const std::string& key, std::string& value) const;
        virtual void setStorage(const std::string& key, const std::string& value);
        virtual void eraseStorage(const std::string& key) {storageMap.erase(key);}

        inline StorageMap::const_iterator getStorageBegin() const {return storageMap.begin();}
        inline StorageMap::const_iterator getStorageEnd() const {return storageMap.end();}

        virtual void gainHealth(Creature* caster, int32_t amount);
        virtual void drainHealth(Creature* attacker, CombatType_t combatType, int32_t damage);
        virtual void drainMana(Creature* attacker, CombatType_t combatType, int32_t damage);

        virtual bool challengeCreature(Creature*) {return false;}
        virtual bool convinceCreature(Creature*) {return false;}

        virtual bool onDeath();
        virtual double getGainedExperience(Creature* attacker) const;
        void addDamagePoints(Creature* attacker, int32_t damagePoints);
        void addHealPoints(Creature* caster, int32_t healthPoints);
        bool hasBeenAttacked(uint32_t attackerId) const;

        //combat event functions
        virtual void onAddCondition(ConditionType_t type, bool hadCondition);
        virtual void onAddCombatCondition(ConditionType_t, bool) {}
        virtual void onEndCondition(ConditionType_t type);
        virtual void onTickCondition(ConditionType_t type, int32_t interval, bool& _remove);
        virtual void onCombatRemoveCondition(const Creature* attacker, Condition* condition);
        virtual void onTarget(Creature*) {}
        virtual void onSummonTarget(Creature*, Creature*) {}
        virtual void onAttacked() {}
        virtual void onTargetDrainHealth(Creature* target, int32_t points);
        virtual void onSummonTargetDrainHealth(Creature*, Creature*, int32_t) {}
        virtual void onTargetDrainMana(Creature* target, int32_t points);
        virtual void onSummonTargetDrainMana(Creature*, Creature*, int32_t) {}
        virtual void onTargetDrain(Creature* target, int32_t points);
        virtual void onSummonTargetDrain(Creature*, Creature*, int32_t) {}
        virtual void onTargetGainHealth(Creature* target, int32_t points);
        virtual void onTargetGainMana(Creature* target, int32_t points);
        virtual void onTargetGain(Creature* target, int32_t points);
        virtual void onTargetKilled(Creature* target);
        virtual bool onKilledCreature(Creature* target, DeathEntry& entry);
        virtual void onGainExperience(double& gainExp, Creature* target, bool multiplied);
        virtual void onGainSharedExperience(double& gainExp, Creature* target, bool multiplied);
        virtual void onTargetBlockHit(Creature*, BlockType_t) {}
        virtual void onBlockHit(BlockType_t) {}
        virtual void onChangeZone(ZoneType_t zone);
        virtual void onTargetChangeZone(ZoneType_t zone);
        virtual void onIdleStatus();

        virtual void getCreatureLight(LightInfo& light) const;
        virtual void resetLight();
        void setCreatureLight(LightInfo& light) {internalLight = light;}

        virtual void onThink(uint32_t interval);
        virtual void onAttacking(uint32_t interval);
        virtual void onWalk();
        virtual bool getNextStep(Direction& dir, uint32_t& flags);

        virtual void onAddTileItem(const Tile* tile, const Position& pos, const Item* item);
        virtual void onUpdateTileItem(const Tile* tile, const Position& pos, const Item* oldItem,
            const ItemType& oldType, const Item* newItem, const ItemType& newType);
        virtual void onRemoveTileItem(const Tile* tile, const Position& pos, const ItemType& iType, const Item* item);
        virtual void onUpdateTile(const Tile*, const Position&) {}

        virtual void onCreatureAppear(const Creature* creature);
        virtual void onCreatureDisappear(const Creature* creature, bool) {internalCreatureDisappear(creature, true);}
        virtual void onCreatureMove(const Creature* creature, const Tile* newTile, const Position& newPos,
            const Tile* oldTile, const Position& oldPos, bool teleport);

        virtual void onTargetDisappear(bool) {}
        virtual void onFollowCreatureDisappear(bool) {}

        virtual void onCreatureTurn(const Creature*) {}
        virtual void onCreatureSay(const Creature*, MessageClasses, const std::string&,
            Position* = NULL) {}

        virtual void onCreatureChangeOutfit(const Creature*, const Outfit_t&) {}
        virtual void onCreatureConvinced(const Creature*, const Creature*) {}
        virtual void onCreatureChangeVisible(const Creature*, Visible_t) {}
        virtual void onPlacedCreature() {}
        virtual void onRemovedCreature();

        virtual WeaponType_t getWeaponType() {return WEAPON_NONE;}
        virtual bool getCombatValues(int32_t&, int32_t&) {return false;}

        virtual void setSkull(Skulls_t newSkull) {skull = newSkull;}
        virtual Skulls_t getSkull() const {return skull;}
        virtual Skulls_t getSkullType(const Creature* creature) const {return creature->getSkull();}

        virtual void setShield(PartyShields_t newPartyShield) {partyShield = newPartyShield;}
        virtual PartyShields_t getShield() const {return partyShield;}
        virtual PartyShields_t getPartyShield(const Creature* creature) const {return creature->getShield();}

        virtual void setDropLoot(lootDrop_t _lootDrop) {lootDrop = _lootDrop;}
        virtual void setLossSkill(bool _skillLoss) {skillLoss = _skillLoss;}

        bool getLossSkill() const {return skillLoss;}
        void setNoMove(bool _cannotMove)
        {
            cannotMove = _cannotMove;
            cancelNextWalk = true;
        }
        bool getNoMove() const {return cannotMove;}

        //creature script events
        bool registerCreatureEvent(const std::string& name);
        bool unregisterCreatureEvent(const std::string& name);
        void unregisterCreatureEvent(CreatureEventType_t type);
        CreatureEventList getCreatureEvents(CreatureEventType_t type);

        virtual void setParent(Cylinder* cylinder)
        {
            _tile = dynamic_cast<Tile*>(cylinder);
            Thing::setParent(cylinder);
        }

        virtual Position getPosition() const {return _tile->getPosition();}
        virtual Tile* getTile() {return _tile;}
        virtual const Tile* getTile() const {return _tile;}
        int32_t getWalkCache(const Position& pos) const;

        const Position& getLastPosition() {return lastPosition;}
        void setLastPosition(Position newLastPos) {lastPosition = newLastPos;}
        static bool canSee(const Position& myPos, const Position& pos, uint32_t viewRangeX, uint32_t viewRangeY);

    protected:
        static const int32_t mapWalkWidth = Map::maxViewportX * 2 + 1;
        static const int32_t mapWalkHeight = Map::maxViewportY * 2 + 1;
        bool localMapCache[mapWalkHeight][mapWalkWidth];

        virtual bool useCacheMap() const {return false;}

        Tile* _tile;
        uint32_t id;
        bool removed;
        bool isMapLoaded;
        bool isUpdatingPath;
        bool checked;
        StorageMap storageMap;

        int32_t checkVector;
        int32_t health, healthMax;
        int32_t mana, manaMax;
        int64_t lastFailedFollow;

        bool hideName, hideHealth, cannotMove;
        MessageClasses speakType;

        Outfit_t currentOutfit;
        Outfit_t defaultOutfit;

        Position masterPosition;
        Position lastPosition;
        int32_t masterRadius;
        uint64_t lastStep;
        uint32_t lastStepCost;
        uint32_t baseSpeed;
        int32_t varSpeed;
        bool skillLoss;
        lootDrop_t lootDrop;
        Skulls_t skull;
        PartyShields_t partyShield;
        Direction direction;
        ConditionList conditions;
        LightInfo internalLight;

        //summon variables
        Creature* master;
        std::list<Creature*> summons;

        //follow variables
        Creature* followCreature;
        uint32_t eventWalk;
        bool cancelNextWalk;
        std::list<Direction> listWalkDir;
        uint32_t walkUpdateTicks;
        bool hasFollowPath;
        bool forceUpdateFollowPath;

        //combat variables
        Creature* attackedCreature;
        struct CountBlock_t
        {
            uint32_t total;
            int64_t start, ticks;

            CountBlock_t(uint32_t points)
            {
                total = points;
                start = ticks = OTSYS_TIME();
            }

            CountBlock_t() {total = start = ticks = 0;}
        };

        typedef std::map<uint32_t, CountBlock_t> CountMap;
        CountMap damageMap;
        CountMap healMap;

        CreatureEventList eventsList;
        uint32_t blockCount, blockTicks, lastHitCreature;
        CombatType_t lastDamageSource;

        #ifdef __DEBUG__
        void validateMapCache();
        #endif
        void updateMapCache();

        void updateTileCache(const Tile* tile);
        void updateTileCache(const Tile* tile, int32_t dx, int32_t dy);
        void updateTileCache(const Tile* tile, const Position& pos);

        void internalCreatureDisappear(const Creature* creature, bool isLogout);

        virtual bool hasExtraSwing() {return false;}

        virtual uint16_t getLookCorpse() const {return 0;}
        virtual uint64_t getLostExperience() const {return 0;}

        virtual double getDamageRatio(Creature* attacker) const;
        virtual void getPathSearchParams(const Creature* creature, FindPathParams& fpp) const;
        DeathList getKillers();

        virtual Item* createCorpse(DeathList deathList);
        virtual void dropLoot(Container*) {}
        virtual void dropCorpse(DeathList deathList);

        virtual void doAttacking(uint32_t) {}

        friend class Game;
        friend class Map;
        friend class LuaInterface;
};
#endif
 

amatria

Well-Known Member
Joined
May 15, 2021
Messages
62
Solutions
5
Reaction score
63
Location
Spain
GitHub
amatria
I am guessing one of your scripts is iterating over a list of creatures, and at some point it is calling the getZone() method over a creature that no longer exists in the game. This may happen, for instance, if you want to display a message over the players that are currently standing in a protected zone using a GlobalEvent (needless to say this is not the right approach).

Take a look at the following pseudocode:
Python:
players = game.getPlayersOnline()
time.sleep(60) # suspend the execution for 60s
for player in players:
    if player.getZone() == Tile.PROTECTED_ZONE:
        player.getPosition().sendMessage('foo bar')
Because it stores a list of currently online players (at the time of calling the method), the real list of players online may well have completely changed at the time the script actually accesses the player objects in the for loop (notice the time.sleep(60)). Put differently, the lists of players may not match the state of the game once you run the for loop (even without the time.sleep thing).

So, how do you solve your crash? Look for a script that iterates over a list of players and calls the getZone() method over them. Once you find it, rewrite it so that it works as a CreatureEvent, which will be guaranteed to always succeed because the execution of the script will be associated to the lifecycle of the player object.
 
OP
OP
potinho

potinho

Premium User
Premium User
Joined
Oct 11, 2009
Messages
1,046
Solutions
18
Reaction score
77
Location
Brazil
I am guessing one of your scripts is iterating over a list of creatures, and at some point it is calling the getZone() method over a creature that no longer exists in the game. This may happen, for instance, if you want to display a message over the players that are currently standing in a protected zone using a GlobalEvent (needless to say this is not the right approach).

Take a look at the following pseudocode:
Python:
players = game.getPlayersOnline()
time.sleep(60) # suspend the execution for 60s
for player in players:
    if player.getZone() == Tile.PROTECTED_ZONE:
        player.getPosition().sendMessage('foo bar')
Because it stores a list of currently online players (at the time of calling the method), the real list of players online may well have completely changed at the time the script actually accesses the player objects in the for loop (notice the time.sleep(60)). Put differently, the lists of players may not match the state of the game once you run the for loop (even without the time.sleep thing).

So, how do you solve your crash? Look for a script that iterates over a list of players and calls the getZone() method over them. Once you find it, rewrite it so that it works as a CreatureEvent, which will be guaranteed to always succeed because the execution of the script will be associated to the lifecycle of the player object.
Thanks for the very detailed answer, but I didn't find the use of the getZone() function in any script, could it be something else? Any relative? Like, for example, getTilePzInfo or just getTile().
Post automatically merged:

Have some scripts who interact with monsters, like:

Lua:
function ExistMonsterByName(name) -- by vodka
    local monster = io.open("data/monster/monsters.xml", "r"):read("*all")
    local get = monster:lower():match('name="' .. name:lower() ..'"')
    if get == nil or get == "" then
        return false
    end
    return true
end
function getDirMonsterByNameMonster(name)
    local t = {}
    local monster = io.open("data/monster/monsters.xml", "r")
    for i in monster:read("*a"):gmatch('<monster name="'..tostring(name)..'" file="(.-)"/>') do
        table.insert(t, tostring(i))
    end
    return t[1] or 0
end
function getMonsterLootItens(name)
    local dir = "data/monster/"..getDirMonsterByNameMonster(name)..""
    local monster = io.open(""..dir.."", "r")
    str = ""
    for i in monster:read("*a"):gmatch('id="(.-)"') do
        str = ""..str.." - "..getItemNameById(i)..""
    end
    return str
end
function getAllMonster()
    local str = ""
    local monster = io.open("data/monster/monsters.xml", "r")
    str = "Voce digitou incorretamente o nome do monstro veja a lista de monstro\n"
    for i in monster:read("*a"):gmatch('<monster name="(.-)"') do
        str = ""..str.." - "..i..""
    end
    return str
end
function getAttrMonster(name)
    return "Life = "..getMonsterInfo(name).health.."\nExp = "..getMonsterInfo(name).experience.."\n"
end
function onSay(cid, words, param, channel)
    if param == "" or not param or param == " " then
        doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE, "You need to enter the monster's name.")
        return true
    end
    local name = param:lower()
    if not ExistMonsterByName(name) then
        doShowTextDialog(cid, 1397, getAllMonster()) return true
    end
    local name = name:gsub("(%l)(%w*)", function(a,b) return string.upper(a)..b end)
    doShowTextDialog(cid, 1397, "Info Monster "..name.."\n"..getAttrMonster(name).."\n\nLoots = "..getMonsterLootItens(name).."")
    return true
end

XML:
<?xml version="1.0" encoding="ISO-8859-1"?>
<mod name="Simple Task" version="4.0" author="Vodkart" contact="tibiaking.com" enabled="yes">
<config name="task_func"><![CDATA[
task_sys = {
    [1] = {name = "Trolls", start = 176201, monsters_list = {"Troll"}, level = 8, count = 40, points = 1, items = {}, reward = {}, exp = 20000, money = 2000},
    [2] = {name = "rotworms", start = 176202, monsters_list = {"rotworm"}, level = 12, count = 50, points = 1, items = {}, reward = {}, exp = 25000, money = 3000},
    [3] = {name = "Minotaurs", start = 176216, monsters_list = {"minotaur","minotaur guard","minotaur archer","minotaur mage"}, level = 15, count = 150, points = 2, items = {}, reward = {}, exp = 30000, money = 10000},
    [4] = {name = "cyclops", start = 176203, monsters_list = {"cyclops"}, level = 19, count = 60, points = 2, items = {}, reward = {{2486,1}}, exp = 30000, money = 3000},
    [5] = {name = "Green Djinn", start = 176204, monsters_list = {"Green Djinn","Efreet"}, level = 23, count = 80, points = 3, items = {}, reward = {}, exp = 100000, money = 5000},
    [6] = {name = "Blue Djinn", start = 176205, monsters_list = {"Blue Djinn","Marid"}, level = 25, count = 80, points = 3, items = {}, reward = {}, exp = 100000, money = 5000},
    [7] = {name = "Terror Birds", start = 176206, monsters_list = {"Terror Bird"}, level = 30, count = 120, points = 3, items = {}, reward = {}, exp = 100000, money = 5000},
    [8] = {name = "Stone Golems", start = 176207, monsters_list = {"Stone Golem"}, level = 33, count = 130, points = 4, items = {}, reward = {}, exp = 120000, money = 7000},
    [9] = {name = "Carniphilas", start = 176208, monsters_list = {"carniphila"}, level = 36, count = 135, points = 4, items = {}, reward = {}, exp = 80000, money = 8000},
    [10] = {name = "Elephants", start = 176209, monsters_list = {"elephant"}, level = 40, count = 150, points = 4, items = {}, reward = {}, exp = 120000, money = 8200},
    [11] = {name = "Dwarves", start = 176210, monsters_list = {"dwarf","dwarf soldier","dwarf guard","dwarf geomancer"}, level = 42, count = 150, points = 4, items = {}, reward = {}, exp = 200000, money = 15000},
    [12] = {name = "Vampires", start = 176211, monsters_list = {"vampire"}, level = 46, count = 170, points = 5, items = {}, reward = {}, exp = 80000, money = 8500},
    [13] = {name = "Dragons", start = 176212, monsters_list = {"dragon"}, level = 50, count = 120, points = 5, items = {}, reward = {}, exp = 90000, money = 9000},
    [14] = {name = "Necromancer" ,start = 176213, monsters_list = {"Necromancer"}, level = 60, count = 200, points = 5, items = {}, reward = {}, exp = 200000, money = 15000},
    [15] = {name = "Bonebeasts" ,start = 176214, monsters_list = {"Bonebeast"}, level = 63, count = 250, points = 5, items = {}, reward = {}, exp = 250000, money = 11000},
    [16] = {name = "Giant Spider" ,start = 176215, monsters_list = {"Giant Spider","The old widow"}, level = 80, count = 500, points = 6, items = {}, reward = {}, exp = 200000, money = 32000},
    [17] = {name = "Dragon Lords" ,start = 176219, monsters_list = {"Dragon lord"}, level = 88, count = 650, points = 6, items = {}, reward = {}, exp = 30000, money = 35000},
    [18] = {name = "Hydras" ,start = 176222, monsters_list = {"Hydra"}, level = 100, count = 700, points = 7, items = {{4850,10}}, reward = {}, exp = 400000, money = 40000},
    [19] = {name = "Serpent Spawn" ,start = 176223, monsters_list = {"Serpent Spawn"}, level = 103, count = 720, points = 7, items = {{2445,1}}, reward = {}, exp = 500000, money = 45000},
    [20] = {name = "Behemoths" ,start = 176224, monsters_list = {"Behemoth"}, level = 108, count = 800, points = 8, items = {}, reward = {}, exp = 5000000, money = 200000},
    [21] = {name = "Demons" ,start = 176225, monsters_list = {"Demon"}, level = 110, count = 6666, points = 20, items = {}, reward = {{2495,1}}, exp = 6660000, money = 500000},
    [22] = {name = "Orshabaals" ,start = 176226, monsters_list = {"Orshabaal"}, level = 120, count = 300, points = 10, items = {}, reward = {{2341,1},{5114,1}}, exp = 9960000, money = 800000},
    [23] = {name = "Ferumbras" ,start = 176227, monsters_list = {"Ferumbras"}, level = 130, count = 50, points = 10, items = {}, reward = {{5161,1}}, exp = 6660000, money = 666000},
    [24] = {name = "Golden Knights" ,start = 176228, monsters_list = {"Golden Knight"}, level = 200, count = 10, points = 10, items = {}, reward = {{2646,1}}, exp = 10660000, money = 900000},
    [25] = {name = "Cacheros" ,start = 176229, monsters_list = {"Cachero"}, level = 200, count = 200, points = 10, items = {}, reward = {{2646,1}}, exp = 10000000, money = 300000},
    [26] = {name = "Eternal Oblivions" ,start = 176230, monsters_list = {"Eternal Oblivion"}, level = 200, count = 200, points = 10, items = {}, reward = {{2646,1}}, exp = 10000000, money = 300000},
    [27] = {name = "Infernus" ,start = 176231, monsters_list = {"Infernus"}, level = 200, count = 300, points = 15, items = {}, reward = {{5149,3}}, exp = 10000000, money = 300000}
}
daily_task = {
    [1] = {name = "Orcs" ,monsters_list = {"Orc Berserker","Orc Rider","Orc Leader","Orc Warlord", "Orc", "Orc Spearman", "Orc Warrior"}, count = 100, points = 2, reward = {}, exp = 50000, money = 10000},
    [2] = {name = "Rotworms" ,monsters_list = {"Rotworm"}, count = 220, points = 2, reward = {}, exp = 90000, money = 12000},
    [3] = {name = "Cyclops" ,monsters_list = {"Cyclops"}, count = 165, points = 3, reward = {}, exp = 9000, money = 15000},
    [4] = {name = "Minotaurs" ,monsters_list = {"minotaur","minotaur guard","minotaur archer","minotaur mage"}, count = 185, points = 3, reward = {}, exp = 90000, money = 15000},
    [5] = {name = "Ghouls" ,monsters_list = {"Ghoul"}, count = 150, points = 3, reward = {}, exp = 90000, money = 11000},
    [6] = {name = "Dragons" ,monsters_list = {"Dragon"}, count = 150, points = 3, reward = {}, exp = 20000, money = 10000},
    [7] = {name = "Vampires" ,monsters_list = {"Vampire"}, count = 200, points = 3, reward = {}, exp = 200000, money = 25000},
    [8] = {name = "Ancient Scarabs" ,monsters_list = {"Ancient Scarab"}, count = 180, points = 5, reward = {}, exp = 220000, money = 18000},
    [9] = {name = "Behemoths" ,monsters_list = {"Behemoth"}, count = 300, points = 5, reward = {}, exp = 500000, money = 60000},
    [10] = {name = "Heroes" ,monsters_list = {"Hero"}, count = 260, points = 5, reward = {}, exp = 400000, money = 55000},
    [11] = {name = "Black Knights" ,monsters_list = {"Black Knight"}, count = 260, points = 5, reward = {}, exp = 400000, money = 55000},
    [12] = {name = "Giant Spiders" ,monsters_list = {"Giant Spider"}, count = 350, points = 5, reward = {}, exp = 60000, money = 70000},
    [13] = {name = "Warlocks" ,monsters_list = {"Warlock"}, count = 700, points = 5, reward = {{2173,1}}, exp = 90000, money = 120000},
    [14] = {name = "Hydras" ,monsters_list = {"Hydra"}, count = 700, points = 5, reward = {}, exp = 100000, money = 160000},
    [15] = {name = "Dragon Lords" ,monsters_list = {"Dragon Lord"}, count = 400, points = 5, reward = {{2445,1}}, exp = 1300000, money = 200000},
    [16] = {name = "Frost Dragons" ,monsters_list = {"Frost Dragon"}, count = 400, points = 5, reward = {{2445,1}}, exp = 1300000, money = 200000},
    [17] = {name = "Serpent Spawns" ,monsters_list = {"Serpent Spawn"}, count = 400, points = 5, reward = {{2445,1}}, exp = 1300000, money = 200000},
    [18] = {name = "Juggernauts" ,monsters_list = {"Juggernaut"}, count = 600, points = 5, reward = {{5156,1}}, exp = 1000000, money = 200000},
    [19] = {name = "Undead Dragons" ,monsters_list = {"Undead Dragon"}, count = 600, points = 8, reward = {{5154,1}}, exp = 1000000, money = 200000},
    [20] = {name = "Hellhounds" ,monsters_list = {"Hellhound"}, count = 600, points = 8, reward = {{5159,1}}, exp = 1000000, money = 200000},
    [21] = {name = "Cacheros" ,monsters_list = {"Cachero"}, count = 600, points = 10, reward = {}, exp = 10000000, money = 300000}
  
}
task_sys_storages = {176601, 176602, 176603, 176604, 176605, 176606, 176607, 176608} -- task, points, count, daily task, daily count, daily time , daily start, contador
function getTaskMission(cid)
    return getPlayerStorageValue(cid,task_sys_storages[1]) < 0 and 1 or getPlayerStorageValue(cid,task_sys_storages[1])
end
function getDailyTaskMission(cid)
    return getPlayerStorageValue(cid,task_sys_storages[4]) < 0 and 1 or getPlayerStorageValue(cid,task_sys_storages[4])
end
function getTaskPoints(cid)
    return getPlayerStorageValue(cid,task_sys_storages[2]) < 0 and 0 or getPlayerStorageValue(cid,task_sys_storages[2])
end
function doRandomDailyTask(cid)
    local t = {
        [{6,80}] = {1,5},
        [{81,149}] = {6,12},
        [{150,250}] = {13,17},
        [{251,math.huge}] = {18,21}
    }
    for a , b in pairs(t) do
        if getPlayerLevel(cid) >= a[1] and getPlayerLevel(cid) <= a[2] then
            return math.random(b[1], b[2])
        end
    end
    return 0
end
function GetRankTask(cid)
    local ranks = {
        [{1, 20}] = "Huntsman",
        [{21, 50}] = "Ranger",
        [{51, 100}] = "Big Game Hunter",
        [{101, 200}] = "Senior Hunter",     
        [{201, math.huge}] = "Extreme Hunter"
    }
    for v , r in pairs(ranks) do
        if getTaskPoints(cid) >= v[1] and getTaskPoints(cid) <= v[2] then
            return r
        end
    end
    return 0
end
function getItemsFromList(items)
    local str = ''
    if table.maxn(items) > 0 then
        for i = 1, table.maxn(items) do
            str = str .. items[i][2] .. ' ' .. getItemNameById(items[i][1])
            if i ~= table.maxn(items) then str = str .. ', '
            end
        end
    end
    return str
end
function doRemoveItemsFromList(cid,items)
    local count = 0
    if table.maxn(items) > 0 then
        for i = 1, table.maxn(items) do
            if getPlayerItemCount(cid,items[i][1]) >= items[i][2] then
            count = count + 1 end
        end
    end
    if count == table.maxn(items) then
        for i = 1, table.maxn(items) do doPlayerRemoveItem(cid,items[i][1],items[i][2]) end
    else
        return false
    end
    return true
end
function getMonsterFromList(monster)
    local str = ''
    if #monster > 0 then
        for i = 1, #monster do
            str = str .. monster[i]
            if i ~= #monster then str = str .. ', ' end
        end
    end
    return str
end
function GiveRewardsTask(cid, items)
    local backpack = doPlayerAddItem(cid, 1999, 1) -- backpackID
    for _, i_i in ipairs(items) do
        local item, amount = i_i[1],i_i[2]
        if isItemStackable(item) or amount == 1 then
            doAddContainerItem(backpack, item, amount)
        else
            for i = 1, amount do
                doAddContainerItem(backpack, item, 1)
            end
        end
    end
end
function isSummon(cid)
    if(not isCreature(cid)) then
        return false
    end
    return getCreatureMaster(cid) ~= cid
end
]]></config>
<event type="login" name="TaskLogin" event="script"><![CDATA[
function onLogin(cid)
    registerCreatureEvent(cid, "KillTask")
    registerCreatureEvent(cid, "TaskLook")
    return true
end]]></event>
<talkaction words="/task;!task" event="buffer"><![CDATA[
domodlib('task_func')
param,task,daily = param:lower(), getTaskMission(cid), getDailyTaskMission(cid)
if isInArray({"counter","contador"},param) then
    setPlayerStorageValue(cid, task_sys_storages[8], getPlayerStorageValue(cid, task_sys_storages[8]) <= 0 and 1 or 0)
    doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE,"[Task System] The counter was "..(getPlayerStorageValue(cid, task_sys_storages[8]) <= 0 and "enabled" or "disabled")..".") return true
elseif isInArray({"daily","diaria"},param) then
    if not daily_task[daily] or getPlayerStorageValue(cid, task_sys_storages[7]) <= 0 then
        doPlayerSendCancel(cid, "Sorry, but you are not on any Task Daily.") return true
    elseif getPlayerStorageValue(cid, task_sys_storages[6]) - os.time() <= 0 and getPlayerStorageValue(cid, task_sys_storages[5]) < daily_task[daily].count then
        doPlayerSendCancel(cid,"Sorry, you didn't finish the Daily Task in time! Please go back to NPC Task and start a new Daily Task.") return true
    end
    return doShowTextDialog(cid, 1961, "[->] CURRENT DAILY TASK INFO [<-]\n\nName: "..daily_task[daily].name.."\nProgress: ["..(getPlayerStorageValue(cid, task_sys_storages[5]) < 0 and 0 or getPlayerStorageValue(cid, task_sys_storages[5])).."/"..daily_task[daily].count.."]\nDelivery time: "..os.date("%d %B %Y %X ", getPlayerStorageValue(cid,task_sys_storages[6])).."\nMonsters to hunt: "..getMonsterFromList(daily_task[daily].monsters_list).."\n\n[->] CURRENT TASK REWARDS [<-]\n\nMoney: "..(daily_task[daily].money > 0 and daily_task[daily].money or 0).."\nExperience: "..(daily_task[daily].exp > 0 and daily_task[daily].exp or 0).."\nTask Points: "..daily_task[daily].points.."\nItems: "..(#daily_task[daily].reward > 0 and getItemsFromList(daily_task[daily].reward) or "None")..".")
end
if not task_sys[task] or getPlayerStorageValue(cid, task_sys[task].start) <= 0 then
    doPlayerSendCancel(cid, "You are not on any task.") return true
end
return doShowTextDialog(cid, 1961, "-> TASK POINTS [" .. getTaskPoints(cid).. "] <- \n\n-> CURRENT TASK ["..getTaskMission(cid).."/"..#task_sys.."] <-\n\nTask Name: "..task_sys[task].name.."\nTask Level: "..task_sys[task].level.."\nTask Progress: ["..(getPlayerStorageValue(cid, task_sys_storages[3]) < 0 and 0 or getPlayerStorageValue(cid, task_sys_storages[3])).."/"..task_sys[task].count.."]\nMonster To Hunt: "..getMonsterFromList(task_sys[task].monsters_list)..".\nItens Para Entrega: "..(#task_sys[task].items > 0 and getItemsFromList(task_sys[task].items) or "None")..".\n\n[->] CURRENT TASK REWARDS [<-]\n\nReward Money: "..(task_sys[task].money > 0 and task_sys[task].money or 0).."\nReward Experience: "..(task_sys[task].exp > 0 and task_sys[task].exp or 0).."\nReward Points: "..task_sys[task].points.."\nReward Items: "..(#task_sys[task].reward > 0 and getItemsFromList(task_sys[task].reward) or "None")..".")
]]></talkaction>
<event type="look" name="TaskLook" event="script"><![CDATA[
domodlib('task_func')
function onLook(cid, thing, position, lookDistance)
    if isPlayer(thing.uid) and getTaskPoints(thing.uid) > 0 then
        doPlayerSetSpecialDescription(thing.uid, "\n"..(getPlayerSex(thing.uid) == 0 and "She" or "He").. " is a "..GetRankTask(thing.uid))
    end 
    return true
end]]></event>
<event type="kill" name="KillTask" event="script"><![CDATA[
domodlib('task_func')
function onKill(cid, target)
    if isPlayer(cid) and isMonster(target) then
        local t,daily = task_sys[getTaskMission(cid)], daily_task[getDailyTaskMission(cid)]     
        if t and getPlayerStorageValue(cid, t.start) > 0 and isInArray(t.monsters_list, getCreatureName(target):lower())then
            local ab = getPlayerStorageValue(cid, task_sys_storages[3]) == -1 and tonumber(0) or tonumber(getPlayerStorageValue(cid, task_sys_storages[3]))
            if tonumber(ab) and tonumber(ab) < t.count then
                setPlayerStorageValue(cid, task_sys_storages[3], ab <= 0 and tonumber(1) or tonumber(ab+1))
                if getPlayerStorageValue(cid, task_sys_storages[8]) <= 0 and tonumber(getPlayerStorageValue(cid, task_sys_storages[3])) < t.count then
                    doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE,"[Task System] You defeated Total [" .. tonumber(getPlayerStorageValue(cid, task_sys_storages[3])) .. "/" .. t.count .. "] of the Task of the " .. t.name .. ".")
                end
                if tonumber(getPlayerStorageValue(cid, task_sys_storages[3])) >= t.count then
                    doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE,"[Task System] Congratulations! You have finished the Task of "..t.name..", go back to NPC to get your reward.")
                end
            end
        end
        if daily and getPlayerStorageValue(cid, task_sys_storages[7]) > 0 and getPlayerStorageValue(cid, task_sys_storages[6]) - os.time() >= 0 and isInArray(daily.monsters_list, getCreatureName(target):lower()) then
            local cd = getPlayerStorageValue(cid, task_sys_storages[5]) == -1 and tonumber(0) or tonumber(getPlayerStorageValue(cid, task_sys_storages[5]))
            if tonumber(cd) and cd < daily.count then
                setPlayerStorageValue(cid, task_sys_storages[5], cd <= 0 and tonumber(1) or tonumber(cd+1))
                if getPlayerStorageValue(cid, task_sys_storages[8]) <= 0 and tonumber(getPlayerStorageValue(cid, task_sys_storages[5])) < daily.count then
                    doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_BLUE,"[Daily Task System] You defeated Total [" .. tonumber(getPlayerStorageValue(cid, task_sys_storages[5])) .. "/" .. daily.count .. "] of the Task of the " .. daily.name .. ".")
                end
                if tonumber(getPlayerStorageValue(cid, task_sys_storages[5])) >= daily.count then
                    doPlayerSendTextMessage(cid, MESSAGE_STATUS_CONSOLE_ORANGE,"[Daily Task System] Congratulations! You have finished the Task of "..daily.name..", go back to NPC to get your reward.")
                end
            end
        end
        return true
    end
    return true
end]]></event>
</mod>

and autoloot attached
 

Attachments

  • new_perfect_autoloot_otx.xml
    15.3 KB · Views: 2 · VirusTotal
Last edited:
OP
OP
potinho

potinho

Premium User
Premium User
Joined
Oct 11, 2009
Messages
1,046
Solutions
18
Reaction score
77
Location
Brazil
Found the bug. For no reason, when some player throw SD in specific trainer in specific area, server crashes, i dont know why :eek:
 
Top