Esempio n. 1
0
 MoveInfo getAttackMove(Creature* other, bool chase) {
   int distance = 10000;
   CHECK(other);
   if (other->getAttributes().isInvincible())
     return NoMove;
   Debug() << creature->getName().bare() << " enemy " << other->getName().bare();
   Vec2 enemyDir = creature->getPosition().getDir(other->getPosition());
   distance = enemyDir.length8();
   if (creature->getAttributes().isHumanoid() && !creature->getWeapon()) {
     if (Item* weapon = getBestWeapon())
       if (auto action = creature->equip(weapon))
         return {3.0 / (2.0 + distance), action.prepend([=](Creature* creature) {
           creature->setInCombat();
           other->setInCombat();
       })};
   }
   if (distance == 1)
     if (MoveInfo move = tryEffect(EffectId::AIR_BLAST, 1))
       return move;
   if (distance <= 5)
     for (EffectType effect : {
         EffectType(EffectId::LASTING, LastingEffect::INVISIBLE),
         EffectType(EffectId::LASTING, LastingEffect::STR_BONUS),
         EffectType(EffectId::LASTING, LastingEffect::DEX_BONUS),
         EffectType(EffectId::LASTING, LastingEffect::SPEED),
         EffectType(EffectId::DECEPTION),
         EffectType(EffectId::SUMMON, CreatureId::SPIRIT)})
       if (MoveInfo move = tryEffect(effect, 1))
         return move;
   if (distance > 1) {
     if (distance < 10) {
       if (MoveInfo move = getFireMove(enemyDir))
         return move;
       if (MoveInfo move = getThrowMove(enemyDir))
         return move;
     }
     if (chase && !other->getAttributes().dontChase() && !isChaseFrozen(other)) {
       lastSeen = none;
       if (auto action = creature->moveTowards(other->getPosition()))
         return {max(0., 1.0 - double(distance) / 10), action.prepend([=](Creature* creature) {
           creature->setInCombat();
           other->setInCombat();
           lastSeen = {other->getPosition(), creature->getGlobalTime(), LastSeen::ATTACK, other->getUniqueId()};
           if (!chaseFreeze.count(other) || other->getGlobalTime() > chaseFreeze.at(other).second)
             chaseFreeze[other] = make_pair(other->getGlobalTime() + 20, other->getGlobalTime() + 70);
         })};
     }
   }
   if (distance == 1)
     if (auto action = creature->attack(other, getAttackParams(other)))
       return {1.0, action.prepend([=](Creature* creature) {
           creature->setInCombat();
           other->setInCombat();
       })};
   return NoMove;
 }
Esempio n. 2
0
 MoveInfo getAttackMove(const Creature* other, bool chase) {
   int radius = 4;
   int distance = 10000;
   CHECK(other);
   if (other->isInvincible())
     return NoMove;
   Debug() << creature->getName() << " enemy " << other->getName();
   Vec2 enemyDir = (other->getPosition() - creature->getPosition());
   distance = enemyDir.length8();
   if (creature->isHumanoid() && !creature->getEquipment().getItem(EquipmentSlot::WEAPON)) {
     Item* weapon = getBestWeapon();
     if (weapon != nullptr && creature->canEquip(weapon, nullptr))
       return {3.0 / (2.0 + distance), [this, weapon, other]() {
         EventListener::addCombatEvent(creature);
         EventListener::addCombatEvent(other);
         creature->globalMessage(creature->getTheName() + " draws " + weapon->getAName());
         creature->equip(weapon);
       }};
   }
   if (distance <= 5)
     for (EffectType effect : {EffectType::INVISIBLE, EffectType::STR_BONUS, EffectType::DEX_BONUS,
         EffectType::SPEED, EffectType::SUMMON_SPIRIT})
       if (MoveInfo move = tryToApplyItem(effect, 1))
         return move;
   if (distance > 1) {
     if (MoveInfo move = getFireMove(enemyDir))
       return move;
     if (MoveInfo move = getThrowMove(enemyDir))
       return move;
     if (chase && other->getTribe() != Tribes::get(TribeId::WILDLIFE)) {
       Optional<Vec2> move = creature->getMoveTowards(creature->getPosition() + enemyDir);
       lastSeen = Nothing();
       if (move)
         return {max(0., 1.0 - double(distance) / 10), [this, enemyDir, move, other]() {
           EventListener::addCombatEvent(creature);
           EventListener::addCombatEvent(other);
           lastSeen = {creature->getPosition() + enemyDir, creature->getTime(), creature->getLevel(),
               LastSeen::ATTACK, other};
           creature->move(*move);
         }};
     }
   }
   if (distance == 1) {
     if (creature->canAttack(other))
       return {1.0, [this, other]() {
         EventListener::addCombatEvent(creature);
         EventListener::addCombatEvent(other);
         creature->attack(other);
       }};
   }
   return NoMove;
 }