1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

Nullkiller: fix/refactor temporary bonus nodes, fix gather army quest completion

This commit is contained in:
Andrii Danylchenko 2021-05-23 14:28:43 +03:00 committed by Andrii Danylchenko
parent ae67ef027a
commit d47564955e
11 changed files with 60 additions and 48 deletions

View File

@ -407,7 +407,6 @@ bool shouldVisit(const Nullkiller * ai, const CGHeroInstance * h, const CGObject
case Obj::BORDERGUARD: //open borderguard if possible
return (dynamic_cast<const CGKeys *>(obj))->wasMyColorVisited(ai->playerID);
case Obj::SEER_HUT:
case Obj::QUEST_GUARD:
{
for(auto q : ai->cb->getMyQuests())
{

View File

@ -85,8 +85,8 @@ class TemporaryArmy : public CArmedInstance
public:
void armyChanged() override {}
TemporaryArmy()
:CArmedInstance(true)
{
CBonusSystemNode::isHypotheticNode = true;
}
};

View File

@ -162,17 +162,14 @@ TGoalVec CompleteQuest::missionHero() const
TGoalVec CompleteQuest::missionArmy() const
{
TGoalVec solutions = tryCompleteQuest();
auto paths = ai->nullkiller->pathfinder->getPathInfo(q.obj->visitablePos());
if(!solutions.empty())
return solutions;
/*
for(auto creature : q.quest->m6creatures)
vstd::erase_if(paths, [&](const AIPath & path) -> bool
{
solutions.push_back(sptr(GatherTroops(creature.type->idNumber, creature.count)));
}*/
return !CQuest::checkMissionArmy(q.quest, path.heroArmy);
});
return solutions;
return CaptureObjectsBehavior::getVisitGoals(paths, q.obj);
}
TGoalVec CompleteQuest::missionIncreasePrimaryStat() const

View File

@ -29,9 +29,8 @@ public:
virtual bool needsLastStack() const override;
std::shared_ptr<SpecialAction> getActorAction() const;
HeroExchangeArmy() : CArmedInstance(), armyCost(), requireBuyArmy(false)
HeroExchangeArmy() : CArmedInstance(true), armyCost(), requireBuyArmy(false)
{
CBonusSystemNode::isHypotheticNode = true;
}
};

View File

@ -536,21 +536,19 @@ CStackInstance::CStackInstance()
}
CStackInstance::CStackInstance(CreatureID id, TQuantity Count, bool isHypothetic)
: armyObj(_armyObj)
: CBonusSystemNode(isHypothetic), armyObj(_armyObj)
{
init();
setType(id);
count = Count;
CBonusSystemNode::isHypotheticNode = isHypothetic;
}
CStackInstance::CStackInstance(const CCreature *cre, TQuantity Count, bool isHypothetic)
: armyObj(_armyObj)
: CBonusSystemNode(isHypothetic), armyObj(_armyObj)
{
init();
setType(cre);
count = Count;
CBonusSystemNode::isHypotheticNode = isHypothetic;
}
void CStackInstance::init()

View File

