+ Glasses 606 Posted December 15, 2015 (edited) Damage Formulas 101 MV Edition You probably wondered how to make a skill do more damage against enemies with a state, or heal more if player has a state, or deal exactly half of enemy's HP. And so on. All of that and more can be done through custom damage formula. Basics: Type - sets what does the formula damage or heal. None - Nothing, no damage will be dealt. HP Damage - HP will be damaged MP Damage - MP will be damaged HP Recover - HP will be restored MP Recover - MP will be restored HP Drain - Deals damage to enemy HP and restores that much HP for attacker MP Drain - Deals damage to enemy MP and restores that much MP for attacker Element - Sets which element to use. Normal attack - means will use same element as weapon. Variance - How will damage fluctuate. E.g. If skill formula says it deals 100 damage and variance is 20%, the skill will deal between 80 and 120 damage. Critical - Can skill critically hit, dealing increased damage by 300%. And now, the actual fun part - formulas! It decides how much damage will opponent take or ally will heal. Let's dissect one of basic formulas that come with RPG Maker MV - Fire 100 + a.mat * 2 - b.mdf * 2 What do things like a and b mean? a - attacker b - defender So if Actor Glasses were to cast Fire on a Slime. a would be Glasses and b would be Slime. Meaning the takes double of Glasses mat (Magic Attack) parameter and subtracts double of Slime's mdf (Magic Defense) parameter and adds that to the 100 in the beginning ofthe formula. E.g. Glasses has 100 mat and Slime has 20 mdf. If we were to convert fomula using those numbers, we'd have - 100 + 100*2 - 20*2, after calculation we see with those parameters Fire would deal 260 damage if there were no variance. But only last number in the formula deals damage. If you had 2 lines of formula. (semicolon ; tells where line ends for the program) E.g. a.atk; a.atk*2 Only a.atk*2 would be calculated for damage. Are there more letters other than a and b for the formulas? Yes. There are variables. Which are used like this: v[iD]. ID - index of the variable. So you could have a skill that gets stronger the higher variable is. E.g. v[10] * 2 - b.def * 3 Is there a way to make skill even more complex, e.g. if some variable is over 100, deal extra damage? Yes, in that case we can use if else statements. How if else statement looks: if (statement) { formula1; } else { formula2; } But how to write it to the damage formula? It only has 1 line! Just write everything together~ if (statement) { formula1; } else { formula2; } E.g.: if (v[10] > 100) { a.atk*4 - b.def*2 } else { a.atk*2 - b.def*2 } Which can be shortened to this if you're using only 1 line of formula. if (statement) formula1; else formula2; E.g.: if (v[10] > 100) a.atk*4 - b.def*2; else a.atk*2 - b.def*2; And you can shorten it even further using ternary operator (my favorite one): statement ? formula1 : formula2; E.g.: v[10] > 100 ? a.atk*4 - b.def*2 : a.atk*2 - b.def*2; Symbols for statements: > - more than < - less than >= more than or equal to <= less than or equal to === equal to && and || or !== not equal ! not Examples: v[10] > 100 ? 1000 : 100; (If variable 10 is more than 100, it'll deal 1000 damage, else it'll only deal 100) v[10] < 100 ? 1000 : 100; (If variable 10 is less than 100, it'll deal 1000 damage, else, it'll only deal 100) v[10] >== 100 ? 1000 : 100; (If variable is 100 or more, it'll deal 1000 damage, else it'll only deal 100) v[10] <== 100 ? 1000 : 100; (If variable is 100 or less, it'll deal 1000 damage, else it'll only deal 100) v[10] === 100 ? 1000: 100; (If variable is equal to 100, it'll deal 1000 damage, else it'll only deal 100) v[10] > 50 && v[11] >== 25 ? 1000 : 100; (If variable 10 is more than 50 and variable 11 is 25 or more, it'll deal 1000 damage, else it'll only deal 100) v[10] > 50 || v[11] > 50 ? 1000 : 100; (If variable 10 is more than 50 or variable 11 is more than 50 then it'll deal 1000 damage, it'll only deal 100) v[10] !== 100 ? 1000 : 100; (If variable 10 is not equal to 100, it'll deal 1000 damage else it'll only deal 100) What about parameters to use for a and b? Here's a whole list of them: Current: (All flat numbers, e.g.: 900, 999, 11) level - current level (Actor only by default) hp - current hp mp - current mp tp - current tp Params: (All flat numbers, e.g.: 1337, 7331, 156) mhp - max hp mmp - max MP atk - attack def - defence mat - magic attack mdf - magic defence agi - agility luk - luck XParams: (All decimal numbers symbolizing percent, e.g. 1.0, 0.5, 0.75, 2.44 would be 100%, 50%, 75%, 244%) hit - Hit rate eva - Evasion rate cri - Critical rate cev - Critical evasion rate mev - Magic evasion rate mrf - Magic reflection rate cnt - Counter attack rate hrg - HP regeneration rate mrg - MP regeneration rate trg - TP regeneration rate SParams:(All decimal numbers symbolizing percent, e.g. 1.0, 0.5, 0.75, 2.44 would be 100%, 50%, 75%, 244%) tgr - Target Rate grd - Guard effect rate rec - Recovery effect rate pha - Pharmacology mcr - MP Cost rate tcr - TP Charge rate pdr - Physical damage rate mdr - Magical damage rate fdr - Floor damage rate exr - Experience rate How about changing HP/MP/TP? gainHp(value) - restores HP by value gainMp(value) - restores MP by value gainTp(value) - restores TP by value setHp(hp) - sets HP to value setMp(mp) - sets MP to value setTp(tp) - sets TP to value E.g. a.setHp(a.mhp) E.g. a.setHp(a.hp + 100) clearTp() - sets TP to 0 What about advanced stuff where you can influence formulas with states? We got all that! isStateAffected(stateId) - checks if battler has state inflicted to them. E.g. b.isStateAffected(10) ? 10000 : 1; isDeathStateAffected() - checks if battler has death state inflicted to them. E.g. b.isDeathStateAffected() ? 10000 : 1; resetStateCounts(stateId) - refreshes how long state will last for the battler if (b.isStateAffected(10)) b.resetStateCounts(10); 100 updateStateTurns() - shortens all states on battler by 1 turn b.updateStateTurns(); 100 addState(stateId) - adds state to the battler if (!b.isStateAffected(10)) b.addState(10); 100 isStateAddable(stateId) - checks if state can be added to the battler c=100; if (b.isStateAddable(10)) b.addState(10); else c=4000; c removeState(stateId) - removes state from the battler if (a.isStateAffected(10)) a.removeState(10); 0 What about buffs? Can we buff and debuff battlers? Yes! addBuff(paramId, turns) - adds a buff for a parameter a.addBuff(0, 3); b.def*10 addDebuff(paramId, turns) - adds a debuff for a parameter b.addDebuff(2, 10); 9999 removeBuff(paramId) - removes a buff or debuff from a battler removeAllBuffs() - removes all buffs and debuffs from a battler Parameter IDs 0 - Max HP 1 - Max MP 2 - Attack 3 - Defence 4 - Magic Attack 5 - Magic Defence 6 - Agility 7 - Luck General Battler Stuff die() - kills the battler b.die(); 0 revive() - revives the battler a.revive(); 1000 paramBase(paramId) - gets base parameter a.paramBase(3)*10 - b.def*2 paramPlus(paramId) - gets the bonus of parameter a.paramPlus(3)*2 - b.def*2 paramMax(paramId) - gets max possible value of parameter b.paramMax(0) elementRate(elementId) - checks element rate of the battler (rate being decimal numbers representing %) b.elementRate(10) >== 0.5 ? 10000 : a.mat*4; isStateResist(stateId) - checks whether the battler resists state c=0; b.isStateResist(10) ? c+=2000 : b.addState(10); c isSkillTypeSealed(stypeId) - checks if battler's skill type is sealed isSkillSealed(skillId) - checks if battler's skill is sealed isEquipTypeSealed(etypeId) - checks if battler's equip type is sealed isDualWield() - checks if battler can dual wield isGuard() - checks if battler is guarding recoverAll() - removes all states, restores HP and MP to max hpRate() - checks HP rate of battler mpRate() - checks MP rate of battler tpRate() - checks TP rate of battler b.hpRate() < 0.5 ? b.hp-1 : 100; isActor() - checks if battler is actor isEnemy() - checks if battler is enemy escape() - escapes from battle b.escape() (makes enemy run away) consumeItem(item) - eat up an item a.consumeItem($dataItems[15]); 100 For actor only: currentExp() - current EXP currentLevelExp() - EXP needed for current level nextLevelExp() - EXP needed for next level nextRequiredExp() - EXP left until next level maxLevel() - max level of actor isMaxlevel() - is actor max level (true/false) hasWeapon() - is actor wielding a weapon (true/false) hasArmor() - is actor wearing any armor (true/false) clearEquipments() - unequip everything actor is wearing isClass(gameClass) - checks if actor is of a class (gameClass - $dataClasses[iD]) hasNoWeapons() - checks if actor doesn't have any weapons levelUp() - levels actor up levelDown() - level actor down gainExp(exp) - gives actor exp learnSkill(skillId) - makes actor learn a skill forgetSkill(skillId) - makes actor forget a skill isLearnedSkill(skillId) - checks if actor has a skill learned actorId() - returns Actor's ID For enemy only: enemyId() - returns Enemy's ID What about Math? Can we use Math methods inside the formula? Yup, you totally can. Math.random() - returns a random number between 0 and 1 (0 <= n < 1) Math.min(numbers) - returns a minimum number from provided numbers. E.g. Math.min(10, 50, 40, 200) - would return 10. Math.max(numbers) - returns a maximum number from provided numbers. E.g. Math.max(10, 50, 40, 200) - would return 200. Math.round(number) - rounds a number to nearest integer. Math.ceil(number) - rounds the number up to nearest integer. Math.floor(number) - rounds the number down to nearest integer. Math.rand() returns a number between 0 and 1, but can we get a random number between 1 and 100? Or 5 and 200? No problem: Math.floor(Math.random()*100)+1 ^ That would return a number between 1 and 100. If we didn't add 1 at the end, it'd only return a number between 0 and 99. But that's a lot of text? Could we simplify somehow? Thankfully, there's a method in rpg_core.js that adds Math.randomInt(max); So we can write the same using: Math.randomInt(100)+1 If you have any questions, feel free to ask or discuss various ways to make specific skills. Edited January 29, 2016 by Glasses 7 Share this post Link to post Share on other sites
Cookie Ninja 374 Posted December 16, 2015 (edited) Nice! Loveley to see this topic! I was wondering though, in Ace you had a character limit of 100, what is it in MV? Ooo... and one more, if you wanted to go beyond those 100 char you could write something like: class Game_Battler < Game_BattlerBase def cookie_skill(a, # Insert whatever you want it to do endend and then call that code in the damage formula box by writing: a.cookie_skill(a, How would you go about doing something similar in MV? Thx alot for this wonderful post! Edited December 16, 2015 by Cookie Ninja Share this post Link to post Share on other sites
+ Glasses 606 Posted December 16, 2015 @Cookie Ninja, No character limit in MV. And creating Game_Battler method in MV would look like. Game_Battler.prototype.glassesSkill = function(a, { var v = $gameVariables._data; //Do Stuff here }; Share this post Link to post Share on other sites
Cookie Ninja 374 Posted December 16, 2015 Sweet! No character limit!? Interesting, better make sure to get everything right when writing the longer type stuff! Thx!^^ Share this post Link to post Share on other sites
eatorl 16 Posted December 16, 2015 (edited) Hi there! Thank you! I have two questions:-Is it possible to use two conditions in one damage formula? Like If(x){ if(y){a} else{b} }else{c} If not, should it be done through common event?-Not sure if this is the place but: Which do you think is the minimum "numerical magnitude order" Magnitude orderto work with when designing stats and skills? I found that there can be problems with some multipliers when you got values under 100, for example in a "berserker skill" where low health is important: (a.mhp - a.hp)*0.2 + a.atk - b.def0.5 // with values as a.hp = 10 a.mhp = 25 a.atk = 5 b.def = 4 // the result would be (25-8)*0.2 + 5 - 2 = 6.2 = 6 // but with a higher order values (10) the result would be (250-90)*0.2 + 50 - 20 = 62 // And that 2 is important. That makes me think that it depends on how many decimals you want to "save". I was using stats with the "minimum" number order (1) but it turns out that it got some limitations, well, a lot of limitations. Another example with multiple hits: (a.agi-b.def) < 1 ? 1: (a.agi-b.def); (4-4) = 1 //It is a 3 hits skill. Because of the inexistent range between one number and another the result will be zero when the enemy defense is high enough because the result can not be a number between 0 and 1. That forces me to push the base value up to 1. //Now with values in the order of 10 (45-40) = 5 //That is way more balanced than just give an entire "1" value to the user. So.. do you think someone as a developer can adapt his formulas for simple interactions in low magnitude orders or is it much better to go to a "safe zone" and then do whatever you want with multipliers and stuff?Thanks! Edited December 16, 2015 by eatorl Share this post Link to post Share on other sites
+ Glasses 606 Posted December 16, 2015 @eatorl, Yes, you can use any number of nested if statements. As for the numbers, I assume you ask how big the numbers should be for parameters/damage. Then, yeah, it depends if decimals are important to you - if they are, you move that many decimals to the right. And if they aren't, you can work with small numbers. Share this post Link to post Share on other sites
Amber 1 Posted December 17, 2015 I want to make a formula that if the caster's HP is below 25% it would deal much damage as normal attack (+ 100) and it heal the player, but I tried it gives me a 0. Is there a way to work around it Share this post Link to post Share on other sites
+ Glasses 606 Posted December 17, 2015 @Amber, What formula did you try. And how much damage does the skill do if the caster's HP is above 25%? it could be be something like this. if (a.hpRate() <== 0.25) { a.hp += 100; a.atk*4 - b.def*2 + 100; } else { a.atk*4 - b.def*2; } 1 Share this post Link to post Share on other sites
Jeanne d'Ys 166 Posted December 17, 2015 Finally! This is really helpful, thanks a lot~ XD I've been rooting for custom damage formulas in MV, since the way they're written are a bit different XD Share this post Link to post Share on other sites
+ Takeo212 1,079 Posted December 17, 2015 How would you make it so that your attack gradually increases with the more TP you have? I've never been good with formula's (probably because I sucked at maths) so I can't get it to work exactly. Share this post Link to post Share on other sites
+ Glasses 606 Posted December 17, 2015 @Takeo212, Decide how much attack should increase depending on TP. Maybe attack will deal 300% more damage if Actor has full TP, then. (a.atk * 4 - b.def * 2) * (1 + 2 * a.tpRate()) 1 Share this post Link to post Share on other sites
Amber 1 Posted December 17, 2015 IT only do no damage and no full restore and I want with fully heal though Share this post Link to post Share on other sites
+ Glasses 606 Posted December 17, 2015 @Amber, Woops, my bad. Changed up the guide a little bit and added a few new methods. Should be fine now. if (a.hpRate() <= 0.25) { a.setHp(a.mhp); a.atk*4-b.def*2 + 100; } else { a.atk*4 - b.def*2; } 1 Share this post Link to post Share on other sites
Amber 1 Posted December 18, 2015 I wonder if there is a formula that have a random chance to debuff the caster/target or buffs the caster/target instead using the add buff/debuff from the effect section. I want to add a chance instead relying on those add buff/debuff all the time. Share this post Link to post Share on other sites
eatorl 16 Posted December 21, 2015 (edited) I wonder if there is a formula that have a random chance to debuff the caster/target or buffs the caster/target instead using the add buff/debuff from the effect section. I want to add a chance instead relying on those add buff/debuff all the time. Turns out Math.random() works in Damage Formula: if(Math.random()<0.5)a.addBuff(paramId, turns); 100 Here you have a 50% chance to add the Buff, I guess you can control that with a variable or even control the chance with a parameter such as luck, etc. if(Math.random()*100<(10 + a.luk))a.addBuff(paramId, turns); 100 If your luck values goes from 10 to 70 or something like that you could use a formula like that to "balance" that randomness, I guess. Or use a game variable. I think it is with \v[id] or something, correct me if I am wrong. Have a good one. Edited December 21, 2015 by eatorl 1 Share this post Link to post Share on other sites
+ Takeo212 1,079 Posted December 30, 2015 (edited) How would you make a formula for something like; The less HP the character has, the more damage they gain? I've been messing around with this for a bit, but can't get it to work the way I want it too :< Any help please? EDIT Also, if possible, how can I make a move that drains some mp from an enemy? I can't get the formula right >.< My BF is a math wiz. I spent 1 minute explaining formula's to him, and he already knows how to make them better than me ;-; I got these 2~ They were alot simpler that I was writing them... Edited December 30, 2015 by Takeo212 Share this post Link to post Share on other sites
manoma 1 Posted January 9, 2016 (edited) is there a way to get the attacked actor ID? I wanted to make the characters earn MHP or/and DEF as they get hurt, for example each hit they take increases the maxhp by 1. i know i can make buffs, but what i want is something permanent. well, while i wrote all that i also came up with new ideas of how to do it, but i still would like to know if there is a way to get attacker and defender ID. DMG dealt value would be nice too (for a alternative heal where you do DMG to a monster and acumulate part of it to use in a healing skill, is currently easy to do all of it with no variance in skills tought). Edit: i managed to do it by making the attack teach a skill for the target and after that call a common event that would check who had the skill and would add +1mhp to him and delete the skill. Edited January 9, 2016 by manoma Share this post Link to post Share on other sites
+ Glasses 606 Posted January 9, 2016 You mean this? b.actorId() 1 Share this post Link to post Share on other sites
manoma 1 Posted January 9, 2016 (edited) You mean this? b.actorId() i tried this: ------------------- formula: v[10] = b.actorId; d = a.atk * 4 - b.def * 2; if (d < 2) 1; else d; notetag: <Custom Execution> $gameActors.actor(v[10]).setName(popo) </Custom Execution> ---------------------------------- Formula: d = a.atk * 4 - b.def * 2; if (d < 2) 1; else d; notetag: <Custom Execution> $gameActors.actor(b.actorId).setName(popo) </Custom Execution> ---------------------------- none of them worked :/ (i used setname to see the effect easily), could you give a example of how to use it? Edited January 9, 2016 by manoma Share this post Link to post Share on other sites
+ Glasses 606 Posted January 9, 2016 Well, yes, because it's b.actorId() not, b.actorId 2 Share this post Link to post Share on other sites
manoma 1 Posted January 9, 2016 (edited) Well, yes, because it's b.actorId() not, b.actorId hmm, ok thanks, i tried this before but i got a error saying it's not a function(that is why i took off the ()), but this time it worked. Seens my game is a little bugged and i got myself confused because of that, sorry. Sometimes i'm getting the error saying the value is null because for some reason the custom execution command is executed when it isn't suposed to. Will need to check my plugins and I'll try to do some conditionals to fix that. as for the damage, yanfly damage control helped me with that, i used value = v[10]; in the global dmg calculation. I just need to see how i'll set it to 0 when it's a miss also, i saw that in another place (and in one of this topic posts), but you can use math. functions in the DMG formula. Could be a nice thing to add to your post (like using it to generate a random number and using "if" later to determine the DMG of the skill) EDIT: Helck FTW o/ EDIT 2: seens that the <Custon Execution> was used before the damage calculation, that is why i was getting the error, but now i managed to do it using a common event. Thanks again. EDIT 3: seens that it is causing the actors to do 0 DMG for some reason, only monsters are doing DMG like the formula (even without plugins) v[10] = b.actorId(); a.atk; EDIT 4: i solved it using yanfly DMG core, now i can store the last attacked actor ID and DMG dealt. Edited January 10, 2016 by manoma Share this post Link to post Share on other sites
Antioch 33 Posted January 22, 2016 This is such a well-written tutorial! I genuinely enjoyed reading it, really easy to understand and to the point Share this post Link to post Share on other sites
kagekiri 0 Posted January 25, 2016 (edited) Hi Glasses, first of all the information here is brilliant and thanks for putting it all together for us! Now... I'm not the sharpest tool in the box nad I've been trying to make a spell that does damage and applies a state, but only when there's another state already on the target, if not I want it to just do damage. For imagination sake. The fire spell Burns the target, and hte Ignite spell immolates the target, but only if the target is Burned to begin with. What I've got so far is if (b.isStateAffected(11)) b.addState(12); 100; else 100; but I can't seem to get it to work how I want it to =/ It just says target takes no damage on a blank dummy monster. Any help would be greatly appreciated Edited January 25, 2016 by kagekiri Share this post Link to post Share on other sites
+ Glasses 606 Posted January 25, 2016 @kagekiri, This should work: if (b.isStateAffected(11)) b.addState(12); 100 Since you want to deal damage regardless of state being on the enemy, else is not required. 2 Share this post Link to post Share on other sites
kagekiri 0 Posted January 25, 2016 =O so simple and it works! Amazing thank you! You're in my credits now ^_~ Share this post Link to post Share on other sites