Enemy that adds State on Death

Discussion in 'RPG Maker MV' started by Yawgmoth, Jan 14, 2019.

  1. Yawgmoth

    Yawgmoth Veteran Veteran

    Messages:
    74
    Likes Received:
    5
    Location:
    Nebraska
    First Language:
    English
    Primarily Uses:
    RMMV
    Hi all,

    In my game I have a class that has a skill that adds a special state. I want that state to cause a 10% increase of max HP whenever an enemy dies. I am using Yanfly's Buff and State Core Plugin to control stacking to a max of 5 times. I just can't seem to get a foot hold on this issue. I believe this can all be done using only states but perhaps I am wrong. I would prefer not to use troop events if it can be helped. Any help or suggestions would be greatly appreciated. Thank you all in advance.
     
    #1
  2. Zevia

    Zevia Veteran Veteran

    Messages:
    576
    Likes Received:
    267
    First Language:
    English
    Primarily Uses:
    RMMV
    EDIT: For the most up-to-date version of the Plugin I wrote in this post, see this thread.

    I've written a Plugin that will run common events after any Actor or Enemy dies. If you want to use it, make sure you save it as "DeathCommonEvent.js". You can also download it from this post.

    Code:
    /*:
    * @plugindesc This plugin will call a common event whenever any Actor or Enemy dies.
    * @author Zevia
    *
    * @help You can specify two separate common events to run for when an Actor dies
    * and for when an Enemy dies. You can also specify what game variables to use to
    * store some information about how the battler died, such as the Id of the
    * dying battler as well as its index within the troop or the party, or the Id
    * and index of the last battler to act (most likely the battler that had the
    * killing blow).
    *
    * You can also reference the Id and type of the skill or item last used before
    * the battler died. For example, if you want to have a conditional branch in
    * your common event that depends on an enemy being killed with skill ID 4,
    * you could reference the actionId variable (5 by default) and the actionType
    * variable (6 by default) to check if actionId is 4 and actionType is "skill".
    *
    * Common events are added to a queue if an Enemy or Actor's death causes the
    * battle to end, such as when the last Enemy or Actor dies. This can sometimes
    * cause issues, like trying to refer to enemies when you're no longer in
    * battle. If you want a Death Common Event to run at the end of the Battle,
    * before the victory logic is processed, then turn Run At Battle End ON.
    * If you want it to run after the battle is over and you're returned to the
    * previous Scene, turn Run At Battle End OFF and turn ON Run After Battle End.
    *
    * If you'd rather not have common events run after the last Enemy or Actor in
    * battle dies, turn Run At Battle End AND Run After Battle End OFF.
    *
    * If Run At Battle End AND Run After Battle End are ON, then the common
    * event will only be called before victory and will not be called again
    * after battle.
    *
    * @param actorCommonEventId
    * @text Actor Death Common Event ID
    * @type number
    * @desc The ID of the common event to call whenever an Actor dies.
    * @default 1
    *
    * @param enemyCommonEventId
    * @text Enemy Death Common Event ID
    * @type number
    * @desc The ID of the common events to call whenever an Enemy dies.
    * @default 2
    *
    * @param targetId
    * @text Target ID Variable
    * @type number
    * @desc The variable used to store the ID of the battler that just died.
    * @default 1
    *
    * @param targetIndex
    * @text Target Index Variable
    * @type number
    * @desc The variable used to store the index in the battle party or troop of the battler that just died.
    * @default 2
    *
    * @param targetStates
    * @text Target States Variable
    * @type number
    * @desc The variable used to store the list of states of the battler just before they died.
    * @default 3
    *
    * @param subjectId
    * @text Subject ID Variable
    * @type number
    * @desc The variable used to store the ID of the battler that just acted.
    * @default 4
    *
    * @param subjectIndex
    * @text Subject Index Variable
    * @type number
    * @desc The variable used to store the index in the battle party or troop of the battler that just acted.
    * @default 5
    *
    * @param actionId
    * @text Last Action ID Variable
    * @type number
    * @desc The variable used to store the ID of the last skill or item used before the battler died.
    * @default 6
    *
    * @param actionType
    * @text Last Action Type Variable
    * @type string
    * @desc The variable used to store the type of the last action used. Values are "skill" or "item".
    * @default 7
    *
    * @param shouldRunAtEndOfBattle
    * @text Run At Battle End
    * @desc Whether the death common events should be run when the last Enemy or Actor dies, before victory is processed.
    * @type boolean
    * @default true
    *
    * @param shouldRunAfterBattle
    * @text Run After Battle
    * @type boolean
    * @desc Whether the death common events should be run when the last Enemy or Actor dies, after the battle is over.
    * @default false
    */
    
    (function(module) {
        'use strict';
    
        module.Zevia = module.Zevia || {};
        var DeathCommonEvent = module.Zevia.DeathCommonEvent = {};
    
        var parameters = PluginManager.parameters('DeathCommonEvent');
        var actorCommonEventId = parseInt(parameters.actorCommonEventId);
        var enemyCommonEventId = parseInt(parameters.enemyCommonEventId);
        var targetId = parseInt(parameters.targetId);
        var targetIndex = parseInt(parameters.targetIndex);
        var targetStates = parseInt(parameters.targetStates);
        var subjectId = parseInt(parameters.subjectId);
        var subjectIndex = parseInt(parameters.subjectIndex);
        var actionId = parseInt(parameters.actionId);
        var actionType = parseInt(parameters.actionType);
        var shouldRunAfterBattle = !!parameters.shouldRunAfterBattle.match(/true/i);
        var shouldRunAtEndOfBattle = !!parameters.shouldRunAtEndOfBattle.match(/true/i);
    
        DeathCommonEvent.shouldExecute = function(isActorDeath) {
            return shouldRunAfterBattle || shouldRunAtEndOfBattle || ((isActorDeath ? $gameParty.aliveMembers() : $gameTroop.aliveMembers()).length > 1);
        };
    
        Game_BattlerBase.prototype.executeDeathCommonEvents = function() {
            var isActorDeath = this instanceof Game_Actor;
            if (!DeathCommonEvent.shouldExecute(isActorDeath)) { return; }
    
            var subject = BattleManager._subject;
            var actionItem = BattleManager._action && BattleManager._action._item;
            var partyBattleMembers = $gameParty.battleMembers();
            var enemyMembers = $gameTroop.members();
            $gameVariables.setValue(targetId, (isActorDeath ? this._actorId : this._enemyId));
            $gameVariables.setValue(targetIndex, (isActorDeath ? partyBattleMembers.indexOf(this) : enemyMembers.indexOf(this)));
            $gameVariables.setValue(targetStates, this._states);
            if (subject) {
                var isActorSubject = subject instanceof Game_Actor;
                $gameVariables.setValue(subjectId, (isActorSubject ? subject._actorId : subject._enemyId));
                $gameVariables.setValue(subjectIndex, (isActorSubject ? partyBattleMembers.indexOf(subject) : enemyMembers.indexOf(subject)));
            }
            if (actionItem) {
                $gameVariables.setValue(actionId, actionItem._itemId);
                $gameVariables.setValue(actionType, actionItem._dataClass);
            }
    
            $gameTemp.reserveCommonEvent(isActorDeath ? actorCommonEventId : enemyCommonEventId);
        };
    
        DeathCommonEvent.die = Game_BattlerBase.prototype.die;
        Game_BattlerBase.prototype.die = function() {
            this.executeDeathCommonEvents();
            DeathCommonEvent.die.call(this);
        };
    
        DeathCommonEvent.processVictory = BattleManager.processVictory;
        BattleManager.processVictory = function() {
            if (shouldRunAtEndOfBattle && $gameTroop._interpreter.setupReservedCommonEvent()) { return; }
            DeathCommonEvent.processVictory.call(this);
        };
    })(window);
    
    The plugin includes some logic to assign values to game variables that may be useful when writing common events, such as the Id and index of the last battler to act, the Id and index of the battler that just died, and the Id and type of the last skill or item used. By default, the Id of the Actor or Enemy that died is variable 1, the index in either battleMembers or gameTroop is variable 2, the Id of the last Actor or Enemy to act is variable 3, the index in either battleMembers or gameTroop is variable 4, the Id of the last skill or item used is variable 5, and the type of the last action ("skill" or "item") is variable 6.

    In your particular case, you could have a common event assigned to enemy death that looks something like this:
    [​IMG]

    A quirk of common events is that their execution is queued up instead of immediately executed, so if you kill the last Enemy in a troop, the victory logic will process before the common event and your state would be applied outside of battle. If you don't want that to happen, you can either set your common event up to check if the current Scene is Scene_Battle, or you can configure the Plugin to not run on Actor or Enemy death if they are the last Actor or Enemy to die (basically, don't run on death if the death causes the battle to end).
     

    Attached Files:

    Last edited: Feb 7, 2019
    #2
  3. Yawgmoth

    Yawgmoth Veteran Veteran

    Messages:
    74
    Likes Received:
    5
    Location:
    Nebraska
    First Language:
    English
    Primarily Uses:
    RMMV
    Wow well this looks great. My knowledge of script is very limited though. I downloaded the plugin.

    All I need is for my actors target state when applied to a foe to allow a state to be applied to my actor if my actor has the proper state on himself and the targeted for does. The foe can die in any way that part does not matter.

    If you can talk me through how to go about doing that along with how to set up the variables I would really appreciate it. Thank you for your quick reply.
     
    #3
  4. Zevia

    Zevia Veteran Veteran

    Messages:
    576
    Likes Received:
    267
    First Language:
    English
    Primarily Uses:
    RMMV
    You'd have to store what states the enemy was affected by prior to being killed, since when the common event runs, the only state they'll have is 1 (knockout).

    I'll look into adding that information to the Plugin so that it's easily accessible without adding a bunch of common events to every skill that applies states or having to add troop events, then get back to you when I have some time to create a guide with screenshots.
     
    #4
  5. Yawgmoth

    Yawgmoth Veteran Veteran

    Messages:
    74
    Likes Received:
    5
    Location:
    Nebraska
    First Language:
    English
    Primarily Uses:
    RMMV
    That would be great and thank you for helping. I look forward to your next post.
     
    #5
  6. Zevia

    Zevia Veteran Veteran

    Messages:
    576
    Likes Received:
    267
    First Language:
    English
    Primarily Uses:
    RMMV
    I've modified the Plugin to now also store the state IDs a battler had just before they died as a game variable, as well, so you'll want to replace your version with the newest one. I've edited my post that has it, so you can either copy or download from there.

    In regards to game variables, when you use the "control variables" option in the event editor, you should reserve 7 variable slots that you aren't currently using somewhere. The reason is, this Plugin is going to frequently store values in them, so if you're using the ones the Plugin intends to use, you're going to get odd behavior.

    You can tell the Plugin what variable slots you want it to use in the configuration. By default, it uses variables 0001 through 0007, but you're welcome to change them however you'd like. The variables it stores are:

    1 - The Id of the Actor or Enemy that just died.
    2 - The index of the Actor or Enemy that just died, referencing either the party's battle members or the current troop. For example, if you have a troop with Bat A and Bat B and Bat B dies, this value would be 1 (since Bat A is index 0).
    3 - An array of state IDs the battler that just died had before they died (arrays can't really be manipulated through the default interface, so you'll probably only reference this in script commands)
    4 - The Id of the Actor or Enemy that last acted (most likely the Actor or Enemy who just killed someone)
    5 - The index of the Actor or Enemy that last acted, referencing either the party's battle members or the current troop
    6 - The Id of the last action used before the Actor or Enemy died (most likely the skill or item that killed someone)
    7 - The type of the last action used (either "skill" or "item")

    If you want to use the defaults, you could mark your variables using the "control variables" interface similar to below. If you've already got variables in the 0001 - 0007 sections, then just use the Plugin parameters configuration to change them to something else.
    [​IMG]

    So for your common event, there are a few conditionals we want to write. Let's suppose that you want an actor to gain state 11 if the enemy had state 4 when it died and the actor had state 4 when the enemy died. Your first conditional would be, "Did the enemy have state 4 when it died?"

    Since, in the interface, you can't reference enemies by variable in a conditional statement, you'll have to use a script command in your conditional:
    Code:
    $gameVariables.value(3).indexOf(4) !== -1
    
    The value you want to check is whatever variable you're using to store the states of the enemy that just died. So, in the Plugin configuration, whatever variable you're using for "Target States Variable" would replace the number 3 and whatever state ID you want to check for would replace the number 4. The Target States Variable will store all the states the battler that just died had as an array of state IDs, so you want to check if that array has the state ID 4. If you're using RMMV 1.6, you could do
    Code:
    $gameVariables.value(3).includes(4)
    
    But if you're using an older version, you'll have to use the indexOf check mentioned above. When you use indexOf on an array, if the array has the value, then you get back its index. If the array does not have it, you get -1.

    Next, you want to check if the actor has the same state. Since you can't check actor by variable in a conditional branch, you'll have to use a script command here, too. We have the index of the last battler to act, so we can reference
    Code:
    $gameParty.battleMembers()
    in order to get an array of all the party's battle members. We can then reference our stored index variable to get the correct actor:
    Code:
    $gameParty.battleMembers()[$gameVariables.value(5)]
    
    You'll want to replace 5 with whatever you have in the Plugin configuration for "Subject Index Variable." In order to determine if a battler has a particular state, we use the isStateAffected function, so the whole thing comes down to:
    Code:
    $gameParty.battleMembers()[$gameVariables.value(5)].isStateAffected(4)
    
    replacing 4 with whatever the state ID is you want to check.

    Finally, we want to add a state to that actor - however, the default interface allows us to add states to actors referencing variables, so no script command necessary here!
    [​IMG]

    It's a fair amount of JavaScript to use in your conditionals, but ultimately the common event would look something like this:
    [​IMG]
     
    #6
  7. Yawgmoth

    Yawgmoth Veteran Veteran

    Messages:
    74
    Likes Received:
    5
    Location:
    Nebraska
    First Language:
    English
    Primarily Uses:
    RMMV
    @Zevia Wow! You explained that very well! I think I have everything set up but will have to test it out tomorrow after work. I'll post back whether it works or doesn't. I am also using RPG Maker MV 1.6.1 and went with that specific script. I am using variables 91-97 since I had already used 1-7. My target state ID is 211. I'll post a screen shot below of my common event.

    Now I have a few questions if that is alright?
    1. How is the common event called?
    2. If I wanted to create another effect like this one could I use the same variables and change the evented state? No plans to do this.
    3. In $gameParty.battleMembers()[$gameVariables.value(5)].isStateAffected(4) if I altered (4) to lets say a different state then the enemy, would the script then check the enemy for 4 and the actor for the the alteration? Would everything still work?

    Thank you for all this help! I really do appreciate it. I plan on doing a series of skills for a Ranger like character who hunts monsters. I wanted the character to get better as a battle progresses. I needed the character to have it's own unique thing and I think this will do the trick. I can't ait to play test. Please take a look at my common event .png below.
     

    Attached Files:

    #7
  8. Zevia

    Zevia Veteran Veteran

    Messages:
    576
    Likes Received:
    267
    First Language:
    English
    Primarily Uses:
    RMMV
    The "die" method that gets called whenever a Game_Actor dies has been modified in the Plugin to call the common event with the ID matching the Plugin configuration parameter "Actor Death Common Event". The same is true for Game_Enemy calling the "Enemy Death Common Event" ID. So, make sure you configure the Plugin parameters to set the "Enemy Death Common Event" value to 150. You'll also want to make sure the value for "Actor Death Common Event" isn't calling something you don't want to be called, so you'll want to change that value, too.

    Sure - if you want the same effect, but a different state to be applied, just change the state that gets applied. You should be able to make your common event do whatever you would normally do in a common event.

    Correct - they don't have to have the same state. So you could check if the enemy has state 4 and the actor has state 5. You don't even have to check states, if you don't want to - you could just see if an actor is wearing a particular item, or if they killed an enemy with a specific skill, or really whatever you might do in a common event.

    Looks to me like your common event will check if the enemy that just died had state 211, if the actor that just acted has state 211, then apply the state "Consume" to the actor that just acted.
     
    #8
  9. Yawgmoth

    Yawgmoth Veteran Veteran

    Messages:
    74
    Likes Received:
    5
    Location:
    Nebraska
    First Language:
    English
    Primarily Uses:
    RMMV
    That sounds correct. I'll make those changes in the plugin parameters and hopefully give it a test tomorrow evening. Thanks so much.

    EDIT: @Zevia I'm having some trouble locating the parameters you said need altered to common event 150. Could you maybe show a screen shot of the lines highlighted. I'm sure I'm just missing them. Thanks again.
     
    Last edited: Jan 16, 2019
    #9
  10. Yawgmoth

    Yawgmoth Veteran Veteran

    Messages:
    74
    Likes Received:
    5
    Location:
    Nebraska
    First Language:
    English
    Primarily Uses:
    RMMV
    Ok, I think I may of figured it out. How does this look?

    Code:
    /*:
    * @plugindesc This plugin will call a common event whenever any Actor or Enemy dies.
    * @author Zevia
    *
    * @help You can specify two separate common events to run for when an Actor dies
    * and for when an Enemy dies. You can also specify what game variables to use to
    * store some information about how the battler died, such as the Id of the
    * dying battler as well as its index within the troop or the party, or the Id
    * and index of the last battler to act (most likely the battler that had the
    * killing blow).
    *
    * You can also reference the Id and type of the skill or item last used before
    * the battler died. For example, if you want to have a conditional branch in
    * your common event that depends on an enemy being killed with skill ID 4,
    * you could reference the actionId variable (5 by default) and the actionType
    * variable (6 by default) to check if actionId is 4 and actionType is "skill".
    *
    * Common events are added to a queue if an Enemy or Actor's death causes the
    * battle to end, such as when the last Enemy or Actor dies. This can sometimes
    * cause issues, like trying to refer to enemies when you're no longer in
    * battle. If you'd rather not have common events run after the last Enemy
    * or Actor in battle dies, you can turn off the "Run Common Events After Battle"
    * option.
    *
    * @param actorCommonEventId
    * @text Actor Death Common Event ID
    * @type number
    * @desc The ID of the common event to call whenever an Actor dies.
    * @default 149
    *
    * @param enemyCommonEventId
    * @text Enemy Death Common Event ID
    * @type number
    * @desc The ID of the common events to call whenever an Enemy dies.
    * @default 150
    *
    * @param targetId
    * @text Target ID Variable
    * @type number
    * @desc The variable used to store the ID of the battler that just died.
    * @default 91
    *
    * @param targetIndex
    * @text Target Index Variable
    * @type number
    * @desc The variable used to store the index in the battle party or troop of the battler that just died.
    * @default 92
    *
    * @param targetStates
    * @text Target States Variable
    * @type number
    * @desc The variable used to store the list of states of the battler just before they died.
    * @default 93
    *
    * @param subjectId
    * @text Subject ID Variable
    * @type number
    * @desc The variable used to store the ID of the battler that just acted.
    * @default 94
    *
    * @param subjectIndex
    * @text Subject Index Variable
    * @type number
    * @desc The variable used to store the index in the battle party or troop of the battler that just acted.
    * @default 95
    *
    * @param actionId
    * @text Last Action ID Variable
    * @type number
    * @desc The variable used to store the ID of the last skill or item used before the battler died.
    * @default 96
    *
    * @param actionType
    * @text Last Action Type Variable
    * @type string
    * @desc The variable used to store the type of the last action used. Values are "skill" or "item".
    * @default 97
    *
    * @param shouldRunAfterBattle
    * @text Run Common Events After Battle
    * @type boolean
    * @desc Whether the death common events should be run when the last Enemy or Actor dies.
    * @default false
    */
    
    (function(module) {
        'use strict';
    
        module.Zevia = module.Zevia || {};
        var DeathCommonEvent = module.Zevia.DeathCommonEvent = {};
    
        var parameters = PluginManager.parameters('DeathCommonEvent');
        var actorCommonEventId = parseInt(parameters.actorCommonEventId);
        var enemyCommonEventId = parseInt(parameters.enemyCommonEventId);
        var targetId = parseInt(parameters.targetId);
        var targetIndex = parseInt(parameters.targetIndex);
        var targetStates = parseInt(parameters.targetStates);
        var subjectId = parseInt(parameters.subjectId);
        var subjectIndex = parseInt(parameters.subjectIndex);
        var actionId = parseInt(parameters.actionId);
        var actionType = parseInt(parameters.actionType);
        var shouldRunAfterBattle = !!parameters.shouldRunAfterBattle.match(/true/i);
    
        DeathCommonEvent.shouldExecute = function(isActorDeath) {
            return shouldRunAfterBattle || ((isActorDeath ? $gameParty.aliveMembers() : $gameTroop.aliveMembers()).length > 1);
        };
    
        Game_BattlerBase.prototype.executeDeathCommonEvents = function() {
            var isActorDeath = this instanceof Game_Actor;
            if (!DeathCommonEvent.shouldExecute(isActorDeath)) { return; }
    
            var subject = BattleManager._subject;
            var actionItem = BattleManager._action && BattleManager._action._item;
            var partyBattleMembers = $gameParty.battleMembers();
            var enemyMembers = $gameTroop.members();
            $gameVariables.setValue(targetId, (isActorDeath ? this._actorId : this._enemyId));
            $gameVariables.setValue(targetIndex, (isActorDeath ? partyBattleMembers.indexOf(this) : enemyMembers.indexOf(this)));
            $gameVariables.setValue(targetStates, this._states);
            if (subject) {
                var isActorSubject = subject instanceof Game_Actor;
                $gameVariables.setValue(subjectId, (isActorSubject ? subject._actorId : subject._enemyId));
                $gameVariables.setValue(subjectIndex, (isActorSubject ? partyBattleMembers.indexOf(subject) : enemyMembers.indexOf(subject)));
            }
            if (actionItem) {
                $gameVariables.setValue(actionId, actionItem._itemId);
                $gameVariables.setValue(actionType, actionItem._dataClass);
            }
    
            $gameTemp.reserveCommonEvent(isActorDeath ? actorCommonEventId : enemyCommonEventId);
        };
    
        DeathCommonEvent.die = Game_BattlerBase.prototype.die;
        Game_BattlerBase.prototype.die = function() {
            this.executeDeathCommonEvents();
            DeathCommonEvent.die.call(this);
        };
    })(window);
     
    #10
  11. Zevia

    Zevia Veteran Veteran

    Messages:
    576
    Likes Received:
    267
    First Language:
    English
    Primarily Uses:
    RMMV
    Ah - when I say you can edit plugin parameters, you can actually do it without editing the JavaScript at all.

    If you go into your Plugin menu and double click on the Plugin, you should get another interface with a help window and available parameters.
    [​IMG]

    These parameters are handled via the comments you edited, but the idea is that a Plugin's author can make the Plugin configurable via the RMMV interface without having to edit the actual text of the Plugin.
     
    #11
  12. Yawgmoth

    Yawgmoth Veteran Veteran

    Messages:
    74
    Likes Received:
    5
    Location:
    Nebraska
    First Language:
    English
    Primarily Uses:
    RMMV
    Well last night nothing had showed up when I had looked in the parameters so I had dismissed it as an option. However I just looked and all the parameters are there. I guess I altered it the hard way. LOL. Anyways here's a screen shot, I think everything looks good in the parameters from what you have said. I guess I am ready for a play test?

    EDIT: It seems like everything is working well during the play test. Thank you for all your help. This is a great plugin. If I have any further problems I'll let you know but I think I have it from here.
     

    Attached Files:

    Last edited: Jan 16, 2019
    #12

Share This Page