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