# The obligatory "DnD Skill checks" question for RPG Maker MZ

#### SoCalAshez

##### Villager
Hello All!

So I've done a little research and am aware that this question is asked at least once every couple years across the different iterations of the game. I have done pretty well in incorporating DnD-like mechanics, formulas, etc. into RPG Maker MZ either through Plug-ins, self teaching, videos and all that. I nailed down a formula to have DND style combat with dice rolls after doing some tweaks to an article I found online. The end formula for DND style combat:

if (b.def <= Math.randomInt(20)+1+a.agi+a.mdf) {Math.randomInt(a.atk)+1+a.agi} else {0}

Explanation: b.def being enemy defense (AC); the d20 roll, agi representing str/dex; mdf being actors proficiency bonus (i know this sounds silly but it works), atk being the weapons attack while the actors have none (i.e.sword giving 8 attack to represent 1d8). The attack or spell is set to Certain hit, 100 percent success, and 0 variance to bypass RPG Maker Hit Rate and Evasion calculation and make it as pure dice roll as able.

Anyway, I am hoping to use the above formula to do skill checks in events but I am not literate in java enough to make that on my own. Some idea's I've seen floating around include: making skills into variables and doing conditional branches if the numbers are high enough by having choices that the player decides which actor gets to make the attempt based on their variable. That just seems like a killer amount of work to set up and I feel there may be a better way.

Is there a way I can use my above formula but change it up just a bit, for example:

if (TARGET NUMBER <= Math.randomInt(20)+1+SKILL MODIFIER+a.mdf(PROFICIENCY BONUS)) {succeed} else {fail}

The thing is I wouldn't know where to put that or what to use specifically to make it work. Any help from you guys would be GREATLY appreciated.

Thank You!
-SoCalAshez

#### ChatS

##### Villager
Variables are the best way to go with this! First you need a variable named "random roll" (Or whatever you wish!), then you need to create a variable for each stat, for each actor.

Then you can check a random 0-19 check (+ actor stat modifier) VS a DC for whatever purpose you need.

It is tedious at first, but once it's all set up it it works pretty well.

#### SoCalAshez

##### Villager
Variables are the best way to go with this! First you need a variable named "random roll" (Or whatever you wish!), then you need to create a variable for each stat, for each actor.

Then you can check a random 0-19 check (+ actor stat modifier) VS a DC for whatever purpose you need.

It is tedious at first, but once it's all set up it it works pretty well.

Okay yeah I'll give that a try. Do you know how I should reflect that in the event editor? Would love a quick screenshot if you could get it to work.

I'm such a newb

#### ChatS

##### Villager
Actually you just need 1 variable and that's the random roll one. The actor's stats is already stored.

and this is how I would set it up. (Note 1: that you probably should check if the actor is in the party to begin with!) But I forgot about that! (Just make a condition for it before the rest!)

