mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-06 09:09:40 +02:00
Removed hardcoded AI logic for Water Walk and Fly spell
This commit is contained in:
@@ -12,6 +12,8 @@
|
||||
#include "../Engine/Nullkiller.h"
|
||||
#include "../../../lib/mapObjects/MapObjects.h"
|
||||
#include "../../../lib/IGameSettings.h"
|
||||
#include "../../../lib/spells/ISpellMechanics.h"
|
||||
#include "../../../lib/spells/adventure/TownPortalEffect.h"
|
||||
|
||||
namespace NKAI
|
||||
{
|
||||
@@ -210,32 +212,31 @@ float HeroManager::getFightingStrengthCached(const CGHeroInstance * hero) const
|
||||
|
||||
float HeroManager::getMagicStrength(const CGHeroInstance * hero) const
|
||||
{
|
||||
auto hasFly = hero->spellbookContainsSpell(SpellID::FLY);
|
||||
auto hasTownPortal = hero->spellbookContainsSpell(SpellID::TOWN_PORTAL);
|
||||
auto manaLimit = hero->manaLimit();
|
||||
auto spellPower = hero->getPrimSkillLevel(PrimarySkill::SPELL_POWER);
|
||||
auto hasEarth = hero->getSpellSchoolLevel(SpellID(SpellID::TOWN_PORTAL).toSpell()) > 0;
|
||||
|
||||
auto score = 0.0f;
|
||||
|
||||
// FIXME: this will not cover spells give by scrolls / tomes. Intended?
|
||||
for(auto spellId : hero->getSpellsInSpellbook())
|
||||
{
|
||||
auto spell = spellId.toSpell();
|
||||
auto schoolLevel = hero->getSpellSchoolLevel(spell);
|
||||
auto townPortalEffect = spell->getAdventureMechanics().getEffectAs<TownPortalEffect>(hero);
|
||||
|
||||
score += (spell->getLevel() + 1) * (schoolLevel + 1) * 0.05f;
|
||||
|
||||
if (spell->getAdventureMechanics().givesBonus(hero, BonusType::FLYING_MOVEMENT))
|
||||
score += 0.3;
|
||||
|
||||
if(townPortalEffect != nullptr && schoolLevel != 0)
|
||||
score += 0.6f;
|
||||
}
|
||||
|
||||
vstd::amin(score, 1);
|
||||
|
||||
score *= std::min(1.0f, spellPower / 10.0f);
|
||||
|
||||
if(hasFly)
|
||||
score += 0.3f;
|
||||
|
||||
if(hasTownPortal && hasEarth)
|
||||
score += 0.6f;
|
||||
|
||||
vstd::amin(score, 1);
|
||||
|
||||
score *= std::min(1.0f, manaLimit / 100.0f);
|
||||
|
||||
@@ -28,12 +28,12 @@ namespace AIPathfinding
|
||||
manaCost = hero->getSpellCost(spellToCast.toSpell());
|
||||
}
|
||||
|
||||
WaterWalkingAction::WaterWalkingAction(const CGHeroInstance * hero)
|
||||
:AdventureCastAction(SpellID::WATER_WALK, hero, DayFlags::WATER_WALK_CAST)
|
||||
WaterWalkingAction::WaterWalkingAction(const CGHeroInstance * hero, SpellID spellToCast)
|
||||
:AdventureCastAction(spellToCast, hero, DayFlags::WATER_WALK_CAST)
|
||||
{ }
|
||||
|
||||
AirWalkingAction::AirWalkingAction(const CGHeroInstance * hero)
|
||||
: AdventureCastAction(SpellID::FLY, hero, DayFlags::FLY_CAST)
|
||||
AirWalkingAction::AirWalkingAction(const CGHeroInstance * hero, SpellID spellToCast)
|
||||
: AdventureCastAction(spellToCast, hero, DayFlags::FLY_CAST)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -45,14 +45,16 @@ namespace AIPathfinding
|
||||
|
||||
class WaterWalkingAction : public AdventureCastAction
|
||||
{
|
||||
SpellID spellToCast;
|
||||
public:
|
||||
WaterWalkingAction(const CGHeroInstance * hero);
|
||||
WaterWalkingAction(const CGHeroInstance * hero, SpellID spellToCast);
|
||||
};
|
||||
|
||||
class AirWalkingAction : public AdventureCastAction
|
||||
{
|
||||
SpellID spellToCast;
|
||||
public:
|
||||
AirWalkingAction(const CGHeroInstance * hero);
|
||||
AirWalkingAction(const CGHeroInstance * hero, SpellID spellToCast);
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
@@ -111,19 +111,22 @@ namespace AIPathfinding
|
||||
|
||||
void AILayerTransitionRule::setup()
|
||||
{
|
||||
SpellID waterWalk = SpellID::WATER_WALK;
|
||||
SpellID airWalk = SpellID::FLY;
|
||||
|
||||
for(const CGHeroInstance * hero : nodeStorage->getAllHeroes())
|
||||
{
|
||||
if(hero->canCastThisSpell(waterWalk.toSpell()) && hero->mana >= hero->getSpellCost(waterWalk.toSpell()))
|
||||
for (const auto & spell : LIBRARY->spellh->objects)
|
||||
{
|
||||
waterWalkingActions[hero] = std::make_shared<WaterWalkingAction>(hero);
|
||||
}
|
||||
if (!spell || !spell->isAdventure())
|
||||
continue;
|
||||
|
||||
if(hero->canCastThisSpell(airWalk.toSpell()) && hero->mana >= hero->getSpellCost(airWalk.toSpell()))
|
||||
{
|
||||
airWalkingActions[hero] = std::make_shared<AirWalkingAction>(hero);
|
||||
if(spell->getAdventureMechanics().givesBonus(hero, BonusType::WATER_WALKING) && hero->canCastThisSpell(spell.get()) && hero->mana >= hero->getSpellCost(spell.get()))
|
||||
{
|
||||
waterWalkingActions[hero] = std::make_shared<WaterWalkingAction>(hero, spell->id);
|
||||
}
|
||||
|
||||
if(spell->getAdventureMechanics().givesBonus(hero, BonusType::FLYING_MOVEMENT) && hero->canCastThisSpell(spell.get()) && hero->mana >= hero->getSpellCost(spell.get()))
|
||||
{
|
||||
airWalkingActions[hero] = std::make_shared<AirWalkingAction>(hero, spell->id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -25,6 +25,7 @@
|
||||
#include "../mapObjects/MiscObjects.h"
|
||||
#include "../mapping/CMap.h"
|
||||
#include "../spells/CSpellHandler.h"
|
||||
#include "spells/ISpellMechanics.h"
|
||||
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
@@ -502,7 +503,9 @@ CPathfinderHelper::CPathfinderHelper(const IGameInfoCallback & gameInfo, const C
|
||||
turn(-1),
|
||||
owner(Hero->tempOwner),
|
||||
hero(Hero),
|
||||
options(Options)
|
||||
options(Options),
|
||||
canCastFly(false),
|
||||
canCastWaterWalk(false)
|
||||
{
|
||||
turnsInfo.reserve(16);
|
||||
updateTurnInfo();
|
||||
@@ -510,11 +513,20 @@ CPathfinderHelper::CPathfinderHelper(const IGameInfoCallback & gameInfo, const C
|
||||
|
||||
whirlpoolProtection = Hero->hasBonusOfType(BonusType::WHIRLPOOL_PROTECTION);
|
||||
|
||||
SpellID flySpell = SpellID::FLY;
|
||||
canCastFly = Hero->canCastThisSpell(flySpell.toSpell());
|
||||
if (options.canUseCast)
|
||||
{
|
||||
for (const auto & spell : LIBRARY->spellh->objects)
|
||||
{
|
||||
if (!spell || !spell->isAdventure())
|
||||
continue;
|
||||
|
||||
SpellID waterWalk = SpellID::WATER_WALK;
|
||||
canCastWaterWalk = Hero->canCastThisSpell(waterWalk.toSpell());
|
||||
if(spell->getAdventureMechanics().givesBonus(hero, BonusType::WATER_WALKING) && hero->canCastThisSpell(spell.get()) && hero->mana >= hero->getSpellCost(spell.get()))
|
||||
canCastWaterWalk = true;
|
||||
|
||||
if(spell->getAdventureMechanics().givesBonus(hero, BonusType::FLYING_MOVEMENT) && hero->canCastThisSpell(spell.get()) && hero->mana >= hero->getSpellCost(spell.get()))
|
||||
canCastFly = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CPathfinderHelper::~CPathfinderHelper() = default;
|
||||
|
||||
@@ -359,6 +359,8 @@ public:
|
||||
|
||||
static std::unique_ptr<IAdventureSpellMechanics> createMechanics(const CSpell * s);
|
||||
|
||||
virtual bool givesBonus(const spells::Caster * caster, BonusType which) const = 0;
|
||||
|
||||
template<typename EffectType>
|
||||
const EffectType * getEffectAs(const spells::Caster * caster) const
|
||||
{
|
||||
|
||||
@@ -84,6 +84,15 @@ const IAdventureSpellEffect * AdventureSpellMechanics::getEffect(const spells::C
|
||||
return getLevel(caster).effect.get();
|
||||
}
|
||||
|
||||
bool AdventureSpellMechanics::givesBonus(const spells::Caster * caster, BonusType which) const
|
||||
{
|
||||
for (const auto & bonus : getLevel(caster).bonuses)
|
||||
if (bonus->type == which)
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool AdventureSpellMechanics::canBeCast(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster) const
|
||||
{
|
||||
if(!owner->isAdventure())
|
||||
|
||||
@@ -39,6 +39,7 @@ public:
|
||||
bool canBeCastAt(spells::Problem & problem, const IGameInfoCallback * cb, const spells::Caster * caster, const int3 & pos) const final;
|
||||
bool adventureCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const final;
|
||||
const IAdventureSpellEffect * getEffect(const spells::Caster * caster) const final;
|
||||
bool givesBonus(const spells::Caster * caster, BonusType which) const final;
|
||||
void performCast(SpellCastEnvironment * env, const AdventureSpellCastParameters & parameters) const;
|
||||
};
|
||||
|
||||
|
||||
Reference in New Issue
Block a user