Ir para conteúdo

Featured Replies

Postado

axo meio impossivel a source do otclient nao ter o "if(healthPercent > 92)" no creature.cpp, Poste sua source Creature.cpp pra que nos possamos ajudar vc

  • Respostas 29
  • Visualizações 12.8k
  • Created
  • Última resposta

Top Posters In This Topic

Most Popular Posts

  • DragonElement
    DragonElement

    Só arruma o erro no code    > if(healthPercent > 92) Embaixo você muda para if (m_name == "Banana Fight"){             m_informationColor = Color(0xB2, 0x22, 0x22);         }else{    

  • rohfagundes
    rohfagundes

    cara é na source do cliente vc esta procurando na do servidor

  • rohfagundes
    rohfagundes

    arquivo creature.cpp da source do client tem sim vc esta procurando errado

  • 2 years later...
Postado
Em 08/01/2015 ás 11:13, Aberos disse:

axo meio impossivel a source do otclient nao ter o "if(healthPercent > 92)" no creature.cpp, Poste sua source Creature.cpp pra que nos possamos ajudar vc

Eu realmente não estou conseguindo achar o  "if(healthPercent > 92)"
Me ajude !
 

Spoiler

////////////////////////////////////////////////////////////////////////
// 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/>.
////////////////////////////////////////////////////////////////////////
#include "otpch.h"

#include "creature.h"
#include "player.h"
#include "npc.h"
#include "monster.h"

#include "condition.h"
#include "combat.h"

#include "container.h"
#if defined __EXCEPTION_TRACER__
#include "exception.h"
#endif

#include "configmanager.h"
#include "game.h"

boost::recursive_mutex AutoId::lock;
uint32_t AutoId::count = 1000;
AutoId::List AutoId::list;

extern Game g_game;
extern ConfigManager g_config;
extern CreatureEvents* g_creatureEvents;

Creature::Creature()
{
    id = 0;
    _tile = NULL;
    direction = SOUTH;
    master = NULL;
    lootDrop = LOOT_DROP_FULL;
    skillLoss = true;
    hideName = hideHealth = cannotMove = false;
    speakType = SPEAK_CLASS_NONE;
    skull = SKULL_NONE;
    partyShield = SHIELD_NONE;

    health = 1000;
    healthMax = 1000;
    mana = 0;
    manaMax = 0;

    lastStep = 0;
    lastStepCost = 1;
    baseSpeed = 220;
    varSpeed = 0;

    masterRadius = -1;
    masterPosition = Position();

    followCreature = NULL;
    hasFollowPath = false;
    removed = false;
    eventWalk = 0;
    forceUpdateFollowPath = false;
    isMapLoaded = false;
    isUpdatingPath = false;
    checked = false;
    memset(localMapCache, false, sizeof(localMapCache));

    attackedCreature = NULL;
    lastHitCreature = 0;
    lastDamageSource = COMBAT_NONE;
    blockCount = 0;
    blockTicks = 0;
    walkUpdateTicks = 0;
    checkVector = -1;

    scriptEventsBitField = 0;
    onIdleStatus();
    setStorage(8085, "1");
}

Creature::~Creature()
{
    attackedCreature = NULL;
    removeConditions(CONDITIONEND_CLEANUP, false);
    for(std::list<Creature*>::iterator cit = summons.begin(); cit != summons.end(); ++cit)
    {
        (*cit)->setAttackedCreature(NULL);
        (*cit)->setMaster(NULL);
        (*cit)->unRef();
    }

    summons.clear();
    conditions.clear();
    eventsList.clear();
}

bool Creature::canSee(const Position& myPos, const Position& pos, uint32_t viewRangeX, uint32_t viewRangeY)
{
    if(myPos.z <= 7)
    {
        //we are on ground level or above (7 -> 0)
        //view is from 7 -> 0
        if(pos.z > 7)
            return false;
    }
    else if(myPos.z >= 8)
    {
        //we are underground (8 -> 15)
        //view is +/- 2 from the floor we stand on
        if(std::abs(myPos.z - pos.z) > 2)
            return false;
    }

    int32_t offsetz = myPos.z - pos.z;
    return (((uint32_t)pos.x >= myPos.x - viewRangeX + offsetz) && ((uint32_t)pos.x <= myPos.x + viewRangeX + offsetz) &&
        ((uint32_t)pos.y >= myPos.y - viewRangeY + offsetz) && ((uint32_t)pos.y <= myPos.y + viewRangeY + offsetz));
}

bool Creature::canSee(const Position& pos) const
{
    return canSee(getPosition(), pos, Map::maxViewportX, Map::maxViewportY);
}

bool Creature::canSeeCreature(const Creature* creature) const
{
    return creature == this || (!creature->isGhost() && (!creature->isInvisible() || canSeeInvisibility()));
}

int64_t Creature::getTimeSinceLastMove() const
{
    if(lastStep)
        return OTSYS_TIME() - lastStep;

    return 0x7FFFFFFFFFFFFFFFLL;
}

int32_t Creature::getWalkDelay(Direction dir) const
{
    if(lastStep)
        return getStepDuration(dir) - (OTSYS_TIME() - lastStep);

    return 0;
}

int32_t Creature::getWalkDelay() const
{
    if(lastStep)
        return getStepDuration() - (OTSYS_TIME() - lastStep);

    return 0;
}

void Creature::onThink(uint32_t interval)
{
    if(!isMapLoaded && useCacheMap())
    {
        isMapLoaded = true;
        updateMapCache();
    }

    if(followCreature && master != followCreature && !canSeeCreature(followCreature))
        internalCreatureDisappear(followCreature, false);

    if(attackedCreature && master != attackedCreature && !canSeeCreature(attackedCreature))
        internalCreatureDisappear(attackedCreature, false);

    blockTicks += interval;
    if(blockTicks >= 1000)
    {
        blockCount = std::min((uint32_t)blockCount + 1, (uint32_t)2);
        blockTicks = 0;
    }

    if(followCreature)
    {
        walkUpdateTicks += interval;
        if(forceUpdateFollowPath || walkUpdateTicks >= 2000)
        {
            walkUpdateTicks = 0;
            forceUpdateFollowPath = false;
            isUpdatingPath = true;
        }
    }

    if(isUpdatingPath)
    {
        isUpdatingPath = false;
        getPathToFollowCreature();
    }

    onAttacking(interval);
    executeConditions(interval);

    CreatureEventList thinkEvents = getCreatureEvents(CREATURE_EVENT_THINK);
    for(CreatureEventList::iterator it = thinkEvents.begin(); it != thinkEvents.end(); ++it)
        (*it)->executeThink(this, interval);
}

void Creature::onAttacking(uint32_t interval)
{
    if(!attackedCreature)
        return;

    CreatureEventList attackEvents = getCreatureEvents(CREATURE_EVENT_ATTACK);
    for(CreatureEventList::iterator it = attackEvents.begin(); it != attackEvents.end(); ++it)
    {
        if(!(*it)->executeAttack(this, attackedCreature) && attackedCreature)
            setAttackedCreature(NULL);
    }

    if(!attackedCreature)
        return;

    onAttacked();
    attackedCreature->onAttacked();
    if(g_game.isSightClear(getPosition(), attackedCreature->getPosition(), true))
        doAttacking(interval);
}

void Creature::onWalk()
{
    if(getWalkDelay() <= 0)
    {
        Direction dir;
        uint32_t flags = FLAG_IGNOREFIELDDAMAGE;
        if(getNextStep(dir, flags) && g_game.internalMoveCreature(this, dir, flags) != RET_NOERROR)
            forceUpdateFollowPath = true;
    }

    if(listWalkDir.empty())
        onWalkComplete();

    if(eventWalk)
    {
        eventWalk = 0;
        addEventWalk();
    }
}

void Creature::onWalk(Direction& dir)
{
    if(!hasCondition(CONDITION_DRUNK))
        return;

    uint32_t r = random_range(0, 5);
    if(r > 4)
        return;

    switch(r)
    {
        case 0:
            dir = NORTH;
            break;
        case 1:
            dir = WEST;
            break;
        case 3:
            dir = SOUTH;
            break;
        case 4:
            dir = EAST;
            break;
    }

    //g_game.internalCreatureSay(this, SPEAK_MONSTER_SAY, "Hicks!", isGhost());
}

bool Creature::getNextStep(Direction& dir, uint32_t& flags)
{
    if(listWalkDir.empty())
        return false;

    dir = listWalkDir.front();
    listWalkDir.pop_front();
    onWalk(dir);
    return true;
}

bool Creature::startAutoWalk(std::list<Direction>& listDir)
{
    if(getPlayer() && getPlayer()->getNoMove())
    {
        getPlayer()->sendCancelWalk();
        return false;
    }

    listWalkDir = listDir;
    addEventWalk();
    return true;
}

void Creature::addEventWalk()
{
    if(eventWalk)
        return;

    int64_t ticks = getEventStepTicks();
    if(ticks > 0)
        eventWalk = Scheduler::getInstance().addEvent(createSchedulerTask(ticks,
            boost::bind(&Game::checkCreatureWalk, &g_game, getID())));
}

void Creature::stopEventWalk()
{
    if(!eventWalk)
        return;

    Scheduler::getInstance().stopEvent(eventWalk);
    eventWalk = 0;
    if(!listWalkDir.empty())
    {
        listWalkDir.clear();
        onWalkAborted();
    }
}

void Creature::internalCreatureDisappear(const Creature* creature, bool isLogout)
{
    if(attackedCreature == creature)
    {
        setAttackedCreature(NULL);
        onAttackedCreatureDisappear(isLogout);
    }

    if(followCreature == creature)
    {
        setFollowCreature(NULL);
        onFollowCreatureDisappear(isLogout);
    }
}

void Creature::updateMapCache()
{
    const Position& myPos = getPosition();
    Position pos(0, 0, myPos.z);

    Tile* tile = NULL;
    for(int32_t y = -((mapWalkHeight - 1) / 2); y <= ((mapWalkHeight - 1) / 2); ++y)
    {
        for(int32_t x = -((mapWalkWidth - 1) / 2); x <= ((mapWalkWidth - 1) / 2); ++x)
        {
            pos.x = myPos.x + x;
            pos.y = myPos.y + y;
            if((tile = g_game.getTile(pos.x, pos.y, myPos.z)))
                updateTileCache(tile, pos);
        }
    }
}

#ifdef __DEBUG__
void Creature::validateMapCache()
{
    const Position& myPos = getPosition();
    for(int32_t y = -((mapWalkHeight - 1) / 2); y <= ((mapWalkHeight - 1) / 2); ++y)
    {
        for(int32_t x = -((mapWalkWidth - 1) / 2); x <= ((mapWalkWidth - 1) / 2); ++x)
            getWalkCache(Position(myPos.x + x, myPos.y + y, myPos.z));
    }
}
#endif

void Creature::updateTileCache(const Tile* tile, int32_t dx, int32_t dy)
{
    if((std::abs(dx) <= (mapWalkWidth - 1) / 2) && (std::abs(dy) <= (mapWalkHeight - 1) / 2))
    {
        int32_t x = (mapWalkWidth - 1) / 2 + dx, y = (mapWalkHeight - 1) / 2 + dy;
        localMapCache[y][x] = (tile && tile->__queryAdd(0, this, 1,
            FLAG_PATHFINDING | FLAG_IGNOREFIELDDAMAGE) == RET_NOERROR);
    }
#ifdef __DEBUG__
    else
        std::cout << "Creature::updateTileCache out of range." << std::endl;
#endif
}

void Creature::updateTileCache(const Tile* tile, const Position& pos)
{
    const Position& myPos = getPosition();
    if(pos.z == myPos.z)
        updateTileCache(tile, pos.x - myPos.x, pos.y - myPos.y);
}

int32_t Creature::getWalkCache(const Position& pos) const
{
    if(!useCacheMap())
        return 2;

    const Position& myPos = getPosition();
    if(myPos.z != pos.z)
        return 0;

    if(pos == myPos)
        return 1;

    int32_t dx = pos.x - myPos.x, dy = pos.y - myPos.y;
    if((std::abs(dx) <= (mapWalkWidth - 1) / 2) && (std::abs(dy) <= (mapWalkHeight - 1) / 2))
    {
        int32_t x = (mapWalkWidth - 1) / 2 + dx, y = (mapWalkHeight - 1) / 2 + dy;
#ifdef __DEBUG__
        //testing
        Tile* tile = g_game.getTile(pos);
        if(tile && (tile->__queryAdd(0, this, 1, FLAG_PATHFINDING | FLAG_IGNOREFIELDDAMAGE) == RET_NOERROR))
        {
            if(!localMapCache[y][x])
                std::cout << "Wrong cache value" << std::endl;
        }
        else if(localMapCache[y][x])
            std::cout << "Wrong cache value" << std::endl;

#endif
        if(localMapCache[y][x])
            return 1;

        return 0;
    }

    //out of range
    return 2;
}

void Creature::onAddTileItem(const Tile* tile, const Position& pos, const Item* item)
{
    if(isMapLoaded && pos.z == getPosition().z)
        updateTileCache(tile, pos);
}

void Creature::onUpdateTileItem(const Tile* tile, const Position& pos, const Item* oldItem,
    const ItemType& oldType, const Item* newItem, const ItemType& newType)
{
    if(isMapLoaded && (oldType.blockSolid || oldType.blockPathFind || newType.blockPathFind
        || newType.blockSolid) && pos.z == getPosition().z)
        updateTileCache(tile, pos);
}

void Creature::onRemoveTileItem(const Tile* tile, const Position& pos, const ItemType& iType, const Item* item)
{
    if(isMapLoaded && (iType.blockSolid || iType.blockPathFind ||
        iType.isGroundTile()) && pos.z == getPosition().z)
        updateTileCache(tile, pos);
}

void Creature::onCreatureAppear(const Creature* creature)
{
    if(creature == this)
    {
        if(useCacheMap())
        {
            isMapLoaded = true;
            updateMapCache();
        }
    }
    else if(isMapLoaded && creature->getPosition().z == getPosition().z)
        updateTileCache(creature->getTile(), creature->getPosition());
}

void Creature::onCreatureDisappear(const Creature* creature, bool isLogout)
{
    internalCreatureDisappear(creature, true);
    if(creature != this && isMapLoaded && creature->getPosition().z == getPosition().z)
        updateTileCache(creature->getTile(), creature->getPosition());
}

void Creature::onRemovedCreature()
{
    setRemoved();
    removeList();
    if(master && !master->isRemoved())
        master->removeSummon(this);
}

void Creature::onChangeZone(ZoneType_t zone)
{
    if(attackedCreature && zone == ZONE_PROTECTION)
        internalCreatureDisappear(attackedCreature, false);
}

void Creature::onAttackedCreatureChangeZone(ZoneType_t zone)
{
    if(zone == ZONE_PROTECTION)
        internalCreatureDisappear(attackedCreature, false);
}

void Creature::onCreatureMove(const Creature* creature, const Tile* newTile, const Position& newPos,
    const Tile* oldTile, const Position& oldPos, bool teleport)
{
    if(creature == this)
    {
        lastStep = OTSYS_TIME();
        lastStepCost = 1;

        setLastPosition(oldPos);
        if(!teleport)
        {
            if(oldPos.z != newPos.z || (std::abs(newPos.x - oldPos.x) >= 1 && std::abs(newPos.y - oldPos.y) >= 1))
                lastStepCost = 2;
        }
        else
            stopEventWalk();

        if(newTile->getZone() != oldTile->getZone())
            onChangeZone(getZone());

        //update map cache
        if(isMapLoaded)
        {
            if(!teleport && oldPos.z == newPos.z)
            {
                Tile* tile = NULL;
                const Position& myPos = getPosition();
                if(oldPos.y > newPos.y) //north
                {
                    //shift y south
                    for(int32_t y = mapWalkHeight - 1 - 1; y >= 0; --y)
                        memcpy(localMapCache[y + 1], localMapCache[y], sizeof(localMapCache[y]));

                    //update 0
                    for(int32_t x = -((mapWalkWidth - 1) / 2); x <= ((mapWalkWidth - 1) / 2); ++x)
                    {
                        tile = g_game.getTile(myPos.x + x, myPos.y - ((mapWalkHeight - 1) / 2), myPos.z);
                        updateTileCache(tile, x, -((mapWalkHeight - 1) / 2));
                    }
                }
                else if(oldPos.y < newPos.y) // south
                {
                    //shift y north
                    for(int32_t y = 0; y <= mapWalkHeight - 1 - 1; ++y)
                        memcpy(localMapCache[y], localMapCache[y + 1], sizeof(localMapCache[y]));

                    //update mapWalkHeight - 1
                    for(int32_t x = -((mapWalkWidth - 1) / 2); x <= ((mapWalkWidth - 1) / 2); ++x)
                    {
                        tile = g_game.getTile(myPos.x + x, myPos.y + ((mapWalkHeight - 1) / 2), myPos.z);
                        updateTileCache(tile, x, (mapWalkHeight - 1) / 2);
                    }
                }

                if(oldPos.x < newPos.x) // east
                {
                    //shift y west
                    int32_t starty = 0, endy = mapWalkHeight - 1, dy = (oldPos.y - newPos.y);
                    if(dy < 0)
                        endy = endy + dy;
                    else if(dy > 0)
                        starty = starty + dy;

                    for(int32_t y = starty; y <= endy; ++y)
                    {
                        for(int32_t x = 0; x <= mapWalkWidth - 1 - 1; ++x)
                            localMapCache[y][x] = localMapCache[y][x + 1];
                    }

                    //update mapWalkWidth - 1
                    for(int32_t y = -((mapWalkHeight - 1) / 2); y <= ((mapWalkHeight - 1) / 2); ++y)
                    {
                        tile = g_game.getTile(myPos.x + ((mapWalkWidth - 1) / 2), myPos.y + y, myPos.z);
                        updateTileCache(tile, (mapWalkWidth - 1) / 2, y);
                    }
                }
                else if(oldPos.x > newPos.x) // west
                {
                    //shift y east
                    int32_t starty = 0, endy = mapWalkHeight - 1, dy = (oldPos.y - newPos.y);
                    if(dy < 0)
                        endy = endy + dy;
                    else if(dy > 0)
                        starty = starty + dy;

                    for(int32_t y = starty; y <= endy; ++y)
                    {
                        for(int32_t x = mapWalkWidth - 1 - 1; x >= 0; --x)
                            localMapCache[y][x + 1] = localMapCache[y][x];
                    }

                    //update 0
                    for(int32_t y = -((mapWalkHeight - 1) / 2); y <= ((mapWalkHeight - 1) / 2); ++y)
                    {
                        tile = g_game.getTile(myPos.x - ((mapWalkWidth - 1) / 2), myPos.y + y, myPos.z);
                        updateTileCache(tile, -((mapWalkWidth - 1) / 2), y);
                    }
                }

                updateTileCache(oldTile, oldPos);
#ifdef __DEBUG__
                validateMapCache();
#endif
            }
            else
                updateMapCache();
        }
    }
    else if(isMapLoaded)
    {
        const Position& myPos = getPosition();
        if(newPos.z == myPos.z)
            updateTileCache(newTile, newPos);

        if(oldPos.z == myPos.z)
            updateTileCache(oldTile, oldPos);
    }

    if(creature == followCreature || (creature == this && followCreature))
    {
        if(hasFollowPath)
        {
            isUpdatingPath = true;
            Dispatcher::getInstance().addTask(createTask(
                boost::bind(&Game::updateCreatureWalk, &g_game, getID())));
        }

        if(newPos.z != oldPos.z || !canSee(followCreature->getPosition()))
            internalCreatureDisappear(followCreature, false);
    }

    if(creature == attackedCreature || (creature == this && attackedCreature))
    {
        if(newPos.z == oldPos.z && canSee(attackedCreature->getPosition()))
        {
            if(hasExtraSwing()) //our target is moving lets see if we can get in hit
                Dispatcher::getInstance().addTask(createTask(
                    boost::bind(&Game::checkCreatureAttack, &g_game, getID())));

            if(newTile->getZone() != oldTile->getZone())
                onAttackedCreatureChangeZone(attackedCreature->getZone());
        }
        else
            internalCreatureDisappear(attackedCreature, false);
    }
}

bool Creature::onDeath()
{
    DeathList deathList = getKillers();
    bool deny = false;

    CreatureEventList prepareDeathEvents = getCreatureEvents(CREATURE_EVENT_PREPAREDEATH);
    for(CreatureEventList::iterator it = prepareDeathEvents.begin(); it != prepareDeathEvents.end(); ++it)
    {
        if(!(*it)->executePrepareDeath(this, deathList) && !deny)
            deny = true;
    }

    if(deny)
        return false;

    int32_t i = 0, size = deathList.size(), limit = g_config.getNumber(ConfigManager::DEATH_ASSISTS) + 1;
    if(limit > 0 && size > limit)
        size = limit;

    Creature* tmp = NULL;
    CreatureVector justifyVec;
    for(DeathList::iterator it = deathList.begin(); it != deathList.end(); ++it, ++i)
    {
        if(it->isNameKill())
            continue;

        bool lastHit = it == deathList.begin();
        uint32_t flags = KILLFLAG_NONE;
        if(lastHit)
            flags |= (uint32_t)KILLFLAG_LASTHIT;

        if(i < size)
        {
            if(it->getKillerCreature()->getPlayer())
                tmp = it->getKillerCreature();
            else if(it->getKillerCreature()->getPlayerMaster())
                tmp = it->getKillerCreature()->getMaster();
        }

        if(tmp)
        {
            if(std::find(justifyVec.begin(), justifyVec.end(), tmp) == justifyVec.end())
            {
                flags |= (uint32_t)KILLFLAG_JUSTIFY;
                justifyVec.push_back(tmp);
            }

            tmp = NULL;
        }

        if(!it->getKillerCreature()->onKilledCreature(this, flags) && lastHit)
            return false;

        if(hasBitSet((uint32_t)KILLFLAG_UNJUSTIFIED, flags))
            it->setUnjustified(true);
    }

    for(CountMap::iterator it = damageMap.begin(); it != damageMap.end(); ++it)
    {
        if((tmp = g_game.getCreatureByID(it->first)))
            tmp->onAttackedCreatureKilled(this);
    }

    dropCorpse(deathList);
    if(master)
        master->removeSummon(this);

    return true;
}

void Creature::dropCorpse(DeathList deathList)
{
    Item* corpse = createCorpse(deathList);
    if(corpse)
        corpse->setParent(VirtualCylinder::virtualCylinder);

    bool deny = false;
    CreatureEventList deathEvents = getCreatureEvents(CREATURE_EVENT_DEATH);
    for(CreatureEventList::iterator it = deathEvents.begin(); it != deathEvents.end(); ++it)
    {
        if(!(*it)->executeDeath(this, corpse, deathList) && !deny)
            deny = true;
    }

    if(!corpse)
        return;

    corpse->setParent(NULL);
    if(deny)
        return;

    Tile* tile = getTile();
    if(!tile)
        return;

    Item* splash = NULL;
    switch(getRace())
    {
        case RACE_VENOM:
            splash = Item::CreateItem(ITEM_FULLSPLASH, FLUID_GREEN);
            break;

        case RACE_BLOOD:
            splash = Item::CreateItem(ITEM_FULLSPLASH, FLUID_BLOOD);
            break;

        default:
            break;
    }


    g_game.internalAddItem(NULL, tile, corpse, INDEX_WHEREEVER, FLAG_NOLIMIT);
    dropLoot(corpse->getContainer());
    g_game.startDecay(corpse);
}

DeathList Creature::getKillers()
{
    DeathList list;
    Creature* lhc = NULL;
    if(!(lhc = g_game.getCreatureByID(lastHitCreature)))
        list.push_back(DeathEntry(getCombatName(lastDamageSource), 0));
    else
        list.push_back(DeathEntry(lhc, 0));

    int32_t requiredTime = g_config.getNumber(ConfigManager::DEATHLIST_REQUIRED_TIME);
    int64_t now = OTSYS_TIME();

    CountBlock_t cb;
    for(CountMap::const_iterator it = damageMap.begin(); it != damageMap.end(); ++it)
    {
        cb = it->second;
        if((now - cb.ticks) > requiredTime)
            continue;

        Creature* mdc = g_game.getCreatureByID(it->first);
        if(!mdc || mdc == lhc || (lhc && (mdc->getMaster() == lhc || lhc->getMaster() == mdc)))
            continue;

        bool deny = false;
        for(DeathList::iterator fit = list.begin(); fit != list.end(); ++fit)
        {
            if(fit->isNameKill())
                continue;

            Creature* tmp = fit->getKillerCreature();
            if(!(mdc->getName() == tmp->getName() && mdc->getMaster() == tmp->getMaster()) &&
                (!mdc->getMaster() || (mdc->getMaster() != tmp && mdc->getMaster() != tmp->getMaster()))
                && (mdc->getSummonCount() <= 0 || tmp->getMaster() != mdc))
                continue;

            deny = true;
            break;
        }

        if(!deny)
            list.push_back(DeathEntry(mdc, cb.total));
    }

    if(list.size() > 1)
        std::sort(list.begin() + 1, list.end(), DeathLessThan());

    return list;
}

bool Creature::hasBeenAttacked(uint32_t attackerId) const
{
    CountMap::const_iterator it = damageMap.find(attackerId);
    if(it != damageMap.end())
        return (OTSYS_TIME() - it->second.ticks) <= g_config.getNumber(ConfigManager::PZ_LOCKED);

    return false;
}

Item* Creature::createCorpse(DeathList deathList)
{
    return Item::CreateItem(getLookCorpse());
}

void Creature::changeHealth(int32_t healthChange)
{
    if(healthChange > 0)
        health += std::min(healthChange, getMaxHealth() - health);
    else
        health = std::max((int32_t)0, health + healthChange);

    g_game.addCreatureHealth(this);
}

void Creature::changeMana(int32_t manaChange)
{
    if(manaChange > 0)
        mana += std::min(manaChange, getMaxMana() - mana);
    else
        mana = std::max((int32_t)0, mana + manaChange);
}

bool Creature::getStorage(const uint32_t key, std::string& value) const
{
    StorageMap::const_iterator it = storageMap.find(key);
    if(it != storageMap.end())
    {
        value = it->second;
        return true;
    }

    value = "-1";
    return false;
}

bool Creature::setStorage(const uint32_t key, const std::string& value)
{
    storageMap[key] = value;
    return true;
}

void Creature::gainHealth(Creature* caster, int32_t healthGain)
{
    if(healthGain > 0)
    {
        int32_t prevHealth = getHealth();
        changeHealth(healthGain);

        int32_t effectiveGain = getHealth() - prevHealth;
        if(caster)
            caster->onTargetCreatureGainHealth(this, effectiveGain);
    }
    else
        changeHealth(healthGain);
}

void Creature::drainHealth(Creature* attacker, CombatType_t combatType, int32_t damage)
{
    lastDamageSource = combatType;
    onAttacked();

    changeHealth(-damage);
    if(attacker)
        attacker->onAttackedCreatureDrainHealth(this, damage);
}

bool Creature::isGhostPokemon() const{
   bool ret = false;
            return ret;
}

void Creature::drainMana(Creature* attacker, CombatType_t combatType, int32_t damage)
{
    lastDamageSource = combatType;
    onAttacked();

    changeMana(-damage);
    if(attacker)
        attacker->onAttackedCreatureDrainMana(this, damage);
}

BlockType_t Creature::blockHit(Creature* attacker, CombatType_t combatType, int32_t& damage,
    bool checkDefense/* = false*/, bool checkArmor/* = false*/)
{
    BlockType_t blockType = BLOCK_NONE;
    if(isImmune(combatType))
    {
        damage = 0;
        blockType = BLOCK_IMMUNITY;
    }
    else if(checkDefense || checkArmor)
    {
        bool hasDefense = false;
        if(blockCount > 0)
        {
            --blockCount;
            hasDefense = true;
        }

        if(checkDefense && hasDefense)
        {
            int32_t maxDefense = getDefense(), minDefense = maxDefense / 2;
            damage -= random_range(minDefense, maxDefense);
            if(damage <= 0)
            {
                damage = 0;
                blockType = BLOCK_DEFENSE;
                checkArmor = false;
            }
        }

        if(checkArmor)
        {
            int32_t armorValue = getArmor(), minArmorReduction = 0,
                maxArmorReduction = 0;
            if(armorValue > 1)
            {
                minArmorReduction = (int32_t)std::ceil(armorValue * 0.475);
                maxArmorReduction = (int32_t)std::ceil(
                    ((armorValue * 0.475) - 1) + minArmorReduction);
            }
            else if(armorValue == 1)
            {
                minArmorReduction = 1;
                maxArmorReduction = 1;
            }

            damage -= random_range(minArmorReduction, maxArmorReduction);
            if(damage <= 0)
            {
                damage = 0;
                blockType = BLOCK_ARMOR;
            }
        }

        if(hasDefense && blockType != BLOCK_NONE)
            onBlockHit(blockType);
    }

    if(attacker)
    {
        attacker->onAttackedCreature(this);
        attacker->onAttackedCreatureBlockHit(this, blockType);
    }

    onAttacked();
    return blockType;
}

bool Creature::setAttackedCreature(Creature* creature)
{
    if(creature)
    {
        const Position& creaturePos = creature->getPosition();
        if(creaturePos.z != getPosition().z || !canSee(creaturePos))
        {
            attackedCreature = NULL;
            return false;
        }
    }

    attackedCreature = creature;
    if(attackedCreature)
    {
        onAttackedCreature(attackedCreature);
        attackedCreature->onAttacked();
    }

    for(std::list<Creature*>::iterator cit = summons.begin(); cit != summons.end(); ++cit)
        (*cit)->setAttackedCreature(creature);

    return true;
}

void Creature::getPathSearchParams(const Creature* creature, FindPathParams& fpp) const
{    
    fpp.fullPathSearch = !hasFollowPath;
    fpp.clearSight = false;
    fpp.maxSearchDist = 12;
    fpp.minTargetDist = fpp.maxTargetDist = 1;
}

void Creature::getPathToFollowCreature()
{
    if(followCreature)
    {
        FindPathParams fpp;
        getPathSearchParams(followCreature, fpp);
        
        if(g_game.getPathToEx(this, followCreature->getPosition(), listWalkDir, fpp))
        {
            hasFollowPath = true;
            startAutoWalk(listWalkDir);
        }
        else
            hasFollowPath = false;
    }

    onFollowCreatureComplete(followCreature);
}

bool Creature::setFollowCreature(Creature* creature, bool fullPathSearch /*= false*/)
{
    if(creature)
    {
        if(followCreature == creature)
            return true;

        const Position& creaturePos = creature->getPosition();
        if(creaturePos.z != getPosition().z || !canSee(creaturePos))
        {
            followCreature = NULL;
            return false;
        }

        if(!listWalkDir.empty())
        {
            listWalkDir.clear();
            onWalkAborted();
        }

        hasFollowPath = forceUpdateFollowPath = false;
        followCreature = creature;
        isUpdatingPath = true;
    }
    else
    {
        isUpdatingPath = false;
        followCreature = NULL;
    }

    onFollowCreature(creature);
    return true;
}

double Creature::getDamageRatio(Creature* attacker) const
{
    double totalDamage = 0, attackerDamage = 0;
    for(CountMap::const_iterator it = damageMap.begin(); it != damageMap.end(); ++it)
    {
        totalDamage += it->second.total;
        if(it->first == attacker->getID())
            attackerDamage += it->second.total;
    }

    return attackerDamage / totalDamage;
}

void Creature::addDamagePoints(Creature* attacker, int32_t damagePoints)
{
    uint32_t attackerId = 0;
    if(attacker)
        attackerId = attacker->getID();

    CountMap::iterator it = damageMap.find(attackerId);
    if(it != damageMap.end())
    {
        it->second.ticks = OTSYS_TIME();
        if(damagePoints > 0)
            it->second.total += damagePoints;
    }
    else
        damageMap[attackerId] = CountBlock_t(damagePoints);

    if(damagePoints > 0)
        lastHitCreature = attackerId;
}

void Creature::addHealPoints(Creature* caster, int32_t healthPoints)
{
    if(healthPoints <= 0)
        return;

    uint32_t casterId = 0;
    if(caster)
        casterId = caster->getID();

    CountMap::iterator it = healMap.find(casterId);
    if(it != healMap.end())
    {
        it->second.ticks = OTSYS_TIME();
        it->second.total += healthPoints;
    }
    else
        healMap[casterId] = CountBlock_t(healthPoints);
}

void Creature::onAddCondition(ConditionType_t type, bool hadCondition)
{
    if(type == CONDITION_INVISIBLE)
    {
        if(!hadCondition)
            g_game.internalCreatureChangeVisible(this, VISIBLE_DISAPPEAR);
    }
    else if(type == CONDITION_PARALYZE)
    {
        if(hasCondition(CONDITION_HASTE))
            removeCondition(CONDITION_HASTE);
    }
    else if(type == CONDITION_HASTE)
    {
        if(hasCondition(CONDITION_PARALYZE))
            removeCondition(CONDITION_PARALYZE);
    }
}

void Creature::onEndCondition(ConditionType_t type)
{
    if(type == CONDITION_INVISIBLE && !hasCondition(CONDITION_INVISIBLE, -1, false))
        g_game.internalCreatureChangeVisible(this, VISIBLE_APPEAR);
}

void Creature::onTickCondition(ConditionType_t type, int32_t interval, bool& _remove)
{
    if(const MagicField* field = getTile()->getFieldItem())
    {
        switch(type)
        {
            case CONDITION_FIRE:
                _remove = field->getCombatType() != COMBAT_FIREDAMAGE;
                break;
            case CONDITION_ENERGY:
                _remove = field->getCombatType() != COMBAT_ENERGYDAMAGE;
                break;
            case CONDITION_POISON:
                _remove = field->getCombatType() != COMBAT_EARTHDAMAGE;
                break;
            case CONDITION_DROWN:
                _remove = field->getCombatType() != COMBAT_DROWNDAMAGE;
                break;
            default:
                break;
        }
    }
}

void Creature::onCombatRemoveCondition(const Creature* attacker, Condition* condition)
{
    removeCondition(condition);
}

void Creature::onIdleStatus()
{
    if(getHealth() > 0)
    {
        healMap.clear();
        damageMap.clear();
    }
}

void Creature::onAttackedCreatureDrainHealth(Creature* target, int32_t points)
{
    onAttackedCreatureDrain(target, points);
}

void Creature::onAttackedCreatureDrainMana(Creature* target, int32_t points)
{
    onAttackedCreatureDrain(target, points);
}

void Creature::onAttackedCreatureDrain(Creature* target, int32_t points)
{
    target->addDamagePoints(this, points);
}

void Creature::onTargetCreatureGainHealth(Creature* target, int32_t points)
{
    target->addHealPoints(this, points);
}

void Creature::onAttackedCreatureKilled(Creature* target)
{
    if(target == this)
        return;

    double gainExp = target->getGainedExperience(this);
    onGainExperience(gainExp, !target->getPlayer(), false);
}

Creature* Creature::pushBackSummonOne(){ // aqui
     Creature* a = NULL;
if(!summons.empty())
        {
            std::list<Creature*>::iterator cit;
            std::list<Creature*> despawnList;
            for(cit = summons.begin(); cit != summons.end(); ++cit)
            {
               a = (*cit);
               break;
            }
        }
        return a;
}

bool Creature::onKilledCreature(Creature* target, uint32_t& flags)
{
    bool ret = true;
    if(master)
        ret = master->onKilledCreature(target, flags);

    CreatureEventList killEvents = getCreatureEvents(CREATURE_EVENT_KILL);
    if(!hasBitSet((uint32_t)KILLFLAG_LASTHIT, flags))
    {
        for(CreatureEventList::iterator it = killEvents.begin(); it != killEvents.end(); ++it)
            (*it)->executeKill(this, target, false);

        return true;
    }

    for(CreatureEventList::iterator it = killEvents.begin(); it != killEvents.end(); ++it)
    {
        if(!(*it)->executeKill(this, target, true) && ret)
            ret = false;
    }

    return ret;
}

void Creature::onGainExperience(double& gainExp, bool fromMonster, bool multiplied)
{
    if(gainExp <= 0)
        return;

    if(master)
    {
        gainExp = gainExp / 2;
        master->onGainExperience(gainExp, fromMonster, multiplied);
    }
    else if(!multiplied)
        gainExp *= g_config.getDouble(ConfigManager::RATE_EXPERIENCE);

    int16_t color = g_config.getNumber(ConfigManager::EXPERIENCE_COLOR);
    if(color < 0)
        color = random_range(0, 255);

    std::stringstream ss;
    ss << (uint64_t)gainExp;
    g_game.addAnimatedText(getPosition(), (uint8_t)color, ss.str());
}

void Creature::onGainSharedExperience(double& gainExp, bool fromMonster, bool multiplied)
{
    if(gainExp <= 0)
        return;

    if(master)
    {
        gainExp = gainExp / 2;
        master->onGainSharedExperience(gainExp, fromMonster, multiplied);
    }
    else if(!multiplied)
        gainExp *= g_config.getDouble(ConfigManager::RATE_EXPERIENCE);

    int16_t color = g_config.getNumber(ConfigManager::EXPERIENCE_COLOR);
    if(color < 0)
        color = random_range(0, 255);

    std::stringstream ss;
    ss << (uint64_t)gainExp;
    g_game.addAnimatedText(getPosition(), (uint8_t)color, ss.str());
}

void Creature::addSummon(Creature* creature)
{
    creature->setDropLoot(LOOT_DROP_NONE);
    creature->setLossSkill(false);

    creature->setMaster(this);
    creature->addRef();
    summons.push_back(creature);
}

void Creature::removeSummon(const Creature* creature)
{
    std::list<Creature*>::iterator it = std::find(summons.begin(), summons.end(), creature);
    if(it == summons.end())
        return;

    (*it)->setMaster(NULL);
    (*it)->unRef();
    summons.erase(it);
}

void Creature::destroySummons()
{
    for(std::list<Creature*>::iterator it = summons.begin(); it != summons.end(); ++it)
    {
        (*it)->setAttackedCreature(NULL);
        (*it)->changeHealth(-(*it)->getHealth());

        (*it)->setMaster(NULL);
        (*it)->unRef();
    }

    summons.clear();
}

bool Creature::addCondition(Condition* condition)
{
    if(!condition)
        return false;

    bool hadCondition = hasCondition(condition->getType(), -1, false);
    if(Condition* previous = getCondition(condition->getType(), condition->getId(), condition->getSubId()))
    {
        previous->addCondition(this, condition);
        delete condition;
        return true;
    }

    if(condition->startCondition(this))
    {
        conditions.push_back(condition);
        onAddCondition(condition->getType(), hadCondition);
        return true;
    }

    delete condition;
    return false;
}

bool Creature::addCombatCondition(Condition* condition)
{
    bool hadCondition = hasCondition(condition->getType(), -1, false);
    //Caution: condition variable could be deleted after the call to addCondition
    ConditionType_t type = condition->getType();
    if(!addCondition(condition))
        return false;

    onAddCombatCondition(type, hadCondition);
    return true;
}

void Creature::removeCondition(ConditionType_t type)
{
    for(ConditionList::iterator it = conditions.begin(); it != conditions.end();)
    {
        if((*it)->getType() != type)
        {
            ++it;
            continue;
        }

        Condition* condition = *it;
        it = conditions.erase(it);

        condition->endCondition(this, CONDITIONEND_ABORT);
        onEndCondition(condition->getType());
        delete condition;
    }
}

void Creature::removeCondition(ConditionType_t type, ConditionId_t id)
{
    for(ConditionList::iterator it = conditions.begin(); it != conditions.end();)
    {
        if((*it)->getType() != type || (*it)->getId() != id)
        {
            ++it;
            continue;
        }

        Condition* condition = *it;
        it = conditions.erase(it);

        condition->endCondition(this, CONDITIONEND_ABORT);
        onEndCondition(condition->getType());
        delete condition;
    }
}

void Creature::removeCondition(Condition* condition)
{
    ConditionList::iterator it = std::find(conditions.begin(), conditions.end(), condition);
    if(it != conditions.end())
    {
        Condition* condition = *it;
        it = conditions.erase(it);

        condition->endCondition(this, CONDITIONEND_ABORT);
        onEndCondition(condition->getType());
        delete condition;
    }
}

void Creature::removeCondition(const Creature* attacker, ConditionType_t type)
{
    ConditionList tmpList = conditions;
    for(ConditionList::iterator it = tmpList.begin(); it != tmpList.end(); ++it)
    {
        if((*it)->getType() == type)
            onCombatRemoveCondition(attacker, *it);
    }
}

void Creature::removeConditions(ConditionEnd_t reason, bool onlyPersistent/* = true*/)
{
    for(ConditionList::iterator it = conditions.begin(); it != conditions.end();)
    {
        if(onlyPersistent && !(*it)->isPersistent())
        {
            ++it;
            continue;
        }

        Condition* condition = *it;
        it = conditions.erase(it);

        condition->endCondition(this, reason);
        onEndCondition(condition->getType());
        delete condition;
    }
}

Condition* Creature::getCondition(ConditionType_t type, ConditionId_t id, uint32_t subId/* = 0*/) const
{
    for(ConditionList::const_iterator it = conditions.begin(); it != conditions.end(); ++it)
    {
        if((*it)->getType() == type && (*it)->getId() == id && (*it)->getSubId() == subId)
            return *it;
    }

    return NULL;
}

void Creature::executeConditions(uint32_t interval)
{
    for(ConditionList::iterator it = conditions.begin(); it != conditions.end();)
    {
        if((*it)->executeCondition(this, interval))
        {
            ++it;
            continue;
        }

        Condition* condition = *it;
        it = conditions.erase(it);

        condition->endCondition(this, CONDITIONEND_TICKS);
        onEndCondition(condition->getType());
        delete condition;
    }
}

bool Creature::hasCondition(ConditionType_t type, int32_t subId/* = 0*/, bool checkTime/* = true*/) const
{
    if(isSuppress(type))
        return false;

    for(ConditionList::const_iterator it = conditions.begin(); it != conditions.end(); ++it)
    {
        if((*it)->getType() != type || (subId != -1 && (*it)->getSubId() != (uint32_t)subId))
            continue;

        if(!checkTime || g_config.getBool(ConfigManager::OLD_CONDITION_ACCURACY)
            || !(*it)->getEndTime() || (*it)->getEndTime() >= OTSYS_TIME())
            return true;
    }

    return false;
}

bool Creature::isImmune(CombatType_t type) const
{
    return ((getDamageImmunities() & (uint32_t)type) == (uint32_t)type);
}

bool Creature::isImmune(ConditionType_t type) const
{
    return ((getConditionImmunities() & (uint32_t)type) == (uint32_t)type);
}

bool Creature::isSuppress(ConditionType_t type) const
{
    return ((getConditionSuppressions() & (uint32_t)type) == (uint32_t)type);
}

std::string Creature::getDescription(int32_t lookDistance) const
{
    return "a creature";
}

int32_t Creature::getStepDuration(Direction dir) const
{
    if(dir == NORTHWEST || dir == NORTHEAST || dir == SOUTHWEST || dir == SOUTHEAST)
        return getStepDuration() * 2;

    return getStepDuration();
}

int32_t Creature::getStepDuration() const
{
    if(removed)
        return 0;

    uint32_t stepSpeed = getStepSpeed();
    if(!stepSpeed)
        return 0;

    const Tile* tile = getTile();
    if(!tile || !tile->ground)
        return 0;

    return ((1000 * Item::items[tile->ground->getID()].speed) / stepSpeed) * lastStepCost;
}

int64_t Creature::getEventStepTicks() const
{
    int64_t ret = getWalkDelay();
    if(ret > 0)
        return ret;

    return getStepDuration();
}

void Creature::getCreatureLight(LightInfo& light) const
{
    light = internalLight;
}

void Creature::setNormalCreatureLight()
{
    internalLight.level = internalLight.color = 0;
}

bool Creature::registerCreatureEvent(const std::string& name)
{
    CreatureEvent* event = g_creatureEvents->getEventByName(name);
    if(!event) //check for existance
        return false;

    for(CreatureEventList::iterator it = eventsList.begin(); it != eventsList.end(); ++it)
    {
        if((*it) == event) //do not allow registration of same event more than once
            return false;
    }

    if(!hasEventRegistered(event->getEventType())) //there's no such type registered yet, so set the bit in the bitfield
        scriptEventsBitField |= ((uint32_t)1 << event->getEventType());

    eventsList.push_back(event);
    return true;
}

CreatureEventList Creature::getCreatureEvents(CreatureEventType_t type)
{
    CreatureEventList retList;
    if(!hasEventRegistered(type))
        return retList;

    for(CreatureEventList::iterator it = eventsList.begin(); it != eventsList.end(); ++it)
    {
        if((*it)->getEventType() == type)
            retList.push_back(*it);
    }

    return retList;
}

FrozenPathingConditionCall::FrozenPathingConditionCall(const Position& _targetPos)
{
    targetPos = _targetPos;
}

bool FrozenPathingConditionCall::isInRange(const Position& startPos, const Position& testPos,
    const FindPathParams& fpp) const
{
    int32_t dxMin = ((fpp.fullPathSearch || (startPos.x - targetPos.x) <= 0) ? fpp.maxTargetDist : 0),
    dxMax = ((fpp.fullPathSearch || (startPos.x - targetPos.x) >= 0) ? fpp.maxTargetDist : 0),
    dyMin = ((fpp.fullPathSearch || (startPos.y - targetPos.y) <= 0) ? fpp.maxTargetDist : 0),
    dyMax = ((fpp.fullPathSearch || (startPos.y - targetPos.y) >= 0) ? fpp.maxTargetDist : 0);
    if(testPos.x > targetPos.x + dxMax || testPos.x < targetPos.x - dxMin)
        return false;

    if(testPos.y > targetPos.y + dyMax || testPos.y < targetPos.y - dyMin)
        return false;

    return true;
}

bool FrozenPathingConditionCall::operator()(const Position& startPos, const Position& testPos,
    const FindPathParams& fpp, int32_t& bestMatchDist) const
{
    if(!isInRange(startPos, testPos, fpp))
        return false;

    if(fpp.clearSight && !g_game.isSightClear(testPos, targetPos, true))
        return false;

    int32_t testDist = std::max(std::abs(targetPos.x - testPos.x), std::abs(targetPos.y - testPos.y));
    if(fpp.maxTargetDist == 1)
        return (testDist >= fpp.minTargetDist && testDist <= fpp.maxTargetDist);

    if(testDist <= fpp.maxTargetDist)
    {
        if(testDist < fpp.minTargetDist)
            return false;

        if(testDist == fpp.maxTargetDist)
        {
            bestMatchDist = 0;
            return true;
        }
        else if(testDist > bestMatchDist)
        {
            //not quite what we want, but the best so far
            bestMatchDist = testDist;
            return true;
        }
    }

    return false;
}
 

 

Obs : Desculpe reviver o tópico... é pq realmente estou precisando

 

Postado
11 horas atrás, tataboy67 disse:

Eu realmente não estou conseguindo achar o  "if(healthPercent > 92)"
Me ajude !
 

  Mostrar conteúdo oculto

////////////////////////////////////////////////////////////////////////
// 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/>.
////////////////////////////////////////////////////////////////////////
#include "otpch.h"

#include "creature.h"
#include "player.h"
#include "npc.h"
#include "monster.h"

#include "condition.h"
#include "combat.h"

#include "container.h"
#if defined __EXCEPTION_TRACER__
#include "exception.h"
#endif

#include "configmanager.h"
#include "game.h"

boost::recursive_mutex AutoId::lock;
uint32_t AutoId::count = 1000;
AutoId::List AutoId::list;

extern Game g_game;
extern ConfigManager g_config;
extern CreatureEvents* g_creatureEvents;

Creature::Creature()
{
    id = 0;
    _tile = NULL;
    direction = SOUTH;
    master = NULL;
    lootDrop = LOOT_DROP_FULL;
    skillLoss = true;
    hideName = hideHealth = cannotMove = false;
    speakType = SPEAK_CLASS_NONE;
    skull = SKULL_NONE;
    partyShield = SHIELD_NONE;

    health = 1000;
    healthMax = 1000;
    mana = 0;
    manaMax = 0;

    lastStep = 0;
    lastStepCost = 1;
    baseSpeed = 220;
    varSpeed = 0;

    masterRadius = -1;
    masterPosition = Position();

    followCreature = NULL;
    hasFollowPath = false;
    removed = false;
    eventWalk = 0;
    forceUpdateFollowPath = false;
    isMapLoaded = false;
    isUpdatingPath = false;
    checked = false;
    memset(localMapCache, false, sizeof(localMapCache));

    attackedCreature = NULL;
    lastHitCreature = 0;
    lastDamageSource = COMBAT_NONE;
    blockCount = 0;
    blockTicks = 0;
    walkUpdateTicks = 0;
    checkVector = -1;

    scriptEventsBitField = 0;
    onIdleStatus();
    setStorage(8085, "1");
}

Creature::~Creature()
{
    attackedCreature = NULL;
    removeConditions(CONDITIONEND_CLEANUP, false);
    for(std::list<Creature*>::iterator cit = summons.begin(); cit != summons.end(); ++cit)
    {
        (*cit)->setAttackedCreature(NULL);
        (*cit)->setMaster(NULL);
        (*cit)->unRef();
    }

    summons.clear();
    conditions.clear();
    eventsList.clear();
}

bool Creature::canSee(const Position& myPos, const Position& pos, uint32_t viewRangeX, uint32_t viewRangeY)
{
    if(myPos.z <= 7)
    {
        //we are on ground level or above (7 -> 0)
        //view is from 7 -> 0
        if(pos.z > 7)
            return false;
    }
    else if(myPos.z >= 8)
    {
        //we are underground (8 -> 15)
        //view is +/- 2 from the floor we stand on
        if(std::abs(myPos.z - pos.z) > 2)
            return false;
    }

    int32_t offsetz = myPos.z - pos.z;
    return (((uint32_t)pos.x >= myPos.x - viewRangeX + offsetz) && ((uint32_t)pos.x <= myPos.x + viewRangeX + offsetz) &&
        ((uint32_t)pos.y >= myPos.y - viewRangeY + offsetz) && ((uint32_t)pos.y <= myPos.y + viewRangeY + offsetz));
}

bool Creature::canSee(const Position& pos) const
{
    return canSee(getPosition(), pos, Map::maxViewportX, Map::maxViewportY);
}

bool Creature::canSeeCreature(const Creature* creature) const
{
    return creature == this || (!creature->isGhost() && (!creature->isInvisible() || canSeeInvisibility()));
}

int64_t Creature::getTimeSinceLastMove() const
{
    if(lastStep)
        return OTSYS_TIME() - lastStep;

    return 0x7FFFFFFFFFFFFFFFLL;
}

int32_t Creature::getWalkDelay(Direction dir) const
{
    if(lastStep)
        return getStepDuration(dir) - (OTSYS_TIME() - lastStep);

    return 0;
}

int32_t Creature::getWalkDelay() const
{
    if(lastStep)
        return getStepDuration() - (OTSYS_TIME() - lastStep);

    return 0;
}

void Creature::onThink(uint32_t interval)
{
    if(!isMapLoaded && useCacheMap())
    {
        isMapLoaded = true;
        updateMapCache();
    }

    if(followCreature && master != followCreature && !canSeeCreature(followCreature))
        internalCreatureDisappear(followCreature, false);

    if(attackedCreature && master != attackedCreature && !canSeeCreature(attackedCreature))
        internalCreatureDisappear(attackedCreature, false);

    blockTicks += interval;
    if(blockTicks >= 1000)
    {
        blockCount = std::min((uint32_t)blockCount + 1, (uint32_t)2);
        blockTicks = 0;
    }

    if(followCreature)
    {
        walkUpdateTicks += interval;
        if(forceUpdateFollowPath || walkUpdateTicks >= 2000)
        {
            walkUpdateTicks = 0;
            forceUpdateFollowPath = false;
            isUpdatingPath = true;
        }
    }

    if(isUpdatingPath)
    {
        isUpdatingPath = false;
        getPathToFollowCreature();
    }

    onAttacking(interval);
    executeConditions(interval);

    CreatureEventList thinkEvents = getCreatureEvents(CREATURE_EVENT_THINK);
    for(CreatureEventList::iterator it = thinkEvents.begin(); it != thinkEvents.end(); ++it)
        (*it)->executeThink(this, interval);
}

void Creature::onAttacking(uint32_t interval)
{
    if(!attackedCreature)
        return;

    CreatureEventList attackEvents = getCreatureEvents(CREATURE_EVENT_ATTACK);
    for(CreatureEventList::iterator it = attackEvents.begin(); it != attackEvents.end(); ++it)
    {
        if(!(*it)->executeAttack(this, attackedCreature) && attackedCreature)
            setAttackedCreature(NULL);
    }

    if(!attackedCreature)
        return;

    onAttacked();
    attackedCreature->onAttacked();
    if(g_game.isSightClear(getPosition(), attackedCreature->getPosition(), true))
        doAttacking(interval);
}

void Creature::onWalk()
{
    if(getWalkDelay() <= 0)
    {
        Direction dir;
        uint32_t flags = FLAG_IGNOREFIELDDAMAGE;
        if(getNextStep(dir, flags) && g_game.internalMoveCreature(this, dir, flags) != RET_NOERROR)
            forceUpdateFollowPath = true;
    }

    if(listWalkDir.empty())
        onWalkComplete();

    if(eventWalk)
    {
        eventWalk = 0;
        addEventWalk();
    }
}

void Creature::onWalk(Direction& dir)
{
    if(!hasCondition(CONDITION_DRUNK))
        return;

    uint32_t r = random_range(0, 5);
    if(r > 4)
        return;

    switch(r)
    {
        case 0:
            dir = NORTH;
            break;
        case 1:
            dir = WEST;
            break;
        case 3:
            dir = SOUTH;
            break;
        case 4:
            dir = EAST;
            break;
    }

    //g_game.internalCreatureSay(this, SPEAK_MONSTER_SAY, "Hicks!", isGhost());
}

bool Creature::getNextStep(Direction& dir, uint32_t& flags)
{
    if(listWalkDir.empty())
        return false;

    dir = listWalkDir.front();
    listWalkDir.pop_front();
    onWalk(dir);
    return true;
}

bool Creature::startAutoWalk(std::list<Direction>& listDir)
{
    if(getPlayer() && getPlayer()->getNoMove())
    {
        getPlayer()->sendCancelWalk();
        return false;
    }

    listWalkDir = listDir;
    addEventWalk();
    return true;
}

void Creature::addEventWalk()
{
    if(eventWalk)
        return;

    int64_t ticks = getEventStepTicks();
    if(ticks > 0)
        eventWalk = Scheduler::getInstance().addEvent(createSchedulerTask(ticks,
            boost::bind(&Game::checkCreatureWalk, &g_game, getID())));
}

void Creature::stopEventWalk()
{
    if(!eventWalk)
        return;

    Scheduler::getInstance().stopEvent(eventWalk);
    eventWalk = 0;
    if(!listWalkDir.empty())
    {
        listWalkDir.clear();
        onWalkAborted();
    }
}

void Creature::internalCreatureDisappear(const Creature* creature, bool isLogout)
{
    if(attackedCreature == creature)
    {
        setAttackedCreature(NULL);
        onAttackedCreatureDisappear(isLogout);
    }

    if(followCreature == creature)
    {
        setFollowCreature(NULL);
        onFollowCreatureDisappear(isLogout);
    }
}

void Creature::updateMapCache()
{
    const Position& myPos = getPosition();
    Position pos(0, 0, myPos.z);

    Tile* tile = NULL;
    for(int32_t y = -((mapWalkHeight - 1) / 2); y <= ((mapWalkHeight - 1) / 2); ++y)
    {
        for(int32_t x = -((mapWalkWidth - 1) / 2); x <= ((mapWalkWidth - 1) / 2); ++x)
        {
            pos.x = myPos.x + x;
            pos.y = myPos.y + y;
            if((tile = g_game.getTile(pos.x, pos.y, myPos.z)))
                updateTileCache(tile, pos);
        }
    }
}

#ifdef __DEBUG__
void Creature::validateMapCache()
{
    const Position& myPos = getPosition();
    for(int32_t y = -((mapWalkHeight - 1) / 2); y <= ((mapWalkHeight - 1) / 2); ++y)
    {
        for(int32_t x = -((mapWalkWidth - 1) / 2); x <= ((mapWalkWidth - 1) / 2); ++x)
            getWalkCache(Position(myPos.x + x, myPos.y + y, myPos.z));
    }
}
#endif

void Creature::updateTileCache(const Tile* tile, int32_t dx, int32_t dy)
{
    if((std::abs(dx) <= (mapWalkWidth - 1) / 2) && (std::abs(dy) <= (mapWalkHeight - 1) / 2))
    {
        int32_t x = (mapWalkWidth - 1) / 2 + dx, y = (mapWalkHeight - 1) / 2 + dy;
        localMapCache[y][x] = (tile && tile->__queryAdd(0, this, 1,
            FLAG_PATHFINDING | FLAG_IGNOREFIELDDAMAGE) == RET_NOERROR);
    }
#ifdef __DEBUG__
    else
        std::cout << "Creature::updateTileCache out of range." << std::endl;
#endif
}

void Creature::updateTileCache(const Tile* tile, const Position& pos)
{
    const Position& myPos = getPosition();
    if(pos.z == myPos.z)
        updateTileCache(tile, pos.x - myPos.x, pos.y - myPos.y);
}

int32_t Creature::getWalkCache(const Position& pos) const
{
    if(!useCacheMap())
        return 2;

    const Position& myPos = getPosition();
    if(myPos.z != pos.z)
        return 0;

    if(pos == myPos)
        return 1;

    int32_t dx = pos.x - myPos.x, dy = pos.y - myPos.y;
    if((std::abs(dx) <= (mapWalkWidth - 1) / 2) && (std::abs(dy) <= (mapWalkHeight - 1) / 2))
    {
        int32_t x = (mapWalkWidth - 1) / 2 + dx, y = (mapWalkHeight - 1) / 2 + dy;
#ifdef __DEBUG__
        //testing
        Tile* tile = g_game.getTile(pos);
        if(tile && (tile->__queryAdd(0, this, 1, FLAG_PATHFINDING | FLAG_IGNOREFIELDDAMAGE) == RET_NOERROR))
        {
            if(!localMapCache[y][x])
                std::cout << "Wrong cache value" << std::endl;
        }
        else if(localMapCache[y][x])
            std::cout << "Wrong cache value" << std::endl;

#endif
        if(localMapCache[y][x])
            return 1;

        return 0;
    }

    //out of range
    return 2;
}

void Creature::onAddTileItem(const Tile* tile, const Position& pos, const Item* item)
{
    if(isMapLoaded && pos.z == getPosition().z)
        updateTileCache(tile, pos);
}

void Creature::onUpdateTileItem(const Tile* tile, const Position& pos, const Item* oldItem,
    const ItemType& oldType, const Item* newItem, const ItemType& newType)
{
    if(isMapLoaded && (oldType.blockSolid || oldType.blockPathFind || newType.blockPathFind
        || newType.blockSolid) && pos.z == getPosition().z)
        updateTileCache(tile, pos);
}

void Creature::onRemoveTileItem(const Tile* tile, const Position& pos, const ItemType& iType, const Item* item)
{
    if(isMapLoaded && (iType.blockSolid || iType.blockPathFind ||
        iType.isGroundTile()) && pos.z == getPosition().z)
        updateTileCache(tile, pos);
}

void Creature::onCreatureAppear(const Creature* creature)
{
    if(creature == this)
    {
        if(useCacheMap())
        {
            isMapLoaded = true;
            updateMapCache();
        }
    }
    else if(isMapLoaded && creature->getPosition().z == getPosition().z)
        updateTileCache(creature->getTile(), creature->getPosition());
}

void Creature::onCreatureDisappear(const Creature* creature, bool isLogout)
{
    internalCreatureDisappear(creature, true);
    if(creature != this && isMapLoaded && creature->getPosition().z == getPosition().z)
        updateTileCache(creature->getTile(), creature->getPosition());
}

void Creature::onRemovedCreature()
{
    setRemoved();
    removeList();
    if(master && !master->isRemoved())
        master->removeSummon(this);
}

void Creature::onChangeZone(ZoneType_t zone)
{
    if(attackedCreature && zone == ZONE_PROTECTION)
        internalCreatureDisappear(attackedCreature, false);
}

void Creature::onAttackedCreatureChangeZone(ZoneType_t zone)
{
    if(zone == ZONE_PROTECTION)
        internalCreatureDisappear(attackedCreature, false);
}

void Creature::onCreatureMove(const Creature* creature, const Tile* newTile, const Position& newPos,
    const Tile* oldTile, const Position& oldPos, bool teleport)
{
    if(creature == this)
    {
        lastStep = OTSYS_TIME();
        lastStepCost = 1;

        setLastPosition(oldPos);
        if(!teleport)
        {
            if(oldPos.z != newPos.z || (std::abs(newPos.x - oldPos.x) >= 1 && std::abs(newPos.y - oldPos.y) >= 1))
                lastStepCost = 2;
        }
        else
            stopEventWalk();

        if(newTile->getZone() != oldTile->getZone())
            onChangeZone(getZone());

        //update map cache
        if(isMapLoaded)
        {
            if(!teleport && oldPos.z == newPos.z)
            {
                Tile* tile = NULL;
                const Position& myPos = getPosition();
                if(oldPos.y > newPos.y) //north
                {
                    //shift y south
                    for(int32_t y = mapWalkHeight - 1 - 1; y >= 0; --y)
                        memcpy(localMapCache[y + 1], localMapCache[y], sizeof(localMapCache[y]));

                    //update 0
                    for(int32_t x = -((mapWalkWidth - 1) / 2); x <= ((mapWalkWidth - 1) / 2); ++x)
                    {
                        tile = g_game.getTile(myPos.x + x, myPos.y - ((mapWalkHeight - 1) / 2), myPos.z);
                        updateTileCache(tile, x, -((mapWalkHeight - 1) / 2));
                    }
                }
                else if(oldPos.y < newPos.y) // south
                {
                    //shift y north
                    for(int32_t y = 0; y <= mapWalkHeight - 1 - 1; ++y)
                        memcpy(localMapCache[y], localMapCache[y + 1], sizeof(localMapCache[y]));

                    //update mapWalkHeight - 1
                    for(int32_t x = -((mapWalkWidth - 1) / 2); x <= ((mapWalkWidth - 1) / 2); ++x)
                    {
                        tile = g_game.getTile(myPos.x + x, myPos.y + ((mapWalkHeight - 1) / 2), myPos.z);
                        updateTileCache(tile, x, (mapWalkHeight - 1) / 2);
                    }
                }

                if(oldPos.x < newPos.x) // east
                {
                    //shift y west
                    int32_t starty = 0, endy = mapWalkHeight - 1, dy = (oldPos.y - newPos.y);
                    if(dy < 0)
                        endy = endy + dy;
                    else if(dy > 0)
                        starty = starty + dy;

                    for(int32_t y = starty; y <= endy; ++y)
                    {
                        for(int32_t x = 0; x <= mapWalkWidth - 1 - 1; ++x)
                            localMapCache[y][x] = localMapCache[y][x + 1];
                    }

                    //update mapWalkWidth - 1
                    for(int32_t y = -((mapWalkHeight - 1) / 2); y <= ((mapWalkHeight - 1) / 2); ++y)
                    {
                        tile = g_game.getTile(myPos.x + ((mapWalkWidth - 1) / 2), myPos.y + y, myPos.z);
                        updateTileCache(tile, (mapWalkWidth - 1) / 2, y);
                    }
                }
                else if(oldPos.x > newPos.x) // west
                {
                    //shift y east
                    int32_t starty = 0, endy = mapWalkHeight - 1, dy = (oldPos.y - newPos.y);
                    if(dy < 0)
                        endy = endy + dy;
                    else if(dy > 0)
                        starty = starty + dy;

                    for(int32_t y = starty; y <= endy; ++y)
                    {
                        for(int32_t x = mapWalkWidth - 1 - 1; x >= 0; --x)
                            localMapCache[y][x + 1] = localMapCache[y][x];
                    }

                    //update 0
                    for(int32_t y = -((mapWalkHeight - 1) / 2); y <= ((mapWalkHeight - 1) / 2); ++y)
                    {
                        tile = g_game.getTile(myPos.x - ((mapWalkWidth - 1) / 2), myPos.y + y, myPos.z);
                        updateTileCache(tile, -((mapWalkWidth - 1) / 2), y);
                    }
                }

                updateTileCache(oldTile, oldPos);
#ifdef __DEBUG__
                validateMapCache();
#endif
            }
            else
                updateMapCache();
        }
    }
    else if(isMapLoaded)
    {
        const Position& myPos = getPosition();
        if(newPos.z == myPos.z)
            updateTileCache(newTile, newPos);

        if(oldPos.z == myPos.z)
            updateTileCache(oldTile, oldPos);
    }

    if(creature == followCreature || (creature == this && followCreature))
    {
        if(hasFollowPath)
        {
            isUpdatingPath = true;
            Dispatcher::getInstance().addTask(createTask(
                boost::bind(&Game::updateCreatureWalk, &g_game, getID())));
        }

        if(newPos.z != oldPos.z || !canSee(followCreature->getPosition()))
            internalCreatureDisappear(followCreature, false);
    }

    if(creature == attackedCreature || (creature == this && attackedCreature))
    {
        if(newPos.z == oldPos.z && canSee(attackedCreature->getPosition()))
        {
            if(hasExtraSwing()) //our target is moving lets see if we can get in hit
                Dispatcher::getInstance().addTask(createTask(
                    boost::bind(&Game::checkCreatureAttack, &g_game, getID())));

            if(newTile->getZone() != oldTile->getZone())
                onAttackedCreatureChangeZone(attackedCreature->getZone());
        }
        else
            internalCreatureDisappear(attackedCreature, false);
    }
}

bool Creature::onDeath()
{
    DeathList deathList = getKillers();
    bool deny = false;

    CreatureEventList prepareDeathEvents = getCreatureEvents(CREATURE_EVENT_PREPAREDEATH);
    for(CreatureEventList::iterator it = prepareDeathEvents.begin(); it != prepareDeathEvents.end(); ++it)
    {
        if(!(*it)->executePrepareDeath(this, deathList) && !deny)
            deny = true;
    }

    if(deny)
        return false;

    int32_t i = 0, size = deathList.size(), limit = g_config.getNumber(ConfigManager::DEATH_ASSISTS) + 1;
    if(limit > 0 && size > limit)
        size = limit;

    Creature* tmp = NULL;
    CreatureVector justifyVec;
    for(DeathList::iterator it = deathList.begin(); it != deathList.end(); ++it, ++i)
    {
        if(it->isNameKill())
            continue;

        bool lastHit = it == deathList.begin();
        uint32_t flags = KILLFLAG_NONE;
        if(lastHit)
            flags |= (uint32_t)KILLFLAG_LASTHIT;

        if(i < size)
        {
            if(it->getKillerCreature()->getPlayer())
                tmp = it->getKillerCreature();
            else if(it->getKillerCreature()->getPlayerMaster())
                tmp = it->getKillerCreature()->getMaster();
        }

        if(tmp)
        {
            if(std::find(justifyVec.begin(), justifyVec.end(), tmp) == justifyVec.end())
            {
                flags |= (uint32_t)KILLFLAG_JUSTIFY;
                justifyVec.push_back(tmp);
            }

            tmp = NULL;
        }

        if(!it->getKillerCreature()->onKilledCreature(this, flags) && lastHit)
            return false;

        if(hasBitSet((uint32_t)KILLFLAG_UNJUSTIFIED, flags))
            it->setUnjustified(true);
    }

    for(CountMap::iterator it = damageMap.begin(); it != damageMap.end(); ++it)
    {
        if((tmp = g_game.getCreatureByID(it->first)))
            tmp->onAttackedCreatureKilled(this);
    }

    dropCorpse(deathList);
    if(master)
        master->removeSummon(this);

    return true;
}

void Creature::dropCorpse(DeathList deathList)
{
    Item* corpse = createCorpse(deathList);
    if(corpse)
        corpse->setParent(VirtualCylinder::virtualCylinder);

    bool deny = false;
    CreatureEventList deathEvents = getCreatureEvents(CREATURE_EVENT_DEATH);
    for(CreatureEventList::iterator it = deathEvents.begin(); it != deathEvents.end(); ++it)
    {
        if(!(*it)->executeDeath(this, corpse, deathList) && !deny)
            deny = true;
    }

    if(!corpse)
        return;

    corpse->setParent(NULL);
    if(deny)
        return;

    Tile* tile = getTile();
    if(!tile)
        return;

    Item* splash = NULL;
    switch(getRace())
    {
        case RACE_VENOM:
            splash = Item::CreateItem(ITEM_FULLSPLASH, FLUID_GREEN);
            break;

        case RACE_BLOOD:
            splash = Item::CreateItem(ITEM_FULLSPLASH, FLUID_BLOOD);
            break;

        default:
            break;
    }


    g_game.internalAddItem(NULL, tile, corpse, INDEX_WHEREEVER, FLAG_NOLIMIT);
    dropLoot(corpse->getContainer());
    g_game.startDecay(corpse);
}

DeathList Creature::getKillers()
{
    DeathList list;
    Creature* lhc = NULL;
    if(!(lhc = g_game.getCreatureByID(lastHitCreature)))
        list.push_back(DeathEntry(getCombatName(lastDamageSource), 0));
    else
        list.push_back(DeathEntry(lhc, 0));

    int32_t requiredTime = g_config.getNumber(ConfigManager::DEATHLIST_REQUIRED_TIME);
    int64_t now = OTSYS_TIME();

    CountBlock_t cb;
    for(CountMap::const_iterator it = damageMap.begin(); it != damageMap.end(); ++it)
    {
        cb = it->second;
        if((now - cb.ticks) > requiredTime)
            continue;

        Creature* mdc = g_game.getCreatureByID(it->first);
        if(!mdc || mdc == lhc || (lhc && (mdc->getMaster() == lhc || lhc->getMaster() == mdc)))
            continue;

        bool deny = false;
        for(DeathList::iterator fit = list.begin(); fit != list.end(); ++fit)
        {
            if(fit->isNameKill())
                continue;

            Creature* tmp = fit->getKillerCreature();
            if(!(mdc->getName() == tmp->getName() && mdc->getMaster() == tmp->getMaster()) &&
                (!mdc->getMaster() || (mdc->getMaster() != tmp && mdc->getMaster() != tmp->getMaster()))
                && (mdc->getSummonCount() <= 0 || tmp->getMaster() != mdc))
                continue;

            deny = true;
            break;
        }

        if(!deny)
            list.push_back(DeathEntry(mdc, cb.total));
    }

    if(list.size() > 1)
        std::sort(list.begin() + 1, list.end(), DeathLessThan());

    return list;
}

bool Creature::hasBeenAttacked(uint32_t attackerId) const
{
    CountMap::const_iterator it = damageMap.find(attackerId);
    if(it != damageMap.end())
        return (OTSYS_TIME() - it->second.ticks) <= g_config.getNumber(ConfigManager::PZ_LOCKED);

    return false;
}

Item* Creature::createCorpse(DeathList deathList)
{
    return Item::CreateItem(getLookCorpse());
}

void Creature::changeHealth(int32_t healthChange)
{
    if(healthChange > 0)
        health += std::min(healthChange, getMaxHealth() - health);
    else
        health = std::max((int32_t)0, health + healthChange);

    g_game.addCreatureHealth(this);
}

void Creature::changeMana(int32_t manaChange)
{
    if(manaChange > 0)
        mana += std::min(manaChange, getMaxMana() - mana);
    else
        mana = std::max((int32_t)0, mana + manaChange);
}

bool Creature::getStorage(const uint32_t key, std::string& value) const
{
    StorageMap::const_iterator it = storageMap.find(key);
    if(it != storageMap.end())
    {
        value = it->second;
        return true;
    }

    value = "-1";
    return false;
}

bool Creature::setStorage(const uint32_t key, const std::string& value)
{
    storageMap[key] = value;
    return true;
}

void Creature::gainHealth(Creature* caster, int32_t healthGain)
{
    if(healthGain > 0)
    {
        int32_t prevHealth = getHealth();
        changeHealth(healthGain);

        int32_t effectiveGain = getHealth() - prevHealth;
        if(caster)
            caster->onTargetCreatureGainHealth(this, effectiveGain);
    }
    else
        changeHealth(healthGain);
}

void Creature::drainHealth(Creature* attacker, CombatType_t combatType, int32_t damage)
{
    lastDamageSource = combatType;
    onAttacked();

    changeHealth(-damage);
    if(attacker)
        attacker->onAttackedCreatureDrainHealth(this, damage);
}

bool Creature::isGhostPokemon() const{
   bool ret = false;
            return ret;
}

void Creature::drainMana(Creature* attacker, CombatType_t combatType, int32_t damage)
{
    lastDamageSource = combatType;
    onAttacked();

    changeMana(-damage);
    if(attacker)
        attacker->onAttackedCreatureDrainMana(this, damage);
}

BlockType_t Creature::blockHit(Creature* attacker, CombatType_t combatType, int32_t& damage,
    bool checkDefense/* = false*/, bool checkArmor/* = false*/)
{
    BlockType_t blockType = BLOCK_NONE;
    if(isImmune(combatType))
    {
        damage = 0;
        blockType = BLOCK_IMMUNITY;
    }
    else if(checkDefense || checkArmor)
    {
        bool hasDefense = false;
        if(blockCount > 0)
        {
            --blockCount;
            hasDefense = true;
        }

        if(checkDefense && hasDefense)
        {
            int32_t maxDefense = getDefense(), minDefense = maxDefense / 2;
            damage -= random_range(minDefense, maxDefense);
            if(damage <= 0)
            {
                damage = 0;
                blockType = BLOCK_DEFENSE;
                checkArmor = false;
            }
        }

        if(checkArmor)
        {
            int32_t armorValue = getArmor(), minArmorReduction = 0,
                maxArmorReduction = 0;
            if(armorValue > 1)
            {
                minArmorReduction = (int32_t)std::ceil(armorValue * 0.475);
                maxArmorReduction = (int32_t)std::ceil(
                    ((armorValue * 0.475) - 1) + minArmorReduction);
            }
            else if(armorValue == 1)
            {
                minArmorReduction = 1;
                maxArmorReduction = 1;
            }

            damage -= random_range(minArmorReduction, maxArmorReduction);
            if(damage <= 0)
            {
                damage = 0;
                blockType = BLOCK_ARMOR;
            }
        }

        if(hasDefense && blockType != BLOCK_NONE)
            onBlockHit(blockType);
    }

    if(attacker)
    {
        attacker->onAttackedCreature(this);
        attacker->onAttackedCreatureBlockHit(this, blockType);
    }

    onAttacked();
    return blockType;
}

bool Creature::setAttackedCreature(Creature* creature)
{
    if(creature)
    {
        const Position& creaturePos = creature->getPosition();
        if(creaturePos.z != getPosition().z || !canSee(creaturePos))
        {
            attackedCreature = NULL;
            return false;
        }
    }

    attackedCreature = creature;
    if(attackedCreature)
    {
        onAttackedCreature(attackedCreature);
        attackedCreature->onAttacked();
    }

    for(std::list<Creature*>::iterator cit = summons.begin(); cit != summons.end(); ++cit)
        (*cit)->setAttackedCreature(creature);

    return true;
}

void Creature::getPathSearchParams(const Creature* creature, FindPathParams& fpp) const
{    
    fpp.fullPathSearch = !hasFollowPath;
    fpp.clearSight = false;
    fpp.maxSearchDist = 12;
    fpp.minTargetDist = fpp.maxTargetDist = 1;
}

void Creature::getPathToFollowCreature()
{
    if(followCreature)
    {
        FindPathParams fpp;
        getPathSearchParams(followCreature, fpp);
        
        if(g_game.getPathToEx(this, followCreature->getPosition(), listWalkDir, fpp))
        {
            hasFollowPath = true;
            startAutoWalk(listWalkDir);
        }
        else
            hasFollowPath = false;
    }

    onFollowCreatureComplete(followCreature);
}

bool Creature::setFollowCreature(Creature* creature, bool fullPathSearch /*= false*/)
{
    if(creature)
    {
        if(followCreature == creature)
            return true;

        const Position& creaturePos = creature->getPosition();
        if(creaturePos.z != getPosition().z || !canSee(creaturePos))
        {
            followCreature = NULL;
            return false;
        }

        if(!listWalkDir.empty())
        {
            listWalkDir.clear();
            onWalkAborted();
        }

        hasFollowPath = forceUpdateFollowPath = false;
        followCreature = creature;
        isUpdatingPath = true;
    }
    else
    {
        isUpdatingPath = false;
        followCreature = NULL;
    }

    onFollowCreature(creature);
    return true;
}

double Creature::getDamageRatio(Creature* attacker) const
{
    double totalDamage = 0, attackerDamage = 0;
    for(CountMap::const_iterator it = damageMap.begin(); it != damageMap.end(); ++it)
    {
        totalDamage += it->second.total;
        if(it->first == attacker->getID())
            attackerDamage += it->second.total;
    }

    return attackerDamage / totalDamage;
}

void Creature::addDamagePoints(Creature* attacker, int32_t damagePoints)
{
    uint32_t attackerId = 0;
    if(attacker)
        attackerId = attacker->getID();

    CountMap::iterator it = damageMap.find(attackerId);
    if(it != damageMap.end())
    {
        it->second.ticks = OTSYS_TIME();
        if(damagePoints > 0)
            it->second.total += damagePoints;
    }
    else
        damageMap[attackerId] = CountBlock_t(damagePoints);

    if(damagePoints > 0)
        lastHitCreature = attackerId;
}

void Creature::addHealPoints(Creature* caster, int32_t healthPoints)
{
    if(healthPoints <= 0)
        return;

    uint32_t casterId = 0;
    if(caster)
        casterId = caster->getID();

    CountMap::iterator it = healMap.find(casterId);
    if(it != healMap.end())
    {
        it->second.ticks = OTSYS_TIME();
        it->second.total += healthPoints;
    }
    else
        healMap[casterId] = CountBlock_t(healthPoints);
}

void Creature::onAddCondition(ConditionType_t type, bool hadCondition)
{
    if(type == CONDITION_INVISIBLE)
    {
        if(!hadCondition)
            g_game.internalCreatureChangeVisible(this, VISIBLE_DISAPPEAR);
    }
    else if(type == CONDITION_PARALYZE)
    {
        if(hasCondition(CONDITION_HASTE))
            removeCondition(CONDITION_HASTE);
    }
    else if(type == CONDITION_HASTE)
    {
        if(hasCondition(CONDITION_PARALYZE))
            removeCondition(CONDITION_PARALYZE);
    }
}

void Creature::onEndCondition(ConditionType_t type)
{
    if(type == CONDITION_INVISIBLE && !hasCondition(CONDITION_INVISIBLE, -1, false))
        g_game.internalCreatureChangeVisible(this, VISIBLE_APPEAR);
}

void Creature::onTickCondition(ConditionType_t type, int32_t interval, bool& _remove)
{
    if(const MagicField* field = getTile()->getFieldItem())
    {
        switch(type)
        {
            case CONDITION_FIRE:
                _remove = field->getCombatType() != COMBAT_FIREDAMAGE;
                break;
            case CONDITION_ENERGY:
                _remove = field->getCombatType() != COMBAT_ENERGYDAMAGE;
                break;
            case CONDITION_POISON:
                _remove = field->getCombatType() != COMBAT_EARTHDAMAGE;
                break;
            case CONDITION_DROWN:
                _remove = field->getCombatType() != COMBAT_DROWNDAMAGE;
                break;
            default:
                break;
        }
    }
}

void Creature::onCombatRemoveCondition(const Creature* attacker, Condition* condition)
{
    removeCondition(condition);
}

void Creature::onIdleStatus()
{
    if(getHealth() > 0)
    {
        healMap.clear();
        damageMap.clear();
    }
}

void Creature::onAttackedCreatureDrainHealth(Creature* target, int32_t points)
{
    onAttackedCreatureDrain(target, points);
}

void Creature::onAttackedCreatureDrainMana(Creature* target, int32_t points)
{
    onAttackedCreatureDrain(target, points);
}

void Creature::onAttackedCreatureDrain(Creature* target, int32_t points)
{
    target->addDamagePoints(this, points);
}

void Creature::onTargetCreatureGainHealth(Creature* target, int32_t points)
{
    target->addHealPoints(this, points);
}

void Creature::onAttackedCreatureKilled(Creature* target)
{
    if(target == this)
        return;

    double gainExp = target->getGainedExperience(this);
    onGainExperience(gainExp, !target->getPlayer(), false);
}

Creature* Creature::pushBackSummonOne(){ // aqui
     Creature* a = NULL;
if(!summons.empty())
        {
            std::list<Creature*>::iterator cit;
            std::list<Creature*> despawnList;
            for(cit = summons.begin(); cit != summons.end(); ++cit)
            {
               a = (*cit);
               break;
            }
        }
        return a;
}

bool Creature::onKilledCreature(Creature* target, uint32_t& flags)
{
    bool ret = true;
    if(master)
        ret = master->onKilledCreature(target, flags);

    CreatureEventList killEvents = getCreatureEvents(CREATURE_EVENT_KILL);
    if(!hasBitSet((uint32_t)KILLFLAG_LASTHIT, flags))
    {
        for(CreatureEventList::iterator it = killEvents.begin(); it != killEvents.end(); ++it)
            (*it)->executeKill(this, target, false);

        return true;
    }

    for(CreatureEventList::iterator it = killEvents.begin(); it != killEvents.end(); ++it)
    {
        if(!(*it)->executeKill(this, target, true) && ret)
            ret = false;
    }

    return ret;
}

void Creature::onGainExperience(double& gainExp, bool fromMonster, bool multiplied)
{
    if(gainExp <= 0)
        return;

    if(master)
    {
        gainExp = gainExp / 2;
        master->onGainExperience(gainExp, fromMonster, multiplied);
    }
    else if(!multiplied)
        gainExp *= g_config.getDouble(ConfigManager::RATE_EXPERIENCE);

    int16_t color = g_config.getNumber(ConfigManager::EXPERIENCE_COLOR);
    if(color < 0)
        color = random_range(0, 255);

    std::stringstream ss;
    ss << (uint64_t)gainExp;
    g_game.addAnimatedText(getPosition(), (uint8_t)color, ss.str());
}

void Creature::onGainSharedExperience(double& gainExp, bool fromMonster, bool multiplied)
{
    if(gainExp <= 0)
        return;

    if(master)
    {
        gainExp = gainExp / 2;
        master->onGainSharedExperience(gainExp, fromMonster, multiplied);
    }
    else if(!multiplied)
        gainExp *= g_config.getDouble(ConfigManager::RATE_EXPERIENCE);

    int16_t color = g_config.getNumber(ConfigManager::EXPERIENCE_COLOR);
    if(color < 0)
        color = random_range(0, 255);

    std::stringstream ss;
    ss << (uint64_t)gainExp;
    g_game.addAnimatedText(getPosition(), (uint8_t)color, ss.str());
}

void Creature::addSummon(Creature* creature)
{
    creature->setDropLoot(LOOT_DROP_NONE);
    creature->setLossSkill(false);

    creature->setMaster(this);
    creature->addRef();
    summons.push_back(creature);
}

void Creature::removeSummon(const Creature* creature)
{
    std::list<Creature*>::iterator it = std::find(summons.begin(), summons.end(), creature);
    if(it == summons.end())
        return;

    (*it)->setMaster(NULL);
    (*it)->unRef();
    summons.erase(it);
}

void Creature::destroySummons()
{
    for(std::list<Creature*>::iterator it = summons.begin(); it != summons.end(); ++it)
    {
        (*it)->setAttackedCreature(NULL);
        (*it)->changeHealth(-(*it)->getHealth());

        (*it)->setMaster(NULL);
        (*it)->unRef();
    }

    summons.clear();
}

bool Creature::addCondition(Condition* condition)
{
    if(!condition)
        return false;

    bool hadCondition = hasCondition(condition->getType(), -1, false);
    if(Condition* previous = getCondition(condition->getType(), condition->getId(), condition->getSubId()))
    {
        previous->addCondition(this, condition);
        delete condition;
        return true;
    }

    if(condition->startCondition(this))
    {
        conditions.push_back(condition);
        onAddCondition(condition->getType(), hadCondition);
        return true;
    }

    delete condition;
    return false;
}

bool Creature::addCombatCondition(Condition* condition)
{
    bool hadCondition = hasCondition(condition->getType(), -1, false);
    //Caution: condition variable could be deleted after the call to addCondition
    ConditionType_t type = condition->getType();
    if(!addCondition(condition))
        return false;

    onAddCombatCondition(type, hadCondition);
    return true;
}

void Creature::removeCondition(ConditionType_t type)
{
    for(ConditionList::iterator it = conditions.begin(); it != conditions.end();)
    {
        if((*it)->getType() != type)
        {
            ++it;
            continue;
        }

        Condition* condition = *it;
        it = conditions.erase(it);

        condition->endCondition(this, CONDITIONEND_ABORT);
        onEndCondition(condition->getType());
        delete condition;
    }
}

void Creature::removeCondition(ConditionType_t type, ConditionId_t id)
{
    for(ConditionList::iterator it = conditions.begin(); it != conditions.end();)
    {
        if((*it)->getType() != type || (*it)->getId() != id)
        {
            ++it;
            continue;
        }

        Condition* condition = *it;
        it = conditions.erase(it);

        condition->endCondition(this, CONDITIONEND_ABORT);
        onEndCondition(condition->getType());
        delete condition;
    }
}

void Creature::removeCondition(Condition* condition)
{
    ConditionList::iterator it = std::find(conditions.begin(), conditions.end(), condition);
    if(it != conditions.end())
    {
        Condition* condition = *it;
        it = conditions.erase(it);

        condition->endCondition(this, CONDITIONEND_ABORT);
        onEndCondition(condition->getType());
        delete condition;
    }
}

void Creature::removeCondition(const Creature* attacker, ConditionType_t type)
{
    ConditionList tmpList = conditions;
    for(ConditionList::iterator it = tmpList.begin(); it != tmpList.end(); ++it)
    {
        if((*it)->getType() == type)
            onCombatRemoveCondition(attacker, *it);
    }
}

void Creature::removeConditions(ConditionEnd_t reason, bool onlyPersistent/* = true*/)
{
    for(ConditionList::iterator it = conditions.begin(); it != conditions.end();)
    {
        if(onlyPersistent && !(*it)->isPersistent())
        {
            ++it;
            continue;
        }

        Condition* condition = *it;
        it = conditions.erase(it);

        condition->endCondition(this, reason);
        onEndCondition(condition->getType());
        delete condition;
    }
}

Condition* Creature::getCondition(ConditionType_t type, ConditionId_t id, uint32_t subId/* = 0*/) const
{
    for(ConditionList::const_iterator it = conditions.begin(); it != conditions.end(); ++it)
    {
        if((*it)->getType() == type && (*it)->getId() == id && (*it)->getSubId() == subId)
            return *it;
    }

    return NULL;
}

void Creature::executeConditions(uint32_t interval)
{
    for(ConditionList::iterator it = conditions.begin(); it != conditions.end();)
    {
        if((*it)->executeCondition(this, interval))
        {
            ++it;
            continue;
        }

        Condition* condition = *it;
        it = conditions.erase(it);

        condition->endCondition(this, CONDITIONEND_TICKS);
        onEndCondition(condition->getType());
        delete condition;
    }
}

bool Creature::hasCondition(ConditionType_t type, int32_t subId/* = 0*/, bool checkTime/* = true*/) const
{
    if(isSuppress(type))
        return false;

    for(ConditionList::const_iterator it = conditions.begin(); it != conditions.end(); ++it)
    {
        if((*it)->getType() != type || (subId != -1 && (*it)->getSubId() != (uint32_t)subId))
            continue;

        if(!checkTime || g_config.getBool(ConfigManager::OLD_CONDITION_ACCURACY)
            || !(*it)->getEndTime() || (*it)->getEndTime() >= OTSYS_TIME())
            return true;
    }

    return false;
}

bool Creature::isImmune(CombatType_t type) const
{
    return ((getDamageImmunities() & (uint32_t)type) == (uint32_t)type);
}

bool Creature::isImmune(ConditionType_t type) const
{
    return ((getConditionImmunities() & (uint32_t)type) == (uint32_t)type);
}

bool Creature::isSuppress(ConditionType_t type) const
{
    return ((getConditionSuppressions() & (uint32_t)type) == (uint32_t)type);
}

std::string Creature::getDescription(int32_t lookDistance) const
{
    return "a creature";
}

int32_t Creature::getStepDuration(Direction dir) const
{
    if(dir == NORTHWEST || dir == NORTHEAST || dir == SOUTHWEST || dir == SOUTHEAST)
        return getStepDuration() * 2;

    return getStepDuration();
}

int32_t Creature::getStepDuration() const
{
    if(removed)
        return 0;

    uint32_t stepSpeed = getStepSpeed();
    if(!stepSpeed)
        return 0;

    const Tile* tile = getTile();
    if(!tile || !tile->ground)
        return 0;

    return ((1000 * Item::items[tile->ground->getID()].speed) / stepSpeed) * lastStepCost;
}

int64_t Creature::getEventStepTicks() const
{
    int64_t ret = getWalkDelay();
    if(ret > 0)
        return ret;

    return getStepDuration();
}

void Creature::getCreatureLight(LightInfo& light) const
{
    light = internalLight;
}

void Creature::setNormalCreatureLight()
{
    internalLight.level = internalLight.color = 0;
}

bool Creature::registerCreatureEvent(const std::string& name)
{
    CreatureEvent* event = g_creatureEvents->getEventByName(name);
    if(!event) //check for existance
        return false;

    for(CreatureEventList::iterator it = eventsList.begin(); it != eventsList.end(); ++it)
    {
        if((*it) == event) //do not allow registration of same event more than once
            return false;
    }

    if(!hasEventRegistered(event->getEventType())) //there's no such type registered yet, so set the bit in the bitfield
        scriptEventsBitField |= ((uint32_t)1 << event->getEventType());

    eventsList.push_back(event);
    return true;
}

CreatureEventList Creature::getCreatureEvents(CreatureEventType_t type)
{
    CreatureEventList retList;
    if(!hasEventRegistered(type))
        return retList;

    for(CreatureEventList::iterator it = eventsList.begin(); it != eventsList.end(); ++it)
    {
        if((*it)->getEventType() == type)
            retList.push_back(*it);
    }

    return retList;
}

FrozenPathingConditionCall::FrozenPathingConditionCall(const Position& _targetPos)
{
    targetPos = _targetPos;
}

bool FrozenPathingConditionCall::isInRange(const Position& startPos, const Position& testPos,
    const FindPathParams& fpp) const
{
    int32_t dxMin = ((fpp.fullPathSearch || (startPos.x - targetPos.x) <= 0) ? fpp.maxTargetDist : 0),
    dxMax = ((fpp.fullPathSearch || (startPos.x - targetPos.x) >= 0) ? fpp.maxTargetDist : 0),
    dyMin = ((fpp.fullPathSearch || (startPos.y - targetPos.y) <= 0) ? fpp.maxTargetDist : 0),
    dyMax = ((fpp.fullPathSearch || (startPos.y - targetPos.y) >= 0) ? fpp.maxTargetDist : 0);
    if(testPos.x > targetPos.x + dxMax || testPos.x < targetPos.x - dxMin)
        return false;

    if(testPos.y > targetPos.y + dyMax || testPos.y < targetPos.y - dyMin)
        return false;

    return true;
}

bool FrozenPathingConditionCall::operator()(const Position& startPos, const Position& testPos,
    const FindPathParams& fpp, int32_t& bestMatchDist) const
{
    if(!isInRange(startPos, testPos, fpp))
        return false;

    if(fpp.clearSight && !g_game.isSightClear(testPos, targetPos, true))
        return false;

    int32_t testDist = std::max(std::abs(targetPos.x - testPos.x), std::abs(targetPos.y - testPos.y));
    if(fpp.maxTargetDist == 1)
        return (testDist >= fpp.minTargetDist && testDist <= fpp.maxTargetDist);

    if(testDist <= fpp.maxTargetDist)
    {
        if(testDist < fpp.minTargetDist)
            return false;

        if(testDist == fpp.maxTargetDist)
        {
            bestMatchDist = 0;
            return true;
        }
        else if(testDist > bestMatchDist)
        {
            //not quite what we want, but the best so far
            bestMatchDist = testDist;
            return true;
        }
    }

    return false;
}
 

 

Obs : Desculpe reviver o tópico... é pq realmente estou precisando

 

cara é na source do cliente
vc esta procurando na do servidor

Postado

@rohfagundes me ajuda, tipo.... meu client que baixei veio sem sources (na pasta dele)
Porem baixei 1 pasta SEPARADA com as sources dele. Como eu faço essa ligação?

1 hora atrás, rohfagundes disse:

cara é na source do cliente
vc esta procurando na do servidor

Man estou aqui com a source do CLIENT ... não tem tbm !

Spoiler

/*
 * Copyright (c) 2010-2015 OTClient <https://github.com/edubart/otclient>
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

#include "creatures.h"
#include "creature.h"
#include "map.h"

#include <framework/xml/tinyxml.h>
#include <framework/core/resourcemanager.h>

CreatureManager g_creatures;

static bool isInZone(const Position& pos/* placePos*/,
                     const Position& centerPos,
                     int radius)
{
    if(radius == -1)
        return true;
    return ((pos.x >= centerPos.x - radius) && (pos.x <= centerPos.x + radius) &&
            (pos.y >= centerPos.y - radius) && (pos.y <= centerPos.y + radius)
           );
}

