Ir para conteúdo
  • Cadastre-se

C++ [C++] Color Name [DigiWo]


Posts Recomendados

Muito bom, alguém deveria adicionar uma função no otclient para fazer isso em lua...

Quem sabe eu tenho algum tempo :3

Bruno de Carvalho Câmara / Administrador TibiaKing

[email protected]


 

btn_donateCC_LG.gif

 

Em 26/12/2016 em 03:47, Spraypaint disse:

A força da alienação vem dessa fragilidade dos indivíduos, quando apenas conseguem identificar o que os separa e não o que os une.

-miltinho

 

wMwSJFE.png?1

 

Link para o post
Compartilhar em outros sites

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{

            m_informationColor = Color(0x00, 0xBC, 0x00);

        }

Pelo menos botou os créditos xD

 

 

Seria uma boa Comedinha.

 

Att, BananaFight.

Editado por DragonElement (veja o histórico de edições)
Link para o post
Compartilhar em outros sites

Se tiver um player com o mesmo nome do monstro, o que acontece?

 

 

Muito bom, alguém deveria adicionar uma função no otclient para fazer isso em lua...

Quem sabe eu tenho algum tempo :3

 

Vou baixar o compilador e depois faço aqui :_)

-"Supra Omnes Lux Lucis"

- Acima de todos brilha a Luz -

5VGnDyBz.png

Link para o post
Compartilhar em outros sites
  • 1 month later...
  • 2 weeks later...

Para colocar para group 6 ter um nome diferente vai ter que mexer nas sources dos 2...

Ele modifica nome de todas as criaturas que você especificou. No caso, o jogador/npc/monstro Banana Flight vão ter o nome com a cor especificada (não da para escolher se será apenas o jogador usando o script desta maneira).

Link para o post
Compartilhar em outros sites
  • 1 month later...
  • 1 month later...
  • 2 weeks later...

 

Por: BananaFight > DragonElement

 

Depois de ver muitos pedidos, Resolvi doar em nome da equipe DigiWo o código que muda a cor do nome dos monstros.

483597_533417260043045_121647455_n.png

Este é uma versão 1.0 que não serve mais para o DigiWo por ja termos um sistema mais avançado.

Instalação

Creature.cpp procure por


if(healthPercent > 92)

Embaixo você muda para




if (m_name == "Banana Fight"){

            m_informationColor = Color(0xB2, 0x22, 0x22);

        }else{

            m_informationColor = Color(0x00, 0xBC, 0x00);

        }

Acho que deu de entender o que tem que fazer,

Adicionando Nomes

Isto representa o nome do monstro/player que terá a cor do nome alterada. (Sim, vai ter que cadastrar nome por nome nesse sistema.)

if (m_name == "Banana Fight")

Para adicionar mais nomes é só seguindo a logica

if (m_name == "Banana Fight"){
            m_informationColor = Color(0xB2, 0x22, 0x22);
        }else if (m_name == "Demon"){
            m_informationColor = Color(0xFF, 0xFF, 0xFF);
        }else{
            m_informationColor = Color(0x00, 0xBC, 0x00);
        }

E para colorir o resto das porcentagens a mesma coisa

else if(healthPercent > 60)
    if (m_name == "Banana Fight"){
            m_informationColor = Color(0xB2, 0x22, 0x22);
        }else{
        m_informationColor = Color(0x50, 0xA1, 0x50);
}

Só recomendo que não mecha no ultimo, pois se não souber mexer pode dar erro.

else
        m_informationColor = Color(0x85, 0x0C, 0x0C);

Adicionando Cores

Isto representa a porcentagem de hp que o player ou monstro vai estar

m_informationColor = Color(0x00, 0xBC, 0x00);

Para mudar a cor você edita aqui :

Color(0x00, 0xBC, 0x00)

As corer funcionam da seguinte maneira (RGB)

00 BC 00 < Está é uma cor RGB Hexadecimal

Aqui um link com uma tabela: http://shibolete.tripod.com/RGB.html

Você tem que pegar a cor hexadecimal e dividir em 3 partes

#FFFF00 > FF FF 00

Ai é só você preencher, Color(0xFF, 0xFF, 0x00) com cada letra/numero.

Exemplo Final

