Implement perception criteria when searching for nth nearest creature

This commit is contained in:
Vsevolod Kremianskii 2021-03-23 16:05:19 +07:00
parent ff9d939c32
commit 9e436508bd
6 changed files with 56 additions and 14 deletions

View file

@ -34,13 +34,13 @@ CreatureFinder::CreatureFinder(Area *area) : _area(area) {
}
}
shared_ptr<Creature> CreatureFinder::getNearestCreature(const SpatialObject &target, const CreatureFinder::CriteriaList &criterias, int nth) {
shared_ptr<Creature> CreatureFinder::getNearestCreature(const std::shared_ptr<SpatialObject> &target, const CreatureFinder::CriteriaList &criterias, int nth) {
vector<pair<shared_ptr<Creature>, float>> candidates;
for (auto &object : _area->getObjectsByType(ObjectType::Creature)) {
auto creature = static_pointer_cast<Creature>(object);
if (matchesCriterias(*creature, criterias)) {
float distance2 = creature->getDistanceTo2(target);
if (matchesCriterias(*creature, criterias, target)) {
float distance2 = creature->getDistanceTo2(*target);
candidates.push_back(make_pair(move(creature), distance2));
}
}
@ -52,7 +52,7 @@ shared_ptr<Creature> CreatureFinder::getNearestCreature(const SpatialObject &tar
return nth < candidates.size() ? candidates[nth].first : nullptr;
}
bool CreatureFinder::matchesCriterias(const Creature &creature, const CriteriaList &criterias, shared_ptr<SpatialObject> target) const {
bool CreatureFinder::matchesCriterias(const Creature &creature, const CriteriaList &criterias, std::shared_ptr<SpatialObject> target) const {
for (auto &criteria : criterias) {
switch (criteria.first) {
case CreatureType::Reputation: {
@ -72,6 +72,44 @@ bool CreatureFinder::matchesCriterias(const Creature &creature, const CriteriaLi
}
break;
}
case CreatureType::Perception: {
if (!target) return false;
bool seen = creature.perception().seen.count(target) > 0;
bool heard = creature.perception().heard.count(target) > 0;
bool matches = false;
auto perception = static_cast<PerceptionType>(criteria.second);
switch (perception) {
case PerceptionType::SeenAndHeard:
matches = seen && heard;
break;
case PerceptionType::NotSeenAndNotHeard:
matches = !seen && !heard;
break;
case PerceptionType::HeardAndNotSeen:
matches = heard && !seen;
break;
case PerceptionType::SeenAndNotHeard:
matches = seen && !heard;
break;
case PerceptionType::NotHeard:
matches = !heard;
break;
case PerceptionType::Heard:
matches = heard;
break;
case PerceptionType::NotSeen:
matches = !seen;
break;
case PerceptionType::Seen:
matches = seen;
break;
default:
break;
}
if (!matches) return false;
break;
}
default:
// TODO: implement other criterias
break;

View file

@ -39,7 +39,7 @@ public:
* @param nth 0-based index of the creature
* @return nth nearest creature to the target object, that matches the specified criterias
*/
std::shared_ptr<Creature> getNearestCreature(const SpatialObject &target, const CriteriaList &criterias, int nth = 0);
std::shared_ptr<Creature> getNearestCreature(const std::shared_ptr<SpatialObject> &target, const CriteriaList &criterias, int nth = 0);
/**
* @param nth 0-based index of the creature

View file

@ -578,7 +578,7 @@ void Creature::runOnNoticeScript() {
void Creature::onObjectVanished(const shared_ptr<SpatialObject> &object) {
_perception.seen.erase(object);
_perception.lastPerception = PerceptionType::Vanished;
_perception.lastPerception = PerceptionType::NotSeen;
_perception.lastPerceived = object;
runOnNoticeScript();
}
@ -592,7 +592,7 @@ void Creature::onObjectHeard(const shared_ptr<SpatialObject> &object) {
void Creature::onObjectInaudible(const shared_ptr<SpatialObject> &object) {
_perception.heard.erase(object);
_perception.lastPerception = PerceptionType::Inaudible;
_perception.lastPerception = PerceptionType::NotHeard;
_perception.lastPerceived = object;
runOnNoticeScript();
}

View file

@ -423,7 +423,7 @@ Variable Routines::getNearestCreature(const VariablesList &args, ExecutionContex
criterias.push_back(make_pair(static_cast<CreatureType>(thirdCriteriaType), thirdCriteriaValue));
}
shared_ptr<Creature> creature(_game->module()->area()->creatureFinder().getNearestCreature(*target, criterias, nth - 1));
shared_ptr<Creature> creature(_game->module()->area()->creatureFinder().getNearestCreature(target, criterias, nth - 1));
return static_pointer_cast<ScriptObject>(creature);
}

View file

@ -64,7 +64,7 @@ Variable Routines::getLastPerceptionVanished(const VariablesList &args, Executio
auto caller = getCallerAsCreature(ctx);
if (caller) {
result.intValue = caller->perception().lastPerception == PerceptionType::Vanished;
result.intValue = caller->perception().lastPerception == PerceptionType::NotSeen;
} else {
warn("Script: getLastPerceptionVanished: invalid caller");
}
@ -92,7 +92,7 @@ Variable Routines::getLastPerceptionInaudible(const VariablesList &args, Executi
auto caller = getCallerAsCreature(ctx);
if (caller) {
result.intValue = caller->perception().lastPerception == PerceptionType::Inaudible;
result.intValue = caller->perception().lastPerception == PerceptionType::NotHeard;
} else {
warn("Script: getLastPerceptionInaudible: invalid caller");
}

View file

@ -834,10 +834,14 @@ enum class ReputationType {
};
enum class PerceptionType {
Seen,
Vanished,
Heard,
Inaudible
SeenAndHeard = 0,
NotSeenAndNotHeard = 1,
HeardAndNotSeen = 2,
SeenAndNotHeard = 3,
NotHeard = 4,
Heard = 5,
NotSeen = 6,
Seen = 7
};
struct InventorySlot {