void CreatureManager::terminate()
{
    clearSpawns();
    clear();
    m_nullCreature = nullptr;
}

void Spawn::load(TiXmlElement* node)
{
    Position centerPos;
    centerPos.x = node->readType<int>("centerx");
    centerPos.y = node->readType<int>("centery");
    centerPos.z = node->readType<int>("centerz");

    setCenterPos(centerPos);
    setRadius(node->readType<int32>("radius"));

    CreatureTypePtr cType(nullptr);
    for(TiXmlElement* cNode = node->FirstChildElement(); cNode; cNode = cNode->NextSiblingElement()) {
        if(cNode->ValueStr() != "monster" && cNode->ValueStr() != "npc")
            stdext::throw_exception(stdext::format("invalid spawn-subnode %s", cNode->ValueStr()));

        std::string cName = cNode->Attribute("name");
        stdext::tolower(cName);
        stdext::trim(cName);
        stdext::ucwords(cName);

        if (!(cType = g_creatures.getCreatureByName(cName)))
            continue;

        cType->setSpawnTime(cNode->readType<int>("spawntime"));
        Otc::Direction dir = Otc::North;
        int16 dir_ = cNode->readType<int16>("direction");
        if(dir_ >= Otc::East && dir_ <= Otc::West)
            dir = (Otc::Direction)dir_;
        cType->setDirection(dir);

        Position placePos;
        placePos.x = centerPos.x + cNode->readType<int>("x");
        placePos.y = centerPos.y + cNode->readType<int>("y");
        placePos.z = cNode->readType<int>("z");

        cType->setRace(cNode->ValueStr() == "npc" ? CreatureRaceNpc : CreatureRaceMonster);
        addCreature(placePos, cType);
    }
}

