Mad Skills II -Ver 1.0-
Mad Skills IIAs the title suggests, this is the second part of an existing tutorial. Therefore, I will continue as if you’ve previously read and followed the examples given in the first part. If you haven't read it already, part one can be found here: Mad Skills I
Quick Refresher: (Skip ahead if you don’t need one)
This:
def damage(a, b, f, o, d, t)is a method. Those letters within the parenthesis are arguments that the method accepts. When we drop this method inside of our skill’s formula text box, we’re calling that method whenever the skill is used. This simply does some calculations and returns a number. What do I mean by that exactly?
a = User b = Target
Let’s assume we know the ATK value of our User, and the DEF value of the Target.
Let’s also assume we perform a physical attack.
a.ATK = 32 b.DEF = 60
The skill that is being performed by the User: a.damage(a, b, 100, 5, 2, 1)
Let’s take a look at our formula for type 1:
when 1 then x = f + a.atk * o - b.def * d # physicalNow we'll replace those variables with values based on our assumptions and the skill being performed.
x = 100 + 32 * 5 – 60 * 2
x = 140
When you type a.damage(a, b, 100, 5, 2, 1), it is calculated and returns 140. The default variance for a damaging skill is 20. This simply means that the formula's output will be a number between 20% less than the value returned, and 20% greater. In this case its: 112 - 168
So last time, I showed you a skill which uses a different formula if the enemy manages to resist the damage entirely. We’ll call it… ‘Shell Crush’ for now. That was before we setup our localized damage formula, so go ahead and incorporate that skill into our new damage formula.
Old:
x = a.atk * 4 - b.def * 2 ; y = 100 * a.level ; if x <= 0 then y ; else x endNew:
x = a.damage(a, b, 0, 4, 2, 1) ; x <= 0 ? a.level * 100 : xSimple enough. Our method returns a number based on the arguments we give it, so it can be stored within a local variable as usual. This isn’t an ideal use of that particular skill, so we’ll be revisiting it shortly.
Normal Attacks
The ‘Normal Attack’ is somewhat controversial in classical RPG games. It’s usually a fast-acting physical attack at the top of an actor’s command list, that doesn’t cost any resources. This can easily become over-powered, giving your players no reason to use any of the unique skills that you worked so hard to design and balance. It can become under-powered as well, giving the attack no real reason to exist in the game. Diving too deeply into this would be outside of the scope of this tutorial, so we’ll just do something that’ll make dealing with this potential issue easier in the future.
Personally, I like to separate normal attacks from skills. We’ll give it its own un-adjustable formula and separate it from the usual skill calculations. This doesn’t seem very important right now, but it may come in handy later… Its 'type' will be 0.
case t # Skill Type when 0 then x = a.atk * 4 - b.def * 2 when 1 then x = f + a.atk * o - b.def * d # physical when 2 then x = f + a.atk * o - b.def * d # magical when 3 then x = f + a.atk * o + (a.def * (o / 2)) - b.def * d # atk/def when 4 then x = f + a.atk * o + (a.mat * (o * 0.75)) - (b.def + b.mdf) * d when 5 then x = f + a.atk * o + (a.agi * (o / 2)) - b.def * d # atk/agi when 6 then x = f + a.atk * o + (a.luk * (o * 2)) - b.def * d # atk/luk else x = f + a.atk * o - b.def * d # your bacon is secure endNow go back to your normal attack and change the formula so that it points to our new type instead. a.damage(a, b, 0, 0, 0, 0) – since normal attack doesn’t make use of the arguments we setup, it doesn’t matter what value you give them.
Provisional Variables
Just hear me out on this one. When you’re working on your game, there’s going to come a point in time where you’ll need variables to accomplish some of your more complex eventing, or scripting needs. Variables are one of the most powerful tools at your disposal, however, keeping them organized can be a pain; it just requires good planning. There is one thing you can do to save yourself a lot of trouble though.
Provisional Variables are basically a set of temporary variables that can be used in many different situations. You may have encountered such a situation where you only need a variable to keep track of something within a very narrow scope. If you haven’t encountered this yet, you will.
I highly recommend that everyone do this, no matter what kind of project they’re working on. Go to your list of variables and reserve at least the first five, maybe ten if you’re not efficient. Use these variables for quick and temporary value setting and storing. If you have to keep track of something for more than an instance, use a different variable.
Mad Skills
Shell Crush Effect: While our Shell Crush is an interesting skill, how useful is it? It’s pretty much a normal attack with a conditional effect that will likely be a very rare occurrence. That’s not good, whoever plays this game will likely never use it, so let’s fix that.
There’s an infinite number of ways to approach this, but let’s try making the skill more useful without changing its effect. It would be pretty cool if it was a weapon effect, right? Yes? Let’s do this then.
First return to your damage method, and add this somewhere below your ‘case t’ check:
if t == 0 && a.is_a?(Game_Actor) && a.equips.name.include?("Shell Crush") x = a.level * 100 if x < 1 end
Now any weapon with the words “Shell Crush” in its name will give that actor our Shell Crush effect. I made sure that the code only allows this for actors, since enemies do not have equipment.
If you want to test this: Give an enemy a DEF of 999. When you perform a normal attack on that enemy, it shouldn’t deal any damage. Now go into your weapons database and add “Shell Crush” (without quotations) to the name of any weapon of your choosing. Equip it to your actor and test the normal attack again.
So what if we have a dual-wielding actor? Will this work if our Shell Crush weapon is equipped in the second weapon slot? The answer is no. Sure you could compromise and just make sure that your players know that the Shell Crush effect will only work if the weapon is equipped in the primary weapon slot. Or… we could just fix it… Heck, let’s 'improve' the whole design! Time for a rewrite:
if t == 0 && x < 1 && a.is_a?(Game_Actor) # Shell Crush Weapon x = 0 a.equips.name.include?("Shell Crush") ? x += a.level * 100 : x a.equips.name.include?("Shell Crush") ? x += a.level * 100 : x endNot only does it work for both slots, but the effect is also additive now. This means that if we happen to equip two Shell Crush weapons, the effect is doubled.
Keep in mind that x is set to 0 for any actor dealing less than 1 damage with a normal attack. Although this allows us to set up similar effects within the same IF statement, it could potentially cause issues, though unlikely.
Enemies with very low or 0% PDR will still receive very little or no damage.
Mana Barrier: Guard just not doing it for you? How about we make a barrier that absorbs damage into MP! Obviously the shield should break if the caster runs out of MP, right? We have what we need, let’s set it up:
if b.state?(27) # Winged Barrier b.mp -= (x * 0.7 / 5).to_i x *= 0.3 b.remove_state(27) if b.mp < x endNow 70% of incoming damage will be absorbed into MP for whoever has state 27. By default MP values are a lot less than HP values, so I’m only having 1/5 of the actual damage value subtracted from MP. I’ll leave how the state is added to your actor or enemy up to you.
The MP will be subtracted from the actor/enemy who has the state, which may not necessarily be the caster.
Force Shell: While we’re on the subject of barriers, what if we want the barrier to resist a certain amount of damage, and break if that damage threshold is exceeded?
if b.state?(28) # Shield x -= b.mdf * 4 b.remove_state(28) if x > b.mdf * 4 endUnlike the last barrier, this one reduces damage by 4 times the magic defense of the affected. If the enemy uses an attack which exceeds this limit, the barrier will be broken and the actor will receive a bit of overflow damage. Again, how you apply this is up to you.
If an enemy is using either of the above barriers and your actor has a Shell Crush weapon, the Shell Crush effect will be much more likely to activate and bypass their damage reduction. This can change depending on where you put these effects in your formula. Ideally, Shell Crush should be placed near the bottom of your method.
Spirit Surge: Need to build up TP quickly? Don’t want to use TCR because its effect too broad? This is the skill for you. This one allows actors or enemies to receive bonus TP whenever they receive damage. Many different ways to approach this, so I’ll keep mine simple.
if b.state?(29) x = 0 if x < 0 b.tp += 5 + (x / 5.0).to_i endLets your tanky character build up TP more quickly. This can be important since TP gained though receiving damage is based on the percentage of HP you lose. Tanks tend to receive less damage and have more HP. This skill will bypass that little drawback for the most part.
With my setup, you can get negative x values if the enemy’s DEF or MDF is really high, so setting x to 0 in the event of a negative number is very important for this effect to work properly. Think of it this way… what happens when you add a negative number to a positive number? Subtraction!
Cripple: Want to punish an actor or enemy for attacking? Sure there’s always counter attack, but what if we want to punish someone for attacking period?
if a.state?(30) then a.hp -= x / 4.0 end # CrippleIf the user of any skill or attack is inflicted with state 30, they’ll receive 25% of the damage they would deal (recoil). You should place this one higher in your script so that the afflicted are still damaged when they hit barriers.
Retaliate: A counter attack for your magic users. This effect deals damage to the attacker based on the magic defense of the affected. It also cost MP every time it is triggered, and of course, it’ll be removed if the affected has insufficient MP.
if b.state?(31) # Retaliate a.hp -= b.mdf * 4 - x b.mp -= b.mdf / 2 endI made it so that this skill can be overcome by high amounts of damage, heck, it’ll even heal the enemy if they hit you hard enough. You’ll have to figure out how to fix that… Think of it as homework.
Lightning Shield: Another variation of counter attack, this one stuns the attacker instead of dealing damage to them. It’s a one-time thing, once it triggers, the effect is removed.
if b.state?(32) a.add_state(8) ; b.remove_state(32) endFocus Flaws: Critical hits deal an additional 50% damage… Nope, you don’t need another script for this one either, actually it’s pretty easy.
if a.state?(33) && b.result.critical then x *= 1.5 end # Focus FlawsBy the way, critical hits deal 3 times normal damage with the default settings. If you want to change it to, say: 2 times damage; you can use this.
#-------------------------------------------------------------------------- # * Apply Critical #-------------------------------------------------------------------------- def apply_critical(damage) damage * 2 endIt’s within the same class as our damage formula, so just add it as another method below your damage method (or whatever you called it). Check the bottom of this page for an example.
If you're using, or plan to use a script which modifies critical damage or the way that critical hits are applied, I recommend adjusting the settings within said script instead.
Crystal Edge: What about skills that buff your normal attacks for a time. Sure there’s some that give your attacks elemental damage, but that’s too easy. We’ll make a skill that gives your actor a state, which applies another state, which deals extra damage and adds a state to the afflicted if they’re damaged again by the attacker which has the first state. Confused?
if b.state?(35) && a.state?(34) && a.is_a?(Game_Actor)# Crystal Edge x += ((1800 / 100) * a.level).to_i b.add_state(8) ; b.remove_state(35) endI made this an actor only effect because I wanted to use level in the formula. The skill scales with the user’s level so that it’s never too strong or weak; though that really depends on your game. To set this up properly, make state 34 your Crystal Edge state which is added to the user of the skill. Then have your Crystal Edge add the Atk State 35, I named mine Polar Lights. This skill can be balanced in a few different ways, such as lowering the chance to apply Polar Lights, adjusting the damage per level, or changing which states are applied when Polar Lights is triggered.
Pet System: I’m not a fan of pets as a companion in games unless they’re part of the core game mechanics. Just putting that out there… I thought I’d give you guys a little bonus since I’ll be cutting this tutorial a little short. We’re going to set up a simple battle pet system from scratch. Even if you don’t want this, I suggest you follow along anyway, might pick up a neat trick or two.
Here’s The Plan: The player will obtain an item that we’ll call a Pet Token. Each token will contain a different type of pet. Equipping this token will grant the player a spell that allows him/her to Summon or Dismiss this pet. Some ‘pets’ will always be equal to the player’s level, others will need to level independently. We’ll add onto this in the next tutorial…
First, let’s create a few pet tokens. Go into your Armors tab and create three accessories named: Token: Fairy, Spirit of Fire, and Token: Skeleton Knight. Armor Type can be General Armor to ensure that everyone can use them. These will add the appropriate skills necessary for summoning the pet once equipped. We haven't made these skills yet, so just remember to come back and add them.
Second, go to your actors tab and create three new actors with corresponding names. The face and character graphics for these should be obvious…
Third, the common event that will summon the pets. You remember our provisional variables? We’re going to need one of those here. Create a conditional branch for each pet, have it check whether or not Variable 1 is equal to 1, 2, or 3. This variable will be set by our summoning skills. We'll give the player the option of summoning or dismissing their current pet for the Token types. The Fire Spirit will simply be summoned upon using the skill.
There's a script within the conditional branch for summoning the Spirit of Fire. The $game_actors, should be equal to the actor id of your Spirit of Fire. $game_variables will be set by the skill needed to summon the spirit. The spirit should be completely healed with each summon, we'll give her a timer in the next tutorial.
Fourth, we will write a simple script. This bit of code checks the actor’s accessory slot for a name matching an array of pet names. Once it finds something, it simply sets variable 1 to a new value. If there aren’t any matches, a message is displayed instead. Variable 1 will then be used by our common event to determine which pet we’re managing. There are likely better ways to do that, however, this is the first approach that came to mind.
class Game_Battler < Game_BattlerBasedef pets(a, p_array = ["Token: Fairy", "Spirit of Fire", "Token: Skeleton Knight"] case a.equips.name when p_array then var = 1 when p_array then var = 2 when p_array then var = 3 else $game_message.add("Pet Token must first be equipped!") end $game_variables = varendendFifth, we need to actually make the pet summoning skills. I’ll name one Battle Pet, and the other Manifest. These skills target the user and call a script, and common event in that order. We’ll use the formula area for this.
Battle Pet:
a.pets(a, ; $game_temp.reserve_common_event(1) if v > 0 ; 0Manifest:
a.pets(a, ; $game_temp.reserve_common_event(1) if v > 0 ; v = a.level ; 0
Should be functional, but we'll need the turn manager to complete the pet system.
I’ll cover the Turn Manager in part III. Check out our completed code below.
Code:
#===============================================================================# Mad Skills II## a = user# b = target# f = flat damage# o = offense# d = defense# t = type#===============================================================================class Game_Battler < Game_BattlerBasedef damage(a, b, f, o, d, t) case t # Skill Type when 0 then x = a.atk * 4 - b.def * 2 when 1 then x = f + a.atk * o - b.def * d # physical when 2 then x = f + a.atk * o - b.def * d # magical when 3 then x = f + a.atk * o + (a.def * (o / 2)) - b.def * d # atk/def when 4 then x = f + a.atk * o + (a.mat * (o * 0.75)) - (b.def + b.mdf) * d when 5 then x = f + a.atk * o + (a.agi * (o / 2)) - b.def * d # atk/agi when 6 then x = f + a.atk * o + (a.luk * (o * 2)) - b.def * d # atk/luk else x = f + a.atk * o - b.def * d # your bacon is secure end if a.state?(30) then a.hp -= x / 4.0 end # Cripple if b.state?(26) # exploit state id ext = 1+rand(99) b.result.critical = true if ext < 51 end if b.state?(27) # Mana Barrier b.mp -= (x * 0.7 / 5).to_i ; x *= 0.3 b.remove_state(27) if b.mp < x end if b.state?(28) # Force Shell x -= b.mdf * 4 b.remove_state(28) if x >= b.mdf * 4 end if b.state?(29) # Spirit Surge x = 0 if x < 0 b.tp += 5 + (x / 5.0).to_i end if b.state?(31) # Retaliate a.hp -= b.mdf * 4 - x b.mp -= b.mdf / 2 end if b.state?(32) a.add_state(8) ; b.remove_state(32) end if a.state?(33) && b.result.critical then x *= 1.5 end # Focus Flaws if b.state?(35) && a.state?(34) && a.is_a?(Game_Actor)# Crystal Edge x += ((1800 / 100) * a.level).to_i b.add_state(8) ; b.remove_state(35) end if t == 0 && x < 1 && a.is_a?(Game_Actor) # Shell Crush Weapon x = 0 a.equips.name.include?("Shell Crush") ? x += a.level * 100 : x a.equips.name.include?("Shell Crush") ? x += a.level * 100 : x end x # Resultend #--------------------------------------------------------------------------# * Apply Critical#--------------------------------------------------------------------------def apply_critical(damage) damage * 2endend
本贴来自国际rpgmaker官方论坛作者:Rinobi处,因国际论坛即将永久关站,为了存档多年珍贵资料,署名转载到本论坛存档,由于官方帖子为英文原帖,需要中文翻译请点击论坛顶部切换语言为中文就可以将帖子翻译成中文浏览,方便大家随时查看,原文地址:https://forums.rpgmakerweb.com/threads/mad-skills-ii-ver-1-0.45005/
页:
[1]