Compare commits

...

1 Commits

Author SHA1 Message Date
a54b042e49 Starting to implement GOAP plan 2026-02-06 22:14:48 +03:00
2 changed files with 127 additions and 1 deletions

View File

@@ -376,6 +376,129 @@ CharacterAIModule::CharacterAIModule(flecs::world &ecs)
});
});
});
struct ActionExec {
enum { OK = 0, BUSY, ERROR };
TownNPCs::NPCData &npc;
Blackboard &bb;
nlohmann::json &memory;
bool complete;
bool active;
const goap::BaseAction<Blackboard> *action;
ActionExec(TownNPCs::NPCData &npc, Blackboard &bb,
nlohmann::json &memory,
const goap::BaseAction<Blackboard> *action)
: npc(npc)
, bb(bb)
, memory(memory)
, complete(false)
, active(false)
, action(action)
{
}
ActionExec(const ActionExec &other)
: npc(other.npc)
, bb(other.bb)
, memory(other.memory)
, complete(other.complete)
, active(other.active)
, action(other.action)
{
}
ActionExec &operator=(const ActionExec &other)
{
npc = other.npc;
bb = other.bb;
memory = other.memory;
complete = other.complete;
active = other.active;
action = other.action;
return *this;
}
private:
int update(float delta)
{
return OK;
}
void finish(int result)
{
}
void activate()
{
std::cout << action->get_name();
OgreAssert(false, "activate");
}
public:
int operator()(float delta)
{
if (!active)
activate();
int ret = update(delta);
if (ret != BUSY)
finish(ret);
return ret;
}
};
struct PlanExec {
enum { OK = 0, BUSY, ERROR };
std::vector<struct ActionExec> action_exec;
int index;
PlanExec()
: index(-1)
{
}
int operator()(float delta)
{
if (index == -1)
index = 0;
int rc = action_exec[index](delta);
if (rc == ActionExec::ERROR)
return ERROR;
if (action_exec[index].complete)
index++;
if (index >= action_exec.size())
return OK;
return BUSY;
}
};
static std::unordered_map<int, struct PlanExec> plan_exec;
ecs.system<const EngineData, TownNPCs, TownAI>("RunPLAN")
.kind(flecs::OnUpdate)
.each([&](flecs::entity town, const EngineData &eng,
TownNPCs &npcs, TownAI &ai) {
for (const auto &plans : ai.plans) {
if (plan_exec.find(plans.first) !=
plan_exec.end()) {
plan_exec[plans.first](eng.delta);
continue;
}
std::cout << "NPC: " << plans.first;
std::cout << " Plans: " << plans.second.size();
for (const auto &plan : plans.second) {
struct PlanExec pexec;
if (plan.plan.size() == 0)
continue;
std::cout << " Goal: ";
plan.goal->goal.dump_bits();
for (const auto &action : plan.plan) {
pexec.action_exec.emplace_back(
npcs.npcs.at(
plans.first),
ai.blackboards.at(
plans.first),
ai.memory.at(
plans.first),
action);
std::cout << action->get_name()
<< " ";
}
plan_exec[plans.first] = pexec;
break;
}
std::cout << std::endl;
}
});
}
void CharacterAIModule::createAI(flecs::entity town)

View File

@@ -576,7 +576,10 @@ public:
, object_vs_object_layer_filter{}
, debugDraw(false)
{
// Create a factory, this class is responsible for creating instances of classes based on their name or hash and is mainly used for deserialization of saved data.
static int instanceCount = 0;
OgreAssert(instanceCount == 0, "Bad initialisation");
instanceCount++;
// Create a factory, this class is responsible for creating instances of classes based on their name or hash and is mainly used for deserialization of saved data.
// It is not directly used in this example but still required.
JPH::Factory::sInstance = new JPH::Factory();