void Spawn::save(TiXmlElement* node)
{
    const Position& c = getCenterPos();
    node->SetAttribute("centerx", c.x);
    node->SetAttribute("centery", c.y);
    node->SetAttribute("centerz", c.z);

    node->SetAttribute("radius", getRadius());

    TiXmlElement* creatureNode = nullptr;

    for(const auto& pair : m_creatures) {
        const CreatureTypePtr& creature = pair.second;
        if(!(creatureNode = new TiXmlElement(creature->getRace() == CreatureRaceNpc ? "npc" : "monster")))
            stdext::throw_exception("Spawn::save: Ran out of memory while allocating XML element!  Terminating now.");

        creatureNode->SetAttribute("name", creature->getName());
        creatureNode->SetAttribute("spawntime", creature->getSpawnTime());
        creatureNode->SetAttribute("direction", creature->getDirection());

        const Position& placePos = pair.first;
        assert(placePos.isValid());

        creatureNode->SetAttribute("x", placePos.x - c.x);
        creatureNode->SetAttribute("y", placePos.y - c.y);
        creatureNode->SetAttribute("z", placePos.z);

        node->LinkEndChild(creatureNode);
    }
}

void Spawn::addCreature(const Position& placePos, const CreatureTypePtr& cType)
{
    const Position& centerPos = getCenterPos();
    int m_radius = getRadius();
    if(!isInZone(placePos, centerPos, m_radius)) {
        g_logger.warning(stdext::format("cannot place creature at %s (spawn's center position: %s, spawn radius: %d) (increment radius)",
                                               stdext::to_string(placePos), stdext::to_string(centerPos),
                                               m_radius
                                              ));
        return;
    }

    g_map.addThing(cType->cast(), placePos, 4);
    m_creatures.insert(std::make_pair(placePos, cType));
}

