diff --git a/doc/angelscript/Game2Script/script_callbacks.h b/doc/angelscript/Game2Script/script_callbacks.h index 2fe7f730ee..f8080280ce 100644 --- a/doc/angelscript/Game2Script/script_callbacks.h +++ b/doc/angelscript/Game2Script/script_callbacks.h @@ -19,12 +19,19 @@ void main(); */ void frameStep(float dt); -/** Optional; Invoked if a registered event is triggered, see Script2Game::game::registerForEvent. +/** Optional; Invoked if a registered event is triggered, see `GameScriptClass::registerForEvent()`. * @param event Event code. * @param param Event-specific parameter, see docs for the event codes. */ void eventCallback(Script2Game::scriptEvents event, int param); +/** Optional; if present, will be used instead of `Game2Script::eventCallback()`. +* Invoked if a registered event is triggered, see `GameScriptClass::registerForEvent()`. +* The first argument is the same as `eventCallback()` gets, other are extras, see descriptions at `Script2Game::scriptEvents`. +* @param event Event code. +*/ +void eventCallbackEx(Script2Game::scriptEvents event, int arg1, int arg2ex, int arg3ex, int arg4ex, string arg5ex, string arg6ex, string arg7ex, string arg8ex); + /** Optional; Invoked when a vehicle touches an eventbox which has no custom handler function. * @param trigger_type Unused, always 0. * @param inst Unique ID of the terrain object instance which created the eventbox. diff --git a/source/main/gameplay/ScriptEvents.h b/source/main/gameplay/ScriptEvents.h index ec3708f3a3..7935901b6c 100644 --- a/source/main/gameplay/ScriptEvents.h +++ b/source/main/gameplay/ScriptEvents.h @@ -20,31 +20,36 @@ #pragma once +#include "BitFlags.h" + /// This enum describes what events are existing. The script can register to receive events. enum scriptEvents { - SE_TRUCK_ENTER = 0x00000004, //!< triggered when switching from person mode to vehicle mode, the argument refers to the actor ID of the vehicle - SE_TRUCK_EXIT = 0x00000008, //!< triggered when switching from vehicle mode to person mode, the argument refers to the actor ID of the vehicle + SE_EVENTBOX_ENTER = BITMASK(1), //!< Actor or person entered an eventbox; arguments: #1 type, #2 actorID (actor only), #3 node ID (actor only), #4 unused, #5 object instance name #6 eventbox name, #7 unused #8 unused. + SE_EVENTBOX_EXIT = BITMASK(2), //!< Actor or person left an eventbox; arguments: #1 type, #2 actorID (actor only), #3 unused, #4 unused, #5 object instance name #6 eventbox name, #7 unused #8 unused. + + SE_TRUCK_ENTER = BITMASK(3), //!< triggered when switching from person mode to vehicle mode, the argument refers to the actor ID of the vehicle + SE_TRUCK_EXIT = BITMASK(4), //!< triggered when switching from vehicle mode to person mode, the argument refers to the actor ID of the vehicle - SE_TRUCK_ENGINE_DIED = 0x00000010, //!< triggered when the vehicle's engine dies (from underrev, water, etc), the argument refers to the actor ID of the vehicle - SE_TRUCK_ENGINE_FIRE = 0x00000020, //!< triggered when the planes engines start to get on fire, the argument refers to the actor ID of the vehicle - SE_TRUCK_TOUCHED_WATER = 0x00000040, //!< triggered when any part of the actor touches water, the argument refers to the actor ID - SE_TRUCK_LIGHT_TOGGLE = 0x00000400, //!< triggered when the main light is toggled, the argument refers to the actor ID - SE_TRUCK_TIE_TOGGLE = 0x00001000, //!< triggered when the user toggles ties, the argument refers to the actor ID - SE_TRUCK_PARKINGBRAKE_TOGGLE = 0x00002000, //!< triggered when the user toggles the parking brake, the argument refers to the actor ID - SE_TRUCK_BEACONS_TOGGLE = 0x00004000, //!< triggered when the user toggles beacons, the argument refers to the actor ID - SE_TRUCK_CPARTICLES_TOGGLE = 0x00008000, //!< triggered when the user toggles custom particles, the argument refers to the actor ID + SE_TRUCK_ENGINE_DIED = BITMASK(5), //!< triggered when the vehicle's engine dies (from underrev, water, etc), the argument refers to the actor ID of the vehicle + SE_TRUCK_ENGINE_FIRE = BITMASK(6), //!< triggered when the planes engines start to get on fire, the argument refers to the actor ID of the vehicle + SE_TRUCK_TOUCHED_WATER = BITMASK(7), //!< triggered when any part of the actor touches water, the argument refers to the actor ID + SE_TRUCK_LIGHT_TOGGLE = BITMASK(8), //!< triggered when the main light is toggled, the argument refers to the actor ID + SE_TRUCK_TIE_TOGGLE = BITMASK(9), //!< triggered when the user toggles ties, the argument refers to the actor ID + SE_TRUCK_PARKINGBRAKE_TOGGLE = BITMASK(10), //!< triggered when the user toggles the parking brake, the argument refers to the actor ID + SE_TRUCK_BEACONS_TOGGLE = BITMASK(11), //!< triggered when the user toggles beacons, the argument refers to the actor ID + SE_TRUCK_CPARTICLES_TOGGLE = BITMASK(12), //!< triggered when the user toggles custom particles, the argument refers to the actor ID - SE_GENERIC_NEW_TRUCK = 0x00020000, //!< triggered when the user spawns a new actor, the argument refers to the actor ID - SE_GENERIC_DELETED_TRUCK = 0x00040000, //!< triggered when the user deletes an actor, the argument refers to the actor ID + SE_GENERIC_NEW_TRUCK = BITMASK(13), //!< triggered when the user spawns a new actor, the argument refers to the actor ID + SE_GENERIC_DELETED_TRUCK = BITMASK(14), //!< triggered when the user deletes an actor, the argument refers to the actor ID - SE_TRUCK_RESET = 0x00200000, //!< triggered when the user resets the truck, the argument refers to the actor ID of the vehicle - SE_TRUCK_TELEPORT = 0x00400000, //!< triggered when the user teleports the truck, the argument refers to the actor ID of the vehicle - SE_TRUCK_MOUSE_GRAB = 0x00100000, //!< triggered when the user uses the mouse to interact with the actor, the argument refers to the actor ID + SE_TRUCK_RESET = BITMASK(15), //!< triggered when the user resets the truck, the argument refers to the actor ID of the vehicle + SE_TRUCK_TELEPORT = BITMASK(16), //!< triggered when the user teleports the truck, the argument refers to the actor ID of the vehicle + SE_TRUCK_MOUSE_GRAB = BITMASK(17), //!< triggered when the user uses the mouse to interact with the actor, the argument refers to the actor ID - SE_ANGELSCRIPT_MANIPULATIONS = 0x00800000, //!< triggered when the user tries to dynamically use the scripting capabilities (prevent cheating) + SE_ANGELSCRIPT_MANIPULATIONS = BITMASK(18), //!< triggered when the user tries to dynamically use the scripting capabilities (prevent cheating) - SE_GENERIC_MESSAGEBOX_CLICK = 0x01000000, //!< triggered when the user clicks on a message box button, the argument refers to the button pressed + SE_GENERIC_MESSAGEBOX_CLICK = BITMASK(19), //!< triggered when the user clicks on a message box button, the argument refers to the button pressed SE_ALL_EVENTS = 0xffffffff, diff --git a/source/main/physics/ActorForcesEuler.cpp b/source/main/physics/ActorForcesEuler.cpp index 3c52f17143..1591ca2175 100644 --- a/source/main/physics/ActorForcesEuler.cpp +++ b/source/main/physics/ActorForcesEuler.cpp @@ -35,6 +35,7 @@ #include "GameContext.h" #include "Replay.h" #include "ScrewProp.h" +#include "ScriptEngine.h" #include "SoundScriptManager.h" #include "Terrain.h" #include "Water.h" @@ -1671,10 +1672,19 @@ void Actor::CalcEventBoxes() if (do_callback) { App::GetGameContext()->GetTerrain()->GetCollisions()->envokeScriptCallback(cbox, &ar_nodes[i]); + + const eventsource_t& eventsource = App::GetGameContext()->GetTerrain()->GetCollisions()->getEventSource(cbox->eventsourcenum); + TRIGGER_EVENT_EX(SE_EVENTBOX_ENTER, 0, ar_vector_index, ar_nodes[i].pos, 0, eventsource.es_instance_name, eventsource.es_box_name, "", ""); } break; } } + + if (!has_collision) + { + const eventsource_t & eventsource = App::GetGameContext()->GetTerrain()->GetCollisions()->getEventSource(cbox->eventsourcenum); + TRIGGER_EVENT_EX(SE_EVENTBOX_EXIT, 0, ar_vector_index, 0, 0, eventsource.es_instance_name, eventsource.es_box_name, "", ""); + } } } } diff --git a/source/main/scripting/ScriptEngine.cpp b/source/main/scripting/ScriptEngine.cpp index 6005699de4..dae6eb2441 100644 --- a/source/main/scripting/ScriptEngine.cpp +++ b/source/main/scripting/ScriptEngine.cpp @@ -59,6 +59,7 @@ using namespace Ogre; using namespace RoR; +using namespace AngelScript; const char* RoR::ScriptCategoryToString(ScriptCategory c) { @@ -366,6 +367,11 @@ int ScriptEngine::addFunction(const String &arg) if (m_script_units[unitID].eventCallbackFunctionPtr == nullptr) m_script_units[unitID].eventCallbackFunctionPtr = func; } + else if (func == mod->GetFunctionByDecl("void eventCallbackEx(scriptEvents, int, int, int, int, string, string, string, string)")) + { + if (m_script_units[unitID].eventCallbackExFunctionPtr == nullptr) + m_script_units[unitID].eventCallbackExFunctionPtr = func; + } else if (func == mod->GetFunctionByDecl("void defaultEventCallback(int, string, string, int)")) { if (m_script_units[unitID].defaultEventCallbackFunctionPtr == nullptr) @@ -442,6 +448,9 @@ int ScriptEngine::deleteFunction(const String &arg) if ( m_script_units[m_terrain_script_unit].eventCallbackFunctionPtr == func ) m_script_units[m_terrain_script_unit].eventCallbackFunctionPtr = nullptr; + if (m_script_units[m_terrain_script_unit].eventCallbackExFunctionPtr == func) + m_script_units[m_terrain_script_unit].eventCallbackExFunctionPtr = nullptr; + if ( m_script_units[m_terrain_script_unit].defaultEventCallbackFunctionPtr == func ) m_script_units[m_terrain_script_unit].defaultEventCallbackFunctionPtr = nullptr; @@ -507,23 +516,38 @@ int ScriptEngine::deleteVariable(const String &arg) return index; } -void ScriptEngine::triggerEvent(int eventnum, int value) +void ScriptEngine::triggerEvent(scriptEvents eventnum, int arg1, int arg2ex, int arg3ex, int arg4ex, std::string arg5ex, std::string arg6ex, std::string arg7ex, std::string arg8ex) { if (!engine || !context) return; for (auto& pair: m_script_units) { ScriptUnitId_t id = pair.first; - if (m_script_units[id].eventCallbackFunctionPtr==nullptr) + asIScriptFunction* callback = m_script_units[id].eventCallbackExFunctionPtr; + if (!callback) + callback = m_script_units[id].eventCallbackFunctionPtr; + if (!callback) continue; + if (m_script_units[id].eventMask & eventnum) { // script registered for that event, so sent it - context->Prepare(m_script_units[id].eventCallbackFunctionPtr); + context->Prepare(callback); // Set the function arguments context->SetArgDWord(0, eventnum); - context->SetArgDWord(1, value); + context->SetArgDWord(1, arg1); + if (callback == m_script_units[id].eventCallbackExFunctionPtr) + { + // Extended arguments + context->SetArgDWord(2, arg2ex); + context->SetArgDWord(3, arg3ex); + context->SetArgDWord(4, arg4ex); + context->SetArgObject(5, &arg5ex); + context->SetArgObject(6, &arg6ex); + context->SetArgObject(7, &arg7ex); + context->SetArgObject(8, &arg8ex); + } m_currently_executing_script_unit = id; int r = context->Execute(); @@ -641,6 +665,7 @@ int ScriptEngine::setupScriptUnit(int unit_id) m_script_units[unit_id].frameStepFunctionPtr = m_script_units[unit_id].scriptModule->GetFunctionByDecl("void frameStep(float)"); m_script_units[unit_id].eventCallbackFunctionPtr = m_script_units[unit_id].scriptModule->GetFunctionByDecl("void eventCallback(int, int)"); + m_script_units[unit_id].eventCallbackExFunctionPtr = m_script_units[unit_id].scriptModule->GetFunctionByDecl("void eventCallbackEx(scriptEvents, int, int, int, int, string, string, string, string)"); m_script_units[unit_id].defaultEventCallbackFunctionPtr = m_script_units[unit_id].scriptModule->GetFunctionByDecl("void defaultEventCallback(int, string, string, int)"); diff --git a/source/main/scripting/ScriptEngine.h b/source/main/scripting/ScriptEngine.h index 4aef471ae0..c822412026 100644 --- a/source/main/scripting/ScriptEngine.h +++ b/source/main/scripting/ScriptEngine.h @@ -27,8 +27,12 @@ #ifdef USE_ANGELSCRIPT +/// Invoke script function `eventCallbackEx()`, if registered, otherwise fall back to `eventCallback()` #define TRIGGER_EVENT(x, y) App::GetScriptEngine()->triggerEvent((x), (y)) +/// Invoke script function `eventCallbackEx()`, if registered, otherwise fall back to `eventCallback()` +#define TRIGGER_EVENT_EX(ev, a1, a2, a3, a4, a5, a6, a7, a8) App::GetScriptEngine()->triggerEvent((ev), (a1), (a2), (a3), (a4), (a5), (a6), (a7), (a8)) + #define DEFAULT_TERRAIN_SCRIPT "terrain_default.as" // Used when map creator doesn't provide custom script. #define DEFAULT_MISSION_SCRIPT "mission_default.as" // Used when mission creator doesn't provide custom script. @@ -71,6 +75,7 @@ struct ScriptUnit AngelScript::asIScriptModule* scriptModule = nullptr; AngelScript::asIScriptFunction* frameStepFunctionPtr = nullptr; //!< script function pointer to the frameStep function AngelScript::asIScriptFunction* eventCallbackFunctionPtr = nullptr; //!< script function pointer to the event callback function + AngelScript::asIScriptFunction* eventCallbackExFunctionPtr = nullptr; //!< script function pointer to the event callback function AngelScript::asIScriptFunction* defaultEventCallbackFunctionPtr = nullptr; //!< script function pointer for spawner events AngelScript::asIScriptFunction* loadMissionFunctionPtr = nullptr; //!< only `ScriptCategory::MISSION`, called to set up the mission. AngelScript::asIScriptFunction* unloadMissionFunctionPtr = nullptr; //!< only `ScriptCategory::MISSION`, called to clean up the mission. @@ -119,10 +124,10 @@ class ScriptEngine : public Ogre::LogListener, public ZeroedMemoryAllocator void activateLogging(); /** - * triggers an event. Not to be used by the end-user - * @param eventValue \see enum scriptEvents + * triggers an event; Not to be used by the end-user. + * Runs either `eventCallbackEx()`, if registered, or `eventCallback()`, if registered, in this order. */ - void triggerEvent(int scriptEvents, int value = 0); + void triggerEvent(scriptEvents eventnum, int arg1, int arg2ex=0, int arg3ex=0, int arg4ex=0, std::string arg5ex="", std::string arg6ex="", std::string arg7ex="", std::string arg8ex=""); /** * executes a string (useful for the console) @@ -227,4 +232,5 @@ class ScriptEngine : public Ogre::LogListener, public ZeroedMemoryAllocator #else // USE_ANGELSCRIPT # define TRIGGER_EVENT(x, y) +# define TRIGGER_EVENT_EX(ev, a1, a2, a3, a4, a5, a6, a7, a8) #endif // USE_ANGELSCRIPT diff --git a/source/main/scripting/bindings/ScriptEventsAngelscript.cpp b/source/main/scripting/bindings/ScriptEventsAngelscript.cpp index 0ebe4835fc..5150133e5f 100644 --- a/source/main/scripting/bindings/ScriptEventsAngelscript.cpp +++ b/source/main/scripting/bindings/ScriptEventsAngelscript.cpp @@ -32,6 +32,10 @@ void RoR::RegisterScriptEvents(asIScriptEngine *engine) // enum scriptEvents result = engine->RegisterEnum("scriptEvents"); ROR_ASSERT(result>=0); + + result = engine->RegisterEnumValue("scriptEvents", "SE_EVENTBOX_ENTER", SE_EVENTBOX_ENTER); ROR_ASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_EVENTBOX_EXIT", SE_EVENTBOX_EXIT); ROR_ASSERT(result >= 0); + result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_ENTER", SE_TRUCK_ENTER); ROR_ASSERT(result>=0); result = engine->RegisterEnumValue("scriptEvents", "SE_TRUCK_EXIT", SE_TRUCK_EXIT); ROR_ASSERT(result>=0);