Caethyril's MZ Plugins

● ARCHIVED · READ-ONLY
Started by caethyril 209 posts Page 9 of 11 View original ↗
  1. @Niniann - oh, I see. Yea, unfortunately it's difficult to help without knowing precisely where VisuStella applies those tag effects. You could try manually calculating the default calcElementRate:
    JavaScript:
    // rmmz_objects, Game_Action.prototype.calcElementRate
    const eId  = this.item().damage.elementId;
    const rate = eId < 0 ?
        this.elementsMaxRate(target, this.subject().attackElements()) :
        target.elementRate(eId);
    // Is it more than 100%?
    return rate > 1;
    Otherwise, someone familiar with VisuStella might know of a solution.
  2. caethyril said:
    @Niniann - oh, I see. Yea, unfortunately it's difficult to help without knowing precisely where VisuStella applies those tag effects. You could try manually calculating the default calcElementRate:
    JavaScript:
    // rmmz_objects, Game_Action.prototype.calcElementRate
    const eId  = this.item().damage.elementId;
    const rate = eId < 0 ?
        this.elementsMaxRate(target, this.subject().attackElements()) :
        target.elementRate(eId);
    // Is it more than 100%?
    return rate > 1;
    Otherwise, someone familiar with VisuStella might know of a solution.
    caethyril,

    Thank you for the post! I just figured out a solution in part thanks to your post here; I realized I had some typos in my code and that's why it wasn't working, hehe.

    So what I ended up doing is this:

    if (this.item().damage.elementId == 3 && target.elementRate(3) > 1) {
    return true;
    } else {
    return false;
    }

    This will check the Element of the Skill and if the target has a weakness to that same Element. If true, show a weakness custom popup. Else, don't show any popup.

    I just create a different custom weakness popup for each Element type that checks for that Element. Since I've only a few Elements, this works perfectly. Perhaps not the most elegant solution, but a functional one nonetheless!

    Since the code is directly checking the Skill and the Enemy, instead of checking the final calculated Element Rate, this will correctly only show the popup when the Enemy is actually weak to the Element, and will not appear if Element damage is boosted through a State or Armor.

    Note: As a bonus, I could now have a different text color appear for the weakness popup depending on what Element the Enemy is weak too. Hmm...
  3. Hi @caethyril! Just wanted to pop by and say thank you for the slope move plugin! Literally a life saver!
  4. Thank you, for the Face to right plugin. Some people may think that isn't important. But it adds so much. I could never understand why it was removed after 2k3.
  5. Great work on the plugins; have been using them a lot to clean out spaghetti eventing in my project. Especially the OnUseEffects and MapEvents.

    I noticed through the 1.8.1 patch that the cancelMessageWait functionality gets lost in the updateMainMultply method and changed my local version like this to get it back.

    Code:
            // Override! Update map as many times as appropriate.
            void (mult => { if (mult === 2) return;
                Scene_Map.prototype.updateMainMultiply = function() {
                    this.updateMain();
                    if (this.isFastForward()) {
                        this.cancelMessageWait();
                        for (let n = mult; --n > 0;) this.updateMain();
                    }
                };
            })($.ffmult);
  6. @auradev - oh, thanks for pointing that out! Looks like cancelMessageWait was actually introduced in v1.8.0, I just forgot that would impact any of my plugins. :kaoslp:

    Cae_MapEvents has been updated to v1.1: it now uses a different patch when the cancelMessageWait method exists~ :kaohi:
  7. Puppet Knight said:
    So realized that i can just sorta.. cheat?

    ;void (alias => {
    CAE.OnUseEffects.canTarget = function(action, target) {
    const subject = action.subject();
    return eval(((subject.columnIndex - subject.range) <= target.columnIndex && target.columnIndex <= (subject.columnIndex + subject.range)));//}
    return alias.apply(this, arguments);
    };
    })(CAE.OnUseEffects.canTarget);

    My project has the skill targeting range dictated by the properties shown. So rather than even using a note tag at all, I can just enter the check directly into the hack you provided ^_^.

    Did some testing and I am good to go now !


    The original hack script actually gave me a good foundation to add in some extra checks where needed to override the eval I have set (which will basically be the fall back)


    So following up here on my patch needs. This ^ still works like gold. so no issues there. However I want to further extend this out to include some checks based on note tagging from my plugin that handles enemy positioning and row/column set up.


    The plugin i have set up includes the following alias to Game_Action.prototype.apply:
    Game_Action.prototype.apply aliasing
    // Alias Game_Action.prototype.apply to introduce the <strikeLine> effect
    const pkEnemy_Game_Action_apply = Game_Action.prototype.apply;
    Game_Action.prototype.apply = function(target) {
    // Apply to the initial target first (avoid double applying later)
    pkEnemy_Game_Action_apply.call(this, target);

    // Check if the skill has the <strikeLine> note tag
    if (this.item().meta.strikeLine) {
    const targetRow = target._row; // Get the row of the initial target

    // Get all other enemies in the same row, excluding the initial target
    const enemiesInSameRow = $gameTroop.aliveMembers().filter(enemy => enemy._row === targetRow && enemy !== target);

    // Apply the action to all other enemies in the same row
    enemiesInSameRow.forEach(enemy => {
    // Apply the action to the enemy
    pkEnemy_Game_Action_apply.call(this, enemy);

    // Check if the hit was successful
    if (enemy.result().isHit()) {
    // If the enemy was hit, trigger the damage motion
    enemy.requestMotion("damage");
    } else if (enemy.result().missed || enemy.result().evaded) {
    // If the attack missed or was evaded, trigger the evade motion
    enemy.requestMotion("evade");
    }

    // Show the damage popup for the enemy
    enemy.startDamagePopup();

    // Handle collapse if the enemy is dead
    if (enemy.isDead()) {
    enemy.performCollapse(); // Trigger the collapse animation if the enemy dies
    }
    });
    }
    };


    Which on its own does what it says on the tin. If an attack has <strikeLine> all enemies in the same row get hit by the attack. However if Cae_OnUseEffects is in play, only the originally targetted enemy is hit. I can make `CAE.OnUseEffects.canTarget` return true if the <strikeLine> notetag is present, but then that allows all enemies to be targetted, instead of just the ones that are meant to be.

    Any thoughts on this @caethyril ? Attaching my plugin for reference as well. (No rush or urgency, but your help would be awesome)
  8. @Puppet Knight - I don't see anything obvious, no. However...

    I feel like this would be more neatly handled by patching Game_Action#makeTargets instead, e.g.
    JavaScript:
    void (() => {
      const pkEnemy_Game_Action_makeTargets = Game_Action.prototype.makeTargets;
      Game_Action.prototype.makeTargets = function() {
        const res = pkEnemy_Game_Action_makeTargets.apply(this, arguments);
        const tgt = res[0];
        if (this.item().meta.strikeLine && tgt?.isEnemy())
          res.push(...$gameTroop.aliveMembers().filter(
            nme => nme !== tgt && nme._row === tgt._row
          ));
        return res;
      };
    })();
    (This is completely untested, I just based it on what you provided.)

    [Edit: corrected alias.apply to pkEnemy_Game_Action_makeTargets.apply.]
  9. caethyril said:
    @Puppet Knight - I don't see anything obvious, no. However...

    I feel like this would be more neatly handled by patching Game_Action#makeTargets instead, e.g.
    JavaScript:
    void (() => {
      const pkEnemy_Game_Action_makeTargets = Game_Action.prototype.makeTargets;
      Game_Action.prototype.makeTargets = function() {
        const res = alias.apply(this, arguments);
        const tgt = res[0];
        if (this.item().meta.strikeLine && tgt?.isEnemy())
          res.push(...$gameTroop.aliveMembers().filter(
            nme => nme !== tgt && nme._row === tgt._row
          ));
        return res;
      };
    })();
    (This is completely untested, I just based it on what you provided.)


    I think this was a step in the right direction, the animation is playing on both intended enemies now. I just have to figure out getting the damage to hit all the enemies it should be. Thanks Cae. Will update If I get more progress.

    so with some testing its a bit funky going the makeTargets route, the selected target is being hit, but no other enemy in the row is having the damage applied to them. If i further alias CAE.OnUseEffects.canTarget to create an exception for <strikeLine> I can damage the entire row, but that also makes it so that ANY enemy can be selected for the attack initially, which is also not ideal.



    The flow I'm looking for is:
    1. Action selected

    2. Targeting based on eval((subject.columnIndex - subject.range) <= target.columnIndex && target.columnIndex <= (subject.columnIndex + subject.range));

    3. Target Selected

    4. Action Applied to all enemies/actors in that row
  10. @Puppet Knight - I just ran a test (core script v1.8.1) with 2 plugins active, in this order:
    • Cae_OnUseEffects v1.7: unedited, no changes to default plugin param values.
    • The following test plugin:
      plugin code
      JavaScript:
      /*:
       * @target MZ
       * @plugindesc test
       * @author Caethyril
       * @url https://forums.rpgmakerweb.com/posts/1470712/
       * @help Free to use and/or modify for any project, no credit required.
       */
      ;void (() => {
          const alias = Game_Action.prototype.makeTargets;
          Game_Action.prototype.makeTargets = function() {
              const res = alias.apply(this, arguments);
              const tgt = res[0];
              if (this.item().meta.strikeId && tgt?.isEnemy())
                  res.push(...$gameTroop.aliveMembers().filter(
                      nme => nme !== tgt && nme.enemyId() === tgt.enemyId()
                  ));
              return res;
          };
      })();
    I added a new line, <strikeId>, to the Note field of the default Attack skill (ID 1). I then created a troop with 3 enemies: 2x Enemy ID 1, 1x Enemy ID 2. I saved the project, then launched a battle test. On attacking:
    • Enemy 1, both instances of that enemy were hit, regardless of which one was selected.
    • Enemy 2, only the selected instance of that enemy (the only one in the troop) was hit.
    By "hit", I mean that the attack animation and damage popup were displayed on the target, and the damage was correctly subtracted from the target's current HP.
  11. caethyril said:
    @Puppet Knight - I just ran a test (core script v1.8.1) with 2 plugins active, in this order:
    • Cae_OnUseEffects v1.7: unedited, no changes to default plugin param values.
    • The following test plugin:
      plugin code
      JavaScript:
      /*:
      * @target MZ
      * @plugindesc test
      * @author Caethyril
      * @url https://forums.rpgmakerweb.com/posts/1470712/
      * @help Free to use and/or modify for any project, no credit required.
      */
      ;void (() => {
          const alias = Game_Action.prototype.makeTargets;
          Game_Action.prototype.makeTargets = function() {
              const res = alias.apply(this, arguments);
              const tgt = res[0];
              if (this.item().meta.strikeId && tgt?.isEnemy())
                  res.push(...$gameTroop.aliveMembers().filter(
                      nme => nme !== tgt && nme.enemyId() === tgt.enemyId()
                  ));
              return res;
          };
      })();
    I added a new line, <strikeId>, to the Note field of the default Attack skill (ID 1). I then created a troop with 3 enemies: 2x Enemy ID 1, 1x Enemy ID 2. I saved the project, then launched a battle test. On attacking:
    • Enemy 1, both instances of that enemy were hit, regardless of which one was selected.
    • Enemy 2, only the selected instance of that enemy (the only one in the troop) was hit.
    By "hit", I mean that the attack animation and damage popup were displayed on the target, and the damage was correctly subtracted from the target's current HP.

    For my own head cannon before testing, this would be set up separate of the patch i am already using to alias canTarget?:


    Multiclass Plugin Code
    /*:
    * @target MZ
    * @plugindesc Cae_OnUseEffects patch: eval <target filter> on Classes.
    * @author Caethyril
    * @url https://forums.rpgmakerweb.com/posts/1435060/
    * @base Cae_OnUseEffects
    * @orderAfter Cae_OnUseEffects
    * @help Terms identical to Cae_OnUseEffects.
    */
    ;void (alias => {
    CAE.OnUseEffects.canTarget = function(action, target) {
    const item = action.item();
    const subject = action.subject();
    const user = subject;
    const multiclass = user.multiclass;
    if (item?.meta.sequence){
    return
    }
    return eval(((subject.columnIndex - subject.range) <= target.columnIndex && target.columnIndex <= (subject.columnIndex + subject.range)));//}
    return alias.apply(this, arguments);
    };
    })(CAE.OnUseEffects.canTarget);
  12. OK, I assume it's blocking on testApply. canTarget filters testApply mainly to prevent using items on forbidden actors via the menu. But it also gets checked to determine whether an action gets used on apply. You could patch it for your use case, e.g.
    JavaScript:
    void (alias => {
      Game_Action.prototype.testApply = function(target) {
        return this.item()?.meta.sequence || alias.apply(this, arguments);
      };
    })(Game_Action.prototype.testApply);
  13. caethyril said:
    OK, I assume it's blocking on testApply. canTarget filters testApply mainly to prevent using items on forbidden actors via the menu. But it also gets checked to determine whether an action gets used on apply. You could patch it for your use case, e.g.
    JavaScript:
    void (alias => {
      Game_Action.prototype.testApply = function(target) {
        return this.item()?.meta.sequence || alias.apply(this, arguments);
      };
    })(Game_Action.prototype.testApply);

    YAAAAAASSSS!!!!!

    That did it, just had to swap in strikeLine in place of sequence (my sequence fix was for a different skill type i have in play).

    Thank you so much @caethyril


    Now to make some funky combinations haha


    EDIT EDIT:


    Found some success going the following route:


    PLUGIN CODE
    void (() => {
    const pkEnemy_Game_Action_makeTargets = Game_Action.prototype.makeTargets;
    Game_Action.prototype.makeTargets = function() {
    const res = pkEnemy_Game_Action_makeTargets.apply(this, arguments);
    const tgt = res[0];
    const strikeLine = this.item().meta.strikeLine;
    let targetGroup = $gameTroop.aliveMembers();
    if (tgt?.isActor()) targetGroup = $gameParty.aliveMembers();
    if (this.item().meta.strikeLine)
    res.push(...targetGroup.filter(
    nme => nme !== tgt && nme._row === tgt._row
    ));
    return res;
    };
    })();

    void (alias => {
    Game_Action.prototype.testApply = function(target) {
    return this.item()?.meta.strikeLine || alias.apply(this, arguments);
    };
    })(Game_Action.prototype.testApply);


    Working fine overall. I just have to figure out why on the gameParty side, both damage pop ups show on the initial target only, and not each Actor applied.


    EDIT EDIT EDIT!
    Damage popups semi corrected themselves. Now just trying to figure out why popUps on actors are doubling for MP damage only
  14. I see testApply in the Cae_OnUseEffects came up in the previous posts. Not sure if the following falls into the same discussion since I didn't follow the full code exchange, although I don't think so.

    I noticed the conditional effects tag is evaluated for the purpose of the application of an action during
    applyItemEffect, but not during hasItemAnyValidEffects - which gets called by testApply.
    Is this intended?

    Asking since, when out of battle, MZ by default tries to filter out items which have no effects (E.g. an item with the effect of removing a state won't be usable on a battler that doesn't have said said.)
    This creates a slightly inconsistent user experience of out-of-battle usage between items/skills which use effect conditions and those which don't.
  15. @auradev - yes, it's intended. OnUseEffects applies a conditional restriction; it doesn't allow for expanding or overriding the target set.

    This is the default testApply:
    JavaScript:
    Game_Action.prototype.testApply = function(target) {
        return (
            this.testLifeAndDeath(target) &&
            ($gameParty.inBattle() ||
                (this.isHpRecover() && target.hp < target.mhp) ||
                (this.isMpRecover() && target.mp < target.mmp) ||
                this.hasItemAnyValidEffects(target))
        );
    };
    I.e.
    • The target must be alive/dead as appropriate to match the action scope; AND
      • The party must be in battle; OR
      • The action must be HP Recover type and the target be under full HP; OR
      • The action must be MP Recover type and the target be under full MP; OR
      • The action must have 1+ "valid" effects.
    By default, if an item/skill fails this check, it will be disabled in its menu. As you can see, most validity checks are skipped in battle, presumably to allow for stuff like pre-emptive heals of damage that will land after selecting an action but before that action is performed. (testApply is also checked on Game_Action#apply, which determines whether it was "used" or not - e.g. if you targetted revive on someone at low HP but they didn't die before casting.)

    You can get around this by adding a effect that never does anything, but still counts as "valid", e.g. Add State: Death 0% on a skill that targets the living. (For Add State effects it only checks if the target already has the state: the apply chance is ignored.)


    Now, my OnUseEffects plugin applies several patches to different methods. The very first patch is to Game_Action#testApply, for item/skill use from the pause menu:
    JavaScript:
            // Alias! Restrict target actors as appropriate.
            void (alias => {
                Game_Action.prototype.testApply = function(target) {
                    return alias.apply(this, arguments) && $.canTarget(this, target);
                };
            })($.alias.Game_Action_testApply = Game_Action.prototype.testApply);
    This just adds another condition: the target must also be valid re any applicable <target filter> tag.
  16. caethyril said:
    @auradev - yes, it's intended. OnUseEffects applies a conditional restriction; it doesn't allow for expanding or overriding the target set.

    This is the default testApply:
    JavaScript:
    Game_Action.prototype.testApply = function(target) {
        return (
            this.testLifeAndDeath(target) &&
            ($gameParty.inBattle() ||
                (this.isHpRecover() && target.hp < target.mhp) ||
                (this.isMpRecover() && target.mp < target.mmp) ||
                this.hasItemAnyValidEffects(target))
        );
    };
    I.e.
    • The target must be alive/dead as appropriate to match the action scope; AND
      • The party must be in battle; OR
      • The action must be HP Recover type and the target be under full HP; OR
      • The action must be MP Recover type and the target be under full MP; OR
      • The action must have 1+ "valid" effects.
    By default, if an item/skill fails this check, it will be disabled in its menu. As you can see, most validity checks are skipped in battle, presumably to allow for stuff like pre-emptive heals of damage that will land after selecting an action but before that action is performed. (testApply is also checked on Game_Action#apply, which determines whether it was "used" or not - e.g. if you targetted revive on someone at low HP but they didn't die before casting.)

    You can get around this by adding a effect that never does anything, but still counts as "valid", e.g. Add State: Death 0% on a skill that targets the living. (For Add State effects it only checks if the target already has the state: the apply chance is ignored.)


    Now, my OnUseEffects plugin applies several patches to different methods. The very first patch is to Game_Action#testApply, for item/skill use from the pause menu:
    JavaScript:
            // Alias! Restrict target actors as appropriate.
            void (alias => {
                Game_Action.prototype.testApply = function(target) {
                    return alias.apply(this, arguments) && $.canTarget(this, target);
                };
            })($.alias.Game_Action_testApply = Game_Action.prototype.testApply);
    This just adds another condition: the target must also be valid re any applicable <target filter> tag.
    Thanks for the response! I like the default way RPGMaker handles the exclusion to prevent healing items being used without having an effect. Useful when players slam down a bunch to get to full HP, so I will probably look in some other way to get results like the default behavior, rather than changing items to behave by default as if they were always applicable outside of battle.

    As a minor note: The default behavior doesn't disable item/skills that fail the testApply check. They are enabled in the menu and allow the user to select a target and *then* reject the target. I noticed this because one of my players reported me that I have one healing item that exhibits that behavior and another healing item that wasn't usable at all because I initially used target filter in order to control the targets before started looking into the conditional effect tag.
  17. Ah, yep, the disabling is something my plugin does with other patches. Been a while since I touched the code, I'm a bit rusty on it. :kaoswt:

    :kaoslp: Also, sorry, I just realised I misread this earlier, thought you were talking about target filter for some reason instead of effect conditions:
    auradev said:
    I noticed the conditional effects tag is evaluated for the purpose of the application of an action during
    applyItemEffect, but not during hasItemAnyValidEffects - which gets called by testApply.
    Is this intended?
    Yes, I think so. :kaohi:

    The main problem I can see is with any condition that relies on result info. To disable items/skills appropriately, the conditions of each item/skill would basically have to be calculated, against potential targets, when the scene is created (and every time an item/skill is used), rather than only when an item/skill is applied to a selected target. But to do that we'd need to simulate some kind of result, or completely remove the ability to reference the action's result in conditions. No thanks! :kaoback:
  18. Hello, found a bug that prevents criticals.

    On line 586 of v1.7 Cae_OnUseEffects, it should be "item.damage.critical" in order for doesCrit to function. Otherwise, it always throws an undefined.

    Thanks for the cool scripts!
  19. Crazetex said:
    On line 586 of v1.7 Cae_OnUseEffects, it should be "item.damage.critical" in order for doesCrit to function.
    Oh! Thanks for letting me know, I've uploaded v1.8 with the correction~ :kaohi:
  20. Hello! I would like to use Cae_TitleMenu to add a ’New Game’ command to the main menu that only appears once the player has completed one certain ending.

    I know the plugin says “They can be hidden/shown and enabled/disabled with script conditions.” So is there code that I can put in the JS: Visible or JS: Enabled sections to make the ‘New Game’ command only appear if a certain switch is ON, or something similar?

    I hope you will excuse me. I am awfully code illiterate. Thank you very much for your time and for making the plugin.