mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-26 22:57:00 +02:00
Nullkiller: allow buy army through pathfinder
This commit is contained in:
parent
673d908c40
commit
3822d788e8
@ -202,7 +202,11 @@ ui64 ArmyManager::howManyReinforcementsCanBuy(const CCreatureSet * h, const CGDw
|
|||||||
|
|
||||||
std::vector<creInfo> ArmyManager::getArmyAvailableToBuy(const CCreatureSet * hero, const CGDwelling * dwelling) const
|
std::vector<creInfo> ArmyManager::getArmyAvailableToBuy(const CCreatureSet * hero, const CGDwelling * dwelling) const
|
||||||
{
|
{
|
||||||
auto availableRes = cb->getResourceAmount();
|
return getArmyAvailableToBuy(hero, dwelling, cb->getResourceAmount());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<creInfo> ArmyManager::getArmyAvailableToBuy(const CCreatureSet * hero, const CGDwelling * dwelling, TResources availableRes) const
|
||||||
|
{
|
||||||
std::vector<creInfo> creaturesInDwellings;
|
std::vector<creInfo> creaturesInDwellings;
|
||||||
int freeHeroSlots = GameConstants::ARMY_SIZE - hero->stacksCount();
|
int freeHeroSlots = GameConstants::ARMY_SIZE - hero->stacksCount();
|
||||||
|
|
||||||
|
@ -48,13 +48,14 @@ public:
|
|||||||
virtual std::vector<SlotInfo> getBestArmy(const IBonusBearer * armyCarrier, const CCreatureSet * target, const CCreatureSet * source) const = 0;
|
virtual std::vector<SlotInfo> getBestArmy(const IBonusBearer * armyCarrier, const CCreatureSet * target, const CCreatureSet * source) const = 0;
|
||||||
virtual std::vector<SlotInfo>::iterator getWeakestCreature(std::vector<SlotInfo> & army) const = 0;
|
virtual std::vector<SlotInfo>::iterator getWeakestCreature(std::vector<SlotInfo> & army) const = 0;
|
||||||
virtual std::vector<SlotInfo> getSortedSlots(const CCreatureSet * target, const CCreatureSet * source) const = 0;
|
virtual std::vector<SlotInfo> getSortedSlots(const CCreatureSet * target, const CCreatureSet * source) const = 0;
|
||||||
virtual std::vector<creInfo> getArmyAvailableToBuy(const CCreatureSet * hero, const CGDwelling * dwelling) const = 0;
|
virtual std::vector<creInfo> getArmyAvailableToBuy(const CCreatureSet * hero, const CGDwelling * dwelling, TResources availableRes) const = 0;
|
||||||
virtual uint64_t evaluateStackPower(const CCreature * creature, int count) const = 0;
|
virtual uint64_t evaluateStackPower(const CCreature * creature, int count) const = 0;
|
||||||
virtual SlotInfo getTotalCreaturesAvailable(CreatureID creatureID) const = 0;
|
virtual SlotInfo getTotalCreaturesAvailable(CreatureID creatureID) const = 0;
|
||||||
virtual ArmyUpgradeInfo calculateCreateresUpgrade(
|
virtual ArmyUpgradeInfo calculateCreateresUpgrade(
|
||||||
const CCreatureSet * army,
|
const CCreatureSet * army,
|
||||||
const CGObjectInstance * upgrader,
|
const CGObjectInstance * upgrader,
|
||||||
const TResources & availableResources) const = 0;
|
const TResources & availableResources) const = 0;
|
||||||
|
virtual std::vector<creInfo> getArmyAvailableToBuy(const CCreatureSet * hero, const CGDwelling * dwelling) const = 0;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct StackUpgradeInfo;
|
struct StackUpgradeInfo;
|
||||||
@ -75,6 +76,7 @@ public:
|
|||||||
std::vector<SlotInfo> getBestArmy(const IBonusBearer * armyCarrier, const CCreatureSet * target, const CCreatureSet * source) const override;
|
std::vector<SlotInfo> getBestArmy(const IBonusBearer * armyCarrier, const CCreatureSet * target, const CCreatureSet * source) const override;
|
||||||
std::vector<SlotInfo>::iterator getWeakestCreature(std::vector<SlotInfo> & army) const override;
|
std::vector<SlotInfo>::iterator getWeakestCreature(std::vector<SlotInfo> & army) const override;
|
||||||
std::vector<SlotInfo> getSortedSlots(const CCreatureSet * target, const CCreatureSet * source) const override;
|
std::vector<SlotInfo> getSortedSlots(const CCreatureSet * target, const CCreatureSet * source) const override;
|
||||||
|
std::vector<creInfo> getArmyAvailableToBuy(const CCreatureSet * hero, const CGDwelling * dwelling, TResources availableRes) const override;
|
||||||
std::vector<creInfo> getArmyAvailableToBuy(const CCreatureSet * hero, const CGDwelling * dwelling) const override;
|
std::vector<creInfo> getArmyAvailableToBuy(const CCreatureSet * hero, const CGDwelling * dwelling) const override;
|
||||||
uint64_t evaluateStackPower(const CCreature * creature, int count) const override;
|
uint64_t evaluateStackPower(const CCreature * creature, int count) const override;
|
||||||
SlotInfo getTotalCreaturesAvailable(CreatureID creatureID) const override;
|
SlotInfo getTotalCreaturesAvailable(CreatureID creatureID) const override;
|
||||||
|
@ -7,6 +7,8 @@ set(VCAI_SRCS
|
|||||||
Pathfinding/Actors.cpp
|
Pathfinding/Actors.cpp
|
||||||
Pathfinding/Actions/SpecialAction.cpp
|
Pathfinding/Actions/SpecialAction.cpp
|
||||||
Pathfinding/Actions/BattleAction.cpp
|
Pathfinding/Actions/BattleAction.cpp
|
||||||
|
Pathfinding/Actions/QuestAction.cpp
|
||||||
|
Pathfinding/Actions/BuyArmyAction.cpp
|
||||||
Pathfinding/Actions/BoatActions.cpp
|
Pathfinding/Actions/BoatActions.cpp
|
||||||
Pathfinding/Actions/TownPortalAction.cpp
|
Pathfinding/Actions/TownPortalAction.cpp
|
||||||
Pathfinding/Rules/AILayerTransitionRule.cpp
|
Pathfinding/Rules/AILayerTransitionRule.cpp
|
||||||
@ -62,6 +64,8 @@ set(VCAI_HEADERS
|
|||||||
Pathfinding/Actors.h
|
Pathfinding/Actors.h
|
||||||
Pathfinding/Actions/SpecialAction.h
|
Pathfinding/Actions/SpecialAction.h
|
||||||
Pathfinding/Actions/BattleAction.h
|
Pathfinding/Actions/BattleAction.h
|
||||||
|
Pathfinding/Actions/QuestAction.h
|
||||||
|
Pathfinding/Actions/BuyArmyAction.h
|
||||||
Pathfinding/Actions/BoatActions.h
|
Pathfinding/Actions/BoatActions.h
|
||||||
Pathfinding/Actions/TownPortalAction.h
|
Pathfinding/Actions/TownPortalAction.h
|
||||||
Pathfinding/Rules/AILayerTransitionRule.h
|
Pathfinding/Rules/AILayerTransitionRule.h
|
||||||
|
@ -613,6 +613,12 @@ void AINodeStorage::addHeroChain(const std::vector<ExchangeCandidate> & result)
|
|||||||
exchangeNode->theNodeBefore = carrier;
|
exchangeNode->theNodeBefore = carrier;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if(exchangeNode->actor->actorAction)
|
||||||
|
{
|
||||||
|
exchangeNode->theNodeBefore = carrier;
|
||||||
|
exchangeNode->specialAction = exchangeNode->actor->actorAction;
|
||||||
|
}
|
||||||
|
|
||||||
exchangeNode->chainOther = other;
|
exchangeNode->chainOther = other;
|
||||||
exchangeNode->armyLoss = chainInfo.armyLoss;
|
exchangeNode->armyLoss = chainInfo.armyLoss;
|
||||||
|
|
||||||
|
@ -11,7 +11,7 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#define PATHFINDER_TRACE_LEVEL 0
|
#define PATHFINDER_TRACE_LEVEL 0
|
||||||
#define AI_TRACE_LEVEL 0
|
#define AI_TRACE_LEVEL 2
|
||||||
#define SCOUT_TURN_DISTANCE_LIMIT 3
|
#define SCOUT_TURN_DISTANCE_LIMIT 3
|
||||||
|
|
||||||
#include "../../../lib/CPathfinder.h"
|
#include "../../../lib/CPathfinder.h"
|
||||||
|
@ -28,30 +28,4 @@ namespace AIPathfinding
|
|||||||
{
|
{
|
||||||
return "Battle at " + targetTile.toString();
|
return "Battle at " + targetTile.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QuestAction::canAct(const AIPathNode * node) const
|
|
||||||
{
|
|
||||||
if(questInfo.obj->ID == Obj::BORDER_GATE || questInfo.obj->ID == Obj::BORDERGUARD)
|
|
||||||
{
|
|
||||||
return dynamic_cast<const IQuestObject *>(questInfo.obj)->checkQuest(node->actor->hero);
|
|
||||||
}
|
|
||||||
|
|
||||||
return questInfo.quest->progress == CQuest::NOT_ACTIVE
|
|
||||||
|| questInfo.quest->checkQuest(node->actor->hero);
|
|
||||||
}
|
|
||||||
|
|
||||||
Goals::TSubgoal QuestAction::decompose(const CGHeroInstance * hero) const
|
|
||||||
{
|
|
||||||
return Goals::sptr(Goals::CompleteQuest(questInfo));
|
|
||||||
}
|
|
||||||
|
|
||||||
void QuestAction::execute(const CGHeroInstance * hero) const
|
|
||||||
{
|
|
||||||
ai->moveHeroToTile(questInfo.obj->visitablePos(), hero);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string QuestAction::toString() const
|
|
||||||
{
|
|
||||||
return "Complete Quest";
|
|
||||||
}
|
|
||||||
}
|
}
|
@ -30,24 +30,4 @@ namespace AIPathfinding
|
|||||||
|
|
||||||
virtual std::string toString() const override;
|
virtual std::string toString() const override;
|
||||||
};
|
};
|
||||||
|
|
||||||
class QuestAction : public SpecialAction
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
QuestInfo questInfo;
|
|
||||||
|
|
||||||
public:
|
|
||||||
QuestAction(QuestInfo questInfo)
|
|
||||||
:questInfo(questInfo)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
virtual bool canAct(const AIPathNode * node) const override;
|
|
||||||
|
|
||||||
virtual Goals::TSubgoal decompose(const CGHeroInstance * hero) const override;
|
|
||||||
|
|
||||||
virtual void execute(const CGHeroInstance * hero) const override;
|
|
||||||
|
|
||||||
virtual std::string toString() const override;
|
|
||||||
};
|
|
||||||
}
|
}
|
31
AI/Nullkiller/Pathfinding/Actions/BuyArmyAction.cpp
Normal file
31
AI/Nullkiller/Pathfinding/Actions/BuyArmyAction.cpp
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* BattleAction.cpp, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "StdInc.h"
|
||||||
|
#include "BuyArmyAction.h"
|
||||||
|
#include "../../VCAI.h"
|
||||||
|
#include "../../Goals/CompleteQuest.h"
|
||||||
|
#include "../../../../lib/mapping/CMap.h" //for victory conditions
|
||||||
|
|
||||||
|
extern boost::thread_specific_ptr<CCallback> cb;
|
||||||
|
extern boost::thread_specific_ptr<VCAI> ai;
|
||||||
|
|
||||||
|
namespace AIPathfinding
|
||||||
|
{
|
||||||
|
void BuyArmyAction::execute(const CGHeroInstance * hero) const
|
||||||
|
{
|
||||||
|
ai->recruitCreatures(hero->visitedTown, hero);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string BuyArmyAction::toString() const
|
||||||
|
{
|
||||||
|
return "Buy Army";
|
||||||
|
}
|
||||||
|
}
|
31
AI/Nullkiller/Pathfinding/Actions/BuyArmyAction.h
Normal file
31
AI/Nullkiller/Pathfinding/Actions/BuyArmyAction.h
Normal file
@ -0,0 +1,31 @@
|
|||||||
|
/*
|
||||||
|
* BuyArmyAction.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SpecialAction.h"
|
||||||
|
#include "../../../../lib/CGameState.h"
|
||||||
|
|
||||||
|
namespace AIPathfinding
|
||||||
|
{
|
||||||
|
class BuyArmyAction : public SpecialAction
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
|
||||||
|
public:
|
||||||
|
bool canAct(const AIPathNode * source) const override
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
void execute(const CGHeroInstance * hero) const override;
|
||||||
|
std::string toString() const override;
|
||||||
|
};
|
||||||
|
}
|
47
AI/Nullkiller/Pathfinding/Actions/QuestAction.cpp
Normal file
47
AI/Nullkiller/Pathfinding/Actions/QuestAction.cpp
Normal file
@ -0,0 +1,47 @@
|
|||||||
|
/*
|
||||||
|
* QuestAction.cpp, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "StdInc.h"
|
||||||
|
#include "QuestAction.h"
|
||||||
|
#include "../../VCAI.h"
|
||||||
|
#include "../../Goals/CompleteQuest.h"
|
||||||
|
#include "../../../../lib/mapping/CMap.h" //for victory conditions
|
||||||
|
|
||||||
|
extern boost::thread_specific_ptr<CCallback> cb;
|
||||||
|
extern boost::thread_specific_ptr<VCAI> ai;
|
||||||
|
|
||||||
|
namespace AIPathfinding
|
||||||
|
{
|
||||||
|
bool QuestAction::canAct(const AIPathNode * node) const
|
||||||
|
{
|
||||||
|
if(questInfo.obj->ID == Obj::BORDER_GATE || questInfo.obj->ID == Obj::BORDERGUARD)
|
||||||
|
{
|
||||||
|
return dynamic_cast<const IQuestObject *>(questInfo.obj)->checkQuest(node->actor->hero);
|
||||||
|
}
|
||||||
|
|
||||||
|
return questInfo.quest->progress == CQuest::NOT_ACTIVE
|
||||||
|
|| questInfo.quest->checkQuest(node->actor->hero);
|
||||||
|
}
|
||||||
|
|
||||||
|
Goals::TSubgoal QuestAction::decompose(const CGHeroInstance * hero) const
|
||||||
|
{
|
||||||
|
return Goals::sptr(Goals::CompleteQuest(questInfo));
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuestAction::execute(const CGHeroInstance * hero) const
|
||||||
|
{
|
||||||
|
ai->moveHeroToTile(questInfo.obj->visitablePos(), hero);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string QuestAction::toString() const
|
||||||
|
{
|
||||||
|
return "Complete Quest";
|
||||||
|
}
|
||||||
|
}
|
37
AI/Nullkiller/Pathfinding/Actions/QuestAction.h
Normal file
37
AI/Nullkiller/Pathfinding/Actions/QuestAction.h
Normal file
@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* QuestAction.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "SpecialAction.h"
|
||||||
|
#include "../../../../lib/CGameState.h"
|
||||||
|
|
||||||
|
namespace AIPathfinding
|
||||||
|
{
|
||||||
|
class QuestAction : public SpecialAction
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
QuestInfo questInfo;
|
||||||
|
|
||||||
|
public:
|
||||||
|
QuestAction(QuestInfo questInfo)
|
||||||
|
:questInfo(questInfo)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
virtual bool canAct(const AIPathNode * node) const override;
|
||||||
|
|
||||||
|
virtual Goals::TSubgoal decompose(const CGHeroInstance * hero) const override;
|
||||||
|
|
||||||
|
virtual void execute(const CGHeroInstance * hero) const override;
|
||||||
|
|
||||||
|
virtual std::string toString() const override;
|
||||||
|
};
|
||||||
|
}
|
@ -14,6 +14,7 @@
|
|||||||
#include "../../../CCallback.h"
|
#include "../../../CCallback.h"
|
||||||
#include "../../../lib/mapping/CMap.h"
|
#include "../../../lib/mapping/CMap.h"
|
||||||
#include "../../../lib/mapObjects/MapObjects.h"
|
#include "../../../lib/mapObjects/MapObjects.h"
|
||||||
|
#include "Actions/BuyArmyAction.h"
|
||||||
|
|
||||||
CCreatureSet emptyArmy;
|
CCreatureSet emptyArmy;
|
||||||
|
|
||||||
@ -22,9 +23,21 @@ bool HeroExchangeArmy::needsLastStack() const
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<SpecialAction> HeroExchangeArmy::getActorAction() const
|
||||||
|
{
|
||||||
|
std::shared_ptr<SpecialAction> result;
|
||||||
|
|
||||||
|
if(requireBuyArmy)
|
||||||
|
{
|
||||||
|
result.reset(new AIPathfinding::BuyArmyAction());
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
ChainActor::ChainActor(const CGHeroInstance * hero, HeroRole heroRole, uint64_t chainMask)
|
ChainActor::ChainActor(const CGHeroInstance * hero, HeroRole heroRole, uint64_t chainMask)
|
||||||
:hero(hero), heroRole(heroRole), isMovable(true), chainMask(chainMask), creatureSet(hero),
|
:hero(hero), heroRole(heroRole), isMovable(true), chainMask(chainMask), creatureSet(hero),
|
||||||
baseActor(this), carrierParent(nullptr), otherParent(nullptr), actorExchangeCount(1), armyCost()
|
baseActor(this), carrierParent(nullptr), otherParent(nullptr), actorExchangeCount(1), armyCost(), actorAction()
|
||||||
{
|
{
|
||||||
initialPosition = hero->visitablePos();
|
initialPosition = hero->visitablePos();
|
||||||
layer = hero->boat ? EPathfindingLayer::SAIL : EPathfindingLayer::LAND;
|
layer = hero->boat ? EPathfindingLayer::SAIL : EPathfindingLayer::LAND;
|
||||||
@ -37,7 +50,7 @@ ChainActor::ChainActor(const CGHeroInstance * hero, HeroRole heroRole, uint64_t
|
|||||||
ChainActor::ChainActor(const ChainActor * carrier, const ChainActor * other, const CCreatureSet * heroArmy)
|
ChainActor::ChainActor(const ChainActor * carrier, const ChainActor * other, const CCreatureSet * heroArmy)
|
||||||
:hero(carrier->hero), heroRole(carrier->heroRole), isMovable(true), creatureSet(heroArmy), chainMask(carrier->chainMask | other->chainMask),
|
:hero(carrier->hero), heroRole(carrier->heroRole), isMovable(true), creatureSet(heroArmy), chainMask(carrier->chainMask | other->chainMask),
|
||||||
baseActor(this), carrierParent(carrier), otherParent(other), heroFightingStrength(carrier->heroFightingStrength),
|
baseActor(this), carrierParent(carrier), otherParent(other), heroFightingStrength(carrier->heroFightingStrength),
|
||||||
actorExchangeCount(carrier->actorExchangeCount + other->actorExchangeCount), armyCost(carrier->armyCost + other->armyCost)
|
actorExchangeCount(carrier->actorExchangeCount + other->actorExchangeCount), armyCost(carrier->armyCost + other->armyCost), actorAction()
|
||||||
{
|
{
|
||||||
armyValue = heroArmy->getArmyStrength();
|
armyValue = heroArmy->getArmyStrength();
|
||||||
}
|
}
|
||||||
@ -45,7 +58,7 @@ ChainActor::ChainActor(const ChainActor * carrier, const ChainActor * other, con
|
|||||||
ChainActor::ChainActor(const CGObjectInstance * obj, const CCreatureSet * creatureSet, uint64_t chainMask, int initialTurn)
|
ChainActor::ChainActor(const CGObjectInstance * obj, const CCreatureSet * creatureSet, uint64_t chainMask, int initialTurn)
|
||||||
:hero(nullptr), heroRole(HeroRole::MAIN), isMovable(false), creatureSet(creatureSet), chainMask(chainMask),
|
:hero(nullptr), heroRole(HeroRole::MAIN), isMovable(false), creatureSet(creatureSet), chainMask(chainMask),
|
||||||
baseActor(this), carrierParent(nullptr), otherParent(nullptr), initialTurn(initialTurn), initialMovement(0),
|
baseActor(this), carrierParent(nullptr), otherParent(nullptr), initialTurn(initialTurn), initialMovement(0),
|
||||||
heroFightingStrength(0), actorExchangeCount(1), armyCost()
|
heroFightingStrength(0), actorExchangeCount(1), armyCost(), actorAction()
|
||||||
{
|
{
|
||||||
initialPosition = obj->visitablePos();
|
initialPosition = obj->visitablePos();
|
||||||
layer = EPathfindingLayer::LAND;
|
layer = EPathfindingLayer::LAND;
|
||||||
@ -82,11 +95,13 @@ HeroActor::HeroActor(const CGHeroInstance * hero, HeroRole heroRole, uint64_t ch
|
|||||||
HeroActor::HeroActor(
|
HeroActor::HeroActor(
|
||||||
const ChainActor * carrier,
|
const ChainActor * carrier,
|
||||||
const ChainActor * other,
|
const ChainActor * other,
|
||||||
const CCreatureSet * army,
|
const HeroExchangeArmy * army,
|
||||||
const Nullkiller * ai)
|
const Nullkiller * ai)
|
||||||
:ChainActor(carrier, other, army)
|
:ChainActor(carrier, other, army)
|
||||||
{
|
{
|
||||||
exchangeMap = new HeroExchangeMap(this, ai);
|
exchangeMap = new HeroExchangeMap(this, ai);
|
||||||
|
armyCost += army->armyCost;
|
||||||
|
actorAction = army->getActorAction();
|
||||||
setupSpecialActors();
|
setupSpecialActors();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -104,6 +119,7 @@ void ChainActor::setBaseActor(HeroActor * base)
|
|||||||
isMovable = base->isMovable;
|
isMovable = base->isMovable;
|
||||||
heroFightingStrength = base->heroFightingStrength;
|
heroFightingStrength = base->heroFightingStrength;
|
||||||
armyCost = base->armyCost;
|
armyCost = base->armyCost;
|
||||||
|
actorAction = base->actorAction;
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeroActor::setupSpecialActors()
|
void HeroActor::setupSpecialActors()
|
||||||
@ -192,6 +208,12 @@ bool HeroExchangeMap::canExchange(const ChainActor * other)
|
|||||||
if(other->creatureSet->Slots().size())
|
if(other->creatureSet->Slots().size())
|
||||||
reinforcment += ai->armyManager->howManyReinforcementsCanGet(actor->hero, actor->creatureSet, other->creatureSet);
|
reinforcment += ai->armyManager->howManyReinforcementsCanGet(actor->hero, actor->creatureSet, other->creatureSet);
|
||||||
|
|
||||||
|
auto obj = other->getActorObject();
|
||||||
|
if(obj && obj->ID == Obj::TOWN)
|
||||||
|
{
|
||||||
|
reinforcment += ai->armyManager->howManyReinforcementsCanBuy(actor->creatureSet, ai->cb->getTown(obj->id));
|
||||||
|
}
|
||||||
|
|
||||||
#if PATHFINDER_TRACE_LEVEL >= 2
|
#if PATHFINDER_TRACE_LEVEL >= 2
|
||||||
logAi->trace(
|
logAi->trace(
|
||||||
"Exchange %s->%s reinforcement: %d, %f%%",
|
"Exchange %s->%s reinforcement: %d, %f%%",
|
||||||
@ -242,14 +264,16 @@ HeroActor * HeroExchangeMap::exchange(const ChainActor * other)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
TResources availableResources = ai->cb->getResourceAmount() - actor->armyCost - other->armyCost;
|
TResources availableResources = ai->cb->getResourceAmount() - actor->armyCost - other->armyCost;
|
||||||
CCreatureSet * upgradedInitialArmy = tryUpgrade(actor->creatureSet, other->getActorObject(), availableResources);
|
HeroExchangeArmy * upgradedInitialArmy = tryUpgrade(actor->creatureSet, other->getActorObject(), availableResources);
|
||||||
CCreatureSet * newArmy;
|
HeroExchangeArmy * newArmy;
|
||||||
|
|
||||||
if(other->creatureSet->Slots().size())
|
if(other->creatureSet->Slots().size())
|
||||||
{
|
{
|
||||||
if(upgradedInitialArmy)
|
if(upgradedInitialArmy)
|
||||||
{
|
{
|
||||||
newArmy = pickBestCreatures(upgradedInitialArmy, other->creatureSet);
|
newArmy = pickBestCreatures(upgradedInitialArmy, other->creatureSet);
|
||||||
|
newArmy->armyCost = upgradedInitialArmy->armyCost;
|
||||||
|
|
||||||
delete upgradedInitialArmy;
|
delete upgradedInitialArmy;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -263,21 +287,23 @@ HeroActor * HeroExchangeMap::exchange(const ChainActor * other)
|
|||||||
}
|
}
|
||||||
|
|
||||||
result = new HeroActor(actor, other, newArmy, ai);
|
result = new HeroActor(actor, other, newArmy, ai);
|
||||||
|
result->armyCost += newArmy->armyCost;
|
||||||
exchangeMap[other] = result;
|
exchangeMap[other] = result;
|
||||||
}
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
CCreatureSet * HeroExchangeMap::tryUpgrade(const CCreatureSet * army, const CGObjectInstance * upgrader, TResources resources) const
|
HeroExchangeArmy * HeroExchangeMap::tryUpgrade(
|
||||||
|
const CCreatureSet * army,
|
||||||
|
const CGObjectInstance * upgrader,
|
||||||
|
TResources resources) const
|
||||||
{
|
{
|
||||||
|
HeroExchangeArmy * target = new HeroExchangeArmy();
|
||||||
auto upgradeInfo = ai->armyManager->calculateCreateresUpgrade(army, upgrader, resources);
|
auto upgradeInfo = ai->armyManager->calculateCreateresUpgrade(army, upgrader, resources);
|
||||||
|
|
||||||
if(!upgradeInfo.upgradeValue)
|
if(upgradeInfo.upgradeValue)
|
||||||
return nullptr;
|
{
|
||||||
|
|
||||||
CCreatureSet * target = new HeroExchangeArmy();
|
|
||||||
|
|
||||||
for(auto & slotInfo : upgradeInfo.resultingArmy)
|
for(auto & slotInfo : upgradeInfo.resultingArmy)
|
||||||
{
|
{
|
||||||
auto targetSlot = target->getFreeSlot();
|
auto targetSlot = target->getFreeSlot();
|
||||||
@ -285,12 +311,42 @@ CCreatureSet * HeroExchangeMap::tryUpgrade(const CCreatureSet * army, const CGOb
|
|||||||
target->addToSlot(targetSlot, slotInfo.creature->idNumber, TQuantity(slotInfo.count));
|
target->addToSlot(targetSlot, slotInfo.creature->idNumber, TQuantity(slotInfo.count));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
resources -= upgradeInfo.upgradeCost;
|
||||||
|
target->armyCost += upgradeInfo.upgradeCost;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
for(auto slot : army->Slots())
|
||||||
|
{
|
||||||
|
auto targetSlot = target->getSlotFor(slot.second->getCreatureID());
|
||||||
|
|
||||||
|
target->addToSlot(targetSlot, slot.second->getCreatureID(), slot.second->count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(upgrader->ID == Obj::TOWN)
|
||||||
|
{
|
||||||
|
auto buyArmy = ai->armyManager->getArmyAvailableToBuy(target, ai->cb->getTown(upgrader->id), resources);
|
||||||
|
|
||||||
|
for(auto creatureToBuy : buyArmy)
|
||||||
|
{
|
||||||
|
auto targetSlot = target->getSlotFor(creatureToBuy.cre);
|
||||||
|
|
||||||
|
target->addToSlot(targetSlot, creatureToBuy.creID, creatureToBuy.count);
|
||||||
|
target->armyCost += creatureToBuy.cre->cost * creatureToBuy.count;
|
||||||
|
target->requireBuyArmy = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(target->getArmyStrength() <= army->getArmyStrength())
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
return target;
|
return target;
|
||||||
}
|
}
|
||||||
|
|
||||||
CCreatureSet * HeroExchangeMap::pickBestCreatures(const CCreatureSet * army1, const CCreatureSet * army2) const
|
HeroExchangeArmy * HeroExchangeMap::pickBestCreatures(const CCreatureSet * army1, const CCreatureSet * army2) const
|
||||||
{
|
{
|
||||||
CCreatureSet * target = new HeroExchangeArmy();
|
HeroExchangeArmy * target = new HeroExchangeArmy();
|
||||||
auto bestArmy = ai->armyManager->getBestArmy(actor->hero, army1, army2);
|
auto bestArmy = ai->armyManager->getBestArmy(actor->hero, army1, army2);
|
||||||
|
|
||||||
for(auto & slotInfo : bestArmy)
|
for(auto & slotInfo : bestArmy)
|
||||||
|
@ -21,7 +21,14 @@ class Nullkiller;
|
|||||||
class HeroExchangeArmy : public CCreatureSet
|
class HeroExchangeArmy : public CCreatureSet
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
TResources armyCost;
|
||||||
|
bool requireBuyArmy;
|
||||||
virtual bool needsLastStack() const override;
|
virtual bool needsLastStack() const override;
|
||||||
|
std::shared_ptr<SpecialAction> getActorAction() const;
|
||||||
|
|
||||||
|
HeroExchangeArmy() : CCreatureSet(), armyCost(), requireBuyArmy(false)
|
||||||
|
{
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
class ChainActor
|
class ChainActor
|
||||||
@ -37,6 +44,7 @@ public:
|
|||||||
bool allowUseResources;
|
bool allowUseResources;
|
||||||
bool allowBattle;
|
bool allowBattle;
|
||||||
bool allowSpellCast;
|
bool allowSpellCast;
|
||||||
|
std::shared_ptr<SpecialAction> actorAction;
|
||||||
const CGHeroInstance * hero;
|
const CGHeroInstance * hero;
|
||||||
HeroRole heroRole;
|
HeroRole heroRole;
|
||||||
const CCreatureSet * creatureSet;
|
const CCreatureSet * creatureSet;
|
||||||
@ -87,8 +95,8 @@ public:
|
|||||||
bool canExchange(const ChainActor * other);
|
bool canExchange(const ChainActor * other);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
CCreatureSet * pickBestCreatures(const CCreatureSet * army1, const CCreatureSet * army2) const;
|
HeroExchangeArmy * pickBestCreatures(const CCreatureSet * army1, const CCreatureSet * army2) const;
|
||||||
CCreatureSet * tryUpgrade(const CCreatureSet * army, const CGObjectInstance * upgrader, TResources resources) const;
|
HeroExchangeArmy * tryUpgrade(const CCreatureSet * army, const CGObjectInstance * upgrader, TResources resources) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
class HeroActor : public ChainActor
|
class HeroActor : public ChainActor
|
||||||
@ -107,7 +115,7 @@ public:
|
|||||||
// chain flags, can be combined meaning hero exchange and so on
|
// chain flags, can be combined meaning hero exchange and so on
|
||||||
|
|
||||||
HeroActor(const CGHeroInstance * hero, HeroRole heroRole, uint64_t chainMask, const Nullkiller * ai);
|
HeroActor(const CGHeroInstance * hero, HeroRole heroRole, uint64_t chainMask, const Nullkiller * ai);
|
||||||
HeroActor(const ChainActor * carrier, const ChainActor * other, const CCreatureSet * army, const Nullkiller * ai);
|
HeroActor(const ChainActor * carrier, const ChainActor * other, const HeroExchangeArmy * army, const Nullkiller * ai);
|
||||||
|
|
||||||
virtual bool canExchange(const ChainActor * other) const override;
|
virtual bool canExchange(const ChainActor * other) const override;
|
||||||
|
|
||||||
|
@ -10,6 +10,7 @@
|
|||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "AIMovementAfterDestinationRule.h"
|
#include "AIMovementAfterDestinationRule.h"
|
||||||
#include "../Actions/BattleAction.h"
|
#include "../Actions/BattleAction.h"
|
||||||
|
#include "../Actions/QuestAction.h"
|
||||||
#include "../../Goals/Invalid.h"
|
#include "../../Goals/Invalid.h"
|
||||||
#include "AIPreviousNodeRule.h"
|
#include "AIPreviousNodeRule.h"
|
||||||
|
|
||||||
|
@ -526,6 +526,7 @@ void VCAI::heroGotLevel(const CGHeroInstance * hero, PrimarySkill::PrimarySkill
|
|||||||
{
|
{
|
||||||
if(hPtr.validAndSet())
|
if(hPtr.validAndSet())
|
||||||
{
|
{
|
||||||
|
nullkiller->heroManager->update();
|
||||||
answerQuery(queryID, nullkiller->heroManager->selectBestSkill(hPtr, skills));
|
answerQuery(queryID, nullkiller->heroManager->selectBestSkill(hPtr, skills));
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user