From 5638cc53f82c30e86b4dec7334d198d82b82a518 Mon Sep 17 00:00:00 2001 From: Rochet2 Date: Tue, 25 Jul 2017 21:20:59 +0300 Subject: [PATCH] Implement delay ranges https://github.com/ElunaLuaEngine/Eluna/issues/205 --- ElunaEventMgr.cpp | 8 +++++--- ElunaEventMgr.h | 16 +++++++++++---- GlobalMethods.h | 29 ++++++++++++++++++++++---- WorldObjectMethods.h | 38 +++++++++++++++++++++++++++-------- docs/ElunaDoc/static/main.css | 2 +- 5 files changed, 73 insertions(+), 20 deletions(-) diff --git a/ElunaEventMgr.cpp b/ElunaEventMgr.cpp index dd42fa5..2a2075c 100644 --- a/ElunaEventMgr.cpp +++ b/ElunaEventMgr.cpp @@ -47,12 +47,13 @@ void ElunaEventProcessor::Update(uint32 diff) if (luaEvent->state == LUAEVENT_STATE_RUN) { + uint32 delay = luaEvent->delay; bool remove = luaEvent->repeats == 1; if (!remove) AddEvent(luaEvent); // Reschedule before calling incase RemoveEvents used // Call the timed event - (*E)->OnTimedEvent(luaEvent->funcRef, luaEvent->delay, luaEvent->repeats ? luaEvent->repeats-- : luaEvent->repeats, obj); + (*E)->OnTimedEvent(luaEvent->funcRef, delay, luaEvent->repeats ? luaEvent->repeats-- : luaEvent->repeats, obj); if (!remove) continue; @@ -97,13 +98,14 @@ void ElunaEventProcessor::SetState(int eventId, LuaEventState state) void ElunaEventProcessor::AddEvent(LuaEvent* luaEvent) { + luaEvent->GenerateDelay(); eventList.insert(std::pair(m_time + luaEvent->delay, luaEvent)); eventMap[luaEvent->funcRef] = luaEvent; } -void ElunaEventProcessor::AddEvent(int funcRef, uint32 delay, uint32 repeats) +void ElunaEventProcessor::AddEvent(int funcRef, uint32 min, uint32 max, uint32 repeats) { - AddEvent(new LuaEvent(funcRef, delay, repeats)); + AddEvent(new LuaEvent(funcRef, min, max, repeats)); } void ElunaEventProcessor::RemoveEvent(LuaEvent* luaEvent) diff --git a/ElunaEventMgr.h b/ElunaEventMgr.h index 354144a..e27b45d 100644 --- a/ElunaEventMgr.h +++ b/ElunaEventMgr.h @@ -9,6 +9,7 @@ #include "ElunaUtility.h" #include "Common.h" +#include "Random.h" #include #ifdef TRINITY @@ -31,8 +32,8 @@ enum LuaEventState struct LuaEvent { - LuaEvent(int _funcRef, uint32 _delay, uint32 _repeats) : - delay(_delay), repeats(_repeats), funcRef(_funcRef), state(LUAEVENT_STATE_RUN) + LuaEvent(int _funcRef, uint32 _min, uint32 _max, uint32 _repeats) : + min(_min), max(_max), delay(0), repeats(_repeats), funcRef(_funcRef), state(LUAEVENT_STATE_RUN) { } @@ -42,7 +43,14 @@ struct LuaEvent state = _state; } - uint32 delay; // Delay between event calls + void GenerateDelay() + { + delay = urand(min, max); + } + + uint32 min; // Minimum delay between event calls + uint32 max; // Maximum delay between event calls + uint32 delay; // The currently used waiting time uint32 repeats; // Amount of repeats to make, 0 for infinite int funcRef; // Lua function reference ID, also used as event ID LuaEventState state; // State for next call @@ -64,7 +72,7 @@ public: void SetStates(LuaEventState state); // set the event to be removed when executing void SetState(int eventId, LuaEventState state); - void AddEvent(int funcRef, uint32 delay, uint32 repeats); + void AddEvent(int funcRef, uint32 min, uint32 max, uint32 repeats); EventMap eventMap; private: diff --git a/GlobalMethods.h b/GlobalMethods.h index 5aeb61e..04a016a 100644 --- a/GlobalMethods.h +++ b/GlobalMethods.h @@ -1303,22 +1303,43 @@ namespace LuaGlobalFunctions * * Repeats will decrease on each call if the event does not repeat indefinitely * + * @proto eventId = (function, delay) + * @proto eventId = (function, delaytable) + * @proto eventId = (function, delay, repeats) + * @proto eventId = (function, delaytable, repeats) + * * @param function function : function to trigger when the time has passed * @param uint32 delay : set time in milliseconds for the event to trigger - * @param uint32 repeats : how many times for the event to repeat, 0 is infinite + * @param table delaytable : a table `{min, max}` containing the minimum and maximum delay time + * @param uint32 repeats = 1 : how many times for the event to repeat, 0 is infinite * @return int eventId : unique ID for the timed event used to cancel it or nil */ int CreateLuaEvent(lua_State* L) { luaL_checktype(L, 1, LUA_TFUNCTION); - uint32 delay = Eluna::CHECKVAL(L, 2); - uint32 repeats = Eluna::CHECKVAL(L, 3); + uint32 min, max; + if (lua_istable(L, 2)) + { + Eluna::Push(L, 1); + lua_gettable(L, 2); + min = Eluna::CHECKVAL(L, -1); + Eluna::Push(L, 2); + lua_gettable(L, 2); + max = Eluna::CHECKVAL(L, -1); + lua_pop(L, 2); + } + else + min = max = Eluna::CHECKVAL(L, 2); + uint32 repeats = Eluna::CHECKVAL(L, 3, 1); + + if (min > max) + return luaL_argerror(L, 2, "min is bigger than max delay"); lua_pushvalue(L, 1); int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); if (functionRef != LUA_REFNIL && functionRef != LUA_NOREF) { - Eluna::GetEluna(L)->eventMgr->globalProcessor->AddEvent(functionRef, delay, repeats); + Eluna::GetEluna(L)->eventMgr->globalProcessor->AddEvent(functionRef, min, max, repeats); Eluna::Push(L, functionRef); } return 1; diff --git a/WorldObjectMethods.h b/WorldObjectMethods.h index aad86f8..2fa105b 100644 --- a/WorldObjectMethods.h +++ b/WorldObjectMethods.h @@ -778,27 +778,49 @@ namespace LuaWorldObject * Note that for [Creature] and [GameObject] the timed event timer ticks only if the creature is in sight of someone * For all [WorldObject]s the timed events are removed when the object is destoryed. This means that for example a [Player]'s events are removed on logout. * - * local function Timed(eventid, delay, repeats, worldobject) - * print(worldobject:GetName()) - * end - * worldobject:RegisterEvent(Timed, 1000, 1) -- do it after 1 second once + * local function Timed(eventid, delay, repeats, worldobject) + * print(worldobject:GetName()) + * end + * worldobject:RegisterEvent(Timed, 1000, 5) -- do it after 1 second 5 times + * worldobject:RegisterEvent(Timed, {1000, 10000}, 0) -- do it after 1 to 10 seconds forever + * + * @proto eventId = (function, delay) + * @proto eventId = (function, delaytable) + * @proto eventId = (function, delay, repeats) + * @proto eventId = (function, delaytable, repeats) * * @param function function : function to trigger when the time has passed * @param uint32 delay : set time in milliseconds for the event to trigger - * @param uint32 repeats : how many times for the event to repeat, 0 is infinite + * @param table delaytable : a table `{min, max}` containing the minimum and maximum delay time + * @param uint32 repeats = 1 : how many times for the event to repeat, 0 is infinite * @return int eventId : unique ID for the timed event used to cancel it or nil */ int RegisterEvent(lua_State* L, WorldObject* obj) { luaL_checktype(L, 2, LUA_TFUNCTION); - uint32 delay = Eluna::CHECKVAL(L, 3); - uint32 repeats = Eluna::CHECKVAL(L, 4); + uint32 min, max; + if (lua_istable(L, 3)) + { + Eluna::Push(L, 1); + lua_gettable(L, 3); + min = Eluna::CHECKVAL(L, -1); + Eluna::Push(L, 2); + lua_gettable(L, 3); + max = Eluna::CHECKVAL(L, -1); + lua_pop(L, 2); + } + else + min = max = Eluna::CHECKVAL(L, 3); + uint32 repeats = Eluna::CHECKVAL(L, 4, 1); + + if (min > max) + return luaL_argerror(L, 3, "min is bigger than max delay"); lua_pushvalue(L, 2); int functionRef = luaL_ref(L, LUA_REGISTRYINDEX); if (functionRef != LUA_REFNIL && functionRef != LUA_NOREF) { - obj->elunaEvents->AddEvent(functionRef, delay, repeats); + obj->elunaEvents->AddEvent(functionRef, min, max, repeats); Eluna::Push(L, functionRef); } return 1; diff --git a/docs/ElunaDoc/static/main.css b/docs/ElunaDoc/static/main.css index f9d3aa4..4d943cf 100644 --- a/docs/ElunaDoc/static/main.css +++ b/docs/ElunaDoc/static/main.css @@ -123,7 +123,7 @@ code, pre { .docblock code { background-color: #F5F5F5; border-radius: 3px; - padding: 0 0.2em; + /*padding: 0 0.2em;*/ } pre { background-color: #F5F5F5;