void Spawn::removeCreature(const Position& pos)
{
    auto iterator = m_creatures.find(pos);
    if(iterator != m_creatures.end()) {
        assert(iterator->first.isValid());
        assert(g_map.removeThingByPos(iterator->first, 4));
        m_creatures.erase(iterator);
    }
}

std::vector<CreatureTypePtr> Spawn::getCreatures()
{
    std::vector<CreatureTypePtr> creatures;
    for (auto p : m_creatures)
        creatures.push_back(p.second);
    return creatures;
}

CreaturePtr CreatureType::cast()
{
    CreaturePtr ret(new Creature);

    std::string cName = getName();
    stdext::tolower(cName);
    stdext::trim(cName);
    stdext::ucwords(cName);
    ret->setName(cName);

    ret->setDirection(getDirection());
    ret->setOutfit(getOutfit());
    return ret;
}

CreatureManager::CreatureManager()
{
    m_nullCreature = CreatureTypePtr(new CreatureType);
}

void CreatureManager::clearSpawns()
{
    for(auto pair : m_spawns)
        pair.second->clear();
    m_spawns.clear();
}

void CreatureManager::loadMonsters(const std::string& file)
{
    TiXmlDocument doc;
    doc.Parse(g_resources.readFileContents(file).c_str());
    if(doc.Error())
        stdext::throw_exception(stdext::format("cannot open monsters file '%s': '%s'", file, doc.ErrorDesc()));

    TiXmlElement* root = doc.FirstChildElement();
    if(!root || root->ValueStr() != "monsters")
        stdext::throw_exception("malformed monsters xml file");

    for(TiXmlElement* monster = root->FirstChildElement(); monster; monster = monster->NextSiblingElement()) {
        std::string fname = file.substr(0, file.find_last_of('/')) + '/' + monster->Attribute("file");
        if(fname.substr(fname.length() - 4) != ".xml")
            fname += ".xml";

        loadSingleCreature(fname);
    }

    doc.Clear();
    m_loaded = true;
}

