JavaScript questions that don't deserve their own thread

● ARCHIVED · READ-ONLY
Started by Shaz 3413 posts Page 133 of 171 View original ↗
  1. My understanding is that the template for patches is like this, but I could never fully grasp what the voidin the beginning is for.

    JavaScript:
    void (alias => {
        Function_To_Be_Patched = function() {
            alias.apply(this, arguments);
            /*Some code to be added*/;
        };
    })(Function_To_Be_Patched);
  2. werzaque said:
    My understanding is that the template for patches is like this
    I've never seen that syntax. It appears to be overly verbose.

    The method that sealion demonstrated is what's typically done in plugins because it does the same thing with less typing.

    werzaque said:
    I could never fully grasp what the voidin the beginning is for.
    void would make the function have no return value, which I should think would break functions that are intended to return something.
  3. ATT_Turan said:
    void would make the function have no return value, which I should think would break functions that are intended to return something.
    Void only applied to the outer function that does the aliasing, not the aliased function - this syntax works perfectly fine for aliasing functions with return values too.
    And I guess the advantage is that you're not creating any new variables in the outer scope, so you can just plop this snippet into the global scope without polluting it.
  4. Yea, that's the structure I usually use for patches: like Mac says, it's harder to mess up, thus ideal for sharing with users who aren't familiar with JS. I think it's also nice to have alias be the same name in all cases!

    I use void as extra fluff to signify that the IIFE-for-local-scope is not meant to return a value. Likewise, for optional features:
    JavaScript:
    void (() => { if (!isEnabled) return;
      const alias = method;  // store reference to existing method in memory
      method = function() {  // create new function in memory and replace method with that
        return alias.apply(this, arguments) - 1;
      };
    })();
    The important part is to define the alias either as:
    • A local variable inside an appropriate function, e.g. an IIFE, or
    • A member of your plugin namespace - optional; a global variable/object on which you define everything public related to your plugin.
    Otherwise, like Mac says, you get global scope pollution, which means bad things can happen if another plugin tries to create a global variable with the same name. :kaoback:
  5. I feel like a Greek peasant eavesdropping on Gods talking. Wonderful!

    And yes, I have been able to successfully patch things on my own using @caethyril 's structure, so it's very easy to use for me. Many, many thanks for this.

    caethyril said:
    I use void as extra fluff to signify that the IIFE-for-local-scope is not meant to return a value.
    So... there will be no consequences if it was left out?
  6. @caethyril doesn't that create problems if someone else needs to modify it, though?

    I seem to recall instances where people wanted to change or add onto plugin functionality and trying to refer to/override the functions didn't work because they were wrapped in an IIFE so the code can't be externally referenced.

    That's why I prefer adding a definition to the window namespace.

    (feel free to tell me if I am completely misremembering)
  7. werzaque said:
    So... there will be no consequences if it was left out?
    Correct! Although omitting it does allow for situations like this:
    JavaScript:
    (() => { console.log("IIFE 1"); })()
    (() => { console.log("IIFE 2"); })()
    Without semi-colons at the end of each IIFE, the engine has to guess where to put them. And in this case, it guesses wrong, yielding "intermediate value is not a function". Because it sees the second line as function arguments for the first line. With void at the start of each line, no error occurs. :kaohi:

    ATT_Turan said:
    I seem to recall instances where people wanted to change or add onto plugin functionality and trying to refer to/override the functions didn't work because they were wrapped in an IIFE so the code can't be externally referenced.
    As-is, yes. For a "proper" plugin, you'd want to define any public data as:
    caethyril said:
    A member of your plugin namespace - optional; a global variable/object on which you define everything public related to your plugin.
    I just don't bother with that when it comes to small snipppets. :kaoswt:

    The global scope is still accessible from within the IIFE, and you can define new globals by referencing the global object explicitly (window or globalThis), e.g.
    JavaScript:
    void (() => {
      const $ = window.myNamespace || (window.myNamespace = {});
      $.apple = "tasty";
    })();
    void (() => {
      const alias = myNamespace.alias_Game_Player_realMoveSpeed
                  = Game_Player.prototype.realMoveSpeed;
      Game_Player.prototype.realMoveSpeed = function() {
        return alias.apply(this, arguments) - 1;
      };
    })();
    console.log(myNamespace);

    Edit: for my "full" plugins, I typically nest the namespaces: I have one global variable, CAE, which has one property per plugin. Each of those properties serves as a namespace for the respective plugin.
  8. @caethyril Maybe I just misunderstand. If you're defining your own namespace, and any functions/variables you use in the plugin are properties of that namespace, what's the purpose/benefit of further wrapping them in an IIFE? Aren't they already not "cluttering the global namespace"?

    I don't wish to derail the topic, though.
  9. @ATT_Turan - if you exclusively use stuff on the public namespace, yes. And that's a perfectly valid way of doing things! :kaohi:

    In my case, I prefer (immediately-invoked) functions partly because they let me define local abbreviations, e.g. alias and $ from my examples. I find it makes things easier to maintain, read, and search through.

    Here's a thread on pros and cons, it's pretty much a code style choice:
  10. ATT_Turan said:
    I seem to recall instances where people wanted to change or add onto plugin functionality and trying to refer to/override the functions didn't work because they were wrapped in an IIFE so the code can't be externally referenced.
    Not an authority on this and I remember there being more in depth discussions about this but cannot find them again right now (Edit: thanks caethyril :)).

    I would say in the case of alias functions you can kind of work around that restriction by splitting any patch into two and creating your own aliases first if worst comes to worst, plus aliases should at least in theory reduce the chance that a manual merge becomes necessary in the first place.

    Also when it comes to name spaces, you should make sure to put at least your new classes in the global namespace when you want their objects to be compatible with the save file system.
  11. I've been pretty much making super long word salad names for consts so that ending up with the same name twice would be very unlikely. Annoying to type, but they only get called once so idk.
    Code:
    const Game_Battler_Battle_Master_Plugin_Init_Members = Game_Battler.prototype.initMembers;
    const Game_Battler_Battle_Master_Plugin_Remove_State = Game_Battler.prototype.removeState;
    const Game_Battler_Battle_Master_Plugin_Use_Item = Game_Battler.prototype.useItem;
    I did notice, that you don't need to have them right on top of the code. Just somewhere before, so sometimes I group them all to the top instead of between every function im using it on. But using const, does seem to be a bit tidier method?
  12. I need help getting the property of a parent object from a child event. Basically ChronoEngine creates a Game_Battler object from a Game_Event object and while I can get the battle properties of an (enemy) event on the map, I can't do the reverse (gets its map event id from the battler object). I need the map event object, or its event id so I can do things like slow the enemy map event down when the battler has the slow battle state applied.

    Game Event:
    $gameMap.allEnemiesOnMap()[0]

    Game Battler:
    $gameMap.allEnemiesOnMap()[0]._user.battler
  13. There is no general way in JavaScript to find what other objects that reference a given object. Usually when you want to do that you'll just set a 'parent' property on the child when creating it, which luckily seems to be fairly simple here. Inside that if statement you've highlighted, after the battler is created, simply add this._user.battler.parent = this;, which will allow you to reference it more easily.

    Alternatively, use the current event's Id instead of this, in case the above leads to any issues with saving the game.
  14. Mac15001900 said:
    Inside that if statement you've highlighted, after the battler is created, simply add this._user.battler.parent = this;, which will allow you to reference it more easily.

    Alternatively, use the current event's Id instead of this, in case the above leads to any issues with saving the game.
    Simple solution but passing down the property works. Thank you very much
    Code:
    this._user.battler._eventId = this._eventId
  15. What is the best way to allow plugin interactions?

    If I declare a function in the plugin code outside the IIFE can it access that plugin functions?
    Or can I declare a function on a global scope variable?

    I've two very different plugins that can work stand alone but have option to enter in combo. For now they simply interact with content saved in the RpgMaker savecontent but now I need that one plugin calls the other plugin function, is it possible?
  16. Winthorp said:
    What is the best way to allow plugin interactions?
    I'm not sure this question doesn't deserve a thread. It's unlikely to get a one-post answer.

    There was a discussion just a page back about IIFE, declaring functions to be methods of a window object, etc. including a link to discussion threads.

    If none of that helps answer your question, you may want to post the question separately.

    For myself, I don't use IIFEs, I declare all of my stuff as properties of my own window object so I can simply call TUR.WhateverFunction() from within the project or any other plugin.
  17. My bad, I totally missed that discussion, I'll have a read, thanks!
  18. If I'm making a legit plugin, I always declare everything inside a global Athran.PluginAbbreviation object. Generally, I only use IIFE's for tiny plugins that only patch a function or two.
  19. Good night. I need help with this script:

    JavaScript:
    window.open ("ab.html","Celular","menubar=0,resizable=0,width=400,height=650,left=200,top=200")

    I am using this script in my game so that the player can open an html file in a window during the game.
    It works as I want, the problem is that even though I set resizable=0 the window can still be resized. I need the window to not be resized.
    Could you help me, please?

    I have tried with "resizable=no" but it doesn't work.
    The strange thing is that a couple of hours ago "resizable=0" was working
  20. @Orugario - the built-in window.open method recognises a limited set of options, and resizable is not one of those.

    For standalone deployments, you can use the NWJS nw.Window.open method instead, which amongst other things recognises a boolean resizable option, e.g.
    JavaScript:
    if (Utils.isNwjs()) {
      nw.Window.open("https://www.example.com/", { resizable: false });
    } else {
      window.open("https://www.example.com/");
    }