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); } } }
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); } } }