(Note 2: I used MV here, but I'm pretty sure you can do the very same in MZ!)

I always set a random variable to 0 first. You probably can ignore that, but I found that resetting random variables that way makes sure it doesn't call a previous random number first.

Hope that helps!

#### Trihan

##### Speedy Scripter
If you don't want to go down the route of adding the ability score modifiers as variables in their own right, remember that the mod is just (ability score - 10) / 2 rounded down.

So if you wanted to incorporate, say, the str mod, you'd just do Math.floor((a.atk - 10) / 2)

#### SoCalAshez

##### Villager
@ChatS , I cannot thank you enough. I cannot wait to put this in my game and give it a shot, means a lot that you went the extra mile for a person like me!

#### ChatS

##### Villager
No need to thank me! Just enjoy making your games!

#### Frogboy

##### I'm not weak to fire
I have a bunch of D&D style-plugins for MV. These will eventually get rolled into my current MZ project I'm working on but they won't be quite as easy to just slap onto an existing project.

#### SoCalAshez

##### Villager
Wow!

When I first got MZ in august and tried to make this game a reality, I saw your work and tried it in MZ. I had no knowledge of how things worked, kinda like now but minus 1, and was pretty disappointed it didn’t just work in MZ, more because I REALLY leaned into the spells and slots for our sorcerer before actually testing it and the game kept crashing. Honestly honored you would visit this humble post.

Your plugins were really inspiring and using the visustella and home plugins I was able to do some similar stuff with race and class stuff, hope you are able to add yours to MZ soon!

Thank you @Frogboy

#### Frogboy

##### I'm not weak to fire
While the changes made from MV to MZ probably weren't as extensive as most of us were hoping for, they changed enough that any complex plugin won't work as-is ... and my plugins ended up getting crazy complex. My work with MV was a learning experience and I'm approaching things differently this time. But when I'm far enough along, I should have a solid D&D inspired RPG Maker engine for us all to enjoy.

#### SoCalAshez

##### Villager
@ChatS that worked perfectly btw, I made a success and failure common events that tell the player what the roll was and then activate a self switch after doling out the reward or telling them how it failed. I love it!!!

#### Ashouse

##### Resident Zombie
Super cool thread. When you're familiar with one system, as those of us interested in this thread likely are, it makes it much easier to write everything else. I know I'm old, but I've been writing D&D modules off and on for 30 years. (Literally... And no, not professionally, just for the fam)

#### MLyons

##### Villager
Here's something to ponder from what I'm working on to incorporate D20 (D&D) 3.5e type rules. It's not complete yet as i'm only now starting to work on incorporating the ability score sections of the existing character classes (STR, DEX, INT, CON, CHA, WIS) to support the attacking/defense. You'll see it uses another plug-in I found from BodkinsOdds that provides the foundation for armor class (AC) and to hit AC 0 (THAC0).

I have a LOT of extra code in here that helped me with troubleshooting and to learn what the heck RPG Maker was doing (I use a LOT of console.logs)...and will be pulled out eventually but perhaps you can learn a bit from this. It overrides two functions from the core rmmz_objects scripts. The "apply" function, the "to hit" logic and the "critical hit" logic. I'm avoiding the use of the built in critical hit chance and used instead a pure D20 roll as the indicator of a crit hit ... which then returns a value >100% chance of hitting and leads to the crit damage calculation (which I limited to 2x for now and can update later and make variable depending on factors).

JavaScript:
``````//=============================================================================
// MLyons - RPG Maker MZ Hit Logic Update addon
// hit_logic_update.js
//=============================================================================

//=============================================================================
/*:
* @target MZ
* @plugindesc [RPG Maker MZ] [Version 0.1 - ALPHA] [Hit_Logic_Update addon]
* @author MLyons
*
* @help
* ============================================================================
* Introduction
* ============================================================================
* Overrides the GMZ Hit Logic to match the character of a d20 game
*
* ============================================================================
* Credits
* ============================================================================
*
* Mike Lyons
* BodkinsOdds for the THAC0 scripts that this uses
*
* ============================================================================
* Changelog
* ============================================================================
*
* Version 0.1: December 24, 2020
* * Initial Release of Plugin!
*
* ============================================================================
* End of Helpfile
* ============================================================================
*
* @ --------------------------------------------------------------------------
*
*/
//=============================================================================

Game_Action.prototype.apply = function(target) {
const result = target.result();
this.subject().clearResult();
result.clear();
result.used = this.testApply(target);
var wasCriticalHit = this.itemHit( target );
result.missed = result.used && Math.random() >= wasCriticalHit;
//result.evaded = !result.missed && Math.random() < this.itemEva(target);
// removed the legacy evasion ability
result.physical = this.isPhysical();
result.drain = this.isDrain();
if (result.isHit()) {
if (this.item().damage.type > 0) {
if( wasCriticalHit > 100 ){
//it was a critical hit
this.executeDamage( target, this.makeDamageValue(target, true) );
} else {
//it was a normal hit
this.executeDamage( target, this.makeDamageValue(target, false) );
}
//result.critical = Math.random() < this.itemCri(target);
//const value = this.makeDamageValue(target, result.critical);
//this.executeDamage(target, value);
}
for (const effect of this.item().effects) {
this.applyItemEffect(target, effect);
}
this.applyItemUserEffect(target);
}
this.updateLastTarget(target);
};

Game_Action.prototype.itemHit = function ( target ) {
const id = target._enemyId;
const d = false;
if( d ) {
if(target.isEnemy() ) {
//if it is enemy type - do this stuff
//console.log( successRate * 0.01 * this.subject().hit );
console.log( "Target is enemy:" );
console.log( target ); // will point to the Game_Enemy object
//letter in Game_Enemy tells which specific one...and index above it
//with the index to the \$dataEnemies array
console.log( this ); // will point to the Game_Action object with the skill
console.log( this.subject() ); // the actor
console.log( \$gameActors.actor(this._subjectActorId) );
//to pull the AC + toHit from each group...start with actor option...then enemy

console.log( "Player hit % is: " + this.subject().hit );
//console.log ( "THAC0: " + Game_Character.toHit );
//console.log ( "AC: " + Game_Character.ac );
} else {
console.log ( "Target is player:" );
console.log ( target );
console.log ( this );
console.log ( this.subject() );
console.log( "Enemy hit % is: " + this.subject().hit );
//console.log ( "THAC0: " + \$dataEnemies[id].toHit );
//console.log ( "AC: " + \$dataEnemies[id].ac );
}
}//close out debugging section
//ok...plan - use this:
var ToHit = 0;
var DefAC = 0;
var RollNeeded = 0;
if (this._subjectActorId > 0) {
//return \$gameActors.actor(this._subjectActorId);
ToHit = \$gameActors.actor(this._subjectActorId).toHit;
DefAC = \$dataEnemies[target._enemyId].ac;
} else {
//return \$gameTroop.members()[this._subjectEnemyIndex];
ToHit = \$dataEnemies[this.subject()._enemyId].toHit;
DefAC = target.ac;
}
RollNeeded = 10 + DefAC;
var d20RollResult = (Math.floor(Math.random() * (20 - 1 + 1)) + 1);
const critHit = d20RollResult;
d20RollResult += ToHit;
const successRate = this.item().successRate;

if (this.isPhysical()) {
if( critHit == 20 ) {
//console.log ( "Critical Hit!" );
return 120;
}
if( critHit == 1 ) {
//console.log( "Crital Miss!" );
return 0;
}
if( d20RollResult >= RollNeeded ) {
console.log ( " d20 HIT! BAB: " + ToHit + " ACb: " + DefAC + " Roll Needed: " + RollNeeded + " Roll Result: " + d20RollResult );
return 100;
} else {
console.log (" d20 Miss...BAB: " + ToHit + " ACb: " + DefAC + " Roll Needed: " + RollNeeded + " Roll Result: " + d20RollResult );
return 0;
}
} else {
// default non-physical successRate
return successRate * 0.01;
}
};

Game_Action.prototype.applyCritical = function(damage) {
//console.log( "Critical hit x2 damage!" );
return damage * 2;
};``````

#### SoCalAshez

##### Villager
Hey there! Based on this line of script for attacks:

if (b.def <= Math.randomInt(20)+1+a.agi+a.mdf) {Math.randomInt(a.atk)+1+a.agi} else {0}

Is there a way I can have it say Miss instead of 0, i.e:

if (b.def <= Math.randomInt(20)+1+a.agi+a.mdf) {Math.randomInt(a.atk)+1+a.agi} else {Miss!}

Thank You!

### Latest Profile Posts

I ran out of paper sheets to draw, so I guess I'm forced to do digital for a while now...

Still haven0t found a colouring style that I like

Mapping is becoming so much easier!
Are the default-size "chibi" sprites really a bad thing for a project? I'm not planning to sell my game anyway but I was wondering if they were as hated as some videos seem to claim...
Only 9 things left on the to-do list before my game's next big update. Minus the soul-crushing playtesting session, of course! So close...