void Creature::setHealthPercent(uint8 healthPercent)[/center]
{
    if(healthPercent > 92)
        if (m_name == "Banana Fight"){
            m_informationColor = Color(0xB2, 0x22, 0x22);
        }else{
            m_informationColor = Color(0x00, 0xBC, 0x00);
        }
    else if(healthPercent > 60)
        if (m_name == "Banana Fight"){
            m_informationColor = Color(0xB2, 0x22, 0x22);
        }else{
        m_informationColor = Color(0x50, 0xA1, 0x50);
        }
    else if(healthPercent > 30)
        if (m_name == "Banana Fight"){
            m_informationColor = Color(0xB2, 0x22, 0x22);
        }else{
        m_informationColor = Color(0xA1, 0xA1, 0x00);
        }
    else if(healthPercent > 8)
        if (m_name == "Banana Fight"){
            m_informationColor = Color(0xB2, 0x22, 0x22);
        }else{
        m_informationColor = Color(0xBF, 0x0A, 0x0A);
        }
    else if(healthPercent > 3)
        if (m_name == "Banana Fight"){
            m_informationColor = Color(0xB2, 0x22, 0x22);
        }else{
        m_informationColor = Color(0x91, 0x0F, 0x0F);
        }
    else
        m_informationColor = Color(0x85, 0x0C, 0x0C);

    m_healthPercent = healthPercent;
    callLuaField("onHealthPercentChange", healthPercent);

    if(healthPercent <= 0)
        onDeath();
}

o Sistema de Color Name, só funciona com Source??

 

Queria por Script ou Mod para PokeTibia

Meus Contatos!

 

Minhas Funções:

 

               Skype: TsplayerT

         Facebook: TakaFukushii

          YouTube: ADoseDupla

           Twitter: @_Splayer_

 

 

 

 

 

 

 

                             Mapper:▓▓▓▓▓▓▓▓▓▓ 97%

     Programmer:▓▓▓▓▓▒▒▒▒▒ 45%

             Scripter:▓▓▓▓▓▓▓▓▓▒ 83%

              Spriter:▓▓▓▓▓▓▒▒▒▒ 57%

    Gamemaster:▓▓▓▓▓▓▓▓▓▓ 99%

        Ot Creator:▓▓▓▓▓▓▓▒▒▒71%

Ot Client Maker:▓▓▓▓▓▓▓▒▒▒74%

 

Link para o post
Compartilhar em outros sites
  • 1 month later...

se vc colocar essa isso la no seu arquivo thing.lua antes do ultimo end os npc teram a cor azul g_game.enableFeature(GameBlueNpcNameColor).

Link para o post
Compartilhar em outros sites
  • 2 weeks later...

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

Link para o post
Compartilhar em outros sites
  • 2 years later...
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

 

Link para o post
Compartilhar em outros sites
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

Link para o post
Compartilhar em outros sites

@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)
Link para o post
Compartilhar em outros sites

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

×   Você colou conteúdo com formatação.   Remover formatação

  Apenas 75 emojis são permitidos.

×   Seu link foi automaticamente incorporado.   Mostrar como link

×   Seu conteúdo anterior foi restaurado.   Limpar o editor

