Events - morcSkyrim/SkyrimSE GitHub Wiki

Events

Documentation on the creation of events, the different types of events, how to set handles etc. Existing examples include Ryan's Skywind, which has handles for UIEvents, and QuickLoot's main function has an pretty simple example of a keyListener.

Types of Events

From a quick search of the commonlib files we have

  1. InputEvent - Pretty self explanatory, pertains to user input, things like keyboard, mouse commands etc. Children:
  • IDEvent Children:
    • ButtonEvent
    • KineticEvent
    • MouseMoveEvent
    • ThumbstickEvent

Event Sinks

An event sink is essentially a function which is used to handle an event. In the case of skyrim, this involves an object of type BSTEventSink, where EventType specifies the type of Event. The BSTEventSink is extremely simple,

template <class Event>
	class BSTEventSink
	{
	public:
		virtual ~BSTEventSink() = default;																			// 00
		virtual BSEventNotifyControl ProcessEvent(const Event* a_event, BSTEventSource<Event>* a_eventSource) = 0;	// 01
	};
	static_assert(sizeof(BSTEventSink<void>) == 0x8);

with its only member functions being its destructor, and the ProcessEvent, which will specify the function that gets called during the event. The only job that our custom event sink must provide is the ProcessEvent function.

Event Sink Registration

Every event sink must be registered with the associated event source, such that it can be called when an event occurs. To the best of my knowledge this occurs exclusively through the BSTEventSource virtual class interface, which has the following functions

void AddEventSink(Sink* a_eventSink) {
  ....
}
void RemoveEventSink(Sink* a_eventSink) {
  ....
}
void SendEvent(const Event* a_event) {
  ....
}

This allows us to easily identify all the different header files defining event sources in CommonLib,

  1. BeamProjectile.h
  2. BGSFootstepManager.h
  3. BGSMoviePlayer.h
  4. BGSSaveLoadManager.h
  5. BGSStoryTeller.h
  6. bhkCharacterController.h
  7. BSAnimationGraphManager.h
  8. BSGamepadDevice.h
  9. BShkbAnimationGraph.h
  10. BSInputDeviceManager.h
  11. BSSaveDataSystemUtility.h
  12. ControlMap.h
  13. ErrorLogger.h
  14. PlayerCharacter.h: 3 event declarations
  15. ScriptEventSourceHolder.h: 53 events source declarations
  16. SkyrimVM.h
  17. UI : 3 sub declarations
  18. VirtualMachine.h

According to my search through commonlib, there are apparently a total of 74 unique event holders.

Putting it all Together

The procedure for setting up a new event listener goes something like

  1. Locate the appropriate event.
  2. Locate the appropriate event source.
  3. Program a class that inherits from the EventSink with your appropriate event type.
  4. Program the ProcessEvent function to handle the associated event.
  5. Register your new class with the appropriate event source using the AddEventSink function.
  6. Test
  7. Profit
Example

We would like to listen for key presses when in the inventory to provide some additional functionality to items. This leaves us with a few options for event types, InputEvent, ButtonEvent, and possibly MenuControls. Considering ButtonEvent derives from InputEvent, it's presumably an event that is specific to buttonpresses. Either should be appropriate in this case, though ButtonEvent must be used if the information in its members is required.

⚠️ **GitHub.com Fallback** ⚠️