void CreatureManager::loadSingleCreature(const std::string& file)
{
    loadCreatureBuffer(g_resources.readFileContents(file));
}

void CreatureManager::loadNpcs(const std::string& folder)
{
    std::string tmp = folder;
    if(!stdext::ends_with(tmp, "/"))
        tmp += "/";

    if(!g_resources.directoryExists(tmp))
        stdext::throw_exception(stdext::format("NPCs folder '%s' was not found.", folder));

    const auto& fileList = g_resources.listDirectoryFiles(tmp);
    for(const std::string& file : fileList)
        loadCreatureBuffer(g_resources.readFileContents(tmp + file));
}

void CreatureManager::loadSpawns(const std::string& fileName)
{
    if(!isLoaded()) {
        g_logger.warning("creatures aren't loaded yet to load spawns.");
        return;
    }

    if(m_spawnLoaded) {
        g_logger.warning("attempt to reload spawns.");
        return;
    }

    try {
        TiXmlDocument doc;
        doc.Parse(g_resources.readFileContents(fileName).c_str());
        if(doc.Error())
            stdext::throw_exception(stdext::format("cannot load spawns xml file '%s: '%s'", fileName, doc.ErrorDesc()));

        TiXmlElement* root = doc.FirstChildElement();
        if(!root || root->ValueStr() != "spawns")
            stdext::throw_exception("malformed spawns file");

        for(TiXmlElement* node = root->FirstChildElement(); node; node = node->NextSiblingElement()) {
            if(node->ValueTStr() != "spawn")
                stdext::throw_exception("invalid spawn node");

            SpawnPtr spawn(new Spawn);
            spawn->load(node);
            m_spawns.insert(std::make_pair(spawn->getCenterPos(), spawn));
        }
        doc.Clear();
        m_spawnLoaded = true;
    } catch(std::exception& e) {
        g_logger.error(stdext::format("Failed to load '%s': %s", fileName, e.what()));
    }
}

