RMMV Damage Formula - ideas and help

Discussion in 'RPG Maker MV' started by Shaz, Oct 25, 2015.

  1. Kryss

    Kryss Villager Member

    Messages:
    16
    Likes Received:
    1
    First Language:
    Spanish
    Primarily Uses:
    RMMV
    Thank you! I will try to put this and see if it works ^^
     
    Silva likes this.
  2. Nilom

    Nilom Veteran Veteran

    Messages:
    178
    Likes Received:
    39
    First Language:
    German
    Primarily Uses:
    RMMV
    That's a good solution! Actually I would put the damage formula before the state evaluation. For the reasons I mentioned in my last comment. If her character, for example, does more damage on stunned enemies than it could be faulty that way. Or if another bomb adds a debuff that reduces the defense, than the bomb would benefit itself from an effect that should be applied after the detonation, not before.

    Code:
    damageFormula; if (a.hasWeapon($dataWeapons[weaponId]) && (b.isStateAffected(confusedId) || b.isStateAffected(blindId) || Math.randomInt(100) < 25)) {b.addState(stunId)}



    Edit:
    I have two questions.

    Question 1:
    Is it possible to use global $variables in the formula field and will they be useable in the editors test battles?
    I'm thinking of the case that I design 100 or 200 skills and then I realize that I need to rebalance my base formula. That would be pure horror!

    I'm thinking of setting something like this up, in the common event that will initialize all important variables:

    Code:
    //base formula
    $formula_physical = (1+(a.atk-b.def)/200).clamp(0.25, 1.75)
    $formula_magical = (1+(a.mat-b.mdef)/200).clamp(0.25, 1.75)
    

    And then use it in the skill formula field:

    Code:
    (a.luk * 1.5) * $formula_physical
    The example above would have 150% weapon damage as base damage multiplied by the base formula.


    Question 2:
    How can I access the Off-Hands defense param?

    When I have a mainhand weapon with wtype ID 7 equipped it works. But if not it doesn't work, even though I check for off-hand ID 5.

    Code:
    <Custom Requirement>
    if (user.isAtypeEquipped(5)) {
    value = true;
    } else {
    value = false;
    }
    </Custom Requirement>
    
    That seems strange. Is there another way or does someone see the bug?
     
    Last edited: Jun 14, 2019
  3. Engr. Adiktuzmiko

    Engr. Adiktuzmiko Chemical Engineer, Game Developer, Using BlinkBoy' Veteran

    Messages:
    14,571
    Likes Received:
    2,921
    Location:
    Philippines
    First Language:
    Tagalog
    Question 1:

    Yes, you can use global variables in your damage formulas. You can also opt to use a function instead.

    Personally I use a custom defined function as my base formula and just have each skill send parameters to that base formula.

    Question 2: The behavior is weird, for one, it only checks the armors so your mainhand weapon shouldnt even be affecting the result of that code

    Also, this probably wont help with the problem but I think you can shorten it to

    value = a.isAtypeEquipped(id);

    since the function returns true or false anyway, and you only need to know if its true or false. Using an if would only make more sense if you need to something else when its true or false.
     
    Nilom likes this.
  4. Nilom

    Nilom Veteran Veteran

    Messages:
    178
    Likes Received:
    39
    First Language:
    German
    Primarily Uses:
    RMMV
    Thank you for the reply!

    Oh that seems like a smart way to do! I will just ninja that. Do you set the function up in a .js plugin file? I will have to look into functions, as I never sat one up myself yet.

    Yes it is weird. But I didn't bug hunt it extensively. Later I will smash some functions through the debug tool and check some IDs.

    Ahhh, you are totally right! Thank you for this advice. It is always beneficial to clean up and simplify the code. I will change and remember this. :LZScheeze:

    Not sure if this is the right place to ask this but do you (or someone else) know if I can change the text color when gaining mp? The background is that I use Yanflys Skill Rewards plugin to restore "MP" on my Warrior-like class when Shield-Smashing. And the MP number is blue, but Rage is something like red. Just a very tiny detail. I could live with that, if it can't be done without great efforts. :LZSjoy:


    Edit:
    Okay after some more testing I found the fault by myself. xD
    When I initially created the skill I sat weapon requirements in the skill tabs, for testing purposes. Obviously I forgot to remove that. :LZSoops:

    I got it working that way:
    Code:
    <Custom Requirement>
    if (user.equips()[1] && user.isAtypeEquipped(5)) {
    value = true;
    } else {
    value = false; }
    </Custom Requirement>
     
    Last edited: Jun 14, 2019
  5. Silva

    Silva Scoobityboo Veteran

    Messages:
    292
    Likes Received:
    142
    First Language:
    English
    Primarily Uses:
    RMMV
    You can define them in a .js file or if it's only a short function you can use the script event command to define the function (autorun/parallel at start of game, perhaps). Using a .js file and adding it to your plugin list is probably the better option. Functions are relatively easy to define, something like this would work to replicate MV's default damage formula

    Code:
    baseDamageFormula = function(a, b) {
        var damage = a.atk * 4 - b.def * 2;
        return damage
    }
    
    //to call in battle formula
    baseDamageFormula(a, b)
     
    Nilom likes this.
  6. Nilom

    Nilom Veteran Veteran

    Messages:
    178
    Likes Received:
    39
    First Language:
    German
    Primarily Uses:
    RMMV
    Thank you for the example! What I did not understand yet is: Can the function use a.atk and b.def and things like a.equips()[1].params[3] or do I need to define every single param etc. in the function call?

    Like this:
    Code:
    baseDamageFormula(a.atk, b.def, a.equips()[1].params[3])

    Or would this work?
    Code:
    function damage_formula(type){
        switch(true){
            case (type == "physical"): return (1+(a.atk-b.def)/200).clamp(0.25, 1.75);
            case (type == "magical"): return (1+(a.matk-b.mdef)/200).clamp(0.25, 1.75);
            case (type == "shield"): return (a.equips()[1].params[3] * 2) * (1+(a.atk-b.def)/200).clamp(0.25, 1.75);
            case (type == "offhand"): return a.equips()[1].params[2] * (1+(a.atk-b.def)/200).clamp(0.25, 1.75);
        }
    }
    
    And in the skill databases formula field:
    Code:
    (a.luk*1.5) * damage_formula("physical")
    
    Would it work that way or do I need to send all parameters like a.atk to the function?

    And can I define constants in the .js file too that will always be defined (=usable)?
    Like:
    Code:
    $hp = 0
    $mp = 1
    $atk = 2
    $def = 3
    $mat = 4
    $mdef = 5
    $agi = 6
    $luk = 7
    
    So that this can be done?
    Code:
    a.equips()[1].params[$atk]

    Edit:

    Meanwhile I did some testing and got to the following cognizances:
    1) All battle parameters used need to be passed.
    2) Constants can be set and are quite handy.

    Code:
    //function for custom damage formula in the editors database
    
    function damage_formula(type, a_atk, a_mat, b_def, b_mdf){
        switch(true){
            case (type == "physical"): console.log("physical formula"); return (1+(a_atk-b_def)/200).clamp(0.25, 1.75);
            case (type == "magical"): console.log("magical formula"); return (1+(a_matk-b_mdf)/200).clamp(0.25, 1.75);
            case (type == "shield"): console.log("shield formula"); return (1+(a_atk-b_def)/200).clamp(0.25, 1.75);
            case (type == "offhand"): console.log("offhand formula"); return (1+(a_atk-b_def)/200).clamp(0.25, 1.75);
        }
    }
    
    
    //defining constants
    
    //params
    $hp = 0;
    $mp = 1;
    $atk = 2;
    $def = 3;
    $mat = 4;
    $mdf = 5;
    $agi = 6;
    $dmg = 7;
    
    //equip types
    $main = 0;
    $off = 1;
    $head = 2;
    $body = 3;
    $belt = 4;
    $legs = 5;
    $feet = 6;
    $hands = 7;
    $acc = 8;
    
    //script movement commands
    $turn_left = 17;
    $turn_up = 19;
    $turn_right = 18;
    $turn_down = 16;
    $move_forward = 12;
    $step_forward = 12;
    
     
    Last edited: Jun 14, 2019
  7. Silva

    Silva Scoobityboo Veteran

    Messages:
    292
    Likes Received:
    142
    First Language:
    English
    Primarily Uses:
    RMMV
    There's no need to add anything extra for use with "a" and "b", anything that works in the damage formula on them will work in this function as well.

    This wouldn't work because when you've declared your function you haven't added the parameters "a" or "b", but you are using them for your calculations, so this would cause errors "can't read property atk of undefined" etc. Example:

    Code:
    //function call
    baseDamageFormula(a, b, type)
    
    //function declaration
    baseDamageFormula = function(a, b, type) {
     //code
    }
    There's nothing stopping you defining constants and variables in your .js file for later use as well.

    EDIT: RE multiplying by the function - you can do this. eg a.luk * 1.5 * formula(a, b, type)
     
    Engr. Adiktuzmiko and Nilom like this.
  8. Nilom

    Nilom Veteran Veteran

    Messages:
    178
    Likes Received:
    39
    First Language:
    German
    Primarily Uses:
    RMMV
    Oh I guess you didn't see my last comments spoiler. You are right, I got an error that a/b are not defined. So I edited it.

    But I did it the stupid way. I didn't know that a and b can be sent to the function. And I thought I have to do this for all the params that I will ever use in the function.. :biggrin:
    So, thanks for the example! :LZSsmile:
     
    Silva likes this.
  9. Silva

    Silva Scoobityboo Veteran

    Messages:
    292
    Likes Received:
    142
    First Language:
    English
    Primarily Uses:
    RMMV
    No problem. :) The a and b parameters are just references to the subject and target so you can do anything to them that you can do to a battler.

    Another something you might find useful - because of where the damage formula is executed (ie. within Game_Action) you don't actually need to pass the action type to the function. You can refer to the action itself using "this" so rather than pass the type in the parameters you could use

    Code:
    this.isPhysical()
    this.isMagical()
    this.isCertainHit()
    Along with any other function that is defined for Game_Action. I know that doesn't help with your "shield" and "offhand" types but it's still worth mentioning.
     
    Nilom likes this.
  10. Nilom

    Nilom Veteran Veteran

    Messages:
    178
    Likes Received:
    39
    First Language:
    German
    Primarily Uses:
    RMMV
    Oh that's quite useful! The less I have to type the better it is!

    That's what I've came up with:
    Code:
    function damage_formula(type, a, b) {
        if (this.isCertainHit()) { console.log("Certain"); return 1; }
        else {
        switch(true){
            case (type == ""):
                if (this.isPhysical()) { console.log("Normal Physical"); return (1+(a.atk-b.def)/200).clamp(0.25, 1.75); }
                if (this.isMagical()) { console.log("Normal Magical"); return (1+(a.matk-b.mdf)/200).clamp(0.25, 1.75); }
                break;
            case (type == "shield"):
                if (this.isPhysical()) { console.log("Shield Physical"); return (1+(a.atk-b.def)/200).clamp(0.25, 1.75); }
                if (this.isMagical()) { console.log("Shield Magical"); return (1+(a.matk-b.mdf)/200).clamp(0.25, 1.75); }
                break;
            case (type == "offhand"):
                if (this.isPhysical()) { console.log("Offhand Physical"); return (1+(a.atk-b.def)/200).clamp(0.25, 1.75); }
                if (this.isMagical()) { console.log("Offhand Magical"); return (1+(a.matk-b.mdf)/200).clamp(0.25, 1.75); }
                break;
            }
        }
    }
    
    Is it optimal that way? :LZSsmile:


    Edit:
    It didn't work that way. It tells me that this.isCertainHit() is not a function. :LZSsad:
     
    Last edited: Jun 16, 2019
  11. Silva

    Silva Scoobityboo Veteran

    Messages:
    292
    Likes Received:
    142
    First Language:
    English
    Primarily Uses:
    RMMV
    That's a mistake on my part. It would work in the damage formula, so you can pass the function this and then use any of the Game_Action functions within your function. My apologies.

    Code:
    //example function
    damageFormula(a, b, action) {
        if (action.isCertainHit()) return a.atk*4 - b.def*2
    }
    
    //example function call
    damageFormula(a, b, this)
     
  12. Nilom

    Nilom Veteran Veteran

    Messages:
    178
    Likes Received:
    39
    First Language:
    German
    Primarily Uses:
    RMMV
    Don't worry. Mistakes can happen. :LZScheeze:

    Unfortunately I tried this already and I tried it again now. It crashes my game when the enemy attacks. (Normal attack calls the function too)

    [​IMG]

    This is what I get. The text above is unimportant. :LZSgrin:


    Edit:
    That's how my function looks now:
    Code:
    function damage_formula(type, a, b, action) {
        console.log(action)
        if (action.isCertainHit()) { console.log("Certain"); return 1; }
        else {  
        switch(true){
            case (type == ""):
                if (action.isPhysical()) { console.log("Normal Physical"); return (1+(a.atk-b.def)/200).clamp(0.25, 1.75); }
                if (action.isMagical()) { console.log("Normal Magical"); return (1+(a.matk-b.mdf)/200).clamp(0.25, 1.75); }
                break;
            case (type == "shield"):
                if (action.isPhysical()) { console.log("Shield Physical"); return (1+(a.atk-b.def)/200).clamp(0.25, 1.75); }
                if (action.isMagical()) { console.log("Shield Magical"); return (1+(a.matk-b.mdf)/200).clamp(0.25, 1.75); }
                break;
            case (type == "offhand"):
                if (action.isPhysical()) { console.log("Offhand Physical"); return (1+(a.atk-b.def)/200).clamp(0.25, 1.75); }
                if (action.isMagical()) { console.log("Offhand Magical"); return (1+(a.matk-b.mdf)/200).clamp(0.25, 1.75); }
                break;
            }
        }
    }
    
     
  13. Silva

    Silva Scoobityboo Veteran

    Messages:
    292
    Likes Received:
    142
    First Language:
    English
    Primarily Uses:
    RMMV
    Looks to me like an issue drawing gauges rather than anything wrong with the values being passed to your function. Seems to be trying to draw gauges with incorrect numbers (null, undefined, infinity). The console is definitely logging the action itself.
     
    Nilom likes this.
  14. Nilom

    Nilom Veteran Veteran

    Messages:
    178
    Likes Received:
    39
    First Language:
    German
    Primarily Uses:
    RMMV
    But the game only crashes with my function call. I removed it from the skill formula windows and now it doesn't crash anymore. :LZSsad:
     
  15. Silva

    Silva Scoobityboo Veteran

    Messages:
    292
    Likes Received:
    142
    First Language:
    English
    Primarily Uses:
    RMMV
    I can't say for certain what the issue is, but my concern is your switch statement. I don't think it's evaluating anything. It may be worth swapping these for if statements, and possibly adding a 'return 0' line to the bottom of your function so as to ensure you're still passing a finite number back from the function.
     
    Nilom likes this.
  16. Nilom

    Nilom Veteran Veteran

    Messages:
    178
    Likes Received:
    39
    First Language:
    German
    Primarily Uses:
    RMMV
    Oh you are absolutely right! With the return 0 added to the bottom the game will not crash anymore. But why is this? I thought I used a true switch successfully before. Did I use wrong syntax or wrong logic?


    Edit:
    Okay seems like I'm officially an idiot. I still had my old function call in the normal attack skill which sat type to "physical". :kaodes:
    Setting that to "" solved the issue. The true switch is working now. :LZScheeze:
    Thank you again for your help! :kaohi:
     
    Last edited: Jun 16, 2019
    Silva likes this.
  17. Silva

    Silva Scoobityboo Veteran

    Messages:
    292
    Likes Received:
    142
    First Language:
    English
    Primarily Uses:
    RMMV
    I'll be honest with you, I don't really use switch statements all that often. My understanding is for your use you'd want to set it up like so:

    Code:
    switch(type) {
       case "shield":
          //code
       case "offhand":
          //code
       default:
          //code
    }
     
    Nilom likes this.
  18. Engr. Adiktuzmiko

    Engr. Adiktuzmiko Chemical Engineer, Game Developer, Using BlinkBoy' Veteran

    Messages:
    14,571
    Likes Received:
    2,921
    Location:
    Philippines
    First Language:
    Tagalog
    @XZINED - your way of using a Switch case is kinda off.. See Silva's code for a better or at least the normal usage of a Switch case
     
  19. Nilom

    Nilom Veteran Veteran

    Messages:
    178
    Likes Received:
    39
    First Language:
    German
    Primarily Uses:
    RMMV
    True switches are indeed normal ways to use switches.
    Maybe it was not beneficial in my case though. But they are useful to have multiple cases trigger if the break is omitted.
    But I already changed the switch to "normal usage". :LZScheeze:
     
  20. jetboost

    jetboost Veteran Veteran

    Messages:
    84
    Likes Received:
    26
    First Language:
    Dutch
    Primarily Uses:
    RMMV
    So i've been watching on as an onlooker mostly because i'm feeling a bit salty that I didn't think of something like this for my own.
    I had used common events to create damage formulas but because you couldn't call a and b and thus also not their stats you had to define them all yourself and put them in gameVariables and then make use of them in the damage formula noteboxand this had to be done for every actor you may or may not want to have in your game.
    Needless to say everything turned out very large, and in my defense it's something I had created 3 years ago while I couldn't read javaScript as well as I can now.

    But to get to the point, I may or may not redo it and in case I do I have a few questions.
    -In my understanding you have created an plugin with an function which can be called in an damage formula?
    -What use is the 4th parameter of the function "action"?

    Thank you for showing me a better way to do this, really if I had known this 3 years ago it would have at the very least halved my work.
     

Share This Page