diff --git a/src/modes/world.cpp b/src/modes/world.cpp index 5310bdf80..8c88faced 100644 --- a/src/modes/world.cpp +++ b/src/modes/world.cpp @@ -933,6 +933,7 @@ void World::update(float dt) if(ReplayPlay::get()) ReplayPlay::get()->update(dt); if(history->replayHistory()) dt=history->getNextDelta(); WorldStatus::update(dt); + if (m_script_engine) m_script_engine->update(dt); PROFILER_POP_CPU_MARKER(); if (!history->dontDoPhysics()) diff --git a/src/scriptengine/script_engine.cpp b/src/scriptengine/script_engine.cpp index 77fc84ceb..a520c667e 100644 --- a/src/scriptengine/script_engine.cpp +++ b/src/scriptengine/script_engine.cpp @@ -407,4 +407,27 @@ namespace Scripting return true; } + + //----------------------------------------------------------------------------- + + void ScriptEngine::addPendingTimeout(double time, const std::string& callback_name) + { + m_pending_timeouts.push_back(PendingTimeout(time, callback_name)); + } + + //----------------------------------------------------------------------------- + + void ScriptEngine::update(double dt) + { + for (int i = m_pending_timeouts.size() - 1; i >= 0; i--) + { + PendingTimeout& curr = m_pending_timeouts[i]; + curr.m_time -= dt; + if (curr.m_time <= 0.0) + { + runFunction("void " + curr.m_callback_name + "()"); + m_pending_timeouts.erase(m_pending_timeouts.begin() + i); + } + } + } } diff --git a/src/scriptengine/script_engine.hpp b/src/scriptengine/script_engine.hpp index 1d6aa956d..ab0bd8fd1 100644 --- a/src/scriptengine/script_engine.hpp +++ b/src/scriptengine/script_engine.hpp @@ -27,6 +27,19 @@ class TrackObjectPresentation; namespace Scripting { + /** Represents a scripting function to execute after a given time */ + struct PendingTimeout + { + double m_time; + std::string m_callback_name; + + PendingTimeout(double time, const std::string& callback_name) + { + m_time = time; + m_callback_name = callback_name; + } + }; + class ScriptEngine { public: @@ -46,9 +59,13 @@ namespace Scripting bool loadScript(std::string script_path, bool clear_previous); bool compileLoadedScripts(); + void addPendingTimeout(double time, const std::string& callback_name); + void update(double dt); + private: asIScriptEngine *m_engine; std::map m_functions_cache; + std::vector m_pending_timeouts; void configureEngine(asIScriptEngine *engine); }; // class ScriptEngine diff --git a/src/scriptengine/script_utils.cpp b/src/scriptengine/script_utils.cpp index 5ab527efa..dc925b0f6 100644 --- a/src/scriptengine/script_utils.cpp +++ b/src/scriptengine/script_utils.cpp @@ -108,6 +108,25 @@ namespace Scripting script_engine->runFunction(*str); } + /** Generate a random integer value */ + int randomInt(int min, int maxExclusive) + { + return min + (rand() % (maxExclusive - min)); + } + + /** Generate a random floating-point value */ + float randomFloat(int min, int maxExclusive) + { + int val = min * 100 + (rand() % ((maxExclusive - min) * 100)); + return val / 100.0f; + } + + /** Call a function after the specified delay */ + void setTimeout(const std::string* callback_name, float delay) + { + World::getWorld()->getScriptEngine()->addPendingTimeout(delay, *callback_name); + } + /** Log to the console */ void logInfo(std::string* log) { @@ -163,6 +182,10 @@ namespace Scripting r = engine->RegisterGlobalFunction("void runScript(string &in)", asFUNCTION(runScript), asCALL_CDECL); assert(r >= 0); + r = engine->RegisterGlobalFunction("int randomInt(int, int)", asFUNCTION(randomInt), asCALL_CDECL); assert(r >= 0); + r = engine->RegisterGlobalFunction("float randomFloat(int, int)", asFUNCTION(randomFloat), asCALL_CDECL); assert(r >= 0); + r = engine->RegisterGlobalFunction("void setTimeout(const string &in, float)", asFUNCTION(setTimeout), asCALL_CDECL); assert(r >= 0); + r = engine->RegisterGlobalFunction("void logInfo(const string &in)", asFUNCTION(logInfo), asCALL_CDECL); assert(r >= 0); r = engine->RegisterGlobalFunction("void logWarning(const string &in)", asFUNCTION(logWarning), asCALL_CDECL); assert(r >= 0); r = engine->RegisterGlobalFunction("void logError(const string &in)", asFUNCTION(logError), asCALL_CDECL); assert(r >= 0);