#include "gameplay/ai.h" #include "gameplay/gameactor.h" #include "utility/raycaster.h" #include "utility/script.h" AI::AI(GameActor* actor, std::unique_ptr raycaster) : state(AIState::Idle), raycaster(std::move(raycaster)), actor(actor), lastGCTime(std::chrono::high_resolution_clock::now()), GCTimeout(3) {} void AI::attachBehaviourScript(std::unique_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 = std::move(behaviour); this->behaviour->lua["raycaster"] = sol::make_reference(this->behaviour->lua, raycaster.get()); this->behaviour->lua["ai"] = sol::make_reference(this->behaviour->lua, this); idleFunc = this->behaviour->lua["idle"]; patrolFunc = this->behaviour->lua["patrol"]; alertFunc = this->behaviour->lua["alert"]; } void AI::update() { try { if (actor && target) { 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; } } AI::~AI() { behaviour->lua["raycaster"] = sol::nil; behaviour->lua["ai"] = sol::nil; behaviour->lua["idle"] = sol::nil; behaviour->lua["patrol"] = sol::nil; behaviour->lua["alert"] = sol::nil; behaviour->lua.collect_gc(); }