1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Nullkiller: fixes for keymaster

This commit is contained in:
Andrii Danylchenko 2021-05-16 14:39:18 +03:00 committed by Andrii Danylchenko
parent 8f8c5ca255
commit 33b499976a
6 changed files with 96 additions and 80 deletions

View File

@ -1,5 +1,5 @@
/*
* CompleteQuestBehavior.cpp, part of VCMI engine
* CompleteQuest.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
@ -21,57 +21,59 @@ extern FuzzyHelper * fh;
using namespace Goals;
std::string CompleteQuestBehavior::toString() const
std::string CompleteQuest::toString() const
{
return "Complete Quests";
return "Complete quest " + questToString();
}
TGoalVec CompleteQuestBehavior::decompose() const
TGoalVec CompleteQuest::decompose() const
{
TGoalVec solutions;
/*TGoalVec solutions;
auto quests = cb->getMyQuests();
for(auto & q : quests)
{
if(q.quest->missionType == CQuest::MISSION_NONE || q.quest->progress == CQuest::COMPLETE)
if(q.quest->missionType == CQuest::MISSION_NONE
|| q.quest->progress == CQuest::COMPLETE)
{
continue;
}
vstd::concatenate(solutions, getQuestTasks(q));
vstd::concatenate(solutions, getQuestTasks());
}
return solutions;
}
return solutions;*/
logAi->debug("Trying to realize quest: %s", questToString());
TGoalVec CompleteQuestBehavior::getQuestTasks(const QuestInfo & q) const
{
logAi->debug("Trying to realize quest: %s", questToString(q));
if(q.obj && (q.obj->ID == Obj::BORDER_GATE || q.obj->ID == Obj::BORDERGUARD))
{
return missionKeymaster();
}
switch(q.quest->missionType)
{
case CQuest::MISSION_ART:
return missionArt(q);
return missionArt();
case CQuest::MISSION_HERO:
return missionHero(q);
return missionHero();
case CQuest::MISSION_ARMY:
return missionArmy(q);
return missionArmy();
case CQuest::MISSION_RESOURCES:
return missionResources(q);
return missionResources();
case CQuest::MISSION_KILL_HERO:
case CQuest::MISSION_KILL_CREATURE:
return missionDestroyObj(q);
return missionDestroyObj();
case CQuest::MISSION_PRIMARY_STAT:
return missionIncreasePrimaryStat(q);
return missionIncreasePrimaryStat();
case CQuest::MISSION_LEVEL:
return missionLevel(q);
return missionLevel();
case CQuest::MISSION_PLAYER:
if(ai->playerID.getNum() != q.quest->m13489val)
@ -80,14 +82,19 @@ TGoalVec CompleteQuestBehavior::getQuestTasks(const QuestInfo & q) const
break;
case CQuest::MISSION_KEYMASTER:
return missionKeymaster(q);
return missionKeymaster();
} //end of switch
return TGoalVec();
}
std::string CompleteQuestBehavior::questToString(const QuestInfo & q) const
bool CompleteQuest::operator==(const CompleteQuest & other) const
{
return q.quest->qid == other.q.quest->qid;
}
std::string CompleteQuest::questToString() const
{
if(q.quest->missionType == CQuest::MISSION_NONE)
return "inactive quest";
@ -98,7 +105,7 @@ std::string CompleteQuestBehavior::questToString(const QuestInfo & q) const
return ms.toString();
}
TGoalVec CompleteQuestBehavior::tryCompleteQuest(const QuestInfo & q) const
TGoalVec CompleteQuest::tryCompleteQuest() const
{
TGoalVec solutions;
@ -115,9 +122,9 @@ TGoalVec CompleteQuestBehavior::tryCompleteQuest(const QuestInfo & q) const
return solutions;
}
TGoalVec CompleteQuestBehavior::missionArt(const QuestInfo & q) const
TGoalVec CompleteQuest::missionArt() const
{
TGoalVec solutions = tryCompleteQuest(q);
TGoalVec solutions = tryCompleteQuest();
if(!solutions.empty())
return solutions;
@ -130,9 +137,9 @@ TGoalVec CompleteQuestBehavior::missionArt(const QuestInfo & q) const
return solutions;
}
TGoalVec CompleteQuestBehavior::missionHero(const QuestInfo & q) const
TGoalVec CompleteQuest::missionHero() const
{
TGoalVec solutions = tryCompleteQuest(q);
TGoalVec solutions = tryCompleteQuest();
if(solutions.empty())
{
@ -143,9 +150,9 @@ TGoalVec CompleteQuestBehavior::missionHero(const QuestInfo & q) const
return solutions;
}
TGoalVec CompleteQuestBehavior::missionArmy(const QuestInfo & q) const
TGoalVec CompleteQuest::missionArmy() const
{
TGoalVec solutions = tryCompleteQuest(q);
TGoalVec solutions = tryCompleteQuest();
if(!solutions.empty())
return solutions;
@ -158,19 +165,19 @@ TGoalVec CompleteQuestBehavior::missionArmy(const QuestInfo & q) const
return solutions;
}
TGoalVec CompleteQuestBehavior::missionIncreasePrimaryStat(const QuestInfo & q) const
TGoalVec CompleteQuest::missionIncreasePrimaryStat() const
{
return tryCompleteQuest(q);
return tryCompleteQuest();
}
TGoalVec CompleteQuestBehavior::missionLevel(const QuestInfo & q) const
TGoalVec CompleteQuest::missionLevel() const
{
return tryCompleteQuest(q);
return tryCompleteQuest();
}
TGoalVec CompleteQuestBehavior::missionKeymaster(const QuestInfo & q) const
TGoalVec CompleteQuest::missionKeymaster() const
{
TGoalVec solutions = tryCompleteQuest(q);
TGoalVec solutions = tryCompleteQuest();
if(solutions.empty())
{
@ -180,7 +187,7 @@ TGoalVec CompleteQuestBehavior::missionKeymaster(const QuestInfo & q) const
return solutions;
}
TGoalVec CompleteQuestBehavior::missionResources(const QuestInfo & q) const
TGoalVec CompleteQuest::missionResources() const
{
TGoalVec solutions;
@ -209,7 +216,7 @@ TGoalVec CompleteQuestBehavior::missionResources(const QuestInfo & q) const
return solutions;
}
TGoalVec CompleteQuestBehavior::missionDestroyObj(const QuestInfo & q) const
TGoalVec CompleteQuest::missionDestroyObj() const
{
auto obj = cb->getObjByQuestIdentifier(q.quest->m13489val);

View File

@ -16,33 +16,33 @@
namespace Goals
{
class CompleteQuestBehavior : public CGoal<CompleteQuestBehavior>
class CompleteQuest : public CGoal<CompleteQuest>
{
private:
QuestInfo q;
public:
CompleteQuestBehavior()
:CGoal(COMPLETE_QUEST)
CompleteQuest(const QuestInfo & quest)
:CGoal(COMPLETE_QUEST), q(quest)
{
}
virtual Goals::TGoalVec decompose() const override;
virtual std::string toString() const override;
virtual bool operator==(const CompleteQuestBehavior & other) const override
{
return true;
}
virtual bool operator==(const CompleteQuest & other) const override;
private:
TGoalVec getQuestTasks(const QuestInfo & q) const;
TGoalVec tryCompleteQuest(const QuestInfo & q) const;
TGoalVec missionArt(const QuestInfo & q) const;
TGoalVec missionHero(const QuestInfo & q) const;
TGoalVec missionArmy(const QuestInfo & q) const;
TGoalVec missionResources(const QuestInfo & q) const;
TGoalVec missionDestroyObj(const QuestInfo & q) const;
TGoalVec missionIncreasePrimaryStat(const QuestInfo & q) const;
TGoalVec missionLevel(const QuestInfo & q) const;
TGoalVec missionKeymaster(const QuestInfo & q) const;
std::string questToString(const QuestInfo & q) const;
TGoalVec getQuestTasks() const;
TGoalVec tryCompleteQuest() const;
TGoalVec missionArt() const;
TGoalVec missionHero() const;
TGoalVec missionArmy() const;
TGoalVec missionResources() const;
TGoalVec missionDestroyObj() const;
TGoalVec missionIncreasePrimaryStat() const;
TGoalVec missionLevel() const;
TGoalVec missionKeymaster() const;
std::string questToString() const;
};
}

View File

@ -10,8 +10,8 @@
#pragma once
#define VCMI_TRACE_PATHFINDER 2
#define AI_TRACE_LEVEL 2
#define VCMI_TRACE_PATHFINDER 1
#define AI_TRACE_LEVEL 1
#include "../../../lib/CPathfinder.h"
#include "../../../lib/mapObjects/CGHeroInstance.h"

View File

@ -31,13 +31,17 @@ namespace AIPathfinding
bool QuestAction::canAct(const AIPathNode * node) const
{
QuestInfo q = questInfo;
return q.quest->checkQuest(node->actor->hero);
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->checkQuest(node->actor->hero);
}
Goals::TSubgoal QuestAction::decompose(const CGHeroInstance * hero) const
{
return Goals::sptr(Goals::Invalid());
return Goals::sptr(Goals::CompleteQuest(questInfo));
}
void QuestAction::execute(const CGHeroInstance * hero) const

View File

@ -11,6 +11,7 @@
#include "AIMovementAfterDestinationRule.h"
#include "../Actions/BattleAction.h"
#include "../../Goals/Invalid.h"
#include "AIPreviousNodeRule.h"
namespace AIPathfinding
{
@ -94,17 +95,9 @@ namespace AIPathfinding
const PathfinderConfig * pathfinderConfig,
CPathfinderHelper * pathfinderHelper) const
{
auto enemyHero = destination.nodeHero && destination.heroRelations == PlayerRelations::ENEMIES;
if(!enemyHero && !isObjectRemovable(destination.nodeObject))
{
if(nodeStorage->getHero(destination.node) == destination.nodeHero)
return true;
return false;
}
if(destination.nodeObject->ID == Obj::QUEST_GUARD || destination.nodeObject->ID == Obj::BORDERGUARD)
if(destination.nodeObject->ID == Obj::QUEST_GUARD
|| destination.nodeObject->ID == Obj::BORDERGUARD
|| destination.nodeObject->ID == Obj::BORDER_GATE)
{
auto questObj = dynamic_cast<const IQuestObject *>(destination.nodeObject);
auto nodeHero = pathfinderHelper->hero;
@ -119,6 +112,18 @@ namespace AIPathfinding
node->specialAction.reset(new QuestAction(questInfo));
});
}
return true;
}
auto enemyHero = destination.nodeHero && destination.heroRelations == PlayerRelations::ENEMIES;
if(!enemyHero && !isObjectRemovable(destination.nodeObject))
{
if(nodeStorage->getHero(destination.node) == destination.nodeHero)
return true;
return false;
}
return true;
@ -213,12 +218,9 @@ namespace AIPathfinding
vstd::amax(battleNode->danger, danger);
battleNode->specialAction = std::make_shared<BattleAction>(destination.coord);
AIPreviousNodeRule(nodeStorage).process(source, destination, pathfinderConfig, pathfinderHelper);
if(source.nodeObject && isObjectRemovable(source.nodeObject))
{
battleNode->theNodeBefore = source.node;
}
battleNode->specialAction = std::make_shared<BattleAction>(destination.coord);
#ifdef VCMI_TRACE_PATHFINDER
logAi->trace(

View File

@ -582,12 +582,15 @@ void VCAI::showBlockingDialog(const std::string & text, const std::vector<Compon
{
//yes&no -> always answer yes, we are a brave AI :)
auto answer = 1;
if(nullkiller)
{
auto hero = nullkiller->getActiveHero();
auto target = nullkiller->getTargetTile();
auto hero = nullkiller->getActiveHero();
auto target = nullkiller->getTargetTile();
auto objects = cb->getVisitableObjs(target);
if(hero.validAndSet() && target.valid())
if(hero.validAndSet() && target.valid() && objects.size())
{
auto objType = objects.front()->ID;
if(objType == Obj::ARTIFACT || objType == Obj::RESOURCE)
{
auto ratio = (float)fh->evaluateDanger(target, hero.get()) / (float)hero->getTotalStrength();
bool dangerUnknown = ratio == 0;