じ☆ve冰风 发表于 2026-7-28 14:12:39

Event Manager

This is a javascript plugin that will not do anything on it's own, but can be useful for other scripters. This script essentially implements an observer pattern into RPG Maker. Event systems help modularize your code by sending messages between pieces of code that do not directly know about each other. They allow things to respond to a change in a state without constantly monitoring it in an update loop. You can read more about it here:
Observer pattern - Wikipedia



https://en.wikipedia.org/static/favicon/wikipedia.ico                                        en.wikipedia.org                               




This script hasn't been fully optimized and I'm sure there are some things that may not be fully standardized with RPG Makers coding style. It was made in a couple of hours. On every triple a project I've worked on so far, each engine has had one of these, so I wanted to make my own for my internal project. Hopefully this comes in handy for you!

This was made with RPG Maker MV in mind. I have not tested this with RPG Maker MZ, but I don't see much of a reason why this wouldn't work with MZ as well.

I made a small project with a couple of use-case examples! Nothing mind-blowing, but hopefully will provide you with a few ideas to get some ideas across for how it can be used! You can find that project here.

Terms of Use: Free to use or modify for free or commercial projects. My only request is that you don't republish this (or your edits) and claim it as your own. If you want to give credit (not required), please give to Nathan Pringle and specify it was this script in particular.

                JavaScript:       
//=============================================================================
// EventManager
// by Nathan Pringle
// Date: 2021-10-11
//=============================================================================
/*:
* @plugindesc Adds event support for internal scripts.
* @author Nathan Pringle
*
* @help
* -----------------------------------------------------------------------------
* Event systems help modularize your code by sending messages between pieces of
* code that do not directly know about each other. They allow things to respond
* to a change in a state without constantly monitoring it in an update loop. This is
* generally known as an "Observer pattern". You can read more about it here:
* https://en.wikipedia.org/wiki/Observer_pattern
*
* Usage: Free to use or modify for free or commercial projects. My only request
* is that you don't republish this (or your edits) and claim it as your own. If
* you want to give credit (not required), please give to Nathan Pringle and
* specify it was this script in particular.
*
* -----------------------------------------------------------------------------
* Methods Available:
* -----------------------------------------------------------------------------
* EventManager.StartListening ( string eventName, string methodName, method callbackMethod )
*
* string eventName: The event you want to listen to. When this event is invoked, the callbackMethod will be called.
* string methodName: The string name of the method. This is simply used for lookup. When you stop listening, you will need to provide this string again.
* method methodCallback: The method to call when the event is invoked.
*
* -----------------------------------------------------------------------------
* EventManager.StopListening ( string eventName, string methodName )
*
* string eventName: The name of the event to stop listening to.
* string methodName: The string name of the method. This is the same methodName that you used to start listening.
*
* -----------------------------------------------------------------------------
* EventManager.Invoke ( string eventName )
*
* string eventName: This will call the event. Will call all methods that are listening for this event.
*
* -----------------------------------------------------------------------------
* EventManager.InvokeWithParameter ( string eventName, var parameter )
*
* string eventName: This will call the event. Will call all methods that are listening for this event.
* var parameter: Will pass a single parameter to all methods being invoked.
*
* -----------------------------------------------------------------------------
* EventManager.InvokeAfterTime ( string eventName, float time )
*
* string eventName: same as above.
* float time: how long it will take to call this event, in seconds
*
* -----------------------------------------------------------------------------
* EventManager.InvokeWhenConditionIsTrue ( string eventName, method condition )
*
* string eventName: same as above.
* method condition: a method that should only return true or false. Will be checked every frame. When the condition returns true, the event will be invoked once.
*
*/

NP_EventManager_DataManager_createGameObjects = DataManager.createGameObjects;
DataManager.createGameObjects = function() {
    NP_EventManager_DataManager_createGameObjects.call(this);
    EventManager.setup();
};

NP_EventManager_Graphics_render = Graphics.render;
Graphics.render = function(stage) {
    NP_EventManager_Graphics_render.call(this, stage);
    EventManager.Tick();
}

function EventManager() {
    throw new Error('This is a static class');
}

/// Summary: Sets up the EventManager. Should only be called once.
/// Returns: N/A
EventManager.setup = function() {
    if (!this._isSetup) {
      this._isSetup = true;
      this._eventDictionary = [];
      this._eventsToCallAfterTime = [];
      this._eventsToCallWhenCondition = [];
      this._tickTime = 1.0 / 60.0;
    }
};

/// Summary: This will call the event. Will call all methods that are listening for this event.
/// Argument - eventName: The name of the event to invoke.
/// Returns: N/A
EventManager.Invoke = function(eventName) {
    var eventExists = false;
    var eventIndex = -1;
    for (var i = 0; i < this._eventDictionary.length && !eventExists; ++i) {
      var eventEntry = this._eventDictionary;
      if (eventEntry.eventName == eventName) {
            eventExists = true;
            eventIndex = i;
      }
    }


    if (eventExists) {
      var eventDetails = this._eventDictionary;
      for (var i = 0; i < eventDetails["methods"].length; ++i) {
            eventDetails["methods"]["methodCallback"].call(this);
      }
    }
}