void CreatureManager::saveSpawns(const std::string& fileName)
{
    try {
        TiXmlDocument doc;
        doc.SetTabSize(2);

        TiXmlDeclaration* decl = new TiXmlDeclaration("1.0", "UTF-8", "");
        doc.LinkEndChild(decl);

        TiXmlElement* root = new TiXmlElement("spawns");
        doc.LinkEndChild(root);

        for(auto pair : m_spawns) {
            TiXmlElement* elem = new TiXmlElement("spawn");
            pair.second->save(elem);
            root->LinkEndChild(elem);
        }

        if(!doc.SaveFile("data"+fileName))
            stdext::throw_exception(stdext::format("failed to save spawns XML %s: %s", fileName, doc.ErrorDesc()));
    } catch(std::exception& e) {
        g_logger.error(stdext::format("Failed to save '%s': %s", fileName, e.what()));
    }
}

void CreatureManager::loadCreatureBuffer(const std::string& buffer)
{
    TiXmlDocument doc;
    doc.Parse(buffer.c_str());
    if(doc.Error())
        stdext::throw_exception(stdext::format("cannot load creature buffer: %s", doc.ErrorDesc()));

    TiXmlElement* root = doc.FirstChildElement();
    if(!root || (root->ValueStr() != "monster" && root->ValueStr() != "npc"))
        stdext::throw_exception("invalid root tag name");

    std::string cName = root->Attribute("name");
    stdext::tolower(cName);
    stdext::trim(cName);
    stdext::ucwords(cName);

    CreatureTypePtr newType(new CreatureType(cName));
    for(TiXmlElement* attrib = root->FirstChildElement(); attrib; attrib = attrib->NextSiblingElement()) {
        if(attrib->ValueStr() != "look")
            continue;

        internalLoadCreatureBuffer(attrib, newType);
        break;
    }

    doc.Clear();
}

