RMMV Damage Formula - ideas and help

● ARCHIVED · READ-ONLY
Started by Shaz 1539 posts Page 77 of 77 View original ↗
  1. PvtRyan96 said:
    What is wrong with my damage formula
    1 - There's no such thing as Math.arctan()

    2 - There's no such thing as enemy

    The JavaScript function for this is Math.atan():
    W3Schools.com
    I'm not sure why you correctly use b in one place but try to use enemy in another - the damage formula only has b.

    PvtRyan96 said:
    Now the complaint: It is very very frustrating to search for basic information on the syntax, operators, and formulae I must use for the damage formula in RPGM.
    Why?

    PvtRyan96 said:
    Does it obey typical PEMDAS?
    Yes.

    PvtRyan96 said:
    I literally have no idea where to even go for that information.
    Googling it worked fine for me.

    PvtRyan96 said:
    That kind of stuff should really be added to some of the damage formula tutorial posts, tbh.
    They don't get specifically into order of operations (because it is standard), but damage formula tutorial posts do have information on syntax, operators, and formulae.

    Damage Formulas 101
    As would any basic JavaScript tutorials, many of which come right up by Googling those words.

    As does, for that matter, MV's instructions, at least for the operators.
    1723251156788.png
  2. I do see an issue with that damage formula in general too. An enemy's level * enemy's level calculation is going to get very huge very fast, and massively dwarf your arctan * a.atk value very quickly. To demonstrate.

    A.atk caps at 999 in the database. So the most you can do is:

    4*999 which is 3996.

    But enemy level * enemy level caps at 99 in the engine, 99 * 99 is 9801, so you will be computing:

    3996 - 9801 = -5805. Which will be 0 in the engine.

    In fact, any enemy level 64 or over it is impossible to do damage to with this formula, as even 64 x 64 = 4096.

    This can be fixed by keeping enemy levels low, or plugins to go past the 999 limit in the database for ATK, but it is something you will need to consider as you set up the rest.
  3. caethyril said:
    Math.arctan does not exist; consider Math.atan instead:


    MV/Z damage formulae are JavaScript evals. Almost any JS is valid:
    Certain values like a and b are local variables defined specifically for ease of reference in the eval:
    rpg_objects.js excerpt
    JavaScript:
    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);
            var value = Math.max(eval(item.damage.formula), 0) * sign;
            if (isNaN(value)) value = 0;
            return value;
        } catch (e) {
            return 0;
        }
    };
    >arctan does not exist
    Curse my muscle memory; I was looking at quite literally that exact page and had convinced myself it was, like, some issue of RPGM using a different version of JavaScript and having different object names. Thank you -- it works perfectly as expected. I now feel very silly. Thank you for those links, though. I hope other people who were frustrated like I was (due to not knowing, like, any Javascript at all...) can find their way here and find that useful too.

    ATT_Turan said:
    I'm not sure why you correctly use b in one place but try to use enemy in another - the damage formula only has b.
    That seemed to be the language used in YEP_EnemyLevels.js. Attachment related. Is that not correct?
    ATT_Turan said:
    Why?
    Lack of JavaScript literacy makes it easy to second-guess one's self as to whether or not certain things hold true in certain cases or not, especially when the information comes from third-party sources that aren't specifically linked to RPGM. Do object names change per version? Does the damage formula box respect the same rules that JavaScript itself does? Do ALL parts of RPGM do so? For someone even less literate at it than I am, they might wonder if even the operators change per version (you and I know this is silly, but they might not). And if one thing is wrong in the implementation, prior knowledge does a lot of the heavy lifting when it comes to speculating as to *what part* was wrong, rather than simply then second-guessing the entire implementation and thinking "any singular part of this could be wrong and I don't know which one it is." And, naturally, prior knowledge also helps with the recognition of new information and the synthesis of it. Because I don't have that, it's hard to know if I am even looking at the right thing. Of course, I plan to learn more Javascript as I go along; I'm just relaying the source of the frustration in a way I hope conveys it well. Anyway, I digress, but that's why.
    bgillisp said:
    I do see an issue with that damage formula in general too. An enemy's level * enemy's level calculation is going to get very huge very fast, and massively dwarf your arctan * a.atk value very quickly.
    Don't worry, that's already being controlled for.
  4. FYI I merged your two posts together into one.
  5. PvtRyan96 said:
    That seemed to be the language used in YEP_EnemyLevels.js. Attachment related. Is that not correct?
    Those are examples. The word enemy there requires an actual reference in your game to an enemy - it might be going off of a specific member of the troop,
    Code:
    $gameTroop.members()[2].level

    or in the case of the damage formula, the battler you're hitting is always b
    Code:
    b.level

    PvtRyan96 said:
    Lack of JavaScript literacy makes it easy to second-guess one's self as to whether or not certain things hold true in certain cases or not, especially when the information comes from third-party sources that aren't specifically linked to RPGM. Do object names change per version? Does the damage formula box respect the same rules that JavaScript itself does? Do ALL parts of RPGM do so?
    I understand where you're coming from, but to me it's just sensible to see that "RPG Maker MV/MZ uses JavaScript," so I'm going to use JavaScript information. There's no real reason to think it wouldn't work unless, y'know, you try it and it doesn't :wink:

    And, again, there are certainly multiple sources of information about this which are specifically related to RPG Maker. The basic operators are listed in the help file, there are several tutorial threads on here which discuss operators and some of the commonly-used math functions, etc.

    I'm not trying to make you feel bad, I just didn't see how any of it was so hard to find that you had to express such uncertainty and frustration in your original post.

    I'm glad you got it working the way you want.

    As a side tip for troubleshooting - when things aren't working right, a helpful step is always to press F8 and go to the Console tab. Any code-related errors will print there - your formula should have generated errors for arctan not being a function as well as enemy being undefined.
  6. ATT_Turan said:
    Those are examples. The word enemy there requires an actual reference in your game to an enemy - it might be going off of a specific member of the troop,
    Code:
    $gameTroop.members()[2].level

    or in the case of the damage formula, the battler you're hitting is always b
    Code:
    b.level


    I understand where you're coming from, but to me it's just sensible to see that "RPG Maker MV/MZ uses JavaScript," so I'm going to use JavaScript information. There's no real reason to think it wouldn't work unless, y'know, you try it and it doesn't :wink:

    And, again, there are certainly multiple sources of information about this which are specifically related to RPG Maker. The basic operators are listed in the help file, there are several tutorial threads on here which discuss operators and some of the commonly-used math functions, etc.

    I'm not trying to make you feel bad, I just didn't see how any of it was so hard to find that you had to express such uncertainty and frustration in your original post.

    I'm glad you got it working the way you want.

    As a side tip for troubleshooting - when things aren't working right, a helpful step is always to press F8 and go to the Console tab. Any code-related errors will print there - your formula should have generated errors for arctan not being a function as well as enemy being undefined.
    Much appreciated on the console tip and the format of "b.level." I had assumed that because enemies don't have levels in the base game that that would be invalid.

    For the curious bystanders who might want to use a similar setup, the final formula I decided upon (for now) was:
    ( ( Math.atan(a.atk - b.def) + 2 ) * a.atk ) - ( Math.pow(b.level, 1.1) - Math.pow(a.level, 1.1) )
    Provides some nice, smooth values with the "anchor" value being the attacker's attack (double it, technically, but I'm personally fine with that) without letting things get out-of-hand too quickly where people suddenly start taking zero damage from everything. Changed the flat damage reduction to be a much more conservative value based upon level difference rather than raw enemy level. Requires Yanfly's Enemy Levels plugin, naturally.

    bgillisp said:
    FYI I merged your two posts together into one.
    Thanks. I had first replied before seeing the other posts at the time.
  7. I'm mostly working with Set Damage for my damage formulas, as in the damage is a fixed number with maybe one operation affecting it at best. However, I have states that reduce the defenses from the enemies. I'm trying to find a formula that will change that set damage according to the defense drops from that state

    (i.e. the base damage is 50 but the enemy has a 10% drop in defense so the formula would make it deal 55 damage)

    I'm unsure as to how to build the formula since it would be working with percentage stat changes
  8. Alkaline said:
    I'm mostly working with Set Damage for my damage formulas, as in the damage is a fixed number with maybe one operation affecting it at best. However, I have states that reduce the defenses from the enemies. I'm trying to find a formula that will change that set damage according to the defense drops from that state

    (i.e. the base damage is 50 but the enemy has a 10% drop in defense so the formula would make it deal 55 damage)

    I'm unsure as to how to build the formula since it would be working with percentage stat changes
    The easiest way would be to actually factor defense into the formula, like the default one does.

    If all battlers normally have the same defense, then that would be a set amount of damage under most circumstances; then debuffing it would increase the damage, like normal.
  9. So I have this formula for example:
    Formula example
    1728414146821.png

    With an enemy with 10 def it will deal 40 damage, with a 10% defense drop it will deal 41
    The issue I'm having is finding a way to put in the defense in the formula but to act it as a multiplier so instead of dealing 41 on a 10% defense debuff it would deal 55

    I was trying something along the lines of
    Code:
    50 * (1+(a.atk-b.def)/100)
    to try and get something like 50 *1.1 when the debuff is active, but it didnt work
  10. Alkaline said:
    So I have this formula for example:
    Okay...so that's not "set damage" to begin with, it already incorporates a variable. The enemy's defense. So my advice is less correct since that's out the window :guffaw:

    Alkaline said:
    The issue I'm having is finding a way to put in the defense in the formula but to act it as a multiplier
    You incorporate it as a multiplier. However, since it also needs to be subtracted from the original damage, you can't do it simply.

    If you have separate skills for enemies and actors (e.g. you know this skill can only hit enemies), then you can do:
    Code:
    b.enemy().params[3]
    to get their original defense value from the database.

    From there, simple division gives you the percentage you're looking for. So you could do something like
    [/code](50 - b.def) * b.enemy().params[3] / b.def[/code]
    That will do 40 damage against an enemy with defense 10, but 44 if they're reduced by 10%.

    If your skills can hit both enemies and actors, or if you just want something you can copy and paste into everything, you'd do
    Code:
    (b.isActor() ? b.actor().params[3] : b.enemy().params[3])
  11. ATT_Turan said:
    Okay...so that's not "set damage" to begin with, it already incorporates a variable. The enemy's defense. So my advice is less correct since that's out the window :guffaw:
    Yea sorry, I got it mixed up :rswt
    ATT_Turan said:
    If you have separate skills for enemies and actors (e.g. you know this skill can only hit enemies), then you can do:
    Code:
    b.enemy().params[3]
    to get their original defense value from the database.

    From there, simple division gives you the percentage you're looking for. So you could do something like
    [/code](50 - b.def) * b.enemy().params[3] / b.def[/code]
    That will do 40 damage against an enemy with defense 10, but 44 if they're reduced by 10%.
    Yes the skills are only to target enemies, the params[3] part was what I needed so now I can make a formula to extract the percentage difference and add it to the multiplier! Thanks!
  12. Since there's a damage formula sticky here, I'll ask my question here instead of making a whole new post, although I obviously can't go through all 77 pages to see if my question has been addressed.

    I wanted my damage formula to work in such a way that the actors always did at least a teeny bit of damage, even against high defense enemies, for a few different reasons, not least of which so they'd know whether it was in fact a high defense keeping them from hitting normally, or if the enemy was just resistant to all physical damage--something like that. So I thought of adding "+ a.level" to the end of my formula, with the understanding that this would add flat damage (with variance) based on the actor's level to any attack. Now I know enemies don't have levels (at least not without a plugin), so I figured this would just be like adding + 0 to their attacks. But instead, it results in them doing 0 damage every single time they attack. Why? Why wouldn't adding something that doesn't exist be just like adding 0?

    in case it matters, the full formula was "a.atk * 2 - b.def + a.level"
  13. ethervagabond said:
    instead, it results in them doing 0 damage every single time they attack. Why? Why wouldn't adding something that doesn't exist be just like adding 0?
    Because the formulas are purely javascript. In javascript, adding an undefined value to a number results in NaN, and the the function that calculates the damage using the formula has a safety measure where if the formula results in something that isnt a number, it makes the result 0.

    If you want to use that formula, it doesnt actually do everything you want either. If the enemy's def is greater than or equal to twice the actor's atk plus their level, then youll still get 0 as the result. Try
    Code:
    Math.max(a.atk * 2 - b.def, 0) + (a.level || 0)
    And that should work for both actors and enemies. You wont need to make separate skills, but without an enemy level plugin, it will never be an actual factor for them
  14. Robro33 said:
    If you want to use that formula, it doesnt actually do everything you want either. If the enemy's def is greater than or equal to twice the actor's atk plus their level, then youll still get 0 as the result. Try
    Code:
    Math.max(a.atk * 2 - b.def, 0) + (a.level || 0)
    And that should work for both actors and enemies. You wont need to make separate skills, but without an enemy level plugin, it will never be an actual factor for them

    Thanks! Hey, can you let me know what "Math.max" and "||" actually do, in case I want to tweak it later? Oh, and also that ", 0" you put after "b.def" ? I'd really appreciate it :)
  15. As mentioned, the formula is JS. As long as what you use forms valid JS, it can be used.

    Math.max() is a function that takes numbers and returns the highest number in the set it was given (its mentioned on the first page). You needed it because you wanted the level bonus to be added to the formula in a way that it would allow disallow 0s. By taking your formula and imposing a minimum of 0 there theough Math.max(x,0), it prevents the negative value of def being more than double atk from deducting from the level factor.

    The || is the OR operator in JS. The general use of it is to control logic within conditional statements, but because of how it works, it can also be used to provide a default value incase the value of something youre trying to use may be undefined (falsy really, but the distinction isnt important here). Since enemies dont have levels, a.level will always be undefined if the user is an enemy. In that case it will use 0 instead. For actors, it will use their level as theyll always have a level to use
  16. im not used to writing complex formulas and i havent really been able to find out if i can do what i want through searching so if possible,
    how would i write a formula using luck(its normal function is disabled its been renamed and repurposed for this) to multiply damage based on the percentage of the parameter

    to better explain, if i have a parameter that rises in 15 increments of 20 up to 300 throughout the game what formula would be able to multiply damage x1.2 for each increment of 20 (for example 20 luck on an attack thats going to deal 25 damage would mean a x1.2 increase in damage totaling to 30, and 300 luck would mean a x18 increase in damage totaling to 450 damage)
    apologize for any inaccuracies math was never something i was good at but thats the general idea
  17. sudo7777 said:
    i have a parameter that rises in 15 increments of 20 up to 300 throughout the game what formula would be able to multiply damage x1.2 for each increment of 20
    if luck is only gained in set increments, you could have divided it by 20 to get the number of increments and then multiply that by 1.2
    Code:
    a.luk/20*1.2
    , or you could have divided your parameter by 20/1.2
    Code:
    a.luk/(20/1.2)

    but the other thing is if luck is only gained in those static increments, then whats the point of the increment itself? why not let each increment be a gain of 1 luck instead of 20? having the parameter be 1-15 is going to be easier to work with than 20-300 thats always going to be divided by 20 internally.
  18. It might make sense if the fixed increment is different for each class? In which case, your solution won't help at all…
  19. Robro33 said:
    if luck is only gained in set increments, you could have divided it by 20 to get the number of increments and then multiply that by 1.2
    Code:
    a.luk/20*1.2
    , or you could have divided your parameter by 20/1.2
    Code:
    a.luk/(20/1.2)

    but the other thing is if luck is only gained in those static increments, then whats the point of the increment itself? why not let each increment be a gain of 1 luck instead of 20? having the parameter be 1-15 is going to be easier to work with than 20-300 thats always going to be divided by 20 internally.
    it originally was only going to be 12 increments and honestly my only reason was that 12 was a weird number but after changing it to 15 youre right theres no reason for me not to do that