@ -989,12 +989,17 @@ std::shared_ptr<Bonus> CBonusSystemNode::update(const std::shared_ptr<Bonus> & b
}
CBonusSystemNode::CBonusSystemNode()
:CBonusSystemNode(false)
{
}
CBonusSystemNode::CBonusSystemNode(bool isHypotetic)
: bonuses(true),
exportedBonuses(true),
nodeType(UNKNOWN),
cachedLast(0),
sync(),
isHypotheticNode(false)
isHypotheticNode(isHypotetic)
{
}
@ -1015,17 +1020,20 @@ CBonusSystemNode::CBonusSystemNode(CBonusSystemNode && other):
description(other.description),
cachedLast(0),
sync(),
isHypotheticNode(false)
isHypotheticNode(other.isHypotheticNode)
{
std::swap(parents, other.parents);
std::swap(children, other.children);
//fixing bonus tree without recalculation
for(CBonusSystemNode * n : parents)
if(!isHypothetic())
{
n->children -= &other;
n->children.push_back(this);
for(CBonusSystemNode * n : parents)
{
n->children -= &other;
n->children.push_back(this);
}
}
for(CBonusSystemNode * n : children)

View File

@ -751,6 +751,7 @@ private:
ENodeTypes nodeType;
std::string description;
bool isHypotheticNode;
static const bool cachingEnabled;
mutable BonusList cachedBonuses;
@ -768,11 +769,9 @@ private:
TConstBonusListPtr getAllBonusesWithoutCaching(const CSelector &selector, const CSelector &limit, const CBonusSystemNode *root = nullptr) const;
std::shared_ptr<Bonus> update(const std::shared_ptr<Bonus> & b) const;
protected:
bool isHypotheticNode;
public:
explicit CBonusSystemNode();
explicit CBonusSystemNode(bool isHypotetic);
explicit CBonusSystemNode(ENodeTypes NodeType);
CBonusSystemNode(CBonusSystemNode && other);
virtual ~CBonusSystemNode();

View File

@ -40,7 +40,12 @@ void CArmedInstance::randomizeArmy(int type)
CSelector CArmedInstance::nonEvilAlignmentMixSelector = Selector::type()(Bonus::NONEVIL_ALIGNMENT_MIX);
CArmedInstance::CArmedInstance()
:nonEvilAlignmentMix(this, nonEvilAlignmentMixSelector)
:CArmedInstance(false)
{
}
CArmedInstance::CArmedInstance(bool isHypotetic)
:CBonusSystemNode(isHypotetic), nonEvilAlignmentMix(this, nonEvilAlignmentMixSelector)
{
battle = nullptr;
}

View File

@ -36,6 +36,7 @@ public:
//////////////////////////////////////////////////////////////////////////
CArmedInstance();
CArmedInstance(bool isHypotetic);
template <typename Handler> void serialize(Handler &h, const int version)
{

View File

@ -60,6 +60,33 @@ static std::string & visitedTxt(const bool visited)
return VLC->generaltexth->allTexts[id];
}
bool CQuest::checkMissionArmy(const CQuest * q, const CCreatureSet * army)
{
std::vector<CStackBasicDescriptor>::const_iterator cre;
TSlots::const_iterator it;
ui32 count;
ui32 slotsCount = 0;
bool hasExtraCreatures = false;
for(cre = q->m6creatures.begin(); cre != q->m6creatures.end(); ++cre)
{
for(count = 0, it = army->Slots().begin(); it != army->Slots().end(); ++it)
{
if(it->second->type == cre->type)
{
count += it->second->count;
slotsCount++;
}
}
if((TQuantity)count < cre->count) //not enough creatures of this kind
return false;
hasExtraCreatures |= (TQuantity)count > cre->count;
}
return hasExtraCreatures || slotsCount < army->Slots().size();
}
bool CQuest::checkQuest(const CGHeroInstance * h) const
{
switch (missionType)
@ -91,29 +118,7 @@ bool CQuest::checkQuest(const CGHeroInstance * h) const
}
return true;
case MISSION_ARMY:
{
std::vector<CStackBasicDescriptor>::const_iterator cre;
TSlots::const_iterator it;
ui32 count;
ui32 slotsCount = 0;
bool hasExtraCreatures = false;
for(cre = m6creatures.begin(); cre != m6creatures.end(); ++cre)
{
for(count = 0, it = h->Slots().begin(); it != h->Slots().end(); ++it)
{
if(it->second->type == cre->type)
{
count += it->second->count;
slotsCount++;
}
}
if((TQuantity)count < cre->count) //not enough creatures of this kind
return false;
hasExtraCreatures |= (TQuantity)count > cre->count;
}
return hasExtraCreatures || slotsCount < h->Slots().size();
}
return checkMissionArmy(this, h);
case MISSION_RESOURCES:
for(Res::ERes i = Res::WOOD; i <= Res::GOLD; vstd::advance(i, +1)) //including Mithril ?
{ //Quest has no direct access to callback

View File

@ -52,6 +52,7 @@ public:
CQuest();
virtual ~CQuest(){};
static bool checkMissionArmy(const CQuest * q, const CCreatureSet * army);
virtual bool checkQuest (const CGHeroInstance * h) const; //determines whether the quest is complete or not
virtual void getVisitText (MetaString &text, std::vector<Component> &components, bool isCustom, bool FirstVisit, const CGHeroInstance * h = nullptr) const;
virtual void getCompletionText (MetaString &text, std::vector<Component> &components, bool isCustom, const CGHeroInstance * h = nullptr) const;