.. _implementPlayerExtension: =================================== How to Implement a Player Extension =================================== Player extensions are main ways of handling input in Limon Engine. Input from player is first handled by PhysicalPlayer class, which governs look around and movement, then all input information is passed to selected extension, so it can handle custom interactions, like pickups, shooting etc. On the other side, any interaction send by other entities to player is directly passed to player extension for handling. Player extensions follow the :ref:`unified parameter contract `. Like Triggers, the base class holds the values on a protected ``parameters`` member: you seed any default parameters into that member in the **constructor**, the base ``getParameters() const`` returns it, and ``setParameters()`` overwrites it when the designer edits values or a map is loaded. The configured values are persisted with the map and editable in the editor. An extension with no configurable settings simply seeds nothing and the member stays empty. PlayerExtensionInterface Class ______________________________ .. list-table:: :widths: 20 80 * - - :ref:`PlayerExtensionInterface(LimonAPI *limonAPI)` * - ``void`` - :ref:`processInput(const InputStates &inputState, const PlayerInformation &playerInformation, long time)` * - ``void`` - :ref:`interact(std::vector\ ¶meters)` * - ``std::vector`` - :ref:`getParameters() const` * - ``void`` - :ref:`setParameters(std::vector\parameters)` * - ``std::string`` - :ref:`getName() const` .. _PlayerExtensionInterface-PlayerExtensionInterface: PlayerExtensionInterface(LimonAPI \*limonAPI) ============================================= The constructor of the interface. If the extension exposes editor-configurable settings, this is where it seeds their **defaults**: build each ``LimonTypes::GenericParameter`` descriptor and ``push_back`` it onto the protected ``this->parameters`` member. .. note:: All Player Extension must have the same signature, no other parameters should be required. .. _PlayerExtensionInterface-processInput: void processInput(const InputStates &inputState, const PlayerInformation &playerInformation, long time) ======================================================================================================== Called each frame with updated input information, current player state, and the frame time in milliseconds. Parameters: #. const InputStates &inputState: Current input state for this frame. #. const PlayerInformation &playerInformation: Current player position and look direction. See :ref:`PlayerInformation struct` below. #. long time: Frame time in milliseconds. .. _PlayerExtensionInterface-interact: void interact(std::vector &interactionData) ========================================================================= Called by other entities to interact with player. .. _PlayerExtensionInterface-getParameters: std::vector getParameters() const =============================================================== Returns the configurable parameters of this extension. These are rendered by the editor under the selected extension and persisted with the map. The base implementation returns the instance's protected ``parameters`` member - the defaults you seeded in the constructor, or the configured values after an edit or load - so you normally do not override it. Override only to expose typed members as descriptors (Actor-style). An empty member means the extension has no editor-exposed configuration. .. _PlayerExtensionInterface-setParameters: void setParameters(std::vectorparameters) ======================================================================= Stores the configured parameter values on the extension instance. Called when the map designer edits values in the editor and when a map is loaded. The base implementation keeps the values in the protected ``parameters`` member - the single source of truth for load, serialize, and editor edits. Override only if the extension needs to react to value changes. .. _PlayerExtensionInterface-getName: std::string getName() const =========================== Returns the name of the Player Extension. .. warning:: The name must be unique, or the results will be undefined. .. note:: To drive the camera from a player extension, activate a :ref:`camera rig ` at runtime with ``createCameraRig`` / ``activateCameraRig`` (for example from ``processInput``). The old ``getCustomCameraAttachment`` mechanism has been removed. .. _PlayerExtensionInterface-PlayerInformation: PlayerInformation struct ________________________ Passed to :ref:`processInput ` each frame. +-----------------------------+------------------------+---------------------------------------------------+ | Type | Name | Description | +-----------------------------+------------------------+---------------------------------------------------+ | LimonTypes::Vec4 | position | Current world-space position of the player. | +-----------------------------+------------------------+---------------------------------------------------+ | LimonTypes::Vec4 | lookDirection | Normalized direction the player is looking at. | | | | w component unused. | +-----------------------------+------------------------+---------------------------------------------------+ .. _ActorInterface-InputStatesUsage: InputStates Class Usage _______________________ Input is queried through ``InputStates`` using hash-keyed action names. Any binding — keyboard, mouse, or gamepad — maps to the same logical action, so plugin code never needs to know which physical key is pressed. See :ref:`InputSystem` for the full API reference, the built-in action name table, how to define custom game actions in XML, and how to detect which input device the player is using. .. _PlayerExtensionInterface-enableDynamicDiscovery: How to enable Dynamic Library discovery _______________________________________ Limon engine will try to load custom player extensions on engine startup, from libcustomTriggers file (extension based on platform). If the file is found, engine will check for a method with following signature: :: void registerPlayerExtensions(std::map* playerExtensionMap) This method should fill the actorMap passed, with all the custom actors, like this: :: (*playerExtensionMap)["$EXTENSION_NAME1$"] = &createPlayerExtension<$ExtensionClass1$>; (*playerExtensionMap)["$EXTENSION_NAME2$"] = &createPlayerExtension<$ExtensionClass2$>; .. note:: Every registered extension name is available through the static ``PlayerExtensionInterface::getExtensionNames()`` (Python: ``get_extension_names()``). The editor uses this list to present the launch-time extension as a drop-down in Player Properties, so the registered name you use here is the one a map designer will pick from. See :ref:`UsingBuiltinEditor`. .. note:: ``getExtensionNames()`` was previously named ``getTriggerNames()``. It returns registered player-extension names, not trigger names; the old name was a misnomer and has been corrected. .. _PlayerExtensionInterface-samples: Sample Player Extensions ________________________ The engine ships with sample player extensions under ``samples/`` that implement ``PlayerExtensionInterface``: * `ShooterPlayerExtension `_ - a first-person shooter player controller. * `CowboyShooterExtension `_ - the western-demo shooter controller, which also activates a third-person :ref:`camera rig ` at runtime (``createCameraRig`` / ``activateCameraRig``). * `WesternMenuPlayerExtension `_ - a menu controller using absolute mouse input for the western demo's menus. A Python player-extension sample ships under ``Engine/Scripts/`` as `python_player_extension.py `_ (the ``PythonPlayerExtension`` class), subclassing the Python base in `player_extension_interface.py `_.