RMMV Damage Formula - ideas and help

● ARCHIVED · READ-ONLY
Started by Shaz 1539 posts Page 54 of 77 View original ↗
  1. Silva said:
    Ah, that's a total goof on my part. If you want to use the damage formula to add this effect from the weapons you will need to check the actor has it equipped. The best check to use for this would be

    Code:
    a.hasWeapon($dataWeapons[id])
    
    //where id = weapons database id

    Now to get that into damage formulas with the above would look something like this:

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

    It's messy, but it should work in your skills damage formula.

    Thank you! I will try to put this and see if it works ^^
  2. Silva said:
    Code:
    if (a.hasWeapon($dataWeapons[weaponId]) && (b.isStateAffected(confusedId) || b.isStateAffected(blindId) || Math.randomInt(100) < 25)) {b.addState(stunId)}; damageFormula

    It's messy, but it should work in your skills damage formula.

    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?
  3. 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.
  4. Thank you for the reply!

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

    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.

    Engr. Adiktuzmiko said:
    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

    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.

    Engr. Adiktuzmiko said:
    value = a.isAtypeEquipped(id);

    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>
  5. XZINED said:
    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.

    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)
  6. Silva said:
    Code:
    baseDamageFormula = function(a, b) {
        var damage = a.atk * 4 - b.def * 2;
        return damage
    }
    
    //to call in battle formula
    baseDamageFormula(a, b)

    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.

    My .js file
    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;
  7. XZINED said:
    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])

    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.

    XZINED said:
    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")

    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)
  8. 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:
  9. 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.
  10. Silva said:
    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.

    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:
  11. 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. Silva said:
    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)

    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)

    x6ldet.jpg

    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. 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.
  14. 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. 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.
  16. Silva said:
    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.

    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:
  17. 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
    }
  18. @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. 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. 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.