Battle Action Exp
In RPG Maker, actors can receive exp by defeating enemies in battle. When all enemies are defeated, the victory processing will occur, and actors will receive exp from the battle.
However, this means that if you were to escape before the battle was over, your actors would not receive any exp even if they defeated some enemies.
This plugin changes the way exp is obtained. Instead of only on battle end, exp is received whenever you perform an action.
For example, if an actor attacks an enemy, exp calculation will occur and if the actor earns exp from that attack, the actor will receive that exp
immediately, and potentially level up on the spot.
Action exp can also be obtained outside of battle, depending on the rules you have set up for your exp calculations.
With this plugin, actors will be rewarded immediately for their actions, which provides you with some additional mechanics that you can use.
Download
Plugin: download here (right-click, save as)
Addons
- Battle Exp Popup – example plugin showing how you can display exp gained in battle.
Patches
- Patch for Yanfly Victory Aftermath. The exp gained screen will display how much exp was gained in battle. However, the victory aftermath plugin disables level up messages during battle.
Installation
Download the plugin and place it in the “plugins” folder in your project’s “js” folder. Then open your Plugin Manager (F10), double-click an empty row, and select the HIME_BattleActionExp plugin.
Once it is in your list of plugins, turn the plugin on.
Usage
Global Action Exp Formula
The global formula is used whenever action exp calculations are required and applies to all actions, regardless whether it’s an actor or an enemy. It is defined in the plugin parameters:
The following formula variables are available:
a - user of the action b - target of the action v - game variables s - game switches
By default, you only receive EXP when you defeat the enemy. Here is the formula:
b.isEnemy() && b.isDead() ? b.exp() : 0
This means
IF the target of the action is an enemy, and the target is dead, THEN the amount of EXP gained is equal to the enemy's EXP. OTHERWISE, no EXP
It also means that if an actor targets another actor, no EXP is gained. It is important to check whether the target is an actor or enemy in certain situations, since certain properties may not exist for all battlers.
Examples
Let’s say that instead of only receiving exp when an enemy is defeated, you wanted to receive exp based on the amount of damage you deal, as a percentage of the enemy’s exp.
That is to say, if the enemy has 100 HP and gives a total of 100 exp, and you deal 20 damage, then you will receive 20% exp from the enemy, or 20 exp.
To accomplish this, you can retrieve the damage dealt from the action result object for the target:
b.result()
From there, you can ask for the HP Damage:
b.result().hpDamage
To get the ratio, you would take that and divide it by the target’s max HP
b.result().hpDamage / b.mhp
Which would give you the percentage of damage that you dealt relative to the target’s total HP.
Finally, you can multiply this percentage with the enemy’s total EXP, to determine the fraction of EXP that the attacker receives:
(b.result().hpDamage / b.mhp) * b.exp()
Again, because only enemy’s have EXP by default, you may need to check if the target is actually an enemy:
b.isEnemy() ? (b.result().hpDamage / b.mhp) * b.exp() : 0
Which means if you target an actor, you receive no exp.
Now, what happens if the amount of damage you deal is greater than the amount of HP the enemy has left? For example, if you deal 200 damage to an enemy with only 100 HP.
Unfortunately, with this plugin alone, you don’t have access to the enemy’s HP BEFORE the action was applied, but if you had such a plugin, and it stored this information in a property called `oldHp` in the action result, you could say this:
b.isEnemy() ? (Math.min(b.result().hpDamage, b.result().oldHp) / b.mhp) * b.exp() : 0
For anyone using this, there has been an issue discovered where EXP gains are not cleared if you are not in a battle. Please refer to this post for the patch: https://forums.rpgmakerweb.com/index.php?threads/battleactionexp-mp-recovery-troubles.168667/post-1444484
Here is the most current code I am using.
Math.round(b.isEnemy() ? (b.result().hpDamage / b.mhp) * b.exp() + ((b.level – a.level) * (b.exp() * 0.12)) : 0)
It rounds exp to a whole number, and if enemy level is higher or lower than character, it adjusts amount of exp given by 20% per level difference.
I made some code for my new in development game combining Himes original code, and some comment section code, its working so I thought I would share it.
It gives exp per damage of max hp and changes exp amount based upon difference of level of the actor and the enemy (Note you will need to partner this plugin with himes enemy levels plugin for this code to work)
b.isEnemy() ? (b.result().hpDamage / b.mhp) * b.exp() + ((b.level – a.level) * (b.exp() * 0.15)) : 0
Hime, Is there a way to only display exp gained up to 0.00 im getting like 0.0000000 and its a bit much, can you help?
If you use YEP_InstantCast and level during an ‘Instant Cast’ attack the game stalls at that point. You can’t take any further actions or anything. Any thoughts or recommendations?
Thanks in advance
Hello. First of all, it’s a great script. The problem is that it doesn’t work well in me. I have troops or when a monster dies another one. So the script doesn’t take into account party b.isdead or it works perfectly. I can’t send a version of my project because I’m not in France, so I’m limited by the Internet. I can just say that I use mostly yanfly scripts. If anybody had an idea. Thank you very much.
Okay so the forum is poinltess to ask on at this point so I’m gonna ask on here and pray I get a reply:
Is there a way to make it so that exp is distributed AFTER combat(at the end) still with this plugin?
Since I’m not very code savy I’m unsure of how to do this if its even possible and the reason I ask is because there will be instances where I want the actor to gain exp AFTER battle instead of during.
It sometimes gives a long decimal when receiving exp based on damage
Can it accumulate a ExpWeight (no Exp) during battle and it defines enemy Exp piece in the end?
Example:
.
You & I
VS
Dungger
.
You attack –> +3 weight
I heal –> +2 weight
You attack –> +3 weight
I attack –> +3 weight
Dungger dead
.
Dungger Exp = 1000
You: 6/11 –> Exp +545
I: 5/11 –> Exp +455
This would be better off as a separate add-on to implements a particular way for distributing EXP.
If you had two enemies, how would the weights be applied?
Individually
Hello. Loving the this plugin.
I used this parameter,,
b.isEnemy() && b.isDead() ? b.exp() : 0
But, when you knock down with continuous attack, experience value is obtained many times.
ex) 1000exp 1000exp 1000exp 1000exp..
Is there a solution?
Unfortunately, I am not sure how to check for whether a damage is part of the same action, or a different action.
There may be a situation where someone wants each consecutive hit to count for exp as well.
It may be necessary to change the exp formula.
I have a huge issue with your plugin and Victory Aftermath.
Everything is in order as it should, but more often than not there always seems to be a lockup that you really have to wait through before any exp is showed as being earned. It’s really hampering the game and I would really love to use your plugin plus Victory Aftermath but it just doesn’t want to cooperate.
If you can help, it would be appreciated
Set up a debug demo here http://himeworks.com/2016/01/super-small-debug-demo/ and send it to me
Hi Hime! This plugin is amazing!
I was trying to make it a passive effect, so those who have a certain state ON will gain experience per hit but those who doesn’t are not getting experience at all, I tried this but when I access the Status Menu the game cannot process the exp that was gained by the non-affected battlers. Any suggestion as how to do this? This is the code I used:
a.isStateAffected(8) ? b.isEnemy() ? Math.ceil((Math.min(b.result().hpDamage, b.hp) / b.mhp) * b.exp()) : 0 : b.exp
After a while I realized that that formula wouldn’t work, I’m trying this one now, but there will be no exp for those who do not have the state for some reason:
a.isStateAffected(8) ? b.isEnemy() ? Math.ceil((Math.min(b.result().hpDamage, b.hp) / b.mhp) * b.exp()) : 0 : b.isEnemy() && b.isDead() ? b.exp() : 0
Your logic as it is written means
So basically you want it so that if the state isn’t applied, the actor should gain exp normally when the enemy dies?
Exactly. If the state is on, then they get experience per hit. If it’s not, they get experience normally.
I think the problem is when the enemy dies, only the actor that killed it will get exp.
So there’s currently no solution to this?
Not with this plugin. It changes the way exp is earned, so you can’t really have exp split at the end of battle, and also exp earned during battle.
Would it be too hard to make an add-on that allows you to play an animation if a character levels up during battle?
I’m not sure how much work would be needed to add support for playing an animation.
Hello I really love this and want to say thanks for your work. I have a question, when a pj “miss” the attack, he/she wins exp. ¿How can I turn off the exp for miss?
What is the exp gain based on? You might want to check if damage was dealt. Something like including this condition in the formula:
b.result().hpDamage > 0
It doesn’t work with Yanfly’s Aftermath plugin. Even with the Fix provided. Instead, when I add the fix at the end of both plugins(yanfly’s and this one) it gives me a RangeError: Maximum stack call exceeded.
Is there someway to fix this?
I just tried it with aftermath and it works fine for me. If you have other plugins installed you’ll need to figure out which one is causing the problem.
Just to make sure I’m adding it right. I have to add the fix after all the code, right? Even after the closing braces, right?
I’m using almost all Yanfly’s plugins and some of yours.
The fix isn’t for the range error problem. You should create a new project to see if the two plugins work together.
Yeah, I know. However, the console says the error is in the Image of the error
Am I doing anything wrong? The console says the error is in your code. I don’t know why. Even if I disable all my other plugins, it continues to give me this error. I tried to create a new project, I tried to disable everything. I let enabled the core plugins and yours, yet, it continues to give this error every single time.
So… Either the fix is wrong, or I copy/pasted it wrong or I don’t know. I’m running MV 1.3.1. Everything works fine except when I put your “fix” in both Yanfly’s and yours. I don’t get it. 🙁
Set up the plugin in this project and see if the same error occurs. If it doesn’t, upgrade it to 1.3.1 and then test it again.
If the error occurs, send it to me and I will take a look.
I got it to work. I just didn’t add anything to Yanfly’s plugin whatsoever. No error and XP showing up mid-battle and also popping up.
This was the mistake all along. I added the fix code under both plugins, as it is stated in this website, but it didn’t need to be that way. I only added the fix to your plugin and everything is great.
Thanks for every help and everything. Really appreciate it.
Also, one question. My EXP keep showing up like “20.333333333” or “8.6666667” or “0.67748347”.
Is there a way to show only Integer numbers and not Float ones? It’s really annoying to see so many numbers at once, also the letter become so small due to this many numbers.
Is there a fix for this?
Thanks in advance.
Any advice on that exp float number issue?
Use Math.round( YOUR_FORMULA ) to round the exp off to an integer.
Is it possible that you could use this plugin to where they gain the XP during the battle by like… killing pawn enemies and then level up and are able to now use a new skill because say… they reached level 20, which was the prerequisite for learning a new skill?
You can level up during battle and learn skills based on your class requirements.
Sweet!
can’t i make the user get XP by simply perform an action?
If I have a plugin that adds levels to monsters, how could the formula be so if the monster is lvl 3 and the actor lvl 5, X ammount of xp would be substracted?
Loving the plugin, with that tweak I would use it.
You could for example say something like (assuming
level
is how you access the level property)b.isEnemy() && b.isDead() ? b.exp() + ((b.level - a.level) * (b.exp() * 0.1)) : 0
Which is basically (EXP + BONUS). The bonus can be positive or negative.
In our case, we add or subtract 10% depending on their level difference.
So if enemy was level 3 and actor was level 5, then the difference between enemy and actor is -2. Multiplied by 10% of enemy’s EXP, that means the attacker will gain only 80% of the EXP they would have originally obtained if the level was the same.
Depending on how complex the calculation is, you might introduce a plugin that will handle level difference calculations for you, and then plug that into the formula.