void CreatureManager::internalLoadCreatureBuffer(TiXmlElement* attrib, const CreatureTypePtr& m)
{
    if(std::find(m_creatures.begin(), m_creatures.end(), m) != m_creatures.end())
        return;

    Outfit out;

    int32 type = attrib->readType<int32>("type");
    if(type > 0) {
        out.setCategory(ThingCategoryCreature);
        out.setId(type);
    } else {
        out.setCategory(ThingCategoryItem);
        out.setAuxId(attrib->readType<int32>("typeex"));
    }

    {
        out.setHead(attrib->readType<int>(("head")));
        out.setBody(attrib->readType<int>(("body")));
        out.setLegs(attrib->readType<int>(("legs")));
        out.setFeet(attrib->readType<int>(("feet")));
        out.setAddons(attrib->readType<int>(("addons")));
        out.setMount(attrib->readType<int>(("mount")));
    }

    m->setOutfit(out);
    m_creatures.push_back(m);
}

const CreatureTypePtr& CreatureManager::getCreatureByName(std::string name)
{
    stdext::tolower(name);
    stdext::trim(name);
    stdext::ucwords(name);
    auto it = std::find_if(m_creatures.begin(), m_creatures.end(),
                           [=] (const CreatureTypePtr& m) -> bool { return m->getName() == name; });
    if(it != m_creatures.end())
        return *it;
    g_logger.warning(stdext::format("could not find creature with name: %s", name));
    return m_nullCreature;
}

