#include "gameplay/ai.h" #include "gameplay/gameactor.h" #include "utility/raycaster.h" #include "utility/script.h" #include AI::AI(const std::shared_ptr& actor, const std::shared_ptr& raycaster) : actor(actor), raycaster(raycaster), state(AIState::Idle), lastGCTime(std::chrono::high_resolution_clock::now()), GCTimeout(3) {} void AI::attachBehaviourScript(const std::shared_ptr& behaviour) { // passing out instance of raycaster and this AI into our scripting api // pay special attention each ai script has control of only their own instance of ai! this->behaviour = behaviour; this->behaviour->lua["raycaster"] = raycaster; this->behaviour->lua["ai"] = shared_from_this(); if (this->behaviour->lua["idle"].valid()) idleFunc = this->behaviour->lua["idle"]; if (this->behaviour->lua["patrol"].valid()) patrolFunc = this->behaviour->lua["patrol"]; if (this->behaviour->lua["alert"].valid()) alertFunc = this->behaviour->lua["alert"]; } void AI::update() { try { switch (state) { case AIState::Idle: if (idleFunc.valid()) { auto result = idleFunc(actor, target); if (!result.valid()) { sol::error err = result; std::cerr << "lua error: " << err.what() << std::endl; } } break; case AIState::Patrol: if (patrolFunc.valid()) { auto result = patrolFunc(actor, target); if (!result.valid()) { sol::error err = result; std::cerr << "lua error: " << err.what() << std::endl; } } break; case AIState::Alert: if (alertFunc.valid()) { auto result = alertFunc(actor, target); if (!result.valid()) { sol::error err = result; std::cerr << "lua error: " << err.what() << std::endl; } } break; } std::chrono::high_resolution_clock::time_point curTime = std::chrono::high_resolution_clock::now(); if (curTime - lastGCTime >= GCTimeout) { behaviour->lua.collect_gc(); lastGCTime = curTime; } } catch (const std::exception& e) { std::cerr << "Error during AI update: " << e.what() << std::endl; state = AIState::Idle; } }