Yanfly Core Engine - Error during Side View Battle

Status
Not open for further replies.

Archeia

Level 99 Demi-fiend
Staff member
Developer
Joined
Mar 1, 2012
Messages
15,307
Reaction score
15,772
First Language
Filipino
Primarily Uses
RMMZ
I was replying to your post by order. Like I said it was confusing.

I am confused even more now, after reading this. in (no.1), you said "that's the last one". I do not understand what that is in reference to. Do you mean by last one, that no more branches will develop on the forums? or does it mean something else?
I meant that we haven't done any forum layout changes unless necessary.

in (no.2) I do not understand no.2 at all. You said that "it's in" the javascript department. Then you contradicted your own statement by saying at the end : "but if it's from play-testing, then it means it's in the core engine"
The core engine is the javascript files. You need these files because they are the meat of MV games.


Not the editor engine. The editor just helps you create your game visually but it isn't required to play any MV games. Is that clearer?

(No.4) you said you have not encountered this problem in 2 months. I believe that completely, because I, myself have not incurred this problem  in two months. that's because It just happened today to me, Overall, I get the basic gist of your reply...it is just the things I pointed out here that are confusing to me. As for posting my battle formulas, what do you mean by "over here". is "over here" this page?
Over here as in this topic or page yes.
 
Last edited by a moderator:

DoubleX

Just a nameless weakling
Veteran
Joined
Jan 2, 2014
Messages
1,817
Reaction score
969
First Language
Chinese
Primarily Uses
N/A
After a brief investigation, right now I can come up with 2 possibilities:

1. Like what DarkDesu said in #15 - There's something wrong with the damage formula.

If that's the case, then the error should occur whenever skills/items having such problematic formulae are used.

2. One of the targets having grd as 0% is guarding when hit.

If that's the case, then the error should occur whenever one of the targets having grd as 0% is guarding when hit.

If neither's your case, you can place this diagnose snippet above all custom plugins and check what's logged on the console:

