示例#1
0
void Monster::refreshTarget()
{
    // Check potential attack positions
    Being *bestAttackTarget = mTarget = NULL;
    int bestTargetPriority = 0;
    Point bestAttackPosition;
    BeingDirection bestAttackDirection = DOWN;

    // Iterate through objects nearby
    int aroundArea = Configuration::getValue("game_visualRange", 448);
    for (BeingIterator i(getMap()->getAroundBeingIterator(this, aroundArea));
         i; ++i)
    {
        // We only want to attack player characters
        if ((*i)->getType() != OBJECT_CHARACTER)
            continue;

        Being *target = static_cast<Being *>(*i);

        // Dead characters are ignored
        if (target->getAction() == DEAD)
            continue;

        // Determine how much we hate the target
        int targetPriority = 0;
        std::map<Being *, int, std::greater<Being *> >::iterator angerIterator;
        angerIterator = mAnger.find(target);
        if (angerIterator != mAnger.end())
        {
            targetPriority = angerIterator->second;
        }
        else if (mSpecy->isAggressive())
        {
            targetPriority = 1;
        }
        else
        {
            continue;
        }

        // Check all attack positions
        for (std::list<AttackPosition>::iterator j = mAttackPositions.begin();
             j != mAttackPositions.end(); j++)
        {
            Point attackPosition = target->getPosition();
            attackPosition.x += j->x;
            attackPosition.y += j->y;

            int posPriority = calculatePositionPriority(attackPosition,
                                                        targetPriority);
            if (posPriority > bestTargetPriority)
            {
                bestAttackTarget = mTarget = target;
                bestTargetPriority = posPriority;
                bestAttackPosition = attackPosition;
                bestAttackDirection = j->direction;
            }
        }
    }

    // Check if an enemy has been found
    if (bestAttackTarget)
    {
        // Check which attacks have a chance to hit the target
        MonsterAttacks allAttacks = mSpecy->getAttacks();
        std::map<int, MonsterAttack *> workingAttacks;
        int prioritySum = 0;

        const int distX = getPosition().x - bestAttackTarget->getPosition().x;
        const int distY = getPosition().y - bestAttackTarget->getPosition().y;
        const int distSquare = (distX * distX + distY * distY);

        for (MonsterAttacks::iterator i = allAttacks.begin();
             i != allAttacks.end();
             i++)
        {
            int maxDist = (*i)->range + bestAttackTarget->getSize();

            if (maxDist * maxDist >= distSquare)
            {
                prioritySum += (*i)->priority;
                workingAttacks[prioritySum] = (*i);
            }
        }

        if (workingAttacks.empty() || !prioritySum)
        {   //when no attack can hit move closer to attack position
            setDestination(bestAttackPosition);
        }
        else
        {
            // Prepare for using a random attack which can hit the enemy
            // Stop movement
            setDestination(getPosition());
            // Turn into direction of enemy
            setDirection(bestAttackDirection);
            // Perform a random attack based on priority
            mCurrentAttack =
                         workingAttacks.upper_bound(rand()%prioritySum)->second;
            setAction(ATTACK);
            raiseUpdateFlags(UPDATEFLAG_ATTACK);
        }
    }
}
示例#2
0
void MonsterComponent::refreshTarget(Entity &entity)
{
    auto *beingComponent = entity.getComponent<BeingComponent>();

    // We are dead and sadly not possible to keep attacking :(
    if (beingComponent->getAction() == DEAD)
        return;

    // Check potential attack positions
    int bestTargetPriority = 0;
    Entity *bestTarget = 0;
    Point bestAttackPosition;

    // reset Target. We will find a new one if possible
    entity.getComponent<CombatComponent>()->clearTarget();

    // Iterate through objects nearby
    int aroundArea = Configuration::getValue("game_visualRange", 448);
    for (BeingIterator i(entity.getMap()->getAroundBeingIterator(&entity,
                                                                 aroundArea));
         i; ++i)
    {
        // We only want to attack player characters
        if ((*i)->getType() != OBJECT_CHARACTER)
            continue;

        Entity *target = *i;

        // Dead characters are ignored
        if (beingComponent->getAction() == DEAD)
            continue;

        // Determine how much we hate the target
        int targetPriority = 0;
        std::map<Entity *, AggressionInfo>::iterator angerIterator =
                mAnger.find(target);
        if (angerIterator != mAnger.end())
        {
            const AggressionInfo &aggressionInfo = angerIterator->second;
            targetPriority = aggressionInfo.anger;
        }
        else if (mSpecy->isAggressive())
        {
            targetPriority = 1;
        }
        else
        {
            continue;
        }

        // Check all attack positions
        for (std::list<AttackPosition>::iterator j = mAttackPositions.begin();
             j != mAttackPositions.end(); j++)
        {
            Point attackPosition =
                    target->getComponent<ActorComponent>()->getPosition();
            attackPosition.x += j->x;
            attackPosition.y += j->y;

            int posPriority = calculatePositionPriority(entity,
                                                        attackPosition,
                                                        targetPriority);
            if (posPriority > bestTargetPriority)
            {
                bestTargetPriority = posPriority;
                bestTarget = target;
                bestAttackPosition = attackPosition;
            }
        }
    }
    if (bestTarget)
    {
        const Point &ownPosition =
                entity.getComponent<ActorComponent>()->getPosition();
        const Point &targetPosition =
                bestTarget->getComponent<ActorComponent>()->getPosition();

        entity.getComponent<CombatComponent>()->setTarget(bestTarget);
        if (bestAttackPosition == ownPosition)
        {
            beingComponent->setAction(entity, ATTACK);
            beingComponent->updateDirection(entity, ownPosition,
                                            targetPosition);
        }
        else
        {
            beingComponent->setDestination(entity, bestAttackPosition);
        }
    }
}