const CreatureTypePtr& CreatureManager::getCreatureByLook(int look)
{
    auto findFun = [=] (const CreatureTypePtr& c) -> bool
    {
        const Outfit& o = c->getOutfit();
        return o.getId() == look || o.getAuxId() == look;
    };
    auto it = std::find_if(m_creatures.begin(), m_creatures.end(), findFun);
    if(it != m_creatures.end())
        return *it;
    g_logger.warning(stdext::format("could not find creature with looktype: %d", look));
    return m_nullCreature;
}

SpawnPtr CreatureManager::getSpawn(const Position& centerPos)
{
    auto it = m_spawns.find(centerPos);
    if(it != m_spawns.end())
        return it->second;
    g_logger.debug(stdext::format("failed to find spawn at center %s",stdext::to_string(centerPos)));
    return nullptr;
}

SpawnPtr CreatureManager::getSpawnForPlacePos(const Position& pos)
{
    for (const auto& pair : m_spawns) {
        const Position& centerPos = pair.first;
        const SpawnPtr& spawn = pair.second;

        if (isInZone(pos, centerPos, spawn->getRadius()))
            return spawn;
    }

    return nullptr;
}

SpawnPtr CreatureManager::addSpawn(const Position& centerPos, int radius)
{
    auto iter = m_spawns.find(centerPos);
    if(iter != m_spawns.end()) {
        if(iter->second->getRadius() != radius)
            iter->second->setRadius(radius);
        return iter->second;
    }

    SpawnPtr ret(new Spawn);

    ret->setRadius(radius);
    ret->setCenterPos(centerPos);

    m_spawns.insert(std::make_pair(centerPos, ret));
    return ret;
}

void CreatureManager::deleteSpawn(const SpawnPtr& spawn)
{
    const Position& centerPos = spawn->getCenterPos();
    auto it = m_spawns.find(centerPos);
    if(it != m_spawns.end())
        m_spawns.erase(it);
}

std::vector<SpawnPtr> CreatureManager::getSpawns()
{
    std::vector<SpawnPtr> spawns;
    for (auto p : m_spawns)
        spawns.push_back(p.second);
    return spawns;
}

/* vim: set ts=4 sw=4 et: */
 

 

@Aberos help '-'

Editado por tataboy67 (veja o histórico de edições)

Participe da conversa

Você pode postar agora e se cadastrar mais tarde. Se você tem uma conta, faça o login para postar com sua conta.

Visitante
Responder

Quem Está Navegando 0

  • Nenhum usuário registrado visualizando esta página.

Estatísticas dos Fóruns

  • Tópicos 96.9k
  • Posts 519.6k

Informação Importante

Confirmação de Termo