/// Summary: This will call the event, but also pass a single parameter to all methods being invoked. Will call all methods that are listening for this event.
/// Argument - eventName: The name of the event to invoke.
/// Argument - parameter: The data to pass to the methods.
/// Returns: N/A
EventManager.InvokeWithParameter = function (eventName, parameter) {
    var eventExists = false;
    var eventIndex = -1;
    for (var i = 0; i < this._eventDictionary.length && !eventExists; ++i) {
      var eventEntry = this._eventDictionary;
      if (eventEntry.eventName == eventName) {
            eventExists = true;
            eventIndex = i;
      }
    }

    if (eventExists) {
      var eventDetails = this._eventDictionary;
      for (var i = 0; i < eventDetails["methods"].length; ++i) {
            eventDetails["methods"]["methodCallback"].call(this, parameter);
      }
    }
}

/// Summary: This will call the event as invoke, but will do so after a certain amount of time.
/// Argument - eventName: The name of the event to invoke.
/// Argument - time: The amount of time in seconds.
/// Returns: N/A
EventManager.InvokeAfterTime = function (eventName, time) {
    var entry = {};
    entry["eventName"] = eventName;
    entry["time"] = time;
    this._eventsToCallAfterTime.push(entry);
}

/// Summary: This will call the event as invoke, but will do so only when a certain condition is true.
/// Argument - eventName: The name of the event to invoke.
/// Argument - condition: a method that should return either true or false. It will be checked every frame. When it returns true, the event will be invoked. Will only be invoked once.
/// Returns: N/A
EventManager.InvokeWhenConditionIsTrue = function (eventName, condition) {
    var result = condition.call(this);

    var entry = {};
    entry["eventName"] = eventName;
    entry["condition"] = condition;
    this._eventsToCallWhenCondition.push(entry);
}

/// Summary: A single tick. Should not be called outside of Window.update
/// Returns: N/A
EventManager.Tick = function() {
    for (var i = 0; i < this._eventsToCallAfterTime.length; ++i) {
      this._eventsToCallAfterTime["time"] -= this._tickTime;

      if (this._eventsToCallAfterTime["time"] <= 0.0) {
            EventManager.Invoke(this._eventsToCallAfterTime["eventName"]);
            this._eventsToCallAfterTime.splice(i, 1);
            --i;
      }
    }

    for (var i = 0; i < this._eventsToCallWhenCondition.length; ++i) {
      var result = this._eventsToCallWhenCondition["condition"].call(this);
      if (result == true) {
            var eventName = this._eventsToCallWhenCondition["eventName"];
            this._eventsToCallWhenCondition.splice(i, 1);
            --i;
            EventManager.Invoke(eventName);
      }
    }
}

/// Summary: Starts listening for a specific event. When a piece of code calls the invoke method, this method will be called.
/// Argument - eventName: The name of the event to listen to.
/// Argument - methodName: The string name of the method. This is simply used for lookup. When you stop listening, you will need to provide this string again.
/// Argument - methodCallback: The method to call when the event is invoked.
/// Returns: N/A
EventManager.StartListening = function(eventName, methodName, methodCallback) {
    var eventExists = false;
    var eventIndex = -1;
    for (var i = 0; i < this._eventDictionary.length && !eventExists; ++i) {
      var eventEntry = this._eventDictionary;
      if (eventEntry.eventName == eventName) {
            eventExists = true;
            eventIndex = i;
      }
    }

    if (!eventExists) {
      eventIndex = this._eventDictionary.length;
      var entry = {};
      entry["eventName"] = eventName;
      entry["methods"] = [];
      this._eventDictionary.push(entry);
    }

    for (var i = 0; i < this._eventDictionary["methods"].length; ++i) {
      if (this._eventDictionary["methods"]["methodName"] == methodName) {
            throw new Error('Trying to add a method that already exists.');
      }
    }

    var methodEntry = {};
    methodEntry["methodName"] = methodName;
    methodEntry["methodCallback"] = methodCallback = methodCallback;
    this._eventDictionary["methods"].push(methodEntry);
}

/// Summary: Stops listening for a specific event. The method will no longer be called when the event is invoked.
/// Argument - eventName: The name of the event to stop listening to.
/// Argument - methodName: The string name of the method. This is the same methodName that you used to start listening.
/// Returns: N/A
EventManager.StopListening = function(eventName, methodName) {
    var eventExists = false;
    var eventIndex = -1;
    for (var i = 0; i < this._eventDictionary.length && !eventExists; ++i) {
      var eventEntry = this._eventDictionary;
      if (eventEntry.eventName == eventName) {
            eventExists = true;
            eventIndex = i;
      }
    }

    if (!eventExists) {
      throw new Error('Trying to remove a method that does not exist.');
    }

    var methodsArrayLength = this._eventDictionary["methods"].length;
    var methodIndex = -1;
    for (var i = 0; i < this._eventDictionary["methods"].length && methodIndex == -1; ++i) {
      if (this._eventDictionary["methods"]["methodName"] == methodName) {
            methodIndex = i;
      }
    }

    if (methodIndex == -1) {
      throw new Error('Trying to remove a method that does not exist.');
    }

    if (methodsArrayLength == 1) {
      this._eventDictionary.splice(eventIndex, 1);
    }
    else {
      this._eventDictionary["methods"].splice(methodIndex, 1);
    }
}




本贴来自国际rpgmaker官方论坛作者:nathanlink169处,因国际论坛即将永久关站,为了存档多年珍贵资料,署名转载到本论坛存档,由于官方帖子为英文原帖,需要中文翻译请点击论坛顶部切换语言为中文就可以将帖子翻译成中文浏览,方便大家随时查看,原文地址:https://forums.rpgmakerweb.com/threads/event-manager.141246/
页: [1]
查看完整版本: Event Manager