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