25void WarScene::printMessage(
const U8 eventId,
const string& unitName)
const {
29 eventName =
"Captured flag";
32 eventName =
"Recovered flag";
35 eventName =
"Unknown!";
45void WarScene::checkGameCompletion() {
46 bool restartGame =
false;
47 bool timeReason =
false;
67 _context.app().RequestShutdown(
false);
72 const U32 elapsedTimeMinutes = Time::MicrosecondsToSeconds<U32>(
_elapsedGameTime) / 60 % 60;
88 _context.app().RequestShutdown(
false);
101 for (
U8 i = 0; i < 2; ++i) {
113void WarScene::registerPoint(
const U16 teamID,
const string& unitName) {
118 for (
U8 i = 0; i < 2; ++i) {
119 if (
_flag[i] !=
nullptr )
133 Console::d_printfn(
Util::StringFormat(
"[GAME TIME: {}:{}][TEAM {} REGISTER POINT]: {}", elapsedTimeMinutes, elapsedTimeSeconds, teamID == 0 ?
"A" :
"B", unitName.c_str()).c_str());
138bool WarScene::initializeAI(
bool ) {
141 for (
U8 i = 0; i < 2; ++i)
143 _faction[i] = _aiManager->registerTeam(i);
160bool WarScene::removeUnits()
163 for (
U8 i = 0; i < 2; ++i)
168 _sceneGraph->removeNode(npc);
176bool WarScene::addUnits() {
181 WarSceneAction approachEnemyFlag(ActionType::APPROACH_ENEMY_FLAG,
"ApproachEnemyFlag");
186 WarSceneAction protectFlagInBase(ActionType::APPROACH_ENEMY_FLAG,
"ProtectFlagInBase");
193 WarSceneAction captureEnemyFlag(ActionType::CAPTURE_ENEMY_FLAG,
"CaptureEnemyFlag");
200 WarSceneAction recoverFlag(ActionType::RECOVER_FLAG,
"RecoverFlag");
206 WarSceneAction returnToBase(ActionType::RETURN_TO_BASE,
"ReturnToBase");
211 WarSceneAction scoreEnemyFlag(ActionType::SCORE_FLAG,
"ScoreEnemyFlag");
227 GOAPGoal recoverOwnFlag(
"Recover flag",
to_base(WarSceneOrder::WarOrder::RECOVER_FLAG));
230 GOAPGoal captureFlag(
"Capture enemy flag",
to_base(WarSceneOrder::WarOrder::CAPTURE_ENEMY_FLAG));
234 GOAPGoal scoreFlag(
"Score",
to_base(WarSceneOrder::WarOrder::SCORE_ENEMY_FLAG));
240 GOAPGoal killEnemy(
"Kill",
to_base(WarSceneOrder::WarOrder::KILL_ENEMY));
243 GOAPGoal protectFlagCarrier(
"Protect Flag Carrier",
to_base(WarSceneOrder::WarOrder::PROTECT_FLAG_CARRIER));
248 goapPackage._worldState.setVariable(
GOAPFact(Fact::AT_HOME_BASE),
GOAPValue(
true));
249 goapPackage._worldState.setVariable(
GOAPFact(Fact::ENEMY_DEAD),
GOAPValue(
false));
250 goapPackage._worldState.setVariable(
GOAPFact(Fact::ENEMY_HAS_FLAG),
GOAPValue(
false));
251 goapPackage._worldState.setVariable(
GOAPFact(Fact::HAS_ENEMY_FLAG),
GOAPValue(
false));
253 goapPackage._worldState.setVariable(
GOAPFact(Fact::NEAR_ENEMY_FLAG),
GOAPValue(
false));
255 goapPackage._actionSet.push_back(idleAction);
256 goapPackage._actionSet.push_back(attackAction);
257 goapPackage._actionSet.push_back(recoverFlag);
258 goapPackage._actionSet.push_back(protectFlagInBase);
259 goapPackage._goalList.push_back(idle);
260 goapPackage._goalList.push_back(killEnemy);
261 goapPackage._goalList.push_back(recoverOwnFlag);
264 GOAPPackage& lightPackage = goapPackages[
to_base(WarSceneAIProcessor::AIType::LIGHT)];
265 GOAPPackage& heavyPackage = goapPackages[
to_base(WarSceneAIProcessor::AIType::HEAVY)];
267 heavyPackage.
_actionSet.push_back(approachEnemyFlag);
268 heavyPackage.
_actionSet.push_back(captureEnemyFlag);
269 heavyPackage.
_actionSet.push_back(returnToBase);
270 heavyPackage.
_actionSet.push_back(scoreEnemyFlag);
271 lightPackage.
_actionSet.push_back(approachEnemyFlag);
273 heavyPackage.
_goalList.push_back(captureFlag);
274 heavyPackage.
_goalList.push_back(scoreFlag);
275 heavyPackage.
_goalList.push_back(protectFlagCarrier);
276 lightPackage.
_goalList.push_back(protectFlagCarrier);
302 for (
I32 k = 0; k < 2; ++k)
304 for (
I32 i = 0; i < 15; ++i)
349 npcNodeDescriptor.
_name = currentName;
377 std::shared_ptr<NPC> soldier = std::make_shared<NPC>( tComp->
getWorldPosition(), currentNode->name() );
381 soldier->setMovementSpeed(speed);
382 soldier->setAcceleration(acc);
384 aiSoldier = soldier->getAIEntity();
400 _aiManager->registerEntity(k, aiSoldier);
415 for (
U8 i = 0; i < 2; ++i) {
417 if (npc->getGUID() == targetGUID) {
418 return npc->get<
UnitComponent>()->getUnit<NPC>()->getAIEntity();
426bool WarScene::resetUnits() {
427 _aiManager->pauseUpdate(
true);
432 _aiManager->pauseUpdate(
false);
436bool WarScene::deinitializeAI(
bool ) {
437 _aiManager->pauseUpdate(
true);
440 for (
U8 i = 0; i < 2; ++i)
442 if (_aiManager->unregisterTeam(i))
457void WarScene::startSimulation(
I64 )
459 if (g_navMeshStarted ||
_armyNPCs[0].empty()) {
463 g_navMeshStarted =
true;
465 _aiManager->pauseUpdate(
true);
468 bool previousMesh =
false;
469 bool loadedFromFile =
true;
483 _aiManager->destroyNavMesh( radius );
486 navMesh = _aiManager->addNavMesh(_context, *_parent.parent().recast(), *
this, radius);
489 if (!navMesh->
load(_sceneGraph->getRoot()))
491 loadedFromFile =
false;
492 navMesh->
build(_sceneGraph->getRoot(),
495 _aiManager->toggleNavMeshDebugDraw(
true);
496 g_navMeshStarted =
false;
508 if (loadedFromFile) {
510 "Re-loaded the navigation mesh from file!");
514 "Re-building the navigation mesh in a background thread!");
518 if (loadedFromFile) {
523 "Navigation mesh building in a background thread!");
528 for (
U8 i = 0; i < 2; ++i) {
545 "Can't reload the navigation mesh this soon.\n Please wait \\[ ");
548 info.append(
" ] seconds more!");
555 _aiManager->pauseUpdate(
false);
#define WAIT_FOR_CONDITION(...)
bool setAndSurrenderAIProcessor(AIProcessor *processor)
bool addSensor(SensorType type)
PresetAgentRadius getAgentRadiusCategory() const noexcept
The radius category of this character.
void addOrder(const OrderPtr &order)
bool addEnemyTeam(U32 enemyTeamID)
bool build(SceneGraphNode *sgn, CreationCallback creationCompleteCallback, bool threaded=true)
void debugDraw(const bool state) noexcept
void setFileName(const Str< 256 > &fileName)
bool load(const SceneGraphNode *sgn)
Load a saved NavigationMesh from a file.
void registerGOAPPackage(const GOAPPackage &package)
static U8 getScore(const U16 teamID)
static void resetScore(const U8 teamID)
static void registerFlags(SceneGraphNode *flag1, SceneGraphNode *flag2)
static void incrementScore(const U16 teamID)
FORCE_INLINE I64 getGUID() const noexcept
void setMessage(const string &message)
void setTitle(const string &titleText)
void setMessageType(MessageType type)
NPC base class. Every character in the game is an NPC by default except the Player.
AI::AIEntity * getAIEntity() const noexcept
FORCE_INLINE SceneNodeHandle handle() const noexcept
void setParent(SceneGraphNode *parent, bool defer=false)
Changing a node's parent means removing this node from the current parent's child list and appending ...
SceneGraphNode * addChildNode(const SceneGraphNodeDescriptor &descriptor)
Add child node increments the node's ref counter if the node was already added to the scene graph.
FORCE_INLINE T * get() const
Returns a pointer to a specific component. Returns null if the SGN does not have the component reques...
std::shared_ptr< T > getUnit() const noexcept
void setPrecondition(const I32 key, const bool value)
void setEffect(const I32 key, const bool value)
constexpr bool IS_DEBUG_BUILD
constexpr T Base(T a)
Base value.
U64 ElapsedMicroseconds() noexcept
constexpr T SecondsToMicroseconds(U a) noexcept
Str StringFormat(const char *fmt, Args &&...args)
string to_string(GET_PASS_TYPE< T > value)
Handle console commands that start with a forward slash.
constexpr U32 to_U32(const T value)
AI::AITeam * _faction[2]
Teams are factions for AIEntites so they can manage friend/foe situations.
U64 _lastNavMeshBuildTime
bool IS_IN_RANGE_INCLUSIVE(const T x, const U min, const U max) noexcept
vector< SceneGraphNode * > _armyNPCs[2]
NPC's are the actual game entities.
SceneGraphNode * _flag[2]
void checkGameCompletion()
constexpr auto to_base(const Type value) -> Type
vector< WarSceneAction > _actionSet
static NO_INLINE void d_printfn(const char *format, T &&... args)
SceneNodeHandle _nodeHandle
NodeUsageContext _usageContext
void setVariable(const int var_id, const bool value)