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