Game_Action.prototype.makeDamageValue = function(target, critical) { // Rewrite var item = this.item(); console.log("subject", this.subject().name, "item", item.name, "target", target.name, "critical", critical); // Added var baseValue = this.evalDamageFormula(target); console.log("baseValue = this.evalDamageFormula(target)", baseValue); // Added var value = baseValue * this.calcElementRate(target); console.log("value = baseValue * this.calcElementRate(target)", value); // Added if (this.isPhysical()) { value *= target.pdr; console.log("value *= target.pdr", value); // Added } if (this.isMagical()) { value *= target.mdr; console.log("value *= target.mdr", value); // Added } if (baseValue < 0) { value *= target.rec; console.log("value *= target.rec", value); // Added } if (critical) { value = this.applyCritical(value); console.log("value = this.applyCritical(value)", value); // Added } value = this.applyVariance(value, item.damage.variance); console.log("value = this.applyVariance(value, item.damage.variance)", value); // Added value = this.applyGuard(value, target); console.log("value = this.applyGuard(value, target)", value); // Added value = Math.round(value); console.log("value = Math.round(value)", value); // Added return value;}; // Game_Action.prototype.makeDamageValueGame_Action.prototype.executeHpDamage = function(target, value) { // Rewrite if (this.isDrain()) { value = Math.min(target.hp, value); console.log("value = Math.min(target.hp, value)", value); // Added } this.makeSuccess(target); target.gainHp(-value); if (value > 0) { target.onDamage(value); } this.gainDrainedHp(value);}; // Game_Action.prototype.executeHpDamageGame_Action.prototype.executeMpDamage = function(target, value) { // Rewrite if (!this.isMpRecover()) { value = Math.min(target.mp, value); console.log("value = Math.min(target.mp, value)", value); // Added } if (value !== 0) { this.makeSuccess(target); } target.gainMp(-value); this.gainDrainedMp(value);}; // Game_Action.prototype.executeMpDamageGame_Action.prototype.itemEffectRecoverHp = function(target, effect) { // Rewrite var value = (target.mhp * effect.value1 + effect.value2) * target.rec; console.log("value = (target.mhp * effect.value1 + effect.value2) * target.rec", value); // Added if (this.isItem()) { value *= this.subject().pha; console.log("value *= this.subject().pha", value); // Added } value = Math.floor(value); console.log("value = Math.floor(value)", value); // Added if (value !== 0) { target.gainHp(value); this.makeSuccess(target); }}; // Game_Action.prototype.itemEffectRecoverHpGame_Action.prototype.itemEffectRecoverMp = function(target, effect) { // Rewrite var value = (target.mmp * effect.value1 + effect.value2) * target.rec; console.log("value = (target.mmp * effect.value1 + effect.value2) * target.rec", value); // Added if (this.isItem()) { value *= this.subject().pha; console.log("value *= this.subject().pha", value); // Added } value = Math.floor(value); console.log("value = Math.floor(value)", value); // Added if (value !== 0) { target.gainMp(value); this.makeSuccess(target); }}; // Game_Action.prototype.itemEffectRecoverHp
About the technical stuff:

While the default RMMV codebase tried to catch for errors in the damage formula and do the boundary checks for the final value, neither of them are fool proof.

Case 1 - A problematic damage formula's used

Let's consider the example gave by DarkDesu in #15:

a.matkAs battlers don't have matk in the default RMMV codebase, a.matk will return undefined.

Consider the function evaluating the damage formula:

Game_Action.prototype.evalDamageFormula = function(target) { try { var item = this.item(); var a = this.subject(); var b = target; var v = $gameVariables._data; var sign = ([3, 4].contains(item.damage.type) ? -1 : 1); return Math.max(eval(item.damage.formula), 0) * sign; } catch (e) { return 0; }};
If at least 1 argument of Math.max is NaN(eval(item.damage.formula) in this case), it'll also return NaN.

Also, when a number does an arithmetic operation with NaN(NaN * sign in this case), the result will be NaN too.

Thorough the entire process, no errors will be catched, however.

The return value, NaN in this case, will be carried all along:

Game_Action.prototype.makeDamageValue = function(target, critical) {    var item = this.item();    var baseValue = this.evalDamageFormula(target);    var value = baseValue * this.calcElementRate(target);    if (this.isPhysical()) {        value *= target.pdr;    }    if (this.isMagical()) {        value *= target.mdr;    }    if (baseValue < 0) {        value *= target.rec;    }    if (critical) {        value = this.applyCritical(value);    }    value = this.applyVariance(value, item.damage.variance);    value = this.applyGuard(value, target);    value = Math.round(value);    return value;};Game_Action.prototype.executeDamage = function(target, value) { var result = target.result(); if (value === 0) { result.critical = false; } if (this.isHpEffect()) { this.executeHpDamage(target, value); } if (this.isMpEffect()) { this.executeMpDamage(target, value); }};Game_Action.prototype.executeHpDamage = function(target, value) { if (this.isDrain()) { value = Math.min(target.hp, value); } this.makeSuccess(target); target.gainHp(-value); if (value > 0) { target.onDamage(value); } this.gainDrainedHp(value);};Game_Action.prototype.executeMpDamage = function(target, value) { if (!this.isMpRecover()) { value = Math.min(target.mp, value); } if (value !== 0) { this.makeSuccess(target); } target.gainMp(-value); this.gainDrainedMp(value);};Game_Action.prototype.gainDrainedHp = function(value) { if (this.isDrain()) { this.subject().gainHp(value); }};Game_Action.prototype.gainDrainedMp = function(value) { if (this.isDrain()) { this.subject().gainMp(value); }};
Code:
Game_Battler.prototype.gainHp = function(value) {    this._result.hpDamage = -value;    this._result.hpAffected = true;    this.setHp(this.hp + value);};Game_Battler.prototype.gainMp = function(value) {    this._result.mpDamage = -value;    this.setMp(this.mp + value);};
Until Game_BattlerBase.prototype.refresh is reached, where boundary checks will be done:

Game_BattlerBase.prototype.refresh = function() { this.stateResistSet().forEach(function(stateId) { this.eraseState(stateId); }, this); this._hp = this._hp.clamp(0, this.mhp); this._mp = this._mp.clamp(0, this.mmp); this._tp = this._tp.clamp(0, this.maxTp());};
Where Math.clamp is this:

/** * Returns a number whose value is limited to the given range. * * @method Number.prototype.clamp * @param {Number} min The lower boundary * @param {Number} max The upper boundary * @return {Number} A number in the range (min, max) */Number.prototype.clamp = function(min, max) { return Math.min(Math.max(this, min), max);};
If at least 1 argument of Math.max is NaN(this._hp in this case), it'll also return NaN. The same goes for Math.min.

It means that the above boundary check will fail if the original value is NaN to begin with.

Case 2 - One of the targets having grd as 0% is guarding when hit

grd is applied in Game_Action.prototype.applyGuard:

Game_Action.prototype.applyGuard = function(damage, target) { return damage / (damage > 0 && target.isGuard() ? 2 * target.grd : 1);};
If target.grd is 0, the result will become a damage / 2 * 0, which is infinity and thus NaN.

The return value, NaN in this case, will be carried all along:

Game_Action.prototype.executeDamage = function(target, value) { var result = target.result(); if (value === 0) { result.critical = false; } if (this.isHpEffect()) { this.executeHpDamage(target, value); } if (this.isMpEffect()) { this.executeMpDamage(target, value); }};Game_Action.prototype.executeHpDamage = function(target, value) { if (this.isDrain()) { value = Math.min(target.hp, value); } this.makeSuccess(target); target.gainHp(-value); if (value > 0) { target.onDamage(value); } this.gainDrainedHp(value);};Game_Action.prototype.executeMpDamage = function(target, value) { if (!this.isMpRecover()) { value = Math.min(target.mp, value); } if (value !== 0) { this.makeSuccess(target); } target.gainMp(-value); this.gainDrainedMp(value);};Game_Action.prototype.gainDrainedHp = function(value) { if (this.isDrain()) { this.subject().gainHp(value); }};Game_Action.prototype.gainDrainedMp = function(value) { if (this.isDrain()) { this.subject().gainMp(value); }};
Code:
Game_Battler.prototype.gainHp = function(value) {    this._result.hpDamage = -value;    this._result.hpAffected = true;    this.setHp(this.hp + value);};Game_Battler.prototype.gainMp = function(value) {    this._result.mpDamage = -value;    this.setMp(this.mp + value);};
Until Game_BattlerBase.prototype.refresh is reached, where boundary checks will be done:

Game_BattlerBase.prototype.refresh = function() { this.stateResistSet().forEach(function(stateId) { this.eraseState(stateId); }, this); this._hp = this._hp.clamp(0, this.mhp); this._mp = this._mp.clamp(0, this.mmp); this._tp = this._tp.clamp(0, this.maxTp());};
Where Math.clamp is this:

/** * Returns a number whose value is limited to the given range. * * @method Number.prototype.clamp * @param {Number} min The lower boundary * @param {Number} max The upper boundary * @return {Number} A number in the range (min, max) */Number.prototype.clamp = function(min, max) { return Math.min(Math.max(this, min), max);};
If at least 1 argument of Math.max is NaN(this._hp in this case), it'll also return NaN. The same goes for Math.min.

It means that the above boundary check will fail if the original value is NaN to begin with.



Anyway, I'd suggest the below parts of the default RMMV codebase to be changed into something like these:

Code:
Game_Action.prototype.evalDamageFormula = function(target) {    try {        var item = this.item();        var a = this.subject();        var b = target;        var v = $gameVariables._data;        var sign = ([3, 4].contains(item.damage.type) ? -1 : 1);        // Rewritten        var value = Math.max(eval(item.damage.formula), 0) * sign;        if (isNan(value)) {            console.log("The damage formula: " + item.damage.formula + " of item: " + item.name + " used by subject: " + a.name + " targeting target: " + b.name + " has return NaN.");            // Exceptions can also be thrown right afterwards if it'd do more good than harm here in most cases        }        return value;        //    } catch (e) {        console.log("Game_Action.prototype.evalDamageFormula", e.name, e.message); // Added        return 0;    }};
Code:
Game_Action.prototype.applyGuard = function(damage, target) {    var value = damage / (damage > 0 && target.isGuard() ? 2 * target.grd : 1);    if (isNan(value)) {    console.log("The grd of target: " + target.name + " is 0");    // Exceptions can also be thrown right afterwards if it'd do more good than harm here in most cases    }};
 
Last edited by a moderator:

RPGcrafter07

Veteran
Veteran
Joined
Jan 22, 2016
Messages
31
Reaction score
4
First Language
English
Primarily Uses
Here's a question for yah, what do you do if you go into battle the characters come one screen and then you get "Type Error undefined is not a function" without doing anything at all! Then to top it off, f8 doesn't work either. :(
 

Tyrael79

Veteran
Veteran
Joined
Jan 10, 2016
Messages
90
Reaction score
15
First Language
english
Primarily Uses
I had this error and managed to solve it.


Mine would always occur when I cast a resurrection spell.


It turned out that as a result of the way I wrote my resurrection spell it would go into an infinite loop as it tried to remove the knockout status before appling the healing.


How it was: I initially create the spell to have the effect of recovering< X> HP, and remove the effect knockout,


Despite the recover being before the remove knock out effect it the system tried to remove knockout before the healing.


How I Fixed it: I just changed the healing part of my spell to be in the formula section and it resolved the issue.


As such It would seem that the "formula section" of the skill is applied first, then the Effects Section.


Possibly one of your skills \ states are set up in such a way that causes a similar issue. Hopefully this might point you in a direction that will help you troubleshoot whats causing your error.
 

Coopziana

Veteran
Veteran
Joined
Jan 18, 2016
Messages
115
Reaction score
51
First Language
English
The problem is that you have "a.level" in your skill formula and enemies don't have a.level or b.level. That is why the error occurs! Even when using yanfly's enemy level scrips it will not solve the issue.


If you wish to use a.level in a skill that both party and enemies use you'll probably have to setup a.level as a variable instead and use a common event or yanfly's action sequence pack to edit the variable based on who is using the skill.


Reason I write this now is that I've just come up against this issue myself and am looking for a simple way around it without having to write a load of commands/scrips for it!
 

MadeBySaints

Villager
Member
Joined
Sep 23, 2016
Messages
24
Reaction score
14
First Language
English
Primarily Uses
Had this error and couldn't figure out why it was happened. Turned out I had messed up a damage formula for Fire. Instead of a.mat, I had put a.matk.

Double check all your formulas and see if any of the paramaters are wrong.

You rock! I couldnt figure out what in the world was going on... turns out my b.mdf was set to b.mdef -.-
i was so happy when i read your post. 
 
Joined
Mar 10, 2018
Messages
2
Reaction score
0
First Language
English
Primarily Uses
RMMV
I am also running into this Issue. For Extreme Darkness: It only seems to happen with HP Drain. If I switch it to HP Damage it works but does no Damage. For Attacks (Short for Attack Slash) it was working fine but now brings up the same error. All the plugins I use are fully updated as of 6/3/2018.Screenshot (14).png Screenshot (13).png
 

bgillisp

Global Moderators
Global Mod
Joined
Jul 2, 2014
Messages
13,789
Reaction score
14,591
First Language
English
Primarily Uses
RMVXA
@Zoran_BlackRose : It would be best if you post a new thread for this, as this thread is over 2 years old and was for a different version of MV so the solutions here will not work for you.
 
Status
Not open for further replies.

Latest Threads

Latest Profile Posts

I've been getting into YuGiOh again!
Gameboy Tiles, Cure Writer's Block, Animations on Menu, Generate Tasks | RPG Maker News #40

How would you judge a game you played? Art/Graphics? Story? Gameplay?
Learn MV sales goal = 2%
NSFW game sales goal = 2500% (no jokes) :guffaw:

Forum statistics

Threads
111,377
Messages
1,060,596
Members
144,706
Latest member
DonTonyPepperoni
Top