×   Não é possível colar imagens diretamente. Carregar ou inserir imagens do URL.

  • Quem Está Navegando   0 membros estão online

    Nenhum usuário registrado visualizando esta página.

  • Conteúdo Similar

    • Por L3K0T
      TUTORIAL BY L3K0T PT~EN
       
      Olá pessoal, trago a vocês uma atualização que fiz no sistema, contendo 3 novas funcionalidades de movimentação de itens e uma proteção contra Elf Bot. Estas adições foram cuidadosamente implementadas para aperfeiçoar a experiência de jogo e manter a integridade do seu servidor.
      As novas funcionalidades têm a função vital de impedir que jogadores deixem itens indesejados em locais inapropriados, como na entrada de sua casa, em cima de seus depósitos ou em teleportes. Agora, apenas proprietários, subproprietários e convidados têm permissão para manipular itens nesses locais.
      Este pacote de atualização foi meticulosamente revisado para evitar abusos por parte de jogadores mal-intencionados e garantir um ambiente de jogo justo e equilibrado para todos os usuários.
       
       
       
      Iniciando o Tutorial
      1Abra o arquivo "creatureevents.cpp" com o editor de sua preferência. Eu pessoalmente recomendo o Notepad++. 
       
       
      Em creatureevents.cpp:
      return "onPrepareDeath"; Adicione abaixo:
      case CREATURE_EVENT_MOVEITEM: return "onMoveItem"; case CREATURE_EVENT_MOVEITEM2: return "onMoveItem2";  
      Em:
      return "cid, deathList"; Adicione abaixo:
      case CREATURE_EVENT_MOVEITEM: return "moveItem, frompos, topos, cid"; case CREATURE_EVENT_MOVEITEM2: return "cid, item, count, toContainer, fromContainer, fromPos, toPos";  
      Em:
      m_type = CREATURE_EVENT_PREPAREDEATH; Adicione abaixo:
      else if(tmpStr == "moveitem") m_type = CREATURE_EVENT_MOVEITEM; else if(tmpStr == "moveitem2") m_type = CREATURE_EVENT_MOVEITEM2;  
      Procure por:
      bool CreatureEvents::playerLogout(Player* player, bool forceLogout) { //fire global event if is registered bool result = true; for(CreatureEventList::iterator it = m_creatureEvents.begin(); it != m_creatureEvents.end(); ++it) { if((*it)->getEventType() == CREATURE_EVENT_LOGOUT && (*it)->isLoaded() && !(*it)->executeLogout(player, forceLogout) && result) result = false; } return result; } Adicione abaixo:
      uint32_t CreatureEvents::executeMoveItems(Creature* actor, Item* item, const Position& frompos, const Position& pos) { // fire global event if is registered for(CreatureEventList::iterator it = m_creatureEvents.begin(); it != m_creatureEvents.end(); ++it) { if((*it)->getEventType() == CREATURE_EVENT_MOVEITEM) { if(!(*it)->executeMoveItem(actor, item, frompos, pos)) return 0; } } return 1; }  
      Em:
      bool CreatureEvents::playerLogin(Player* player) { //fire global event if is registered bool result = true; for(CreatureEventList::iterator it = m_creatureEvents.begin(); it != m_creatureEvents.end(); ++it) { if((*it)->getEventType() == CREATURE_EVENT_LOGIN && (*it)->isLoaded() && !(*it)->executeLogin(player) && result) result = false; } if (result) { for(CreatureEventList::iterator it = m_creatureEvents.begin(); it != m_creatureEvents.end(); ++it) { CreatureEvent* event = *it; if(event->isLoaded() && ( event->getRegister() == "player" || event->getRegister() == "all") ) player->registerCreatureEvent(event->getName()); } } return result; } Adicione Abaixo:
      uint32_t CreatureEvent::executeMoveItem(Creature* actor, Item* item, const Position& frompos, const Position& pos) { //onMoveItem(moveItem, frompos, position, cid) if(m_interface->reserveEnv()) { ScriptEnviroment* env = m_interface->getEnv(); if(m_scripted == EVENT_SCRIPT_BUFFER) { env->setRealPos(pos); std::stringstream scriptstream; env->streamThing(scriptstream, "moveItem", item, env->addThing(item)); env->streamPosition(scriptstream, "position", frompos, 0); env->streamPosition(scriptstream, "position", pos, 0); scriptstream << "local cid = " << env->addThing(actor) << std::endl; scriptstream << m_scriptData; bool result = true; if(m_interface->loadBuffer(scriptstream.str())) { lua_State* L = m_interface->getState(); result = m_interface->getGlobalBool(L, "_result", true); } m_interface->releaseEnv(); return result; } else { #ifdef __DEBUG_LUASCRIPTS__ char desc[35]; sprintf(desc, "%s", player->getName().c_str()); env->setEventDesc(desc); #endif env->setScriptId(m_scriptId, m_interface); env->setRealPos(pos); lua_State* L = m_interface->getState(); m_interface->pushFunction(m_scriptId); LuaInterface::pushThing(L, item, env->addThing(item)); LuaInterface::pushPosition(L, frompos, 0); LuaInterface::pushPosition(L, pos, 0); lua_pushnumber(L, env->addThing(actor)); bool result = m_interface->callFunction(4); m_interface->releaseEnv(); return result; } } else { std::clog << "[Error - CreatureEvent::executeMoveItem] Call stack overflow." << std::endl; return 0; } } uint32_t CreatureEvent::executeMoveItem2(Player* player, Item* item, uint8_t count, const Position& fromPos, const Position& toPos, Item* toContainer, Item* fromContainer, int16_t fstack) { //onMoveItem2(cid, item, count, toContainer, fromContainer, fromPos, toPos) if(m_interface->reserveEnv()) { ScriptEnviroment* env = m_interface->getEnv(); if(m_scripted == EVENT_SCRIPT_BUFFER) { env->setRealPos(player->getPosition()); std::stringstream scriptstream; scriptstream << "local cid = " << env->addThing(player) << std::endl; env->streamThing(scriptstream, "item", item, env->addThing(item)); scriptstream << "local count = " << count << std::endl; env->streamThing(scriptstream, "toContainer", toContainer, env->addThing(toContainer)); env->streamThing(scriptstream, "fromContainer", fromContainer, env->addThing(fromContainer)); env->streamPosition(scriptstream, "fromPos", fromPos, fstack); env->streamPosition(scriptstream, "toPos", toPos, 0); scriptstream << m_scriptData; bool result = true; if(m_interface->loadBuffer(scriptstream.str())) { lua_State* L = m_interface->getState(); result = m_interface->getGlobalBool(L, "_result", true); } m_interface->releaseEnv(); return result; } else { #ifdef __DEBUG_LUASCRIPTS__ char desc[30]; sprintf(desc, "%s", player->getName().c_str()); env->setEvent(desc); #endif env->setScriptId(m_scriptId, m_interface); env->setRealPos(player->getPosition()); lua_State* L = m_interface->getState(); m_interface->pushFunction(m_scriptId); lua_pushnumber(L, env->addThing(player)); LuaInterface::pushThing(L, item, env->addThing(item)); lua_pushnumber(L, count); LuaInterface::pushThing(L, toContainer, env->addThing(toContainer)); LuaInterface::pushThing(L, fromContainer, env->addThing(fromContainer)); LuaInterface::pushPosition(L, fromPos, fstack); LuaInterface::pushPosition(L, toPos, 0); //lua_pushnumber(L, env->addThing(actor)); bool result = m_interface->callFunction(7); m_interface->releaseEnv(); return result; } } else { std::clog << "[Error - CreatureEvent::executeMoveItem] Call stack overflow." << std::endl; return 0; } }  
       
       
      Agora em em creatureevents.h:
      CREATURE_EVENT_PREPAREDEATH, Adicione abaixo:
      CREATURE_EVENT_MOVEITEM, CREATURE_EVENT_MOVEITEM2  
      Em:
      uint32_t executePrepareDeath(Creature* creature, DeathList deathList); Adicione abaixo:
      uint32_t executeMoveItem(Creature* actor, Item* item, const Position& frompos, const Position& pos); uint32_t executeMoveItem2(Player* player, Item* item, uint8_t count, const Position& fromPos, const Position& toPos, Item* toContainer, Item* fromContainer, int16_t fstack);  
      Em:
      bool playerLogout(Player* player, bool forceLogout); Abaixo adicone também
      uint32_t executeMoveItems(Creature* actor, Item* item, const Position& frompos, const Position& pos); uint32_t executeMoveItem2(Player* player, Item* item, uint8_t count, const Position& fromPos, const Position& toPos, Item* toContainer, Item* fromContainer, int16_t fstack);  
       
      Agora em em game.cpp:
      if(!canThrowObjectTo(mapFromPos, mapToPos) && !player->hasCustomFlag(PlayerCustomFlag_CanThrowAnywhere)) { player->sendCancelMessage(RET_CANNOTTHROW); return false; } ReturnValue ret = internalMoveItem(player, fromCylinder, toCylinder, toIndex, item, count, NULL); if(ret == RET_NOERROR) return true; player->sendCancelMessage(ret); return false; } Altere para:
      if (!canThrowObjectTo(mapFromPos, mapToPos) && !player->hasCustomFlag(PlayerCustomFlag_CanThrowAnywhere)) { player->sendCancelMessage(RET_CANNOTTHROW); return false; } bool success = true; CreatureEventList moveitemEvents = player->getCreatureEvents(CREATURE_EVENT_MOVEITEM2); for (CreatureEventList::iterator it = moveitemEvents.begin(); it != moveitemEvents.end(); ++it) { Item* toContainer = toCylinder->getItem(); Item* fromContainer = fromCylinder->getItem(); if (!(*it)->executeMoveItem2(player, item, count, fromPos, toPos, (toContainer ? toContainer : 0), (fromContainer ? fromContainer : 0), fromStackpos) && success) success = false; } if (!success) return false; if (g_config.getBool(ConfigManager::ANTI_PUSH)) { std::string antiPushItems = g_config.getString(ConfigManager::ANTI_PUSH_ITEMS); IntegerVec tmpVec = vectorAtoi(explodeString(antiPushItems, ",")); if (tmpVec[0] != 0) { for (IntegerVec::iterator it = tmpVec.begin(); it != tmpVec.end(); ++it) { if (item->getID() == uint32_t(*it) && player->hasCondition(CONDITION_EXHAUST, 1)) { player->sendTextMessage(MSG_STATUS_SMALL, "Please wait a few seconds to move this item."); return false; } } } } int32_t delay = g_config.getNumber(ConfigManager::ANTI_PUSH_DELAY); if (Condition* condition = Condition::createCondition(CONDITIONID_DEFAULT, CONDITION_EXHAUST, delay, 0, false, 1)) player->addCondition(condition); if (!g_creatureEvents->executeMoveItems(player, item, mapFromPos, mapToPos)) return false; ReturnValue ret = internalMoveItem(player, fromCylinder, toCylinder, toIndex, item, count, NULL); if (ret != RET_NOERROR) { player->sendCancelMessage(ret); return false; } player->setNextAction(OTSYS_TIME() + g_config.getNumber(ConfigManager::ACTIONS_DELAY_INTERVAL) - 10); return true; }  
      Agora em configmanager.h
      ADMIN_ENCRYPTION_DATA Adicione abaixo:
      ANTI_PUSH_ITEMS,  
      em:
      STAMINA_DESTROY_LOOT, Adicione abaixo:
      ANTI_PUSH_DELAY,  
      em:
      ADDONS_PREMIUM, Adicione abaixo:
      ANTI_PUSH  
      Agora você pode compilar a Source.
       
       
      Configurando no servidor:
       
      Abra seu config.lua do servidor e adicione isso dentro qualquer lugar:
      -- Anti-Push useAntiPush = true antiPushItems = "2148,2152,2160,3976" antiPushDelay = 500  
       
      Navegue até o diretório 'creaturescripts' e localize o arquivo 'login.lua'.
      em resgistros de eventos adicione:
      login.lua
      registerCreatureEvent(cid, "MoveItem") registerCreatureEvent(cid, "MoveItem2")  
      Agora abra o aquivo creaturescript .xml
      <event type="moveitem" name="MoveItem" event="script" value="houseprotecao.lua"/> <event type="moveitem2" name="MoveItem2" event="script" value="moveitem2.lua"/>  
      Crie um novo arquivo lua em scripts com o nome houseprotecao.lua e adicione isso:
      function onMoveItem(moveItem, frompos, position, cid) if position.x == CONTAINER_POSITION then return true end local house = getHouseFromPos(frompos) or getHouseFromPos(position) --correção 100% if type(house) == "number" then local owner = getHouseOwner(house) if owner == 0 then return false, doPlayerSendCancel(cid, "Isso não é Possível.") end if owner ~= getPlayerGUID(cid) then local sub = getHouseAccessList(house, 0x101):explode("\n") local guest = getHouseAccessList(house, 0x100):explode("\n") local isInvited = false if (#sub > 0) and isInArray(sub, getCreatureName(cid)) then isInvited = true end if (#guest > 0) and isInArray(guest, getCreatureName(cid)) then isInvited = true end if not isInvited then return false, doPlayerSendCancel(cid, "Desculpe, você não está invitado.") end end end return true end  
      Crie um novo arquivo lua em scripts com o nome moveitem2.lua e adicione isso abaixo:
      local depottiles = {} --piso pra n jogar local depots = {2589} --id dos dps local group = 3 --id dos group 6 é todos. local function checkIfThrow(pos,topos) if topos.x == 0xffff then return false end local thing = getThingFromPos(pos) if isInArray(depottiles,thing.itemid) then if not isInArea(topos,{x=pos.x-1,y=pos.y-1,z=pos.z},{x=pos.x+1,y=pos.y+1, z=pos.z}) then return true end else for i = 1, #depots do if depots[i] == getTileItemById(topos,depots[i]).itemid or getTileInfo(topos).actionid == 7483 then return true end end end return false end function onMoveItem2(cid, item, count, toContainer, fromContainer, fromPos, toPos) if isPlayer(cid) then local pos = getThingPos(cid) if getPlayerGroupId(cid) > group then return true end if checkIfThrow({x=pos.x,y=pos.y,z=pos.z,stackpos=0},toPos) then doPlayerSendCancel(cid,"Não jogue item ai!!") doSendMagicEffect(getThingPos(cid),CONST_ME_POFF) return false end end return true end  
      ajudei?? REP+
      CRÉDITOS:
      @L3K0T
      Fir3element
      Summ
      Wise
      GOD Wille
      Yan Lima
       
       
       
       
    • Por Doria Louro
      Olá senhores.
       
      Gostaria de uma ajuda com um script de summon que venho trabalhando no momento, gostaria que o summon andasse do lado do jogador, entretanto o mesmo sempre fica para trás ou a frente do jogador.
      Efetuei a alteração na source creature.cpp:
       
      void Creature::getPathSearchParams(const Creature* creature, FindPathParams& fpp) const { fpp.fullPathSearch = !hasFollowPath; fpp.clearSight = true; if(creature->isPlayerSummon()) { if(creature->getName() == "Summon Name") fpp.clearSight = false; } fpp.maxSearchDist = 12; fpp.minTargetDist = fpp.maxTargetDist = 1; }  
      fpp.maxTargetDist = 1;
      Porém ele sempre mantem 1 de distancia do jogador, alterando para zero o "Zero" summon nem segue o jogador.
      Resultado:

       
      Agradeço desde já.
    • Por Imperius
      O propósito é criar uma nova função em creaturescripts que será acionada toda vez que um novo report (CTRL + R) for aberto.
       
      Eu implementei para enviar uma notificação no grupo do Telegram, contendo os dados do report.
       
      Isso garantirá que os GMs tenham acesso aos reports dos jogadores mesmo quando não estiverem logados, e também evitará que algum report seja perdido caso o jogador saia do servidor.
      A parte do Telegram é apenas um exemplo. Você pode ajustar o script para executar outras ações desejadas.
       
      creatureevent.cpp:
      Dentro deste arquivo, localize a função:
       
      uint32_t CreatureEvent::executeChannelLeave(Player* player, uint16_t channelId, UsersMap usersMap)  
      abaixo dela, adicione:
       
      uint32_t CreatureEvent::executeOpenRuleViolation(Player* player, std::string message) { if (!m_interface->reserveEnv()) { std::clog << "[Error - CreatureEvent::executeOpenRuleViolation] Call stack overflow." << std::endl; return 0; } ScriptEnviroment* env = m_interface->getEnv(); env->setScriptId(m_scriptId, m_interface); lua_State* L = m_interface->getState(); m_interface->pushFunction(m_scriptId); lua_pushnumber(L, env->addThing(player)); lua_pushstring(L, message.c_str()); bool result = m_interface->callFunction(2); m_interface->releaseEnv(); return result; }  
      Após, procure por:
       
      std::string CreatureEvent::getScriptEventName() const  
      abaixo de:
       
      case CREATURE_EVENT_CHANNEL_LEAVE: return "onLeaveChannel";  
      adicione:
       
      case CREATURE_EVENT_OPEN_RULE_VIOLATION: return "onOpenRuleViolation";  
      Agora, procure por:
       
      std::string CreatureEvent::getScriptEventParams() const  
      abaixo de:
       
      case CREATURE_EVENT_CHANNEL_LEAVE: return "cid, channel, users";  
      adicione:
       
      case CREATURE_EVENT_OPEN_RULE_VIOLATION: return "cid, message";  
      Procure por:
       
      bool CreatureEvent::configureEvent(xmlNodePtr p)  
      abaixo de:
       
      else if(tmpStr == "leavechannel") m_type = CREATURE_EVENT_CHANNEL_LEAVE;  
      adicione:
       
      else if(tmpStr == "openruleviolation") m_type = CREATURE_EVENT_OPEN_RULE_VIOLATION;  
       
      creatureevent.h:
      Dentro deste arquivo, localize:
       
      enum CreatureEventType_t  
      adicione "CREATURE_EVENT_OPEN_RULE_VIOLATION" como o último item de enum CreatureEventType_t
       
      Exemplo:
       
      enum CreatureEventType_t { // ... CREATURE_EVENT_OPEN_RULE_VIOLATION };  
      Agora, procure por:
       
      uint32_t executeChannelLeave(Player* player, uint16_t channelId, UsersMap usersMap);  
      abaixo dela, adicione:
       
      uint32_t executeOpenRuleViolation(Player* player, std::string message);  
      game.cpp:
      Dentro deste arquivo, localize:
       
      bool Game::playerReportRuleViolation(Player* player, const std::string& text)  
      e substitua por:
       
      bool Game::playerReportRuleViolation(Player* player, const std::string& text) { //Do not allow reports on multiclones worlds since reports are name-based if(g_config.getNumber(ConfigManager::ALLOW_CLONES)) { player->sendTextMessage(MSG_INFO_DESCR, "Rule violation reports are disabled."); return false; } cancelRuleViolation(player); boost::shared_ptr<RuleViolation> rvr(new RuleViolation(player, text, time(NULL))); ruleViolations[player->getID()] = rvr; ChatChannel* channel = g_chat.getChannelById(CHANNEL_RVR); if(!channel) return false; for(UsersMap::const_iterator it = channel->getUsers().begin(); it != channel->getUsers().end(); ++it) it->second->sendToChannel(player, SPEAK_RVR_CHANNEL, text, CHANNEL_RVR, rvr->time); CreatureEventList joinEvents = player->getCreatureEvents(CREATURE_EVENT_OPEN_RULE_VIOLATION); for(CreatureEventList::iterator it = joinEvents.begin(); it != joinEvents.end(); ++it) (*it)->executeOpenRuleViolation(player, text); return true; }  
      Agora é só compilar a source.
       
      depois em "data > creaturescripts > creaturescripts.xml", adicione:
       
      <event type="login" name="loginNotifyRuleViolation" script="notifyRuleViolation.lua"/> <event type="openruleviolation" name="openNotifyRuleViolation" script="notifyRuleViolation.lua"/>  
      em "data > creaturescripts > scripts", crie um arquivo notifyRuleViolation.lua e adicione:
       
      function onOpenRuleViolation(cid, message) local config = { token = "", -- Token do seu BOT no Telegram chatId = "" -- ID do chat do Telegram que será enviado a notificação. } local message = "Player: "..getCreatureName(cid).."\n\nReport:\n"..message.."" message = string.gsub(message, "\n", "%%0A") local url = "https://api.telegram.org/bot"..config.token.."/sendMessage" local data = "chat_id="..config.chatId.."&text="..message.."" local curl = io.popen('curl -d "'..data..'" "'..url..'"'):read("*a") return true end function onLogin(cid) registerCreatureEvent(cid, "openNotifyRuleViolation") return true end  
       
      Demonstração:
      1. Jogador abre um novo report (CTRL + R)

      2. notifyRuleViolation.lua, definido em creaturescripts.xml, é acionado para enviar uma notificação ao grupo do Telegram.
       

       
    • Por FeeTads
      SALVE rapaziada do TK, esses dias vim pensando em novos scripts pro meu OT, e em um deles eu precisava que determinada area não contasse frag pro player que matasse outros, PORÉM eu precisava que os players que morressem nessa area ainda assim tivessem as penalidades da sua morte, procurei por ai, achei alguns scripts que apenas tiravam o SKULL e não realmente o FRAG do player.

      **script atualizado 22/10/2023** - melhorado e otimizado, levei o script pra puxar as infos por .lua / creatureScripts

      vou disponibilizar o code aqui, e o que fazer pra determinada area não contar frag.

      SOURCE OTX 2 / TFS 0.x, Funciona em TFS 1.x mudando as tags e ajeitando as sintaxes.

      vá em creatureevent.cpp

      procure por:
      else if(type == "preparedeath") _type = CREATURE_EVENT_PREPAREDEATH;
      Adiciona abaixo:
      else if(type == "nocountfrag") _type = CREATURE_EVENT_NOCOUNTFRAG;

      procure por:
      case CREATURE_EVENT_PREPAREDEATH: return "onPrepareDeath";  
      Adicione abaixo: 
      case CREATURE_EVENT_NOCOUNTFRAG: return "noCountFragArea";

      procure por:
      case CREATURE_EVENT_PREPAREDEATH: return "cid, deathList";
      Adicione abaixo:
      case CREATURE_EVENT_NOCOUNTFRAG: return "cid, target";

      agora no mesmo arquivo, vá até o final do arquivo e adicione essa função:
      uint32_t CreatureEvent::executeNoCountFragArea(Creature* creature, Creature* target) { //noCountFragArea(cid, target) if(m_interface->reserveEnv()) { ScriptEnviroment* env = m_interface->getEnv(); if(m_scripted == EVENT_SCRIPT_BUFFER) { env->setRealPos(creature->getPosition()); std::ostringstream scriptstream; scriptstream << "local cid = " << env->addThing(creature) << std::endl; scriptstream << "local target = " << env->addThing(target) << std::endl; if(m_scriptData) scriptstream << *m_scriptData; bool result = true; if(m_interface->loadBuffer(scriptstream.str())) { lua_State* L = m_interface->getState(); result = m_interface->getGlobalBool(L, "_result", true); } m_interface->releaseEnv(); return result; } else { #ifdef __DEBUG_LUASCRIPTS__ std::ostringstream desc; desc << creature->getName(); env->setEvent(desc.str()); #endif env->setScriptId(m_scriptId, m_interface); env->setRealPos(creature->getPosition()); lua_State* L = m_interface->getState(); m_interface->pushFunction(m_scriptId); lua_pushnumber(L, env->addThing(creature)); lua_pushnumber(L, env->addThing(target)); bool result = m_interface->callFunction(2); m_interface->releaseEnv(); return result; } } else { std::clog << "[Error - CreatureEvent::noCountFragArea] Call stack overflow." << std::endl; return 0; } }

      agora vá em creatureevent.h

      procure por:
      CREATURE_EVENT_PREPAREDEATH
      adicione abaixo:
      CREATURE_EVENT_NOCOUNTFRAG

      procure por:
      uint32_t executePrepareDeath(Creature* creature, DeathList deathList);
      Adicione abaixo:
      uint32_t executeNoCountFragArea(Creature* creature, Creature* target);

      agora vá em player.cpp

      procure por:
      bool Player::onKilledCreature(Creature* target, DeathEntry& entry)
      abaixo de:
      War_t enemy; if(targetPlayer->getEnemy(this, enemy)) { if(entry.isLast()) IOGuild::getInstance()->updateWar(enemy); entry.setWar(enemy); }
      Adicione o seguinte código:
      if (targetPlayer){ CreatureEventList killEvents = getCreatureEvents(CREATURE_EVENT_NOCOUNTFRAG); for (const auto &event : killEvents) { if (!event->executeNoCountFragArea(this, target)) { return true; } } }

      //

      Feito isso, tudo completo na sua source, agora é necessário adicionar o creaturescript dentro do servidor

      vá até creaturescripts/scripts
      crie um arquivo chamado, "noCountFragInArea.lua"
      e dentro dele cole o código:
       
      --[[ script feito por feetads / TibiaKing ]]-- --[[ discord: feetads / FeeTads#0246 ]]-- -- Add positions here for which you do not want to count frags local areas = { [1] = {from = {x = 91, y = 122, z = 7}, to = {x = 98, y = 127, z = 7}}, -- from = area superior esquerda / to = area inferior direita (formando um quadrado) } local onlyKillerInArea = false -- only killer need to be in area? function noCountFragArea(cid, target) if not isCreature(cid) or not isCreature(target) then return true end local posKiller = getPlayerPosition(cid) local posTarget = getPlayerPosition(target) for i = 1, #areas do local area = areas[i] if isInArea(posKiller, area.from, area.to) then if onlyKillerInArea then return false elseif isInArea(posTarget, area.from, area.to) then return false end end end return true end
      agora em creaturescripts.xml
      <event type="nocountfrag" name="fragarea" event="script" value="noCountFragInArea.lua"/>
      agora em creaturescripts/scripts/login.lua
       procure por OU semelhante a esse:
      registerCreatureEvent(cid, "AdvanceSave")
      e abaixo adicione:
      registerCreatureEvent(cid, "fragarea")

      //


      Agora tudo certo, quando quiser adiciona uma area que não pega frag, vá até o script e apenas coloque a area, igual o demonstrado no script

      Exemplo:
      local areas = { [1] = {from = {x = 91, y = 122, z = 7}, to = {x = 98, y = 127, z = 7}}, [2] = {from = {x = 1000, y = 1000, z = 7}, to = {x = 1100, y = 1100, z = 7}}, }
      assim somente colocando a area no script e abrindo o server ou dando /reload, já funcionará a area como não pegar frag.
      Esse sistema pode ser bom pra areas de pvp ativo, onde você ainda quer que o player que morrer perca os atributos, como se fosse uma morte normal, porém não conta frag pra quem matar.
      Bom pra sistemas tipo castle 48h (guild war), onde há diversas mortes e risco de pegar red, atrapalhando a war.

      Façam bom proveito dos scripts, e deixem os créditos no script rsrs

      **Eu fiz as alterações e o simples código por isso vim disponibilizar, créditos meus**
    • Por Mateus Robeerto
      Para quem deseja utilizar o 'IncreaseMagicPercent' no arquivo items.xml, que aumenta o dano mágico em porcentagem
       
       
      No arquivo game.cpp
      depois.
      Player* attackerPlayer; if (attacker) { attackerPlayer = attacker->getPlayer(); } else { attackerPlayer = nullptr; } Player* targetPlayer = target->getPlayer(); if (attackerPlayer && targetPlayer && attackerPlayer->getSkull() == SKULL_BLACK && attackerPlayer->getSkullClient(targetPlayer) == SKULL_NONE) { return false; } damage.primary.value = std::abs(damage.primary.value); damage.secondary.value = std::abs(damage.secondary.value); int32_t healthChange = damage.primary.value + damage.secondary.value; if (healthChange == 0) { return true; } adicionar
      // Inc Magic by lursky auto originList = { ORIGIN_RANGED, ORIGIN_MELEE, ORIGIN_CONDITION }; auto it = std::find(originList.begin(), originList.end(), damage.origin); if (attackerPlayer && it == originList.end()) { int32_t magicPercentBonus = 0; for (int32_t slot = CONST_SLOT_FIRST; slot <= CONST_SLOT_LAST; ++slot) { Item* item = attackerPlayer->inventory[slot]; if (item) { const ItemType& iiType = Item::items[item->getID()]; const int32_t& slotPosition = item->getSlotPosition(); if (iiType.increaseMagicPercent && (iiType.slotPosition & slotPosition)) { magicPercentBonus += iiType.increaseMagicPercent; } } } if (magicPercentBonus > 0) { damage.primary.value += damage.primary.value * (magicPercentBonus / 100.0f); } } No arquivo item.cpp
       
      post edit: Deve ter colocado duas vezes, ok? É só procurar no item.cpp essa linha e adicionar. Repita a busca pela mesma linha e adicione para exibir 'inc magic'. Pronto 

      depois.
      if (it.abilities) { for (uint8_t i = SKILL_FIRST; i <= SKILL_LAST; i++) { if (!it.abilities->skills[i]) { continue; } if (begin) { begin = false; s << " ("; } else { s << ", "; } s << getSkillName(i) << ' ' << std::showpos << it.abilities->skills[i] << std::noshowpos; } adicionar.
      if (it.increaseMagicPercent) { if (begin) { begin = false; s << " ("; } else { s << ", "; } s << "Inc.Magic " << std::showpos << it.increaseMagicPercent << '%' << std::noshowpos; } No arquivo items.cpp
      depois.
      {"worth", ITEM_PARSE_WORTH}, adicionar:
      { "increasemagicpercent", ITEM_PARSE_INCREASEMAGICPERCENT }, Novamente, no arquivo items.cpp:
      depois.
      case ITEM_PARSE_SUPPRESSCURSE: { if (valueAttribute.as_bool()) { abilities.conditionSuppressions |= CONDITION_CURSED; } break; } adicionar.
      case ITEM_PARSE_INCREASEMAGICPERCENT: { it.increaseMagicPercent = pugi::cast<int32_t>(valueAttribute.value()); break; } No arquivo items.h
      depois.
      uint64_t worth = 0; adicionar.
      int32_t increaseMagicPercent = 0; Novamente, no arquivo items.h:
      after.
      ITEM_PARSE_WORTH, adicionar:
      ITEM_PARSE_INCREASEMAGICPERCENT, FIM
      É só recompilar e testar
      Como funciona usar esses atributos? Veja aqui um exemplo
      item id="xxx" name="teste robe"> <attribute key="weight" value="7100"/> <attribute key="armor" value="18"/> <attribute key="slotType" value="body"/> <attribute key="increaseMagicPercent" value="50"/> </item>  
      Obs: Esses adições na source foram feitas por Mateus Roberto, e Lurskcy fez uma correção de erro que estava causando um .crash no arquivo games.cpp. Está funcionando bem.
       
      Espero que gostem
×
×
  • Criar Novo...

Informação Importante

Confirmação de Termo